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);
}
}