/[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

Annotation of /trunk/src/devices/bus_pci.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 7 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 dpavlin 4 /*
2 dpavlin 34 * Copyright (C) 2004-2007 Anders Gavare. All rights reserved.
3 dpavlin 4 *
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 dpavlin 42 * $Id: bus_pci.c,v 1.84 2007/06/15 18:13:04 debug Exp $
29 dpavlin 4 *
30 dpavlin 42 * COMMENT: Generic PCI bus framework
31 dpavlin 4 *
32 dpavlin 42 * This is not a normal "device", but is used by individual PCI controllers
33     * and devices.
34     *
35 dpavlin 20 * 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 dpavlin 4 */
46    
47     #include <stdio.h>
48     #include <stdlib.h>
49     #include <string.h>
50    
51 dpavlin 20 #define BUS_PCI_C
52    
53 dpavlin 34 #include "bus_isa.h"
54 dpavlin 20 #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 dpavlin 4 #include "memory.h"
61     #include "misc.h"
62    
63 dpavlin 42 #include "cpc700reg.h"
64 dpavlin 30 #include "wdc.h"
65    
66 dpavlin 20 extern int verbose;
67 dpavlin 4
68 dpavlin 20
69 dpavlin 24 #ifdef UNSTABLE_DEVEL
70     #define debug fatal
71     #endif
72 dpavlin 4
73 dpavlin 14
74 dpavlin 22 /*
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 dpavlin 20 {
81 dpavlin 22 *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 dpavlin 20 }
91    
92    
93 dpavlin 4 /*
94 dpavlin 20 * bus_pci_data_access():
95     *
96 dpavlin 22 * Reads from or writes to the PCI configuration registers of a device.
97 dpavlin 20 */
98 dpavlin 22 void bus_pci_data_access(struct cpu *cpu, struct pci_data *pci_data,
99     uint64_t *data, int len, int writeflag)
100 dpavlin 20 {
101     struct pci_device *dev;
102     unsigned char *cfg_base;
103     uint64_t x, idata = *data;
104 dpavlin 22 int i;
105 dpavlin 20
106     /* Scan through the list of pci_device entries. */
107     dev = pci_data->first_device;
108     while (dev != NULL) {
109 dpavlin 22 if (dev->bus == pci_data->cur_bus &&
110     dev->function == pci_data->cur_func &&
111     dev->device == pci_data->cur_device)
112 dpavlin 20 break;
113     dev = dev->next;
114     }
115    
116     /* No device? Then return emptiness. */
117     if (dev == NULL) {
118 dpavlin 22 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 dpavlin 20 return;
128     }
129    
130     /* Return normal config data, or length data? */
131     if (pci_data->last_was_write_ffffffff &&
132 dpavlin 22 pci_data->cur_reg >= PCI_MAPREG_START &&
133     pci_data->cur_reg <= PCI_MAPREG_END - 4)
134 dpavlin 20 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 dpavlin 22 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 dpavlin 20 }
145    
146     /* Register write: */
147     if (writeflag == MEM_WRITE) {
148 dpavlin 22 debug("[ bus_pci: write to PCI DATA: data = 0x%08llx ]\n",
149 dpavlin 20 (long long)idata);
150 dpavlin 22 if (idata == 0xffffffffULL &&
151     pci_data->cur_reg >= PCI_MAPREG_START &&
152     pci_data->cur_reg <= PCI_MAPREG_END - 4) {
153 dpavlin 20 pci_data->last_was_write_ffffffff = 1;
154     return;
155     }
156 dpavlin 30
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 dpavlin 20 debug("[ bus_pci: write to PCI DATA: data = 0x%08llx"
162 dpavlin 30 " (current value = 0x%08llx); NOT YET"
163 dpavlin 20 " SUPPORTED. bus %i, device %i, function %i (%s)"
164     " register 0x%02x ]\n", (long long)idata,
165 dpavlin 22 (long long)x, pci_data->cur_bus,
166     pci_data->cur_device, pci_data->cur_func,
167     dev->name, pci_data->cur_reg);
168 dpavlin 30
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 dpavlin 20 }
178     return;
179     }
180    
181     /* Register read: */
182     *data = x;
183    
184     pci_data->last_was_write_ffffffff = 0;
185    
186 dpavlin 22 debug("[ bus_pci: read from PCI DATA, bus %i, device "
187 dpavlin 24 "%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 dpavlin 20 }
191    
192    
193     /*
194 dpavlin 22 * bus_pci_setaddr():
195 dpavlin 4 *
196 dpavlin 22 * Sets the address in preparation for a PCI register transfer.
197 dpavlin 4 */
198 dpavlin 22 void bus_pci_setaddr(struct cpu *cpu, struct pci_data *pci_data,
199     int bus, int device, int function, int reg)
200 dpavlin 4 {
201 dpavlin 22 if (cpu == NULL || pci_data == NULL) {
202     fatal("bus_pci_setaddr(): NULL ptr\n");
203     exit(1);
204 dpavlin 4 }
205    
206 dpavlin 22 pci_data->cur_bus = bus;
207     pci_data->cur_device = device;
208     pci_data->cur_func = function;
209     pci_data->cur_reg = reg;
210 dpavlin 4 }
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 dpavlin 22 const char *name)
221 dpavlin 4 {
222 dpavlin 20 struct pci_device *pd;
223     int ofs;
224     void (*init)(struct machine *, struct memory *, struct pci_device *);
225 dpavlin 4
226 dpavlin 14 if (pci_data == NULL) {
227     fatal("bus_pci_add(): pci_data == NULL!\n");
228 dpavlin 34 abort();
229 dpavlin 14 }
230    
231 dpavlin 20 /* Find the PCI device: */
232     init = pci_lookup_initf(name);
233    
234 dpavlin 4 /* Make sure this bus/device/function number isn't already in use: */
235 dpavlin 20 pd = pci_data->first_device;
236     while (pd != NULL) {
237     if (pd->bus == bus && pd->device == device &&
238     pd->function == function) {
239 dpavlin 4 fatal("bus_pci_add(): (bus %i, device %i, function"
240     " %i) already in use\n", bus, device, function);
241 dpavlin 20 exit(1);
242 dpavlin 4 }
243 dpavlin 20 pd = pd->next;
244 dpavlin 4 }
245    
246 dpavlin 42 CHECK_ALLOCATION(pd = malloc(sizeof(struct pci_device)));
247 dpavlin 20 memset(pd, 0, sizeof(struct pci_device));
248 dpavlin 4
249     /* Add the new device first in the PCI bus' chain: */
250 dpavlin 20 pd->next = pci_data->first_device;
251     pci_data->first_device = pd;
252 dpavlin 4
253 dpavlin 42 CHECK_ALLOCATION(pd->name = strdup(name));
254 dpavlin 20 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 dpavlin 22 * 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 dpavlin 20 */
265 dpavlin 22 PCI_SET_DATA(PCI_COMMAND_STATUS_REG,
266     PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE);
267 dpavlin 20 for (ofs = PCI_MAPREG_START; ofs < PCI_MAPREG_END; ofs += 4)
268 dpavlin 22 PCI_SET_DATA_SIZE(ofs, 0x00100000 - 1);
269 dpavlin 20
270     if (init == NULL) {
271     fatal("No init function for PCI device \"%s\"?\n", name);
272     exit(1);
273     }
274    
275 dpavlin 4 /* Call the PCI device' init function: */
276 dpavlin 20 init(machine, mem, pd);
277 dpavlin 4 }
278    
279    
280     /*
281 dpavlin 20 * 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 dpavlin 22 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 dpavlin 24 ((portsize - 1) & ~0xf) | 0xd);
305 dpavlin 22 pd->cur_mapreg_offset += sizeof(uint32_t);
306 dpavlin 20 }
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 dpavlin 22 PCI_SET_DATA(PCI_MAPREG_START + pd->cur_mapreg_offset, mem);
314     PCI_SET_DATA_SIZE(PCI_MAPREG_START + pd->cur_mapreg_offset,
315 dpavlin 24 ((memsize - 1) & ~0xf) | 0x0);
316 dpavlin 22 pd->cur_mapreg_offset += sizeof(uint32_t);
317 dpavlin 20 }
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 dpavlin 4 * bus_pci_init():
342     *
343     * This doesn't register a device, but instead returns a pointer to a struct
344 dpavlin 22 * which should be passed to other bus_pci functions when accessing the bus.
345 dpavlin 20 *
346 dpavlin 34 * irq_path is the interrupt path to the PCI controller.
347 dpavlin 20 *
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 dpavlin 4 */
357 dpavlin 34 struct pci_data *bus_pci_init(struct machine *machine, char *irq_path,
358 dpavlin 20 uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset,
359 dpavlin 34 uint64_t pci_portbase, uint64_t pci_membase, char *pci_irqbase,
360     uint64_t isa_portbase, uint64_t isa_membase, char *isa_irqbase)
361 dpavlin 4 {
362     struct pci_data *d;
363    
364 dpavlin 42 CHECK_ALLOCATION(d = malloc(sizeof(struct pci_data)));
365 dpavlin 4 memset(d, 0, sizeof(struct pci_data));
366 dpavlin 34
367 dpavlin 42 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 dpavlin 34
371 dpavlin 20 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 dpavlin 4
378 dpavlin 40 d->cur_pci_portbase = d->pci_portbase;
379     d->cur_pci_membase = d->pci_membase;
380    
381 dpavlin 20 /* Assume that the first 64KB could be used by legacy ISA devices: */
382 dpavlin 40 if (d->isa_portbase != 0 || d->isa_membase != 0) {
383     d->cur_pci_portbase += 0x10000;
384     d->cur_pci_membase += 0x10000;
385     }
386 dpavlin 20
387 dpavlin 4 return d;
388     }
389    
390 dpavlin 20
391    
392     /******************************************************************************
393 dpavlin 22 * *
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 dpavlin 20 ******************************************************************************/
400    
401    
402    
403     /*
404 dpavlin 30 * Integraphics Systems "igsfb" Framebuffer (graphics) card, used in at
405     * least the NetWinder.
406 dpavlin 20 */
407    
408     #define PCI_VENDOR_INTEGRAPHICS 0x10ea
409    
410     PCIINIT(igsfb)
411     {
412 dpavlin 30 char tmpstr[200];
413    
414 dpavlin 20 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 dpavlin 22 PCI_SET_DATA(0x10, 0x08000000);
423 dpavlin 20
424 dpavlin 30 snprintf(tmpstr, sizeof(tmpstr), "igsfb addr=0x%llx",
425     (long long)(pd->pcibus->isa_membase + 0x08000000));
426     device_add(machine, tmpstr);
427 dpavlin 20 }
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 dpavlin 34
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 dpavlin 20 }
490    
491     PCIINIT(ali_m5229)
492     {
493 dpavlin 34 char tmpstr[300], irqstr[300];
494 dpavlin 20
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 dpavlin 34 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 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
512     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
513 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s.%i",
514 dpavlin 20 (long long)(pd->pcibus->isa_portbase + 0x1f0),
515 dpavlin 34 irqstr, 14);
516 dpavlin 20 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 dpavlin 22 #define PCI_PRODUCT_GALILEO_GT64260 0x6430 /* GT-64260 */
596 dpavlin 20
597     PCIINIT(gt64011)
598     {
599     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
600     PCI_PRODUCT_GALILEO_GT64011));
601    
602 dpavlin 22 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
603 dpavlin 20 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 dpavlin 22 PCIINIT(gt64260)
622     {
623     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_GALILEO,
624     PCI_PRODUCT_GALILEO_GT64260));
625 dpavlin 20
626 dpavlin 22 PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_BRIDGE,
627     PCI_SUBCLASS_BRIDGE_HOST, 0) + 0x01); /* Revision 1? */
628     }
629 dpavlin 20
630 dpavlin 22
631    
632 dpavlin 20 /*
633 dpavlin 30 * 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 dpavlin 22 * 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 dpavlin 20 */
681    
682     #define PCI_VENDOR_INTEL 0x8086
683 dpavlin 22 #define PCI_PRODUCT_INTEL_31244 0x3200
684     #define PCI_PRODUCT_INTEL_82371SB_ISA 0x7000
685     #define PCI_PRODUCT_INTEL_82371SB_IDE 0x7010
686 dpavlin 20 #define PCI_PRODUCT_INTEL_82371AB_ISA 0x7110
687     #define PCI_PRODUCT_INTEL_82371AB_IDE 0x7111
688     #define PCI_PRODUCT_INTEL_SIO 0x0484
689    
690 dpavlin 22 PCIINIT(i31244)
691 dpavlin 20 {
692 dpavlin 22 uint64_t port, memaddr;
693 dpavlin 24 int irq = 0;
694 dpavlin 22
695 dpavlin 20 PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
696 dpavlin 22 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 dpavlin 24 /* S-PCI-X slot uses PCI IRQ A, int 29 */
704     irq = (1 << 8) + 29;
705 dpavlin 22 break;
706     default:fatal("i31244 in non-implemented machine type %i\n",
707     machine->machine_type);
708     exit(1);
709     }
710    
711 dpavlin 24 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x01100000 | irq);
712 dpavlin 22
713 dpavlin 24 allocate_device_space(pd, 0x1000, 0, &port, &memaddr);
714     allocate_device_space(pd, 0x1000, 0, &port, &memaddr);
715 dpavlin 22
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 dpavlin 34 snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%s.%i",
721 dpavlin 22 (long long)(pd->pcibus->pci_actual_io_offset + 0),
722 dpavlin 34 pd->pcibus->irq_path_pci, irq & 255);
723 dpavlin 22 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 dpavlin 20 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 dpavlin 22
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 dpavlin 20 }
767    
768 dpavlin 30 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 dpavlin 22 PCIINIT(piix3_ide)
794 dpavlin 20 {
795     char tmpstr[100];
796    
797     PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_INTEL,
798 dpavlin 22 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 dpavlin 42 CHECK_ALLOCATION(pd->extra = malloc(sizeof(struct piix_ide_extra)));
809 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc0 = NULL;
810     ((struct piix_ide_extra *)pd->extra)->wdc1 = NULL;
811    
812 dpavlin 22 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
813     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
814 dpavlin 34 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 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc0 =
818     device_add(machine, tmpstr);
819 dpavlin 22 }
820    
821     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
822     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
823 dpavlin 34 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 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc1 =
827     device_add(machine, tmpstr);
828 dpavlin 22 }
829 dpavlin 30
830     pd->cfg_reg_write = piix_ide_cfg_reg_write;
831 dpavlin 22 }
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 dpavlin 20 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 dpavlin 42 CHECK_ALLOCATION(pd->extra = malloc(sizeof(struct piix_ide_extra)));
849 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc0 = NULL;
850     ((struct piix_ide_extra *)pd->extra)->wdc1 = NULL;
851    
852 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
853     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
854 dpavlin 34 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 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc0 =
858     device_add(machine, tmpstr);
859 dpavlin 20 }
860    
861     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
862     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
863 dpavlin 34 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 dpavlin 30 ((struct piix_ide_extra *)pd->extra)->wdc1 =
867     device_add(machine, tmpstr);
868 dpavlin 20 }
869 dpavlin 30
870     pd->cfg_reg_write = piix_ide_cfg_reg_write;
871 dpavlin 20 }
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 dpavlin 30 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 dpavlin 20 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 dpavlin 42 CHECK_ALLOCATION(pd->extra = malloc(sizeof(struct vt82c586_ide_extra)));
985 dpavlin 30 ((struct vt82c586_ide_extra *)pd->extra)->wdc0 = NULL;
986     ((struct vt82c586_ide_extra *)pd->extra)->wdc1 = NULL;
987    
988 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
989     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
990 dpavlin 34 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 dpavlin 30 ((struct vt82c586_ide_extra *)pd->extra)->wdc0 =
994     device_add(machine, tmpstr);
995 dpavlin 20 }
996    
997     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
998     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
999 dpavlin 34 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 dpavlin 30 ((struct vt82c586_ide_extra *)pd->extra)->wdc1 =
1003     device_add(machine, tmpstr);
1004 dpavlin 20 }
1005 dpavlin 30
1006     pd->cfg_reg_write = vt82c586_ide_cfg_reg_write;
1007 dpavlin 20 }
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 dpavlin 34
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 dpavlin 20 }
1040    
1041 dpavlin 32 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 dpavlin 20 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 dpavlin 32 /* TODO: Interrupt line: */
1091     /* PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000); */
1092    
1093 dpavlin 20 /* APO_IDECONF */
1094     /* channel 0 and 1 enabled */
1095     PCI_SET_DATA(0x40, 0x00000003);
1096    
1097 dpavlin 42 CHECK_ALLOCATION(pd->extra = malloc(sizeof(struct symphony_82c105_extra)));
1098 dpavlin 32 ((struct symphony_82c105_extra *)pd->extra)->wdc0 = NULL;
1099     ((struct symphony_82c105_extra *)pd->extra)->wdc1 = NULL;
1100    
1101 dpavlin 20 if (diskimage_exist(machine, 0, DISKIMAGE_IDE) ||
1102     diskimage_exist(machine, 1, DISKIMAGE_IDE)) {
1103 dpavlin 34 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 dpavlin 32 ((struct symphony_82c105_extra *)pd->extra)->wdc0 =
1107     device_add(machine, tmpstr);
1108 dpavlin 20 }
1109    
1110     if (diskimage_exist(machine, 2, DISKIMAGE_IDE) ||
1111     diskimage_exist(machine, 3, DISKIMAGE_IDE)) {
1112 dpavlin 34 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 dpavlin 32 ((struct symphony_82c105_extra *)pd->extra)->wdc1 =
1116     device_add(machine, tmpstr);
1117 dpavlin 20 }
1118 dpavlin 32
1119     pd->cfg_reg_write = symphony_82c105_cfg_reg_write;
1120 dpavlin 20 }
1121    
1122    
1123    
1124     /*
1125 dpavlin 40 * 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 dpavlin 20 * 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 dpavlin 34 int pci_int_line = 0x101, irq = 0, isa = 0;
1180     char irqstr[200];
1181 dpavlin 20 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 dpavlin 22 /* CATS int 18 = PCI. */
1196 dpavlin 20 irq = 18;
1197 dpavlin 22 pci_int_line = 0x101;
1198 dpavlin 20 break;
1199 dpavlin 22 case MACHINE_COBALT:
1200     /* On Cobalt, IRQ 7 = PCI. */
1201     irq = 8 + 7;
1202     pci_int_line = 0x407;
1203     break;
1204 dpavlin 20 case MACHINE_PREP:
1205 dpavlin 34 irq = 10;
1206     isa = 1;
1207 dpavlin 22 pci_int_line = 0x20a;
1208 dpavlin 20 break;
1209 dpavlin 22 case MACHINE_MVMEPPC:
1210     /* TODO */
1211 dpavlin 34 irq = 10;
1212 dpavlin 22 pci_int_line = 0x40a;
1213     break;
1214 dpavlin 20 case MACHINE_PMPPC:
1215 dpavlin 22 /* TODO, not working yet */
1216 dpavlin 42 irq = 31 - CPC_IB_EXT1;
1217     pci_int_line = 0x101;
1218 dpavlin 20 break;
1219 dpavlin 22 case MACHINE_MACPPC:
1220     /* TODO, not working yet */
1221     irq = 25;
1222     pci_int_line = 0x101;
1223     break;
1224 dpavlin 20 }
1225    
1226 dpavlin 22 PCI_SET_DATA(PCI_INTERRUPT_REG, 0x28140000 | pci_int_line);
1227 dpavlin 20
1228     allocate_device_space(pd, 0x100, 0x100, &port, &memaddr);
1229    
1230 dpavlin 34 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 dpavlin 20 snprintf(tmpstr, sizeof(tmpstr), "dec21143 addr=0x%llx addr2=0x%llx "
1238 dpavlin 34 "irq=%s pci_little_endian=1", (long long)port,
1239     (long long)memaddr, irqstr);
1240    
1241 dpavlin 20 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 dpavlin 22
1299 dpavlin 20 /*
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 dpavlin 22
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