Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:52

0001 /*
0002  * RTEMS generic MPC5200 BSP
0003  *
0004  * RTEMS MPC5x00 PCMCIA IDE harddisk driver
0005  *
0006  * This file contains the BSP layer for PCMCIA IDE access below the
0007  * libchip IDE harddisc driver based on a board specific driver from
0008  * Eugeny S. Mints, Oktet
0009  */
0010 
0011 /*
0012  * Copyright (c) 2003 IMD Ingenieurbuero fuer Microcomputertechnik
0013  * All rights reserved.
0014  * Copyright (c) 2003 IPR Engineering
0015  * Copyright (c) 2005 embedded brains GmbH & Co. KG
0016  *
0017  * The license and distribution terms for this file may be
0018  * found in the file LICENSE in this distribution or at
0019  * http://www.rtems.org/license/LICENSE.
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 /* DMA supported PIO mode is broken */
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 /* Task number assignment */
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;  /* SDMA RX task ID */
0061 static TaskId pcmcia_ide_txTaskId;  /* SDMA TX task ID */
0062 #define PCMCIA_IDE_RD_SECTOR_SIZE 512   /* FIXME: make this better... */
0063 #define PCMCIA_IDE_WR_SECTOR_SIZE 512   /* FIXME: make this better... */
0064 
0065 bool mpc5200_dma_task_started[2] = {false,false};
0066 #endif /* IDE_USE_DMA */
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  * support functions for PCMCIA IDE IF
0082  */
0083 static bool mpc5200_pcmciaide_probe(int minor)
0084   {
0085   bool ide_card_plugged = false; /* assume: we don't have a card plugged in */
0086   struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[GPT2]);
0087 
0088   #ifdef MPC5200_BOARD_DP2
0089     /* Deactivate RESET signal */
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     /* FIXME */
0098     volatile int i = 0;
0099     while (++i < 20000000);
0100   #endif
0101 
0102   /* enable card detection on GPT2 */
0103   gpt->emsel = (GPT_EMSEL_GPIO_IN | GPT_EMSEL_TIMER_MS_GPIO);
0104 
0105 #if defined (MPC5200_BOARD_BRS5L)
0106   /* Check for card detection (-CD0) */
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   /* set timings according according to selected ATA mode */
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  * MPC5200 BestComm interrupt handlers
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 /*Disable receive ints*/
0201   bestcomm_glue_irq_disable(IDE_RX_TASK_NO);
0202 
0203   pcmcia_ide_rxInterrupts++;        /* Rx int has occurred */
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   /*Disable transmit ints*/
0216   bestcomm_glue_irq_disable(IDE_TX_TASK_NO);
0217 
0218   pcmcia_ide_txInterrupts++;        /* Tx int has occurred */
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;    /* RX task setup parameters */
0229   TaskSetupParamSet_t   txParam;    /* TX task setup parameters */
0230   /*
0231    * Init Bestcomm system
0232    */
0233   bestcomm_glue_init();
0234   /*
0235    * Setup the SDMA RX task.
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);  /* XXX: set this to 32 bit? */
0247 
0248   pcmcia_ide_rxTaskId  = TaskSetup(IDE_RX_TASK_NO,&rxParam );
0249 
0250   /*
0251    * Setup the TX task.
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); /* do not set this to 32 bit! */
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    * FIXME: Init BD rings
0267    */
0268   /*
0269    * Enable the SmartDMA transmit/receive task.
0270    * do not enable interrupts to CPU
0271    */
0272   /*
0273    * connect interrupt handlers
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 /* IDE_USE_DMA */
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    * Nameing:
0291    * - a block is one unit of data on disk (multiple sectors)
0292    * - a buffer is a contignuous chunk of data in memory
0293    * a block on disk may be filled with data from several buffers
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    * determine number of blocks
0304    */
0305   llength = 0;
0306   buf_idx = 0;
0307   bufs += *cbuf; /* *cbuf is the index of the next buffer to send in this transaction */
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    * here all BDs should be unused
0316    */
0317   bds_free = is_write ? PCMCIA_IDE_DMA_WR_BD_CNT : PCMCIA_IDE_DMA_RD_BD_CNT;
0318   /*
0319    * repeat, until all bufs are transferred
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        * fill in BD, set interrupt if needed
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/* flags */);
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/* flags */);
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        * enable interrupts, wait for interrupt event
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        * HACK: just wait some time...
0383        */
0384       /*
0385        * FIXME: poll, until SDMA is finished
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 /* IDE_USE_DMA */
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    * FIXME: walk through buffer list. If any buffer has other size than default,
0426    * then do not use DMA
0427    * Is this needed?
0428    */
0429   use_dma = true;
0430   /* use_dma = false; */
0431 #else
0432   use_dma = false;
0433 #endif
0434   if (use_dma) {
0435     /*
0436      * FIXME: wait for DRQ ready
0437      * check, that once DRQ is ready, we really can send ALL data for this
0438      * type of transfer mode
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      * translate (part of) buffer list into DMA BDs
0445      * only last (available) DMA BD sends interrupt
0446      * DMA BDs may get ready as soon as possible
0447      */
0448     mpc5200_pcmciaide_dma_blockop(FALSE, /* read operation */
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)); /* only 16 bit data port */
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); /* only 16 bit data port */
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    * FIXME: walk through buffer list. If any buffer has other size than default,
0505    * then do not use DMA
0506    * Is this needed?
0507    */
0508   use_dma = true;
0509 #else
0510   use_dma = false;
0511 #endif
0512 
0513   if (use_dma) {
0514     /*
0515      * wait for DRQ ready
0516      * FIXME: check, that once DRQ is ready, we really can send ALL data for this
0517      * type of transfer mode
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      * translate (part of) buffer list into DMA BDs
0524      * only last (available) DMA BD sends interrupt
0525      * DMA BDs may get ready as soon as possible
0526      */
0527     mpc5200_pcmciaide_dma_blockop(true, /* write opeartion */
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++); /* only 16 bit data port */
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++; /* only 16 bit data port */
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   /* invert ATA reset on GPT7 */
0589   gpt->emsel = (GPT_EMSEL_GPIO_OUT_HIGH | GPT_EMSEL_TIMER_MS_GPIO);
0590 #endif
0591   /* reset ata host contr. and FIFO */
0592   mpc5200.ata_hcfg |= (ATA_HCFG_SMR | ATA_HCFG_FR);
0593   mpc5200.ata_hcfg &= ~(ATA_HCFG_SMR | ATA_HCFG_FR);
0594 
0595   /* for the first access set lowest performance transfer mode to PIO3 */
0596   mpc5200_pcmciaide_config_io_speed(minor, ATA_MODES_PIO3);
0597 
0598   /* enable PIO operations (PIO 3/4) */
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  * The following table configures the functions used for IDE drivers
0613  * in this BSP.
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