PMON启动流程2

   

   sw        t1,BONITO_PCIMEMBASECFG(bonito)

        /* enable configuration cycles now */

        lw        t0,BONITO_BONPONCFG(bonito)

        and        t0,~BONITO_BONPONCFG_CONFIG_DIS

        sw        t0,BONITO_BONPONCFG(bonito)

        PRINTSTR("Init SDRAM Done!\r\n");

地址译码的结果和bonito64 的相兼容,为了实现对大容量(2GB)

存储器的支持,将原来的0x8000_0000~0x1_0000_0000 之间的2GB 空间分配给了SDRAM,

为了保持软件的兼容性,把2GB 空间的低256MB 和起始的256MB 存储空间重叠,对应同

一块存储区。

<img src=北桥设计文档.pdf:北桥内部地址空间分配>

初始化cache,将cache寄存器中填入内容,并cache有效?

...

下面完成程序和数据从flash到内存的拷贝

        la        a0, start

        li        a1, 0xbfc00000

        la        a2, _edata

        or      a0, 0xa0000000

        or      a2, 0xa0000000

        subu        t1, a2, a0

        srl        t1, t1, 2

        move        t0, a0

        move        t1, a1

        move        t2, a2

        /* copy text section */

       

1:        and        t3,t0,0x0000ffff

        bnez        t3,2f

        nop

        move        a0,t0

        bal        hexserial

        nop

        li        a0,'\r'

        bal         tgt_putchar

        nop

2:        lw        t3, 0(t1)

        nop

        sw        t3, 0(t0)

        addu        t0, 4

        addu        t1, 4

        bne        t2, t0, 1b

        nop

        PRINTSTR("\ncopy text section done.\r\n")

       

        /* Clear BSS */

        la        a0, _edata

        la        a2, _end

2:        sw        zero, 0(a0)

        bne        a2, a0, 2b

        addu        a0, 4

        TTYDBG("Copy PMON to execute location done.\r\n")

/* zhb */

#if 0

zhb:

        TTYDBG("Testing...\r\n")

        la        a0, start

        li        a1, 0xbfc00000

        la        a2, _edata

        or      a0, 0xa0000000

        or      a2, 0xa0000000

/*        subu        s6, a2, a0*/

/*        srl        s6, s6, 2*/

        move        t0, a0

        move        t1, a1

        move        t2, a2

        /* copy text section */

       

1:        lw        t4, 0(t1)

        nop

        lw        t5, 0(t0)

        addu        t0, 4

        addu        t1, 4

        beq        t4, t5, 2f

        nop

        move        a0, t0

        subu        a0, 4

        bal        hexserial

        nop

        TTYDBG        (" ")

        move        a0, t4

        bal        hexserial

        nop

        TTYDBG        (" ")

        move        a0, t5

        bal        hexserial

        nop

        TTYDBG        ("\r\n")

2:        bne        t2, t0, 1b

        nop

        TTYDBG        ("test ok!\r\n")

3:        beqz        zero, 3b

        nop

#endif

       

#if 1

        mfc0   a0,COP_0_CONFIG

        and    a0,a0,0xfffffff8

        or     a0,a0,0x2

        mtc0   a0,COP_0_CONFIG

#endif

        li        a0, 4096*1024

        sw        a0, CpuTertiaryCacheSize /* Set L3 cache size */

        move        a0,msize

        srl        a0,20

        la        v0, initmips

        jalr        v0

        nop

       

其中initmips是c代码的入口,初始化过程结束

initmips传入了memorysize,其中memorysize是start.S中的msize,是根据sdram内存条的信息计算出来的。

/home/dsm/pmon2003/src/Targets/Bonito/Bonito/tgt_machdep.c:

140     void

141     initmips(unsigned int memsz)

142     {

143             /*

144              *      Set up memory address decoders to map entire memory.

145              *      But first move away bootrom map to high memory.

146              */

147     #if 0

148             GT_WRITE(BOOTCS_LOW_DECODE_ADDRESS, BOOT_BASE >> 20);

149             GT_WRITE(BOOTCS_HIGH_DECODE_ADDRESS, (BOOT_BASE - 1 + BOOT_SIZE) >> 20);

150     #endif

151             memorysize=(memsz&0x0000ffff) << 20;//recover to original size:256M

152             memorysize_high=((memsz&0xffff0000)>>16) << 20;//0

153

154             /*

155              *  Probe clock frequencys so delays will work properly.

156              */

157             tgt_cpufreq();

158             SBD_DISPLAY("DONE",0);

159             /*

160              *  Init PMON and debug

161              */

162             cpuinfotab[0] = &DBGREG;

163             dbginit(NULL);

164

165             /*

166              *  Set up exception vectors.

167              */

168             SBD_DISPLAY("BEV1",0);

169             bcopy(MipsException, (char *)TLB_MISS_EXC_VEC, MipsExceptionEnd - MipsException);

170             bcopy(MipsException, (char *)GEN_EXC_VEC, MipsExceptionEnd - MipsException);

171

172             CPU_FlushCache();

173

174             CPU_SetSR(0, SR_BOOT_EXC_VEC);

175             SBD_DISPLAY("BEV0",0);

176

177             printf("BEV in SR set to zero.\n");

178

179     #if 0

180             /* memtest */

181             addr_tst1();

182             addr_tst2();

183             movinv1(2,0,~0);

184             movinv1(2,0xaa5555aa,~0xaa5555aa);

185             printf("memtest done\n");

186     #endif

187

188             /*

189              * Launch!

190              */

191             main();

192     }

其中很重要的是dbginit

/home/dsm/pmon2003/src/pmon/common/main.c:

284     void

285     dbginit (char *adr)

286     {

287             int     memsize, freq;

288             char    fs[10], *fp;

289             char    *s;

290

291             /*splhigh();*/

292

293             memsize = memorysize;

(gdb)

294

295             SBD_DISPLAY ("mems", CHKPNT_ENVI);

296             __init();       /* Do all constructor initialisation */

297

298

299             SBD_DISPLAY ("ENVI", CHKPNT_ENVI);

300             envinit ();

301

302     #if defined(SMP)

303             /* Turn on caches unless opted out */

(gdb)

304             if (!getenv("nocache"))

305                     md_cacheon();

306     #endif

307

308             SBD_DISPLAY ("DEVI", CHKPNT_SBDD);

309             tgt_devinit();

310

311     #ifdef INET

312             SBD_DISPLAY ("NETI", CHKPNT_NETI);

313             init_net (1);

(gdb)

314     #endif

315

316     #if NCMD_HIST > 0

317             SBD_DISPLAY ("HSTI", CHKPNT_HSTI);

318             histinit ();

319     #endif

320

321     #if NMOD_SYMBOLS > 0

322             SBD_DISPLAY ("SYMI", CHKPNT_SYMI);

323             syminit ();

(gdb)

324     #endif

325

326     #ifdef DEMO

327             SBD_DISPLAY ("DEMO", CHKPNT_DEMO);

328             demoinit ();

329     #endif

330

331             SBD_DISPLAY ("SBDE", CHKPNT_SBDE);

332             initial_sr |= tgt_enable (tgt_getmachtype ());

333

(gdb)

334     #ifdef SR_FR

335             Status = initial_sr & ~SR_FR; /* don't confuse naive clients */

336     #endif

337             /* Set up initial console terminal state */

338             ioctl(STDIN, TCGETA, &consterm);

339

340     #ifdef HAVE_LOGO

341             tgt_logo();

342     #else

343             printf ("\n * PMON2000 Professional *");

(gdb)

344     #endif

345             printf ("\nConfiguration [%s,%s", TARGETNAME,

346                             BYTE_ORDER == BIG_ENDIAN ? "EB" : "EL");

347     #ifdef INET

348             printf (",NET");

349     #endif

350     #if NSD > 0

351             printf (",SCSI");

352     #endif

353     #if NWD > 0

(gdb)

354             printf (",IDE");

355     #endif

356             printf ("]\nVersion: %s.\n", vers);

357             printf ("Supported loaders [%s]\n", getExecString());

358             printf ("Supported filesystems [%s]\n", getFSString());

359             printf ("This software may be redistributed under the BSD copyright.\n");

360

361             //print_cmd_name();

362

363             tgt_machprint();

(gdb)

364

365             freq = tgt_pipefreq ();

366             sprintf(fs, "%d", freq);

367             fp = fs + strlen(fs) - 6;

368             fp[3] = '\0';

369             fp[2] = fp[1];

370             fp[1] = fp[0];

371             fp[0] = '.';

372             printf (" %s MHz", fs);

373

(gdb)

374             freq = tgt_cpufreq ();

375             sprintf(fs, "%d", freq);

376             fp = fs + strlen(fs) - 6;

377             fp[3] = '\0';

378             fp[2] = fp[1];

379             fp[1] = fp[0];

380             fp[0] = '.';

381             printf (" / Bus @ %s MHz\n", fs);

382

383             printf ("Memory size %3d MB (%3d MB Low memory, %3d MB High memory) .\n",

(gdb)

384                     (memsize+memorysize_high)>>20,(memsize>>20), (memorysize_high>>20));

385

386             tgt_memprint();

387     #if defined(SMP)

388             tgt_smpstartup();

389     #endif

390

391             printf ("\n");

392

393             md_clreg(NULL);

(gdb)

394             md_setpc(NULL, (int32_t) CLIENTPC);

395             md_setsp(NULL, tgt_clienttos ());

396     #ifdef AUTOLOAD

397             s = getenv ("al");

398             autoload (s);

399     #else

400             s = getenv ("autoboot");

401             autorun (s);

402     #endif

403     }

__init():构造函数初始化.

将所有的constructor的函数执行一遍,建立一些基本的数据结构。在pmon中有三类constructor函数,它们都是静态函数。

1)        命令处理初始化函数,位于pmon/cmds目录下,其名称都叫init_cmd()。

init_cmd是静态函数,几乎在每个命令文件中都有.

2)        文件系统初始化函数。pmon/fs目录下。函数名称叫init_fs()或者init_xxxfs()。

init_diskfs,init_fs,init_netfs等每个都是静态函数.

如src/pmon/fs/diskfs.c中

static FileSystem diskfs =

{

        "fs",FS_FILE,

        diskfs_open,

        diskfs_read,

        diskfs_write,

        diskfs_lseek,

        diskfs_close,

        NULL

};

static void init_fs __P((void)) __attribute__ ((constructor));

static void

   init_fs()

{

        /*

         * Install diskfs based file system.

         */

        filefs_init(&diskfs);

}

int

filefs_init(FileSystem *fs)

{

        SLIST_INSERT_HEAD(&FileSystems, fs, i_next);

        return(0);

}

文件系统初始化就是代表各个文件系统的数据结构插入到相应链表。

对于磁盘文件系统,链表的头指针式DiskFileSystems。对于其他的文件系统,头指针是FileSystems。

这样当需要对某个文件操作(包括虚拟文件,如与用户交互的终端termio)。通过这两个链表可以找到相应的结构,

在通过里面的函数指针就可以对文件进行具体操作了。

3)        可执行文件类型初始化。在pmon/loader目录下。函数名称叫init_exec()

<input type="image" src="">

(gdb) l __init

89

90              /*

91               * Call global constructors.

92               * Arrange to call global destructors at exit.

93               */

94              if (!initialized) {

95                      initialized = 1;

96                      __ctors();

97              }

98      }

75      static void

76      __ctors()

77      {

78              void (**p)(void) = __CTOR_LIST__ + 1;

79

80              while (*p) {

81                      (**p++)();

82              }

83      }

    envinit ();初始化环境变量.从flash中读取并设置环境变量等

    tgt_devinit();初始化与板级相关的过程,在我们系统中主要是初始化北桥和PCI.

    241     void

