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

Changeset a1f48f6 in mainline


Ignore:
Timestamp:
2009-08-22T18:36:30Z (12 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
1c1657c
Parents:
4ef117f8
Message:

Add LBA-48 addressing support.

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

Legend:

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

    r4ef117f8 ra1f48f6  
    3535 * @brief ATA disk driver
    3636 *
    37  * This driver currently works only with CHS addressing and uses PIO.
    38  * Currently based on the (now obsolete) ATA-1, ATA-2 standards.
     37 * This driver supports CHS, 28-bit and 48-bit LBA addressing. It only uses
     38 * PIO transfers. There is no support DMA, the PACKET feature set or any other
     39 * fancy features such as S.M.A.R.T, removable devices, etc.
     40 *
     41 * This driver is based on the ATA-1, ATA-2, ATA-3 and ATA/ATAPI-4 through 7
     42 * standards, as published by the ANSI, NCITS and INCITS standards bodies,
     43 * which are freely available. This driver contains no vendor-specific
     44 * code at this moment.
    3945 *
    4046 * The driver services a single controller which can have up to two disks
     
    100106        printf(NAME ": ATA disk driver\n");
    101107
    102         printf("I/O address 0x%x\n", cmd_physical);
     108        printf("I/O address 0x%p/0x%p\n", ctl_physical, cmd_physical);
    103109
    104110        if (ata_bd_init() != EOK)
     
    156162        printf("%s: ", d->model);
    157163
    158         if (d->amode == am_chs) {
     164        switch (d->amode) {
     165        case am_chs:
    159166                printf("CHS %u cylinders, %u heads, %u sectors",
    160167                    disk->geom.cylinders, disk->geom.heads, disk->geom.sectors);
    161         } else {
     168                break;
     169        case am_lba28:
    162170                printf("LBA-28");
     171                break;
     172        case am_lba48:
     173                printf("LBA-48");
     174                break;
    163175        }
    164176
     
    288300        size_t pos, len;
    289301        int rc;
    290         int i;
     302        unsigned i;
    291303
    292304        rc = drive_identify(disk_id, &idata);
     
    305317
    306318                d->blocks = d->geom.cylinders * d->geom.heads * d->geom.sectors;
    307         } else {
    308                 /* Device supports LBA-28. */
     319        } else if ((idata.cmd_set1 & cs1_addr48) == 0) {
     320                /* Device only supports LBA-28 addressing. */
    309321                d->amode = am_lba28;
    310322
     
    314326
    315327                d->blocks =
    316                     (uint32_t) idata.total_lba_sec0 |
    317                     ((uint32_t) idata.total_lba_sec1 << 16);
     328                     (uint32_t) idata.total_lba28_0 |
     329                    ((uint32_t) idata.total_lba28_1 << 16);
     330        } else {
     331                /* Device supports LBA-48 addressing. */
     332                d->amode = am_lba48;
     333
     334                d->geom.cylinders = 0;
     335                d->geom.heads = 0;
     336                d->geom.sectors = 0;
     337
     338                d->blocks =
     339                     (uint64_t) idata.total_lba48_0 |
     340                    ((uint64_t) idata.total_lba48_1 << 16) |
     341                    ((uint64_t) idata.total_lba48_2 << 32) |
     342                    ((uint64_t) idata.total_lba48_3 << 48);
    318343        }
    319344
     
    451476        uint16_t data;
    452477        uint8_t status;
    453         uint64_t c, h, s;
     478        uint64_t c, h, s, c1, s1;
    454479        uint64_t idx;
    455480        uint8_t drv_head;
     
    462487                return EINVAL;
    463488
    464         if (d->amode == am_chs) {
     489        switch (d->amode) {
     490        case am_chs:
    465491                /* Compute CHS coordinates. */
    466492                c = blk_idx / (d->geom.heads * d->geom.sectors);
     
    469495                h = idx / d->geom.sectors;
    470496                s = 1 + (idx % d->geom.sectors);
    471         } else {
     497                break;
     498
     499        case am_lba28:
    472500                /* Compute LBA-28 coordinates. */
    473501                s = blk_idx & 0xff;             /* bits 0-7 */
    474502                c = (blk_idx >> 8) & 0xffff;    /* bits 8-23 */
    475503                h = (blk_idx >> 24) & 0x0f;     /* bits 24-27 */
     504                break;
     505
     506        case am_lba48:
     507                /* Compute LBA-48 coordinates. */
     508                s = blk_idx & 0xff;             /* bits 0-7 */
     509                c = (blk_idx >> 8) & 0xffff;    /* bits 8-23 */
     510                s1 = (blk_idx >> 24) & 0xff;    /* bits 24-31 */
     511                c1 = (blk_idx >> 32) & 0xffff;  /* bits 32-47 */
     512                h = 0;
     513                break;
    476514        }
    477515
     
    498536        }
    499537
     538        if (d->amode == am_lba48) {
     539                /* Write high-order bits. */
     540                pio_write_8(&cmd->sector_count, 0);
     541                pio_write_8(&cmd->sector_number, s1);
     542                pio_write_8(&cmd->cylinder_low, c1 & 0xff);
     543                pio_write_8(&cmd->cylinder_high, c1 >> 16);
     544        }
     545
     546        /* Write low-order bits. */
    500547        pio_write_8(&cmd->sector_count, 1);
    501548        pio_write_8(&cmd->sector_number, s);
     
    540587        size_t i;
    541588        uint8_t status;
    542         uint64_t c, h, s;
     589        uint64_t c, h, s, c1, s1;
    543590        uint64_t idx;
    544591        uint8_t drv_head;
     
    551598                return EINVAL;
    552599
    553         if (d->amode == am_chs) {
     600        switch (d->amode) {
     601        case am_chs:
    554602                /* Compute CHS coordinates. */
    555603                c = blk_idx / (d->geom.heads * d->geom.sectors);
     
    558606                h = idx / d->geom.sectors;
    559607                s = 1 + (idx % d->geom.sectors);
    560         } else {
     608                break;
     609
     610        case am_lba28:
    561611                /* Compute LBA-28 coordinates. */
    562612                s = blk_idx & 0xff;             /* bits 0-7 */
    563613                c = (blk_idx >> 8) & 0xffff;    /* bits 8-23 */
    564614                h = (blk_idx >> 24) & 0x0f;     /* bits 24-27 */
     615                break;
     616
     617        case am_lba48:
     618                /* Compute LBA-48 coordinates. */
     619                s = blk_idx & 0xff;             /* bits 0-7 */
     620                c = (blk_idx >> 8) & 0xffff;    /* bits 8-23 */
     621                s1 = (blk_idx >> 24) & 0xff;    /* bits 24-31 */
     622                c1 = (blk_idx >> 32) & 0xffff;  /* bits 32-47 */
     623                h = 0;
     624                break;
    565625        }
    566626
     
    587647        }
    588648
     649        if (d->amode == am_lba48) {
     650                /* Write high-order bits. */
     651                pio_write_8(&cmd->sector_count, 0);
     652                pio_write_8(&cmd->sector_number, s1);
     653                pio_write_8(&cmd->cylinder_low, c1 & 0xff);
     654                pio_write_8(&cmd->cylinder_high, c1 >> 16);
     655        }
     656
     657        /* Write low-order bits. */
    589658        pio_write_8(&cmd->sector_count, 1);
    590659        pio_write_8(&cmd->sector_number, s);
  • uspace/srv/bd/ata_bd/ata_bd.h

    r4ef117f8 ra1f48f6  
    156156        uint16_t _vs8;
    157157        uint16_t _vs9;
     158
    158159        uint16_t serial_number[10];
    159160        uint16_t _vs20;
     
    162163        uint16_t firmware_rev[4];
    163164        uint16_t model_name[20];
     165
    164166        uint16_t max_rw_multiple;
    165167        uint16_t _res48;
     
    168170        uint16_t pio_timing;
    169171        uint16_t dma_timing;
     172
    170173        uint16_t validity;
    171174        uint16_t cur_cyl;
     
    175178        uint16_t cur_capacity1;
    176179        uint16_t mss;
    177         uint16_t total_lba_sec0;
    178         uint16_t total_lba_sec1;
     180        uint16_t total_lba28_0;
     181        uint16_t total_lba28_1;
    179182        uint16_t sw_dma;
    180183        uint16_t mw_dma;
     
    184187        uint16_t min_raw_pio_cycle;
    185188        uint16_t min_iordy_pio_cycle;
     189
    186190        uint16_t _res69;
    187191        uint16_t _res70;
    188         uint16_t _res71[1 + 127 - 71];
     192        uint16_t _res71;
     193        uint16_t _res72;
     194        uint16_t _res73;
     195        uint16_t _res74;
     196
     197        uint16_t queue_depth;
     198        uint16_t _res76[1 + 79 - 76];
     199        uint16_t version_maj;
     200        uint16_t version_min;
     201        uint16_t cmd_set0;
     202        uint16_t cmd_set1;
     203        uint16_t csf_sup_ext;
     204        uint16_t csf_enabled0;
     205        uint16_t csf_enabled1;
     206        uint16_t csf_default;
     207        uint16_t udma;
     208
     209        uint16_t _res89[1 + 99 - 89];
     210
     211        /* Total number of blocks in LBA-48 addressing */
     212        uint16_t total_lba48_0;
     213        uint16_t total_lba48_1;
     214        uint16_t total_lba48_2;
     215        uint16_t total_lba48_3;
     216
     217        /* Note: more fields are defined in ATA/ATAPI-7 */
     218        uint16_t _res104[1 + 127 - 104];
    189219        uint16_t _vs128[1 + 159 - 128];
    190220        uint16_t _res160[1 + 255 - 160];
     
    198228};
    199229
     230/** Bits of @c identify_data_t.cmd_set1 */
     231enum ata_cs1 {
     232        cs1_addr48      = 0x0400        /**< 48-bit address feature set */
     233};
     234
    200235/** Block addressing mode. */
    201236enum addr_mode {
    202         am_chs,
    203         am_lba28
     237        am_chs,         /**< CHS block addressing */
     238        am_lba28,       /**< LBA-28 block addressing */
     239        am_lba48        /**< LBA-48 block addressing */
    204240};
    205241
Note: See TracChangeset for help on using the changeset viewer.