Changes in / [a71c158:e5792d1] in mainline


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

Legend:

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

    ra71c158 re5792d1  
    5050#include <as.h>
    5151#include <fibril_sync.h>
     52#include <string.h>
    5253#include <devmap.h>
    5354#include <sys/types.h>
     
    8586static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
    8687    const void *buf);
    87 static int drive_identify(int drive_id, disk_t *d);
     88static int disk_init(disk_t *d, int disk_id);
     89static int drive_identify(int drive_id, void *buf);
     90static void disk_print_summary(disk_t *d);
    8891static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus,
    8992    unsigned timeout);
     
    106109                fflush(stdout);
    107110
    108                 rc = drive_identify(i, &disk[i]);
     111                rc = disk_init(&disk[i], i);
    109112
    110113                if (rc == EOK) {
    111                         printf("%u cylinders, %u heads, %u sectors\n",
    112                             disk[i].cylinders, disk[i].heads, disk[i].sectors);
     114                        disk_print_summary(&disk[i]);
    113115                } else {
    114116                        printf("Not found.\n");
     
    147149}
    148150
     151/** Print one-line device summary. */
     152static void disk_print_summary(disk_t *d)
     153{
     154        uint64_t mbytes;
     155
     156        printf("%s: ", d->model);
     157
     158        if (d->amode == am_chs) {
     159                printf("CHS %u cylinders, %u heads, %u sectors",
     160                    disk->geom.cylinders, disk->geom.heads, disk->geom.sectors);
     161        } else {
     162                printf("LBA-28");
     163        }
     164
     165        printf(" %llu blocks", d->blocks, d->blocks / (2 * 1024));
     166
     167        mbytes = d->blocks / (2 * 1024);
     168        if (mbytes > 0)
     169                printf(" %llu MB.", mbytes);
     170
     171        printf("\n");
     172}
    149173
    150174/** Register driver and enable device I/O. */
     
    251275}
    252276
     277/** Initialize a disk.
     278 *
     279 * Probes for a disk, determines its parameters and initializes
     280 * the disk structure.
     281 */
     282static int disk_init(disk_t *d, int disk_id)
     283{
     284        identify_data_t idata;
     285        uint8_t model[40];
     286        uint16_t w;
     287        uint8_t c;
     288        size_t pos, len;
     289        int rc;
     290        int i;
     291
     292        rc = drive_identify(disk_id, &idata);
     293        if (rc != EOK) {
     294                d->present = false;
     295                return rc;
     296        }
     297
     298        if ((idata.caps & cap_lba) == 0) {
     299                /* Device only supports CHS addressing. */
     300                d->amode = am_chs;
     301
     302                d->geom.cylinders = idata.cylinders;
     303                d->geom.heads = idata.heads;
     304                d->geom.sectors = idata.sectors;
     305
     306                d->blocks = d->geom.cylinders * d->geom.heads * d->geom.sectors;
     307        } else {
     308                /* Device supports LBA-28. */
     309                d->amode = am_lba28;
     310
     311                d->geom.cylinders = 0;
     312                d->geom.heads = 0;
     313                d->geom.sectors = 0;
     314
     315                d->blocks =
     316                    (uint32_t) idata.total_lba_sec0 |
     317                    ((uint32_t) idata.total_lba_sec1 << 16);
     318        }
     319
     320        /*
     321         * Convert model name to string representation.
     322         */
     323        for (i = 0; i < 20; i++) {
     324                w = idata.model_name[i];
     325                model[2 * i] = w >> 8;
     326                model[2 * i + 1] = w & 0x00ff;
     327        }
     328
     329        len = 40;
     330        while (len > 0 && model[len - 1] == 0x20)
     331                --len;
     332
     333        pos = 0;
     334        for (i = 0; i < len; ++i) {
     335                c = model[i];
     336                if (c >= 0x80) c = '?';
     337
     338                chr_encode(c, d->model, &pos, 40);
     339        }
     340        d->model[pos] = '\0';
     341
     342        d->present = true;
     343        fibril_mutex_initialize(&d->lock);
     344
     345        return EOK;
     346}
     347
    253348/** Transfer a logical block from/to the device.
    254349 *
     
    294389/** Issue IDENTIFY command.
    295390 *
    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.
     391 * Reads @c identify data into the provided buffer. This is used to detect
     392 * whether an ATA device is present and if so, to determine its parameters.
    298393 *
    299394 * @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)
     395 * @param buf           Pointer to a 512-byte buffer.
     396 */
     397static int drive_identify(int disk_id, void *buf)
    303398{
    304399        uint16_t data;
     
    308403
    309404        drv_head = ((disk_id != 0) ? DHR_DRV : 0);
    310         d->present = false;
    311405
    312406        if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
     
    330424
    331425        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 
    337426                for (i = 0; i < block_size / 2; i++) {
    338427                        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                         }
     428                        ((uint16_t *) buf)[i] = data;
    345429                }
    346430        }
     
    348432        if ((status & SR_ERR) != 0)
    349433                return EIO;
    350 
    351         d->blocks = d->cylinders * d->heads * d->sectors;
    352 
    353         d->present = true;
    354         fibril_mutex_initialize(&d->lock);
    355434
    356435        return EOK;
     
    383462                return EINVAL;
    384463
    385         /* Compute CHS. */
    386         c = blk_idx / (d->heads * d->sectors);
    387         idx = blk_idx % (d->heads * d->sectors);
    388 
    389         h = idx / d->sectors;
    390         s = 1 + (idx % d->sectors);
     464        if (d->amode == am_chs) {
     465                /* Compute CHS coordinates. */
     466                c = blk_idx / (d->geom.heads * d->geom.sectors);
     467                idx = blk_idx % (d->geom.heads * d->geom.sectors);
     468
     469                h = idx / d->geom.sectors;
     470                s = 1 + (idx % d->geom.sectors);
     471        } else {
     472                /* Compute LBA-28 coordinates. */
     473                s = blk_idx & 0xff;             /* bits 0-7 */
     474                c = (blk_idx >> 8) & 0xffff;    /* bits 8-23 */
     475                h = (blk_idx >> 24) & 0x0f;     /* bits 24-27 */
     476        }
    391477
    392478        /* New value for Drive/Head register */
    393479        drv_head =
    394480            ((disk_id != 0) ? DHR_DRV : 0) |
     481            ((d->amode != am_chs) ? DHR_LBA : 0) |
    395482            (h & 0x0f);
    396483
     
    464551                return EINVAL;
    465552
    466         /* Compute CHS. */
    467         c = blk_idx / (d->heads * d->sectors);
    468         idx = blk_idx % (d->heads * d->sectors);
    469 
    470         h = idx / d->sectors;
    471         s = 1 + (idx % d->sectors);
     553        if (d->amode == am_chs) {
     554                /* Compute CHS coordinates. */
     555                c = blk_idx / (d->geom.heads * d->geom.sectors);
     556                idx = blk_idx % (d->geom.heads * d->geom.sectors);
     557
     558                h = idx / d->geom.sectors;
     559                s = 1 + (idx % d->geom.sectors);
     560        } else {
     561                /* Compute LBA-28 coordinates. */
     562                s = blk_idx & 0xff;             /* bits 0-7 */
     563                c = (blk_idx >> 8) & 0xffff;    /* bits 8-23 */
     564                h = (blk_idx >> 24) & 0x0f;     /* bits 24-27 */
     565        }
    472566
    473567        /* New value for Drive/Head register */
    474568        drv_head =
    475569            ((disk_id != 0) ? DHR_DRV : 0) |
     570            ((d->amode != am_chs) ? DHR_LBA : 0) |
    476571            (h & 0x0f);
    477572
  • uspace/srv/bd/ata_bd/ata_bd.h

    ra71c158 re5792d1  
    3838#include <sys/types.h>
    3939#include <fibril_sync.h>
     40#include <string.h>
    4041
    4142enum {
     
    115116
    116117enum drive_head_bits {
    117         DHR_DRV         = 0x10
     118        DHR_LBA         = 0x40, /**< Use LBA addressing mode */
     119        DHR_DRV         = 0x10  /**< Select device 1 */
    118120};
    119121
     
    142144};
    143145
     146/** Data returned from @c identify command. */
     147typedef struct {
     148        uint16_t gen_conf;
     149        uint16_t cylinders;
     150        uint16_t _res2;
     151        uint16_t heads;
     152        uint16_t _vs4;
     153        uint16_t _vs5;
     154        uint16_t sectors;
     155        uint16_t _vs7;
     156        uint16_t _vs8;
     157        uint16_t _vs9;
     158        uint16_t serial_number[10];
     159        uint16_t _vs20;
     160        uint16_t _vs21;
     161        uint16_t vs_bytes;
     162        uint16_t firmware_rev[4];
     163        uint16_t model_name[20];
     164        uint16_t max_rw_multiple;
     165        uint16_t _res48;
     166        uint16_t caps;
     167        uint16_t _res50;
     168        uint16_t pio_timing;
     169        uint16_t dma_timing;
     170        uint16_t validity;
     171        uint16_t cur_cyl;
     172        uint16_t cur_heads;
     173        uint16_t cur_sectors;
     174        uint16_t cur_capacity0;
     175        uint16_t cur_capacity1;
     176        uint16_t mss;
     177        uint16_t total_lba_sec0;
     178        uint16_t total_lba_sec1;
     179        uint16_t sw_dma;
     180        uint16_t mw_dma;
     181        uint16_t pio_modes;
     182        uint16_t min_mw_dma_cycle;
     183        uint16_t rec_mw_dma_cycle;
     184        uint16_t min_raw_pio_cycle;
     185        uint16_t min_iordy_pio_cycle;
     186        uint16_t _res69;
     187        uint16_t _res70;
     188        uint16_t _res71[1 + 127 - 71];
     189        uint16_t _vs128[1 + 159 - 128];
     190        uint16_t _res160[1 + 255 - 160];
     191} identify_data_t;
     192
     193enum ata_caps {
     194        cap_iordy       = 0x0800,
     195        cap_iordy_cbd   = 0x0400,
     196        cap_lba         = 0x0200,
     197        cap_dma         = 0x0100
     198};
     199
     200/** Block addressing mode. */
     201enum addr_mode {
     202        am_chs,
     203        am_lba28
     204};
     205
    144206typedef struct {
    145207        bool present;
    146         unsigned heads;
    147         unsigned cylinders;
    148         unsigned sectors;
     208        enum addr_mode amode;
     209
     210        /*
     211         * Geometry. Only valid if operating in CHS mode.
     212         */
     213        struct {
     214                unsigned heads;
     215                unsigned cylinders;
     216                unsigned sectors;
     217        } geom;
     218
    149219        uint64_t blocks;
     220
     221        char model[STR_BOUNDS(40) + 1];
    150222
    151223        fibril_mutex_t lock;
Note: See TracChangeset for help on using the changeset viewer.