/[gxemul]/trunk/src/devices/dev_wdsc.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/dev_wdsc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 20 - (hide annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 10140 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


1 dpavlin 4 /*
2     * Copyright (C) 2004-2005 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 dpavlin 20 * $Id: dev_wdsc.c,v 1.28 2005/11/13 00:14:10 debug Exp $
29 dpavlin 4 *
30     * WDSC SCSI (WD33C93) controller.
31     * (For SGI-IP22. See sys/arch/sgimips/hpc/sbic* in NetBSD for details.)
32     *
33     * TODO: This device doesn't do much yet.
34     */
35    
36     #include <stdio.h>
37     #include <stdlib.h>
38     #include <string.h>
39    
40     #include "cpu.h"
41     #include "devices.h"
42     #include "diskimage.h"
43     #include "machine.h"
44     #include "memory.h"
45     #include "misc.h"
46    
47     #include "wdsc_sbicreg.h"
48    
49    
50     struct wdsc_data {
51     int irq_nr;
52     int controller_nr;
53    
54     int register_select;
55     unsigned char reg[DEV_WDSC_NREGS];
56    
57     int irq_pending;
58    
59     int buf_allocatedlen;
60     int buf_curptr;
61     unsigned char *buf;
62    
63     int current_phase;
64    
65     struct scsi_transfer *xfer;
66     };
67    
68    
69     /*
70     * dev_wdsc_tick():
71     */
72     void dev_wdsc_tick(struct cpu *cpu, void *extra)
73     {
74     struct wdsc_data *d = extra;
75    
76     if (d->irq_pending)
77     cpu_interrupt(cpu, d->irq_nr);
78     else
79     cpu_interrupt_ack(cpu, d->irq_nr);
80     }
81    
82    
83     /*
84     * dev_wdsc_regwrite():
85     *
86     * Handle writes to WDSC registers.
87     */
88     static void dev_wdsc_regwrite(struct cpu *cpu, struct wdsc_data *d, int idata)
89     {
90     d->reg[d->register_select] = idata & 0xff;
91    
92     debug("[ wdsc: write to register %i", d->register_select);
93    
94     switch (d->register_select) {
95    
96     case SBIC_myid:
97     debug(" (myid): 0x%02x => ", (int)idata);
98     if (idata & SBIC_ID_FS_16_20)
99     debug("16-20MHz, ");
100     if (idata & SBIC_ID_FS_12_15)
101     debug("12-15MHz, ");
102     if (idata & SBIC_ID_RAF)
103     debug("RAF(?), ");
104     if (idata & SBIC_ID_EHP)
105     debug("Parity, ");
106     if (idata & SBIC_ID_EAF)
107     debug("EnableAdvancedFeatures, ");
108     debug("ID=%i", idata & SBIC_ID_MASK);
109     break;
110    
111     case SBIC_control:
112     debug(" (control): 0x%02x =>", (int)idata);
113     if (idata & SBIC_CTL_DMA)
114     debug(" SingleByteDMA");
115     if (idata & SBIC_CTL_DBA_DMA)
116     debug(" DirectBufferAccess");
117     if (idata & SBIC_CTL_BURST_DMA)
118     debug(" BurstDMA");
119     if (idata & SBIC_CTL_HHP)
120     debug(" HaltOnParity");
121     if (idata & SBIC_CTL_EDI)
122     debug(" EndDisconIntr");
123     if (idata & SBIC_CTL_IDI)
124     debug(" IntermediateDisconIntr");
125     if (idata & SBIC_CTL_HA)
126     debug(" HaltOnATN");
127     if (idata & SBIC_CTL_HSP)
128     debug(" HaltOnParityError");
129    
130     if (idata == SBIC_CTL_NO_DMA)
131     debug(" PIO");
132    
133     /* TODO: When/how are interrupts acknowledged? */
134     if (idata & SBIC_CTL_EDI)
135     d->irq_pending = 0;
136    
137     break;
138    
139     case SBIC_count_hi:
140     debug(" (count_hi): 0x%02x", (int)idata);
141     break;
142    
143     case SBIC_count_med:
144     debug(" (count_med): 0x%02x", (int)idata);
145     break;
146    
147     case SBIC_count_lo:
148     debug(" (count_lo): 0x%02x", (int)idata);
149     break;
150    
151     case SBIC_selid:
152     debug(" (selid): 0x%02x => ", (int)idata);
153    
154     if (idata & SBIC_SID_SCC)
155     debug("SelectCommandChaining, ");
156     if (idata & SBIC_SID_FROM_SCSI)
157     debug("FromSCSI, ");
158     else
159     debug("ToSCSI, ");
160    
161     debug("id %i", idata & SBIC_SID_IDMASK);
162     break;
163    
164     case SBIC_rselid:
165     debug(" (rselid): 0x%02x => ", (int)idata);
166    
167     if (idata & SBIC_RID_ER)
168     debug("EnableReselection, ");
169     if (idata & SBIC_RID_ES)
170     debug("EnableSelection, ");
171     if (idata & SBIC_RID_DSP)
172     debug("DisableSelectParity, ");
173     if (idata & SBIC_RID_SIV)
174     debug("SourceIDValid, ");
175    
176     debug("id %i", idata & SBIC_RID_MASK);
177     break;
178    
179     case SBIC_cmd:
180     debug(" (cmd): 0x%02x => ", (int)idata);
181    
182     /* SBT = Single Byte Transfer */
183     if (idata & SBIC_CMD_SBT)
184     debug("SBT, ");
185    
186     /* Handle commands: */
187     switch (idata & SBIC_CMD_MASK) {
188     case SBIC_CMD_RESET:
189     debug("RESET");
190     d->irq_pending = 1;
191     d->reg[SBIC_csr] = SBIC_CSR_RESET;
192     break;
193     case SBIC_CMD_ABORT:
194     debug("ABORT");
195     break;
196     case SBIC_CMD_SEL_ATN:
197     debug("SEL_ATN");
198     d->irq_pending = 1;
199     d->reg[SBIC_csr] = SBIC_CSR_SEL_TIMEO;
200     if (d->controller_nr == 0 && diskimage_exist(
201     cpu->machine, d->reg[SBIC_selid] &
202 dpavlin 6 SBIC_SID_IDMASK, DISKIMAGE_SCSI)) {
203 dpavlin 4 if (d->xfer != NULL)
204     scsi_transfer_free(d->xfer);
205     d->xfer = scsi_transfer_alloc();
206    
207     /* According to NetBSD, we can go either to
208     SBIC_CSR_MIS_2 | CMD_PHASE, or
209     SBIC_CSR_MIS_2 | MESG_OUT_PHASE. */
210    
211     d->reg[SBIC_csr] = SBIC_CSR_MIS_2 | CMD_PHASE;
212    
213     d->current_phase = CMD_PHASE;
214     }
215     break;
216     case SBIC_CMD_XFER_INFO:
217     debug("XFER_INFO");
218    
219     if (d->buf != NULL)
220     free(d->buf);
221    
222     d->buf_allocatedlen = (d->reg[SBIC_count_hi] << 16)
223     + (d->reg[SBIC_count_med] << 8) +
224     d->reg[SBIC_count_lo];
225    
226     d->buf = malloc(d->buf_allocatedlen);
227     if (d->buf == NULL) {
228     fprintf(stderr, "out of memory in wdsc\n");
229     exit(1);
230     }
231    
232     d->buf_curptr = 0;
233     d->irq_pending = 0;
234     break;
235     default:
236     debug("unimplemented command");
237     }
238     break;
239    
240     case SBIC_data:
241     debug(" (data): 0x%02x", (int)idata);
242    
243     switch (d->reg[SBIC_cmd] & ~SBIC_CMD_SBT) {
244     case SBIC_CMD_XFER_INFO:
245     if (d->buf == NULL || d->buf_curptr >=
246     d->buf_allocatedlen) {
247     fprintf(stderr, "fatal error in wdsc\n");
248     exit(1);
249     }
250    
251     d->buf[d->buf_curptr++] = idata;
252    
253     if (d->buf_curptr >= d->buf_allocatedlen) {
254     int res;
255    
256     /*
257     * Transfer buf to/from the SCSI unit:
258     */
259    
260     switch (d->current_phase) {
261     case CMD_PHASE:
262     scsi_transfer_allocbuf(
263     &d->xfer->cmd_len, &d->xfer->cmd,
264     d->buf_allocatedlen, 1);
265     memcpy(d->xfer->cmd, d->buf,
266     d->buf_allocatedlen);
267     break;
268     default:
269     fatal("wdsc: unimplemented phase %i!\n",
270     d->current_phase);
271     }
272    
273     res = diskimage_scsicommand(cpu,
274     d->reg[SBIC_selid] & SBIC_SID_IDMASK,
275 dpavlin 6 DISKIMAGE_SCSI, d->xfer);
276 dpavlin 4 debug("{ res = %i }", res);
277    
278     d->irq_pending = 1;
279    
280     if (res == 2)
281     d->reg[SBIC_csr] = SBIC_CSR_XFERRED |
282     DATA_OUT_PHASE;
283     else
284     d->reg[SBIC_csr] = SBIC_CSR_XFERRED |
285     DATA_IN_PHASE;
286    
287     /* status phase? msg in and msg out? */
288     }
289     break;
290     default:
291     fatal("[ wdsc: don't know how to handle data for "
292     "cmd = 0x%02x ]\n", d->reg[SBIC_cmd]);
293     }
294    
295     break;
296    
297     default:
298     debug(" (TODO): 0x%02x", (int)idata);
299     }
300    
301     debug(" ]\n");
302    
303     /* After writing to a register, advance to the next: */
304     d->register_select ++;
305     }
306    
307    
308     /*
309     * dev_wdsc_access():
310     */
311     int dev_wdsc_access(struct cpu *cpu, struct memory *mem,
312     uint64_t relative_addr, unsigned char *data, size_t len,
313     int writeflag, void *extra)
314     {
315     int i;
316     struct wdsc_data *d = extra;
317     uint64_t idata = 0, odata = 0;
318    
319 dpavlin 18 if (writeflag == MEM_WRITE)
320     idata = memory_readmax64(cpu, data, len);
321 dpavlin 4
322     /*
323     * All registers on the WDSC seem to be accessed by writing the
324     * register number to one address (SBIC_ADDR), and then reading/
325     * writing another address (SBIC_VAL).
326     *
327     * On SGI-IP22, these are at offset 3 and 7, respectively.
328     *
329     * TODO: If this device is to be used by other machine types, then
330     * this needs to be conditionalized.
331     */
332     relative_addr = (relative_addr - 3) / 4;
333    
334     switch (relative_addr) {
335    
336     case SBIC_ADDR:
337     /*
338     * Reading the combined ADDR/ASR returns the Status
339     * Register, writing selects which register to access
340     * via SBIC_VAL.
341     */
342     if (writeflag == MEM_READ) {
343     odata = SBIC_ASR_DBR;
344     if (d->irq_pending)
345     odata |= SBIC_ASR_INT;
346    
347     debug("[ wdsc: read from Status Register: %02x ]\n",
348     (int)odata);
349     } else {
350     d->register_select = idata & (DEV_WDSC_NREGS - 1);
351     }
352     break;
353    
354     case SBIC_VAL:
355     if (writeflag == MEM_READ) {
356     odata = d->reg[d->register_select];
357    
358     if (d->register_select == SBIC_csr) {
359     /* TODO: when should interrupts actually be
360     ack:ed? */
361     d->irq_pending = 0;
362     }
363    
364     debug("[ wdsc: read from register %i: 0x%02x ]\n",
365     d->register_select, (int)odata);
366     } else {
367     dev_wdsc_regwrite(cpu, d, idata & 0xff);
368     }
369     break;
370    
371     default:
372     /* These should never occur: */
373     if (writeflag==MEM_READ) {
374     fatal("[ wdsc: read from 0x%x:", (int)relative_addr);
375     for (i=0; i<len; i++)
376     fatal(" %02x", data[i]);
377     fatal(" (len=%i) ]\n", len);
378     } else {
379     fatal("[ wdsc: write to 0x%x:", (int)relative_addr);
380     for (i=0; i<len; i++)
381     fatal(" %02x", data[i]);
382     fatal(" (len=%i) ]\n", len);
383     }
384     }
385    
386     if (writeflag == MEM_READ)
387     memory_writemax64(cpu, data, len, odata);
388    
389     dev_wdsc_tick(cpu, extra);
390    
391     return 1;
392     }
393    
394    
395     /*
396     * dev_wdsc_init():
397     */
398     void dev_wdsc_init(struct machine *machine, struct memory *mem,
399     uint64_t baseaddr, int controller_nr, int irq_nr)
400     {
401     struct wdsc_data *d;
402    
403     d = malloc(sizeof(struct wdsc_data));
404     if (d == NULL) {
405     fprintf(stderr, "out of memory\n");
406     exit(1);
407     }
408     memset(d, 0, sizeof(struct wdsc_data));
409     d->irq_nr = irq_nr;
410     d->controller_nr = controller_nr;
411    
412     memory_device_register(mem, "wdsc", baseaddr, DEV_WDSC_LENGTH,
413 dpavlin 20 dev_wdsc_access, d, DM_DEFAULT, NULL);
414 dpavlin 4
415     machine_add_tickfunction(machine, dev_wdsc_tick, d, 14);
416     }
417    

  ViewVC Help
Powered by ViewVC 1.1.26