/[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 42 - (show annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 37547 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26