source: mainline/uspace/drv/block/ata_bd/ata_bd.c@ 1433ecda

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1433ecda was 1433ecda, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

  • Property mode set to 100644
File size: 31.0 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 errno_t ata_bd_init_io(ata_ctrl_t *ctrl);
85static void ata_bd_fini_io(ata_ctrl_t *ctrl);
86
87static errno_t ata_bd_open(bd_srvs_t *, bd_srv_t *);
88static errno_t ata_bd_close(bd_srv_t *);
89static errno_t ata_bd_read_blocks(bd_srv_t *, uint64_t ba, size_t cnt, void *buf,
90 size_t);
91static errno_t ata_bd_read_toc(bd_srv_t *, uint8_t session, void *buf, size_t);
92static errno_t ata_bd_write_blocks(bd_srv_t *, uint64_t ba, size_t cnt,
93 const void *buf, size_t);
94static errno_t ata_bd_get_block_size(bd_srv_t *, size_t *);
95static errno_t ata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
96static errno_t ata_bd_sync_cache(bd_srv_t *, aoff64_t, size_t);
97
98static errno_t ata_rcmd_read(disk_t *disk, uint64_t ba, size_t cnt,
99 void *buf);
100static errno_t ata_rcmd_write(disk_t *disk, uint64_t ba, size_t cnt,
101 const void *buf);
102static errno_t ata_rcmd_flush_cache(disk_t *disk);
103static errno_t disk_init(ata_ctrl_t *ctrl, disk_t *d, int disk_id);
104static errno_t ata_identify_dev(disk_t *disk, void *buf);
105static errno_t ata_identify_pkt_dev(disk_t *disk, void *buf);
106static errno_t 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 errno_t ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size,
109 size_t *rcvd_size);
110static errno_t ata_pcmd_read_12(disk_t *disk, uint64_t ba, size_t cnt,
111 void *obuf, size_t obuf_size);
112static errno_t ata_pcmd_read_capacity(disk_t *disk, uint64_t *nblocks,
113 size_t *block_size);
114static errno_t 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 errno_t 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 errno_t 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. */
145errno_t ata_ctrl_init(ata_ctrl_t *ctrl, ata_base_t *res)
146{
147 int i;
148 errno_t 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. */
211errno_t ata_ctrl_remove(ata_ctrl_t *ctrl)
212{
213 int i;
214 errno_t 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. */
236errno_t ata_ctrl_gone(ata_ctrl_t *ctrl)
237{
238 int i;
239 errno_t 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 errno_t ata_bd_init_io(ata_ctrl_t *ctrl)
311{
312 errno_t 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 errno_t 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 errno_t 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)
464 c = '?';
465
466 chr_encode(c, d->model, &pos, 40);
467 }
468 d->model[pos] = '\0';
469
470 if (d->dev_type == ata_pkt_dev) {
471 /* Send inquiry. */
472 rc = ata_pcmd_inquiry(d, &inq_data, sizeof(inq_data), &isize);
473 if (rc != EOK || isize < sizeof(inq_data)) {
474 ddf_msg(LVL_ERROR, "Device inquiry failed.");
475 d->present = false;
476 return EIO;
477 }
478
479 /* Check device type. */
480 if (INQUIRY_PDEV_TYPE(inq_data.pqual_devtype) != SCSI_DEV_CD_DVD)
481 ddf_msg(LVL_WARN, "Peripheral device type is not CD-ROM.");
482
483 rc = ata_pcmd_read_capacity(d, &nblocks, &block_size);
484 if (rc != EOK) {
485 ddf_msg(LVL_ERROR, "Read capacity command failed.");
486 d->present = false;
487 return EIO;
488 }
489
490 d->blocks = nblocks;
491 d->block_size = block_size;
492 } else {
493 /* Assume register Read always uses 512-byte blocks. */
494 d->block_size = 512;
495 }
496
497 d->present = true;
498 return EOK;
499}
500
501static errno_t ata_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
502{
503 return EOK;
504}
505
506static errno_t ata_bd_close(bd_srv_t *bd)
507{
508 return EOK;
509}
510
511/** Read multiple blocks from the device. */
512static errno_t ata_bd_read_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
513 void *buf, size_t size)
514{
515 disk_t *disk = bd_srv_disk(bd);
516 errno_t rc;
517
518 if (size < cnt * disk->block_size)
519 return EINVAL;
520
521 while (cnt > 0) {
522 if (disk->dev_type == ata_reg_dev) {
523 rc = ata_rcmd_read(disk, ba, 1, buf);
524 } else {
525 rc = ata_pcmd_read_12(disk, ba, 1, buf,
526 disk->block_size);
527 }
528
529 if (rc != EOK)
530 return rc;
531
532 ++ba;
533 --cnt;
534 buf += disk->block_size;
535 }
536
537 return EOK;
538}
539
540/** Read TOC from device. */
541static errno_t ata_bd_read_toc(bd_srv_t *bd, uint8_t session, void *buf, size_t size)
542{
543 disk_t *disk = bd_srv_disk(bd);
544
545 return ata_pcmd_read_toc(disk, session, buf, size);
546}
547
548/** Write multiple blocks to the device. */
549static errno_t ata_bd_write_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
550 const void *buf, size_t size)
551{
552 disk_t *disk = bd_srv_disk(bd);
553 errno_t rc;
554
555 if (disk->dev_type != ata_reg_dev)
556 return ENOTSUP;
557
558 if (size < cnt * disk->block_size)
559 return EINVAL;
560
561 while (cnt > 0) {
562 rc = ata_rcmd_write(disk, ba, 1, buf);
563 if (rc != EOK)
564 return rc;
565
566 ++ba;
567 --cnt;
568 buf += disk->block_size;
569 }
570
571 return EOK;
572}
573
574/** Get device block size. */
575static errno_t ata_bd_get_block_size(bd_srv_t *bd, size_t *rbsize)
576{
577 disk_t *disk = bd_srv_disk(bd);
578
579 *rbsize = disk->block_size;
580 return EOK;
581}
582
583/** Get device number of blocks. */
584static errno_t ata_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
585{
586 disk_t *disk = bd_srv_disk(bd);
587
588 *rnb = disk->blocks;
589 return EOK;
590}
591
592/** Flush cache. */
593static errno_t ata_bd_sync_cache(bd_srv_t *bd, uint64_t ba, size_t cnt)
594{
595 disk_t *disk = bd_srv_disk(bd);
596
597 /* ATA cannot flush just some blocks, we just flush everything. */
598 (void)ba;
599 (void)cnt;
600
601 return ata_rcmd_flush_cache(disk);
602}
603
604/** PIO data-in command protocol. */
605static errno_t ata_pio_data_in(disk_t *disk, void *obuf, size_t obuf_size,
606 size_t blk_size, size_t nblocks)
607{
608 ata_ctrl_t *ctrl = disk->ctrl;
609 uint16_t data;
610 size_t i;
611 uint8_t status;
612
613 /* XXX Support multiple blocks */
614 assert(nblocks == 1);
615 assert(blk_size % 2 == 0);
616
617 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
618 return EIO;
619
620 if ((status & SR_DRQ) != 0) {
621 /* Read data from the device buffer. */
622
623 for (i = 0; i < blk_size / 2; i++) {
624 data = pio_read_16(&ctrl->cmd->data_port);
625 ((uint16_t *) obuf)[i] = data;
626 }
627 }
628
629 if ((status & SR_ERR) != 0)
630 return EIO;
631
632 return EOK;
633}
634
635/** PIO data-out command protocol. */
636static errno_t ata_pio_data_out(disk_t *disk, const void *buf, size_t buf_size,
637 size_t blk_size, size_t nblocks)
638{
639 ata_ctrl_t *ctrl = disk->ctrl;
640 size_t i;
641 uint8_t status;
642
643 /* XXX Support multiple blocks */
644 assert(nblocks == 1);
645 assert(blk_size % 2 == 0);
646
647 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
648 return EIO;
649
650 if ((status & SR_DRQ) != 0) {
651 /* Write data to the device buffer. */
652
653 for (i = 0; i < blk_size / 2; i++) {
654 pio_write_16(&ctrl->cmd->data_port, ((uint16_t *) buf)[i]);
655 }
656 }
657
658 if (status & SR_ERR)
659 return EIO;
660
661 return EOK;
662}
663
664/** PIO non-data command protocol. */
665static errno_t ata_pio_nondata(disk_t *disk)
666{
667 ata_ctrl_t *ctrl = disk->ctrl;
668 uint8_t status;
669
670 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
671 return EIO;
672
673 if (status & SR_ERR)
674 return EIO;
675
676 return EOK;
677}
678
679/** Issue IDENTIFY DEVICE command.
680 *
681 * Reads @c identify data into the provided buffer. This is used to detect
682 * whether an ATA device is present and if so, to determine its parameters.
683 *
684 * @param disk Disk
685 * @param buf Pointer to a 512-byte buffer.
686 *
687 * @return ETIMEOUT on timeout (this can mean the device is
688 * not present). EIO if device responds with error.
689 */
690static errno_t ata_identify_dev(disk_t *disk, void *buf)
691{
692 ata_ctrl_t *ctrl = disk->ctrl;
693 uint8_t status;
694 uint8_t drv_head;
695
696 drv_head = ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0);
697
698 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
699 return ETIMEOUT;
700
701 pio_write_8(&ctrl->cmd->drive_head, drv_head);
702
703 /*
704 * Do not wait for DRDY to be set in case this is a packet device.
705 * We determine whether the device is present by waiting for DRQ to be
706 * set after issuing the command.
707 */
708 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
709 return ETIMEOUT;
710
711 pio_write_8(&ctrl->cmd->command, CMD_IDENTIFY_DRIVE);
712
713 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
714 return ETIMEOUT;
715
716 /*
717 * If ERR is set, this may be a packet device, so return EIO to cause
718 * the caller to check for one.
719 */
720 if ((status & SR_ERR) != 0)
721 return EIO;
722
723 /*
724 * For probing purposes we need to wait for some status bit to become
725 * active - otherwise we could be fooled just by receiving all zeroes.
726 */
727 if (wait_status(ctrl, SR_DRQ, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
728 return ETIMEOUT;
729
730 return ata_pio_data_in(disk, buf, identify_data_size,
731 identify_data_size, 1);
732}
733
734/** Issue Identify Packet Device command.
735 *
736 * Reads @c identify data into the provided buffer. This is used to detect
737 * whether an ATAPI device is present and if so, to determine its parameters.
738 *
739 * @param disk Disk
740 * @param buf Pointer to a 512-byte buffer.
741 */
742static errno_t ata_identify_pkt_dev(disk_t *disk, void *buf)
743{
744 ata_ctrl_t *ctrl = disk->ctrl;
745 uint8_t drv_head;
746
747 drv_head = ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0);
748
749 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
750 return EIO;
751
752 pio_write_8(&ctrl->cmd->drive_head, drv_head);
753
754 /* For ATAPI commands we do not need to wait for DRDY. */
755 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
756 return EIO;
757
758 pio_write_8(&ctrl->cmd->command, CMD_IDENTIFY_PKT_DEV);
759
760 return ata_pio_data_in(disk, buf, identify_data_size,
761 identify_data_size, 1);
762}
763
764/** Issue packet command (i. e. write a command packet to the device).
765 *
766 * Only data-in commands are supported (e.g. inquiry, read).
767 *
768 * @param disk Disk
769 * @param obuf Buffer for storing data read from device
770 * @param obuf_size Size of obuf in bytes
771 * @param rcvd_size Place to store number of bytes read or @c NULL
772 *
773 * @return EOK on success, EIO on error.
774 */
775static errno_t ata_cmd_packet(disk_t *disk, const void *cpkt, size_t cpkt_size,
776 void *obuf, size_t obuf_size, size_t *rcvd_size)
777{
778 ata_ctrl_t *ctrl = disk->ctrl;
779 size_t i;
780 uint8_t status;
781 uint8_t drv_head;
782 size_t data_size;
783 uint16_t val;
784
785 fibril_mutex_lock(&ctrl->lock);
786
787 /* New value for Drive/Head register */
788 drv_head =
789 ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0);
790
791 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
792 fibril_mutex_unlock(&ctrl->lock);
793 return EIO;
794 }
795
796 pio_write_8(&ctrl->cmd->drive_head, drv_head);
797
798 if (wait_status(ctrl, 0, ~(SR_BSY | SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
799 fibril_mutex_unlock(&ctrl->lock);
800 return EIO;
801 }
802
803 /* Byte count <- max. number of bytes we can read in one transfer. */
804 pio_write_8(&ctrl->cmd->cylinder_low, 0xfe);
805 pio_write_8(&ctrl->cmd->cylinder_high, 0xff);
806
807 pio_write_8(&ctrl->cmd->command, CMD_PACKET);
808
809 if (wait_status(ctrl, SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
810 fibril_mutex_unlock(&ctrl->lock);
811 return EIO;
812 }
813
814 /* Write command packet. */
815 for (i = 0; i < (cpkt_size + 1) / 2; i++)
816 pio_write_16(&ctrl->cmd->data_port, ((uint16_t *) cpkt)[i]);
817
818 if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
819 fibril_mutex_unlock(&ctrl->lock);
820 return EIO;
821 }
822
823 if ((status & SR_DRQ) == 0) {
824 fibril_mutex_unlock(&ctrl->lock);
825 return EIO;
826 }
827
828 /* Read byte count. */
829 data_size = (uint16_t) pio_read_8(&ctrl->cmd->cylinder_low) +
830 ((uint16_t) pio_read_8(&ctrl->cmd->cylinder_high) << 8);
831
832 /* Check whether data fits into output buffer. */
833 if (data_size > obuf_size) {
834 /* Output buffer is too small to store data. */
835 fibril_mutex_unlock(&ctrl->lock);
836 return EIO;
837 }
838
839 /* Read data from the device buffer. */
840 for (i = 0; i < (data_size + 1) / 2; i++) {
841 val = pio_read_16(&ctrl->cmd->data_port);
842 ((uint16_t *) obuf)[i] = val;
843 }
844
845 fibril_mutex_unlock(&ctrl->lock);
846
847 if (status & SR_ERR)
848 return EIO;
849
850 if (rcvd_size != NULL)
851 *rcvd_size = data_size;
852 return EOK;
853}
854
855/** Issue ATAPI Inquiry.
856 *
857 * @param disk Disk
858 * @param obuf Buffer for storing inquiry data read from device
859 * @param obuf_size Size of obuf in bytes
860 *
861 * @return EOK on success, EIO on error.
862 */
863static errno_t ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size,
864 size_t *rcvd_size)
865{
866 uint8_t cpb[12];
867 scsi_cdb_inquiry_t *cp = (scsi_cdb_inquiry_t *)cpb;
868 errno_t rc;
869
870 memset(cpb, 0, sizeof(cpb));
871
872 /*
873 * For SFF 8020 compliance the inquiry must be padded to 12 bytes
874 * and allocation length must fit in one byte.
875 */
876 cp->op_code = SCSI_CMD_INQUIRY;
877
878 /* Allocation length */
879 cp->alloc_len = host2uint16_t_be(min(obuf_size, 0xff));
880
881 rc = ata_cmd_packet(disk, cpb, sizeof(cpb), obuf, obuf_size, rcvd_size);
882 if (rc != EOK)
883 return rc;
884
885 return EOK;
886}
887
888/** Issue ATAPI read capacity(10) command.
889 *
890 * @param disk Disk
891 * @param nblocks Place to store number of blocks
892 * @param block_size Place to store block size
893 *
894 * @return EOK on success, EIO on error.
895 */
896static errno_t ata_pcmd_read_capacity(disk_t *disk, uint64_t *nblocks,
897 size_t *block_size)
898{
899 scsi_cdb_read_capacity_10_t cdb;
900 scsi_read_capacity_10_data_t data;
901 size_t rsize;
902 errno_t rc;
903
904 memset(&cdb, 0, sizeof(cdb));
905 cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
906
907 rc = ata_cmd_packet(disk, &cdb, sizeof(cdb), &data, sizeof(data), &rsize);
908 if (rc != EOK)
909 return rc;
910
911 if (rsize != sizeof(data))
912 return EIO;
913
914 *nblocks = uint32_t_be2host(data.last_lba) + 1;
915 *block_size = uint32_t_be2host(data.block_size);
916
917 return EOK;
918}
919
920/** Issue ATAPI read(12) command.
921 *
922 * Output buffer must be large enough to hold the data, otherwise the
923 * function will fail.
924 *
925 * @param disk Disk
926 * @param ba Starting block address
927 * @param cnt Number of blocks to read
928 * @param obuf Buffer for storing inquiry data read from device
929 * @param obuf_size Size of obuf in bytes
930 *
931 * @return EOK on success, EIO on error.
932 */
933static errno_t ata_pcmd_read_12(disk_t *disk, uint64_t ba, size_t cnt,
934 void *obuf, size_t obuf_size)
935{
936 scsi_cdb_read_12_t cp;
937 errno_t rc;
938
939 if (ba > UINT32_MAX)
940 return EINVAL;
941
942 memset(&cp, 0, sizeof(cp));
943
944 cp.op_code = SCSI_CMD_READ_12;
945 cp.lba = host2uint32_t_be(ba);
946 cp.xfer_len = host2uint32_t_be(cnt);
947
948 rc = ata_cmd_packet(disk, &cp, sizeof(cp), obuf, obuf_size, NULL);
949 if (rc != EOK)
950 return rc;
951
952 return EOK;
953}
954
955/** Issue ATAPI read TOC command.
956 *
957 * Read TOC in 'multi-session' format (first and last session number
958 * with last session LBA).
959 *
960 * http://suif.stanford.edu/~csapuntz/specs/INF-8020.PDF page 171
961 *
962 * Output buffer must be large enough to hold the data, otherwise the
963 * function will fail.
964 *
965 * @param disk Disk
966 * @param session Starting session
967 * @param obuf Buffer for storing inquiry data read from device
968 * @param obuf_size Size of obuf in bytes
969 *
970 * @return EOK on success, EIO on error.
971 */
972static errno_t ata_pcmd_read_toc(disk_t *disk, uint8_t session, void *obuf,
973 size_t obuf_size)
974{
975 uint8_t cpb[12];
976 scsi_cdb_read_toc_t *cp = (scsi_cdb_read_toc_t *)cpb;
977 errno_t rc;
978
979 memset(cpb, 0, sizeof(cpb));
980
981 cp->op_code = SCSI_CMD_READ_TOC;
982 cp->msf = 0;
983 cp->format = 0x01; /* 0x01 = multi-session mode */
984 cp->track_sess_no = session;
985 cp->alloc_len = host2uint16_t_be(obuf_size);
986 cp->control = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */
987
988 rc = ata_cmd_packet(disk, cpb, sizeof(cpb), obuf, obuf_size, NULL);
989 if (rc != EOK)
990 return rc;
991
992 return EOK;
993}
994
995/** Read a physical block from the device.
996 *
997 * @param disk Disk
998 * @param ba Address the first block.
999 * @param cnt Number of blocks to transfer.
1000 * @param buf Buffer for holding the data.
1001 *
1002 * @return EOK on success, EIO on error.
1003 */
1004static errno_t ata_rcmd_read(disk_t *disk, uint64_t ba, size_t blk_cnt,
1005 void *buf)
1006{
1007 ata_ctrl_t *ctrl = disk->ctrl;
1008 uint8_t drv_head;
1009 block_coord_t bc;
1010 errno_t rc;
1011
1012 /* Silence warning. */
1013 memset(&bc, 0, sizeof(bc));
1014
1015 /* Compute block coordinates. */
1016 if (coord_calc(disk, ba, &bc) != EOK)
1017 return EINVAL;
1018
1019 /* New value for Drive/Head register */
1020 drv_head =
1021 ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0) |
1022 ((disk->amode != am_chs) ? DHR_LBA : 0) |
1023 (bc.h & 0x0f);
1024
1025 fibril_mutex_lock(&ctrl->lock);
1026
1027 /* Program a Read Sectors operation. */
1028
1029 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
1030 fibril_mutex_unlock(&ctrl->lock);
1031 return EIO;
1032 }
1033
1034 pio_write_8(&ctrl->cmd->drive_head, drv_head);
1035
1036 if (wait_status(ctrl, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
1037 fibril_mutex_unlock(&ctrl->lock);
1038 return EIO;
1039 }
1040
1041 /* Program block coordinates into the device. */
1042 coord_sc_program(ctrl, &bc, 1);
1043
1044 pio_write_8(&ctrl->cmd->command, disk->amode == am_lba48 ?
1045 CMD_READ_SECTORS_EXT : CMD_READ_SECTORS);
1046
1047 rc = ata_pio_data_in(disk, buf, blk_cnt * disk->block_size,
1048 disk->block_size, blk_cnt);
1049
1050 fibril_mutex_unlock(&ctrl->lock);
1051
1052 return rc;
1053}
1054
1055/** Write a physical block to the device.
1056 *
1057 * @param disk Disk
1058 * @param ba Address of the first block.
1059 * @param cnt Number of blocks to transfer.
1060 * @param buf Buffer holding the data to write.
1061 *
1062 * @return EOK on success, EIO on error.
1063 */
1064static errno_t ata_rcmd_write(disk_t *disk, uint64_t ba, size_t cnt,
1065 const void *buf)
1066{
1067 ata_ctrl_t *ctrl = disk->ctrl;
1068 uint8_t drv_head;
1069 block_coord_t bc;
1070 errno_t rc;
1071
1072 /* Silence warning. */
1073 memset(&bc, 0, sizeof(bc));
1074
1075 /* Compute block coordinates. */
1076 if (coord_calc(disk, ba, &bc) != EOK)
1077 return EINVAL;
1078
1079 /* New value for Drive/Head register */
1080 drv_head =
1081 ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0) |
1082 ((disk->amode != am_chs) ? DHR_LBA : 0) |
1083 (bc.h & 0x0f);
1084
1085 fibril_mutex_lock(&ctrl->lock);
1086
1087 /* Program a Write Sectors operation. */
1088
1089 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
1090 fibril_mutex_unlock(&ctrl->lock);
1091 return EIO;
1092 }
1093
1094 pio_write_8(&ctrl->cmd->drive_head, drv_head);
1095
1096 if (wait_status(ctrl, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
1097 fibril_mutex_unlock(&ctrl->lock);
1098 return EIO;
1099 }
1100
1101 /* Program block coordinates into the device. */
1102 coord_sc_program(ctrl, &bc, 1);
1103
1104 pio_write_8(&ctrl->cmd->command, disk->amode == am_lba48 ?
1105 CMD_WRITE_SECTORS_EXT : CMD_WRITE_SECTORS);
1106
1107 rc = ata_pio_data_out(disk, buf, cnt * disk->block_size,
1108 disk->block_size, cnt);
1109
1110 fibril_mutex_unlock(&ctrl->lock);
1111 return rc;
1112}
1113
1114/** Flush cached data to nonvolatile storage.
1115 *
1116 * @param disk Disk
1117 *
1118 * @return EOK on success, EIO on error.
1119 */
1120static errno_t ata_rcmd_flush_cache(disk_t *disk)
1121{
1122 ata_ctrl_t *ctrl = disk->ctrl;
1123 uint8_t drv_head;
1124 errno_t rc;
1125
1126 /* New value for Drive/Head register */
1127 drv_head =
1128 (disk_dev_idx(disk) != 0) ? DHR_DRV : 0;
1129
1130 fibril_mutex_lock(&ctrl->lock);
1131
1132 /* Program a Flush Cache operation. */
1133
1134 if (wait_status(ctrl, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
1135 fibril_mutex_unlock(&ctrl->lock);
1136 return EIO;
1137 }
1138
1139 pio_write_8(&ctrl->cmd->drive_head, drv_head);
1140
1141 if (wait_status(ctrl, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
1142 fibril_mutex_unlock(&ctrl->lock);
1143 return EIO;
1144 }
1145
1146 pio_write_8(&ctrl->cmd->command, CMD_FLUSH_CACHE);
1147
1148 rc = ata_pio_nondata(disk);
1149
1150 fibril_mutex_unlock(&ctrl->lock);
1151 return rc;
1152}
1153
1154/** Calculate block coordinates.
1155 *
1156 * Calculates block coordinates in the best coordinate system supported
1157 * by the device. These can be later programmed into the device using
1158 * @c coord_sc_program().
1159 *
1160 * @return EOK on success or EINVAL if block index is past end of device.
1161 */
1162static errno_t coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc)
1163{
1164 uint64_t c;
1165 uint64_t idx;
1166
1167 /* Check device bounds. */
1168 if (ba >= d->blocks)
1169 return EINVAL;
1170
1171 bc->amode = d->amode;
1172
1173 switch (d->amode) {
1174 case am_chs:
1175 /* Compute CHS coordinates. */
1176 c = ba / (d->geom.heads * d->geom.sectors);
1177 idx = ba % (d->geom.heads * d->geom.sectors);
1178
1179 bc->cyl_lo = c & 0xff;
1180 bc->cyl_hi = (c >> 8) & 0xff;
1181 bc->h = (idx / d->geom.sectors) & 0x0f;
1182 bc->sector = (1 + (idx % d->geom.sectors)) & 0xff;
1183 break;
1184
1185 case am_lba28:
1186 /* Compute LBA-28 coordinates. */
1187 bc->c0 = ba & 0xff; /* bits 0-7 */
1188 bc->c1 = (ba >> 8) & 0xff; /* bits 8-15 */
1189 bc->c2 = (ba >> 16) & 0xff; /* bits 16-23 */
1190 bc->h = (ba >> 24) & 0x0f; /* bits 24-27 */
1191 break;
1192
1193 case am_lba48:
1194 /* Compute LBA-48 coordinates. */
1195 bc->c0 = ba & 0xff; /* bits 0-7 */
1196 bc->c1 = (ba >> 8) & 0xff; /* bits 8-15 */
1197 bc->c2 = (ba >> 16) & 0xff; /* bits 16-23 */
1198 bc->c3 = (ba >> 24) & 0xff; /* bits 24-31 */
1199 bc->c4 = (ba >> 32) & 0xff; /* bits 32-39 */
1200 bc->c5 = (ba >> 40) & 0xff; /* bits 40-47 */
1201 bc->h = 0;
1202 break;
1203 }
1204
1205 return EOK;
1206}
1207
1208/** Program block coordinates and sector count into ATA registers.
1209 *
1210 * Note that bc->h must be programmed separately into the device/head register.
1211 *
1212 * @param ctrl Controller
1213 * @param bc Block coordinates
1214 * @param scnt Sector count
1215 */
1216static void coord_sc_program(ata_ctrl_t *ctrl, const block_coord_t *bc,
1217 uint16_t scnt)
1218{
1219 ata_cmd_t *cmd = ctrl->cmd;
1220
1221 if (bc->amode == am_lba48) {
1222 /* Write high-order bits. */
1223 pio_write_8(&cmd->sector_count, scnt >> 8);
1224 pio_write_8(&cmd->sector_number, bc->c3);
1225 pio_write_8(&cmd->cylinder_low, bc->c4);
1226 pio_write_8(&cmd->cylinder_high, bc->c5);
1227 }
1228
1229 /* Write low-order bits. */
1230 pio_write_8(&cmd->sector_count, scnt & 0x00ff);
1231 pio_write_8(&cmd->sector_number, bc->c0);
1232 pio_write_8(&cmd->cylinder_low, bc->c1);
1233 pio_write_8(&cmd->cylinder_high, bc->c2);
1234}
1235
1236/** Wait until some status bits are set and some are reset.
1237 *
1238 * Example: wait_status(ctrl, SR_DRDY, ~SR_BSY, ...) waits for SR_DRDY to become
1239 * set and SR_BSY to become reset.
1240 *
1241 * @param ctrl Controller
1242 * @param set Combination if bits which must be all set.
1243 * @param n_reset Negated combination of bits which must be all reset.
1244 * @param pstatus Pointer where to store last read status or NULL.
1245 * @param timeout Timeout in 10ms units.
1246 *
1247 * @return EOK on success, EIO on timeout.
1248 */
1249static errno_t wait_status(ata_ctrl_t *ctrl, unsigned set, unsigned n_reset,
1250 uint8_t *pstatus, unsigned timeout)
1251{
1252 uint8_t status;
1253 int cnt;
1254
1255 status = pio_read_8(&ctrl->cmd->status);
1256
1257 /*
1258 * This is crude, yet simple. First try with 1us delays
1259 * (most likely the device will respond very fast). If not,
1260 * start trying every 10 ms.
1261 */
1262
1263 cnt = 100;
1264 while ((status & ~n_reset) != 0 || (status & set) != set) {
1265 --cnt;
1266 if (cnt <= 0)
1267 break;
1268
1269 status = pio_read_8(&ctrl->cmd->status);
1270 }
1271
1272 cnt = timeout;
1273 while ((status & ~n_reset) != 0 || (status & set) != set) {
1274 async_usleep(10000);
1275 --cnt;
1276 if (cnt <= 0)
1277 break;
1278
1279 status = pio_read_8(&ctrl->cmd->status);
1280 }
1281
1282 if (pstatus)
1283 *pstatus = status;
1284
1285 if (cnt == 0)
1286 return EIO;
1287
1288 return EOK;
1289}
1290
1291/**
1292 * @}
1293 */
Note: See TracBrowser for help on using the repository browser.