Subversion Repositories HelenOS

Rev

Rev 4507 | Rev 4530 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4507 Rev 4529
Line 48... Line 48...
48
#include <as.h>
48
#include <as.h>
49
#include <futex.h>
49
#include <futex.h>
50
#include <devmap.h>
50
#include <devmap.h>
51
#include <sys/types.h>
51
#include <sys/types.h>
52
#include <errno.h>
52
#include <errno.h>
-
 
53
#include <bool.h>
53
 
54
 
54
#define NAME "ata_bd"
55
#define NAME "ata_bd"
55
 
56
 
56
enum {
57
enum {
57
    CTL_READ_START  = 0,
58
    CTL_READ_START  = 0,
Line 131... Line 132...
131
    ER_ABRT     = 0x04, /**< Aborted Command */
132
    ER_ABRT     = 0x04, /**< Aborted Command */
132
    ER_TK0NF    = 0x02, /**< Track 0 Not Found */
133
    ER_TK0NF    = 0x02, /**< Track 0 Not Found */
133
    ER_AMNF     = 0x01  /**< Address Mark Not Found */
134
    ER_AMNF     = 0x01  /**< Address Mark Not Found */
134
};
135
};
135
 
136
 
-
 
137
typedef struct {
-
 
138
    bool present;
-
 
139
    unsigned heads;
-
 
140
    unsigned cylinders;
-
 
141
    unsigned sectors;
-
 
142
    uint64_t blocks;
-
 
143
} disk_t;
-
 
144
 
136
static const size_t block_size = 512;
145
static const size_t block_size = 512;
137
static size_t comm_size;
146
static size_t comm_size;
138
 
147
 
139
static uintptr_t cmd_physical = 0x1f0;
148
static uintptr_t cmd_physical = 0x1f0;
140
static uintptr_t ctl_physical = 0x170;
149
static uintptr_t ctl_physical = 0x170;
Line 143... Line 152...
143
 
152
 
144
static dev_handle_t dev_handle[MAX_DISKS];
153
static dev_handle_t dev_handle[MAX_DISKS];
145
 
154
 
146
static atomic_t dev_futex = FUTEX_INITIALIZER;
155
static atomic_t dev_futex = FUTEX_INITIALIZER;
147
 
156
 
148
static unsigned heads, cylinders, sectors;
-
 
149
static uint64_t disk_blocks;
157
static disk_t disk[2];
150
 
158
 
151
static int ata_bd_init(void);
159
static int ata_bd_init(void);
152
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
160
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
153
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size,
161
static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, off_t size,
154
    void *buf);
162
    void *buf);
155
static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
163
static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
156
    void *buf);
164
    void *buf);
-
 
165
static int drive_identify(int drive_id, disk_t *d);
157
 
166
 
158
int main(int argc, char **argv)
167
int main(int argc, char **argv)
159
{
168
{
160
    uint8_t status;
169
    uint8_t status;
-
 
170
    char name[16];
161
    uint16_t data;
171
    int i, rc;
162
    int i;
172
    int n_disks;
163
 
173
 
164
    printf(NAME ": ATA disk driver\n");
174
    printf(NAME ": ATA disk driver\n");
165
 
175
 
166
    printf("cmd_physical = 0x%x\n", cmd_physical);
176
    printf("cmd_physical = 0x%x\n", cmd_physical);
167
    printf("ctl_physical = 0x%x\n", ctl_physical);
177
    printf("ctl_physical = 0x%x\n", ctl_physical);
Line 185... Line 195...
185
    } while ((status & SR_BSY) != 0);
195
    } while ((status & SR_BSY) != 0);
186
    printf("Done\n");
196
    printf("Done\n");
187
 
197
 
188
    printf("Status = 0x%x\n", pio_read_8(&cmd->status));
198
    printf("Status = 0x%x\n", pio_read_8(&cmd->status));
189
 
199
 
-
 
200
    (void) drive_identify(0, &disk[0]);
-
 
201
    (void) drive_identify(1, &disk[1]);
-
 
202
 
-
 
203
    n_disks = 0;
-
 
204
 
-
 
