2017-05-30 03:38:38 +02:00
|
|
|
/*
|
|
|
|
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
|
|
|
* running old operating systems and software designed for IBM
|
|
|
|
|
* PC systems and compatibles from 1981 through fairly recent
|
|
|
|
|
* system designs based on the PCI bus.
|
|
|
|
|
*
|
|
|
|
|
* This file is part of the 86Box distribution.
|
|
|
|
|
*
|
|
|
|
|
* Implementation of the IDE emulation for hard disks and ATAPI
|
|
|
|
|
* CD-ROM devices.
|
|
|
|
|
*
|
2018-03-02 21:58:42 +01:00
|
|
|
* Version: @(#)hdc_ide.c 1.0.30 2018/03/02
|
2017-05-30 03:38:38 +02:00
|
|
|
*
|
2017-06-04 02:11:19 -04:00
|
|
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
2017-05-30 03:38:38 +02:00
|
|
|
* Miran Grca, <mgrca8@gmail.com>
|
2017-10-10 03:07:29 -04:00
|
|
|
*
|
2018-01-01 02:57:39 +01:00
|
|
|
* Copyright 2008-2018 Sarah Walker.
|
2018-01-26 22:17:09 +01:00
|
|
|
* Copyright 2016-2018 Miran Grca.
|
2017-05-30 03:38:38 +02:00
|
|
|
*/
|
2017-10-12 14:25:17 -04:00
|
|
|
#define __USE_LARGEFILE64
|
|
|
|
|
#define _LARGEFILE_SOURCE
|
|
|
|
|
#define _LARGEFILE64_SOURCE
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <stdio.h>
|
2016-06-26 00:34:39 +02:00
|
|
|
#include <stdint.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <string.h>
|
2017-06-16 14:09:40 -04:00
|
|
|
#include <stdarg.h>
|
2017-10-26 20:37:39 +02:00
|
|
|
#include <inttypes.h>
|
2017-05-05 22:36:10 +02:00
|
|
|
#include <wchar.h>
|
2017-12-10 02:53:10 -05:00
|
|
|
#define HAVE_STDARG_H
|
2017-08-27 00:58:44 +02:00
|
|
|
#include "../86box.h"
|
2017-11-05 01:57:04 -05:00
|
|
|
#include "../cpu/cpu.h"
|
2017-11-02 02:28:00 -05:00
|
|
|
#include "../machine/machine.h"
|
2017-08-27 00:58:44 +02:00
|
|
|
#include "../io.h"
|
|
|
|
|
#include "../pic.h"
|
2017-08-28 06:58:51 +02:00
|
|
|
#include "../pci.h"
|
2017-08-27 00:58:44 +02:00
|
|
|
#include "../timer.h"
|
2017-09-30 16:56:38 -04:00
|
|
|
#include "../device.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../cdrom/cdrom.h"
|
2017-08-27 04:33:47 +01:00
|
|
|
#include "../scsi/scsi.h"
|
2018-01-26 22:17:09 +01:00
|
|
|
#include "../zip.h"
|
2017-10-27 04:54:45 -04:00
|
|
|
#include "../plat.h"
|
2017-10-10 03:07:29 -04:00
|
|
|
#include "../ui.h"
|
2017-09-30 16:56:38 -04:00
|
|
|
#include "hdc.h"
|
|
|
|
|
#include "hdc_ide.h"
|
2017-10-01 16:29:15 -04:00
|
|
|
#include "hdd.h"
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-09-04 01:52:29 -04:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
/* Bits of 'atastat' */
|
|
|
|
|
#define ERR_STAT 0x01
|
|
|
|
|
#define DRQ_STAT 0x08 /* Data request */
|
|
|
|
|
#define DSC_STAT 0x10
|
|
|
|
|
#define SERVICE_STAT 0x10
|
|
|
|
|
#define READY_STAT 0x40
|
|
|
|
|
#define BUSY_STAT 0x80
|
|
|
|
|
|
|
|
|
|
/* Bits of 'error' */
|
|
|
|
|
#define ABRT_ERR 0x04 /* Command aborted */
|
|
|
|
|
#define MCR_ERR 0x08 /* Media change request */
|
|
|
|
|
|
|
|
|
|
/* ATA Commands */
|
2016-08-10 01:14:22 +02:00
|
|
|
#define WIN_NOP 0x00
|
2016-06-26 00:34:39 +02:00
|
|
|
#define WIN_SRST 0x08 /* ATAPI Device Reset */
|
|
|
|
|
#define WIN_RECAL 0x10
|
|
|
|
|
#define WIN_RESTORE WIN_RECAL
|
|
|
|
|
#define WIN_READ 0x20 /* 28-Bit Read */
|
|
|
|
|
#define WIN_READ_NORETRY 0x21 /* 28-Bit Read - no retry*/
|
|
|
|
|
#define WIN_WRITE 0x30 /* 28-Bit Write */
|
|
|
|
|
#define WIN_WRITE_NORETRY 0x31 /* 28-Bit Write */
|
|
|
|
|
#define WIN_VERIFY 0x40 /* 28-Bit Verify */
|
2017-05-05 01:49:42 +02:00
|
|
|
#define WIN_VERIFY_ONCE 0x41 /* Added by OBattler - deprected older ATA command, according to the specification I found, it is identical to 0x40 */
|
2016-06-26 00:34:39 +02:00
|
|
|
#define WIN_FORMAT 0x50
|
|
|
|
|
#define WIN_SEEK 0x70
|
|
|
|
|
#define WIN_DRIVE_DIAGNOSTICS 0x90 /* Execute Drive Diagnostics */
|
|
|
|
|
#define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */
|
|
|
|
|
#define WIN_PACKETCMD 0xA0 /* Send a packet command. */
|
|
|
|
|
#define WIN_PIDENTIFY 0xA1 /* Identify ATAPI device */
|
|
|
|
|
#define WIN_READ_MULTIPLE 0xC4
|
|
|
|
|
#define WIN_WRITE_MULTIPLE 0xC5
|
|
|
|
|
#define WIN_SET_MULTIPLE_MODE 0xC6
|
|
|
|
|
#define WIN_READ_DMA 0xC8
|
2017-10-24 04:15:05 +02:00
|
|
|
#define WIN_READ_DMA_ALT 0xC9
|
2016-06-26 00:34:39 +02:00
|
|
|
#define WIN_WRITE_DMA 0xCA
|
2017-10-24 04:15:05 +02:00
|
|
|
#define WIN_WRITE_DMA_ALT 0xCB
|
2016-08-10 00:46:56 +02:00
|
|
|
#define WIN_STANDBYNOW1 0xE0
|
2017-01-17 19:41:42 +01:00
|
|
|
#define WIN_IDLENOW1 0xE1
|
2016-06-26 00:34:39 +02:00
|
|
|
#define WIN_SETIDLE1 0xE3
|
2016-08-10 00:46:56 +02:00
|
|
|
#define WIN_CHECKPOWERMODE1 0xE5
|
2017-05-05 01:49:42 +02:00
|
|
|
#define WIN_SLEEP1 0xE6
|
2016-06-26 00:34:39 +02:00
|
|
|
#define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */
|
2016-08-10 00:46:56 +02:00
|
|
|
#define WIN_SET_FEATURES 0xEF
|
|
|
|
|
#define WIN_READ_NATIVE_MAX 0xF8
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
IDE_NONE = 0,
|
|
|
|
|
IDE_HDD,
|
2018-01-26 22:17:09 +01:00
|
|
|
IDE_CDROM,
|
|
|
|
|
IDE_ZIP
|
2016-06-26 00:34:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2017-05-27 03:53:32 +02:00
|
|
|
IDE ide_drives[IDE_NUM + XTIDE_NUM];
|
2016-06-26 00:34:39 +02:00
|
|
|
IDE *ext_ide;
|
2017-01-16 01:49:19 +01:00
|
|
|
int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length);
|
|
|
|
|
int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length);
|
2016-06-26 00:34:39 +02:00
|
|
|
void (*ide_bus_master_set_irq)(int channel);
|
2017-10-09 01:48:36 +02:00
|
|
|
int64_t idecallback[5] = {0LL, 0LL, 0LL, 0LL, 0LL};
|
2017-05-27 03:53:32 +02:00
|
|
|
int cur_ide[5];
|
2018-02-14 13:52:19 +01:00
|
|
|
int ide_init_ch[2] = {0, 0};
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-10-01 16:29:15 -04:00
|
|
|
|
2017-10-16 06:19:18 +02:00
|
|
|
#ifdef ENABLE_IDE_LOG
|
2017-10-26 20:37:39 +02:00
|
|
|
int ide_do_log = ENABLE_IDE_LOG;
|
2017-10-16 06:19:18 +02:00
|
|
|
#endif
|
2016-11-12 15:06:38 +01:00
|
|
|
|
2017-11-24 02:23:00 -05:00
|
|
|
|
2017-12-10 02:53:10 -05:00
|
|
|
static void ide_log(const char *fmt, ...)
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
2017-01-21 17:52:27 +01:00
|
|
|
#ifdef ENABLE_IDE_LOG
|
2017-12-05 23:35:35 +01:00
|
|
|
va_list ap;
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
if (ide_do_log)
|
|
|
|
|
{
|
2017-12-10 02:53:10 -05:00
|
|
|
va_start(ap, fmt);
|
|
|
|
|
pclog_ex(fmt, ap);
|
2017-11-24 02:23:00 -05:00
|
|
|
va_end(ap);
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2017-01-21 17:52:27 +01:00
|
|
|
#endif
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2016-11-12 15:06:38 +01:00
|
|
|
|
2017-11-24 02:23:00 -05:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
uint8_t getstat(IDE *ide) { return ide->atastat; }
|
|
|
|
|
|
2017-11-24 02:23:00 -05:00
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
int ide_drive_is_cdrom(IDE *ide)
|
|
|
|
|
{
|
2017-06-01 22:26:56 +02:00
|
|
|
if (ide->channel >= 8)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
if (atapi_cdrom_drives[ide->channel] >= CDROM_NUM)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-05-27 03:53:32 +02:00
|
|
|
if ((cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
int ide_drive_is_zip(IDE *ide)
|
|
|
|
|
{
|
|
|
|
|
if (ide->channel >= 8)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (atapi_zip_drives[ide->channel] >= ZIP_NUM)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((zip_drives[atapi_zip_drives[ide->channel]].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[atapi_zip_drives[ide->channel]].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA))
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-27 03:53:32 +02:00
|
|
|
int ide_enable[5] = { 1, 1, 0, 0, 1 };
|
2017-06-01 22:26:56 +02:00
|
|
|
int ide_irq[5] = { 14, 15, 10, 11, 0 };
|
2016-12-28 23:34:00 +01:00
|
|
|
|
2017-01-20 23:53:19 +01:00
|
|
|
void ide_irq_raise(IDE *ide)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-10-16 06:19:18 +02:00
|
|
|
/* ide_log("Attempting to raise IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); */
|
2017-09-04 05:15:12 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
if ((ide->board > 3) || ide->irqstat)
|
|
|
|
|
{
|
2017-06-01 22:26:56 +02:00
|
|
|
ide->irqstat=1;
|
|
|
|
|
ide->service=1;
|
|
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 18:42:20 +01:00
|
|
|
ide_log("Raising IRQ %i (board %i)\n", ide_irq[ide->board], ide->board);
|
2016-12-29 20:40:24 +01:00
|
|
|
|
|
|
|
|
if (!(ide->fdisk&2))
|
|
|
|
|
{
|
2017-10-16 06:19:18 +02:00
|
|
|
if (pci_use_mirq(0) && (ide->board == 1))
|
2017-08-28 06:58:51 +02:00
|
|
|
{
|
2017-10-16 06:19:18 +02:00
|
|
|
pci_set_mirq(0);
|
2017-08-28 06:58:51 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
picint(1 << ide_irq[ide->board]);
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
|
|
|
|
|
if (ide->board < 2)
|
|
|
|
|
{
|
|
|
|
|
if (ide_bus_master_set_irq)
|
|
|
|
|
{
|
2017-09-04 05:15:12 +02:00
|
|
|
ide_bus_master_set_irq(ide->board | 0x40);
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
ide->irqstat=1;
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->service=1;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
void ide_irq_lower(IDE *ide)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2016-12-29 20:40:24 +01:00
|
|
|
if ((ide->board > 3) || !(ide->irqstat))
|
|
|
|
|
{
|
2017-06-01 22:26:56 +02:00
|
|
|
ide->irqstat=0;
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 18:42:20 +01:00
|
|
|
ide_log("Lowering IRQ %i (board %i)\n", ide_irq[ide->board], ide->board);
|
2016-12-29 20:40:24 +01:00
|
|
|
|
2017-10-16 06:19:18 +02:00
|
|
|
if (pci_use_mirq(0) && (ide->board == 1))
|
2017-08-28 16:53:53 +02:00
|
|
|
{
|
2017-10-16 06:19:18 +02:00
|
|
|
pci_clear_mirq(0);
|
2017-08-28 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
picintc(1 << ide_irq[ide->board]);
|
|
|
|
|
}
|
2017-09-04 05:15:12 +02:00
|
|
|
|
|
|
|
|
if (ide_bus_master_set_irq)
|
|
|
|
|
{
|
|
|
|
|
ide_bus_master_set_irq(ide->board);
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
ide->irqstat=0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Copy a string into a buffer, padding with spaces, and placing characters as
|
|
|
|
|
* if they were packed into 16-bit values, stored little-endian.
|
|
|
|
|
*
|
|
|
|
|
* @param str Destination buffer
|
|
|
|
|
* @param src Source string
|
|
|
|
|
* @param len Length of destination buffer to fill in. Strings shorter than
|
|
|
|
|
* this length will be padded with spaces.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
ide_padstr(char *str, const char *src, int len)
|
|
|
|
|
{
|
|
|
|
|
int i, v;
|
|
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
{
|
|
|
|
|
if (*src != '\0')
|
|
|
|
|
{
|
2016-06-26 00:34:39 +02:00
|
|
|
v = *src++;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-06-26 00:34:39 +02:00
|
|
|
v = ' ';
|
|
|
|
|
}
|
|
|
|
|
str[i ^ 1] = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Copy a string into a buffer, padding with spaces. Does not add string
|
|
|
|
|
* terminator.
|
|
|
|
|
*
|
|
|
|
|
* @param buf Destination buffer
|
|
|
|
|
* @param buf_size Size of destination buffer to fill in. Strings shorter than
|
|
|
|
|
* this length will be padded with spaces.
|
|
|
|
|
* @param src Source string
|
|
|
|
|
*/
|
2017-01-16 01:49:19 +01:00
|
|
|
void ide_padstr8(uint8_t *buf, int buf_size, const char *src)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
for (i = 0; i < buf_size; i++)
|
|
|
|
|
{
|
|
|
|
|
if (*src != '\0')
|
|
|
|
|
{
|
2016-06-26 00:34:39 +02:00
|
|
|
buf[i] = *src++;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-06-26 00:34:39 +02:00
|
|
|
buf[i] = ' ';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fill in ide->buffer with the output of the "IDENTIFY DEVICE" command
|
|
|
|
|
*/
|
|
|
|
|
static void ide_identify(IDE *ide)
|
|
|
|
|
{
|
2017-10-24 04:15:05 +02:00
|
|
|
uint32_t d;
|
2017-05-27 03:53:32 +02:00
|
|
|
char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 };
|
2017-10-24 04:15:05 +02:00
|
|
|
|
|
|
|
|
uint64_t d_hpc, d_spt, d_tracks;
|
2017-09-30 16:56:38 -04:00
|
|
|
uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
device_identify[6] = (ide->hdd_num / 10) + 0x30;
|
|
|
|
|
device_identify[7] = (ide->hdd_num % 10) + 0x30;
|
2017-01-16 01:49:19 +01:00
|
|
|
ide_log("IDE Identify: %s\n", device_identify);
|
2016-12-23 03:16:24 +01:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
memset(ide->buffer, 0, 512);
|
2017-10-24 04:15:05 +02:00
|
|
|
d_spt = ide->spt;
|
|
|
|
|
if (ide->hpc <= 16) {
|
|
|
|
|
/* HPC <= 16, report as needed. */
|
|
|
|
|
d_tracks = ide->tracks;
|
|
|
|
|
d_hpc = ide->hpc;
|
|
|
|
|
} else {
|
|
|
|
|
/* HPC > 16, convert to 16 HPC. */
|
|
|
|
|
d_hpc = 16;
|
|
|
|
|
d_tracks = (ide->tracks * ide->hpc) / 16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Specify default CHS translation */
|
|
|
|
|
if (full_size <= 16514064) {
|
|
|
|
|
ide->buffer[1] = d_tracks; /* Tracks in default CHS translation. */
|
|
|
|
|
ide->buffer[3] = d_hpc; /* Heads in default CHS translation. */
|
|
|
|
|
ide->buffer[6] = d_spt; /* Heads in default CHS translation. */
|
2017-10-26 20:37:39 +02:00
|
|
|
} else {
|
|
|
|
|
ide->buffer[1] = 16383; /* Tracks in default CHS translation. */
|
|
|
|
|
ide->buffer[3] = 16; /* Heads in default CHS translation. */
|
|
|
|
|
ide->buffer[6] = 63; /* Heads in default CHS translation. */
|
2017-10-24 04:15:05 +02:00
|
|
|
}
|
|
|
|
|
ide_log("Default CHS translation: %i, %i, %i\n", ide->buffer[1], ide->buffer[3], ide->buffer[6]);
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
|
2017-06-04 02:11:19 -04:00
|
|
|
ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */
|
2017-01-16 01:49:19 +01:00
|
|
|
ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */
|
2016-11-12 15:06:38 +01:00
|
|
|
ide->buffer[20] = 3; /*Buffer type*/
|
|
|
|
|
ide->buffer[21] = 512; /*Buffer size*/
|
|
|
|
|
ide->buffer[48] = 1; /*Dword transfers supported*/
|
2017-10-24 04:15:05 +02:00
|
|
|
if (PCI && (ide->board < 2) && (hdd[ide->hdd_num].bus == HDD_BUS_IDE_PIO_AND_DMA)) {
|
|
|
|
|
ide->buffer[47] = 32 | 0x8000; /*Max sectors on multiple transfer command*/
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->buffer[49] = (1 << 8); /* LBA and DMA supported */
|
2017-10-24 04:15:05 +02:00
|
|
|
} else {
|
|
|
|
|
ide->buffer[47] = 16 | 0x8000; /*Max sectors on multiple transfer command*/
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->buffer[49] = 0;
|
|
|
|
|
}
|
2017-10-24 04:15:05 +02:00
|
|
|
if ((ide->tracks >= 1024) || (ide->hpc > 16) || (ide->spt > 63))
|
2016-12-23 03:16:24 +01:00
|
|
|
{
|
|
|
|
|
ide->buffer[49] |= (1 << 9);
|
2017-10-26 20:37:39 +02:00
|
|
|
ide_log("LBA supported\n");
|
2016-12-23 03:16:24 +01:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
ide->buffer[50] = 0x4000; /* Capabilities */
|
|
|
|
|
ide->buffer[51] = 2 << 8; /*PIO timing mode*/
|
2017-10-24 04:15:05 +02:00
|
|
|
|
2017-02-15 18:19:00 +01:00
|
|
|
if (ide->buffer[49] & (1 << 9))
|
|
|
|
|
{
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[60] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */
|
|
|
|
|
ide->buffer[61] = (full_size >> 16) & 0x0FFF;
|
2017-10-26 20:37:39 +02:00
|
|
|
ide_log("Full size: %" PRIu64 "\n", full_size);
|
2017-10-24 04:15:05 +02:00
|
|
|
|
|
|
|
|
ide->buffer[53] |= 1;
|
|
|
|
|
|
2017-10-26 20:37:39 +02:00
|
|
|
if (ide->specify_success) {
|
|
|
|
|
ide->buffer[54] = (full_size / ide->t_hpc) / ide->t_spt;
|
|
|
|
|
ide->buffer[55] = ide->t_hpc;
|
|
|
|
|
ide->buffer[56] = ide->t_spt;
|
|
|
|
|
} else {
|
|
|
|
|
if (full_size <= 16514064) {
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[54] = d_tracks;
|
|
|
|
|
ide->buffer[55] = d_hpc;
|
|
|
|
|
ide->buffer[56] = d_spt;
|
2017-10-26 20:37:39 +02:00
|
|
|
} else {
|
|
|
|
|
ide->buffer[54] = 16383;
|
|
|
|
|
ide->buffer[55] = 16;
|
|
|
|
|
ide->buffer[56] = 63;
|
2017-10-24 04:15:05 +02:00
|
|
|
}
|
2017-10-26 20:37:39 +02:00
|
|
|
}
|
2017-10-24 04:15:05 +02:00
|
|
|
|
2017-10-26 20:37:39 +02:00
|
|
|
full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * ((uint64_t) ide->buffer[56]);
|
2017-10-24 04:15:05 +02:00
|
|
|
|
2017-10-26 20:37:39 +02:00
|
|
|
ide->buffer[57] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */
|
|
|
|
|
ide->buffer[58] = (full_size >> 16) & 0x0FFF;
|
|
|
|
|
|
|
|
|
|
ide_log("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]);
|
2017-02-15 18:19:00 +01:00
|
|
|
}
|
2017-10-24 04:15:05 +02:00
|
|
|
|
|
|
|
|
ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0;
|
|
|
|
|
|
2017-10-25 02:17:27 +02:00
|
|
|
if (ide->buffer[49] & (1 << 8))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-05-10 02:46:01 +02:00
|
|
|
ide->buffer[52] = 2 << 8; /*DMA timing mode*/
|
2017-10-25 02:17:27 +02:00
|
|
|
ide->buffer[53] |= 6;
|
2017-05-14 18:37:32 +02:00
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[62] = 7;
|
2017-05-05 01:49:42 +02:00
|
|
|
ide->buffer[63] = 7;
|
2017-10-25 02:17:27 +02:00
|
|
|
ide->buffer[88] = 7;
|
2017-05-14 18:37:32 +02:00
|
|
|
if (ide->mdma_mode != -1)
|
|
|
|
|
{
|
2017-10-24 04:15:05 +02:00
|
|
|
d = (ide->mdma_mode & 0xff);
|
|
|
|
|
d <<= 8;
|
2017-10-26 20:37:39 +02:00
|
|
|
if ((ide->mdma_mode & 0x300) == 0x200)
|
2017-10-25 02:17:27 +02:00
|
|
|
ide->buffer[88] |= d;
|
2017-10-26 20:37:39 +02:00
|
|
|
else if ((ide->mdma_mode & 0x300) == 0x100)
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[63] |= d;
|
|
|
|
|
else
|
|
|
|
|
ide->buffer[62] |= d;
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log(" IDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]);
|
2017-05-14 18:37:32 +02:00
|
|
|
}
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[65] = 120;
|
|
|
|
|
ide->buffer[66] = 120;
|
|
|
|
|
ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/
|
|
|
|
|
ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/
|
|
|
|
|
} else {
|
|
|
|
|
ide->buffer[80] = 0x0e; /*ATA-1 to ATA-3 supported*/
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command
|
|
|
|
|
*/
|
|
|
|
|
static void ide_atapi_identify(IDE *ide)
|
|
|
|
|
{
|
2017-05-27 03:53:32 +02:00
|
|
|
char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 };
|
2017-10-24 04:15:05 +02:00
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
uint8_t cdrom_id;
|
2017-10-24 04:15:05 +02:00
|
|
|
int32_t d;
|
2018-01-26 22:17:09 +01:00
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
memset(ide->buffer, 0, 512);
|
|
|
|
|
cdrom_id = atapi_cdrom_drives[ide->channel];
|
|
|
|
|
|
2017-05-27 03:53:32 +02:00
|
|
|
device_identify[7] = cdrom_id + 0x30;
|
2017-01-16 01:49:19 +01:00
|
|
|
ide_log("ATAPI Identify: %s\n", device_identify);
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */
|
|
|
|
|
ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
|
2017-06-04 02:11:19 -04:00
|
|
|
ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */
|
2017-01-16 01:49:19 +01:00
|
|
|
ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[48] = 1; /*Dword transfers supported*/
|
2016-11-17 20:41:27 +01:00
|
|
|
ide->buffer[49] = 0x200; /* LBA supported */
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[51] = 2 << 8; /*PIO timing mode*/
|
2018-02-27 23:55:28 +01:00
|
|
|
ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2017-05-27 03:53:32 +02:00
|
|
|
if (PCI && (ide->board < 2) && (cdrom_drives[cdrom_id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
ide->buffer[49] |= 0x100; /* DMA supported */
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[52] = 2 << 8; /*DMA timing mode*/
|
2017-10-25 02:17:27 +02:00
|
|
|
ide->buffer[53] = 7;
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[62] = 7;
|
2017-05-05 01:49:42 +02:00
|
|
|
ide->buffer[63] = 7;
|
2017-10-25 02:17:27 +02:00
|
|
|
ide->buffer[88] = 7;
|
2017-10-24 04:15:05 +02:00
|
|
|
if (ide->mdma_mode != -1)
|
|
|
|
|
{
|
|
|
|
|
d = (ide->mdma_mode & 0xff);
|
|
|
|
|
d <<= 8;
|
2017-10-26 20:37:39 +02:00
|
|
|
if ((ide->mdma_mode & 0x300) == 0x200)
|
2017-10-25 02:17:27 +02:00
|
|
|
ide->buffer[88] |= d;
|
2017-10-26 20:37:39 +02:00
|
|
|
else if ((ide->mdma_mode & 0x300) == 0x100)
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->buffer[63] |= d;
|
|
|
|
|
else
|
|
|
|
|
ide->buffer[62] |= d;
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]);
|
2017-10-24 04:15:05 +02:00
|
|
|
}
|
|
|
|
|
ide->buffer[65] = 0xb4;
|
|
|
|
|
ide->buffer[66] = 0xb4;
|
|
|
|
|
ide->buffer[71] = 30;
|
|
|
|
|
ide->buffer[72] = 30;
|
|
|
|
|
ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/
|
|
|
|
|
ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
static void ide_atapi_zip_identify(IDE *ide)
|
|
|
|
|
{
|
|
|
|
|
uint8_t zip_id;
|
|
|
|
|
int32_t d;
|
|
|
|
|
|
|
|
|
|
zip_id = atapi_zip_drives[ide->channel];
|
|
|
|
|
|
|
|
|
|
ide->buffer[0] = 0x8000 | (0<<8) | 0x80 | (2<<5); /* ATAPI device, direct-access device, removable media, accelerated DRQ */
|
|
|
|
|
ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
|
|
|
|
|
if (zip_drives[zip_id].is_250) {
|
|
|
|
|
ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */
|
|
|
|
|
ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */
|
|
|
|
|
} else {
|
|
|
|
|
ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */
|
|
|
|
|
ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */
|
|
|
|
|
}
|
|
|
|
|
ide->buffer[49] = 0x200; /* LBA supported */
|
|
|
|
|
|
|
|
|
|
/* Note by Kotori: Look at this if this is supported by ZIP at all. */
|
|
|
|
|
ide->buffer[48] = 1; /*Dword transfers supported*/
|
|
|
|
|
ide->buffer[51] = 2 << 8; /*PIO timing mode*/
|
|
|
|
|
|
2018-02-27 23:55:28 +01:00
|
|
|
ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (PCI && (ide->board < 2) && (zip_drives[zip_id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA))
|
|
|
|
|
{
|
|
|
|
|
ide->buffer[49] |= 0x100; /* DMA supported */
|
|
|
|
|
ide->buffer[52] = 2 << 8; /*DMA timing mode*/
|
|
|
|
|
ide->buffer[53] = 7;
|
|
|
|
|
ide->buffer[62] = 7;
|
|
|
|
|
ide->buffer[63] = 7;
|
|
|
|
|
ide->buffer[88] = 7;
|
|
|
|
|
if (ide->mdma_mode != -1)
|
|
|
|
|
{
|
|
|
|
|
d = (ide->mdma_mode & 0xff);
|
|
|
|
|
d <<= 8;
|
|
|
|
|
if ((ide->mdma_mode & 0x300) == 0x200)
|
|
|
|
|
ide->buffer[88] |= d;
|
|
|
|
|
else if ((ide->mdma_mode & 0x300) == 0x100)
|
|
|
|
|
ide->buffer[63] |= d;
|
|
|
|
|
else
|
|
|
|
|
ide->buffer[62] |= d;
|
|
|
|
|
ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]);
|
|
|
|
|
}
|
|
|
|
|
ide->buffer[65] = 0xb4;
|
|
|
|
|
ide->buffer[66] = 0xb4;
|
|
|
|
|
ide->buffer[71] = 30;
|
|
|
|
|
ide->buffer[72] = 30;
|
|
|
|
|
ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/
|
|
|
|
|
ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
/*
|
|
|
|
|
* Return the sector offset for the current register values
|
|
|
|
|
*/
|
|
|
|
|
static off64_t ide_get_sector(IDE *ide)
|
|
|
|
|
{
|
|
|
|
|
if (ide->lba)
|
|
|
|
|
{
|
|
|
|
|
return (off64_t)ide->lba_addr + ide->skip512;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-10-24 04:15:05 +02:00
|
|
|
uint32_t heads = ide->t_hpc;
|
|
|
|
|
uint32_t sectors = ide->t_spt;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
return ((((off64_t) ide->cylinder * heads) + ide->head) *
|
|
|
|
|
sectors) + (ide->sector - 1) + ide->skip512;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Move to the next sector using CHS addressing
|
|
|
|
|
*/
|
|
|
|
|
static void ide_next_sector(IDE *ide)
|
|
|
|
|
{
|
|
|
|
|
if (ide->lba)
|
|
|
|
|
{
|
|
|
|
|
ide->lba_addr++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->sector++;
|
2017-10-24 04:15:05 +02:00
|
|
|
if (ide->sector == (ide->t_spt + 1))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2016-06-26 00:34:39 +02:00
|
|
|
ide->sector = 1;
|
|
|
|
|
ide->head++;
|
2017-10-24 04:15:05 +02:00
|
|
|
if (ide->head == ide->t_hpc)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2016-06-26 00:34:39 +02:00
|
|
|
ide->head = 0;
|
|
|
|
|
ide->cylinder++;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-05 22:36:10 +02:00
|
|
|
static void loadhd(IDE *ide, int d, const wchar_t *fn)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
if (! hdd_image_load(d)) {
|
2017-06-16 03:18:59 +02:00
|
|
|
ide->type = IDE_NONE;
|
|
|
|
|
return;
|
2016-09-25 21:39:21 +02:00
|
|
|
}
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
ide->spt = hdd[d].spt;
|
|
|
|
|
ide->hpc = hdd[d].hpc;
|
|
|
|
|
ide->tracks = hdd[d].tracks;
|
2017-06-16 03:18:59 +02:00
|
|
|
ide->type = IDE_HDD;
|
2017-09-30 16:56:38 -04:00
|
|
|
ide->hdd_num = d;
|
2017-06-16 03:18:59 +02:00
|
|
|
ide->hdi = hdd_image_get_type(d);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_set_signature(IDE *ide)
|
|
|
|
|
{
|
2017-02-13 20:21:57 +01:00
|
|
|
uint8_t cdrom_id = atapi_cdrom_drives[ide->channel];
|
2018-01-26 22:17:09 +01:00
|
|
|
uint8_t zip_id = atapi_zip_drives[ide->channel];
|
2016-06-26 00:34:39 +02:00
|
|
|
ide->sector=1;
|
|
|
|
|
ide->head=0;
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip_set_signature(zip_id);
|
|
|
|
|
ide->secount = zip[zip_id].phase;
|
|
|
|
|
ide->cylinder = zip[zip_id].request_length;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom_set_signature(cdrom_id);
|
2017-01-21 17:48:45 +01:00
|
|
|
ide->secount = cdrom[cdrom_id].phase;
|
|
|
|
|
ide->cylinder = cdrom[cdrom_id].request_length;
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->secount=1;
|
|
|
|
|
ide->cylinder=((ide->type == IDE_HDD) ? 0 : 0xFFFF);
|
|
|
|
|
if (ide->type == IDE_HDD)
|
|
|
|
|
{
|
|
|
|
|
ide->drive = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
static int ide_set_features(IDE *ide)
|
2016-08-10 00:46:56 +02:00
|
|
|
{
|
2017-05-14 18:37:32 +02:00
|
|
|
uint8_t features, features_data;
|
|
|
|
|
uint8_t mode, submode;
|
2017-10-24 04:15:05 +02:00
|
|
|
|
|
|
|
|
int bus, dma;
|
|
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
features = ide->cylprecomp;
|
|
|
|
|
features_data = ide->secount;
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide)) {
|
|
|
|
|
bus = zip_drives[atapi_zip_drives[ide->channel]].bus_type;
|
|
|
|
|
dma = (bus == ZIP_BUS_ATAPI_PIO_AND_DMA);
|
|
|
|
|
} else if (ide_drive_is_cdrom(ide)) {
|
2017-10-24 04:15:05 +02:00
|
|
|
bus = cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type;
|
|
|
|
|
dma = (bus == CDROM_BUS_ATAPI_PIO_AND_DMA);
|
|
|
|
|
} else {
|
|
|
|
|
bus = hdd[ide->hdd_num].bus;
|
|
|
|
|
dma = (bus == HDD_BUS_IDE_PIO_AND_DMA);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-01 22:26:56 +02:00
|
|
|
ide_log("Features code %02X\n", features);
|
2016-08-10 00:46:56 +02:00
|
|
|
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %02X: Set features: %02X, %02X\n", ide->channel, features, features_data);
|
2017-10-24 04:15:05 +02:00
|
|
|
|
2017-01-17 19:41:42 +01:00
|
|
|
switch(features)
|
2016-08-10 00:46:56 +02:00
|
|
|
{
|
2017-05-14 18:37:32 +02:00
|
|
|
case 0x03: /* Set transfer mode. */
|
2017-06-01 22:26:56 +02:00
|
|
|
ide_log("Transfer mode %02X\n", features_data >> 3);
|
2017-05-14 18:37:32 +02:00
|
|
|
|
|
|
|
|
mode = (features_data >> 3);
|
|
|
|
|
submode = features_data & 7;
|
|
|
|
|
|
|
|
|
|
switch(mode)
|
2016-08-10 00:46:56 +02:00
|
|
|
{
|
2017-05-14 18:37:32 +02:00
|
|
|
case 0x00: /* PIO default */
|
2017-05-14 18:39:58 +02:00
|
|
|
if (submode != 0)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2017-05-14 18:37:32 +02:00
|
|
|
ide->mdma_mode = -1;
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode);
|
2016-08-10 00:46:56 +02:00
|
|
|
break;
|
2017-05-14 18:37:32 +02:00
|
|
|
|
|
|
|
|
case 0x01: /* PIO mode */
|
2017-05-14 18:39:58 +02:00
|
|
|
if (submode > 2)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2017-05-14 18:37:32 +02:00
|
|
|
ide->mdma_mode = -1;
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %02X: Setting PIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode);
|
2017-05-14 18:37:32 +02:00
|
|
|
break;
|
|
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
case 0x02: /* Singleword DMA mode */
|
|
|
|
|
if (!PCI || !dma || (ide->board >= 2) || (submode > 2))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-05-14 18:41:58 +02:00
|
|
|
return 0;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
2017-05-14 18:37:32 +02:00
|
|
|
ide->mdma_mode = (1 << submode);
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %02X: Setting SDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode);
|
2016-08-10 00:46:56 +02:00
|
|
|
break;
|
2017-10-24 04:15:05 +02:00
|
|
|
|
|
|
|
|
case 0x04: /* Multiword DMA mode */
|
|
|
|
|
if (!PCI || !dma || (ide->board >= 2) || (submode > 2))
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
ide->mdma_mode = (1 << submode) | 0x100;
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %02X: Setting MDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x08: /* Ultra DMA mode */
|
|
|
|
|
if (!PCI || !dma || (ide->board >= 2) || (submode > 2))
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
ide->mdma_mode = (1 << submode) | 0x200;
|
|
|
|
|
ide_log("IDE %02X: Setting UDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode);
|
2017-10-24 04:15:05 +02:00
|
|
|
break;
|
|
|
|
|
|
2016-08-10 00:46:56 +02:00
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2017-10-24 04:15:05 +02:00
|
|
|
|
|
|
|
|
case 0x66: /* Disable reverting to power on defaults. */
|
|
|
|
|
case 0xCC: /* Enable reverting to power on defaults. */
|
|
|
|
|
return 1;
|
|
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
default:
|
|
|
|
|
return 0;
|
2016-08-10 00:46:56 +02:00
|
|
|
}
|
2017-05-14 18:37:32 +02:00
|
|
|
|
2016-08-10 00:46:56 +02:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_set_sector(IDE *ide, int64_t sector_num)
|
|
|
|
|
{
|
|
|
|
|
unsigned int cyl, r;
|
2016-08-10 06:15:52 +02:00
|
|
|
if (ide->lba)
|
2016-08-10 00:46:56 +02:00
|
|
|
{
|
2016-08-10 01:04:08 +02:00
|
|
|
ide->head = (sector_num >> 24);
|
2016-08-10 00:54:09 +02:00
|
|
|
ide->cylinder = (sector_num >> 8);
|
2016-08-10 00:46:56 +02:00
|
|
|
ide->sector = (sector_num);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
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);
|
2016-08-10 00:54:09 +02:00
|
|
|
ide->cylinder = cyl;
|
2017-09-30 16:56:38 -04:00
|
|
|
ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f);
|
|
|
|
|
ide->sector = (r % hdd[ide->hdd_num].spt) + 1;
|
2016-08-10 00:46:56 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
void ide_ter_disable_cond();
|
|
|
|
|
void ide_qua_disable_cond();
|
|
|
|
|
|
2017-10-01 16:29:15 -04:00
|
|
|
|
|
|
|
|
void ide_reset(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-05 01:49:42 +02:00
|
|
|
int c, d;
|
2017-10-01 16:29:15 -04:00
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
build_atapi_cdrom_map();
|
2018-01-26 22:17:09 +01:00
|
|
|
build_atapi_zip_map();
|
2016-12-29 20:40:24 +01:00
|
|
|
|
|
|
|
|
/* Close hard disk image files (if previously open) */
|
2017-09-30 16:56:38 -04:00
|
|
|
for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-16 01:49:19 +01:00
|
|
|
ide_drives[d].channel = d;
|
2016-12-29 20:40:24 +01:00
|
|
|
ide_drives[d].type = IDE_NONE;
|
2017-10-01 16:29:15 -04:00
|
|
|
if (ide_drives[d].hdd_num != -1)
|
|
|
|
|
hdd_image_close(ide_drives[d].hdd_num);
|
2018-01-26 22:17:09 +01:00
|
|
|
if ((d < 8) && ide_drive_is_zip(&ide_drives[d]))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[d]].status = READY_STAT | DSC_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if ((d < 8) && ide_drive_is_cdrom(&ide_drives[d]))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[d]].status = READY_STAT | DSC_STAT;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
ide_drives[d].atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide_drives[d].service = 0;
|
|
|
|
|
ide_drives[d].board = d >> 1;
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[0]=idecallback[1]=0LL;
|
|
|
|
|
idecallback[2]=idecallback[3]=0LL;
|
|
|
|
|
idecallback[4]=0LL;
|
2016-11-12 15:06:38 +01:00
|
|
|
|
2017-10-16 06:19:18 +02:00
|
|
|
ide_log("IDE: loading disks...\n");
|
2017-05-05 01:49:42 +02:00
|
|
|
c = 0;
|
2017-09-30 16:56:38 -04:00
|
|
|
for (d = 0; d < HDD_NUM; d++)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
if (((hdd[d].bus == HDD_BUS_IDE_PIO_ONLY) || (hdd[d].bus == HDD_BUS_IDE_PIO_AND_DMA)) && (hdd[d].ide_channel < IDE_NUM))
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
ide_log("Found IDE hard disk on channel %i\n", hdd[d].ide_channel);
|
|
|
|
|
loadhd(&ide_drives[hdd[d].ide_channel], d, hdd[d].fn);
|
|
|
|
|
if (++c >= (IDE_NUM+XTIDE_NUM)) break;
|
2017-05-27 03:53:32 +02:00
|
|
|
}
|
2017-09-30 16:56:38 -04:00
|
|
|
if ((hdd[d].bus==HDD_BUS_XTIDE) && (hdd[d].xtide_channel < XTIDE_NUM))
|
2017-05-27 03:53:32 +02:00
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
ide_log("Found XT IDE hard disk on channel %i\n", hdd[d].xtide_channel);
|
|
|
|
|
loadhd(&ide_drives[hdd[d].xtide_channel | 8], d, hdd[d].fn);
|
|
|
|
|
if (++c >= (IDE_NUM+XTIDE_NUM)) break;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
2017-10-16 06:19:18 +02:00
|
|
|
ide_log("IDE: done, loaded %d disks.\n", c);
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
for (d = 0; d < IDE_NUM; d++)
|
|
|
|
|
{
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(&ide_drives[d]) && (ide_drives[d].type != IDE_HDD))
|
|
|
|
|
{
|
|
|
|
|
ide_drives[d].type = IDE_ZIP;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(&ide_drives[d]) && (ide_drives[d].type != IDE_HDD))
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-05 01:49:42 +02:00
|
|
|
ide_drives[d].type = IDE_CDROM;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2018-01-26 22:17:09 +01:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
ide_set_signature(&ide_drives[d]);
|
2016-08-10 01:04:08 +02:00
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
ide_drives[d].mdma_mode = -1;
|
2016-12-23 03:16:24 +01:00
|
|
|
ide_drives[d].error = 1;
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-27 03:53:32 +02:00
|
|
|
for (d = 0; d < XTIDE_NUM; d++)
|
|
|
|
|
{
|
|
|
|
|
ide_set_signature(&ide_drives[d | 8]);
|
|
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
ide_drives[d | 8].mdma_mode = -1;
|
2017-05-29 01:18:32 +02:00
|
|
|
ide_drives[d | 8].error = 1;
|
2017-05-27 03:53:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (d = 0; d < 5; d++)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
cur_ide[d] = d << 1;
|
|
|
|
|
}
|
2017-01-17 19:41:42 +01:00
|
|
|
|
|
|
|
|
ide_ter_disable_cond();
|
|
|
|
|
ide_qua_disable_cond();
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
|
|
|
|
|
void ide_reset_hard(void)
|
|
|
|
|
{
|
|
|
|
|
int d;
|
|
|
|
|
|
|
|
|
|
for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++)
|
|
|
|
|
{
|
|
|
|
|
ide_drives[d].t_spt = ide_drives[d].spt;
|
|
|
|
|
ide_drives[d].t_hpc = ide_drives[d].hpc;
|
|
|
|
|
ide_drives[d].specify_success = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ide_reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
int idetimes = 0;
|
|
|
|
|
|
2017-10-26 20:37:39 +02:00
|
|
|
void ide_set_callback(uint8_t channel, int64_t callback)
|
|
|
|
|
{
|
|
|
|
|
IDE *ide = &ide_drives[channel];
|
|
|
|
|
if (callback)
|
|
|
|
|
idecallback[ide->board] += callback;
|
|
|
|
|
else
|
|
|
|
|
idecallback[ide->board] = 0LL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-18 21:51:03 +01:00
|
|
|
void ide_write_data(int ide_board, uint32_t val, int length)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2016-12-29 20:40:24 +01:00
|
|
|
IDE *ide = &ide_drives[cur_ide[ide_board]];
|
2017-01-17 00:01:59 +01:00
|
|
|
|
|
|
|
|
uint8_t *idebufferb = (uint8_t *) ide->buffer;
|
2017-01-18 21:51:03 +01:00
|
|
|
uint16_t *idebufferw = ide->buffer;
|
|
|
|
|
uint32_t *idebufferl = (uint32_t *) ide->buffer;
|
2017-01-04 20:37:31 +01:00
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
if (ide->command == WIN_PACKETCMD)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-18 21:51:03 +01:00
|
|
|
ide->pos = 0;
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-16 01:49:19 +01:00
|
|
|
return;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
zip_write(cur_ide[ide_board], val, length);
|
|
|
|
|
else
|
|
|
|
|
cdrom_write(cur_ide[ide_board], val, length);
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
else
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-18 21:51:03 +01:00
|
|
|
switch(length)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
idebufferb[ide->pos] = val & 0xff;
|
|
|
|
|
ide->pos++;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
idebufferw[ide->pos >> 1] = val & 0xffff;
|
|
|
|
|
ide->pos += 2;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
idebufferl[ide->pos >> 2] = val;
|
|
|
|
|
ide->pos += 4;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-01-17 19:41:42 +01:00
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
if (ide->pos>=512)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-16 01:49:19 +01:00
|
|
|
ide->pos=0;
|
|
|
|
|
ide->atastat = BUSY_STAT;
|
|
|
|
|
timer_process();
|
|
|
|
|
if (ide->command == WIN_WRITE_MULTIPLE)
|
|
|
|
|
{
|
|
|
|
|
callbackide(ide_board);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board]=6LL*IDE_TIME;
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
timer_update_outstanding();
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-01-17 00:01:59 +01:00
|
|
|
void writeidew(int ide_board, uint16_t val)
|
|
|
|
|
{
|
2017-01-18 21:51:03 +01:00
|
|
|
ide_write_data(ide_board, val, 2);
|
2017-01-17 00:01:59 +01:00
|
|
|
}
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
void writeidel(int ide_board, uint32_t val)
|
|
|
|
|
{
|
2017-01-20 23:53:19 +01:00
|
|
|
writeidew(ide_board, val);
|
|
|
|
|
writeidew(ide_board, val >> 16);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void writeide(int ide_board, uint16_t addr, uint8_t val)
|
|
|
|
|
{
|
2016-12-29 20:40:24 +01:00
|
|
|
IDE *ide = &ide_drives[cur_ide[ide_board]];
|
|
|
|
|
IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1];
|
|
|
|
|
|
2017-11-05 01:57:04 -05:00
|
|
|
ide_log("WriteIDE %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc);
|
2016-12-29 20:40:24 +01:00
|
|
|
addr|=0x90;
|
|
|
|
|
addr&=0xFFF7;
|
|
|
|
|
|
|
|
|
|
if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
switch (addr)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
case 0x1F0: /* Data */
|
2017-01-18 21:51:03 +01:00
|
|
|
writeidew(ide_board, val | (val << 8));
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
/* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */
|
|
|
|
|
case 0x1F1: /* Features */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO");
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board]]].features = val;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO");
|
2017-01-16 01:49:19 +01:00
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].features = val;
|
|
|
|
|
}
|
2017-01-21 17:48:45 +01:00
|
|
|
ide->cylprecomp = val;
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide_other))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].features = val;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide_other))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].features = val;
|
|
|
|
|
}
|
2017-01-21 17:48:45 +01:00
|
|
|
ide_other->cylprecomp = val;
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case 0x1F2: /* Sector count */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
ide_log("Sector count write: %i\n", val);
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board]]].phase = val;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
ide_log("Sector count write: %i\n", val);
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].phase = val;
|
|
|
|
|
}
|
2017-01-21 17:48:45 +01:00
|
|
|
ide->secount = val;
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide_other))
|
|
|
|
|
{
|
|
|
|
|
ide_log("Other sector count write: %i\n", val);
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].phase = val;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide_other))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
ide_log("Other sector count write: %i\n", val);
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].phase = val;
|
|
|
|
|
}
|
2017-01-21 17:48:45 +01:00
|
|
|
ide_other->secount = val;
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case 0x1F3: /* Sector */
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->sector = val;
|
|
|
|
|
ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | val;
|
|
|
|
|
ide_other->sector = val;
|
|
|
|
|
ide_other->lba_addr = (ide_other->lba_addr & 0xFFFFF00) | val;
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case 0x1F4: /* Cylinder low */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board]]].request_length &= 0xFF00;
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board]]].request_length |= val;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length &= 0xFF00;
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length |= val;
|
|
|
|
|
}
|
2017-01-21 17:48:45 +01:00
|
|
|
ide->cylinder = (ide->cylinder & 0xFF00) | val;
|
|
|
|
|
ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8);
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide_other))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF00;
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length |= val;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide_other))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF00;
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length |= val;
|
|
|
|
|
}
|
2017-01-21 17:48:45 +01:00
|
|
|
ide_other->cylinder = (ide_other->cylinder&0xFF00) | val;
|
|
|
|
|
ide_other->lba_addr = (ide_other->lba_addr&0xFFF00FF) | (val << 8);
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case 0x1F5: /* Cylinder high */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board]]].request_length &= 0xFF;
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board]]].request_length |= (val << 8);
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length &= 0xFF;
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length |= (val << 8);
|
|
|
|
|
}
|
2017-01-21 17:48:45 +01:00
|
|
|
ide->cylinder = (ide->cylinder & 0xFF) | (val << 8);
|
|
|
|
|
ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16);
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide_other))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF;
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length |= (val << 8);
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide_other))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF;
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length |= (val << 8);
|
|
|
|
|
}
|
2017-01-21 17:48:45 +01:00
|
|
|
ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8);
|
|
|
|
|
ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16);
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case 0x1F6: /* Drive/Head */
|
2016-12-29 20:40:24 +01:00
|
|
|
if (cur_ide[ide_board] != ((val>>4)&1)+(ide_board<<1))
|
|
|
|
|
{
|
|
|
|
|
cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1);
|
|
|
|
|
|
|
|
|
|
if (ide->reset || ide_other->reset)
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide->error = ide_other->error = 1;
|
|
|
|
|
ide->secount = ide_other->secount = 1;
|
|
|
|
|
ide->sector = ide_other->sector = 1;
|
|
|
|
|
ide->head = ide_other->head = 0;
|
|
|
|
|
ide->cylinder = ide_other->cylinder = 0;
|
|
|
|
|
ide->reset = ide_other->reset = 0;
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = READY_STAT | DSC_STAT;
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].error = 1;
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].phase = 1;
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].request_length = 0xEB14;
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 0LL;
|
|
|
|
|
ide->cylinder = 0xEB14;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-16 01:49:19 +01:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT | DSC_STAT;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].error = 1;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].phase = 1;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].request_length = 0xEB14;
|
2017-10-09 01:48:36 +02:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 0LL;
|
2017-01-21 17:48:45 +01:00
|
|
|
ide->cylinder = 0xEB14;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
2018-01-26 22:17:09 +01:00
|
|
|
|
|
|
|
|
if (ide_drive_is_zip(ide_other))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide_other->channel]].status = READY_STAT | DSC_STAT;
|
|
|
|
|
zip[atapi_zip_drives[ide_other->channel]].error = 1;
|
|
|
|
|
zip[atapi_zip_drives[ide_other->channel]].phase = 1;
|
|
|
|
|
zip[atapi_zip_drives[ide_other->channel]].request_length = 0xEB14;
|
|
|
|
|
zip[atapi_zip_drives[ide_other->channel]].callback = 0LL;
|
|
|
|
|
ide->cylinder = 0xEB14;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide_other))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-16 01:49:19 +01:00
|
|
|
cdrom[atapi_cdrom_drives[ide_other->channel]].status = READY_STAT | DSC_STAT;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide_other->channel]].error = 1;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide_other->channel]].phase = 1;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide_other->channel]].request_length = 0xEB14;
|
2017-10-09 01:48:36 +02:00
|
|
|
cdrom[atapi_cdrom_drives[ide_other->channel]].callback = 0LL;
|
2017-01-21 17:48:45 +01:00
|
|
|
ide->cylinder = 0xEB14;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board] = 0LL;
|
2016-12-29 20:40:24 +01:00
|
|
|
timer_update_outstanding();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ide = &ide_drives[cur_ide[ide_board]];
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->head = val & 0xF;
|
|
|
|
|
ide->lba = val & 0x40;
|
|
|
|
|
ide_other->head = val & 0xF;
|
|
|
|
|
ide_other->lba = val & 0x40;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24);
|
|
|
|
|
ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24);
|
2016-08-10 06:15:52 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case 0x1F7: /* Command register */
|
2016-12-29 20:40:24 +01:00
|
|
|
if (ide->type == IDE_NONE)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-01-21 17:48:45 +01:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
ide_irq_lower(ide);
|
|
|
|
|
ide->command=val;
|
2017-01-21 17:48:45 +01:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
ide->error=0;
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].error = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].error = 0;
|
|
|
|
|
}
|
2018-03-02 21:57:37 +01:00
|
|
|
if (((val >= WIN_RESTORE) && (val <= 0x1F)) || ((val >= WIN_SEEK) && (val <= 0x7F)))
|
2018-02-25 22:01:56 +01:00
|
|
|
{
|
|
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = READY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
|
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-03-02 21:57:37 +01:00
|
|
|
ide->atastat = BUSY_STAT;
|
2018-02-25 22:01:56 +01:00
|
|
|
}
|
|
|
|
|
timer_process();
|
|
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
2018-03-02 21:58:42 +01:00
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 100LL*IDE_TIME;
|
2018-02-25 22:01:56 +01:00
|
|
|
}
|
|
|
|
|
if (ide_drive_is_cdrom(ide))
|
|
|
|
|
{
|
2018-03-02 21:58:42 +01:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 100LL*IDE_TIME;
|
2018-02-25 22:01:56 +01:00
|
|
|
}
|
2018-03-02 21:57:37 +01:00
|
|
|
idecallback[ide_board]=40000LL * TIMER_USEC /*100LL*IDE_TIME*/;
|
2018-02-25 22:01:56 +01:00
|
|
|
timer_update_outstanding();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-05-15 00:35:26 +02:00
|
|
|
switch (val)
|
|
|
|
|
{
|
|
|
|
|
case WIN_SRST: /* ATAPI Device Reset */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = READY_STAT;
|
|
|
|
|
}
|
|
|
|
|
timer_process();
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 100LL*IDE_TIME;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 100LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
}
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board]=100LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
timer_update_outstanding();
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case WIN_READ_MULTIPLE:
|
|
|
|
|
/* Fatal removed in accordance with the official ATAPI reference:
|
|
|
|
|
If the Read Multiple command is attempted before the Set Multiple Mode
|
|
|
|
|
command has been executed or when Read Multiple commands are
|
|
|
|
|
disabled, the Read Multiple operation is rejected with an Aborted Com-
|
|
|
|
|
mand error. */
|
|
|
|
|
ide->blockcount = 0;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case WIN_READ:
|
|
|
|
|
case WIN_READ_NORETRY:
|
|
|
|
|
case WIN_READ_DMA:
|
2017-10-24 04:15:05 +02:00
|
|
|
case WIN_READ_DMA_ALT:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
timer_process();
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
}
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board]=200LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
timer_update_outstanding();
|
2017-06-19 06:46:08 +02:00
|
|
|
ide->do_initial_read = 1;
|
2017-05-15 00:35:26 +02:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case WIN_WRITE_MULTIPLE:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (!ide->blocksize && !ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
fatal("Write_MULTIPLE - blocksize = 0\n");
|
|
|
|
|
}
|
|
|
|
|
ide->blockcount = 0;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case WIN_WRITE:
|
|
|
|
|
case WIN_WRITE_NORETRY:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = DRQ_STAT | DSC_STAT | READY_STAT;
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].pos = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = DRQ_STAT | DSC_STAT | READY_STAT;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].pos = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = DRQ_STAT | DSC_STAT | READY_STAT;
|
|
|
|
|
ide->pos=0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case WIN_WRITE_DMA:
|
2017-10-24 04:15:05 +02:00
|
|
|
case WIN_WRITE_DMA_ALT:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
timer_process();
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
}
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board]=200LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
timer_update_outstanding();
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case WIN_VERIFY:
|
|
|
|
|
case WIN_VERIFY_ONCE:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
timer_process();
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
}
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board]=200LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
timer_update_outstanding();
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case WIN_FORMAT:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
goto ide_bad_command;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = DRQ_STAT;
|
|
|
|
|
ide->pos=0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case WIN_SPECIFY: /* Initialize Drive Parameters */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
timer_process();
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 30LL*IDE_TIME;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 30LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
}
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board]=30LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
timer_update_outstanding();
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */
|
2018-02-11 20:51:42 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
else
|
|
|
|
|
ide->atastat = BUSY_STAT;
|
|
|
|
|
|
|
|
|
|
if (ide_drive_is_zip(ide_other))
|
|
|
|
|
zip[atapi_zip_drives[ide_other->channel]].status = BUSY_STAT;
|
|
|
|
|
else if (ide_drive_is_cdrom(ide_other))
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide_other->channel]].status = BUSY_STAT;
|
|
|
|
|
else
|
|
|
|
|
ide_other->atastat = BUSY_STAT;
|
|
|
|
|
|
|
|
|
|
timer_process();
|
|
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 200LL * IDE_TIME;
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL * IDE_TIME;
|
|
|
|
|
idecallback[ide_board] = 200LL * IDE_TIME;
|
|
|
|
|
timer_update_outstanding();
|
|
|
|
|
return;
|
|
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case WIN_PIDENTIFY: /* Identify Packet Device */
|
|
|
|
|
case WIN_SET_MULTIPLE_MODE: /* Set Multiple Mode */
|
|
|
|
|
case WIN_NOP:
|
|
|
|
|
case WIN_STANDBYNOW1:
|
|
|
|
|
case WIN_IDLENOW1:
|
|
|
|
|
case WIN_SETIDLE1: /* Idle */
|
|
|
|
|
case WIN_CHECKPOWERMODE1:
|
|
|
|
|
case WIN_SLEEP1:
|
2018-02-11 20:51:42 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT;
|
2017-05-15 00:35:26 +02:00
|
|
|
else
|
2018-02-11 20:51:42 +01:00
|
|
|
ide->atastat = BUSY_STAT;
|
|
|
|
|
timer_process();
|
|
|
|
|
callbackide(ide_board);
|
|
|
|
|
timer_update_outstanding();
|
2017-05-15 00:35:26 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case WIN_IDENTIFY: /* Identify Device */
|
2018-02-11 20:51:42 +01:00
|
|
|
case WIN_SET_FEATURES: /* Set Features */
|
2017-05-15 00:35:26 +02:00
|
|
|
case WIN_READ_NATIVE_MAX:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
timer_process();
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 200LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
}
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board]=200LL*IDE_TIME;
|
2017-05-15 00:35:26 +02:00
|
|
|
timer_update_outstanding();
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case WIN_PACKETCMD: /* ATAPI Packet */
|
|
|
|
|
/* Skip the command callback wait, and process immediately. */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].packet_status = ZIP_PHASE_IDLE;
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].pos=0;
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].phase = 1;
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = READY_STAT | DRQ_STAT | (zip[cur_ide[ide_board]].status & ERR_STAT);
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].packet_status = CDROM_PHASE_IDLE;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].pos=0;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].phase = 1;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT | DRQ_STAT | (cdrom[cur_ide[ide_board]].status & ERR_STAT);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = BUSY_STAT;
|
2016-12-29 20:40:24 +01:00
|
|
|
timer_process();
|
2018-02-11 20:51:42 +01:00
|
|
|
idecallback[ide_board]=200LL*IDE_TIME;
|
2016-12-29 20:40:24 +01:00
|
|
|
timer_update_outstanding();
|
2017-05-15 00:35:26 +02:00
|
|
|
ide->pos=0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
case 0xF0:
|
|
|
|
|
default:
|
2017-01-16 01:49:19 +01:00
|
|
|
ide_bad_command:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = READY_STAT | ERR_STAT | DSC_STAT;
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].error = ABRT_ERR;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-05-15 00:35:26 +02:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT | ERR_STAT | DSC_STAT;
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].error = ABRT_ERR;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = READY_STAT | ERR_STAT | DSC_STAT;
|
|
|
|
|
ide->error = ABRT_ERR;
|
|
|
|
|
}
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
return;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
case 0x3F6: /* Device control */
|
2016-12-29 20:40:24 +01:00
|
|
|
if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE))
|
|
|
|
|
{
|
|
|
|
|
timer_process();
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].callback = 0LL;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].callback = 0LL;
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board]=500LL*IDE_TIME;
|
2016-12-29 20:40:24 +01:00
|
|
|
timer_update_outstanding();
|
|
|
|
|
|
|
|
|
|
if (ide->type != IDE_NONE)
|
|
|
|
|
{
|
|
|
|
|
ide->reset = 1;
|
|
|
|
|
}
|
|
|
|
|
if (ide_other->type != IDE_NONE)
|
|
|
|
|
{
|
|
|
|
|
ide->reset = 1;
|
|
|
|
|
}
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->atastat = ide_other->atastat = BUSY_STAT;
|
|
|
|
|
}
|
2017-02-02 02:55:08 +01:00
|
|
|
if (val & 4)
|
|
|
|
|
{
|
|
|
|
|
/*Drive held in reset*/
|
|
|
|
|
timer_process();
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board] = 0LL;
|
2017-02-02 02:55:08 +01:00
|
|
|
timer_update_outstanding();
|
|
|
|
|
ide->atastat = ide_other->atastat = BUSY_STAT;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->fdisk = ide_other->fdisk = val;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-01-18 21:51:03 +01:00
|
|
|
uint32_t ide_read_data(int ide_board, int length)
|
2017-01-17 00:01:59 +01:00
|
|
|
{
|
|
|
|
|
IDE *ide = &ide_drives[cur_ide[ide_board]];
|
2017-01-18 21:51:03 +01:00
|
|
|
uint32_t temp;
|
2017-01-17 00:01:59 +01:00
|
|
|
|
|
|
|
|
uint8_t *idebufferb = (uint8_t *) ide->buffer;
|
2017-01-18 21:51:03 +01:00
|
|
|
uint16_t *idebufferw = ide->buffer;
|
|
|
|
|
uint32_t *idebufferl = (uint32_t *) ide->buffer;
|
2017-01-17 00:01:59 +01:00
|
|
|
|
|
|
|
|
if (ide->command == WIN_PACKETCMD)
|
|
|
|
|
{
|
2017-01-18 21:51:03 +01:00
|
|
|
ide->pos = 0;
|
2018-01-26 22:17:09 +01:00
|
|
|
if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide))
|
2017-01-17 00:01:59 +01:00
|
|
|
{
|
2018-01-26 22:17:09 +01:00
|
|
|
ide_log("Drive not ZIP or CD-ROM (position: %i)\n", ide->pos);
|
2017-01-17 00:01:59 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
temp = zip_read(cur_ide[ide_board], length);
|
|
|
|
|
else
|
|
|
|
|
temp = cdrom_read(cur_ide[ide_board], length);
|
2017-01-17 00:01:59 +01:00
|
|
|
}
|
2017-01-17 19:41:42 +01:00
|
|
|
else
|
|
|
|
|
{
|
2017-01-18 21:51:03 +01:00
|
|
|
switch (length)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
temp = idebufferb[ide->pos];
|
|
|
|
|
ide->pos++;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
temp = idebufferw[ide->pos >> 1];
|
|
|
|
|
ide->pos += 2;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
2017-01-20 23:53:19 +01:00
|
|
|
temp = idebufferl[ide->pos >> 2];
|
2017-01-18 21:51:03 +01:00
|
|
|
ide->pos += 4;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2017-01-17 19:41:42 +01:00
|
|
|
}
|
2017-01-17 00:01:59 +01:00
|
|
|
if (ide->pos>=512 && ide->command != WIN_PACKETCMD)
|
|
|
|
|
{
|
|
|
|
|
ide->pos=0;
|
|
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board]]].status = READY_STAT | DSC_STAT;
|
|
|
|
|
zip[atapi_zip_drives[cur_ide[ide_board]]].packet_status = ZIP_PHASE_IDLE;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-17 00:01:59 +01:00
|
|
|
{
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].status = READY_STAT | DSC_STAT;
|
|
|
|
|
cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].packet_status = CDROM_PHASE_IDLE;
|
|
|
|
|
}
|
|
|
|
|
if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE)
|
|
|
|
|
{
|
|
|
|
|
ide->secount = (ide->secount - 1) & 0xff;
|
|
|
|
|
if (ide->secount)
|
|
|
|
|
{
|
|
|
|
|
ide_next_sector(ide);
|
|
|
|
|
ide->atastat = BUSY_STAT;
|
|
|
|
|
timer_process();
|
|
|
|
|
if (ide->command == WIN_READ_MULTIPLE)
|
|
|
|
|
{
|
|
|
|
|
callbackide(ide_board);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[ide_board]=6LL*IDE_TIME;
|
2017-01-17 00:01:59 +01:00
|
|
|
}
|
|
|
|
|
timer_update_outstanding();
|
|
|
|
|
}
|
2017-05-05 01:49:42 +02:00
|
|
|
else
|
|
|
|
|
{
|
2017-10-10 03:07:29 -04:00
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
2017-01-17 00:01:59 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
uint8_t readide(int ide_board, uint16_t addr)
|
|
|
|
|
{
|
2016-12-29 20:40:24 +01:00
|
|
|
IDE *ide = &ide_drives[cur_ide[ide_board]];
|
|
|
|
|
uint8_t temp;
|
|
|
|
|
uint16_t tempw;
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
addr |= 0x90;
|
|
|
|
|
addr &= 0xFFF7;
|
2016-11-12 15:06:38 +01:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
switch (addr)
|
|
|
|
|
{
|
|
|
|
|
case 0x1F0: /* Data */
|
2017-01-18 21:51:03 +01:00
|
|
|
tempw = readidew(ide_board);
|
|
|
|
|
temp = tempw & 0xff;
|
2016-12-29 20:40:24 +01:00
|
|
|
break;
|
2017-01-16 01:49:19 +01:00
|
|
|
|
|
|
|
|
/* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested),
|
|
|
|
|
Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media),
|
2017-05-15 00:35:26 +02:00
|
|
|
and Bit 0 = ILI (illegal length indication). */
|
2016-12-29 20:40:24 +01:00
|
|
|
case 0x1F1: /* Error */
|
|
|
|
|
if (ide->type == IDE_NONE)
|
|
|
|
|
{
|
2017-01-17 19:41:42 +01:00
|
|
|
temp = 0;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
temp = zip[atapi_zip_drives[cur_ide[ide_board]]].error;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].error;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
temp = ide->error;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
/* For ATAPI:
|
|
|
|
|
Bit 0: Command or Data:
|
|
|
|
|
Data if clear, Command if set;
|
|
|
|
|
Bit 1: I/OB
|
|
|
|
|
Direction:
|
|
|
|
|
To device if set;
|
|
|
|
|
From device if clear.
|
|
|
|
|
IO DRQ CoD
|
|
|
|
|
0 1 1 Ready to accept command packet
|
|
|
|
|
1 1 1 Message - ready to send message to host
|
|
|
|
|
1 1 0 Data to host
|
|
|
|
|
0 1 0 Data from host
|
|
|
|
|
1 0 1 Status. */
|
2016-12-29 20:40:24 +01:00
|
|
|
case 0x1F2: /* Sector count */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
temp = zip[atapi_zip_drives[cur_ide[ide_board]]].phase;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-17 19:41:42 +01:00
|
|
|
temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].phase;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-01-17 19:41:42 +01:00
|
|
|
temp = ide->secount;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
case 0x1F3: /* Sector */
|
2017-01-17 19:41:42 +01:00
|
|
|
temp = (uint8_t)ide->sector;
|
2016-12-29 20:40:24 +01:00
|
|
|
break;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
case 0x1F4: /* Cylinder low */
|
|
|
|
|
if (ide->type == IDE_NONE)
|
|
|
|
|
{
|
|
|
|
|
temp = 0xFF;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
temp = zip[atapi_zip_drives[cur_ide[ide_board]]].request_length & 0xff;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length & 0xff;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
temp = ide->cylinder & 0xff;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
case 0x1F5: /* Cylinder high */
|
|
|
|
|
if (ide->type == IDE_NONE)
|
|
|
|
|
{
|
|
|
|
|
temp = 0xFF;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
temp = zip[atapi_zip_drives[cur_ide[ide_board]]].request_length >> 8;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length >> 8;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
temp = ide->cylinder >> 8;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
case 0x1F6: /* Drive/Head */
|
2017-01-21 17:48:45 +01:00
|
|
|
temp = (uint8_t)(ide->head | ((cur_ide[ide_board] & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0);
|
2016-12-29 20:40:24 +01:00
|
|
|
break;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
/* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is
|
|
|
|
|
DF (drive fault). */
|
2016-12-29 20:40:24 +01:00
|
|
|
case 0x1F7: /* Status */
|
|
|
|
|
ide_irq_lower(ide);
|
2017-01-17 19:41:42 +01:00
|
|
|
if (ide->type == IDE_NONE)
|
|
|
|
|
{
|
2017-09-04 05:15:12 +02:00
|
|
|
temp = 0;
|
2017-01-17 19:41:42 +01:00
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
else
|
|
|
|
|
{
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
temp = (zip[atapi_zip_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-09-06 06:03:34 +02:00
|
|
|
{
|
|
|
|
|
temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
temp = ide->atastat;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
case 0x3F6: /* Alternate Status */
|
|
|
|
|
if (ide->type == IDE_NONE)
|
|
|
|
|
{
|
2017-09-04 05:15:12 +02:00
|
|
|
temp = 0;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
temp = (zip[atapi_zip_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-09-06 06:03:34 +02:00
|
|
|
{
|
|
|
|
|
temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
temp = ide->atastat;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
default:
|
2017-09-04 05:15:12 +02:00
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
/* if (ide_board) */ ide_log("Read IDEb %04X %02X %02X %02X %i %04X:%04X %i\n", addr, temp, ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,cpu_state.pc,ide_board);
|
2016-12-29 20:40:24 +01:00
|
|
|
return temp;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
uint8_t cdb[16];
|
|
|
|
|
|
|
|
|
|
int old_len = 0;
|
|
|
|
|
|
|
|
|
|
int total_read = 0;
|
|
|
|
|
|
|
|
|
|
int block_total = 0;
|
|
|
|
|
int all_blocks_total = 0;
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
uint16_t readidew(int ide_board)
|
|
|
|
|
{
|
2017-01-20 23:53:19 +01:00
|
|
|
return ide_read_data(ide_board, 2);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t readidel(int ide_board)
|
|
|
|
|
{
|
2016-12-29 20:40:24 +01:00
|
|
|
uint16_t temp;
|
2017-01-20 23:53:19 +01:00
|
|
|
temp = readidew(ide_board);
|
|
|
|
|
return temp | (readidew(ide_board) << 16);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int times30=0;
|
|
|
|
|
void callbackide(int ide_board)
|
|
|
|
|
{
|
2017-05-05 01:49:42 +02:00
|
|
|
IDE *ide, *ide_other;
|
2016-12-29 20:40:24 +01:00
|
|
|
int64_t snum;
|
2017-01-16 01:49:19 +01:00
|
|
|
int cdrom_id;
|
2017-09-08 00:17:49 +02:00
|
|
|
int cdrom_id_other;
|
2018-01-26 22:17:09 +01:00
|
|
|
int zip_id;
|
|
|
|
|
int zip_id_other;
|
2017-06-01 22:26:56 +02:00
|
|
|
uint64_t full_size = 0;
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
ide = &ide_drives[cur_ide[ide_board]];
|
|
|
|
|
ide_other = &ide_drives[cur_ide[ide_board] ^ 1];
|
2017-06-01 22:26:56 +02:00
|
|
|
if (ide->type == IDE_HDD)
|
|
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
|
2017-06-01 22:26:56 +02:00
|
|
|
}
|
2017-05-05 01:49:42 +02:00
|
|
|
ext_ide = ide;
|
2016-12-29 20:40:24 +01:00
|
|
|
|
|
|
|
|
if (ide->command==0x30) times30++;
|
2017-01-16 01:49:19 +01:00
|
|
|
/*if (ide_board) */ide_log("CALLBACK %02X %i %i %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]);
|
2016-12-29 20:40:24 +01:00
|
|
|
|
|
|
|
|
if (ide->reset)
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide->error = ide_other->error = 1;
|
|
|
|
|
ide->secount = ide_other->secount = 1;
|
|
|
|
|
ide->sector = ide_other->sector = 1;
|
|
|
|
|
ide->head = ide_other->head = 0;
|
|
|
|
|
ide->cylinder = ide_other->cylinder = 0;
|
|
|
|
|
ide->reset = ide_other->reset = 0;
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip_id = atapi_zip_drives[cur_ide[ide_board]];
|
|
|
|
|
zip[zip_id].status = READY_STAT | DSC_STAT;
|
|
|
|
|
zip[zip_id].error = 1;
|
|
|
|
|
zip[zip_id].phase = 1;
|
|
|
|
|
zip[zip_id].request_length=0xEB14;
|
|
|
|
|
ide->cylinder = 0xEB14;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-16 01:49:19 +01:00
|
|
|
cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]];
|
|
|
|
|
cdrom[cdrom_id].status = READY_STAT | DSC_STAT;
|
|
|
|
|
cdrom[cdrom_id].error = 1;
|
|
|
|
|
cdrom[cdrom_id].phase = 1;
|
|
|
|
|
cdrom[cdrom_id].request_length=0xEB14;
|
2017-01-21 17:48:45 +01:00
|
|
|
ide->cylinder = 0xEB14;
|
2017-01-16 01:49:19 +01:00
|
|
|
if (cdrom_drives[cdrom_id].handler->stop)
|
|
|
|
|
{
|
|
|
|
|
cdrom_drives[cdrom_id].handler->stop(cdrom_id);
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
if (ide->type == IDE_NONE)
|
|
|
|
|
{
|
|
|
|
|
ide->cylinder=0xFFFF;
|
|
|
|
|
}
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide_other))
|
|
|
|
|
{
|
|
|
|
|
zip_id_other = atapi_zip_drives[cur_ide[ide_board] ^ 1];
|
|
|
|
|
zip[zip_id_other].status = READY_STAT | DSC_STAT;
|
|
|
|
|
zip[zip_id_other].error = 1;
|
|
|
|
|
zip[zip_id_other].phase = 1;
|
|
|
|
|
zip[zip_id_other].request_length=0xEB14;
|
|
|
|
|
ide->cylinder = 0xEB14;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide_other))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-09-08 00:17:49 +02:00
|
|
|
cdrom_id_other = atapi_cdrom_drives[cur_ide[ide_board] ^ 1];
|
|
|
|
|
cdrom[cdrom_id_other].status = READY_STAT | DSC_STAT;
|
|
|
|
|
cdrom[cdrom_id_other].error = 1;
|
|
|
|
|
cdrom[cdrom_id_other].phase = 1;
|
|
|
|
|
cdrom[cdrom_id_other].request_length=0xEB14;
|
2017-01-21 17:48:45 +01:00
|
|
|
ide_other->cylinder = 0xEB14;
|
2017-09-08 00:17:49 +02:00
|
|
|
if (cdrom_drives[cdrom_id_other].handler->stop)
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
2017-09-08 00:17:49 +02:00
|
|
|
cdrom_drives[cdrom_id_other].handler->stop(cdrom_id_other);
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
if (ide_other->type == IDE_NONE)
|
|
|
|
|
{
|
|
|
|
|
ide_other->cylinder=0xFFFF;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]];
|
2017-09-08 00:17:49 +02:00
|
|
|
cdrom_id_other = atapi_cdrom_drives[cur_ide[ide_board] ^ 1];
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
zip_id = atapi_zip_drives[cur_ide[ide_board]];
|
|
|
|
|
zip_id_other = atapi_zip_drives[cur_ide[ide_board] ^ 1];
|
|
|
|
|
|
2018-03-02 21:57:37 +01:00
|
|
|
if (((ide->command >= WIN_RESTORE) && (ide->command <= 0x1F)) || ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F)))
|
2018-02-25 22:01:56 +01:00
|
|
|
{
|
|
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
|
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2018-03-02 21:57:37 +01:00
|
|
|
if ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F))
|
2018-02-25 22:01:56 +01:00
|
|
|
{
|
2018-03-02 21:57:37 +01:00
|
|
|
full_size /= ide->t_hpc;
|
|
|
|
|
full_size /= ide->t_spt;
|
|
|
|
|
|
|
|
|
|
if ((ide->cylinder >= full_size) || (ide->head >= ide->t_hpc) || !ide->sector || (ide->sector > ide->t_spt))
|
|
|
|
|
goto id_not_found;
|
2018-02-25 22:01:56 +01:00
|
|
|
}
|
2018-03-02 21:57:37 +01:00
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
2018-02-25 22:01:56 +01:00
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
switch (ide->command)
|
|
|
|
|
{
|
|
|
|
|
/* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h,
|
|
|
|
|
Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h. */
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_SRST: /*ATAPI Device Reset */
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide->error=1; /*Device passed*/
|
|
|
|
|
ide->secount = ide->sector = 1;
|
|
|
|
|
ide_set_signature(ide);
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[zip_id].status = READY_STAT | DSC_STAT;
|
|
|
|
|
zip[zip_id].error = 1;
|
|
|
|
|
zip[zip_id].phase = 1;
|
|
|
|
|
zip_reset(zip_id);
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-21 17:48:45 +01:00
|
|
|
cdrom[cdrom_id].status = READY_STAT | DSC_STAT;
|
|
|
|
|
cdrom[cdrom_id].error = 1;
|
|
|
|
|
cdrom[cdrom_id].phase = 1;
|
2017-01-16 01:49:19 +01:00
|
|
|
cdrom_reset(cdrom_id);
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
ide_irq_raise(ide);
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
ide->service = 0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-08-10 01:14:22 +02:00
|
|
|
case WIN_NOP:
|
2016-08-10 00:46:56 +02:00
|
|
|
case WIN_STANDBYNOW1:
|
2017-01-17 19:41:42 +01:00
|
|
|
case WIN_IDLENOW1:
|
2016-08-10 00:46:56 +02:00
|
|
|
case WIN_SETIDLE1:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[zip_id].status = READY_STAT | DSC_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom[cdrom_id].status = READY_STAT | DSC_STAT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-08-10 00:46:56 +02:00
|
|
|
case WIN_CHECKPOWERMODE1:
|
2017-01-17 19:41:42 +01:00
|
|
|
case WIN_SLEEP1:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[zip_id].phase = 0xFF;
|
|
|
|
|
zip[zip_id].status = READY_STAT | DSC_STAT;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-17 19:41:42 +01:00
|
|
|
cdrom[cdrom_id].phase = 0xFF;
|
|
|
|
|
cdrom[cdrom_id].status = READY_STAT | DSC_STAT;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
ide->secount = 0xFF;
|
|
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
return;
|
2016-08-10 00:46:56 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_READ:
|
|
|
|
|
case WIN_READ_NORETRY:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
ide_set_signature(ide);
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-02-15 18:19:00 +01:00
|
|
|
if (!ide->specify_success)
|
|
|
|
|
{
|
|
|
|
|
goto id_not_found;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
|
2017-06-19 06:46:08 +02:00
|
|
|
if (ide->do_initial_read)
|
|
|
|
|
{
|
|
|
|
|
ide->do_initial_read = 0;
|
|
|
|
|
ide->sector_pos = 0;
|
|
|
|
|
if (ide->secount)
|
|
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
|
2017-06-19 06:46:08 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer);
|
2017-06-19 06:46:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512);
|
|
|
|
|
|
|
|
|
|
ide->sector_pos++;
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->pos=0;
|
2017-06-19 06:46:08 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
|
|
|
|
|
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
|
2017-10-10 03:07:29 -04:00
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_READ_DMA:
|
2017-10-24 04:15:05 +02:00
|
|
|
case WIN_READ_DMA_ALT:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel);
|
2016-12-29 20:40:24 +01:00
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-02-15 18:19:00 +01:00
|
|
|
if (!ide->specify_success)
|
|
|
|
|
{
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel);
|
2017-02-15 18:19:00 +01:00
|
|
|
goto id_not_found;
|
|
|
|
|
}
|
2017-06-19 06:46:08 +02:00
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->sector_pos = 0;
|
|
|
|
|
if (ide->secount)
|
2017-06-19 06:46:08 +02:00
|
|
|
{
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->sector_pos = ide->secount;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->sector_pos = 256;
|
2017-06-19 06:46:08 +02:00
|
|
|
}
|
2017-10-24 04:15:05 +02:00
|
|
|
hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer);
|
2017-06-19 06:46:08 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->pos=0;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
if (ide_bus_master_read)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-10-24 04:15:05 +02:00
|
|
|
if (ide_bus_master_read(ide_board, ide->sector_buffer, ide->sector_pos * 512))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel);
|
2017-10-24 04:15:05 +02:00
|
|
|
goto abort_cmd;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*DMA successful*/
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA read successful\n", ide->channel);
|
2016-12-29 20:40:24 +01:00
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
2017-10-24 04:15:05 +02:00
|
|
|
} else {
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA read aborted (no bus master)\n", ide->channel);
|
2017-10-24 04:15:05 +02:00
|
|
|
goto abort_cmd;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_READ_MULTIPLE:
|
2016-12-29 20:40:24 +01:00
|
|
|
/* According to the official ATA reference:
|
|
|
|
|
|
|
|
|
|
If the Read Multiple command is attempted before the Set Multiple Mode
|
|
|
|
|
command has been executed or when Read Multiple commands are
|
|
|
|
|
disabled, the Read Multiple operation is rejected with an Aborted Com-
|
|
|
|
|
mand error. */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || !ide->blocksize)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-02-15 18:19:00 +01:00
|
|
|
if (!ide->specify_success)
|
|
|
|
|
{
|
|
|
|
|
goto id_not_found;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
|
2017-06-19 06:46:08 +02:00
|
|
|
if (ide->do_initial_read)
|
|
|
|
|
{
|
|
|
|
|
ide->do_initial_read = 0;
|
|
|
|
|
ide->sector_pos = 0;
|
|
|
|
|
if (ide->secount)
|
|
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
|
2017-06-19 06:46:08 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer);
|
2017-06-19 06:46:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512);
|
|
|
|
|
|
|
|
|
|
ide->sector_pos++;
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->pos=0;
|
2017-06-19 06:46:08 +02:00
|
|
|
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
|
|
|
|
|
if (!ide->blockcount)
|
|
|
|
|
{
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
}
|
|
|
|
|
ide->blockcount++;
|
|
|
|
|
if (ide->blockcount >= ide->blocksize)
|
|
|
|
|
{
|
|
|
|
|
ide->blockcount = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-10 03:07:29 -04:00
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_WRITE:
|
|
|
|
|
case WIN_WRITE_NORETRY:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-02-15 18:19:00 +01:00
|
|
|
if (!ide->specify_success)
|
|
|
|
|
{
|
|
|
|
|
goto id_not_found;
|
|
|
|
|
}
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
|
2016-12-29 20:40:24 +01:00
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
ide->secount = (ide->secount - 1) & 0xff;
|
|
|
|
|
if (ide->secount)
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
|
|
|
|
|
ide->pos=0;
|
|
|
|
|
ide_next_sector(ide);
|
2017-10-10 03:07:29 -04:00
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
2017-10-10 03:07:29 -04:00
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_WRITE_DMA:
|
2017-10-24 04:15:05 +02:00
|
|
|
case WIN_WRITE_DMA_ALT:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide_board >= 2))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel);
|
2016-12-29 20:40:24 +01:00
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-02-15 18:19:00 +01:00
|
|
|
if (!ide->specify_success)
|
|
|
|
|
{
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel);
|
2017-02-15 18:19:00 +01:00
|
|
|
goto id_not_found;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
if (ide_bus_master_read)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-10-24 04:15:05 +02:00
|
|
|
if (ide->secount)
|
|
|
|
|
ide->sector_pos = ide->secount;
|
|
|
|
|
else
|
|
|
|
|
ide->sector_pos = 256;
|
|
|
|
|
|
|
|
|
|
if (ide_bus_master_write(ide_board, ide->sector_buffer, ide->sector_pos * 512))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA write aborted (failed)\n", ide->channel);
|
2017-10-24 04:15:05 +02:00
|
|
|
goto abort_cmd;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*DMA successful*/
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA write successful\n", ide->channel);
|
2016-12-29 20:40:24 +01:00
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
hdd_image_write(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer);
|
2016-12-29 20:40:24 +01:00
|
|
|
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
2017-10-24 04:15:05 +02:00
|
|
|
} else {
|
2017-10-25 02:17:27 +02:00
|
|
|
ide_log("IDE %i: DMA write aborted (no bus master)\n", ide->channel);
|
2017-10-24 04:15:05 +02:00
|
|
|
goto abort_cmd;
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_WRITE_MULTIPLE:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-02-15 18:19:00 +01:00
|
|
|
if (!ide->specify_success)
|
|
|
|
|
{
|
|
|
|
|
goto id_not_found;
|
|
|
|
|
}
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->blockcount++;
|
|
|
|
|
if (ide->blockcount >= ide->blocksize || ide->secount == 1)
|
|
|
|
|
{
|
|
|
|
|
ide->blockcount = 0;
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
}
|
|
|
|
|
ide->secount = (ide->secount - 1) & 0xff;
|
|
|
|
|
if (ide->secount)
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
|
|
|
|
|
ide->pos=0;
|
|
|
|
|
ide_next_sector(ide);
|
2017-10-10 03:07:29 -04:00
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
2017-10-10 03:07:29 -04:00
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
case WIN_VERIFY:
|
|
|
|
|
case WIN_VERIFY_ONCE:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-02-15 18:19:00 +01:00
|
|
|
if (!ide->specify_success)
|
|
|
|
|
{
|
|
|
|
|
goto id_not_found;
|
|
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->pos=0;
|
|
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide_irq_raise(ide);
|
2017-10-10 03:07:29 -04:00
|
|
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_FORMAT:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-02-15 18:19:00 +01:00
|
|
|
if (!ide->specify_success)
|
|
|
|
|
{
|
|
|
|
|
goto id_not_found;
|
|
|
|
|
}
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount);
|
2017-06-16 03:18:59 +02:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide_irq_raise(ide);
|
2016-12-29 20:40:24 +01:00
|
|
|
|
2017-10-10 03:07:29 -04:00
|
|
|
/* ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); */
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
|
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_DRIVE_DIAGNOSTICS:
|
2016-12-29 20:40:24 +01:00
|
|
|
ide_set_signature(ide);
|
|
|
|
|
ide->error=1; /*No error detected*/
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[zip_id].status = 0;
|
|
|
|
|
zip[zip_id].error = 1;
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
2017-01-16 01:49:19 +01:00
|
|
|
cdrom[cdrom_id].status = 0;
|
2017-01-17 19:41:42 +01:00
|
|
|
cdrom[cdrom_id].error = 1;
|
|
|
|
|
ide_irq_raise(ide);
|
2016-12-29 20:40:24 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
2017-01-17 19:41:42 +01:00
|
|
|
ide->error = 1;
|
2016-12-29 20:40:24 +01:00
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
}
|
2017-09-08 00:17:49 +02:00
|
|
|
|
|
|
|
|
ide_set_signature(ide_other);
|
|
|
|
|
ide_other->error=1; /*No error detected*/
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide_other))
|
|
|
|
|
{
|
|
|
|
|
zip[zip_id_other].status = 0;
|
|
|
|
|
zip[zip_id_other].error = 1;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide_other))
|
2017-09-08 00:17:49 +02:00
|
|
|
{
|
|
|
|
|
cdrom[cdrom_id_other].status = 0;
|
|
|
|
|
cdrom[cdrom_id_other].error = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide_other->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide_other->error = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cur_ide[ide_board] &= ~1;
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_SPECIFY: /* Initialize Drive Parameters */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-05-05 01:49:42 +02:00
|
|
|
full_size /= (ide->head+1);
|
|
|
|
|
full_size /= ide->secount;
|
|
|
|
|
ide->specify_success = 1;
|
2017-09-30 16:56:38 -04:00
|
|
|
hdd_image_specify(ide->hdd_num, ide->head + 1, ide->secount);
|
2017-10-24 04:15:05 +02:00
|
|
|
ide->t_spt=ide->secount;
|
|
|
|
|
ide->t_hpc=ide->head;
|
|
|
|
|
ide->t_hpc++;
|
2016-12-29 20:40:24 +01:00
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_PIDENTIFY: /* Identify Packet Device */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
ide_atapi_zip_identify(ide);
|
|
|
|
|
ide->pos = 0;
|
|
|
|
|
zip[zip_id].phase = 2;
|
|
|
|
|
zip[zip_id].pos = 0;
|
|
|
|
|
zip[zip_id].error = 0;
|
|
|
|
|
zip[zip_id].status = DRQ_STAT | READY_STAT | DSC_STAT;
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
ide_atapi_identify(ide);
|
2017-01-16 01:49:19 +01:00
|
|
|
ide->pos = 0;
|
2017-10-25 02:17:27 +02:00
|
|
|
cdrom[cdrom_id].phase = 2;
|
2017-01-16 01:49:19 +01:00
|
|
|
cdrom[cdrom_id].pos = 0;
|
|
|
|
|
cdrom[cdrom_id].error = 0;
|
|
|
|
|
cdrom[cdrom_id].status = DRQ_STAT | READY_STAT | DSC_STAT;
|
2016-12-29 20:40:24 +01:00
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
goto abort_cmd;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_SET_MULTIPLE_MODE:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
|
|
|
|
ide->blocksize = ide->secount;
|
|
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
return;
|
2016-08-10 00:46:56 +02:00
|
|
|
|
|
|
|
|
case WIN_SET_FEATURES:
|
2017-10-27 20:54:31 -04:00
|
|
|
if (ide->type == IDE_NONE)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-05-14 18:37:32 +02:00
|
|
|
|
|
|
|
|
if (!ide_set_features(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
2017-05-14 18:37:32 +02:00
|
|
|
goto abort_cmd;
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide)) {
|
|
|
|
|
zip[zip_id].status = READY_STAT | DSC_STAT;
|
|
|
|
|
zip[zip_id].pos = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide)) {
|
2017-10-24 04:15:05 +02:00
|
|
|
cdrom[cdrom_id].status = READY_STAT | DSC_STAT;
|
|
|
|
|
cdrom[cdrom_id].pos = 0;
|
|
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
2017-05-14 18:37:32 +02:00
|
|
|
ide_irq_raise(ide);
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2017-05-14 18:37:32 +02:00
|
|
|
|
2016-08-10 00:46:56 +02:00
|
|
|
case WIN_READ_NATIVE_MAX:
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide->type != IDE_HDD)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
2017-09-30 16:56:38 -04:00
|
|
|
snum = hdd[ide->hdd_num].spt;
|
|
|
|
|
snum *= hdd[ide->hdd_num].hpc;
|
|
|
|
|
snum *= hdd[ide->hdd_num].tracks;
|
2016-12-29 20:40:24 +01:00
|
|
|
ide_set_sector(ide, snum - 1);
|
|
|
|
|
ide->atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
return;
|
2017-05-14 18:37:32 +02:00
|
|
|
|
|
|
|
|
case WIN_IDENTIFY: /* Identify Device */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide->type != IDE_HDD)
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
ide_set_signature(ide);
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide_identify(ide);
|
|
|
|
|
ide->pos=0;
|
|
|
|
|
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
|
|
|
|
|
ide_irq_raise(ide);
|
|
|
|
|
}
|
|
|
|
|
return;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-14 18:37:32 +02:00
|
|
|
case WIN_PACKETCMD: /* ATAPI Packet */
|
2018-01-26 22:17:09 +01:00
|
|
|
if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide))
|
2016-12-29 20:40:24 +01:00
|
|
|
{
|
|
|
|
|
goto abort_cmd;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
zip_phase_callback(atapi_zip_drives[cur_ide[ide_board]]);
|
|
|
|
|
else
|
|
|
|
|
cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]]);
|
2017-01-16 01:49:19 +01:00
|
|
|
ide_log("IDE callback now: %i\n", idecallback[ide_board]);
|
2016-12-29 20:40:24 +01:00
|
|
|
return;
|
2017-01-17 19:41:42 +01:00
|
|
|
|
|
|
|
|
case 0xFF:
|
|
|
|
|
goto abort_cmd;
|
2017-05-14 18:37:32 +02:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
abort_cmd:
|
|
|
|
|
ide->command = 0;
|
2018-01-26 22:17:09 +01:00
|
|
|
if (ide_drive_is_zip(ide))
|
|
|
|
|
{
|
|
|
|
|
zip[zip_id].status = READY_STAT | ERR_STAT | DSC_STAT;
|
|
|
|
|
zip[zip_id].error = ABRT_ERR;
|
|
|
|
|
zip[zip_id].pos = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (ide_drive_is_cdrom(ide))
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
|
|
|
|
cdrom[cdrom_id].status = READY_STAT | ERR_STAT | DSC_STAT;
|
|
|
|
|
cdrom[cdrom_id].error = ABRT_ERR;
|
|
|
|
|
cdrom[cdrom_id].pos = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ide->atastat = READY_STAT | ERR_STAT | DSC_STAT;
|
|
|
|
|
ide->error = ABRT_ERR;
|
|
|
|
|
ide->pos = 0;
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
ide_irq_raise(ide);
|
2017-02-15 18:19:00 +01:00
|
|
|
return;
|
2017-05-14 18:37:32 +02:00
|
|
|
|
2017-02-15 18:19:00 +01:00
|
|
|
id_not_found:
|
|
|
|
|
ide->atastat = READY_STAT | ERR_STAT | DSC_STAT;
|
|
|
|
|
ide->error = ABRT_ERR | 0x10;
|
|
|
|
|
ide->pos = 0;
|
|
|
|
|
ide_irq_raise(ide);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_callback_pri()
|
|
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[0] = 0LL;
|
2016-06-26 00:34:39 +02:00
|
|
|
callbackide(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_callback_sec()
|
|
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[1] = 0LL;
|
2016-06-26 00:34:39 +02:00
|
|
|
callbackide(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_callback_ter()
|
|
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[2] = 0LL;
|
2016-06-26 00:34:39 +02:00
|
|
|
callbackide(2);
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-28 23:34:00 +01:00
|
|
|
void ide_callback_qua()
|
|
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[3] = 0LL;
|
2016-12-28 23:34:00 +01:00
|
|
|
callbackide(3);
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-27 03:53:32 +02:00
|
|
|
void ide_callback_xtide()
|
|
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
idecallback[4] = 0LL;
|
2017-05-27 03:53:32 +02:00
|
|
|
callbackide(4);
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
void ide_write_pri(uint16_t addr, uint8_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeide(0, addr, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
void ide_write_pri_w(uint16_t addr, uint16_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeidew(0, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
void ide_write_pri_l(uint16_t addr, uint32_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeidel(0, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
uint8_t ide_read_pri(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readide(0, addr);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
uint16_t ide_read_pri_w(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readidew(0);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
uint32_t ide_read_pri_l(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readidel(0);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_write_sec(uint16_t addr, uint8_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeide(1, addr, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
void ide_write_sec_w(uint16_t addr, uint16_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeidew(1, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
void ide_write_sec_l(uint16_t addr, uint32_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeidel(1, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
uint8_t ide_read_sec(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readide(1, addr);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
uint16_t ide_read_sec_w(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readidew(1);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
uint32_t ide_read_sec_l(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readidel(1);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_write_ter(uint16_t addr, uint8_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeide(2, addr, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
void ide_write_ter_w(uint16_t addr, uint16_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeidew(2, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
void ide_write_ter_l(uint16_t addr, uint32_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeidel(2, val);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
uint8_t ide_read_ter(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readide(2, addr);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
uint16_t ide_read_ter_w(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readidew(2);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
uint32_t ide_read_ter_l(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readidel(2);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2016-12-28 23:34:00 +01:00
|
|
|
|
|
|
|
|
void ide_write_qua(uint16_t addr, uint8_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeide(3, addr, val);
|
2016-12-28 23:34:00 +01:00
|
|
|
}
|
|
|
|
|
void ide_write_qua_w(uint16_t addr, uint16_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeidew(3, val);
|
2016-12-28 23:34:00 +01:00
|
|
|
}
|
|
|
|
|
void ide_write_qua_l(uint16_t addr, uint32_t val, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
writeidel(3, val);
|
2016-12-28 23:34:00 +01:00
|
|
|
}
|
|
|
|
|
uint8_t ide_read_qua(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readide(3, addr);
|
2016-12-28 23:34:00 +01:00
|
|
|
}
|
|
|
|
|
uint16_t ide_read_qua_w(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readidew(3);
|
2016-12-28 23:34:00 +01:00
|
|
|
}
|
|
|
|
|
uint32_t ide_read_qua_l(uint16_t addr, void *priv)
|
|
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
return readidel(3);
|
2016-12-28 23:34:00 +01:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
static uint16_t ide_base_main[2] = { 0x1f0, 0x170 };
|
|
|
|
|
static uint16_t ide_side_main[2] = { 0x3f6, 0x376 };
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
|
|
|
|
void ide_pri_enable(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
|
|
|
|
|
io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
|
|
|
|
|
ide_base_main[0] = 0x1f0;
|
|
|
|
|
ide_side_main[0] = 0x3f6;
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_pri_enable_ex(void)
|
2017-05-05 01:49:42 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
if (ide_base_main[0] & 0x300)
|
|
|
|
|
{
|
2017-06-01 22:26:56 +02:00
|
|
|
ide_log("Enabling primary base (%04X)...\n", ide_base_main[0]);
|
2017-05-15 00:35:26 +02:00
|
|
|
io_sethandler(ide_base_main[0], 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
|
|
|
|
|
}
|
|
|
|
|
if (ide_side_main[0] & 0x300)
|
|
|
|
|
{
|
2017-06-01 22:26:56 +02:00
|
|
|
ide_log("Enabling primary side (%04X)...\n", ide_side_main[0]);
|
2017-05-15 00:35:26 +02:00
|
|
|
io_sethandler(ide_side_main[0], 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_pri_disable(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
io_removehandler(ide_base_main[0], 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
|
|
|
|
|
io_removehandler(ide_side_main[0], 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_sec_enable(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
|
|
|
|
|
io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
|
|
|
|
|
ide_base_main[1] = 0x170;
|
|
|
|
|
ide_side_main[1] = 0x376;
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_sec_enable_ex(void)
|
2017-05-05 01:49:42 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
if (ide_base_main[1] & 0x300)
|
|
|
|
|
{
|
|
|
|
|
io_sethandler(ide_base_main[1], 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
|
|
|
|
|
}
|
|
|
|
|
if (ide_side_main[1] & 0x300)
|
|
|
|
|
{
|
|
|
|
|
io_sethandler(ide_side_main[1], 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_sec_disable(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
io_removehandler(ide_base_main[1], 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
|
|
|
|
|
io_removehandler(ide_side_main[1], 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
void ide_set_base(int controller, uint16_t port)
|
|
|
|
|
{
|
|
|
|
|
ide_base_main[controller] = port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_set_side(int controller, uint16_t port)
|
|
|
|
|
{
|
|
|
|
|
ide_side_main[controller] = port;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_ter_enable(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
io_sethandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL);
|
|
|
|
|
io_sethandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_ter_disable(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
io_removehandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL);
|
|
|
|
|
io_removehandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_ter_disable_cond(void)
|
2017-01-17 19:41:42 +01:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
if ((ide_drives[4].type == IDE_NONE) && (ide_drives[5].type == IDE_NONE))
|
|
|
|
|
{
|
|
|
|
|
ide_ter_disable();
|
|
|
|
|
}
|
2017-01-17 19:41:42 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_ter_init(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
ide_ter_enable();
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
timer_add(ide_callback_ter, &idecallback[2], &idecallback[2], NULL);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2016-12-28 23:34:00 +01:00
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_qua_enable(void)
|
2016-12-28 23:34:00 +01:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
io_sethandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL);
|
|
|
|
|
io_sethandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL);
|
2016-12-28 23:34:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_qua_disable_cond(void)
|
2017-01-17 19:41:42 +01:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
if ((ide_drives[6].type == IDE_NONE) && (ide_drives[7].type == IDE_NONE))
|
|
|
|
|
{
|
|
|
|
|
ide_qua_disable();
|
|
|
|
|
}
|
2017-01-17 19:41:42 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_qua_disable(void)
|
2016-12-28 23:34:00 +01:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
io_removehandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL);
|
|
|
|
|
io_removehandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL);
|
2016-12-28 23:34:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_qua_init(void)
|
2016-12-28 23:34:00 +01:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
ide_qua_enable();
|
2016-12-28 23:34:00 +01:00
|
|
|
|
2017-05-15 00:35:26 +02:00
|
|
|
timer_add(ide_callback_qua, &idecallback[3], &idecallback[3], NULL);
|
2016-12-28 23:34:00 +01:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
|
2017-10-01 16:29:15 -04:00
|
|
|
/*FIXME: this will go away after Kotori's rewrite. --FvK */
|
|
|
|
|
void ide_init_first(void)
|
|
|
|
|
{
|
|
|
|
|
int d;
|
|
|
|
|
|
|
|
|
|
memset(ide_drives, 0x00, sizeof(ide_drives));
|
|
|
|
|
for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++)
|
|
|
|
|
{
|
|
|
|
|
ide_drives[d].channel = d;
|
|
|
|
|
ide_drives[d].type = IDE_NONE;
|
|
|
|
|
ide_drives[d].hdd_num = -1;
|
|
|
|
|
ide_drives[d].atastat = READY_STAT | DSC_STAT;
|
|
|
|
|
ide_drives[d].service = 0;
|
|
|
|
|
ide_drives[d].board = d >> 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-09-30 16:56:38 -04:00
|
|
|
void ide_xtide_init(void)
|
2017-05-27 03:53:32 +02:00
|
|
|
{
|
|
|
|
|
ide_bus_master_read = ide_bus_master_write = NULL;
|
|
|
|
|
|
|
|
|
|
timer_add(ide_callback_xtide, &idecallback[4], &idecallback[4], NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel))
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-15 00:35:26 +02:00
|
|
|
ide_bus_master_read = read;
|
|
|
|
|
ide_bus_master_write = write;
|
|
|
|
|
ide_bus_master_set_irq = set_irq;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2017-09-02 20:39:57 +02:00
|
|
|
|
|
|
|
|
void secondary_ide_check(void)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
int secondary_cdroms = 0;
|
2018-01-26 22:17:09 +01:00
|
|
|
int secondary_zips = 0;
|
2017-09-02 20:39:57 +02:00
|
|
|
|
2018-02-14 13:52:19 +01:00
|
|
|
for (i=0; i<ZIP_NUM; i++) {
|
2018-01-26 22:17:09 +01:00
|
|
|
if ((zip_drives[i].ide_channel >= 2) && (zip_drives[i].ide_channel <= 3) && ((zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)))
|
|
|
|
|
secondary_zips++;
|
|
|
|
|
}
|
2018-02-14 13:52:19 +01:00
|
|
|
for (i=0; i<CDROM_NUM; i++) {
|
2017-09-02 20:39:57 +02:00
|
|
|
if ((cdrom_drives[i].ide_channel >= 2) && (cdrom_drives[i].ide_channel <= 3) && ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)))
|
|
|
|
|
secondary_cdroms++;
|
|
|
|
|
}
|
2018-02-14 13:52:19 +01:00
|
|
|
if (!secondary_zips && !secondary_cdroms) {
|
|
|
|
|
ide_sec_disable();
|
|
|
|
|
ide_init_ch[1] = 0;
|
|
|
|
|
}
|
2017-09-02 20:39:57 +02:00
|
|
|
}
|
2017-12-16 00:02:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialization of standalone IDE controller instance.
|
|
|
|
|
*
|
|
|
|
|
* Eventually, we should clean up the whole mess by only
|
|
|
|
|
* using device_t units, with configuration parameters to
|
|
|
|
|
* indicate primary/secondary and all that, rather than
|
|
|
|
|
* keeping a zillion of duplicate functions around.
|
|
|
|
|
*/
|
|
|
|
|
static void *
|
|
|
|
|
ide_sainit(device_t *info)
|
|
|
|
|
{
|
|
|
|
|
switch(info->local) {
|
|
|
|
|
case 0: /* ISA, single-channel */
|
2018-02-14 13:52:19 +01:00
|
|
|
case 2: /* ISA, dual-channel */
|
|
|
|
|
case 3: /* ISA, dual-channel, optional 2nd channel */
|
|
|
|
|
case 4: /* VLB, single-channel */
|
|
|
|
|
case 6: /* VLB, dual-channel */
|
|
|
|
|
case 8: /* PCI, single-channel */
|
|
|
|
|
case 10: /* PCI, dual-channel */
|
|
|
|
|
if (!ide_init_ch[0]) {
|
|
|
|
|
ide_pri_enable();
|
|
|
|
|
timer_add(ide_callback_pri, &idecallback[0], &idecallback[0], NULL);
|
|
|
|
|
ide_init_ch[0] = 1;
|
|
|
|
|
}
|
2017-12-16 00:02:13 -05:00
|
|
|
|
2018-02-14 13:52:19 +01:00
|
|
|
if ((info->local & 2) && !ide_init_ch[1]) {
|
|
|
|
|
ide_sec_enable();
|
|
|
|
|
timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL);
|
|
|
|
|
ide_init_ch[1] = 1;
|
2017-12-16 00:02:13 -05:00
|
|
|
|
2018-02-14 13:52:19 +01:00
|
|
|
if (info->local & 1)
|
|
|
|
|
secondary_ide_check();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(info->local & 8))
|
|
|
|
|
ide_bus_master_read = ide_bus_master_write = NULL;
|
2017-12-16 00:02:13 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return(info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Close a standalone IDE unit. */
|
|
|
|
|
static void
|
|
|
|
|
ide_saclose(void *priv)
|
|
|
|
|
{
|
2018-02-14 13:52:19 +01:00
|
|
|
ide_init_ch[0] = ide_init_ch[1] = 0;
|
2017-12-16 00:02:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
device_t ide_isa_device = {
|
|
|
|
|
"ISA PC/AT IDE Controller",
|
|
|
|
|
DEVICE_ISA | DEVICE_AT,
|
|
|
|
|
0,
|
|
|
|
|
ide_sainit, ide_saclose, NULL,
|
|
|
|
|
NULL, NULL, NULL, NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
2018-02-14 13:52:19 +01:00
|
|
|
device_t ide_isa_2ch_device = {
|
|
|
|
|
"ISA PC/AT IDE Controller (Dual-Channel)",
|
|
|
|
|
DEVICE_ISA | DEVICE_AT,
|
2017-12-16 00:02:13 -05:00
|
|
|
2,
|
|
|
|
|
ide_sainit, ide_saclose, NULL,
|
|
|
|
|
NULL, NULL, NULL, NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
2018-02-14 13:52:19 +01:00
|
|
|
device_t ide_isa_2ch_opt_device = {
|
|
|
|
|
"ISA PC/AT IDE Controller (Single/Dual)",
|
|
|
|
|
DEVICE_ISA | DEVICE_AT,
|
|
|
|
|
3,
|
|
|
|
|
ide_sainit, ide_saclose, NULL,
|
|
|
|
|
NULL, NULL, NULL, NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
2017-12-16 00:02:13 -05:00
|
|
|
device_t ide_vlb_device = {
|
|
|
|
|
"VLB IDE Controller",
|
|
|
|
|
DEVICE_VLB | DEVICE_AT,
|
2018-02-14 13:52:19 +01:00
|
|
|
4,
|
|
|
|
|
ide_sainit, ide_saclose, NULL,
|
|
|
|
|
NULL, NULL, NULL, NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
device_t ide_vlb_2ch_device = {
|
|
|
|
|
"VLB IDE Controller (Dual-Channel)",
|
|
|
|
|
DEVICE_VLB | DEVICE_AT,
|
|
|
|
|
6,
|
|
|
|
|
ide_sainit, ide_saclose, NULL,
|
|
|
|
|
NULL, NULL, NULL, NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
device_t ide_pci_device = {
|
|
|
|
|
"PCI IDE Controller",
|
|
|
|
|
DEVICE_PCI | DEVICE_AT,
|
|
|
|
|
8,
|
|
|
|
|
ide_sainit, ide_saclose, NULL,
|
|
|
|
|
NULL, NULL, NULL, NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
device_t ide_pci_2ch_device = {
|
|
|
|
|
"PCI IDE Controller (Dual-Channel)",
|
|
|
|
|
DEVICE_PCI | DEVICE_AT,
|
|
|
|
|
10,
|
2017-12-16 00:02:13 -05:00
|
|
|
ide_sainit, ide_saclose, NULL,
|
|
|
|
|
NULL, NULL, NULL, NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|