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