ahci: FUA (force-write) support

This commit is contained in:
David van Moolenbroek 2011-11-23 15:35:07 +01:00
parent b4d909d415
commit 9874865a6f
2 changed files with 22 additions and 8 deletions

View file

@ -541,6 +541,11 @@ PRIVATE int ata_id_check(struct port_state *ps, u16_t *buf)
if (buf[ATA_ID_SUP0] & ATA_ID_SUP0_WCACHE)
ps->flags |= FLAG_HAS_WCACHE;
/* Check Force Unit Access capability of the device. */
if ((buf[ATA_ID_ENA2] & (ATA_ID_ENA2_VALID_MASK | ATA_ID_ENA2_FUA)) ==
(ATA_ID_ENA2_VALID | ATA_ID_ENA2_FUA))
ps->flags |= FLAG_HAS_FUA;
return TRUE;
}
@ -548,11 +553,12 @@ PRIVATE int ata_id_check(struct port_state *ps, u16_t *buf)
* ata_transfer *
*===========================================================================*/
PRIVATE int ata_transfer(struct port_state *ps, int cmd, u64_t start_lba,
unsigned int count, int write, prd_t *prdt, int nr_prds)
unsigned int count, int write, int force, prd_t *prdt, int nr_prds)
{
/* Perform data transfer from or to an ATA device.
*/
cmd_fis_t fis;
u8_t opcode;
assert(count <= ATA_MAX_SECTORS);
@ -561,8 +567,13 @@ PRIVATE int ata_transfer(struct port_state *ps, int cmd, u64_t start_lba,
count = 0;
/* Fill in a transfer command. */
if (write && force && (ps->flags & FLAG_HAS_FUA))
opcode = ATA_CMD_WRITE_DMA_FUA_EXT;
else
opcode = write ? ATA_CMD_WRITE_DMA_EXT : ATA_CMD_READ_DMA_EXT;
memset(&fis, 0, sizeof(fis));
fis.cf_cmd = write ? ATA_CMD_WRITE_DMA_EXT : ATA_CMD_READ_DMA_EXT;
fis.cf_cmd = opcode;
fis.cf_lba = ex64lo(start_lba) & 0x00FFFFFFL;
fis.cf_dev = ATA_DEV_LBA;
fis.cf_lba_exp = ex64lo(rshift64(start_lba, 24)) & 0x00FFFFFFL;
@ -945,7 +956,8 @@ PRIVATE int setup_prdt(struct port_state *ps, endpoint_t endpt,
* port_transfer *
*===========================================================================*/
PRIVATE ssize_t port_transfer(struct port_state *ps, int cmd, u64_t pos,
u64_t eof, endpoint_t endpt, iovec_s_t *iovec, int nr_req, int write)
u64_t eof, endpoint_t endpt, iovec_s_t *iovec, int nr_req, int write,
int flags)
{
/* Perform an I/O transfer on a port.
*/
@ -1012,8 +1024,8 @@ PRIVATE ssize_t port_transfer(struct port_state *ps, int cmd, u64_t pos,
r = atapi_transfer(ps, cmd, start_lba, count, write, prdt,
nr_prds);
else
r = ata_transfer(ps, cmd, start_lba, count, write, prdt,
nr_prds);
r = ata_transfer(ps, cmd, start_lba, count, write,
!!(flags & BDEV_FORCEWRITE), prdt, nr_prds);
if (r != OK) return r;
@ -2343,8 +2355,7 @@ PRIVATE int ahci_close(dev_t minor)
* ahci_transfer *
*===========================================================================*/
PRIVATE ssize_t ahci_transfer(dev_t minor, int do_write, u64_t position,
endpoint_t endpt, iovec_t *iovec, unsigned int count,
int UNUSED(flags))
endpoint_t endpt, iovec_t *iovec, unsigned int count, int flags)
{
/* Perform data transfer on the selected device.
*/
@ -2372,7 +2383,7 @@ PRIVATE ssize_t ahci_transfer(dev_t minor, int do_write, u64_t position,
eof = add64(dv->dv_base, dv->dv_size);
return port_transfer(ps, 0, pos, eof, endpt, (iovec_s_t *) iovec,
count, do_write);
count, do_write, flags);
}
/*===========================================================================*

View file

@ -30,6 +30,7 @@
#define ATA_H2D_CMD 2 /* Command */
#define ATA_CMD_READ_DMA_EXT 0x25 /* READ DMA EXT */
#define ATA_CMD_WRITE_DMA_EXT 0x35 /* WRITE DMA EXT */
#define ATA_CMD_WRITE_DMA_FUA_EXT 0x3D /* WRITE DMA FUA EXT */
#define ATA_CMD_PACKET 0xA0 /* PACKET */
#define ATA_CMD_IDENTIFY_PACKET 0xA1 /* IDENTIFY PACKET DEVICE */
#define ATA_CMD_FLUSH_CACHE 0xE7 /* FLUSH CACHE */
@ -84,6 +85,7 @@
#define ATA_ID_ENA2 87 /* Features enabled (3/3) */
#define ATA_ID_ENA2_VALID_MASK 0xC000 /* Word validity mask */
#define ATA_ID_ENA2_VALID 0x4000 /* Word contents are valid */
#define ATA_ID_ENA2_FUA 0x0040 /* Forced Unit Access sup. */
#define ATA_ID_LBA0 100 /* Max. LBA48 address (LSW) */
#define ATA_ID_LBA1 101 /* Max. LBA48 address */
#define ATA_ID_LBA2 102 /* Max. LBA48 address */
@ -271,6 +273,7 @@ enum {
#define FLAG_HAS_WCACHE 0x00000080 /* is a write cache present? */
#define FLAG_HAS_FLUSH 0x00000100 /* is FLUSH CACHE supported? */
#define FLAG_SUSPENDED 0x00000200 /* is the thread suspended? */
#define FLAG_HAS_FUA 0x00000400 /* is WRITE DMA FUA EX sup.? */
/* Mapping between devices and ports. */
#define NO_PORT -1 /* this device maps to no port */