Changeset 15d0046 in mainline for uspace/drv/block/ata_bd/ata_bd.c


Ignore:
Timestamp:
2014-09-12T13:22:33Z (10 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9b20126
Parents:
8db09e4 (diff), 105d8d6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/block/ata_bd/ata_bd.c

    r8db09e4 r15d0046  
    5454#include <bd_srv.h>
    5555#include <fibril_synch.h>
     56#include <scsi/mmc.h>
     57#include <scsi/sbc.h>
     58#include <scsi/spc.h>
    5659#include <stdint.h>
    5760#include <str.h>
     
    9497static int ata_bd_get_block_size(bd_srv_t *, size_t *);
    9598static int ata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
     99static int ata_bd_sync_cache(bd_srv_t *, aoff64_t, size_t);
    96100
    97101static int ata_rcmd_read(disk_t *disk, uint64_t ba, size_t cnt,
     
    99103static int ata_rcmd_write(disk_t *disk, uint64_t ba, size_t cnt,
    100104    const void *buf);
     105static int ata_rcmd_flush_cache(disk_t *disk);
    101106static int disk_init(ata_ctrl_t *ctrl, disk_t *d, int disk_id);
    102107static int ata_identify_dev(disk_t *disk, void *buf);
    103108static int ata_identify_pkt_dev(disk_t *disk, void *buf);
    104109static int ata_cmd_packet(disk_t *disk, const void *cpkt, size_t cpkt_size,
    105     void *obuf, size_t obuf_size);
    106 static int ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size);
     110    void *obuf, size_t obuf_size, size_t *rcvd_size);
     111static int ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size,
     112    size_t *rcvd_size);
    107113static int ata_pcmd_read_12(disk_t *disk, uint64_t ba, size_t cnt,
    108114    void *obuf, size_t obuf_size);
     115static int ata_pcmd_read_capacity(disk_t *disk, uint64_t *nblocks,
     116    size_t *block_size);
    109117static int ata_pcmd_read_toc(disk_t *disk, uint8_t ses,
    110118    void *obuf, size_t obuf_size);
     
    123131        .write_blocks = ata_bd_write_blocks,
    124132        .get_block_size = ata_bd_get_block_size,
    125         .get_num_blocks = ata_bd_get_num_blocks
     133        .get_num_blocks = ata_bd_get_num_blocks,
     134        .sync_cache = ata_bd_sync_cache
    126135};
    127136
     
    339348        identify_data_t idata;
    340349        uint8_t model[40];
    341         ata_inquiry_data_t inq_data;
     350        scsi_std_inquiry_data_t inq_data;
     351        size_t isize;
    342352        uint16_t w;
    343353        uint8_t c;
    344354        uint16_t bc;
     355        uint64_t nblocks;
     356        size_t block_size;
    345357        size_t pos, len;
    346358        int rc;
     
    457469        if (d->dev_type == ata_pkt_dev) {
    458470                /* Send inquiry. */
    459                 rc = ata_pcmd_inquiry(d, &inq_data, sizeof(inq_data));
    460                 if (rc != EOK) {
     471                rc = ata_pcmd_inquiry(d, &inq_data, sizeof(inq_data), &isize);
     472                if (rc != EOK || isize < sizeof(inq_data)) {
    461473                        ddf_msg(LVL_ERROR, "Device inquiry failed.");
    462474                        d->present = false;
     
    465477
    466478                /* Check device type. */
    467                 if (INQUIRY_PDEV_TYPE(inq_data.pdev_type) != PDEV_TYPE_CDROM)
     479                if (INQUIRY_PDEV_TYPE(inq_data.pqual_devtype) != SCSI_DEV_CD_DVD)
    468480                        ddf_msg(LVL_WARN, "Peripheral device type is not CD-ROM.");
    469481
    470                 /* Assume 2k block size for now. */
    471                 d->block_size = 2048;
     482                rc = ata_pcmd_read_capacity(d, &nblocks, &block_size);
     483                if (rc != EOK) {
     484                        ddf_msg(LVL_ERROR, "Read capacity command failed.");
     485                        d->present = false;
     486                        return EIO;
     487                }
     488
     489                d->blocks = nblocks;
     490                d->block_size = block_size;
    472491        } else {
    473492                /* Assume register Read always uses 512-byte blocks. */
     
    570589}
    571590
     591/** Flush cache. */
     592static int ata_bd_sync_cache(bd_srv_t *bd, uint64_t ba, size_t cnt)
     593{
     594        disk_t *disk = bd_srv_disk(bd);
     595
     596        /* ATA cannot flush just some blocks, we just flush everything. */
     597        (void)ba;
     598        (void)cnt;
     599
     600        return ata_rcmd_flush_cache(disk);
     601}
     602
    572603/** PIO data-in command protocol. */
    573604static int ata_pio_data_in(disk_t *disk, void *obuf, size_t obuf_size,
     
    623654                }
    624655        }
     656
     657        if (status & SR_ERR)
     658                return EIO;
     659
     660        return EOK;
     661}
     662
     663/** PIO non-data command protocol. */
     664static int ata_pio_nondata(disk_t *disk)
     665{
     666        ata_ctrl_t *ctrl = disk->ctrl;
     667        uint8_t status;
     668
     669        if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
     670                return EIO;
    625671
    626672        if (status & SR_ERR)
     
    722768 * @param obuf          Buffer for storing data read from device
    723769 * @param obuf_size     Size of obuf in bytes
     770 * @param rcvd_size     Place to store number of bytes read or @c NULL
    724771 *
    725772 * @return EOK on success, EIO on error.
    726773 */
    727774static int ata_cmd_packet(disk_t *disk, const void *cpkt, size_t cpkt_size,
    728     void *obuf, size_t obuf_size)
     775    void *obuf, size_t obuf_size, size_t *rcvd_size)
    729776{
    730777        ata_ctrl_t *ctrl = disk->ctrl;
     
    800847                return EIO;
    801848
     849        if (rcvd_size != NULL)
     850                *rcvd_size = data_size;
    802851        return EOK;
    803852}
     
    811860 * @return EOK on success, EIO on error.
    812861 */
    813 static int ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size)
    814 {
    815         ata_pcmd_inquiry_t cp;
     862static int ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size,
     863    size_t *rcvd_size)
     864{
     865        uint8_t cpb[12];
     866        scsi_cdb_inquiry_t *cp = (scsi_cdb_inquiry_t *)cpb;
    816867        int rc;
    817868
    818         memset(&cp, 0, sizeof(cp));
    819 
    820         cp.opcode = PCMD_INQUIRY;
    821         cp.alloc_len = min(obuf_size, 0xff); /* Allocation length */
    822 
    823         rc = ata_cmd_packet(disk, &cp, sizeof(cp), obuf, obuf_size);
     869        memset(cpb, 0, sizeof(cpb));
     870
     871        /*
     872         * For SFF 8020 compliance the inquiry must be padded to 12 bytes
     873         * and allocation length must fit in one byte.
     874         */
     875        cp->op_code = SCSI_CMD_INQUIRY;
     876
     877        /* Allocation length */
     878        cp->alloc_len = host2uint16_t_be(min(obuf_size, 0xff));
     879
     880        rc = ata_cmd_packet(disk, cpb, sizeof(cpb), obuf, obuf_size, rcvd_size);
    824881        if (rc != EOK)
    825882                return rc;
     883
     884        return EOK;
     885}
     886
     887/** Issue ATAPI read capacity(10) command.
     888 *
     889 * @param disk          Disk
     890 * @param nblocks       Place to store number of blocks
     891 * @param block_size    Place to store block size
     892 *
     893 * @return EOK on success, EIO on error.
     894 */
     895static int ata_pcmd_read_capacity(disk_t *disk, uint64_t *nblocks,
     896    size_t *block_size)
     897{
     898        scsi_cdb_read_capacity_10_t cdb;
     899        scsi_read_capacity_10_data_t data;
     900        size_t rsize;
     901        int rc;
     902
     903        memset(&cdb, 0, sizeof(cdb));
     904        cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
     905
     906        rc = ata_cmd_packet(disk, &cdb, sizeof(cdb), &data, sizeof(data), &rsize);
     907        if (rc != EOK)
     908                return rc;
     909
     910        if (rsize != sizeof(data))
     911                return EIO;
     912
     913        *nblocks = uint32_t_be2host(data.last_lba) + 1;
     914        *block_size = uint32_t_be2host(data.block_size);
    826915
    827916        return EOK;
     
    844933    void *obuf, size_t obuf_size)
    845934{
    846         ata_pcmd_read_12_t cp;
     935        scsi_cdb_read_12_t cp;
    847936        int rc;
    848937
     
    852941        memset(&cp, 0, sizeof(cp));
    853942
    854         cp.opcode = PCMD_READ_12;
    855         cp.ba = host2uint32_t_be(ba);
    856         cp.nblocks = host2uint32_t_be(cnt);
    857 
    858         rc = ata_cmd_packet(disk, &cp, sizeof(cp), obuf, obuf_size);
     943        cp.op_code = SCSI_CMD_READ_12;
     944        cp.lba = host2uint32_t_be(ba);
     945        cp.xfer_len = host2uint32_t_be(cnt);
     946
     947        rc = ata_cmd_packet(disk, &cp, sizeof(cp), obuf, obuf_size, NULL);
    859948        if (rc != EOK)
    860949                return rc;
     
    883972    size_t obuf_size)
    884973{
    885         ata_pcmd_read_toc_t cp;
     974        uint8_t cpb[12];
     975        scsi_cdb_read_toc_t *cp = (scsi_cdb_read_toc_t *)cpb;
    886976        int rc;
    887977
    888         memset(&cp, 0, sizeof(cp));
    889 
    890         cp.opcode = PCMD_READ_TOC;
    891         cp.msf = 0;
    892         cp.format = 0x01; /* 0x01 = multi-session mode */
    893         cp.start = session;
    894         cp.size = host2uint16_t_be(obuf_size);
    895         cp.oldformat = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */
    896        
    897         rc = ata_cmd_packet(disk, &cp, sizeof(cp), obuf, obuf_size);
     978        memset(cpb, 0, sizeof(cpb));
     979
     980        cp->op_code = SCSI_CMD_READ_TOC;
     981        cp->msf = 0;
     982        cp->format = 0x01; /* 0x01 = multi-session mode */
     983        cp->track_sess_no = session;
     984        cp->alloc_len = host2uint16_t_be(obuf_size);
     985        cp->control = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */
     986
     987        rc = ata_cmd_packet(disk, cpb, sizeof(cpb), obuf, obuf_size, NULL);
    898988        if (rc != EOK)
    899989                return rc;
    900        
     990
    901991        return EOK;
    902992}
     
    10161106        rc = ata_pio_data_out(disk, buf, cnt * disk->block_size,
    10171107            disk->block_size, cnt);
     1108
     1109        fibril_mutex_unlock(&ctrl->lock);
     1110        return rc;
     1111}
     1112
     1113/** Flush cached data to nonvolatile storage.
     1114 *
     1115 * @param disk          Disk
     1116 *
     1117 * @return EOK on success, EIO on error.
     1118 */
     1119static int ata_rcmd_flush_cache(disk_t *disk)
     1120{
     1121        ata_ctrl_t *ctrl = disk->ctrl;
     1122        uint8_t drv_head;
     1123        int rc;
     1124
     1125        /* New value for Drive/Head register */
     1126        drv_head =
     1127            (disk_dev_idx(disk) != 0) ? DHR_DRV : 0;
     1128
     1129        fibril_mutex_lock(&ctrl->lock);
     1130
     1131        /* Program a Flush Cache operation. */
     1132
     1133        if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
     1134                fibril_mutex_unlock(&ctrl->lock);
     1135                return EIO;
     1136        }
     1137
     1138        pio_write_8(&ctrl->cmd->drive_head, drv_head);
     1139
     1140        if (wait_status(ctrl, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
     1141                fibril_mutex_unlock(&ctrl->lock);
     1142                return EIO;
     1143        }
     1144
     1145        pio_write_8(&ctrl->cmd->command, CMD_FLUSH_CACHE);
     1146
     1147        rc = ata_pio_nondata(disk);
    10181148
    10191149        fibril_mutex_unlock(&ctrl->lock);
Note: See TracChangeset for help on using the changeset viewer.