Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 54d0ddc in mainline


Ignore:
Timestamp:
2009-08-08T14:04:07Z (12 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
31de325
Parents:
d5f8f19
Message:

Add comments and wait_status() function.

File:
1 edited

Legend:

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

    rd5f8f19 r54d0ddc  
    6060#define NAME "ata_bd"
    6161
     62/** Physical block size. Should be always 512. */
    6263static const size_t block_size = 512;
     64
     65/** Size of the communication area. */
    6366static size_t comm_size;
    6467
     68/** I/O base address of the command registers. */
    6569static uintptr_t cmd_physical = 0x1f0;
     70/** I/O base address of the control registers. */
    6671static uintptr_t ctl_physical = 0x170;
     72
    6773static ata_cmd_t *cmd;
    6874static ata_ctl_t *ctl;
     
    8086    const void *buf);
    8187static int drive_identify(int drive_id, disk_t *d);
     88static uint8_t wait_status(unsigned set, unsigned n_reset);
    8289
    8390int main(int argc, char **argv)
    8491{
    85         uint8_t status;
    8692        char name[16];
    8793        int i, rc;
     
    129135}
    130136
    131 static 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 
     137
     138/** Register driver and enable device I/O. */
    207139static int ata_bd_init(void)
    208140{
     
    236168}
    237169
     170/** Block device connection handler */
    238171static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
    239172{
     
    306239}
    307240
     241/** Transfer a logical block from/to the device.
     242 *
     243 * @param disk_id       Device index (0 or 1)
     244 * @param method        @c BD_READ_BLOCK or @c BD_WRITE_BLOCK
     245 * @param blk_idx       Index of the first block.
     246 * @param size          Size of the logical block.
     247 * @param buf           Data buffer.
     248 *
     249 * @return EOK on success, EIO on error.
     250 */
    308251static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, size_t size,
    309252    void *buf)
     
    337280}
    338281
    339 
     282/** Issue IDENTIFY command.
     283 *
     284 * This is used to detect whether an ATA device is present and if so,
     285 * to determine its parameters. The parameters are written to @a d.
     286 *
     287 * @param disk_id       Device ID, 0 or 1.
     288 * @param d             Device structure to store parameters in.
     289 */
     290static int drive_identify(int disk_id, disk_t *d)
     291{
     292        uint16_t data;
     293        uint8_t status;
     294        uint8_t drv_head;
     295        size_t i;
     296
     297        printf("Identify drive %d... ", disk_id);
     298        fflush(stdout);
     299
     300        drv_head = ((disk_id != 0) ? DHR_DRV : 0);
     301        d->present = false;
     302
     303        wait_status(0, ~SR_BSY);
     304        pio_write_8(&cmd->drive_head, drv_head);
     305
     306        /*
     307         * Detect if drive is present. This is only temorary.
     308         * We should really try for some time before giving up.
     309         */
     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);
     319        pio_write_8(&cmd->command, CMD_IDENTIFY_DRIVE);
     320
     321        status = wait_status(0, ~SR_BSY);
     322
     323        /* Read data from the disk buffer. */
     324
     325        if ((status & SR_DRQ) != 0) {
     326//              for (i = 0; i < block_size / 2; i++) {
     327//                      data = pio_read_16(&cmd->data_port);
     328//                      ((uint16_t *) buf)[i] = data;
     329//              }
     330
     331                for (i = 0; i < block_size / 2; i++) {
     332                        data = pio_read_16(&cmd->data_port);
     333
     334                        switch (i) {
     335                        case 1: d->cylinders = data; break;
     336                        case 3: d->heads = data; break;
     337                        case 6: d->sectors = data; break;
     338                        }
     339                }
     340        }
     341
     342        if ((status & SR_ERR) != 0)
     343                return EIO;
     344
     345        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);
     349
     350        d->present = true;
     351        fibril_mutex_initialize(&d->lock);
     352
     353        return EOK;
     354}
     355
     356/** Read a physical from the device.
     357 *
     358 * @param disk_id       Device index (0 or 1)
     359 * @param blk_idx       Index of the first block.
     360 * @param blk_cnt       Number of blocks to transfer.
     361 * @param buf           Buffer for holding the data.
     362 *
     363 * @return EOK on success, EIO on error.
     364 */
    340365static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
    341366    void *buf)
     
    371396        /* Program a Read Sectors operation. */
    372397
    373         do {
    374                 status = pio_read_8(&cmd->status);
    375         } while ((status & SR_BSY) != 0);
    376 
     398        wait_status(0, ~SR_BSY);
    377399        pio_write_8(&cmd->drive_head, drv_head);
    378400
    379         do {
    380                 status = pio_read_8(&cmd->status);
    381         } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0);
    382 
     401        wait_status(SR_DRDY, ~SR_BSY);
    383402        pio_write_8(&cmd->sector_count, 1);
    384403        pio_write_8(&cmd->sector_number, s);
     
    388407        pio_write_8(&cmd->command, CMD_READ_SECTORS);
    389408
    390         do {
    391                 status = pio_read_8(&cmd->status);
    392         } while ((status & SR_BSY) != 0);
     409        status = wait_status(0, ~SR_BSY);
    393410
    394411        /* Read data from the disk buffer. */
     
    408425}
    409426
     427/** Write a physical block to the device.
     428 *
     429 * @param disk_id       Device index (0 or 1)
     430 * @param blk_idx       Index of the first block.
     431 * @param blk_cnt       Number of blocks to transfer.
     432 * @param buf           Buffer holding the data to write.
     433 *
     434 * @return EOK on success, EIO on error.
     435 */
    410436static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
    411437    const void *buf)
     
    440466        /* Program a Read Sectors operation. */
    441467
    442         do {
    443                 status = pio_read_8(&cmd->status);
    444         } while ((status & SR_BSY) != 0);
    445        
     468        wait_status(0, ~SR_BSY);
    446469        pio_write_8(&cmd->drive_head, drv_head);
    447470
    448         do {
    449                 status = pio_read_8(&cmd->status);
    450         } while ((status & SR_BSY) != 0 || (status & SR_DRDY) == 0);
    451 
     471        wait_status(SR_DRDY, ~SR_BSY);
    452472        pio_write_8(&cmd->sector_count, 1);
    453473        pio_write_8(&cmd->sector_number, s);
     
    457477        pio_write_8(&cmd->command, CMD_WRITE_SECTORS);
    458478
    459         do {
    460                 status = pio_read_8(&cmd->status);
    461         } while ((status & SR_BSY) != 0);
     479        status = wait_status(0, ~SR_BSY);
    462480
    463481        /* Write data to the disk buffer. */
     
    477495}
    478496
     497/** Wait until some status bits are set and some reset.
     498 *
     499 * Example: wait_status(SR_DRDY, ~SR_BSY) waits for SR_DRDY to become
     500 * set and SR_BSY to become reset.
     501 *
     502 * @param set           Combination if bits which must be all set.
     503 * @param n_reset       Negated combination of bits which must be all reset.
     504 * @return              The last value of status register that was read.
     505 */
     506static uint8_t wait_status(unsigned set, unsigned n_reset)
     507{
     508        uint8_t status;
     509
     510        do {
     511                status = pio_read_8(&cmd->status);
     512        } while ((status & ~n_reset) != 0 || (status & set) != set);
     513
     514        return status;
     515}
     516
    479517/**
    480518 * @}
Note: See TracChangeset for help on using the changeset viewer.