File indexing completed on 2025-05-11 08:24:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <errno.h>
0017 #include <rtems/chain.h>
0018 #include <assert.h>
0019 #include <string.h> /* for "memset" declaration */
0020
0021 #include <rtems/blkdev.h>
0022 #include <libchip/ide_ctrl_io.h>
0023 #include <libchip/ide_ctrl_cfg.h>
0024 #include <libchip/ata_internal.h>
0025 #include <libchip/ata.h>
0026
0027 #define ATA_DEBUG 0
0028
0029 #if ATA_DEBUG
0030 #include <stdio.h>
0031 bool ata_trace;
0032 #define ata_printf if (ata_trace) printf
0033 #endif
0034
0035 #if CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE
0036 #include <rtems/irq.h>
0037 #define ATA_IRQ_CHAIN_MAX_CNT 4
0038 typedef struct {
0039 rtems_irq_number name;
0040 rtems_chain_control irq_chain;
0041 } ata_irq_chain_t;
0042
0043 ata_irq_chain_t ata_irq_chain[ATA_IRQ_CHAIN_MAX_CNT];
0044 int ata_irq_chain_cnt = 0;
0045 #endif
0046
0047 static rtems_id ata_lock;
0048 static void
0049 rtems_ata_lock (void)
0050 {
0051 rtems_status_code sc = rtems_semaphore_obtain (ata_lock,
0052 RTEMS_WAIT,
0053 RTEMS_NO_TIMEOUT);
0054 if (sc != RTEMS_SUCCESSFUL)
0055 rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
0056 }
0057
0058 static void
0059 rtems_ata_unlock (void)
0060 {
0061 rtems_status_code sc = rtems_semaphore_release (ata_lock);
0062 if (sc != RTEMS_SUCCESSFUL)
0063 rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
0064 }
0065
0066 #define RTEMS_ATA_LOCK_ATTRIBS \
0067 (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
0068 RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
0069
0070
0071 #undef ATA_DEV_IS_FLASH_DISK
0072
0073
0074 static ata_ide_ctrl_t ata_ide_ctrls[IDE_CTRL_MAX_MINOR_NUMBER];
0075
0076
0077
0078
0079
0080 static ata_ide_dev_t ata_devs[2 * IDE_CTRL_MAX_MINOR_NUMBER];
0081 static int ata_devs_number;
0082
0083
0084 static bool ata_initialized = false;
0085
0086
0087
0088 static rtems_id ata_task_id;
0089 static rtems_id ata_queue_id;
0090
0091 #if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE
0092
0093 static rtems_chain_control ata_int_vec[ATA_MAX_RTEMS_INT_VEC_NUMBER + 1];
0094 #endif
0095
0096 static void
0097 ata_process_request(rtems_device_minor_number ctrl_minor);
0098
0099 static void
0100 ata_add_to_controller_queue(rtems_device_minor_number ctrl_minor,
0101 ata_req_t *areq);
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 static rtems_status_code
0121 ata_io_data_request(ata_ide_dev_t *ata_dev, rtems_blkdev_request *req)
0122 {
0123 ata_req_t *areq;
0124 rtems_device_minor_number ctrl_minor;
0125 uint8_t dev;
0126
0127
0128 ctrl_minor = ata_dev->ctrl_minor;
0129
0130
0131 dev = ata_dev->device;
0132
0133 areq = malloc(sizeof(ata_req_t));
0134 if (areq == NULL)
0135 {
0136 rtems_blkdev_request_done(req, RTEMS_NO_MEMORY);
0137 return RTEMS_SUCCESSFUL;
0138 }
0139
0140 areq->breq = req;
0141 areq->cnt = req->bufnum;
0142 areq->cbuf = 0;
0143 areq->pos = 0;
0144
0145
0146 areq->regs.to_write = ATA_REGISTERS_POSITION;
0147 areq->regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS);
0148
0149
0150 areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] =
0151 (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS);
0152
0153
0154 if (ATA_DEV_INFO(ctrl_minor, dev).mode_active & ATA_MODES_DMA)
0155 {
0156
0157 areq->type = ATA_COMMAND_TYPE_DMA;
0158 if (req->req == RTEMS_BLKDEV_REQ_READ)
0159 areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_READ_DMA;
0160 else
0161 areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_WRITE_DMA;
0162 }
0163 else
0164 {
0165 if (req->req == RTEMS_BLKDEV_REQ_READ)
0166 {
0167 areq->type = ATA_COMMAND_TYPE_PIO_IN;
0168 areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_READ_SECTORS;
0169 #if ATA_DEBUG
0170 ata_printf("ata_io_data_request: type: READ: %lu, %lu cmd:%02x\n",
0171 req->bufs[0].block, req->bufnum,
0172 areq->regs.regs[IDE_REGISTER_COMMAND]);
0173 #endif
0174 }
0175 else
0176 {
0177 areq->type = ATA_COMMAND_TYPE_PIO_OUT;
0178 areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_WRITE_SECTORS;
0179 #if ATA_DEBUG
0180 ata_printf("ata_io_data_request: type: WRITE: %lu, %lu cmd:%02x\n",
0181 req->bufs[0].block, req->bufnum,
0182 areq->regs.regs[IDE_REGISTER_COMMAND]);
0183 #endif
0184 }
0185 }
0186
0187
0188
0189
0190 if (ATA_DEV_INFO(ctrl_minor, dev).lba_avaible)
0191 {
0192 uint32_t start = req->bufs[0].block;
0193 areq->regs.regs[IDE_REGISTER_LBA0] = (uint8_t)start;
0194 areq->regs.regs[IDE_REGISTER_LBA1] = (uint8_t)(start >> 8);
0195 areq->regs.regs[IDE_REGISTER_LBA2] = (uint8_t)(start >> 16);
0196
0197 areq->regs.regs[IDE_REGISTER_LBA3] |= (uint8_t) (start >> 24);
0198 areq->regs.regs[IDE_REGISTER_LBA3] |= IDE_REGISTER_LBA3_L;
0199 }
0200 else
0201 {
0202 uint32_t count = req->bufs[0].block;
0203
0204 areq->regs.regs[IDE_REGISTER_SECTOR_NUMBER] =
0205 (count % ATA_DEV_INFO(ctrl_minor, dev).sectors) + 1;
0206
0207
0208 count /= ATA_DEV_INFO(ctrl_minor, dev).sectors;
0209 areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] |=
0210 (count / ATA_DEV_INFO(ctrl_minor, dev).cylinders);
0211
0212
0213 count %= ATA_DEV_INFO(ctrl_minor, dev).cylinders;
0214 areq->regs.regs[IDE_REGISTER_CYLINDER_LOW] = (uint8_t)count;
0215 areq->regs.regs[IDE_REGISTER_CYLINDER_HIGH] = (uint8_t)(count >> 8);
0216 areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &=
0217 ~IDE_REGISTER_DEVICE_HEAD_L;
0218 }
0219
0220
0221
0222
0223
0224 areq->regs.regs[IDE_REGISTER_SECTOR_COUNT] =
0225 areq->breq->bufnum * (areq->breq->bufs[0].length / ATA_SECTOR_SIZE);
0226
0227
0228 ata_add_to_controller_queue(ctrl_minor, areq);
0229
0230 return RTEMS_SUCCESSFUL;
0231 }
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 static rtems_status_code
0247 ata_non_data_request(ata_ide_dev_t *ata_dev, uint32_t cmd, void *argp)
0248 {
0249 rtems_status_code rc;
0250 ata_req_t *areq;
0251 rtems_device_minor_number ctrl_minor;
0252 uint8_t dev;
0253 ata_queue_msg_t msg;
0254
0255
0256 ctrl_minor = ata_dev->ctrl_minor;
0257
0258
0259 dev = ata_dev->device;
0260
0261
0262 areq = malloc(sizeof(ata_req_t));
0263 if (areq == NULL)
0264 {
0265 return RTEMS_NO_MEMORY;
0266 }
0267 memset(areq, 0, sizeof(ata_req_t));
0268
0269 areq->type = ATA_COMMAND_TYPE_NON_DATA;
0270 areq->regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
0271 areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] |=
0272 (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS);
0273 areq->breq = NULL;
0274 areq->regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR);
0275
0276
0277
0278
0279
0280 switch(cmd)
0281 {
0282 case ATAIO_SET_MULTIPLE_MODE:
0283 areq->regs.regs[IDE_REGISTER_COMMAND] =
0284 ATA_COMMAND_SET_MULTIPLE_MODE;
0285 areq->regs.to_write |=
0286 ATA_REGISTERS_VALUE(IDE_REGISTER_SECTOR_COUNT);
0287 areq->regs.regs[IDE_REGISTER_SECTOR_COUNT] = *(uint8_t*)argp;
0288 break;
0289
0290 default:
0291 free(areq);
0292 return RTEMS_INVALID_NUMBER;
0293 break;
0294 }
0295
0296 rc = rtems_semaphore_create(rtems_build_name('I', 'D', 'E', 'S'),
0297 0,
0298 RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE |
0299 RTEMS_NO_INHERIT_PRIORITY |
0300 RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
0301 0,
0302 &(areq->sema));
0303 if (rc != RTEMS_SUCCESSFUL)
0304 {
0305 free(areq);
0306 return rc;
0307 }
0308
0309 ata_add_to_controller_queue(ctrl_minor, areq);
0310
0311
0312 rc = rtems_semaphore_obtain(areq->sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0313 if (rc != RTEMS_SUCCESSFUL)
0314 {
0315 free(areq);
0316 return rc;
0317 }
0318
0319 rtems_semaphore_delete(areq->sema);
0320
0321
0322
0323
0324
0325 if (areq->status == RTEMS_SUCCESSFUL)
0326 {
0327 switch(cmd)
0328 {
0329 case ATAIO_SET_MULTIPLE_MODE:
0330
0331 default:
0332 rc = RTEMS_INVALID_NUMBER;
0333 break;
0334 }
0335 }
0336 else
0337 {
0338
0339
0340
0341 rc = RTEMS_IO_ERROR;
0342 }
0343
0344
0345 ATA_SEND_EVT(msg, ATA_MSG_SUCCESS_EVT, ctrl_minor, 0);
0346
0347 return rc;
0348 }
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359 static void
0360 ata_process_request(rtems_device_minor_number ctrl_minor)
0361 {
0362 ata_req_t *areq;
0363 uint16_t byte;
0364 ata_queue_msg_t msg;
0365 uint8_t i;
0366 #if 0
0367 uint8_t dev;
0368 #endif
0369 uint16_t val;
0370 ISR_Level level;
0371
0372
0373 if (rtems_chain_is_empty(&ata_ide_ctrls[ctrl_minor].reqs))
0374 return;
0375
0376
0377 _ISR_Local_disable(level);
0378 areq = (ata_req_t *)rtems_chain_first(&ata_ide_ctrls[ctrl_minor].reqs);
0379 _ISR_Local_enable(level);
0380
0381 #if 0
0382
0383 dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
0384 IDE_REGISTER_DEVICE_HEAD_DEV;
0385 #endif
0386
0387
0388 ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD,
0389 areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]);
0390
0391 do {
0392 ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);
0393 } while ((byte & IDE_REGISTER_STATUS_BSY) ||
0394 (!(byte & IDE_REGISTER_STATUS_DRDY)));
0395
0396
0397 for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++)
0398 {
0399 uint32_t reg = (1 << i);
0400 if (areq->regs.to_write & reg)
0401 ide_controller_write_register(ctrl_minor, i, areq->regs.regs[i]);
0402 }
0403
0404 #if ATA_DEBUG
0405 ata_printf("ata_process_request: type: %d\n", areq->type);
0406 #endif
0407
0408
0409 if (areq->type == ATA_COMMAND_TYPE_PIO_OUT)
0410 {
0411 do {
0412 ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
0413 &byte);
0414 } while (byte & IDE_REGISTER_STATUS_BSY);
0415
0416 if (byte & IDE_REGISTER_STATUS_DRQ)
0417 {
0418 if (areq->cnt)
0419 {
0420 int ccbuf = areq->cbuf;
0421 ide_controller_write_data_block(ctrl_minor,
0422 areq->breq->bufs[0].length * areq->cnt,
0423 areq->breq->bufs, &areq->cbuf,
0424 &areq->pos);
0425 ccbuf = areq->cbuf - ccbuf;
0426 areq->cnt -= ccbuf;
0427 }
0428 }
0429 else
0430 {
0431 if (IDE_Controller_Table[ctrl_minor].int_driven == false)
0432 {
0433 ide_controller_read_register(
0434 ctrl_minor,
0435 IDE_REGISTER_ALTERNATE_STATUS_OFFSET,
0436 &val);
0437 ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
0438 &val);
0439
0440 ATA_SEND_EVT(msg, ATA_MSG_ERROR_EVT, ctrl_minor,
0441 RTEMS_IO_ERROR);
0442 }
0443 }
0444 }
0445
0446 if (IDE_Controller_Table[ctrl_minor].int_driven == false)
0447 {
0448 do {
0449 ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
0450 &byte);
0451 } while (byte & IDE_REGISTER_STATUS_BSY);
0452
0453 ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);
0454 }
0455 }
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470 static inline void
0471 ata_request_done(ata_req_t *areq, rtems_device_minor_number ctrl_minor,
0472 rtems_status_code status)
0473 {
0474 assert(areq);
0475
0476 #if ATA_DEBUG
0477 ata_printf("ata_request_done: entry\n");
0478 #endif
0479
0480 ATA_EXEC_CALLBACK(areq, status);
0481 rtems_chain_extract(&areq->link);
0482
0483 if (!rtems_chain_is_empty(&ata_ide_ctrls[ctrl_minor].reqs))
0484 {
0485 free(areq);
0486 ata_process_request(ctrl_minor);
0487 return;
0488 }
0489
0490 free(areq);
0491
0492 #if ATA_DEBUG
0493 ata_printf("ata_request_done: exit\n");
0494 #endif
0495 }
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509 static inline void
0510 ata_non_data_request_done(ata_req_t *areq,
0511 rtems_device_minor_number ctrl_minor,
0512 rtems_status_code status, int info)
0513 {
0514 #if ATA_DEBUG
0515 ata_printf("ata_non_data_request_done: entry\n");
0516 #endif
0517
0518 areq->status = status;
0519 areq->info = info;
0520 rtems_semaphore_release(areq->sema);
0521 }
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534 static void
0535 ata_add_to_controller_queue(rtems_device_minor_number ctrl_minor,
0536 ata_req_t *areq)
0537 {
0538 rtems_ata_lock();
0539
0540 rtems_chain_append(&ata_ide_ctrls[ctrl_minor].reqs, &areq->link);
0541 if (rtems_chain_has_only_one_node(&ata_ide_ctrls[ctrl_minor].reqs))
0542 {
0543
0544 ata_queue_msg_t msg;
0545
0546 #if ATA_DEBUG_DOES_NOT_WORK_WITH_QEMU
0547 uint16_t val;
0548
0549
0550
0551
0552 ide_controller_read_register(ctrl_minor,
0553 IDE_REGISTER_ALTERNATE_STATUS,
0554 &val);
0555 if (val & IDE_REGISTER_STATUS_BSY)
0556 return;
0557 #endif
0558 ATA_SEND_EVT(msg, ATA_MSG_PROCESS_NEXT_EVT, ctrl_minor, 0);
0559 }
0560
0561 rtems_ata_unlock();
0562 }
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576 #if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE
0577 static rtems_isr ata_interrupt_handler(rtems_vector_number vec)
0578 {
0579 rtems_chain_node *the_node = rtems_chain_first(&ata_int_vec[vec]);
0580 ata_queue_msg_t msg;
0581 uint16_t byte;
0582
0583 for ( ; !rtems_chain_is_tail(&ata_int_vec[vec], the_node) ; )
0584 {
0585
0586
0587
0588
0589 if (1)
0590 {
0591 msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor;
0592 ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS,
0593 &byte);
0594 ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0);
0595 }
0596 the_node = the_node->next;
0597 }
0598 }
0599 #else
0600 static void ata_interrupt_handler(rtems_irq_hdl_param handle)
0601 {
0602 uintptr_t ata_irq_chain_index = (uintptr_t) handle;
0603 rtems_chain_node *the_node =
0604 rtems_chain_last(&ata_irq_chain[ata_irq_chain_index].irq_chain);
0605 ata_queue_msg_t msg;
0606 uint16_t byte;
0607
0608
0609 for ( ; !rtems_chain_is_tail(&ata_irq_chain[ata_irq_chain_index].irq_chain,
0610 the_node) ; )
0611 {
0612
0613
0614
0615
0616 if (1)
0617 {
0618 msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor;
0619 ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS,
0620 &byte);
0621 ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0);
0622 }
0623 the_node = the_node->next;
0624 }
0625 }
0626
0627 static void ata_interrupt_on(const rtems_irq_connect_data *ptr)
0628 {
0629
0630
0631 ide_controller_write_register(0,
0632 IDE_REGISTER_DEVICE_CONTROL_OFFSET,
0633 0x00
0634 );
0635 }
0636
0637
0638 static void ata_interrupt_off(const rtems_irq_connect_data *ptr)
0639 {
0640
0641
0642 ide_controller_write_register(0,
0643 IDE_REGISTER_DEVICE_CONTROL_OFFSET,
0644 IDE_REGISTER_DEVICE_CONTROL_nIEN
0645 );
0646 }
0647
0648
0649 static int ata_interrupt_isOn(const rtems_irq_connect_data *ptr)
0650 {
0651 uint16_t byte;
0652
0653
0654 ide_controller_read_register(0,
0655 IDE_REGISTER_DEVICE_CONTROL_OFFSET,
0656 &byte
0657 );
0658
0659 return !(byte & IDE_REGISTER_DEVICE_CONTROL_nIEN);
0660 }
0661
0662
0663 static rtems_irq_connect_data ata_irq_data =
0664 {
0665
0666 0,
0667 ata_interrupt_handler,
0668 NULL,
0669 ata_interrupt_on,
0670 ata_interrupt_off,
0671 ata_interrupt_isOn
0672 };
0673 #endif
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685 static inline void
0686 ata_pio_in_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq)
0687 {
0688 uint16_t val;
0689 #if 0
0690 uint8_t dev;
0691 #endif
0692 ata_queue_msg_t msg;
0693
0694 #if 0
0695 dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
0696 IDE_REGISTER_DEVICE_HEAD_DEV;
0697 #endif
0698
0699 if (areq->cnt)
0700 {
0701 int ccbuf = areq->cbuf;
0702 ide_controller_read_data_block(ctrl_minor,
0703 areq->breq->bufs[0].length * areq->cnt,
0704 areq->breq->bufs, &areq->cbuf, &areq->pos);
0705 ccbuf = areq->cbuf - ccbuf;
0706 areq->cnt -= ccbuf;
0707 }
0708
0709 if (areq->cnt == 0)
0710 {
0711 ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL);
0712 }
0713 else if (IDE_Controller_Table[ctrl_minor].int_driven == false)
0714 {
0715 do {
0716 ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val);
0717 } while (val & IDE_REGISTER_STATUS_BSY);
0718
0719 ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);
0720 }
0721 }
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732
0733 static inline void
0734 ata_pio_out_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq)
0735 {
0736 uint16_t val;
0737 #if 0
0738 uint8_t dev;
0739 #endif
0740 ata_queue_msg_t msg;
0741
0742 #if ATA_DEBUG
0743 ata_printf("ata_pio_out_protocol:\n");
0744 #endif
0745
0746 #if 0
0747 dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
0748 IDE_REGISTER_DEVICE_HEAD_DEV;
0749 #endif
0750
0751 if (areq->cnt == 0)
0752 {
0753 ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL);
0754 }
0755 else
0756 {
0757 if (areq->cnt)
0758 {
0759 int ccbuf = areq->cbuf;
0760 ide_controller_write_data_block(ctrl_minor,
0761 areq->breq->bufs[0].length * areq->cnt,
0762 areq->breq->bufs, &areq->cbuf,
0763 &areq->pos);
0764 ccbuf = areq->cbuf - ccbuf;
0765 areq->cnt -= ccbuf;
0766 }
0767 if (IDE_Controller_Table[ctrl_minor].int_driven == false)
0768 {
0769 do {
0770 ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
0771 &val);
0772 } while (val & IDE_REGISTER_STATUS_BSY);
0773
0774 ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);
0775 }
0776 }
0777 }
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790
0791 static rtems_task
0792 ata_queue_task(rtems_task_argument arg)
0793 {
0794 ata_queue_msg_t msg;
0795 size_t size;
0796 ata_req_t *areq;
0797 rtems_device_minor_number ctrl_minor;
0798 uint16_t val;
0799 uint16_t val1;
0800 rtems_status_code rc;
0801 ISR_Level level;
0802
0803 rtems_ata_lock();
0804
0805 while (1)
0806 {
0807 rtems_ata_unlock();
0808
0809
0810 rc = rtems_message_queue_receive(ata_queue_id, &msg, &size, RTEMS_WAIT,
0811 RTEMS_NO_TIMEOUT);
0812 if (rc != RTEMS_SUCCESSFUL)
0813 rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
0814
0815
0816 ctrl_minor = msg.ctrl_minor;
0817
0818 rtems_ata_lock();
0819
0820
0821 _ISR_Local_disable(level);
0822 areq = (ata_req_t *)rtems_chain_first(&ata_ide_ctrls[ctrl_minor].reqs);
0823 _ISR_Local_enable(level);
0824
0825 switch(msg.type)
0826 {
0827 case ATA_MSG_PROCESS_NEXT_EVT:
0828
0829 ata_process_request(ctrl_minor);
0830 break;
0831
0832 case ATA_MSG_SUCCESS_EVT:
0833
0834
0835
0836
0837
0838 ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL);
0839 break;
0840
0841 case ATA_MSG_ERROR_EVT:
0842
0843
0844
0845
0846
0847 ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR);
0848 break;
0849
0850 case ATA_MSG_GEN_EVT:
0851
0852
0853
0854
0855
0856 ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
0857 &val);
0858
0859 if (val & IDE_REGISTER_STATUS_ERR)
0860 {
0861 ide_controller_read_register(ctrl_minor,
0862 IDE_REGISTER_ERROR,
0863 &val);
0864 if (val & (IDE_REGISTER_ERROR_UNC |
0865 IDE_REGISTER_ERROR_ICRC |
0866 IDE_REGISTER_ERROR_IDNF |
0867 IDE_REGISTER_ERROR_NM |
0868 IDE_REGISTER_ERROR_MED))
0869 {
0870 if (areq->type == ATA_COMMAND_TYPE_NON_DATA)
0871 ata_non_data_request_done(areq, ctrl_minor,
0872 RTEMS_UNSATISFIED,
0873 RTEMS_IO_ERROR);
0874 else
0875 ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR);
0876 break;
0877 }
0878 }
0879
0880 switch(areq->type)
0881 {
0882 case ATA_COMMAND_TYPE_PIO_IN:
0883 ata_pio_in_protocol(ctrl_minor, areq);
0884 break;
0885
0886 case ATA_COMMAND_TYPE_PIO_OUT:
0887 ata_pio_out_protocol(ctrl_minor, areq);
0888 break;
0889
0890 case ATA_COMMAND_TYPE_NON_DATA:
0891 ide_controller_read_register(ctrl_minor,
0892 IDE_REGISTER_ERROR,
0893 &val1);
0894 ata_non_data_request_done(areq, ctrl_minor,
0895 RTEMS_SUCCESSFUL,
0896 val1);
0897 break;
0898
0899 default:
0900 #if ATA_DEBUG
0901 ata_printf("ata_queue_task: non-supported command type\n");
0902 #endif
0903 ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR);
0904 break;
0905 }
0906 break;
0907
0908 default:
0909 #if ATA_DEBUG
0910 ata_printf("ata_queue_task: internal error\n");
0911 rtems_task_exit();
0912 #endif
0913 rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
0914 break;
0915 }
0916 }
0917 }
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930 static int
0931 ata_ioctl(rtems_disk_device *dd, uint32_t cmd, void *argp)
0932 {
0933 ata_ide_dev_t *ata_dev = rtems_disk_get_driver_data(dd);
0934 rtems_status_code status;
0935
0936
0937
0938
0939
0940 if (ata_dev->device == ATA_UNDEFINED_VALUE)
0941 {
0942 errno = ENODEV;
0943 return -1;
0944 }
0945
0946 switch (cmd)
0947 {
0948 case RTEMS_BLKIO_REQUEST:
0949 status = ata_io_data_request(ata_dev, (rtems_blkdev_request *)argp);
0950 break;
0951
0952 case ATAIO_SET_MULTIPLE_MODE:
0953 status = ata_non_data_request(ata_dev, cmd, argp);
0954 break;
0955
0956 case RTEMS_BLKIO_CAPABILITIES:
0957 *((uint32_t*) argp) = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
0958 status = RTEMS_SUCCESSFUL;
0959 break;
0960
0961 default:
0962 return rtems_blkdev_ioctl (dd, cmd, argp);
0963 break;
0964 }
0965
0966 if (status != RTEMS_SUCCESSFUL)
0967 {
0968 errno = EIO;
0969 return -1;
0970 }
0971 return 0;
0972 }
0973
0974 static void ata_execute_device_diagnostic(
0975 rtems_device_minor_number ctrl_minor,
0976 uint16_t *sector_buffer
0977 )
0978 {
0979 #if ATA_EXEC_DEVICE_DIAGNOSTIC
0980 ata_req_t areq;
0981 blkdev_request1 breq;
0982
0983 ata_breq_init(&breq, sector_buffer);
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993 memset(&areq, 0, sizeof(ata_req_t));
0994 areq.type = ATA_COMMAND_TYPE_NON_DATA;
0995 areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
0996 areq.regs.regs[IDE_REGISTER_COMMAND] =
0997 ATA_COMMAND_EXECUTE_DEVICE_DIAGNOSTIC;
0998 areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR);
0999
1000 areq.breq = (rtems_blkdev_request *)&breq;
1001
1002
1003
1004
1005
1006
1007 ata_process_request_on_init_phase(ctrl_minor, &areq);
1008
1009
1010
1011
1012 if (breq.req.status == RTEMS_SUCCESSFUL)
1013 {
1014
1015 if (areq.info == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT)
1016 {
1017 printk("ATA: ctrl:%d: primary, secondary\n", ctrl_minor);
1018 ATA_DEV_INFO(ctrl_minor,0).present = true;
1019 ATA_DEV_INFO(ctrl_minor,1).present = true;
1020 }
1021 else if (areq.info == ATA_DEV0_PASSED_DEV1_FAILED)
1022 {
1023 printk("ATA: ctrl:%d: primary\n", ctrl_minor);
1024 ATA_DEV_INFO(ctrl_minor,0).present = true;
1025 ATA_DEV_INFO(ctrl_minor,1).present = false;
1026 }
1027 else if (areq.info < ATA_DEV1_PASSED_DEV0_FAILED)
1028 {
1029 printk("ATA: ctrl:%d: secondary\n", ctrl_minor);
1030 ATA_DEV_INFO(ctrl_minor,0).present = false;
1031 ATA_DEV_INFO(ctrl_minor,1).present = true;
1032 }
1033 else
1034 {
1035 printk("ATA: ctrl:%d: none\n", ctrl_minor);
1036 ATA_DEV_INFO(ctrl_minor, 0).present = false;
1037 ATA_DEV_INFO(ctrl_minor, 1).present = false;
1038 }
1039
1040
1041 if (ATA_DEV_INFO(ctrl_minor, 1).present)
1042 {
1043 uint16_t ec = 0;
1044 ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &ec);
1045 if (ec & ATA_DEV1_PASSED_DEV0_FAILED)
1046 {
1047 printk("ATA: ctrl:%d: secondary inforced\n", ctrl_minor);
1048 ATA_DEV_INFO(ctrl_minor, 1).present = true;
1049 }
1050 else
1051 {
1052 printk("ATA: ctrl:%d: secondary removed\n", ctrl_minor);
1053 ATA_DEV_INFO(ctrl_minor, 1).present = false;
1054 }
1055 }
1056 }
1057 else
1058 #endif
1059 {
1060 ATA_DEV_INFO(ctrl_minor, 0).present = true;
1061 ATA_DEV_INFO(ctrl_minor,1).present = true;
1062 }
1063 }
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078 rtems_device_driver
1079 rtems_ata_initialize(rtems_device_major_number major,
1080 rtems_device_minor_number minor_arg,
1081 void *args)
1082 {
1083 uint32_t ctrl_minor;
1084 rtems_status_code status;
1085 uint16_t *buffer;
1086 int i, dev = 0;
1087 char name[ATA_MAX_NAME_LENGTH];
1088 ata_int_st_t *int_st;
1089
1090 #if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE
1091 rtems_isr_entry old_isr;
1092 #else
1093 int ata_irq_chain_use;
1094 #endif
1095
1096 if (ata_initialized)
1097 return RTEMS_SUCCESSFUL;
1098
1099 status = rtems_semaphore_create (rtems_build_name ('A', 'T', 'A', 'L'),
1100 1, RTEMS_ATA_LOCK_ATTRIBS, 0,
1101 &ata_lock);
1102 if (status != RTEMS_SUCCESSFUL)
1103 return status;
1104
1105
1106 status = rtems_message_queue_create(
1107 rtems_build_name('A', 'T', 'A', 'Q'),
1108 ATA_DRIVER_MESSAGE_QUEUE_SIZE,
1109 sizeof(ata_queue_msg_t),
1110 RTEMS_FIFO | RTEMS_LOCAL,
1111 &ata_queue_id);
1112 if (status != RTEMS_SUCCESSFUL)
1113 {
1114 return status;
1115 }
1116
1117
1118
1119
1120
1121 status = rtems_task_create(
1122 rtems_build_name ('A', 'T', 'A', 'T'),
1123 ((rtems_ata_driver_task_priority > 0)
1124 ? rtems_ata_driver_task_priority
1125 : ATA_DRIVER_TASK_DEFAULT_PRIORITY),
1126 ATA_DRIVER_TASK_STACK_SIZE,
1127 RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
1128 RTEMS_INTERRUPT_LEVEL(0),
1129 RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
1130 &ata_task_id);
1131 if (status != RTEMS_SUCCESSFUL)
1132 {
1133 rtems_message_queue_delete(ata_queue_id);
1134 return status;
1135 }
1136
1137
1138
1139
1140
1141 status = rtems_task_start(ata_task_id, ata_queue_task, 0);
1142 if (status != RTEMS_SUCCESSFUL)
1143 {
1144 rtems_task_delete(ata_task_id);
1145 rtems_message_queue_delete(ata_queue_id);
1146 return status;
1147 }
1148
1149 buffer = (uint16_t*)malloc(ATA_SECTOR_SIZE);
1150 if (buffer == NULL)
1151 {
1152 rtems_task_delete(ata_task_id);
1153 rtems_message_queue_delete(ata_queue_id);
1154 return RTEMS_NO_MEMORY;
1155 }
1156
1157 ata_devs_number = 0;
1158
1159 for (i = 0; i < (2 * IDE_CTRL_MAX_MINOR_NUMBER); i++)
1160 ata_devs[i].device = ATA_UNDEFINED_VALUE;
1161
1162 #if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE
1163
1164 for (i = 0; i < ATA_MAX_RTEMS_INT_VEC_NUMBER; i++)
1165 rtems_chain_initialize_empty(&ata_int_vec[i]);
1166 #else
1167 for (i = 0; i < ATA_IRQ_CHAIN_MAX_CNT; i++) {
1168 rtems_chain_initialize_empty(&(ata_irq_chain[i].irq_chain));
1169 }
1170 #endif
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184 for (ctrl_minor = 0; ctrl_minor < IDE_Controller_Count; ctrl_minor++)
1185 if (IDE_Controller_Table[ctrl_minor].status == IDE_CTRL_INITIALIZED)
1186 {
1187 rtems_chain_initialize_empty(&ata_ide_ctrls[ctrl_minor].reqs);
1188
1189 if (IDE_Controller_Table[ctrl_minor].int_driven == true)
1190 {
1191 int_st = malloc(sizeof(ata_int_st_t));
1192 if (int_st == NULL)
1193 {
1194 free(buffer);
1195 rtems_task_delete(ata_task_id);
1196 rtems_message_queue_delete(ata_queue_id);
1197 return RTEMS_NO_MEMORY;
1198 }
1199
1200 int_st->ctrl_minor = ctrl_minor;
1201 #if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE
1202 status = rtems_interrupt_catch(
1203 ata_interrupt_handler,
1204 IDE_Controller_Table[ctrl_minor].int_vec,
1205 &old_isr);
1206 #else
1207
1208
1209
1210
1211
1212 ata_irq_chain_use = -1;
1213 for (i = 0;
1214 ((i < ata_irq_chain_cnt) &&
1215 (ata_irq_chain_use < 0));i++) {
1216 if (ata_irq_chain[i].name ==
1217 IDE_Controller_Table[ctrl_minor].int_vec) {
1218 ata_irq_chain_use = i;
1219 }
1220 }
1221 if (ata_irq_chain_use < 0) {
1222
1223
1224
1225 if (ata_irq_chain_cnt < ATA_IRQ_CHAIN_MAX_CNT) {
1226 ata_irq_chain_use = ata_irq_chain_cnt++;
1227
1228 ata_irq_chain[ata_irq_chain_use].name =
1229 IDE_Controller_Table[ctrl_minor].int_vec;
1230 ata_irq_data.name =
1231 IDE_Controller_Table[ctrl_minor].int_vec;
1232 ata_irq_data.hdl = ata_interrupt_handler;
1233 ata_irq_data.handle = (rtems_irq_hdl_param) (uintptr_t) ctrl_minor;
1234
1235 status = ((0 == BSP_install_rtems_irq_handler(&ata_irq_data))
1236 ? RTEMS_INVALID_NUMBER
1237 : RTEMS_SUCCESSFUL);
1238 }
1239 else {
1240 status = RTEMS_TOO_MANY;
1241 }
1242 }
1243 #endif
1244 if (status != RTEMS_SUCCESSFUL)
1245 {
1246 free(int_st);
1247 free(buffer);
1248 rtems_task_delete(ata_task_id);
1249 rtems_message_queue_delete(ata_queue_id);
1250 return status;
1251 }
1252 #if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE
1253 rtems_chain_append(
1254 &ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec],
1255 &int_st->link);
1256 #else
1257 rtems_chain_append(
1258 &(ata_irq_chain[ata_irq_chain_use].irq_chain),
1259 &int_st->link);
1260 #endif
1261
1262
1263 ide_controller_write_register(ctrl_minor,
1264 IDE_REGISTER_DEVICE_CONTROL_OFFSET,
1265 IDE_REGISTER_DEVICE_CONTROL_nIEN);
1266 }
1267
1268 ata_execute_device_diagnostic(ctrl_minor, buffer);
1269
1270
1271 for (dev = 0; dev < 2; dev++)
1272 if (ATA_DEV_INFO(ctrl_minor, dev).present)
1273 {
1274 status = ata_identify_device(
1275 ctrl_minor,
1276 dev,
1277 buffer,
1278 &ATA_DEV_INFO(ctrl_minor, dev));
1279 if (status != RTEMS_SUCCESSFUL)
1280 continue;
1281
1282
1283
1284
1285
1286 status = ide_controller_config_io_speed(
1287 ctrl_minor,
1288 ATA_DEV_INFO(ctrl_minor, dev).modes_available);
1289 if (status != RTEMS_SUCCESSFUL)
1290 continue;
1291
1292
1293
1294
1295 ata_devs[ata_devs_number].ctrl_minor = ctrl_minor;
1296 ata_devs[ata_devs_number].device = dev;
1297
1298
1299 strcpy(name, "/dev/hd ");
1300 name[7] = 'a' + 2 * ctrl_minor + dev;
1301
1302 status = rtems_blkdev_create(name, ATA_SECTOR_SIZE,
1303 ATA_DEV_INFO(ctrl_minor, dev).lba_avaible ?
1304 ATA_DEV_INFO(ctrl_minor, dev).lba_sectors :
1305 (ATA_DEV_INFO(ctrl_minor, dev).heads *
1306 ATA_DEV_INFO(ctrl_minor, dev).cylinders *
1307 ATA_DEV_INFO(ctrl_minor, dev).sectors),
1308 ata_ioctl, &ata_devs[ata_devs_number]);
1309 if (status != RTEMS_SUCCESSFUL)
1310 {
1311 ata_devs[ata_devs_number].device = ATA_UNDEFINED_VALUE;
1312 continue;
1313 }
1314 ata_devs_number++;
1315 }
1316 if (IDE_Controller_Table[ctrl_minor].int_driven == true)
1317 {
1318 ide_controller_write_register(ctrl_minor,
1319 IDE_REGISTER_DEVICE_CONTROL_OFFSET,
1320 0x00);
1321 }
1322 }
1323
1324 free(buffer);
1325 ata_initialized = true;
1326 return RTEMS_SUCCESSFUL;
1327 }