/[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 18 - (hide annotations)
Mon Oct 8 16:19:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 31818 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1004 2005/10/27 14:01:10 debug Exp $
20051011        Passing -A as the default boot arg for CATS (works fine with
                OpenBSD/cats).
20051012	Fixing the VGA cursor offset bug, and speeding up framebuffer
		redraws if character cells contain the same thing as during
		the last redraw.
20051013	Adding a slow strd ARM instruction hack.
20051017	Minor updates: Adding a dummy i80321 Verde controller (for
		XScale emulation), fixing the disassembly of the ARM "ldrd"
		instruction, adding "support" for less-than-4KB pages for ARM
		(by not adding them to translation tables).
20051020	Continuing on some HPCarm stuff. A NetBSD/hpcarm kernel prints
		some boot messages on an emulated Jornada 720.
		Making dev_ram work better with dyntrans (speeds up some things
		quite a bit).
20051021	Automatically generating some of the most common ARM load/store
		multiple instructions.
20051022	Better statistics gathering for the ARM load/store multiple.
		Various other dyntrans and device updates.
20051023	Various minor updates.
20051024	Continuing; minor device and dyntrans fine-tuning. Adding the
		first "reasonable" instruction combination hacks for ARM (the
		cores of NetBSD/cats' memset and memcpy).
20051025	Fixing a dyntrans-related bug in dev_vga. Also changing the
		dyntrans low/high access notification to only be updated on
		writes, not reads. Hopefully it will be enough. (dev_vga in
		charcell mode now seems to work correctly with both reads and
		writes.)
		Experimenting with gathering dyntrans statistics (which parts
		of emulated RAM that are actually executed), and adding
		instruction combination hacks for cache cleaning and a part of
		NetBSD's scanc() function.
20051026	Adding a bitmap for ARM emulation which indicates if a page is
		(specifically) user accessible; loads and stores with the t-
		flag set can now use the translation arrays, which results in
		a measurable speedup.
20051027	Dyntrans updates; adding an extra bitmap array for 32-bit
		emulation modes, speeding up the check whether a physical page
		has any code translations or not (O(n) -> O(1)). Doing a
		similar reduction of O(n) to O(1) by avoiding the scan through
		the translation entries on a translation update (32-bit mode
		only).
		Various other minor hacks.
20051029	Quick release, without any testing at all.

==============  RELEASE 0.3.6.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26