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

📄 ata.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * ata_initialize -- *     Initializes all ATA devices found on initialized IDE controllers. *  * PARAMETERS: *     major - device major number *     minor - device minor number *     args   - arguments * * RETURNS: *     RTEMS_SUCCESSFUL on success, or error code if *     error occured  */rtems_device_driver ata_initialize(rtems_device_major_number major,                rtems_device_minor_number minor_arg,                void *args){    unsigned32         ctrl_minor;    rtems_status_code  status;    ata_req_t          areq;    blkdev_request1    breq;         unsigned8          i, dev = 0;    unsigned16        *buffer;    unsigned16         ec;    char               name[ATA_MAX_NAME_LENGTH];    dev_t              device;    ata_int_st_t      *int_st;    rtems_isr_entry    old_isr;    if (ata_initialized)        return RTEMS_SUCCESSFUL;                /* initialization of disk devices library */    status = rtems_disk_io_initialize();    if (status != RTEMS_SUCCESSFUL)        return status;            /* create queue for asynchronous requests handling */    status = rtems_message_queue_create(                 rtems_build_name('A', 'T', 'A', 'Q'),                 ATA_DRIVER_MESSAGE_QUEUE_SIZE,                 sizeof(ata_queue_msg_t),                 RTEMS_FIFO | RTEMS_LOCAL,                 &ata_queue_id);    if (status != RTEMS_SUCCESSFUL)    {        rtems_disk_io_done();        return status;    }        /*      * create ATA driver task, see comments for task implementation for      * details      */    status = rtems_task_create(                 rtems_build_name ('A', 'T', 'A', 'T'),                 ATA_DRIVER_TASK_PRIORITY,                 ATA_DRIVER_TASK_STACK_SIZE,                 RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_ASR |                  RTEMS_INTERRUPT_LEVEL(0),                 RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,                 &ata_task_id);    if (status != RTEMS_SUCCESSFUL)    {        rtems_message_queue_delete(ata_queue_id);        rtems_disk_io_done();        return status;    }            /*      * start ATA driver task. Actually the task will not start immediately -      * it will start only after multitasking support will be started     */     status = rtems_task_start(ata_task_id, ata_queue_task, 0);     if (status != RTEMS_SUCCESSFUL)    {        rtems_task_delete(ata_task_id);        rtems_message_queue_delete(ata_queue_id);        rtems_disk_io_done();        return status;    }            buffer = (unsigned16 *)malloc(ATA_SECTOR_SIZE);    if (buffer == NULL)    {        rtems_task_delete(ata_task_id);        rtems_message_queue_delete(ata_queue_id);        rtems_disk_io_done();        return RTEMS_NO_MEMORY;    }                ata_devs_number = 0;    for (i = 0; i < (2 * IDE_CTRL_MAX_MINOR_NUMBER); i++)        ata_devs[i].device = ATA_UNDEFINED_VALUE;    /* prepare ATA driver for handling  interrupt driven devices */    for (i = 0; i < ATA_MAX_RTEMS_INT_VEC_NUMBER; i++)        Chain_Initialize_empty(&ata_int_vec[i]);    /*      * during ATA driver initialization EXECUTE DEVICE DIAGNOSTIC and      * IDENTIFY DEVICE ATA command should be issued; for these purposes ATA      * requests should be formed; ATA requests contain block device request,      * so form block device request first     */    memset(&breq, 0, sizeof(blkdev_request1));    breq.req.req_done = NULL;    breq.req.done_arg = &breq;    breq.req.bufnum = 1;    breq.req.count = 1;    breq.req.bufs[0].length = ATA_SECTOR_SIZE;    breq.req.bufs[0].buffer = buffer;    /*      * for each presented IDE controller execute EXECUTE DEVICE DIAGNOSTIC     * ATA command; for each found device execute IDENTIFY DEVICE ATA      * command      */    for (ctrl_minor = 0; ctrl_minor < IDE_Controller_Count; ctrl_minor++)    if (IDE_Controller_Table[ctrl_minor].status == IDE_CTRL_INITIALIZED)    {        Chain_Initialize_empty(&ata_ide_ctrls[ctrl_minor].reqs);                if (IDE_Controller_Table[ctrl_minor].int_driven == TRUE)        {            int_st = malloc(sizeof(ata_int_st_t));            if (int_st == NULL)            {                free(buffer);                rtems_task_delete(ata_task_id);                rtems_message_queue_delete(ata_queue_id);                rtems_disk_io_done();                return RTEMS_NO_MEMORY;            }                   int_st->ctrl_minor = ctrl_minor;            status = rtems_interrupt_catch(                         ata_interrupt_handler,                          IDE_Controller_Table[ctrl_minor].int_vec,                          &old_isr);            if (status != RTEMS_SUCCESSFUL)            {                free(int_st);                free(buffer);                rtems_task_delete(ata_task_id);                rtems_message_queue_delete(ata_queue_id);                rtems_disk_io_done();                return status;            }             Chain_Append(                &ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec],                &int_st->link);            /* disable interrupts */            ide_controller_write_register(ctrl_minor,                                           IDE_REGISTER_DEVICE_CONTROL_OFFSET,                                           IDE_REGISTER_DEVICE_CONTROL_nIEN);        }        /*         * Issue EXECUTE DEVICE DIAGNOSTIC ATA command for explore is         * there any ATA device on the controller.         */        memset(&areq, 0, sizeof(ata_req_t));        areq.type = ATA_COMMAND_TYPE_NON_DATA;        areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);        areq.regs.regs[IDE_REGISTER_COMMAND] =                                   ATA_COMMAND_EXECUTE_DEVICE_DIAGNOSTIC;        areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR);        areq.breq = (blkdev_request *)&breq;        /*          * Process the request. Special processing of requests on          * initialization phase is needed because at this moment there          * is no multitasking enviroment         */        ata_process_request_on_init_phase(ctrl_minor, &areq);        /*         * check status of I/O operation         */        if (breq.req.status != RTEMS_SUCCESSFUL)            continue;              /* disassemble returned diagnostic codes */         if (breq.req.error == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT)        {            ATA_DEV_INFO(ctrl_minor, 0).present = 1;            ATA_DEV_INFO(ctrl_minor,1).present = 1;         }        else if (breq.req.error == ATA_DEV0_PASSED_DEV1_FAILED)        {            ATA_DEV_INFO(ctrl_minor,0).present = 1;            ATA_DEV_INFO(ctrl_minor,1).present = 0;        }        else if (breq.req.error < ATA_DEV1_PASSED_DEV0_FAILED)        {            ATA_DEV_INFO(ctrl_minor,0).present = 0;            ATA_DEV_INFO(ctrl_minor,1).present = 1;        }        else        {            ATA_DEV_INFO(ctrl_minor, 0).present = 0;            ATA_DEV_INFO(ctrl_minor, 1).present = 0;        }        /* refine the returned codes */        if (ATA_DEV_INFO(ctrl_minor, 1).present != 0)        {            ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &ec);            if (ec & ATA_DEV1_PASSED_DEV0_FAILED)                ATA_DEV_INFO(ctrl_minor, 1).present = 1;            else                ATA_DEV_INFO(ctrl_minor, 1).present = 0;        }        /* for each found ATA device obtain it configuration */        for (dev = 0; dev < 2; dev++)        if (ATA_DEV_INFO(ctrl_minor, dev).present)        {            /*             * Issue DEVICE IDENTIFY ATA command and get device              * configuration                        */            memset(&areq, 0, sizeof(ata_req_t));            areq.type = ATA_COMMAND_TYPE_PIO_IN;            areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);            areq.regs.regs[IDE_REGISTER_COMMAND] =                                               ATA_COMMAND_IDENTIFY_DEVICE;            areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS);            areq.breq = (blkdev_request *)&breq;                        areq.cnt = breq.req.count;            areq.regs.regs[IDE_REGISTER_DEVICE_HEAD] |=                                    (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS);            /*              * Process the request. Special processing of requests on              * initialization phase is needed because at this moment there              * is no multitasking enviroment             */            ata_process_request_on_init_phase(ctrl_minor, &areq);            /* check status of I/O operation */            if (breq.req.status != RTEMS_SUCCESSFUL)                continue;            /*             * Parse returned device configuration and fill in ATA internal              * device info structure             */            ATA_DEV_INFO(ctrl_minor, dev).cylinders =                 CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_CLNDS]);            ATA_DEV_INFO(ctrl_minor, dev).heads =                 CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_HEADS]);            ATA_DEV_INFO(ctrl_minor, dev).sectors =                 CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_SECS]);            ATA_DEV_INFO(ctrl_minor, dev).lba_sectors =                 (CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS0]) << 16) +                  CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS1]);            ATA_DEV_INFO(ctrl_minor, dev).lba_avaible =                 (CF_LE_W(buffer[ATA_IDENT_WORD_CAPABILITIES]) >> 9) & 0x1;            ATA_DEV_INFO(ctrl_minor, dev).max_multiple =                 (unsigned8) (CF_LE_W(buffer[ATA_IDENT_WORD_RW_MULT]));            ATA_DEV_INFO(ctrl_minor, dev).current_multiple =                 (CF_LE_W(buffer[ATA_IDENT_WORD_MULT_SECS]) & 0x100) ?                 (unsigned8)(CF_LE_W(buffer[ATA_IDENT_WORD_MULT_SECS])) :                 0;            if ((CF_LE_W(buffer[ATA_IDENT_WORD_FIELD_VALIDITY]) &                  ATA_IDENT_BIT_VALID) == 0) {	      /* no "supported modes" info -> use default */	      ATA_DEV_INFO(ctrl_minor, dev).mode_active = ATA_MODES_PIO3;	    }	    else {	      ATA_DEV_INFO(ctrl_minor, dev).modes_avaible =		((CF_LE_W(buffer[64]) & 0x1) ? ATA_MODES_PIO3 : 0) |		((CF_LE_W(buffer[64]) & 0x2) ? ATA_MODES_PIO4 : 0) |		((CF_LE_W(buffer[63]) & 0x1) ? ATA_MODES_DMA0 : 0) |		((CF_LE_W(buffer[63]) & 0x2) ? 		 ATA_MODES_DMA0 | ATA_MODES_DMA1 : 0) |		((CF_LE_W(buffer[63]) & 0x4) ? 		 ATA_MODES_DMA0 | ATA_MODES_DMA1 | ATA_MODES_DMA2 : 0);	      if (ATA_DEV_INFO(ctrl_minor, dev).modes_avaible == 0)                continue;	      /* 	       * choose most appropriate ATA device data I/O speed supported	       * by the controller	       */	      status = ide_controller_config_io_speed(                ctrl_minor,                 ATA_DEV_INFO(ctrl_minor, dev).modes_avaible);	      if (status != RTEMS_SUCCESSFUL)                continue;	    }                  /*             * Ok, let register new ATA device in the system             */            ata_devs[ata_devs_number].ctrl_minor = ctrl_minor;            ata_devs[ata_devs_number].device = dev;            /* The space leaves a hole for the character. */            strcpy(name, "/dev/hd ");            name[7] = 'a' + 2 * ctrl_minor + dev;            device = rtems_filesystem_make_dev_t(                         major,                          (ata_devs_number *                           ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE));            status = rtems_disk_create_phys(device, ATA_SECTOR_SIZE,                 ATA_DEV_INFO(ctrl_minor, dev).lba_avaible ?                 ATA_DEV_INFO(ctrl_minor, dev).lba_sectors :                 (ATA_DEV_INFO(ctrl_minor, dev).heads *                 ATA_DEV_INFO(ctrl_minor, dev).cylinders *                 ATA_DEV_INFO(ctrl_minor, dev).sectors),                (block_device_ioctl) ata_ioctl, name);            if (status != RTEMS_SUCCESSFUL)            {                ata_devs[ata_devs_number].device = ATA_UNDEFINED_VALUE;                continue;            }                   ata_devs_number++;        }        if (IDE_Controller_Table[ctrl_minor].int_driven == TRUE)        {                ide_controller_write_register(ctrl_minor,                                           IDE_REGISTER_DEVICE_CONTROL_OFFSET,                                           0x00);        }    }    free(buffer);    ata_initialized = TRUE;    return RTEMS_SUCCESSFUL;}/* ata_process_request_on_init_phase --  *     Process the ATA request during system initialization. Request  *     processing is syncronous and doesn't use multiprocessing enviroment. *  * PARAMETERS: *     ctrl_minor - controller identifier *     areq       - ATA request * * RETURNS: *     NONE  */static voidata_process_request_on_init_phase(rtems_device_minor_number  ctrl_minor,                                  ata_req_t                 *areq){    unsigned16         byte;/* emphasize that only 8 low bits is meaningful */    unsigned8          i, dev;    unsigned16         val, val1;    unsigned16         data_bs; /* the number of 512 bytes sectors into one                                  * data block                                  */    assert(areq);        dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &            IDE_REGISTER_DEVICE_HEAD_DEV;    data_bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ?                ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1;              ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD,                                   areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]);        do {        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);    } while ((byte & IDE_REGISTER_STATUS_BSY) ||              (!(byte & IDE_REGISTER_STATUS_DRDY)));    for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++)    {        unsigned32 reg = (1 << i);        if (areq->regs.to_write & reg)            ide_controller_write_register(ctrl_minor, i,                                           areq->regs.regs[i]);    }    do {        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);    } while (byte & IDE_REGISTER_STATUS_BSY);    ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val);    ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &val1);    if (val & IDE_REGISTER_STATUS_ERR)    {        areq->breq->status = RTEMS_UNSATISFIED;        areq->breq->error = RTEMS_IO_ERROR;        return;    }     switch(areq->type)    {        case ATA_COMMAND_TYPE_PIO_IN:            ide_controller_read_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);            if (areq->cnt == 0)            {                areq->breq->status = RTEMS_SUCCESSFUL;            }            else             {                /*                  * this shouldn't happend on the initialization                  * phase!                  */                rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);             }            break;                        case ATA_COMMAND_TYPE_NON_DATA:            areq->breq->status = RTEMS_SUCCESSFUL;            areq->breq->error = val1;            break;                    default:            printf("ata_queue_task: non-supported command type\n");            areq->breq->status = RTEMS_UNSATISFIED;            areq->breq->error = RTEMS_NOT_IMPLEMENTED;            break;              }}

⌨️ 快捷键说明

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