# HG changeset patch # Parent 2eed5d64f7479cc0e80a8ff86035f87c48ab7978 Create a function to generate a Host to Device FIS for commands. diff -r 2eed5d64f747 sys/cam/ata/ata_all.c --- a/sys/cam/ata/ata_all.c +++ b/sys/cam/ata/ata_all.c @@ -478,6 +478,73 @@ ata_pm_write_cmd(struct ccb_ataio *ataio } void +ata_h2d_fis_cmd(struct ccb_satafisio *satafisio, uint8_t cmd, uint8_t subcmd, + uint64_t lba, uint16_t sector_count, uint32_t aux) +{ + uint8_t *fis; + + /* xxx not sure what flags should be here yet */ + satafisio->flags = CAM_ATAIO_48BIT | CAM_ATAIO_FPDMA; + satafisio->fis_cmd_len = 20; /* Host to device len, per standard */ + satafisio->fis_rep_len = 16; /* Response from device */ + + /* + * Construct a standard host to device FIS SATA 10.5.5 + * nb: sector cound lives in the feature register and + * the tag and subcommand live in the count register. + * After Figure 275 in Serial ATA Revision 3.2, converted to bytes + * 0 FIS TYPE (27h Host to Device) + * 1 C|R|R|R|PM Port(3:0) PMP mapped to target_id in CAM + * 2 Command(7:0) Updated only when C set + * 3 Features(7:0) + * 4 LBA(7:0) + * 5 LBA(15:8) + * 6 LBA(23:16) + * 7 Device(7:0) + * 8 LBA(31:24) + * 9 LBA(39:32) + * 10 LBA(47:40) + * 11 Features(15:8) + * 12 Count(7:0) + * 13 Count(15:8) + * 14 ICC(7:0) + * 15 Control(7:0) updated only when C clear + * 16 Auxiliary(7:0) + * 17 Auxiliary(15:8) + * 18 Auxiliary(23:16) + * 19 Auxiliary(31:24) + * 20 --- Total length + */ + fis = satafisio->fis_cmd; + fis[ 0] = 0x27; /* Host to device register dump */ + fis[ 1] = 0x80 | (satafisio->ccb_h.target_id & 0x0f); + fis[ 2] = cmd; + fis[ 3] = sector_count & 0xff; /* Lower half feature register */ + fis[ 4] = (lba >> 0) & 0xff; + fis[ 5] = (lba >> 8) & 0xff; + fis[ 6] = (lba >> 16) & 0xff; + fis[ 7] = ATA_DEV_LBA; + fis[ 8] = (lba >> 24) & 0xff; + fis[ 9] = (lba >> 32) & 0xff; + fis[10] = (lba >> 40) & 0xff; + fis[11] = (sector_count >> 8) & 0xff; /* upper half feature */ + fis[12] = 0; /* Reserved for tag -- sim fills in */ + fis[13] = subcmd; /* And priority */ + fis[14] = 0; /* ICC */ + fis[15] = 0; /* reserved since C clear */ + fis[16] = (aux >> 0) & 0xff; + fis[17] = (aux >> 8) & 0xff; + fis[18] = (aux >> 16) & 0xff; + fis[19] = (aux >> 24) & 0xff; + + /* + * Sim is expected to fill in the tag + * Not sure who owns the priority field (unused atm) + * not sure who owns the icc isosynchronous field (unused atm) + */ +} + +void ata_bswap(int8_t *buf, int len) { u_int16_t *ptr = (u_int16_t*)(buf + len); diff -r 2eed5d64f747 sys/cam/ata/ata_all.h --- a/sys/cam/ata/ata_all.h +++ b/sys/cam/ata/ata_all.h @@ -32,6 +32,7 @@ #include struct ccb_ataio; +struct ccb_satafisio; struct cam_periph; union ccb; @@ -119,6 +120,8 @@ void ata_28bit_cmd(struct ccb_ataio *ata uint32_t lba, uint8_t sector_count); void ata_48bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint16_t features, uint64_t lba, uint16_t sector_count); +void ata_h2d_fis_cmd(struct ccb_satafisio *satafisio, uint8_t cmd, uint8_t subcmd, + uint64_t lba, uint16_t sector_count, uint32_t aux); void ata_ncq_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint64_t lba, uint16_t sector_count); void ata_reset_cmd(struct ccb_ataio *ataio);