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