Implemented ATAPI DMA transfer modes.
This commit is contained in:
parent
1d5afd1d9a
commit
6602368cc4
9 changed files with 289 additions and 54 deletions
35
src/ide.c
35
src/ide.c
|
|
@ -45,6 +45,7 @@
|
|||
#define WIN_SETIDLE1 0xE3
|
||||
#define WIN_CHECK_POWER_MODE 0xE5
|
||||
#define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */
|
||||
#define WIN_SET_FEATURES 0xEF
|
||||
|
||||
/** Evaluate to non-zero if the currently selected drive is an ATAPI device */
|
||||
#define IDE_DRIVE_IS_CDROM(ide) (ide->type == IDE_CDROM)
|
||||
|
|
@ -93,8 +94,8 @@ IDE *ext_ide;
|
|||
|
||||
char ide_fn[7][512];
|
||||
|
||||
int (*ide_bus_master_read_sector)(int channel, uint8_t *data);
|
||||
int (*ide_bus_master_write_sector)(int channel, uint8_t *data);
|
||||
int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size);
|
||||
int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size);
|
||||
void (*ide_bus_master_set_irq)(int channel);
|
||||
|
||||
int idecallback[2] = {0, 0};
|
||||
|
|
@ -582,7 +583,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
|
|||
return;
|
||||
|
||||
case WIN_IDENTIFY: /* Identify Device */
|
||||
case 0xEF:
|
||||
case WIN_SET_FEATURES:
|
||||
// output=3;
|
||||
// timetolive=500;
|
||||
ide->atastat = BUSY_STAT;
|
||||
|
|
@ -593,7 +594,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
|
|||
|
||||
case WIN_PACKETCMD: /* ATAPI Packet */
|
||||
if (ide->type == IDE_CDROM)
|
||||
atapi_command_start(&ide->atapi);
|
||||
atapi_command_start(&ide->atapi, ide->cylprecomp);
|
||||
|
||||
ide->atastat = BUSY_STAT;
|
||||
timer_process();
|
||||
|
|
@ -932,9 +933,9 @@ void callbackide(int ide_board)
|
|||
}
|
||||
ide->pos=0;
|
||||
|
||||
if (ide_bus_master_read_sector)
|
||||
if (ide_bus_master_read_data)
|
||||
{
|
||||
if (ide_bus_master_read_sector(ide_board, &ide->sector_buffer[ide->sector_pos*512]))
|
||||
if (ide_bus_master_read_data(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512))
|
||||
idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/
|
||||
else
|
||||
{
|
||||
|
|
@ -1010,9 +1011,9 @@ void callbackide(int ide_board)
|
|||
goto abort_cmd;
|
||||
}
|
||||
|
||||
if (ide_bus_master_write_sector)
|
||||
if (ide_bus_master_write_data)
|
||||
{
|
||||
if (ide_bus_master_write_sector(ide_board, (uint8_t *)ide->buffer))
|
||||
if (ide_bus_master_write_data(ide_board, (uint8_t *)ide->buffer, 512))
|
||||
idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/
|
||||
else
|
||||
{
|
||||
|
|
@ -1138,7 +1139,6 @@ void callbackide(int ide_board)
|
|||
return;
|
||||
|
||||
case WIN_SETIDLE1: /* Idle */
|
||||
case 0xEF:
|
||||
goto abort_cmd;
|
||||
|
||||
case WIN_IDENTIFY: /* Identify Device */
|
||||
|
|
@ -1161,7 +1161,18 @@ void callbackide(int ide_board)
|
|||
}
|
||||
return;
|
||||
|
||||
case WIN_SET_FEATURES:
|
||||
if (ide->type == IDE_NONE)
|
||||
goto abort_cmd;
|
||||
if (!IDE_DRIVE_IS_CDROM(ide))
|
||||
goto abort_cmd;
|
||||
|
||||
if (!atapi_dev->bus.devices[0]->atapi_set_feature(ide->cylprecomp, ide->secount, atapi_dev->bus.device_data[0]))
|
||||
goto abort_cmd;
|
||||
ide->atastat = READY_STAT | DSC_STAT;
|
||||
ide_irq_raise(ide);
|
||||
return;
|
||||
|
||||
case WIN_CHECK_POWER_MODE:
|
||||
if (ide->type == IDE_NONE)
|
||||
{
|
||||
|
|
@ -1291,10 +1302,10 @@ static void ide_close(void *p)
|
|||
{
|
||||
}
|
||||
|
||||
void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), int (*write_sector)(int channel, uint8_t *data), void (*set_irq)(int channel))
|
||||
void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size), int (*write_data)(int channel, uint8_t *data, int size), void (*set_irq)(int channel))
|
||||
{
|
||||
ide_bus_master_read_sector = read_sector;
|
||||
ide_bus_master_write_sector = write_sector;
|
||||
ide_bus_master_read_data = read_data;
|
||||
ide_bus_master_write_data = write_data;
|
||||
ide_bus_master_set_irq = set_irq;
|
||||
}
|
||||
|
||||
|
|
|
|||
14
src/ide.h
14
src/ide.h
|
|
@ -15,9 +15,13 @@ extern void ide_pri_enable();
|
|||
extern void ide_sec_enable();
|
||||
extern void ide_pri_disable();
|
||||
extern void ide_sec_disable();
|
||||
extern void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), int (*write_sector)(int channel, uint8_t *data), void (*set_irq)(int channel));
|
||||
extern void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size), int (*write_data)(int channel, uint8_t *data, int size), void (*set_irq)(int channel));
|
||||
void ide_irq_raise(struct IDE *ide);
|
||||
|
||||
extern int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size);
|
||||
extern int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size);
|
||||
extern void (*ide_bus_master_set_irq)(int channel);
|
||||
|
||||
#include "ide_atapi.h"
|
||||
|
||||
extern int ideboard;
|
||||
|
|
@ -47,4 +51,12 @@ extern device_t ide_device;
|
|||
#define ABRT_ERR 0x04 /* Command aborted */
|
||||
#define MCR_ERR 0x08 /* Media change request */
|
||||
|
||||
#define FEATURE_SET_TRANSFER_MODE 0x03
|
||||
#define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d
|
||||
#define FEATURE_ENABLE_IRQ_SERVICE 0x5e
|
||||
#define FEATURE_DISABLE_REVERT 0x66
|
||||
#define FEATURE_ENABLE_REVERT 0xcc
|
||||
#define FEATURE_DISABLE_IRQ_OVERLAPPED 0xdd
|
||||
#define FEATURE_DISABLE_IRQ_SERVICE 0xde
|
||||
|
||||
#endif //__IDE__
|
||||
|
|
|
|||
120
src/ide_atapi.c
120
src/ide_atapi.c
|
|
@ -17,6 +17,11 @@
|
|||
#define ATAPI_STATE_READ_DATA_WAIT 8
|
||||
#define ATAPI_STATE_WRITE_DATA 9
|
||||
#define ATAPI_STATE_WRITE_DATA_WAIT 10
|
||||
#define ATAPI_STATE_RETRY_READ_DMA 11
|
||||
#define ATAPI_STATE_RETRY_WRITE_DMA 12
|
||||
|
||||
#define FEATURES_DMA 0x01
|
||||
#define FEATURES_OVERLAP 0x02
|
||||
|
||||
ATAPI *atapi;
|
||||
|
||||
|
|
@ -94,9 +99,11 @@ static int wait_for_bus(scsi_bus_t *bus, int state, int req_needed)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void atapi_command_start(atapi_device_t *atapi)
|
||||
void atapi_command_start(atapi_device_t *atapi, uint8_t features)
|
||||
{
|
||||
scsi_bus_t *bus = &atapi->bus;
|
||||
|
||||
atapi->use_dma = features & 1;
|
||||
|
||||
scsi_bus_update(bus, BUS_SEL | BUS_SETDATA(1 << 0));
|
||||
if (!(scsi_bus_read(bus) & BUS_BSY))
|
||||
|
|
@ -243,19 +250,47 @@ void atapi_process_packet(atapi_device_t *atapi_dev)
|
|||
switch (bus_state & (BUS_IO | BUS_CD | BUS_MSG))
|
||||
{
|
||||
case 0:
|
||||
atapi_dev->state = ATAPI_STATE_WRITE_DATA_WAIT;
|
||||
|
||||
atapi_dev->data_read_pos = scsi_dev->get_bytes_required(scsi_data);
|
||||
if (atapi_dev->data_read_pos > atapi_dev->max_transfer_len)
|
||||
atapi_dev->data_read_pos = atapi_dev->max_transfer_len;
|
||||
|
||||
atapi_dev->data_write_pos = 0;
|
||||
*atapi_dev->cylinder = atapi_dev->data_read_pos;
|
||||
|
||||
if (atapi_dev->use_dma)
|
||||
{
|
||||
if (ide_bus_master_write_data)
|
||||
{
|
||||
if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos))
|
||||
{
|
||||
atapi_dev->state = ATAPI_STATE_RETRY_WRITE_DMA;
|
||||
idecallback[atapi_dev->board] = 1*IDE_TIME;
|
||||
}
|
||||
else
|
||||
|
||||
atapi_dev->data_write_pos = atapi_dev->data_read_pos; {
|
||||
atapi_dev->bus_state = 0;
|
||||
atapi_dev->state = ATAPI_STATE_WRITE_DATA;
|
||||
idecallback[atapi_dev->board] = 6 * IDE_TIME;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
atapi_dev->state = ATAPI_STATE_RETRY_WRITE_DMA;
|
||||
idecallback[atapi_dev->board] = 1*IDE_TIME;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (atapi_dev->data_read_pos > atapi_dev->max_transfer_len)
|
||||
atapi_dev->data_read_pos = atapi_dev->max_transfer_len;
|
||||
|
||||
atapi_dev->state = ATAPI_STATE_WRITE_DATA_WAIT;
|
||||
|
||||
// pclog("WRITE_DATA: bytes=%i\n", *atapi_dev->cylinder);
|
||||
*atapi_dev->atastat = READY_STAT | DRQ_STAT | (*atapi_dev->atastat & ERR_STAT);
|
||||
atapi_dev->bus_state = BUS_REQ;
|
||||
ide_irq_raise(atapi_dev->ide);
|
||||
*atapi_dev->cylinder = atapi_dev->data_read_pos;
|
||||
|
||||
// pclog("WRITE_DATA: bytes=%i\n", *atapi_dev->cylinder);
|
||||
*atapi_dev->atastat = READY_STAT | DRQ_STAT | (*atapi_dev->atastat & ERR_STAT);
|
||||
atapi_dev->bus_state = BUS_REQ;
|
||||
ide_irq_raise(atapi_dev->ide);
|
||||
}
|
||||
break;
|
||||
|
||||
case BUS_IO:
|
||||
|
|
@ -391,12 +426,36 @@ void atapi_process_packet(atapi_device_t *atapi_dev)
|
|||
if ((scsi_bus_read(&atapi_dev->bus) & (BUS_IO | BUS_CD | BUS_MSG)) != BUS_IO)
|
||||
break;
|
||||
}
|
||||
atapi_dev->state = ATAPI_STATE_READ_DATA_WAIT;
|
||||
*atapi_dev->atastat = READY_STAT | DRQ_STAT | (*atapi_dev->atastat & ERR_STAT);
|
||||
*atapi_dev->cylinder = atapi_dev->data_write_pos;
|
||||
// pclog("READ_DATA: bytes=%i\n", *atapi_dev->cylinder);
|
||||
atapi_dev->bus_state = BUS_IO | BUS_REQ;
|
||||
ide_irq_raise(atapi_dev->ide);
|
||||
if (atapi_dev->use_dma)
|
||||
{
|
||||
if (ide_bus_master_read_data)
|
||||
{
|
||||
if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos))
|
||||
{
|
||||
atapi_dev->state = ATAPI_STATE_RETRY_READ_DMA;
|
||||
idecallback[atapi_dev->board] = 1*IDE_TIME;
|
||||
}
|
||||
else
|
||||
{
|
||||
atapi_dev->state = ATAPI_STATE_NEXT_PHASE;
|
||||
idecallback[atapi_dev->board] = 6*IDE_TIME;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
atapi_dev->state = ATAPI_STATE_RETRY_READ_DMA;
|
||||
idecallback[atapi_dev->board] = 1*IDE_TIME;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
atapi_dev->state = ATAPI_STATE_READ_DATA_WAIT;
|
||||
*atapi_dev->atastat = READY_STAT | DRQ_STAT | (*atapi_dev->atastat & ERR_STAT);
|
||||
*atapi_dev->cylinder = atapi_dev->data_write_pos;
|
||||
// pclog("READ_DATA: bytes=%i\n", *atapi_dev->cylinder);
|
||||
atapi_dev->bus_state = BUS_IO | BUS_REQ;
|
||||
ide_irq_raise(atapi_dev->ide);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -473,5 +532,34 @@ void atapi_process_packet(atapi_device_t *atapi_dev)
|
|||
idecallback[atapi_dev->board] = 6 * IDE_TIME;
|
||||
}
|
||||
break;
|
||||
|
||||
case ATAPI_STATE_RETRY_READ_DMA:
|
||||
{
|
||||
if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos))
|
||||
{
|
||||
idecallback[atapi_dev->board] = 1*IDE_TIME;
|
||||
}
|
||||
else
|
||||
{
|
||||
atapi_dev->state = ATAPI_STATE_NEXT_PHASE;
|
||||
idecallback[atapi_dev->board] = 6*IDE_TIME;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ATAPI_STATE_RETRY_WRITE_DMA:
|
||||
{
|
||||
if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos))
|
||||
{
|
||||
idecallback[atapi_dev->board] = 1*IDE_TIME;
|
||||
}
|
||||
else
|
||||
{
|
||||
atapi_dev->bus_state = 0;
|
||||
atapi_dev->state = ATAPI_STATE_WRITE_DATA;
|
||||
idecallback[atapi_dev->board] = 6 * IDE_TIME;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,11 +53,13 @@ typedef struct atapi_device_t
|
|||
uint8_t *atastat;
|
||||
uint8_t *error;
|
||||
int *cylinder;
|
||||
|
||||
int use_dma;
|
||||
} atapi_device_t;
|
||||
|
||||
void atapi_data_write(atapi_device_t *atapi_dev, uint16_t val);
|
||||
uint16_t atapi_data_read(atapi_device_t *atapi_dev);
|
||||
void atapi_command_start(atapi_device_t *atapi);
|
||||
void atapi_command_start(atapi_device_t *atapi, uint8_t features);
|
||||
uint8_t atapi_read_iir(atapi_device_t *atapi_dev);
|
||||
uint8_t atapi_read_drq(atapi_device_t *atapi_dev);
|
||||
void atapi_process_packet(atapi_device_t *atapi_dev);
|
||||
|
|
|
|||
44
src/piix.c
44
src/piix.c
|
|
@ -216,21 +216,21 @@ uint8_t piix_bus_master_read(uint16_t port, void *priv)
|
|||
return 0xff;
|
||||
}
|
||||
|
||||
int piix_bus_master_sector_read(int channel, uint8_t *data)
|
||||
int piix_bus_master_data_read(int channel, uint8_t *data, int size)
|
||||
{
|
||||
int transferred = 0;
|
||||
|
||||
if (!(piix_busmaster[channel].status & 1))
|
||||
return 1; /*DMA disabled*/
|
||||
|
||||
while (transferred < 512)
|
||||
while (transferred < size)
|
||||
{
|
||||
if (piix_busmaster[channel].count < (512 - transferred) && piix_busmaster[channel].eot)
|
||||
fatal("DMA on channel %i - Read count less than 512! Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot);
|
||||
if (piix_busmaster[channel].count < (size - transferred) && piix_busmaster[channel].eot)
|
||||
fatal("DMA on channel %i - Read count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot, size);
|
||||
|
||||
mem_invalidate_range(piix_busmaster[channel].addr, piix_busmaster[channel].addr+511);
|
||||
mem_invalidate_range(piix_busmaster[channel].addr, piix_busmaster[channel].addr+(size-1));
|
||||
|
||||
if (piix_busmaster[channel].count < (512 - transferred))
|
||||
if (piix_busmaster[channel].count < (size - transferred))
|
||||
{
|
||||
// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count);
|
||||
if (piix_busmaster[channel].addr < (mem_size * 1024))
|
||||
|
|
@ -246,17 +246,17 @@ int piix_bus_master_sector_read(int channel, uint8_t *data)
|
|||
}
|
||||
else
|
||||
{
|
||||
// pclog("Transferring larger - %i bytes\n", 512 - transferred);
|
||||
// pclog("Transferring larger - %i bytes\n", size - transferred);
|
||||
if (piix_busmaster[channel].addr < (mem_size * 1024))
|
||||
{
|
||||
int count = 512 - transferred;
|
||||
int count = size - transferred;
|
||||
if ((piix_busmaster[channel].addr + count) > (mem_size * 1024))
|
||||
count = (mem_size * 1024) - piix_busmaster[channel].addr;
|
||||
memcpy(&ram[piix_busmaster[channel].addr], data + transferred, count);
|
||||
}
|
||||
piix_busmaster[channel].addr += (512 - transferred);
|
||||
piix_busmaster[channel].count -= (512 - transferred);
|
||||
transferred += (512 - transferred);
|
||||
piix_busmaster[channel].addr += (size - transferred);
|
||||
piix_busmaster[channel].count -= (size - transferred);
|
||||
transferred += (size - transferred);
|
||||
}
|
||||
|
||||
// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot);
|
||||
|
|
@ -275,19 +275,19 @@ int piix_bus_master_sector_read(int channel, uint8_t *data)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
int piix_bus_master_sector_write(int channel, uint8_t *data)
|
||||
int piix_bus_master_data_write(int channel, uint8_t *data, int size)
|
||||
{
|
||||
int transferred = 0;
|
||||
|
||||
if (!(piix_busmaster[channel].status & 1))
|
||||
return 1; /*DMA disabled*/
|
||||
|
||||
while (transferred < 512)
|
||||
while (transferred < size)
|
||||
{
|
||||
if (piix_busmaster[channel].count < (512 - transferred) && piix_busmaster[channel].eot)
|
||||
fatal("DMA on channel %i - Write count less than 512! Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot);
|
||||
if (piix_busmaster[channel].count < (size - transferred) && piix_busmaster[channel].eot)
|
||||
fatal("DMA on channel %i - Write count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot, size);
|
||||
|
||||
if (piix_busmaster[channel].count < (512 - transferred))
|
||||
if (piix_busmaster[channel].count < (size - transferred))
|
||||
{
|
||||
// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count);
|
||||
if (piix_busmaster[channel].addr < (mem_size * 1024))
|
||||
|
|
@ -303,17 +303,17 @@ int piix_bus_master_sector_write(int channel, uint8_t *data)
|
|||
}
|
||||
else
|
||||
{
|
||||
// pclog("Transferring larger - %i bytes\n", 512 - transferred);
|
||||
// pclog("Transferring larger - %i bytes\n", size - transferred);
|
||||
if (piix_busmaster[channel].addr < (mem_size * 1024))
|
||||
{
|
||||
int count = 512 - transferred;
|
||||
int count = size - transferred;
|
||||
if ((piix_busmaster[channel].addr + count) > (mem_size * 1024))
|
||||
count = (mem_size * 1024) - piix_busmaster[channel].addr;
|
||||
memcpy(data + transferred, &ram[piix_busmaster[channel].addr], count);
|
||||
}
|
||||
piix_busmaster[channel].addr += (512 - transferred);
|
||||
piix_busmaster[channel].count -= (512 - transferred);
|
||||
transferred += (512 - transferred);
|
||||
piix_busmaster[channel].addr += (size - transferred);
|
||||
piix_busmaster[channel].count -= (size - transferred);
|
||||
transferred += (size - transferred);
|
||||
}
|
||||
|
||||
// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot);
|
||||
|
|
@ -377,7 +377,7 @@ void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d)
|
|||
card_piix_ide[0x40] = card_piix_ide[0x41] = 0x00;
|
||||
card_piix_ide[0x42] = card_piix_ide[0x43] = 0x00;
|
||||
|
||||
ide_set_bus_master(piix_bus_master_sector_read, piix_bus_master_sector_write, piix_bus_master_set_irq);
|
||||
ide_set_bus_master(piix_bus_master_data_read, piix_bus_master_data_write, piix_bus_master_set_irq);
|
||||
|
||||
pci_set_card_routing(pci_a, PCI_INTA);
|
||||
pci_set_card_routing(pci_b, PCI_INTB);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ typedef struct scsi_device_t
|
|||
int (*get_bytes_required)(void *p);
|
||||
|
||||
void (*atapi_identify)(uint16_t *buffer, void *p);
|
||||
int (*atapi_set_feature)(uint8_t feature, uint8_t val, void *p);
|
||||
|
||||
uint8_t (*read)(void *p);
|
||||
void (*write)(uint8_t val, void *p);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ibm.h"
|
||||
#include "ide.h"
|
||||
#include "ide_atapi.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi_cd.h"
|
||||
|
|
@ -194,6 +195,8 @@ typedef struct scsi_cd_data_t
|
|||
|
||||
int is_atapi;
|
||||
atapi_device_t *atapi_dev;
|
||||
|
||||
int pio_mode, mdma_mode;
|
||||
} scsi_cd_data_t;
|
||||
|
||||
static void scsi_add_data(scsi_cd_data_t *data, uint8_t val)
|
||||
|
|
@ -1171,16 +1174,72 @@ static int scsi_cd_get_bytes_required(void *p)
|
|||
|
||||
static void scsi_cd_atapi_identify(uint16_t *buffer, void *p)
|
||||
{
|
||||
scsi_cd_data_t *data = p;
|
||||
|
||||
memset(buffer, 0, 512);
|
||||
|
||||
buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */
|
||||
ide_padstr((char *)(buffer + 10), "", 20); /* Serial Number */
|
||||
ide_padstr((char *)(buffer + 23), "v1.0", 8); /* Firmware */
|
||||
ide_padstr((char *)(buffer + 27), "PCemCD", 40); /* Model */
|
||||
buffer[49] = 0x200; /* LBA supported */
|
||||
buffer[49] = 0x300; /*DMA and LBA supported*/
|
||||
buffer[51] = 120;
|
||||
buffer[52] = 120;
|
||||
buffer[53] = 2; /*Words 64-70 are valid*/
|
||||
buffer[62] = 0x0000;
|
||||
buffer[63] = 0x0007 | (0x100 << data->mdma_mode); /*Multi-word DMA 0, 1 & 2*/
|
||||
buffer[64] = 0x0003; /*PIO Modes 3 & 4*/
|
||||
if (data->pio_mode >= 3)
|
||||
buffer[64] |= (0x100 << (data->pio_mode - 3));
|
||||
buffer[65] = 120; /*Minimum multi-word cycle time*/
|
||||
buffer[66] = 120; /*Recommended multi-word cycle time*/
|
||||
buffer[67] = 120; /*Minimum PIO cycle time*/
|
||||
buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */
|
||||
}
|
||||
|
||||
static int scsi_cd_atapi_set_feature(uint8_t feature, uint8_t val, void *p)
|
||||
{
|
||||
scsi_cd_data_t *data = p;
|
||||
|
||||
switch (feature)
|
||||
{
|
||||
case FEATURE_SET_TRANSFER_MODE:
|
||||
if (!(val & 0xfe))
|
||||
{
|
||||
/*Default transfer mode*/
|
||||
data->pio_mode = 0;
|
||||
return 1;
|
||||
}
|
||||
else if ((val & 0xf8) == 0x08)
|
||||
{
|
||||
/*PIO transfer mode*/
|
||||
if ((val & 7) > 4)
|
||||
return 0;
|
||||
data->pio_mode = (val & 7);
|
||||
return 1;
|
||||
}
|
||||
else if ((val & 0xf8) == 0x20)
|
||||
{
|
||||
/*Multi-word DMA transfer mode*/
|
||||
if ((val & 7) > 2)
|
||||
return 0;
|
||||
data->mdma_mode = (val & 7);
|
||||
return 1;
|
||||
}
|
||||
return 0; /*Invalid data*/
|
||||
|
||||
case FEATURE_ENABLE_IRQ_OVERLAPPED:
|
||||
case FEATURE_ENABLE_IRQ_SERVICE:
|
||||
case FEATURE_DISABLE_REVERT:
|
||||
case FEATURE_DISABLE_IRQ_OVERLAPPED:
|
||||
case FEATURE_DISABLE_IRQ_SERVICE:
|
||||
case FEATURE_ENABLE_REVERT:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0; /*Feature not supported*/
|
||||
}
|
||||
|
||||
scsi_device_t scsi_cd =
|
||||
{
|
||||
scsi_cd_init,
|
||||
|
|
@ -1195,6 +1254,7 @@ scsi_device_t scsi_cd =
|
|||
scsi_cd_get_bytes_required,
|
||||
|
||||
scsi_cd_atapi_identify,
|
||||
scsi_cd_atapi_set_feature,
|
||||
|
||||
scsi_cd_read,
|
||||
scsi_cd_write,
|
||||
|
|
|
|||
|
|
@ -826,6 +826,7 @@ scsi_device_t scsi_hd =
|
|||
scsi_hd_get_sense_key,
|
||||
scsi_hd_get_bytes_required,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
scsi_hd_read,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <string.h>
|
||||
#include "ibm.h"
|
||||
#include "hdd_file.h"
|
||||
#include "ide.h"
|
||||
#include "ide_atapi.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi_zip.h"
|
||||
|
|
@ -73,6 +74,8 @@ typedef struct scsi_zip_data
|
|||
atapi_device_t *atapi_dev;
|
||||
|
||||
int read_only;
|
||||
|
||||
int pio_mode, mdma_mode;
|
||||
} scsi_zip_data;
|
||||
|
||||
static scsi_zip_data *zip_data;
|
||||
|
|
@ -1077,16 +1080,72 @@ static int scsi_zip_get_bytes_required(void *p)
|
|||
|
||||
static void scsi_zip_atapi_identify(uint16_t *buffer, void *p)
|
||||
{
|
||||
scsi_zip_data *data = p;
|
||||
|
||||
memset(buffer, 0, 512);
|
||||
|
||||
buffer[0] = 0x8000 | (0<<8) | 0x80 | (2<<5); /* ATAPI device, direct-access device, removable media, accelerated DRQ */
|
||||
ide_padstr((char *)(buffer + 10), "", 20); /* Serial Number */
|
||||
ide_padstr((char *)(buffer + 23), "E.08", 8); /* Firmware */
|
||||
ide_padstr((char *)(buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */
|
||||
buffer[49] = 0x200; /* LBA supported */
|
||||
buffer[49] = 0x300; /*DMA and LBA supported*/
|
||||
buffer[51] = 120;
|
||||
buffer[52] = 120;
|
||||
buffer[53] = 2; /*Words 64-70 are valid*/
|
||||
buffer[62] = 0x0000;
|
||||
buffer[63] = 0x0003 | (0x100 << data->mdma_mode); /*Multi-word DMA 0 & 1*/
|
||||
buffer[64] = 0x0001; /*PIO Mode 3*/
|
||||
if (data->pio_mode >= 3)
|
||||
buffer[64] |= (0x100 << (data->pio_mode - 3));
|
||||
buffer[65] = 120; /*Minimum multi-word cycle time*/
|
||||
buffer[66] = 120; /*Recommended multi-word cycle time*/
|
||||
buffer[67] = 120; /*Minimum PIO cycle time*/
|
||||
buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */
|
||||
}
|
||||
|
||||
static int scsi_zip_atapi_set_feature(uint8_t feature, uint8_t val, void *p)
|
||||
{
|
||||
scsi_zip_data *data = p;
|
||||
|
||||
switch (feature)
|
||||
{
|
||||
case FEATURE_SET_TRANSFER_MODE:
|
||||
if (!(val & 0xfe))
|
||||
{
|
||||
/*Default transfer mode*/
|
||||
data->pio_mode = 0;
|
||||
return 1;
|
||||
}
|
||||
else if ((val & 0xf8) == 0x08)
|
||||
{
|
||||
/*PIO transfer mode*/
|
||||
if ((val & 7) > 3)
|
||||
return 0;
|
||||
data->pio_mode = (val & 7);
|
||||
return 1;
|
||||
}
|
||||
else if ((val & 0xf8) == 0x20)
|
||||
{
|
||||
/*Multi-word DMA transfer mode*/
|
||||
if ((val & 7) > 1)
|
||||
return 0;
|
||||
data->mdma_mode = (val & 7);
|
||||
return 1;
|
||||
}
|
||||
return 0; /*Invalid data*/
|
||||
|
||||
case FEATURE_ENABLE_IRQ_OVERLAPPED:
|
||||
case FEATURE_ENABLE_IRQ_SERVICE:
|
||||
case FEATURE_DISABLE_REVERT:
|
||||
case FEATURE_DISABLE_IRQ_OVERLAPPED:
|
||||
case FEATURE_DISABLE_IRQ_SERVICE:
|
||||
case FEATURE_ENABLE_REVERT:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0; /*Feature not supported*/
|
||||
}
|
||||
|
||||
scsi_device_t scsi_zip =
|
||||
{
|
||||
scsi_zip_init,
|
||||
|
|
@ -1101,6 +1160,7 @@ scsi_device_t scsi_zip =
|
|||
scsi_zip_get_bytes_required,
|
||||
|
||||
scsi_zip_atapi_identify,
|
||||
scsi_zip_atapi_set_feature,
|
||||
|
||||
scsi_zip_read,
|
||||
scsi_zip_write,
|
||||
|
|
|
|||
Loading…
Reference in a new issue