source: mainline/uspace/drv/block/pci-ide/pci-ide.c@ 01d5049

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

PCI-IDE should correctly handle interrupt sharing

  • Property mode set to 100644
File size: 17.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 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%lx",
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;
189
190 ddf_msg(LVL_DEBUG, "pci_ide_channel_init()");
191
192 chan->ctrl = ctrl;
193 chan->chan_id = chan_id;
194 fibril_mutex_initialize(&chan->lock);
195 if (chan_id == 0) {
196 chan->cmd_physical = res->cmd1;
197 chan->ctl_physical = res->ctl1;
198 chan->irq = res->irq1;
199 } else {
200 chan->cmd_physical = res->cmd2;
201 chan->ctl_physical = res->ctl2;
202 chan->irq = res->irq2;
203 }
204
205 chan->dma_buf_size = 8192;
206
207 ddf_msg(LVL_NOTE, "I/O address %p/%p", (void *) chan->cmd_physical,
208 (void *) chan->ctl_physical);
209
210 ddf_msg(LVL_DEBUG, "Init I/O");
211 rc = pci_ide_init_io(chan);
212 if (rc != EOK)
213 return rc;
214
215 ddf_msg(LVL_DEBUG, "Init IRQ");
216 rc = pci_ide_init_irq(chan);
217 if (rc != EOK) {
218 ddf_msg(LVL_NOTE, "init IRQ failed");
219 goto error;
220 }
221
222 irq_inited = true;
223
224 ddf_msg(LVL_DEBUG, "Allocate PRD table");
225
226 buffer = AS_AREA_ANY;
227 rc = dmamem_map_anonymous(sizeof (pci_ide_prd_t), DMAMEM_4GiB | 0xffff,
228 AS_AREA_WRITE | AS_AREA_READ, 0, &chan->prdt_pa, &buffer);
229 if (rc != EOK) {
230 ddf_msg(LVL_NOTE, "Failed allocating PRD table.");
231 goto error;
232 }
233
234 chan->prdt = (pci_ide_prd_t *)buffer;
235
236 ddf_msg(LVL_DEBUG, "Allocate DMA buffer");
237
238 buffer = AS_AREA_ANY;
239 rc = dmamem_map_anonymous(chan->dma_buf_size, DMAMEM_4GiB | 0xffff,
240 AS_AREA_WRITE | AS_AREA_READ, 0, &chan->dma_buf_pa, &buffer);
241 if (rc != EOK) {
242 ddf_msg(LVL_NOTE, "Failed allocating PRD table.");
243 goto error;
244 }
245
246 chan->dma_buf = buffer;
247
248 /* Populate PRD with information on our single DMA buffer */
249 chan->prdt->pba = host2uint32_t_le(chan->dma_buf_pa);
250 chan->prdt->bcnt = host2uint16_t_le(chan->dma_buf_size);
251 chan->prdt->eot_res = host2uint16_t_le(pci_ide_prd_eot);
252
253 /* Program PRD table pointer register */
254 if (chan_id == 0) {
255 pio_write_32(&chan->ctrl->bmregs->bmidtpp,
256 (uint32_t)chan->prdt_pa);
257 } else {
258 pio_write_32(&chan->ctrl->bmregs->bmidtps,
259 (uint32_t)chan->prdt_pa);
260 }
261
262 ddf_msg(LVL_DEBUG, "pci_ide_channel_init(): Initialize IDE channel");
263
264 params.arg = (void *)chan;
265 params.have_irq = (chan->irq >= 0) ? true : false;
266 params.use_dma = true;
267 params.max_dma_xfer = chan->dma_buf_size;
268 params.write_data_16 = pci_ide_write_data_16;
269 params.read_data_16 = pci_ide_read_data_16;
270 params.write_cmd_8 = pci_ide_write_cmd_8;
271 params.read_cmd_8 = pci_ide_read_cmd_8;
272 params.write_ctl_8 = pci_ide_write_ctl_8;
273 params.read_ctl_8 = pci_ide_read_ctl_8;
274 params.irq_enable = pci_ide_irq_enable;
275 params.irq_disable = pci_ide_irq_disable;
276 params.dma_chan_setup = pci_ide_dma_chan_setup;
277 params.dma_chan_teardown = pci_ide_dma_chan_teardown;
278 params.add_device = pci_ide_add_device;
279 params.remove_device = pci_ide_remove_device;
280 params.msg_debug = pci_ide_msg_debug;
281 params.msg_note = pci_ide_msg_note;
282 params.msg_warn = pci_ide_msg_warn;
283 params.msg_error = pci_ide_msg_error;
284
285 rc = ata_channel_create(&params, &chan->channel);
286 if (rc != EOK)
287 goto error;
288
289 rc = ata_channel_initialize(chan->channel);
290 if (rc != EOK)
291 goto error;
292
293 ddf_msg(LVL_DEBUG, "pci_ide_channel_init: DONE");
294 return EOK;
295error:
296 if (irq_inited)
297 pci_ide_fini_irq(chan);
298 pci_ide_fini_io(chan);
299 return rc;
300}
301
302/** Finalize PCI IDE channel. */
303errno_t pci_ide_channel_fini(pci_ide_channel_t *chan)
304{
305 errno_t rc;
306
307 ddf_msg(LVL_DEBUG, ": pci_ide_channel_fini()");
308
309 fibril_mutex_lock(&chan->lock);
310
311 rc = ata_channel_destroy(chan->channel);
312 if (rc != EOK) {
313 fibril_mutex_unlock(&chan->lock);
314 return rc;
315 }
316
317 pci_ide_fini_irq(chan);
318 pci_ide_fini_io(chan);
319 fibril_mutex_unlock(&chan->lock);
320
321 return EOK;
322}
323
324/** Enable device I/O. */
325static errno_t pci_ide_init_io(pci_ide_channel_t *chan)
326{
327 errno_t rc;
328 void *vaddr;
329
330 rc = pio_enable((void *) chan->cmd_physical, sizeof(ata_cmd_t), &vaddr);
331 if (rc != EOK) {
332 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
333 return rc;
334 }
335
336 chan->cmd = vaddr;
337
338 rc = pio_enable((void *) chan->ctl_physical, sizeof(ata_ctl_t), &vaddr);
339 if (rc != EOK) {
340 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
341 return rc;
342 }
343
344 chan->ctl = vaddr;
345
346 rc = pio_enable((void *) chan->cmd_physical, sizeof(ata_cmd_t), &vaddr);
347 if (rc != EOK) {
348 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
349 return rc;
350 }
351
352 chan->cmd = vaddr;
353
354 return EOK;
355}
356
357/** Clean up device I/O. */
358static void pci_ide_fini_io(pci_ide_channel_t *chan)
359{
360 (void) chan;
361 /* XXX TODO */
362}
363
364/** Initialize IRQ. */
365static errno_t pci_ide_init_irq(pci_ide_channel_t *chan)
366{
367 irq_code_t irq_code;
368 irq_pio_range_t *ranges;
369 irq_cmd_t *cmds;
370 uint8_t *bmisx;
371 errno_t rc;
372
373 if (chan->irq < 0)
374 return EOK;
375
376 ranges = malloc(sizeof(pci_ide_irq_ranges));
377 if (ranges == NULL)
378 return ENOMEM;
379
380 cmds = malloc(sizeof(pci_ide_irq_cmds));
381 if (cmds == NULL) {
382 free(cmds);
383 return ENOMEM;
384 }
385
386 /* Bus master IDE status register (primary or secondary) */
387 bmisx = chan->chan_id == 0 ?
388 &chan->ctrl->bmregs->bmisp :
389 &chan->ctrl->bmregs->bmiss;
390
391 memcpy(ranges, &pci_ide_irq_ranges, sizeof(pci_ide_irq_ranges));
392 ranges[0].base = chan->cmd_physical;
393 ranges[1].base = chan->ctrl->bmregs_physical;
394
395 memcpy(cmds, &pci_ide_irq_cmds, sizeof(pci_ide_irq_cmds));
396 cmds[0].addr = bmisx;
397 cmds[3].addr = bmisx;
398 cmds[4].addr = &chan->cmd->status;
399
400 irq_code.rangecount = sizeof(pci_ide_irq_ranges) / sizeof(irq_pio_range_t);
401 irq_code.ranges = ranges;
402 irq_code.cmdcount = sizeof(pci_ide_irq_cmds) / sizeof(irq_cmd_t);
403 irq_code.cmds = cmds;
404
405 ddf_msg(LVL_NOTE, "IRQ %d", chan->irq);
406 rc = register_interrupt_handler(chan->ctrl->dev, chan->irq,
407 pci_ide_irq_handler, (void *)chan, &irq_code, &chan->ihandle);
408 if (rc != EOK) {
409 ddf_msg(LVL_ERROR, "Error registering IRQ.");
410 goto error;
411 }
412
413 ddf_msg(LVL_DEBUG, "Interrupt handler registered");
414 free(ranges);
415 free(cmds);
416 return EOK;
417error:
418 free(ranges);
419 free(cmds);
420 return rc;
421}
422
423/** Clean up IRQ. */
424static void pci_ide_fini_irq(pci_ide_channel_t *chan)
425{
426 errno_t rc;
427 async_sess_t *parent_sess;
428
429 parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
430
431 rc = hw_res_disable_interrupt(parent_sess, chan->irq);
432 if (rc != EOK)
433 ddf_msg(LVL_ERROR, "Error disabling IRQ.");
434
435 (void) unregister_interrupt_handler(chan->ctrl->dev, chan->ihandle);
436}
437
438/** Interrupt handler.
439 *
440 * @param call Call data
441 * @param arg Argument (pci_ide_channel_t *)
442 */
443static void pci_ide_irq_handler(ipc_call_t *call, void *arg)
444{
445 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
446 uint8_t status;
447 async_sess_t *parent_sess;
448
449 status = ipc_get_arg1(call);
450 ata_channel_irq(chan->channel, status);
451
452 parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
453 hw_res_clear_interrupt(parent_sess, chan->irq);
454}
455
456/** Write the data register callback handler.
457 *
458 * @param arg Argument (pci_ide_channel_t *)
459 * @param data Data
460 * @param nwords Number of words to write
461 */
462static void pci_ide_write_data_16(void *arg, uint16_t *data, size_t nwords)
463{
464 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
465 size_t i;
466
467 for (i = 0; i < nwords; i++)
468 pio_write_16(&chan->cmd->data_port, data[i]);
469}
470
471/** Read the data register callback handler.
472 *
473 * @param arg Argument (pci_ide_channel_t *)
474 * @param buf Destination buffer
475 * @param nwords Number of words to read
476 */
477static void pci_ide_read_data_16(void *arg, uint16_t *buf, size_t nwords)
478{
479 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
480 size_t i;
481
482 for (i = 0; i < nwords; i++)
483 buf[i] = pio_read_16(&chan->cmd->data_port);
484}
485
486/** Write command register callback handler.
487 *
488 * @param arg Argument (pci_ide_channel_t *)
489 * @param off Register offset
490 * @param value Value to write to command register
491 */
492static void pci_ide_write_cmd_8(void *arg, uint16_t off, uint8_t value)
493{
494 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
495
496 pio_write_8(((ioport8_t *)chan->cmd) + off, value);
497}
498
499/** Read command register callback handler.
500 *
501 * @param arg Argument (pci_ide_channel_t *)
502 * @param off Register offset
503 * @return value Value read from command register
504 */
505static uint8_t pci_ide_read_cmd_8(void *arg, uint16_t off)
506{
507 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
508
509 return pio_read_8(((ioport8_t *)chan->cmd) + off);
510}
511
512/** Write control register callback handler.
513 *
514 * @param arg Argument (pci_ide_channel_t *)
515 * @param off Register offset
516 * @param value Value to write to control register
517 */
518static void pci_ide_write_ctl_8(void *arg, uint16_t off, uint8_t value)
519{
520 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
521
522 pio_write_8(((ioport8_t *)chan->ctl) + off, value);
523}
524
525/** Read control register callback handler.
526 *
527 * @param arg Argument (pci_ide_channel_t *)
528 * @param off Register offset
529 * @return value Value read from control register
530 */
531static uint8_t pci_ide_read_ctl_8(void *arg, uint16_t off)
532{
533 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
534
535 return pio_read_8(((ioport8_t *)chan->ctl) + off);
536}
537
538/** Enable IRQ callback handler
539 *
540 * @param arg Argument (pci_ide_channel_t *)
541 * @return EOK on success or an error code
542 */
543static errno_t pci_ide_irq_enable(void *arg)
544{
545 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
546 async_sess_t *parent_sess;
547 errno_t rc;
548
549 ddf_msg(LVL_DEBUG, "Enable IRQ %d for channel %u",
550 chan->irq, chan->chan_id);
551
552 parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
553
554 rc = hw_res_enable_interrupt(parent_sess, chan->irq);
555 if (rc != EOK) {
556 ddf_msg(LVL_ERROR, "Error enabling IRQ.");
557 return rc;
558 }
559
560 return EOK;
561}
562
563/** Disable IRQ callback handler
564 *
565 * @param arg Argument (pci_ide_channel_t *)
566 * @return EOK on success or an error code
567 */
568static errno_t pci_ide_irq_disable(void *arg)
569{
570 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
571 async_sess_t *parent_sess;
572 errno_t rc;
573
574 ddf_msg(LVL_DEBUG, "Disable IRQ");
575
576 parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
577
578 rc = hw_res_disable_interrupt(parent_sess, chan->irq);
579 if (rc != EOK) {
580 ddf_msg(LVL_ERROR, "Error disabling IRQ.");
581 return rc;
582 }
583
584 return EOK;
585}
586
587/** Set up DMA channel callback handler
588 *
589 * @param arg Argument (pci_ide_channel_t *)
590 * @param buf Buffer
591 * @param buf_size Buffer size
592 * @param dir DMA transfer direction
593 */
594static void pci_ide_dma_chan_setup(void *arg, void *buf, size_t buf_size,
595 ata_dma_dir_t dir)
596{
597 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
598 uint8_t *bmicx;
599 uint8_t val;
600
601 /* Needed later in teardown */
602 chan->cur_dir = dir;
603 chan->cur_buf = buf;
604 chan->cur_buf_size = buf_size;
605
606 if (dir == ata_dma_write) {
607 assert(buf_size < chan->dma_buf_size);
608 memcpy(chan->dma_buf, buf, buf_size);
609 }
610
611 /* Primary or secondary channel control register */
612 bmicx = (chan->chan_id == 0) ? &chan->ctrl->bmregs->bmicp :
613 &chan->ctrl->bmregs->bmics;
614
615 /* Set read / write */
616 val = (dir == ata_dma_write) ? bmicx_rwcon : 0;
617 pio_write_8(bmicx, val);
618
619 /* Start bus master DMA engine */
620 val = val | bmicx_ssbm;
621 pio_write_8(bmicx, val);
622}
623
624/** Tear down DMA channel callback handler
625 *
626 * @param arg Argument (pci_ide_channel_t *)
627 */
628static void pci_ide_dma_chan_teardown(void *arg)
629{
630 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
631 uint8_t *bmicx;
632 uint8_t val;
633
634 /* Primary or secondary channel control register */
635 bmicx = (chan->chan_id == 0) ? &chan->ctrl->bmregs->bmicp :
636 &chan->ctrl->bmregs->bmics;
637
638 /* Stop bus master DMA engine clear SSBM but keep RWCON the same */
639 val = (chan->cur_dir == ata_dma_write) ? bmicx_rwcon : 0;
640 pio_write_8(bmicx, val);
641
642 if (chan->cur_dir == ata_dma_read) {
643 assert(chan->cur_buf_size < chan->dma_buf_size);
644 memcpy(chan->cur_buf, chan->dma_buf, chan->cur_buf_size);
645 }
646}
647
648/** Add ATA device callback handler.
649 *
650 * @param arg Argument (pci_ide_channel_t *)
651 * @param idx Device index
652 * $param charg Connection handler argument
653 * @return EOK on success or an error code
654 */
655static errno_t pci_ide_add_device(void *arg, unsigned idx, void *charg)
656{
657 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
658 return pci_ide_fun_create(chan, idx, charg);
659}
660
661/** Remove ATA device callback handler.
662 *
663 * @param arg Argument (pci_ide_channel_t *)
664 * @param idx Device index
665 * @return EOK on success or an error code
666 */
667static errno_t pci_ide_remove_device(void *arg, unsigned idx)
668{
669 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg;
670 return pci_ide_fun_remove(chan, idx);
671}
672
673/** Debug message callback handler.
674 *
675 * @param arg Argument (pci_ide_channel_t *)
676 * @param msg Message
677 */
678static void pci_ide_msg_debug(void *arg, char *msg)
679{
680 (void)arg;
681 ddf_msg(LVL_DEBUG, "%s", msg);
682}
683
684/** Notice message callback handler.
685 *
686 * @param arg Argument (pci_ide_channel_t *)
687 * @param msg Message
688 */
689static void pci_ide_msg_note(void *arg, char *msg)
690{
691 (void)arg;
692 ddf_msg(LVL_NOTE, "%s", msg);
693}
694
695/** Warning message callback handler.
696 *
697 * @param arg Argument (pci_ide_channel_t *)
698 * @param msg Message
699 */
700static void pci_ide_msg_warn(void *arg, char *msg)
701{
702 (void)arg;
703 ddf_msg(LVL_WARN, "%s", msg);
704}
705
706/** Error message callback handler.
707 *
708 * @param arg Argument (pci_ide_channel_t *)
709 * @param msg Message
710 */
711static void pci_ide_msg_error(void *arg, char *msg)
712{
713 (void)arg;
714 ddf_msg(LVL_ERROR, "%s", msg);
715}
716
717/**
718 * @}
719 */
Note: See TracBrowser for help on using the repository browser.