242     tgt_devinit()

243     {

244             /*

245              *  Gather info about and configure caches.

246              */

247             if(getenv("ocache_off")) {

(gdb)

248                     CpuOnboardCacheOn = 0;

249             }

250             else {

251                     CpuOnboardCacheOn = 1;

252             }

253             if(getenv("ecache_off")) {

254                     CpuExternalCacheOn = 0;

255             }

256             else {

257                     CpuExternalCacheOn = 1;

(gdb)

258             }

259

260            CPU_ConfigCache();

261

262            //godson2_cache_flush();

263

264            //tgt_putchar('&');

265            

266            //test_icache_2(0);

267            //test_icache_3(0);

(gdb)

268            //tgt_putchar(0x30+i);

269            //tgt_putchar('Y');

270           

271            //tgt_test_memory();

272

273            //tgt_putchar('Z');

274

275             _pci_businit(1);        /* PCI bus initialization */

276     }

(gdb) info functions CPU_ConfigCache

File /home/dsm/pmon2003/src/pmon/arch/mips/cache.S:

<function, no debug info> CPU_ConfigCache;

873     _pci_businit (int init)

874     {

...

init = _pci_hwinit (init, &def_bus_iot, &def_bus_memt);

...

}

904_pci_hwinit初始化北桥的寄存器

tgt_devinit()>_pci_businit()>_pci_hwinit

pci_hwinit() 为Pmon主要初始化PCI在北桥的窗口的函数

Located in /home/dsm/pmon2003/src/Targets/Bonito/pci/pci_machdep.c

68      int

69      _pci_hwinit(initialise, iot, memt)

70              int initialise;

71              bus_space_tag_t iot;

72              bus_space_tag_t memt;

73      {

74              /*pcireg_t stat;*/

75              struct pci_device *pd;

76              struct pci_bus *pb;

77

(gdb)

78

79              if (!initialise) {

80                      return(0);

81              }

82

83              pci_local_mem_pci_base = PCI_LOCAL_MEM_PCI_BASE;

84              /*

85               *  Allocate and initialize PCI bus heads.

86               */

87

(gdb)

88              /*

89               * PCI Bus 0

90               */

91              pd = pmalloc(sizeof(struct pci_device));

92              pb = pmalloc(sizeof(struct pci_bus));

93              if(pd == NULL || pb == NULL) {

94                      printf("pci: can't alloc memory. pci not initialized\n");

95                      return(-1);

96              }

97

(gdb)   

98              pd->pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;

99              pd->pa.pa_iot = pmalloc(sizeof(bus_space_tag_t));

100             pd->pa.pa_iot->bus_reverse = 1;

101             pd->pa.pa_iot->bus_base = BONITO_PCIIO_BASE_VA;

102             //printf("pd->pa.pa_iot=%p,bus_base=0x%x\n",pd->pa.pa_iot,pd->pa.pa_iot->bus_base);

103             pd->pa.pa_memt = pmalloc(sizeof(bus_space_tag_t));

104             pd->pa.pa_memt->bus_reverse = 1;

105             pd->pa.pa_memt->bus_base = PCI_LOCAL_MEM_PCI_BASE;

106             pd->pa.pa_dmat = &bus_dmamap_tag;

107             pd->bridge.secbus = pb;

(gdb)

108             _pci_head = pd;

109

110             pb->minpcimemaddr  = PCI_MEM_SPACE_PCI_BASE+0x01000000;

111             pb->nextpcimemaddr = PCI_MEM_SPACE_PCI_BASE+BONITO_PCILO_SIZE;

112             pb->minpciioaddr  = PCI_IO_SPACE_BASE+0x000a000;

113             pb->nextpciioaddr =PCI_IO_SPACE_BASE+ BONITO_PCIIO_SIZE;

114             pb->pci_mem_base   = BONITO_PCILO_BASE_VA;

115             pb->pci_io_base    = BONITO_PCIIO_BASE_VA;

116             pb->max_lat = 255;

117             pb->fast_b2b = 1;

(gdb)

118             pb->prefetch = 1;

119             pb->bandwidth = 4000000;

120             pb->ndev = 1;

121             _pci_bushead = pb;

122             _pci_bus[_max_pci_bus++] = pd;

123

124

125             bus_dmamap_tag._dmamap_offs = 0;

126

127             /*set Bonito register*/

(gdb)

128             BONITO_PCIMAP =

129                 BONITO_PCIMAP_WIN(0, PCI_MEM_SPACE_PCI_BASE+0x00000000) |

130                 BONITO_PCIMAP_WIN(1, PCI_MEM_SPACE_PCI_BASE+0x04000000) |

131                 BONITO_PCIMAP_WIN(2, PCI_MEM_SPACE_PCI_BASE+0x08000000) |

132                 BONITO_PCIMAP_PCIMAP_2;

133

134             BONITO_PCIBASE0 = PCI_LOCAL_MEM_PCI_BASE;

135             BONITO_PCIBASE1 = PCI_LOCAL_MEM_ISA_BASE;

136             BONITO_PCIBASE2 = PCI_LOCAL_MEM_PCI_BASE + 0x10000000;

137

(gdb)

138             return(1);

139     }

