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

4.115
Last change on this file since d7a267b3 was d7a267b3, checked in by Sebastian Huber <sebastian.huber@…>, on 10/10/14 at 07:43:59

bsp/gen5200: Fix warnings

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