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

Last change on this file since 36cb812 was 36cb812, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 12/18/06 at 09:46:59

corrected bug in ata.c to avoid lockup of libblock
added remote frequest support to gen5200 BSP

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