⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ata.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
            ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,                                          &byte);        } while (byte & IDE_REGISTER_STATUS_BSY);        if (byte & IDE_REGISTER_STATUS_DRQ)        {            ide_controller_write_data_block(                ctrl_minor,                 MIN(data_bs, areq->cnt) * ATA_SECTOR_SIZE,                areq->breq->bufs, &areq->cbuf,                &areq->pos);            areq->cnt -= MIN(data_bs, areq->cnt);        }            else        {                if (IDE_Controller_Table[ctrl_minor].int_driven == 0)            {                ide_controller_read_register(                    ctrl_minor,                     IDE_REGISTER_ALTERNATE_STATUS_OFFSET,                    &val);                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,                                             &val);                ATA_SEND_EVT(msg, ATA_MSG_ERROR_EVT, ctrl_minor,                              RTEMS_IO_ERROR);            }        }        }    if (IDE_Controller_Table[ctrl_minor].int_driven == 0)    {        do {            ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,                                          &byte);        } while (byte & IDE_REGISTER_STATUS_BSY);                ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);    }    }/* ata_request_done --  *     Extract request from controller queue, execute callback if necessary *     and process next request for the controller. *  * PARAMETERS: *     areq       - ATA request  *     ctrl_minor - controller identifier *     status     - status with which request has been done *     error      - error, if status != RTEMS_SUCCESSFUL * * RETURNS: *     NONE */static inline voidata_request_done(ata_req_t *areq, rtems_device_minor_number ctrl_minor,                 rtems_status_code status, int error){    preemption_key key;    assert(areq);    DISABLE_PREEMPTION(key);    ATA_EXEC_CALLBACK(areq, status, error);    Chain_Extract(&areq->link);    free(areq);    if (!Chain_Is_empty(&ata_ide_ctrls[ctrl_minor].reqs))    {        ENABLE_PREEMPTION(key);        ata_process_request(ctrl_minor);        return;    }    ENABLE_PREEMPTION(key); }/* ata_non_data_request_done --  *     Set up request status and release request's semaphore. *  * PARAMETERS: *     areq       - ATA request  *     ctrl_minor - controller identifier *     status     - status with which request has been done *     error      - error, if status != RTEMS_SUCCESSFUL * * RETURNS: *     NONE */static inline voidata_non_data_request_done(ata_req_t *areq,                           rtems_device_minor_number ctrl_minor,                          rtems_status_code status, int error){    areq->status = status;    areq->error = error;    rtems_semaphore_release(areq->sema);}/* ata_add_to_controller_queue --  *     Add request to the controller's queue. *  * PARAMETERS: *     ctrl_minor - controller identifier *     areq       - ATA request  * * RETURNS: *     NONE */static voidata_add_to_controller_queue(rtems_device_minor_number  ctrl_minor,                             ata_req_t                 *areq){    Chain_Append(&ata_ide_ctrls[ctrl_minor].reqs, &areq->link);    if (Chain_Has_only_one_node(&ata_ide_ctrls[ctrl_minor].reqs))    {        unsigned16      val;        ata_queue_msg_t msg;#ifdef DEBUG        /*          * read IDE_REGISTER_ALTERNATE_STATUS instead IDE_REGISTER_STATUS         * to prevent clearing of pending interrupt         */        ide_controller_read_register(ctrl_minor,                                      IDE_REGISTER_ALTERNATE_STATUS,                                      &val);        if (val & IDE_REGISTER_STATUS_BSY)            return;#endif        ATA_SEND_EVT(msg, ATA_MSG_PROCESS_NEXT_EVT, ctrl_minor, 0);    }    }                            /* ata_interrupt_handler --  *     ATA driver interrrupt handler. If interrrupt happend it mapped it to *     controller (controllerS, if a number of controllers share one int line) *     and generates ATA event(s). *  * PARAMETERS: *     vec - interrupt vector   * * RETURNS: *     NONE */rtems_israta_interrupt_handler(rtems_vector_number vec){    Chain_Node      *the_node = ((Chain_Control *)(&ata_int_vec[vec]))->first;    ata_queue_msg_t  msg;    unsigned16       byte; /* emphasize that only 8 low bits is meaningful */        for ( ; !Chain_Is_tail(&ata_int_vec[vec], the_node) ; )    {        /* if (1) - is temporary hack - currently I don't know how to identify         * controller which asserted interrupt if few controllers share one         * interrupt line         */        if (1)        {            msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor;            ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS,                                          &byte);            ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0);                                     }        the_node = the_node->next;    }   }/* ata_pio_in_protocol --  *     ATA PIO_IN protocol implementation, see specification *  * PARAMETERS: *     ctrl_minor - controller identifier *     areq       - ATA request  * * RETURNS: *     NONE */static inline voidata_pio_in_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq){    unsigned16      bs, val;    unsigned8       dev;    unsigned32      min_val;    ata_queue_msg_t msg;            dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &            IDE_REGISTER_DEVICE_HEAD_DEV;    bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ?           ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1;          min_val = MIN(bs, areq->cnt);        ide_controller_read_data_block(ctrl_minor, min_val * ATA_SECTOR_SIZE,                                    areq->breq->bufs, &areq->cbuf, &areq->pos);                  areq->cnt -= min_val;    if (areq->cnt == 0)    {        ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL, RTEMS_SUCCESSFUL);    }    else if (IDE_Controller_Table[ctrl_minor].int_driven == 0)    {        do {           ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val);        } while (val & IDE_REGISTER_STATUS_BSY);                ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);    }}/* ata_pio_out_protocol --  *     ATA PIO_OUT protocol implementation, see specification *  * PARAMETERS: *     ctrl_minor - controller identifier *     areq       - ATA request  * * RETURNS: *     NONE */static inline voidata_pio_out_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq){    unsigned16      bs, val;    unsigned8       dev;    unsigned32      min_val;    ata_queue_msg_t msg;        dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &            IDE_REGISTER_DEVICE_HEAD_DEV;    bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ?           ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1;          min_val = MIN(bs, areq->cnt);         if (areq->cnt == 0)    {        ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL, RTEMS_SUCCESSFUL);    }    else     {        ide_controller_write_data_block(ctrl_minor, min_val * ATA_SECTOR_SIZE,                                        areq->breq->bufs, &areq->cbuf,                                         &areq->pos);        areq->cnt -= min_val;        if (IDE_Controller_Table[ctrl_minor].int_driven == 0)        {            do {                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,                                              &val);            } while (val & IDE_REGISTER_STATUS_BSY);            ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);        }  }}/* ata_queue_task --  *     Task which manages ATA driver events queue. *  * PARAMETERS: *     arg - ignored * * RETURNS: *     NONE * * NOTES: *     should be non-preemptive  */static rtems_taskata_queue_task(rtems_task_argument arg){    ata_queue_msg_t            msg;    rtems_unsigned32           size;    ata_req_t                 *areq;    rtems_device_minor_number  ctrl_minor;    unsigned16                 val;    unsigned16                 val1;    rtems_status_code          rc;    ISR_Level                  level;    while (1)    {        /* get event which has happend */        rc = rtems_message_queue_receive(ata_queue_id, &msg, &size, RTEMS_WAIT,                                          RTEMS_NO_TIMEOUT);        if (rc != RTEMS_SUCCESSFUL)            rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);                                                     /* get controller on which event has happend */        ctrl_minor = msg.ctrl_minor;                /* get current request to the controller */        _ISR_Disable(level);                areq = (ata_req_t *)(ata_ide_ctrls[ctrl_minor].reqs.first);        _ISR_Enable(level);                switch(msg.type)        {            case ATA_MSG_PROCESS_NEXT_EVT:                /* process next request in the controller queue */                ata_process_request(ctrl_minor);                break;            case ATA_MSG_SUCCESS_EVT:                /*                  * finish processing of current request with successful                  * status and start processing of the next request in the                  * controller queue                 */                ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL,                                  msg.error);                break;                            case ATA_MSG_ERROR_EVT:                /*                  * finish processing of current request with error                  * status and start processing of the next request in the                  * controller queue                 */                ata_request_done(areq, ctrl_minor, RTEMS_UNSATISFIED,                                  msg.error);                break;                            case ATA_MSG_GEN_EVT:                /*                  * continue processing of the current request to the                  * controller according to current request state and                  * ATA protocol                 */                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,                                            &val);                /* process error case */                if (val & IDE_REGISTER_STATUS_ERR)                {                     ide_controller_read_register(ctrl_minor,                                                  IDE_REGISTER_ERROR,                                                  &val);                    if (areq->type == ATA_COMMAND_TYPE_NON_DATA)                        ata_non_data_request_done(areq, ctrl_minor,                                                   RTEMS_UNSATISFIED,                                                   RTEMS_IO_ERROR);                    else                                                     ata_request_done(areq, ctrl_minor, RTEMS_UNSATISFIED,                                          RTEMS_IO_ERROR);                    break;                                                  }                switch(areq->type)                {                    case ATA_COMMAND_TYPE_PIO_IN:                        ata_pio_in_protocol(ctrl_minor, areq);                        break;                                    case ATA_COMMAND_TYPE_PIO_OUT:                        ata_pio_out_protocol(ctrl_minor, areq);                        break;                                    case ATA_COMMAND_TYPE_NON_DATA:                        ide_controller_read_register(ctrl_minor,                                                       IDE_REGISTER_ERROR,                                                      &val1);                        ata_non_data_request_done(areq, ctrl_minor,                                                  RTEMS_SUCCESSFUL,                                                  val1);                        break;                                default:                        printf("ata_queue_task: non-supported command type\n");                        ata_request_done(areq, ctrl_minor,                                         RTEMS_UNSATISFIED,                                         RTEMS_NOT_IMPLEMENTED);                        break;                          }                break;                default:                rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);                break;        }    }}/* ata_ioctl --  *     ATA driver ioctl interface. *  * PARAMETERS: *     device - device identifier *     cmd    - command *     argp   - arguments * * RETURNS: *     depend on 'cmd' */int ata_ioctl(dev_t device, int cmd, void *argp){    rtems_status_code         status;    rtems_device_minor_number rel_minor;        rel_minor = (rtems_filesystem_dev_minor_t(device)) /                ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE;    /*      * in most cases this means that device 'device' is not an registred ATA     * device     */     if (ata_devs[rel_minor].device == ATA_UNDEFINED_VALUE)    {        errno = ENODEV;        return -1;    }        switch (cmd)     {        case BLKIO_REQUEST:            status = ata_io_data_request(device, (blkdev_request *)argp);            break;                case ATAIO_SET_MULTIPLE_MODE:            status = ata_non_data_request(device, cmd, argp);            break;              default:            errno = EBADRQC;            return -1;            break;    }    if (status != RTEMS_SUCCESSFUL)    {        errno = EIO;        return -1;     }    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -