Added support for DTC 5150X HDD controller.
Fixed some bugs in the 'Xebec' MFM controller in the process.
This commit is contained in:
parent
4fcd35fded
commit
ed7021a2e1
3 changed files with 324 additions and 86 deletions
11
src/hdd.c
11
src/hdd.c
|
|
@ -20,11 +20,12 @@ static struct
|
|||
int is_mfm;
|
||||
} hdd_controllers[] =
|
||||
{
|
||||
{"None", "none", &null_hdd_device, 0},
|
||||
{"AT Fixed Disk Adapter", "mfm_at", &mfm_at_device, 1},
|
||||
{"Fixed Disk Adapter (Xebec)", "mfm_xebec", &mfm_xebec_device, 1},
|
||||
{"XTIDE", "xtide", &xtide_device, 0},
|
||||
{"XTIDE (AT)", "xtide_at", &xtide_at_device, 0},
|
||||
{"None", "none", &null_hdd_device, 0},
|
||||
{"AT Fixed Disk Adapter", "mfm_at", &mfm_at_device, 1},
|
||||
{"DTC 5150X", "dtc5150x", &dtc_5150x_device, 1},
|
||||
{"Fixed Disk Adapter (Xebec)", "mfm_xebec", &mfm_xebec_device, 1},
|
||||
{"XTIDE", "xtide", &xtide_device, 0},
|
||||
{"XTIDE (AT)", "xtide_at", &xtide_at_device, 0},
|
||||
{"", "", NULL, 0}
|
||||
};
|
||||
|
||||
|
|
|
|||
412
src/mfm_xebec.c
412
src/mfm_xebec.c
|
|
@ -70,12 +70,8 @@ typedef struct xebec_t
|
|||
uint8_t completion_byte;
|
||||
uint8_t error;
|
||||
|
||||
// int cylinder[2];
|
||||
|
||||
int drive_sel;
|
||||
|
||||
// int max_cylinders[2], max_heads[2];
|
||||
|
||||
mfm_drive_t drives[2];
|
||||
|
||||
int sector, head, cylinder;
|
||||
|
|
@ -98,14 +94,22 @@ typedef struct xebec_t
|
|||
#define CMD_RECALIBRATE 0x01
|
||||
#define CMD_READ_STATUS 0x03
|
||||
#define CMD_VERIFY_SECTORS 0x05
|
||||
#define CMD_FORMAT_TRACK 0x06
|
||||
#define CMD_READ_SECTORS 0x08
|
||||
#define CMD_WRITE_SECTORS 0x0a
|
||||
#define CMD_SEEK 0x0b
|
||||
#define CMD_INIT_DRIVE_PARAMS 0x0c
|
||||
#define CMD_WRITE_SECTOR_BUFFER 0x0f
|
||||
#define CMD_BUFFER_DIAGNOSTIC 0xe0
|
||||
#define CMD_CONTROLLER_DIAGNOSTIC 0xe4
|
||||
#define CMD_DTC_GET_DRIVE_PARAMS 0xfb
|
||||
#define CMD_DTC_SET_STEP_RATE 0xfc
|
||||
#define CMD_DTC_SET_GEOMETRY 0xfe
|
||||
#define CMD_DTC_GET_GEOMETRY 0xff
|
||||
|
||||
#define ERR_NOT_READY 0x04
|
||||
#define ERR_NOT_READY 0x04
|
||||
#define ERR_SEEK_ERROR 0x15
|
||||
#define ERR_ILLEGAL_SECTOR_ADDRESS 0x21
|
||||
|
||||
static uint8_t xebec_read(uint16_t port, void *p)
|
||||
{
|
||||
|
|
@ -257,21 +261,25 @@ static int xebec_get_sector(xebec_t *xebec, off64_t *addr)
|
|||
if (drive->current_cylinder != xebec->cylinder)
|
||||
{
|
||||
pclog("mfm_get_sector: wrong cylinder\n");
|
||||
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
|
||||
return 1;
|
||||
}
|
||||
if (xebec->head > heads)
|
||||
{
|
||||
pclog("mfm_get_sector: past end of configured heads\n");
|
||||
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
|
||||
return 1;
|
||||
}
|
||||
if (xebec->head > drive->hpc)
|
||||
{
|
||||
pclog("mfm_get_sector: past end of heads\n");
|
||||
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
|
||||
return 1;
|
||||
}
|
||||
if (xebec->sector >= 17)
|
||||
{
|
||||
pclog("mfm_get_sector: past end of sectors\n");
|
||||
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -368,7 +376,12 @@ static void xebec_callback(void *p)
|
|||
|
||||
// pclog("xebec Verify %i,%i,%i %i\n", xebec->cylinder, xebec->head, xebec->sector, xebec->sector_count);
|
||||
if (xebec_get_sector(xebec, &addr))
|
||||
fatal("xebec_get_sector failed\n");
|
||||
{
|
||||
pclog("xebec_get_sector failed\n");
|
||||
xebec_error(xebec, xebec->error);
|
||||
xebec_complete(xebec);
|
||||
return;
|
||||
}
|
||||
|
||||
xebec_next_sector(xebec);
|
||||
|
||||
|
|
@ -385,11 +398,37 @@ static void xebec_callback(void *p)
|
|||
}
|
||||
break;
|
||||
|
||||
case CMD_FORMAT_TRACK:
|
||||
{
|
||||
off64_t addr;
|
||||
int c;
|
||||
|
||||
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
|
||||
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
|
||||
xebec->head = xebec->command[1] & 0x1f;
|
||||
// pclog("Format track %i,%i\n", xebec->cylinder, xebec->head);
|
||||
|
||||
if (xebec_get_sector(xebec, &addr))
|
||||
{
|
||||
pclog("xebec_get_sector failed\n");
|
||||
xebec_error(xebec, xebec->error);
|
||||
xebec_complete(xebec);
|
||||
return;
|
||||
}
|
||||
|
||||
fseeko64(drive->hdfile, addr * 512, SEEK_SET);
|
||||
for (c = 0; c < 17; c++)
|
||||
fwrite(xebec->sector_buf, 512, 1, drive->hdfile);
|
||||
|
||||
xebec_complete(xebec);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_READ_SECTORS:
|
||||
switch (xebec->state)
|
||||
{
|
||||
case STATE_START_COMMAND:
|
||||
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xe0) << 3);
|
||||
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
|
||||
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
|
||||
xebec->head = xebec->command[1] & 0x1f;
|
||||
xebec->sector = xebec->command[2] & 0x1f;
|
||||
|
|
@ -397,54 +436,91 @@ static void xebec_callback(void *p)
|
|||
xebec->state = STATE_SEND_DATA;
|
||||
xebec->data_pos = 0;
|
||||
xebec->data_len = 512;
|
||||
{
|
||||
off64_t addr;
|
||||
|
||||
if (xebec_get_sector(xebec, &addr))
|
||||
{
|
||||
xebec_error(xebec, xebec->error);
|
||||
xebec_complete(xebec);
|
||||
return;
|
||||
}
|
||||
// pclog("xebec Read %i,%i,%i\n", xebec->cylinder, xebec->head, xebec->sector);
|
||||
|
||||
fseeko64(drive->hdfile, addr * 512, SEEK_SET);
|
||||
fread(xebec->sector_buf, 512, 1, drive->hdfile);
|
||||
readflash = 1;
|
||||
}
|
||||
if (xebec->irq_dma_mask & DMA_ENA)
|
||||
xebec->callback = XEBEC_TIME;
|
||||
else
|
||||
fatal("READ_SECTORS no DMA\n");
|
||||
{
|
||||
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
|
||||
memcpy(xebec->data, xebec->sector_buf, 512);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_SEND_DATA:
|
||||
xebec->status = STAT_BSY;
|
||||
if (xebec->irq_dma_mask & DMA_ENA)
|
||||
{
|
||||
do
|
||||
for (; xebec->data_pos < 512; xebec->data_pos++)
|
||||
{
|
||||
if (!xebec->data_pos)
|
||||
int val = dma_channel_write(3, xebec->sector_buf[xebec->data_pos]);
|
||||
|
||||
if (val == DMA_NODATA)
|
||||
{
|
||||
off64_t addr;
|
||||
|
||||
if (xebec_get_sector(xebec, &addr))
|
||||
fatal("xebec_get_sector failed\n");
|
||||
pclog("xebec Read %i,%i,%i %i %08llx %i\n", xebec->cylinder, xebec->head, xebec->sector, xebec->sector_count, addr, xebec->drive_sel);
|
||||
fseeko64(drive->hdfile, addr * 512, SEEK_SET);
|
||||
fread(xebec->sector_buf, 512, 1, drive->hdfile);
|
||||
pclog("CMD_READ_SECTORS out of data!\n");
|
||||
xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
|
||||
xebec->callback = XEBEC_TIME;
|
||||
return;
|
||||
}
|
||||
|
||||
for (; xebec->data_pos < 512; xebec->data_pos++)
|
||||
{
|
||||
int val = dma_channel_write(3, xebec->sector_buf[xebec->data_pos]);
|
||||
|
||||
if (val == DMA_NODATA)
|
||||
{
|
||||
pclog("CMD_READ_SECTORS out of data!\n");
|
||||
xebec->callback = XEBEC_TIME;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
xebec_next_sector(xebec);
|
||||
|
||||
xebec->data_pos = 0;
|
||||
|
||||
xebec->sector_count = (xebec->sector_count-1) & 0xff;
|
||||
|
||||
readflash = 1;
|
||||
} while (xebec->sector_count);
|
||||
|
||||
xebec_complete(xebec);
|
||||
}
|
||||
xebec->state = STATE_SENT_DATA;
|
||||
xebec->callback = XEBEC_TIME;
|
||||
}
|
||||
else
|
||||
fatal("Read sectors no DMA!\n");
|
||||
fatal("Read sectors no DMA! - shouldn't get here\n");
|
||||
break;
|
||||
|
||||
case STATE_SENT_DATA:
|
||||
xebec_next_sector(xebec);
|
||||
|
||||
xebec->data_pos = 0;
|
||||
|
||||
xebec->sector_count = (xebec->sector_count-1) & 0xff;
|
||||
|
||||
if (xebec->sector_count)
|
||||
{
|
||||
off64_t addr;
|
||||
|
||||
if (xebec_get_sector(xebec, &addr))
|
||||
{
|
||||
xebec_error(xebec, xebec->error);
|
||||
xebec_complete(xebec);
|
||||
return;
|
||||
}
|
||||
|
||||
// pclog("xebec Read %i,%i,%i\n", xebec->cylinder, xebec->head, xebec->sector);
|
||||
|
||||
fseeko64(drive->hdfile, addr * 512, SEEK_SET);
|
||||
fread(xebec->sector_buf, 512, 1, drive->hdfile);
|
||||
readflash = 1;
|
||||
|
||||
xebec->state = STATE_SEND_DATA;
|
||||
|
||||
if (xebec->irq_dma_mask & DMA_ENA)
|
||||
xebec->callback = XEBEC_TIME;
|
||||
else
|
||||
{
|
||||
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
|
||||
memcpy(xebec->data, xebec->sector_buf, 512);
|
||||
}
|
||||
}
|
||||
else
|
||||
xebec_complete(xebec);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
fatal("CMD_READ_SECTORS: bad state %i\n", xebec->state);
|
||||
|
|
@ -455,7 +531,7 @@ static void xebec_callback(void *p)
|
|||
switch (xebec->state)
|
||||
{
|
||||
case STATE_START_COMMAND:
|
||||
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xe0) << 3);
|
||||
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
|
||||
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
|
||||
xebec->head = xebec->command[1] & 0x1f;
|
||||
xebec->sector = xebec->command[2] & 0x1f;
|
||||
|
|
@ -466,61 +542,93 @@ static void xebec_callback(void *p)
|
|||
if (xebec->irq_dma_mask & DMA_ENA)
|
||||
xebec->callback = XEBEC_TIME;
|
||||
else
|
||||
fatal("READ_SECTORS no DMA\n");
|
||||
xebec->status = STAT_BSY | STAT_REQ;
|
||||
break;
|
||||
|
||||
case STATE_RECEIVE_DATA:
|
||||
xebec->status = STAT_BSY;
|
||||
if (xebec->irq_dma_mask & DMA_ENA)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!xebec->data_pos)
|
||||
for (; xebec->data_pos < 512; xebec->data_pos++)
|
||||
{
|
||||
int val = dma_channel_read(3);
|
||||
|
||||
if (val == DMA_NODATA)
|
||||
{
|
||||
off64_t addr;
|
||||
|
||||
// pclog("xebec Write %i,%i,%i %i\n", xebec->cylinder, xebec->head, xebec->sector, xebec->sector_count);
|
||||
if (xebec_get_sector(xebec, &addr))
|
||||
fatal("xebec_get_sector failed\n");
|
||||
|
||||
fseeko64(drive->hdfile, addr * 512, SEEK_SET);
|
||||
pclog("CMD_WRITE_SECTORS out of data!\n");
|
||||
xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
|
||||
xebec->callback = XEBEC_TIME;
|
||||
return;
|
||||
}
|
||||
|
||||
for (; xebec->data_pos < 512; xebec->data_pos++)
|
||||
{
|
||||
int val = dma_channel_read(3);
|
||||
|
||||
if (val == DMA_NODATA)
|
||||
{
|
||||
pclog("CMD_WRITE_SECTORS out of data!\n");
|
||||
xebec->callback = XEBEC_TIME;
|
||||
return;
|
||||
}
|
||||
|
||||
xebec->sector_buf[xebec->data_pos] = val & 0xff;
|
||||
}
|
||||
|
||||
fwrite(xebec->sector_buf, 512, 1, drive->hdfile);
|
||||
|
||||
xebec_next_sector(xebec);
|
||||
xebec->sector_buf[xebec->data_pos] = val & 0xff;
|
||||
}
|
||||
|
||||
xebec->data_pos = 0;
|
||||
|
||||
xebec->sector_count = (xebec->sector_count-1) & 0xff;
|
||||
|
||||
readflash = 1;
|
||||
} while (xebec->sector_count);
|
||||
|
||||
xebec_complete(xebec);
|
||||
xebec->state = STATE_RECEIVED_DATA;
|
||||
xebec->callback = XEBEC_TIME;
|
||||
}
|
||||
else
|
||||
fatal("Write sectors no DMA!\n");
|
||||
fatal("Write sectors no DMA! - should never get here\n");
|
||||
break;
|
||||
|
||||
case STATE_RECEIVED_DATA:
|
||||
if (!(xebec->irq_dma_mask & DMA_ENA))
|
||||
memcpy(xebec->sector_buf, xebec->data, 512);
|
||||
|
||||
{
|
||||
off64_t addr;
|
||||
|
||||
if (xebec_get_sector(xebec, &addr))
|
||||
{
|
||||
xebec_error(xebec, xebec->error);
|
||||
xebec_complete(xebec);
|
||||
return;
|
||||
}
|
||||
|
||||
// pclog("xebec Write %i,%i,%i %i\n", xebec->cylinder, xebec->head, xebec->sector, xebec->drive_sel);
|
||||
|
||||
fseeko64(drive->hdfile, addr * 512, SEEK_SET);
|
||||
fwrite(xebec->sector_buf, 512, 1, drive->hdfile);
|
||||
}
|
||||
|
||||
readflash = 1;
|
||||
|
||||
xebec_next_sector(xebec);
|
||||
xebec->data_pos = 0;
|
||||
xebec->sector_count = (xebec->sector_count-1) & 0xff;
|
||||
|
||||
if (xebec->sector_count)
|
||||
{
|
||||
xebec->state = STATE_RECEIVE_DATA;
|
||||
if (xebec->irq_dma_mask & DMA_ENA)
|
||||
xebec->callback = XEBEC_TIME;
|
||||
else
|
||||
xebec->status = STAT_BSY | STAT_REQ;
|
||||
}
|
||||
else
|
||||
xebec_complete(xebec);
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("CMD_WRITE_SECTORS: bad state %i\n", xebec->state);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case CMD_SEEK:
|
||||
if (!drive->hdfile)
|
||||
xebec_error(xebec, ERR_NOT_READY);
|
||||
else
|
||||
{
|
||||
int cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
|
||||
|
||||
drive->current_cylinder = (cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : cylinder;
|
||||
|
||||
if (cylinder != drive->current_cylinder)
|
||||
xebec_error(xebec, ERR_SEEK_ERROR);
|
||||
}
|
||||
xebec_complete(xebec);
|
||||
break;
|
||||
|
||||
case CMD_INIT_DRIVE_PARAMS:
|
||||
switch (xebec->state)
|
||||
{
|
||||
|
|
@ -532,7 +640,6 @@ static void xebec_callback(void *p)
|
|||
break;
|
||||
|
||||
case STATE_RECEIVED_DATA:
|
||||
// pclog("State STATE_RECEIVED_DATA\n");
|
||||
drive->cfg_cyl = xebec->data[1] | (xebec->data[0] << 8);
|
||||
drive->cfg_hpc = xebec->data[2];
|
||||
pclog("Drive %i: cylinders=%i, heads=%i\n", xebec->drive_sel, drive->cfg_cyl, drive->cfg_hpc);
|
||||
|
|
@ -548,24 +655,44 @@ static void xebec_callback(void *p)
|
|||
switch (xebec->state)
|
||||
{
|
||||
case STATE_START_COMMAND:
|
||||
xebec->state = STATE_RECEIVE_DATA;
|
||||
xebec->data_pos = 0;
|
||||
xebec->data_len = 512;
|
||||
if (xebec->irq_dma_mask & DMA_ENA)
|
||||
xebec->callback = XEBEC_TIME;
|
||||
else
|
||||
xebec->status = STAT_BSY | STAT_REQ;
|
||||
break;
|
||||
|
||||
case STATE_RECEIVE_DATA:
|
||||
if (xebec->irq_dma_mask & DMA_ENA)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < 512; c++)
|
||||
xebec->status = STAT_BSY;
|
||||
|
||||
for (; xebec->data_pos < 512; xebec->data_pos++)
|
||||
{
|
||||
int val = dma_channel_read(3);
|
||||
|
||||
if (val == DMA_NODATA)
|
||||
fatal("CMD_WRITE_SECTOR_DATA out of data!\n");
|
||||
{
|
||||
pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n");
|
||||
xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
|
||||
xebec->callback = XEBEC_TIME;
|
||||
return;
|
||||
}
|
||||
|
||||
xebec->sector_buf[c] = val & 0xff;
|
||||
xebec->data[xebec->data_pos] = val & 0xff;
|
||||
}
|
||||
|
||||
xebec_complete(xebec);
|
||||
xebec->state = STATE_RECEIVED_DATA;
|
||||
xebec->callback = XEBEC_TIME;
|
||||
}
|
||||
else
|
||||
fatal("CMD_WRITE_SECTOR_BUFFER - no DMA\n");
|
||||
fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n");
|
||||
break;
|
||||
case STATE_RECEIVED_DATA:
|
||||
memcpy(xebec->sector_buf, xebec->data, 512);
|
||||
xebec_complete(xebec);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -578,6 +705,75 @@ static void xebec_callback(void *p)
|
|||
xebec_complete(xebec);
|
||||
break;
|
||||
|
||||
case 0xfa:
|
||||
xebec_complete(xebec);
|
||||
break;
|
||||
|
||||
case CMD_DTC_SET_STEP_RATE:
|
||||
xebec_complete(xebec);
|
||||
break;
|
||||
|
||||
case CMD_DTC_GET_DRIVE_PARAMS:
|
||||
switch (xebec->state)
|
||||
{
|
||||
case STATE_START_COMMAND:
|
||||
xebec->state = STATE_SEND_DATA;
|
||||
xebec->data_pos = 0;
|
||||
xebec->data_len = 4;
|
||||
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
|
||||
memset(xebec->data, 0, 4);
|
||||
xebec->data[0] = drive->tracks & 0xff;
|
||||
xebec->data[1] = 17 | ((drive->tracks >> 2) & 0xc0);
|
||||
xebec->data[2] = drive->hpc-1;
|
||||
pclog("Get drive params %02x %02x %02x %i\n", xebec->data[0], xebec->data[1], xebec->data[2], drive->tracks);
|
||||
break;
|
||||
|
||||
case STATE_SENT_DATA:
|
||||
xebec_complete(xebec);
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", xebec->state);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_DTC_GET_GEOMETRY:
|
||||
switch (xebec->state)
|
||||
{
|
||||
case STATE_START_COMMAND:
|
||||
xebec->state = STATE_SEND_DATA;
|
||||
xebec->data_pos = 0;
|
||||
xebec->data_len = 16;
|
||||
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
|
||||
memset(xebec->data, 0, 16);
|
||||
xebec->data[0x4] = drive->tracks & 0xff;
|
||||
xebec->data[0x5] = (drive->tracks >> 8) & 0xff;
|
||||
xebec->data[0xa] = drive->hpc;
|
||||
break;
|
||||
|
||||
case STATE_SENT_DATA:
|
||||
xebec_complete(xebec);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_DTC_SET_GEOMETRY:
|
||||
switch (xebec->state)
|
||||
{
|
||||
case STATE_START_COMMAND:
|
||||
xebec->state = STATE_RECEIVE_DATA;
|
||||
xebec->data_pos = 0;
|
||||
xebec->data_len = 16;
|
||||
xebec->status = STAT_BSY | STAT_REQ;
|
||||
break;
|
||||
|
||||
case STATE_RECEIVED_DATA:
|
||||
/*Bit of a cheat here - we always report the actual geometry of the drive in use*/
|
||||
xebec_complete(xebec);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Unknown Xebec command - %02x %02x %02x %02x %02x %02x\n",
|
||||
xebec->command[0], xebec->command[1],
|
||||
|
|
@ -715,3 +911,43 @@ device_t mfm_xebec_device =
|
|||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void *dtc_5150x_init()
|
||||
{
|
||||
xebec_t *xebec = malloc(sizeof(xebec_t));
|
||||
memset(xebec, 0, sizeof(xebec_t));
|
||||
|
||||
loadhd(xebec, 0, ide_fn[0]);
|
||||
loadhd(xebec, 1, ide_fn[1]);
|
||||
xebec->switches = 0xff;
|
||||
|
||||
xebec->drives[0].cfg_cyl = xebec->drives[0].tracks;
|
||||
xebec->drives[0].cfg_hpc = xebec->drives[0].hpc;
|
||||
xebec->drives[1].cfg_cyl = xebec->drives[1].tracks;
|
||||
xebec->drives[1].cfg_hpc = xebec->drives[1].hpc;
|
||||
|
||||
rom_init(&xebec->bios_rom, "roms/dtc_cxd21a.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec);
|
||||
|
||||
timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec);
|
||||
|
||||
return xebec;
|
||||
}
|
||||
static int dtc_5150x_available()
|
||||
{
|
||||
return rom_present("roms/dtc_cxd21a.bin");
|
||||
}
|
||||
|
||||
device_t dtc_5150x_device =
|
||||
{
|
||||
"DTC 5150X",
|
||||
0,
|
||||
dtc_5150x_init,
|
||||
xebec_close,
|
||||
dtc_5150x_available,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
extern device_t mfm_xebec_device;
|
||||
extern device_t dtc_5150x_device;
|
||||
|
|
|
|||
Loading…
Reference in a new issue