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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 34940 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26