205
    for (i = 0; i < MAX_DISKS; i++) {
-
 
206
        /* Skip unattached drives. */
-
 
207
        if (disk[i].present == false)
-
 
208
            continue;
-
 
209
 
-
 
210
        snprintf(name, 16, "disk%d", i);
-
 
211
        rc = devmap_device_register(name, &dev_handle[i]);
-
 
212
        if (rc != EOK) {
-
 
213
            devmap_hangup_phone(DEVMAP_DRIVER);
-
 
214
            printf(NAME ": Unable to register device %s.\n",
-
 
215
                name);
-
 
216
            return rc;
-
 
217
        }
-
 
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
 
-
 
233
static int drive_identify(int disk_id, disk_t *d)
-
 
234
{
-
 
235
    uint16_t data;
-
 
236
    uint8_t status;
-
 
237
    int i;
-
 
238
 
190
    printf("Issue drive_identify command\n");
239
    printf("Identify drive %d\n", disk_id);
191
    pio_write_8(&cmd->drive_head, 0x00);
240
    pio_write_8(&cmd->drive_head, ((disk_id != 0) ? DHR_DRV : 0));
192
    async_usleep(100);
241
    async_usleep(100);
193
    pio_write_8(&cmd->command, 0xEC);
242
    pio_write_8(&cmd->command, 0xEC);
194
 
243
 
-
 
244
    status = pio_read_8(&cmd->status);
195
    printf("Status = 0x%x\n", 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
    }
196
 
257
 
197
    for (i = 0; i < 256; i++) {
258
    for (i = 0; i < 256; i++) {
198
        do {
259
        do {
199
            status = pio_read_8(&cmd->status);
260
            status = pio_read_8(&cmd->status);
200
        } while ((status & SR_DRDY) == 0);
261
        } while ((status & SR_DRDY) == 0);
201
 
262
 
202
        data = pio_read_16(&cmd->data_port);
263
        data = pio_read_16(&cmd->data_port);
203
 
264
 
204
        switch (i) {
265
        switch (i) {
205
        case 1: cylinders = data; break;
266
        case 1: d->cylinders = data; break;
206
        case 3: heads = data; break;
267
        case 3: d->heads = data; break;
207
        case 6: sectors = data; break;
268
        case 6: d->sectors = data; break;
208
        }
269
        }
209
    }
270
    }
210
 
271
 
211
    printf("\n\nStatus = 0x%x\n", pio_read_8(&cmd->status));
272
    printf("\n\nStatus = 0x%x\n", pio_read_8(&cmd->status));
212
 
273
 
-
 
274
    d->blocks = d->cylinders * d->heads * d->sectors;
-
 
275
 
213
    printf("Geometry: %u cylinders, %u heads, %u sectors\n",
276
    printf("Geometry: %u cylinders, %u heads, %u sectors\n",
214
        cylinders, heads, sectors);
277
        d->cylinders, d->heads, d->sectors);
215
    disk_blocks = cylinders * heads * sectors;
-
 
216
 
278
 
217
    printf(NAME ": Accepting connections\n");
-
 
218
    async_manager();
279
    d->present = true;
219
 
280
 
220
    /* Not reached */
-
 
221
    return 0;
281
    return EOK;
222
}
282
}
223
 
283
 
224
static int ata_bd_init(void)
284
static int ata_bd_init(void)
225
{
285
{
226
    void *vaddr;
286
    void *vaddr;
227
    int rc, i;
287
    int rc;
228
    char name[16];
-
 
229
 
288
 
230
    rc = devmap_driver_register(NAME, ata_bd_connection);
289
    rc = devmap_driver_register(NAME, ata_bd_connection);
231
    if (rc < 0) {
290
    if (rc < 0) {
232
        printf(NAME ": Unable to register driver.\n");
291
        printf(NAME ": Unable to register driver.\n");
233
        return rc;
292
        return rc;
Line 247... Line 306...
247
        return rc;
306
        return rc;
248
    }
307
    }
249
 
308
 
250
    ctl = vaddr;
309
    ctl = vaddr;
251
 
310
 
252
    for (i = 0; i < MAX_DISKS; i++) {
-
 
253
        snprintf(name, 16, "disk%d", i);
-
 
254
        rc = devmap_device_register(name, &dev_handle[i]);
-
 
255
        if (rc != EOK) {
-
 
256
            devmap_hangup_phone(DEVMAP_DRIVER);
-
 
257
            printf(NAME ": Unable to register device %s.\n",
-
 
258
                name);
-
 
259
            return rc;
-
 
260
        }
-
 
261
    }
-
 
262
 
311
 
263
    return EOK;
312
    return EOK;
264
}
313
}
265
 
314
 
266
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
315
static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
Line 283... Line 332...
283
    disk_id = -1;
332
    disk_id = -1;
284
    for (i = 0; i < MAX_DISKS; i++)
333
    for (i = 0; i < MAX_DISKS; i++)
285
        if (dev_handle[i] == dh)
334
        if (dev_handle[i] == dh)
286
            disk_id = i;
335
            disk_id = i;
287
 
336
 
288
    if (disk_id < 0) {
337
    if (disk_id < 0 || disk[disk_id].present == false) {
289
        ipc_answer_0(iid, EINVAL);
338
        ipc_answer_0(iid, EINVAL);
290
        return;
339
        return;
291
    }
340
    }
292
 
341
 
293
    /* Answer the IPC_M_CONNECT_ME_TO call. */
342
    /* Answer the IPC_M_CONNECT_ME_TO call. */
Line 372... Line 421...
372
    uint16_t data;
421
    uint16_t data;
373
    uint8_t status;
422
    uint8_t status;
374
    uint64_t c, h, s;
423
    uint64_t c, h, s;
375
    uint64_t idx;
424
    uint64_t idx;
376
    uint8_t drv_head;
425
    uint8_t drv_head;
-
 
426
    disk_t *d;
-
 
427
 
-
 
428
    d = &disk[disk_id];
377
 
429
 
378
    /* Check device bounds. */
430
    /* Check device bounds. */
379
    if (blk_idx >= disk_blocks)
431
    if (blk_idx >= d->blocks)
380
        return EINVAL;
432
        return EINVAL;
381
 
433
 
382
    /* Compute CHS. */
434
    /* Compute CHS. */
383
    c = blk_idx / (heads * sectors);
435
    c = blk_idx / (d->heads * d->sectors);
384
    idx = blk_idx % (heads * sectors);
436
    idx = blk_idx % (d->heads * d->sectors);
385
 
437
 
386
    h = idx / sectors;
438
    h = idx / d->sectors;
387
    s = 1 + (idx % sectors);
439
    s = 1 + (idx % d->sectors);
388
 
440
 
389
    /* New value for Drive/Head register */
441
    /* New value for Drive/Head register */
390
    drv_head =
442
    drv_head =
391
        ((disk_id != 0) ? DHR_DRV : 0) |
443
        ((disk_id != 0) ? DHR_DRV : 0) |
392
        (h & 0x0f);
444
        (h & 0x0f);