Implemented ATAPI DMA transfer modes.
This commit is contained in:
parent
1d5afd1d9a
commit
6602368cc4
9 changed files with 289 additions and 54 deletions
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue