source: mainline/uspace/drv/block/pci-ide/pci-ide.c@ 144fafd

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

Implement quiesce in ISA and PCI IDE and in PC Floppy.

  • Property mode set to 100644
File size: 18.3 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup pci-ide
30 * @{
31 */
32
33/**
34 * @file
35 * @brief PCI IDE driver
36 */
37
38#include <assert.h>
39#include <ddi.h>
40#include <ddf/interrupt.h>
41#include <ddf/log.h>
42#include <async.h>
43#include <as.h>
44#include <fibril_synch.h>
45#include <stdint.h>
46#include <stdbool.h>
47#include <stdio.h>
48#include <stddef.h>
49#include <str.h>
50#include <inttypes.h>
51#include <errno.h>
52
53#include "pci-ide.h"
54#include "main.h"
55
56static errno_t pci_ide_init_io(pci_ide_channel_t *);
57static void pci_ide_fini_io(pci_ide_channel_t *);
58static errno_t pci_ide_init_irq(pci_ide_channel_t *);
59static void pci_ide_fini_irq(pci_ide_channel_t *);
60static void pci_ide_irq_handler(ipc_call_t *, void *);
61
62static void pci_ide_write_data_16(void *, uint16_t *, size_t);
63static void pci_ide_read_data_16(void *, uint16_t *, size_t);
64static void pci_ide_write_cmd_8(void *, uint16_t, uint8_t);
65static uint8_t pci_ide_read_cmd_8(void *, uint16_t);
66static void pci_ide_write_ctl_8(void *, uint16_t, uint8_t);
67static uint8_t pci_ide_read_ctl_8(void *, uint16_t);
68static errno_t pci_ide_irq_enable(void *);
69static errno_t pci_ide_irq_disable(void *);
70static void pci_ide_dma_chan_setup(void *, void *, size_t, ata_dma_dir_t);
71static void pci_ide_dma_chan_teardown(void *);
72static errno_t pci_ide_add_device(void *, unsigned, void *);
73static errno_t pci_ide_remove_device(void *, unsigned);
74static void pci_ide_msg_debug(void *, char *);
75static void pci_ide_msg_note(void *, char *);
76static void pci_ide_msg_warn(void *, char *);
77static void pci_ide_msg_error(void *, char *);
78
79static const irq_pio_range_t pci_ide_irq_ranges[] = {
80 {
81 .base = 0,
82 .size = sizeof(ata_cmd_t)
83 },
84 {
85 .base = 0,
86 .size = sizeof(pci_ide_regs_t)
87 }
88};
89
90/** IDE interrupt pseudo code. */
91static const irq_cmd_t pci_ide_irq_cmds[] = {
92 /* [0] Read BMISX */
93 {
94 .cmd = CMD_PIO_READ_8,
95 .addr = NULL, /* will be patched in run-time */
96 .dstarg = 1
97 },
98 /* [1] Test BMISX.IDEINTS */
99 {
100 .cmd = CMD_AND,
101 .value = bmisx_ideints,
102 .srcarg = 1,
103 .dstarg = 2
104 },
105 /* [2] if (BMISX.IDEINTS != 0) { */
106 {
107 .cmd = CMD_PREDICATE,
108 .srcarg = 2,
109 .value = 3
110 },
111 /*
112 * [3] Clear BMISX.IDEINTS by writing 1 to it. This clears bits 6,5,
113 * but that should not matter.
114 */
115 {
116 .cmd = CMD_PIO_WRITE_8,
117 .addr = NULL, /* will be patched in run-time */
118 .value = bmisx_ideints
119 },
120 /* [4] Read IDE status register */
121 {
122 .cmd = CMD_PIO_READ_8,
123 .addr = NULL, /* will be patched in run-time */
124 .dstarg = 1
125 },
126 /* [5] Accept */
127 {
128 .cmd = CMD_ACCEPT
129 },
130 /* [6] } else { Decline */
131 {
132 .cmd = CMD_DECLINE
133 }
134 /* } */
135};
136
137/** Initialize PCI IDE controller.
138 *
139 * @param ctrl PCI IDE controller
140 * @param res Hardware resources
141 *
142 * @return EOK on success or an error code
143 */
144errno_t pci_ide_ctrl_init(pci_ide_ctrl_t *ctrl, pci_ide_hwres_t *res)
145{
146 errno_t rc;
147 void *vaddr;
148
149 ddf_msg(LVL_DEBUG, "pci_ide_ctrl_init()");
150 ctrl->bmregs_physical = res->bmregs;
151
152 ddf_msg(LVL_NOTE, "Bus master IDE regs I/O address: 0x%" PRIxPTR,
153 ctrl->bmregs_physical);
154
155 rc = pio_enable((void *)ctrl->bmregs_physical, sizeof(pci_ide_regs_t),
156 &vaddr);
157 if (rc != EOK) {
158 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
159 return rc;
160 }
161
162 ctrl->bmregs = vaddr;
163
164 ddf_msg(LVL_DEBUG, "pci_ide_ctrl_init: DONE");
165 return EOK;
166}
167
168/** Finalize PCI IDE controller.
169 *
170 * @param ctrl PCI IDE controller
171 * @return EOK on success or an error code
172 */
173errno_t pci_ide_ctrl_fini(pci_ide_ctrl_t *ctrl)
174{
175 ddf_msg(LVL_DEBUG, ": pci_ide_ctrl_fini()");
176
177 // XXX TODO
178 return EOK;
179}
180
181/** Initialize PCI IDE channel. */
182errno_t pci_ide_channel_init(pci_ide_ctrl_t *ctrl, pci_ide_channel_t *chan,
183 unsigned chan_id, pci_ide_hwres_t *res)
184{
185 errno_t rc;
186 bool irq_inited = false;
187 ata_params_t params;
188 void *buffer = NULL;
189
190 ddf_msg(LVL_DEBUG, "pci_ide_channel_init()");
191
192 memset(&params, 0, sizeof(params));
193
194 chan->ctrl = ctrl;
195 chan->chan_id = chan_id;
196 fibril_mutex_initialize(&chan->lock);
197 if (chan_id == 0) {
198 chan->cmd_physical = res->cmd1;
199 chan->ctl_physical = res->ctl1;
200 chan->irq = res->irq1;
201 } else {
202 chan->cmd_physical = res->cmd2;
203 chan->ctl_physical = res->ctl2;
204 chan->irq = res->irq2;
205 }
206
207 chan->dma_buf_size = 8192;
208
209 ddf_msg(LVL_NOTE, "I/O address %p/%p", (void *) chan->cmd_physical,
210 (void *) chan->ctl_physical);
211
212 ddf_msg(LVL_DEBUG, "Init I/O");
213 rc = pci_ide_init_io(chan);
214 if (rc != EOK)
215 return rc;
216
217 ddf_msg(LVL_DEBUG, "Init IRQ");
218 rc = pci_ide_init_irq(chan);
219 if (rc != EOK) {
220 ddf_msg(LVL_NOTE, "init IRQ failed");
221 goto error;
222 }
223
224 irq_inited = true;
225
226 ddf_msg(LVL_DEBUG, "Allocate PRD table");
227
228 buffer = AS_AREA_ANY;
229 rc = dmamem_map_anonymous(sizeof (pci_ide_prd_t), DMAMEM_4GiB | 0xffff,
230 AS_AREA_WRITE | AS_AREA_READ, 0, &chan->prdt_pa, &buffer);
231 if (rc != EOK) {
232 ddf_msg(LVL_NOTE, "Failed allocating PRD table.");
233 goto error;
234 }
235
236 chan->prdt = (pci_ide_prd_t *)buffer;
237
238 ddf_msg(LVL_DEBUG, "Allocate DMA buffer");
239
240 buffer = AS_AREA_ANY;
241 rc = dmamem_map_anonymous(chan->dma_buf_size, DMAMEM_4GiB | 0xffff,
242 AS_AREA_WRITE | AS_AREA_READ, 0, &chan->dma_buf_pa, &buffer);
243 if (rc != EOK) {
244 ddf_msg(LVL_NOTE, "Failed allocating PRD table.");
245 goto error;
246 }
247
248 chan->dma_buf = buffer;
249
250 /* Populate PRD with information on our single DMA buffer */
251 chan->prdt->pba = host2uint32_t_le(chan->dma_buf_pa);
252 chan->prdt->bcnt = host2uint16_t_le(chan->dma_buf_size);
253 chan->prdt->eot_res = host2uint16_t_le(pci_ide_prd_eot);
254
255 /* Program PRD table pointer register */
256 if (chan_id == 0) {
257 pio_write_32(&chan->ctrl->bmregs->bmidtpp,
258 (uint32_t)chan->prdt_pa);
259 } else {
260 pio_write_32(&chan->ctrl->bmregs->bmidtps,
261 (uint32_t)chan->prdt_pa);
262 }
263
264 ddf_msg(LVL_DEBUG, "pci_ide_channel_init(): Initialize IDE channel");
265
266 params.arg = (void *)chan;
267 params.have_irq = (chan->irq >= 0) ? true : false;
268 params.use_dma = true;
269 params.max_dma_xfer = chan->dma_buf_size;
270 params.write_data_16 = pci_ide_write_data_16;
271 params.read_data_16 = pci_ide_read_data_16;
272 params.write_cmd_8 = pci_ide_write_cmd_8;
273 params.read_cmd_8 = pci_ide_read_cmd_8;
274 params.write_ctl_8 = pci_ide_write_ctl_8;
275 params.read_ctl_8 = pci_ide_read_ctl_8;
276 params.irq_enable = pci_ide_irq_enable;
277 params.irq_disable = pci_ide_irq_disable;
278 params.dma_chan_setup = pci_ide_dma_chan_setup;
279 params.dma_chan_teardown = pci_ide_dma_chan_teardown;
280 params.add_device = pci_ide_add_device;
281 params.remove_device = pci_ide_remove_device;
282 params.msg_debug = pci_ide_msg_debug;
283 params.msg_note = pci_ide_msg_note;
284 params.msg_warn = pci_ide_msg_warn;
285 params.msg_error = pci_ide_msg_error;
286
287 rc = ata_channel_create(&params, &chan->channel);
288 if (rc != EOK)
289 goto error;
290
291 rc = ata_channel_initialize(chan->channel);
292 if (rc != EOK)
293 goto error;
294
295 ddf_msg(LVL_DEBUG, "pci_ide_channel_init: DONE");
296 return EOK;
297error:
298 if (chan->channel != NULL) {
299 (void) ata_channel_destroy(chan->channel);
300 chan->channel = NULL;
301 }
302 if (buffer != NULL)
303 dmamem_unmap_anonymous(buffer);
304 if (irq_inited)
305 pci_ide_fini_irq(chan);
306 pci_ide_fini_io(chan);
307 return rc;
308}
309
310/** Finalize PCI IDE channel. */
311errno_t pci_ide_channel_fini(pci_ide_channel_t *chan)
312{
313 errno_t rc;
314
315 ddf_msg(LVL_DEBUG, ": pci_ide_channel_fini()");
316
317 fibril_mutex_lock(&chan->lock);
318
319 rc = ata_channel_destroy(chan->channel);
320 if (rc != EOK) {
321 fibril_mutex_unlock(&chan->lock);
322 return rc;
323 }
324
325 dmamem_unmap_anonymous(chan->dma_buf);
326 pci_ide_fini_irq(chan);
327 pci_ide_fini_io(chan);
328 fibril_mutex_unlock(&chan->lock);
329
330 return EOK;
331}
332
333/** Quiesce PCI IDE channel. */
334void pci_ide_channel_quiesce(pci_ide_channel_t *chan)
335{
336 ddf_msg(LVL_DEBUG, ": pci_ide_channel_quiesce()");
337
338 fibril_mutex_lock(&chan->lock);
339 ata_channel_quiesce(chan->channel);
340 fibril_mutex_unlock(&chan->lock);
341}
342
343/** Enable device I/O. */
344static errno_t pci_ide_init_io(pci_ide_channel_t *chan)
345{
346 errno_t rc;
347 void *vaddr;
348
349 rc = pio_enable((void *) chan->cmd_physical, sizeof(ata_cmd_t), &vaddr);
350 if (rc != EOK) {
351 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
352 return rc;
353 }
354
355 chan->cmd = vaddr;
356
357 rc = pio_enable((void *) chan->ctl_physical, sizeof(ata_ctl_t), &vaddr);
358 if (rc != EOK) {
359 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
360 return rc;
361 }
362
363 chan->ctl = vaddr;
364
365 rc = pio_enable((void *) chan->cmd_physical, sizeof(ata_cmd_t), &vaddr);
366 if (rc != EOK) {
367 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
368 return rc;
369 }
370
371 chan->cmd = vaddr;
372
373 return EOK;
374}
375
376/** Clean up device I/O. */
377static void pci_ide_fini_io(pci_ide_channel_t *chan)
378{
379 (void) chan;
380 /* XXX TODO */
381}
382
383/** Initialize IRQ. */
384static errno_t pci_ide_init_irq(pci_ide_channel_t *chan)
385{
386 irq_code_t irq_code;
387 irq_pio_range_t *ranges;
388 irq_cmd_t *cmds;
389 uint8_t *bmisx;
390 errno_t rc;
391
392 if (chan->irq < 0)
393 return EOK;
394
395 ranges = malloc(sizeof(pci_ide_irq_ranges));
396 if (ranges == NULL)
397 return ENOMEM;
398
399 cmds = malloc(sizeof(pci_ide_irq_cmds));
400 if (cmds == NULL) {
401 free(cmds);
402 return ENOMEM;
403 }
404
405 /* Bus master IDE status register (primary or secondary) */
406 bmisx = chan->chan_id == 0 ?
407 &chan->ctrl->bmregs->bmisp :
408 &chan->ctrl->bmregs->bmiss;
409
410 memcpy(ranges, &pci_ide_irq_ranges, sizeof(pci_ide_irq_ranges));
411 ranges[0].base = chan->cmd_physical;
412 ranges[1].base = chan->ctrl->bmregs_physical;
413
414 memcpy(cmds, &pci_ide_irq_cmds, sizeof(pci_ide_irq_cmds));
415 cmds[0].addr = bmisx;
416 cmds[3].addr = bmisx;
417 cmds[4].addr = &chan->cmd->status;
418
419 irq_code.rangecount = sizeof(pci_ide_irq_ranges) / sizeof(irq_pio_range_t);
420 irq_code.ranges = ranges;
421 irq_code.cmdcount = sizeof(pci_ide_irq_cmds) / sizeof(irq_cmd_t);
422 irq_code.cmds = cmds;
423
424 ddf_msg(LVL_NOTE, "IRQ %d", chan->irq);
425 rc = register_interrupt_handler(chan->ctrl->dev, chan->irq,
426 pci_ide_irq_handler, (void *)chan, &irq_code, &chan->ihandle);
427 if (rc != EOK) {
428 ddf_msg(LVL_ERROR, "Error registering IRQ.");
429 goto error;
430 }
431
432 ddf_msg(LVL_DEBUG, "Interrupt handler registered");
433 free(ranges);
434 free(cmds);
435 return EOK;
436error:
437 free(ranges);
438 free(cmds);
439 return rc;
440}
441
442/** Clean up IRQ. */
443static void pci_ide_fini_irq(pci_ide_channel_t *chan)
444{
445 errno_t rc;
446 async_sess_t *parent_sess;
447
448 parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
449
450 rc = hw_res_disable_interrupt(parent_sess, chan->irq);
451 if (rc != EOK)
452 ddf_msg(LVL_ERROR, "Error disabling IRQ.");
453
454 (void) unregister_interrupt_handler(chan->ctrl->dev, chan->ihandle);
455}
456
457/** Interrupt handler.
458 *
459 * @param call Call data
460 * @param arg Argument (pci_ide_channel_t *)
461 */
462static void pci_ide_irq_handler(ipc_call_t *call, void *arg)
463{
464 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
465 uint8_t status;
466 async_sess_t *parent_sess;
467
468 status = ipc_get_arg1(call);
469 ata_channel_irq(chan->channel, status);
470
471 parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
472 hw_res_clear_interrupt(parent_sess, chan->irq);
473}
474
475/** Write the data register callback handler.
476 *
477 * @param arg Argument (pci_ide_channel_t *)
478 * @param data Data
479 * @param nwords Number of words to write
480 */
481static void pci_ide_write_data_16(void *arg, uint16_t *data, size_t nwords)
482{
483 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
484 size_t i;
485
486 for (i = 0; i < nwords; i++)
487 pio_write_16(&chan->cmd->data_port, data[i]);
488}
489
490/** Read the data register callback handler.
491 *
492 * @param arg Argument (pci_ide_channel_t *)
493 * @param buf Destination buffer
494 * @param nwords Number of words to read
495 */
496static void pci_ide_read_data_16(void *arg, uint16_t *buf, size_t nwords)
497{
498 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
499 size_t i;
500
501 for (i = 0; i < nwords; i++)
502 buf[i] = pio_read_16(&chan->cmd->data_port);
503}
504
505/** Write command register callback handler.
506 *
507 * @param arg Argument (pci_ide_channel_t *)
508 * @param off Register offset
509 * @param value Value to write to command register
510 */
511static void pci_ide_write_cmd_8(void *arg, uint16_t off, uint8_t value)
512{
513 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
514
515 pio_write_8(((ioport8_t *)chan->cmd) + off, value);
516}
517
518/** Read command register callback handler.
519 *
520 * @param arg Argument (pci_ide_channel_t *)
521 * @param off Register offset
522 * @return value Value read from command register
523 */
524static uint8_t pci_ide_read_cmd_8(void *arg, uint16_t off)
525{
526 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
527
528 return pio_read_8(((ioport8_t *)chan->cmd) + off);
529}
530
531/** Write control register callback handler.
532 *
533 * @param arg Argument (pci_ide_channel_t *)
534 * @param off Register offset
535 * @param value Value to write to control register
536 */
537static void pci_ide_write_ctl_8(void *arg, uint16_t off, uint8_t value)
538{
539 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
540
541 pio_write_8(((ioport8_t *)chan->ctl) + off, value);
542}
543
544/** Read control register callback handler.
545 *
546 * @param arg Argument (pci_ide_channel_t *)
547 * @param off Register offset
548 * @return value Value read from control register
549 */
550static uint8_t pci_ide_read_ctl_8(void *arg, uint16_t off)
551{
552 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
553
554 return pio_read_8(((ioport8_t *)chan->ctl) + off);
555}
556
557/** Enable IRQ callback handler
558 *
559 * @param arg Argument (pci_ide_channel_t *)
560 * @return EOK on success or an error code
561 */
562static errno_t pci_ide_irq_enable(void *arg)
563{
564 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
565 async_sess_t *parent_sess;
566 errno_t rc;
567
568 ddf_msg(LVL_DEBUG, "Enable IRQ %d for channel %u",
569 chan->irq, chan->chan_id);
570
571 parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
572
573 rc = hw_res_enable_interrupt(parent_sess, chan->irq);
574 if (rc != EOK) {
575 ddf_msg(LVL_ERROR, "Error enabling IRQ.");
576 return rc;
577 }
578
579 return EOK;
580}
581
582/** Disable IRQ callback handler
583 *
584 * @param arg Argument (pci_ide_channel_t *)
585 * @return EOK on success or an error code
586 */
587static errno_t pci_ide_irq_disable(void *arg)
588{
589 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
590 async_sess_t *parent_sess;
591 errno_t rc;
592
593 ddf_msg(LVL_DEBUG, "Disable IRQ");
594
595 parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
596
597 rc = hw_res_disable_interrupt(parent_sess, chan->irq);
598 if (rc != EOK) {
599 ddf_msg(LVL_ERROR, "Error disabling IRQ.");
600 return rc;
601 }
602
603 return EOK;
604}
605
606/** Set up DMA channel callback handler
607 *
608 * @param arg Argument (pci_ide_channel_t *)
609 * @param buf Buffer
610 * @param buf_size Buffer size
611 * @param dir DMA transfer direction
612 */
613static void pci_ide_dma_chan_setup(void *arg, void *buf, size_t buf_size,
614 ata_dma_dir_t dir)
615{
616 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
617 uint8_t *bmicx;
618 uint8_t val;
619
620 /* Needed later in teardown */
621 chan->cur_dir = dir;
622 chan->cur_buf = buf;
623 chan->cur_buf_size = buf_size;
624
625 if (dir == ata_dma_write) {
626 assert(buf_size <= chan->dma_buf_size);
627 memcpy(chan->dma_buf, buf, buf_size);
628 }
629
630 /* Primary or secondary channel control register */
631 bmicx = (chan->chan_id == 0) ? &chan->ctrl->bmregs->bmicp :
632 &chan->ctrl->bmregs->bmics;
633
634 /* Set read / write */
635 val = (dir == ata_dma_write) ? bmicx_rwcon : 0;
636 pio_write_8(bmicx, val);
637
638 /* Start bus master DMA engine */
639 val = val | bmicx_ssbm;
640 pio_write_8(bmicx, val);
641}
642
643/** Tear down DMA channel callback handler
644 *
645 * @param arg Argument (pci_ide_channel_t *)
646 */
647static void pci_ide_dma_chan_teardown(void *arg)
648{
649 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
650 uint8_t *bmicx;
651 uint8_t val;
652
653 /* Primary or secondary channel control register */
654 bmicx = (chan->chan_id == 0) ? &chan->ctrl->bmregs->bmicp :
655 &chan->ctrl->bmregs->bmics;
656
657 /* Stop bus master DMA engine clear SSBM but keep RWCON the same */
658 val = (chan->cur_dir == ata_dma_write) ? bmicx_rwcon : 0;
659 pio_write_8(bmicx, val);
660
661 if (chan->cur_dir == ata_dma_read) {
662 assert(chan->cur_buf_size <= chan->dma_buf_size);
663 memcpy(chan->cur_buf, chan->dma_buf, chan->cur_buf_size);
664 }
665}
666
667/** Add ATA device callback handler.
668 *
669 * @param arg Argument (pci_ide_channel_t *)
670 * @param idx Device index
671 * $param charg Connection handler argument
672 * @return EOK on success or an error code
673 */
674static errno_t pci_ide_add_device(void *arg, unsigned idx, void *charg)
675{
676 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
677 return pci_ide_fun_create(chan, idx, charg);
678}
679
680/** Remove ATA device callback handler.
681 *
682 * @param arg Argument (pci_ide_channel_t *)
683 * @param idx Device index
684 * @return EOK on success or an error code
685 */
686static errno_t pci_ide_remove_device(void *arg, unsigned idx)
687{
688 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
689 return pci_ide_fun_remove(chan, idx);
690}
691
692/** Debug message callback handler.
693 *
694 * @param arg Argument (pci_ide_channel_t *)
695 * @param msg Message
696 */
697static void pci_ide_msg_debug(void *arg, char *msg)
698{
699 (void)arg;
700 ddf_msg(LVL_DEBUG, "%s", msg);
701}
702
703/** Notice message callback handler.
704 *
705 * @param arg Argument (pci_ide_channel_t *)
706 * @param msg Message
707 */
708static void pci_ide_msg_note(void *arg, char *msg)
709{
710 (void)arg;
711 ddf_msg(LVL_NOTE, "%s", msg);
712}
713
714/** Warning message callback handler.
715 *
716 * @param arg Argument (pci_ide_channel_t *)
717 * @param msg Message
718 */
719static void pci_ide_msg_warn(void *arg, char *msg)
720{
721 (void)arg;
722 ddf_msg(LVL_WARN, "%s", msg);
723}
724
725/** Error message callback handler.
726 *
727 * @param arg Argument (pci_ide_channel_t *)
728 * @param msg Message
729 */
730static void pci_ide_msg_error(void *arg, char *msg)
731{
732 (void)arg;
733 ddf_msg(LVL_ERROR, "%s", msg);
734}
735
736/**
737 * @}
738 */
Note: See TracBrowser for help on using the repository browser.