/[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 40 - (show annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 37769 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26