More IDE clean-ups and properly implemented task file ownership, fixes OS/2 Warp 3.0 booting from IDE hard disks.
This commit is contained in:
@@ -82,23 +82,23 @@
|
|||||||
#define WIN_SEEK 0x70
|
#define WIN_SEEK 0x70
|
||||||
#define WIN_DRIVE_DIAGNOSTICS 0x90 /* Execute Drive Diagnostics */
|
#define WIN_DRIVE_DIAGNOSTICS 0x90 /* Execute Drive Diagnostics */
|
||||||
#define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */
|
#define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */
|
||||||
#define WIN_PACKETCMD 0xA0 /* Send a packet command. */
|
#define WIN_PACKETCMD 0xa0 /* Send a packet command. */
|
||||||
#define WIN_PIDENTIFY 0xA1 /* Identify ATAPI device */
|
#define WIN_PIDENTIFY 0xa1 /* Identify ATAPI device */
|
||||||
#define WIN_READ_MULTIPLE 0xC4
|
#define WIN_READ_MULTIPLE 0xc4
|
||||||
#define WIN_WRITE_MULTIPLE 0xC5
|
#define WIN_WRITE_MULTIPLE 0xc5
|
||||||
#define WIN_SET_MULTIPLE_MODE 0xC6
|
#define WIN_SET_MULTIPLE_MODE 0xc6
|
||||||
#define WIN_READ_DMA 0xC8
|
#define WIN_READ_DMA 0xc8
|
||||||
#define WIN_READ_DMA_ALT 0xC9
|
#define WIN_READ_DMA_ALT 0xc9
|
||||||
#define WIN_WRITE_DMA 0xCA
|
#define WIN_WRITE_DMA 0xcA
|
||||||
#define WIN_WRITE_DMA_ALT 0xCB
|
#define WIN_WRITE_DMA_ALT 0xcB
|
||||||
#define WIN_STANDBYNOW1 0xE0
|
#define WIN_STANDBYNOW1 0xe0
|
||||||
#define WIN_IDLENOW1 0xE1
|
#define WIN_IDLENOW1 0xe1
|
||||||
#define WIN_SETIDLE1 0xE3
|
#define WIN_SETIDLE1 0xe3
|
||||||
#define WIN_CHECKPOWERMODE1 0xE5
|
#define WIN_CHECKPOWERMODE1 0xe5
|
||||||
#define WIN_SLEEP1 0xE6
|
#define WIN_SLEEP1 0xe6
|
||||||
#define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */
|
#define WIN_IDENTIFY 0xeC /* Ask drive to identify itself */
|
||||||
#define WIN_SET_FEATURES 0xEF
|
#define WIN_SET_FEATURES 0xeF
|
||||||
#define WIN_READ_NATIVE_MAX 0xF8
|
#define WIN_READ_NATIVE_MAX 0xf8
|
||||||
|
|
||||||
#define FEATURE_SET_TRANSFER_MODE 0x03
|
#define FEATURE_SET_TRANSFER_MODE 0x03
|
||||||
#define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d
|
#define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d
|
||||||
@@ -138,50 +138,90 @@ typedef struct ide_board_t {
|
|||||||
ide_board_t *ide_boards[IDE_BUS_MAX];
|
ide_board_t *ide_boards[IDE_BUS_MAX];
|
||||||
|
|
||||||
static uint8_t ide_ter_pnp_rom[] = {
|
static uint8_t ide_ter_pnp_rom[] = {
|
||||||
0x09, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* BOX0001, serial 0, dummy checksum (filled in by isapnp_add_card) */
|
/* BOX0001, serial 0, dummy checksum (filled in by isapnp_add_card) */
|
||||||
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
|
0x09, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'l', 'e', 'r', /* ANSI identifier */
|
/* PnP version 1.0, vendor version 1.0 */
|
||||||
|
0x0a, 0x10, 0x10,
|
||||||
|
/* ANSI identifier */
|
||||||
|
0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o',
|
||||||
|
'l', 'l', 'e', 'r',
|
||||||
|
|
||||||
0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, /* logical device BOX0001 */
|
/* Logical device BOX0001 */
|
||||||
0x1c, 0x41, 0xd0, 0x06, 0x00, /* compatible device PNP0600 */
|
0x15, 0x09, 0xf8, 0x00, 0x01, 0x00,
|
||||||
0x31, 0x00, /* start dependent functions, preferred */
|
/* Compatible device PNP0600 */
|
||||||
0x22, 0x00, 0x08, /* IRQ 11 */
|
0x1c, 0x41, 0xd0, 0x06, 0x00,
|
||||||
0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */
|
/* Start dependent functions, preferred */
|
||||||
0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */
|
0x31, 0x00,
|
||||||
0x30, /* start dependent functions, acceptable */
|
/* IRQ 11 */
|
||||||
0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */
|
0x22, 0x00, 0x08,
|
||||||
0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */
|
/* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */
|
||||||
0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */
|
0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08,
|
||||||
0x30, /* start dependent functions, acceptable */
|
/* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */
|
||||||
0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */
|
0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01,
|
||||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
/* Start dependent functions, acceptable */
|
||||||
0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */
|
0x30,
|
||||||
0x38, /* end dependent functions */
|
/* IRQ 3/4/5/7/9/10/11/12 */
|
||||||
|
0x22, 0xb8, 0x1e,
|
||||||
|
/* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */
|
||||||
|
0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08,
|
||||||
|
/* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */
|
||||||
|
0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01,
|
||||||
|
/* Start dependent functions, acceptable */
|
||||||
|
0x30,
|
||||||
|
/* IRQ 3/4/5/7/9/10/11/12 */
|
||||||
|
0x22, 0xb8, 0x1e,
|
||||||
|
/* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||||
|
0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08,
|
||||||
|
/* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */
|
||||||
|
0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01,
|
||||||
|
/* End dependent functions */
|
||||||
|
0x38,
|
||||||
|
|
||||||
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
|
/* End tag, dummy checksum (filled in by isapnp_add_card) */
|
||||||
|
0x79, 0x00
|
||||||
};
|
};
|
||||||
static uint8_t ide_qua_pnp_rom[] = {
|
static uint8_t ide_qua_pnp_rom[] = {
|
||||||
0x09, 0xf8, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, /* BOX0001, serial 1, dummy checksum (filled in by isapnp_add_card) */
|
/* BOX0001, serial 1, dummy checksum (filled in by isapnp_add_card) */
|
||||||
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
|
0x09, 0xf8, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'l', 'e', 'r', /* ANSI identifier */
|
/* PnP version 1.0, vendor version 1.0 */
|
||||||
|
0x0a, 0x10, 0x10,
|
||||||
|
/* ANSI identifier */
|
||||||
|
0x82, 0x0e, 0x00, 'I', 'D', 'E', ' ', 'C', 'o', 'n', 't', 'r', 'o',
|
||||||
|
'l', 'l', 'e', 'r',
|
||||||
|
|
||||||
0x15, 0x09, 0xf8, 0x00, 0x01, 0x00, /* logical device BOX0001 */
|
/* Logical device BOX0001 */
|
||||||
0x1c, 0x41, 0xd0, 0x06, 0x00, /* compatible device PNP0600 */
|
0x15, 0x09, 0xf8, 0x00, 0x01, 0x00,
|
||||||
0x31, 0x00, /* start dependent functions, preferred */
|
/* Compatible device PNP0600 */
|
||||||
0x22, 0x00, 0x04, /* IRQ 10 */
|
0x1c, 0x41, 0xd0, 0x06, 0x00,
|
||||||
0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */
|
/* Start dependent functions, preferred */
|
||||||
0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */
|
0x31, 0x00,
|
||||||
0x30, /* start dependent functions, acceptable */
|
/* IRQ 10 */
|
||||||
0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */
|
0x22, 0x00, 0x04,
|
||||||
0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */
|
/* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */
|
||||||
0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */
|
0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08,
|
||||||
0x30, /* start dependent functions, acceptable */
|
/* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */
|
||||||
0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */
|
0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01,
|
||||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
/* Start dependent functions, acceptable */
|
||||||
0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01, /* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */
|
0x30,
|
||||||
0x38, /* end dependent functions */
|
/* IRQ 3/4/5/7/9/10/11/12 */
|
||||||
|
0x22, 0xb8, 0x1e,
|
||||||
|
/* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */
|
||||||
|
0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08,
|
||||||
|
/* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */
|
||||||
|
0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01,
|
||||||
|
/* Start dependent functions, acceptable */
|
||||||
|
0x30,
|
||||||
|
/* IRQ 3/4/5/7/9/10/11/12 */
|
||||||
|
0x22, 0xb8, 0x1e,
|
||||||
|
/* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||||
|
0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08,
|
||||||
|
/* I/O 0x100-0xFFFF, decodes 16-bit, 1-byte alignment, 1 address */
|
||||||
|
0x47, 0x01, 0x00, 0x01, 0xff, 0xff, 0x01, 0x01,
|
||||||
|
/* End dependent functions */
|
||||||
|
0x38,
|
||||||
|
|
||||||
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
|
/* End tag, dummy checksum (filled in by isapnp_add_card) */
|
||||||
|
0x79, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
ide_t *ide_drives[IDE_NUM];
|
ide_t *ide_drives[IDE_NUM];
|
||||||
@@ -364,8 +404,8 @@ ide_irq(ide_t *ide, int set, int log)
|
|||||||
if (!ide_boards[ide->board])
|
if (!ide_boards[ide->board])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef IDE_MORE_SPECIFIC_LOGS
|
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
|
||||||
ide_log("IDE %i: IRQ %s\n", set ? "raise" : "lower");
|
ide_log("IDE %i: IRQ %s\n", ide->channel, set ? "raise" : "lower");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ide->irqstat = set;
|
ide->irqstat = set;
|
||||||
@@ -583,7 +623,7 @@ ide_identify(ide_t *ide)
|
|||||||
|
|
||||||
if (ide->type == IDE_ATAPI)
|
if (ide->type == IDE_ATAPI)
|
||||||
ide->identify(ide, !IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL));
|
ide->identify(ide, !IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL));
|
||||||
else if (ide->type != IDE_NONE)
|
else if (ide->type == IDE_HDD)
|
||||||
ide_hd_identify(ide);
|
ide_hd_identify(ide);
|
||||||
else {
|
else {
|
||||||
fatal("IDE IDENTIFY or IDENTIFY PACKET DEVICE on non-attached IDE device\n");
|
fatal("IDE IDENTIFY or IDENTIFY PACKET DEVICE on non-attached IDE device\n");
|
||||||
@@ -675,15 +715,15 @@ ide_get_sector(ide_t *ide)
|
|||||||
uint32_t heads;
|
uint32_t heads;
|
||||||
uint32_t sectors;
|
uint32_t sectors;
|
||||||
|
|
||||||
if (ide->lba)
|
if (ide->tf->lba)
|
||||||
return (off64_t) ide->lba_addr;
|
return (off64_t) ide->lba_addr;
|
||||||
else {
|
else {
|
||||||
heads = ide->cfg_hpc;
|
heads = ide->cfg_hpc;
|
||||||
sectors = ide->cfg_spt;
|
sectors = ide->cfg_spt;
|
||||||
|
|
||||||
uint8_t sector = ide->sector ? (ide->sector - 1) : 0;
|
uint8_t sector = ide->tf->sector ? (ide->tf->sector - 1) : 0;
|
||||||
|
|
||||||
return ((((off64_t) ide->tf->cylinder * heads) + (off64_t) ide->head) * sectors) +
|
return ((((off64_t) ide->tf->cylinder * heads) + (off64_t) ide->tf->head) * sectors) +
|
||||||
(off64_t) sector;
|
(off64_t) sector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -694,15 +734,15 @@ ide_get_sector(ide_t *ide)
|
|||||||
static void
|
static void
|
||||||
ide_next_sector(ide_t *ide)
|
ide_next_sector(ide_t *ide)
|
||||||
{
|
{
|
||||||
if (ide->lba)
|
if (ide->tf->lba)
|
||||||
ide->lba_addr++;
|
ide->lba_addr++;
|
||||||
else {
|
else {
|
||||||
ide->sector++;
|
ide->tf->sector++;
|
||||||
if ((ide->sector == 0) || (ide->sector == (ide->cfg_spt + 1))) {
|
if ((ide->tf->sector == 0) || (ide->tf->sector == (ide->cfg_spt + 1))) {
|
||||||
ide->sector = 1;
|
ide->tf->sector = 1;
|
||||||
ide->head++;
|
ide->tf->head++;
|
||||||
if ((ide->head == 0) || (ide->head == ide->cfg_hpc)) {
|
if ((ide->tf->head == 0) || (ide->head == ide->cfg_hpc)) {
|
||||||
ide->head = 0;
|
ide->tf->head = 0;
|
||||||
ide->tf->cylinder++;
|
ide->tf->cylinder++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -729,13 +769,12 @@ loadhd(ide_t *ide, int d, UNUSED(const char *fn))
|
|||||||
void
|
void
|
||||||
ide_set_signature(ide_t *ide)
|
ide_set_signature(ide_t *ide)
|
||||||
{
|
{
|
||||||
uint16_t ide_signatures[3] = { /* 0xffff */ 0x7f7f, 0x0000, 0xeb14 };
|
uint16_t ide_signatures[4] = { 0x7f7f, 0x0000, 0xeb14, 0x7f7f };
|
||||||
|
|
||||||
ide->sector = 1;
|
ide->tf->sector = 1;
|
||||||
ide->head = 0;
|
ide->tf->head = 0;
|
||||||
|
ide->tf->secount = 1;
|
||||||
ide->tf->secount = 1;
|
ide->tf->cylinder = ide_signatures[ide->type & ~IDE_SHADOW];
|
||||||
ide->tf->cylinder = ide_signatures[ide->type];
|
|
||||||
|
|
||||||
if (ide->type == IDE_HDD)
|
if (ide->type == IDE_HDD)
|
||||||
ide->drive = 0;
|
ide->drive = 0;
|
||||||
@@ -839,16 +878,16 @@ ide_set_sector(ide_t *ide, int64_t sector_num)
|
|||||||
{
|
{
|
||||||
unsigned int cyl;
|
unsigned int cyl;
|
||||||
unsigned int r;
|
unsigned int r;
|
||||||
if (ide->lba) {
|
if (ide->tf->lba) {
|
||||||
ide->head = (sector_num >> 24) & 0xff;
|
ide->tf->head = (sector_num >> 24) & 0xff;
|
||||||
ide->tf->cylinder = (sector_num >> 8) & 0xffff;
|
ide->tf->cylinder = (sector_num >> 8) & 0xffff;
|
||||||
ide->sector = sector_num & 0xff;
|
ide->tf->sector = sector_num & 0xff;
|
||||||
} else {
|
} else {
|
||||||
cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
|
cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
|
||||||
r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
|
r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
|
||||||
ide->tf->cylinder = cyl & 0xffff;
|
ide->tf->cylinder = cyl & 0xffff;
|
||||||
ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f) & 0xff;
|
ide->tf->head = ((r / hdd[ide->hdd_num].spt) & 0x0f) & 0xff;
|
||||||
ide->sector = ((r % hdd[ide->hdd_num].spt) + 1) & 0xff;
|
ide->tf->sector = ((r % hdd[ide->hdd_num].spt) + 1) & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -954,14 +993,20 @@ ide_atapi_callback(ide_t *ide)
|
|||||||
"Complete" };
|
"Complete" };
|
||||||
char *phase;
|
char *phase;
|
||||||
|
|
||||||
if (ide->sc->packet_status <= PHASE_COMPLETE)
|
switch (ide->sc->packet_status) {
|
||||||
phase = phases[ide->sc->packet_status];
|
default:
|
||||||
else if (ide->sc->packet_status == PHASE_ERROR)
|
phase = "Unknown";
|
||||||
phase = "Error";
|
break;
|
||||||
else if (ide->sc->packet_status == PHASE_NONE)
|
case PHASE_IDLE ... PHASE_COMPLETE:
|
||||||
phase = "None";
|
phase = phases[ide->sc->packet_status];
|
||||||
else
|
break;
|
||||||
phase = "Unknown";
|
case PHASE_ERROR:
|
||||||
|
phase = "Error";
|
||||||
|
break;
|
||||||
|
case PHASE_NONE:
|
||||||
|
phase = "None";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ide_log("Phase: %02X (%s)\n", ide->sc->packet_status, phase);
|
ide_log("Phase: %02X (%s)\n", ide->sc->packet_status, phase);
|
||||||
#endif
|
#endif
|
||||||
@@ -1162,36 +1207,38 @@ ide_write_data(ide_t *ide, uint16_t val, int length)
|
|||||||
uint8_t *idebufferb = (uint8_t *) ide->buffer;
|
uint8_t *idebufferb = (uint8_t *) ide->buffer;
|
||||||
uint16_t *idebufferw = ide->buffer;
|
uint16_t *idebufferw = ide->buffer;
|
||||||
|
|
||||||
if (ide->command == WIN_PACKETCMD) {
|
if ((ide->type != IDE_NONE) && !(ide->type & IDE_SHADOW) && ide->buffer) {
|
||||||
if (ide->type == IDE_ATAPI)
|
if (ide->command == WIN_PACKETCMD) {
|
||||||
ide_atapi_packet_write(ide, val, length);
|
if (ide->type == IDE_ATAPI)
|
||||||
else
|
ide_atapi_packet_write(ide, val, length);
|
||||||
ide->tf->pos = 0;
|
else
|
||||||
} else {
|
ide->tf->pos = 0;
|
||||||
if (length == 2) {
|
|
||||||
idebufferw[ide->tf->pos >> 1] = val & 0xffff;
|
|
||||||
ide->tf->pos += 2;
|
|
||||||
} else {
|
} else {
|
||||||
idebufferb[ide->tf->pos] = val & 0xff;
|
if (length == 2) {
|
||||||
ide->tf->pos++;
|
idebufferw[ide->tf->pos >> 1] = val & 0xffff;
|
||||||
}
|
ide->tf->pos += 2;
|
||||||
|
} else {
|
||||||
|
idebufferb[ide->tf->pos] = val & 0xff;
|
||||||
|
ide->tf->pos++;
|
||||||
|
}
|
||||||
|
|
||||||
if (ide->tf->pos >= 512) {
|
if (ide->tf->pos >= 512) {
|
||||||
ide->tf->pos = 0;
|
ide->tf->pos = 0;
|
||||||
ide->tf->atastat = BSY_STAT;
|
ide->tf->atastat = BSY_STAT;
|
||||||
double seek_time = hdd_timing_write(&hdd[ide->hdd_num], ide_get_sector(ide), 1);
|
double seek_time = hdd_timing_write(&hdd[ide->hdd_num], ide_get_sector(ide), 1);
|
||||||
double xfer_time = ide_get_xfer_time(ide, 512);
|
double xfer_time = ide_get_xfer_time(ide, 512);
|
||||||
double wait_time = seek_time + xfer_time;
|
double wait_time = seek_time + xfer_time;
|
||||||
if (ide->command == WIN_WRITE_MULTIPLE) {
|
if (ide->command == WIN_WRITE_MULTIPLE) {
|
||||||
if ((ide->blockcount + 1) >= ide->blocksize || ide->tf->secount == 1) {
|
if ((ide->blockcount + 1) >= ide->blocksize || ide->tf->secount == 1) {
|
||||||
ide_set_callback(ide, seek_time + xfer_time + ide->pending_delay);
|
ide_set_callback(ide, seek_time + xfer_time + ide->pending_delay);
|
||||||
ide->pending_delay = 0;
|
ide->pending_delay = 0;
|
||||||
} else {
|
} else {
|
||||||
ide->pending_delay += wait_time;
|
ide->pending_delay += wait_time;
|
||||||
ide_callback(ide);
|
ide_callback(ide);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ide_set_callback(ide, wait_time);
|
ide_set_callback(ide, wait_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1207,7 +1254,7 @@ ide_writew(uint16_t addr, uint16_t val, void *priv)
|
|||||||
ch = dev->cur_dev;
|
ch = dev->cur_dev;
|
||||||
ide = ide_drives[ch];
|
ide = ide_drives[ch];
|
||||||
|
|
||||||
#ifdef IDE_MORE_SPECIFIC_LOGS
|
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
|
||||||
ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv);
|
ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1241,7 +1288,7 @@ ide_writel(uint16_t addr, uint32_t val, void *priv)
|
|||||||
ch = dev->cur_dev;
|
ch = dev->cur_dev;
|
||||||
ide = ide_drives[ch];
|
ide = ide_drives[ch];
|
||||||
|
|
||||||
#ifdef IDE_MORE_SPECIFIC_LOGS
|
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
|
||||||
ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv);
|
ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1289,6 +1336,10 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
|||||||
uint8_t old;
|
uint8_t old;
|
||||||
|
|
||||||
ch = dev->cur_dev;
|
ch = dev->cur_dev;
|
||||||
|
/* ATA/ATAPI specification: On a slave with non-present master, pretend the
|
||||||
|
master is selected. */
|
||||||
|
if (ide_drives[ch]->type & IDE_SHADOW)
|
||||||
|
ch ^= 1;
|
||||||
ide = ide_drives[ch];
|
ide = ide_drives[ch];
|
||||||
ide_other = ide_drives[ch ^ 1];
|
ide_other = ide_drives[ch ^ 1];
|
||||||
|
|
||||||
@@ -1364,16 +1415,16 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
|||||||
static void
|
static void
|
||||||
ide_reset_registers(ide_t *ide)
|
ide_reset_registers(ide_t *ide)
|
||||||
{
|
{
|
||||||
uint16_t ide_signatures[3] = { /* 0xffff */ 0x7f7f, 0x0000, 0xeb14 };
|
uint16_t ide_signatures[4] = { 0x7f7f, 0x0000, 0xeb14, 0x7f7f };
|
||||||
|
|
||||||
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
||||||
ide->tf->error = 1;
|
ide->tf->error = 1;
|
||||||
ide->tf->secount = 1;
|
ide->tf->secount = 1;
|
||||||
ide->tf->cylinder = ide_signatures[ide->type];
|
ide->tf->cylinder = ide_signatures[ide->type & ~IDE_SHADOW];
|
||||||
|
ide->tf->sector = 1;
|
||||||
|
ide->tf->head = 0;
|
||||||
|
|
||||||
ide->sector = 1;
|
ide->reset = 0;
|
||||||
ide->head = 0;
|
|
||||||
ide->reset = 0;
|
|
||||||
|
|
||||||
if (ide->type == IDE_ATAPI)
|
if (ide->type == IDE_ATAPI)
|
||||||
ide->sc->callback = 0.0;
|
ide->sc->callback = 0.0;
|
||||||
@@ -1388,7 +1439,6 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
|||||||
ide_t *ide;
|
ide_t *ide;
|
||||||
ide_t *ide_other;
|
ide_t *ide_other;
|
||||||
int ch;
|
int ch;
|
||||||
int absent = 0;
|
|
||||||
int bad = 0;
|
int bad = 0;
|
||||||
int reset = 0;
|
int reset = 0;
|
||||||
|
|
||||||
@@ -1396,65 +1446,74 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
|||||||
ide = ide_drives[ch];
|
ide = ide_drives[ch];
|
||||||
ide_other = ide_drives[ch ^ 1];
|
ide_other = ide_drives[ch ^ 1];
|
||||||
|
|
||||||
/* Absent and is master or both are absent. */
|
|
||||||
if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1)))
|
|
||||||
absent = 1;
|
|
||||||
/* Absent and is slave and master is present. */
|
|
||||||
else if ((ide->type == IDE_NONE) && (ch & 1))
|
|
||||||
absent = 2;
|
|
||||||
|
|
||||||
ide_log("ide_writeb(%04X, %02X, %08X)\n", addr, val, priv);
|
ide_log("ide_writeb(%04X, %02X, %08X)\n", addr, val, priv);
|
||||||
|
|
||||||
addr &= 0x7;
|
addr &= 0x7;
|
||||||
|
|
||||||
if ((absent != 1) || ((addr != 0x0) && (addr != 0x7))) switch (addr) {
|
if ((ide->type != IDE_NONE) || ((addr != 0x0) && (addr != 0x7))) switch (addr) {
|
||||||
case 0x0: /* Data */
|
case 0x0: /* Data */
|
||||||
if (absent == 0)
|
ide_write_data(ide, val | (val << 8), 2);
|
||||||
ide_write_data(ide, val | (val << 8), 2);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */
|
/* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */
|
||||||
case 0x1: /* Features */
|
case 0x1: /* Features */
|
||||||
ide->tf->cylprecomp = val;
|
if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) {
|
||||||
if (ide->type == IDE_ATAPI)
|
ide->tf->cylprecomp = val;
|
||||||
ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO");
|
if (ide->type == IDE_ATAPI)
|
||||||
|
ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO");
|
||||||
|
}
|
||||||
|
|
||||||
/* The ATA-3 specification says this register is the parameter for the
|
if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT)))
|
||||||
command and is unclear as to whether or not it's written to both
|
ide_other->tf->cylprecomp = val;
|
||||||
devices at once. Writing it to both devices at once breaks CD boot
|
|
||||||
on the AMI Apollo. */
|
|
||||||
#ifdef WRITE_PARAM_TO_BOTH_DEVICES
|
|
||||||
ide_other->tf->cylprecomp = val;
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2: /* Sector count */
|
case 0x2: /* Sector count */
|
||||||
ide->tf->secount = val;
|
if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT)))
|
||||||
ide_other->tf->secount = val;
|
ide->tf->secount = val;
|
||||||
|
if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT)))
|
||||||
|
ide_other->tf->secount = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3: /* Sector */
|
case 0x3: /* Sector */
|
||||||
ide->sector = val;
|
if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) {
|
||||||
ide->lba_addr = (ide->lba_addr & 0xfffff00) | val;
|
ide->tf->sector = val;
|
||||||
|
ide->lba_addr = (ide->lba_addr & 0xfffff00) | val;
|
||||||
|
}
|
||||||
|
|
||||||
ide_other->sector = val;
|
if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) {
|
||||||
ide_other->lba_addr = (ide_other->lba_addr & 0xfffff00) | val;
|
ide_other->tf->sector = val;
|
||||||
|
ide_other->lba_addr = (ide_other->lba_addr & 0xfffff00) | val;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x4: /* Cylinder low */
|
case 0x4: /* Cylinder low */
|
||||||
ide->tf->cylinder = (ide->tf->cylinder & 0xff00) | val;
|
if (ide->type & IDE_SHADOW)
|
||||||
ide->lba_addr = (ide->lba_addr & 0xfff00ff) | (val << 8);
|
break;
|
||||||
|
|
||||||
ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff00) | val;
|
if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) {
|
||||||
ide_other->lba_addr = (ide_other->lba_addr & 0xfff00ff) | (val << 8);
|
ide->tf->cylinder = (ide->tf->cylinder & 0xff00) | val;
|
||||||
|
ide->lba_addr = (ide->lba_addr & 0xfff00ff) | (val << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) {
|
||||||
|
ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff00) | val;
|
||||||
|
ide_other->lba_addr = (ide_other->lba_addr & 0xfff00ff) | (val << 8);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x5: /* Cylinder high */
|
case 0x5: /* Cylinder high */
|
||||||
ide->tf->cylinder = (ide->tf->cylinder & 0xff) | (val << 8);
|
if (ide->type & IDE_SHADOW)
|
||||||
ide->lba_addr = (ide->lba_addr & 0xf00ffff) | (val << 16);
|
break;
|
||||||
|
|
||||||
ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff) | (val << 8);
|
if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) {
|
||||||
ide_other->lba_addr = (ide_other->lba_addr & 0xf00ffff) | (val << 16);
|
ide->tf->cylinder = (ide->tf->cylinder & 0xff) | (val << 8);
|
||||||
|
ide->lba_addr = (ide->lba_addr & 0xf00ffff) | (val << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) {
|
||||||
|
ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff) | (val << 8);
|
||||||
|
ide_other->lba_addr = (ide_other->lba_addr & 0xf00ffff) | (val << 16);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x6: /* Drive/Head */
|
case 0x6: /* Drive/Head */
|
||||||
@@ -1484,16 +1543,27 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!reset) {
|
if (!reset) {
|
||||||
ide->head = ide_other->head = val & 0xF;
|
if (!(ide->tf->atastat & (BSY_STAT | DRQ_STAT))) {
|
||||||
ide->lba = ide_other->lba = val & 0x40;
|
ide->tf->head = val & 0xf;
|
||||||
|
ide->tf->lba = val & 0x40;
|
||||||
|
|
||||||
ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24);
|
ide->lba_addr = (ide->lba_addr & 0x0ffffff) | (ide->tf->head << 24);
|
||||||
ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24);
|
}
|
||||||
|
|
||||||
|
if (!(ide_other->tf->atastat & (BSY_STAT | DRQ_STAT))) {
|
||||||
|
ide_other->tf->head = val & 0xf;
|
||||||
|
ide_other->tf->lba = val & 0x40;
|
||||||
|
|
||||||
|
ide_other->lba_addr = (ide_other->lba_addr & 0x0ffffff) | (ide->tf->head << 24);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x7: /* Command register */
|
case 0x7: /* Command register */
|
||||||
if (absent != 0)
|
if (ide->tf->atastat & (BSY_STAT | DRQ_STAT))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((ide->type == IDE_NONE) || ((ide->type & IDE_SHADOW) && (val != WIN_DRIVE_DIAGNOSTICS)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ide_irq_lower(ide);
|
ide_irq_lower(ide);
|
||||||
@@ -1719,70 +1789,70 @@ ide_read_data(ide_t *ide, int length)
|
|||||||
{
|
{
|
||||||
const uint8_t *idebufferb = (uint8_t *) ide->buffer;
|
const uint8_t *idebufferb = (uint8_t *) ide->buffer;
|
||||||
const uint16_t *idebufferw = ide->buffer;
|
const uint16_t *idebufferw = ide->buffer;
|
||||||
int ch = ide->channel;
|
|
||||||
uint16_t ret = 0;
|
uint16_t ret = 0;
|
||||||
|
double seek_us;
|
||||||
|
double xfer_us;
|
||||||
|
|
||||||
/* Absent and is master or both are absent. */
|
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
|
||||||
if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) {
|
ide_log("ide_read_data(): ch = %i, board = %i, type = %i\n", ch,
|
||||||
|
ide->board, ide->type);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((ide->type == IDE_NONE) || (ide->type & IDE_SHADOW) || !ide->buffer) {
|
||||||
if (length == 2)
|
if (length == 2)
|
||||||
ret = 0xff7f;
|
ret = 0xff7f;
|
||||||
else
|
else
|
||||||
ret = 0x7f;
|
ret = 0x7f;
|
||||||
/* Absent and is slave and master is present. */
|
} else if (ide->command == WIN_PACKETCMD) {
|
||||||
} else if ((ide->type != IDE_NONE) || !(ch & 1)) {
|
if (ide->type == IDE_ATAPI)
|
||||||
if (!ide->buffer) {
|
ret = ide_atapi_packet_read(ide, length);
|
||||||
if (length == 2)
|
else {
|
||||||
ret = 0xffff;
|
ide_log("Drive not ATAPI (position: %i)\n", ide->tf->pos);
|
||||||
else
|
ide->tf->pos = 0;
|
||||||
ret = 0xff;
|
}
|
||||||
} else if (ide->command == WIN_PACKETCMD) {
|
} else {
|
||||||
if (ide->type == IDE_ATAPI)
|
if (length == 2) {
|
||||||
ret = ide_atapi_packet_read(ide, length);
|
ret = idebufferw[ide->tf->pos >> 1];
|
||||||
else {
|
ide->tf->pos += 2;
|
||||||
ide_log("Drive not ATAPI (position: %i)\n", ide->tf->pos);
|
|
||||||
ide->tf->pos = 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (length == 2) {
|
ret = idebufferb[ide->tf->pos];
|
||||||
ret = idebufferw[ide->tf->pos >> 1];
|
ide->tf->pos++;
|
||||||
ide->tf->pos += 2;
|
}
|
||||||
} else {
|
|
||||||
ret = idebufferb[ide->tf->pos];
|
|
||||||
ide->tf->pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ide->tf->pos >= 512) {
|
if (ide->tf->pos >= 512) {
|
||||||
ide->tf->pos = 0;
|
ide->tf->pos = 0;
|
||||||
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
||||||
if (ide->type == IDE_ATAPI)
|
if (ide->type == IDE_ATAPI)
|
||||||
ide->sc->packet_status = PHASE_IDLE;
|
ide->sc->packet_status = PHASE_IDLE;
|
||||||
|
|
||||||
if ((ide->command == WIN_READ) || (ide->command == WIN_READ_NORETRY) ||
|
if ((ide->command == WIN_READ) ||
|
||||||
(ide->command == WIN_READ_MULTIPLE)) {
|
(ide->command == WIN_READ_NORETRY) ||
|
||||||
ide->tf->secount--;
|
(ide->command == WIN_READ_MULTIPLE)) {
|
||||||
|
ide->tf->secount--;
|
||||||
|
|
||||||
if (ide->tf->secount) {
|
if (ide->tf->secount) {
|
||||||
ide_next_sector(ide);
|
ide_next_sector(ide);
|
||||||
ide->tf->atastat = BSY_STAT | READY_STAT | DSC_STAT;
|
ide->tf->atastat = BSY_STAT | READY_STAT | DSC_STAT;
|
||||||
if (ide->command == WIN_READ_MULTIPLE) {
|
if (ide->command == WIN_READ_MULTIPLE) {
|
||||||
if (!ide->blockcount) {
|
if (!ide->blockcount) {
|
||||||
uint32_t sec_count = ide->tf->secount ? ide->tf->secount : 256;
|
uint32_t cnt = ide->tf->secount ?
|
||||||
if (sec_count > ide->blocksize)
|
ide->tf->secount : 256;
|
||||||
sec_count = ide->blocksize;
|
if (cnt > ide->blocksize)
|
||||||
double seek_time = hdd_timing_read(&hdd[ide->hdd_num],
|
cnt = ide->blocksize;
|
||||||
ide_get_sector(ide), sec_count);
|
seek_us = hdd_timing_read(&hdd[ide->hdd_num],
|
||||||
double xfer_time = ide_get_xfer_time(ide, 512 * sec_count);
|
ide_get_sector(ide), cnt);
|
||||||
ide_set_callback(ide, seek_time + xfer_time);
|
xfer_us = ide_get_xfer_time(ide, 512 * cnt);
|
||||||
} else
|
ide_set_callback(ide, seek_us + xfer_us);
|
||||||
ide_callback(ide);
|
} else
|
||||||
} else {
|
ide_callback(ide);
|
||||||
double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), 1);
|
} else {
|
||||||
double xfer_time = ide_get_xfer_time(ide, 512);
|
seek_us = hdd_timing_read(&hdd[ide->hdd_num],
|
||||||
ide_set_callback(ide, seek_time + xfer_time);
|
ide_get_sector(ide), 1);
|
||||||
}
|
xfer_us = ide_get_xfer_time(ide, 512);
|
||||||
} else
|
ide_set_callback(ide, seek_us + xfer_us);
|
||||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
}
|
||||||
}
|
} else
|
||||||
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1796,11 +1866,11 @@ ide_status(ide_t *ide, ide_t *ide_other, int ch)
|
|||||||
uint8_t ret;
|
uint8_t ret;
|
||||||
|
|
||||||
/* Absent and is master or both are absent. */
|
/* Absent and is master or both are absent. */
|
||||||
if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) {
|
if (ide->type == IDE_NONE) {
|
||||||
/* Bit 7 pulled down, all other bits pulled up, per the spec. */
|
/* Bit 7 pulled down, all other bits pulled up, per the spec. */
|
||||||
ret = 0x7f;
|
ret = 0x7f;
|
||||||
/* Absent and is slave and master is present. */
|
/* Absent and is slave and master is present. */
|
||||||
} else if ((ide->type == IDE_NONE) && (ch & 1)) {
|
} else if (ide->type & IDE_SHADOW) {
|
||||||
/* On real hardware, a slave with a present master always
|
/* On real hardware, a slave with a present master always
|
||||||
returns a status of 0x00.
|
returns a status of 0x00.
|
||||||
Confirmed by the ATA-3 and ATA-4 specifications. */
|
Confirmed by the ATA-3 and ATA-4 specifications. */
|
||||||
@@ -1819,21 +1889,11 @@ ide_readb(uint16_t addr, void *priv)
|
|||||||
{
|
{
|
||||||
const ide_board_t *dev = (ide_board_t *) priv;
|
const ide_board_t *dev = (ide_board_t *) priv;
|
||||||
int ch;
|
int ch;
|
||||||
int absent = 0;
|
|
||||||
ide_t *ide;
|
ide_t *ide;
|
||||||
ide_t *ide_other;
|
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
ch = dev->cur_dev;
|
ch = dev->cur_dev;
|
||||||
ide = ide_drives[ch];
|
ide = ide_drives[ch];
|
||||||
ide_other = ide_drives[ch ^ 1];
|
|
||||||
|
|
||||||
/* Absent and is master or both are absent. */
|
|
||||||
if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1)))
|
|
||||||
absent = 1;
|
|
||||||
/* Absent and is slave and master is present. */
|
|
||||||
else if ((ide->type == IDE_NONE) && (ch & 1))
|
|
||||||
absent = 2;
|
|
||||||
|
|
||||||
switch (addr & 0x7) {
|
switch (addr & 0x7) {
|
||||||
case 0x0: /* Data */
|
case 0x0: /* Data */
|
||||||
@@ -1844,7 +1904,7 @@ ide_readb(uint16_t addr, void *priv)
|
|||||||
Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media),
|
Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media),
|
||||||
and Bit 0 = ILI (illegal length indication). */
|
and Bit 0 = ILI (illegal length indication). */
|
||||||
case 0x1: /* Error */
|
case 0x1: /* Error */
|
||||||
if (absent == 1)
|
if (ide->type == IDE_NONE)
|
||||||
ret = 0x7f;
|
ret = 0x7f;
|
||||||
else
|
else
|
||||||
ret = ide->tf->error;
|
ret = ide->tf->error;
|
||||||
@@ -1864,46 +1924,46 @@ ide_readb(uint16_t addr, void *priv)
|
|||||||
0 1 0 Data from host
|
0 1 0 Data from host
|
||||||
1 0 1 Status. */
|
1 0 1 Status. */
|
||||||
case 0x2: /* Sector count */
|
case 0x2: /* Sector count */
|
||||||
if (absent == 1)
|
if (ide->type == IDE_NONE)
|
||||||
ret = 0x7f;
|
ret = 0x7f;
|
||||||
else if (absent == 2)
|
|
||||||
ret = ide_other->tf->secount;
|
|
||||||
else
|
else
|
||||||
ret = ide->tf->secount;
|
ret = ide->tf->secount;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3: /* Sector */
|
case 0x3: /* Sector */
|
||||||
if (absent == 1)
|
if (ide->type == IDE_NONE)
|
||||||
ret = 0x7f;
|
ret = 0x7f;
|
||||||
else if (absent == 2)
|
|
||||||
ret = (uint8_t) ide_other->sector;
|
|
||||||
else
|
else
|
||||||
ret = (uint8_t) ide->sector;
|
ret = (uint8_t) ide->tf->sector;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x4: /* Cylinder low */
|
case 0x4: /* Cylinder low */
|
||||||
if (absent == 1)
|
if (ide->type == IDE_NONE)
|
||||||
ret = 0x7f;
|
ret = 0x7f;
|
||||||
else if (absent == 2)
|
|
||||||
ret = ide_other->tf->cylinder & 0xff;
|
|
||||||
else
|
else
|
||||||
ret = ide->tf->cylinder & 0xff;
|
ret = ide->tf->cylinder & 0xff;
|
||||||
|
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
|
||||||
|
ide_log("Cylinder low @ board %i, channel %i: ide->type = %i, "
|
||||||
|
"ret = %02X\n", ide->board, ide->channel, ide->type, ret);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x5: /* Cylinder high */
|
case 0x5: /* Cylinder high */
|
||||||
if (absent == 1)
|
if (ide->type == IDE_NONE)
|
||||||
ret = 0x7f;
|
ret = 0x7f;
|
||||||
else if (absent == 2)
|
|
||||||
ret = ide_other->tf->cylinder >> 8;
|
|
||||||
else
|
else
|
||||||
ret = ide->tf->cylinder >> 8;
|
ret = ide->tf->cylinder >> 8;
|
||||||
|
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
|
||||||
|
pclog("Cylinder high @ board %i, channel %i: ide->type = %i, "
|
||||||
|
"ret = %02X\n", ide->board, ide->channel, ide->type, ret);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x6: /* Drive/Head */
|
case 0x6: /* Drive/Head */
|
||||||
if (absent == 1)
|
if (ide->type == IDE_NONE)
|
||||||
ret = 0x7f;
|
ret = 0x7f;
|
||||||
else
|
else
|
||||||
ret = (uint8_t) (ide->head | ((ch & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0);
|
ret = ide->tf->drvsel | ((ch & 1) ? 0xb0 : 0xa0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is
|
/* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is
|
||||||
@@ -1967,7 +2027,7 @@ ide_readw(uint16_t addr, void *priv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IDE_MORE_SPECIFIC_LOGS
|
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
|
||||||
ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret);
|
ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret);
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2002,7 +2062,7 @@ ide_readl(uint16_t addr, void *priv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IDE_MORE_SPECIFIC_LOGS
|
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
|
||||||
ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret);
|
ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret);
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2060,13 +2120,13 @@ ide_callback(void *priv)
|
|||||||
ide_log("ide_callback(%i): %02X\n", ide->channel, ide->command);
|
ide_log("ide_callback(%i): %02X\n", ide->channel, ide->command);
|
||||||
|
|
||||||
switch (ide->command) {
|
switch (ide->command) {
|
||||||
case WIN_SEEK ... 0x7F:
|
case WIN_SEEK ... 0x7f:
|
||||||
chk_chs = !ide->lba;
|
chk_chs = !ide->tf->lba;
|
||||||
if (ide->type == IDE_ATAPI)
|
if (ide->type == IDE_ATAPI)
|
||||||
atapi_error_no_ready(ide);
|
atapi_error_no_ready(ide);
|
||||||
else {
|
else {
|
||||||
if (chk_chs && ((ide->tf->cylinder >= ide->tracks) || (ide->head >= ide->hpc) ||
|
if (chk_chs && ((ide->tf->cylinder >= ide->tracks) || (ide->tf->head >= ide->hpc) ||
|
||||||
!ide->sector || (ide->sector > ide->spt)))
|
!ide->tf->sector || (ide->tf->sector > ide->spt)))
|
||||||
err = IDNF_ERR;
|
err = IDNF_ERR;
|
||||||
else {
|
else {
|
||||||
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
||||||
@@ -2075,7 +2135,7 @@ ide_callback(void *priv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WIN_RECAL ... 0x1F:
|
case WIN_RECAL ... 0x1f:
|
||||||
if (ide->type == IDE_ATAPI)
|
if (ide->type == IDE_ATAPI)
|
||||||
atapi_error_no_ready(ide);
|
atapi_error_no_ready(ide);
|
||||||
else {
|
else {
|
||||||
@@ -2091,7 +2151,7 @@ ide_callback(void *priv)
|
|||||||
ide->tf->error = 1; /*Device passed*/
|
ide->tf->error = 1; /*Device passed*/
|
||||||
|
|
||||||
ide->tf->secount = 1;
|
ide->tf->secount = 1;
|
||||||
ide->sector = 1;
|
ide->tf->sector = 1;
|
||||||
|
|
||||||
ide_set_signature(ide);
|
ide_set_signature(ide);
|
||||||
|
|
||||||
@@ -2129,7 +2189,7 @@ ide_callback(void *priv)
|
|||||||
if (ide->type == IDE_ATAPI) {
|
if (ide->type == IDE_ATAPI) {
|
||||||
ide_set_signature(ide);
|
ide_set_signature(ide);
|
||||||
err = ABRT_ERR;
|
err = ABRT_ERR;
|
||||||
} else if (!ide->lba && (ide->cfg_spt == 0))
|
} else if (!ide->tf->lba && (ide->cfg_spt == 0))
|
||||||
err = IDNF_ERR;
|
err = IDNF_ERR;
|
||||||
else {
|
else {
|
||||||
if (ide->do_initial_read) {
|
if (ide->do_initial_read) {
|
||||||
@@ -2157,7 +2217,7 @@ ide_callback(void *priv)
|
|||||||
if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) {
|
if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) {
|
||||||
ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel);
|
ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel);
|
||||||
err = ABRT_ERR;
|
err = ABRT_ERR;
|
||||||
} else if (!ide->lba && (ide->cfg_spt == 0)) {
|
} else if (!ide->tf->lba && (ide->cfg_spt == 0)) {
|
||||||
ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel);
|
ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel);
|
||||||
err = IDNF_ERR;
|
err = IDNF_ERR;
|
||||||
} else {
|
} else {
|
||||||
@@ -2207,7 +2267,7 @@ ide_callback(void *priv)
|
|||||||
mand error. */
|
mand error. */
|
||||||
if ((ide->type == IDE_ATAPI) || !ide->blocksize)
|
if ((ide->type == IDE_ATAPI) || !ide->blocksize)
|
||||||
err = ABRT_ERR;
|
err = ABRT_ERR;
|
||||||
else if (!ide->lba && (ide->cfg_spt == 0))
|
else if (!ide->tf->lba && (ide->cfg_spt == 0))
|
||||||
err = IDNF_ERR;
|
err = IDNF_ERR;
|
||||||
else {
|
else {
|
||||||
if (ide->do_initial_read) {
|
if (ide->do_initial_read) {
|
||||||
@@ -2235,7 +2295,7 @@ ide_callback(void *priv)
|
|||||||
case WIN_WRITE_NORETRY:
|
case WIN_WRITE_NORETRY:
|
||||||
if (ide->type == IDE_ATAPI)
|
if (ide->type == IDE_ATAPI)
|
||||||
err = ABRT_ERR;
|
err = ABRT_ERR;
|
||||||
else if (!ide->lba && (ide->cfg_spt == 0))
|
else if (!ide->tf->lba && (ide->cfg_spt == 0))
|
||||||
err = IDNF_ERR;
|
err = IDNF_ERR;
|
||||||
else {
|
else {
|
||||||
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
|
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
|
||||||
@@ -2258,7 +2318,7 @@ ide_callback(void *priv)
|
|||||||
if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) {
|
if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) {
|
||||||
ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel);
|
ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel);
|
||||||
err = ABRT_ERR;
|
err = ABRT_ERR;
|
||||||
} else if (!ide->lba && (ide->cfg_spt == 0)) {
|
} else if (!ide->tf->lba && (ide->cfg_spt == 0)) {
|
||||||
ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel);
|
ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel);
|
||||||
err = IDNF_ERR;
|
err = IDNF_ERR;
|
||||||
} else {
|
} else {
|
||||||
@@ -2307,7 +2367,7 @@ ide_callback(void *priv)
|
|||||||
mand error. */
|
mand error. */
|
||||||
if ((ide->type == IDE_ATAPI) || !ide->blocksize)
|
if ((ide->type == IDE_ATAPI) || !ide->blocksize)
|
||||||
err = ABRT_ERR;
|
err = ABRT_ERR;
|
||||||
else if (!ide->lba && (ide->cfg_spt == 0))
|
else if (!ide->tf->lba && (ide->cfg_spt == 0))
|
||||||
err = IDNF_ERR;
|
err = IDNF_ERR;
|
||||||
else {
|
else {
|
||||||
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
|
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
|
||||||
@@ -2332,7 +2392,7 @@ ide_callback(void *priv)
|
|||||||
case WIN_VERIFY_ONCE:
|
case WIN_VERIFY_ONCE:
|
||||||
if (ide->type == IDE_ATAPI)
|
if (ide->type == IDE_ATAPI)
|
||||||
err = ABRT_ERR;
|
err = ABRT_ERR;
|
||||||
else if (!ide->lba && (ide->cfg_spt == 0))
|
else if (!ide->tf->lba && (ide->cfg_spt == 0))
|
||||||
err = IDNF_ERR;
|
err = IDNF_ERR;
|
||||||
else {
|
else {
|
||||||
ide->tf->pos = 0;
|
ide->tf->pos = 0;
|
||||||
@@ -2345,7 +2405,7 @@ ide_callback(void *priv)
|
|||||||
case WIN_FORMAT:
|
case WIN_FORMAT:
|
||||||
if (ide->type == IDE_ATAPI)
|
if (ide->type == IDE_ATAPI)
|
||||||
err = ABRT_ERR;
|
err = ABRT_ERR;
|
||||||
else if (!ide->lba && (ide->cfg_spt == 0))
|
else if (!ide->tf->lba && (ide->cfg_spt == 0))
|
||||||
err = IDNF_ERR;
|
err = IDNF_ERR;
|
||||||
else {
|
else {
|
||||||
hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->tf->secount);
|
hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->tf->secount);
|
||||||
@@ -2364,7 +2424,7 @@ ide_callback(void *priv)
|
|||||||
if (ide->cfg_spt == 0) {
|
if (ide->cfg_spt == 0) {
|
||||||
/* Only accept after RESET or DIAG. */
|
/* Only accept after RESET or DIAG. */
|
||||||
ide->cfg_spt = ide->tf->secount;
|
ide->cfg_spt = ide->tf->secount;
|
||||||
ide->cfg_hpc = ide->head + 1;
|
ide->cfg_hpc = ide->tf->head + 1;
|
||||||
}
|
}
|
||||||
ide->command = 0x00;
|
ide->command = 0x00;
|
||||||
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
||||||
@@ -2863,8 +2923,14 @@ ide_drive_reset(int d)
|
|||||||
{
|
{
|
||||||
ide_log("Resetting IDE drive %i...\n", d);
|
ide_log("Resetting IDE drive %i...\n", d);
|
||||||
|
|
||||||
|
if ((d & 1) && (ide_drives[d]->type == IDE_NONE) && (ide_drives[d ^ 1]->type != IDE_NONE)) {
|
||||||
|
ide_drives[d]->type = ide_drives[d ^ 1]->type | IDE_SHADOW;
|
||||||
|
free(ide_drives[d]->tf);
|
||||||
|
ide_drives[d]->tf = ide_drives[d ^ 1]->tf;
|
||||||
|
} else
|
||||||
|
ide_drives[d]->tf->atastat = DRDY_STAT | DSC_STAT;
|
||||||
|
|
||||||
ide_drives[d]->channel = d;
|
ide_drives[d]->channel = d;
|
||||||
ide_drives[d]->tf->atastat = DRDY_STAT | DSC_STAT;
|
|
||||||
ide_drives[d]->service = 0;
|
ide_drives[d]->service = 0;
|
||||||
ide_drives[d]->board = d >> 1;
|
ide_drives[d]->board = d >> 1;
|
||||||
ide_drives[d]->selected = !(d & 1);
|
ide_drives[d]->selected = !(d & 1);
|
||||||
|
@@ -36,9 +36,13 @@
|
|||||||
#define HDC_QUATERNARY_IRQ 10
|
#define HDC_QUATERNARY_IRQ 10
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
IDE_NONE = 0,
|
IDE_NONE = 0, /* Absent master or both. */
|
||||||
IDE_HDD,
|
IDE_HDD, /* Hard disk. */
|
||||||
IDE_ATAPI
|
IDE_ATAPI, /* ATAPI device. */
|
||||||
|
IDE_RESERVED, /* Reserved, do not use. */
|
||||||
|
IDE_SHADOW, /* Shadow flag, do not assign on is own. */
|
||||||
|
IDE_HDD_SHADOW, /* Shadow of a hard disk. */
|
||||||
|
IDE_ATAPI_SHADOW /* Shadow of an ATAPI device. */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ide_tf_s {
|
typedef struct ide_tf_s {
|
||||||
@@ -59,28 +63,26 @@ typedef struct ide_tf_s {
|
|||||||
uint8_t status;
|
uint8_t status;
|
||||||
};
|
};
|
||||||
uint8_t error;
|
uint8_t error;
|
||||||
uint16_t pad;
|
uint8_t sector;
|
||||||
|
union {
|
||||||
|
uint8_t drvsel;
|
||||||
|
struct {
|
||||||
|
uint8_t head :4;
|
||||||
|
uint8_t pad :2;
|
||||||
|
uint8_t lba :1;
|
||||||
|
uint8_t pad0 :1;
|
||||||
|
};
|
||||||
|
};
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
} ide_tf_t;
|
} ide_tf_t;
|
||||||
|
|
||||||
#ifdef _TIMER_H_
|
#ifdef _TIMER_H_
|
||||||
typedef struct ide_s {
|
typedef struct ide_s {
|
||||||
#ifdef ANCIENT_CODE
|
|
||||||
/* Task file. */
|
|
||||||
uint8_t cylprecomp;
|
|
||||||
uint8_t secount;
|
|
||||||
uint16_t cylinder;
|
|
||||||
uint8_t atastat;
|
|
||||||
uint8_t error;
|
|
||||||
uint16_t pad;
|
|
||||||
uint32_t pos;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The rest. */
|
/* The rest. */
|
||||||
uint8_t selected;
|
uint8_t selected;
|
||||||
uint8_t command;
|
uint8_t command;
|
||||||
uint8_t head;
|
uint8_t head;
|
||||||
uint8_t sector;
|
uint8_t pad;
|
||||||
int type;
|
int type;
|
||||||
int board;
|
int board;
|
||||||
int irqstat;
|
int irqstat;
|
||||||
@@ -90,7 +92,6 @@ typedef struct ide_s {
|
|||||||
int hdd_num;
|
int hdd_num;
|
||||||
int channel;
|
int channel;
|
||||||
int sector_pos;
|
int sector_pos;
|
||||||
int lba;
|
|
||||||
int reset;
|
int reset;
|
||||||
int mdma_mode;
|
int mdma_mode;
|
||||||
int do_initial_read;
|
int do_initial_read;
|
||||||
|
Reference in New Issue
Block a user