/[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 34 - (show annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 36662 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


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.80 2007/02/11 10:03:55 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 /* Assume that the first 64KB could be used by legacy ISA devices: */
385 d->cur_pci_portbase = d->pci_portbase + 0x10000;
386 d->cur_pci_membase = d->pci_membase + 0x10000;
387
388 return d;
389 }
390
391
392
393 /******************************************************************************
394 * *
395 * The following is glue code for PCI controllers and devices. The glue *
396 * code does the minimal stuff necessary to get an emulated OS to detect *
397 * the device (i.e. set up PCI configuration registers), and then if *
398 * necessary adds a "normal" device. *
399 * *
400 ******************************************************************************/
401
402
403
404 /*
405 * Integraphics Systems "igsfb" Framebuffer (graphics) card, used in at
406 * least the NetWinder.
407 */
408
409 #define PCI_VENDOR_INTEGRAPHICS 0x10ea
410
411 PCIINIT(igsfb)
412 {
413 char tmpstr[200];
414
415 PCI_SET_DATA(PCI_ID_REG,
416 PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010));
417
418 PCI_SET_DATA(PCI_CLASS_REG,
419 PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
420 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
421
422 /* TODO */
423 PCI_SET_DATA(0x10, 0x08000000);
424
425 snprintf(tmpstr, sizeof(tmpstr), "igsfb addr=0x%llx",
426 (long long)(pd->pcibus->isa_membase + 0x08000000));
427 device_add(machine, tmpstr);
428 }
429
430
431
432 /*
433 * S3 ViRGE graphics.
434 *
435 * TODO: Only emulates a standard VGA card, so far.
436 */
437
438 #define PCI_VENDOR_S3 0x5333
439 #define PCI_PRODUCT_S3_VIRGE 0x5631
440 #define PCI_PRODUCT_S3_VIRGE_DX 0x8a01
441
442 PCIINIT(s3_virge)
443 {
444 PCI_SET_DATA(PCI_ID_REG,
445 PCI_ID_CODE(PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_DX));
446
447 PCI_SET_DATA(PCI_CLASS_REG,
448 PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
449 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x01);
450
451 dev_vga_init(machine, mem, pd->pcibus->isa_membase + 0xa0000,
452 pd->pcibus->isa_portbase + 0x3c0, machine->machine_name);
453 }
454
455
456
457 /*
458 * Acer Labs M5229 PCI-IDE (UDMA) controller.
459 * Acer Labs M1543 PCI->ISA bridge.
460 */
461
462 #define PCI_VENDOR_ALI 0x10b9
463 #define PCI_PRODUCT_ALI_M1543 0x1533 /* NOTE: not 1543 */
464 #define PCI_PRODUCT_ALI_M5229 0x5229
465
466 PCIINIT(ali_m1543)
467 {
468 PCI_SET_DATA(PCI_ID_REG,
469 PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1543));
470
471 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
472 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0xc3);
473
474 PCI_SET_DATA(PCI_BHLC_REG,
475 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
476
477 /* Linux uses these to detect which IRQ the IDE controller uses: */
478 PCI_SET_DATA(0x44, 0x0000000e);
479 PCI_SET_DATA(0x58, 0x00000003);
480
481 switch (machine->machine_type) {
482 case MACHINE_CATS:
483 bus_isa_init(machine, pd->pcibus->irq_path_isa,
484 BUS_ISA_PCKBC_FORCE_USE | BUS_ISA_PCKBC_NONPCSTYLE,
485 0x7c000000, 0x80000000);
486 break;
487 default:fatal("ali_m1543 init: unimplemented machine type\n");
488 exit(1);
489 }
490 }
491
492 PCIINIT(ali_m5229)
493 {
494 char tmpstr[300], irqstr[300];
495
496 PCI_SET_DATA(PCI_ID_REG,
497 PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5229));
498
499 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
500 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x60) + 0xc1);
501
502 switch (machine->machine_type) {
503 case MACHINE_CATS:
504 /* CATS ISA interrupts are at footbridge irq 10: */
505 snprintf(irqstr, sizeof(irqstr), "%s.10.isa",
506 pd->pcibus->irq_path);
507 break;
508 default:fatal("ali_m5229 init: unimplemented machine type\n");
509 exit(1);
510 }
511
512 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
513 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
514 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s.%i",
515 (long long)(pd->pcibus->isa_portbase + 0x1f0),
516 irqstr, 14);
517 device_add(machine, tmpstr);
518 }
519
520 /* The secondary channel is disabled. TODO: fix this. */
521 }
522
523
524
525 /*
526 * Adaptec AHC SCSI controller.
527 */
528
529 #define PCI_VENDOR_ADP 0x9004 /* Adaptec */
530 #define PCI_VENDOR_ADP2 0x9005 /* Adaptec (2nd PCI Vendor ID) */
531 #define PCI_PRODUCT_ADP_2940U 0x8178 /* AHA-2940 Ultra */
532 #define PCI_PRODUCT_ADP_2940UP 0x8778 /* AHA-2940 Ultra Pro */
533
534 PCIINIT(ahc)
535 {
536 /* Numbers taken from a Adaptec 2940U: */
537 /* http://mail-index.netbsd.org/netbsd-bugs/2000/04/29/0000.html */
538
539 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ADP,
540 PCI_PRODUCT_ADP_2940U));
541
542 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02900007);
543
544 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
545 PCI_SUBCLASS_MASS_STORAGE_SCSI, 0) + 0x01);
546
547 PCI_SET_DATA(PCI_BHLC_REG, 0x00004008);
548
549 /* 1 = type i/o. 0x0000e801; address? */
550 /* second address reg = 0xf1002000? */
551 PCI_SET_DATA(PCI_MAPREG_START + 0x00, 0x00000001);
552 PCI_SET_DATA(PCI_MAPREG_START + 0x04, 0x00000000);
553
554 PCI_SET_DATA(PCI_MAPREG_START + 0x08, 0x00000000);
555 PCI_SET_DATA(PCI_MAPREG_START + 0x0c, 0x00000000);
556 PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x00000000);
557 PCI_SET_DATA(PCI_MAPREG_START + 0x14, 0x00000000);
558 PCI_SET_DATA(PCI_MAPREG_START + 0x18, 0x00000000);
559
560 /* Subsystem vendor ID? 0x78819004? */
561 PCI_SET_DATA(PCI_MAPREG_START + 0x1c, 0x00000000);
562
563 PCI_SET_DATA(0x30, 0xef000000);
564 PCI_SET_DATA(PCI_CAPLISTPTR_REG, 0x000000dc);
565 PCI_SET_DATA(0x38, 0x00000000);
566 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x08080109); /* interrupt pin A */
567
568 /*
569 * TODO: this address is based on what NetBSD/sgimips uses
570 * on SGI IP32 (O2). Fix this!
571 */
572
573 device_add(machine, "ahc addr=0x18000000");
574
575 /* OpenBSD/sgi snapshots sometime between 2005-03-11 and
576 2005-04-04 changed to using 0x1a000000: */
577 dev_ram_init(machine, 0x1a000000, 0x2000000, DEV_RAM_MIRROR,
578 0x18000000);
579 }
580
581
582
583 /*
584 * Galileo Technology GT-64xxx PCI controller.
585 *
586 * GT-64011 Used in Cobalt machines.
587 * GT-64120 Used in evbmips machines (Malta).
588 *
589 * NOTE: This works in the opposite way compared to other devices; the PCI
590 * device is added from the normal device instead of the other way around.
591 */
592
593 #define PCI_VENDOR_GALILEO 0x11ab /* Galileo Technology */
594 #define PCI_PRODUCT_GALILEO_GT64011 0x4146 /* GT-64011 System Controller */
595 #define PCI_PRODUCT_GALILEO_GT64120 0x4620 /* GT-64120 */
596 #define PCI_PRODUCT_GALILEO_GT64260 0x6430 /* GT-64260 */
597
598 PCIINIT(gt64011)
599 {
600 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
601 PCI_PRODUCT_GALILEO_GT64011));
602
603 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
604 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01); /* Revision 1 */
605 }
606
607 PCIINIT(gt64120)
608 {
609 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
610 PCI_PRODUCT_GALILEO_GT64120));
611
612 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
613 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x02); /* Revision 2? */
614
615 switch (machine->machine_type) {
616 case MACHINE_EVBMIPS:
617 PCI_SET_DATA(PCI_MAPREG_START + 0x10, 0x1be00000);
618 break;
619 }
620 }
621
622 PCIINIT(gt64260)
623 {
624 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
625 PCI_PRODUCT_GALILEO_GT64260));
626
627 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
628 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01); /* Revision 1? */
629 }
630
631
632
633 /*
634 * AMD PCnet Ethernet card.
635 *
636 * "Am79c970A PCnet-PCI II rev 0" or similar.
637 */
638
639 #define PCI_VENDOR_AMD 0x1022 /* Advanced Micro Devices */
640 #define PCI_PRODUCT_AMD_PCNET_PCI 0x2000 /* PCnet-PCI Ethernet */
641
642 PCIINIT(pcn)
643 {
644 int irq;
645
646 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_AMD,
647 PCI_PRODUCT_AMD_PCNET_PCI));
648
649 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
650 PCI_SUBCLASS_NETWORK_ETHERNET, 0) + 0x00); /* Revision 0 */
651
652 switch (machine->machine_type) {
653
654 case MACHINE_EVBMIPS:
655 irq = (1 << 8) + 10; /* TODO */
656 break;
657
658 default:fatal("pcn in non-implemented machine type %i\n",
659 machine->machine_type);
660 exit(1);
661 }
662
663 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x01100000 | irq);
664
665 /*
666 * TODO: Add the pcn device here. The pcn device will need to work as
667 * a wrapper for dev_le + all the DMA magic and whatever is required.
668 * It's too much to implement right now.
669 */
670 }
671
672
673
674 /*
675 * Intel 31244 Serial ATA Controller
676 * Intel 82371SB PIIX3 PCI-ISA bridge
677 * Intel 82371AB PIIX4 PCI-ISA bridge
678 * Intel 82371SB IDE controller
679 * Intel 82371AB IDE controller
680 * Intel 82378ZB System I/O controller.
681 */
682
683 #define PCI_VENDOR_INTEL 0x8086
684 #define PCI_PRODUCT_INTEL_31244 0x3200
685 #define PCI_PRODUCT_INTEL_82371SB_ISA 0x7000
686 #define PCI_PRODUCT_INTEL_82371SB_IDE 0x7010
687 #define PCI_PRODUCT_INTEL_82371AB_ISA 0x7110
688 #define PCI_PRODUCT_INTEL_82371AB_IDE 0x7111
689 #define PCI_PRODUCT_INTEL_SIO 0x0484
690
691 PCIINIT(i31244)
692 {
693 uint64_t port, memaddr;
694 int irq = 0;
695
696 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
697 PCI_PRODUCT_INTEL_31244));
698
699 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
700 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x33) + 0x00);
701
702 switch (machine->machine_type) {
703 case MACHINE_IQ80321:
704 /* S-PCI-X slot uses PCI IRQ A, int 29 */
705 irq = (1 << 8) + 29;
706 break;
707 default:fatal("i31244 in non-implemented machine type %i\n",
708 machine->machine_type);
709 exit(1);
710 }
711
712 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x01100000 | irq);
713
714 allocate_device_space(pd, 0x1000, 0, &port, &memaddr);
715 allocate_device_space(pd, 0x1000, 0, &port, &memaddr);
716
717 /* PCI IDE using dev_wdc: */
718 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
719 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
720 char tmpstr[150];
721 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s.%i",
722 (long long)(pd->pcibus->pci_actual_io_offset + 0),
723 pd->pcibus->irq_path_pci, irq & 255);
724 device_add(machine, tmpstr);
725 }
726 }
727
728 PCIINIT(piix3_isa)
729 {
730 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
731 PCI_PRODUCT_INTEL_82371SB_ISA));
732
733 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
734 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x01); /* Rev 1 */
735
736 PCI_SET_DATA(PCI_BHLC_REG,
737 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
738 }
739
740 PCIINIT(piix4_isa)
741 {
742 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
743 PCI_PRODUCT_INTEL_82371AB_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(i82378zb)
753 {
754 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
755 PCI_PRODUCT_INTEL_SIO));
756
757 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
758 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x43);
759
760 PCI_SET_DATA(PCI_BHLC_REG,
761 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
762
763 PCI_SET_DATA(0x40, 0x20);
764
765 /* PIRQ[0]=10 PIRQ[1]=11 PIRQ[2]=14 PIRQ[3]=15 */
766 PCI_SET_DATA(0x60, 0x0f0e0b0a);
767 }
768
769 struct piix_ide_extra {
770 void *wdc0;
771 void *wdc1;
772 };
773
774 int piix_ide_cfg_reg_write(struct pci_device *pd, int reg, uint32_t value)
775 {
776 void *wdc0 = ((struct piix_ide_extra *)pd->extra)->wdc0;
777 void *wdc1 = ((struct piix_ide_extra *)pd->extra)->wdc1;
778 int enabled = 0;
779
780 switch (reg) {
781 case PCI_COMMAND_STATUS_REG:
782 if (value & PCI_COMMAND_IO_ENABLE)
783 enabled = 1;
784 if (wdc0 != NULL)
785 wdc_set_io_enabled(wdc0, enabled);
786 if (wdc1 != NULL)
787 wdc_set_io_enabled(wdc1, enabled);
788 return 1;
789 }
790
791 return 0;
792 }
793
794 PCIINIT(piix3_ide)
795 {
796 char tmpstr[100];
797
798 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
799 PCI_PRODUCT_INTEL_82371SB_IDE));
800
801 /* Possibly not correct: */
802 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
803 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x00);
804
805 /* PIIX_IDETIM (see NetBSD's pciide_piix_reg.h) */
806 /* channel 0 and 1 enabled as IDE */
807 PCI_SET_DATA(0x40, 0x80008000);
808
809 pd->extra = malloc(sizeof(struct piix_ide_extra));
810 if (pd->extra == NULL) {
811 fatal("Out of memory.\n");
812 exit(1);
813 }
814 ((struct piix_ide_extra *)pd->extra)->wdc0 = NULL;
815 ((struct piix_ide_extra *)pd->extra)->wdc1 = NULL;
816
817 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
818 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
819 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx "
820 "irq=%s.isa.%i", (long long)(pd->pcibus->isa_portbase +
821 0x1f0), pd->pcibus->irq_path_isa, 14);
822 ((struct piix_ide_extra *)pd->extra)->wdc0 =
823 device_add(machine, tmpstr);
824 }
825
826 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
827 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
828 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx "
829 "irq=%s.isa.%i", (long long)(pd->pcibus->isa_portbase +
830 0x170), pd->pcibus->irq_path_isa, 15);
831 ((struct piix_ide_extra *)pd->extra)->wdc1 =
832 device_add(machine, tmpstr);
833 }
834
835 pd->cfg_reg_write = piix_ide_cfg_reg_write;
836 }
837
838 PCIINIT(piix4_ide)
839 {
840 char tmpstr[100];
841
842 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
843 PCI_PRODUCT_INTEL_82371AB_IDE));
844
845 /* Possibly not correct: */
846 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
847 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
848
849 /* PIIX_IDETIM (see NetBSD's pciide_piix_reg.h) */
850 /* channel 0 and 1 enabled as IDE */
851 PCI_SET_DATA(0x40, 0x80008000);
852
853 pd->extra = malloc(sizeof(struct piix_ide_extra));
854 if (pd->extra == NULL) {
855 fatal("Out of memory.\n");
856 exit(1);
857 }
858 ((struct piix_ide_extra *)pd->extra)->wdc0 = NULL;
859 ((struct piix_ide_extra *)pd->extra)->wdc1 = NULL;
860
861 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
862 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
863 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
864 "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x1f0),
865 pd->pcibus->irq_path_isa, 14);
866 ((struct piix_ide_extra *)pd->extra)->wdc0 =
867 device_add(machine, tmpstr);
868 }
869
870 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
871 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
872 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
873 "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x170),
874 pd->pcibus->irq_path_isa, 15);
875 ((struct piix_ide_extra *)pd->extra)->wdc1 =
876 device_add(machine, tmpstr);
877 }
878
879 pd->cfg_reg_write = piix_ide_cfg_reg_write;
880 }
881
882
883
884 /*
885 * IBM ISA bridge (used by at least one PReP machine).
886 */
887
888 #define PCI_VENDOR_IBM 0x1014
889 #define PCI_PRODUCT_IBM_ISABRIDGE 0x000a
890
891 PCIINIT(ibm_isa)
892 {
893 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_IBM,
894 PCI_PRODUCT_IBM_ISABRIDGE));
895
896 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
897 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x02);
898
899 PCI_SET_DATA(PCI_BHLC_REG,
900 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
901 }
902
903
904
905 /*
906 * Heuricon PCI host bridge for PM/PPC.
907 */
908
909 #define PCI_VENDOR_HEURICON 0x1223
910 #define PCI_PRODUCT_HEURICON_PMPPC 0x000e
911
912 PCIINIT(heuricon_pmppc)
913 {
914 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_HEURICON,
915 PCI_PRODUCT_HEURICON_PMPPC));
916
917 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
918 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x00); /* Revision? */
919
920 PCI_SET_DATA(PCI_BHLC_REG,
921 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
922 }
923
924
925
926 /*
927 * VIATECH VT82C586 devices:
928 *
929 * vt82c586_isa PCI->ISA bridge
930 * vt82c586_ide IDE controller
931 *
932 * TODO: This more or less just a dummy device, so far.
933 */
934
935 #define PCI_VENDOR_VIATECH 0x1106 /* VIA Technologies */
936 #define PCI_PRODUCT_VIATECH_VT82C586_IDE 0x1571 /* VT82C586 (Apollo VP)
937 IDE Controller */
938 #define PCI_PRODUCT_VIATECH_VT82C586_ISA 0x0586 /* VT82C586 (Apollo VP)
939 PCI-ISA Bridge */
940
941 PCIINIT(vt82c586_isa)
942 {
943 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
944 PCI_PRODUCT_VIATECH_VT82C586_ISA));
945
946 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
947 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x39); /* Revision 37 or 39 */
948
949 PCI_SET_DATA(PCI_BHLC_REG,
950 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
951 }
952
953 struct vt82c586_ide_extra {
954 void *wdc0;
955 void *wdc1;
956 };
957
958 int vt82c586_ide_cfg_reg_write(struct pci_device *pd, int reg, uint32_t value)
959 {
960 void *wdc0 = ((struct vt82c586_ide_extra *)pd->extra)->wdc0;
961 void *wdc1 = ((struct vt82c586_ide_extra *)pd->extra)->wdc1;
962 int enabled = 0;
963
964 switch (reg) {
965 case PCI_COMMAND_STATUS_REG:
966 if (value & PCI_COMMAND_IO_ENABLE)
967 enabled = 1;
968 if (wdc0 != NULL)
969 wdc_set_io_enabled(wdc0, enabled);
970 if (wdc1 != NULL)
971 wdc_set_io_enabled(wdc1, enabled);
972 return 1;
973 }
974
975 return 0;
976 }
977
978 PCIINIT(vt82c586_ide)
979 {
980 char tmpstr[100];
981
982 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_VIATECH,
983 PCI_PRODUCT_VIATECH_VT82C586_IDE));
984
985 /* Possibly not correct: */
986 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
987 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x01);
988
989 /* APO_IDECONF */
990 /* channel 0 and 1 enabled */
991 PCI_SET_DATA(0x40, 0x00000003);
992
993 pd->extra = malloc(sizeof(struct vt82c586_ide_extra));
994 if (pd->extra == NULL) {
995 fatal("Out of memory.\n");
996 exit(1);
997 }
998 ((struct vt82c586_ide_extra *)pd->extra)->wdc0 = NULL;
999 ((struct vt82c586_ide_extra *)pd->extra)->wdc1 = NULL;
1000
1001 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
1002 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
1003 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1004 "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x1f0),
1005 pd->pcibus->irq_path_isa, 14);
1006 ((struct vt82c586_ide_extra *)pd->extra)->wdc0 =
1007 device_add(machine, tmpstr);
1008 }
1009
1010 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
1011 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
1012 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1013 "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x170),
1014 pd->pcibus->irq_path_isa, 15);
1015 ((struct vt82c586_ide_extra *)pd->extra)->wdc1 =
1016 device_add(machine, tmpstr);
1017 }
1018
1019 pd->cfg_reg_write = vt82c586_ide_cfg_reg_write;
1020 }
1021
1022
1023
1024 /*
1025 * Symphony Labs 83C553 PCI->ISA bridge.
1026 * Symphony Labs 82C105 PCIIDE controller.
1027 */
1028
1029 #define PCI_VENDOR_SYMPHONY 0x10ad
1030 #define PCI_PRODUCT_SYMPHONY_83C553 0x0565
1031 #define PCI_PRODUCT_SYMPHONY_82C105 0x0105
1032
1033 PCIINIT(symphony_83c553)
1034 {
1035 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
1036 PCI_PRODUCT_SYMPHONY_83C553));
1037
1038 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1039 PCI_SUBCLASS_BRIDGE_ISA, 0) + 0x10);
1040
1041 PCI_SET_DATA(PCI_BHLC_REG,
1042 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1043
1044 switch (machine->machine_type) {
1045 case MACHINE_NETWINDER:
1046 bus_isa_init(machine, pd->pcibus->irq_path_isa,
1047 0, 0x7c000000, 0x80000000);
1048 break;
1049 default:fatal("symphony_83c553 init: unimplemented machine type\n");
1050 exit(1);
1051 }
1052 }
1053
1054 struct symphony_82c105_extra {
1055 void *wdc0;
1056 void *wdc1;
1057 };
1058
1059 int symphony_82c105_cfg_reg_write(struct pci_device *pd, int reg,
1060 uint32_t value)
1061 {
1062 void *wdc0 = ((struct symphony_82c105_extra *)pd->extra)->wdc0;
1063 void *wdc1 = ((struct symphony_82c105_extra *)pd->extra)->wdc1;
1064 int enabled = 0;
1065
1066 printf("reg = 0x%x\n", reg);
1067 switch (reg) {
1068 case PCI_COMMAND_STATUS_REG:
1069 if (value & PCI_COMMAND_IO_ENABLE)
1070 enabled = 1;
1071 printf(" value = 0x%"PRIx32"\n", value);
1072 if (wdc0 != NULL)
1073 wdc_set_io_enabled(wdc0, enabled);
1074 if (wdc1 != NULL)
1075 wdc_set_io_enabled(wdc1, enabled);
1076 /* Set all bits: */
1077 PCI_SET_DATA(reg, value);
1078 return 1;
1079 case PCI_MAPREG_START:
1080 case PCI_MAPREG_START + 4:
1081 case PCI_MAPREG_START + 8:
1082 case PCI_MAPREG_START + 12:
1083 case PCI_MAPREG_START + 16:
1084 case PCI_MAPREG_START + 20:
1085 PCI_SET_DATA(reg, value);
1086 return 1;
1087 }
1088
1089 return 0;
1090 }
1091
1092 PCIINIT(symphony_82c105)
1093 {
1094 char tmpstr[100];
1095
1096 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_SYMPHONY,
1097 PCI_PRODUCT_SYMPHONY_82C105));
1098
1099 /* Possibly not correct: */
1100 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_MASS_STORAGE,
1101 PCI_SUBCLASS_MASS_STORAGE_IDE, 0x00) + 0x05);
1102
1103 /* TODO: Interrupt line: */
1104 /* PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000); */
1105
1106 /* APO_IDECONF */
1107 /* channel 0 and 1 enabled */
1108 PCI_SET_DATA(0x40, 0x00000003);
1109
1110 pd->extra = malloc(sizeof(struct symphony_82c105_extra));
1111 if (pd->extra == NULL) {
1112 fatal("Out of memory.\n");
1113 exit(1);
1114 }
1115 ((struct symphony_82c105_extra *)pd->extra)->wdc0 = NULL;
1116 ((struct symphony_82c105_extra *)pd->extra)->wdc1 = NULL;
1117
1118 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
1119 diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
1120 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1121 "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x1f0),
1122 pd->pcibus->irq_path_isa, 14);
1123 ((struct symphony_82c105_extra *)pd->extra)->wdc0 =
1124 device_add(machine, tmpstr);
1125 }
1126
1127 if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
1128 diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
1129 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s."
1130 "isa.%i", (long long)(pd->pcibus->isa_portbase + 0x170),
1131 pd->pcibus->irq_path_isa, 15);
1132 ((struct symphony_82c105_extra *)pd->extra)->wdc1 =
1133 device_add(machine, tmpstr);
1134 }
1135
1136 pd->cfg_reg_write = symphony_82c105_cfg_reg_write;
1137 }
1138
1139
1140
1141 /*
1142 * DEC 21143 ("Tulip") PCI ethernet.
1143 */
1144
1145 #define PCI_VENDOR_DEC 0x1011 /* Digital Equipment */
1146 #define PCI_PRODUCT_DEC_21142 0x0019 /* DECchip 21142/21143 10/100 Ethernet */
1147
1148 PCIINIT(dec21143)
1149 {
1150 uint64_t port, memaddr;
1151 int pci_int_line = 0x101, irq = 0, isa = 0;
1152 char irqstr[200];
1153 char tmpstr[200];
1154
1155 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
1156 PCI_PRODUCT_DEC_21142));
1157
1158 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02000017);
1159
1160 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK,
1161 PCI_SUBCLASS_NETWORK_ETHERNET, 0x00) + 0x41);
1162
1163 PCI_SET_DATA(PCI_BHLC_REG, PCI_BHLC_CODE(0,0,0, 0x40,0));
1164
1165 switch (machine->machine_type) {
1166 case MACHINE_CATS:
1167 /* CATS int 18 = PCI. */
1168 irq = 18;
1169 pci_int_line = 0x101;
1170 break;
1171 case MACHINE_COBALT:
1172 /* On Cobalt, IRQ 7 = PCI. */
1173 irq = 8 + 7;
1174 pci_int_line = 0x407;
1175 break;
1176 case MACHINE_PREP:
1177 irq = 10;
1178 isa = 1;
1179 pci_int_line = 0x20a;
1180 break;
1181 case MACHINE_MVMEPPC:
1182 /* TODO */
1183 irq = 10;
1184 pci_int_line = 0x40a;
1185 break;
1186 case MACHINE_PMPPC:
1187 /* TODO, not working yet */
1188 irq = 31 - 21;
1189 pci_int_line = 0x201;
1190 break;
1191 case MACHINE_MACPPC:
1192 /* TODO, not working yet */
1193 irq = 25;
1194 pci_int_line = 0x101;
1195 break;
1196 }
1197
1198 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000 | pci_int_line);
1199
1200 allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);
1201
1202 if (isa)
1203 snprintf(irqstr, sizeof(irqstr), "%s.isa.%i",
1204 pd->pcibus->irq_path_isa, irq);
1205 else
1206 snprintf(irqstr, sizeof(irqstr), "%s.%i",
1207 pd->pcibus->irq_path_pci, irq);
1208
1209 snprintf(tmpstr, sizeof(tmpstr), "dec21143 addr=0x%llx addr2=0x%llx "
1210 "irq=%s pci_little_endian=1", (long long)port,
1211 (long long)memaddr, irqstr);
1212
1213 device_add(machine, tmpstr);
1214 }
1215
1216
1217
1218 /*
1219 * DEC 21030 "tga" graphics.
1220 */
1221
1222 #define PCI_PRODUCT_DEC_21030 0x0004 /* DECchip 21030 ("TGA") */
1223
1224 PCIINIT(dec21030)
1225 {
1226 uint64_t base = 0;
1227 char tmpstr[200];
1228
1229 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_DEC,
1230 PCI_PRODUCT_DEC_21030));
1231
1232 PCI_SET_DATA(PCI_COMMAND_STATUS_REG, 0x02800087); /* TODO */
1233
1234 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
1235 PCI_SUBCLASS_DISPLAY_VGA, 0x00) + 0x03);
1236
1237 /*
1238 * See http://mail-index.netbsd.org/port-arc/2001/08/13/0000.html
1239 * for more info.
1240 */
1241
1242 PCI_SET_DATA(PCI_BHLC_REG, 0x0000ff00);
1243
1244 /* 8 = prefetchable */
1245 PCI_SET_DATA(0x10, 0x00000008);
1246 PCI_SET_DATA(0x30, 0x08000001);
1247 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x00000100); /* interrupt pin A? */
1248
1249 /*
1250 * Experimental:
1251 *
1252 * TODO: Base address, pci_little_endian, ...
1253 */
1254
1255 switch (machine->machine_type) {
1256 case MACHINE_ARC:
1257 base = 0x100000000ULL;
1258 break;
1259 default:fatal("dec21030 in non-implemented machine type %i\n",
1260 machine->machine_type);
1261 exit(1);
1262 }
1263
1264 snprintf(tmpstr, sizeof(tmpstr), "dec21030 addr=0x%llx",
1265 (long long)(base));
1266 device_add(machine, tmpstr);
1267 }
1268
1269
1270
1271 /*
1272 * Motorola MPC105 "Eagle" Host Bridge
1273 *
1274 * Used in at least PReP and BeBox.
1275 */
1276
1277 #define PCI_VENDOR_MOT 0x1057
1278 #define PCI_PRODUCT_MOT_MPC105 0x0001
1279
1280 PCIINIT(eagle)
1281 {
1282 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_MOT,
1283 PCI_PRODUCT_MOT_MPC105));
1284
1285 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1286 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x24);
1287
1288 PCI_SET_DATA(PCI_BHLC_REG,
1289 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1290 }
1291
1292
1293
1294 /*
1295 * Apple (MacPPC) stuff:
1296 *
1297 * Grand Central (I/O controller)
1298 * Uni-North (PCI controller)
1299 */
1300
1301 #define PCI_VENDOR_APPLE 0x106b
1302 #define PCI_PRODUCT_APPLE_GC 0x0002
1303 #define PCI_PRODUCT_APPLE_UNINORTH1 0x001e
1304
1305 PCIINIT(gc_obio)
1306 {
1307 uint64_t port, memaddr;
1308
1309 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1310 PCI_PRODUCT_APPLE_GC));
1311
1312 /* TODO: */
1313 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_SYSTEM,
1314 PCI_SUBCLASS_SYSTEM_PIC, 0) + 0x00);
1315
1316 PCI_SET_DATA(PCI_BHLC_REG,
1317 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1318
1319 /* TODO */
1320 allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1321 }
1322
1323 PCIINIT(uninorth)
1324 {
1325 uint64_t port, memaddr;
1326
1327 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_APPLE,
1328 PCI_PRODUCT_APPLE_UNINORTH1));
1329
1330 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
1331 PCI_SUBCLASS_BRIDGE_HOST, 0) + 0xff);
1332
1333 PCI_SET_DATA(PCI_BHLC_REG,
1334 PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0));
1335
1336 /* TODO */
1337 allocate_device_space(pd, 0x10000, 0x10000, &port, &memaddr);
1338 }
1339
1340
1341
1342 /*
1343 * ATI graphics cards
1344 */
1345
1346 #define PCI_VENDOR_ATI 0x1002
1347 #define PCI_PRODUCT_ATI_RADEON_9200_2 0x5962
1348
1349 PCIINIT(ati_radeon_9200_2)
1350 {
1351 uint64_t port, memaddr;
1352
1353 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_ATI,
1354 PCI_PRODUCT_ATI_RADEON_9200_2));
1355
1356 /* TODO: other subclass? */
1357 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_DISPLAY,
1358 PCI_SUBCLASS_DISPLAY_VGA, 0) + 0x03);
1359
1360 /* TODO */
1361 allocate_device_space(pd, 0x1000, 0x400000, &port, &memaddr);
1362 }
1363

  ViewVC Help
Powered by ViewVC 1.1.26