dev_asc.cc Source File

Back to the index.

dev_asc.cc
Go to the documentation of this file.
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 
105  struct interrupt irq;
107 
108  /* Current state and transfer: */
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;
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 
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 
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  */
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  */
187 static void dev_asc_reset(struct asc_data *d)
188 {
190  d->atn = 0;
191 
192  if (d->xferp != NULL)
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  */
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  */
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  */
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");
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  */
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(
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 -
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) {
433  &d->xferp->data_out, len, 0);
434 
435  if (d->dma_controller != NULL)
436  d->dma_controller(
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(
450  d->xferp->data_out +
452  len2, 0);
453  else
454  memcpy(d->xferp->data_out +
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);
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)
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  */
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) {
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 
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 
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)
730  else if (d->xferp->data_in != NULL)
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 
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 
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 
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;
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 
1001 
1002  if (d->xferp != NULL)
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)
1076  else {
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)
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);
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) {
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)
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) {
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)
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 */
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  */
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);
1239  d->mode = mode;
1240 
1242 
1243  CHECK_ALLOCATION(d->dma_address_reg_memory = (unsigned char *)
1244  malloc(machine->arch_pagesize));
1246 
1247  CHECK_ALLOCATION(d->dma = (unsigned char *) malloc(ASC_DMA_SIZE));
1248  memset(d->dma, 0, ASC_DMA_SIZE);
1249 
1252 
1253  memory_device_register(mem, "asc", baseaddr,
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,
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,
1265  }
1266 
1267  machine_add_tickfunction(machine, dev_asc_tick, d, ASC_TICK_SHIFT);
1268 }
1269 
DEVICE_TICK
DEVICE_TICK(asc)
Definition: dev_asc.cc:156
scsi_transfer::msg_out
unsigned char * msg_out
Definition: diskimage.h:97
scsi_transfer::msg_out_len
size_t msg_out_len
Definition: diskimage.h:98
asc_data::cur_state
int cur_state
Definition: dev_asc.cc:109
data
u_short data
Definition: siireg.h:79
machine::arch_pagesize
int arch_pagesize
Definition: machine.h:151
NCRCFG1_PARENB
#define NCRCFG1_PARENB
Definition: ncr53c9xreg.h:122
NCRCMD_MSGOK
#define NCRCMD_MSGOK
Definition: ncr53c9xreg.h:74
INTERRUPT_CONNECT
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
INTERRUPT_ASSERT
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
NCRINTR_BS
#define NCRINTR_BS
Definition: ncr53c9xreg.h:95
diskimage.h
diskimage_scsicommand
int diskimage_scsicommand(struct cpu *cpu, int id, int type, struct scsi_transfer *xferp)
Definition: diskimage_scsicmd.cc:214
PHASE_MSG_OUT
#define PHASE_MSG_OUT
Definition: dev_asc.cc:92
memory
Definition: memory.h:75
debug
#define debug
Definition: dev_adb.cc:57
scsi_transfer::data_out_len
size_t data_out_len
Definition: diskimage.h:105
NCR_CFG3
#define NCR_CFG3
Definition: ncr53c9xreg.h:151
NCRSTAT_TC
#define NCRSTAT_TC
Definition: ncr53c9xreg.h:83
asc_data::xferp
struct scsi_transfer * xferp
Definition: dev_asc.cc:111
NCR_SELID
#define NCR_SELID
Definition: ncr53c9xreg.h:87
asc_data::cur_phase
int cur_phase
Definition: dev_asc.cc:110
NCRCMD_SETATN
#define NCRCMD_SETATN
Definition: ncr53c9xreg.h:76
scsi_transfer_free
void scsi_transfer_free(struct scsi_transfer *p)
Definition: diskimage_scsicmd.cc:92
memory_device_register
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
asc_data::reg_wo
uint32_t reg_wo[0x10]
Definition: dev_asc.cc:138
NCRINTR_FC
#define NCRINTR_FC
Definition: ncr53c9xreg.h:96
ASC_DMA_SIZE
#define ASC_DMA_SIZE
Definition: dev_asc.cc:99
asc_data::dma_controller
size_t(* dma_controller)(void *dma_controller_data, unsigned char *data, size_t len, int writeflag)
Definition: dev_asc.cc:133
MEM_READ
#define MEM_READ
Definition: memory.h:116
PHASE_DATA_OUT
#define PHASE_DATA_OUT
Definition: dev_asc.cc:88
dev_asc_access
int dev_asc_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
NCR_TCM
#define NCR_TCM
Definition: ncr53c9xreg.h:40
ncr53c9xreg.h
DM_DEFAULT
#define DM_DEFAULT
Definition: memory.h:130
NCRCMD_SELATN
#define NCRCMD_SELATN
Definition: ncr53c9xreg.h:54
NCR_TCL
#define NCR_TCL
Definition: ncr53c9xreg.h:39
scsi_transfer
Definition: diskimage.h:93
NCRCMD_TRPAD
#define NCRCMD_TRPAD
Definition: ncr53c9xreg.h:75
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
scsi_transfer::cmd_len
size_t cmd_len
Definition: diskimage.h:100
scsi_transfer::data_out
unsigned char * data_out
Definition: diskimage.h:104
PHASE_STATUS
#define PHASE_STATUS
Definition: dev_asc.cc:91
asc_data::incoming_data
unsigned char * incoming_data
Definition: dev_asc.cc:123
DM_DYNTRANS_WRITE_OK
#define DM_DYNTRANS_WRITE_OK
Definition: memory.h:132
machine_add_tickfunction
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
asc_data::atn
int atn
Definition: dev_asc.cc:120
asc_data
Definition: dev_asc.cc:101
DEV_ASC_DEC_LENGTH
#define DEV_ASC_DEC_LENGTH
Definition: devices.h:114
asc_data::fifo_in
int fifo_in
Definition: dev_asc.cc:115
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
DISKIMAGE_SCSI
#define DISKIMAGE_SCSI
Definition: diskimage.h:40
NCR_STAT
#define NCR_STAT
Definition: ncr53c9xreg.h:79
misc.h
NCRINTR_DIS
#define NCRINTR_DIS
Definition: ncr53c9xreg.h:94
asc_data::irq
struct interrupt irq
Definition: dev_asc.cc:105
NCR_INTR
#define NCR_INTR
Definition: ncr53c9xreg.h:91
NCRCMD_SELATN3
#define NCRCMD_SELATN3
Definition: ncr53c9xreg.h:58
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
machine.h
machine
Definition: machine.h:97
asc_data::dma_address_reg
uint32_t dma_address_reg
Definition: dev_asc.cc:128
asc_data::n_bytes_in_fifo
int n_bytes_in_fifo
Definition: dev_asc.cc:117
NCRCMD_RSTATN
#define NCRCMD_RSTATN
Definition: ncr53c9xreg.h:77
cpu.h
dev_turbochannel_access
int dev_turbochannel_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
quiet_mode
int quiet_mode
Definition: main.cc:78
STATE_DISCONNECTED
#define STATE_DISCONNECTED
Definition: dev_asc.cc:84
ASC_TICK_SHIFT
#define ASC_TICK_SHIFT
Definition: dev_asc.cc:78
scsi_transfer::status
unsigned char * status
Definition: diskimage.h:113
cpu::machine
struct machine * machine
Definition: cpu.h:328
DEV_ASC_PICA
#define DEV_ASC_PICA
Definition: devices.h:117
NCRCMD_ICCS
#define NCRCMD_ICCS
Definition: ncr53c9xreg.h:73
dev_asc_init
void 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)
Definition: dev_asc.cc:1226
asc_data::mode
int mode
Definition: dev_asc.cc:102
NCRCMD_SELNATN
#define NCRCMD_SELNATN
Definition: ncr53c9xreg.h:53
NCR_FFLAG
#define NCR_FFLAG
Definition: ncr53c9xreg.h:110
STATE_INITIATOR
#define STATE_INITIATOR
Definition: dev_asc.cc:85
scsi_transfer_allocbuf
void scsi_transfer_allocbuf(size_t *lenp, unsigned char **pp, size_t want_len, int clearflag)
Definition: diskimage_scsicmd.cc:126
ASC_FIFO_LEN
#define ASC_FIFO_LEN
Definition: dev_asc.cc:83
NCRCMD_RSTSCSI
#define NCRCMD_RSTSCSI
Definition: ncr53c9xreg.h:51
NCR_SYNCTP
#define NCR_SYNCTP
Definition: ncr53c9xreg.h:107
NCRCMD_RSTCHIP
#define NCRCMD_RSTCHIP
Definition: ncr53c9xreg.h:50
asc_data::turbochannel
void * turbochannel
Definition: dev_asc.cc:104
NCRCMD_SELATNS
#define NCRCMD_SELATNS
Definition: ncr53c9xreg.h:55
asc_data::reg_ro
uint32_t reg_ro[0x10]
Definition: dev_asc.cc:137
scsi_transfer_alloc
struct scsi_transfer * scsi_transfer_alloc(void)
Definition: diskimage_scsicmd.cc:64
INTERRUPT_DEASSERT
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
NCR_STEP
#define NCR_STEP
Definition: ncr53c9xreg.h:103
NCR_FIFO
#define NCR_FIFO
Definition: ncr53c9xreg.h:44
NCRCMD_ENSEL
#define NCRCMD_ENSEL
Definition: ncr53c9xreg.h:56
scsi_transfer::data_in_len
size_t data_in_len
Definition: diskimage.h:110
DEVICE_ACCESS
DEVICE_ACCESS(asc_address_reg)
Definition: dev_asc.cc:745
asc_data::dma_controller_data
void * dma_controller_data
Definition: dev_asc.cc:132
scsi_transfer::data_out_offset
size_t data_out_offset
Definition: diskimage.h:106
asc_data::dma
unsigned char * dma
Definition: dev_asc.cc:130
asc_data::incoming_data_addr
int incoming_data_addr
Definition: dev_asc.cc:125
NCRCFG1_SRR
#define NCRCFG1_SRR
Definition: ncr53c9xreg.h:120
asc_data::dma_address_reg_memory
unsigned char * dma_address_reg_memory
Definition: dev_asc.cc:129
NCRINTR_SBR
#define NCRINTR_SBR
Definition: ncr53c9xreg.h:92
asc_data::incoming_len
int incoming_len
Definition: dev_asc.cc:124
PHASE_DATA_IN
#define PHASE_DATA_IN
Definition: dev_asc.cc:89
NCRCMD_TRANS
#define NCRCMD_TRANS
Definition: ncr53c9xreg.h:72
interrupt
Definition: interrupt.h:36
DEV_ASC_PICA_LENGTH
#define DEV_ASC_PICA_LENGTH
Definition: devices.h:115
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
DEV_ASC_DEC
#define DEV_ASC_DEC
Definition: devices.h:116
PHASE_MSG_IN
#define PHASE_MSG_IN
Definition: dev_asc.cc:93
NCR_CFG1
#define NCR_CFG1
Definition: ncr53c9xreg.h:118
asc_data::irq_asserted
int irq_asserted
Definition: dev_asc.cc:106
devices.h
NCR_TCH
#define NCR_TCH
Definition: ncr53c9xreg.h:41
cpu
Definition: cpu.h:326
PHASE_COMMAND
#define PHASE_COMMAND
Definition: dev_asc.cc:90
asc_data::fifo_out
int fifo_out
Definition: dev_asc.cc:116
scsi_transfer::msg_in
unsigned char * msg_in
Definition: diskimage.h:111
DM_DYNTRANS_OK
#define DM_DYNTRANS_OK
Definition: memory.h:131
scsi_transfer::cmd
unsigned char * cmd
Definition: diskimage.h:99
scsi_transfer::data_in
unsigned char * data_in
Definition: diskimage.h:109
NCRCMD_FLUSH
#define NCRCMD_FLUSH
Definition: ncr53c9xreg.h:49
NCRSTAT_INT
#define NCRSTAT_INT
Definition: ncr53c9xreg.h:80
NCRINTR_ILL
#define NCRINTR_ILL
Definition: ncr53c9xreg.h:93
NCRCMD_DMA
#define NCRCMD_DMA
Definition: ncr53c9xreg.h:47
asc_reg_names
const char * asc_reg_names[0x10]
Definition: dev_asc.cc:142
memory.h
NCRF9XCFG3_CDB
#define NCRF9XCFG3_CDB
Definition: ncr53c9xreg.h:181
ASC_SCSI_ID
#define ASC_SCSI_ID
Definition: dev_asc.cc:97
diskimage_exist
int diskimage_exist(struct machine *machine, int id, int type)
Definition: diskimage.cc:106
asc_data::fifo
unsigned char fifo[ASC_FIFO_LEN]
Definition: dev_asc.cc:114
NCRCMD_NOP
#define NCRCMD_NOP
Definition: ncr53c9xreg.h:48
NCR_CMD
#define NCR_CMD
Definition: ncr53c9xreg.h:46
NCR_CCF
#define NCR_CCF
Definition: ncr53c9xreg.h:126
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18