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

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

Limit I/O operations not to exceed DMA buffer size

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