Changeset 31de325 in mainline for uspace/srv/bd/ata_bd/ata_bd.c


Ignore:
Timestamp:
2009-08-08T15:21:01Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
330965c
Parents:
54d0ddc
Message:

Implement simple timeout when waiting for device.

File:
1 edited

Legend:

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

    r54d0ddc r31de325  
    8686    const void *buf);
    8787static int drive_identify(int drive_id, disk_t *d);
    88 static uint8_t wait_status(unsigned set, unsigned n_reset);
     88static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus,
     89    unsigned timeout);
    8990
    9091int main(int argc, char **argv)
     
    101102                return -1;
    102103
    103         (void) drive_identify(0, &disk[0]);
    104         (void) drive_identify(1, &disk[1]);
     104        for (i = 0; i < MAX_DISKS; i++) {
     105                printf("Identify drive %d... ", i);
     106                fflush(stdout);
     107
     108                rc = drive_identify(i, &disk[i]);
     109
     110                if (rc == EOK) {
     111                        printf("%u cylinders, %u heads, %u sectors\n",
     112                            disk[i].cylinders, disk[i].heads, disk[i].sectors);
     113                } else {
     114                        printf("Not found.\n");
     115                }
     116        }
    105117
    106118        n_disks = 0;
     
    295307        size_t i;
    296308
    297         printf("Identify drive %d... ", disk_id);
    298         fflush(stdout);
    299 
    300309        drv_head = ((disk_id != 0) ? DHR_DRV : 0);
    301310        d->present = false;
    302311
    303         wait_status(0, ~SR_BSY);
     312        if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
     313                return EIO;
     314
    304315        pio_write_8(&cmd->drive_head, drv_head);
    305316
    306317        /*
    307          * Detect if drive is present. This is only temorary.
    308          * We should really try for some time before giving up.
     318         * This is where we would most likely expect a non-existing device to
     319         * show up by not setting SR_DRDY.
    309320         */
    310         status = wait_status(0, ~SR_BSY);
    311 
    312         if ((status & SR_DRDY) == 0) {
    313                 printf("None attached.\n");
    314                 return ENOENT;
    315         }
    316         /***/
    317 
    318         wait_status(SR_DRDY, ~SR_BSY);
     321        if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
     322                return EIO;
     323
    319324        pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE);
    320325
    321         status = wait_status(0, ~SR_BSY);
     326        if (wait_status(0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
     327                return EIO;
    322328
    323329        /* Read data from the disk buffer. */
     
    344350
    345351        d->blocks = d->cylinders * d->heads * d->sectors;
    346 
    347         printf("Geometry: %u cylinders, %u heads, %u sectors\n",
    348                 d->cylinders, d->heads, d->sectors);
    349352
    350353        d->present = true;
     
    396399        /* Program a Read Sectors operation. */
    397400
    398         wait_status(0, ~SR_BSY);
     401        if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
     402                fibril_mutex_unlock(&d->lock);
     403                return EIO;
     404        }
     405
    399406        pio_write_8(&cmd->drive_head, drv_head);
    400407
    401         wait_status(SR_DRDY, ~SR_BSY);
     408        if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
     409                fibril_mutex_unlock(&d->lock);
     410                return EIO;
     411        }
     412
    402413        pio_write_8(&cmd->sector_count, 1);
    403414        pio_write_8(&cmd->sector_number, s);
     
    407418        pio_write_8(&cmd->command, CMD_READ_SECTORS);
    408419
    409         status = wait_status(0, ~SR_BSY);
    410 
    411         /* Read data from the disk buffer. */
     420        if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
     421                fibril_mutex_unlock(&d->lock);
     422                return EIO;
     423        }
    412424
    413425        if ((status & SR_DRQ) != 0) {
     426                /* Read data from the device buffer. */
     427
    414428                for (i = 0; i < block_size / 2; i++) {
    415429                        data = pio_read_16(&cmd->data_port);
     
    464478        fibril_mutex_lock(&d->lock);
    465479
    466         /* Program a Read Sectors operation. */
    467 
    468         wait_status(0, ~SR_BSY);
     480        /* Program a Write Sectors operation. */
     481
     482        if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
     483                fibril_mutex_unlock(&d->lock);
     484                return EIO;
     485        }
     486
    469487        pio_write_8(&cmd->drive_head, drv_head);
    470488
    471         wait_status(SR_DRDY, ~SR_BSY);
     489        if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
     490                fibril_mutex_unlock(&d->lock);
     491                return EIO;
     492        }
     493
    472494        pio_write_8(&cmd->sector_count, 1);
    473495        pio_write_8(&cmd->sector_number, s);
     
    477499        pio_write_8(&cmd->command, CMD_WRITE_SECTORS);
    478500
    479         status = wait_status(0, ~SR_BSY);
    480 
    481         /* Write data to the disk buffer. */
     501        if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
     502                fibril_mutex_unlock(&d->lock);
     503                return EIO;
     504        }
    482505
    483506        if ((status & SR_DRQ) != 0) {
     507                /* Write data to the device buffer. */
     508
    484509                for (i = 0; i < block_size / 2; i++) {
    485510                        pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]);
     
    495520}
    496521
    497 /** Wait until some status bits are set and some reset.
     522/** Wait until some status bits are set and some are reset.
    498523 *
    499524 * Example: wait_status(SR_DRDY, ~SR_BSY) waits for SR_DRDY to become
     
    502527 * @param set           Combination if bits which must be all set.
    503528 * @param n_reset       Negated combination of bits which must be all reset.
    504  * @return              The last value of status register that was read.
    505  */
    506 static uint8_t wait_status(unsigned set, unsigned n_reset)
     529 * @param pstatus       Pointer where to store last read status or NULL.
     530 * @param timeout       Timeout in 10ms units.
     531 *
     532 * @return              EOK on success, EIO on timeout.
     533 */
     534static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus,
     535    unsigned timeout)
    507536{
    508537        uint8_t status;
    509 
    510         do {
     538        int cnt;
     539
     540        status = pio_read_8(&cmd->status);
     541
     542        /*
     543         * This is crude, yet simple. First try with 1us delays
     544         * (most likely the device will respond very fast). If not,
     545         * start trying every 10 ms.
     546         */
     547
     548        cnt = 100;
     549        while ((status & ~n_reset) != 0 || (status & set) != set) {
     550                async_usleep(1);
     551                --cnt;
     552                if (cnt <= 0) break;
     553
    511554                status = pio_read_8(&cmd->status);
    512         } while ((status & ~n_reset) != 0 || (status & set) != set);
    513 
    514         return status;
     555        }
     556
     557        cnt = timeout;
     558        while ((status & ~n_reset) != 0 || (status & set) != set) {
     559                async_usleep(10000);
     560                --cnt;
     561                if (cnt <= 0) break;
     562
     563                status = pio_read_8(&cmd->status);
     564        }
     565
     566        if (pstatus)
     567                *pstatus = status;
     568
     569        if (cnt == 0)
     570                return EIO;
     571
     572        return EOK;
    515573}
    516574
Note: See TracChangeset for help on using the changeset viewer.