Changes in / [330965c:42cfd91] in mainline


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

Legend:

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

    r330965c r42cfd91  
    6060#define NAME "ata_bd"
    6161
    62 /** Physical block size. Should be always 512. */
    6362static const size_t block_size = 512;
    64 
    65 /** Size of the communication area. */
    6663static size_t comm_size;
    6764
    68 /** I/O base address of the command registers. */
    6965static uintptr_t cmd_physical = 0x1f0;
    70 /** I/O base address of the control registers. */
    7166static uintptr_t ctl_physical = 0x170;
    72 
    7367static ata_cmd_t *cmd;
    7468static ata_ctl_t *ctl;
     
    8680    const void *buf);
    8781static int drive_identify(int drive_id, disk_t *d);
    88 static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus,
    89     unsigned timeout);
    9082
    9183int main(int argc, char **argv)
    9284{
     85        uint8_t status;
    9386        char name[16];
    9487        int i, rc;
     
    10295                return -1;
    10396
    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         }
     97        (void) drive_identify(0, &disk[0]);
     98        (void) drive_identify(1, &disk[1]);
    11799
    118100        n_disks = 0;
     
    147129}
    148130
    149 
    150 /** Register driver and enable device I/O. */
     131static int drive_identify(int disk_id, disk_t *d)
     132{
     133        uint16_t data;
     134        uint8_t status;
     135        uint8_t drv_head;
     136        size_t i;
     137
     138        printf("Identify drive %d... ", disk_id);
     139        fflush(stdout);
     140
     141        drv_head = ((disk_id != 0) ? DHR_DRV : 0);
     142        d->present = false;
     143
     144        do {
     145                status = pio_read_8(&cmd->status);
     146        } while ((status & SR_BSY) != 0);
     147
     148        pio_write_8(&cmd->drive_head, drv_head);
     149
     150        /*
     151         * Detect if drive is present. This is Qemu only! Need to
     152         * do the right thing to work with real drives.
     153         */
     154        do {
     155                status = pio_read_8(&cmd->status);
     156        } while ((status & SR_BSY) != 0);
     157
     158        if ((status & SR_DRDY) == 0) {
     159                printf("None attached.\n");
     160                return ENOENT;
     161        }
     162        /***/
     163
     164        do {
     165                status = pio_read_8(&cmd->status);
     166        } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0);
     167
     168        pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE);
     169
     170        do {
     171                status = pio_read_8(&cmd->status);
     172        } while ((status & SR_BSY) != 0);
     173
     174        /* Read data from the disk buffer. */
     175
     176        if ((status & SR_DRQ) != 0) {
     177//              for (i = 0; i < block_size / 2; i++) {
     178//                      data = pio_read_16(&cmd->data_port);
     179//                      ((uint16_t *) buf)[i] = data;
     180//              }
     181
     182                for (i = 0; i < block_size / 2; i++) {
     183                        data = pio_read_16(&cmd->data_port);
     184
     185                        switch (i) {
     186                        case 1: d->cylinders = data; break;
     187                        case 3: d->heads = data; break;
     188                        case 6: d->sectors = data; break;
     189                        }
     190                }
     191        }
     192
     193        if ((status & SR_ERR) != 0)
     194                return EIO;
     195
     196        d->blocks = d->cylinders * d->heads * d->sectors;
     197
     198        printf("Geometry: %u cylinders, %u heads, %u sectors\n",
     199                d->cylinders, d->heads, d->sectors);
     200
     201        d->present = true;
     202        fibril_mutex_initialize(&d->lock);
     203
     204        return EOK;
     205}
     206
    151207static int ata_bd_init(void)
    152208{
     
    180236}
    181237
    182 /** Block device connection handler */
    183238static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
    184239{
     
    251306}
    252307
    253 /** Transfer a logical block from/to the device.
    254  *
    255  * @param disk_id       Device index (0 or 1)
    256  * @param method        @c BD_READ_BLOCK or @c BD_WRITE_BLOCK
    257  * @param blk_idx       Index of the first block.
    258  * @param size          Size of the logical block.
    259  * @param buf           Data buffer.
    260  *
    261  * @return EOK on success, EIO on error.
    262  */
    263308static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, size_t size,
    264309    void *buf)
     
    292337}
    293338
    294 /** Issue IDENTIFY command.
    295  *
    296  * This is used to detect whether an ATA device is present and if so,
    297  * to determine its parameters. The parameters are written to @a d.
    298  *
    299  * @param disk_id       Device ID, 0 or 1.
    300  * @param d             Device structure to store parameters in.
    301  */
    302 static int drive_identify(int disk_id, disk_t *d)
    303 {
    304         uint16_t data;
    305         uint8_t status;
    306         uint8_t drv_head;
    307         size_t i;
    308 
    309         drv_head = ((disk_id != 0) ? DHR_DRV : 0);
    310         d->present = false;
    311 
    312         if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
    313                 return EIO;
    314 
    315         pio_write_8(&cmd->drive_head, drv_head);
    316 
    317         /*
    318          * This is where we would most likely expect a non-existing device to
    319          * show up by not setting SR_DRDY.
    320          */
    321         if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
    322                 return EIO;
    323 
    324         pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE);
    325 
    326         if (wait_status(0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
    327                 return EIO;
    328 
    329         /* Read data from the disk buffer. */
    330 
    331         if ((status & SR_DRQ) != 0) {
    332 //              for (i = 0; i < block_size / 2; i++) {
    333 //                      data = pio_read_16(&cmd->data_port);
    334 //                      ((uint16_t *) buf)[i] = data;
    335 //              }
    336 
    337                 for (i = 0; i < block_size / 2; i++) {
    338                         data = pio_read_16(&cmd->data_port);
    339 
    340                         switch (i) {
    341                         case 1: d->cylinders = data; break;
    342                         case 3: d->heads = data; break;
    343                         case 6: d->sectors = data; break;
    344                         }
    345                 }
    346         }
    347 
    348         if ((status & SR_ERR) != 0)
    349                 return EIO;
    350 
    351         d->blocks = d->cylinders * d->heads * d->sectors;
    352 
    353         d->present = true;
    354         fibril_mutex_initialize(&d->lock);
    355 
    356         return EOK;
    357 }
    358 
    359 /** Read a physical from the device.
    360  *
    361  * @param disk_id       Device index (0 or 1)
    362  * @param blk_idx       Index of the first block.
    363  * @param blk_cnt       Number of blocks to transfer.
    364  * @param buf           Buffer for holding the data.
    365  *
    366  * @return EOK on success, EIO on error.
    367  */
     339
    368340static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
    369341    void *buf)
     
    399371        /* Program a Read Sectors operation. */
    400372
    401         if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
    402                 fibril_mutex_unlock(&d->lock);
    403                 return EIO;
    404         }
     373        do {
     374                status = pio_read_8(&cmd->status);
     375        } while ((status & SR_BSY) != 0);
    405376
    406377        pio_write_8(&cmd->drive_head, drv_head);
    407378
    408         if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
    409                 fibril_mutex_unlock(&d->lock);
    410                 return EIO;
    411         }
     379        do {
     380                status = pio_read_8(&cmd->status);
     381        } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0);
    412382
    413383        pio_write_8(&cmd->sector_count, 1);
     
    418388        pio_write_8(&cmd->command, CMD_READ_SECTORS);
    419389
    420         if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
    421                 fibril_mutex_unlock(&d->lock);
    422                 return EIO;
    423         }
     390        do {
     391                status = pio_read_8(&cmd->status);
     392        } while ((status & SR_BSY) != 0);
     393
     394        /* Read data from the disk buffer. */
    424395
    425396        if ((status & SR_DRQ) != 0) {
    426                 /* Read data from the device buffer. */
    427 
    428397                for (i = 0; i < block_size / 2; i++) {
    429398                        data = pio_read_16(&cmd->data_port);
     
    439408}
    440409
    441 /** Write a physical block to the device.
    442  *
    443  * @param disk_id       Device index (0 or 1)
    444  * @param blk_idx       Index of the first block.
    445  * @param blk_cnt       Number of blocks to transfer.
    446  * @param buf           Buffer holding the data to write.
    447  *
    448  * @return EOK on success, EIO on error.
    449  */
    450410static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
    451411    const void *buf)
     
    478438        fibril_mutex_lock(&d->lock);
    479439
    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 
     440        /* Program a Read Sectors operation. */
     441
     442        do {
     443                status = pio_read_8(&cmd->status);
     444        } while ((status & SR_BSY) != 0);
     445       
    487446        pio_write_8(&cmd->drive_head, drv_head);
    488447
    489         if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
    490                 fibril_mutex_unlock(&d->lock);
    491                 return EIO;
    492         }
     448        do {
     449                status = pio_read_8(&cmd->status);
     450        } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0);
    493451
    494452        pio_write_8(&cmd->sector_count, 1);
     
    499457        pio_write_8(&cmd->command, CMD_WRITE_SECTORS);
    500458
    501         if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
    502                 fibril_mutex_unlock(&d->lock);
    503                 return EIO;
    504         }
     459        do {
     460                status = pio_read_8(&cmd->status);
     461        } while ((status & SR_BSY) != 0);
     462
     463        /* Write data to the disk buffer. */
    505464
    506465        if ((status & SR_DRQ) != 0) {
    507                 /* Write data to the device buffer. */
    508 
    509466                for (i = 0; i < block_size / 2; i++) {
    510467                        pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]);
     
    520477}
    521478
    522 /** Wait until some status bits are set and some are reset.
    523  *
    524  * Example: wait_status(SR_DRDY, ~SR_BSY) waits for SR_DRDY to become
    525  * set and SR_BSY to become reset.
    526  *
    527  * @param set           Combination if bits which must be all set.
    528  * @param n_reset       Negated combination of bits which must be all 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  */
    534 static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus,
    535     unsigned timeout)
    536 {
    537         uint8_t status;
    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 
    554                 status = pio_read_8(&cmd->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;
    573 }
    574 
    575479/**
    576480 * @}
  • uspace/srv/bd/ata_bd/ata_bd.h

    r330965c r42cfd91  
    135135};
    136136
    137 /** Timeout definitions. Unit is 10 ms. */
    138 enum ata_timeout {
    139         TIMEOUT_PROBE   =  100, /*  1 s */
    140         TIMEOUT_BSY     =  100, /*  1 s */
    141         TIMEOUT_DRDY    = 1000  /* 10 s */
    142 };
    143 
    144137typedef struct {
    145138        bool present;
Note: See TracChangeset for help on using the changeset viewer.