1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * A4000T / A4091 NCR 53C710 SCSI
5 *
6 * (c) 2007-2014 Toni Wilen
7 */
8
9 #include "sysconfig.h"
10 #include "sysdeps.h"
11
12 #ifdef NCR
13
14 #define NCR_DEBUG 2
15
16 #include "options.h"
17 #include "uae.h"
18 #include "uae/memory.h"
19 #include "rommgr.h"
20 #include "custom.h"
21 #include "newcpu.h"
22 #include "ncr_scsi.h"
23 #include "scsi.h"
24 #include "filesys.h"
25 #include "zfile.h"
26 #include "blkdev.h"
27 #include "cpuboard.h"
28 #include "qemuvga/qemuuaeglue.h"
29 #include "qemuvga/queue.h"
30 #include "qemuvga/scsi/scsi.h"
31 #include "autoconf.h"
32 #include "gui.h"
33
34 #define BOARD_SIZE 16777216
35 #define IO_MASK 0xff
36
37 #define A4091_ROM_VECTOR 0x0200
38 #define A4091_ROM_OFFSET 0x0000
39 #define A4091_ROM_SIZE 32768
40 #define A4091_ROM_MASK (A4091_ROM_SIZE - 1)
41
42 #define A4091_IO_OFFSET 0x00800000
43 #define A4091_IO_ALT 0x00840000
44 #define A4091_IO_END 0x00880000
45
46 #define A4091_DIP_OFFSET 0x008c0003
47
48 #define WARP_ENGINE_IO_OFFSET 0x40000
49 #define WARP_ENGINE_IO_END 0x80000
50
51 #define CYBERSTORM_SCSI_RAM_OFFSET 0x1000
52 #define CYBERSTORM_SCSI_RAM_SIZE 0x2000
53 #define CYBERSTORM_SCSI_RAM_MASK 0x1fff
54
55 struct ncr_state
56 {
57 bool newncr;
58 DeviceState devobject;
59 SCSIDevice *scsid[8];
60 SCSIBus scsibus;
61 uae_u32 board_mask;
62 uae_u8 *rom;
63 int ramsize;
64 uae_u8 acmemory[128];
65 uae_u32 expamem_hi;
66 uae_u32 expamem_lo;
67 uaecptr baseaddress;
68 int configured;
69 bool enabled;
70 int rom_start, rom_end, rom_offset;
71 int io_start, io_end;
72 addrbank *bank;
73 bool irq;
74 void (*irq_func)(int);
75 struct romconfig *rc;
76 struct ncr_state **self_ptr;
77 };
78
79 #define MAX_NCR_UNITS 10
80 static struct ncr_state *ncr_units[MAX_NCR_UNITS + 1];
81
freescsi(SCSIDevice * scsi)82 static void freescsi (SCSIDevice *scsi)
83 {
84 if (scsi) {
85 free_scsi((struct scsi_data*)scsi->handle);
86 xfree (scsi);
87 }
88 }
89
freencrunit(struct ncr_state * ncr)90 static void freencrunit(struct ncr_state *ncr)
91 {
92 if (!ncr)
93 return;
94 for (int i = 0; i < MAX_NCR_UNITS; i++) {
95 if (ncr_units[i] == ncr) {
96 ncr_units[i] = NULL;
97 }
98 }
99 for (int ch = 0; ch < 8; ch++) {
100 freescsi (ncr->scsid[ch]);
101 ncr->scsid[ch] = NULL;
102 }
103 xfree(ncr->rom);
104 if (ncr->self_ptr)
105 *ncr->self_ptr = NULL;
106 xfree(ncr);
107 }
108
allocscsi(struct ncr_state ** ncr,struct romconfig * rc,int ch)109 static struct ncr_state *allocscsi(struct ncr_state **ncr, struct romconfig *rc, int ch)
110 {
111 struct ncr_state *scsi;
112
113 if (ch < 0) {
114 freencrunit(*ncr);
115 *ncr = NULL;
116 }
117 if ((*ncr) == NULL) {
118 scsi = xcalloc(struct ncr_state, 1);
119 for (int i = 0; i < MAX_NCR_UNITS; i++) {
120 if (ncr_units[i] == NULL) {
121 ncr_units[i] = scsi;
122 if (rc)
123 rc->unitdata = scsi;
124 scsi->rc = rc;
125 scsi->self_ptr = ncr;
126 *ncr = scsi;
127 return scsi;
128 }
129 }
130 }
131 return *ncr;
132 }
133
getscsi(struct romconfig * rc)134 static struct ncr_state *getscsi(struct romconfig *rc)
135 {
136 for (int i = 0; i < MAX_NCR_UNITS; i++) {
137 if (ncr_units[i]) {
138 struct ncr_state *ncr = ncr_units[i];
139 if (ncr->rc == rc)
140 return ncr;
141 }
142 }
143 return NULL;
144 }
145
getscsiboard(uaecptr addr)146 static struct ncr_state *getscsiboard(uaecptr addr)
147 {
148 for (int i = 0; ncr_units[i]; i++) {
149 if (!ncr_units[i]->baseaddress && !ncr_units[i]->configured)
150 return ncr_units[i];
151 if ((addr & ~ncr_units[i]->board_mask) == ncr_units[i]->baseaddress)
152 return ncr_units[i];
153 }
154 return NULL;
155 }
156
157 static struct ncr_state *ncr_cs;
158 static struct ncr_state *ncr_bppc;
159 static struct ncr_state *ncr_cpuboard;
160 static struct ncr_state *ncr_we;
161 static struct ncr_state *ncr_a4000t;
162 static struct ncr_state *ncra4091[MAX_DUPLICATE_EXPANSION_BOARDS];
163 static struct ncr_state *ncr_wildfire;
164
set_irq2(int level)165 static void set_irq2(int level)
166 {
167 if (level)
168 INTREQ(0x8000 | 0x0008);
169 }
170
ncr_rethink(void)171 void ncr_rethink(void)
172 {
173 for (int i = 0; ncr_units[i]; i++) {
174 if (ncr_units[i] != ncr_cs && ncr_units[i]->irq)
175 INTREQ_0(0x8000 | 0x0008);
176 }
177 if (ncr_cs && ncr_cs->irq)
178 cyberstorm_mk3_ppc_irq(1);
179 }
180
181 /* 720+ */
182
pci_set_irq(PCIDevice * pci_dev,int level)183 void pci_set_irq(PCIDevice *pci_dev, int level)
184 {
185 struct ncr_state *ncr = (struct ncr_state*)pci_dev;
186 ncr->irq = level != 0;
187 ncr->irq_func(ncr->irq);
188 }
189
scsi_req_continue(SCSIRequest * req)190 void scsi_req_continue(SCSIRequest *req)
191 {
192 struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
193 if (sd->data_len < 0) {
194 lsi_command_complete(req, sd->status, 0);
195 } else if (sd->data_len) {
196 lsi_transfer_data(req, sd->data_len);
197 } else {
198 if (sd->direction > 0)
199 scsi_emulate_cmd(sd);
200 lsi_command_complete(req, sd->status, 0);
201 }
202 }
scsi_req_new(SCSIDevice * d,uint32_t tag,uint32_t lun,uint8_t * buf,int len,void * hba_private)203 SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, uint8_t *buf, int len, void *hba_private)
204 {
205 SCSIRequest *req = xcalloc(SCSIRequest, 1);
206 struct scsi_data *sd = (struct scsi_data*)d->handle;
207 struct ncr_state *ncr = (struct ncr_state*)sd->privdata;
208
209 req->dev = d;
210 req->hba_private = hba_private;
211 req->bus = &ncr->scsibus;
212 req->bus->qbus.parent = &ncr->devobject;
213
214 memcpy(sd->cmd, buf, len);
215 sd->cmd_len = len;
216 return req;
217 }
scsi_req_enqueue(SCSIRequest * req)218 int32_t scsi_req_enqueue(SCSIRequest *req)
219 {
220 struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
221
222 if (sd->device_type == UAEDEV_CD)
223 gui_flicker_led (LED_CD, sd->id, 1);
224
225 sd->data_len = 0;
226 scsi_start_transfer(sd);
227 scsi_emulate_analyze(sd);
228 //write_log (_T("%02x.%02x.%02x.%02x.%02x.%02x\n"), sd->cmd[0], sd->cmd[1], sd->cmd[2], sd->cmd[3], sd->cmd[4], sd->cmd[5]);
229
230 if (sd->direction <= 0)
231 scsi_emulate_cmd(sd);
232 if (sd->direction == 0)
233 return 1;
234 return -sd->direction;
235 }
scsi_req_unref(SCSIRequest * req)236 void scsi_req_unref(SCSIRequest *req)
237 {
238 xfree(req);
239 }
scsi_req_get_buf(SCSIRequest * req)240 uint8_t *scsi_req_get_buf(SCSIRequest *req)
241 {
242 struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
243 sd->data_len = 0;
244 return sd->buffer;
245 }
scsi_device_find(SCSIBus * bus,int channel,int target,int lun)246 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun)
247 {
248 struct ncr_state *ncr = (struct ncr_state*)bus->privdata;
249 if (lun != 0 || target < 0 || target >= 8)
250 return NULL;
251 return ncr->scsid[target];
252 }
scsi_req_cancel(SCSIRequest * req)253 void scsi_req_cancel(SCSIRequest *req)
254 {
255 write_log(_T("scsi_req_cancel\n"));
256 }
257
pci_dma_rw(PCIDevice * dev,dma_addr_t addr,void * buf,dma_addr_t len,DMADirection dir)258 int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir)
259 {
260 int i = 0;
261 uae_u8 *p = (uae_u8*)buf;
262 while (len > 0) {
263 if (!dir) {
264 *p = get_byte(addr);
265 }
266 else {
267 put_byte(addr, *p);
268 }
269 p++;
270 len--;
271 addr++;
272 }
273 return 0;
274 }
275 /* 710 */
276
pci710_set_irq(PCIDevice * pci_dev,int level)277 void pci710_set_irq(PCIDevice *pci_dev, int level)
278 {
279 struct ncr_state *ncr = (struct ncr_state*)pci_dev;
280 ncr->irq = level != 0;
281 ncr->irq_func(ncr->irq);
282 }
283
scsi710_req_continue(SCSIRequest * req)284 void scsi710_req_continue(SCSIRequest *req)
285 {
286 struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
287 if (sd->data_len < 0) {
288 lsi710_command_complete(req, sd->status, 0);
289 } else if (sd->data_len) {
290 lsi710_transfer_data(req, sd->data_len);
291 } else {
292 if (sd->direction > 0)
293 scsi_emulate_cmd(sd);
294 lsi710_command_complete(req, sd->status, 0);
295 }
296 }
scsi710_req_new(SCSIDevice * d,uint32_t tag,uint32_t lun,uint8_t * buf,int len,void * hba_private)297 SCSIRequest *scsi710_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, uint8_t *buf, int len, void *hba_private)
298 {
299 SCSIRequest *req = xcalloc(SCSIRequest, 1);
300 struct scsi_data *sd = (struct scsi_data*)d->handle;
301 struct ncr_state *ncr = (struct ncr_state*)sd->privdata;
302
303 req->dev = d;
304 req->hba_private = hba_private;
305 req->bus = &ncr->scsibus;
306 req->bus->qbus.parent = &ncr->devobject;
307
308 memcpy (sd->cmd, buf, len);
309 sd->cmd_len = len;
310 return req;
311 }
scsi710_req_enqueue(SCSIRequest * req)312 int32_t scsi710_req_enqueue(SCSIRequest *req)
313 {
314 struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
315
316 if (sd->device_type == UAEDEV_CD)
317 gui_flicker_led (LED_CD, sd->id, 1);
318
319 sd->data_len = 0;
320 scsi_start_transfer (sd);
321 scsi_emulate_analyze (sd);
322 //write_log (_T("%02x.%02x.%02x.%02x.%02x.%02x\n"), sd->cmd[0], sd->cmd[1], sd->cmd[2], sd->cmd[3], sd->cmd[4], sd->cmd[5]);
323
324 if (sd->direction <= 0)
325 scsi_emulate_cmd(sd);
326 if (sd->direction == 0)
327 return 1;
328 return -sd->direction;
329 }
scsi710_req_unref(SCSIRequest * req)330 void scsi710_req_unref(SCSIRequest *req)
331 {
332 xfree (req);
333 }
scsi710_req_get_buf(SCSIRequest * req)334 uint8_t *scsi710_req_get_buf(SCSIRequest *req)
335 {
336 struct scsi_data *sd = (struct scsi_data*)req->dev->handle;
337 sd->data_len = 0;
338 return sd->buffer;
339 }
scsi710_device_find(SCSIBus * bus,int channel,int target,int lun)340 SCSIDevice *scsi710_device_find(SCSIBus *bus, int channel, int target, int lun)
341 {
342 struct ncr_state *ncr = (struct ncr_state*)bus->privdata;
343 if (lun != 0 || target < 0 || target >= 8)
344 return NULL;
345 return ncr->scsid[target];
346 }
scsi710_req_cancel(SCSIRequest * req)347 void scsi710_req_cancel(SCSIRequest *req)
348 {
349 write_log (_T("scsi_req_cancel\n"));
350 }
351
pci710_dma_rw(PCIDevice * dev,dma_addr_t addr,void * buf,dma_addr_t len,DMADirection dir)352 int pci710_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir)
353 {
354 int i = 0;
355 uae_u8 *p = (uae_u8*)buf;
356 while (len > 0) {
357 if (!dir) {
358 *p = get_byte (addr);
359 } else {
360 put_byte (addr, *p);
361 }
362 p++;
363 len--;
364 addr++;
365 }
366 return 0;
367 }
368
read_rombyte(struct ncr_state * ncr,uaecptr addr)369 static uae_u8 read_rombyte(struct ncr_state *ncr, uaecptr addr)
370 {
371 uae_u8 v = ncr->rom[addr];
372 //write_log (_T("%08X = %02X PC=%08X\n"), addr, v, M68K_GETPC);
373 return v;
374 }
375
beswap(uaecptr addr)376 static uaecptr beswap(uaecptr addr)
377 {
378 return (addr & ~3) | (3 - (addr & 3));
379 }
380
ncr_io_bput(struct ncr_state * ncr,uaecptr addr,uae_u32 val)381 static void ncr_io_bput(struct ncr_state *ncr, uaecptr addr, uae_u32 val)
382 {
383 if (addr >= CYBERSTORM_SCSI_RAM_OFFSET && ncr->ramsize) {
384 cyberstorm_scsi_ram_put(addr, val);
385 return;
386 }
387 addr &= IO_MASK;
388 lsi_mmio_write(ncr->devobject.lsistate, beswap(addr), val, 1);
389 }
390
ncr710_io_bput(struct ncr_state * ncr,uaecptr addr,uae_u32 val)391 static void ncr710_io_bput(struct ncr_state *ncr, uaecptr addr, uae_u32 val)
392 {
393 addr &= IO_MASK;
394 lsi710_mmio_write(ncr->devobject.lsistate, beswap(addr), val, 1);
395 }
396
cpuboard_ncr710_io_bput(uaecptr addr,uae_u32 v)397 void cpuboard_ncr710_io_bput(uaecptr addr, uae_u32 v)
398 {
399 ncr710_io_bput(ncr_cpuboard, addr, v);
400 }
401
ncr_bput2(struct ncr_state * ncr,uaecptr addr,uae_u32 val)402 static void ncr_bput2 (struct ncr_state *ncr, uaecptr addr, uae_u32 val)
403 {
404 uae_u32 v = val;
405 addr &= ncr->board_mask;
406 if (ncr->io_end && (addr < ncr->io_start || addr >= ncr->io_end))
407 return;
408 if (ncr->newncr)
409 ncr_io_bput(ncr, addr, val);
410 else
411 ncr710_io_bput(ncr, addr, val);
412 }
413
ncr_io_bget(struct ncr_state * ncr,uaecptr addr)414 static uae_u32 ncr_io_bget(struct ncr_state *ncr, uaecptr addr)
415 {
416 if (addr >= CYBERSTORM_SCSI_RAM_OFFSET && ncr->ramsize)
417 return cyberstorm_scsi_ram_get(addr);
418 addr &= IO_MASK;
419 return lsi_mmio_read(ncr->devobject.lsistate, beswap(addr), 1);
420 }
421
ncr710_io_bget(struct ncr_state * ncr,uaecptr addr)422 static uae_u32 ncr710_io_bget(struct ncr_state *ncr, uaecptr addr)
423 {
424 addr &= IO_MASK;
425 return lsi710_mmio_read(ncr->devobject.lsistate, beswap(addr), 1);
426 }
427
cpuboard_ncr710_io_bget(uaecptr addr)428 uae_u32 cpuboard_ncr710_io_bget(uaecptr addr)
429 {
430 return ncr710_io_bget(ncr_cpuboard, addr);
431 }
432
ncr_bget2(struct ncr_state * ncr,uaecptr addr)433 static uae_u32 ncr_bget2 (struct ncr_state *ncr, uaecptr addr)
434 {
435 uae_u32 v = 0;
436
437 addr &= ncr->board_mask;
438 if (ncr->rom && addr >= ncr->rom_start && addr < ncr->rom_end)
439 return read_rombyte (ncr, addr - ncr->rom_offset);
440 if (addr == A4091_DIP_OFFSET) {
441 uae_u8 v = 0;
442 v |= ncr->rc->device_id;
443 v |= ncr->rc->device_settings << 3;
444 v ^= 0xff & ~7;
445 return v;
446 }
447 if (ncr->io_end && (addr < ncr->io_start || addr >= ncr->io_end))
448 return v;
449 if (ncr->newncr)
450 return ncr_io_bget(ncr, addr);
451 else
452 return ncr710_io_bget(ncr, addr);
453 }
454
ncr_lget(struct ncr_state * ncr,uaecptr addr)455 static uae_u32 REGPARAM2 ncr_lget (struct ncr_state *ncr, uaecptr addr)
456 {
457 uae_u32 v = 0;
458 if (ncr) {
459 addr &= ncr->board_mask;
460 if (ncr == ncr_we) {
461 addr &= ~0x80;
462 v = (ncr_bget2(ncr, addr + 3) << 0) | (ncr_bget2(ncr, addr + 2) << 8) |
463 (ncr_bget2(ncr, addr + 1) << 16) | (ncr_bget2(ncr, addr + 0) << 24);
464 } else {
465 if (addr >= A4091_IO_ALT) {
466 v = (ncr_bget2 (ncr, addr + 3) << 0) | (ncr_bget2 (ncr, addr + 2) << 8) |
467 (ncr_bget2 (ncr, addr + 1) << 16) | (ncr_bget2 (ncr, addr + 0) << 24);
468 } else {
469 v = (ncr_bget2 (ncr, addr + 3) << 0) | (ncr_bget2 (ncr, addr + 2) << 8) |
470 (ncr_bget2 (ncr, addr + 1) << 16) | (ncr_bget2 (ncr, addr + 0) << 24);
471 }
472 }
473 }
474 return v;
475 }
476
ncr_wget(struct ncr_state * ncr,uaecptr addr)477 static uae_u32 REGPARAM2 ncr_wget (struct ncr_state *ncr, uaecptr addr)
478 {
479 uae_u32 v = 0;
480 if (ncr) {
481 v = (ncr_bget2 (ncr, addr) << 8) | ncr_bget2 (ncr, addr + 1);
482 }
483 return v;
484 }
485
ncr_bget(struct ncr_state * ncr,uaecptr addr)486 static uae_u32 REGPARAM2 ncr_bget (struct ncr_state *ncr, uaecptr addr)
487 {
488 uae_u32 v = 0;
489 if (ncr) {
490 addr &= ncr->board_mask;
491 if (!ncr->configured) {
492 addr &= 65535;
493 if (addr >= sizeof ncr->acmemory)
494 return 0;
495 return ncr->acmemory[addr];
496 }
497 v = ncr_bget2 (ncr, addr);
498 }
499 return v;
500 }
501
ncr_lput(struct ncr_state * ncr,uaecptr addr,uae_u32 l)502 static void REGPARAM2 ncr_lput (struct ncr_state *ncr, uaecptr addr, uae_u32 l)
503 {
504 if (!ncr)
505 return;
506 addr &= ncr->board_mask;
507 if (ncr == ncr_we) {
508 addr &= ~0x80;
509 ncr_bput2(ncr, addr + 3, l >> 0);
510 ncr_bput2(ncr, addr + 2, l >> 8);
511 ncr_bput2(ncr, addr + 1, l >> 16);
512 ncr_bput2(ncr, addr + 0, l >> 24);
513 } else {
514 if (addr >= A4091_IO_ALT) {
515 ncr_bput2 (ncr, addr + 3, l >> 0);
516 ncr_bput2 (ncr, addr + 2, l >> 8);
517 ncr_bput2 (ncr, addr + 1, l >> 16);
518 ncr_bput2 (ncr, addr + 0, l >> 24);
519 } else {
520 ncr_bput2 (ncr, addr + 3, l >> 0);
521 ncr_bput2 (ncr, addr + 2, l >> 8);
522 ncr_bput2 (ncr, addr + 1, l >> 16);
523 ncr_bput2 (ncr, addr + 0, l >> 24);
524 }
525 }
526 }
527
ncr_wput(struct ncr_state * ncr,uaecptr addr,uae_u32 w)528 static void REGPARAM2 ncr_wput (struct ncr_state *ncr, uaecptr addr, uae_u32 w)
529 {
530 if (!ncr)
531 return;
532 w &= 0xffff;
533 addr &= ncr->board_mask;
534 if (!ncr->configured) {
535 addr &= 65535;
536 switch (addr)
537 {
538 case 0x44:
539 map_banks_z3(ncr->bank, expamem_z3_pointer >> 16, BOARD_SIZE >> 16);
540 ncr->board_mask = 0x00ffffff;
541 ncr->baseaddress = expamem_z3_pointer;
542 ncr->configured = 1;
543 expamem_next (ncr->bank, NULL);
544 break;
545 }
546 return;
547 }
548 ncr_bput2(ncr, addr, w >> 8);
549 ncr_bput2 (ncr, addr + 1, w);
550 }
551
ncr_bput(struct ncr_state * ncr,uaecptr addr,uae_u32 b)552 static void REGPARAM2 ncr_bput (struct ncr_state *ncr, uaecptr addr, uae_u32 b)
553 {
554 if (!ncr)
555 return;
556 b &= 0xff;
557 addr &= ncr->board_mask;
558 if (!ncr->configured) {
559 addr &= 65535;
560 switch (addr)
561 {
562 case 0x4c:
563 ncr->configured = 1;
564 expamem_shutup(ncr->bank);
565 break;
566 case 0x48:
567 ncr->expamem_lo = b & 0xff;
568 break;
569 }
570 return;
571 }
572 ncr_bput2 (ncr, addr, b);
573 }
574
ncr710_io_bput_a4000t(uaecptr addr,uae_u32 v)575 void ncr710_io_bput_a4000t(uaecptr addr, uae_u32 v)
576 {
577 ncr710_io_bput(ncr_a4000t, addr, v);
578 }
ncr710_io_bget_a4000t(uaecptr addr)579 uae_u32 ncr710_io_bget_a4000t(uaecptr addr)
580 {
581 return ncr710_io_bget(ncr_a4000t, addr);
582 }
583
ncr815_io_bput_wildfire(uaecptr addr,uae_u32 v)584 void ncr815_io_bput_wildfire(uaecptr addr, uae_u32 v)
585 {
586 ncr_io_bput(ncr_wildfire, addr, v);
587 }
ncr815_io_bget_wildfire(uaecptr addr)588 uae_u32 ncr815_io_bget_wildfire(uaecptr addr)
589 {
590 return ncr_io_bget(ncr_wildfire, addr);
591 }
592
ncr_generic_bput(uaecptr addr,uae_u32 b)593 static void REGPARAM2 ncr_generic_bput (uaecptr addr, uae_u32 b)
594 {
595 struct ncr_state *ncr = getscsiboard(addr);
596 if (ncr)
597 ncr_bput(ncr, addr, b);
598 }
ncr_generic_wput(uaecptr addr,uae_u32 b)599 static void REGPARAM2 ncr_generic_wput (uaecptr addr, uae_u32 b)
600 {
601 struct ncr_state *ncr = getscsiboard(addr);
602 if (ncr)
603 ncr_wput(ncr, addr, b);
604 }
ncr_generic_lput(uaecptr addr,uae_u32 b)605 static void REGPARAM2 ncr_generic_lput (uaecptr addr, uae_u32 b)
606 {
607 struct ncr_state *ncr = getscsiboard(addr);
608 if (ncr)
609 ncr_lput(ncr, addr, b);
610 }
ncr_generic_bget(uaecptr addr)611 static uae_u32 REGPARAM2 ncr_generic_bget (uaecptr addr)
612 {
613 struct ncr_state *ncr = getscsiboard(addr);
614 if (ncr)
615 return ncr_bget(ncr, addr);
616 return 0;
617 }
ncr_generic_wget(uaecptr addr)618 static uae_u32 REGPARAM2 ncr_generic_wget (uaecptr addr)
619 {
620 struct ncr_state *ncr = getscsiboard(addr);
621 if (ncr)
622 return ncr_wget(ncr, addr);
623 return 0;
624 }
ncr_generic_lget(uaecptr addr)625 static uae_u32 REGPARAM2 ncr_generic_lget (uaecptr addr)
626 {
627 struct ncr_state *ncr = getscsiboard(addr);
628 if (ncr)
629 return ncr_lget(ncr, addr);
630 return 0;
631 }
632
cs_bput(uaecptr addr,uae_u32 b)633 static void REGPARAM2 cs_bput(uaecptr addr, uae_u32 b)
634 {
635 ncr_bput(ncr_cs, addr, b);
636 }
cs_wput(uaecptr addr,uae_u32 b)637 static void REGPARAM2 cs_wput(uaecptr addr, uae_u32 b)
638 {
639 ncr_wput(ncr_cs, addr, b);
640 }
cs_lput(uaecptr addr,uae_u32 b)641 static void REGPARAM2 cs_lput(uaecptr addr, uae_u32 b)
642 {
643 ncr_lput(ncr_cs, addr, b);
644 }
cs_bget(uaecptr addr)645 static uae_u32 REGPARAM2 cs_bget(uaecptr addr)
646 {
647 return ncr_bget(ncr_cs, addr);
648 }
cs_wget(uaecptr addr)649 static uae_u32 REGPARAM2 cs_wget(uaecptr addr)
650 {
651 return ncr_wget(ncr_cs, addr);
652 }
cs_lget(uaecptr addr)653 static uae_u32 REGPARAM2 cs_lget(uaecptr addr)
654 {
655 return ncr_lget(ncr_cs, addr);
656 }
657
658 static addrbank ncr_bank_cs_scsi_ram = {
659 cs_lget, cs_wget, cs_bget,
660 cs_lput, cs_wput, cs_bput,
661 cyberstorm_scsi_ram_xlate, cyberstorm_scsi_ram_check, NULL, NULL, _T("CyberStorm SCSI RAM"),
662 cs_lget, cs_wget,
663 ABFLAG_IO | ABFLAG_THREADSAFE, S_READ, S_WRITE
664 };
665 static addrbank ncr_bank_cs_scsi_io = {
666 cs_lget, cs_wget, cs_bget,
667 cs_lput, cs_wput, cs_bput,
668 default_xlate, default_check, NULL, NULL, _T("CyberStorm SCSI IO"),
669 dummy_lgeti, dummy_wgeti,
670 ABFLAG_IO | ABFLAG_THREADSAFE, S_READ, S_WRITE
671 };
672
673 static struct addrbank_sub ncr_sub_bank_cs[] = {
674 { &ncr_bank_cs_scsi_io, 0x0000, 0x0000 },
675 { &ncr_bank_cs_scsi_ram, 0x1000, 0x0000 },
676 { &ncr_bank_cs_scsi_ram, 0x3000, 0x2000 },
677 { &ncr_bank_cs_scsi_ram, 0x5000, 0x4000 },
678 { &ncr_bank_cs_scsi_ram, 0x7000, 0x6000 },
679 { &ncr_bank_cs_scsi_ram, 0x9000, 0x8000 },
680 { &ncr_bank_cs_scsi_ram, 0xb000, 0xa000 },
681 { &ncr_bank_cs_scsi_ram, 0xd000, 0xc000 },
682 { &ncr_bank_cs_scsi_ram, 0xf000, 0xe000 },
683 { NULL }
684 };
685
686 addrbank ncr_bank_cyberstorm = {
687 sub_bank_lget, sub_bank_wget, sub_bank_bget,
688 sub_bank_lput, sub_bank_wput, sub_bank_bput,
689 sub_bank_xlate, sub_bank_check, NULL, NULL, _T("CyberStorm SCSI"),
690 sub_bank_lgeti, sub_bank_wgeti,
691 ABFLAG_IO | ABFLAG_THREADSAFE, S_READ, S_WRITE, ncr_sub_bank_cs
692 };
693
694 addrbank ncr_bank_generic = {
695 ncr_generic_lget, ncr_generic_wget, ncr_generic_bget,
696 ncr_generic_lput, ncr_generic_wput, ncr_generic_bput,
697 default_xlate, default_check, NULL, NULL, _T("NCR53C700/800"),
698 dummy_lgeti, dummy_wgeti,
699 ABFLAG_IO | ABFLAG_THREADSAFE, S_READ, S_WRITE
700 };
701
ew(struct ncr_state * ncr,int addr,uae_u8 value)702 static void ew (struct ncr_state *ncr, int addr, uae_u8 value)
703 {
704 if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
705 ncr->acmemory[addr] = (value & 0xf0);
706 ncr->acmemory[addr + 2] = (value & 0x0f) << 4;
707 } else {
708 ncr->acmemory[addr] = ~(value & 0xf0);
709 ncr->acmemory[addr + 2] = ~((value & 0x0f) << 4);
710 }
711 }
712
ncr_init_board(struct ncr_state * ncr)713 static void ncr_init_board(struct ncr_state *ncr)
714 {
715 if (!ncr)
716 return;
717 if (!ncr->devobject.lsistate) {
718 if (ncr->newncr)
719 lsi_scsi_init(&ncr->devobject);
720 else
721 lsi710_scsi_init (&ncr->devobject);
722 }
723 if (ncr->newncr)
724 lsi_scsi_reset(&ncr->devobject, ncr);
725 else
726 lsi710_scsi_reset (&ncr->devobject, ncr);
727 ncr->board_mask = 0xffff;
728 ncr->irq_func = set_irq2;
729 ncr->bank = &ncr_bank_generic;
730 ncr->configured = 0;
731 }
732
ncr_reset_board(struct ncr_state * ncr)733 static void ncr_reset_board (struct ncr_state *ncr)
734 {
735 if (!ncr)
736 return;
737 ncr->irq = false;
738 }
739
740 // 01010040
741 // 01020040 = H
742 // 01040040 = J
743 // 01080040 = K
744
745 static const uae_u8 warpengine_a4000_autoconfig[16] = {
746 0x90, 0x13, 0x75, 0x00, 0x08, 0x9b, 0x00, 0x19, 0x01, 0x0e, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00
747 };
748 #define WARP_ENGINE_ROM_SIZE 32768
749
ncr710_warpengine_autoconfig_init(struct romconfig * rc)750 addrbank *ncr710_warpengine_autoconfig_init(struct romconfig *rc)
751 {
752 struct ncr_state *ncr = getscsi(rc);
753
754 if (!ncr)
755 return &expamem_null;
756
757 ncr_we = ncr;
758 xfree(ncr->rom);
759 ncr->rom = NULL;
760
761 ncr->enabled = true;
762 memset (ncr->acmemory, 0xff, sizeof ncr->acmemory);
763 ncr->rom_start = 0x10;
764 ncr->rom_offset = 0;
765 ncr->rom_end = WARP_ENGINE_ROM_SIZE * 4;
766 ncr->io_start = WARP_ENGINE_IO_OFFSET;
767 ncr->io_end = WARP_ENGINE_IO_END;
768
769 for (int i = 0; i < 16; i++) {
770 uae_u8 b = warpengine_a4000_autoconfig[i];
771 if (i == 9) {
772 b = currprefs.cpuboard_settings & 7;
773 if (!b)
774 b = 1;
775 else
776 b <<= 1;
777 }
778 ew(ncr, i * 4, b);
779 }
780 ncr->rom = xcalloc (uae_u8, WARP_ENGINE_ROM_SIZE * 4);
781 struct zfile *z = read_device_from_romconfig(rc, ROMTYPE_CB_WENGINE);
782 if (z) {
783 for (int i = 0; i < WARP_ENGINE_ROM_SIZE; i++) {
784 uae_u8 b = 0xff;
785 zfile_fread(&b, 1, 1, z);
786 ncr->rom[i * 4 + 0] = b | 0x0f;
787 ncr->rom[i * 4 + 1] = 0xff;
788 ncr->rom[i * 4 + 2] = (b << 4) | 0x0f;
789 ncr->rom[i * 4 + 3] = 0xff;
790 }
791 zfile_fclose(z);
792 }
793
794 ncr_reset_board(ncr);
795
796 return &ncr_bank_generic;
797 }
798
ncr710_a4091_autoconfig_init(struct romconfig * rc)799 addrbank *ncr710_a4091_autoconfig_init (struct romconfig *rc)
800 {
801 struct ncr_state *ncr = getscsi(rc);
802
803 if (!ncr)
804 return &expamem_null;
805
806 xfree(ncr->rom);
807 ncr->rom = NULL;
808
809 ncr->enabled = true;
810 memset (ncr->acmemory, 0xff, sizeof ncr->acmemory);
811 ncr->rom_start = 0;
812 ncr->rom_offset = A4091_ROM_OFFSET;
813 ncr->rom_end = A4091_IO_OFFSET;
814 ncr->io_start = A4091_IO_OFFSET;
815 ncr->io_end = A4091_IO_END;
816
817 ncr_reset_board(ncr);
818
819 struct zfile *z = read_device_from_romconfig(rc, ROMTYPE_A4091);
820 if (z) {
821 ncr->rom = xmalloc (uae_u8, A4091_ROM_SIZE * 4);
822 for (int i = 0; i < A4091_ROM_SIZE; i++) {
823 uae_u8 b;
824 zfile_fread (&b, 1, 1, z);
825 ncr->rom[i * 4 + 0] = b | 0x0f;
826 ncr->rom[i * 4 + 2] = (b << 4) | 0x0f;
827 if (i < 0x20) {
828 ncr->acmemory[i * 4 + 0] = b;
829 } else if (i >= 0x40 && i < 0x60) {
830 ncr->acmemory[(i - 0x40) * 4 + 2] = b;
831 }
832 }
833 zfile_fclose(z);
834 }
835
836 return &ncr_bank_generic;
837 }
838
ncr_free(void)839 void ncr_free(void)
840 {
841 for (int i = 0; i < MAX_NCR_UNITS; i++) {
842 freencrunit(ncr_units[i]);
843 }
844 }
845
ncr_init(void)846 void ncr_init(void)
847 {
848 }
849
ncr_reset(void)850 void ncr_reset(void)
851 {
852 for (int i = 0; i < MAX_NCR_UNITS; i++) {
853 ncr_reset_board(ncr_units[i]);
854 }
855 }
856
allocscsidevice(struct ncr_state * ncr,int ch,struct scsi_data * handle)857 static void allocscsidevice(struct ncr_state *ncr, int ch, struct scsi_data *handle)
858 {
859 handle->privdata = ncr;
860 ncr->scsid[ch] = xcalloc (SCSIDevice, 1);
861 ncr->scsid[ch]->id = ch;
862 ncr->scsid[ch]->handle = handle;
863 }
864
add_ncr_scsi_hd(struct ncr_state * ncr,int ch,struct hd_hardfiledata * hfd,struct uaedev_config_info * ci)865 static void add_ncr_scsi_hd (struct ncr_state *ncr, int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci)
866 {
867 struct scsi_data *handle = NULL;
868
869 freescsi (ncr->scsid[ch]);
870 ncr->scsid[ch] = NULL;
871 if (!add_scsi_hd(&handle, ch, hfd, ci))
872 return;
873 allocscsidevice(ncr, ch, handle);
874 ncr->enabled = true;
875 }
876
add_ncr_scsi_cd(struct ncr_state * ncr,int ch,int unitnum)877 static void add_ncr_scsi_cd (struct ncr_state *ncr, int ch, int unitnum)
878 {
879 struct scsi_data *handle = NULL;
880
881 freescsi (ncr->scsid[ch]);
882 ncr->scsid[ch] = NULL;
883 if (!add_scsi_cd(&handle, ch, unitnum))
884 return;
885 allocscsidevice(ncr, ch, handle);
886 ncr->enabled = true;
887 }
888
add_ncr_scsi_tape(struct ncr_state * ncr,int ch,const TCHAR * tape_directory,bool readonly)889 static void add_ncr_scsi_tape (struct ncr_state *ncr, int ch, const TCHAR *tape_directory, bool readonly)
890 {
891 struct scsi_data *handle = NULL;
892
893 freescsi (ncr->scsid[ch]);
894 ncr->scsid[ch] = NULL;
895 if (!add_scsi_tape(&handle, ch, tape_directory, readonly))
896 return;
897 allocscsidevice(ncr, ch, handle);
898 ncr->enabled = true;
899 }
900
ncr_add_scsi_unit(struct ncr_state ** ncrp,int ch,struct uaedev_config_info * ci,struct romconfig * rc,bool newncr)901 static void ncr_add_scsi_unit(struct ncr_state **ncrp, int ch, struct uaedev_config_info *ci, struct romconfig *rc, bool newncr)
902 {
903 struct ncr_state *ncr = allocscsi(ncrp, rc, ch);
904 if (!ncr)
905 return;
906 ncr->newncr = newncr;
907 ncr_init_board(ncr);
908 if (ch >= 0 && ncr) {
909 if (ci->type == UAEDEV_CD)
910 add_ncr_scsi_cd (ncr, ch, ci->device_emu_unit);
911 else if (ci->type == UAEDEV_TAPE)
912 add_ncr_scsi_tape (ncr, ch, ci->rootdir, ci->readonly);
913 else if (ci->type == UAEDEV_HDF)
914 add_ncr_scsi_hd (ncr, ch, NULL, ci);
915 }
916 }
917
a4000t_add_scsi_unit(int ch,struct uaedev_config_info * ci,struct romconfig * rc)918 void a4000t_add_scsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc)
919 {
920 ncr_add_scsi_unit(&ncr_a4000t, ch, ci, rc, false);
921 ncr_a4000t->configured = -1;
922 ncr_a4000t->enabled = true;
923 }
924
warpengine_add_scsi_unit(int ch,struct uaedev_config_info * ci,struct romconfig * rc)925 void warpengine_add_scsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc)
926 {
927 ncr_add_scsi_unit(&ncr_we, ch, ci, rc, false);
928 }
929
tekmagic_add_scsi_unit(int ch,struct uaedev_config_info * ci,struct romconfig * rc)930 void tekmagic_add_scsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc)
931 {
932 ncr_add_scsi_unit(&ncr_cpuboard, ch, ci, rc, false);
933 }
934
a4091_add_scsi_unit(int ch,struct uaedev_config_info * ci,struct romconfig * rc)935 void a4091_add_scsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc)
936 {
937 ncr_add_scsi_unit(&ncra4091[ci->controller_type_unit], ch, ci, rc, false);
938 }
939
cyberstorm_add_scsi_unit(int ch,struct uaedev_config_info * ci,struct romconfig * rc)940 void cyberstorm_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
941 {
942 ncr_add_scsi_unit(&ncr_cs, ch, ci, rc, true);
943 ncr_cs->configured = -1;
944 ncr_cs->enabled = true;
945 ncr_cs->ramsize = CYBERSTORM_SCSI_RAM_SIZE;
946 ncr_cs->irq_func = cyberstorm_mk3_ppc_irq;
947 ncr_cs->bank = &ncr_bank_cyberstorm;
948 ncr_cs->baseaddress = 0xf40000;
949 }
950
blizzardppc_add_scsi_unit(int ch,struct uaedev_config_info * ci,struct romconfig * rc)951 void blizzardppc_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
952 {
953 ncr_add_scsi_unit(&ncr_bppc, ch, ci, rc, false);
954 ncr_bppc->configured = -1;
955 ncr_bppc->enabled = true;
956 ncr_bppc->irq_func = blizzardppc_irq;
957 ncr_bppc->bank = &ncr_bank_cyberstorm;
958 ncr_bppc->baseaddress = 0xf40000;
959 }
960
wildfire_add_scsi_unit(int ch,struct uaedev_config_info * ci,struct romconfig * rc)961 void wildfire_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
962 {
963 ncr_add_scsi_unit(&ncr_wildfire, ch, ci, rc, true);
964 ncr_wildfire->configured = -1;
965 ncr_wildfire->enabled = true;
966 ncr_wildfire->irq_func = wildfire_ncr815_irq;
967 ncr_wildfire->bank = &ncr_bank_generic;
968 }
969
970 #endif
971