source: mainline/uspace/lib/ata/src/ata.c@ 4285f384

Last change on this file since 4285f384 was 4285f384, checked in by Jiri Svoboda <jiri@…>, 4 months ago

Allow physically ejecting CD-ROM using vol eject -s

  • Property mode set to 100644
File size: 44.6 KB
Line 
1/*
2 * Copyright (c) 2025 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 libata
30 * @{
31 */
32
33/**
34 * @file
35 * @brief ATA disk driver library
36 *
37 * This driver library implements the generic part of ATA/ATAPI. It is
38 * meant to be used by a driver which implements the actual transport
39 * (such as ISA, PCI).
40 *
41 * This driver libary supports CHS, 28-bit and 48-bit LBA addressing,
42 * as well as PACKET devices. It supports PIO transfers and IRQ.
43 *
44 * There is no support DMA, S.M.A.R.T or removable devices.
45 *
46 * This driver is based on the ATA-1, ATA-2, ATA-3 and ATA/ATAPI-4 through 7
47 * standards, as published by the ANSI, NCITS and INCITS standards bodies,
48 * which are freely available. This driver contains no vendor-specific
49 * code at this moment.
50 */
51
52#include <bd_srv.h>
53#include <byteorder.h>
54#include <errno.h>
55#include <macros.h>
56#include <scsi/mmc.h>
57#include <scsi/sbc.h>
58#include <scsi/spc.h>
59#include <stdarg.h>
60#include <stdbool.h>
61#include <stddef.h>
62#include <stdint.h>
63#include <stdio.h>
64#include <stdlib.h>
65
66#include "ata/ata.h"
67#include "ata/ata_hw.h"
68
69#define MSG_BUF_SIZE 256
70
71/**
72 * Size of data returned from Identify Device or Identify Packet Device
73 * command.
74 */
75static const size_t identify_data_size = 512;
76static void ata_msg_note(ata_channel_t *, const char *, ...);
77static void ata_msg_debug(ata_channel_t *, const char *, ...);
78static void ata_msg_warn(ata_channel_t *, const char *, ...);
79static void ata_msg_error(ata_channel_t *, const char *, ...);
80static errno_t ata_device_add(ata_device_t *);
81static errno_t ata_device_remove(ata_device_t *);
82static void ata_read_data_16(ata_channel_t *, uint16_t *, size_t);
83static void ata_write_data_16(ata_channel_t *, uint16_t *, size_t);
84static uint8_t ata_read_cmd_8(ata_channel_t *, uint16_t);
85static void ata_write_cmd_8(ata_channel_t *, uint16_t, uint8_t);
86
87static errno_t ata_bd_init_irq(ata_channel_t *);
88static void ata_bd_fini_irq(ata_channel_t *);
89
90static errno_t ata_bd_open(bd_srvs_t *, bd_srv_t *);
91static errno_t ata_bd_close(bd_srv_t *);
92static errno_t ata_bd_read_blocks(bd_srv_t *, uint64_t, size_t, void *, size_t);
93static errno_t ata_bd_read_toc(bd_srv_t *, uint8_t, void *, size_t);
94static errno_t ata_bd_write_blocks(bd_srv_t *, uint64_t, size_t, const void *,
95 size_t);
96static errno_t ata_bd_get_block_size(bd_srv_t *, size_t *);
97static errno_t ata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
98static errno_t ata_bd_eject(bd_srv_t *);
99static errno_t ata_bd_sync_cache(bd_srv_t *, aoff64_t, size_t);
100
101static errno_t ata_rcmd_read(ata_device_t *, uint64_t, size_t, void *);
102static errno_t ata_rcmd_write(ata_device_t *, uint64_t, size_t,
103 const void *);
104static errno_t ata_rcmd_flush_cache(ata_device_t *);
105static errno_t ata_device_init(ata_channel_t *, ata_device_t *, int);
106static errno_t ata_identify_dev(ata_device_t *, void *);
107static errno_t ata_identify_pkt_dev(ata_device_t *, void *);
108static errno_t ata_cmd_packet_nondata(ata_device_t *, const void *, size_t);
109static errno_t ata_cmd_packet_din(ata_device_t *, const void *, size_t, void *,
110 size_t, size_t *);
111static errno_t ata_pcmd_inquiry(ata_device_t *, void *, size_t, size_t *);
112static errno_t ata_pcmd_read_12(ata_device_t *, uint64_t, size_t, void *, size_t);
113static errno_t ata_pcmd_read_capacity(ata_device_t *, uint64_t *, size_t *);
114static errno_t ata_pcmd_read_toc(ata_device_t *, uint8_t, void *, size_t);
115static errno_t ata_pcmd_start_stop_unit(ata_device_t *, uint8_t);
116static void disk_print_summary(ata_device_t *);
117static size_t ata_disk_maxnb(ata_device_t *);
118static errno_t coord_calc(ata_device_t *, uint64_t, block_coord_t *);
119static void coord_sc_program(ata_channel_t *, const block_coord_t *, uint16_t);
120static errno_t wait_status(ata_channel_t *, unsigned, unsigned, uint8_t *,
121 unsigned);
122static errno_t wait_irq(ata_channel_t *, uint8_t *, unsigned);
123static void ata_dma_chan_setup(ata_device_t *, void *, size_t, ata_dma_dir_t);
124static void ata_dma_chan_teardown(ata_device_t *);
125
126static bd_ops_t ata_bd_ops = {
127 .open = ata_bd_open,
128 .close = ata_bd_close,
129 .read_blocks = ata_bd_read_blocks,
130 .read_toc = ata_bd_read_toc,
131 .write_blocks = ata_bd_write_blocks,
132 .get_block_size = ata_bd_get_block_size,
133 .get_num_blocks = ata_bd_get_num_blocks,
134 .sync_cache = ata_bd_sync_cache,
135 .eject = ata_bd_eject
136};
137
138static ata_device_t *bd_srv_device(bd_srv_t *bd)
139{
140 return (ata_device_t *)bd->srvs->sarg;
141}
142
143static int disk_dev_idx(ata_device_t *device)
144{
145 return (device->device_id & 1);
146}
147
148/** Create ATA channel.
149 *
150 * @param params Channel creation parameters
151 * @param rchan Place to store pointer to new channel
152 * @return EOK on success or an error code
153 */
154errno_t ata_channel_create(ata_params_t *params, ata_channel_t **rchan)
155{
156 ata_channel_t *chan;
157 int i;
158
159 chan = calloc(1, sizeof(ata_channel_t));
160 if (chan == NULL)
161 return ENOMEM;
162
163 chan->params = *params;
164 ata_msg_debug(chan, "ata_channel_create()");
165
166 fibril_mutex_initialize(&chan->lock);
167 fibril_mutex_initialize(&chan->irq_lock);
168 fibril_condvar_initialize(&chan->irq_cv);
169
170 for (i = 0; i < MAX_DEVICES; i++)
171 chan->device[i].chan = chan;
172
173 *rchan = chan;
174 return EOK;
175}
176
177/** Initialize ATA channel.
178 *
179 * @param params Channel creation parameters
180 * @param rchan Place to store pointer to new channel
181 * @return EOK on success or an error code
182 */
183errno_t ata_channel_initialize(ata_channel_t *chan)
184{
185 int i;
186 errno_t rc;
187 int n_disks;
188 bool irq_inited = false;
189 bool dev_added[MAX_DEVICES];
190
191 for (i = 0; i < MAX_DEVICES; i++)
192 dev_added[i] = false;
193
194 ata_msg_debug(chan, "ata_channel_initialize()");
195
196 rc = ata_bd_init_irq(chan);
197 if (rc != EOK)
198 return rc;
199
200 irq_inited = true;
201
202 for (i = 0; i < MAX_DEVICES; i++) {
203 ata_msg_debug(chan, "Identify drive %d...", i);
204
205 rc = ata_device_init(chan, &chan->device[i], i);
206
207 if (rc == EOK) {
208 disk_print_summary(&chan->device[i]);
209 } else {
210 ata_msg_debug(chan, "Not found.");
211 }
212 }
213
214 n_disks = 0;
215
216 for (i = 0; i < MAX_DEVICES; i++) {
217 /* Skip unattached devices. */
218 if (chan->device[i].present == false)
219 continue;
220
221 rc = ata_device_add(&chan->device[i]);
222 if (rc != EOK) {
223 ata_msg_error(chan, "Unable to add device %d.", i);
224 goto error;
225 }
226 dev_added[i] = true;
227 ++n_disks;
228 }
229
230 if (n_disks == 0) {
231 ata_msg_warn(chan, "No devices detected.");
232 rc = ENOENT;
233 goto error;
234 }
235
236 return EOK;
237error:
238 for (i = 0; i < MAX_DEVICES; i++) {
239 if (dev_added[i]) {
240 rc = ata_device_remove(&chan->device[i]);
241 if (rc != EOK) {
242 ata_msg_error(chan,
243 "Unable to remove device %d.", i);
244 }
245 }
246 }
247 if (irq_inited)
248 ata_bd_fini_irq(chan);
249 return rc;
250}
251
252/** Destroy ATA channel. */
253errno_t ata_channel_destroy(ata_channel_t *chan)
254{
255 int i;
256 errno_t rc;
257
258 ata_msg_debug(chan, ": ata_channel_destroy()");
259
260 fibril_mutex_lock(&chan->lock);
261
262 for (i = 0; i < MAX_DEVICES; i++) {
263 if (chan->device[i].present == false)
264 continue;
265
266 rc = ata_device_remove(&chan->device[i]);
267 if (rc != EOK) {
268 ata_msg_error(chan, "Unable to remove device %d.", i);
269 fibril_mutex_unlock(&chan->lock);
270 return rc;
271 }
272 }
273
274 ata_bd_fini_irq(chan);
275 fibril_mutex_unlock(&chan->lock);
276 free(chan);
277
278 return rc;
279}
280
281/** Add ATA device.
282 *
283 * @param d Device
284 * @return EOK on success or an error code
285 */
286static errno_t ata_device_add(ata_device_t *d)
287{
288 bd_srvs_init(&d->bds);
289 d->bds.ops = &ata_bd_ops;
290 d->bds.sarg = (void *)d;
291
292 return d->chan->params.add_device(d->chan->params.arg, d->device_id,
293 (void *)d);
294}
295
296/** Remove ATA device.
297 *
298 * @param d Device
299 * @return EOK on success or an error code
300 */
301static errno_t ata_device_remove(ata_device_t *d)
302{
303 return d->chan->params.remove_device(d->chan->params.arg, d->device_id);
304}
305
306/** Read 16 bits from data port.
307 *
308 * @param chan ATA channel
309 * @param buf Buffer to hold data
310 * @param nwords Number of words to read
311 */
312static void ata_read_data_16(ata_channel_t *chan, uint16_t *buf,
313 size_t nwords)
314{
315 chan->params.read_data_16(chan->params.arg, buf, nwords);
316}
317
318/** Write 16 bits to data port.
319 *
320 * @param chan ATA channel
321 * @param data Data
322 * @param nwords Number of words to write
323 */
324static void ata_write_data_16(ata_channel_t *chan, uint16_t *data,
325 size_t nwords)
326{
327 chan->params.write_data_16(chan->params.arg, data, nwords);
328}
329
330/** Read 8 bits from 8-bit command port.
331 *
332 * @param chan ATA channel
333 * @param port Port number
334 * @return 8-bit register value
335 */
336static uint8_t ata_read_cmd_8(ata_channel_t *chan, uint16_t port)
337{
338 return chan->params.read_cmd_8(chan->params.arg, port);
339}
340
341/** Write 8 bits to 8-bit command port.
342 *
343 * @param chan ATA channel
344 * @param port Port number
345 * @param value Register value
346 */
347static void ata_write_cmd_8(ata_channel_t *chan, uint16_t port, uint8_t value)
348{
349 return chan->params.write_cmd_8(chan->params.arg, port, value);
350}
351
352/** Log a notice message.
353 *
354 * @param chan Channel
355 * @param fmt Format
356 */
357static void ata_msg_note(ata_channel_t *chan, const char *fmt, ...)
358{
359 va_list ap;
360 char buf[MSG_BUF_SIZE];
361
362 va_start(ap, fmt);
363 vsnprintf(buf, sizeof(buf), fmt, ap);
364 va_end(ap);
365
366 chan->params.msg_note(chan->params.arg, buf);
367}
368
369/** Log a debug message.
370 *
371 * @param chan Channel
372 * @param fmt Format
373 */
374static void ata_msg_debug(ata_channel_t *chan, const char *fmt, ...)
375{
376 va_list ap;
377 char buf[MSG_BUF_SIZE];
378
379 va_start(ap, fmt);
380 vsnprintf(buf, sizeof(buf), fmt, ap);
381 va_end(ap);
382
383 chan->params.msg_debug(chan->params.arg, buf);
384}
385
386/** Log a warning message.
387 *
388 * @param chan Channel
389 * @param fmt Format
390 */
391static void ata_msg_warn(ata_channel_t *chan, const char *fmt, ...)
392{
393 va_list ap;
394 char buf[MSG_BUF_SIZE];
395
396 va_start(ap, fmt);
397 vsnprintf(buf, sizeof(buf), fmt, ap);
398 va_end(ap);
399
400 chan->params.msg_warn(chan->params.arg, buf);
401}
402
403/** Log an error message.
404 *
405 * @param chan Channel
406 * @param fmt Format
407 */
408static void ata_msg_error(ata_channel_t *chan, const char *fmt, ...)
409{
410 va_list ap;
411 char buf[MSG_BUF_SIZE];
412
413 va_start(ap, fmt);
414 vsnprintf(buf, sizeof(buf), fmt, ap);
415 va_end(ap);
416
417 chan->params.msg_error(chan->params.arg, buf);
418}
419
420/** Print one-line device summary. */
421static void disk_print_summary(ata_device_t *d)
422{
423 uint64_t mbytes;
424 char *atype = NULL;
425 char *cap = NULL;
426 int rc;
427
428 if (d->dev_type == ata_reg_dev) {
429 switch (d->amode) {
430 case am_chs:
431 rc = asprintf(&atype, "CHS %u cylinders, %u heads, "
432 "%u sectors", d->geom.cylinders, d->geom.heads,
433 d->geom.sectors);
434 if (rc < 0) {
435 /* Out of memory */
436 atype = NULL;
437 }
438 break;
439 case am_lba28:
440 atype = str_dup("LBA-28");
441 break;
442 case am_lba48:
443 atype = str_dup("LBA-48");
444 break;
445 }
446 } else {
447 atype = str_dup("PACKET");
448 }
449
450 if (atype == NULL)
451 return;
452
453 mbytes = d->blocks / (2 * 1024);
454 if (mbytes > 0) {
455 rc = asprintf(&cap, " %" PRIu64 " MB.", mbytes);
456 if (rc < 0) {
457 cap = NULL;
458 goto cleanup;
459 }
460 }
461
462 ata_msg_note(d->chan, "%s: %s %" PRIu64 " blocks%s", d->model, atype,
463 d->blocks, cap);
464cleanup:
465 free(atype);
466 free(cap);
467}
468
469/** Initialize IRQ. */
470static errno_t ata_bd_init_irq(ata_channel_t *chan)
471{
472 if (!chan->params.have_irq)
473 return EOK;
474
475 return chan->params.irq_enable(chan->params.arg);
476}
477
478/** Clean up IRQ. */
479static void ata_bd_fini_irq(ata_channel_t *chan)
480{
481 if (!chan->params.have_irq)
482 return;
483
484 (void)chan->params.irq_disable(chan->params.arg);
485}
486
487/** Initialize a device.
488 *
489 * Probes for a device, determines its parameters and initializes
490 * the device structure.
491 */
492static errno_t ata_device_init(ata_channel_t *chan, ata_device_t *d,
493 int device_id)
494{
495 identify_data_t idata;
496 uint8_t model[40];
497 scsi_std_inquiry_data_t inq_data;
498 size_t isize;
499 uint16_t w;
500 uint8_t c;
501 uint16_t bc;
502 uint64_t nblocks;
503 size_t block_size;
504 size_t pos, len;
505 errno_t rc;
506 unsigned i;
507
508 d->device_id = device_id;
509 d->present = false;
510
511 /* Try identify command. */
512 rc = ata_identify_dev(d, &idata);
513 if (rc == EOK) {
514 /* Success. It's a register (non-packet) device. */
515 ata_msg_debug(chan, "ATA register-only device found.");
516 d->dev_type = ata_reg_dev;
517 } else if (rc == EIO) {
518 /*
519 * There is something, but not a register device. Check to see
520 * whether the IDENTIFY command left the packet signature in
521 * the registers in case this is a packet device.
522 *
523 * According to the ATA specification, the LBA low and
524 * interrupt reason registers should be set to 0x01. However,
525 * there are many devices that do not follow this and only set
526 * the byte count registers. So, only check these.
527 */
528 bc = ((uint16_t)ata_read_cmd_8(chan, REG_CYLINDER_HIGH) << 8) |
529 ata_read_cmd_8(chan, REG_CYLINDER_LOW);
530
531 if (bc == PDEV_SIGNATURE_BC) {
532 rc = ata_identify_pkt_dev(d, &idata);
533 if (rc == EOK) {
534 /* We have a packet device. */
535 d->dev_type = ata_pkt_dev;
536 } else {
537 return EIO;
538 }
539 } else {
540 /* Nope. Something's there, but not recognized. */
541 return EIO;
542 }
543 } else {
544 /* Operation timed out. That means there is no device there. */
545 return EIO;
546 }
547
548 if (d->dev_type == ata_pkt_dev) {
549 /* Packet device */
550 d->amode = 0;
551
552 d->geom.cylinders = 0;
553 d->geom.heads = 0;
554 d->geom.sectors = 0;
555
556 d->blocks = 0;
557 } else if ((idata.caps & rd_cap_lba) == 0) {
558 /* Device only supports CHS addressing. */
559 d->amode = am_chs;
560
561 d->geom.cylinders = idata.cylinders;
562 d->geom.heads = idata.heads;
563 d->geom.sectors = idata.sectors;
564
565 d->blocks = d->geom.cylinders * d->geom.heads * d->geom.sectors;
566 } else if ((idata.cmd_set1 & cs1_addr48) == 0) {
567 /* Device only supports LBA-28 addressing. */
568 d->amode = am_lba28;
569
570 d->geom.cylinders = 0;
571 d->geom.heads = 0;
572 d->geom.sectors = 0;
573
574 d->blocks =
575 (uint32_t) idata.total_lba28_0 |
576 ((uint32_t) idata.total_lba28_1 << 16);
577 } else {
578 /* Device supports LBA-48 addressing. */
579 d->amode = am_lba48;
580
581 d->geom.cylinders = 0;
582 d->geom.heads = 0;
583 d->geom.sectors = 0;
584
585 d->blocks =
586 (uint64_t) idata.total_lba48_0 |
587 ((uint64_t) idata.total_lba48_1 << 16) |
588 ((uint64_t) idata.total_lba48_2 << 32) |
589 ((uint64_t) idata.total_lba48_3 << 48);
590 }
591
592 /*
593 * Convert model name to string representation.
594 */
595 for (i = 0; i < 20; i++) {
596 w = idata.model_name[i];
597 model[2 * i] = w >> 8;
598 model[2 * i + 1] = w & 0x00ff;
599 }
600
601 len = 40;
602 while (len > 0 && model[len - 1] == 0x20)
603 --len;
604
605 pos = 0;
606 for (i = 0; i < len; ++i) {
607 c = model[i];
608 if (c >= 0x80)
609 c = '?';
610
611 chr_encode(c, d->model, &pos, 40);
612 }
613 d->model[pos] = '\0';
614
615 if (d->dev_type == ata_pkt_dev) {
616 /* Send inquiry. */
617 rc = ata_pcmd_inquiry(d, &inq_data, sizeof(inq_data), &isize);
618 if (rc != EOK || isize < sizeof(inq_data)) {
619 ata_msg_error(chan, "Device inquiry failed.");
620 d->present = false;
621 return EIO;
622 }
623
624 /* Check device type. */
625 if (INQUIRY_PDEV_TYPE(inq_data.pqual_devtype) != SCSI_DEV_CD_DVD)
626 ata_msg_warn(chan, "Peripheral device type is not CD-ROM.");
627
628 rc = ata_pcmd_read_capacity(d, &nblocks, &block_size);
629 if (rc != EOK) {
630 ata_msg_error(chan, "Read capacity command failed.");
631 d->present = false;
632 return EIO;
633 }
634
635 d->blocks = nblocks;
636 d->block_size = block_size;
637 } else {
638 /* Assume register Read always uses 512-byte blocks. */
639 d->block_size = 512;
640 }
641
642 d->present = true;
643 return EOK;
644}
645
646static errno_t ata_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
647{
648 return EOK;
649}
650
651static errno_t ata_bd_close(bd_srv_t *bd)
652{
653 return EOK;
654}
655
656/** Read multiple blocks from the device. */
657static errno_t ata_bd_read_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
658 void *buf, size_t size)
659{
660 ata_device_t *device = bd_srv_device(bd);
661 size_t maxnb;
662 size_t nb;
663 errno_t rc;
664
665 if (size < cnt * device->block_size) {
666 rc = EINVAL;
667 goto error;
668 }
669
670 /* Maximum number of blocks to transfer at the same time */
671 maxnb = ata_disk_maxnb(device);
672 while (cnt > 0) {
673 nb = min(maxnb, cnt);
674 if (device->dev_type == ata_reg_dev) {
675 rc = ata_rcmd_read(device, ba, nb, buf);
676 } else {
677 rc = ata_pcmd_read_12(device, ba, nb, buf,
678 device->block_size);
679 }
680
681 if (rc != EOK)
682 goto error;
683
684 ba += nb;
685 cnt -= nb;
686 buf += device->block_size * nb;
687 }
688
689 return EOK;
690error:
691 ata_msg_debug(device->chan, "ata_bd_read_blocks: rc=%d", rc);
692 return rc;
693}
694
695/** Read TOC from device. */
696static errno_t ata_bd_read_toc(bd_srv_t *bd, uint8_t session, void *buf, size_t size)
697{
698 ata_device_t *device = bd_srv_device(bd);
699
700 return ata_pcmd_read_toc(device, session, buf, size);
701}
702
703/** Write multiple blocks to the device. */
704static errno_t ata_bd_write_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
705 const void *buf, size_t size)
706{
707 ata_device_t *device = bd_srv_device(bd);
708 size_t maxnb;
709 size_t nb;
710 errno_t rc;
711
712 if (device->dev_type != ata_reg_dev)
713 return ENOTSUP;
714
715 if (size < cnt * device->block_size)
716 return EINVAL;
717
718 /* Maximum number of blocks to transfer at the same time */
719 maxnb = ata_disk_maxnb(device);
720 while (cnt > 0) {
721 nb = min(maxnb, cnt);
722 rc = ata_rcmd_write(device, ba, nb, buf);
723 if (rc != EOK)
724 return rc;
725
726 ba += nb;
727 cnt -= nb;
728 buf += device->block_size * nb;
729 }
730
731 return EOK;
732}
733
734/** Get device block size. */
735static errno_t ata_bd_get_block_size(bd_srv_t *bd, size_t *rbsize)
736{
737 ata_device_t *device = bd_srv_device(bd);
738
739 *rbsize = device->block_size;
740 return EOK;
741}
742
743/** Get device number of blocks. */
744static errno_t ata_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
745{
746 ata_device_t *device = bd_srv_device(bd);
747
748 *rnb = device->blocks;
749 return EOK;
750}
751
752/** Flush cache. */
753static errno_t ata_bd_sync_cache(bd_srv_t *bd, uint64_t ba, size_t cnt)
754{
755 ata_device_t *device = bd_srv_device(bd);
756
757 /* ATA cannot flush just some blocks, we just flush everything. */
758 (void)ba;
759 (void)cnt;
760
761 return ata_rcmd_flush_cache(device);
762}
763
764/** Eject medium. */
765static errno_t ata_bd_eject(bd_srv_t *bd)
766{
767 ata_device_t *device = bd_srv_device(bd);
768
769 ata_msg_debug(device->chan, "ata_bd_eject()");
770 return ata_pcmd_start_stop_unit(device, ssf_pc_no_change |
771 ssf_loej);
772}
773
774/** PIO data-in command protocol. */
775static errno_t ata_pio_data_in(ata_device_t *device, void *obuf, size_t obuf_size,
776 size_t blk_size, size_t nblocks)
777{
778 ata_channel_t *chan = device->chan;
779 uint8_t status;
780 errno_t rc;
781
782 assert(nblocks > 0);
783 assert(blk_size % 2 == 0);
784
785 while (nblocks > 0) {
786 if (chan->params.have_irq)
787 rc = wait_irq(chan, &status, TIMEOUT_BSY);
788 else
789 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY);
790
791 if (rc != EOK) {
792 ata_msg_debug(chan, "wait_irq/wait_status failed");
793 return EIO;
794 }
795
796 if ((status & SR_DRQ) == 0) {
797 ata_msg_debug(chan, "DRQ == 0");
798 break;
799 }
800
801 /* Read data from the device buffer. */
802 ata_read_data_16(chan, (uint16_t *)obuf, blk_size / 2);
803 obuf += blk_size;
804
805 --nblocks;
806 }
807
808 if ((status & SR_ERR) != 0) {
809 ata_msg_debug(chan, "status & SR_ERR != 0");
810 return EIO;
811 }
812 if (nblocks > 0) {
813 ata_msg_debug(chan, "remaining nblocks = %zu", nblocks);
814 return EIO;
815 }
816
817 return EOK;
818}
819
820/** PIO data-out command protocol. */
821static errno_t ata_pio_data_out(ata_device_t *device, const void *buf, size_t buf_size,
822 size_t blk_size, size_t nblocks)
823{
824 ata_channel_t *chan = device->chan;
825 uint8_t status;
826 errno_t rc;
827
828 assert(nblocks > 0);
829 assert(blk_size % 2 == 0);
830
831 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY);
832 if (rc != EOK)
833 return EIO;
834
835 while (nblocks > 0) {
836 if ((status & SR_DRQ) == 0) {
837 ata_msg_debug(chan, "pio_data_out: unexpected DRQ=0");
838 break;
839 }
840
841 /* Write data to the device buffer. */
842 ata_write_data_16(chan, (uint16_t *)buf, blk_size / 2);
843 buf += blk_size;
844
845 if (chan->params.have_irq)
846 rc = wait_irq(chan, &status, TIMEOUT_BSY);
847 else
848 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY);
849 if (rc != EOK)
850 return EIO;
851
852 --nblocks;
853 }
854
855 if (status & SR_ERR)
856 return EIO;
857 if (nblocks > 0)
858 return EIO;
859
860 return EOK;
861}
862
863/** PIO non-data command protocol. */
864static errno_t ata_pio_nondata(ata_device_t *device)
865{
866 ata_channel_t *chan = device->chan;
867 uint8_t status;
868 errno_t rc;
869
870 if (chan->params.have_irq)
871 rc = wait_irq(chan, &status, TIMEOUT_BSY);
872 else
873 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY);
874
875 if (rc != EOK)
876 return EIO;
877
878 if (status & SR_ERR)
879 return EIO;
880
881 return EOK;
882}
883
884/** DMA command protocol.
885 *
886 * @param device ATA device
887 * @param cmd Command code
888 * @param buf Data buffer
889 * @param buf_size Data buffer size in bytes
890 * @param dir DMA direction
891 *
892 * @return EOK on success or an error code
893 */
894static errno_t ata_dma_proto(ata_device_t *device, uint8_t cmd, void *buf,
895 size_t buf_size, ata_dma_dir_t dir)
896{
897 ata_channel_t *chan = device->chan;
898 uint8_t status;
899 errno_t rc;
900
901 /* Set up DMA channel */
902 ata_dma_chan_setup(device, buf, buf_size, dir);
903
904 ata_write_cmd_8(chan, REG_COMMAND, cmd);
905
906 if (chan->params.have_irq)
907 rc = wait_irq(chan, &status, TIMEOUT_BSY);
908 else
909 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY);
910
911 /* Tear down DMA channel */
912 ata_dma_chan_teardown(device);
913
914 if (rc != EOK) {
915 ata_msg_debug(chan, "wait_irq/wait_status failed");
916 return EIO;
917 }
918
919 if ((status & SR_ERR) != 0) {
920 ata_msg_debug(chan, "status & SR_ERR != 0");
921 return EIO;
922 }
923
924 return EOK;
925}
926
927/** Issue IDENTIFY DEVICE command.
928 *
929 * Reads @c identify data into the provided buffer. This is used to detect
930 * whether an ATA device is present and if so, to determine its parameters.
931 *
932 * @param device Device
933 * @param buf Pointer to a 512-byte buffer.
934 *
935 * @return ETIMEOUT on timeout (this can mean the device is
936 * not present). EIO if device responds with error.
937 */
938static errno_t ata_identify_dev(ata_device_t *device, void *buf)
939{
940 ata_channel_t *chan = device->chan;
941 uint8_t status;
942 uint8_t drv_head;
943
944 drv_head = ((disk_dev_idx(device) != 0) ? DHR_DRV : 0);
945
946 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
947 return ETIMEOUT;
948
949 ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head);
950
951 /*
952 * Do not wait for DRDY to be set in case this is a packet device.
953 * We determine whether the device is present by waiting for DRQ to be
954 * set after issuing the command.
955 */
956 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
957 return ETIMEOUT;
958
959 ata_write_cmd_8(chan, REG_COMMAND, CMD_IDENTIFY_DRIVE);
960
961 /*
962 * For probing purposes we need to wait for some status bit to become
963 * active - otherwise we could be fooled just by receiving all zeroes.
964 */
965 if (wait_status(chan, SR_DRQ, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK) {
966 if ((status & SR_ERR) == 0) {
967 /* Probably no device at all */
968 return ETIMEOUT;
969 }
970 }
971
972 return ata_pio_data_in(device, buf, identify_data_size,
973 identify_data_size, 1);
974}
975
976/** Issue Identify Packet Device command.
977 *
978 * Reads @c identify data into the provided buffer. This is used to detect
979 * whether an ATAPI device is present and if so, to determine its parameters.
980 *
981 * @param device Device
982 * @param buf Pointer to a 512-byte buffer.
983 */
984static errno_t ata_identify_pkt_dev(ata_device_t *device, void *buf)
985{
986 ata_channel_t *chan = device->chan;
987 uint8_t drv_head;
988
989 drv_head = ((disk_dev_idx(device) != 0) ? DHR_DRV : 0);
990
991 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
992 return EIO;
993
994 ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head);
995
996 /* For ATAPI commands we do not need to wait for DRDY. */
997 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
998 return EIO;
999
1000 ata_write_cmd_8(chan, REG_COMMAND, CMD_IDENTIFY_PKT_DEV);
1001
1002 return ata_pio_data_in(device, buf, identify_data_size,
1003 identify_data_size, 1);
1004}
1005
1006/** Read data using PIO during a PACKET command.
1007 *
1008 * @param device Device
1009 * @param obuf Output buffer
1010 * @param obuf_size Output buffer size
1011 * @param rcvd_size Place to store number of bytes actually transferred
1012 * or @c NULL
1013 */
1014static errno_t ata_packet_pio_data_in(ata_device_t *device, void *obuf,
1015 size_t obuf_size, size_t *rcvd_size)
1016{
1017 ata_channel_t *chan = device->chan;
1018 size_t data_size;
1019 size_t remain;
1020 uint8_t status;
1021 errno_t rc;
1022
1023 remain = obuf_size;
1024 while (remain > 0) {
1025 if (chan->params.have_irq)
1026 rc = wait_irq(chan, &status, TIMEOUT_BSY);
1027 else
1028 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY);
1029
1030 if (rc != EOK) {
1031 fibril_mutex_unlock(&chan->lock);
1032 return EIO;
1033 }
1034
1035 if ((status & SR_DRQ) == 0)
1036 break;
1037
1038 /* Read byte count. */
1039 data_size = (uint16_t) ata_read_cmd_8(chan, REG_CYLINDER_LOW) +
1040 ((uint16_t) ata_read_cmd_8(chan, REG_CYLINDER_HIGH) << 8);
1041
1042 /* Check whether data fits into output buffer. */
1043 if (data_size > obuf_size) {
1044 /* Output buffer is too small to store data. */
1045 fibril_mutex_unlock(&chan->lock);
1046 return EIO;
1047 }
1048
1049 /* Read data from the device buffer. */
1050 ata_read_data_16(chan, obuf, (data_size + 1) / 2);
1051 obuf += data_size;
1052
1053 remain -= data_size;
1054 }
1055
1056 if (chan->params.have_irq)
1057 rc = wait_irq(chan, &status, TIMEOUT_BSY);
1058 else
1059 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY);
1060
1061 if (status & SR_ERR)
1062 return EIO;
1063
1064 if (rcvd_size != NULL)
1065 *rcvd_size = obuf_size - remain;
1066
1067 return EOK;
1068}
1069
1070/** Transfer data using DMA during PACKET command.
1071 *
1072 * @param device Device
1073 * @param buf Buffer
1074 * @param buf_size Buffer size
1075 * @param dir DMA direction
1076 *
1077 * @return EOK on success or an error code
1078 */
1079static errno_t ata_packet_dma(ata_device_t *device, void *buf, size_t buf_size,
1080 ata_dma_dir_t dir)
1081{
1082 ata_channel_t *chan = device->chan;
1083 uint8_t status;
1084 errno_t rc;
1085
1086 if (chan->params.have_irq)
1087 rc = wait_irq(chan, &status, TIMEOUT_BSY);
1088 else
1089 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY);
1090
1091 if (rc != EOK) {
1092 ata_msg_debug(chan, "wait_irq/wait_status failed");
1093 return EIO;
1094 }
1095
1096 if ((status & SR_ERR) != 0) {
1097 ata_msg_debug(chan, "status & SR_ERR != 0");
1098 return EIO;
1099 }
1100
1101 return EOK;
1102}
1103
1104/** Issue packet command (i. e. write a command packet to the device)
1105 * with no data transfer.
1106 *
1107 * @param device Device
1108 * @param cpkt Command packet
1109 * @param cpkt_size Command packet size in bytes
1110 *
1111 * @return EOK on success, EIO on error.
1112 */
1113static errno_t ata_cmd_packet_nondata(ata_device_t *device, const void *cpkt,
1114 size_t cpkt_size)
1115{
1116 ata_channel_t *chan = device->chan;
1117 uint8_t status;
1118 uint8_t drv_head;
1119 errno_t rc;
1120
1121 ata_msg_debug(chan, "ata_cmd_packet_nondata()");
1122
1123 fibril_mutex_lock(&chan->lock);
1124
1125 /* New value for Drive/Head register */
1126 drv_head =
1127 ((disk_dev_idx(device) != 0) ? DHR_DRV : 0);
1128
1129 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
1130 fibril_mutex_unlock(&chan->lock);
1131 return EIO;
1132 }
1133
1134 ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head);
1135
1136 if (wait_status(chan, 0, ~(SR_BSY | SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
1137 fibril_mutex_unlock(&chan->lock);
1138 return EIO;
1139 }
1140
1141 ata_write_cmd_8(chan, REG_COMMAND, CMD_PACKET);
1142
1143 if (wait_status(chan, SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
1144 if (chan->params.use_dma)
1145 ata_dma_chan_teardown(device);
1146 fibril_mutex_unlock(&chan->lock);
1147 return EIO;
1148 }
1149
1150 /* Write command packet. */
1151 ata_write_data_16(chan, ((uint16_t *) cpkt), (cpkt_size + 1) / 2);
1152
1153 rc = ata_pio_nondata(device);
1154
1155 fibril_mutex_unlock(&chan->lock);
1156
1157 return rc;
1158}
1159
1160/** Issue packet command (i. e. write a command packet to the device)
1161 * performing data-in transfer.
1162 *
1163 * @param device Device
1164 * @param cpkt Command packet
1165 * @param cpkt_size Command packet size in bytes
1166 * @param obuf Buffer for storing data read from device
1167 * @param obuf_size Size of obuf in bytes
1168 * @param rcvd_size Place to store number of bytes read or @c NULL
1169 *
1170 * @return EOK on success, EIO on error.
1171 */
1172static errno_t ata_cmd_packet_din(ata_device_t *device, const void *cpkt,
1173 size_t cpkt_size, void *obuf, size_t obuf_size, size_t *rcvd_size)
1174{
1175 ata_channel_t *chan = device->chan;
1176 uint8_t status;
1177 uint8_t drv_head;
1178 errno_t rc;
1179
1180 fibril_mutex_lock(&chan->lock);
1181
1182 /* New value for Drive/Head register */
1183 drv_head =
1184 ((disk_dev_idx(device) != 0) ? DHR_DRV : 0);
1185
1186 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
1187 fibril_mutex_unlock(&chan->lock);
1188 return EIO;
1189 }
1190
1191 ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head);
1192
1193 if (wait_status(chan, 0, ~(SR_BSY | SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
1194 fibril_mutex_unlock(&chan->lock);
1195 return EIO;
1196 }
1197
1198 if (chan->params.use_dma) {
1199 /* Set up DMA channel */
1200 ata_dma_chan_setup(device, obuf, obuf_size, ata_dma_read);
1201 ata_write_cmd_8(chan, REG_FEATURES, 0x01); // XXX
1202 } else {
1203 /*
1204 * Byte count <- max. number of bytes we can read in one
1205 * PIO transfer.
1206 */
1207 ata_write_cmd_8(chan, REG_CYLINDER_LOW, 0xfe);
1208 ata_write_cmd_8(chan, REG_CYLINDER_HIGH, 0xff);
1209 }
1210
1211 ata_write_cmd_8(chan, REG_COMMAND, CMD_PACKET);
1212
1213 if (wait_status(chan, SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
1214 if (chan->params.use_dma)
1215 ata_dma_chan_teardown(device);
1216 fibril_mutex_unlock(&chan->lock);
1217 return EIO;
1218 }
1219
1220 /* Write command packet. */
1221 ata_write_data_16(chan, ((uint16_t *) cpkt), (cpkt_size + 1) / 2);
1222
1223 if (chan->params.use_dma) {
1224 /* Read data using DMA */
1225 rc = ata_packet_dma(device, obuf, obuf_size, ata_dma_read);
1226 if (rc == EOK && rcvd_size != NULL)
1227 *rcvd_size = obuf_size;
1228 ata_dma_chan_teardown(device);
1229 } else {
1230 /* Read data using PIO */
1231 rc = ata_packet_pio_data_in(device, obuf, obuf_size, rcvd_size);
1232 }
1233
1234 fibril_mutex_unlock(&chan->lock);
1235
1236 if (rc != EOK)
1237 return rc;
1238
1239 return EOK;
1240}
1241
1242/** Issue ATAPI Inquiry.
1243 *
1244 * @param device Device
1245 * @param obuf Buffer for storing inquiry data read from device
1246 * @param obuf_size Size of obuf in bytes
1247 *
1248 * @return EOK on success, EIO on error.
1249 */
1250static errno_t ata_pcmd_inquiry(ata_device_t *device, void *obuf, size_t obuf_size,
1251 size_t *rcvd_size)
1252{
1253 uint8_t cpb[12];
1254 scsi_cdb_inquiry_t *cp = (scsi_cdb_inquiry_t *)cpb;
1255 errno_t rc;
1256
1257 memset(cpb, 0, sizeof(cpb));
1258
1259 /*
1260 * For SFF 8020 compliance the inquiry must be padded to 12 bytes
1261 * and allocation length must fit in one byte.
1262 */
1263 cp->op_code = SCSI_CMD_INQUIRY;
1264
1265 /* Allocation length */
1266 cp->alloc_len = host2uint16_t_be(min(obuf_size, 0xff));
1267
1268 rc = ata_cmd_packet_din(device, cpb, sizeof(cpb), obuf, obuf_size,
1269 rcvd_size);
1270 if (rc != EOK)
1271 return rc;
1272
1273 return EOK;
1274}
1275
1276/** Issue ATAPI read capacity(10) command.
1277 *
1278 * @param device Device
1279 * @param nblocks Place to store number of blocks
1280 * @param block_size Place to store block size
1281 *
1282 * @return EOK on success, EIO on error.
1283 */
1284static errno_t ata_pcmd_read_capacity(ata_device_t *device, uint64_t *nblocks,
1285 size_t *block_size)
1286{
1287 scsi_cdb_read_capacity_10_t cdb;
1288 scsi_read_capacity_10_data_t data;
1289 size_t rsize;
1290 errno_t rc;
1291
1292 memset(&cdb, 0, sizeof(cdb));
1293 cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
1294
1295 rc = ata_cmd_packet_din(device, &cdb, sizeof(cdb), &data, sizeof(data),
1296 &rsize);
1297 if (rc != EOK)
1298 return rc;
1299
1300 if (rsize != sizeof(data))
1301 return EIO;
1302
1303 *nblocks = uint32_t_be2host(data.last_lba) + 1;
1304 *block_size = uint32_t_be2host(data.block_size);
1305
1306 return EOK;
1307}
1308
1309/** Issue ATAPI read(12) command.
1310 *
1311 * Output buffer must be large enough to hold the data, otherwise the
1312 * function will fail.
1313 *
1314 * @param device Device
1315 * @param ba Starting block address
1316 * @param cnt Number of blocks to read
1317 * @param obuf Buffer for storing inquiry data read from device
1318 * @param obuf_size Size of obuf in bytes
1319 *
1320 * @return EOK on success, EIO on error.
1321 */
1322static errno_t ata_pcmd_read_12(ata_device_t *device, uint64_t ba, size_t cnt,
1323 void *obuf, size_t obuf_size)
1324{
1325 scsi_cdb_read_12_t cp;
1326 errno_t rc;
1327
1328 if (ba > UINT32_MAX)
1329 return EINVAL;
1330
1331 memset(&cp, 0, sizeof(cp));
1332
1333 cp.op_code = SCSI_CMD_READ_12;
1334 cp.lba = host2uint32_t_be(ba);
1335 cp.xfer_len = host2uint32_t_be(cnt);
1336
1337 rc = ata_cmd_packet_din(device, &cp, sizeof(cp), obuf, obuf_size, NULL);
1338 if (rc != EOK)
1339 return rc;
1340
1341 return EOK;
1342}
1343
1344/** Issue ATAPI read TOC command.
1345 *
1346 * Read TOC in 'multi-session' format (first and last session number
1347 * with last session LBA).
1348 *
1349 * http://suif.stanford.edu/~csapuntz/specs/INF-8020.PDF page 171
1350 *
1351 * Output buffer must be large enough to hold the data, otherwise the
1352 * function will fail.
1353 *
1354 * @param device Device
1355 * @param session Starting session
1356 * @param obuf Buffer for storing inquiry data read from device
1357 * @param obuf_size Size of obuf in bytes
1358 *
1359 * @return EOK on success, EIO on error.
1360 */
1361static errno_t ata_pcmd_read_toc(ata_device_t *device, uint8_t session,
1362 void *obuf, size_t obuf_size)
1363{
1364 uint8_t cpb[12];
1365 scsi_cdb_read_toc_t *cp = (scsi_cdb_read_toc_t *)cpb;
1366 errno_t rc;
1367
1368 memset(cpb, 0, sizeof(cpb));
1369
1370 cp->op_code = SCSI_CMD_READ_TOC;
1371 cp->msf = 0;
1372 cp->format = 0x01; /* 0x01 = multi-session mode */
1373 cp->track_sess_no = session;
1374 cp->alloc_len = host2uint16_t_be(obuf_size);
1375 cp->control = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */
1376
1377 rc = ata_cmd_packet_din(device, cpb, sizeof(cpb), obuf, obuf_size,
1378 NULL);
1379 if (rc != EOK)
1380 return rc;
1381
1382 return EOK;
1383}
1384
1385/** Issue Start Stop Unit command.
1386 *
1387 * @param device Device
1388 * @param flags Flags field of Start Stop Unit command (ssf_*)
1389 * @return EOK on success, EIO on error.
1390 */
1391static errno_t ata_pcmd_start_stop_unit(ata_device_t *device, uint8_t flags)
1392{
1393 uint8_t cpb[12];
1394 scsi_cdb_start_stop_unit_t *cp = (scsi_cdb_start_stop_unit_t *)cpb;
1395 errno_t rc;
1396
1397 ata_msg_debug(device->chan, "ata_pcmd_start_stop_unit(device, 0x%x)",
1398 flags);
1399
1400 memset(cpb, 0, sizeof(cpb));
1401
1402 /*
1403 * For SFF 8020 compliance the command must be padded to 12 bytes.
1404 */
1405 cp->op_code = SCSI_CMD_START_STOP_UNIT;
1406 cp->immed = 0;
1407 cp->flags = flags;
1408 cp->control = 0;
1409
1410 rc = ata_cmd_packet_nondata(device, cpb, sizeof(cpb));
1411 if (rc != EOK)
1412 return rc;
1413
1414 ata_msg_debug(device->chan, "ata_pcmd_start_stop_unit(): "
1415 "ata_cmd_packet_nondata -> %d", rc);
1416
1417 return EOK;
1418}
1419
1420/** Read a physical block from the device.
1421 *
1422 * @param device Device
1423 * @param ba Address the first block.
1424 * @param cnt Number of blocks to transfer.
1425 * @param buf Buffer for holding the data.
1426 *
1427 * @return EOK on success, EIO on error.
1428 */
1429static errno_t ata_rcmd_read(ata_device_t *device, uint64_t ba, size_t blk_cnt,
1430 void *buf)
1431{
1432 ata_channel_t *chan = device->chan;
1433 uint8_t drv_head;
1434 block_coord_t bc;
1435 uint8_t cmd;
1436 errno_t rc;
1437
1438 /* Silence warning. */
1439 memset(&bc, 0, sizeof(bc));
1440
1441 /* Compute block coordinates. */
1442 if (coord_calc(device, ba, &bc) != EOK) {
1443 ata_msg_note(chan, "ata_rcmd_read() -> coord_calc failed");
1444 return EINVAL;
1445 }
1446
1447 /* New value for Drive/Head register */
1448 drv_head =
1449 ((disk_dev_idx(device) != 0) ? DHR_DRV : 0) |
1450 ((device->amode != am_chs) ? DHR_LBA : 0) |
1451 (bc.h & 0x0f);
1452
1453 fibril_mutex_lock(&chan->lock);
1454
1455 /* Program a Read Sectors operation. */
1456
1457 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
1458 fibril_mutex_unlock(&chan->lock);
1459 ata_msg_note(chan, "ata_rcmd_read() -> wait_status failed");
1460 return EIO;
1461 }
1462
1463 ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head);
1464
1465 if (wait_status(chan, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
1466 fibril_mutex_unlock(&chan->lock);
1467 ata_msg_note(chan, "ata_rcmd_read() -> wait_status 2 failed");
1468 return EIO;
1469 }
1470
1471 /* Program block coordinates into the device. */
1472 coord_sc_program(chan, &bc, blk_cnt);
1473
1474 if (chan->params.use_dma) {
1475 cmd = (device->amode == am_lba48) ? CMD_READ_DMA_EXT :
1476 CMD_READ_DMA;
1477
1478 rc = ata_dma_proto(device, cmd, buf,
1479 blk_cnt * device->block_size, ata_dma_read);
1480 if (rc != EOK) {
1481 ata_msg_note(chan, "ata_rcmd_read() -> dma_proto->%d",
1482 rc);
1483 }
1484 } else {
1485 ata_write_cmd_8(chan, REG_COMMAND, device->amode == am_lba48 ?
1486 CMD_READ_SECTORS_EXT : CMD_READ_SECTORS);
1487
1488 rc = ata_pio_data_in(device, buf, blk_cnt * device->block_size,
1489 device->block_size, blk_cnt);
1490 if (rc != EOK) {
1491 ata_msg_note(chan, "ata_rcmd_read() -> pio_data_in->%d",
1492 rc);
1493 }
1494 }
1495
1496 fibril_mutex_unlock(&chan->lock);
1497
1498 return rc;
1499}
1500
1501/** Write a physical block to the device.
1502 *
1503 * @param device Device
1504 * @param ba Address of the first block.
1505 * @param cnt Number of blocks to transfer.
1506 * @param buf Buffer holding the data to write.
1507 *
1508 * @return EOK on success, EIO on error.
1509 */
1510static errno_t ata_rcmd_write(ata_device_t *device, uint64_t ba, size_t cnt,
1511 const void *buf)
1512{
1513 ata_channel_t *chan = device->chan;
1514 uint8_t drv_head;
1515 block_coord_t bc;
1516 uint8_t cmd;
1517 errno_t rc;
1518
1519 /* Silence warning. */
1520 memset(&bc, 0, sizeof(bc));
1521
1522 /* Compute block coordinates. */
1523 if (coord_calc(device, ba, &bc) != EOK)
1524 return EINVAL;
1525
1526 /* New value for Drive/Head register */
1527 drv_head =
1528 ((disk_dev_idx(device) != 0) ? DHR_DRV : 0) |
1529 ((device->amode != am_chs) ? DHR_LBA : 0) |
1530 (bc.h & 0x0f);
1531
1532 fibril_mutex_lock(&chan->lock);
1533
1534 /* Program a Write Sectors operation. */
1535
1536 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
1537 fibril_mutex_unlock(&chan->lock);
1538 return EIO;
1539 }
1540
1541 ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head);
1542
1543 if (wait_status(chan, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
1544 fibril_mutex_unlock(&chan->lock);
1545 return EIO;
1546 }
1547
1548 /* Program block coordinates into the device. */
1549 coord_sc_program(chan, &bc, cnt);
1550
1551 if (chan->params.use_dma) {
1552 cmd = (device->amode == am_lba48) ? CMD_WRITE_DMA_EXT :
1553 CMD_WRITE_DMA;
1554
1555 rc = ata_dma_proto(device, cmd, (void *)buf,
1556 cnt * device->block_size, ata_dma_write);
1557 if (rc != EOK) {
1558 ata_msg_note(chan, "ata_rcmd_write() -> dma_proto->%d",
1559 rc);
1560 }
1561 } else {
1562 ata_write_cmd_8(chan, REG_COMMAND, device->amode == am_lba48 ?
1563 CMD_WRITE_SECTORS_EXT : CMD_WRITE_SECTORS);
1564
1565 rc = ata_pio_data_out(device, buf, cnt * device->block_size,
1566 device->block_size, cnt);
1567 if (rc != EOK) {
1568 ata_msg_note(chan,
1569 "ata_rcmd_read() -> pio_data_out->%d", rc);
1570 }
1571 }
1572
1573 fibril_mutex_unlock(&chan->lock);
1574 return rc;
1575}
1576
1577/** Flush cached data to nonvolatile storage.
1578 *
1579 * @param device Device
1580 *
1581 * @return EOK on success, EIO on error.
1582 */
1583static errno_t ata_rcmd_flush_cache(ata_device_t *device)
1584{
1585 ata_channel_t *chan = device->chan;
1586 uint8_t drv_head;
1587 errno_t rc;
1588
1589 /* New value for Drive/Head register */
1590 drv_head =
1591 (disk_dev_idx(device) != 0) ? DHR_DRV : 0;
1592
1593 fibril_mutex_lock(&chan->lock);
1594
1595 /* Program a Flush Cache operation. */
1596
1597 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
1598 fibril_mutex_unlock(&chan->lock);
1599 return EIO;
1600 }
1601
1602 ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head);
1603
1604 if (wait_status(chan, SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
1605 fibril_mutex_unlock(&chan->lock);
1606 return EIO;
1607 }
1608
1609 ata_write_cmd_8(chan, REG_COMMAND, CMD_FLUSH_CACHE);
1610
1611 rc = ata_pio_nondata(device);
1612
1613 fibril_mutex_unlock(&chan->lock);
1614 return rc;
1615}
1616
1617/** Get the maximum number of blocks to be transferred in one I/O
1618 *
1619 * @param d Device
1620 * @return Maximum number of blocks
1621 */
1622static size_t ata_disk_maxnb(ata_device_t *d)
1623{
1624 size_t maxnb;
1625 size_t dma_maxnb;
1626
1627 maxnb = 0;
1628
1629 if (d->dev_type == ata_pkt_dev) {
1630 /* Could be more depending on SCSI command support */
1631 maxnb = 0x100;
1632 } else {
1633 switch (d->amode) {
1634 case am_chs:
1635 case am_lba28:
1636 maxnb = 0x100;
1637 break;
1638 case am_lba48:
1639 maxnb = 0x10000;
1640 break;
1641 }
1642 }
1643
1644 /*
1645 * If using DMA, this needs to be further restricted not to
1646 * exceed DMA buffer size.
1647 */
1648 if (d->chan->params.use_dma) {
1649 dma_maxnb = d->chan->params.max_dma_xfer / d->block_size;
1650 if (dma_maxnb < maxnb)
1651 maxnb = dma_maxnb;
1652 }
1653
1654 return maxnb;
1655}
1656
1657/** Calculate block coordinates.
1658 *
1659 * Calculates block coordinates in the best coordinate system supported
1660 * by the device. These can be later programmed into the device using
1661 * @c coord_sc_program().
1662 *
1663 * @return EOK on success or EINVAL if block index is past end of device.
1664 */
1665static errno_t coord_calc(ata_device_t *d, uint64_t ba, block_coord_t *bc)
1666{
1667 uint64_t c;
1668 uint64_t idx;
1669
1670 /* Check device bounds. */
1671 if (ba >= d->blocks)
1672 return EINVAL;
1673
1674 bc->amode = d->amode;
1675
1676 switch (d->amode) {
1677 case am_chs:
1678 /* Compute CHS coordinates. */
1679 c = ba / (d->geom.heads * d->geom.sectors);
1680 idx = ba % (d->geom.heads * d->geom.sectors);
1681
1682 bc->cyl_lo = c & 0xff;
1683 bc->cyl_hi = (c >> 8) & 0xff;
1684 bc->h = (idx / d->geom.sectors) & 0x0f;
1685 bc->sector = (1 + (idx % d->geom.sectors)) & 0xff;
1686 break;
1687
1688 case am_lba28:
1689 /* Compute LBA-28 coordinates. */
1690 bc->c0 = ba & 0xff; /* bits 0-7 */
1691 bc->c1 = (ba >> 8) & 0xff; /* bits 8-15 */
1692 bc->c2 = (ba >> 16) & 0xff; /* bits 16-23 */
1693 bc->h = (ba >> 24) & 0x0f; /* bits 24-27 */
1694 break;
1695
1696 case am_lba48:
1697 /* Compute LBA-48 coordinates. */
1698 bc->c0 = ba & 0xff; /* bits 0-7 */
1699 bc->c1 = (ba >> 8) & 0xff; /* bits 8-15 */
1700 bc->c2 = (ba >> 16) & 0xff; /* bits 16-23 */
1701 bc->c3 = (ba >> 24) & 0xff; /* bits 24-31 */
1702 bc->c4 = (ba >> 32) & 0xff; /* bits 32-39 */
1703 bc->c5 = (ba >> 40) & 0xff; /* bits 40-47 */
1704 bc->h = 0;
1705 break;
1706 }
1707
1708 return EOK;
1709}
1710
1711/** Program block coordinates and sector count into ATA registers.
1712 *
1713 * Note that bc->h must be programmed separately into the device/head register.
1714 *
1715 * @param chan Channel
1716 * @param bc Block coordinates
1717 * @param scnt Sector count
1718 */
1719static void coord_sc_program(ata_channel_t *chan, const block_coord_t *bc,
1720 uint16_t scnt)
1721{
1722 if (bc->amode == am_lba48) {
1723 /* Write high-order bits. */
1724 ata_write_cmd_8(chan, REG_SECTOR_COUNT, scnt >> 8);
1725 ata_write_cmd_8(chan, REG_SECTOR_NUMBER, bc->c3);
1726 ata_write_cmd_8(chan, REG_CYLINDER_LOW, bc->c4);
1727 ata_write_cmd_8(chan, REG_CYLINDER_HIGH, bc->c5);
1728 }
1729
1730 /* Write low-order bits. */
1731 ata_write_cmd_8(chan, REG_SECTOR_COUNT, scnt & 0x00ff);
1732 ata_write_cmd_8(chan, REG_SECTOR_NUMBER, bc->c0);
1733 ata_write_cmd_8(chan, REG_CYLINDER_LOW, bc->c1);
1734 ata_write_cmd_8(chan, REG_CYLINDER_HIGH, bc->c2);
1735}
1736
1737/** Wait until some status bits are set and some are reset.
1738 *
1739 * Example: wait_status(chan, SR_DRDY, ~SR_BSY, ...) waits for SR_DRDY to become
1740 * set and SR_BSY to become reset.
1741 *
1742 * @param chan Channel
1743 * @param set Combination if bits which must be all set.
1744 * @param n_reset Negated combination of bits which must be all reset.
1745 * @param pstatus Pointer where to store last read status or NULL.
1746 * @param timeout Timeout in 10ms units.
1747 *
1748 * @return EOK on success, EIO on timeout.
1749 */
1750static errno_t wait_status(ata_channel_t *chan, unsigned set, unsigned n_reset,
1751 uint8_t *pstatus, unsigned timeout)
1752{
1753 uint8_t status;
1754 int cnt;
1755
1756 status = ata_read_cmd_8(chan, REG_STATUS);
1757
1758 /*
1759 * This is crude, yet simple. First try with 1us delays
1760 * (most likely the device will respond very fast). If not,
1761 * start trying every 10 ms.
1762 */
1763
1764 cnt = 100;
1765 while ((status & ~n_reset) != 0 || (status & set) != set) {
1766 --cnt;
1767 if (cnt <= 0)
1768 break;
1769
1770 status = ata_read_cmd_8(chan, REG_STATUS);
1771 }
1772
1773 cnt = timeout;
1774 while ((status & ~n_reset) != 0 || (status & set) != set) {
1775 fibril_usleep(10000);
1776 --cnt;
1777 if (cnt <= 0)
1778 break;
1779
1780 status = ata_read_cmd_8(chan, REG_STATUS);
1781 }
1782
1783 if (pstatus)
1784 *pstatus = status;
1785
1786 if (cnt == 0)
1787 return EIO;
1788
1789 return EOK;
1790}
1791
1792/** Wait for IRQ and return status.
1793 *
1794 * @param chan Channel
1795 * @param pstatus Pointer where to store last read status or NULL.
1796 * @param timeout Timeout in 10ms units.
1797 *
1798 * @return EOK on success, EIO on timeout.
1799 */
1800static errno_t wait_irq(ata_channel_t *chan, uint8_t *pstatus, unsigned timeout)
1801{
1802 fibril_mutex_lock(&chan->irq_lock);
1803 while (!chan->irq_fired)
1804 fibril_condvar_wait(&chan->irq_cv, &chan->irq_lock);
1805
1806 chan->irq_fired = false;
1807 *pstatus = chan->irq_status;
1808 fibril_mutex_unlock(&chan->irq_lock);
1809 return EOK;
1810}
1811
1812/** Set up DMA channel.
1813 *
1814 * @param device ATA device
1815 * @param buf Data buffer
1816 * @param buf_size Data buffer size in bytes
1817 * @param dir DMA direction
1818 */
1819static void ata_dma_chan_setup(ata_device_t *device, void *buf,
1820 size_t buf_size, ata_dma_dir_t dir)
1821{
1822 device->chan->params.dma_chan_setup(device->chan->params.arg,
1823 buf, buf_size, dir);
1824}
1825
1826/** Tear down DMA channel.
1827 *
1828 * @param device ATA device
1829 */
1830static void ata_dma_chan_teardown(ata_device_t *device)
1831{
1832 device->chan->params.dma_chan_teardown(device->chan->params.arg);
1833}
1834
1835/** Interrupt handler.
1836 *
1837 * @param chan ATA channel
1838 * @param status Status read by interrupt handler
1839 */
1840void ata_channel_irq(ata_channel_t *chan, uint8_t status)
1841{
1842 fibril_mutex_lock(&chan->irq_lock);
1843 chan->irq_fired = true;
1844 chan->irq_status = status;
1845 fibril_mutex_unlock(&chan->irq_lock);
1846 fibril_condvar_broadcast(&chan->irq_cv);
1847}
1848
1849/** Block device connection handler */
1850void ata_connection(ipc_call_t *icall, ata_device_t *device)
1851{
1852 bd_conn(icall, &device->bds);
1853}
1854
1855/**
1856 * @}
1857 */
Note: See TracBrowser for help on using the repository browser.