📄 ata.c
字号:
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 + -