Changeset 1806e5d in mainline for uspace/srv/bd/ata_bd/ata_bd.c


Ignore:
Timestamp:
2009-06-12T21:27:58Z (15 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4f5caea
Parents:
26360f7
Message:

Properly support two disks per ATA controller. Fake (Qemu-only) check whether disk is present. Only create device nodes for detected disks.

File:
1 edited

Legend:

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

    r26360f7 r1806e5d  
    5151#include <sys/types.h>
    5252#include <errno.h>
     53#include <bool.h>
    5354
    5455#define NAME "ata_bd"
     
    134135};
    135136
     137typedef struct {
     138        bool present;
     139        unsigned heads;
     140        unsigned cylinders;
     141        unsigned sectors;
     142        uint64_t blocks;
     143} disk_t;
     144
    136145static const size_t block_size = 512;
    137146static size_t comm_size;
     
    146155static atomic_t dev_futex = FUTEX_INITIALIZER;
    147156
    148 static unsigned heads, cylinders, sectors;
    149 static uint64_t disk_blocks;
     157static disk_t disk[2];
    150158
    151159static int ata_bd_init(void);
     
    155163static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
    156164    void *buf);
     165static int drive_identify(int drive_id, disk_t *d);
    157166
    158167int main(int argc, char **argv)
    159168{
    160169        uint8_t status;
    161         uint16_t data;
    162         int i;
     170        char name[16];
     171        int i, rc;
     172        int n_disks;
    163173
    164174        printf(NAME ": ATA disk driver\n");
     
    188198        printf("Status = 0x%x\n", pio_read_8(&cmd->status));
    189199
    190         printf("Issue drive_identify command\n");
    191         pio_write_8(&cmd->drive_head, 0x00);
    192         async_usleep(100);
    193         pio_write_8(&cmd->command, 0xEC);
    194 
    195         printf("Status = 0x%x\n", pio_read_8(&cmd->status));
    196 
    197         for (i = 0; i < 256; i++) {
    198                 do {
    199                         status = pio_read_8(&cmd->status);
    200                 } while ((status & SR_DRDY) == 0);
    201 
    202                 data = pio_read_16(&cmd->data_port);
    203 
    204                 switch (i) {
    205                 case 1: cylinders = data; break;
    206                 case 3: heads = data; break;
    207                 case 6: sectors = data; break;
    208                 }
    209         }
    210 
    211         printf("\n\nStatus = 0x%x\n", pio_read_8(&cmd->status));
    212 
    213         printf("Geometry: %u cylinders, %u heads, %u sectors\n",
    214                 cylinders, heads, sectors);
    215         disk_blocks = cylinders * heads * sectors;
    216 
    217         printf(NAME ": Accepting connections\n");
    218         async_manager();
    219 
    220         /* Not reached */
    221         return 0;
    222 }
    223 
    224 static int ata_bd_init(void)
    225 {
    226         void *vaddr;
    227         int rc, i;
    228         char name[16];
    229 
    230         rc = devmap_driver_register(NAME, ata_bd_connection);
    231         if (rc < 0) {
    232                 printf(NAME ": Unable to register driver.\n");
    233                 return rc;
    234         }
    235 
    236         rc = pio_enable((void *) cmd_physical, sizeof(ata_cmd_t), &vaddr);
    237         if (rc != EOK) {
    238                 printf(NAME ": Could not initialize device I/O space.\n");
    239                 return rc;
    240         }
    241 
    242         cmd = vaddr;
    243 
    244         rc = pio_enable((void *) ctl_physical, sizeof(ata_ctl_t), &vaddr);
    245         if (rc != EOK) {
    246                 printf(NAME ": Could not initialize device I/O space.\n");
    247                 return rc;
    248         }
    249 
    250         ctl = vaddr;
     200        (void) drive_identify(0, &disk[0]);
     201        (void) drive_identify(1, &disk[1]);
     202
     203        n_disks = 0;
    251204
    252205        for (i = 0; i < MAX_DISKS; i++) {
     206                /* Skip unattached drives. */
     207                if (disk[i].present == false)
     208                        continue;
     209
    253210                snprintf(name, 16, "disk%d", i);
    254211                rc = devmap_device_register(name, &dev_handle[i]);
     
    259216                        return rc;
    260217                }
    261         }
     218                ++n_disks;
     219        }
     220
     221        if (n_disks == 0) {
     222                printf("No disks detected.\n");
     223                return -1;
     224        }
     225
     226        printf(NAME ": Accepting connections\n");
     227        async_manager();
     228
     229        /* Not reached */
     230        return 0;
     231}
     232
     233static int drive_identify(int disk_id, disk_t *d)
     234{
     235        uint16_t data;
     236        uint8_t status;
     237        int i;
     238
     239        printf("Identify drive %d\n", disk_id);
     240        pio_write_8(&cmd->drive_head, ((disk_id != 0) ? DHR_DRV : 0));
     241        async_usleep(100);
     242        pio_write_8(&cmd->command, 0xEC);
     243
     244        status = pio_read_8(&cmd->status);
     245        printf("Status = 0x%x\n", status);
     246
     247        d->present = false;
     248
     249        /*
     250         * Detect if drive is present. This is Qemu only! Need to
     251         * do the right thing to work with real drives.
     252         */
     253        if ((status & SR_DRDY) == 0) {
     254                printf("None attached.\n");
     255                return ENOENT;
     256        }
     257
     258        for (i = 0; i < 256; i++) {
     259                do {
     260                        status = pio_read_8(&cmd->status);
     261                } while ((status & SR_DRDY) == 0);
     262
     263                data = pio_read_16(&cmd->data_port);
     264
     265                switch (i) {
     266                case 1: d->cylinders = data; break;
     267                case 3: d->heads = data; break;
     268                case 6: d->sectors = data; break;
     269                }
     270        }
     271
     272        printf("\n\nStatus = 0x%x\n", pio_read_8(&cmd->status));
     273
     274        d->blocks = d->cylinders * d->heads * d->sectors;
     275
     276        printf("Geometry: %u cylinders, %u heads, %u sectors\n",
     277                d->cylinders, d->heads, d->sectors);
     278
     279        d->present = true;
     280
     281        return EOK;
     282}
     283
     284static int ata_bd_init(void)
     285{
     286        void *vaddr;
     287        int rc;
     288
     289        rc = devmap_driver_register(NAME, ata_bd_connection);
     290        if (rc < 0) {
     291                printf(NAME ": Unable to register driver.\n");
     292                return rc;
     293        }
     294
     295        rc = pio_enable((void *) cmd_physical, sizeof(ata_cmd_t), &vaddr);
     296        if (rc != EOK) {
     297                printf(NAME ": Could not initialize device I/O space.\n");
     298                return rc;
     299        }
     300
     301        cmd = vaddr;
     302
     303        rc = pio_enable((void *) ctl_physical, sizeof(ata_ctl_t), &vaddr);
     304        if (rc != EOK) {
     305                printf(NAME ": Could not initialize device I/O space.\n");
     306                return rc;
     307        }
     308
     309        ctl = vaddr;
     310
    262311
    263312        return EOK;
     
    286335                        disk_id = i;
    287336
    288         if (disk_id < 0) {
     337        if (disk_id < 0 || disk[disk_id].present == false) {
    289338                ipc_answer_0(iid, EINVAL);
    290339                return;
     
    375424        uint64_t idx;
    376425        uint8_t drv_head;
     426        disk_t *d;
     427
     428        d = &disk[disk_id];
    377429
    378430        /* Check device bounds. */
    379         if (blk_idx >= disk_blocks)
     431        if (blk_idx >= d->blocks)
    380432                return EINVAL;
    381433
    382434        /* Compute CHS. */
    383         c = blk_idx / (heads * sectors);
    384         idx = blk_idx % (heads * sectors);
    385 
    386         h = idx / sectors;
    387         s = 1 + (idx % sectors);
     435        c = blk_idx / (d->heads * d->sectors);
     436        idx = blk_idx % (d->heads * d->sectors);
     437
     438        h = idx / d->sectors;
     439        s = 1 + (idx % d->sectors);
    388440
    389441        /* New value for Drive/Head register */
Note: See TracChangeset for help on using the changeset viewer.