1
2
3
4
/*
* QEMU PCI bus manager
*
* Copyright ( c ) 2004 Fabrice Bellard
ths
authored
18 years ago
5
*
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the "Software" ), to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
# include "vl.h"
// # define DEBUG_PCI
28
29
30
struct PCIBus {
int bus_num ;
int devfn_min ;
31
pci_set_irq_fn set_irq ;
32
pci_map_irq_fn map_irq ;
33
uint32_t config_reg ; /* XXX: suppress */
34
35
/* low level pic */
SetIRQFunc * low_set_irq ;
36
qemu_irq * irq_opaque ;
37
PCIDevice * devices [ 256 ];
38
39
PCIDevice * parent_dev ;
PCIBus * next ;
40
41
/* The bus IRQ state is the logical OR of the connected devices .
Keep a count of the number of devices with raised IRQs . */
42
int irq_count [];
43
};
44
45
static void pci_update_mappings ( PCIDevice * d );
46
static void pci_set_irq ( void * opaque , int irq_num , int level );
47
48
target_phys_addr_t pci_mem_base ;
49
static int pci_irq_index ;
50
51
static PCIBus * first_bus ;
52
PCIBus * pci_register_bus ( pci_set_irq_fn set_irq , pci_map_irq_fn map_irq ,
53
qemu_irq * pic , int devfn_min , int nirq )
54
55
{
PCIBus * bus ;
56
bus = qemu_mallocz ( sizeof ( PCIBus ) + ( nirq * sizeof ( int )));
57
bus -> set_irq = set_irq ;
58
bus -> map_irq = map_irq ;
59
60
bus -> irq_opaque = pic ;
bus -> devfn_min = devfn_min ;
61
62
63
first_bus = bus ;
return bus ;
}
64
65
66
67
68
69
70
71
72
73
74
75
PCIBus * pci_register_secondary_bus ( PCIDevice * dev , pci_map_irq_fn map_irq )
{
PCIBus * bus ;
bus = qemu_mallocz ( sizeof ( PCIBus ));
bus -> map_irq = map_irq ;
bus -> parent_dev = dev ;
bus -> next = dev -> bus -> next ;
dev -> bus -> next = bus ;
return bus ;
}
76
77
78
79
80
int pci_bus_num ( PCIBus * s )
{
return s -> bus_num ;
}
81
void pci_device_save ( PCIDevice * s , QEMUFile * f )
82
{
83
qemu_put_be32 ( f , 1 ); /* PCI device version */
84
85
86
qemu_put_buffer ( f , s -> config , 256 );
}
87
int pci_device_load ( PCIDevice * s , QEMUFile * f )
88
{
89
90
uint32_t version_id ;
version_id = qemu_get_be32 ( f );
91
92
93
if ( version_id != 1 )
return - EINVAL ;
qemu_get_buffer ( f , s -> config , 256 );
94
pci_update_mappings ( s );
95
96
97
return 0 ;
}
98
/* -1 for devfn means auto assign */
ths
authored
18 years ago
99
PCIDevice * pci_register_device ( PCIBus * bus , const char * name ,
100
int instance_size , int devfn ,
ths
authored
18 years ago
101
PCIConfigReadFunc * config_read ,
102
103
PCIConfigWriteFunc * config_write )
{
104
PCIDevice * pci_dev ;
105
106
107
if ( pci_irq_index >= PCI_DEVICES_MAX )
return NULL ;
ths
authored
18 years ago
108
109
if ( devfn < 0 ) {
110
111
for ( devfn = bus -> devfn_min ; devfn < 256 ; devfn += 8 ) {
if ( ! bus -> devices [ devfn ])
112
113
114
115
116
117
118
119
goto found ;
}
return NULL ;
found : ;
}
pci_dev = qemu_mallocz ( instance_size );
if ( ! pci_dev )
return NULL ;
120
pci_dev -> bus = bus ;
121
122
pci_dev -> devfn = devfn ;
pstrcpy ( pci_dev -> name , sizeof ( pci_dev -> name ), name );
123
memset ( pci_dev -> irq_state , 0 , sizeof ( pci_dev -> irq_state ));
124
125
126
127
128
if ( ! config_read )
config_read = pci_default_read_config ;
if ( ! config_write )
config_write = pci_default_write_config ;
129
130
pci_dev -> config_read = config_read ;
pci_dev -> config_write = config_write ;
131
pci_dev -> irq_index = pci_irq_index ++ ;
132
bus -> devices [ devfn ] = pci_dev ;
133
pci_dev -> irq = qemu_allocate_irqs ( pci_set_irq , pci_dev , 4 );
134
135
136
return pci_dev ;
}
ths
authored
18 years ago
137
138
void pci_register_io_region ( PCIDevice * pci_dev , int region_num ,
uint32_t size , int type ,
139
140
141
PCIMapIORegionFunc * map_func )
{
PCIIORegion * r ;
142
uint32_t addr ;
143
144
if (( unsigned int ) region_num >= PCI_NUM_REGIONS )
145
146
147
148
149
150
return ;
r = & pci_dev -> io_regions [ region_num ];
r -> addr = - 1 ;
r -> size = size ;
r -> type = type ;
r -> map_func = map_func ;
151
152
153
154
155
156
if ( region_num == PCI_ROM_SLOT ) {
addr = 0x30 ;
} else {
addr = 0x10 + region_num * 4 ;
}
* ( uint32_t * )( pci_dev -> config + addr ) = cpu_to_le32 ( type );
157
158
}
159
target_phys_addr_t pci_to_cpu_addr ( target_phys_addr_t addr )
160
{
161
return addr + pci_mem_base ;
162
163
}
164
165
166
167
static void pci_update_mappings ( PCIDevice * d )
{
PCIIORegion * r ;
int cmd , i ;
168
uint32_t last_addr , new_addr , config_ofs ;
ths
authored
18 years ago
169
170
cmd = le16_to_cpu ( * ( uint16_t * )( d -> config + PCI_COMMAND ));
171
for ( i = 0 ; i < PCI_NUM_REGIONS ; i ++ ) {
172
r = & d -> io_regions [ i ];
173
174
175
176
177
if ( i == PCI_ROM_SLOT ) {
config_ofs = 0x30 ;
} else {
config_ofs = 0x10 + i * 4 ;
}
178
179
180
if ( r -> size != 0 ) {
if ( r -> type & PCI_ADDRESS_SPACE_IO ) {
if ( cmd & PCI_COMMAND_IO ) {
ths
authored
18 years ago
181
new_addr = le32_to_cpu ( * ( uint32_t * )( d -> config +
182
config_ofs ));
183
184
185
186
187
188
189
190
191
192
193
194
new_addr = new_addr & ~ ( r -> size - 1 );
last_addr = new_addr + r -> size - 1 ;
/* NOTE: we have only 64K ioports on PC */
if ( last_addr <= new_addr || new_addr == 0 ||
last_addr >= 0x10000 ) {
new_addr = - 1 ;
}
} else {
new_addr = - 1 ;
}
} else {
if ( cmd & PCI_COMMAND_MEMORY ) {
ths
authored
18 years ago
195
new_addr = le32_to_cpu ( * ( uint32_t * )( d -> config +
196
197
198
199
config_ofs ));
/* the ROM slot has a specific enable bit */
if ( i == PCI_ROM_SLOT && ! ( new_addr & 1 ))
goto no_mem_map ;
200
201
202
203
204
205
206
207
208
209
210
new_addr = new_addr & ~ ( r -> size - 1 );
last_addr = new_addr + r -> size - 1 ;
/* NOTE: we do not support wrapping */
/* XXX : as we cannot support really dynamic
mappings , we handle specific values as invalid
mappings . */
if ( last_addr <= new_addr || new_addr == 0 ||
last_addr == - 1 ) {
new_addr = - 1 ;
}
} else {
211
no_mem_map :
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
new_addr = - 1 ;
}
}
/* now do the real mapping */
if ( new_addr != r -> addr ) {
if ( r -> addr != - 1 ) {
if ( r -> type & PCI_ADDRESS_SPACE_IO ) {
int class ;
/* NOTE : specific hack for IDE in PC case :
only one byte must be mapped . */
class = d -> config [ 0x0a ] | ( d -> config [ 0x0b ] << 8 );
if ( class == 0x0101 && r -> size == 4 ) {
isa_unassign_ioport ( r -> addr + 2 , 1 );
} else {
isa_unassign_ioport ( r -> addr , r -> size );
}
} else {
229
cpu_register_physical_memory ( pci_to_cpu_addr ( r -> addr ),
ths
authored
18 years ago
230
r -> size ,
231
232
233
234
235
236
237
238
239
240
241
242
IO_MEM_UNASSIGNED );
}
}
r -> addr = new_addr ;
if ( r -> addr != - 1 ) {
r -> map_func ( d , i , r -> addr , r -> size , r -> type );
}
}
}
}
}
ths
authored
18 years ago
243
uint32_t pci_default_read_config ( PCIDevice * d ,
244
uint32_t address , int len )
245
{
246
uint32_t val ;
ths
authored
18 years ago
247
248
249
250
switch ( len ) {
default :
case 4 :
ths
authored
18 years ago
251
252
253
254
255
256
257
258
259
260
261
262
263
if ( address <= 0xfc ) {
val = le32_to_cpu ( * ( uint32_t * )( d -> config + address ));
break ;
}
/* fall through */
case 2 :
if ( address <= 0xfe ) {
val = le16_to_cpu ( * ( uint16_t * )( d -> config + address ));
break ;
}
/* fall through */
case 1 :
val = d -> config [ address ];
264
265
266
267
268
break ;
}
return val ;
}
ths
authored
18 years ago
269
void pci_default_write_config ( PCIDevice * d ,
270
271
272
uint32_t address , uint32_t val , int len )
{
int can_write , i ;
273
uint32_t end , addr ;
274
ths
authored
18 years ago
275
if ( len == 4 && (( address >= 0x10 && address < 0x10 + 4 * 6 ) ||
276
( address >= 0x30 && address < 0x34 ))) {
277
278
279
PCIIORegion * r ;
int reg ;
280
281
282
283
284
if ( address >= 0x30 ) {
reg = PCI_ROM_SLOT ;
} else {
reg = ( address - 0x10 ) >> 2 ;
}
285
286
287
288
r = & d -> io_regions [ reg ];
if ( r -> size == 0 )
goto default_config ;
/* compute the stored value */
289
290
291
292
293
294
295
296
if ( reg == PCI_ROM_SLOT ) {
/* keep ROM enable bit */
val &= ( ~ ( r -> size - 1 )) | 1 ;
} else {
val &= ~ ( r -> size - 1 );
val |= r -> type ;
}
* ( uint32_t * )( d -> config + address ) = cpu_to_le32 ( val );
297
pci_update_mappings ( d );
298
return ;
299
300
301
}
default_config :
/* not efficient, but simple */
302
addr = address ;
303
304
for ( i = 0 ; i < len ; i ++ ) {
/* default read/write accesses */
305
switch ( d -> config [ 0x0e ]) {
306
case 0x00 :
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
case 0x80 :
switch ( addr ) {
case 0x00 :
case 0x01 :
case 0x02 :
case 0x03 :
case 0x08 :
case 0x09 :
case 0x0a :
case 0x0b :
case 0x0e :
case 0x10 ... 0x27 : /* base */
case 0x30 ... 0x33 : /* rom */
case 0x3d :
can_write = 0 ;
break ;
default :
can_write = 1 ;
break ;
}
327
328
break ;
default :
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
case 0x01 :
switch ( addr ) {
case 0x00 :
case 0x01 :
case 0x02 :
case 0x03 :
case 0x08 :
case 0x09 :
case 0x0a :
case 0x0b :
case 0x0e :
case 0x38 ... 0x3b : /* rom */
case 0x3d :
can_write = 0 ;
break ;
default :
can_write = 1 ;
break ;
}
348
349
350
break ;
}
if ( can_write ) {
351
d -> config [ addr ] = val ;
352
}
ths
authored
18 years ago
353
354
if ( ++ addr > 0xff )
break ;
355
356
357
358
359
360
361
val >>= 8 ;
}
end = address + len ;
if ( end > PCI_COMMAND && address < ( PCI_COMMAND + 2 )) {
/* if the command register is modified, we must modify the mappings */
pci_update_mappings ( d );
362
363
364
}
}
365
void pci_data_write ( void * opaque , uint32_t addr , uint32_t val , int len )
366
{
367
368
369
PCIBus * s = opaque ;
PCIDevice * pci_dev ;
int config_addr , bus_num ;
ths
authored
18 years ago
370
371
372
# if defined ( DEBUG_PCI ) && 0
printf ( "pci_data_write: addr=%08x val=%08x len=%d \n " ,
373
addr , val , len );
374
# endif
375
bus_num = ( addr >> 16 ) & 0xff ;
376
377
378
while ( s && s -> bus_num != bus_num )
s = s -> next ;
if ( ! s )
379
return ;
380
pci_dev = s -> devices [( addr >> 8 ) & 0xff ];
381
382
if ( ! pci_dev )
return ;
383
config_addr = addr & 0xff ;
384
385
386
387
# if defined ( DEBUG_PCI )
printf ( "pci_config_write: %s: addr=%02x val=%08x len=%d \n " ,
pci_dev -> name , config_addr , val , len );
# endif
388
pci_dev -> config_write ( pci_dev , config_addr , val , len );
389
390
}
391
uint32_t pci_data_read ( void * opaque , uint32_t addr , int len )
392
{
393
394
395
PCIBus * s = opaque ;
PCIDevice * pci_dev ;
int config_addr , bus_num ;
396
397
uint32_t val ;
398
bus_num = ( addr >> 16 ) & 0xff ;
399
400
401
while ( s && s -> bus_num != bus_num )
s = s -> next ;
if ( ! s )
402
goto fail ;
403
pci_dev = s -> devices [( addr >> 8 ) & 0xff ];
404
405
if ( ! pci_dev ) {
fail :
406
407
408
409
410
411
412
413
414
415
416
417
switch ( len ) {
case 1 :
val = 0xff ;
break ;
case 2 :
val = 0xffff ;
break ;
default :
case 4 :
val = 0xffffffff ;
break ;
}
418
419
goto the_end ;
}
420
config_addr = addr & 0xff ;
421
422
423
424
425
426
427
428
val = pci_dev -> config_read ( pci_dev , config_addr , len );
# if defined ( DEBUG_PCI )
printf ( "pci_config_read: %s: addr=%02x val=%08x len=%d \n " ,
pci_dev -> name , config_addr , val , len );
# endif
the_end :
# if defined ( DEBUG_PCI ) && 0
printf ( "pci_data_read: addr=%08x val=%08x len=%d \n " ,
429
addr , val , len );
430
431
432
433
# endif
return val ;
}
434
435
/***********************************************************/
/* generic PCI irq support */
436
437
/* 0 <= irq_num <= 3. level must be 0 or 1 */
438
static void pci_set_irq ( void * opaque , int irq_num , int level )
439
{
440
PCIDevice * pci_dev = ( PCIDevice * ) opaque ;
441
442
PCIBus * bus ;
int change ;
ths
authored
18 years ago
443
444
445
446
change = level - pci_dev -> irq_state [ irq_num ];
if ( ! change )
return ;
447
448
pci_dev -> irq_state [ irq_num ] = level ;
449
450
for (;;) {
bus = pci_dev -> bus ;
451
irq_num = bus -> map_irq ( pci_dev , irq_num );
452
453
if ( bus -> set_irq )
break ;
454
455
456
pci_dev = bus -> parent_dev ;
}
bus -> irq_count [ irq_num ] += change ;
457
bus -> set_irq ( bus -> irq_opaque , irq_num , bus -> irq_count [ irq_num ] != 0 );
458
459
}
460
461
/***********************************************************/
/* monitor info on PCI */
462
463
464
465
466
467
typedef struct {
uint16_t class ;
const char * desc ;
} pci_class_desc ;
ths
authored
18 years ago
468
static pci_class_desc pci_class_descriptions [] =
469
{
470
{ 0x0100 , "SCSI controller" },
471
{ 0x0101 , "IDE controller" },
ths
authored
18 years ago
472
473
474
475
476
477
{ 0x0102 , "Floppy controller" },
{ 0x0103 , "IPI controller" },
{ 0x0104 , "RAID controller" },
{ 0x0106 , "SATA controller" },
{ 0x0107 , "SAS controller" },
{ 0x0180 , "Storage controller" },
478
{ 0x0200 , "Ethernet controller" },
ths
authored
18 years ago
479
480
481
482
{ 0x0201 , "Token Ring controller" },
{ 0x0202 , "FDDI controller" },
{ 0x0203 , "ATM controller" },
{ 0x0280 , "Network controller" },
483
{ 0x0300 , "VGA controller" },
ths
authored
18 years ago
484
485
486
487
488
489
490
491
492
493
{ 0x0301 , "XGA controller" },
{ 0x0302 , "3D controller" },
{ 0x0380 , "Display controller" },
{ 0x0400 , "Video controller" },
{ 0x0401 , "Audio controller" },
{ 0x0402 , "Phone" },
{ 0x0480 , "Multimedia controller" },
{ 0x0500 , "RAM controller" },
{ 0x0501 , "Flash controller" },
{ 0x0580 , "Memory controller" },
494
495
{ 0x0600 , "Host bridge" },
{ 0x0601 , "ISA bridge" },
ths
authored
18 years ago
496
497
{ 0x0602 , "EISA bridge" },
{ 0x0603 , "MC bridge" },
498
{ 0x0604 , "PCI bridge" },
ths
authored
18 years ago
499
500
501
502
503
{ 0x0605 , "PCMCIA bridge" },
{ 0x0606 , "NUBUS bridge" },
{ 0x0607 , "CARDBUS bridge" },
{ 0x0608 , "RACEWAY bridge" },
{ 0x0680 , "Bridge" },
504
505
506
507
{ 0x0c03 , "USB controller" },
{ 0 , NULL }
};
508
static void pci_info_device ( PCIDevice * d )
509
{
510
511
int i , class ;
PCIIORegion * r ;
512
pci_class_desc * desc ;
513
514
515
516
517
term_printf ( " Bus %2d, device %3d, function %d: \n " ,
d -> bus -> bus_num , d -> devfn >> 3 , d -> devfn & 7 );
class = le16_to_cpu ( * (( uint16_t * )( d -> config + PCI_CLASS_DEVICE )));
term_printf ( " " );
518
519
520
521
522
523
desc = pci_class_descriptions ;
while ( desc -> desc && class != desc -> class )
desc ++ ;
if ( desc -> desc ) {
term_printf ( "%s" , desc -> desc );
} else {
524
term_printf ( "Class %04x" , class );
525
}
526
527
528
term_printf ( ": PCI device %04x:%04x \n " ,
le16_to_cpu ( * (( uint16_t * )( d -> config + PCI_VENDOR_ID ))),
le16_to_cpu ( * (( uint16_t * )( d -> config + PCI_DEVICE_ID ))));
529
530
531
if ( d -> config [ PCI_INTERRUPT_PIN ] != 0 ) {
term_printf ( " IRQ %d. \n " , d -> config [ PCI_INTERRUPT_LINE ]);
532
}
533
534
535
if ( class == 0x0604 ) {
term_printf ( " BUS %d. \n " , d -> config [ 0x19 ]);
}
536
537
538
539
540
for ( i = 0 ; i < PCI_NUM_REGIONS ; i ++ ) {
r = & d -> io_regions [ i ];
if ( r -> size != 0 ) {
term_printf ( " BAR%d: " , i );
if ( r -> type & PCI_ADDRESS_SPACE_IO ) {
ths
authored
18 years ago
541
term_printf ( "I/O at 0x%04x [0x%04x]. \n " ,
542
543
r -> addr , r -> addr + r -> size - 1 );
} else {
ths
authored
18 years ago
544
term_printf ( "32 bit memory at 0x%08x [0x%08x]. \n " ,
545
546
547
r -> addr , r -> addr + r -> size - 1 );
}
}
548
}
549
550
551
if ( class == 0x0604 && d -> config [ 0x19 ] != 0 ) {
pci_for_each_device ( d -> config [ 0x19 ], pci_info_device );
}
552
553
}
554
void pci_for_each_device ( int bus_num , void ( * fn )( PCIDevice * d ))
555
{
556
PCIBus * bus = first_bus ;
557
PCIDevice * d ;
558
int devfn ;
ths
authored
18 years ago
559
560
561
while ( bus && bus -> bus_num != bus_num )
bus = bus -> next ;
562
563
564
565
566
567
if ( bus ) {
for ( devfn = 0 ; devfn < 256 ; devfn ++ ) {
d = bus -> devices [ devfn ];
if ( d )
fn ( d );
}
568
569
570
}
}
571
void pci_info ( void )
572
{
573
pci_for_each_device ( 0 , pci_info_device );
574
}
575
576
/* Initialize a PCI NIC. */
ths
authored
18 years ago
577
void pci_nic_init ( PCIBus * bus , NICInfo * nd , int devfn )
578
579
{
if ( strcmp ( nd -> model , "ne2k_pci" ) == 0 ) {
ths
authored
18 years ago
580
pci_ne2000_init ( bus , nd , devfn );
ths
authored
18 years ago
581
582
583
584
585
586
} else if ( strcmp ( nd -> model , "i82551" ) == 0 ) {
pci_i82551_init ( bus , nd , devfn );
} else if ( strcmp ( nd -> model , "i82557b" ) == 0 ) {
pci_i82557b_init ( bus , nd , devfn );
} else if ( strcmp ( nd -> model , "i82559er" ) == 0 ) {
pci_i82559er_init ( bus , nd , devfn );
587
} else if ( strcmp ( nd -> model , "rtl8139" ) == 0 ) {
ths
authored
18 years ago
588
pci_rtl8139_init ( bus , nd , devfn );
589
} else if ( strcmp ( nd -> model , "pcnet" ) == 0 ) {
ths
authored
18 years ago
590
pci_pcnet_init ( bus , nd , devfn );
591
592
593
594
} else if ( strcmp ( nd -> model , "?" ) == 0 ) {
fprintf ( stderr , "qemu: Supported PCI NICs: i82551 i82557b i82559er"
" ne2k_pci pcnet rtl8139 \n " );
exit ( 1 );
595
596
597
598
599
600
} else {
fprintf ( stderr , "qemu: Unsupported NIC: %s \n " , nd -> model );
exit ( 1 );
}
}
601
602
603
604
605
typedef struct {
PCIDevice dev ;
PCIBus * bus ;
} PCIBridge ;
ths
authored
18 years ago
606
void pci_bridge_write_config ( PCIDevice * d ,
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
uint32_t address , uint32_t val , int len )
{
PCIBridge * s = ( PCIBridge * ) d ;
if ( address == 0x19 || ( address == 0x18 && len > 1 )) {
if ( address == 0x19 )
s -> bus -> bus_num = val & 0xff ;
else
s -> bus -> bus_num = ( val >> 8 ) & 0xff ;
# if defined ( DEBUG_PCI )
printf ( "pci-bridge: %s: Assigned bus %d \n " , d -> name , s -> bus -> bus_num );
# endif
}
pci_default_write_config ( d , address , val , len );
}
PCIBus * pci_bridge_init ( PCIBus * bus , int devfn , uint32_t id ,
pci_map_irq_fn map_irq , const char * name )
{
PCIBridge * s ;
ths
authored
18 years ago
627
s = ( PCIBridge * ) pci_register_device ( bus , name , sizeof ( PCIBridge ),
628
629
devfn , NULL , pci_bridge_write_config );
s -> dev . config [ 0x00 ] = id >> 16 ;
ths
authored
18 years ago
630
s -> dev . config [ 0x01 ] = id >> 24 ;
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
s -> dev . config [ 0x02 ] = id ; // device_id
s -> dev . config [ 0x03 ] = id >> 8 ;
s -> dev . config [ 0x04 ] = 0x06 ; // command = bus master , pci mem
s -> dev . config [ 0x05 ] = 0x00 ;
s -> dev . config [ 0x06 ] = 0xa0 ; // status = fast back - to - back , 66 MHz , no error
s -> dev . config [ 0x07 ] = 0x00 ; // status = fast devsel
s -> dev . config [ 0x08 ] = 0x00 ; // revision
s -> dev . config [ 0x09 ] = 0x00 ; // programming i / f
s -> dev . config [ 0x0A ] = 0x04 ; // class_sub = PCI to PCI bridge
s -> dev . config [ 0x0B ] = 0x06 ; // class_base = PCI_bridge
s -> dev . config [ 0x0D ] = 0x10 ; // latency_timer
s -> dev . config [ 0x0E ] = 0x81 ; // header_type
s -> dev . config [ 0x1E ] = 0xa0 ; // secondary status
s -> bus = pci_register_secondary_bus ( & s -> dev , map_irq );
return s -> bus ;
}