建立PCI的空间分配的数据结构.其中pci_mem_base为Memory空间的基地址,pci_io_base为IO空间的基地址.

pd->pa.pa_iot对应于pci io空间分配

pd->pa.pa_memt对应于pci mem空间分配

minipciioaddr为IO空间的最小可以分配地址,minipcimemaddr为Memory空间的最小可以分配地址.

nextpcimemaddr为PCI的Memory空间的下一个分配地址,nextpciioaddr为PCI的IO空间的下一个分配地址,

在pmon的中地址分配是逆序分配的.

要分清cpu访问pci的地址和pci访问cpu内存的地址,pcimap寄存器定义的是cpu访问pci的地址,pcimap决定cpu访问pci的地址翻译

pcilo,pcil1,pcilo2分别位于0x10000000-0x1C000000的3个64M的窗口

pciio位于0x000a000;

#define BONITO_PCILO_BASE_VA    0xb0000000

#define BONITO_PCILO_SIZE               0x0c000000

这正好是包括PCI Lo0-Lo2的64Mx3 pci内存窗口

注意0xa0000000是地址uncache bit.因此BONITO_PCILO_BASE_VA就是0x10000000。

#define BONITO_PCIIO_BASE_VA            0xbfd00000

#define BONITO_PCIIO_SIZE               0x00010000

这是低1M的pci io空间窗口.

pci设备北桥的寄存器叫pcibase0-2,这是因为北桥本身是一个pci设备,这三个寄存器就是其配置空间的寄存器。

问题,如果有多个pci master,谁有权利来分配地址空间

cpu通过pci查找找到外设,并分配地址空间,北桥自己的地址空间,cpu什么时候分配的

北桥的配置空间的pcibase0-pcibase2就是北桥本身在pci地址空间上分配的位置。

其中_pci_bushead被设置成为

108             _pci_head = pd;

121             _pci_bushead = pb;

122             _pci_bus[_max_pci_bus++] = pd;

(gdb) l _pci_businit

872     void

873     _pci_businit (int init)

874     {

(gdb)

875             char *v;

876

877             v = getenv("pciverbose");

878             if (v) {

879                 _pciverbose = atol(v);

880             }

881

882             /* intialise the PCI bridge */

883             if (init) {

884                     SBD_DISPLAY ("PCIH", CHKPNT_PCIH);

(gdb)

885                     init = _pci_hwinit (init, &def_bus_iot, &def_bus_memt);

886                     pci_roots = init;//pci_roots = 1;

887                     if (init < 1)

888                             return;

889             }

890             if(monarch_mode) {

891                     int i;

892                     struct pci_device *pb;

893

894                     if (_pciverbose) {

(gdb)

895                             printf("setting up %d bus\n", init);

896                     }

897                     for(i = 0, pb = _pci_head; i < pci_roots; i++, pb = pb->next) {

898                             //_pci_scan_dev(pb, i, 0, init);

899                             _pci_scan_dev(pb, i, 8, init);//from 8+11, hu mingchang

900                     }

901                     _setup_pcibuses(init);

902             }

903     }

