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