/*************************************************************************** machine/pc_ide.c Functions to emulate a IDE hard disk controller Not (currently) used, since an XT does not have IDE support in BIOS :( ***************************************************************************/ #include "includes/pc_ide.h" typedef struct { int lba; /* 0 CHS mode, 1 LBA mode */ int cylinder; /* current cylinder (lba = 0) */ int head; /* current head (lba = 0) */ int sector; /* current sector (or LBA if lba = 1) */ int sector_cnt; /* sector count */ int error; /* error code */ int status; /* drive status */ int data_cnt; /* data count */ UINT8 *buffer; /* data buffer */ UINT8 *ptr; /* data pointer */ } DEVICE; typedef struct { int drv; /* 0 master, 1 slave drive */ DEVICE devs[2]; } IDE; static IDE ide[1]={ // currently only 1 is enough { 0 } }; static void pc_ide_data_w(DEVICE *This, int data) { if (This->data_cnt) { *This->ptr++ = data; if (--This->data_cnt == 0) { } } } static int pc_ide_data_r(DEVICE *This) { int data = 0xff; if (This->data_cnt) { data = *This->ptr++; if (--This->data_cnt == 0) { } } return data; } static void pc_ide_write_precomp_w(DEVICE *This, int data) { } /* * ---diagnostic mode errors--- * 7 which drive failed (0 = master, 1 = slave) * 6-3 reserved * 2-0 error code * 001 no error detected * 010 formatter device error * 011 sector buffer error * 100 ECC circuitry error * 101 controlling microprocessor error * ---operation mode--- * 7 bad block detected * 6 uncorrectable ECC error * 5 reserved * 4 ID found * 3 reserved * 2 command aborted prematurely * 1 track 000 not found * 0 DAM not found (always 0 for CP-3022) */ static int pc_ide_error_r(DEVICE *This) { int data = This->error; return data; } static void pc_ide_sector_count_w(DEVICE *This, int data) { This->sector_cnt=data; } static int pc_ide_sector_count_r(DEVICE *This) { int data = This->sector_cnt; return data; } static void pc_ide_sector_number_w(DEVICE *This,int data) { if (This->lba) This->sector = (This->sector & 0xfffff00) | (data & 0xff); else This->sector = data; } static int pc_ide_sector_number_r(DEVICE *This) { int data = This->sector & 0xff; return data; } static void pc_ide_cylinder_number_l_w(DEVICE *This, int data) { if (This->lba) This->sector = (This->sector & 0xfff00ff) | ((data & 0xff) << 8); else This->cylinder = (This->cylinder & 0xff00) | (data & 0xff); } static int pc_ide_cylinder_number_l_r(DEVICE *This) { int data; if (This->lba) data = (This->sector >> 8) & 0xff; else data = This->cylinder & 0xff; return data; } static void pc_ide_cylinder_number_h_w(DEVICE *This,int data) { if (This->lba) This->sector = (This->sector & 0xf00ffff) | ((data & 0xff) << 16); else This->cylinder = (This->cylinder & 0x00ff) | ((data & 0xff) << 8); } static int pc_ide_cylinder_number_h_r(DEVICE *This) { int data; if (This->lba) data = (This->sector >> 16) & 0xff; else data = (This->cylinder >> 8) & 0xff; return data; } static void pc_ide_drive_head_w(IDE *This, int data) { DEVICE *dev; This->drv = (data >> 4) & 1; dev=This->devs+This->drv; dev->lba = (data >> 6) & 1; if (dev->lba) dev->sector = (dev->sector & 0x0ffffff) | ((data & 0x0f) << 24); else dev->head = data & 0x0f; } static int pc_ide_drive_head_r(IDE *This) { int data; DEVICE *dev; dev=This->devs+This->drv; if (dev->lba) data = 0xe0 | (This->drv << 4) | ((dev->sector >> 24) & 0x0f); else data = 0xa0 | (This->drv << 4) | dev->head; return data; } static void pc_ide_command_w(DEVICE *This, int data) { switch (data) { case 0x00: /* nop */ break; case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: /* recalibrate */ This->cylinder = 0; break; case 0x20: case 0x21: /* read sectors (with or w/o retry) */ This->ptr = This->buffer; This->data_cnt = This->sector_cnt * 512; break; case 0x22: case 0x23: /* read long (with or w/o retry) */ break; case 0x30: case 0x31: /* write sectors (with or w/o retry) */ This->ptr = This->buffer; This->data_cnt = This->sector_cnt * 512; break; case 0x32: case 0x33: /* write long (with or w/o retry) */ break; case 0x40: case 0x41: /* read verify sectors (with or w/o retry) */ break; case 0x50: /* format track */ break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: /* seek */ break; case 0x90: /* execute diagnostics */ break; case 0x91: /* initialize drive parameters */ break; } } /* * Bit(s) Description * 7 controller is executing a command * 6 drive is ready * 5 write fault * 4 seek complete * 3 sector buffer requires servicing * 2 disk data read successfully corrected * 1 index - set to 1 each disk revolution * 0 previous command ended in an error */ static int pc_ide_status_r(DEVICE *This) { int data = This->status; return data; } /************************************************************************* * * ATHD * AT hard disk * *************************************************************************/ WRITE8_HANDLER(at_mfm_0_w) { logerror("ide write %.2x %.2x\n", offset, data); switch (offset) { case 0: pc_ide_data_w(ide->devs+ide->drv, data); break; case 1: pc_ide_write_precomp_w(ide->devs+ide->drv, data); break; case 2: pc_ide_sector_count_w(ide->devs+ide->drv, data); break; case 3: pc_ide_sector_number_w(ide->devs+ide->drv, data); break; case 4: pc_ide_cylinder_number_l_w(ide->devs+ide->drv, data); break; case 5: pc_ide_cylinder_number_h_w(ide->devs+ide->drv, data); break; case 6: pc_ide_drive_head_w(ide, data); break; case 7: pc_ide_command_w(ide->devs+ide->drv, data); break; } } READ8_HANDLER(at_mfm_0_r) { int data=0; switch (offset) { case 0: data = pc_ide_data_r(ide->devs+ide->drv); break; case 1: data = pc_ide_error_r(ide->devs+ide->drv); break; case 2: data = pc_ide_sector_count_r(ide->devs+ide->drv); break; case 3: data = pc_ide_sector_number_r(ide->devs+ide->drv); break; case 4: data = pc_ide_cylinder_number_l_r(ide->devs+ide->drv);break; case 5: data = pc_ide_cylinder_number_h_r(ide->devs+ide->drv);break; case 6: data = pc_ide_drive_head_r(ide); break; case 7: data = pc_ide_status_r(ide->devs+ide->drv); break; } logerror("ide read %.2x %.2x\n", offset, data); return data; }