Changeset 646849b3 in mainline for uspace/drv/block/isa-ide/isa-ide.c


Ignore:
Timestamp:
2024-05-17T12:25:26Z (7 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
60744cb
Parents:
59c0f478
git-author:
Jiri Svoboda <jiri@…> (2024-05-16 19:25:07)
git-committer:
Jiri Svoboda <jiri@…> (2024-05-17 12:25:26)
Message:

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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/block/isa-ide/isa-ide.c

    r59c0f478 r646849b3  
    5555#include "main.h"
    5656
    57 static errno_t isa_ide_init_io(isa_ide_ctrl_t *ctrl);
    58 static void isa_ide_fini_io(isa_ide_ctrl_t *ctrl);
    59 static errno_t isa_ide_init_irq(isa_ide_ctrl_t *ctrl);
    60 static void isa_ide_fini_irq(isa_ide_ctrl_t *ctrl);
    61 static void isa_ide_irq_handler(ipc_call_t *call, ddf_dev_t *dev);
     57static errno_t isa_ide_init_io(isa_ide_channel_t *);
     58static void isa_ide_fini_io(isa_ide_channel_t *);
     59static errno_t isa_ide_init_irq(isa_ide_channel_t *);
     60static void isa_ide_fini_irq(isa_ide_channel_t *);
     61static void isa_ide_irq_handler(ipc_call_t *, ddf_dev_t *);
    6262
    6363static void isa_ide_write_data_16(void *, uint16_t *, size_t);
     
    9595};
    9696
    97 /** Initialize ISA IDE controller. */
    98 errno_t isa_ide_ctrl_init(isa_ide_ctrl_t *ctrl, isa_ide_hwres_t *res)
     97/** Initialize ISA IDE channel. */
     98errno_t isa_ide_channel_init(isa_ide_ctrl_t *ctrl, isa_ide_channel_t *chan,
     99    unsigned chan_id, isa_ide_hwres_t *res)
    99100{
    100101        errno_t rc;
     
    104105        ddf_msg(LVL_DEBUG, "isa_ide_ctrl_init()");
    105106
    106         fibril_mutex_initialize(&ctrl->lock);
    107         ctrl->cmd_physical = res->cmd;
    108         ctrl->ctl_physical = res->ctl;
    109         ctrl->irq = res->irq;
    110 
    111         ddf_msg(LVL_NOTE, "I/O address %p/%p", (void *) ctrl->cmd_physical,
    112             (void *) ctrl->ctl_physical);
     107        chan->ctrl = ctrl;
     108        chan->chan_id = chan_id;
     109        fibril_mutex_initialize(&chan->lock);
     110        if (chan_id == 0) {
     111                chan->cmd_physical = res->cmd1;
     112                chan->ctl_physical = res->ctl1;
     113                chan->irq = res->irq1;
     114        } else {
     115                chan->cmd_physical = res->cmd2;
     116                chan->ctl_physical = res->ctl2;
     117                chan->irq = res->irq2;
     118        }
     119
     120        ddf_msg(LVL_NOTE, "I/O address %p/%p", (void *) chan->cmd_physical,
     121            (void *) chan->ctl_physical);
    113122
    114123        ddf_msg(LVL_DEBUG, "Init I/O");
    115         rc = isa_ide_init_io(ctrl);
     124        rc = isa_ide_init_io(chan);
    116125        if (rc != EOK)
    117126                return rc;
    118127
    119128        ddf_msg(LVL_DEBUG, "Init IRQ");
    120         rc = isa_ide_init_irq(ctrl);
     129        rc = isa_ide_init_irq(chan);
    121130        if (rc != EOK) {
    122131                ddf_msg(LVL_NOTE, "init IRQ failed");
     
    128137        ddf_msg(LVL_DEBUG, "isa_ide_ctrl_init(): Initialize IDE channel");
    129138
    130         params.arg = (void *)ctrl;
    131         params.have_irq = (ctrl->irq >= 0) ? true : false;
     139        params.arg = (void *)chan;
     140        params.have_irq = (chan->irq >= 0) ? true : false;
    132141        params.write_data_16 = isa_ide_write_data_16;
    133142        params.read_data_16 = isa_ide_read_data_16;
     
    145154        params.msg_error = isa_ide_msg_error;
    146155
    147         rc = ata_channel_create(&params, &ctrl->channel);
     156        rc = ata_channel_create(&params, &chan->channel);
    148157        if (rc != EOK)
    149158                goto error;
    150159
    151         rc = ata_channel_initialize(ctrl->channel);
     160        rc = ata_channel_initialize(chan->channel);
    152161        if (rc != EOK)
    153162                goto error;
     
    157166error:
    158167        if (irq_inited)
    159                 isa_ide_fini_irq(ctrl);
    160         isa_ide_fini_io(ctrl);
     168                isa_ide_fini_irq(chan);
     169        isa_ide_fini_io(chan);
    161170        return rc;
    162171}
    163172
    164 /** Remove ISA IDE controller. */
    165 errno_t isa_ide_ctrl_remove(isa_ide_ctrl_t *ctrl)
     173/** Finalize ISA IDE channel. */
     174errno_t isa_ide_channel_fini(isa_ide_channel_t *chan)
    166175{
    167176        errno_t rc;
     
    169178        ddf_msg(LVL_DEBUG, ": isa_ide_ctrl_remove()");
    170179
    171         fibril_mutex_lock(&ctrl->lock);
    172 
    173         rc = ata_channel_destroy(ctrl->channel);
    174         if (rc != EOK) {
    175                 fibril_mutex_unlock(&ctrl->lock);
    176                 return rc;
    177         }
    178 
    179         isa_ide_fini_irq(ctrl);
    180         isa_ide_fini_io(ctrl);
    181         fibril_mutex_unlock(&ctrl->lock);
     180        fibril_mutex_lock(&chan->lock);
     181
     182        rc = ata_channel_destroy(chan->channel);
     183        if (rc != EOK) {
     184                fibril_mutex_unlock(&chan->lock);
     185                return rc;
     186        }
     187
     188        isa_ide_fini_irq(chan);
     189        isa_ide_fini_io(chan);
     190        fibril_mutex_unlock(&chan->lock);
    182191
    183192        return EOK;
    184193}
    185194
    186 /** Surprise removal of ISA IDE controller. */
    187 errno_t isa_ide_ctrl_gone(isa_ide_ctrl_t *ctrl)
    188 {
    189         errno_t rc;
    190 
    191         ddf_msg(LVL_DEBUG, "isa_ide_ctrl_gone()");
    192 
    193         fibril_mutex_lock(&ctrl->lock);
    194 
    195         rc = ata_channel_destroy(ctrl->channel);
    196         if (rc != EOK) {
    197                 fibril_mutex_unlock(&ctrl->lock);
    198                 return rc;
    199         }
    200 
    201         isa_ide_fini_io(ctrl);
    202         fibril_mutex_unlock(&ctrl->lock);
    203 
     195/** Enable device I/O. */
     196static errno_t isa_ide_init_io(isa_ide_channel_t *chan)
     197{
     198        errno_t rc;
     199        void *vaddr;
     200
     201        rc = pio_enable((void *) chan->cmd_physical, sizeof(ata_cmd_t), &vaddr);
     202        if (rc != EOK) {
     203                ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
     204                return rc;
     205        }
     206
     207        chan->cmd = vaddr;
     208
     209        rc = pio_enable((void *) chan->ctl_physical, sizeof(ata_ctl_t), &vaddr);
     210        if (rc != EOK) {
     211                ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
     212                return rc;
     213        }
     214
     215        chan->ctl = vaddr;
    204216        return EOK;
    205217}
    206218
    207 /** Enable device I/O. */
    208 static errno_t isa_ide_init_io(isa_ide_ctrl_t *ctrl)
    209 {
    210         errno_t rc;
    211         void *vaddr;
    212 
    213         rc = pio_enable((void *) ctrl->cmd_physical, sizeof(ata_cmd_t), &vaddr);
    214         if (rc != EOK) {
    215                 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
    216                 return rc;
    217         }
    218 
    219         ctrl->cmd = vaddr;
    220 
    221         rc = pio_enable((void *) ctrl->ctl_physical, sizeof(ata_ctl_t), &vaddr);
    222         if (rc != EOK) {
    223                 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
    224                 return rc;
    225         }
    226 
    227         ctrl->ctl = vaddr;
    228         return EOK;
    229 }
    230 
    231219/** Clean up device I/O. */
    232 static void isa_ide_fini_io(isa_ide_ctrl_t *ctrl)
    233 {
    234         (void) ctrl;
     220static void isa_ide_fini_io(isa_ide_channel_t *chan)
     221{
     222        (void) chan;
    235223        /* XXX TODO */
    236224}
    237225
    238226/** Initialize IRQ. */
    239 static errno_t isa_ide_init_irq(isa_ide_ctrl_t *ctrl)
     227static errno_t isa_ide_init_irq(isa_ide_channel_t *chan)
    240228{
    241229        irq_code_t irq_code;
     
    244232        errno_t rc;
    245233
    246         if (ctrl->irq < 0)
     234        if (chan->irq < 0)
    247235                return EOK;
    248236
     
    258246
    259247        memcpy(ranges, &isa_ide_irq_ranges, sizeof(isa_ide_irq_ranges));
    260         ranges[0].base = ctrl->cmd_physical;
     248        ranges[0].base = chan->cmd_physical;
    261249        memcpy(cmds, &isa_ide_irq_cmds, sizeof(isa_ide_irq_cmds));
    262         cmds[0].addr = &ctrl->cmd->status;
     250        cmds[0].addr = &chan->cmd->status;
    263251
    264252        irq_code.rangecount = sizeof(isa_ide_irq_ranges) / sizeof(irq_pio_range_t);
     
    267255        irq_code.cmds = cmds;
    268256
    269         ddf_msg(LVL_NOTE, "IRQ %d", ctrl->irq);
    270         rc = register_interrupt_handler(ctrl->dev, ctrl->irq, isa_ide_irq_handler,
    271             &irq_code, &ctrl->ihandle);
     257        ddf_msg(LVL_NOTE, "IRQ %d", chan->irq);
     258        rc = register_interrupt_handler_arg(chan->ctrl->dev, chan->irq,
     259            isa_ide_irq_handler, (void *)chan, &irq_code, &chan->ihandle);
    272260        if (rc != EOK) {
    273261                ddf_msg(LVL_ERROR, "Error registering IRQ.");
     
    286274
    287275/** Clean up IRQ. */
    288 static void isa_ide_fini_irq(isa_ide_ctrl_t *ctrl)
     276static void isa_ide_fini_irq(isa_ide_channel_t *chan)
    289277{
    290278        errno_t rc;
    291279        async_sess_t *parent_sess;
    292280
    293         parent_sess = ddf_dev_parent_sess_get(ctrl->dev);
    294 
    295         rc = hw_res_disable_interrupt(parent_sess, ctrl->irq);
     281        parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
     282
     283        rc = hw_res_disable_interrupt(parent_sess, chan->irq);
    296284        if (rc != EOK)
    297285                ddf_msg(LVL_ERROR, "Error disabling IRQ.");
    298286
    299         (void) unregister_interrupt_handler(ctrl->dev, ctrl->ihandle);
     287        (void) unregister_interrupt_handler(chan->ctrl->dev, chan->ihandle);
    300288}
    301289
     
    305293 * @param dev Device that caused the interrupt
    306294 */
    307 static void isa_ide_irq_handler(ipc_call_t *call, ddf_dev_t *dev)
    308 {
    309         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)ddf_dev_data_get(dev);
     295static void isa_ide_irq_handler(ipc_call_t *call, ddf_dev_t *xdev)
     296{
     297        isa_ide_channel_t *chan = (isa_ide_channel_t *)(void *)xdev; // XXX
    310298        uint8_t status;
    311299        async_sess_t *parent_sess;
    312300
    313301        status = ipc_get_arg1(call);
    314         ata_channel_irq(ctrl->channel, status);
    315 
    316         parent_sess = ddf_dev_parent_sess_get(dev);
    317         hw_res_clear_interrupt(parent_sess, ctrl->irq);
     302        ata_channel_irq(chan->channel, status);
     303
     304        parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
     305        hw_res_clear_interrupt(parent_sess, chan->irq);
    318306}
    319307
    320308/** Write the data register callback handler.
    321309 *
    322  * @param arg Argument (isa_ide_ctrl_t *)
     310 * @param arg Argument (isa_ide_channel_t *)
    323311 * @param data Data
    324312 * @param nwords Number of words to write
     
    326314static void isa_ide_write_data_16(void *arg, uint16_t *data, size_t nwords)
    327315{
    328         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
     316        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
    329317        size_t i;
    330318
    331319        for (i = 0; i < nwords; i++)
    332                 pio_write_16(&ctrl->cmd->data_port, data[i]);
     320                pio_write_16(&chan->cmd->data_port, data[i]);
    333321}
    334322
    335323/** Read the data register callback handler.
    336324 *
    337  * @param arg Argument (isa_ide_ctrl_t *)
     325 * @param arg Argument (isa_ide_channel_t *)
    338326 * @param buf Destination buffer
    339327 * @param nwords Number of words to read
     
    341329static void isa_ide_read_data_16(void *arg, uint16_t *buf, size_t nwords)
    342330{
    343         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
     331        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
    344332        size_t i;
    345333
    346334        for (i = 0; i < nwords; i++)
    347                 buf[i] = pio_read_16(&ctrl->cmd->data_port);
     335                buf[i] = pio_read_16(&chan->cmd->data_port);
    348336}
    349337
    350338/** Write command register callback handler.
    351339 *
    352  * @param arg Argument (isa_ide_ctrl_t *)
     340 * @param arg Argument (isa_ide_channel_t *)
    353341 * @param off Register offset
    354342 * @param value Value to write to command register
     
    356344static void isa_ide_write_cmd_8(void *arg, uint16_t off, uint8_t value)
    357345{
    358         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
    359 
    360         pio_write_8(((ioport8_t *)ctrl->cmd) + off, value);
     346        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
     347
     348        pio_write_8(((ioport8_t *)chan->cmd) + off, value);
    361349}
    362350
    363351/** Read command register callback handler.
    364352 *
    365  * @param arg Argument (isa_ide_ctrl_t *)
     353 * @param arg Argument (isa_ide_channel_t *)
    366354 * @param off Register offset
    367355 * @return value Value read from command register
     
    369357static uint8_t isa_ide_read_cmd_8(void *arg, uint16_t off)
    370358{
    371         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
    372 
    373         return pio_read_8(((ioport8_t *)ctrl->cmd) + off);
     359        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
     360
     361        return pio_read_8(((ioport8_t *)chan->cmd) + off);
    374362}
    375363
    376364/** Write control register callback handler.
    377365 *
    378  * @param arg Argument (isa_ide_ctrl_t *)
     366 * @param arg Argument (isa_ide_channel_t *)
    379367 * @param off Register offset
    380368 * @param value Value to write to control register
     
    382370static void isa_ide_write_ctl_8(void *arg, uint16_t off, uint8_t value)
    383371{
    384         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
    385 
    386         pio_write_8(((ioport8_t *)ctrl->ctl) + off, value);
     372        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
     373
     374        pio_write_8(((ioport8_t *)chan->ctl) + off, value);
    387375}
    388376
    389377/** Read control register callback handler.
    390378 *
    391  * @param arg Argument (isa_ide_ctrl_t *)
     379 * @param arg Argument (isa_ide_channel_t *)
    392380 * @param off Register offset
    393381 * @return value Value read from control register
     
    395383static uint8_t isa_ide_read_ctl_8(void *arg, uint16_t off)
    396384{
    397         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
    398 
    399         return pio_read_8(((ioport8_t *)ctrl->ctl) + off);
     385        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
     386
     387        return pio_read_8(((ioport8_t *)chan->ctl) + off);
    400388}
    401389
    402390/** Enable IRQ callback handler
    403391 *
    404  * @param arg Argument (isa_ide_ctrl_t *)
     392 * @param arg Argument (isa_ide_channel_t *)
    405393 * @return EOK on success or an error code
    406394 */
    407395static errno_t isa_ide_irq_enable(void *arg)
    408396{
    409         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
     397        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
    410398        async_sess_t *parent_sess;
    411399        errno_t rc;
    412400
    413         ddf_msg(LVL_DEBUG, "Enable IRQ");
    414 
    415         parent_sess = ddf_dev_parent_sess_get(ctrl->dev);
    416 
    417         rc = hw_res_enable_interrupt(parent_sess, ctrl->irq);
     401        ddf_msg(LVL_DEBUG, "Enable IRQ %d for channel %u",
     402            chan->irq, chan->chan_id);
     403
     404        parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
     405
     406        rc = hw_res_enable_interrupt(parent_sess, chan->irq);
    418407        if (rc != EOK) {
    419408                ddf_msg(LVL_ERROR, "Error enabling IRQ.");
    420                 (void) unregister_interrupt_handler(ctrl->dev,
    421                     ctrl->ihandle);
    422409                return rc;
    423410        }
     
    428415/** Disable IRQ callback handler
    429416 *
    430  * @param arg Argument (isa_ide_ctrl_t *)
     417 * @param arg Argument (isa_ide_channel_t *)
    431418 * @return EOK on success or an error code
    432419 */
    433420static errno_t isa_ide_irq_disable(void *arg)
    434421{
    435         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
     422        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
    436423        async_sess_t *parent_sess;
    437424        errno_t rc;
     
    439426        ddf_msg(LVL_DEBUG, "Disable IRQ");
    440427
    441         parent_sess = ddf_dev_parent_sess_get(ctrl->dev);
    442 
    443         rc = hw_res_disable_interrupt(parent_sess, ctrl->irq);
    444         if (rc != EOK) {
    445                 ddf_msg(LVL_ERROR, "Error enabling IRQ.");
    446                 (void) unregister_interrupt_handler(ctrl->dev,
    447                     ctrl->ihandle);
     428        parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
     429
     430        rc = hw_res_disable_interrupt(parent_sess, chan->irq);
     431        if (rc != EOK) {
     432                ddf_msg(LVL_ERROR, "Error disabling IRQ.");
    448433                return rc;
    449434        }
     
    454439/** Add ATA device callback handler.
    455440 *
    456  * @param arg Argument (isa_ide_ctrl_t *)
     441 * @param arg Argument (isa_ide_channel_t *)
    457442 * @param idx Device index
    458443 * $param charg Connection handler argument
     
    461446static errno_t isa_ide_add_device(void *arg, unsigned idx, void *charg)
    462447{
    463         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
    464         return isa_ide_fun_create(ctrl, idx, charg);
     448        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
     449        return isa_ide_fun_create(chan, idx, charg);
    465450}
    466451
    467452/** Remove ATA device callback handler.
    468453 *
    469  * @param arg Argument (isa_ide_ctrl_t *)
     454 * @param arg Argument (isa_ide_channel_t *)
    470455 * @param idx Device index
    471456 * @return EOK on success or an error code
     
    473458static errno_t isa_ide_remove_device(void *arg, unsigned idx)
    474459{
    475         isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
    476         return isa_ide_fun_remove(ctrl, idx);
     460        isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
     461        return isa_ide_fun_remove(chan, idx);
    477462}
    478463
    479464/** Debug message callback handler.
    480465 *
    481  * @param arg Argument (isa_ide_ctrl_t *)
     466 * @param arg Argument (isa_ide_channel_t *)
    482467 * @param msg Message
    483468 */
     
    490475/** Notice message callback handler.
    491476 *
    492  * @param arg Argument (isa_ide_ctrl_t *)
     477 * @param arg Argument (isa_ide_channel_t *)
    493478 * @param msg Message
    494479 */
     
    501486/** Warning message callback handler.
    502487 *
    503  * @param arg Argument (isa_ide_ctrl_t *)
     488 * @param arg Argument (isa_ide_channel_t *)
    504489 * @param msg Message
    505490 */
     
    512497/** Error message callback handler.
    513498 *
    514  * @param arg Argument (isa_ide_ctrl_t *)
     499 * @param arg Argument (isa_ide_channel_t *)
    515500 * @param msg Message
    516501 */
Note: See TracChangeset for help on using the changeset viewer.