source: mainline/uspace/lib/ata/src/ata.c@ 646849b3

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

Handle both IDE channels in the same driver instance

We need to work around libdrv not allowing us to distinguish
between two interrupts registered with the same device.

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