|
|
1.1 root 1: /* Emulation of NCR53C90(A)
2: Includes informations from QEMU-NeXT
3: */
4:
5: #include "ioMem.h"
6: #include "ioMemTables.h"
7: #include "m68000.h"
8: #include "configuration.h"
9: #include "esp.h"
10: #include "sysReg.h"
11: #include "dma.h"
12: #include "scsi.h"
13:
14: #define LOG_SCSI_LEVEL LOG_DEBUG
15:
16:
17: #define IO_SEG_MASK 0x1FFFF
18:
19: typedef enum {
20: DISCONNECTED,
21: RESELECTABLE,
22: SELECTING,
23: INITIATOR,
24: DISABLINGSEL,
25: COMPLETING,
26: DMAING,
27: ACCEPTINGMSG,
28: SENDINGMSG,
29: PADDING,
30: GETTINGMSG,
31: GETTINGLUN,
32: IGNOREILLCMD
33: } SCSI_STATE;
34:
35: SCSI_STATE state;
36:
37: /* SCSI DMA Command/Status Registers */
38: Uint8 csr_value0;
39: Uint8 csr_value1;
40:
41: /* ESP Registers */
42: Uint8 readtranscountl;
43: Uint8 readtranscounth;
44: Uint8 writetranscountl;
45: Uint8 writetranscounth;
46: Uint8 fifo;
47: Uint8 command;
48: Uint8 status;
49: Uint8 selectbusid;
50: Uint8 intstatus;
51: Uint8 selecttimeout;
52: Uint8 seqstep;
53: Uint8 syncperiod;
54: Uint8 fifoflags;
55: Uint8 syncoffset;
56: Uint8 configuration;
57: Uint8 clockconv;
58: Uint8 esptest;
59:
60: /* ESP Status Variables */
61: Uint8 irq_status;
62: Uint8 mode_dma;
63:
64: /* ESP FIFO */
65: #define ESP_FIFO_SIZE 16
66: Uint8 esp_fifo[ESP_FIFO_SIZE];
67: Uint8 fifo_read_ptr;
68: Uint8 fifo_write_ptr;
69:
70: /* Command buffer */
71: #define SCSI_CMD_BUF_SIZE 16
72: Uint8 commandbuf[SCSI_CMD_BUF_SIZE];
73: int command_len;
74:
75:
76: /* Experimental */
77:
78: //Uint32 dma;
79: Uint32 do_cmdvar;
80: Uint32 dma_counter;
81: Uint32 data_len;
82: Uint32 dma_left;
83: Uint32 cmdlen;
84: Uint32 async_len;
85: Uint8 *async_buf;
86: int dma_enabled = 1;
87: void (*dma_cb);
88:
89: static bool no_target=false;
90: static int bus_id_command=0;
91:
92:
93: void SCSI_CSR0_Read(void) {
94: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = csr_value0;
95: Log_Printf(LOG_SCSI_LEVEL,"SCSI DMA control read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
96: }
97:
98: void SCSI_CSR0_Write(void) {
99: Log_Printf(LOG_SCSI_LEVEL,"SCSI DMA control write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
100: csr_value0 = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
101:
102: if ((csr_value0 & 0x04) == 0x04) {
103: Log_Printf(LOG_SCSI_LEVEL, "flush FIFO\n");
104: }
105: if ((csr_value0 & 0x01) == 0x01) {
106: Log_Printf(LOG_SCSI_LEVEL, "scsi chip is WD33C92\n");
107: } else {
108: Log_Printf(LOG_SCSI_LEVEL, "scsi chip is NCR53C90\n");
109: }
110: if ((csr_value0 & 0x02) == 0x02) {
111: Log_Printf(LOG_SCSI_LEVEL, "reset scsi chip\n");
112: esp_reset_hard();
113: }
114: if ((csr_value0 & 0x08) == 0x08) {
115: Log_Printf(LOG_SCSI_LEVEL, "dma from scsi to mem\n");
116: }
117: if ((csr_value0 & 0x10) == 0x10) {
118: // set_interrupt(INT_SCSI_DMA, SET_INT);
119: // esp_raise_irq();
120: Log_Printf(LOG_SCSI_LEVEL, "mode DMA\n");
121: }else{
122: // set_interrupt(INT_SCSI_DMA, RELEASE_INT);
123: //esp_lower_irq();
124: Log_Printf(LOG_SCSI_LEVEL, "mode PIO\n");
125: }
126: if ((csr_value0 & 0x20) == 0x20) {
127: Log_Printf(LOG_SCSI_LEVEL, "interrupt enable");
128: }
129: switch (csr_value0 & 0xC0) {
130: case 0x00:
131: Log_Printf(LOG_SCSI_LEVEL, "10 MHz clock\n");
132: break;
133: case 0x40:
134: Log_Printf(LOG_SCSI_LEVEL, "12.5 MHz clock\n");
135: break;
136: case 0xC0:
137: Log_Printf(LOG_SCSI_LEVEL, "16.6 MHz clock\n");
138: break;
139: case 0x80:
140: Log_Printf(LOG_SCSI_LEVEL, "20 MHz clock\n");
141: break;
142: default:
143: break;
144: }
145: }
146:
147: void SCSI_CSR1_Read(void) {
148:
149: /*
150: * dma fifo status register
151: */
152: #define S5RDMAS_STATE 0xc0 /* DMA/SCSI bank state */
153: #define S5RDMAS_D0S0 0x00 /* DMA rdy for bank 0, SCSI in bank 0 */
154: #define S5RDMAS_D0S1 0x40 /* DMA req for bank 0, SCSI in bank 1 */
155: #define S5RDMAS_D1S1 0x80 /* DMA rdy for bank 1, SCSI in bank 1 */
156: #define S5RDMAS_D1S0 0xc0 /* DMA req for bank 1, SCSI in bank 0 */
157: #define S5RDMAS_OUTFIFOMASK 0x38 /* output fifo byte (INVERTED) */
158: #define S5RDMAS_INFIFOMASK 0x07 /* input fifo byte (INVERTED) */
159:
160: #define S5RDMA_FIFOALIGNMENT 4 /* mass storage chip buffer size */
161:
162:
163: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x80;
164: Log_Printf(LOG_SCSI_LEVEL,"SCSI DMA FIFO status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
165: }
166:
167: void SCSI_CSR1_Write(void) {
168: Log_Printf(LOG_SCSI_LEVEL,"SCSI DMA FIFO status write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
169: csr_value1 = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
170: }
171:
172:
173: /* ESP Registers */
174:
175: void SCSI_TransCountL_Read(void) { // 0x02014000
176: IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=readtranscountl;
177: Log_Printf(LOG_SCSI_LEVEL,"ESP TransCountL read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
178: }
179:
180: void SCSI_TransCountL_Write(void) {
181: writetranscountl=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
182: Log_Printf(LOG_SCSI_LEVEL,"ESP TransCountL write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
183: }
184:
185: void SCSI_TransCountH_Read(void) { // 0x02014001
186: IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=readtranscounth;
187: Log_Printf(LOG_SCSI_LEVEL,"ESP TransCoundH read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
188: }
189:
190: void SCSI_TransCountH_Write(void) {
191: writetranscounth=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
192: Log_Printf(LOG_SCSI_LEVEL,"ESP TransCountH write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
193: }
194:
195: void SCSI_FIFO_Read(void) { // 0x02014002
196: if ((fifo_write_ptr - fifo_read_ptr) > 0) {
197: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = esp_fifo[fifo_read_ptr];
198: Log_Printf(LOG_SCSI_LEVEL,"ESP FIFO read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
199: Log_Printf(LOG_WARN,"ESP FIFO Read, size = %i, val=%02x", fifo_write_ptr - fifo_read_ptr, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
200: fifo_read_ptr++;
201: fifoflags = fifoflags - 1;
202: // esp_raise_irq();
203: } else {
204: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
205: Log_Printf(LOG_WARN, "ESP FIFO is empty!\n");
206: }
207: }
208:
209: void SCSI_FIFO_Write(void) {
210: esp_fifo[fifo_write_ptr] = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
211: fifo_write_ptr++;
212: fifoflags = fifoflags + 1;
213: Log_Printf(LOG_SCSI_LEVEL,"ESP FIFO write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
214:
215: if (fifo_write_ptr > (ESP_FIFO_SIZE - 1)) {
216: Log_Printf(LOG_SCSI_LEVEL, "ESP FIFO overflow! Resetting FIFO!\n");
217: esp_flush_fifo();
218: }
219: Log_Printf(LOG_SCSI_LEVEL,"ESP FIFO size = %i", fifo_write_ptr - fifo_read_ptr);
220: }
221:
222: void SCSI_Command_Read(void) { // 0x02014003
223: IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=command;
224: Log_Printf(LOG_SCSI_LEVEL,"ESP Command read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
225: }
226:
227: void SCSI_Command_Write(void) {
228: command=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
229: Log_Printf(LOG_SCSI_LEVEL,"ESP Command write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
230:
231: if (command & CMD_DMA) {
232: readtranscountl = writetranscountl;
233: readtranscounth = writetranscounth;
234: status &= ~STAT_TC;
235: mode_dma = 1;
236: } else {
237: mode_dma = 0;
238: }
239:
240: if ((command & CMD_CMD) != CMD_NOP)
241: status = (status&STAT_MASK)|STAT_CD;
242:
243: switch (command & CMD_CMD) {
244: /* Miscellaneous */
245: case CMD_NOP:
246: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: NOP\n");
247: // status = (status&STAT_MASK)|STAT_ST;
248: break;
249: case CMD_FLUSH:
250: Log_Printf(LOG_SCSI_LEVEL,"ESP Command: flush FIFO\n");
251: esp_flush_fifo();
252: status = (status&STAT_MASK)|STAT_ST;
253: break;
254: case CMD_RESET:
255: Log_Printf(LOG_SCSI_LEVEL,"ESP Command: reset chip\n");
256: esp_reset_hard();
257: break;
258: case CMD_BUSRESET:
259: //Reset all Devices on SCSI bus
260: Log_Printf(LOG_WARN, "ESP Command: reset SCSI bus\n");
261: esp_reset_soft();
262: if (!(configuration & CFG1_RESREPT)) {
263: intstatus = INTR_RST;
264: status = (status&STAT_MASK)|STAT_MI;
265: seqstep = 0;
266: Log_Printf(LOG_SCSI_LEVEL,"Bus Reset raising IRQ configuration=%x\n",configuration);
267: //esp_raise_irq(); // temporary disabled for experiment! moved to read config reg.
268: } else
269: Log_Printf(LOG_SCSI_LEVEL,"Bus Reset not interrupting configuration=%x\n",configuration);
270: break;
271: /* Disconnected */
272: case CMD_SEL:
273: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: select without ATN sequence\n");
274: //abort();
275: handle_satn(); // enabled for experiment!
276: break;
277: case CMD_SELATN:
278: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: select with ATN sequence\n");
279: handle_satn();
280: break;
281: case CMD_SELATNS:
282: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: select with ATN and stop sequence\n");
283: abort();
284: break;
285: case CMD_ENSEL:
286: Log_Printf(LOG_WARN, "ESP Command: enable selection/reselection no_target=%x intstatus=%x status=%x seqstep=%x",
287: no_target,intstatus,status,seqstep);
288: if (no_target) {
289: Log_Printf(LOG_SCSI_LEVEL, "ESP retry timeout");
290: intstatus = INTR_RESEL;
291: seqstep = SEQ_SELTIMEOUT;
292: } else {
293: Log_Printf(LOG_WARN, "Reselect: target %i, lun %i\n", SCSIcommand.target, SCSIcommand.lun);
294: status = (status&STAT_MASK)|STAT_MI;
295: intstatus = INTR_RESEL|INTR_FC;
296: esp_fifo[0] = (1<<SCSIcommand.target); // target bit
297: esp_fifo[1] = 0x80|(SCSIcommand.lun&0x07); // identify message (identifymask|(lun&lun_mask))
298: fifoflags = 2;
299: fifo_write_ptr = 2;
300: fifo_read_ptr = 0;
301: // esp_raise_irq();
302: }
303: break;
304: case CMD_DISSEL:
305: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: disable selection/reselection\n");
306: intstatus = INTR_FC;
307: esp_raise_irq();
308: break;
309: /* Initiator */
310: case CMD_TI:
311: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: transfer information\n");
312: handle_ti();
313: esp_raise_irq();
314: break;
315: case CMD_ICCS:
316: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: initiator command complete sequence\n");
317: write_response();
318: intstatus = INTR_FC;
319: status = (status&STAT_MASK)|STAT_MI;
320: esp_raise_irq();
321: break;
322: case CMD_MSGACC:
323: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: message accepted\n");
324: status = (status&STAT_MASK)|STAT_ST;
325: intstatus = INTR_BS;
326: seqstep = SEQ_0;
327: fifoflags = 0x00;
328: esp_raise_irq();
329: break;
330: case CMD_PAD:
331: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: transfer pad\n");
332: status = STAT_TC | STAT_DI;
333: intstatus = INTR_FC;
334: seqstep = SEQ_0;
335: esp_raise_irq();
336: break;
337: case CMD_SATN:
338: Log_Printf(LOG_SCSI_LEVEL, "ESP Command: set ATN\n");
339: break;
340: /* Target */
341: case CMD_SEMSG:
342: case CMD_SESTAT:
343: case CMD_SEDAT:
344: case CMD_DISSEQ:
345: case CMD_TERMSEQ:
346: case CMD_TCCS:
347: case CMD_RMSGSEQ:
348: case CMD_RCOMM:
349: case CMD_RDATA:
350: case CMD_RCSEQ:
351:
352: status = (status&STAT_MASK)|STAT_ST;
353: intstatus = INTR_ILL;
354: seqstep = SEQ_0;
355: fifoflags = 0x00;
356: esp_raise_irq();
357: Log_Printf(LOG_WARN, "ESP Command: Target commands not supported!\n");
358: break;
359: case CMD_DIS:
360:
361:
362: Log_Printf(LOG_WARN, "ESP Command: DISCONNECT !\n");
363: status = (status&STAT_MASK)|STAT_ST;
364: intstatus = INTR_DC;
365: seqstep = SEQ_0;
366: break;
367:
368:
369: default:
370: Log_Printf(LOG_WARN, "ESP Command: Illegal command!\n");
371: intstatus |= INTR_ILL;
372: break;
373: }
374: }
375:
376: void SCSI_Status_Read(void) { // 0x02014004
377: IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=status;
378: Log_Printf(LOG_SCSI_LEVEL,"ESP Status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
379: }
380:
381: void SCSI_SelectBusID_Write(void) {
382: selectbusid=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
383: Log_Printf(LOG_SCSI_LEVEL,"ESP SelectBusID write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
384: no_target=false;
385: }
386:
387: void SCSI_IntStatus_Read(void) { // 0x02014005
388: IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=intstatus;
389: Log_Printf(LOG_SCSI_LEVEL,"ESP IntStatus read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
390:
391: if (irq_status == 1) {
392: intstatus = 0x00;
393: status &= ~(STAT_VGC | STAT_PE | STAT_GE );
394: seqstep = SEQ_0;
395: esp_lower_irq();
396: }
397: }
398:
399: void SCSI_SelectTimeout_Write(void) {
400: selecttimeout=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
401: Log_Printf(LOG_SCSI_LEVEL,"ESP SelectTimeout write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
402: }
403:
404: void SCSI_SeqStep_Read(void) { // 0x02014006
405: IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=seqstep;
406: Log_Printf(LOG_SCSI_LEVEL,"ESP SeqStep read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
407: }
408:
409: void SCSI_SyncPeriod_Write(void) {
410: syncperiod=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
411: Log_Printf(LOG_SCSI_LEVEL,"ESP SyncPeriod write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
412: }
413:
414: void SCSI_FIFOflags_Read(void) { // 0x02014007
415: IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=fifoflags;
416: Log_Printf(LOG_WARN,"ESP FIFOflags read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
417: }
418:
419: void SCSI_SyncOffset_Write(void) {
420: syncoffset=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
421: Log_Printf(LOG_SCSI_LEVEL,"ESP SyncOffset write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
422: }
423:
424: void SCSI_Configuration_Read(void) { // 0x02014008
425: IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=configuration;
426: Log_Printf(LOG_SCSI_LEVEL,"ESP Configuration read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
427: esp_raise_irq(); // experimental!
428: }
429:
430: void SCSI_Configuration_Write(void) {
431: configuration=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
432: Log_Printf(LOG_SCSI_LEVEL,"ESP Configuration write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
433: }
434:
435: void SCSI_ClockConv_Write(void) { // 0x02014009
436: IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=clockconv;
437: Log_Printf(LOG_SCSI_LEVEL,"ESP ClockConv write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
438: }
439:
440: void SCSI_Test_Write(void) { // 0x0201400a
441: esptest=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
442: Log_Printf(LOG_SCSI_LEVEL,"ESP Test write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
443: }
444:
445: /* System reads this register to check if we use old or new SCSI controller.
446: * Return 0 to report old chip. */
447: void SCSI_Conf2_Read(void) { // 0x0201400b
448: if (ConfigureParams.System.nSCSI == NCR53C90)
449: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = 0x00;
450: }
451:
452:
453: /* Functions */
454:
455: void esp_reset_hard(void) {
456: Log_Printf(LOG_WARN, "ESP hard reset\n");
457: /* hard reset */
458: clockconv = 0x02;
459: configuration &= ~0xF8; // clear chip test mode, parity enable, parity test, scsi request/int disable, slow cable mode
460: syncperiod = 0x05;
461: syncoffset = 0x00;
462: intstatus = 0x00;
463: status &= ~(STAT_VGC | STAT_PE | STAT_GE); // need valid group code bit? clear transfer complete aka valid group code, parity error, gross error
464: esp_flush_fifo();
465: esp_lower_irq();
466: esp_reset_soft();
467: }
468:
469: void esp_reset_soft(void) {
470: status &= ~STAT_TC; // clear transfer count zero
471:
472: /* incomplete, need to work on everything below this point */
473:
474: dma_cb = NULL; // clear DMA interface - how to do this?
475: mode_dma = 0;
476: readtranscountl = 0x00;
477: readtranscounth = 0x00;
478: writetranscountl = 0x00;
479: writetranscounth = 0x00;
480:
481: seqstep = 0x00;
482:
483: command = 0x00;
484: selectbusid = 0x00;
485: selecttimeout= 0x00;
486: fifoflags = 0x00;
487: esptest = 0x00;
488: }
489:
490: void esp_raise_irq(void) {
491: if(!(status & STAT_INT)) {
492: status |= STAT_INT;
493: irq_status = 1;
494:
495: set_interrupt(INT_SCSI, SET_INT);
496:
497: //Log_Printf(LOG_SCSI_LEVEL, "Raise IRQ\n");
498: char s[16];
499: switch (state) {
500: case DISCONNECTED: sprintf(s, "disconntected"); break;
501: case RESELECTABLE: sprintf(s, "reselectable"); break;
502: case SELECTING: sprintf(s, "selecting"); break;
503: case INITIATOR: sprintf(s, "initiator"); break;
504: case DISABLINGSEL: sprintf(s, "diablingsel"); break;
505: case COMPLETING: sprintf(s, "completing"); break;
506: case DMAING: sprintf(s, "dmaing"); break;
507: case ACCEPTINGMSG: sprintf(s, "acceptingmsg"); break;
508: case SENDINGMSG: sprintf(s, "sendingmsg"); break;
509: case PADDING: sprintf(s, "padding"); break;
510: case GETTINGMSG: sprintf(s, "gettingmsg"); break;
511: case GETTINGLUN: sprintf(s, "gettinglun"); break;
512: case IGNOREILLCMD: sprintf(s, "ignoreillcmd"); break;
513: default: sprintf(s, "unknown"); break;
514: }
515: // Log_Printf(LOG_WARN, "Raise IRQ: state: %s\n", s);
516: Log_Printf(LOG_WARN, "Raise IRQ:");
517: switch (status&STAT_MI) {
518: case STAT_DO: sprintf(s, "data out"); break;
519: case STAT_DI: sprintf(s, "data in"); break;
520: case STAT_CD: sprintf(s, "command"); break;
521: case STAT_ST: sprintf(s, "status"); break;
522: case STAT_MI: sprintf(s, "msg in"); break;
523: case STAT_MO: sprintf(s, "msg out"); break;
524: default: sprintf(s, "unknown"); break;
525: }
526: Log_Printf(LOG_WARN, "Status: %02x (phase: %s, %s%s)\n", status, s,
527: status&STAT_TC?"transfer complete":"",
528: status&STAT_INT?", interrupt":"");
529: Log_Printf(LOG_WARN, "Sequence Step: %02x\n", seqstep);
530: Log_Printf(LOG_WARN, "Interrupt Status: %02x (%s%s%s%s%s%s%s%s)\n", intstatus,
531: intstatus&INTR_RST?"bus reset, ":"",
532: intstatus&INTR_BS?"bus service, ":"",
533: intstatus&INTR_DC?"disconnected, ":"",
534: intstatus&INTR_FC?"function compl, ":"",
535: intstatus&INTR_ILL?"illegal comm, ":"",
536: intstatus&INTR_RESEL?"reselected, ":"",
537: intstatus&INTR_SEL?"selected, ":"",
538: intstatus&INTR_SELATN?"selected w ATN":"");
539: }
540: }
541:
542: void esp_lower_irq(void) {
543: if (status & STAT_INT) {
544: status &= ~STAT_INT;
545: irq_status = 0;
546:
547: set_interrupt(INT_SCSI, RELEASE_INT);
548:
549: Log_Printf(LOG_SCSI_LEVEL, "Lower IRQ\n");
550: }
551: }
552:
553: void esp_flush_fifo(void) {
554: fifo_read_ptr = 0;
555: fifo_write_ptr = 0;
556: esp_fifo[0] = 0;
557: fifoflags &= 0xE0;
558: }
559:
560: Uint32 get_cmd (void) {
561:
562: if(mode_dma == 1) {
563: command_len = readtranscountl | (readtranscounth << 8);
564: //dma_memory_read(command_len);
565: memcpy(commandbuf, dma_read_buffer, command_len);
566: } else {
567: command_len = fifo_write_ptr - fifo_read_ptr;
568: memcpy(commandbuf, esp_fifo, command_len);
569:
570: esp_flush_fifo();
571: }
572: Log_Printf(LOG_SCSI_LEVEL, "get_cmd: len %i", command_len);
573:
574: return command_len;
575: }
576:
577: void do_cmd(void) {
578: Uint8 busid = selectbusid;
579: do_busid_cmd(busid);
580: }
581:
582: void handle_satn(void) {
583: Uint8 scsi_command_group;
584:
585: get_cmd(); // make get_cmd void function?
586: // clear valid command status
587: status &= ~STAT_VGC;
588:
589: /* Decode command to determine the command group and thus the
590: * length of the incoming command. Set "valid group code" bit
591: * in status register if the group is 0, 1, 5, 6, or 7 (group
592: * 2 is also valid on NCR53C90A).
593: */
594: scsi_command_group = (commandbuf[1] & 0xE0) >> 5;
595: if(scsi_command_group < 3 || scsi_command_group > 4) {
596: if(ConfigureParams.System.nSCSI == NCR53C90 && scsi_command_group == 2) {
597: Log_Printf(LOG_WARN, "Invalid command group %i on NCR53C90\n", scsi_command_group);
598: } else {
599: status |= STAT_VGC;
600: }
601: } else {
602: Log_Printf(LOG_WARN, "Invalid command group %i on NCR53C90A\n", scsi_command_group);
603: }
604:
605: if (command_len != 0)
606: do_cmd();
607: }
608:
609: void do_busid_cmd(Uint8 busid) {
610: int lun,lun2;
611: int target = busid & BUSID_DID;
612: Log_Printf(LOG_SCSI_LEVEL, "do_busid_cmd: busid $%02x",busid);
613:
614: lun = (commandbuf[0]&0x07);
615:
616: scsi_command_analyzer(commandbuf, command_len, target,lun);
617: data_len = SCSIcommand.transfer_data_len;
618:
619: if ((target >= ESP_MAX_DEVS) || (SCSIcommand.timeout==true)) { // experimental
620: Log_Printf(LOG_SCSI_LEVEL, "No target found !! Target %d Lun %d raise irq %s at %d",target,lun,__FILE__,__LINE__);
621: intstatus = INTR_DC;
622: seqstep = 0x00;//SEQ_SELTIMEOUT;
623: status = (status&STAT_MASK)|STAT_MI; // seems weird... http://permalink.gmane.org/gmane.os.netbsd.ports.next68k/305
624: no_target=true;
625: esp_raise_irq();
626: return;
627: }
628:
629: if (SCSIcommand.nodevice==true) { // experimental
630: Log_Printf(LOG_SCSI_LEVEL, "No device found !! Target %d Lun %d raise irq %s at %d",target,lun,__FILE__,__LINE__);
631:
632: status = (status&STAT_MASK)|STAT_ST;
633: intstatus = INTR_BS|INTR_FC;//INTR_DC;
634: seqstep = SEQ_CD;//SEQ_SELTIMEOUT;
635: esp_raise_irq();
636: return;
637: }
638:
639: status = (status&STAT_MASK)| STAT_ST;
640:
641: if (data_len != 0) {
642: Log_Printf(LOG_SCSI_LEVEL, "executing command\n");
643: status = STAT_TC;
644:
645: dma_left = 0;
646: dma_counter = 0;
647:
648: if(SCSIcommand.transferdirection_todevice == 0) {
649: Log_Printf(LOG_SCSI_LEVEL, "DATA IN\n");
650: status = (status&STAT_MASK)| STAT_DI;
651: } else {
652: Log_Printf(LOG_SCSI_LEVEL, "DATA OUT\n");
653: status = (status&STAT_MASK)| STAT_DO;
654: }
655: esp_transfer_data();
656: }
657:
658: intstatus = INTR_BS | INTR_FC;
659: seqstep = SEQ_CD;
660:
661: esp_raise_irq();
662: }
663:
664:
665: void esp_transfer_data(void) {
666: Log_Printf(LOG_SCSI_LEVEL, "transfer %d/%d\n", dma_left, data_len);
667:
668: // async_len = len;
669: // async_buf = scsi_req_get_buf(req);
670: if(dma_left) {
671: esp_do_dma();
672: } else if(dma_counter != 0 && data_len <= 0) {
673: esp_dma_done();
674: }
675: }
676:
677:
678: void esp_do_dma(void) {
679:
680: Log_Printf(LOG_SCSI_LEVEL, "call esp_do_dma\n");
681:
682: Uint32 len;
683: int to_device;
684:
685: Uint32 dma_translen; // experimental
686: dma_translen = readtranscountl | (readtranscounth << 8); // experimental
687: Log_Printf(LOG_SCSI_LEVEL, "call dma_write\n"); // experimental
688: dma_memory_write(dma_write_buffer, dma_translen, CHANNEL_SCSI);//experimental !!
689:
690:
691: to_device = SCSIcommand.transferdirection_todevice;
692:
693: len = dma_left;
694:
695: if(do_cmdvar){
696: abort();
697: }
698: if(async_len == 0) {
699:
700: }
701: if(len > async_len) {
702: len = async_len;
703: }
704: if(to_device) {
705: // dma_memory_read(async_buf, len);
706: } else {
707: // dma_memory_write(async_buf, len);
708: }
709:
710: dma_left -= len;
711: async_buf += len;
712: async_len -= len;
713:
714: if(to_device)
715: data_len += len;
716: else
717: data_len -= len;
718:
719: if(async_len == 0) {
720: // scsi_req_continue(current_req);
721:
722: if (to_device || dma_left != 0 || (fifo_write_ptr - fifo_read_ptr) == 0) {
723: // return;
724: }
725: }
726: esp_dma_done();
727: }
728:
729: void esp_dma_done(void) {
730: Log_Printf(LOG_SCSI_LEVEL, "call esp_dma_done\n");
731: status = (status&STAT_MASK)|STAT_ST;
732: status |= STAT_TC;
733: intstatus = INTR_BS;
734: seqstep = 0;
735: fifoflags = 0;
736: readtranscountl = 0;
737: readtranscounth = 0;
738: }
739:
740:
741: // transfer information
742: void handle_ti(void){
743: Uint32 dma_len, min_len;
744:
745: dma_len = readtranscountl | (readtranscounth << 8);
746:
747: if(dma_len == 0) {
748: dma_len = 0x10000;
749: }
750:
751: dma_counter = dma_len;
752:
753: if(do_cmdvar)
754: min_len = (dma_len < 32) ? dma_len : 32;
755: else
756: min_len = (dma_len > data_len) ? dma_len : data_len;
757: Log_Printf(LOG_SCSI_LEVEL, "Transfer Information len %d\n", min_len);
758:
759: if(mode_dma) {
760: dma_left = min_len;
761: status &= ~STAT_TC;
762: esp_do_dma();
763: }else if(do_cmdvar){
764: Log_Printf(LOG_SCSI_LEVEL, "Command len: %i\n",cmdlen);
765: data_len = 0;
766: cmdlen = 0;
767: do_cmdvar = 0;
768: do_cmd();
769: return;
770: }
771: }
772:
773: void esp_command_complete (void) {
774: Log_Printf(LOG_SCSI_LEVEL, "SCSI Command complete\n");
775: if (data_len != 0)
776: Log_Printf(LOG_SCSI_LEVEL, "SCSI Command completed unexpectedly\n");
777: data_len = 0;
778: dma_left = 0;
779: async_len = 0;
780:
781: // if(status) {
782: // Log_Printf(LOG_SCSI_LEVEL, "Command failed\n");
783: // }
784: // status = status; return status, not status register!!
785: status = STAT_ST;
786: seqstep = SEQ_0;
787: if(mode_dma)
788: esp_dma_done();
789: }
790:
791: void write_response(void) {
792: Log_Printf(LOG_SCSI_LEVEL, "Transfer status: $%02x\n", SCSIcommand.returnCode);
793: esp_fifo[0] = SCSIcommand.returnCode; // status
794: esp_fifo[1] = 0x00; // message
795:
796: if(mode_dma == 1) {
797: dma_memory_write(esp_fifo, 2, CHANNEL_SCSI);
798: status = (status & STAT_MASK) | STAT_TC | STAT_ST;
799: intstatus = INTR_BS | INTR_FC;
800: seqstep = SEQ_CD;
801: } else {
802: status = (status & STAT_MASK) | STAT_ST;
803: fifo_read_ptr = 0;
804: fifo_write_ptr = 2;
805: fifoflags = (fifoflags & 0xE0) | 2;
806: }
807: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.