source: rtems/c/src/lib/libbsp/powerpc/gen5200/ide/pcmcia_ide.c @ 47fb2fe

4.115
Last change on this file since 47fb2fe was 47fb2fe, checked in by Sebastian Huber <sebastian.huber@…>, on 04/11/13 at 15:22:02

bsp/mpc5200: Add MPC5200_BOARD prefix

  • Property mode set to 100644
File size: 21.8 KB
Line 
1/*===============================================================*\
2| Project: RTEMS generic MPC5200 BSP                              |
3+-----------------------------------------------------------------+
4| Partially based on the code references which are named below.   |
5| Adaptions, modifications, enhancements and any recent parts of  |
6| the code are:                                                   |
7|                    Copyright (c) 2005                           |
8|                    Embedded Brains GmbH                         |
9|                    Obere Lagerstr. 30                           |
10|                    D-82178 Puchheim                             |
11|                    Germany                                      |
12|                    rtems@embedded-brains.de                     |
13+-----------------------------------------------------------------+
14| The license and distribution terms for this file may be         |
15| found in the file LICENSE in this distribution or at            |
16|                                                                 |
17| http://www.rtems.com/license/LICENSE.                           |
18|                                                                 |
19+-----------------------------------------------------------------+
20| this file contains the PCMCIA IDE access functions              |
21\*===============================================================*/
22/***********************************************************************/
23/*                                                                     */
24/*   Module:       pcmcia_ide.c                                        */
25/*   Date:         07/17/2003                                          */
26/*   Purpose:      RTEMS MPC5x00 PCMCIA IDE harddisk driver            */
27/*                                                                     */
28/*---------------------------------------------------------------------*/
29/*                                                                     */
30/*   Description:                                                      */
31/*                                                                     */
32/*---------------------------------------------------------------------*/
33/*                                                                     */
34/*   Code                                                              */
35/*   References:   RTEMS MBX8xx PCMCIA IDE harddisc driver             */
36/*   Module:       pcmcia_ide.c                                        */
37/*   Project:      RTEMS 4.6.0pre1 / Mbx8xx BSP                        */
38/*   Version                                                           */
39/*   Date:         01/14/2003                                          */
40/*                                                                     */
41/*   Author(s) / Copyright(s):                                         */
42/*                                                                     */
43/*                    Copyright (c) 2003 IMD                           */
44/*      Ingenieurbuero fuer Microcomputertechnik Th. Doerfler          */
45/*               <Thomas.Doerfler@imd-systems.de>                      */
46/*                       all rights reserved                           */
47/*                                                                     */
48/*  this file contains the BSP layer for PCMCIA IDE access below the   */
49/*  libchip IDE harddisc driver based on a board specific driver from  */
50/*  Eugeny S. Mints, Oktet                                             */
51/*                                                                     */
52/*  The license and distribution terms for this file may be            */
53/*  found in the file LICENSE in this distribution or at               */
54/*  http://www.rtems.com/license/LICENSE.                         */
55/*                                                                     */
56/*---------------------------------------------------------------------*/
57/*                                                                     */
58/*   Partially based on the code references which are named above.     */
59/*   Adaptions, modifications, enhancements and any recent parts of    */
60/*   the code are under the right of                                   */
61/*                                                                     */
62/*         IPR Engineering, Dachauer Straße 38, D-80335 MÃŒnchen        */
63/*                        Copyright(C) 2003                            */
64/*                                                                     */
65/*---------------------------------------------------------------------*/
66/*                                                                     */
67/*   IPR Engineering makes no representation or warranties with        */
68/*   respect to the performance of this computer program, and          */
69/*   specifically disclaims any responsibility for any damages,        */
70/*   special or consequential, connected with the use of this program. */
71/*                                                                     */
72/*---------------------------------------------------------------------*/
73/*                                                                     */
74/*   Version history:  1.0                                             */
75/*                                                                     */
76/***********************************************************************/
77
78#include <rtems.h>
79#include <rtems/error.h>
80#include <bsp.h>
81#include <bsp/irq.h>
82#include "../include/mpc5200.h"
83#include "./pcmcia_ide.h"
84
85#include <libchip/ide_ctrl.h>
86#include <libchip/ide_ctrl_cfg.h>
87#include <libchip/ide_ctrl_io.h>
88#include <string.h>
89
90#ifndef MIN
91#define MIN(a,b) (((a)<(b))?(a):(b))
92#endif
93#define IDE_DMA_TEST            FALSE
94
95/* DMA supported PIO mode is broken */
96#define IDE_USE_INT             TRUE
97#define IDE_READ_USE_DMA        FALSE
98#define IDE_USE_READ_PIO_OPT    FALSE
99#define IDE_WRITE_USE_DMA       FALSE
100#define IDE_USE_WRITE_PIO_OPT   FALSE
101#define IDE_USE_DMA (IDE_READ_USE_DMA || IDE_WRITE_USE_DMA)
102
103#define IDE_USE_STATISTICS      TRUE
104
105#if IDE_USE_DMA
106#define PCMCIA_IDE_DMA_WR_BD_CNT 2
107#define PCMCIA_IDE_DMA_RD_BD_CNT 2
108#define PCMCIA_IDE_INTERRUPT_EVENT RTEMS_EVENT_2
109/* Task number assignment */
110#include "../bestcomm/bestcomm_glue.h"
111#include "../bestcomm/bestcomm_api.h"
112#include "../bestcomm/task_api/bestcomm_cntrl.h"
113#include "../bestcomm/task_api/tasksetup_bdtable.h"
114
115#define IDE_RX_TASK_NO TASK_GEN_DP_BD_0
116#define IDE_TX_TASK_NO TASK_GEN_DP_BD_1
117static TaskId pcmcia_ide_rxTaskId;      /* SDMA RX task ID */
118static TaskId pcmcia_ide_txTaskId;      /* SDMA TX task ID */
119#define PCMCIA_IDE_RD_SECTOR_SIZE 512   /* FIXME: make this better... */
120#define PCMCIA_IDE_WR_SECTOR_SIZE 512   /* FIXME: make this better... */
121
122bool mpc5200_dma_task_started[2] = {false,false};
123#endif /* IDE_USE_DMA */
124
125#if IDE_USE_STATISTICS
126uint32_t mpc5200_pcmciaide_write_block_call_cnt  = 0;
127uint32_t mpc5200_pcmciaide_write_block_block_cnt = 0;
128uint32_t mpc5200_pcmciaide_read_block_call_cnt   = 0;
129uint32_t mpc5200_pcmciaide_read_block_block_cnt  = 0;
130#endif
131
132extern volatile uint32_t * mpc5200_ata_drive_regs[];
133extern uint32_t ata_pio_timings[2][6];
134
135void mpc5200_pcmciaide_dma_blockop(
136  bool, int, uint16_t, rtems_blkdev_sg_buffer *, uint32_t *, uint32_t *);
137/*
138 * support functions for PCMCIA IDE IF
139 */
140bool mpc5200_pcmciaide_probe(int minor)
141  {
142  bool ide_card_plugged = false; /* assume: we don't have a card plugged in */
143  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[GPT2]);
144
145  #ifdef MPC5200_BOARD_DP2
146    /* Deactivate RESET signal */
147    rtems_interrupt_level level;
148    rtems_interrupt_disable(level);
149    mpc5200.gpiowe |= GPIO_W_PIN_PSC1_4;
150    mpc5200.gpiowod &= ~GPIO_W_PIN_PSC1_4;
151    mpc5200.gpiowdd |= GPIO_W_PIN_PSC1_4;
152    mpc5200.gpiowdo |= GPIO_W_PIN_PSC1_4;
153    rtems_interrupt_enable(level);
154    /* FIXME */
155    volatile int i = 0;
156    while (++i < 20000000);
157  #endif
158
159  /* enable card detection on GPT2 */
160  gpt->emsel = (GPT_EMSEL_GPIO_IN | GPT_EMSEL_TIMER_MS_GPIO);
161
162#if defined (MPC5200_BOARD_BRS5L)
163  /* Check for card detection (-CD0) */
164  if((gpt->status) & GPT_STATUS_PIN)
165    ide_card_plugged = false;
166  else
167#endif
168    ide_card_plugged = true;
169
170  return ide_card_plugged;
171
172  }
173
174#define DMA1_T0(val) BSP_BFLD32(COUNT_VAL(val), 0, 7)
175#define DMA1_TD(val) BSP_BFLD32(COUNT_VAL(val), 8, 15)
176#define DMA1_TK(val) BSP_BFLD32(COUNT_VAL(val), 16, 23)
177#define DMA1_TM(val) BSP_BFLD32(COUNT_VAL(val), 24, 31)
178
179#define DMA2_TH(val) BSP_BFLD32(COUNT_VAL(val), 0, 7)
180#define DMA2_TJ(val) BSP_BFLD32(COUNT_VAL(val), 8, 15)
181#define DMA2_TN(val) BSP_BFLD32(COUNT_VAL(val), 16, 23)
182
183rtems_status_code mpc5200_pcmciaide_config_io_speed(int minor, uint16_t modes_avail)
184  {
185  uint8_t pio_t0, pio_t2_8, pio_t2_16, pio_t4, pio_t1, pio_ta;
186
187  if((modes_avail & ATA_MODES_PIO4) != 0)
188    {
189
190    pio_t0    = ata_pio_timings[PIO_4][T0];
191    pio_t2_8  = ata_pio_timings[PIO_4][T2_8];
192    pio_t2_16 = ata_pio_timings[PIO_4][T2_16];
193    pio_t4    = ata_pio_timings[PIO_4][T4];
194    pio_t1    = ata_pio_timings[PIO_4][T1];
195    pio_ta    = ata_pio_timings[PIO_4][TA];
196
197    }
198  else
199    {
200
201    pio_t0    = ata_pio_timings[PIO_3][T0];
202    pio_t2_8  = ata_pio_timings[PIO_3][T2_8];
203    pio_t2_16 = ata_pio_timings[PIO_3][T2_16];
204    pio_t4    = ata_pio_timings[PIO_3][T4];
205    pio_t1    = ata_pio_timings[PIO_3][T1];
206    pio_ta    = ata_pio_timings[PIO_3][TA];
207
208    }
209
210  /* set timings according according to selected ATA mode */
211  mpc5200.ata_pio1 = ATA_PIO_TIMING_1(pio_t0, pio_t2_8, pio_t2_16);
212  mpc5200.ata_pio2 = ATA_PIO_TIMING_2(pio_t4, pio_t1, pio_ta);
213
214  mpc5200.ata_dma1 = DMA1_T0(120) | DMA1_TD(70) | DMA1_TK(25) | DMA1_TM(25);
215  mpc5200.ata_dma2 = DMA2_TH(10) | DMA2_TJ(5) | DMA2_TN(10);
216
217  return RTEMS_SUCCESSFUL;
218
219  }
220
221
222
223void mpc5200_pcmciaide_read_reg(int minor, int reg, uint16_t *value)
224  {
225  volatile uint32_t *ata_reg = mpc5200_ata_drive_regs[reg];
226
227  if(reg == IDE_REGISTER_DATA_WORD)
228    *value = *(volatile uint16_t *)(ata_reg);
229  else
230    *value = *(volatile uint8_t  *)(ata_reg);
231  }
232
233
234void mpc5200_pcmciaide_write_reg(int minor, int reg, uint16_t value)
235  {
236  volatile uint32_t *ata_reg = mpc5200_ata_drive_regs[reg];
237
238  if(reg == IDE_REGISTER_DATA_WORD)
239    *(volatile uint16_t *)(ata_reg) = value;
240  else
241    *(volatile uint8_t  *)(ata_reg) = value;
242  }
243
244#if IDE_USE_DMA
245
246
247uint32_t pcmcia_ide_rxInterrupts;
248uint32_t pcmcia_ide_txInterrupts;
249volatile rtems_id pcmcia_ide_hdl_task = 0;
250/*
251 * MPC5200 BestComm interrupt handlers
252 */
253static void pcmcia_ide_recv_dmairq_hdl(rtems_irq_hdl_param unused)
254{
255  SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,IDE_RX_TASK_NO);
256
257/*Disable receive ints*/
258  bestcomm_glue_irq_disable(IDE_RX_TASK_NO);
259
260  pcmcia_ide_rxInterrupts++;            /* Rx int has occurred */
261
262  if (pcmcia_ide_hdl_task != 0) {
263    rtems_event_send(pcmcia_ide_hdl_task,PCMCIA_IDE_INTERRUPT_EVENT);
264  }
265}
266
267static void pcmcia_ide_xmit_dmairq_hdl(rtems_irq_hdl_param unused)
268{
269
270  SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,IDE_TX_TASK_NO);
271
272  /*Disable transmit ints*/
273  bestcomm_glue_irq_disable(IDE_TX_TASK_NO);
274
275  pcmcia_ide_txInterrupts++;            /* Tx int has occurred */
276
277  if (pcmcia_ide_hdl_task != 0) {
278    rtems_event_send(pcmcia_ide_hdl_task,PCMCIA_IDE_INTERRUPT_EVENT);
279  }
280}
281
282
283void mpc5200_pcmciaide_dma_init(int minor)
284{
285  TaskSetupParamSet_t   rxParam;        /* RX task setup parameters     */
286  TaskSetupParamSet_t   txParam;        /* TX task setup parameters     */
287  /*
288   * Init Bestcomm system
289   */
290  bestcomm_glue_init();
291  /*
292   * Setup the SDMA RX task.
293   */
294  rxParam.NumBD        = PCMCIA_IDE_DMA_RD_BD_CNT;
295  rxParam.Size.MaxBuf  = PCMCIA_IDE_RD_SECTOR_SIZE;
296  rxParam.Initiator    = INITIATOR_ALWAYS;
297  rxParam.StartAddrSrc =
298    (uint32)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD];
299  rxParam.IncrSrc      = 0;
300  rxParam.SzSrc        = sizeof(uint16_t);
301  rxParam.StartAddrDst = (uint32)NULL;
302  rxParam.IncrDst      = sizeof(uint16_t);
303  rxParam.SzDst        = sizeof(uint16_t);  /* XXX: set this to 32 bit? */
304
305  pcmcia_ide_rxTaskId  = TaskSetup(IDE_RX_TASK_NO,&rxParam );
306
307  /*
308   * Setup the TX task.
309   */
310  txParam.NumBD        = PCMCIA_IDE_DMA_WR_BD_CNT;
311  txParam.Size.MaxBuf  = PCMCIA_IDE_WR_SECTOR_SIZE;
312  txParam.Initiator    = INITIATOR_ALWAYS;
313  txParam.StartAddrSrc = (uint32)NULL;
314  txParam.IncrSrc      = sizeof(uint16_t);
315  txParam.SzSrc        = sizeof(uint16_t); /* do not set this to 32 bit! */
316  txParam.StartAddrDst =
317    (uint32)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD];
318  txParam.IncrDst      = 0;
319  txParam.SzDst        = sizeof(uint16_t);
320
321  pcmcia_ide_txTaskId  = TaskSetup( IDE_TX_TASK_NO, &txParam );
322  /*
323   * FIXME: Init BD rings
324   */
325  /*
326   * Enable the SmartDMA transmit/receive task.
327   * do not enable interrupts to CPU
328   */
329  /*
330   * connect interrupt handlers
331   */
332  bestcomm_glue_irq_install(IDE_TX_TASK_NO,pcmcia_ide_xmit_dmairq_hdl,NULL);
333  bestcomm_glue_irq_install(IDE_RX_TASK_NO,pcmcia_ide_recv_dmairq_hdl,NULL);
334}
335#endif /* IDE_USE_DMA */
336
337void mpc5200_pcmciaide_dma_blockop(bool is_write,
338                                   int minor,
339                                   uint16_t block_size,
340                                   rtems_blkdev_sg_buffer *bufs,
341                                   uint32_t *cbuf,
342                                   uint32_t *pos)
343
344{
345#if IDE_USE_DMA
346  /*
347   * Nameing:
348   * - a block is one unit of data on disk (multiple sectors)
349   * - a buffer is a contignuous chunk of data in memory
350   * a block on disk may be filled with data from several buffers
351   */
352  uint32_t buf_idx,bufs_from_dma, bufs_to_dma,bufs_total;
353  uint32_t bds_free;
354  uint32_t llength;
355  rtems_status_code rc = RTEMS_SUCCESSFUL;
356  rtems_event_set events;
357  BDIdx nxt_bd_idx;
358  bool use_irq = (_System_state_Current == SYSTEM_STATE_UP);
359  /*
360   * determine number of blocks
361   */
362  llength = 0;
363  buf_idx = 0;
364  bufs += *cbuf; /* *cbuf is the index of the next buffer to send in this transaction */
365  while (llength < block_size) {
366    llength += bufs[buf_idx++].length;
367  }
368  bufs_from_dma = 0;
369  bufs_to_dma   = 0;
370  bufs_total    = buf_idx;
371  /*
372   * here all BDs should be unused
373   */
374  bds_free = is_write ? PCMCIA_IDE_DMA_WR_BD_CNT : PCMCIA_IDE_DMA_RD_BD_CNT;
375  /*
376   * repeat, until all bufs are transferred
377   */
378  while ((rc == RTEMS_SUCCESSFUL) &&
379         (bufs_from_dma < bufs_total)) {
380
381    while ((rc == RTEMS_SUCCESSFUL) &&
382           (bufs_to_dma < bufs_total) &&
383           (bds_free > 0)) {
384      /*
385       * fill in BD, set interrupt if needed
386       */
387    SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,(is_write
388                                          ? IDE_TX_TASK_NO
389                                          : IDE_RX_TASK_NO));
390      if (is_write) {
391        TaskBDAssign(pcmcia_ide_txTaskId ,
392                     (void *)bufs[bufs_to_dma].buffer,
393                     (void *)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD],
394                     bufs[bufs_to_dma].length,
395                     0/* flags */);
396#if IDE_USE_STATISTICS
397        mpc5200_pcmciaide_write_block_block_cnt++;
398#endif
399      }
400      else {
401        TaskBDAssign(pcmcia_ide_rxTaskId ,
402                     (void *)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD],
403                     (void *)bufs[bufs_to_dma].buffer,
404                     bufs[bufs_to_dma].length,
405                     0/* flags */);
406#if IDE_USE_STATISTICS
407        mpc5200_pcmciaide_read_block_block_cnt++;
408#endif
409      }
410      bufs_to_dma ++;
411      bds_free    --;
412    }
413    if (is_write) {
414      TaskStart( pcmcia_ide_txTaskId, TASK_AUTOSTART_DISABLE,
415                 pcmcia_ide_txTaskId, TASK_INTERRUPT_DISABLE );
416    }
417    else {
418      TaskStart( pcmcia_ide_rxTaskId, TASK_AUTOSTART_DISABLE,
419                 pcmcia_ide_rxTaskId, TASK_INTERRUPT_DISABLE );
420    }
421    if (use_irq) {
422
423      /*
424       * enable interrupts, wait for interrupt event
425       */
426      pcmcia_ide_hdl_task = rtems_task_self();
427      bestcomm_glue_irq_enable((is_write
428                                ? IDE_TX_TASK_NO
429                                : IDE_RX_TASK_NO));
430
431      rtems_event_receive(PCMCIA_IDE_INTERRUPT_EVENT,
432                          RTEMS_WAIT | RTEMS_EVENT_ANY,
433                          RTEMS_NO_TIMEOUT, &events);
434
435      pcmcia_ide_hdl_task = 0;
436    }
437    else {
438      /*
439       * HACK: just wait some time...
440       */
441      /*
442       * FIXME: poll, until SDMA is finished
443       */
444      volatile int32_t i;
445      for (i = 0;i < 10000;i++) {};
446    }
447
448    do {
449          nxt_bd_idx = TaskBDRelease(is_write
450                                                     ? pcmcia_ide_txTaskId
451                                                     : pcmcia_ide_rxTaskId);
452      if ((nxt_bd_idx != TASK_ERR_BD_RING_EMPTY) &&
453          (nxt_bd_idx != TASK_ERR_BD_BUSY)) {
454        (*cbuf)++;
455        (*pos) += bufs[bufs_from_dma].length;
456        bufs_from_dma++;
457        bds_free++;
458          }
459    } while ((nxt_bd_idx != TASK_ERR_BD_RING_EMPTY) &&
460             (nxt_bd_idx != TASK_ERR_BD_BUSY)       &&
461                 (bufs_from_dma < bufs_to_dma));
462  }
463#endif /* IDE_USE_DMA */
464}
465
466
467void mpc5200_pcmciaide_read_block(int minor, uint32_t block_size, rtems_blkdev_sg_buffer *bufs,
468                                  uint32_t *cbuf, uint32_t *pos)
469{
470
471  volatile uint32_t *ata_reg=mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD];
472  uint16_t  cnt = 0;
473  uint16_t *lbuf = (uint16_t*)((uint8_t*)(bufs[(*cbuf)].buffer)+(*pos));
474  uint32_t  llength = bufs[(*cbuf)].length;
475  bool      use_dma;
476
477#if IDE_USE_STATISTICS
478      mpc5200_pcmciaide_read_block_call_cnt++;
479#endif
480#if IDE_READ_USE_DMA
481  /*
482   * FIXME: walk through buffer list. If any buffer has other size than default,
483   * then do not use DMA
484   * Is this needed?
485   */
486  use_dma = true;
487  /* use_dma = false; */
488#else
489  use_dma = false;
490#endif
491  if (use_dma) {
492    /*
493     * FIXME: wait for DRQ ready
494     * check, that once DRQ is ready, we really can send ALL data for this
495     * type of transfer mode
496     */
497    while ((GET_UP_BYTE_OF_MPC5200_ATA_DRIVE_REG((volatile uint32_t)
498                                                 (mpc5200.ata_dctr_dasr)) &
499            IDE_REGISTER_STATUS_DRQ) == 0);
500    /*
501     * translate (part of) buffer list into DMA BDs
502     * only last (available) DMA BD sends interrupt
503     * DMA BDs may get ready as soon as possible
504     */
505    mpc5200_pcmciaide_dma_blockop(FALSE, /* read operation */
506                                  minor,
507                                  block_size,bufs,cbuf,pos);
508  }
509  else {
510#if IDE_USE_READ_PIO_OPT
511    while(cnt < block_size) {
512
513      *lbuf++ = GET_UP_WORD_OF_MPC5200_ATA_DRIVE_REG(*(volatile uint32_t *)(ata_reg)); /* only 16 bit data port */
514      cnt += 2;
515      (*pos) += 2;
516
517      if((*pos) == llength) {
518
519          (*pos) = 0;
520          (*cbuf)++;
521          lbuf = bufs[(*cbuf)].buffer;
522          llength = bufs[(*cbuf)].length;
523
524      }
525    }
526#else
527
528    while((GET_UP_BYTE_OF_MPC5200_ATA_DRIVE_REG((volatile uint32_t)(mpc5200.ata_dctr_dasr)) & IDE_REGISTER_STATUS_DRQ) && (cnt < block_size)) {
529
530      *lbuf++ = *(volatile uint16_t *)(ata_reg); /* only 16 bit data port */
531      cnt += 2;
532      (*pos) += 2;
533
534      if((*pos) == llength) {
535        (*pos) = 0;
536        (*cbuf)++;
537        lbuf = bufs[(*cbuf)].buffer;
538        llength = bufs[(*cbuf)].length;
539      }
540    }
541#endif
542  }
543}
544
545void mpc5200_pcmciaide_write_block(int minor, uint32_t block_size,
546                                   rtems_blkdev_sg_buffer *bufs, uint32_t *cbuf,
547                                   uint32_t *pos)
548
549{
550
551
552  volatile uint32_t *ata_reg = mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD];
553  uint16_t  cnt = 0;
554  uint16_t *lbuf = (uint16_t *)((uint8_t *)(bufs[(*cbuf)].buffer) + (*pos));
555  uint32_t  llength = bufs[(*cbuf)].length;
556  bool use_dma;
557
558#if IDE_USE_STATISTICS
559  mpc5200_pcmciaide_write_block_call_cnt++;
560#endif
561#if IDE_WRITE_USE_DMA
562  /*
563   * FIXME: walk through buffer list. If any buffer has other size than default,
564   * then do not use DMA
565   * Is this needed?
566   */
567  use_dma = true;
568#else
569  use_dma = false;
570#endif
571
572  if (use_dma) {
573    /*
574     * wait for DRQ ready
575     * FIXME: check, that once DRQ is ready, we really can send ALL data for this
576     * type of transfer mode
577     */
578    while ((GET_UP_BYTE_OF_MPC5200_ATA_DRIVE_REG((volatile uint32_t)
579                                                 (mpc5200.ata_dctr_dasr)) &
580            IDE_REGISTER_STATUS_DRQ) == 0);
581    /*
582     * translate (part of) buffer list into DMA BDs
583     * only last (available) DMA BD sends interrupt
584     * DMA BDs may get ready as soon as possible
585     */
586    mpc5200_pcmciaide_dma_blockop(true, /* write opeartion */
587                                  minor,
588                                  block_size,bufs,cbuf,pos);
589  }
590  else {
591#if IDE_USE_WRITE_PIO_OPT
592    while(cnt < block_size) {
593      int32_t loop_cnt,loop_max;
594
595#if IDE_USE_STATISTICS
596      mpc5200_pcmciaide_write_block_block_cnt++;
597#endif
598
599      loop_max = llength - (*pos) ;
600      if (loop_max > (block_size - cnt)) {
601        loop_max = (block_size - cnt);
602      }
603      for (loop_cnt = loop_max/2;loop_cnt > 0;loop_cnt--) {
604        *(volatile uint32_t *)(ata_reg) =
605          SET_UP_WORD_OF_MPC5200_ATA_DRIVE_REG(*lbuf++); /* only 16 bit data port */
606      }
607      cnt += loop_max;
608      (*pos) += loop_max;
609
610      if((*pos) == llength) {
611
612        (*pos) = 0;
613        (*cbuf)++;
614        lbuf = bufs[(*cbuf)].buffer;
615        llength = bufs[(*cbuf)].length;
616      }
617    }
618#else
619    while((GET_UP_BYTE_OF_MPC5200_ATA_DRIVE_REG((volatile uint32_t)(mpc5200.ata_dctr_dasr))
620           & IDE_REGISTER_STATUS_DRQ)
621          && (cnt < block_size)) {
622      *(volatile uint16_t *)(ata_reg) = *lbuf++; /* only 16 bit data port */
623      cnt += 2;
624      (*pos) += 2;
625
626      if((*pos) == llength) {
627        (*pos) = 0;
628        (*cbuf)++;
629        lbuf = bufs[(*cbuf)].buffer;
630        llength = bufs[(*cbuf)].length;
631      }
632    }
633#endif
634  }
635}
636
637int mpc5200_pcmciaide_control(int  minor, uint32_t cmd, void * arg)
638  {
639  return RTEMS_SUCCESSFUL;
640  }
641
642void mpc5200_pcmciaide_initialize(int minor)
643  {
644#if defined (MPC5200_BOARD_BRS5L)
645  struct mpc5200_gpt *gpt = (struct mpc5200_gpt *)(&mpc5200.gpt[GPT7]);
646
647  /* invert ATA reset on GPT7 */
648  gpt->emsel = (GPT_EMSEL_GPIO_OUT_HIGH | GPT_EMSEL_TIMER_MS_GPIO);
649#endif
650  /* reset ata host contr. and FIFO */
651  mpc5200.ata_hcfg |= (ATA_HCFG_SMR | ATA_HCFG_FR);
652  mpc5200.ata_hcfg &= ~(ATA_HCFG_SMR | ATA_HCFG_FR);
653
654  /* for the first access set lowest performance transfer mode to PIO3 */
655  mpc5200_pcmciaide_config_io_speed(minor, ATA_MODES_PIO3);
656
657  /* enable PIO operations (PIO 3/4) */
658  mpc5200.ata_hcfg |= ATA_HCFG_IORDY;
659
660#ifdef IDE_USE_INT
661  mpc5200.ata_hcfg |= ATA_HCFG_IE ;
662#endif
663
664#if IDE_USE_DMA
665  mpc5200_pcmciaide_dma_init(minor);
666#endif
667  }
668
669
670/*
671 * The following table configures the functions used for IDE drivers
672 * in this BSP.
673 */
674ide_ctrl_fns_t mpc5200_pcmciaide_ctrl_fns =
675  {
676  mpc5200_pcmciaide_probe,
677  mpc5200_pcmciaide_initialize,
678  mpc5200_pcmciaide_control,
679  mpc5200_pcmciaide_read_reg,
680  mpc5200_pcmciaide_write_reg,
681  mpc5200_pcmciaide_read_block,
682  mpc5200_pcmciaide_write_block,
683  mpc5200_pcmciaide_config_io_speed
684  };
685
Note: See TracBrowser for help on using the repository browser.