source: mainline/uspace/drv/block/ata_bd/ata_bd.c@ e9690b6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e9690b6 was 8d2dd7f2, checked in by Jakub Jermar <jakub@…>, 8 years ago

Reduce the number of files that include <sys/types.h>

  • Property mode set to 100644
File size: 30.8 KB
Line 
1/*
2 * Copyright (c) 2013 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup bd
30 * @{
31 */
32
33/**
34 * @file
35 * @brief ATA disk driver
36 *
37 * This driver supports CHS, 28-bit and 48-bit LBA addressing, as well as
38 * PACKET devices. It only uses PIO transfers. There is no support DMA
39 * or any other 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.
45 *
46 * The driver services a single controller which can have up to two disks
47 * attached.
48 */
49
50#include <ddi.h>
51#include <ddf/log.h>
52#include <async.h>
53#include <as.h>
54#include <bd_srv.h>
55#include <fibril_synch.h>
56#include <scsi/mmc.h>
57#include <scsi/sbc.h>
58#include <scsi/spc.h>
59#include <stdint.h>
60#include <stdbool.h>
61#include <stdio.h>
62#include <stddef.h>
63#include <str.h>
64#include <loc.h>
65#include <inttypes.h>
66#include <errno.h>
67#include <byteorder.h>
68#include <task.h>
69#include <macros.h>
70
71#include "ata_hw.h"
72#include "ata_bd.h"
73#include "main.h"
74
75#define NAME "ata_bd"
76
77/** Number of defined legacy controller base addresses. */
78#define LEGACY_CTLS 4
79
80/**
81 * Size of data returned from Identify Device or Identify Packet Device
82 * command.
83 */
84static const size_t identify_data_size = 512;
85
86static int ata_bd_init_io(ata_ctrl_t *ctrl);
87static void ata_bd_fini_io(ata_ctrl_t *ctrl);
88
89static int ata_bd_open(bd_srvs_t *, bd_srv_t *);
90static int ata_bd_close(bd_srv_t *);
91static int ata_bd_read_blocks(bd_srv_t *, uint64_t ba, size_t cnt, void *buf,
92 size_t);
93static int ata_bd_read_toc(bd_srv_t *, uint8_t session, void *buf, size_t);
94static int ata_bd_write_blocks(bd_srv_t *, uint64_t ba, size_t cnt,
95 const void *buf, size_t);
96static int ata_bd_get_block_size(bd_srv_t *, size_t *);
97static int ata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
98static int ata_bd_sync_cache(bd_srv_t *, aoff64_t, size_t);
99
100static int ata_rcmd_read(disk_t *disk, uint64_t ba, size_t cnt,
101 void *buf);
102static int ata_rcmd_write(disk_t *disk, uint64_t ba, size_t cnt,
103 const void *buf);
104static int ata_rcmd_flush_cache(disk_t *disk);
105static int disk_init(ata_ctrl_t *ctrl, disk_t *d, int disk_id);
106static int ata_identify_dev(disk_t *disk, void *buf);
107static int ata_identify_pkt_dev(disk_t *disk, void *buf);
108static int ata_cmd_packet(disk_t *disk, const void *cpkt, size_t cpkt_size,
109 void *obuf, size_t obuf_size, size_t *rcvd_size);
110static int ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size,
111 size_t *rcvd_size);
112static int ata_pcmd_read_12(disk_t *disk, uint64_t ba, size_t cnt,
113 void *obuf, size_t obuf_size);
114static int ata_pcmd_read_capacity(disk_t *disk, uint64_t *nblocks,
115 size_t *block_size);
116static int ata_pcmd_read_toc(disk_t *disk, uint8_t ses,
117 void *obuf, size_t obuf_size);
118static void disk_print_summary(disk_t *d);
119static int coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc);
120static void coord_sc_program(ata_ctrl_t *ctrl, const block_coord_t *bc,
121 uint16_t scnt);
122static int wait_status(ata_ctrl_t *ctrl, unsigned set, unsigned n_reset,
123 uint8_t *pstatus, unsigned timeout);
124
125bd_ops_t ata_bd_ops = {
126 .open = ata_bd_open,
127 .close = ata_bd_close,
128 .read_blocks = ata_bd_read_blocks,
129 .read_toc = ata_bd_read_toc,
130 .write_blocks = ata_bd_write_blocks,
131 .get_block_size = ata_bd_get_block_size,
132 .get_num_blocks = ata_bd_get_num_blocks,
133 .sync_cache = ata_bd_sync_cache
134};
135
136static disk_t *bd_srv_disk(bd_srv_t *bd)
137{
138 return (disk_t *)bd->srvs->sarg;
139}
140
141static int disk_dev_idx(disk_t *disk)
142{
143 return (disk->disk_id & 1);
144}
145
146/** Initialize ATA controller. */
147int ata_ctrl_init(ata_ctrl_t *ctrl, ata_base_t *res)
148{
149 int i, rc;
150 int n_disks;
151
152 ddf_msg(LVL_DEBUG, "ata_ctrl_init()");
153
154 fibril_mutex_initialize(&ctrl->lock);
155 ctrl->cmd_physical = res->cmd;
156 ctrl->ctl_physical = res->ctl;
157
158 ddf_msg(LVL_NOTE, "I/O address %p/%p", (void *) ctrl->cmd_physical,
159 (void *) ctrl->ctl_physical);
160
161 rc = ata_bd_init_io(ctrl);
162 if (rc != EOK)
163 return rc;
164
165 for (i = 0; i < MAX_DISKS; i++) {
166 ddf_msg(LVL_NOTE, "Identify drive %d...", i);
167
168 rc = disk_init(ctrl, &ctrl->disk[i], i);
169
170 if (rc == EOK) {
171 disk_print_summary(&ctrl->disk[i]);
172 } else {
173 ddf_msg(LVL_NOTE, "Not found.");
174 }
175 }
176
177 n_disks = 0;
178
179 for (i = 0; i < MAX_DISKS; i++) {
180 /* Skip unattached drives. */
181 if (ctrl->disk[i].present == false)
182 continue;
183
184 rc = ata_fun_create(&ctrl->disk[i]);
185 if (rc != EOK) {
186 ddf_msg(LVL_ERROR, "Unable to create function for "
187 "disk %d.", i);
188 goto error;
189 }
190 ++n_disks;
191 }
192
193 if (n_disks == 0) {
194 ddf_msg(LVL_WARN, "No disks detected.");
195 rc = EIO;
196 goto error;
197 }
198
199 return EOK;
200error:
201 for (i = 0; i < MAX_DISKS; i++) {
202 if (ata_fun_remove(&ctrl->disk[i]) != EOK) {
203 ddf_msg(LVL_ERROR, "Unable to clean up function for "
204 "disk %d.", i);
205 }
206 }
207 ata_bd_fini_io(ctrl);
208 return rc;
209}
210
211/** Remove ATA controller. */
212int ata_ctrl_remove(ata_ctrl_t *ctrl)
213{
214 int i, rc;
215
216 ddf_msg(LVL_DEBUG, ": ata_ctrl_remove()");
217
218 fibril_mutex_lock(&ctrl->lock);
219
220 for (i = 0; i < MAX_DISKS; i++) {
221 rc = ata_fun_remove(&ctrl->disk[i]);
222 if (rc != EOK) {
223 ddf_msg(LVL_ERROR, "Unable to clean up function for "
224 "disk %d.", i);
225 return rc;
226 }
227 }
228
229 ata_bd_fini_io(ctrl);
230 fibril_mutex_unlock(&ctrl->lock);
231
232 return EOK;
233}
234
235/** Surprise removal of ATA controller. */
236int ata_ctrl_gone(ata_ctrl_t *ctrl)
237{
238 int i, rc;
239
240 ddf_msg(LVL_DEBUG, "ata_ctrl_gone()");
241
242 fibril_mutex_lock(&ctrl->lock);
243
244 for (i = 0; i < MAX_DISKS; i++) {
245 rc = ata_fun_unbind(&ctrl->disk[i]);
246 if (rc != EOK) {
247 ddf_msg(LVL_ERROR, "Unable to clean up function for "
248 "disk %d.", i);
249 return rc;
250 }
251 }
252
253 ata_bd_fini_io(ctrl);
254 fibril_mutex_unlock(&ctrl->lock);
255
256 return EOK;
257}
258
259/** Print one-line device summary. */
260static void disk_print_summary(disk_t *d)
261{
262 uint64_t mbytes;
263 char *atype = NULL;
264 char *cap = NULL;
265 int rc;
266
267 if (d->dev_type == ata_reg_dev) {
268 switch (d->amode) {
269 case am_chs:
270 rc = asprintf(&atype, "CHS %u cylinders, %u heads, "
271 "%u sectors", d->geom.cylinders, d->geom.heads,
272 d->geom.sectors);
273 if (rc < 0) {
274 /* Out of memory */
275 atype = NULL;
276 }
277 break;
278 case am_lba28:
279 atype = str_dup("LBA-28");
280 break;
281 case am_lba48:
282 atype = str_dup("LBA-48");
283 break;
284 }
285 } else {
286 atype = str_dup("PACKET");
287 }
288
289 if (atype == NULL)
290 return;
291
292 mbytes = d->blocks / (2 * 1024);
293 if (mbytes > 0) {
294 rc = asprintf(&cap, " %" PRIu64 " MB.", mbytes);
295 if (rc < 0) {
296 cap = NULL;
297 goto cleanup;
298 }
299 }
300
301 ddf_msg(LVL_NOTE, "%s: %s %" PRIu64 " blocks%s", d->model, atype,
302 d->blocks, cap);
303cleanup:
304 free(atype);
305 free(cap);
306}
307
308/** Enable device I/O. */
309static int ata_bd_init_io(ata_ctrl_t *ctrl)
310{
311 int rc;
312 void *vaddr;
313
314 rc = pio_enable((void *) ctrl->cmd_physical, sizeof(ata_cmd_t), &vaddr);
315 if (rc != EOK) {
316 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
317 return rc;
318 }
319
320 ctrl->cmd = vaddr;
321
322 rc = pio_enable((void *) ctrl->ctl_physical, sizeof(ata_ctl_t), &vaddr);
323 if (rc != EOK) {
324 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
325 return rc;
326 }
327
328 ctrl->ctl = vaddr;
329
330 return EOK;
331}
332
333/** Clean up device I/O. */
334static void ata_bd_fini_io(ata_ctrl_t *ctrl)
335{
336 (void) ctrl;
337 /* XXX TODO */
338}
339
340/** Initialize a disk.
341 *
342 * Probes for a disk, determines its parameters and initializes
343 * the disk structure.
344 */
345static int disk_init(ata_ctrl_t *ctrl, disk_t *d, int disk_id)
346{
347 identify_data_t idata;
348 uint8_t model[40];
349 scsi_std_inquiry_data_t inq_data;
350 size_t isize;
351 uint16_t w;
352 uint8_t c;
353 uint16_t bc;
354 uint64_t nblocks;
355 size_t block_size;
356 size_t pos, len;
357 int rc;
358 unsigned i;
359
360 d->ctrl = ctrl;
361 d->disk_id = disk_id;
362 d->present = false;
363 d->afun = NULL;
364
365 /* Try identify command. */
366 rc = ata_identify_dev(d, &idata);
367 if (rc == EOK) {
368 /* Success. It's a register (non-packet) device. */
369 ddf_msg(LVL_NOTE, "ATA register-only device found.");
370 d->dev_type = ata_reg_dev;
371 } else if (rc == EIO) {
372 /*
373 * There is something, but not a register device. Check to see
374 * whether the IDENTIFY command left the packet signature in
375 * the registers in case this is a packet device.
376 *
377 * According to the ATA specification, the LBA low and
378 * interrupt reason registers should be set to 0x01. However,
379 * there are many devices that do not follow this and only set
380 * the byte count registers. So, only check these.
381 */
382 bc = ((uint16_t)pio_read_8(&ctrl->cmd->cylinder_high) << 8) |
383 pio_read_8(&ctrl->cmd->cylinder_low);
384
385 if (bc == PDEV_SIGNATURE_BC) {
386 rc = ata_identify_pkt_dev(d, &idata);
387 if (rc == EOK) {
388 /* We have a packet device. */
389 d->dev_type = ata_pkt_dev;
390 } else {
391 return EIO;
392 }
393 } else {
394 /* Nope. Something's there, but not recognized. */
395 return EIO;
396 }
397 } else {
398 /* Operation timed out. That means there is no device there. */
399 return EIO;
400 }
401
402 if (d->dev_type == ata_pkt_dev) {
403 /* Packet device */
404 d->amode = 0;
405
406 d->geom.cylinders = 0;
407 d->geom.heads = 0;
408 d->geom.sectors = 0;
409
410 d->blocks = 0;
411 } else if ((idata.caps & rd_cap_lba) == 0) {
412 /* Device only supports CHS addressing. */
413 d->amode = am_chs;
414
415 d->geom.cylinders = idata.cylinders;
416 d->geom.heads = idata.heads;
417 d->geom.sectors = idata.sectors;
418
419 d->blocks = d->geom.cylinders * d->geom.heads * d->geom.sectors;
420 } else if ((idata.cmd_set1 & cs1_addr48) == 0) {
421 /* Device only supports LBA-28 addressing. */
422 d->amode = am_lba28;
423
424 d->geom.cylinders = 0;
425 d->geom.heads = 0;
426 d->geom.sectors = 0;
427
428 d->blocks =
429 (uint32_t) idata.total_lba28_0 |
430 ((uint32_t) idata.total_lba28_1 << 16);
431 } else {
432 /* Device supports LBA-48 addressing. */
433 d->amode = am_lba48;
434
435 d->geom.cylinders = 0;
436 d->geom.heads = 0;
437 d->geom.sectors = 0;
438
439 d->blocks =
440 (uint64_t) idata.total_lba48_0 |
441 ((uint64_t) idata.total_lba48_1 << 16) |
442 ((uint64_t) idata.total_lba48_2 << 32) |
443 ((uint64_t) idata.total_lba48_3 << 48);
444 }
445
446 /*
447 * Convert model name to string representation.
448 */
449 for (i = 0; i < 20; i++) {
450 w = idata.model_name[i];
451 model[2 * i] = w >> 8;
452 model[2 * i + 1] = w & 0x00ff;
453 }
454
455 len = 40;
456 while (len > 0 && model[len - 1] == 0x20)
457 --len;
458
459 pos = 0;
460 for (i = 0; i < len; ++i) {
461 c = model[i];
462 if (c >= 0x80) c = '?';
463
464 chr_encode(c, d->model, &pos, 40);
465 }
466 d->model[pos] = '\0';
467
468 if (d->dev_type == ata_pkt_dev) {
469 /* Send inquiry. */
470 rc = ata_pcmd_inquiry(d, &inq_data, sizeof(inq_data), &isize);
471 if (rc != EOK || isize < sizeof(inq_data)) {
472 ddf_msg(LVL_ERROR, "Device inquiry failed.");
473 d->present = false;
474 return EIO;
475 }
476
477 /* Check device type. */
478 if (INQUIRY_PDEV_TYPE(inq_data.pqual_devtype) != SCSI_DEV_CD_DVD)
479 ddf_msg(LVL_WARN, "Peripheral device type is not CD-ROM.");
480
481 rc = ata_pcmd_read_capacity(d, &nblocks, &block_size);
482 if (rc != EOK) {
483 ddf_msg(LVL_ERROR, "Read capacity command failed.");
484 d->present = false;
485 return EIO;
486 }
487
488 d->blocks = nblocks;
489 d->block_size = block_size;
490 } else {
491 /* Assume register Read always uses 512-byte blocks. */
492 d->block_size = 512;
493 }
494
495 d->present = true;
496 return EOK;
497}
498
499static int ata_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
500{
501 return EOK;
502}
503
504static int ata_bd_close(bd_srv_t *bd)
505{
506 return EOK;
507}
508
509/** Read multiple blocks from the device. */
510static int ata_bd_read_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
511 void *buf, size_t size)
512{
513 disk_t *disk = bd_srv_disk(bd);
514 int rc;
515
516 if (size < cnt * disk->block_size)
517 return EINVAL;
518
519 while (cnt > 0) {
520 if (disk->dev_type == ata_reg_dev) {
521 rc = ata_rcmd_read(disk, ba, 1, buf);
522 } else {
523 rc = ata_pcmd_read_12(disk, ba, 1, buf,
524 disk->block_size);
525 }
526
527 if (rc != EOK)
528 return rc;
529
530 ++ba;
531 --cnt;
532 buf += disk->block_size;
533 }
534
535 return EOK;
536}
537
538/** Read TOC from device. */
539static int ata_bd_read_toc(bd_srv_t *bd, uint8_t session, void *buf, size_t size)
540{
541 disk_t *disk = bd_srv_disk(bd);
542
543 return ata_pcmd_read_toc(disk, session, buf, size);
544}
545
546/** Write multiple blocks to the device. */
547static int ata_bd_write_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
548 const void *buf, size_t size)
549{
550 disk_t *disk = bd_srv_disk(bd);
551 int rc;
552
553 if (disk->dev_type != ata_reg_dev)
554 return ENOTSUP;
555
556 if (size < cnt * disk->block_size)
557 return EINVAL;
558
559 while (cnt > 0) {
560 rc = ata_rcmd_write(disk, ba, 1, buf);
561 if (rc != EOK)
562 return rc;
563
564 ++ba;
565 --cnt;
566 buf += disk->block_size;
567 }
568
569 return EOK;
570}
571
572/** Get device block size. */
573static int ata_bd_get_block_size(bd_srv_t *bd, size_t *rbsize)
574{
575 disk_t *disk = bd_srv_disk(bd);
576
577 *rbsize = disk->block_size;
578 return EOK;
579}
580
581/** Get device number of blocks. */
582static int ata_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
583{
584 disk_t *disk = bd_srv_disk(bd);
585
586 *rnb = disk->blocks;
587 return EOK;
588}
589
590/** Flush cache. */
591static int ata_bd_sync_cache(bd_srv_t *bd, uint64_t ba, size_t cnt)
592{
593 disk_t *disk = bd_srv_disk(bd);
594
595 /* ATA cannot flush just some blocks, we just flush everything. */
596 (void)ba;
597 (void)cnt;
598
599 return ata_rcmd_flush_cache(disk);
600}
601
602/** PIO data-in command protocol. */
603static int ata_pio_data_in(disk_t *disk, void *obuf, size_t obuf_size,
604 size_t blk_size, size_t nblocks)
605{
606 ata_ctrl_t *ctrl = disk->ctrl;
607 uint16_t data;
608 size_t i;
609 uint8_t status;
610
611 /* XXX Support multiple blocks */
612 assert(nblocks == 1);
613 assert(blk_size % 2 == 0);
614
615 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
616 return EIO;
617
618 if ((status & SR_DRQ) != 0) {
619 /* Read data from the device buffer. */
620
621 for (i = 0; i < blk_size / 2; i++) {
622 data = pio_read_16(&ctrl->cmd->data_port);
623 ((uint16_t *) obuf)[i] = data;
624 }
625 }
626
627 if ((status & SR_ERR) != 0)
628 return EIO;
629
630 return EOK;
631}
632
633/** PIO data-out command protocol. */
634static int ata_pio_data_out(disk_t *disk, const void *buf, size_t buf_size,
635 size_t blk_size, size_t nblocks)
636{
637 ata_ctrl_t *ctrl = disk->ctrl;
638 size_t i;
639 uint8_t status;
640
641 /* XXX Support multiple blocks */
642 assert(nblocks == 1);
643 assert(blk_size % 2 == 0);
644
645 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
646 return EIO;
647
648 if ((status & SR_DRQ) != 0) {
649 /* Write data to the device buffer. */
650
651 for (i = 0; i < blk_size / 2; i++) {
652 pio_write_16(&ctrl->cmd->data_port, ((uint16_t *) buf)[i]);
653 }
654 }
655
656 if (status & SR_ERR)
657 return EIO;
658
659 return EOK;
660}
661
662/** PIO non-data command protocol. */
663static int ata_pio_nondata(disk_t *disk)
664{
665 ata_ctrl_t *ctrl = disk->ctrl;
666 uint8_t status;
667
668 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
669 return EIO;
670
671 if (status & SR_ERR)
672 return EIO;
673
674 return EOK;
675}
676
677/** Issue IDENTIFY DEVICE command.
678 *
679 * Reads @c identify data into the provided buffer. This is used to detect
680 * whether an ATA device is present and if so, to determine its parameters.
681 *
682 * @param disk Disk
683 * @param buf Pointer to a 512-byte buffer.
684 *
685 * @return ETIMEOUT on timeout (this can mean the device is
686 * not present). EIO if device responds with error.
687 */
688static int ata_identify_dev(disk_t *disk, void *buf)
689{
690 ata_ctrl_t *ctrl = disk->ctrl;
691 uint8_t status;
692 uint8_t drv_head;
693
694 drv_head = ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0);
695
696 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
697 return ETIMEOUT;
698
699 pio_write_8(&ctrl->cmd->drive_head, drv_head);
700
701 /*
702 * Do not wait for DRDY to be set in case this is a packet device.
703 * We determine whether the device is present by waiting for DRQ to be
704 * set after issuing the command.
705 */
706 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
707 return ETIMEOUT;
708
709 pio_write_8(&ctrl->cmd->command, CMD_IDENTIFY_DRIVE);
710
711 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
712 return ETIMEOUT;
713
714 /*
715 * If ERR is set, this may be a packet device, so return EIO to cause
716 * the caller to check for one.
717 */
718 if ((status & SR_ERR) != 0)
719 return EIO;
720
721 /*
722 * For probing purposes we need to wait for some status bit to become
723 * active - otherwise we could be fooled just by receiving all zeroes.
724 */
725 if (wait_status(ctrl, SR_DRQ, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
726 return ETIMEOUT;
727
728 return ata_pio_data_in(disk, buf, identify_data_size,
729 identify_data_size, 1);
730}
731
732/** Issue Identify Packet Device command.
733 *
734 * Reads @c identify data into the provided buffer. This is used to detect
735 * whether an ATAPI device is present and if so, to determine its parameters.
736 *
737 * @param disk Disk
738 * @param buf Pointer to a 512-byte buffer.
739 */
740static int ata_identify_pkt_dev(disk_t *disk, void *buf)
741{
742 ata_ctrl_t *ctrl = disk->ctrl;
743 uint8_t drv_head;
744
745 drv_head = ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0);
746
747 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
748 return EIO;
749
750 pio_write_8(&ctrl->cmd->drive_head, drv_head);
751
752 /* For ATAPI commands we do not need to wait for DRDY. */
753 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
754 return EIO;
755
756 pio_write_8(&ctrl->cmd->command, CMD_IDENTIFY_PKT_DEV);
757
758 return ata_pio_data_in(disk, buf, identify_data_size,
759 identify_data_size, 1);
760}
761
762/** Issue packet command (i. e. write a command packet to the device).
763 *
764 * Only data-in commands are supported (e.g. inquiry, read).
765 *
766 * @param disk Disk
767 * @param obuf Buffer for storing data read from device
768 * @param obuf_size Size of obuf in bytes
769 * @param rcvd_size Place to store number of bytes read or @c NULL
770 *
771 * @return EOK on success, EIO on error.
772 */
773static int ata_cmd_packet(disk_t *disk, const void *cpkt, size_t cpkt_size,
774 void *obuf, size_t obuf_size, size_t *rcvd_size)
775{
776 ata_ctrl_t *ctrl = disk->ctrl;
777 size_t i;
778 uint8_t status;
779 uint8_t drv_head;
780 size_t data_size;
781 uint16_t val;
782
783 fibril_mutex_lock(&ctrl->lock);
784
785 /* New value for Drive/Head register */
786 drv_head =
787 ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0);
788
789 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
790 fibril_mutex_unlock(&ctrl->lock);
791 return EIO;
792 }
793
794 pio_write_8(&ctrl->cmd->drive_head, drv_head);
795
796 if (wait_status(ctrl, 0, ~(SR_BSY|SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
797 fibril_mutex_unlock(&ctrl->lock);
798 return EIO;
799 }
800
801 /* Byte count <- max. number of bytes we can read in one transfer. */
802 pio_write_8(&ctrl->cmd->cylinder_low, 0xfe);
803 pio_write_8(&ctrl->cmd->cylinder_high, 0xff);
804
805 pio_write_8(&ctrl->cmd->command, CMD_PACKET);
806
807 if (wait_status(ctrl, SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
808 fibril_mutex_unlock(&ctrl->lock);
809 return EIO;
810 }
811
812 /* Write command packet. */
813 for (i = 0; i < (cpkt_size + 1) / 2; i++)
814 pio_write_16(&ctrl->cmd->data_port, ((uint16_t *) cpkt)[i]);
815
816 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
817 fibril_mutex_unlock(&ctrl->lock);
818 return EIO;
819 }
820
821 if ((status & SR_DRQ) == 0) {
822 fibril_mutex_unlock(&ctrl->lock);
823 return EIO;
824 }
825
826 /* Read byte count. */
827 data_size = (uint16_t) pio_read_8(&ctrl->cmd->cylinder_low) +
828 ((uint16_t) pio_read_8(&ctrl->cmd->cylinder_high) << 8);
829
830 /* Check whether data fits into output buffer. */
831 if (data_size > obuf_size) {
832 /* Output buffer is too small to store data. */
833 fibril_mutex_unlock(&ctrl->lock);
834 return EIO;
835 }
836
837 /* Read data from the device buffer. */
838 for (i = 0; i < (data_size + 1) / 2; i++) {
839 val = pio_read_16(&ctrl->cmd->data_port);
840 ((uint16_t *) obuf)[i] = val;
841 }
842
843 fibril_mutex_unlock(&ctrl->lock);
844
845 if (status & SR_ERR)
846 return EIO;
847
848 if (rcvd_size != NULL)
849 *rcvd_size = data_size;
850 return EOK;
851}
852
853/** Issue ATAPI Inquiry.
854 *
855 * @param disk Disk
856 * @param obuf Buffer for storing inquiry data read from device
857 * @param obuf_size Size of obuf in bytes
858 *
859 * @return EOK on success, EIO on error.
860 */
861static int ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size,
862 size_t *rcvd_size)
863{
864 uint8_t cpb[12];
865 scsi_cdb_inquiry_t *cp = (scsi_cdb_inquiry_t *)cpb;
866 int rc;
867
868 memset(cpb, 0, sizeof(cpb));
869
870 /*
871 * For SFF 8020 compliance the inquiry must be padded to 12 bytes
872 * and allocation length must fit in one byte.
873 */
874 cp->op_code = SCSI_CMD_INQUIRY;
875
876 /* Allocation length */
877 cp->alloc_len = host2uint16_t_be(min(obuf_size, 0xff));
878
879 rc = ata_cmd_packet(disk, cpb, sizeof(cpb), obuf, obuf_size, rcvd_size);
880 if (rc != EOK)
881 return rc;
882
883 return EOK;
884}
885
886/** Issue ATAPI read capacity(10) command.
887 *
888 * @param disk Disk
889 * @param nblocks Place to store number of blocks
890 * @param block_size Place to store block size
891 *
892 * @return EOK on success, EIO on error.
893 */
894static int ata_pcmd_read_capacity(disk_t *disk, uint64_t *nblocks,
895 size_t *block_size)
896{
897 scsi_cdb_read_capacity_10_t cdb;
898 scsi_read_capacity_10_data_t data;
899 size_t rsize;
900 int rc;
901
902 memset(&cdb, 0, sizeof(cdb));
903 cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
904
905 rc = ata_cmd_packet(disk, &cdb, sizeof(cdb), &data, sizeof(data), &rsize);
906 if (rc != EOK)
907 return rc;
908
909 if (rsize != sizeof(data))
910 return EIO;
911
912 *nblocks = uint32_t_be2host(data.last_lba) + 1;
913 *block_size = uint32_t_be2host(data.block_size);
914
915 return EOK;
916}
917
918/** Issue ATAPI read(12) command.
919 *
920 * Output buffer must be large enough to hold the data, otherwise the
921 * function will fail.
922 *
923 * @param disk Disk
924 * @param ba Starting block address
925 * @param cnt Number of blocks to read
926 * @param obuf Buffer for storing inquiry data read from device
927 * @param obuf_size Size of obuf in bytes
928 *
929 * @return EOK on success, EIO on error.
930 */
931static int ata_pcmd_read_12(disk_t *disk, uint64_t ba, size_t cnt,
932 void *obuf, size_t obuf_size)
933{
934 scsi_cdb_read_12_t cp;
935 int rc;
936
937 if (ba > UINT32_MAX)
938 return EINVAL;
939
940 memset(&cp, 0, sizeof(cp));
941
942 cp.op_code = SCSI_CMD_READ_12;
943 cp.lba = host2uint32_t_be(ba);
944 cp.xfer_len = host2uint32_t_be(cnt);
945
946 rc = ata_cmd_packet(disk, &cp, sizeof(cp), obuf, obuf_size, NULL);
947 if (rc != EOK)
948 return rc;
949
950 return EOK;
951}
952
953/** Issue ATAPI read TOC command.
954 *
955 * Read TOC in 'multi-session' format (first and last session number
956 * with last session LBA).
957 *
958 * http://suif.stanford.edu/~csapuntz/specs/INF-8020.PDF page 171
959 *
960 * Output buffer must be large enough to hold the data, otherwise the
961 * function will fail.
962 *
963 * @param disk Disk
964 * @param session Starting session
965 * @param obuf Buffer for storing inquiry data read from device
966 * @param obuf_size Size of obuf in bytes
967 *
968 * @return EOK on success, EIO on error.
969 */
970static int ata_pcmd_read_toc(disk_t *disk, uint8_t session, void *obuf,
971 size_t obuf_size)
972{
973 uint8_t cpb[12];
974 scsi_cdb_read_toc_t *cp = (scsi_cdb_read_toc_t *)cpb;
975 int rc;
976
977 memset(cpb, 0, sizeof(cpb));
978
979 cp->op_code = SCSI_CMD_READ_TOC;
980 cp->msf = 0;
981 cp->format = 0x01; /* 0x01 = multi-session mode */
982 cp->track_sess_no = session;
983 cp->alloc_len = host2uint16_t_be(obuf_size);
984 cp->control = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */
985
986 rc = ata_cmd_packet(disk, cpb, sizeof(cpb), obuf, obuf_size, NULL);
987 if (rc != EOK)
988 return rc;
989
990 return EOK;
991}
992
993/** Read a physical block from the device.
994 *
995 * @param disk Disk
996 * @param ba Address the first block.
997 * @param cnt Number of blocks to transfer.
998 * @param buf Buffer for holding the data.
999 *
1000 * @return EOK on success, EIO on error.
1001 */
1002static int ata_rcmd_read(disk_t *disk, uint64_t ba, size_t blk_cnt,
1003 void *buf)
1004{
1005 ata_ctrl_t *ctrl = disk->ctrl;
1006 uint8_t drv_head;
1007 block_coord_t bc;
1008 int rc;
1009
1010 /* Silence warning. */
1011 memset(&bc, 0, sizeof(bc));
1012
1013 /* Compute block coordinates. */
1014 if (coord_calc(disk, ba, &bc) != EOK)
1015 return EINVAL;
1016
1017 /* New value for Drive/Head register */
1018 drv_head =
1019 ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0) |
1020 ((disk->amode != am_chs) ? DHR_LBA : 0) |
1021 (bc.h & 0x0f);
1022
1023 fibril_mutex_lock(&ctrl->lock);
1024
1025 /* Program a Read Sectors operation. */
1026
1027 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
1028 fibril_mutex_unlock(&ctrl->lock);
1029 return EIO;
1030 }
1031
1032 pio_write_8(&ctrl->cmd->drive_head, drv_head);
1033
1034 if (wait_status(ctrl, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
1035 fibril_mutex_unlock(&ctrl->lock);
1036 return EIO;
1037 }
1038
1039 /* Program block coordinates into the device. */
1040 coord_sc_program(ctrl, &bc, 1);
1041
1042 pio_write_8(&ctrl->cmd->command, disk->amode == am_lba48 ?
1043 CMD_READ_SECTORS_EXT : CMD_READ_SECTORS);
1044
1045 rc = ata_pio_data_in(disk, buf, blk_cnt * disk->block_size,
1046 disk->block_size, blk_cnt);
1047
1048 fibril_mutex_unlock(&ctrl->lock);
1049
1050 return rc;
1051}
1052
1053/** Write a physical block to the device.
1054 *
1055 * @param disk Disk
1056 * @param ba Address of the first block.
1057 * @param cnt Number of blocks to transfer.
1058 * @param buf Buffer holding the data to write.
1059 *
1060 * @return EOK on success, EIO on error.
1061 */
1062static int ata_rcmd_write(disk_t *disk, uint64_t ba, size_t cnt,
1063 const void *buf)
1064{
1065 ata_ctrl_t *ctrl = disk->ctrl;
1066 uint8_t drv_head;
1067 block_coord_t bc;
1068 int rc;
1069
1070 /* Silence warning. */
1071 memset(&bc, 0, sizeof(bc));
1072
1073 /* Compute block coordinates. */
1074 if (coord_calc(disk, ba, &bc) != EOK)
1075 return EINVAL;
1076
1077 /* New value for Drive/Head register */
1078 drv_head =
1079 ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0) |
1080 ((disk->amode != am_chs) ? DHR_LBA : 0) |
1081 (bc.h & 0x0f);
1082
1083 fibril_mutex_lock(&ctrl->lock);
1084
1085 /* Program a Write Sectors operation. */
1086
1087 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
1088 fibril_mutex_unlock(&ctrl->lock);
1089 return EIO;
1090 }
1091
1092 pio_write_8(&ctrl->cmd->drive_head, drv_head);
1093
1094 if (wait_status(ctrl, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
1095 fibril_mutex_unlock(&ctrl->lock);
1096 return EIO;
1097 }
1098
1099 /* Program block coordinates into the device. */
1100 coord_sc_program(ctrl, &bc, 1);
1101
1102 pio_write_8(&ctrl->cmd->command, disk->amode == am_lba48 ?
1103 CMD_WRITE_SECTORS_EXT : CMD_WRITE_SECTORS);
1104
1105 rc = ata_pio_data_out(disk, buf, cnt * disk->block_size,
1106 disk->block_size, cnt);
1107
1108 fibril_mutex_unlock(&ctrl->lock);
1109 return rc;
1110}
1111
1112/** Flush cached data to nonvolatile storage.
1113 *
1114 * @param disk Disk
1115 *
1116 * @return EOK on success, EIO on error.
1117 */
1118static int ata_rcmd_flush_cache(disk_t *disk)
1119{
1120 ata_ctrl_t *ctrl = disk->ctrl;
1121 uint8_t drv_head;
1122 int rc;
1123
1124 /* New value for Drive/Head register */
1125 drv_head =
1126 (disk_dev_idx(disk) != 0) ? DHR_DRV : 0;
1127
1128 fibril_mutex_lock(&ctrl->lock);
1129
1130 /* Program a Flush Cache operation. */
1131
1132 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
1133 fibril_mutex_unlock(&ctrl->lock);
1134 return EIO;
1135 }
1136
1137 pio_write_8(&ctrl->cmd->drive_head, drv_head);
1138
1139 if (wait_status(ctrl, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
1140 fibril_mutex_unlock(&ctrl->lock);
1141 return EIO;
1142 }
1143
1144 pio_write_8(&ctrl->cmd->command, CMD_FLUSH_CACHE);
1145
1146 rc = ata_pio_nondata(disk);
1147
1148 fibril_mutex_unlock(&ctrl->lock);
1149 return rc;
1150}
1151
1152/** Calculate block coordinates.
1153 *
1154 * Calculates block coordinates in the best coordinate system supported
1155 * by the device. These can be later programmed into the device using
1156 * @c coord_sc_program().
1157 *
1158 * @return EOK on success or EINVAL if block index is past end of device.
1159 */
1160static int coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc)
1161{
1162 uint64_t c;
1163 uint64_t idx;
1164
1165 /* Check device bounds. */
1166 if (ba >= d->blocks)
1167 return EINVAL;
1168
1169 bc->amode = d->amode;
1170
1171 switch (d->amode) {
1172 case am_chs:
1173 /* Compute CHS coordinates. */
1174 c = ba / (d->geom.heads * d->geom.sectors);
1175 idx = ba % (d->geom.heads * d->geom.sectors);
1176
1177 bc->cyl_lo = c & 0xff;
1178 bc->cyl_hi = (c >> 8) & 0xff;
1179 bc->h = (idx / d->geom.sectors) & 0x0f;
1180 bc->sector = (1 + (idx % d->geom.sectors)) & 0xff;
1181 break;
1182
1183 case am_lba28:
1184 /* Compute LBA-28 coordinates. */
1185 bc->c0 = ba & 0xff; /* bits 0-7 */
1186 bc->c1 = (ba >> 8) & 0xff; /* bits 8-15 */
1187 bc->c2 = (ba >> 16) & 0xff; /* bits 16-23 */
1188 bc->h = (ba >> 24) & 0x0f; /* bits 24-27 */
1189 break;
1190
1191 case am_lba48:
1192 /* Compute LBA-48 coordinates. */
1193 bc->c0 = ba & 0xff; /* bits 0-7 */
1194 bc->c1 = (ba >> 8) & 0xff; /* bits 8-15 */
1195 bc->c2 = (ba >> 16) & 0xff; /* bits 16-23 */
1196 bc->c3 = (ba >> 24) & 0xff; /* bits 24-31 */
1197 bc->c4 = (ba >> 32) & 0xff; /* bits 32-39 */
1198 bc->c5 = (ba >> 40) & 0xff; /* bits 40-47 */
1199 bc->h = 0;
1200 break;
1201 }
1202
1203 return EOK;
1204}
1205
1206/** Program block coordinates and sector count into ATA registers.
1207 *
1208 * Note that bc->h must be programmed separately into the device/head register.
1209 *
1210 * @param ctrl Controller
1211 * @param bc Block coordinates
1212 * @param scnt Sector count
1213 */
1214static void coord_sc_program(ata_ctrl_t *ctrl, const block_coord_t *bc,
1215 uint16_t scnt)
1216{
1217 ata_cmd_t *cmd = ctrl->cmd;
1218
1219 if (bc->amode == am_lba48) {
1220 /* Write high-order bits. */
1221 pio_write_8(&cmd->sector_count, scnt >> 8);
1222 pio_write_8(&cmd->sector_number, bc->c3);
1223 pio_write_8(&cmd->cylinder_low, bc->c4);
1224 pio_write_8(&cmd->cylinder_high, bc->c5);
1225 }
1226
1227 /* Write low-order bits. */
1228 pio_write_8(&cmd->sector_count, scnt & 0x00ff);
1229 pio_write_8(&cmd->sector_number, bc->c0);
1230 pio_write_8(&cmd->cylinder_low, bc->c1);
1231 pio_write_8(&cmd->cylinder_high, bc->c2);
1232}
1233
1234/** Wait until some status bits are set and some are reset.
1235 *
1236 * Example: wait_status(ctrl, SR_DRDY, ~SR_BSY, ...) waits for SR_DRDY to become
1237 * set and SR_BSY to become reset.
1238 *
1239 * @param ctrl Controller
1240 * @param set Combination if bits which must be all set.
1241 * @param n_reset Negated combination of bits which must be all reset.
1242 * @param pstatus Pointer where to store last read status or NULL.
1243 * @param timeout Timeout in 10ms units.
1244 *
1245 * @return EOK on success, EIO on timeout.
1246 */
1247static int wait_status(ata_ctrl_t *ctrl, unsigned set, unsigned n_reset,
1248 uint8_t *pstatus, unsigned timeout)
1249{
1250 uint8_t status;
1251 int cnt;
1252
1253 status = pio_read_8(&ctrl->cmd->status);
1254
1255 /*
1256 * This is crude, yet simple. First try with 1us delays
1257 * (most likely the device will respond very fast). If not,
1258 * start trying every 10 ms.
1259 */
1260
1261 cnt = 100;
1262 while ((status & ~n_reset) != 0 || (status & set) != set) {
1263 --cnt;
1264 if (cnt <= 0) break;
1265
1266 status = pio_read_8(&ctrl->cmd->status);
1267 }
1268
1269 cnt = timeout;
1270 while ((status & ~n_reset) != 0 || (status & set) != set) {
1271 async_usleep(10000);
1272 --cnt;
1273 if (cnt <= 0) break;
1274
1275 status = pio_read_8(&ctrl->cmd->status);
1276 }
1277
1278 if (pstatus)
1279 *pstatus = status;
1280
1281 if (cnt == 0)
1282 return EIO;
1283
1284 return EOK;
1285}
1286
1287/**
1288 * @}
1289 */
Note: See TracBrowser for help on using the repository browser.