/[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 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 37552 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26