/[gxemul]/upstream/0.3.8/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.8/src/devices/bus_pci.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Mon Oct 8 16:19:43 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 31232 byte(s)
0.3.8
1 /*
2 * Copyright (C) 2004-2006 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.62 2006/02/18 21:03:12 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 /*
67 * bus_pci_decompose_1():
68 *
69 * Helper function for decomposing Mechanism 1 tags.
70 */
71 void bus_pci_decompose_1(uint32_t t, int *bus, int *dev, int *func, int *reg)
72 {
73 *bus = (t >> 16) & 0xff;
74 *dev = (t >> 11) & 0x1f;
75 *func = (t >> 8) & 0x7;
76 *reg = t & 0xff;
77
78 /* Warn about unaligned register access: */
79 if (t & 3)
80 fatal("[ bus_pci_decompose_1: WARNING: reg = 0x%02x ]\n",
81 t & 0xff);
82 }
83
84
85 /*
86 * bus_pci_data_access():
87 *
88 * Reads from or writes to the PCI configuration registers of a device.
89 */
90 void bus_pci_data_access(struct cpu *cpu, struct pci_data *pci_data,
91 uint64_t *data, int len, int writeflag)
92 {
93 struct pci_device *dev;
94 unsigned char *cfg_base;
95 uint64_t x, idata = *data;
96 int i;
97
98 /* Scan through the list of pci_device entries. */
99 dev = pci_data->first_device;
100 while (dev != NULL) {
101 if (dev->bus == pci_data->cur_bus &&
102 dev->function == pci_data->cur_func &&
103 dev->device == pci_data->cur_device)
104 break;
105 dev = dev->next;
106 }
107
108 /* No device? Then return emptiness. */
109 if (dev == NULL) {
110 if (writeflag == MEM_READ) {
111 if (pci_data->cur_reg == 0)
112 *data = -1;
113 else
114 *data = 0;
115 } else {
116 fatal("[ bus_pci_data_access(): write to non-existant"
117 " device? ]\n");
118 }
119 return;
120 }
121
122 /* Return normal config data, or length data? */
123 if (pci_data->last_was_write_ffffffff &&
124 pci_data->cur_reg >= PCI_MAPREG_START &&
125 pci_data->cur_reg <= PCI_MAPREG_END - 4)
126 cfg_base = dev->cfg_mem_size;
127 else
128 cfg_base = dev->cfg_mem;
129
130 /* Read data as little-endian: */
131 x = 0;
132 for (i=len-1; i>=0; i--) {
133 int ofs = pci_data->cur_reg + i;
134 x <<= 8;
135 x |= cfg_base[ofs & (PCI_CFG_MEM_SIZE - 1)];
136 }
137
138 /* Register write: */
139 if (writeflag == MEM_WRITE) {
140 debug("[ bus_pci: write to PCI DATA: data = 0x%08llx ]\n",
141 (long long)idata);
142 if (idata == 0xffffffffULL &&
143 pci_data->cur_reg >= PCI_MAPREG_START &&
144 pci_data->cur_reg <= 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, pci_data->cur_bus,
155 pci_data->cur_device, pci_data->cur_func,
156 dev->name, pci_data->cur_reg);
157 }
158 return;
159 }
160
161 /* Register read: */
162 *data = x;
163
164 pci_data->last_was_write_ffffffff = 0;
165
166 debug("[ bus_pci: read from PCI DATA, bus %i, device "
167 "%i, function %i (%s) register 0x%02x: 0x%08lx ]\n", (long)
168 pci_data->cur_bus, pci_data->cur_device,
169 pci_data->cur_func, dev->name, pci_data->cur_reg, (long)*data);
170 }
171
172
173 /*
174 * bus_pci_setaddr():
175 *
176 * Sets the address in preparation for a PCI register transfer.
177 */
178 void bus_pci_setaddr(struct cpu *cpu, struct pci_data *pci_data,
179 int bus, int device, int function, int reg)
180 {
181 if (cpu == NULL || pci_data == NULL) {
182 fatal("bus_pci_setaddr(): NULL ptr\n");
183 exit(1);
184 }
185
186 pci_data->cur_bus = bus;
187 pci_data->cur_device = device;
188 pci_data->cur_func = function;
189 pci_data->cur_reg = reg;
190 }
191
192
193 /*
194 * bus_pci_add():
195 *
196 * Add a PCI device to a bus_pci device.
197 */
198 void bus_pci_add(struct machine *machine, struct pci_data *pci_data,
199 struct memory *mem, int bus, int device, int function,
200 const char *name)
201 {
202 struct pci_device *pd;
203 int ofs;
204 void (*init)(struct machine *, struct memory *, struct pci_device *);
205
206 if (pci_data == NULL) {
207 fatal("bus_pci_add(): pci_data == NULL!\n");
208 exit(1);
209 }
210
211 /* Find the PCI device: */
212 init = pci_lookup_initf(name);
213
214 /* Make sure this bus/device/function number isn't already in use: */
215 pd = pci_data->first_device;
216 while (pd != NULL) {
217 if (pd->bus == bus && pd->device == device &&
218 pd->function == function) {
219 fatal("bus_pci_add(): (bus %i, device %i, function"
220 " %i) already in use\n", bus, device, function);
221 exit(1);
222 }
223 pd = pd->next;
224 }
225
226 pd = malloc(sizeof(struct pci_device));
227 if (pd == NULL) {
228 fprintf(stderr, "out of memory\n");
229 exit(1);
230 }
231
232 memset(pd, 0, sizeof(struct pci_device));
233
234 /* Add the new device first in the PCI bus' chain: */
235 pd->next = pci_data->first_device;
236 pci_data->first_device = pd;
237
238 pd->pcibus = pci_data;
239 pd->name = strdup(name);
240 pd->bus = bus;
241 pd->device = device;
242 pd->function = function;
243
244 /*
245 * Initialize with some default values:
246 *
247 * TODO: The command status register is best to set up per device.
248 * The size registers should also be set up on a per-device basis.
249 */
250 PCI_SET_DATA(PCI_COMMAND_STATUS_REG,
251 PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE);
252 for (ofs = PCI_MAPREG_START; ofs < PCI_MAPREG_END; ofs += 4)
253 PCI_SET_DATA_SIZE(ofs, 0x00100000 - 1);
254
255 if (init == NULL) {
256 fatal("No init function for PCI device \"%s\"?\n", name);
257 exit(1);
258 }
259
260 /* Call the PCI device' init function: */
261 init(machine, mem, pd);
262 }
263
264
265 /*
266 * allocate_device_space():
267 *
268 * Used by glue code (see below) to allocate space for a PCI device.
269 *
270 * The returned values in portp and memp are the actual (emulated) addresses
271 * that the device should use. (Normally only one of these is actually used.)
272 *
273 * TODO: PCI irqs?
274 */
275 static void allocate_device_space(struct pci_device *pd,
276 uint64_t portsize, uint64_t memsize,
277 uint64_t *portp, uint64_t *memp)
278 {
279 uint64_t port, mem;
280
281 /* Calculate an aligned starting port: */
282 port = pd->pcibus->cur_pci_portbase;
283 if (portsize != 0) {
284 port = ((port - 1) | (portsize - 1)) + 1;
285 pd->pcibus->cur_pci_portbase = port;
286 PCI_SET_DATA(PCI_MAPREG_START + pd->cur_mapreg_offset,
287 port | PCI_MAPREG_TYPE_IO);
288 PCI_SET_DATA_SIZE(PCI_MAPREG_START + pd->cur_mapreg_offset,
289 portsize - 1);
290 pd->cur_mapreg_offset += sizeof(uint32_t);
291 }
292
293 /* Calculate an aligned starting memory location: */
294 mem = pd->pcibus->cur_pci_membase;
295 if (memsize != 0) {
296 mem = ((mem - 1) | (memsize - 1)) + 1;
297 pd->pcibus->cur_pci_membase = mem;
298 PCI_SET_DATA(PCI_MAPREG_START + pd->cur_mapreg_offset, mem);
299 PCI_SET_DATA_SIZE(PCI_MAPREG_START + pd->cur_mapreg_offset,
300 memsize - 1);
301 pd->cur_mapreg_offset += sizeof(uint32_t);
302 }
303
304 *portp = port + pd->pcibus->pci_actual_io_offset;
305 *memp = mem + pd->pcibus->pci_actual_mem_offset;
306
307 if (verbose >= 2) {
308 debug("pci device '%s' at", pd->name);
309 if (portsize != 0)
310 debug(" port 0x%llx-0x%llx", (long long)pd->pcibus->
311 cur_pci_portbase, (long long)(pd->pcibus->
312 cur_pci_portbase + portsize - 1));
313 if (memsize != 0)
314 debug(" mem 0x%llx-0x%llx", (long long)pd->pcibus->
315 cur_pci_membase, (long long)(pd->pcibus->
316 cur_pci_membase + memsize - 1));
317 debug("\n");
318 }
319
320 pd->pcibus->cur_pci_portbase += portsize;
321 pd->pcibus->cur_pci_membase += memsize;
322 }
323
324
325 static void bus_pci_debug_dump__2(struct pci_device *pd)
326 {
327 if (pd == NULL)
328 return;
329 bus_pci_debug_dump__2(pd->next);
330 debug("bus %3i, dev %2i, func %i: %s\n",
331 pd->bus, pd->device, pd->function, pd->name);
332 }
333
334
335 /*
336 * bus_pci_debug_dump():
337 *
338 * Lists the attached PCI devices (in reverse).
339 */
340 void bus_pci_debug_dump(void *extra)
341 {
342 struct pci_data *d = (struct pci_data *) extra;
343 int iadd = DEBUG_INDENTATION;
344
345 debug("pci:\n");
346 debug_indentation(iadd);
347
348 if (d->first_device == NULL)
349 debug("no devices!\n");
350 else
351 bus_pci_debug_dump__2(d->first_device);
352
353 debug_indentation(-iadd);
354 }
355
356
357 /*
358 * bus_pci_init():
359 *
360 * This doesn't register a device, but instead returns a pointer to a struct
361 * which should be passed to other bus_pci functions when accessing the bus.
362 *
363 * irq_nr is the (optional) IRQ nr that this PCI bus interrupts at.
364 *
365 * pci_portbase, pci_membase, and pci_irqbase are the port, memory, and
366 * interrupt bases for PCI devices (as found in the configuration registers).
367 *
368 * pci_actual_io_offset and pci_actual_mem_offset are the offset from
369 * the values in the configuration registers to the actual (emulated) device.
370 *
371 * isa_portbase, isa_membase, and isa_irqbase are the port, memory, and
372 * interrupt bases for legacy ISA devices.
373 */
374 struct pci_data *bus_pci_init(struct machine *machine, int irq_nr,
375 uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset,
376 uint64_t pci_portbase, uint64_t pci_membase, int pci_irqbase,
377 uint64_t isa_portbase, uint64_t isa_membase, int isa_irqbase)
378 {
379 struct pci_data *d;
380
381 d = malloc(sizeof(struct pci_data));
382 if (d == NULL) {
383 fprintf(stderr, "out of memory\n");
384 exit(1);
385 }
386 memset(d, 0, sizeof(struct pci_data));
387 d->irq_nr = irq_nr;
388 d->pci_actual_io_offset = pci_actual_io_offset;
389 d->pci_actual_mem_offset = pci_actual_mem_offset;
390 d->pci_portbase = pci_portbase;
391 d->pci_membase = pci_membase;
392 d->pci_irqbase = pci_irqbase;
393 d->isa_portbase = isa_portbase;
394 d->isa_membase = isa_membase;
395 d->isa_irqbase = isa_irqbase;
396
397 /* Register the bus: */
398 machine_bus_register(machine, "pci", bus_pci_debug_dump, d);
399
400 /* Assume that the first 64KB could be used by legacy ISA devices: */
401 d->cur_pci_portbase = d->pci_portbase + 0x10000;
402 d->cur_pci_membase = d->pci_membase + 0x10000;
403
404 return d;
405 }
406
407
408
409 /******************************************************************************
410 * *
411 * The following is glue code for PCI controllers and devices. The glue *
412 * code does the minimal stuff necessary to get an emulated OS to detect *
413 * the device (i.e. set up PCI configuration registers), and then if *
414 * necessary adds a "normal" device. *
415 * *
416 ******************************************************************************/
417
418
419
420 /*
421 * Integraphics Systems "igsfb" Framebuffer (graphics) card.
422 *
423 * TODO
424 */
425
426 #define PCI_VENDOR_INTEGRAPHICS 0x10ea
427
428 PCIINIT(igsfb)
429 {
430 PCI_SET_DATA(PCI_ID_REG,
431 PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010));
432
433 PCI_SET_DATA(PCI_CLASS_REG,
434 PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
435 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
436
437 /* TODO */
438 PCI_SET_DATA(0x10, 0x08000000);
439
440 dev_vga_init(machine, mem, pd->pcibus->isa_membase + 0xa0000,
441 0x88800000 + 0x3c0, machine->machine_name);
442 }
443
444
445
446 /*
447 * S3 ViRGE graphics.
448 *
449 * TODO: Only emulates a standard VGA card, so far.
450 */
451
452 #define PCI_VENDOR_S3 0x5333
453 #define PCI_PRODUCT_S3_VIRGE 0x5631
454 #define PCI_PRODUCT_S3_VIRGE_DX 0x8a01
455
456 PCIINIT(s3_virge)
457 {
458 PCI_SET_DATA(PCI_ID_REG,
459 PCI_ID_CODE(PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_DX));
460
461 PCI_SET_DATA(PCI_CLASS_REG,
462 PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
463 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
464
465 dev_vga_init(machine, mem, pd->pcibus->isa_membase + 0xa0000,
466 pd->pcibus->isa_portbase + 0x3c0, machine->machine_name);
467 }
468
469
470
471 /*
472 * Acer Labs M5229 PCI-IDE (UDMA) controller.
473 * Acer Labs M1543 PCI->ISA bridge.
474 */
475
476 #define PCI_VENDOR_ALI 0x10b9
477 #define PCI_PRODUCT_ALI_M1543 0x1533 /* NOTE: not 1543 */
478 #define PCI_PRODUCT_ALI_M5229 0x5229
479
480 PCIINIT(ali_m1543)
481 {
482 PCI_SET_DATA(PCI_ID_REG,
483 PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1543));
484
485 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
486 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0xc3);
487
488 PCI_SET_DATA(PCI_BHLC_REG,
489 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
490
491 /* Linux uses these to detect which IRQ the IDE controller uses: */
492 PCI_SET_DATA(0x44, 0x0000000e);
493 PCI_SET_DATA(0x58, 0x00000003);
494 }
495
496 PCIINIT(ali_m5229)
497 {
498 char tmpstr[300];
499
500 PCI_SET_DATA(PCI_ID_REG,
501 PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5229));
502
503 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
504 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x60) + 0xc1);
505
506 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
507 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
508 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
509 (long long)(pd->pcibus->isa_portbase + 0x1f0),
510 pd->pcibus->isa_irqbase + 14);
511 device_add(machine, tmpstr);
512 }
513
514 /* The secondary channel is disabled. TODO: fix this. */
515 }
516
517
518
519 /*
520 * Adaptec AHC SCSI controller.
521 */
522
523 #define PCI_VENDOR_ADP 0x9004 /* Adaptec */
524 #define PCI_VENDOR_ADP2 0x9005 /* Adaptec (2nd PCI Vendor ID) */
525 #define PCI_PRODUCT_ADP_2940U 0x8178 /* AHA-2940 Ultra */
526 #define PCI_PRODUCT_ADP_2940UP 0x8778 /* AHA-2940 Ultra Pro */
527
528 PCIINIT(ahc)
529 {
530 /* Numbers taken from a Adaptec 2940U: */
531 /* http://mail-index.netbsd.org/netbsd-bugs/2000/04/29/0000.html */
532
533 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ADP,
534 PCI_PRODUCT_ADP_2940U));
535
536 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02900007);
537
538 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
539 PCI_SUBCLASS_MASS_STORAGE_SCSI, 0) + 0x01);
540
541 PCI_SET_DATA(PCI_BHLC_REG, 0x00004008);
542
543 /* 1 = type i/o. 0x0000e801; address? */
544 /* second address reg = 0xf1002000? */
545 PCI_SET_DATA(PCI_MAPREG_START + 0x00, 0x00000001);
546 PCI_SET_DATA(PCI_MAPREG_START + 0x04, 0x00000000);
547
548 PCI_SET_DATA(PCI_MAPREG_START + 0x08, 0x00000000);
549 PCI_SET_DATA(PCI_MAPREG_START + 0x0c, 0x00000000);
550 PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x00000000);
551 PCI_SET_DATA(PCI_MAPREG_START + 0x14, 0x00000000);
552 PCI_SET_DATA(PCI_MAPREG_START + 0x18, 0x00000000);
553
554 /* Subsystem vendor ID? 0x78819004? */
555 PCI_SET_DATA(PCI_MAPREG_START + 0x1c, 0x00000000);
556
557 PCI_SET_DATA(0x30, 0xef000000);
558 PCI_SET_DATA(PCI_CAPLISTPTR_REG, 0x000000dc);
559 PCI_SET_DATA(0x38, 0x00000000);
560 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x08080109); /* interrupt pin A */
561
562 /*
563 * TODO: this address is based on what NetBSD/sgimips uses
564 * on SGI IP32 (O2). Fix this!
565 */
566
567 device_add(machine, "ahc addr=0x18000000");
568
569 /* OpenBSD/sgi snapshots sometime between 2005-03-11 and
570 2005-04-04 changed to using 0x1a000000: */
571 dev_ram_init(machine, 0x1a000000, 0x2000000, DEV_RAM_MIRROR,
572 0x18000000);
573 }
574
575
576
577 /*
578 * Galileo Technology GT-64xxx PCI controller.
579 *
580 * GT-64011 Used in Cobalt machines.
581 * GT-64120 Used in evbmips machines (Malta).
582 *
583 * NOTE: This works in the opposite way compared to other devices; the PCI
584 * device is added from the normal device instead of the other way around.
585 */
586
587 #define PCI_VENDOR_GALILEO 0x11ab /* Galileo Technology */
588 #define PCI_PRODUCT_GALILEO_GT64011 0x4146 /* GT-64011 System Controller */
589 #define PCI_PRODUCT_GALILEO_GT64120 0x4620 /* GT-64120 */
590 #define PCI_PRODUCT_GALILEO_GT64260 0x6430 /* GT-64260 */
591
592 PCIINIT(gt64011)
593 {
594 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
595 PCI_PRODUCT_GALILEO_GT64011));
596
597 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
598 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01); /* Revision 1 */
599 }
600
601 PCIINIT(gt64120)
602 {
603 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
604 PCI_PRODUCT_GALILEO_GT64120));
605
606 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
607 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x02); /* Revision 2? */
608
609 switch (machine->machine_type) {
610 case MACHINE_EVBMIPS:
611 PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x1be00000);
612 break;
613 }
614 }
615
616 PCIINIT(gt64260)
617 {
618 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
619 PCI_PRODUCT_GALILEO_GT64260));
620
621 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
622 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01); /* Revision 1? */
623 }
624
625
626
627 /*
628 * Intel 31244 Serial ATA Controller
629 * Intel 82371SB PIIX3 PCI-ISA bridge
630 * Intel 82371AB PIIX4 PCI-ISA bridge
631 * Intel 82371SB IDE controller
632 * Intel 82371AB IDE controller
633 * Intel 82378ZB System I/O controller.
634 */
635
636 #define PCI_VENDOR_INTEL 0x8086
637 #define PCI_PRODUCT_INTEL_31244 0x3200
638 #define PCI_PRODUCT_INTEL_82371SB_ISA 0x7000
639 #define PCI_PRODUCT_INTEL_82371SB_IDE 0x7010
640 #define PCI_PRODUCT_INTEL_82371AB_ISA 0x7110
641 #define PCI_PRODUCT_INTEL_82371AB_IDE 0x7111
642 #define PCI_PRODUCT_INTEL_SIO 0x0484
643
644 PCIINIT(i31244)
645 {
646 uint64_t port, memaddr;
647
648 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
649 PCI_PRODUCT_INTEL_31244));
650
651 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
652 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x33) + 0x00);
653
654 switch (machine->machine_type) {
655 case MACHINE_IQ80321:
656 /* S-PCI-X slot uses PCI IRQ A */
657 break;
658 default:fatal("i31244 in non-implemented machine type %i\n",
659 machine->machine_type);
660 exit(1);
661 }
662
663 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140100);
664
665 allocate_device_space(pd, 0x400, 0, &port, &memaddr);
666 allocate_device_space(pd, 0x400, 0, &port, &memaddr);
667
668 /* PCI IDE using dev_wdc: */
669 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
670 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
671 char tmpstr[150];
672 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
673 (long long)(pd->pcibus->pci_actual_io_offset + 0),
674 pd->pcibus->pci_irqbase + 0);
675 device_add(machine, tmpstr);
676 }
677 }
678
679 PCIINIT(piix3_isa)
680 {
681 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
682 PCI_PRODUCT_INTEL_82371SB_ISA));
683
684 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
685 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x01); /* Rev 1 */
686
687 PCI_SET_DATA(PCI_BHLC_REG,
688 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
689 }
690
691 PCIINIT(piix4_isa)
692 {
693 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
694 PCI_PRODUCT_INTEL_82371AB_ISA));
695
696 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
697 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x01); /* Rev 1 */
698
699 PCI_SET_DATA(PCI_BHLC_REG,
700 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
701 }
702
703 PCIINIT(i82378zb)
704 {
705 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
706 PCI_PRODUCT_INTEL_SIO));
707
708 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
709 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x43);
710
711 PCI_SET_DATA(PCI_BHLC_REG,
712 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
713
714 PCI_SET_DATA(0x40, 0x20);
715
716 /* PIRQ[0]=10 PIRQ[1]=11 PIRQ[2]=14 PIRQ[3]=15 */
717 PCI_SET_DATA(0x60, 0x0f0e0b0a);
718 }
719
720 PCIINIT(piix3_ide)
721 {
722 char tmpstr[100];
723
724 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
725 PCI_PRODUCT_INTEL_82371SB_IDE));
726
727 /* Possibly not correct: */
728 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
729 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x00);
730
731 /* PIIX_IDETIM (see NetBSD's pciide_piix_reg.h) */
732 /* channel 0 and 1 enabled as IDE */
733 PCI_SET_DATA(0x40, 0x80008000);
734
735 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
736 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
737 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
738 (long long)(pd->pcibus->isa_portbase + 0x1f0),
739 pd->pcibus->isa_irqbase + 14);
740 device_add(machine, tmpstr);
741 }
742
743 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
744 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
745 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
746 (long long)(pd->pcibus->isa_portbase + 0x170),
747 pd->pcibus->isa_irqbase + 15);
748 device_add(machine, tmpstr);
749 }
750 }
751
752 PCIINIT(piix4_ide)
753 {
754 char tmpstr[100];
755
756 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
757 PCI_PRODUCT_INTEL_82371AB_IDE));
758
759 /* Possibly not correct: */
760 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
761 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
762
763 /* PIIX_IDETIM (see NetBSD's pciide_piix_reg.h) */
764 /* channel 0 and 1 enabled as IDE */
765 PCI_SET_DATA(0x40, 0x80008000);
766
767 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
768 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
769 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
770 (long long)(pd->pcibus->isa_portbase + 0x1f0),
771 pd->pcibus->isa_irqbase + 14);
772 device_add(machine, tmpstr);
773 }
774
775 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
776 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
777 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
778 (long long)(pd->pcibus->isa_portbase + 0x170),
779 pd->pcibus->isa_irqbase + 15);
780 device_add(machine, tmpstr);
781 }
782 }
783
784
785
786 /*
787 * IBM ISA bridge (used by at least one PReP machine).
788 */
789
790 #define PCI_VENDOR_IBM 0x1014
791 #define PCI_PRODUCT_IBM_ISABRIDGE 0x000a
792
793 PCIINIT(ibm_isa)
794 {
795 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_IBM,
796 PCI_PRODUCT_IBM_ISABRIDGE));
797
798 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
799 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x02);
800
801 PCI_SET_DATA(PCI_BHLC_REG,
802 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
803 }
804
805
806
807 /*
808 * Heuricon PCI host bridge for PM/PPC.
809 */
810
811 #define PCI_VENDOR_HEURICON 0x1223
812 #define PCI_PRODUCT_HEURICON_PMPPC 0x000e
813
814 PCIINIT(heuricon_pmppc)
815 {
816 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_HEURICON,
817 PCI_PRODUCT_HEURICON_PMPPC));
818
819 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
820 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x00); /* Revision? */
821
822 PCI_SET_DATA(PCI_BHLC_REG,
823 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
824 }
825
826
827
828 /*
829 * VIATECH VT82C586 devices:
830 *
831 * vt82c586_isa PCI->ISA bridge
832 * vt82c586_ide IDE controller
833 *
834 * TODO: This more or less just a dummy device, so far.
835 */
836
837 #define PCI_VENDOR_VIATECH 0x1106 /* VIA Technologies */
838 #define PCI_PRODUCT_VIATECH_VT82C586_IDE 0x1571 /* VT82C586 (Apollo VP)
839 IDE Controller */
840 #define PCI_PRODUCT_VIATECH_VT82C586_ISA 0x0586 /* VT82C586 (Apollo VP)
841 PCI-ISA Bridge */
842
843 PCIINIT(vt82c586_isa)
844 {
845 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
846 PCI_PRODUCT_VIATECH_VT82C586_ISA));
847
848 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
849 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x39); /* Revision 37 or 39 */
850
851 PCI_SET_DATA(PCI_BHLC_REG,
852 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
853 }
854
855 PCIINIT(vt82c586_ide)
856 {
857 char tmpstr[100];
858
859 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
860 PCI_PRODUCT_VIATECH_VT82C586_IDE));
861
862 /* Possibly not correct: */
863 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
864 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
865
866 /* APO_IDECONF */
867 /* channel 0 and 1 enabled */
868 PCI_SET_DATA(0x40, 0x00000003);
869
870 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
871 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
872 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
873 (long long)(pd->pcibus->isa_portbase + 0x1f0),
874 pd->pcibus->isa_irqbase + 14);
875 device_add(machine, tmpstr);
876 }
877
878 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
879 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
880 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
881 (long long)(pd->pcibus->isa_portbase + 0x170),
882 pd->pcibus->isa_irqbase + 15);
883 device_add(machine, tmpstr);
884 }
885 }
886
887
888
889 /*
890 * Symphony Labs 83C553 PCI->ISA bridge.
891 * Symphony Labs 82C105 PCIIDE controller.
892 */
893
894 #define PCI_VENDOR_SYMPHONY 0x10ad
895 #define PCI_PRODUCT_SYMPHONY_83C553 0x0565
896 #define PCI_PRODUCT_SYMPHONY_82C105 0x0105
897
898 PCIINIT(symphony_83c553)
899 {
900 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
901 PCI_PRODUCT_SYMPHONY_83C553));
902
903 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
904 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x10);
905
906 PCI_SET_DATA(PCI_BHLC_REG,
907 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
908 }
909
910 PCIINIT(symphony_82c105)
911 {
912 char tmpstr[100];
913
914 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
915 PCI_PRODUCT_SYMPHONY_82C105));
916
917 /* Possibly not correct: */
918 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
919 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x05);
920
921 /* APO_IDECONF */
922 /* channel 0 and 1 enabled */
923 PCI_SET_DATA(0x40, 0x00000003);
924
925 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
926 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
927 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
928 (long long)(pd->pcibus->isa_portbase + 0x1f0),
929 pd->pcibus->isa_irqbase + 14);
930 device_add(machine, tmpstr);
931 }
932
933 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
934 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
935 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i",
936 (long long)(pd->pcibus->isa_portbase + 0x170),
937 pd->pcibus->isa_irqbase + 15);
938 device_add(machine, tmpstr);
939 }
940 }
941
942
943
944 /*
945 * DEC 21143 ("Tulip") PCI ethernet.
946 */
947
948 #define PCI_VENDOR_DEC 0x1011 /* Digital Equipment */
949 #define PCI_PRODUCT_DEC_21142 0x0019 /* DECchip 21142/21143 10/100 Ethernet */
950
951 PCIINIT(dec21143)
952 {
953 uint64_t port, memaddr;
954 int irq = 0; /* TODO */
955 int pci_int_line = 0x101;
956 char tmpstr[200];
957
958 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
959 PCI_PRODUCT_DEC_21142));
960
961 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02000017);
962
963 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
964 PCI_SUBCLASS_NETWORK_ETHERNET, 0x00) + 0x41);
965
966 PCI_SET_DATA(PCI_BHLC_REG, PCI_BHLC_CODE(0,0,0, 0x40,0));
967
968 switch (machine->machine_type) {
969 case MACHINE_CATS:
970 /* CATS int 18 = PCI. */
971 irq = 18;
972 pci_int_line = 0x101;
973 break;
974 case MACHINE_COBALT:
975 /* On Cobalt, IRQ 7 = PCI. */
976 irq = 8 + 7;
977 pci_int_line = 0x407;
978 break;
979 case MACHINE_ALGOR:
980 /* TODO */
981 irq = 8 + 7;
982 pci_int_line = 0x407;
983 break;
984 case MACHINE_PREP:
985 irq = 32 + 10;
986 pci_int_line = 0x20a;
987 break;
988 case MACHINE_MVMEPPC:
989 /* TODO */
990 irq = 32 + 10;
991 pci_int_line = 0x40a;
992 break;
993 case MACHINE_PMPPC:
994 /* TODO, not working yet */
995 irq = 31 - 21;
996 pci_int_line = 0x201;
997 break;
998 case MACHINE_MACPPC:
999 /* TODO, not working yet */
1000 irq = 25;
1001 pci_int_line = 0x101;
1002 break;
1003 }
1004
1005 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000 | pci_int_line);
1006
1007 allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);
1008
1009 snprintf(tmpstr, sizeof(tmpstr), "dec21143 addr=0x%llx addr2=0x%llx "
1010 "irq=%i pci_little_endian=1", (long long)port, (long long)memaddr,
1011 irq);
1012 device_add(machine, tmpstr);
1013 }
1014
1015
1016
1017 /*
1018 * DEC 21030 "tga" graphics.
1019 */
1020
1021 #define PCI_PRODUCT_DEC_21030 0x0004 /* DECchip 21030 ("TGA") */
1022
1023 PCIINIT(dec21030)
1024 {
1025 uint64_t base = 0;
1026 char tmpstr[200];
1027
1028 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
1029 PCI_PRODUCT_DEC_21030));
1030
1031 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02800087); /* TODO */
1032
1033 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
1034 PCI_SUBCLASS_DISPLAY_VGA, 0x00) + 0x03);
1035
1036 /*
1037 * See http://mail-index.netbsd.org/port-arc/2001/08/13/0000.html
1038 * for more info.
1039 */
1040
1041 PCI_SET_DATA(PCI_BHLC_REG, 0x0000ff00);
1042
1043 /* 8 = prefetchable */
1044 PCI_SET_DATA(0x10, 0x00000008);
1045 PCI_SET_DATA(0x30, 0x08000001);
1046 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x00000100); /* interrupt pin A? */
1047
1048 /*
1049 * Experimental:
1050 *
1051 * TODO: Base address, pci_little_endian, ...
1052 */
1053
1054 switch (machine->machine_type) {
1055 case MACHINE_ARC:
1056 base = 0x100000000ULL;
1057 break;
1058 default:fatal("dec21030 in non-implemented machine type %i\n",
1059 machine->machine_type);
1060 exit(1);
1061 }
1062
1063 snprintf(tmpstr, sizeof(tmpstr), "dec21030 addr=0x%llx",
1064 (long long)(base));
1065 device_add(machine, tmpstr);
1066 }
1067
1068
1069
1070 /*
1071 * Motorola MPC105 "Eagle" Host Bridge
1072 *
1073 * Used in at least PReP and BeBox.
1074 */
1075
1076 #define PCI_VENDOR_MOT 0x1057
1077 #define PCI_PRODUCT_MOT_MPC105 0x0001
1078
1079 PCIINIT(eagle)
1080 {
1081 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_MOT,
1082 PCI_PRODUCT_MOT_MPC105));
1083
1084 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1085 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x24);
1086
1087 PCI_SET_DATA(PCI_BHLC_REG,
1088 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1089 }
1090
1091
1092
1093 /*
1094 * Apple (MacPPC) stuff:
1095 *
1096 * Grand Central (I/O controller)
1097 * Uni-North (PCI controller)
1098 */
1099
1100 #define PCI_VENDOR_APPLE 0x106b
1101 #define PCI_PRODUCT_APPLE_GC 0x0002
1102 #define PCI_PRODUCT_APPLE_UNINORTH1 0x001e
1103
1104 PCIINIT(gc_obio)
1105 {
1106 uint64_t port, memaddr;
1107
1108 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1109 PCI_PRODUCT_APPLE_GC));
1110
1111 /* TODO: */
1112 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_SYSTEM,
1113 PCI_SUBCLASS_SYSTEM_PIC, 0) + 0x00);
1114
1115 PCI_SET_DATA(PCI_BHLC_REG,
1116 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1117
1118 /* TODO */
1119 allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1120 }
1121
1122 PCIINIT(uninorth)
1123 {
1124 uint64_t port, memaddr;
1125
1126 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1127 PCI_PRODUCT_APPLE_UNINORTH1));
1128
1129 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1130 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0xff);
1131
1132 PCI_SET_DATA(PCI_BHLC_REG,
1133 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1134
1135 /* TODO */
1136 allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1137 }
1138
1139
1140
1141 /*
1142 * ATI graphics cards
1143 */
1144
1145 #define PCI_VENDOR_ATI 0x1002
1146 #define PCI_PRODUCT_ATI_RADEON_9200_2 0x5962
1147
1148 PCIINIT(ati_radeon_9200_2)
1149 {
1150 uint64_t port, memaddr;
1151
1152 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ATI,
1153 PCI_PRODUCT_ATI_RADEON_9200_2));
1154
1155 /* TODO: other subclass? */
1156 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
1157 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x03);
1158
1159 /* TODO */
1160 allocate_device_space(pd, 0x1000, 0x400000, &port, &memaddr);
1161 }
1162

  ViewVC Help
Powered by ViewVC 1.1.26