25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_asc.c,v 1.70 2005/03/23 08:45:49 debug Exp $ |
* $Id: dev_asc.c,v 1.76 2005/11/13 00:14:08 debug Exp $ |
29 |
* |
* |
30 |
* 'asc' SCSI controller for some DECstation/DECsystem models, and |
* 'asc' SCSI controller for some DECstation/DECsystem models, and |
31 |
* for PICA-61. |
* for PICA-61. |
71 |
/* #define ASC_FULL_REGISTER_ACCESS_DEBUG */ |
/* #define ASC_FULL_REGISTER_ACCESS_DEBUG */ |
72 |
/* static int quiet_mode = 0; */ |
/* static int quiet_mode = 0; */ |
73 |
|
|
74 |
|
#define ASC_TICK_SHIFT 15 |
75 |
|
|
76 |
extern int quiet_mode; |
extern int quiet_mode; |
77 |
|
|
78 |
|
|
92 |
/* The controller's SCSI id: */ |
/* The controller's SCSI id: */ |
93 |
#define ASC_SCSI_ID 7 |
#define ASC_SCSI_ID 7 |
94 |
|
|
95 |
|
#define ASC_DMA_SIZE (128*1024) |
96 |
|
|
97 |
struct asc_data { |
struct asc_data { |
98 |
int mode; |
int mode; |
99 |
|
|
122 |
|
|
123 |
/* Built-in DMA memory (for DECstation 5000/200): */ |
/* Built-in DMA memory (for DECstation 5000/200): */ |
124 |
uint32_t dma_address_reg; |
uint32_t dma_address_reg; |
125 |
unsigned char dma_address_reg_memory[4096]; |
unsigned char *dma_address_reg_memory; |
126 |
/* NOTE: full page, for bintrans */ |
unsigned char *dma; |
|
unsigned char dma[128 * 1024]; |
|
127 |
|
|
128 |
void *dma_controller_data; |
void *dma_controller_data; |
129 |
size_t (*dma_controller)(void *dma_controller_data, |
size_t (*dma_controller)(void *dma_controller_data, |
322 |
|
|
323 |
/* TODO: check len2 in a similar way? */ |
/* TODO: check len2 in a similar way? */ |
324 |
if (len + (d->dma_address_reg & |
if (len + (d->dma_address_reg & |
325 |
((sizeof(d->dma)-1))) > sizeof(d->dma)) |
(ASC_DMA_SIZE-1)) > ASC_DMA_SIZE) |
326 |
len = sizeof(d->dma) - |
len = ASC_DMA_SIZE - |
327 |
(d->dma_address_reg & |
(d->dma_address_reg & |
328 |
((sizeof(d->dma)-1))); |
(ASC_DMA_SIZE-1)); |
329 |
|
|
330 |
if (len2 > len) { |
if (len2 > len) { |
331 |
memset(d->dma + (d->dma_address_reg & |
memset(d->dma + (d->dma_address_reg & |
332 |
((sizeof(d->dma)-1))), 0, len2); |
(ASC_DMA_SIZE-1)), 0, len2); |
333 |
len2 = len; |
len2 = len; |
334 |
} |
} |
335 |
|
|
355 |
len2, 1); |
len2, 1); |
356 |
else |
else |
357 |
memcpy(d->dma + (d->dma_address_reg & |
memcpy(d->dma + (d->dma_address_reg & |
358 |
((sizeof(d->dma)-1))), |
(ASC_DMA_SIZE-1)), |
359 |
d->xferp->data_in, len2); |
d->xferp->data_in, len2); |
360 |
|
|
361 |
if (d->xferp->data_in_len > len2) { |
if (d->xferp->data_in_len > len2) { |
442 |
else |
else |
443 |
memcpy(d->xferp->data_out, |
memcpy(d->xferp->data_out, |
444 |
d->dma + (d->dma_address_reg & |
d->dma + (d->dma_address_reg & |
445 |
((sizeof(d->dma)-1))), len2); |
(ASC_DMA_SIZE-1)), len2); |
446 |
d->xferp->data_out_offset = len2; |
d->xferp->data_out_offset = len2; |
447 |
} else { |
} else { |
448 |
/* Continuing a multi-transfer: */ |
/* Continuing a multi-transfer: */ |
456 |
memcpy(d->xferp->data_out + |
memcpy(d->xferp->data_out + |
457 |
d->xferp->data_out_offset, |
d->xferp->data_out_offset, |
458 |
d->dma + (d->dma_address_reg & |
d->dma + (d->dma_address_reg & |
459 |
((sizeof(d->dma)-1))), len2); |
(ASC_DMA_SIZE-1)), len2); |
460 |
d->xferp->data_out_offset += len2; |
d->xferp->data_out_offset += len2; |
461 |
} |
} |
462 |
|
|
566 |
|
|
567 |
/* Redo the command if data was just sent using DATA_OUT: */ |
/* Redo the command if data was just sent using DATA_OUT: */ |
568 |
if (d->cur_phase == PHASE_DATA_OUT) { |
if (d->cur_phase == PHASE_DATA_OUT) { |
569 |
res = diskimage_scsicommand(cpu, |
res = diskimage_scsicommand(cpu, d->reg_wo[NCR_SELID] & 7, |
570 |
d->reg_wo[NCR_SELID] & 7, d->xferp); |
DISKIMAGE_SCSI, d->xferp); |
571 |
} |
} |
572 |
|
|
573 |
if (all_done) { |
if (all_done) { |
708 |
|
|
709 |
for (i=0; i<len; i++) { |
for (i=0; i<len; i++) { |
710 |
int ofs = d->dma_address_reg + i; |
int ofs = d->dma_address_reg + i; |
711 |
ch = d->dma[ofs & (sizeof(d->dma)-1)]; |
ch = d->dma[ofs & (ASC_DMA_SIZE-1)]; |
712 |
d->xferp->cmd[i] = ch; |
d->xferp->cmd[i] = ch; |
713 |
if (!quiet_mode) |
if (!quiet_mode) |
714 |
debug("%02x ", ch); |
debug("%02x ", ch); |
723 |
/* |
/* |
724 |
* Call the SCSI device to perform the command: |
* Call the SCSI device to perform the command: |
725 |
*/ |
*/ |
726 |
ok = diskimage_scsicommand(cpu, to_id, d->xferp); |
ok = diskimage_scsicommand(cpu, to_id, DISKIMAGE_SCSI, d->xferp); |
727 |
|
|
728 |
|
|
729 |
/* Cause an interrupt: */ |
/* Cause an interrupt: */ |
826 |
int n_messagebytes = 0; |
int n_messagebytes = 0; |
827 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
828 |
|
|
829 |
|
if (writeflag == MEM_WRITE) |
830 |
idata = memory_readmax64(cpu, data, len); |
idata = memory_readmax64(cpu, data, len); |
831 |
|
|
832 |
#if 0 |
#if 0 |
833 |
/* Debug stuff useful when trying to make dev_asc compatible |
/* Debug stuff useful when trying to make dev_asc compatible |
1075 |
/* TODO: not just disk, but some generic |
/* TODO: not just disk, but some generic |
1076 |
SCSI device */ |
SCSI device */ |
1077 |
target_exists = diskimage_exist(cpu->machine, |
target_exists = diskimage_exist(cpu->machine, |
1078 |
d->reg_wo[NCR_SELID] & 7); |
d->reg_wo[NCR_SELID] & 7, DISKIMAGE_SCSI); |
1079 |
|
|
1080 |
if (target_exists) { |
if (target_exists) { |
1081 |
/* |
/* |
1264 |
|
|
1265 |
d->reg_ro[NCR_CFG3] = NCRF9XCFG3_CDB; |
d->reg_ro[NCR_CFG3] = NCRF9XCFG3_CDB; |
1266 |
|
|
1267 |
|
d->dma_address_reg_memory = malloc(machine->arch_pagesize); |
1268 |
|
d->dma = malloc(ASC_DMA_SIZE); |
1269 |
|
if (d->dma == NULL || d->dma_address_reg_memory == NULL) { |
1270 |
|
fprintf(stderr, "out of memory\n"); |
1271 |
|
exit(1); |
1272 |
|
} |
1273 |
|
memset(d->dma_address_reg_memory, 0, machine->arch_pagesize); |
1274 |
|
memset(d->dma, 0, ASC_DMA_SIZE); |
1275 |
|
|
1276 |
d->dma_controller = dma_controller; |
d->dma_controller = dma_controller; |
1277 |
d->dma_controller_data = dma_controller_data; |
d->dma_controller_data = dma_controller_data; |
1278 |
|
|
1279 |
memory_device_register(mem, "asc", baseaddr, |
memory_device_register(mem, "asc", baseaddr, |
1280 |
mode == DEV_ASC_PICA? |
mode == DEV_ASC_PICA? |
1281 |
DEV_ASC_PICA_LENGTH : DEV_ASC_DEC_LENGTH, |
DEV_ASC_PICA_LENGTH : DEV_ASC_DEC_LENGTH, |
1282 |
dev_asc_access, d, MEM_DEFAULT, NULL); |
dev_asc_access, d, DM_DEFAULT, NULL); |
1283 |
|
|
1284 |
if (mode == DEV_ASC_DEC) { |
if (mode == DEV_ASC_DEC) { |
1285 |
memory_device_register(mem, "asc_dma_address_reg", |
memory_device_register(mem, "asc_dma_address_reg", |
1286 |
baseaddr + 0x40000, 4096, dev_asc_address_reg_access, d, |
baseaddr + 0x40000, 4096, dev_asc_address_reg_access, d, |
1287 |
MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK, |
DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK, |
1288 |
d->dma_address_reg_memory); |
(unsigned char *)&d->dma_address_reg_memory[0]); |
1289 |
memory_device_register(mem, "asc_dma", baseaddr + 0x80000, |
memory_device_register(mem, "asc_dma", baseaddr + 0x80000, |
1290 |
128*1024, dev_asc_dma_access, d, |
ASC_DMA_SIZE, dev_asc_dma_access, d, |
1291 |
MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK, d->dma); |
DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK, d->dma); |
1292 |
} |
} |
1293 |
|
|
1294 |
machine_add_tickfunction(machine, dev_asc_tick, d, 15); |
machine_add_tickfunction(machine, dev_asc_tick, d, ASC_TICK_SHIFT); |
1295 |
} |
} |
1296 |
|
|