/[gxemul]/upstream/0.3.7/src/devices/bus_pci.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.7/src/devices/bus_pci.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 21 - (show annotations)
Mon Oct 8 16:19:28 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 26635 byte(s)
0.3.7
1 /*
2 * Copyright (C) 2004-2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: bus_pci.c,v 1.40 2005/11/25 03:59:58 debug Exp $
29 *
30 * Generic PCI bus framework. This is not a normal "device", but is used by
31 * individual PCI controllers and devices.
32 *
33 * See NetBSD's pcidevs.h for more PCI vendor and device identifiers.
34 *
35 * TODO:
36 *
37 * x) Allow guest OSes to do runtime address fixups (i.e. actually
38 * move a device from one address to another).
39 *
40 * x) Generalize the PCI and legacy ISA interrupt routing stuff.
41 *
42 * x) Make sure that pci_little_endian is used correctly everywhere.
43 */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 #define BUS_PCI_C
50
51 #include "bus_pci.h"
52 #include "cpu.h"
53 #include "device.h"
54 #include "devices.h"
55 #include "diskimage.h"
56 #include "machine.h"
57 #include "memory.h"
58 #include "misc.h"
59
60 extern int verbose;
61
62
63 /* #define debug fatal */
64
65
66 static void reverse(uint64_t *p, int len)
67 {
68 uint64_t x = *p, y = 0;
69 int i;
70 for (i=0; i<len; i++) {
71 y <<= 8;
72 y |= ((x >> (8*i)) & 0xff);
73 }
74 *p = y;
75 }
76
77
78 /*
79 * bus_pci_data_access():
80 *
81 * Reads from and writes to the PCI configuration registers of a device.
82 */
83 void bus_pci_data_access(struct cpu *cpu, struct memory *mem,
84 uint64_t *data, int len, int writeflag, struct pci_data *pci_data)
85 {
86 struct pci_device *dev;
87 int bus, device, function, registernr;
88 unsigned char *cfg_base;
89 uint64_t x, idata = *data;
90
91 if (cpu->byte_order == EMUL_BIG_ENDIAN)
92 reverse(&idata, len);
93
94 /* Get the bus, device, and function numbers from the address: */
95 bus = (pci_data->pci_addr >> 16) & 0xff;
96 device = (pci_data->pci_addr >> 11) & 0x1f;
97 function = (pci_data->pci_addr >> 8) & 0x7;
98 registernr = (pci_data->pci_addr) & 0xff;
99
100 /* Scan through the list of pci_device entries. */
101 dev = pci_data->first_device;
102 while (dev != NULL) {
103 if (dev->bus == bus && dev->function == function &&
104 dev->device == device)
105 break;
106 dev = dev->next;
107 }
108
109 /* No device? Then return emptiness. */
110 if (dev == NULL) {
111 if ((pci_data->pci_addr & 0xff) == 0)
112 *data = 0xffffffff;
113 else
114 *data = 0;
115 return;
116 }
117
118 /* Return normal config data, or length data? */
119 if (pci_data->last_was_write_ffffffff &&
120 registernr >= PCI_MAPREG_START && registernr <= PCI_MAPREG_END - 4)
121 cfg_base = dev->cfg_mem_size;
122 else
123 cfg_base = dev->cfg_mem;
124
125 /* Read data as little-endian: */
126 x = 0;
127 if (registernr + len - 1 < PCI_CFG_MEM_SIZE) {
128 x = cfg_base[registernr];
129 if (len > 1)
130 x |= (cfg_base[registernr+1] << 8);
131 if (len > 2)
132 x |= (cfg_base[registernr+2] << 16);
133 if (len > 3)
134 x |= ((uint64_t)cfg_base[registernr+3] << 24);
135 if (len > 4)
136 fatal("TODO: more than 32-bit PCI access?\n");
137 }
138
139 /* Register write: */
140 if (writeflag == MEM_WRITE) {
141 debug("[ bus_pci: write to PCI DATA: data = 0x%016llx ]\n",
142 (long long)idata);
143 if (idata == 0xffffffffULL && registernr >= PCI_MAPREG_START
144 && registernr <= PCI_MAPREG_END - 4) {
145 pci_data->last_was_write_ffffffff = 1;
146 return;
147 }
148 /* Writes are not really supported yet: */
149 if (idata != x) {
150 debug("[ bus_pci: write to PCI DATA: data = 0x%08llx"
151 " differs from current value 0x%08llx; NOT YET"
152 " SUPPORTED. bus %i, device %i, function %i (%s)"
153 " register 0x%02x ]\n", (long long)idata,
154 (long long)x, bus, device, function, dev->name,
155 registernr);
156 }
157 return;
158 }
159
160 /* Register read: */
161 if (cpu->byte_order == EMUL_BIG_ENDIAN)
162 reverse(&x, len);
163 *data = x;
164
165 pci_data->last_was_write_ffffffff = 0;
166
167 debug("[ bus_pci: read from PCI DATA, addr = 0x%08lx (bus %i, device "
168 "%i, function %i (%s) register 0x%02x): 0x%08lx ]\n", (long)
169 pci_data->pci_addr, bus, device, function, dev->name,
170 registernr, (long)*data);
171 }
172
173
174 /*
175 * bus_pci_access():
176 *
177 * relative_addr should be either BUS_PCI_ADDR or BUS_PCI_DATA. The uint64_t
178 * pointed to by data should contain the word to be written to the pci bus,
179 * or a placeholder for information read from the bus.
180 *
181 * Returns 1 if ok, 0 on error.
182 */
183 int bus_pci_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,
184 uint64_t *data, int len, int writeflag, struct pci_data *pci_data)
185 {
186 if (writeflag == MEM_READ)
187 *data = 0;
188
189 switch (relative_addr) {
190
191 case BUS_PCI_ADDR:
192 if (writeflag == MEM_WRITE) {
193 debug("[ bus_pci: write to PCI ADDR: data = 0x%016llx"
194 " ]\n", (long long)*data);
195 pci_data->pci_addr = *data;
196
197 /*
198 * Big-endian systems (e.g. PowerPC) seem to access
199 * PCI config data using little-endian accesses.
200 */
201 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
202 uint32_t t = pci_data->pci_addr;
203 pci_data->pci_addr = ((t >> 24) & 255)
204 | ((t >> 8) & 0xff00)
205 | ((t << 8) & 0xff0000)
206 | ((t << 24) & 0xff000000);
207 }
208
209 /* Linux seems to use type 0 even when it does
210 type 1 detection. Hm. This is commented for now. */
211 /* if (pci_data->pci_addr & 1)
212 fatal("[ bus_pci: WARNING! pci type 0 not"
213 " yet implemented! ]\n"); */
214 } else {
215 debug("[ bus_pci: read from PCI ADDR (data = "
216 "0x%016llx) ]\n", (long long)pci_data->pci_addr);
217 *data = pci_data->pci_addr;
218 }
219 break;
220
221 case BUS_PCI_DATA:
222 bus_pci_data_access(cpu, mem, data, len, writeflag, pci_data);
223 break;
224
225 default:if (writeflag == MEM_READ) {
226 debug("[ bus_pci: read from unimplemented addr "
227 "0x%x ]\n", (int)relative_addr);
228 *data = 0;
229 } else {
230 debug("[ bus_pci: write to unimplemented addr "
231 "0x%x: 0x%llx ]\n", (int)relative_addr,
232 (long long)*data);
233 }
234 }
235
236 return 1;
237 }
238
239
240 /*
241 * bus_pci_add():
242 *
243 * Add a PCI device to a bus_pci device.
244 */
245 void bus_pci_add(struct machine *machine, struct pci_data *pci_data,
246 struct memory *mem, int bus, int device, int function,
247 char *name)
248 {
249 struct pci_device *pd;
250 int ofs;
251 void (*init)(struct machine *, struct memory *, struct pci_device *);
252
253 if (pci_data == NULL) {
254 fatal("bus_pci_add(): pci_data == NULL!\n");
255 exit(1);
256 }
257
258 /* Find the PCI device: */
259 init = pci_lookup_initf(name);
260
261 /* Make sure this bus/device/function number isn't already in use: */
262 pd = pci_data->first_device;
263 while (pd != NULL) {
264 if (pd->bus == bus && pd->device == device &&
265 pd->function == function) {
266 fatal("bus_pci_add(): (bus %i, device %i, function"
267 " %i) already in use\n", bus, device, function);
268 exit(1);
269 }
270 pd = pd->next;
271 }
272
273 pd = malloc(sizeof(struct pci_device));
274 if (pd == NULL) {
275 fprintf(stderr, "out of memory\n");
276 exit(1);
277 }
278
279 memset(pd, 0, sizeof(struct pci_device));
280
281 /* Add the new device first in the PCI bus' chain: */
282 pd->next = pci_data->first_device;
283 pci_data->first_device = pd;
284
285 pd->pcibus = pci_data;
286 pd->name = strdup(name);
287 pd->bus = bus;
288 pd->device = device;
289 pd->function = function;
290
291 /*
292 * Initialize with some default values:
293 *
294 * TODO: The command status register is best to set up per device,
295 * just enabling all bits like this is not really good.
296 * The size registers should also be set up on a per-device
297 * basis.
298 */
299 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x00ffffffULL);
300 for (ofs = PCI_MAPREG_START; ofs < PCI_MAPREG_END; ofs += 4)
301 PCI_SET_DATA_SIZE(ofs, 0x00400000 - 1);
302
303 if (init == NULL) {
304 fatal("No init function for PCI device \"%s\"?\n", name);
305 exit(1);
306 }
307
308 /* Call the PCI device' init function: */
309 init(machine, mem, pd);
310 }
311
312
313 /*
314 * allocate_device_space():
315 *
316 * Used by glue code (see below) to allocate space for a PCI device.
317 *
318 * The returned values in portp and memp are the actual (emulated) addresses
319 * that the device should use. (Normally only one of these is actually used.)
320 *
321 * TODO: PCI irqs?
322 */
323 static void allocate_device_space(struct pci_device *pd,
324 uint64_t portsize, uint64_t memsize,
325 uint64_t *portp, uint64_t *memp)
326 {
327 uint64_t port, mem;
328
329 /* Calculate an aligned starting port: */
330 port = pd->pcibus->cur_pci_portbase;
331 if (portsize != 0) {
332 port = ((port - 1) | (portsize - 1)) + 1;
333 pd->pcibus->cur_pci_portbase = port;
334 PCI_SET_DATA(PCI_MAPREG_START, port | PCI_MAPREG_TYPE_IO);
335 PCI_SET_DATA_SIZE(PCI_MAPREG_START, portsize - 1);
336 }
337
338 /* Calculate an aligned starting memory location: */
339 mem = pd->pcibus->cur_pci_membase;
340 if (memsize != 0) {
341 mem = ((mem - 1) | (memsize - 1)) + 1;
342 pd->pcibus->cur_pci_membase = mem;
343 PCI_SET_DATA(PCI_MAPREG_START + 0x04, mem);
344 PCI_SET_DATA_SIZE(PCI_MAPREG_START + 0x04, memsize - 1);
345 }
346
347 *portp = port + pd->pcibus->pci_actual_io_offset;
348 *memp = mem + pd->pcibus->pci_actual_mem_offset;
349
350 if (verbose >= 2) {
351 debug("pci device '%s' at", pd->name);
352 if (portsize != 0)
353 debug(" port 0x%llx-0x%llx", (long long)pd->pcibus->
354 cur_pci_portbase, (long long)(pd->pcibus->
355 cur_pci_portbase + portsize - 1));
356 if (memsize != 0)
357 debug(" mem 0x%llx-0x%llx", (long long)pd->pcibus->
358 cur_pci_membase, (long long)(pd->pcibus->
359 cur_pci_membase + memsize - 1));
360 debug("\n");
361 }
362
363 pd->pcibus->cur_pci_portbase += portsize;
364 pd->pcibus->cur_pci_membase += memsize;
365 }
366
367
368 /*
369 * bus_pci_init():
370 *
371 * This doesn't register a device, but instead returns a pointer to a struct
372 * which should be passed to bus_pci_access() when accessing the PCI bus.
373 *
374 * irq_nr is the (optional) IRQ nr that this PCI bus interrupts at.
375 *
376 * pci_portbase, pci_membase, and pci_irqbase are the port, memory, and
377 * interrupt bases for PCI devices (as found in the configuration registers).
378 *
379 * pci_actual_io_offset and pci_actual_mem_offset are the offset from
380 * the values in the configuration registers to the actual (emulated) device.
381 *
382 * isa_portbase, isa_membase, and isa_irqbase are the port, memory, and
383 * interrupt bases for legacy ISA devices.
384 */
385 struct pci_data *bus_pci_init(int irq_nr,
386 uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset,
387 uint64_t pci_portbase, uint64_t pci_membase, int pci_irqbase,
388 uint64_t isa_portbase, uint64_t isa_membase, int isa_irqbase)
389 {
390 struct pci_data *d;
391
392 d = malloc(sizeof(struct pci_data));
393 if (d == NULL) {
394 fprintf(stderr, "out of memory\n");
395 exit(1);
396 }
397 memset(d, 0, sizeof(struct pci_data));
398 d->irq_nr = irq_nr;
399 d->pci_actual_io_offset = pci_actual_io_offset;
400 d->pci_actual_mem_offset = pci_actual_mem_offset;
401 d->pci_portbase = pci_portbase;
402 d->pci_membase = pci_membase;
403 d->pci_irqbase = pci_irqbase;
404 d->isa_portbase = isa_portbase;
405 d->isa_membase = isa_membase;
406 d->isa_irqbase = isa_irqbase;
407
408 /* Assume that the first 64KB could be used by legacy ISA devices: */
409 d->cur_pci_portbase = d->pci_portbase + 0x10000;
410 d->cur_pci_membase = d->pci_membase + 0x10000;
411
412 return d;
413 }
414
415
416
417 /******************************************************************************
418 *
419 * The following is glue code for PCI controllers and devices. The glue code
420 * does the minimal stuff necessary to get an emulated OS to detect the
421 * device (i.e. set up PCI configuration registers), and then if necessary
422 * add a "normal" device.
423 *
424 ******************************************************************************/
425
426
427
428 /*
429 * Integraphics Systems "igsfb" Framebuffer (graphics) card.
430 *
431 * TODO
432 */
433
434 #define PCI_VENDOR_INTEGRAPHICS 0x10ea
435
436 PCIINIT(igsfb)
437 {
438 PCI_SET_DATA(PCI_ID_REG,
439 PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010));
440
441 PCI_SET_DATA(PCI_CLASS_REG,
442 PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
443 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
444
445 /* TODO */
446 PCI_SET_DATA(0x10, 0xb0000000);
447
448 /* TODO: This is just a dummy so far. */
449 }
450
451
452
453 /*
454 * S3 ViRGE graphics.
455 *
456 * TODO: Only emulates a standard VGA card, so far.
457 */
458
459 #define PCI_VENDOR_S3 0x5333
460 #define PCI_PRODUCT_S3_VIRGE 0x5631
461 #define PCI_PRODUCT_S3_VIRGE_DX 0x8a01
462
463 PCIINIT(s3_virge)
464 {
465 PCI_SET_DATA(PCI_ID_REG,
466 PCI_ID_CODE(PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_DX));
467
468 PCI_SET_DATA(PCI_CLASS_REG,
469 PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
470 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
471
472 dev_vga_init(machine, mem, pd->pcibus->isa_membase + 0xa0000,
473 pd->pcibus->isa_portbase + 0x3c0, machine->machine_name);
474 }
475
476
477
478 /*
479 * Acer Labs M5229 PCI-IDE (UDMA) controller.
480 * Acer Labs M1543 PCI->ISA bridge.
481 */
482
483 #define PCI_VENDOR_ALI 0x10b9
484 #define PCI_PRODUCT_ALI_M1543 0x1533 /* NOTE: not 1543 */
485 #define PCI_PRODUCT_ALI_M5229 0x5229
486
487 PCIINIT(ali_m1543)
488 {
489 PCI_SET_DATA(PCI_ID_REG,
490 PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1543));
491
492 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
493 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0xc3);
494
495 PCI_SET_DATA(PCI_BHLC_REG,
496 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
497
498 /* Linux uses these to detect which IRQ the IDE controller uses: */
499 PCI_SET_DATA(0x44, 0x0000000e);
500 PCI_SET_DATA(0x58, 0x00000003);
501 }
502
503 PCIINIT(ali_m5229)
504 {
505 char tmpstr[300];
506
507 PCI_SET_DATA(PCI_ID_REG,
508 PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5229));
509
510 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
511 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x60) + 0xc1);
512
513 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
514 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
515 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
516 (long long)(pd->pcibus->isa_portbase + 0x1f0),
517 pd->pcibus->isa_irqbase + 14);
518 device_add(machine, tmpstr);
519 }
520
521 /* The secondary channel is disabled. TODO: fix this. */
522 }
523
524
525
526 /*
527 * Adaptec AHC SCSI controller.
528 */
529
530 #define PCI_VENDOR_ADP 0x9004 /* Adaptec */
531 #define PCI_VENDOR_ADP2 0x9005 /* Adaptec (2nd PCI Vendor ID) */
532 #define PCI_PRODUCT_ADP_2940U 0x8178 /* AHA-2940 Ultra */
533 #define PCI_PRODUCT_ADP_2940UP 0x8778 /* AHA-2940 Ultra Pro */
534
535 PCIINIT(ahc)
536 {
537 /* Numbers taken from a Adaptec 2940U: */
538 /* http://mail-index.netbsd.org/netbsd-bugs/2000/04/29/0000.html */
539
540 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ADP,
541 PCI_PRODUCT_ADP_2940U));
542
543 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02900007);
544
545 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
546 PCI_SUBCLASS_MASS_STORAGE_SCSI, 0) + 0x01);
547
548 PCI_SET_DATA(PCI_BHLC_REG, 0x00004008);
549
550 /* 1 = type i/o. 0x0000e801; address? */
551 /* second address reg = 0xf1002000? */
552 PCI_SET_DATA(PCI_MAPREG_START + 0x00, 0x00000001);
553 PCI_SET_DATA(PCI_MAPREG_START + 0x04, 0x00000000);
554
555 PCI_SET_DATA(PCI_MAPREG_START + 0x08, 0x00000000);
556 PCI_SET_DATA(PCI_MAPREG_START + 0x0c, 0x00000000);
557 PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x00000000);
558 PCI_SET_DATA(PCI_MAPREG_START + 0x14, 0x00000000);
559 PCI_SET_DATA(PCI_MAPREG_START + 0x18, 0x00000000);
560
561 /* Subsystem vendor ID? 0x78819004? */
562 PCI_SET_DATA(PCI_MAPREG_START + 0x1c, 0x00000000);
563
564 PCI_SET_DATA(0x30, 0xef000000);
565 PCI_SET_DATA(PCI_CAPLISTPTR_REG, 0x000000dc);
566 PCI_SET_DATA(0x38, 0x00000000);
567 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x08080109); /* interrupt pin A */
568
569 /*
570 * TODO: this address is based on what NetBSD/sgimips uses
571 * on SGI IP32 (O2). Fix this!
572 */
573
574 device_add(machine, "ahc addr=0x18000000");
575
576 /* OpenBSD/sgi snapshots sometime between 2005-03-11 and
577 2005-04-04 changed to using 0x1a000000: */
578 dev_ram_init(machine, 0x1a000000, 0x2000000, DEV_RAM_MIRROR,
579 0x18000000);
580 }
581
582
583
584 /*
585 * Galileo Technology GT-64xxx PCI controller.
586 *
587 * GT-64011 Used in Cobalt machines.
588 * GT-64120 Used in evbmips machines (Malta).
589 *
590 * NOTE: This works in the opposite way compared to other devices; the PCI
591 * device is added from the normal device instead of the other way around.
592 */
593
594 #define PCI_VENDOR_GALILEO 0x11ab /* Galileo Technology */
595 #define PCI_PRODUCT_GALILEO_GT64011 0x4146 /* GT-64011 System Controller */
596 #define PCI_PRODUCT_GALILEO_GT64120 0x4620 /* GT-64120 */
597
598 PCIINIT(gt64011)
599 {
600 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
601 PCI_PRODUCT_GALILEO_GT64011));
602
603 PCI_SET_DATA(PCI_CLASS_REG,
604 PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
605 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01); /* Revision 1 */
606 }
607
608 PCIINIT(gt64120)
609 {
610 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
611 PCI_PRODUCT_GALILEO_GT64120));
612
613 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
614 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x02); /* Revision 2? */
615
616 switch (machine->machine_type) {
617 case MACHINE_EVBMIPS:
618 PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x1be00000);
619 break;
620 }
621 }
622
623
624
625 /*
626 * Intel 82371AB PIIX4 PCI-ISA bridge and IDE controller
627 * and 82378ZB System I/O controller.
628 */
629
630 #define PCI_VENDOR_INTEL 0x8086
631 #define PCI_PRODUCT_INTEL_82371AB_ISA 0x7110
632 #define PCI_PRODUCT_INTEL_82371AB_IDE 0x7111
633 #define PCI_PRODUCT_INTEL_SIO 0x0484
634
635 PCIINIT(i82371ab_isa)
636 {
637 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
638 PCI_PRODUCT_INTEL_82371AB_ISA));
639
640 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
641 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x01); /* Rev 1 */
642
643 PCI_SET_DATA(PCI_BHLC_REG,
644 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
645 }
646
647 PCIINIT(i82378zb)
648 {
649 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
650 PCI_PRODUCT_INTEL_SIO));
651
652 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
653 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x43);
654
655 PCI_SET_DATA(PCI_BHLC_REG,
656 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
657 }
658
659 PCIINIT(i82371ab_ide)
660 {
661 char tmpstr[100];
662
663 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
664 PCI_PRODUCT_INTEL_82371AB_IDE));
665
666 /* Possibly not correct: */
667 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
668 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
669
670 /* PIIX_IDETIM (see NetBSD's pciide_piix_reg.h) */
671 /* channel 0 and 1 enabled as IDE */
672 PCI_SET_DATA(0x40, 0x80008000);
673
674 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
675 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
676 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
677 (long long)(pd->pcibus->isa_portbase + 0x1f0),
678 pd->pcibus->isa_irqbase + 14);
679 device_add(machine, tmpstr);
680 }
681
682 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
683 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
684 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
685 (long long)(pd->pcibus->isa_portbase + 0x170),
686 pd->pcibus->isa_irqbase + 15);
687 device_add(machine, tmpstr);
688 }
689 }
690
691
692
693 /*
694 * IBM ISA bridge (used by at least one PReP machine).
695 */
696
697 #define PCI_VENDOR_IBM 0x1014
698 #define PCI_PRODUCT_IBM_ISABRIDGE 0x000a
699
700 PCIINIT(ibm_isa)
701 {
702 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_IBM,
703 PCI_PRODUCT_IBM_ISABRIDGE));
704
705 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
706 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x02);
707
708 PCI_SET_DATA(PCI_BHLC_REG,
709 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
710 }
711
712
713
714 /*
715 * Heuricon PCI host bridge for PM/PPC.
716 */
717
718 #define PCI_VENDOR_HEURICON 0x1223
719 #define PCI_PRODUCT_HEURICON_PMPPC 0x000e
720
721 PCIINIT(heuricon_pmppc)
722 {
723 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_HEURICON,
724 PCI_PRODUCT_HEURICON_PMPPC));
725
726 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
727 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x00); /* Revision? */
728
729 PCI_SET_DATA(PCI_BHLC_REG,
730 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
731 }
732
733
734
735 /*
736 * VIATECH VT82C586 devices:
737 *
738 * vt82c586_isa PCI->ISA bridge
739 * vt82c586_ide IDE controller
740 *
741 * TODO: This more or less just a dummy device, so far.
742 */
743
744 #define PCI_VENDOR_VIATECH 0x1106 /* VIA Technologies */
745 #define PCI_PRODUCT_VIATECH_VT82C586_IDE 0x1571 /* VT82C586 (Apollo VP)
746 IDE Controller */
747 #define PCI_PRODUCT_VIATECH_VT82C586_ISA 0x0586 /* VT82C586 (Apollo VP)
748 PCI-ISA Bridge */
749
750 PCIINIT(vt82c586_isa)
751 {
752 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
753 PCI_PRODUCT_VIATECH_VT82C586_ISA));
754
755 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
756 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x39); /* Revision 37 or 39 */
757
758 PCI_SET_DATA(PCI_BHLC_REG,
759 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
760 }
761
762 PCIINIT(vt82c586_ide)
763 {
764 char tmpstr[100];
765
766 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
767 PCI_PRODUCT_VIATECH_VT82C586_IDE));
768
769 /* Possibly not correct: */
770 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
771 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
772
773 /* APO_IDECONF */
774 /* channel 0 and 1 enabled */
775 PCI_SET_DATA(0x40, 0x00000003);
776
777 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
778 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
779 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
780 (long long)(pd->pcibus->isa_portbase + 0x1f0),
781 pd->pcibus->isa_irqbase + 14);
782 device_add(machine, tmpstr);
783 }
784
785 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
786 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
787 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
788 (long long)(pd->pcibus->isa_portbase + 0x170),
789 pd->pcibus->isa_irqbase + 15);
790 device_add(machine, tmpstr);
791 }
792 }
793
794
795
796 /*
797 * Symphony Labs 83C553 PCI->ISA bridge.
798 * Symphony Labs 82C105 PCIIDE controller.
799 */
800
801 #define PCI_VENDOR_SYMPHONY 0x10ad
802 #define PCI_PRODUCT_SYMPHONY_83C553 0x0565
803 #define PCI_PRODUCT_SYMPHONY_82C105 0x0105
804
805 PCIINIT(symphony_83c553)
806 {
807 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
808 PCI_PRODUCT_SYMPHONY_83C553));
809
810 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
811 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x10);
812
813 PCI_SET_DATA(PCI_BHLC_REG,
814 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
815 }
816
817 PCIINIT(symphony_82c105)
818 {
819 char tmpstr[100];
820
821 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
822 PCI_PRODUCT_SYMPHONY_82C105));
823
824 /* Possibly not correct: */
825 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
826 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x05);
827
828 /* APO_IDECONF */
829 /* channel 0 and 1 enabled */
830 PCI_SET_DATA(0x40, 0x00000003);
831
832 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
833 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
834 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
835 (long long)(pd->pcibus->isa_portbase + 0x1f0),
836 pd->pcibus->isa_irqbase + 14);
837 device_add(machine, tmpstr);
838 }
839
840 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
841 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
842 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
843 (long long)(pd->pcibus->isa_portbase + 0x170),
844 pd->pcibus->isa_irqbase + 15);
845 device_add(machine, tmpstr);
846 }
847 }
848
849
850
851 /*
852 * DEC 21143 ("Tulip") PCI ethernet.
853 */
854
855 #define PCI_VENDOR_DEC 0x1011 /* Digital Equipment */
856 #define PCI_PRODUCT_DEC_21142 0x0019 /* DECchip 21142/21143 10/100 Ethernet */
857
858 PCIINIT(dec21143)
859 {
860 uint64_t port, memaddr;
861 int irq = 0; /* TODO */
862 int int_line = 1; /* TODO */
863 char tmpstr[200];
864
865 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
866 PCI_PRODUCT_DEC_21142));
867
868 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02000017);
869
870 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
871 PCI_SUBCLASS_NETWORK_ETHERNET, 0x00) + 0x41);
872
873 PCI_SET_DATA(PCI_BHLC_REG, PCI_BHLC_CODE(0,0,0, 0x40,0));
874
875 switch (machine->machine_type) {
876 case MACHINE_CATS:
877 irq = 18;
878 int_line = 1;
879 break;
880 case MACHINE_PREP:
881 int_line = 0xa;
882 irq = 31 - int_line;
883 break;
884 case MACHINE_PMPPC:
885 irq = 31 - 21;
886 break;
887 }
888
889 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140100 | int_line);
890
891 allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);
892
893 snprintf(tmpstr, sizeof(tmpstr), "dec21143 addr=0x%llx addr2=0x%llx "
894 "irq=%i pci_little_endian=1", (long long)port, (long long)memaddr,
895 irq);
896 device_add(machine, tmpstr);
897 }
898
899
900
901 /*
902 * DEC 21030 "tga" graphics.
903 */
904
905 #define PCI_PRODUCT_DEC_21030 0x0004 /* DECchip 21030 ("TGA") */
906
907 PCIINIT(dec21030)
908 {
909 uint64_t base = 0;
910 char tmpstr[200];
911
912 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
913 PCI_PRODUCT_DEC_21030));
914
915 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02800087); /* TODO */
916
917 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
918 PCI_SUBCLASS_DISPLAY_VGA, 0x00) + 0x03);
919
920 /*
921 * See http://mail-index.netbsd.org/port-arc/2001/08/13/0000.html
922 * for more info.
923 */
924
925 PCI_SET_DATA(PCI_BHLC_REG, 0x0000ff00);
926
927 /* 8 = prefetchable */
928 PCI_SET_DATA(0x10, 0x00000008);
929 PCI_SET_DATA(0x30, 0x08000001);
930 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x00000100); /* interrupt pin A? */
931
932 /*
933 * Experimental:
934 *
935 * TODO: Base address, pci_little_endian, ...
936 */
937
938 switch (machine->machine_type) {
939 case MACHINE_ARC:
940 base = 0x100000000ULL;
941 break;
942 default:fatal("dec21030 in non-implemented machine type %i\n",
943 machine->machine_type);
944 exit(1);
945 }
946
947 snprintf(tmpstr, sizeof(tmpstr), "dec21030 addr=0x%llx",
948 (long long)(base));
949 device_add(machine, tmpstr);
950 }
951
952
953 /*
954 * Motorola MPC105 "Eagle" Host Bridge
955 *
956 * Used in at least PReP and BeBox.
957 */
958
959 #define PCI_VENDOR_MOT 0x1057
960 #define PCI_PRODUCT_MOT_MPC105 0x0001
961
962 PCIINIT(eagle)
963 {
964 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_MOT,
965 PCI_PRODUCT_MOT_MPC105));
966
967 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
968 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x24);
969
970 PCI_SET_DATA(PCI_BHLC_REG,
971 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
972 }
973

  ViewVC Help
Powered by ViewVC 1.1.26