Line 32... |
Line 32... |
|
|
/* Package includes */
|
/* Package includes */
|
#include "atadevice-cmdi.h"
|
#include "atadevice-cmdi.h"
|
#include "atahost.h"
|
#include "atahost.h"
|
#include "atacmd.h"
|
#include "atacmd.h"
|
#include "debug.h"
|
|
#include "sched.h"
|
#include "sched.h"
|
|
|
|
|
DEFAULT_DEBUG_CHANNEL (ata);
|
|
|
|
/* FIXME: If device0 is not selected and then an interrupt occurs and
|
/* FIXME: If device0 is not selected and then an interrupt occurs and
|
* then it is selected, the interrupt should be delivered, but I just drop it
|
* then it is selected, the interrupt should be delivered, but I just drop it
|
* (same goes for device 1). */
|
* (same goes for device 1). */
|
static void
|
static void
|
ata_cmd_complete (void *dat)
|
ata_cmd_complete (void *dat)
|
{
|
{
|
struct ata_device *dev = dat;
|
struct ata_device *dev = dat;
|
|
|
TRACE ("Cmd completed intrq: %i, dev: %i\n", dev->sigs.intrq,
|
|
dev->internals.dev ? 1 : 0);
|
|
|
|
dev->regs.status &= ~ATA_SR_BSY;
|
dev->regs.status &= ~ATA_SR_BSY;
|
|
|
if (dev->regs.device_control & ATA_DCR_IEN)
|
if (dev->regs.device_control & ATA_DCR_IEN)
|
return;
|
return;
|
|
|
Line 123... |
Line 117... |
ata_read_sect (struct ata_device *dev)
|
ata_read_sect (struct ata_device *dev)
|
{
|
{
|
if (!dev->internals.nr_sect)
|
if (!dev->internals.nr_sect)
|
return;
|
return;
|
|
|
TRACE ("Reading sector from %" PRId32 "\n", dev->internals.lba);
|
|
|
|
/* set the file-positon pointer to the start of the sector */
|
/* set the file-positon pointer to the start of the sector */
|
fseek (dev->conf.stream, dev->internals.lba, SEEK_SET);
|
fseek (dev->conf.stream, dev->internals.lba, SEEK_SET);
|
|
|
/* get the bytes from the stream */
|
/* get the bytes from the stream */
|
fread (dev->internals.dbuf, BYTES_PER_SECTOR, 1, dev->conf.stream);
|
fread (dev->internals.dbuf, BYTES_PER_SECTOR, 1, dev->conf.stream);
|
Line 154... |
Line 146... |
{
|
{
|
dev->regs.status = ATA_SR_DRDY;
|
dev->regs.status = ATA_SR_DRDY;
|
return;
|
return;
|
}
|
}
|
|
|
TRACE ("Writeing sector to %" PRId32 "\n", dev->internals.lba);
|
|
|
|
/* set the file-positon pointer to the start of the sector */
|
/* set the file-positon pointer to the start of the sector */
|
fseek (dev->conf.stream, dev->internals.lba, SEEK_SET);
|
fseek (dev->conf.stream, dev->internals.lba, SEEK_SET);
|
|
|
/* get the bytes from the stream */
|
/* get the bytes from the stream */
|
fwrite (dev->internals.dbuf, BYTES_PER_SECTOR, 1, dev->conf.stream);
|
fwrite (dev->internals.dbuf, BYTES_PER_SECTOR, 1, dev->conf.stream);
|
Line 211... |
Line 201... |
A T A _ E X E C U T E _ D E V I C E _ D I A G N O S T I C S
|
A T A _ E X E C U T E _ D E V I C E _ D I A G N O S T I C S
|
*/
|
*/
|
void
|
void
|
ata_execute_device_diagnostics_cmd (struct ata_device *device)
|
ata_execute_device_diagnostics_cmd (struct ata_device *device)
|
{
|
{
|
/* print debug information */
|
|
TRACE ("executing command 'execute_device_diagnostics'\n");
|
|
|
|
/* clear SRST bit, if set */
|
/* clear SRST bit, if set */
|
device->regs.device_control &= ~ATA_DCR_RST;
|
device->regs.device_control &= ~ATA_DCR_RST;
|
|
|
/* content of features register is undefined */
|
/* content of features register is undefined */
|
|
|
Line 264... |
Line 251... |
A T A _ D E V I C E _ R E S E T
|
A T A _ D E V I C E _ R E S E T
|
*/
|
*/
|
static void
|
static void
|
ata_device_reset_cmd (struct ata_device *device)
|
ata_device_reset_cmd (struct ata_device *device)
|
{
|
{
|
/* print debug information */
|
|
TRACE ("executing command 'device reset'\n");
|
|
|
|
if (!device->conf.packet)
|
if (!device->conf.packet)
|
WARN ("executing DEVICE_RESET on non-packet device.");
|
{
|
|
fprintf( stderr, "Warning: executing DEVICE_RESET on non-packet "
|
|
"device\n");
|
|
}
|
|
|
ata_execute_device_diagnostics_cmd (device);
|
ata_execute_device_diagnostics_cmd (device);
|
}
|
}
|
|
|
|
|
Line 285... |
Line 272... |
unsigned char *chksum_buf, chksum;
|
unsigned char *chksum_buf, chksum;
|
unsigned short *buf;
|
unsigned short *buf;
|
int n;
|
int n;
|
unsigned int tmp;
|
unsigned int tmp;
|
|
|
/* print debug information */
|
|
TRACE ("ata_device executing command 'identify device'\n");
|
|
|
|
/* reset databuffer */
|
/* reset databuffer */
|
device->internals.dbuf_cnt = 256;
|
device->internals.dbuf_cnt = 256;
|
device->internals.dbuf_ptr = device->internals.dbuf;
|
device->internals.dbuf_ptr = device->internals.dbuf;
|
device->internals.end_t_func = NULL;
|
device->internals.end_t_func = NULL;
|
|
|
Line 360... |
Line 344... |
/*
|
/*
|
This is a PACKET device.
|
This is a PACKET device.
|
Respond by placing PACKET Command feature set signature in block registers.
|
Respond by placing PACKET Command feature set signature in block registers.
|
Abort command.
|
Abort command.
|
*/
|
*/
|
TRACE ("'identify_device' command: This is a PACKET device\n");
|
|
|
|
ata_set_device_signature (device, 1);
|
ata_set_device_signature (device, 1);
|
device->regs.status = ATA_SR_ERR;
|
device->regs.status = ATA_SR_ERR;
|
device->regs.error = ATA_ERR_ABT;
|
device->regs.error = ATA_ERR_ABT;
|
}
|
}
|
Line 928... |
Line 911... |
A T A _ I N I T I A L I Z E _ D E V I C E _ P A R A M E T E R S
|
A T A _ I N I T I A L I Z E _ D E V I C E _ P A R A M E T E R S
|
*/
|
*/
|
static void
|
static void
|
ata_initialize_device_parameters_cmd (struct ata_device *device)
|
ata_initialize_device_parameters_cmd (struct ata_device *device)
|
{
|
{
|
/* print debug information */
|
|
TRACE ("executing command 'initialize device parameters'\n");
|
|
|
|
device->internals.sectors_per_track = device->regs.sector_count;
|
device->internals.sectors_per_track = device->regs.sector_count;
|
device->internals.heads_per_cylinder = device->regs.device_head & ATA_DHR_H;
|
device->internals.heads_per_cylinder = device->regs.device_head & ATA_DHR_H;
|
|
|
/* set status register bits */
|
/* set status register bits */
|
device->regs.status = ATA_SR_BSY | ATA_SR_DRDY;
|
device->regs.status = ATA_SR_BSY | ATA_SR_DRDY;
|
Line 948... |
Line 928... |
ata_read_sectors_cmd (struct ata_device *device)
|
ata_read_sectors_cmd (struct ata_device *device)
|
{
|
{
|
size_t sector_count;
|
size_t sector_count;
|
uint32_t lba;
|
uint32_t lba;
|
|
|
/* print debug information */
|
|
TRACE ("executing command 'read sectors'\n");
|
|
|
|
/* check if this is a NON-PACKET device */
|
/* check if this is a NON-PACKET device */
|
if (device->conf.packet)
|
if (device->conf.packet)
|
{
|
{
|
/*
|
/*
|
This is a PACKET device.
|
This is a PACKET device.
|
Respond by placing PACKET Command feature set signature in block registers.
|
Respond by placing PACKET Command feature set signature in block registers.
|
Abort command.
|
Abort command.
|
*/
|
*/
|
TRACE ("'identify_device' command: This is a PACKET device\n");
|
|
|
|
ata_set_device_signature (device, 1);
|
ata_set_device_signature (device, 1);
|
device->regs.status = ATA_SR_ERR | ATA_SR_DRDY;
|
device->regs.status = ATA_SR_ERR | ATA_SR_DRDY;
|
device->regs.error = ATA_ERR_ABT;
|
device->regs.error = ATA_ERR_ABT;
|
return;
|
return;
|
}
|
}
|
Line 975... |
Line 950... |
else
|
else
|
sector_count = device->regs.sector_count;
|
sector_count = device->regs.sector_count;
|
|
|
lba = ata_calc_lba (device);
|
lba = ata_calc_lba (device);
|
|
|
TRACE ("Reading from lba %i, %i sectors\n", lba, sector_count);
|
|
|
|
/* check if sector within bounds */
|
/* check if sector within bounds */
|
if (lba >= device->conf.size_sect)
|
if (lba >= device->conf.size_sect)
|
{
|
{
|
/* invalid sector address */
|
/* invalid sector address */
|
/* set the status & error registers */
|
/* set the status & error registers */
|
TRACE ("Sector read out-of-bounds: %i >= %i\n", lba,
|
|
device->conf.size_sect);
|
|
device->regs.status = ATA_SR_DRDY | ATA_SR_ERR;
|
device->regs.status = ATA_SR_DRDY | ATA_SR_ERR;
|
device->regs.error = ATA_ERR_IDNF;
|
device->regs.error = ATA_ERR_IDNF;
|
return;
|
return;
|
}
|
}
|
|
|
Line 1007... |
Line 978... |
A T A _ R E A D _ N A T I V E _ M A X _ A D D R
|
A T A _ R E A D _ N A T I V E _ M A X _ A D D R
|
*/
|
*/
|
static void
|
static void
|
ata_read_native_max_addr (struct ata_device *dev)
|
ata_read_native_max_addr (struct ata_device *dev)
|
{
|
{
|
TRACE ("executing command 'read native max addr'\n");
|
|
// FIXME: Left shift????
|
// FIXME: Left shift????
|
ata_set_sect (dev, dev->conf.size << 11);
|
ata_set_sect (dev, dev->conf.size << 11);
|
|
|
dev->regs.status = ATA_SR_DRDY | ATA_SR_BSY;
|
dev->regs.status = ATA_SR_DRDY | ATA_SR_BSY;
|
}
|
}
|
Line 1023... |
Line 993... |
ata_write_sectors (struct ata_device *dev)
|
ata_write_sectors (struct ata_device *dev)
|
{
|
{
|
size_t sector_count;
|
size_t sector_count;
|
uint32_t lba;
|
uint32_t lba;
|
|
|
TRACE ("executing command 'write sectors'\n");
|
|
|
|
if (dev->conf.packet)
|
if (dev->conf.packet)
|
{
|
{
|
ata_set_device_signature (dev, 1);
|
ata_set_device_signature (dev, 1);
|
dev->regs.status = ATA_SR_ERR | ATA_SR_DRDY;
|
dev->regs.status = ATA_SR_ERR | ATA_SR_DRDY;
|
dev->regs.error = ATA_ERR_ABT;
|
dev->regs.error = ATA_ERR_ABT;
|
Line 1041... |
Line 1009... |
else
|
else
|
sector_count = dev->regs.sector_count;
|
sector_count = dev->regs.sector_count;
|
|
|
lba = ata_calc_lba (dev);
|
lba = ata_calc_lba (dev);
|
|
|
TRACE ("Writeing to lba %i, %i sectors\n", lba, sector_count);
|
|
|
|
/* check if sector within bounds */
|
/* check if sector within bounds */
|
if (lba >= dev->conf.size_sect)
|
if (lba >= dev->conf.size_sect)
|
{
|
{
|
/* invalid sector address */
|
/* invalid sector address */
|
/* set the status & error registers */
|
/* set the status & error registers */
|
TRACE ("Sector read out-of-bounds: %i >= %i\n", lba,
|
|
dev->conf.size_sect);
|
|
dev->regs.status = ATA_SR_DRDY | ATA_SR_ERR;
|
dev->regs.status = ATA_SR_DRDY | ATA_SR_ERR;
|
dev->regs.error = ATA_ERR_IDNF;
|
dev->regs.error = ATA_ERR_IDNF;
|
return;
|
return;
|
}
|
}
|
|
|
Line 1080... |
Line 1044... |
switch (dev->regs.sector_count >> 3)
|
switch (dev->regs.sector_count >> 3)
|
{
|
{
|
case 0: /* Set default */
|
case 0: /* Set default */
|
break;
|
break;
|
case 1: /* Set PIO mode */
|
case 1: /* Set PIO mode */
|
TRACE ("Setting device pio mode %d\n",
|
|
dev->regs.sector_count & 0x7);
|
|
break;
|
break;
|
case 4: /* Set DMA mode */
|
case 4: /* Set DMA mode */
|
FIXME ("Set DMA mode to %d\n", dev->regs.sector_count & 0x7);
|
/* FIXME */
|
|
fprintf (stderr, "Fixme: Set DMA mode to %d\n",
|
|
dev->regs.sector_count & 0x7);
|
break;
|
break;
|
case 8: /* Set UDMA mode */
|
case 8: /* Set UDMA mode */
|
FIXME ("Set UDMA mode to %d\n", dev->regs.sector_count & 0x7);
|
/* FIXME */
|
|
fprintf (stderr, "Fixme: Set UDMA mode to %d\n",
|
|
dev->regs.sector_count & 0x7);
|
break;
|
break;
|
}
|
}
|
dev->regs.status = ATA_SR_DSC | ATA_SR_DRDY | ATA_SR_BSY;
|
dev->regs.status = ATA_SR_DSC | ATA_SR_DRDY | ATA_SR_BSY;
|
break;
|
break;
|
default:
|
default:
|
dev->regs.error = ATA_ERR_ABT;
|
dev->regs.error = ATA_ERR_ABT;
|
dev->regs.status = ATA_SR_ERR | ATA_SR_BSY | ATA_SR_DRDY;
|
dev->regs.status = ATA_SR_ERR | ATA_SR_BSY | ATA_SR_DRDY;
|
FIXME ("Unknown set features sub-command %x\n", dev->regs.features);
|
/* FIXME */
|
|
fprintf (stderr, "Fixme: Unknown set features sub-command %x\n",
|
|
dev->regs.features);
|
}
|
}
|
}
|
}
|
|
|
|
|
int
|
int
|
ata_device_execute_cmd (struct ata_device *device)
|
ata_device_execute_cmd (struct ata_device *device)
|
{
|
{
|
/*display debug information */
|
|
TRACE ("command: 0x%02X\n", device->regs.command);
|
|
|
|
/* execute the commands */
|
/* execute the commands */
|
switch (device->regs.command)
|
switch (device->regs.command)
|
{
|
{
|
case DEVICE_RESET:
|
case DEVICE_RESET:
|
ata_device_reset_cmd (device);
|
ata_device_reset_cmd (device);
|
Line 1154... |
Line 1119... |
return 0;
|
return 0;
|
|
|
default:
|
default:
|
device->regs.error = ATA_ERR_ABT;
|
device->regs.error = ATA_ERR_ABT;
|
device->regs.status = ATA_SR_ERR | ATA_SR_BSY | ATA_SR_DRDY;
|
device->regs.status = ATA_SR_ERR | ATA_SR_BSY | ATA_SR_DRDY;
|
FIXME ("Unknown command %x\n", device->regs.command);
|
/* FIXME */
|
|
fprintf (stderr, "Fixme: Unknown command %x\n", device->regs.command);
|
SCHED_ADD (ata_cmd_complete, device, 40000);
|
SCHED_ADD (ata_cmd_complete, device, 40000);
|
return -1;
|
return -1;
|
}
|
}
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|