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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (hide annotations)
Mon Oct 8 16:18:11 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 31475 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.772 2005/06/04 12:02:16 debug Exp $
20050428	Disabling the "-fmove-all-movables" option in the configure
		script, because it causes the compile to fail on OpenBSD/sgi.
20050502	Minor updates.
20050503	Removing the WRT54G mode (it was bogus anyway), and adding a
		comment about Windows NT for MIPS in doc/experiments.html.
		Minor updates to the x86 instruction decoding.
20050504	Adding some more x86 instructions.
		Adding support for reading files from ISO9660 CDROMs (including
		gzipped files). It's an ugly hack, but it seems to work.
		Various other minor updates (dev_vga.c, pc_bios.c etc).
20050505	Some more x86-related updates.
		Beginning (what I hope will be) a major code cleanup phase.
		"bootris" (an x86 bootsector) runs :-)
20050506	Adding some more x86 instructions.
20050507	tmpnam => mkstemp.
		Working on a hack to allow VGA charcells to be shown even when
		not running with X11.
		Adding more x86 instructions.
20050508	x86 32-bit SIB addressing fix, and more instructions.
20050509	Adding more x86 instructions.
20050510	Minor documentation updates, and other updates (x86 stuff etc.)
20050511	More x86-related updates.
20050513	Various updates, mostly x86-related. (Trying to fix flag 
		calculation, factoring out the ugly shift/rotate code, and
		some other things.)
20050514	Adding support for loading some old i386 a.out executables.
		Finally beginning the cleanup of machine/PROM/bios dependant
		info.
		Some minor documentation updates.
		Trying to clean up ARCBIOS stuff a little.
20050515	Trying to make it possible to actually use more than one disk
		type per machine (floppy, ide, scsi).
		Trying to clean up the kbd vs PROM console stuff. (For PC and
		ARC emulation modes, mostly.)
		Beginning to add an 8259 interrupt controller, and connecting
		it to the x86 emulation.
20050516	The first x86 interrupts seem to work (keyboard stuff).
		Adding a 8253/8254 programmable interval timer skeleton.
		FreeDOS now reaches a command prompt and can be interacted
		with.
20050517	After some bugfixes, MS-DOS also (sometimes) reaches a
		command prompt now.
		Trying to fix the pckbc to work with MS-DOS' keyb.com, but no
		success yet.
20050518	Adding a simple 32-bit x86 MMU skeleton.
20050519	Some more work on the x86 stuff. (Beginning the work on paging,
		and various other fixes).
20050520	More updates. Working on dev_vga (4-bit graphics modes), adding
		40 columns support to the PC bios emulation.
		Trying to add support for resizing windows when switching
		between graphics modes.
20050521	Many more x86-related updates.
20050522	Correcting the initial stack pointer's sign-extension for
		ARCBIOS emulation (thanks to Alec Voropay for noticing the
		error).
		Continuing on the cleanup (ARCBIOS etc).
		dev_vga updates.
20050523	More x86 updates: trying to add some support for protected mode
		interrupts (via gate descriptors) and many other fixes.
		More ARCBIOS cleanup.
		Adding a device flag which indicates that reads cause no
		side-effects. (Useful for the "dump" command in the debugger,
		and other things.)
		Adding support for directly starting up x86 ELFs, skipping the
		bootloader stage. (Most ELFs, however, are not suitable for
		this.)
20050524	Adding simple 32-bit x86 TSS task switching, but no privilege
		level support yet.
		More work on dev_vga. A small "Copper bars" demo works. :-)
		Adding support for Trap Flag (single-step exceptions), at least
		in real mode, and various other x86-related fixes.
20050525	Adding a new disk image prefix (gH;S;) which can be used to
		override the default nr of heads and sectors per track.
20050527	Various bug fixes, more work on the x86 mode (stack change on
		interrupts between different priv.levels), and some minor
		documentation updates.
20050528	Various fixes (x86 stuff).
20050529	More x86 fixes. An OpenBSD/i386 bootfloppy reaches userland
		and can be interacted with (although there are problems with
		key repetition). NetBSD/i386 triggers a serious CISC-related
		problem: instruction fetches across page boundaries, where
		the later part isn't actually part of the instruction.
20050530	Various minor updates. (Documentation updates, etc.)
20050531	Adding some experimental code (experiments/new_test_*) which
		could be useful for dynamic (but not binary) translation in
		the future.
20050602	Adding a dummy ARM skeleton.
		Fixing the pckbc key repetition problem (by adding release
		scancodes for all keypresses).
20050603	Minor updates for the next release.
20050604	Release testing. Minor updates.

==============  RELEASE 0.3.3  ==============

20050604	There'll probably be a 0.3.3.1 release soon, with some very
		very tiny updates.


1 dpavlin 4 /*
2     * Copyright (C) 2003-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 6 * $Id: dev_asc.c,v 1.71 2005/05/15 01:55:50 debug Exp $
29 dpavlin 4 *
30     * 'asc' SCSI controller for some DECstation/DECsystem models, and
31     * for PICA-61.
32     *
33     * Supposed to support SCSI-1 and SCSI-2. I've not yet found any docs
34     * on NCR53C9X, so I'll try to implement this device from LSI53CF92A docs
35     * instead.
36     *
37     *
38     * Memory layout on DECstation:
39     *
40     * NCR53C94 registers at base + 0
41     * DMA address register at base + 0x40000
42     * 128K SRAM buffer at base + 0x80000
43     * ROM at base + 0xc0000
44     *
45     * Memory layout on PICA-61:
46     *
47     * I haven't had time to look this up yet, but length = 0x1000.
48     *
49     *
50     * TODO: This module needs a clean-up, and some testing to see that
51     * it works will all OSes that might use it (NetBSD, OpenBSD,
52     * Ultrix, Linux, Mach, OSF/1, Sprite, ...)
53     */
54    
55     #include <stdio.h>
56     #include <stdlib.h>
57     #include <string.h>
58    
59     #include "cpu.h"
60     #include "devices.h"
61     #include "diskimage.h"
62     #include "machine.h"
63     #include "memory.h"
64     #include "misc.h"
65    
66     #include "ncr53c9xreg.h"
67    
68    
69     /* #define ASC_DEBUG */
70     /* #define debug fatal */
71     /* #define ASC_FULL_REGISTER_ACCESS_DEBUG */
72     /* static int quiet_mode = 0; */
73    
74     extern int quiet_mode;
75    
76    
77     #define ASC_FIFO_LEN 16
78     #define STATE_DISCONNECTED 0
79     #define STATE_INITIATOR 1
80     #define STATE_TARGET 2
81    
82     #define PHASE_DATA_OUT 0
83     #define PHASE_DATA_IN 1
84     #define PHASE_COMMAND 2
85     #define PHASE_STATUS 3
86     #define PHASE_MSG_OUT 6
87     #define PHASE_MSG_IN 7
88    
89    
90     /* The controller's SCSI id: */
91     #define ASC_SCSI_ID 7
92    
93     struct asc_data {
94     int mode;
95    
96     void *turbochannel;
97     int irq_nr;
98     int irq_caused_last_time;
99    
100     /* Current state and transfer: */
101     int cur_state;
102     int cur_phase;
103     struct scsi_transfer *xferp;
104    
105     /* FIFO: */
106     unsigned char fifo[ASC_FIFO_LEN];
107     int fifo_in;
108     int fifo_out;
109     int n_bytes_in_fifo; /* cached */
110    
111     /* ATN signal: */
112     int atn;
113    
114     /* Incoming dma data: */
115     unsigned char *incoming_data;
116     int incoming_len;
117     int incoming_data_addr;
118    
119     /* Built-in DMA memory (for DECstation 5000/200): */
120     uint32_t dma_address_reg;
121     unsigned char dma_address_reg_memory[4096];
122     /* NOTE: full page, for bintrans */
123     unsigned char dma[128 * 1024];
124    
125     void *dma_controller_data;
126     size_t (*dma_controller)(void *dma_controller_data,
127     unsigned char *data, size_t len, int writeflag);
128    
129     /* Read registers and write registers: */
130     uint32_t reg_ro[0x10];
131     uint32_t reg_wo[0x10];
132     };
133    
134     /* (READ/WRITE name, if split) */
135     char *asc_reg_names[0x10] = {
136     "NCR_TCL", "NCR_TCM", "NCR_FIFO", "NCR_CMD",
137     "NCR_STAT/NCR_SELID", "NCR_INTR/NCR_TIMEOUT",
138     "NCR_STEP/NCR_SYNCTP", "NCR_FFLAG/NCR_SYNCOFF",
139     "NCR_CFG1", "NCR_CCF", "NCR_TEST", "NCR_CFG2",
140     "NCR_CFG3", "reg_0xd", "NCR_TCH", "reg_0xf"
141     };
142    
143    
144     /* This is referenced below. */
145     static int dev_asc_select(struct cpu *cpu, struct asc_data *d, int from_id,
146     int to_id, int dmaflag, int n_messagebytes);
147    
148    
149     /*
150     * dev_asc_tick():
151     *
152     * This function is called "every now and then" from the CPU
153     * main loop.
154     */
155     void dev_asc_tick(struct cpu *cpu, void *extra)
156     {
157     struct asc_data *d = extra;
158    
159     if (d->reg_ro[NCR_STAT] & NCRSTAT_INT)
160     cpu_interrupt(cpu, d->irq_nr);
161     }
162    
163    
164     /*
165     * dev_asc_fifo_flush():
166     *
167     * Flush the fifo.
168     */
169     static void dev_asc_fifo_flush(struct asc_data *d)
170     {
171     d->fifo[0] = 0x00;
172     d->fifo_in = 0;
173     d->fifo_out = 0;
174     d->n_bytes_in_fifo = 0;
175     }
176    
177    
178     /*
179     * dev_asc_reset():
180     *
181     * Reset the state of the asc.
182     */
183     static void dev_asc_reset(struct asc_data *d)
184     {
185     d->cur_state = STATE_DISCONNECTED;
186     d->atn = 0;
187    
188     if (d->xferp != NULL)
189     scsi_transfer_free(d->xferp);
190     d->xferp = NULL;
191    
192     dev_asc_fifo_flush(d);
193    
194     /* According to table 4.1 in the LSI53CF92A manual: */
195     memset(d->reg_wo, 0, sizeof(d->reg_wo));
196     d->reg_wo[NCR_TCH] = 0x94;
197     d->reg_wo[NCR_CCF] = 2;
198     memcpy(d->reg_ro, d->reg_wo, sizeof(d->reg_ro));
199     d->reg_wo[NCR_SYNCTP] = 5;
200     }
201    
202    
203     /*
204     * dev_asc_fifo_read():
205     *
206     * Read a byte from the asc FIFO.
207     */
208     static int dev_asc_fifo_read(struct asc_data *d)
209     {
210     int res = d->fifo[d->fifo_out];
211    
212     if (d->fifo_in == d->fifo_out)
213     fatal("dev_asc: WARNING! FIFO overrun!\n");
214    
215     d->fifo_out = (d->fifo_out + 1) % ASC_FIFO_LEN;
216     d->n_bytes_in_fifo --;
217    
218     return res;
219     }
220    
221    
222     /*
223     * dev_asc_fifo_write():
224     *
225     * Write a byte to the asc FIFO.
226     */
227     static void dev_asc_fifo_write(struct asc_data *d, unsigned char data)
228     {
229     d->fifo[d->fifo_in] = data;
230     d->fifo_in = (d->fifo_in + 1) % ASC_FIFO_LEN;
231     d->n_bytes_in_fifo ++;
232    
233     if (d->fifo_in == d->fifo_out)
234     fatal("dev_asc: WARNING! FIFO overrun on write!\n");
235     }
236    
237    
238     /*
239     * dev_asc_newxfer():
240     *
241     * Allocate memory for a new transfer.
242     */
243     static void dev_asc_newxfer(struct asc_data *d)
244     {
245     if (d->xferp != NULL) {
246     printf("WARNING! dev_asc_newxfer(): freeing previous"
247     " transfer\n");
248     scsi_transfer_free(d->xferp);
249     d->xferp = NULL;
250     }
251    
252     d->xferp = scsi_transfer_alloc();
253     #if 0
254     d->xferp->get_data_out = dev_asc_get_data_out;
255     d->xferp->gdo_extra = (void *) d;
256     #endif
257     }
258    
259    
260     /*
261     * dev_asc_transfer():
262     *
263     * Transfer data from a SCSI device to the controller (or vice versa),
264     * depending on the current phase.
265     *
266     * Returns 1 if ok, 0 on error.
267     */
268     static int dev_asc_transfer(struct cpu *cpu, struct asc_data *d, int dmaflag)
269     {
270     int res = 1, all_done = 1;
271     int len, i, ch;
272    
273     if (!quiet_mode)
274     debug(" { TRANSFER to/from id %i: ", d->reg_wo[NCR_SELID] & 7);
275    
276     if (d->cur_phase == PHASE_DATA_IN) {
277     /* Data coming into the controller from external device: */
278     if (!dmaflag) {
279     if (d->xferp->data_in == NULL) {
280     fatal("no incoming data?\n");
281     res = 0;
282     } else {
283     /* TODO */
284     fatal("TODO..............\n");
285     len = d->reg_wo[NCR_TCL] +
286     d->reg_wo[NCR_TCM] * 256;
287    
288     len--;
289     ch = d->incoming_data[d->incoming_data_addr];
290     debug(" %02x", ch);
291    
292     d->incoming_data_addr ++;
293     dev_asc_fifo_write(d, ch);
294    
295     if (len == 0) {
296     free(d->incoming_data);
297     d->incoming_data = NULL;
298     }
299    
300     d->reg_ro[NCR_TCL] = len & 255;
301     d->reg_ro[NCR_TCM] = (len >> 8) & 255;
302     }
303     } else {
304     /* Copy from the incoming data into dma memory: */
305     if (d->xferp->data_in == NULL) {
306     fatal("no incoming DMA data?\n");
307     res = 0;
308     } else {
309     int len = d->xferp->data_in_len;
310     int len2 = d->reg_wo[NCR_TCL] +
311     d->reg_wo[NCR_TCM] * 256;
312     if (len2 == 0)
313     len2 = 65536;
314    
315     if (len < len2) {
316     fatal("{ asc: data in, len=%i len2=%i "
317     "}\n", len, len2);
318     }
319    
320     /* TODO: check len2 in a similar way? */
321     if (len + (d->dma_address_reg &
322     ((sizeof(d->dma)-1))) > sizeof(d->dma))
323     len = sizeof(d->dma) -
324     (d->dma_address_reg &
325     ((sizeof(d->dma)-1)));
326    
327     if (len2 > len) {
328     memset(d->dma + (d->dma_address_reg &
329     ((sizeof(d->dma)-1))), 0, len2);
330     len2 = len;
331     }
332    
333     #ifdef ASC_DEBUG
334     if (!quiet_mode) {
335     int i;
336     for (i=0; i<len; i++)
337     debug(" %02x", d->xferp->
338     data_in[i]);
339     }
340     #endif
341    
342     /*
343     * Are we using an external DMA controller?
344     * Then use it. Otherwise place the data in
345     * the DECstation 5000/200 built-in DMA
346     * region.
347     */
348     if (d->dma_controller != NULL)
349     d->dma_controller(
350     d->dma_controller_data,
351     d->xferp->data_in,
352     len2, 1);
353     else
354     memcpy(d->dma + (d->dma_address_reg &
355     ((sizeof(d->dma)-1))),
356     d->xferp->data_in, len2);
357    
358     if (d->xferp->data_in_len > len2) {
359     unsigned char *n;
360    
361     if (d->dma_controller != NULL)
362     printf("WARNING!!!!!!!!! BUG!!!! Unexpected stuff..."
363     "len2=%i d->xferp->data_in_len=%i\n", (int)len2,
364     (int)d->xferp->data_in_len);
365    
366     all_done = 0;
367     /* fatal("{ asc: multi-transfer"
368     " data_in, len=%i len2=%i }\n",
369     (int)len, (int)len2); */
370    
371     d->xferp->data_in_len -= len2;
372     n = malloc(d->xferp->data_in_len);
373     if (n == NULL) {
374     fprintf(stderr, "out of memory"
375     " in dev_asc\n");
376     exit(1);
377     }
378     memcpy(n, d->xferp->data_in + len2,
379     d->xferp->data_in_len);
380     free(d->xferp->data_in);
381     d->xferp->data_in = n;
382    
383     len = len2;
384     }
385    
386     len = 0;
387    
388     d->reg_ro[NCR_TCL] = len & 255;
389     d->reg_ro[NCR_TCM] = (len >> 8) & 255;
390    
391     /* Successful DMA transfer: */
392     d->reg_ro[NCR_STAT] |= NCRSTAT_TC;
393     }
394     }
395     } else if (d->cur_phase == PHASE_DATA_OUT) {
396     /* Data going from the controller to an external device: */
397     if (!dmaflag) {
398     fatal("TODO.......asdgasin\n");
399     } else {
400     /* Copy data from DMA to data_out: */
401     int len = d->xferp->data_out_len;
402     int len2 = d->reg_wo[NCR_TCL] +
403     d->reg_wo[NCR_TCM] * 256;
404     if (len2 == 0)
405     len2 = 65536;
406    
407     if (len == 0) {
408     fprintf(stderr, "d->xferp->data_out_len == "
409     "0 ?\n");
410     exit(1);
411     }
412    
413     /* TODO: Make sure that len2 doesn't go outside
414     of the dma memory? */
415    
416     /* fatal(" data out offset=%5i len=%5i\n",
417     d->xferp->data_out_offset, len2); */
418    
419     if (d->xferp->data_out_offset + len2 >
420     d->xferp->data_out_len) {
421     len2 = d->xferp->data_out_len -
422     d->xferp->data_out_offset;
423     }
424    
425     /*
426     * Are we using an external DMA controller? Then use
427     * it. Otherwise place the data in the DECstation
428     * 5000/200 built-in DMA region.
429     */
430     if (d->xferp->data_out == NULL) {
431     scsi_transfer_allocbuf(&d->xferp->data_out_len,
432     &d->xferp->data_out, len, 0);
433    
434     if (d->dma_controller != NULL)
435     d->dma_controller(
436     d->dma_controller_data,
437     d->xferp->data_out,
438     len2, 0);
439     else
440     memcpy(d->xferp->data_out,
441     d->dma + (d->dma_address_reg &
442     ((sizeof(d->dma)-1))), len2);
443     d->xferp->data_out_offset = len2;
444     } else {
445     /* Continuing a multi-transfer: */
446     if (d->dma_controller != NULL)
447     d->dma_controller(
448     d->dma_controller_data,
449     d->xferp->data_out +
450     d->xferp->data_out_offset,
451     len2, 0);
452     else
453     memcpy(d->xferp->data_out +
454     d->xferp->data_out_offset,
455     d->dma + (d->dma_address_reg &
456     ((sizeof(d->dma)-1))), len2);
457     d->xferp->data_out_offset += len2;
458     }
459    
460     /* If the disk wants more than we're DMAing,
461     then this is a multitransfer: */
462     if (d->xferp->data_out_offset !=
463     d->xferp->data_out_len) {
464     if (!quiet_mode)
465     debug("[ asc: data_out, multitransfer "
466     "len = %i, len2 = %i ]\n",
467     (int)len, (int)len2);
468     if (d->xferp->data_out_offset >
469     d->xferp->data_out_len)
470     fatal("[ asc data_out dma: too much?"
471     " ]\n");
472     else
473     all_done = 0;
474     }
475    
476     #ifdef ASC_DEBUG
477     if (!quiet_mode) {
478     int i;
479     for (i=0; i<len; i++)
480     debug(" %02x", d->xferp->data_out[i]);
481     }
482     #endif
483     len = 0;
484    
485     d->reg_ro[NCR_TCL] = len & 255;
486     d->reg_ro[NCR_TCM] = (len >> 8) & 255;
487    
488     /* Successful DMA transfer: */
489     d->reg_ro[NCR_STAT] |= NCRSTAT_TC;
490     }
491     } else if (d->cur_phase == PHASE_MSG_OUT) {
492     if (!quiet_mode)
493     debug("MSG OUT: ");
494     /* Data going from the controller to an external device: */
495     if (!dmaflag) {
496     /* There should already be one byte in msg_out, so we
497     just extend the message: */
498     int oldlen = d->xferp->msg_out_len;
499     int newlen;
500    
501     if (oldlen != 1) {
502     fatal(" (PHASE OUT MSG len == %i, "
503     "should be 1)\n", oldlen);
504     }
505    
506     newlen = oldlen + d->n_bytes_in_fifo;
507     d->xferp->msg_out = realloc(d->xferp->msg_out, newlen);
508     d->xferp->msg_out_len = newlen;
509     if (d->xferp->msg_out == NULL) {
510     fprintf(stderr, "out of memory realloc'ing "
511     "msg_out\n");
512     exit(1);
513     }
514    
515     i = oldlen;
516     while (d->fifo_in != d->fifo_out) {
517     ch = dev_asc_fifo_read(d);
518     d->xferp->msg_out[i++] = ch;
519     #ifdef ASC_DEBUG
520     debug("0x%02x ", ch);
521     #endif
522     }
523    
524     #ifdef MACH
525     /* Super-ugly hack for Mach/PMAX: TODO: make nicer */
526     if (d->xferp->msg_out_len == 6 &&
527     (d->xferp->msg_out[0] == 0x80 ||
528     d->xferp->msg_out[0] == 0xc0) &&
529     d->xferp->msg_out[1] == 0x01 &&
530     d->xferp->msg_out[2] == 0x03 &&
531     d->xferp->msg_out[3] == 0x01 &&
532     d->xferp->msg_out[4] == 0x32 &&
533     d->xferp->msg_out[5] == 0x0f) {
534     fatal(" !! Mach/PMAX hack !! ");
535     all_done = 0;
536     d->cur_phase = PHASE_MSG_IN;
537     }
538     #endif
539     } else {
540     /* Copy data from DMA to msg_out: */
541     fatal("[ DMA MSG OUT: xxx TODO! ]");
542     /* TODO */
543     res = 0;
544     }
545     } else if (d->cur_phase == PHASE_MSG_IN) {
546     if (!quiet_mode)
547     debug(" MSG IN");
548     fatal("[ MACH HACK! ]");
549     /* Super-ugly hack for Mach/PMAX: TODO: make nicer */
550     dev_asc_fifo_write(d, 0x07);
551     d->cur_phase = PHASE_COMMAND;
552     all_done = 0;
553     } else if (d->cur_phase == PHASE_COMMAND) {
554     if (!quiet_mode)
555     debug(" COMMAND ==> select ");
556     res = dev_asc_select(cpu, d, d->reg_ro[NCR_CFG1] & 7,
557     d->reg_wo[NCR_SELID] & 7, dmaflag, 0);
558     return res;
559     } else {
560     fatal("!!! TODO: unknown/unimplemented phase "
561     "in transfer: %i\n", d->cur_phase);
562     }
563    
564     /* Redo the command if data was just sent using DATA_OUT: */
565     if (d->cur_phase == PHASE_DATA_OUT) {
566 dpavlin 6 res = diskimage_scsicommand(cpu, d->reg_wo[NCR_SELID] & 7,
567     DISKIMAGE_SCSI, d->xferp);
568 dpavlin 4 }
569    
570     if (all_done) {
571     if (d->cur_phase == PHASE_MSG_OUT)
572     d->cur_phase = PHASE_COMMAND;
573     else
574     d->cur_phase = PHASE_STATUS;
575     }
576    
577     /*
578     * Cause an interrupt after the transfer:
579     *
580     * NOTE: Earlier I had this in here as well:
581     * d->reg_ro[NCR_INTR] |= NCRINTR_FC;
582     * but Linux/DECstation and OpenBSD/pmax seems to choke on that.
583     */
584     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
585     d->reg_ro[NCR_INTR] |= NCRINTR_BS;
586     d->reg_ro[NCR_STAT] = (d->reg_ro[NCR_STAT] & ~7) | d->cur_phase;
587     d->reg_ro[NCR_STEP] = (d->reg_ro[NCR_STEP] & ~7) | 4; /* 4? */
588    
589     if (!quiet_mode)
590     debug("}");
591     return res;
592     }
593    
594    
595     /*
596     * dev_asc_select():
597     *
598     * Select a SCSI device, send msg bytes (if any), and send command bytes.
599     * (Call diskimage_scsicommand() to handle the command.)
600     *
601     * Return value: 1 if ok, 0 on error.
602     */
603     static int dev_asc_select(struct cpu *cpu, struct asc_data *d, int from_id,
604     int to_id, int dmaflag, int n_messagebytes)
605     {
606     int ok, len, i, ch;
607    
608     if (!quiet_mode)
609     debug(" { SELECT id %i: ", to_id);
610    
611     /*
612     * Message bytes, if any:
613     */
614     if (!quiet_mode)
615     debug("msg:");
616    
617     if (n_messagebytes > 0) {
618     scsi_transfer_allocbuf(&d->xferp->msg_out_len,
619     &d->xferp->msg_out, n_messagebytes, 0);
620    
621     i = 0;
622     while (n_messagebytes-- > 0) {
623     int ch = dev_asc_fifo_read(d);
624     if (!quiet_mode)
625     debug(" %02x", ch);
626     d->xferp->msg_out[i++] = ch;
627     }
628    
629     if ((d->xferp->msg_out[0] & 0x7) != 0x00) {
630     debug(" (LUNs not implemented yet: 0x%02x) }",
631     d->xferp->msg_out[0]);
632     return 0;
633     }
634    
635     if (((d->xferp->msg_out[0] & ~0x7) != 0xc0) &&
636     ((d->xferp->msg_out[0] & ~0x7) != 0x80)) {
637     fatal(" (Unimplemented msg out: 0x%02x) }",
638     d->xferp->msg_out[0]);
639     return 0;
640     }
641    
642     if (d->xferp->msg_out_len > 1) {
643     fatal(" (Long msg out, not implemented yet;"
644     " len=%i) }", d->xferp->msg_out_len);
645     return 0;
646     }
647     } else {
648     if (!quiet_mode)
649     debug(" none");
650     }
651    
652     /* Special case: SELATNS (with STOP sequence): */
653     if (d->cur_phase == PHASE_MSG_OUT) {
654     if (!quiet_mode)
655     debug(" MSG OUT DEBUG");
656     if (d->xferp->msg_out_len != 1) {
657     fatal(" (SELATNS: msg out len == %i, should be 1)",
658     d->xferp->msg_out_len);
659     return 0;
660     }
661    
662     /* d->cur_phase = PHASE_COMMAND; */
663    
664     /* According to the LSI manual: */
665     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
666     d->reg_ro[NCR_INTR] |= NCRINTR_FC;
667     d->reg_ro[NCR_INTR] |= NCRINTR_BS;
668     d->reg_ro[NCR_STAT] = (d->reg_ro[NCR_STAT] & ~7) | d->cur_phase;
669     d->reg_ro[NCR_STEP] = (d->reg_ro[NCR_STEP] & ~7) | 1;
670    
671     if (!quiet_mode)
672     debug("}");
673     return 1;
674     }
675    
676     /*
677     * Command bytes:
678     */
679     if (!quiet_mode)
680     debug(", cmd: ");
681    
682     if (!dmaflag) {
683     if (!quiet_mode)
684     debug("[non-DMA] ");
685    
686     scsi_transfer_allocbuf(&d->xferp->cmd_len,
687     &d->xferp->cmd, d->n_bytes_in_fifo, 0);
688    
689     i = 0;
690     while (d->fifo_in != d->fifo_out) {
691     ch = dev_asc_fifo_read(d);
692     d->xferp->cmd[i++] = ch;
693     if (!quiet_mode)
694     debug("%02x ", ch);
695     }
696     } else {
697     if (!quiet_mode)
698     debug("[DMA] ");
699     len = d->reg_wo[NCR_TCL] + d->reg_wo[NCR_TCM] * 256;
700     if (len == 0)
701     len = 65536;
702    
703     scsi_transfer_allocbuf(&d->xferp->cmd_len,
704     &d->xferp->cmd, len, 0);
705    
706     for (i=0; i<len; i++) {
707     int ofs = d->dma_address_reg + i;
708     ch = d->dma[ofs & (sizeof(d->dma)-1)];
709     d->xferp->cmd[i] = ch;
710     if (!quiet_mode)
711     debug("%02x ", ch);
712     }
713    
714     d->reg_ro[NCR_TCL] = len & 255;
715     d->reg_ro[NCR_TCM] = (len >> 8) & 255;
716    
717     d->reg_ro[NCR_STAT] |= NCRSTAT_TC;
718     }
719    
720     /*
721     * Call the SCSI device to perform the command:
722     */
723 dpavlin 6 ok = diskimage_scsicommand(cpu, to_id, DISKIMAGE_SCSI, d->xferp);
724 dpavlin 4
725    
726     /* Cause an interrupt: */
727     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
728     d->reg_ro[NCR_INTR] |= NCRINTR_FC;
729     d->reg_ro[NCR_INTR] |= NCRINTR_BS;
730    
731     if (ok == 2)
732     d->cur_phase = PHASE_DATA_OUT;
733     else if (d->xferp->data_in != NULL)
734     d->cur_phase = PHASE_DATA_IN;
735     else
736     d->cur_phase = PHASE_STATUS;
737    
738     d->reg_ro[NCR_STAT] = (d->reg_ro[NCR_STAT] & ~7) | d->cur_phase;
739     d->reg_ro[NCR_STEP] = (d->reg_ro[NCR_STEP] & ~7) | 4; /* DONE (?) */
740    
741     if (!quiet_mode)
742     debug("}");
743    
744     return ok;
745     }
746    
747    
748     /*
749     * dev_asc_address_reg_access():
750     */
751     int dev_asc_address_reg_access(struct cpu *cpu, struct memory *mem,
752     uint64_t relative_addr, unsigned char *data, size_t len,
753     int writeflag, void *extra)
754     {
755     struct asc_data *d = extra;
756    
757     if (relative_addr + len > 4)
758     return 0;
759    
760     if (writeflag==MEM_READ) {
761     memcpy(data, d->dma_address_reg_memory + relative_addr, len);
762     } else {
763     memcpy(d->dma_address_reg_memory + relative_addr, data, len);
764     }
765    
766     return 1;
767     }
768    
769    
770     /*
771     * dev_asc_dma_access():
772     */
773     int dev_asc_dma_access(struct cpu *cpu, struct memory *mem,
774     uint64_t relative_addr, unsigned char *data, size_t len,
775     int writeflag, void *extra)
776     {
777     struct asc_data *d = extra;
778    
779     if (writeflag==MEM_READ) {
780     memcpy(data, d->dma + relative_addr, len);
781     #ifdef ASC_DEBUG
782     {
783     int i;
784     debug("[ asc: read from DMA addr 0x%05x:",
785     (int) relative_addr);
786     for (i=0; i<len; i++)
787     debug(" %02x", data[i]);
788     debug(" ]\n");
789     }
790     #endif
791    
792     /* Don't return the common way, as that
793     would overwrite data. */
794     return 1;
795     } else {
796     memcpy(d->dma + relative_addr, data, len);
797     #ifdef ASC_DEBUG
798     {
799     int i;
800     debug("[ asc: write to DMA addr 0x%05x:",
801     (int) relative_addr);
802     for (i=0; i<len; i++)
803     debug(" %02x", data[i]);
804     debug(" ]\n");
805     }
806     #endif
807     /* Quick return. */
808     return 1;
809     }
810     }
811    
812    
813     /*
814     * dev_asc_access():
815     */
816     int dev_asc_access(struct cpu *cpu, struct memory *mem,
817     uint64_t relative_addr, unsigned char *data, size_t len,
818     int writeflag, void *extra)
819     {
820     int regnr;
821     struct asc_data *d = extra;
822     int target_exists;
823     int n_messagebytes = 0;
824     uint64_t idata = 0, odata = 0;
825    
826    
827     idata = memory_readmax64(cpu, data, len);
828    
829     #if 0
830     /* Debug stuff useful when trying to make dev_asc compatible
831     with the 'arc' emulation mode, which is different from
832     the DECstation mode. */
833     fatal("[ asc: writeflag=%i addr=%08x idata=%016llx ]\n",
834     writeflag, (int)relative_addr, (long long)idata);
835     #endif
836    
837     switch (d->mode) {
838     case DEV_ASC_DEC:
839     regnr = relative_addr / 4;
840     break;
841     case DEV_ASC_PICA:
842     default:
843     regnr = relative_addr;
844     }
845    
846     /* Controller's ID is fixed: */
847     d->reg_ro[NCR_CFG1] = (d->reg_ro[NCR_CFG1] & ~7) | ASC_SCSI_ID;
848    
849     d->reg_ro[NCR_FFLAG] = ((d->reg_ro[NCR_STEP] & 0x7) << 5)
850     + d->n_bytes_in_fifo;
851    
852     d->dma_address_reg =
853     d->dma_address_reg_memory[0] +
854     (d->dma_address_reg_memory[1] << 8) +
855     (d->dma_address_reg_memory[2] << 16) +
856     (d->dma_address_reg_memory[3] << 24);
857    
858     if (regnr < 0x10) {
859     if (regnr == NCR_FIFO) {
860     if (writeflag == MEM_WRITE)
861     dev_asc_fifo_write(d, idata);
862     else
863     odata = dev_asc_fifo_read(d);
864     } else {
865     if (writeflag==MEM_WRITE)
866     d->reg_wo[regnr] = idata;
867     else
868     odata = d->reg_ro[regnr];
869     }
870    
871     #ifdef ASC_FULL_REGISTER_ACCESS_DEBUG
872     if (!quiet_mode) {
873     if (writeflag==MEM_READ) {
874     debug("[ asc: read from %s: 0x%02x",
875     asc_reg_names[regnr], (int)odata);
876     } else {
877     debug("[ asc: write to %s: 0x%02x",
878     asc_reg_names[regnr], (int)idata);
879     }
880     }
881     #endif
882     } else if (relative_addr >= 0x300 && relative_addr < 0x600
883     && d->turbochannel != NULL) {
884     debug("[ asc: offset 0x%x, redirecting to turbochannel"
885     " access ]\n", relative_addr);
886     return dev_turbochannel_access(cpu, mem,
887     relative_addr, data, len, writeflag,
888     d->turbochannel);
889     } else {
890     if (writeflag==MEM_READ) {
891     fatal("[ asc: read from 0x%04x: 0x%02x ]\n",
892     relative_addr, (int)odata);
893     } else {
894     fatal("[ asc: write to 0x%04x: 0x%02x ]\n",
895     relative_addr, (int)idata);
896     }
897     }
898    
899     /*
900     * Some registers are read/write. Copy contents of
901     * reg_wo to reg_ro:
902     */
903     #if 0
904     d->reg_ro[ 0] = d->reg_wo[0]; /* Transfer count lo and */
905     d->reg_ro[ 1] = d->reg_wo[1]; /* middle */
906     #endif
907     d->reg_ro[ 2] = d->reg_wo[2];
908     d->reg_ro[ 3] = d->reg_wo[3];
909     d->reg_ro[ 8] = d->reg_wo[8];
910     d->reg_ro[ 9] = d->reg_wo[9];
911     d->reg_ro[10] = d->reg_wo[10];
912     d->reg_ro[11] = d->reg_wo[11];
913     d->reg_ro[12] = d->reg_wo[12];
914    
915     if (regnr == NCR_CMD && writeflag == MEM_WRITE) {
916     if (!quiet_mode)
917     debug(" ");
918    
919     /* TODO: Perhaps turn off others here too? */
920     d->reg_ro[NCR_INTR] &= ~NCRINTR_SBR;
921    
922     if (idata & NCRCMD_DMA) {
923     if (!quiet_mode)
924     debug("[DMA] ");
925    
926     /*
927     * DMA commands load the transfer count from the
928     * write-only registers to the read-only ones, and
929     * the Terminal Count bit is cleared.
930     */
931     d->reg_ro[NCR_TCL] = d->reg_wo[NCR_TCL];
932     d->reg_ro[NCR_TCM] = d->reg_wo[NCR_TCM];
933     d->reg_ro[NCR_TCH] = d->reg_wo[NCR_TCH];
934     d->reg_ro[NCR_STAT] &= ~NCRSTAT_TC;
935     }
936    
937     switch (idata & ~NCRCMD_DMA) {
938    
939     case NCRCMD_NOP:
940     if (!quiet_mode)
941     debug("NOP");
942     break;
943    
944     case NCRCMD_FLUSH:
945     if (!quiet_mode)
946     debug("FLUSH");
947     /* Flush the FIFO: */
948     dev_asc_fifo_flush(d);
949     break;
950    
951     case NCRCMD_RSTCHIP:
952     if (!quiet_mode)
953     debug("RSTCHIP");
954     /* Hardware reset. */
955     dev_asc_reset(d);
956     break;
957    
958     case NCRCMD_RSTSCSI:
959     if (!quiet_mode)
960     debug("RSTSCSI");
961     /* No interrupt if interrupts are disabled. */
962     if (!(d->reg_wo[NCR_CFG1] & NCRCFG1_SRR))
963     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
964     d->reg_ro[NCR_INTR] |= NCRINTR_SBR;
965     d->reg_ro[NCR_INTR] |= NCRINTR_FC;
966     d->cur_state = STATE_DISCONNECTED;
967     break;
968    
969     case NCRCMD_ENSEL:
970     if (!quiet_mode)
971     debug("ENSEL");
972     /* TODO */
973     break;
974    
975     case NCRCMD_ICCS:
976     if (!quiet_mode)
977     debug("ICCS");
978     /* Reveice a status byte + a message byte. */
979    
980     /* TODO: how about other status and message bytes? */
981     if (d->xferp != NULL && d->xferp->status != NULL)
982     dev_asc_fifo_write(d, d->xferp->status[0]);
983     else
984     dev_asc_fifo_write(d, 0x00);
985    
986     if (d->xferp != NULL && d->xferp->msg_in != NULL)
987     dev_asc_fifo_write(d, d->xferp->msg_in[0]);
988     else
989     dev_asc_fifo_write(d, 0x00);
990    
991     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
992     d->reg_ro[NCR_INTR] |= NCRINTR_FC;
993     /* d->reg_ro[NCR_INTR] |= NCRINTR_BS; */
994     d->reg_ro[NCR_STAT] = (d->reg_ro[NCR_STAT] & ~7) | 7;
995     /* ? probably 7 */
996     d->reg_ro[NCR_STEP] = (d->reg_ro[NCR_STEP] & ~7) | 4;
997     /* ? */
998     break;
999    
1000     case NCRCMD_MSGOK:
1001     /* Message is being Rejected if ATN is set,
1002     otherwise Accepted. */
1003     if (!quiet_mode) {
1004     debug("MSGOK");
1005     if (d->atn)
1006     debug("; Rejecting message");
1007     else
1008     debug("; Accepting message");
1009     }
1010     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
1011     d->reg_ro[NCR_INTR] |= NCRINTR_DIS;
1012    
1013     d->reg_ro[NCR_STAT] = (d->reg_ro[NCR_STAT] & ~7) |
1014     d->cur_phase; /* 6? */
1015     d->reg_ro[NCR_STEP] = (d->reg_ro[NCR_STEP] & ~7) |
1016     4; /* ? */
1017    
1018     d->cur_state = STATE_DISCONNECTED;
1019    
1020     if (d->xferp != NULL)
1021     scsi_transfer_free(d->xferp);
1022     d->xferp = NULL;
1023     break;
1024    
1025     case NCRCMD_SETATN:
1026     if (!quiet_mode)
1027     debug("SETATN");
1028     d->atn = 1;
1029     break;
1030    
1031     case NCRCMD_RSTATN:
1032     if (!quiet_mode)
1033     debug("RSTATN");
1034     d->atn = 0;
1035     break;
1036    
1037     case NCRCMD_SELNATN:
1038     case NCRCMD_SELATN:
1039     case NCRCMD_SELATNS:
1040     case NCRCMD_SELATN3:
1041     d->cur_phase = PHASE_COMMAND;
1042     switch (idata & ~NCRCMD_DMA) {
1043     case NCRCMD_SELATN:
1044     case NCRCMD_SELATNS:
1045     if ((idata & ~NCRCMD_DMA) == NCRCMD_SELATNS) {
1046     if (!quiet_mode)
1047     debug("SELATNS: select with "
1048     "atn and stop, id %i",
1049     d->reg_wo[NCR_SELID] & 7);
1050     d->cur_phase = PHASE_MSG_OUT;
1051     } else {
1052     if (!quiet_mode)
1053     debug("SELATN: select with atn"
1054     ", id %i",
1055     d->reg_wo[NCR_SELID] & 7);
1056     }
1057     n_messagebytes = 1;
1058     break;
1059     case NCRCMD_SELATN3:
1060     if (!quiet_mode)
1061     debug("SELNATN: select with atn3, "
1062     "id %i", d->reg_wo[NCR_SELID] & 7);
1063     n_messagebytes = 3;
1064     break;
1065     case NCRCMD_SELNATN:
1066     if (!quiet_mode)
1067     debug("SELNATN: select without atn, "
1068     "id %i", d->reg_wo[NCR_SELID] & 7);
1069     n_messagebytes = 0;
1070     }
1071    
1072     /* TODO: not just disk, but some generic
1073     SCSI device */
1074     target_exists = diskimage_exist(cpu->machine,
1075 dpavlin 6 d->reg_wo[NCR_SELID] & 7, DISKIMAGE_SCSI);
1076 dpavlin 4
1077     if (target_exists) {
1078     /*
1079     * Select a SCSI device, send message bytes
1080     * (if any) and command bytes to the target.
1081     */
1082     int ok;
1083    
1084     dev_asc_newxfer(d);
1085    
1086     ok = dev_asc_select(cpu, d,
1087     d->reg_ro[NCR_CFG1] & 7,
1088     d->reg_wo[NCR_SELID] & 7,
1089     idata & NCRCMD_DMA? 1 : 0,
1090     n_messagebytes);
1091    
1092     if (ok)
1093     d->cur_state = STATE_INITIATOR;
1094     else {
1095     d->cur_state = STATE_DISCONNECTED;
1096     d->reg_ro[NCR_INTR] |= NCRINTR_DIS;
1097     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
1098     d->reg_ro[NCR_STEP] =
1099     (d->reg_ro[NCR_STEP] & ~7) | 0;
1100     if (d->xferp != NULL)
1101     scsi_transfer_free(d->xferp);
1102     d->xferp = NULL;
1103     }
1104     } else {
1105     /*
1106     * Selection failed, non-existant scsi ID:
1107     *
1108     * This is good enough to fool Ultrix, NetBSD,
1109     * OpenBSD and Linux to continue detection of
1110     * other IDs, without giving any warnings.
1111     */
1112     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
1113     d->reg_ro[NCR_INTR] |= NCRINTR_DIS;
1114     d->reg_ro[NCR_STEP] &= ~7;
1115     d->reg_ro[NCR_STEP] |= 0;
1116     dev_asc_fifo_flush(d);
1117     d->cur_state = STATE_DISCONNECTED;
1118     }
1119     break;
1120    
1121     case NCRCMD_TRPAD:
1122     if (!quiet_mode)
1123     debug("TRPAD");
1124    
1125     dev_asc_newxfer(d);
1126     {
1127     int ok;
1128    
1129     ok = dev_asc_transfer(cpu, d,
1130     idata & NCRCMD_DMA? 1 : 0);
1131     if (!ok) {
1132     d->cur_state = STATE_DISCONNECTED;
1133     d->reg_ro[NCR_INTR] |= NCRINTR_DIS;
1134     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
1135     d->reg_ro[NCR_STEP] = (d->reg_ro[
1136     NCR_STEP] & ~7) | 0;
1137     if (d->xferp != NULL)
1138     scsi_transfer_free(d->xferp);
1139     d->xferp = NULL;
1140     }
1141     }
1142     break;
1143    
1144     /* Old code which didn't work with Mach: */
1145     #if 0
1146     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
1147     d->reg_ro[NCR_INTR] |= NCRINTR_BS;
1148     d->reg_ro[NCR_INTR] |= NCRINTR_FC;
1149     d->reg_ro[NCR_STAT] |= NCRSTAT_TC;
1150    
1151     d->reg_ro[NCR_TCL] = 0;
1152     d->reg_ro[NCR_TCM] = 0;
1153    
1154     d->reg_ro[NCR_STEP] &= ~7;
1155     #if 0
1156     d->reg_ro[NCR_STEP] |= 0;
1157     dev_asc_fifo_flush(d);
1158     #else
1159     d->reg_ro[NCR_STEP] |= 4;
1160     #endif
1161     break;
1162     #endif
1163    
1164     case NCRCMD_TRANS:
1165     if (!quiet_mode)
1166     debug("TRANS");
1167    
1168     {
1169     int ok;
1170    
1171     ok = dev_asc_transfer(cpu, d,
1172     idata & NCRCMD_DMA? 1 : 0);
1173     if (!ok) {
1174     d->cur_state = STATE_DISCONNECTED;
1175     d->reg_ro[NCR_INTR] |= NCRINTR_DIS;
1176     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
1177     d->reg_ro[NCR_STEP] = (d->reg_ro[
1178     NCR_STEP] & ~7) | 0;
1179     if (d->xferp != NULL)
1180     scsi_transfer_free(d->xferp);
1181     d->xferp = NULL;
1182     }
1183     }
1184     break;
1185    
1186     default:
1187     fatal("(unimplemented asc cmd 0x%02x)", (int)idata);
1188     d->reg_ro[NCR_STAT] |= NCRSTAT_INT;
1189     d->reg_ro[NCR_INTR] |= NCRINTR_ILL;
1190     /*
1191     * TODO: exit or continue with Illegal command
1192     * interrupt?
1193     */
1194     exit(1);
1195     }
1196     }
1197    
1198     if (regnr == NCR_INTR && writeflag == MEM_READ) {
1199     /*
1200     * Reading the interrupt register de-asserts the
1201     * interrupt pin. Also, INTR, STEP, and STAT are all
1202     * cleared, according to page 64 of the LSI53CF92A manual,
1203     * if "interrupt output is true".
1204     */
1205     if (d->reg_ro[NCR_STAT] & NCRSTAT_INT) {
1206     d->reg_ro[NCR_INTR] = 0;
1207     d->reg_ro[NCR_STEP] = 0;
1208     d->reg_ro[NCR_STAT] = 0;
1209    
1210     /* For Mach/PMAX? TODO */
1211     d->reg_ro[NCR_STAT] = PHASE_COMMAND;
1212     }
1213    
1214     cpu_interrupt_ack(cpu, d->irq_nr);
1215     }
1216    
1217     if (regnr == NCR_CFG1) {
1218     /* TODO: other bits */
1219     if (!quiet_mode) {
1220     debug(" parity %s,", d->reg_ro[regnr] &
1221     NCRCFG1_PARENB? "enabled" : "disabled");
1222     debug(" scsi_id %i", d->reg_ro[regnr] & 0x7);
1223     }
1224     }
1225    
1226     #ifdef ASC_FULL_REGISTER_ACCESS_DEBUG
1227     debug(" ]\n");
1228     #endif
1229     dev_asc_tick(cpu, extra);
1230    
1231     if (writeflag == MEM_READ)
1232     memory_writemax64(cpu, data, len, odata);
1233    
1234     return 1;
1235     }
1236    
1237    
1238     /*
1239     * dev_asc_init():
1240     *
1241     * Register an 'asc' device.
1242     */
1243     void dev_asc_init(struct machine *machine, struct memory *mem,
1244     uint64_t baseaddr, int irq_nr, void *turbochannel,
1245     int mode,
1246     size_t (*dma_controller)(void *dma_controller_data,
1247     unsigned char *data, size_t len, int writeflag),
1248     void *dma_controller_data)
1249     {
1250     struct asc_data *d;
1251    
1252     d = malloc(sizeof(struct asc_data));
1253     if (d == NULL) {
1254     fprintf(stderr, "out of memory\n");
1255     exit(1);
1256     }
1257     memset(d, 0, sizeof(struct asc_data));
1258     d->irq_nr = irq_nr;
1259     d->turbochannel = turbochannel;
1260     d->mode = mode;
1261    
1262     d->reg_ro[NCR_CFG3] = NCRF9XCFG3_CDB;
1263    
1264     d->dma_controller = dma_controller;
1265     d->dma_controller_data = dma_controller_data;
1266    
1267     memory_device_register(mem, "asc", baseaddr,
1268     mode == DEV_ASC_PICA?
1269     DEV_ASC_PICA_LENGTH : DEV_ASC_DEC_LENGTH,
1270     dev_asc_access, d, MEM_DEFAULT, NULL);
1271    
1272     if (mode == DEV_ASC_DEC) {
1273     memory_device_register(mem, "asc_dma_address_reg",
1274     baseaddr + 0x40000, 4096, dev_asc_address_reg_access, d,
1275     MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK,
1276     d->dma_address_reg_memory);
1277     memory_device_register(mem, "asc_dma", baseaddr + 0x80000,
1278     128*1024, dev_asc_dma_access, d,
1279     MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK, d->dma);
1280     }
1281    
1282     machine_add_tickfunction(machine, dev_asc_tick, d, 15);
1283     }
1284    

  ViewVC Help
Powered by ViewVC 1.1.26