191     pcitag_t

192     _pci_make_tag(bus, device, function)

193             int bus;

194             int device;

(gdb)

195             int function;

196     {

197             pcitag_t tag;

198

199             tag = (bus << 16) | (device << 11) | (function << 8);

200             return(tag);

201     }

//从下面的pci配置空间的读操作可以看出,PCI的配置空间的访问分两种情况,类型0和类型1.

其中bus为0的为局部总线访问,采用的是pci类型0;bus为非0的是pci桥的访问采用的是pci类型1.两种类型的pci访问采用的地址译码的方法不同.下面的表说明在pci配置空间访问的时候,出现在pci AD总线上的地址的格式.

Pci ad bus 配置的空间为{ AD16UP ,cpuaddr[15:2],1’b0, Type1}

AD31                                         24 23     16 15           11 10             8 7              2 1   AD0

AD31-11 value-system dependent - to create correct IDSEL                 | Function Number| Register Number| 0| 0

             Fields for ‘‘Type 0’’ cycles

AD31-24 value as needed to create correct IDSEL|Bus Number| Device Number| Function Number| Register Number| 0 | 1

             Fields for ‘‘Type 1’’ cycles

pcireg_t

_pci_conf_readn(pcitag_t tag, int reg, int width)

{

    u_int32_t addr, type;

    pcireg_t data;

    int bus, device, function;

    if ((reg & (width-1)) || reg < 0 || reg >= 0x100) {

        if (_pciverbose >= 1)

            _pci_tagprintf (tag, "_pci_conf_read: bad reg 0x%x\n", reg);

        return ~0;

    }

    _pci_break_tag (tag, &bus, &device, &function);

    if (bus == 0) {

        /* Type 0 configuration on onboard PCI bus */

        if (device > 20 || function > 7)

            return ~0;                /* device out of range */

        addr = (1 << (device+11)) | (function << 8) | reg;

        type = 0x00000;

    }

    else {

        /* Type 1 configuration on offboard PCI bus */

        if (bus > 255 || device > 31 || function > 7)

            return ~0;        /* device out of range */

        addr = (bus << 16) | (device << 11) | (function << 8) | reg;

        type = 0x10000;

    }

    /* clear aborts */

    BONITO_PCICMD |= PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT;

    BONITO_PCIMAP_CFG = (addr >> 16) | type;

    data = *(volatile pcireg_t *)PHYS_TO_UNCACHED(BONITO_PCICFG_BASE | (addr & 0xfffc));

    if (BONITO_PCICMD & PCI_STATUS_MASTER_ABORT) {

        BONITO_PCICMD |= PCI_STATUS_MASTER_ABORT;

#if 0

        if (_pciverbose >= 1)

            _pci_tagprintf (tag, "_pci_conf_read: reg=%x master abort\n", reg);

#endif

        return ~0;

    }

    if (BONITO_PCICMD & PCI_STATUS_MASTER_TARGET_ABORT) {

        BONITO_PCICMD |= PCI_STATUS_MASTER_TARGET_ABORT;

        if (_pciverbose >= 1)

            _pci_tagprintf (tag, "_pci_conf_read: target abort\n");

        return ~0;

    }

    return data;

}

_pci_scan_dev代码

static void

_pci_scan_dev(struct pci_device *dev, int bus, int device, int initialise)

{

        //for(; device < 32; device++)

        for(; device < 19; device++) //to 19+11, hu mingchang

        {

                _pci_query_dev (dev, bus, device, initialise);

        }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值