File indexing completed on 2025-05-11 08:23:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <sys/param.h>
0023 #include <rtems.h>
0024 #include <rtems/error.h>
0025 #include <rtems/score/sysstate.h>
0026 #include <bsp.h>
0027 #include <bsp/irq.h>
0028 #include <bsp/mpc5200.h>
0029 #include "./pcmcia_ide.h"
0030
0031 #include <libchip/ide_ctrl.h>
0032 #include <libchip/ide_ctrl_cfg.h>
0033 #include <libchip/ide_ctrl_io.h>
0034 #include <string.h>
0035
0036 #define IDE_DMA_TEST FALSE
0037
0038
0039 #define IDE_USE_INT TRUE
0040 #define IDE_READ_USE_DMA FALSE
0041 #define IDE_USE_READ_PIO_OPT FALSE
0042 #define IDE_WRITE_USE_DMA FALSE
0043 #define IDE_USE_WRITE_PIO_OPT FALSE
0044 #define IDE_USE_DMA (IDE_READ_USE_DMA || IDE_WRITE_USE_DMA)
0045
0046 #define IDE_USE_STATISTICS TRUE
0047
0048 #if IDE_USE_DMA
0049 #define PCMCIA_IDE_DMA_WR_BD_CNT 2
0050 #define PCMCIA_IDE_DMA_RD_BD_CNT 2
0051 #define PCMCIA_IDE_INTERRUPT_EVENT RTEMS_EVENT_2
0052
0053 #include "../bestcomm/bestcomm_glue.h"
0054 #include "../bestcomm/bestcomm_api.h"
0055 #include "../bestcomm/task_api/bestcomm_cntrl.h"
0056 #include "../bestcomm/task_api/tasksetup_bdtable.h"
0057
0058 #define IDE_RX_TASK_NO TASK_GEN_DP_BD_0
0059 #define IDE_TX_TASK_NO TASK_GEN_DP_BD_1
0060 static TaskId pcmcia_ide_rxTaskId;
0061 static TaskId pcmcia_ide_txTaskId;
0062 #define PCMCIA_IDE_RD_SECTOR_SIZE 512
0063 #define PCMCIA_IDE_WR_SECTOR_SIZE 512
0064
0065 bool mpc5200_dma_task_started[2] = {false,false};
0066 #endif
0067
0068 #if IDE_USE_STATISTICS
0069 uint32_t mpc5200_pcmciaide_write_block_call_cnt = 0;
0070 uint32_t mpc5200_pcmciaide_write_block_block_cnt = 0;
0071 uint32_t mpc5200_pcmciaide_read_block_call_cnt = 0;
0072 uint32_t mpc5200_pcmciaide_read_block_block_cnt = 0;
0073 #endif
0074
0075 extern volatile uint32_t * mpc5200_ata_drive_regs[];
0076 extern uint32_t ata_pio_timings[2][6];
0077
0078 void mpc5200_pcmciaide_dma_blockop(
0079 bool, int, uint16_t, rtems_blkdev_sg_buffer *, uint32_t *, uint32_t *);
0080
0081
0082
0083 static bool mpc5200_pcmciaide_probe(int minor)
0084 {
0085 bool ide_card_plugged = false;
0086 struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[GPT2]);
0087
0088 #ifdef MPC5200_BOARD_DP2
0089
0090 rtems_interrupt_level level;
0091 rtems_interrupt_disable(level);
0092 mpc5200.gpiowe |= GPIO_W_PIN_PSC1_4;
0093 mpc5200.gpiowod &= ~GPIO_W_PIN_PSC1_4;
0094 mpc5200.gpiowdd |= GPIO_W_PIN_PSC1_4;
0095 mpc5200.gpiowdo |= GPIO_W_PIN_PSC1_4;
0096 rtems_interrupt_enable(level);
0097
0098 volatile int i = 0;
0099 while (++i < 20000000);
0100 #endif
0101
0102
0103 gpt->emsel = (GPT_EMSEL_GPIO_IN | GPT_EMSEL_TIMER_MS_GPIO);
0104
0105 #if defined (MPC5200_BOARD_BRS5L)
0106
0107 if((gpt->status) & GPT_STATUS_PIN)
0108 ide_card_plugged = false;
0109 else
0110 #endif
0111 ide_card_plugged = true;
0112
0113 return ide_card_plugged;
0114
0115 }
0116
0117 #define DMA1_T0(val) BSP_BFLD32(COUNT_VAL(val), 0, 7)
0118 #define DMA1_TD(val) BSP_BFLD32(COUNT_VAL(val), 8, 15)
0119 #define DMA1_TK(val) BSP_BFLD32(COUNT_VAL(val), 16, 23)
0120 #define DMA1_TM(val) BSP_BFLD32(COUNT_VAL(val), 24, 31)
0121
0122 #define DMA2_TH(val) BSP_BFLD32(COUNT_VAL(val), 0, 7)
0123 #define DMA2_TJ(val) BSP_BFLD32(COUNT_VAL(val), 8, 15)
0124 #define DMA2_TN(val) BSP_BFLD32(COUNT_VAL(val), 16, 23)
0125
0126 static rtems_status_code mpc5200_pcmciaide_config_io_speed(int minor, uint16_t modes_avail)
0127 {
0128 uint8_t pio_t0, pio_t2_8, pio_t2_16, pio_t4, pio_t1, pio_ta;
0129
0130 if((modes_avail & ATA_MODES_PIO4) != 0)
0131 {
0132
0133 pio_t0 = ata_pio_timings[PIO_4][T0];
0134 pio_t2_8 = ata_pio_timings[PIO_4][T2_8];
0135 pio_t2_16 = ata_pio_timings[PIO_4][T2_16];
0136 pio_t4 = ata_pio_timings[PIO_4][T4];
0137 pio_t1 = ata_pio_timings[PIO_4][T1];
0138 pio_ta = ata_pio_timings[PIO_4][TA];
0139
0140 }
0141 else
0142 {
0143
0144 pio_t0 = ata_pio_timings[PIO_3][T0];
0145 pio_t2_8 = ata_pio_timings[PIO_3][T2_8];
0146 pio_t2_16 = ata_pio_timings[PIO_3][T2_16];
0147 pio_t4 = ata_pio_timings[PIO_3][T4];
0148 pio_t1 = ata_pio_timings[PIO_3][T1];
0149 pio_ta = ata_pio_timings[PIO_3][TA];
0150
0151 }
0152
0153
0154 mpc5200.ata_pio1 = ATA_PIO_TIMING_1(pio_t0, pio_t2_8, pio_t2_16);
0155 mpc5200.ata_pio2 = ATA_PIO_TIMING_2(pio_t4, pio_t1, pio_ta);
0156
0157 mpc5200.ata_dma1 = DMA1_T0(120) | DMA1_TD(70) | DMA1_TK(25) | DMA1_TM(25);
0158 mpc5200.ata_dma2 = DMA2_TH(10) | DMA2_TJ(5) | DMA2_TN(10);
0159
0160 return RTEMS_SUCCESSFUL;
0161
0162 }
0163
0164
0165
0166 static void mpc5200_pcmciaide_read_reg(int minor, int reg, uint16_t *value)
0167 {
0168 volatile uint32_t *ata_reg = mpc5200_ata_drive_regs[reg];
0169
0170 if(reg == IDE_REGISTER_DATA_WORD)
0171 *value = *(volatile uint16_t *)(ata_reg);
0172 else
0173 *value = *(volatile uint8_t *)(ata_reg);
0174 }
0175
0176
0177 static void mpc5200_pcmciaide_write_reg(int minor, int reg, uint16_t value)
0178 {
0179 volatile uint32_t *ata_reg = mpc5200_ata_drive_regs[reg];
0180
0181 if(reg == IDE_REGISTER_DATA_WORD)
0182 *(volatile uint16_t *)(ata_reg) = value;
0183 else
0184 *(volatile uint8_t *)(ata_reg) = value;
0185 }
0186
0187 #if IDE_USE_DMA
0188
0189
0190 uint32_t pcmcia_ide_rxInterrupts;
0191 uint32_t pcmcia_ide_txInterrupts;
0192 volatile rtems_id pcmcia_ide_hdl_task = 0;
0193
0194
0195
0196 static void pcmcia_ide_recv_dmairq_hdl(rtems_irq_hdl_param unused)
0197 {
0198 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,IDE_RX_TASK_NO);
0199
0200
0201 bestcomm_glue_irq_disable(IDE_RX_TASK_NO);
0202
0203 pcmcia_ide_rxInterrupts++;
0204
0205 if (pcmcia_ide_hdl_task != 0) {
0206 rtems_event_send(pcmcia_ide_hdl_task,PCMCIA_IDE_INTERRUPT_EVENT);
0207 }
0208 }
0209
0210 static void pcmcia_ide_xmit_dmairq_hdl(rtems_irq_hdl_param unused)
0211 {
0212
0213 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,IDE_TX_TASK_NO);
0214
0215
0216 bestcomm_glue_irq_disable(IDE_TX_TASK_NO);
0217
0218 pcmcia_ide_txInterrupts++;
0219
0220 if (pcmcia_ide_hdl_task != 0) {
0221 rtems_event_send(pcmcia_ide_hdl_task,PCMCIA_IDE_INTERRUPT_EVENT);
0222 }
0223 }
0224
0225
0226 void mpc5200_pcmciaide_dma_init(int minor)
0227 {
0228 TaskSetupParamSet_t rxParam;
0229 TaskSetupParamSet_t txParam;
0230
0231
0232
0233 bestcomm_glue_init();
0234
0235
0236
0237 rxParam.NumBD = PCMCIA_IDE_DMA_RD_BD_CNT;
0238 rxParam.Size.MaxBuf = PCMCIA_IDE_RD_SECTOR_SIZE;
0239 rxParam.Initiator = INITIATOR_ALWAYS;
0240 rxParam.StartAddrSrc =
0241 (uint32)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD];
0242 rxParam.IncrSrc = 0;
0243 rxParam.SzSrc = sizeof(uint16_t);
0244 rxParam.StartAddrDst = (uint32)NULL;
0245 rxParam.IncrDst = sizeof(uint16_t);
0246 rxParam.SzDst = sizeof(uint16_t);
0247
0248 pcmcia_ide_rxTaskId = TaskSetup(IDE_RX_TASK_NO,&rxParam );
0249
0250
0251
0252
0253 txParam.NumBD = PCMCIA_IDE_DMA_WR_BD_CNT;
0254 txParam.Size.MaxBuf = PCMCIA_IDE_WR_SECTOR_SIZE;
0255 txParam.Initiator = INITIATOR_ALWAYS;
0256 txParam.StartAddrSrc = (uint32)NULL;
0257 txParam.IncrSrc = sizeof(uint16_t);
0258 txParam.SzSrc = sizeof(uint16_t);
0259 txParam.StartAddrDst =
0260 (uint32)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD];
0261 txParam.IncrDst = 0;
0262 txParam.SzDst = sizeof(uint16_t);
0263
0264 pcmcia_ide_txTaskId = TaskSetup( IDE_TX_TASK_NO, &txParam );
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 bestcomm_glue_irq_install(IDE_TX_TASK_NO,pcmcia_ide_xmit_dmairq_hdl,NULL);
0276 bestcomm_glue_irq_install(IDE_RX_TASK_NO,pcmcia_ide_recv_dmairq_hdl,NULL);
0277 }
0278 #endif
0279
0280 void mpc5200_pcmciaide_dma_blockop(bool is_write,
0281 int minor,
0282 uint16_t block_size,
0283 rtems_blkdev_sg_buffer *bufs,
0284 uint32_t *cbuf,
0285 uint32_t *pos)
0286
0287 {
0288 #if IDE_USE_DMA
0289
0290
0291
0292
0293
0294
0295 uint32_t buf_idx,bufs_from_dma, bufs_to_dma,bufs_total;
0296 uint32_t bds_free;
0297 uint32_t llength;
0298 rtems_status_code rc = RTEMS_SUCCESSFUL;
0299 rtems_event_set events;
0300 BDIdx nxt_bd_idx;
0301 bool use_irq = (_System_state_Current == SYSTEM_STATE_UP);
0302
0303
0304
0305 llength = 0;
0306 buf_idx = 0;
0307 bufs += *cbuf;
0308 while (llength < block_size) {
0309 llength += bufs[buf_idx++].length;
0310 }
0311 bufs_from_dma = 0;
0312 bufs_to_dma = 0;
0313 bufs_total = buf_idx;
0314
0315
0316
0317 bds_free = is_write ? PCMCIA_IDE_DMA_WR_BD_CNT : PCMCIA_IDE_DMA_RD_BD_CNT;
0318
0319
0320
0321 while ((rc == RTEMS_SUCCESSFUL) &&
0322 (bufs_from_dma < bufs_total)) {
0323
0324 while ((rc == RTEMS_SUCCESSFUL) &&
0325 (bufs_to_dma < bufs_total) &&
0326 (bds_free > 0)) {
0327
0328
0329
0330 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,(is_write
0331 ? IDE_TX_TASK_NO
0332 : IDE_RX_TASK_NO));
0333 if (is_write) {
0334 TaskBDAssign(pcmcia_ide_txTaskId ,
0335 (void *)bufs[bufs_to_dma].buffer,
0336 (void *)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD],
0337 bufs[bufs_to_dma].length,
0338 0);
0339 #if IDE_USE_STATISTICS
0340 mpc5200_pcmciaide_write_block_block_cnt++;
0341 #endif
0342 }
0343 else {
0344 TaskBDAssign(pcmcia_ide_rxTaskId ,
0345 (void *)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD],
0346 (void *)bufs[bufs_to_dma].buffer,
0347 bufs[bufs_to_dma].length,
0348 0);
0349 #if IDE_USE_STATISTICS
0350 mpc5200_pcmciaide_read_block_block_cnt++;
0351 #endif
0352 }
0353 bufs_to_dma ++;
0354 bds_free --;
0355 }
0356 if (is_write) {
0357 TaskStart( pcmcia_ide_txTaskId, TASK_AUTOSTART_DISABLE,
0358 pcmcia_ide_txTaskId, TASK_INTERRUPT_DISABLE );
0359 }
0360 else {
0361 TaskStart( pcmcia_ide_rxTaskId, TASK_AUTOSTART_DISABLE,
0362 pcmcia_ide_rxTaskId, TASK_INTERRUPT_DISABLE );
0363 }
0364 if (use_irq) {
0365
0366
0367
0368
0369 pcmcia_ide_hdl_task = rtems_task_self();
0370 bestcomm_glue_irq_enable((is_write
0371 ? IDE_TX_TASK_NO
0372 : IDE_RX_TASK_NO));
0373
0374 rtems_event_receive(PCMCIA_IDE_INTERRUPT_EVENT,
0375 RTEMS_WAIT | RTEMS_EVENT_ANY,
0376 RTEMS_NO_TIMEOUT, &events);
0377
0378 pcmcia_ide_hdl_task = 0;
0379 }
0380 else {
0381
0382
0383
0384
0385
0386
0387 volatile int32_t i;
0388 for (i = 0;i < 10000;i++) {};
0389 }
0390
0391 do {
0392 nxt_bd_idx = TaskBDRelease(is_write
0393 ? pcmcia_ide_txTaskId
0394 : pcmcia_ide_rxTaskId);
0395 if ((nxt_bd_idx != TASK_ERR_BD_RING_EMPTY) &&
0396 (nxt_bd_idx != TASK_ERR_BD_BUSY)) {
0397 (*cbuf)++;
0398 (*pos) += bufs[bufs_from_dma].length;
0399 bufs_from_dma++;
0400 bds_free++;
0401 }
0402 } while ((nxt_bd_idx != TASK_ERR_BD_RING_EMPTY) &&
0403 (nxt_bd_idx != TASK_ERR_BD_BUSY) &&
0404 (bufs_from_dma < bufs_to_dma));
0405 }
0406 #endif
0407 }
0408
0409
0410 static void mpc5200_pcmciaide_read_block(int minor, uint32_t block_size,
0411 rtems_blkdev_sg_buffer *bufs, uint32_t *cbuf, uint32_t *pos)
0412 {
0413
0414 volatile uint32_t *ata_reg=mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD];
0415 uint16_t cnt = 0;
0416 uint16_t *lbuf = (uint16_t*)((uint8_t*)(bufs[(*cbuf)].buffer)+(*pos));
0417 uint32_t llength = bufs[(*cbuf)].length;
0418 bool use_dma;
0419
0420 #if IDE_USE_STATISTICS
0421 mpc5200_pcmciaide_read_block_call_cnt++;
0422 #endif
0423 #if IDE_READ_USE_DMA
0424
0425
0426
0427
0428
0429 use_dma = true;
0430
0431 #else
0432 use_dma = false;
0433 #endif
0434 if (use_dma) {
0435
0436
0437
0438
0439
0440 while ((GET_UP_BYTE_OF_MPC5200_ATA_DRIVE_REG((volatile uint32_t)
0441 (mpc5200.ata_dctr_dasr)) &
0442 IDE_REGISTER_STATUS_DRQ) == 0);
0443
0444
0445
0446
0447
0448 mpc5200_pcmciaide_dma_blockop(FALSE,
0449 minor,
0450 block_size,bufs,cbuf,pos);
0451 }
0452 else {
0453 #if IDE_USE_READ_PIO_OPT
0454 while(cnt < block_size) {
0455
0456 *lbuf++ = GET_UP_WORD_OF_MPC5200_ATA_DRIVE_REG(*(volatile uint32_t *)(ata_reg));
0457 cnt += 2;
0458 (*pos) += 2;
0459
0460 if((*pos) == llength) {
0461
0462 (*pos) = 0;
0463 (*cbuf)++;
0464 lbuf = bufs[(*cbuf)].buffer;
0465 llength = bufs[(*cbuf)].length;
0466
0467 }
0468 }
0469 #else
0470
0471 while((GET_UP_BYTE_OF_MPC5200_ATA_DRIVE_REG((volatile uint32_t)(mpc5200.ata_dctr_dasr)) & IDE_REGISTER_STATUS_DRQ) && (cnt < block_size)) {
0472
0473 *lbuf++ = *(volatile uint16_t *)(ata_reg);
0474 cnt += 2;
0475 (*pos) += 2;
0476
0477 if((*pos) == llength) {
0478 (*pos) = 0;
0479 (*cbuf)++;
0480 lbuf = bufs[(*cbuf)].buffer;
0481 llength = bufs[(*cbuf)].length;
0482 }
0483 }
0484 #endif
0485 }
0486 }
0487
0488 static void mpc5200_pcmciaide_write_block(int minor, uint32_t block_size,
0489 rtems_blkdev_sg_buffer *bufs, uint32_t *cbuf, uint32_t *pos)
0490 {
0491
0492
0493 volatile uint32_t *ata_reg = mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD];
0494 uint16_t cnt = 0;
0495 uint16_t *lbuf = (uint16_t *)((uint8_t *)(bufs[(*cbuf)].buffer) + (*pos));
0496 uint32_t llength = bufs[(*cbuf)].length;
0497 bool use_dma;
0498
0499 #if IDE_USE_STATISTICS
0500 mpc5200_pcmciaide_write_block_call_cnt++;
0501 #endif
0502 #if IDE_WRITE_USE_DMA
0503
0504
0505
0506
0507
0508 use_dma = true;
0509 #else
0510 use_dma = false;
0511 #endif
0512
0513 if (use_dma) {
0514
0515
0516
0517
0518
0519 while ((GET_UP_BYTE_OF_MPC5200_ATA_DRIVE_REG((volatile uint32_t)
0520 (mpc5200.ata_dctr_dasr)) &
0521 IDE_REGISTER_STATUS_DRQ) == 0);
0522
0523
0524
0525
0526
0527 mpc5200_pcmciaide_dma_blockop(true,
0528 minor,
0529 block_size,bufs,cbuf,pos);
0530 }
0531 else {
0532 #if IDE_USE_WRITE_PIO_OPT
0533 while(cnt < block_size) {
0534 int32_t loop_cnt,loop_max;
0535
0536 #if IDE_USE_STATISTICS
0537 mpc5200_pcmciaide_write_block_block_cnt++;
0538 #endif
0539
0540 loop_max = llength - (*pos) ;
0541 if (loop_max > (block_size - cnt)) {
0542 loop_max = (block_size - cnt);
0543 }
0544 for (loop_cnt = loop_max/2;loop_cnt > 0;loop_cnt--) {
0545 *(volatile uint32_t *)(ata_reg) =
0546 SET_UP_WORD_OF_MPC5200_ATA_DRIVE_REG(*lbuf++);
0547 }
0548 cnt += loop_max;
0549 (*pos) += loop_max;
0550
0551 if((*pos) == llength) {
0552
0553 (*pos) = 0;
0554 (*cbuf)++;
0555 lbuf = bufs[(*cbuf)].buffer;
0556 llength = bufs[(*cbuf)].length;
0557 }
0558 }
0559 #else
0560 while((GET_UP_BYTE_OF_MPC5200_ATA_DRIVE_REG((volatile uint32_t)(mpc5200.ata_dctr_dasr))
0561 & IDE_REGISTER_STATUS_DRQ)
0562 && (cnt < block_size)) {
0563 *(volatile uint16_t *)(ata_reg) = *lbuf++;
0564 cnt += 2;
0565 (*pos) += 2;
0566
0567 if((*pos) == llength) {
0568 (*pos) = 0;
0569 (*cbuf)++;
0570 lbuf = bufs[(*cbuf)].buffer;
0571 llength = bufs[(*cbuf)].length;
0572 }
0573 }
0574 #endif
0575 }
0576 }
0577
0578 static int mpc5200_pcmciaide_control(int minor, uint32_t cmd, void * arg)
0579 {
0580 return RTEMS_SUCCESSFUL;
0581 }
0582
0583 static void mpc5200_pcmciaide_initialize(int minor)
0584 {
0585 #if defined (MPC5200_BOARD_BRS5L)
0586 struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[GPT7]);
0587
0588
0589 gpt->emsel = (GPT_EMSEL_GPIO_OUT_HIGH | GPT_EMSEL_TIMER_MS_GPIO);
0590 #endif
0591
0592 mpc5200.ata_hcfg |= (ATA_HCFG_SMR | ATA_HCFG_FR);
0593 mpc5200.ata_hcfg &= ~(ATA_HCFG_SMR | ATA_HCFG_FR);
0594
0595
0596 mpc5200_pcmciaide_config_io_speed(minor, ATA_MODES_PIO3);
0597
0598
0599 mpc5200.ata_hcfg |= ATA_HCFG_IORDY;
0600
0601 #ifdef IDE_USE_INT
0602 mpc5200.ata_hcfg |= ATA_HCFG_IE ;
0603 #endif
0604
0605 #if IDE_USE_DMA
0606 mpc5200_pcmciaide_dma_init(minor);
0607 #endif
0608 }
0609
0610
0611
0612
0613
0614
0615 ide_ctrl_fns_t mpc5200_pcmciaide_ctrl_fns =
0616 {
0617 mpc5200_pcmciaide_probe,
0618 mpc5200_pcmciaide_initialize,
0619 mpc5200_pcmciaide_control,
0620 mpc5200_pcmciaide_read_reg,
0621 mpc5200_pcmciaide_write_reg,
0622 mpc5200_pcmciaide_read_block,
0623 mpc5200_pcmciaide_write_block,
0624 mpc5200_pcmciaide_config_io_speed
0625 };
0626