Changeset 88743b5 in mainline


Ignore:
Timestamp:
2011-02-01T05:54:29Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0d247f5
Parents:
7a56e33e
Message:

Implement 'Packet' command (for data-in packet-based commands). Implement Inquiry as an example packet command.

Location:
uspace/srv/bd/ata_bd
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/bd/ata_bd/ata_bd.c

    r7a56e33e r88743b5  
    113113static int drive_identify(int drive_id, void *buf);
    114114static int identify_pkt_dev(int dev_idx, void *buf);
     115static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size,
     116    void *obuf, size_t obuf_size);
     117static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size);
    115118static void disk_print_summary(disk_t *d);
    116119static int coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc);
     
    360363        identify_data_t idata;
    361364        uint8_t model[40];
     365        uint8_t inq_buf[36];
    362366        uint16_t w;
    363367        uint8_t c;
     
    367371
    368372        d->present = false;
     373        fibril_mutex_initialize(&d->lock);
    369374
    370375        /* Try identify command. */
     
    373378                /* Success. It's a register (non-packet) device. */
    374379                printf("ATA register-only device found.\n");
    375                 d->present = true;
    376380                d->dev_type = ata_reg_dev;
    377381        } else if (rc == EIO) {
     
    383387                if (rc == EOK) {
    384388                        /* We have a packet device. */
    385                         d->present = true;
    386389                        d->dev_type = ata_pkt_dev;
    387390                } else {
    388391                        /* Nope. Something's there, but not recognized. */
     392                        return EIO;
    389393                }
    390394        } else {
    391395                /* Operation timed out. That means there is no device there. */
    392         }
    393 
    394         if (d->present == false)
    395                 return EIO;
     396                return EIO;
     397        }
    396398
    397399        printf("device caps: 0x%04x\n", idata.caps);
     
    462464        d->model[pos] = '\0';
    463465
     466        if (d->dev_type == ata_pkt_dev) {
     467                /* Send inquiry. */
     468                rc = ata_pcmd_inquiry(0, inq_buf, 36);
     469                if (rc != EOK) {
     470                        printf("Device inquiry failed.\n");
     471                        d->present = false;
     472                        return EIO;
     473                }
     474
     475                /* Check device type. */
     476                if ((inq_buf[0] & 0x1f) != 0x05)
     477                        printf("Warning: Peripheral device type is not CD-ROM.\n");
     478        }
     479
    464480        d->present = true;
    465         fibril_mutex_initialize(&d->lock);
    466 
    467481        return EOK;
    468482}
     
    601615        if ((status & SR_ERR) != 0)
    602616                return EIO;
     617
     618        return EOK;
     619}
     620
     621/** Issue packet command (i. e. write a command packet to the device).
     622 *
     623 * Only data-in commands are supported (e.g. inquiry, read).
     624 *
     625 * @param dev_idx       Device index (0 or 1)
     626 * @param obuf          Buffer for storing data read from device
     627 * @param obuf_size     Size of obuf in bytes
     628 *
     629 * @return EOK on success, EIO on error.
     630 */
     631static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size,
     632    void *obuf, size_t obuf_size)
     633{
     634        size_t i;
     635        uint8_t status;
     636        uint8_t drv_head;
     637        disk_t *d;
     638        size_t data_size;
     639        uint16_t val;
     640
     641        d = &disk[dev_idx];
     642        fibril_mutex_lock(&d->lock);
     643
     644        /* New value for Drive/Head register */
     645        drv_head =
     646            ((dev_idx != 0) ? DHR_DRV : 0);
     647
     648        if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
     649                fibril_mutex_unlock(&d->lock);
     650                return EIO;
     651        }
     652
     653        pio_write_8(&cmd->drive_head, drv_head);
     654
     655        if (wait_status(0, ~(SR_BSY|SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
     656                fibril_mutex_unlock(&d->lock);
     657                return EIO;
     658        }
     659
     660        /* Byte count <- max. number of bytes we can read in one transfer. */
     661        pio_write_8(&cmd->cylinder_low, 0xfe);
     662        pio_write_8(&cmd->cylinder_high, 0xff);
     663
     664        pio_write_8(&cmd->command, CMD_PACKET);
     665
     666        if (wait_status(SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
     667                fibril_mutex_unlock(&d->lock);
     668                return EIO;
     669        }
     670
     671        /* Write command packet. */
     672        for (i = 0; i < (cpkt_size + 1) / 2; i++)
     673                pio_write_16(&cmd->data_port, ((uint16_t *) cpkt)[i]);
     674
     675        if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
     676                fibril_mutex_unlock(&d->lock);
     677                return EIO;
     678        }
     679
     680        if ((status & SR_DRQ) == 0) {
     681                fibril_mutex_unlock(&d->lock);
     682                return EIO;
     683        }
     684
     685        /* Read byte count. */
     686        data_size = (uint16_t) pio_read_8(&cmd->cylinder_low) +
     687            ((uint16_t) pio_read_8(&cmd->cylinder_high) << 8);
     688
     689        /* Check whether data fits into output buffer. */
     690        if (data_size > obuf_size) {
     691                /* Output buffer is too small to store data. */
     692                fibril_mutex_unlock(&d->lock);
     693                return EIO;
     694        }
     695
     696        /* Read data from the device buffer. */
     697        for (i = 0; i < (data_size + 1) / 2; i++) {
     698                val = pio_read_16(&cmd->data_port);
     699                ((uint16_t *) obuf)[i] = val;
     700        }
     701
     702        if (status & SR_ERR) {
     703                fibril_mutex_unlock(&d->lock);
     704                return EIO;
     705        }
     706
     707        fibril_mutex_unlock(&d->lock);
     708
     709        return EOK;
     710}
     711
     712/** Send ATAPI Inquiry.
     713 *
     714 * @param dev_idx       Device index (0 or 1)
     715 * @param obuf          Buffer for storing inquiry data read from device
     716 * @param obuf_size     Size of obuf in bytes
     717 *
     718 * @return EOK on success, EIO on error.
     719 */
     720static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size)
     721{
     722        uint8_t cp[12];
     723        int rc;
     724
     725        memset(cp, 0, 12);
     726        cp[0] = 0x12; /* Inquiry */
     727        cp[4] = min(obuf_size, 0xff); /* Allocation length */
     728
     729        rc = ata_cmd_packet(0, cp, 12, obuf, obuf_size);
     730        if (rc != EOK)
     731                return rc;
    603732
    604733        return EOK;
  • uspace/srv/bd/ata_bd/ata_hw.h

    r7a56e33e r88743b5  
    134134        CMD_WRITE_SECTORS       = 0x30,
    135135        CMD_WRITE_SECTORS_EXT   = 0x34,
     136        CMD_PACKET              = 0xA0,
    136137        CMD_IDENTIFY_PKT_DEV    = 0xA1,
    137138        CMD_IDENTIFY_DRIVE      = 0xEC
Note: See TracChangeset for help on using the changeset viewer.