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

Last change on this file since ee47537 was 3d2d455b, checked in by Miroslav Cimerman <mc@…>, 14 months ago

ata_channel_destroy(): unlock channel mutex after error

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