source: mainline/uspace/drv/block/ata_bd/ata_bd.c@ 132ab5d1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 132ab5d1 was d5c1051, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

"Obviously harmless" error handling tweaks.

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