source: mainline/uspace/drv/block/ata_bd/ata_bd.c@ 95feb3e9

Last change on this file since 95feb3e9 was d7f7a4a, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Replace some license headers with SPDX identifier

Headers are replaced using tools/transorm-copyright.sh only
when it can be matched verbatim with the license header used
throughout most of the codebase.

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