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 |
---|
118 | static TaskId pcmcia_ide_rxTaskId; /* SDMA RX task ID */ |
---|
119 | static 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 | |
---|
123 | bool mpc5200_dma_task_started[2] = {false,false}; |
---|
124 | #endif /* IDE_USE_DMA */ |
---|
125 | |
---|
126 | #if IDE_USE_STATISTICS |
---|
127 | uint32_t mpc5200_pcmciaide_write_block_call_cnt = 0; |
---|
128 | uint32_t mpc5200_pcmciaide_write_block_block_cnt = 0; |
---|
129 | uint32_t mpc5200_pcmciaide_read_block_call_cnt = 0; |
---|
130 | uint32_t mpc5200_pcmciaide_read_block_block_cnt = 0; |
---|
131 | #endif |
---|
132 | |
---|
133 | extern volatile uint32_t * mpc5200_ata_drive_regs[]; |
---|
134 | extern uint32_t ata_pio_timings[2][6]; |
---|
135 | |
---|
136 | void 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 | */ |
---|
141 | static 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 | |
---|
184 | static 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 | |
---|
224 | static 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 | |
---|
235 | static 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 | |
---|
248 | uint32_t pcmcia_ide_rxInterrupts; |
---|
249 | uint32_t pcmcia_ide_txInterrupts; |
---|
250 | volatile rtems_id pcmcia_ide_hdl_task = 0; |
---|
251 | /* |
---|
252 | * MPC5200 BestComm interrupt handlers |
---|
253 | */ |
---|
254 | static 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 | |
---|
268 | static 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 | |
---|
284 | void 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 | |
---|
338 | void 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 | |
---|
468 | static 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 | |
---|
546 | static 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 | |
---|
636 | static int mpc5200_pcmciaide_control(int minor, uint32_t cmd, void * arg) |
---|
637 | { |
---|
638 | return RTEMS_SUCCESSFUL; |
---|
639 | } |
---|
640 | |
---|
641 | static 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 | */ |
---|
673 | ide_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 | |
---|