source: mainline/uspace/lib/ata/src/ata.c@ b1490d2

Last change on this file since b1490d2 was a796812c, checked in by Jiri Svoboda <jiri@…>, 5 months ago

Fix ISA IDE

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