1 #include <stdlib.h>
2 #include "ibm.h"
3 #include "device.h"
4 #include "io.h"
5 #include "mem.h"
6 #include "rom.h"
7 #include "scsi.h"
8 #include "scsi_53c400.h"
9 #include "timer.h"
10
11 #define POLL_TIME_US 10
12 #define MAX_BYTES_TRANSFERRED_PER_POLL 50
13 /*10us poll period with 50 bytes transferred per poll = 5MB/sec*/
14
15 typedef struct ncr5380_t
16 {
17 uint8_t output_data;
18 uint8_t icr;
19 uint8_t mode;
20 uint8_t tcr;
21 uint8_t ser;
22 uint8_t isr;
23
24 int target_id;
25 int target_bsy;
26 int target_req;
27
28 uint8_t bus_status;
29
30 int dma_mode;
31
32 void (*dma_changed)(struct ncr5380_t *ncr, int mode, int enable);
33 void *p;
34
35 scsi_bus_t bus;
36 } ncr5380_t;
37
38 typedef struct lcs6821n_t
39 {
40 rom_t bios_rom;
41
42 mem_mapping_t mapping;
43
44 uint8_t block_count;
45 int block_count_loaded;
46
47 uint8_t status_ctrl;
48
49 uint8_t buffer[0x80];
50 int buffer_pos;
51 int buffer_host_pos;
52
53 uint8_t int_ram[0x40];
54 uint8_t ext_ram[0x600];
55
56 ncr5380_t ncr;
57
58 int ncr5380_dma_enabled;
59
60 int dma_callback;
61 int dma_enabled;
62
63 int ncr_busy;
64 } lcs6821n_t;
65
66 #define ICR_DBP 0x01
67 #define ICR_ATN 0x02
68 #define ICR_SEL 0x04
69 #define ICR_BSY 0x08
70 #define ICR_ACK 0x10
71 #define ICR_ARB_LOST 0x20
72 #define ICR_ARB_IN_PROGRESS 0x40
73
74 #define MODE_ARBITRATE 0x01
75 #define MODE_DMA 0x02
76 #define MODE_MONITOR_BUSY 0x04
77 #define MODE_ENA_EOP_INT 0x08
78
79 #define STATUS_ACK 0x01
80 #define STATUS_BUSY_ERROR 0x04
81 #define STATUS_INT 0x10
82 #define STATUS_DRQ 0x40
83 #define STATUS_END_OF_DMA 0x80
84
85 #define TCR_IO 0x01
86 #define TCR_CD 0x02
87 #define TCR_MSG 0x04
88 #define TCR_REQ 0x08
89 #define TCR_LAST_BYTE_SENT 0x80
90
91 enum
92 {
93 DMA_IDLE = 0,
94 DMA_SEND,
95 DMA_TARGET_RECEIVE,
96 DMA_INITIATOR_RECEIVE
97 };
98
ncr53c400_dma_changed(ncr5380_t * ncr,int mode,int enable)99 static void ncr53c400_dma_changed(ncr5380_t *ncr, int mode, int enable)
100 {
101 lcs6821n_t *scsi = (lcs6821n_t *)ncr->p;
102
103 scsi->ncr5380_dma_enabled = (mode && enable);
104
105 scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded);
106 }
107
ncr5380_reset(ncr5380_t * ncr)108 void ncr5380_reset(ncr5380_t *ncr)
109 {
110 memset(ncr, 0, sizeof(ncr5380_t));
111 }
112
get_bus_host(ncr5380_t * ncr)113 static uint32_t get_bus_host(ncr5380_t *ncr)
114 {
115 uint32_t bus_host = 0;
116
117 if (ncr->icr & ICR_DBP)
118 bus_host |= BUS_DBP;
119 if (ncr->icr & ICR_SEL)
120 bus_host |= BUS_SEL;
121 if (ncr->icr & ICR_ATN)
122 bus_host |= BUS_ATN;
123 if (ncr->tcr & TCR_IO)
124 bus_host |= BUS_IO;
125 if (ncr->tcr & TCR_CD)
126 bus_host |= BUS_CD;
127 if (ncr->tcr & TCR_MSG)
128 bus_host |= BUS_MSG;
129 if (ncr->tcr & TCR_REQ)
130 bus_host |= BUS_REQ;
131 if (ncr->icr & ICR_BSY)
132 bus_host |= BUS_BSY;
133 if (ncr->icr & ICR_ACK)
134 bus_host |= BUS_ACK;
135 if (ncr->mode & MODE_ARBITRATE)
136 bus_host |= BUS_ARB;
137 // pclog("get_bus_host %02x %08x\n", ncr->output_data, BUS_SETDATA(ncr->output_data));
138 return bus_host | BUS_SETDATA(ncr->output_data);
139 }
140
ncr5380_write(uint32_t addr,uint8_t val,void * p)141 void ncr5380_write(uint32_t addr, uint8_t val, void *p)
142 {
143 ncr5380_t *ncr = (ncr5380_t *)p;
144 int bus_host = 0;
145
146 // pclog("ncr5380_write: addr=%06x val=%02x %04x:%04x\n", addr, val, CS,cpu_state.pc);
147 switch (addr & 7)
148 {
149 case 0: /*Output data register*/
150 ncr->output_data = val;
151 break;
152
153 case 1: /*Initiator Command Register*/
154 if ((val & (ICR_BSY | ICR_SEL)) == (ICR_BSY | ICR_SEL) &&
155 (ncr->icr & (ICR_BSY | ICR_SEL)) == ICR_SEL)
156 {
157 uint8_t temp = ncr->output_data & 0x7f;
158
159 ncr->target_id = -1;
160 while (temp)
161 {
162 temp >>= 1;
163 ncr->target_id++;
164 }
165 // pclog("Select - target ID = %i\n", ncr->target_id);
166
167 if (!ncr->target_id)
168 ncr->target_bsy = 1;
169 }
170
171 ncr->icr = val;
172 break;
173
174 case 2: /*Mode register*/
175 if ((val & MODE_ARBITRATE) && !(ncr->mode & MODE_ARBITRATE))
176 {
177 ncr->icr &= ~ICR_ARB_LOST;
178 ncr->icr |= ICR_ARB_IN_PROGRESS;
179 }
180
181 // output = 1;
182 ncr->mode = val;
183 ncr->dma_changed(ncr, ncr->dma_mode, ncr->mode & MODE_DMA);
184 if (!(ncr->mode & MODE_DMA))
185 {
186 ncr->tcr &= ~TCR_LAST_BYTE_SENT;
187 ncr->isr &= ~STATUS_END_OF_DMA;
188 ncr->dma_mode = DMA_IDLE;
189 }
190 break;
191
192 case 3: /*Target Command Register*/
193 ncr->tcr = val;
194 /* switch (val & (TCR_MSG | TCR_CD | TCR_IO))
195 {
196 case TCR_CD:
197 ncr->target_req = 1;
198 break;
199 }*/
200 break;
201 case 4: /*Select Enable Register*/
202 ncr->ser = val;
203 break;
204
205 case 5: /*Start DMA Send*/
206 ncr->dma_mode = DMA_SEND;
207 ncr->dma_changed(ncr, ncr->dma_mode, ncr->mode & MODE_DMA);
208 break;
209
210 case 7: /*Start DMA Initiator Receive*/
211 ncr->dma_mode = DMA_INITIATOR_RECEIVE;
212 ncr->dma_changed(ncr, ncr->dma_mode, ncr->mode & MODE_DMA);
213 break;
214
215 default:
216 pclog("Bad NCR5380 write %06x %02x\n", addr, val);
217 }
218
219 bus_host = get_bus_host(ncr);
220
221 scsi_bus_update(&ncr->bus, bus_host);
222 }
223
ncr5380_read(uint32_t addr,void * p)224 uint8_t ncr5380_read(uint32_t addr, void *p)
225 {
226 ncr5380_t *ncr = (ncr5380_t *)p;
227 uint32_t bus = 0;
228 uint8_t temp = 0xff;
229
230 switch (addr & 7)
231 {
232 case 0: /*Current SCSI Data*/
233 //output = 3;
234 //fatal("Here\n");
235 if (ncr->icr & ICR_DBP)
236 temp = ncr->output_data;
237 else
238 {
239 bus = scsi_bus_read(&ncr->bus);
240 temp = BUS_GETDATA(bus);
241 }
242 break;
243 case 1: /*Initiator Command Register*/
244 temp = ncr->icr;
245 break;
246 case 2: /*Mode Register*/
247 temp = ncr->mode;
248 break;
249 case 3: /*Target Command Register*/
250 temp = ncr->tcr;
251 break;
252
253 case 4: /*Current SCSI Bus Status*/
254 temp = 0;//get_bus_host(ncr);
255 bus = scsi_bus_read(&ncr->bus);
256 // pclog(" SCSI bus status = %02x %02x\n", temp, bus);
257 temp |= (bus & 0xff);
258 // pclog(" SCSI bus status = %02x\n", temp);
259 break;
260
261 case 5: /*Bus and Status Register*/
262 temp = 0;
263
264 bus = get_bus_host(ncr);
265 if (scsi_bus_match(&ncr->bus, bus))
266 temp |= 8;
267 bus = scsi_bus_read(&ncr->bus);
268
269 if (bus & BUS_ACK)
270 temp |= STATUS_ACK;
271 if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA))
272 temp |= STATUS_DRQ;
273 if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA))
274 {
275 int bus_state = 0;
276 if (bus & BUS_IO)
277 bus_state |= TCR_IO;
278 if (bus & BUS_CD)
279 bus_state |= TCR_CD;
280 if (bus & BUS_MSG)
281 bus_state |= TCR_MSG;
282 if ((ncr->tcr & 7) != bus_state)
283 ncr->isr |= STATUS_INT;
284 }
285 if (!(bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY))
286 temp |= STATUS_BUSY_ERROR;
287 temp |= (ncr->isr & (STATUS_INT | STATUS_END_OF_DMA));
288
289 // pclog(" bus and status register = %02x\n", temp);
290 break;
291
292 case 7: /*Reset Parity/Interrupt*/
293 ncr->isr &= ~STATUS_INT;
294 break;
295
296 default:
297 pclog("Bad NCR5380 read %06x\n", addr);
298 }
299 // pclog("ncr5380_read: addr=%06x temp=%02x pc=%04x:%04x\n", addr, temp, CS,cpu_state.pc);
300 return temp;
301 }
302
303 #define CTRL_DATA_DIR (1 << 6)
304
305 #define STATUS_BUFFER_NOT_READY (1 << 2)
306 #define STATUS_53C80_ACCESSIBLE (1 << 7)
307
lcs6821n_read(uint32_t addr,void * p)308 static uint8_t lcs6821n_read(uint32_t addr, void *p)
309 {
310 lcs6821n_t *scsi = (lcs6821n_t *)p;
311 uint8_t temp = 0xff;
312 //if (addr >= 0xca000)
313 addr &= 0x3fff;
314 // pclog("lcs6821n_read %08x\n", addr);
315 if (addr < 0x2000)
316 temp = scsi->bios_rom.rom[addr & 0x1fff];
317 else if (addr < 0x3800)
318 temp = 0xff;
319 else if (addr >= 0x3a00)
320 temp = scsi->ext_ram[addr - 0x3a00];
321 else switch (addr & 0x3f80)
322 {
323 case 0x3800:
324 // pclog("Read intRAM %02x %02x\n", addr & 0x3f, scsi->int_ram[addr & 0x3f]);
325 temp = scsi->int_ram[addr & 0x3f];
326 break;
327
328 case 0x3880:
329 // pclog("Read 53c80 %04x\n", addr);
330 temp = ncr5380_read(addr, &scsi->ncr);
331 break;
332
333 case 0x3900:
334 //pclog(" Read 3900 %i %02x\n", scsi->buffer_host_pos, scsi->status_ctrl);
335 if (scsi->buffer_host_pos >= 128 || !(scsi->status_ctrl & CTRL_DATA_DIR))
336 temp = 0xff;
337 else
338 {
339 temp = scsi->buffer[scsi->buffer_host_pos++];
340
341 if (scsi->buffer_host_pos == 128)
342 scsi->status_ctrl |= STATUS_BUFFER_NOT_READY;
343 }
344 break;
345
346 case 0x3980:
347 switch (addr)
348 {
349 case 0x3980: /*Status*/
350 temp = scsi->status_ctrl;// | 0x80;
351 if (!scsi->ncr_busy)
352 temp |= STATUS_53C80_ACCESSIBLE;
353 break;
354 case 0x3981: /*Block counter register*/
355 temp = scsi->block_count;
356 break;
357 case 0x3982: /*Switch register read*/
358 // temp = 7 | (7 << 3);
359 temp = 0xff;
360 break;
361 case 0x3983:
362 temp = 0xff;
363 break;
364 }
365 break;
366 }
367
368 // if (addr >= 0x3880) pclog("lcs6821n_read: addr=%05x val=%02x %04x:%04x\n", addr, temp, CS,cpu_state.pc);
369
370 return temp;
371 }
372
lcs6821n_write(uint32_t addr,uint8_t val,void * p)373 static void lcs6821n_write(uint32_t addr, uint8_t val, void *p)
374 {
375 lcs6821n_t *scsi = (lcs6821n_t *)p;
376
377 addr &= 0x3fff;
378
379 // /*if (addr >= 0x3880) */pclog("lcs6821n_write: addr=%05x val=%02x %04x:%04x %i %02x\n", addr, val, CS,cpu_state.pc, scsi->buffer_host_pos, scsi->status_ctrl);
380
381 if (addr >= 0x3a00)
382 scsi->ext_ram[addr - 0x3a00] = val;
383 else switch (addr & 0x3f80)
384 {
385 case 0x3800:
386 // pclog("Write intram %02x %02x\n", addr & 0x3f, val);
387 scsi->int_ram[addr & 0x3f] = val;
388 break;
389
390 case 0x3880:
391 // pclog("Write 53c80 %04x %02x\n", addr, val);
392 ncr5380_write(addr, val, &scsi->ncr);
393 break;
394
395 case 0x3900:
396 if (!(scsi->status_ctrl & CTRL_DATA_DIR) && scsi->buffer_host_pos < 128)
397 {
398 // pclog(" Write %i %02x\n", scsi->buffer_host_pos, val);
399 scsi->buffer[scsi->buffer_host_pos++] = val;
400 if (scsi->buffer_host_pos == 128)
401 {
402 scsi->status_ctrl |= STATUS_BUFFER_NOT_READY;
403 scsi->ncr_busy = 1;
404 }
405 }
406 break;
407
408 case 0x3980:
409 switch (addr)
410 {
411 case 0x3980: /*Control*/
412 if ((val & CTRL_DATA_DIR) && !(scsi->status_ctrl & CTRL_DATA_DIR))
413 {
414 scsi->buffer_host_pos = 128;
415 scsi->status_ctrl |= STATUS_BUFFER_NOT_READY;
416 }
417 else if (!(val & CTRL_DATA_DIR) && (scsi->status_ctrl & CTRL_DATA_DIR))
418 {
419 scsi->buffer_host_pos = 0;
420 scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
421 }
422 scsi->status_ctrl = (scsi->status_ctrl & 0x87) | (val & 0x78);
423 break;
424 case 0x3981: /*Block counter register*/
425 scsi->block_count = val;
426 scsi->block_count_loaded = 1;
427 scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded);
428 if (scsi->status_ctrl & CTRL_DATA_DIR)
429 {
430 scsi->buffer_host_pos = 128;
431 scsi->status_ctrl |= STATUS_BUFFER_NOT_READY;
432 }
433 else
434 {
435 scsi->buffer_host_pos = 0;
436 scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
437 }
438 break;
439 }
440 break;
441 }
442 }
443
t130b_read(uint32_t addr,void * p)444 static uint8_t t130b_read(uint32_t addr, void *p)
445 {
446 lcs6821n_t *scsi = (lcs6821n_t *)p;
447 uint8_t temp = 0xff;
448 //if (addr >= 0xca000)
449 addr &= 0x3fff;
450
451 if (addr < 0x1800)
452 temp = scsi->bios_rom.rom[addr & 0x1fff];
453 else if (addr < 0x1880)
454 temp = scsi->ext_ram[addr & 0x7f];
455 // else
456 // pclog("Bad T130B read %04x\n", addr);
457
458 // if (addr >= 0x3880) pclog("lcs6821n_read: addr=%05x val=%02x %04x:%04x\n", addr, temp, CS,cpu_state.pc);
459
460 return temp;
461 }
t130b_write(uint32_t addr,uint8_t val,void * p)462 static void t130b_write(uint32_t addr, uint8_t val, void *p)
463 {
464 lcs6821n_t *scsi = (lcs6821n_t *)p;
465
466 addr &= 0x3fff;
467
468 // if (addr >= 0x3880) pclog("lcs6821n_write: addr=%05x val=%02x %04x:%04x %i %02x\n", addr, val, CS,cpu_state.pc, scsi->buffer_host_pos, scsi->status_ctrl);
469
470 if (addr >= 0x1800 && addr < 0x1880)
471 scsi->ext_ram[addr & 0x7f] = val;
472 // else
473 // pclog("Bad T130B write %04x %02x\n", addr, val);
474 }
475
t130b_in(uint16_t port,void * p)476 static uint8_t t130b_in(uint16_t port, void *p)
477 {
478 lcs6821n_t *scsi = (lcs6821n_t *)p;
479 uint8_t temp = 0xff;
480
481 switch (port & 0xf)
482 {
483 case 0x0: case 0x1: case 0x2: case 0x3:
484 temp = lcs6821n_read((port & 7) | 0x3980, scsi);
485 break;
486
487 case 0x4: case 0x5:
488 temp = lcs6821n_read(0x3900, scsi);
489 break;
490
491 case 0x8: case 0x9: case 0xa: case 0xb:
492 case 0xc: case 0xd: case 0xe: case 0xf:
493 temp = ncr5380_read(port, &scsi->ncr);
494 break;
495 }
496
497 if (CS != 0xdc00)
498 {
499 //pclog("t130b_in: port=%04x val=%02x %04x:%04x\n", port, temp, CS,cpu_state.pc);
500 //output = 3;
501 //fatal("Here\n");
502 }
503 return temp;
504 }
t130b_out(uint16_t port,uint8_t val,void * p)505 static void t130b_out(uint16_t port, uint8_t val, void *p)
506 {
507 lcs6821n_t *scsi = (lcs6821n_t *)p;
508
509 //if (CS != 0xdc00) pclog("t130b_out: port=%04x val=%02x %04x:%04x\n", port, val, CS,cpu_state.pc);
510
511 switch (port & 0xf)
512 {
513 case 0x0: case 0x1: case 0x2: case 0x3:
514 lcs6821n_write((port & 7) | 0x3980, val, scsi);
515 break;
516
517 case 0x4: case 0x5:
518 lcs6821n_write(0x3900, val, scsi);
519 break;
520
521 case 0x8: case 0x9: case 0xa: case 0xb:
522 case 0xc: case 0xd: case 0xe: case 0xf:
523 ncr5380_write(port, val, &scsi->ncr);
524 break;
525 }
526 }
527
ncr53c400_dma_callback(void * p)528 static void ncr53c400_dma_callback(void *p)
529 {
530 lcs6821n_t *scsi = (lcs6821n_t *)p;
531 ncr5380_t *ncr = &scsi->ncr;
532 int c;
533 int bytes_transferred = 0;
534
535 //pclog("dma_Callback poll\n");
536 scsi->dma_callback += POLL_TIME_US;
537
538 switch (scsi->ncr.dma_mode)
539 {
540 case DMA_SEND:
541 if (scsi->status_ctrl & CTRL_DATA_DIR)
542 {
543 pclog("DMA_SEND with DMA direction set wrong\n");
544 break;
545 }
546
547 // if (!device_data[ncr->target_id])
548 // fatal("DMA with no device\n");
549
550 if (!(scsi->status_ctrl & STATUS_BUFFER_NOT_READY))
551 {
552 // pclog(" !(scsi->status_ctrl & STATUS_BUFFER_NOT_READY)\n");
553 break;
554 }
555
556 if (!scsi->block_count_loaded)
557 {
558 // pclog("!scsi->block_count_loaded\n");
559 break;
560 }
561
562 while (bytes_transferred < MAX_BYTES_TRANSFERRED_PER_POLL)
563 {
564 int bus;
565 uint8_t data;
566
567 for (c = 0; c < 10; c++)
568 {
569 uint8_t status = scsi_bus_read(&ncr->bus);
570
571 if (status & BUS_REQ)
572 break;
573 }
574 if (c == 10)
575 {
576 // pclog(" No req\n");
577 break;
578 }
579
580 /*Data ready*/
581 data = scsi->buffer[scsi->buffer_pos];
582 bus = get_bus_host(ncr) & ~BUS_DATAMASK;
583 bus |= BUS_SETDATA(data);
584
585 scsi_bus_update(&ncr->bus, bus | BUS_ACK);
586 scsi_bus_update(&ncr->bus, bus & ~BUS_ACK);
587 // pclog(" Sent data %02x %i\n", data, scsi->buffer_pos);
588
589 scsi->buffer_pos++;
590 bytes_transferred++;
591
592 if (scsi->buffer_pos == 128)
593 {
594 scsi->buffer_pos = 0;
595 scsi->buffer_host_pos = 0;
596 scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
597 scsi->block_count = (scsi->block_count - 1) & 255;
598 scsi->ncr_busy = 0;
599 // pclog("Sent buffer %i\n", scsi->block_count);
600 if (!scsi->block_count)
601 {
602 scsi->block_count_loaded = 0;
603 scsi->dma_enabled = 0;
604 // scsi->buffer_host_pos = 128;
605 // scsi->status_ctrl |= STATUS_BUFFER_NOT_READY;
606
607 ncr->tcr |= TCR_LAST_BYTE_SENT;
608 ncr->isr |= STATUS_END_OF_DMA;
609 if (ncr->mode & MODE_ENA_EOP_INT)
610 ncr->isr |= STATUS_INT;
611 }
612 break;
613 }
614 }
615 break;
616
617 case DMA_INITIATOR_RECEIVE:
618 if (!(scsi->status_ctrl & CTRL_DATA_DIR))
619 {
620 pclog("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n");
621 break;
622 }
623
624 if (!(scsi->status_ctrl & STATUS_BUFFER_NOT_READY))
625 break;
626
627 if (!scsi->block_count_loaded)
628 break;
629
630 while (bytes_transferred < MAX_BYTES_TRANSFERRED_PER_POLL)
631 {
632 int bus;
633 uint8_t temp;
634
635 for (c = 0; c < 10; c++)
636 {
637 uint8_t status = scsi_bus_read(&ncr->bus);
638
639 if (status & BUS_REQ)
640 break;
641 }
642 if (c == 10)
643 break;
644
645 /*Data ready*/
646 bus = scsi_bus_read(&ncr->bus);
647 temp = BUS_GETDATA(bus);
648 // pclog(" Got data %02x %i\n", temp, scsi->buffer_pos);
649
650 bus = get_bus_host(ncr);
651
652 scsi_bus_update(&ncr->bus, bus | BUS_ACK);
653 scsi_bus_update(&ncr->bus, bus & ~BUS_ACK);
654
655 scsi->buffer[scsi->buffer_pos++] = temp;
656 bytes_transferred++;
657
658 if (scsi->buffer_pos == 128)
659 {
660 scsi->buffer_pos = 0;
661 scsi->buffer_host_pos = 0;
662 scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
663 scsi->block_count = (scsi->block_count - 1) & 255;
664 // pclog("Got buffer %i\n", scsi->block_count);
665 if (!scsi->block_count)
666 {
667 scsi->block_count_loaded = 0;
668 scsi->dma_enabled = 0;
669
670 // output=3;
671 ncr->isr |= STATUS_END_OF_DMA;
672 if (ncr->mode & MODE_ENA_EOP_INT)
673 ncr->isr |= STATUS_INT;
674 }
675 break;
676 }
677 }
678 break;
679
680 default:
681 pclog("DMA callback bad mode %i\n", scsi->ncr.dma_mode);
682 break;
683 }
684
685 {
686 int bus = scsi_bus_read(&ncr->bus);
687
688 if (!(bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY))
689 {
690 ncr->mode &= ~MODE_DMA;
691 ncr->dma_mode = DMA_IDLE;
692 ncr->dma_changed(ncr, ncr->dma_mode, ncr->mode & MODE_DMA);
693 }
694 }
695 }
696
scsi_53c400_init(char * bios_fn)697 static void *scsi_53c400_init(char *bios_fn)
698 {
699 lcs6821n_t *scsi = malloc(sizeof(lcs6821n_t));
700 memset(scsi, 0, sizeof(lcs6821n_t));
701
702 rom_init(&scsi->bios_rom, bios_fn, 0xdc000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
703 mem_mapping_disable(&scsi->bios_rom.mapping);
704
705 mem_mapping_add(&scsi->mapping, 0xdc000, 0x4000,
706 lcs6821n_read, NULL, NULL,
707 lcs6821n_write, NULL, NULL,
708 scsi->bios_rom.rom, 0, scsi);
709
710 ncr5380_reset(&scsi->ncr);
711
712 scsi->ncr.dma_changed = ncr53c400_dma_changed;
713 scsi->ncr.p = scsi;
714
715 scsi->status_ctrl = STATUS_BUFFER_NOT_READY;
716 scsi->buffer_host_pos = 128;
717
718 scsi_bus_init(&scsi->ncr.bus);
719
720 timer_add(ncr53c400_dma_callback, &scsi->dma_callback, &scsi->dma_enabled, scsi);
721
722 return scsi;
723 }
724
scsi_lcs6821n_init()725 static void *scsi_lcs6821n_init()
726 {
727 return scsi_53c400_init("Longshine LCS-6821N - BIOS version 1.04.bin");
728 }
scsi_rt1000b_init()729 static void *scsi_rt1000b_init()
730 {
731 return scsi_53c400_init("Rancho_RT1000_RTBios_version_8.10R.bin");
732 }
733
scsi_t130b_init(char * bios_fn)734 static void *scsi_t130b_init(char *bios_fn)
735 {
736 lcs6821n_t *scsi = malloc(sizeof(lcs6821n_t));
737 memset(scsi, 0, sizeof(lcs6821n_t));
738
739 rom_init(&scsi->bios_rom, "trantor_t130b_bios_v2.14.bin", 0xdc000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
740
741 mem_mapping_add(&scsi->mapping, 0xdc000, 0x4000,
742 t130b_read, NULL, NULL,
743 t130b_write, NULL, NULL,
744 scsi->bios_rom.rom, 0, scsi);
745 io_sethandler(0x0350, 0x0010,
746 t130b_in, NULL, NULL,
747 t130b_out, NULL, NULL,
748 scsi);
749
750 ncr5380_reset(&scsi->ncr);
751
752 scsi->ncr.dma_changed = ncr53c400_dma_changed;
753 scsi->ncr.p = scsi;
754
755 scsi->status_ctrl = STATUS_BUFFER_NOT_READY;
756 scsi->buffer_host_pos = 128;
757
758 scsi_bus_init(&scsi->ncr.bus);
759
760 timer_add(ncr53c400_dma_callback, &scsi->dma_callback, &scsi->dma_enabled, scsi);
761
762 return scsi;
763 }
764
scsi_53c400_close(void * p)765 static void scsi_53c400_close(void *p)
766 {
767 lcs6821n_t *scsi = (lcs6821n_t *)p;
768
769 scsi_bus_close(&scsi->ncr.bus);
770
771 free(scsi);
772 }
773
scsi_lcs6821n_available()774 static int scsi_lcs6821n_available()
775 {
776 return rom_present("Longshine LCS-6821N - BIOS version 1.04.bin");
777 }
778
scsi_rt1000b_available()779 static int scsi_rt1000b_available()
780 {
781 return rom_present("Rancho_RT1000_RTBios_version_8.10R.bin");
782 }
783
scsi_t130b_available()784 static int scsi_t130b_available()
785 {
786 return rom_present("trantor_t130b_bios_v2.14.bin");
787 }
788
789 device_t scsi_lcs6821n_device =
790 {
791 "Longshine LCS-6821N (SCSI)",
792 0,
793 scsi_lcs6821n_init,
794 scsi_53c400_close,
795 scsi_lcs6821n_available,
796 NULL,
797 NULL,
798 NULL,
799 NULL
800 };
801
802 device_t scsi_rt1000b_device =
803 {
804 "Ranco RT1000B (SCSI)",
805 0,
806 scsi_rt1000b_init,
807 scsi_53c400_close,
808 scsi_rt1000b_available,
809 NULL,
810 NULL,
811 NULL,
812 NULL
813 };
814
815 device_t scsi_t130b_device =
816 {
817 "Trantor T130B (SCSI)",
818 0,
819 scsi_t130b_init,
820 scsi_53c400_close,
821 scsi_t130b_available,
822 NULL,
823 NULL,
824 NULL,
825 NULL
826 };
827