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
* 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 .
*/
24
25
26
27
# include "hw.h"
# include "pci.h"
# include "console.h"
# include "net.h"
28
29
30
// # define DEBUG_PCI
31
32
33
struct PCIBus {
int bus_num ;
int devfn_min ;
34
pci_set_irq_fn set_irq ;
35
pci_map_irq_fn map_irq ;
36
uint32_t config_reg ; /* XXX: suppress */
37
38
/* low level pic */
SetIRQFunc * low_set_irq ;
39
qemu_irq * irq_opaque ;
40
PCIDevice * devices [ 256 ];
41
42
PCIDevice * parent_dev ;
PCIBus * next ;
43
44
/* The bus IRQ state is the logical OR of the connected devices .
Keep a count of the number of devices with raised IRQs . */
45
int nirq ;
46
int irq_count [];
47
};
48
49
static void pci_update_mappings ( PCIDevice * d );
50
static void pci_set_irq ( void * opaque , int irq_num , int level );
51
52
target_phys_addr_t pci_mem_base ;
53
static int pci_irq_index ;
54
55
static PCIBus * first_bus ;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
static void pcibus_save ( QEMUFile * f , void * opaque )
{
PCIBus * bus = ( PCIBus * ) opaque ;
int i ;
qemu_put_be32 ( f , bus -> nirq );
for ( i = 0 ; i < bus -> nirq ; i ++ )
qemu_put_be32 ( f , bus -> irq_count [ i ]);
}
static int pcibus_load ( QEMUFile * f , void * opaque , int version_id )
{
PCIBus * bus = ( PCIBus * ) opaque ;
int i , nirq ;
if ( version_id != 1 )
return - EINVAL ;
nirq = qemu_get_be32 ( f );
if ( bus -> nirq != nirq ) {
fprintf ( stderr , "pcibus_load: nirq mismatch: src=%d dst=%d \n " ,
nirq , bus -> nirq );
return - EINVAL ;
}
for ( i = 0 ; i < nirq ; i ++ )
bus -> irq_count [ i ] = qemu_get_be32 ( f );
return 0 ;
}
87
PCIBus * pci_register_bus ( pci_set_irq_fn set_irq , pci_map_irq_fn map_irq ,
88
qemu_irq * pic , int devfn_min , int nirq )
89
90
{
PCIBus * bus ;
91
92
static int nbus = 0 ;
93
bus = qemu_mallocz ( sizeof ( PCIBus ) + ( nirq * sizeof ( int )));
94
bus -> set_irq = set_irq ;
95
bus -> map_irq = map_irq ;
96
97
bus -> irq_opaque = pic ;
bus -> devfn_min = devfn_min ;
98
bus -> nirq = nirq ;
99
first_bus = bus ;
100
register_savevm ( "PCIBUS" , nbus ++ , 1 , pcibus_save , pcibus_load , bus );
101
102
return bus ;
}
103
104
static PCIBus * pci_register_secondary_bus ( PCIDevice * dev , pci_map_irq_fn map_irq )
105
106
107
108
109
110
111
112
113
114
{
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 ;
}
115
116
117
118
119
int pci_bus_num ( PCIBus * s )
{
return s -> bus_num ;
}
120
void pci_device_save ( PCIDevice * s , QEMUFile * f )
121
{
122
123
124
int i ;
qemu_put_be32 ( f , 2 ); /* PCI device version */
125
qemu_put_buffer ( f , s -> config , 256 );
126
127
for ( i = 0 ; i < 4 ; i ++ )
qemu_put_be32 ( f , s -> irq_state [ i ]);
128
129
}
130
int pci_device_load ( PCIDevice * s , QEMUFile * f )
131
{
132
uint32_t version_id ;
133
134
int i ;
135
version_id = qemu_get_be32 ( f );
136
if ( version_id > 2 )
137
138
return - EINVAL ;
qemu_get_buffer ( f , s -> config , 256 );
139
pci_update_mappings ( s );
140
141
142
143
144
if ( version_id >= 2 )
for ( i = 0 ; i < 4 ; i ++ )
s -> irq_state [ i ] = qemu_get_be32 ( f );
145
146
147
return 0 ;
}
148
/* -1 for devfn means auto assign */
ths
authored
18 years ago
149
PCIDevice * pci_register_device ( PCIBus * bus , const char * name ,
150
int instance_size , int devfn ,
ths
authored
18 years ago
151
PCIConfigReadFunc * config_read ,
152
153
PCIConfigWriteFunc * config_write )
{
154
PCIDevice * pci_dev ;
155
156
157
if ( pci_irq_index >= PCI_DEVICES_MAX )
return NULL ;
ths
authored
18 years ago
158
159
if ( devfn < 0 ) {
160
161
for ( devfn = bus -> devfn_min ; devfn < 256 ; devfn += 8 ) {
if ( ! bus -> devices [ devfn ])
162
163
164
165
166
167
168
169
goto found ;
}
return NULL ;
found : ;
}
pci_dev = qemu_mallocz ( instance_size );
if ( ! pci_dev )
return NULL ;
170
pci_dev -> bus = bus ;
171
172
pci_dev -> devfn = devfn ;
pstrcpy ( pci_dev -> name , sizeof ( pci_dev -> name ), name );
173
memset ( pci_dev -> irq_state , 0 , sizeof ( pci_dev -> irq_state ));
174
175
176
177
178
if ( ! config_read )
config_read = pci_default_read_config ;
if ( ! config_write )
config_write = pci_default_write_config ;
179
180
pci_dev -> config_read = config_read ;
pci_dev -> config_write = config_write ;
181
pci_dev -> irq_index = pci_irq_index ++ ;
182
bus -> devices [ devfn ] = pci_dev ;
183
pci_dev -> irq = qemu_allocate_irqs ( pci_set_irq , pci_dev , 4 );
184
185
186
return pci_dev ;
}
ths
authored
18 years ago
187
188
void pci_register_io_region ( PCIDevice * pci_dev , int region_num ,
uint32_t size , int type ,
189
190
191
PCIMapIORegionFunc * map_func )
{
PCIIORegion * r ;
192
uint32_t addr ;
193
194
if (( unsigned int ) region_num >= PCI_NUM_REGIONS )
195
196
197
198
199
200
return ;
r = & pci_dev -> io_regions [ region_num ];
r -> addr = - 1 ;
r -> size = size ;
r -> type = type ;
r -> map_func = map_func ;
201
202
203
204
205
206
if ( region_num == PCI_ROM_SLOT ) {
addr = 0x30 ;
} else {
addr = 0x10 + region_num * 4 ;
}
* ( uint32_t * )( pci_dev -> config + addr ) = cpu_to_le32 ( type );
207
208
}
209
static target_phys_addr_t pci_to_cpu_addr ( target_phys_addr_t addr )
210
{
211
return addr + pci_mem_base ;
212
213
}
214
215
216
217
static void pci_update_mappings ( PCIDevice * d )
{
PCIIORegion * r ;
int cmd , i ;
218
uint32_t last_addr , new_addr , config_ofs ;
ths
authored
18 years ago
219
220
cmd = le16_to_cpu ( * ( uint16_t * )( d -> config + PCI_COMMAND ));
221
for ( i = 0 ; i < PCI_NUM_REGIONS ; i ++ ) {
222
r = & d -> io_regions [ i ];
223
224
225
226
227
if ( i == PCI_ROM_SLOT ) {
config_ofs = 0x30 ;
} else {
config_ofs = 0x10 + i * 4 ;
}
228
229
230
if ( r -> size != 0 ) {
if ( r -> type & PCI_ADDRESS_SPACE_IO ) {
if ( cmd & PCI_COMMAND_IO ) {
ths
authored
18 years ago
231
new_addr = le32_to_cpu ( * ( uint32_t * )( d -> config +
232
config_ofs ));
233
234
235
236
237
238
239
240
241
242
243
244
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
245
new_addr = le32_to_cpu ( * ( uint32_t * )( d -> config +
246
247
248
249
config_ofs ));
/* the ROM slot has a specific enable bit */
if ( i == PCI_ROM_SLOT && ! ( new_addr & 1 ))
goto no_mem_map ;
250
251
252
253
254
255
256
257
258
259
260
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 {
261
no_mem_map :
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
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 {
279
cpu_register_physical_memory ( pci_to_cpu_addr ( r -> addr ),
ths
authored
18 years ago
280
r -> size ,
281
282
283
284
285
286
287
288
289
290
291
292
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
293
uint32_t pci_default_read_config ( PCIDevice * d ,
294
uint32_t address , int len )
295
{
296
uint32_t val ;
ths
authored
18 years ago
297
298
299
300
switch ( len ) {
default :
case 4 :
ths
authored
18 years ago
301
302
303
304
305
306
307
308
309
310
311
312
313
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 ];
314
315
316
317
318
break ;
}
return val ;
}
ths
authored
18 years ago
319
void pci_default_write_config ( PCIDevice * d ,
320
321
322
uint32_t address , uint32_t val , int len )
{
int can_write , i ;
323
uint32_t end , addr ;
324
ths
authored
18 years ago
325
if ( len == 4 && (( address >= 0x10 && address < 0x10 + 4 * 6 ) ||
326
( address >= 0x30 && address < 0x34 ))) {
327
328
329
PCIIORegion * r ;
int reg ;
330
331
332
333
334
if ( address >= 0x30 ) {
reg = PCI_ROM_SLOT ;
} else {
reg = ( address - 0x10 ) >> 2 ;
}
335
336
337
338
r = & d -> io_regions [ reg ];
if ( r -> size == 0 )
goto default_config ;
/* compute the stored value */
339
340
341
342
343
344
345
346
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 );
347
pci_update_mappings ( d );
348
return ;
349
350
351
}
default_config :
/* not efficient, but simple */
352
addr = address ;
353
354
for ( i = 0 ; i < len ; i ++ ) {
/* default read/write accesses */
355
switch ( d -> config [ 0x0e ]) {
356
case 0x00 :
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
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 ;
}
377
378
break ;
default :
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
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 ;
}
398
399
400
break ;
}
if ( can_write ) {
401
d -> config [ addr ] = val ;
402
}
ths
authored
18 years ago
403
404
if ( ++ addr > 0xff )
break ;
405
406
407
408
409
410
411
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 );
412
413
414
}
}
415
void pci_data_write ( void * opaque , uint32_t addr , uint32_t val , int len )
416
{
417
418
419
PCIBus * s = opaque ;
PCIDevice * pci_dev ;
int config_addr , bus_num ;
ths
authored
18 years ago
420
421
422
# if defined ( DEBUG_PCI ) && 0
printf ( "pci_data_write: addr=%08x val=%08x len=%d \n " ,
423
addr , val , len );
424
# endif
425
bus_num = ( addr >> 16 ) & 0xff ;
426
427
428
while ( s && s -> bus_num != bus_num )
s = s -> next ;
if ( ! s )
429
return ;
430
pci_dev = s -> devices [( addr >> 8 ) & 0xff ];
431
432
if ( ! pci_dev )
return ;
433
config_addr = addr & 0xff ;
434
435
436
437
# if defined ( DEBUG_PCI )
printf ( "pci_config_write: %s: addr=%02x val=%08x len=%d \n " ,
pci_dev -> name , config_addr , val , len );
# endif
438
pci_dev -> config_write ( pci_dev , config_addr , val , len );
439
440
}
441
uint32_t pci_data_read ( void * opaque , uint32_t addr , int len )
442
{
443
444
445
PCIBus * s = opaque ;
PCIDevice * pci_dev ;
int config_addr , bus_num ;
446
447
uint32_t val ;
448
bus_num = ( addr >> 16 ) & 0xff ;
449
450
451
while ( s && s -> bus_num != bus_num )
s = s -> next ;
if ( ! s )
452
goto fail ;
453
pci_dev = s -> devices [( addr >> 8 ) & 0xff ];
454
455
if ( ! pci_dev ) {
fail :
456
457
458
459
460
461
462
463
464
465
466
467
switch ( len ) {
case 1 :
val = 0xff ;
break ;
case 2 :
val = 0xffff ;
break ;
default :
case 4 :
val = 0xffffffff ;
break ;
}
468
469
goto the_end ;
}
470
config_addr = addr & 0xff ;
471
472
473
474
475
476
477
478
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 " ,
479
addr , val , len );
480
481
482
483
# endif
return val ;
}
484
485
/***********************************************************/
/* generic PCI irq support */
486
487
/* 0 <= irq_num <= 3. level must be 0 or 1 */
488
static void pci_set_irq ( void * opaque , int irq_num , int level )
489
{
490
PCIDevice * pci_dev = ( PCIDevice * ) opaque ;
491
492
PCIBus * bus ;
int change ;
ths
authored
18 years ago
493
494
495
496
change = level - pci_dev -> irq_state [ irq_num ];
if ( ! change )
return ;
497
498
pci_dev -> irq_state [ irq_num ] = level ;
499
500
for (;;) {
bus = pci_dev -> bus ;
501
irq_num = bus -> map_irq ( pci_dev , irq_num );
502
503
if ( bus -> set_irq )
break ;
504
505
506
pci_dev = bus -> parent_dev ;
}
bus -> irq_count [ irq_num ] += change ;
507
bus -> set_irq ( bus -> irq_opaque , irq_num , bus -> irq_count [ irq_num ] != 0 );
508
509
}
510
511
/***********************************************************/
/* monitor info on PCI */
512
513
514
515
516
517
typedef struct {
uint16_t class ;
const char * desc ;
} pci_class_desc ;
518
static const pci_class_desc pci_class_descriptions [] =
519
{
520
{ 0x0100 , "SCSI controller" },
521
{ 0x0101 , "IDE controller" },
ths
authored
18 years ago
522
523
524
525
526
527
{ 0x0102 , "Floppy controller" },
{ 0x0103 , "IPI controller" },
{ 0x0104 , "RAID controller" },
{ 0x0106 , "SATA controller" },
{ 0x0107 , "SAS controller" },
{ 0x0180 , "Storage controller" },
528
{ 0x0200 , "Ethernet controller" },
ths
authored
18 years ago
529
530
531
532
{ 0x0201 , "Token Ring controller" },
{ 0x0202 , "FDDI controller" },
{ 0x0203 , "ATM controller" },
{ 0x0280 , "Network controller" },
533
{ 0x0300 , "VGA controller" },
ths
authored
18 years ago
534
535
536
537
538
539
540
541
542
543
{ 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" },
544
545
{ 0x0600 , "Host bridge" },
{ 0x0601 , "ISA bridge" },
ths
authored
18 years ago
546
547
{ 0x0602 , "EISA bridge" },
{ 0x0603 , "MC bridge" },
548
{ 0x0604 , "PCI bridge" },
ths
authored
18 years ago
549
550
551
552
553
{ 0x0605 , "PCMCIA bridge" },
{ 0x0606 , "NUBUS bridge" },
{ 0x0607 , "CARDBUS bridge" },
{ 0x0608 , "RACEWAY bridge" },
{ 0x0680 , "Bridge" },
554
555
556
557
{ 0x0c03 , "USB controller" },
{ 0 , NULL }
};
558
static void pci_info_device ( PCIDevice * d )
559
{
560
561
int i , class ;
PCIIORegion * r ;
562
const pci_class_desc * desc ;
563
564
565
566
567
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 ( " " );
568
569
570
571
572
573
desc = pci_class_descriptions ;
while ( desc -> desc && class != desc -> class )
desc ++ ;
if ( desc -> desc ) {
term_printf ( "%s" , desc -> desc );
} else {
574
term_printf ( "Class %04x" , class );
575
}
576
577
578
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 ))));
579
580
581
if ( d -> config [ PCI_INTERRUPT_PIN ] != 0 ) {
term_printf ( " IRQ %d. \n " , d -> config [ PCI_INTERRUPT_LINE ]);
582
}
583
584
585
if ( class == 0x0604 ) {
term_printf ( " BUS %d. \n " , d -> config [ 0x19 ]);
}
586
587
588
589
590
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
591
term_printf ( "I/O at 0x%04x [0x%04x]. \n " ,
592
593
r -> addr , r -> addr + r -> size - 1 );
} else {
ths
authored
18 years ago
594
term_printf ( "32 bit memory at 0x%08x [0x%08x]. \n " ,
595
596
597
r -> addr , r -> addr + r -> size - 1 );
}
}
598
}
599
600
601
if ( class == 0x0604 && d -> config [ 0x19 ] != 0 ) {
pci_for_each_device ( d -> config [ 0x19 ], pci_info_device );
}
602
603
}
604
void pci_for_each_device ( int bus_num , void ( * fn )( PCIDevice * d ))
605
{
606
PCIBus * bus = first_bus ;
607
PCIDevice * d ;
608
int devfn ;
ths
authored
18 years ago
609
610
611
while ( bus && bus -> bus_num != bus_num )
bus = bus -> next ;
612
613
614
615
616
617
if ( bus ) {
for ( devfn = 0 ; devfn < 256 ; devfn ++ ) {
d = bus -> devices [ devfn ];
if ( d )
fn ( d );
}
618
619
620
}
}
621
void pci_info ( void )
622
{
623
pci_for_each_device ( 0 , pci_info_device );
624
}
625
626
/* Initialize a PCI NIC. */
ths
authored
18 years ago
627
void pci_nic_init ( PCIBus * bus , NICInfo * nd , int devfn )
628
629
{
if ( strcmp ( nd -> model , "ne2k_pci" ) == 0 ) {
ths
authored
18 years ago
630
pci_ne2000_init ( bus , nd , devfn );
ths
authored
18 years ago
631
632
633
634
635
636
} 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 );
637
} else if ( strcmp ( nd -> model , "rtl8139" ) == 0 ) {
ths
authored
18 years ago
638
pci_rtl8139_init ( bus , nd , devfn );
639
640
} else if ( strcmp ( nd -> model , "e1000" ) == 0 ) {
pci_e1000_init ( bus , nd , devfn );
641
} else if ( strcmp ( nd -> model , "pcnet" ) == 0 ) {
ths
authored
18 years ago
642
pci_pcnet_init ( bus , nd , devfn );
643
644
} else if ( strcmp ( nd -> model , "?" ) == 0 ) {
fprintf ( stderr , "qemu: Supported PCI NICs: i82551 i82557b i82559er"
645
" ne2k_pci pcnet rtl8139 e1000 \n " );
646
exit ( 1 );
647
648
649
650
651
652
} else {
fprintf ( stderr , "qemu: Unsupported NIC: %s \n " , nd -> model );
exit ( 1 );
}
}
653
654
655
656
657
typedef struct {
PCIDevice dev ;
PCIBus * bus ;
} PCIBridge ;
658
static void pci_bridge_write_config ( PCIDevice * d ,
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
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
679
s = ( PCIBridge * ) pci_register_device ( bus , name , sizeof ( PCIBridge ),
680
681
devfn , NULL , pci_bridge_write_config );
s -> dev . config [ 0x00 ] = id >> 16 ;
ths
authored
18 years ago
682
s -> dev . config [ 0x01 ] = id >> 24 ;
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
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 ;
}