1 | /* |
---|
2 | * BRM driver |
---|
3 | * |
---|
4 | * COPYRIGHT (c) 2006. |
---|
5 | * Cobham Gaisler AB. |
---|
6 | * |
---|
7 | * The license and distribution terms for this file may be |
---|
8 | * found in the file LICENSE in this distribution or at |
---|
9 | * http://www.rtems.org/license/LICENSE. |
---|
10 | */ |
---|
11 | |
---|
12 | /********** Set defaults **********/ |
---|
13 | |
---|
14 | /* default to 16K memory layout */ |
---|
15 | #define DMA_MEM_128K |
---|
16 | #if !defined(DMA_MEM_128K) |
---|
17 | #define DMA_MEM_16K |
---|
18 | #endif |
---|
19 | |
---|
20 | #include <bsp.h> |
---|
21 | #include <rtems/libio.h> |
---|
22 | #include <stdlib.h> |
---|
23 | #include <stdio.h> |
---|
24 | #include <string.h> |
---|
25 | #include <assert.h> |
---|
26 | #include <ctype.h> |
---|
27 | #include <rtems/bspIo.h> |
---|
28 | |
---|
29 | #include <drvmgr/drvmgr.h> |
---|
30 | #include <bsp/b1553brm.h> |
---|
31 | #include <ambapp.h> |
---|
32 | #include <drvmgr/ambapp_bus.h> |
---|
33 | |
---|
34 | /* Uncomment for debug output */ |
---|
35 | /*#define DEBUG 1 |
---|
36 | #define FUNCDEBUG 1*/ |
---|
37 | #undef DEBUG |
---|
38 | #undef FUNCDEBUG |
---|
39 | |
---|
40 | /* EVENT_QUEUE_SIZE sets the size of the event queue |
---|
41 | */ |
---|
42 | #define EVENT_QUEUE_SIZE 1024 |
---|
43 | |
---|
44 | |
---|
45 | #define INDEX(x) ( x&(EVENT_QUEUE_SIZE-1) ) |
---|
46 | |
---|
47 | #if 0 |
---|
48 | #define DBG(x...) printk(x) |
---|
49 | #else |
---|
50 | #define DBG(x...) |
---|
51 | #endif |
---|
52 | |
---|
53 | #ifdef FUNCDEBUG |
---|
54 | #define FUNCDBG(x...) printk(x) |
---|
55 | #else |
---|
56 | #define FUNCDBG(x...) |
---|
57 | #endif |
---|
58 | |
---|
59 | #define READ_REG(address) (*(volatile unsigned int *)address) |
---|
60 | #define READ_DMA(address) _BRM_REG_READ16((unsigned int)address) |
---|
61 | static __inline__ unsigned short _BRM_REG_READ16(unsigned int addr) { |
---|
62 | unsigned short tmp; |
---|
63 | __asm__ (" lduha [%1]1, %0 " |
---|
64 | : "=r"(tmp) |
---|
65 | : "r"(addr) |
---|
66 | ); |
---|
67 | return tmp; |
---|
68 | } |
---|
69 | |
---|
70 | static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); |
---|
71 | static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); |
---|
72 | static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); |
---|
73 | static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); |
---|
74 | static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); |
---|
75 | static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); |
---|
76 | |
---|
77 | #define BRM_DRIVER_TABLE_ENTRY { brm_initialize, brm_open, brm_close, brm_read, brm_write, brm_control } |
---|
78 | |
---|
79 | static rtems_driver_address_table b1553brm_driver = BRM_DRIVER_TABLE_ENTRY; |
---|
80 | |
---|
81 | struct msg { |
---|
82 | unsigned short miw; |
---|
83 | unsigned short time; |
---|
84 | unsigned short data[32]; |
---|
85 | }; |
---|
86 | #if defined(DMA_MEM_128K) |
---|
87 | struct circ_buf { |
---|
88 | struct msg msgs[9]; |
---|
89 | }; |
---|
90 | #elif defined(DMA_MEM_16K) |
---|
91 | /* two message queue */ |
---|
92 | struct circ_buf_2 { |
---|
93 | struct msg msgs[2]; |
---|
94 | }; |
---|
95 | /* one message queue */ |
---|
96 | struct circ_buf_1 { |
---|
97 | struct msg msgs[1]; |
---|
98 | }; |
---|
99 | #endif |
---|
100 | |
---|
101 | struct irq_log_list { |
---|
102 | volatile unsigned short iiw; |
---|
103 | volatile unsigned short iaw; |
---|
104 | }; |
---|
105 | |
---|
106 | typedef struct { |
---|
107 | |
---|
108 | struct drvmgr_dev *dev; /* Driver manager device */ |
---|
109 | char devName[32]; /* Device Name */ |
---|
110 | struct brm_reg *regs; |
---|
111 | |
---|
112 | unsigned int memarea_base; |
---|
113 | unsigned int memarea_base_remote; |
---|
114 | unsigned int cfg_clksel; |
---|
115 | unsigned int cfg_clkdiv; |
---|
116 | unsigned int cfg_freq; |
---|
117 | |
---|
118 | /* BRM descriptors */ |
---|
119 | struct desc_table { |
---|
120 | volatile unsigned short ctrl; |
---|
121 | volatile unsigned short top; |
---|
122 | volatile unsigned short cur; |
---|
123 | volatile unsigned short bot; |
---|
124 | } *desc; |
---|
125 | |
---|
126 | volatile unsigned short *mem; |
---|
127 | /* bc mem struct */ |
---|
128 | struct { |
---|
129 | /* BC Descriptors */ |
---|
130 | struct { |
---|
131 | unsigned short ctrl; /* control */ |
---|
132 | unsigned short cw1; /* Command word 1*/ |
---|
133 | unsigned short cw2; /* Command word 1*/ |
---|
134 | unsigned short dptr; /* Data pointer in halfword offset from bcmem */ |
---|
135 | unsigned short tsw[2]; /* status word 1 & 2 */ |
---|
136 | unsigned short ba; /* branch address */ |
---|
137 | unsigned short timer; /* timer value */ |
---|
138 | } descs[128]; /* 2k (1024 half words) */ |
---|
139 | |
---|
140 | /* message data */ |
---|
141 | struct { |
---|
142 | unsigned short data[32]; /* 1 message's data */ |
---|
143 | } msg_data[128]; /* 8k */ |
---|
144 | |
---|
145 | #if defined(DMA_MEM_128K) |
---|
146 | /* offset to last 64bytes of 128k */ |
---|
147 | unsigned short unused[(64*1024-(128*8+128*32))-16*2]; |
---|
148 | #elif defined(DMA_MEM_16K) |
---|
149 | unsigned short unused[(8*1024-(128*8+128*32))-16*2]; |
---|
150 | #endif |
---|
151 | /* interrupt log at 64 bytes from end */ |
---|
152 | struct irq_log_list irq_logs[16]; |
---|
153 | } *bcmem; |
---|
154 | |
---|
155 | #if defined(DMA_MEM_128K) |
---|
156 | /* Memory structure of a RT being inited, just used |
---|
157 | * for RT initialization. |
---|
158 | * |
---|
159 | * *mesgs[32] fit each minimally 8 messages per sub address. |
---|
160 | */ |
---|
161 | struct { |
---|
162 | /* RX Sub Address descriptors */ |
---|
163 | struct desc_table rxsubs[32]; |
---|
164 | /* TX Sub Address descriptors */ |
---|
165 | struct desc_table txsubs[32]; |
---|
166 | /* RX mode code descriptors */ |
---|
167 | struct desc_table rxmodes[32]; |
---|
168 | /* TX mode code descriptors */ |
---|
169 | struct desc_table txmodes[32]; |
---|
170 | |
---|
171 | /* RX Sub Address messages */ |
---|
172 | struct circ_buf rxsuba_msgs[32]; |
---|
173 | /* TX Sub Address messages */ |
---|
174 | struct circ_buf txsuba_msgs[32]; |
---|
175 | /* RX Mode Code messages */ |
---|
176 | struct circ_buf rxmode_msgs[32]; |
---|
177 | /* RX Mode Code messages */ |
---|
178 | struct circ_buf txmode_msgs[32]; |
---|
179 | |
---|
180 | /* offset to last 64bytes of 128k: tot-used-needed */ |
---|
181 | unsigned short unused[(64*1024-(4*32*4+4*32*9*34))-16*2]; |
---|
182 | |
---|
183 | /* interrupt log at 64 bytes from end */ |
---|
184 | struct irq_log_list irq_logs[16]; |
---|
185 | } *rtmem; |
---|
186 | #elif defined(DMA_MEM_16K) |
---|
187 | /* Memory structure of a RT being inited, just used |
---|
188 | * for RT initialization. |
---|
189 | * |
---|
190 | * circ_buf_2 *mesgs[32] fit each minimally 2 messages per queue. |
---|
191 | * circ_buf_1 *mesgs[32] fit each minimally 1 messages per queue. |
---|
192 | */ |
---|
193 | struct { |
---|
194 | /* RX Sub Address descriptors */ |
---|
195 | struct desc_table rxsubs[32]; |
---|
196 | /* TX Sub Address descriptors */ |
---|
197 | struct desc_table txsubs[32]; |
---|
198 | /* RX mode code descriptors */ |
---|
199 | struct desc_table rxmodes[32]; |
---|
200 | /* TX mode code descriptors */ |
---|
201 | struct desc_table txmodes[32]; |
---|
202 | |
---|
203 | /* RX Sub Address messages */ |
---|
204 | struct circ_buf_2 rxsuba_msgs[32]; |
---|
205 | /* TX Sub Address messages */ |
---|
206 | struct circ_buf_2 txsuba_msgs[32]; |
---|
207 | /* RX Mode Code messages */ |
---|
208 | struct circ_buf_2 rxmode_msgs[32]; |
---|
209 | /* RX Mode Code messages */ |
---|
210 | struct circ_buf_1 txmode_msgs[32]; |
---|
211 | |
---|
212 | /* offset to last 64bytes of 16k: tot-used-needed */ |
---|
213 | unsigned short unused[8*1024 -(4*32*4 +3*32*2*34 +1*32*1*34) -16*2]; |
---|
214 | |
---|
215 | /* interrupt log at 64 bytes from end */ |
---|
216 | struct irq_log_list irq_logs[16]; |
---|
217 | } *rtmem; |
---|
218 | #else |
---|
219 | #error You must define one DMA_MEM_???K |
---|
220 | #endif |
---|
221 | |
---|
222 | /* Interrupt log list */ |
---|
223 | struct irq_log_list *irq_log; |
---|
224 | unsigned int irq; |
---|
225 | |
---|
226 | /* Received events waiting to be read */ |
---|
227 | struct rt_msg *rt_event; |
---|
228 | struct bm_msg *bm_event; |
---|
229 | |
---|
230 | unsigned int head, tail; |
---|
231 | |
---|
232 | unsigned int last_read[128]; |
---|
233 | unsigned int written[32]; |
---|
234 | |
---|
235 | struct bc_msg *cur_list; |
---|
236 | |
---|
237 | int tx_blocking, rx_blocking; |
---|
238 | |
---|
239 | rtems_id rx_sem, tx_sem, dev_sem; |
---|
240 | int minor; |
---|
241 | int irqno; |
---|
242 | unsigned int mode; |
---|
243 | #ifdef DEBUG |
---|
244 | unsigned int log[EVENT_QUEUE_SIZE*4]; |
---|
245 | unsigned int log_i; |
---|
246 | #endif |
---|
247 | |
---|
248 | rtems_id event_id; /* event that may be signalled upon errors, needs to be set through ioctl command BRM_SET_EVENTID */ |
---|
249 | unsigned int status; |
---|
250 | int bc_list_fail; |
---|
251 | } brm_priv; |
---|
252 | |
---|
253 | static void b1553brm_interrupt(void *arg); |
---|
254 | static rtems_device_driver rt_init(brm_priv *brm); |
---|
255 | |
---|
256 | #define OFS(ofs) (((unsigned int)&ofs & 0x1ffff)>>1) |
---|
257 | |
---|
258 | static int b1553brm_driver_io_registered = 0; |
---|
259 | static rtems_device_major_number b1553brm_driver_io_major = 0; |
---|
260 | |
---|
261 | /******************* Driver manager interface ***********************/ |
---|
262 | |
---|
263 | /* Driver prototypes */ |
---|
264 | int b1553brm_register_io(rtems_device_major_number *m); |
---|
265 | int b1553brm_device_init(brm_priv *pDev); |
---|
266 | |
---|
267 | int b1553brm_init2(struct drvmgr_dev *dev); |
---|
268 | int b1553brm_init3(struct drvmgr_dev *dev); |
---|
269 | int b1553brm_remove(struct drvmgr_dev *dev); |
---|
270 | |
---|
271 | struct drvmgr_drv_ops b1553brm_ops = |
---|
272 | { |
---|
273 | .init = {NULL, b1553brm_init2, b1553brm_init3, NULL}, |
---|
274 | .remove = b1553brm_remove, |
---|
275 | .info = NULL |
---|
276 | }; |
---|
277 | |
---|
278 | struct amba_dev_id b1553brm_ids[] = |
---|
279 | { |
---|
280 | {VENDOR_GAISLER, GAISLER_B1553BRM}, |
---|
281 | {0, 0} /* Mark end of table */ |
---|
282 | }; |
---|
283 | |
---|
284 | struct amba_drv_info b1553brm_drv_info = |
---|
285 | { |
---|
286 | { |
---|
287 | DRVMGR_OBJ_DRV, /* Driver */ |
---|
288 | NULL, /* Next driver */ |
---|
289 | NULL, /* Device list */ |
---|
290 | DRIVER_AMBAPP_GAISLER_B1553BRM_ID, /* Driver ID */ |
---|
291 | "B1553BRM_DRV", /* Driver Name */ |
---|
292 | DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ |
---|
293 | &b1553brm_ops, |
---|
294 | NULL, /* Funcs */ |
---|
295 | 0, /* No devices yet */ |
---|
296 | 0, |
---|
297 | }, |
---|
298 | &b1553brm_ids[0] |
---|
299 | }; |
---|
300 | |
---|
301 | void b1553brm_register_drv (void) |
---|
302 | { |
---|
303 | DBG("Registering B1553BRM driver\n"); |
---|
304 | drvmgr_drv_register(&b1553brm_drv_info.general); |
---|
305 | } |
---|
306 | |
---|
307 | int b1553brm_init2(struct drvmgr_dev *dev) |
---|
308 | { |
---|
309 | brm_priv *priv; |
---|
310 | |
---|
311 | DBG("B1553BRM[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); |
---|
312 | priv = dev->priv = malloc(sizeof(brm_priv)); |
---|
313 | if ( !priv ) |
---|
314 | return DRVMGR_NOMEM; |
---|
315 | memset(priv, 0, sizeof(*priv)); |
---|
316 | priv->dev = dev; |
---|
317 | |
---|
318 | /* This core will not find other cores, so we wait for init2() */ |
---|
319 | |
---|
320 | return DRVMGR_OK; |
---|
321 | } |
---|
322 | |
---|
323 | int b1553brm_init3(struct drvmgr_dev *dev) |
---|
324 | { |
---|
325 | brm_priv *priv; |
---|
326 | char prefix[32]; |
---|
327 | rtems_status_code status; |
---|
328 | |
---|
329 | priv = dev->priv; |
---|
330 | |
---|
331 | /* Do initialization */ |
---|
332 | |
---|
333 | if ( b1553brm_driver_io_registered == 0) { |
---|
334 | /* Register the I/O driver only once for all cores */ |
---|
335 | if ( b1553brm_register_io(&b1553brm_driver_io_major) ) { |
---|
336 | /* Failed to register I/O driver */ |
---|
337 | dev->priv = NULL; |
---|
338 | return DRVMGR_FAIL; |
---|
339 | } |
---|
340 | |
---|
341 | b1553brm_driver_io_registered = 1; |
---|
342 | } |
---|
343 | |
---|
344 | /* I/O system registered and initialized |
---|
345 | * Now we take care of device initialization. |
---|
346 | */ |
---|
347 | |
---|
348 | if ( b1553brm_device_init(priv) ) { |
---|
349 | return DRVMGR_FAIL; |
---|
350 | } |
---|
351 | |
---|
352 | /* Get Filesystem name prefix */ |
---|
353 | prefix[0] = '\0'; |
---|
354 | if ( drvmgr_get_dev_prefix(dev, prefix) ) { |
---|
355 | /* Failed to get prefix, make sure of a unique FS name |
---|
356 | * by using the driver minor. |
---|
357 | */ |
---|
358 | sprintf(priv->devName, "/dev/b1553brm%d", dev->minor_drv); |
---|
359 | } else { |
---|
360 | /* Got special prefix, this means we have a bus prefix |
---|
361 | * And we should use our "bus minor" |
---|
362 | */ |
---|
363 | sprintf(priv->devName, "/dev/%sb1553brm%d", prefix, dev->minor_bus); |
---|
364 | } |
---|
365 | |
---|
366 | /* Register Device */ |
---|
367 | status = rtems_io_register_name(priv->devName, b1553brm_driver_io_major, dev->minor_drv); |
---|
368 | if (status != RTEMS_SUCCESSFUL) { |
---|
369 | return DRVMGR_FAIL; |
---|
370 | } |
---|
371 | |
---|
372 | return DRVMGR_OK; |
---|
373 | } |
---|
374 | |
---|
375 | int b1553brm_remove(struct drvmgr_dev *dev) |
---|
376 | { |
---|
377 | /* Stop more tasks to open driver */ |
---|
378 | |
---|
379 | /* Throw out all tasks using this driver */ |
---|
380 | |
---|
381 | /* Unregister I/O node */ |
---|
382 | |
---|
383 | /* Unregister and disable Interrupt */ |
---|
384 | |
---|
385 | /* Free device memory */ |
---|
386 | |
---|
387 | /* Return sucessfully */ |
---|
388 | |
---|
389 | return DRVMGR_OK; |
---|
390 | } |
---|
391 | |
---|
392 | /******************* Driver Implementation ***********************/ |
---|
393 | |
---|
394 | int b1553brm_register_io(rtems_device_major_number *m) |
---|
395 | { |
---|
396 | rtems_status_code r; |
---|
397 | |
---|
398 | if ((r = rtems_io_register_driver(0, &b1553brm_driver, m)) == RTEMS_SUCCESSFUL) { |
---|
399 | DBG("B1553BRM driver successfully registered, major: %d\n", *m); |
---|
400 | } else { |
---|
401 | switch(r) { |
---|
402 | case RTEMS_TOO_MANY: |
---|
403 | printk("B1553BRM rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); |
---|
404 | return -1; |
---|
405 | case RTEMS_INVALID_NUMBER: |
---|
406 | printk("B1553BRM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); |
---|
407 | return -1; |
---|
408 | case RTEMS_RESOURCE_IN_USE: |
---|
409 | printk("B1553BRM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); |
---|
410 | return -1; |
---|
411 | default: |
---|
412 | printk("B1553BRM rtems_io_register_driver failed\n"); |
---|
413 | return -1; |
---|
414 | } |
---|
415 | } |
---|
416 | return 0; |
---|
417 | } |
---|
418 | |
---|
419 | int b1553brm_device_init(brm_priv *pDev) |
---|
420 | { |
---|
421 | struct amba_dev_info *ambadev; |
---|
422 | struct ambapp_core *pnpinfo; |
---|
423 | union drvmgr_key_value *value; |
---|
424 | unsigned int mem; |
---|
425 | int size; |
---|
426 | |
---|
427 | /* Get device information from AMBA PnP information */ |
---|
428 | ambadev = (struct amba_dev_info *)pDev->dev->businfo; |
---|
429 | if ( ambadev == NULL ) { |
---|
430 | return -1; |
---|
431 | } |
---|
432 | pnpinfo = &ambadev->info; |
---|
433 | pDev->irqno = pnpinfo->irq; |
---|
434 | /* Two versions of the BRM core. One where the registers are accessed using the AHB bus |
---|
435 | * and one where the APB bus is used |
---|
436 | */ |
---|
437 | if ( pnpinfo->ahb_slv ) { |
---|
438 | /* Registers accessed over AHB */ |
---|
439 | pDev->regs = (struct brm_reg *)pnpinfo->ahb_slv->start[0]; |
---|
440 | } else { |
---|
441 | /* Registers accessed over APB */ |
---|
442 | pDev->regs = (struct brm_reg *)pnpinfo->apb_slv->start; |
---|
443 | } |
---|
444 | pDev->minor = pDev->dev->minor_drv; |
---|
445 | #ifdef DEBUG |
---|
446 | pDev->log_i = 0; |
---|
447 | memset(pDev->log,0,sizeof(pDev->log)); |
---|
448 | #endif |
---|
449 | |
---|
450 | #ifdef DMA_MEM_128K |
---|
451 | size = 128 * 1024; |
---|
452 | #else |
---|
453 | size = 16 * 1024; |
---|
454 | #endif |
---|
455 | |
---|
456 | /* Get memory configuration from bus resources */ |
---|
457 | value = drvmgr_dev_key_get(pDev->dev, "dmaBaseAdr", DRVMGR_KT_POINTER); |
---|
458 | if (value) |
---|
459 | mem = (unsigned int)value->ptr; |
---|
460 | |
---|
461 | if (value && (mem & 1)) { |
---|
462 | /* Remote address, address as BRM looks at it. */ |
---|
463 | |
---|
464 | /* Translate the base address into an address that the the CPU can understand */ |
---|
465 | pDev->memarea_base_remote = mem & ~1; |
---|
466 | drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU, |
---|
467 | (void *)pDev->memarea_base_remote, |
---|
468 | (void **)&pDev->memarea_base, |
---|
469 | size); |
---|
470 | } else { |
---|
471 | if (!value) { |
---|
472 | /* Use dynamically allocated memory + 128k for |
---|
473 | * alignment |
---|
474 | */ |
---|
475 | mem = (unsigned int)malloc(size + 128 * 1024); |
---|
476 | if (!mem){ |
---|
477 | printk("BRM: Failed to allocate HW memory\n\r"); |
---|
478 | return -1; |
---|
479 | } |
---|
480 | /* align memory to 128k boundary */ |
---|
481 | pDev->memarea_base = (mem + 0x1ffff) & ~0x1ffff; |
---|
482 | } else { |
---|
483 | pDev->memarea_base = mem; |
---|
484 | } |
---|
485 | |
---|
486 | /* Translate the base address into an address that the BRM core can understand */ |
---|
487 | drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, |
---|
488 | (void *)pDev->memarea_base, |
---|
489 | (void **)&pDev->memarea_base_remote, |
---|
490 | size); |
---|
491 | } |
---|
492 | |
---|
493 | /* clear the used memory */ |
---|
494 | memset((char *)pDev->memarea_base, 0, size); |
---|
495 | |
---|
496 | /* Set base address of all descriptors */ |
---|
497 | pDev->desc = (struct desc_table *) pDev->memarea_base; |
---|
498 | pDev->mem = (volatile unsigned short *) pDev->memarea_base; |
---|
499 | pDev->irq_log = (struct irq_log_list *)(pDev->memarea_base + (0xFFE0<<1)); /* last 64byte */ |
---|
500 | |
---|
501 | pDev->bm_event = NULL; |
---|
502 | pDev->rt_event = NULL; |
---|
503 | |
---|
504 | pDev->cfg_clksel = 0; |
---|
505 | pDev->cfg_clkdiv = 0; |
---|
506 | pDev->cfg_freq = BRM_FREQ_24MHZ; |
---|
507 | |
---|
508 | value = drvmgr_dev_key_get(pDev->dev, "clkSel", DRVMGR_KT_INT); |
---|
509 | if ( value ) { |
---|
510 | pDev->cfg_clksel = value->i & CLKSEL_MASK; |
---|
511 | } |
---|
512 | |
---|
513 | value = drvmgr_dev_key_get(pDev->dev, "clkDiv", DRVMGR_KT_INT); |
---|
514 | if ( value ) { |
---|
515 | pDev->cfg_clkdiv = value->i & CLKDIV_MASK; |
---|
516 | } |
---|
517 | |
---|
518 | value = drvmgr_dev_key_get(pDev->dev, "coreFreq", DRVMGR_KT_INT); |
---|
519 | if ( value ) { |
---|
520 | pDev->cfg_freq = value->i & BRM_FREQ_MASK; |
---|
521 | } |
---|
522 | |
---|
523 | /* Sel clock so that we can write to BRM's registers */ |
---|
524 | pDev->regs->w_ctrl = (pDev->cfg_clksel<<9) | (pDev->cfg_clkdiv<<5); |
---|
525 | /* Reset BRM core */ |
---|
526 | pDev->regs->w_ctrl = 1<<10 | READ_REG(&pDev->regs->w_ctrl); |
---|
527 | |
---|
528 | /* RX Semaphore created with count = 0 */ |
---|
529 | if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'R', '0' + pDev->minor), |
---|
530 | 0, |
---|
531 | RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, |
---|
532 | 0, |
---|
533 | &pDev->rx_sem) != RTEMS_SUCCESSFUL ) { |
---|
534 | printk("BRM: Failed to create rx semaphore\n"); |
---|
535 | return RTEMS_INTERNAL_ERROR; |
---|
536 | } |
---|
537 | |
---|
538 | /* TX Semaphore created with count = 1 */ |
---|
539 | if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'T', '0' + pDev->minor), |
---|
540 | 1, |
---|
541 | RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, |
---|
542 | 0, |
---|
543 | &pDev->tx_sem) != RTEMS_SUCCESSFUL ){ |
---|
544 | printk("BRM: Failed to create tx semaphore\n"); |
---|
545 | return RTEMS_INTERNAL_ERROR; |
---|
546 | } |
---|
547 | |
---|
548 | /* Device Semaphore created with count = 1 */ |
---|
549 | if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'D', '0' + pDev->minor), |
---|
550 | 1, |
---|
551 | RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, |
---|
552 | 0, |
---|
553 | &pDev->dev_sem) != RTEMS_SUCCESSFUL ){ |
---|
554 | printk("BRM: Failed to create device semaphore\n"); |
---|
555 | return RTEMS_INTERNAL_ERROR; |
---|
556 | } |
---|
557 | |
---|
558 | /* Default to RT-mode */ |
---|
559 | rt_init(pDev); |
---|
560 | |
---|
561 | return 0; |
---|
562 | } |
---|
563 | |
---|
564 | static int odd_parity(unsigned int data) { |
---|
565 | unsigned int i=0; |
---|
566 | |
---|
567 | while(data) |
---|
568 | { |
---|
569 | i++; |
---|
570 | data &= (data - 1); |
---|
571 | } |
---|
572 | |
---|
573 | return !(i&1); |
---|
574 | } |
---|
575 | |
---|
576 | static void start_operation(brm_priv *brm) { |
---|
577 | unsigned int ctrl = READ_REG(&brm->regs->ctrl); |
---|
578 | brm->regs->ctrl = ctrl | 0x8000; |
---|
579 | } |
---|
580 | |
---|
581 | static void stop_operation(brm_priv *brm) { |
---|
582 | unsigned int ctrl = READ_REG(&brm->regs->ctrl); |
---|
583 | brm->regs->ctrl = ctrl & ~0x8000; |
---|
584 | } |
---|
585 | |
---|
586 | static int is_executing(brm_priv *brm) { |
---|
587 | unsigned int ctrl = READ_REG(&brm->regs->ctrl); |
---|
588 | return ((ctrl>>15) & 1); |
---|
589 | } |
---|
590 | |
---|
591 | static void clr_int_logs(struct irq_log_list *logs){ |
---|
592 | int i; |
---|
593 | for(i=0; i<16; i++){ |
---|
594 | logs[i].iiw = 0xffff; |
---|
595 | logs[i].iaw = 0x0; |
---|
596 | } |
---|
597 | } |
---|
598 | |
---|
599 | unsigned short b1553brm_rt_cmd_legalize[16] = { |
---|
600 | 0, |
---|
601 | 0, |
---|
602 | 0, |
---|
603 | 0, |
---|
604 | 0, |
---|
605 | 0, |
---|
606 | 0xffff, |
---|
607 | 0xffff, |
---|
608 | 0xffff, |
---|
609 | 0xfffd, |
---|
610 | 0xfe01, |
---|
611 | 0xfff2, |
---|
612 | 0xffff, |
---|
613 | 0xfffd, |
---|
614 | 0xfe05, |
---|
615 | 0xffff, |
---|
616 | }; |
---|
617 | |
---|
618 | static rtems_device_driver rt_init(brm_priv *brm) { |
---|
619 | unsigned int i; |
---|
620 | |
---|
621 | brm->head = brm->tail = 0; |
---|
622 | brm->rx_blocking = brm->tx_blocking = 1; |
---|
623 | |
---|
624 | if ( brm->bm_event ) |
---|
625 | free(brm->bm_event); |
---|
626 | brm->bm_event = NULL; |
---|
627 | |
---|
628 | if ( brm->rt_event ) |
---|
629 | free(brm->rt_event); |
---|
630 | |
---|
631 | brm->bcmem = NULL; |
---|
632 | brm->rtmem = (void *)brm->mem; |
---|
633 | |
---|
634 | brm->rt_event = (struct rt_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct rt_msg)); |
---|
635 | |
---|
636 | if (brm->rt_event == NULL) { |
---|
637 | DBG("BRM driver failed to allocated memory."); |
---|
638 | return RTEMS_NO_MEMORY; |
---|
639 | } |
---|
640 | |
---|
641 | brm->irq_log = (struct irq_log_list *)&brm->rtmem->irq_logs[0]; |
---|
642 | |
---|
643 | brm->regs->ctrl = 0x1912; /* enable both buses, circular 1 bufmode, broadcast, interrupt log */ |
---|
644 | brm->regs->oper = 0x0900; /* configure as RT, with addr 1 */ |
---|
645 | brm->regs->imask = BRM_RT_ILLCMD_IRQ|BRM_SUBAD_IRQ|BRM_TAPF_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ; |
---|
646 | brm->regs->dpoint = 0; |
---|
647 | brm->regs->ipoint = OFS(brm->rtmem->irq_logs[0]); |
---|
648 | brm->regs->enhanced = 0x0000 | brm->cfg_freq; /* BRM clocked with freq = 12,16,20 or 24MHz */ |
---|
649 | brm->regs->w_ctrl = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1; |
---|
650 | brm->regs->w_irqctrl = 6; |
---|
651 | brm->regs->w_ahbaddr = brm->memarea_base_remote; |
---|
652 | |
---|
653 | clr_int_logs(brm->irq_log); |
---|
654 | |
---|
655 | /* Initialize the Legalize register with standard values */ |
---|
656 | for (i = 0; i < 16; i++) { |
---|
657 | brm->regs->rt_cmd_leg[i] = b1553brm_rt_cmd_legalize[i]; |
---|
658 | } |
---|
659 | |
---|
660 | /* Init descriptor table |
---|
661 | * |
---|
662 | * Each circular buffer has room for 8 messages with up to 34 (32 data + miw + time) words (16b) in each. |
---|
663 | * The buffers must separated by 34 words. |
---|
664 | */ |
---|
665 | |
---|
666 | |
---|
667 | /* RX Sub-address 0 - 31 */ |
---|
668 | for (i = 0; i < 32; i++) { |
---|
669 | brm->rtmem->rxsubs[i].ctrl = 0x00E0; /* Interrupt: INTX, IWA, and IBRD */ |
---|
670 | brm->rtmem->rxsubs[i].top = OFS(brm->rtmem->rxsuba_msgs[i]); /* Top address */ |
---|
671 | brm->rtmem->rxsubs[i].cur = OFS(brm->rtmem->rxsuba_msgs[i]); /* Current address */ |
---|
672 | brm->rtmem->rxsubs[i].bot = OFS(brm->rtmem->rxsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */ |
---|
673 | brm->last_read[i] = OFS(brm->rtmem->rxsuba_msgs[i]); |
---|
674 | } |
---|
675 | /* TX Sub-address 0 - 31 */ |
---|
676 | for (i = 0; i < 32; i++) { |
---|
677 | brm->rtmem->txsubs[i].ctrl = 0x0060; /* Interrupt: IWA and IBRD */ |
---|
678 | brm->rtmem->txsubs[i].top = OFS(brm->rtmem->txsuba_msgs[i]); /* Top address */ |
---|
679 | brm->rtmem->txsubs[i].cur = OFS(brm->rtmem->txsuba_msgs[i]); /* Current address */ |
---|
680 | brm->rtmem->txsubs[i].bot = OFS(brm->rtmem->txsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */ |
---|
681 | brm->last_read[i+32] = OFS(brm->rtmem->txsuba_msgs[i]); |
---|
682 | brm->written[i] = OFS(brm->rtmem->txsuba_msgs[i]); |
---|
683 | } |
---|
684 | /* RX mode code 0 - 31 */ |
---|
685 | for (i = 0; i < 32; i++) { |
---|
686 | brm->rtmem->rxmodes[i].ctrl = 0x00E0; /* Interrupt: INTX, IWA, and IBRD */ |
---|
687 | brm->rtmem->rxmodes[i].top = OFS(brm->rtmem->rxmode_msgs[i]); /* Top address */ |
---|
688 | brm->rtmem->rxmodes[i].cur = OFS(brm->rtmem->rxmode_msgs[i]); /* Current address */ |
---|
689 | brm->rtmem->rxmodes[i].bot = OFS(brm->rtmem->rxmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */ |
---|
690 | brm->last_read[i+64] = OFS(brm->rtmem->rxmode_msgs[i]); |
---|
691 | } |
---|
692 | /* TX mode code 0 - 31 */ |
---|
693 | for (i = 0; i < 32; i++) { |
---|
694 | brm->rtmem->txmodes[i].ctrl = 0x0060; /* Interrupt: IWA and IBRD */ |
---|
695 | brm->rtmem->txmodes[i].top = OFS(brm->rtmem->txmode_msgs[i]); /* Top address */ |
---|
696 | brm->rtmem->txmodes[i].cur = OFS(brm->rtmem->txmode_msgs[i]); /* Current address */ |
---|
697 | brm->rtmem->txmodes[i].bot = OFS(brm->rtmem->txmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */ |
---|
698 | brm->last_read[i+96] = OFS(brm->rtmem->txmode_msgs[i]); |
---|
699 | } |
---|
700 | |
---|
701 | #ifdef DEBUG |
---|
702 | printk("b1553BRM DMA_AREA: 0x%x\n", (unsigned int)brm->rtmem); |
---|
703 | printk("LOG: 0x%x\n", &brm->log[0]); |
---|
704 | printk("LOG_I: 0x%x\n", &brm->log_i); |
---|
705 | #endif |
---|
706 | |
---|
707 | brm->mode = BRM_MODE_RT; |
---|
708 | |
---|
709 | return RTEMS_SUCCESSFUL; |
---|
710 | } |
---|
711 | |
---|
712 | static rtems_device_driver bc_init(brm_priv *brm){ |
---|
713 | |
---|
714 | if ( brm->bm_event ) |
---|
715 | free(brm->bm_event); |
---|
716 | brm->bm_event = NULL; |
---|
717 | |
---|
718 | if ( brm->rt_event ) |
---|
719 | free(brm->rt_event); |
---|
720 | brm->rt_event = NULL; |
---|
721 | |
---|
722 | brm->bcmem = (void *)brm->mem; |
---|
723 | brm->rtmem = NULL; |
---|
724 | brm->irq_log = (struct irq_log_list *)&brm->bcmem->irq_logs[0]; |
---|
725 | |
---|
726 | brm->head = brm->tail = 0; |
---|
727 | brm->rx_blocking = brm->tx_blocking = 1; |
---|
728 | |
---|
729 | brm->regs->ctrl = 0x0006; /* ping pong enable and enable interrupt log */ |
---|
730 | brm->regs->oper = 0x0800; /* configure as BC */ |
---|
731 | brm->regs->imask = BRM_EOL_IRQ|BRM_BC_ILLCMD_IRQ|BRM_ILLOP_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ; |
---|
732 | brm->regs->dpoint = 0; |
---|
733 | brm->regs->ipoint = OFS(brm->bcmem->irq_logs[0]); |
---|
734 | brm->regs->enhanced = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK); /* freq = 24 */ |
---|
735 | brm->regs->w_ctrl = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1; |
---|
736 | brm->regs->w_irqctrl = 6; |
---|
737 | brm->regs->w_ahbaddr = brm->memarea_base_remote; |
---|
738 | |
---|
739 | clr_int_logs(brm->irq_log); |
---|
740 | |
---|
741 | brm->mode = BRM_MODE_BC; |
---|
742 | |
---|
743 | return RTEMS_SUCCESSFUL; |
---|
744 | } |
---|
745 | |
---|
746 | static rtems_device_driver bm_init(brm_priv *brm) { |
---|
747 | |
---|
748 | |
---|
749 | brm->head = brm->tail = 0; |
---|
750 | brm->rx_blocking = brm->tx_blocking = 1; |
---|
751 | |
---|
752 | if ( brm->rt_event ) |
---|
753 | free(brm->rt_event); |
---|
754 | brm->rt_event = NULL; |
---|
755 | |
---|
756 | if ( brm->bm_event ) |
---|
757 | free(brm->bm_event); |
---|
758 | |
---|
759 | brm->bcmem = NULL; |
---|
760 | brm->rtmem = NULL; |
---|
761 | |
---|
762 | brm->bm_event = (struct bm_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct bm_msg)); |
---|
763 | |
---|
764 | if (brm->bm_event == NULL) { |
---|
765 | DBG("BRM driver failed to allocated memory."); |
---|
766 | return RTEMS_NO_MEMORY; |
---|
767 | } |
---|
768 | |
---|
769 | /* end of 16K, fits all current modes (128K, 16K) */ |
---|
770 | brm->irq_log = (struct irq_log_list *)&brm->mem[8*1024-16*2]; |
---|
771 | |
---|
772 | brm->regs->ctrl = 0x0006; /* ping pong enable and enable interrupt log */ |
---|
773 | brm->regs->oper = 0x0A00; /* configure as BM */ |
---|
774 | brm->regs->imask = BRM_MBC_IRQ|BRM_MERR_IRQ|BRM_DMAF_IRQ; |
---|
775 | brm->regs->dpoint = 0; |
---|
776 | brm->regs->ipoint = OFS(brm->mem[8*1024-16*2]); |
---|
777 | brm->regs->mcpoint = 0; /* Command pointer */ |
---|
778 | brm->regs->mdpoint = 0x100; /* Data pointer */ |
---|
779 | brm->regs->mbc = 1; /* Block count */ |
---|
780 | brm->regs->enhanced = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK); /* freq = 24 */ |
---|
781 | brm->regs->w_ctrl = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1; |
---|
782 | brm->regs->w_irqctrl = 6; |
---|
783 | brm->regs->w_ahbaddr = brm->memarea_base_remote; |
---|
784 | |
---|
785 | clr_int_logs(brm->irq_log); |
---|
786 | |
---|
787 | brm->mode = BRM_MODE_BM; |
---|
788 | |
---|
789 | return RTEMS_SUCCESSFUL; |
---|
790 | } |
---|
791 | |
---|
792 | |
---|
793 | static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) |
---|
794 | { |
---|
795 | return RTEMS_SUCCESSFUL; |
---|
796 | } |
---|
797 | |
---|
798 | static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { |
---|
799 | brm_priv *brm; |
---|
800 | struct drvmgr_dev *dev; |
---|
801 | |
---|
802 | FUNCDBG("brm_open\n"); |
---|
803 | |
---|
804 | if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { |
---|
805 | DBG("Wrong minor %d\n", minor); |
---|
806 | return RTEMS_UNSATISFIED; |
---|
807 | } |
---|
808 | brm = (brm_priv *)dev->priv; |
---|
809 | |
---|
810 | if (rtems_semaphore_obtain(brm->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) { |
---|
811 | DBG("brm_open: resource in use\n"); |
---|
812 | return RTEMS_RESOURCE_IN_USE; /* EBUSY */ |
---|
813 | } |
---|
814 | |
---|
815 | /* Set defaults */ |
---|
816 | brm->event_id = 0; |
---|
817 | |
---|
818 | start_operation(brm); |
---|
819 | |
---|
820 | /* Register interrupt routine */ |
---|
821 | if ( drvmgr_interrupt_register(brm->dev, 0, "b1553brm", b1553brm_interrupt, brm) ) { |
---|
822 | rtems_semaphore_release(brm->dev_sem); |
---|
823 | return RTEMS_UNSATISFIED; |
---|
824 | } |
---|
825 | |
---|
826 | return RTEMS_SUCCESSFUL; |
---|
827 | } |
---|
828 | |
---|
829 | static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) |
---|
830 | { |
---|
831 | brm_priv *brm; |
---|
832 | struct drvmgr_dev *dev; |
---|
833 | |
---|
834 | FUNCDBG("brm_close"); |
---|
835 | |
---|
836 | if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { |
---|
837 | return RTEMS_UNSATISFIED; |
---|
838 | } |
---|
839 | brm = (brm_priv *)dev->priv; |
---|
840 | |
---|
841 | drvmgr_interrupt_unregister(brm->dev, 0, b1553brm_interrupt, brm); |
---|
842 | |
---|
843 | stop_operation(brm); |
---|
844 | rtems_semaphore_release(brm->dev_sem); |
---|
845 | |
---|
846 | return RTEMS_SUCCESSFUL; |
---|
847 | } |
---|
848 | |
---|
849 | static int get_rt_messages(brm_priv *brm, void *buf, unsigned int msg_count) |
---|
850 | { |
---|
851 | struct rt_msg *dest = (struct rt_msg *) buf; |
---|
852 | int count = 0; |
---|
853 | |
---|
854 | if (brm->head == brm->tail) { |
---|
855 | return 0; |
---|
856 | } |
---|
857 | |
---|
858 | do { |
---|
859 | |
---|
860 | DBG("rt read - head: %d, tail: %d\n", brm->head, brm->tail); |
---|
861 | dest[count++] = brm->rt_event[INDEX(brm->tail++)]; |
---|
862 | } while (brm->head != brm->tail && count < msg_count); |
---|
863 | |
---|
864 | return count; |
---|
865 | } |
---|
866 | |
---|
867 | static int get_bm_messages(brm_priv *brm, void *buf, unsigned int msg_count) |
---|
868 | { |
---|
869 | struct bm_msg *dest = (struct bm_msg *) buf; |
---|
870 | int count = 0; |
---|
871 | |
---|
872 | if (brm->head == brm->tail) { |
---|
873 | return 0; |
---|
874 | } |
---|
875 | |
---|
876 | do { |
---|
877 | |
---|
878 | DBG("bm read - head: %d, tail: %d\n", brm->head, brm->tail); |
---|
879 | dest[count++] = brm->bm_event[INDEX(brm->tail++)]; |
---|
880 | |
---|
881 | } while (brm->head != brm->tail && count < msg_count); |
---|
882 | |
---|
883 | return count; |
---|
884 | } |
---|
885 | |
---|
886 | static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) |
---|
887 | { |
---|
888 | rtems_libio_rw_args_t *rw_args; |
---|
889 | int count = 0; |
---|
890 | brm_priv *brm; |
---|
891 | struct drvmgr_dev *dev; |
---|
892 | int (*get_messages)(brm_priv *brm, void *buf, unsigned int count); |
---|
893 | |
---|
894 | if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { |
---|
895 | return RTEMS_UNSATISFIED; |
---|
896 | } |
---|
897 | brm = (brm_priv *)dev->priv; |
---|
898 | |
---|
899 | if ( ! (brm->mode & (BRM_MODE_RT | BRM_MODE_BM)) ){ |
---|
900 | return RTEMS_INVALID_NAME; |
---|
901 | } |
---|
902 | |
---|
903 | rw_args = (rtems_libio_rw_args_t *) arg; |
---|
904 | |
---|
905 | if ( ((READ_REG(&brm->regs->oper)>>8) & 3) == 1 ) { /* RT */ |
---|
906 | get_messages = get_rt_messages; |
---|
907 | } else { /* BM */ |
---|
908 | get_messages = get_bm_messages; |
---|
909 | } |
---|
910 | |
---|
911 | FUNCDBG("brm_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count); |
---|
912 | |
---|
913 | while ( (count=get_messages(brm,rw_args->buffer, rw_args->count)) == 0 ) { |
---|
914 | if (brm->rx_blocking) { |
---|
915 | rtems_semaphore_obtain(brm->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
916 | } else { |
---|
917 | /* Translates to EBUSY */ |
---|
918 | return RTEMS_RESOURCE_IN_USE; |
---|
919 | } |
---|
920 | } |
---|
921 | |
---|
922 | rw_args->bytes_moved = count; |
---|
923 | return RTEMS_SUCCESSFUL; |
---|
924 | } |
---|
925 | |
---|
926 | static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) |
---|
927 | { |
---|
928 | rtems_libio_rw_args_t *rw_args; |
---|
929 | struct rt_msg *source; |
---|
930 | unsigned int count=0, current, next, descriptor, wc, suba; |
---|
931 | brm_priv *brm; |
---|
932 | struct drvmgr_dev *dev; |
---|
933 | |
---|
934 | if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { |
---|
935 | return RTEMS_UNSATISFIED; |
---|
936 | } |
---|
937 | brm = (brm_priv *)dev->priv; |
---|
938 | |
---|
939 | if ( ! (brm->mode & BRM_MODE_RT) ){ |
---|
940 | return RTEMS_INVALID_NAME; |
---|
941 | } |
---|
942 | |
---|
943 | rw_args = (rtems_libio_rw_args_t *) arg; |
---|
944 | source = (struct rt_msg *) rw_args->buffer; |
---|
945 | |
---|
946 | FUNCDBG("brm_write [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count); |
---|
947 | |
---|
948 | do { |
---|
949 | |
---|
950 | descriptor = source[count].desc & 0x7F; |
---|
951 | suba = descriptor-32; |
---|
952 | wc = source[count].miw >> 11; |
---|
953 | wc = wc ? wc : 32; |
---|
954 | |
---|
955 | /* Only subaddress transmission is allowed with write */ |
---|
956 | if (descriptor < 32 || descriptor >= 64) |
---|
957 | return RTEMS_INVALID_NAME; |
---|
958 | |
---|
959 | current = brm->desc[descriptor].cur; |
---|
960 | next = brm->written[suba] + 2 + wc; |
---|
961 | |
---|
962 | if (brm->written[suba] < current) { |
---|
963 | |
---|
964 | if (next > current) { |
---|
965 | |
---|
966 | /* No room in transmission buffer */ |
---|
967 | if (brm->tx_blocking && count == 0) { |
---|
968 | rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
969 | } else if ( count > 0 ) { |
---|
970 | /* return the number of messages sent so far */ |
---|
971 | break; |
---|
972 | } else { |
---|
973 | /* Translates to posix EBUSY */ |
---|
974 | return RTEMS_RESOURCE_IN_USE; |
---|
975 | } |
---|
976 | } |
---|
977 | } |
---|
978 | |
---|
979 | memcpy((void *)&brm->mem[brm->written[suba]], &source[count], (2+wc)*2); |
---|
980 | |
---|
981 | count++; |
---|
982 | |
---|
983 | if (next >= brm->desc[descriptor].bot) { |
---|
984 | next = brm->desc[descriptor].top; |
---|
985 | } |
---|
986 | brm->written[suba] = next; |
---|
987 | |
---|
988 | } while (count < rw_args->count); |
---|
989 | |
---|
990 | rw_args->bytes_moved = count; |
---|
991 | |
---|
992 | if (count >= 0) { |
---|
993 | return RTEMS_SUCCESSFUL; |
---|
994 | } |
---|
995 | return RTEMS_UNSATISFIED; |
---|
996 | } |
---|
997 | |
---|
998 | static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) |
---|
999 | { |
---|
1000 | |
---|
1001 | unsigned int i=0; |
---|
1002 | unsigned short ctrl, oper, cw1, cw2; |
---|
1003 | rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg; |
---|
1004 | unsigned int *data = ioarg->buffer; |
---|
1005 | struct bc_msg *cmd_list = (struct bc_msg *) ioarg->buffer; |
---|
1006 | brm_priv *brm; |
---|
1007 | struct drvmgr_dev *dev; |
---|
1008 | rtems_device_driver ret; |
---|
1009 | int len, msglen; |
---|
1010 | |
---|
1011 | FUNCDBG("brm_control[%d]: [%i,%i]\n", minor, major, minor); |
---|
1012 | |
---|
1013 | if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { |
---|
1014 | return RTEMS_UNSATISFIED; |
---|
1015 | } |
---|
1016 | brm = (brm_priv *)dev->priv; |
---|
1017 | |
---|
1018 | if (!ioarg) { |
---|
1019 | DBG("brm_control: invalid argument\n"); |
---|
1020 | return RTEMS_INVALID_NAME; |
---|
1021 | } |
---|
1022 | |
---|
1023 | ioarg->ioctl_return = 0; |
---|
1024 | switch (ioarg->command) { |
---|
1025 | |
---|
1026 | case BRM_SET_MODE: |
---|
1027 | if ( data[0] > 2 ) |
---|
1028 | return RTEMS_INVALID_NAME; |
---|
1029 | stop_operation(brm); |
---|
1030 | if (data[0] == 0) { |
---|
1031 | ret = bc_init(brm); |
---|
1032 | } else if (data[0] == 1) { |
---|
1033 | ret = rt_init(brm); |
---|
1034 | } else if (data[0] == 2) { |
---|
1035 | ret = bm_init(brm); |
---|
1036 | } else { |
---|
1037 | ret = RTEMS_INVALID_NAME; |
---|
1038 | } |
---|
1039 | if ( ret != RTEMS_SUCCESSFUL) |
---|
1040 | return ret; |
---|
1041 | |
---|
1042 | if ( brm->mode & (BRM_MODE_RT | BRM_MODE_BM ) ) |
---|
1043 | start_operation(brm); |
---|
1044 | break; |
---|
1045 | |
---|
1046 | case BRM_SET_BUS: |
---|
1047 | stop_operation(brm); |
---|
1048 | ctrl = READ_REG(&brm->regs->ctrl); |
---|
1049 | ctrl &= 0xE7FF; /* Clear bit 12-11 ... */ |
---|
1050 | ctrl |= (data[0]&0x3)<<11; /* ... OR in new bus status */ |
---|
1051 | brm->regs->ctrl = ctrl; |
---|
1052 | start_operation(brm); |
---|
1053 | break; |
---|
1054 | |
---|
1055 | case BRM_SET_MSGTO: |
---|
1056 | stop_operation(brm); |
---|
1057 | ctrl = READ_REG(&brm->regs->ctrl); |
---|
1058 | ctrl &= 0xFDFF; /* Clear bit 9 ... */ |
---|
1059 | ctrl |= (data[0]&1)<<9; /* ... OR in new MSGTO */ |
---|
1060 | brm->regs->ctrl = ctrl; |
---|
1061 | start_operation(brm); |
---|
1062 | break; |
---|
1063 | |
---|
1064 | case BRM_SET_RT_ADDR: |
---|
1065 | stop_operation(brm); |
---|
1066 | oper = READ_REG(&brm->regs->oper); |
---|
1067 | oper &= 0x03FF; /* Clear bit 15-10 ... */ |
---|
1068 | oper |= (data[0]&0x1f)<<11; /* ... OR in new address */ |
---|
1069 | oper |= odd_parity(data[0]&0x1f)<<10; /* ... OR in parity */ |
---|
1070 | brm->regs->oper = oper; |
---|
1071 | start_operation(brm); |
---|
1072 | break; |
---|
1073 | |
---|
1074 | case BRM_SET_STD: |
---|
1075 | stop_operation(brm); |
---|
1076 | ctrl = READ_REG(&brm->regs->ctrl); |
---|
1077 | ctrl &= 0xFF7F; /* Clear bit 7 ... */ |
---|
1078 | ctrl |= (data[0]&1)<<7; /* ... OR in new ABSTD (1=A) */ |
---|
1079 | brm->regs->ctrl = ctrl; |
---|
1080 | start_operation(brm); |
---|
1081 | break; |
---|
1082 | |
---|
1083 | case BRM_SET_BCE: |
---|
1084 | stop_operation(brm); |
---|
1085 | ctrl = READ_REG(&brm->regs->ctrl); |
---|
1086 | ctrl &= 0xFFEF; /* Clear bit 4 ... */ |
---|
1087 | ctrl |= (data[0]&1)<<4; /* ... OR in new BCE */ |
---|
1088 | brm->regs->ctrl = ctrl; |
---|
1089 | start_operation(brm); |
---|
1090 | break; |
---|
1091 | |
---|
1092 | case BRM_TX_BLOCK: |
---|
1093 | brm->tx_blocking = data[0]; |
---|
1094 | break; |
---|
1095 | |
---|
1096 | case BRM_RX_BLOCK: |
---|
1097 | brm->rx_blocking = data[0]; |
---|
1098 | break; |
---|
1099 | |
---|
1100 | case BRM_DO_LIST: |
---|
1101 | if ( brm->mode != BRM_MODE_BC ){ |
---|
1102 | return RTEMS_INVALID_NAME; |
---|
1103 | } |
---|
1104 | |
---|
1105 | /* Check if we are bus controller */ |
---|
1106 | if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) { |
---|
1107 | return RTEMS_INVALID_NAME; |
---|
1108 | } |
---|
1109 | |
---|
1110 | /* Already processing list? */ |
---|
1111 | if (is_executing(brm)) { |
---|
1112 | return RTEMS_RESOURCE_IN_USE; |
---|
1113 | } |
---|
1114 | |
---|
1115 | /* clear any earlier releases */ |
---|
1116 | rtems_semaphore_obtain(brm->tx_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT); |
---|
1117 | |
---|
1118 | brm->bc_list_fail = 0; |
---|
1119 | brm->cur_list = cmd_list; |
---|
1120 | brm->regs->dpoint = 0; |
---|
1121 | |
---|
1122 | i = 0; |
---|
1123 | while ( (cmd_list[i].ctrl & BC_EOL) == 0) { |
---|
1124 | |
---|
1125 | ctrl = (4<<12) | (((cmd_list[i].ctrl&BC_BUSA)==BC_BUSA)<<9) | (((cmd_list[i].ctrl&BC_RTRT)==BC_RTRT)<<8); |
---|
1126 | |
---|
1127 | if (cmd_list[i].ctrl&BC_RTRT) { |
---|
1128 | cw1 = (cmd_list[i].rtaddr[0]<<11) | (0<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc & 0x1f); /* receive cw */ |
---|
1129 | cw2 = (cmd_list[i].rtaddr[1]<<11) | (1<<10) | (cmd_list[i].subaddr[1]<<5) | (cmd_list[i].wc & 0x1f); /* transmit cw */ |
---|
1130 | } else { |
---|
1131 | cw1 = (cmd_list[i].rtaddr[0]<<11) | (((cmd_list[i].ctrl&BC_TR)==BC_TR)<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc&0x1f); |
---|
1132 | cw2 = 0; |
---|
1133 | } |
---|
1134 | |
---|
1135 | /* Set up command block */ |
---|
1136 | brm->bcmem->descs[i].ctrl = ctrl; |
---|
1137 | brm->bcmem->descs[i].cw1 = cw1; |
---|
1138 | brm->bcmem->descs[i].cw2 = cw2; |
---|
1139 | /* data pointer: |
---|
1140 | * (&brm->bcmem->msg_data[i].data[0] & 0x1ffff) / 2 |
---|
1141 | */ |
---|
1142 | brm->bcmem->descs[i].dptr = 1024+i*32; /* data pointer */ |
---|
1143 | brm->bcmem->descs[i].tsw[0] = 0; |
---|
1144 | brm->bcmem->descs[i].tsw[1] = 0; |
---|
1145 | brm->bcmem->descs[i].ba = 0; |
---|
1146 | brm->bcmem->descs[i].timer = 0; |
---|
1147 | |
---|
1148 | msglen = cmd_list[i].wc; |
---|
1149 | if ( msglen == 0 ) |
---|
1150 | msglen = 32; |
---|
1151 | memcpy((void *)&brm->bcmem->msg_data[i].data[0], &cmd_list[i].data[0], msglen*2); |
---|
1152 | |
---|
1153 | i++; |
---|
1154 | } |
---|
1155 | |
---|
1156 | brm->bcmem->descs[i].ctrl = 0; /* end of list */ |
---|
1157 | |
---|
1158 | start_operation(brm); |
---|
1159 | break; |
---|
1160 | |
---|
1161 | case BRM_LIST_DONE: |
---|
1162 | |
---|
1163 | if ( brm->mode != BRM_MODE_BC ){ |
---|
1164 | return RTEMS_INVALID_NAME; |
---|
1165 | } |
---|
1166 | |
---|
1167 | /* Check if we are bus controller */ |
---|
1168 | if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) { |
---|
1169 | return RTEMS_INVALID_NAME; |
---|
1170 | } |
---|
1171 | |
---|
1172 | if (is_executing(brm)) { |
---|
1173 | |
---|
1174 | data[0] = 0; |
---|
1175 | if (brm->tx_blocking) { |
---|
1176 | rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
1177 | data[0] = 1; |
---|
1178 | if ( brm->bc_list_fail ){ |
---|
1179 | return RTEMS_INVALID_NAME; |
---|
1180 | } |
---|
1181 | } else { |
---|
1182 | return RTEMS_RESOURCE_IN_USE; |
---|
1183 | } |
---|
1184 | } else { |
---|
1185 | data[0] = 1; /* done */ |
---|
1186 | } |
---|
1187 | |
---|
1188 | /* copy finished list results back into bc_msg array */ |
---|
1189 | i = 0; |
---|
1190 | while ( (brm->cur_list[i].ctrl & BC_EOL) == 0) { |
---|
1191 | if (READ_DMA(&brm->bcmem->descs[i].ctrl) & 1) { |
---|
1192 | brm->cur_list[i].ctrl |= 0x8000; /* Set BAME */ |
---|
1193 | } |
---|
1194 | if (brm->cur_list[i].ctrl & BC_TR) { |
---|
1195 | /* RT Transmit command, copy received data */ |
---|
1196 | len = brm->cur_list[i].wc; |
---|
1197 | if ( len == 0 ) |
---|
1198 | len = 32; |
---|
1199 | while ( len-- > 0) { |
---|
1200 | brm->cur_list[i].data[len] = READ_DMA(&brm->bcmem->msg_data[i].data[len]); |
---|
1201 | } |
---|
1202 | } |
---|
1203 | brm->cur_list[i].tsw[0] = READ_DMA(&brm->bcmem->descs[i].tsw[0]); |
---|
1204 | brm->cur_list[i].tsw[1] = READ_DMA(&brm->bcmem->descs[i].tsw[1]); |
---|
1205 | |
---|
1206 | i++; |
---|
1207 | } |
---|
1208 | break; |
---|
1209 | |
---|
1210 | case BRM_CLR_STATUS: |
---|
1211 | brm->status = 0; |
---|
1212 | break; |
---|
1213 | |
---|
1214 | case BRM_GET_STATUS: /* copy status */ |
---|
1215 | if ( !ioarg->buffer ) |
---|
1216 | return RTEMS_INVALID_NAME; |
---|
1217 | |
---|
1218 | *(unsigned int *)ioarg->buffer = brm->status; |
---|
1219 | break; |
---|
1220 | |
---|
1221 | case BRM_SET_EVENTID: |
---|
1222 | brm->event_id = (rtems_id)ioarg->buffer; |
---|
1223 | break; |
---|
1224 | |
---|
1225 | default: |
---|
1226 | return RTEMS_NOT_DEFINED; |
---|
1227 | } |
---|
1228 | return RTEMS_SUCCESSFUL; |
---|
1229 | } |
---|
1230 | |
---|
1231 | static void b1553brm_interrupt(void *arg) |
---|
1232 | { |
---|
1233 | brm_priv *brm = arg; |
---|
1234 | unsigned short descriptor, current, pending, miw, wc, tmp, ctrl; |
---|
1235 | unsigned short msgadr, iaw, iiw; |
---|
1236 | int len; |
---|
1237 | int signal_event=0, wake_rx_task=0, wake_tx_task=0; |
---|
1238 | unsigned int event_status=0; |
---|
1239 | int accessed; |
---|
1240 | #define SET_ERROR_DESCRIPTOR(descriptor) (event_status = (event_status & 0x0000ffff) | descriptor<<16) |
---|
1241 | |
---|
1242 | while( (iiw=READ_DMA(&brm->irq_log[brm->irq].iiw)) != 0xffff ){ |
---|
1243 | iaw=READ_DMA(&brm->irq_log[brm->irq].iaw); |
---|
1244 | |
---|
1245 | /* indicate that the interrupt log entry has been processed */ |
---|
1246 | brm->irq_log[brm->irq].iiw = 0xffff; |
---|
1247 | |
---|
1248 | /* Interpret interrupt log entry */ |
---|
1249 | descriptor = iaw >> 2; |
---|
1250 | pending = iiw; |
---|
1251 | brm->irq = (brm->irq + 1) % 16; |
---|
1252 | |
---|
1253 | /* Clear the log so that we */ |
---|
1254 | |
---|
1255 | |
---|
1256 | /* Subaddress accessed irq (RT only) |
---|
1257 | * |
---|
1258 | * Can be either a receive or transmit command |
---|
1259 | * as well as a mode code. |
---|
1260 | */ |
---|
1261 | if (pending & BRM_SUBAD_IRQ) { |
---|
1262 | |
---|
1263 | /* Pointer to next free message in circular buffer */ |
---|
1264 | current = READ_DMA(&brm->desc[descriptor].cur); |
---|
1265 | ctrl = READ_DMA(&brm->desc[descriptor].ctrl); |
---|
1266 | #ifdef DEBUG |
---|
1267 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xff<<16); |
---|
1268 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current; |
---|
1269 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = ctrl; |
---|
1270 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0; |
---|
1271 | #endif |
---|
1272 | accessed = ctrl & 0x10; |
---|
1273 | /* Note that current may be equal to bot and top when |
---|
1274 | * circular buffer one can handle one message. |
---|
1275 | */ |
---|
1276 | if ( accessed ) |
---|
1277 | do { |
---|
1278 | msgadr = brm->last_read[descriptor]; |
---|
1279 | |
---|
1280 | /* Get word count */ |
---|
1281 | miw = READ_DMA(&brm->mem[msgadr]); |
---|
1282 | wc = miw >> 11; |
---|
1283 | |
---|
1284 | /* Data received */ |
---|
1285 | if (descriptor < 32) { |
---|
1286 | wc = wc ? wc : 32; |
---|
1287 | } |
---|
1288 | /* Data transmitted */ |
---|
1289 | else if (descriptor < 64) { |
---|
1290 | wc = wc ? wc : 32; |
---|
1291 | wake_tx_task=1; |
---|
1292 | } |
---|
1293 | /* RX Mode code */ |
---|
1294 | else if (descriptor < 96) { |
---|
1295 | wc = (wc>>4); |
---|
1296 | } |
---|
1297 | /* TX Mode code */ |
---|
1298 | else if (descriptor < 128) { |
---|
1299 | wc = (wc>>4); |
---|
1300 | } |
---|
1301 | |
---|
1302 | #ifdef DEBUG |
---|
1303 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (descriptor << 16) | wc; |
---|
1304 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current; |
---|
1305 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr; |
---|
1306 | #endif |
---|
1307 | |
---|
1308 | /* If there is room in the event queue, copy the event there */ |
---|
1309 | if (brm->head - brm->tail != EVENT_QUEUE_SIZE) { |
---|
1310 | |
---|
1311 | /* Copy to event queue */ |
---|
1312 | brm->rt_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[msgadr]); |
---|
1313 | brm->rt_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[msgadr+1]); |
---|
1314 | len = wc; |
---|
1315 | while( len-- > 0){ |
---|
1316 | brm->rt_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[msgadr+2+len]); |
---|
1317 | } |
---|
1318 | brm->rt_event[INDEX(brm->head)].desc = descriptor; |
---|
1319 | brm->head++; |
---|
1320 | } |
---|
1321 | else { |
---|
1322 | /* Indicate overrun */ |
---|
1323 | brm->rt_event[INDEX(brm->head)].desc |= 0x8000; |
---|
1324 | } |
---|
1325 | |
---|
1326 | msgadr += (2+wc); |
---|
1327 | |
---|
1328 | if (msgadr >= READ_DMA(&brm->desc[descriptor].bot)) { |
---|
1329 | msgadr = READ_DMA(&brm->desc[descriptor].top); |
---|
1330 | } |
---|
1331 | brm->last_read[descriptor] = msgadr; |
---|
1332 | |
---|
1333 | #ifdef DEBUG |
---|
1334 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr; |
---|
1335 | #endif |
---|
1336 | wake_rx_task = 1; |
---|
1337 | } while ( (msgadr=brm->last_read[descriptor]) != current ); |
---|
1338 | } |
---|
1339 | |
---|
1340 | if (pending & BRM_EOL_IRQ) { |
---|
1341 | wake_tx_task = 1; |
---|
1342 | } |
---|
1343 | |
---|
1344 | if (pending & BRM_BC_ILLCMD_IRQ) { |
---|
1345 | brm->bc_list_fail = 1; |
---|
1346 | wake_tx_task = 1; |
---|
1347 | SET_ERROR_DESCRIPTOR(descriptor); |
---|
1348 | FUNCDBG("BRM: ILLCMD IRQ\n\r"); |
---|
1349 | } |
---|
1350 | |
---|
1351 | /* Monitor irq */ |
---|
1352 | if (pending & BRM_MBC_IRQ) { |
---|
1353 | |
---|
1354 | stop_operation(brm); |
---|
1355 | brm->regs->mbc = 1; |
---|
1356 | start_operation(brm); |
---|
1357 | |
---|
1358 | /* If there is room in the event queue, copy the event there */ |
---|
1359 | if (brm->head - brm->tail != EVENT_QUEUE_SIZE) { |
---|
1360 | |
---|
1361 | /* Copy to event queue */ |
---|
1362 | |
---|
1363 | brm->bm_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[0]); |
---|
1364 | brm->bm_event[INDEX(brm->head)].cw1 = READ_DMA(&brm->mem[1]); |
---|
1365 | brm->bm_event[INDEX(brm->head)].cw2 = READ_DMA(&brm->mem[2]); |
---|
1366 | brm->bm_event[INDEX(brm->head)].sw1 = READ_DMA(&brm->mem[4]); |
---|
1367 | brm->bm_event[INDEX(brm->head)].sw2 = READ_DMA(&brm->mem[5]); |
---|
1368 | brm->bm_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[6]); |
---|
1369 | |
---|
1370 | len = 32; |
---|
1371 | while ( len-- ){ |
---|
1372 | brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]); |
---|
1373 | len--; |
---|
1374 | brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]); |
---|
1375 | len--; |
---|
1376 | brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]); |
---|
1377 | len--; |
---|
1378 | brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]); |
---|
1379 | } |
---|
1380 | /* memcpy((void *)brm->bm_event[INDEX(brm->head)].data, &brm->mem[0x100], 32);*/ |
---|
1381 | |
---|
1382 | #ifdef DEBUG |
---|
1383 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_REG(&brm->regs->mbc) & 0xffff; |
---|
1384 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[0]); |
---|
1385 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[1]); |
---|
1386 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[4]); |
---|
1387 | #endif |
---|
1388 | |
---|
1389 | brm->head++; |
---|
1390 | |
---|
1391 | } |
---|
1392 | else { |
---|
1393 | /* Indicate overrun */ |
---|
1394 | brm->bm_event[INDEX(brm->head)].miw |= 0x8000; |
---|
1395 | } |
---|
1396 | |
---|
1397 | /* Wake any blocking thread */ |
---|
1398 | wake_rx_task = 1; |
---|
1399 | } |
---|
1400 | |
---|
1401 | /* The reset of the interrupts |
---|
1402 | * cause a event to be signalled |
---|
1403 | * so that user can handle error. |
---|
1404 | */ |
---|
1405 | if ( pending & BRM_RT_ILLCMD_IRQ){ |
---|
1406 | FUNCDBG("BRM: BRM_RT_ILLCMD_IRQ\n\r"); |
---|
1407 | brm->status |= BRM_RT_ILLCMD_IRQ; |
---|
1408 | event_status |= BRM_RT_ILLCMD_IRQ; |
---|
1409 | SET_ERROR_DESCRIPTOR(descriptor); |
---|
1410 | signal_event=1; |
---|
1411 | } |
---|
1412 | |
---|
1413 | if ( pending & BRM_ILLOP_IRQ){ |
---|
1414 | FUNCDBG("BRM: BRM_ILLOP_IRQ\n\r"); |
---|
1415 | brm->bc_list_fail = 1; |
---|
1416 | wake_tx_task = 1; |
---|
1417 | event_status |= BRM_ILLOP_IRQ; |
---|
1418 | SET_ERROR_DESCRIPTOR(descriptor); |
---|
1419 | signal_event=1; |
---|
1420 | } |
---|
1421 | |
---|
1422 | if ( pending & BRM_MERR_IRQ){ |
---|
1423 | FUNCDBG("BRM: BRM_MERR_IRQ\n\r"); |
---|
1424 | event_status |= BRM_MERR_IRQ; |
---|
1425 | SET_ERROR_DESCRIPTOR(descriptor); |
---|
1426 | signal_event=1; |
---|
1427 | } |
---|
1428 | /* Clear Block Accessed Bit */ |
---|
1429 | tmp = READ_DMA(&brm->desc[descriptor].ctrl); |
---|
1430 | brm->desc[descriptor].ctrl = tmp & ~0x10; |
---|
1431 | #ifdef DEBUG |
---|
1432 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xfe<<16); |
---|
1433 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0; |
---|
1434 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp & ~0x10; |
---|
1435 | brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp; |
---|
1436 | #endif |
---|
1437 | } /* While */ |
---|
1438 | |
---|
1439 | /* clear interrupt flags & handle Hardware errors */ |
---|
1440 | pending = READ_REG(&brm->regs->ipend); |
---|
1441 | |
---|
1442 | if ( pending & BRM_DMAF_IRQ){ |
---|
1443 | FUNCDBG("BRM: BRM_DMAF_IRQ\n\r"); |
---|
1444 | event_status |= BRM_DMAF_IRQ; |
---|
1445 | signal_event=1; |
---|
1446 | } |
---|
1447 | |
---|
1448 | if ( pending & BRM_WRAPF_IRQ){ |
---|
1449 | FUNCDBG("BRM: BRM_WRAPF_IRQ\n\r"); |
---|
1450 | event_status |= BRM_WRAPF_IRQ; |
---|
1451 | signal_event=1; |
---|
1452 | } |
---|
1453 | |
---|
1454 | if ( pending & BRM_TAPF_IRQ){ |
---|
1455 | FUNCDBG("BRM: BRM_TAPF_IRQ\n\r"); |
---|
1456 | event_status |= BRM_TAPF_IRQ; |
---|
1457 | signal_event=1; |
---|
1458 | } |
---|
1459 | |
---|
1460 | /* Copy current mask to status mask */ |
---|
1461 | if ( event_status ){ |
---|
1462 | if ( event_status & 0xffff0000 ) |
---|
1463 | brm->status &= 0x0000ffff; |
---|
1464 | brm->status |= event_status; |
---|
1465 | } |
---|
1466 | |
---|
1467 | /* Wake any blocked rx thread only on receive interrupts */ |
---|
1468 | if ( wake_rx_task ) { |
---|
1469 | rtems_semaphore_release(brm->rx_sem); |
---|
1470 | } |
---|
1471 | |
---|
1472 | /* Wake any blocked tx thread only on transmit interrupts */ |
---|
1473 | if ( wake_tx_task ) { |
---|
1474 | rtems_semaphore_release(brm->tx_sem); |
---|
1475 | } |
---|
1476 | |
---|
1477 | /* signal event once */ |
---|
1478 | if ( signal_event && (brm->event_id!=0) ){ |
---|
1479 | rtems_event_send(brm->event_id, event_status); |
---|
1480 | } |
---|
1481 | |
---|
1482 | } |
---|
1483 | |
---|
1484 | void b1553brm_print_dev(struct drvmgr_dev *dev, int options) |
---|
1485 | { |
---|
1486 | brm_priv *pDev = dev->priv; |
---|
1487 | struct brm_reg *regs = pDev->regs; |
---|
1488 | |
---|
1489 | /* Print */ |
---|
1490 | printf("--- B1553BRM[%d] %s ---\n", pDev->minor, pDev->devName); |
---|
1491 | printf(" REGS: 0x%x\n", (unsigned int)pDev->regs); |
---|
1492 | printf(" IRQ: %d\n", pDev->irqno); |
---|
1493 | switch (pDev->mode) { |
---|
1494 | case BRM_MODE_BC: |
---|
1495 | printf(" MODE: BC\n"); |
---|
1496 | printf(" DESCS: 0x%x\n", (unsigned int)&pDev->bcmem->descs[0]); |
---|
1497 | printf(" DATA: 0x%x\n", (unsigned int)&pDev->bcmem->msg_data[0].data[0]); |
---|
1498 | printf(" IRQLOG: 0x%x\n", (unsigned int)&pDev->bcmem->irq_logs[0]); |
---|
1499 | break; |
---|
1500 | case BRM_MODE_BM: |
---|
1501 | printf(" MODE: BM\n"); |
---|
1502 | break; |
---|
1503 | case BRM_MODE_RT: |
---|
1504 | printf(" MODE: RT\n"); |
---|
1505 | printf(" RXSUBS: 0x%x\n", (unsigned int)&pDev->rtmem->rxsubs[0]); |
---|
1506 | printf(" TXSUBS: 0x%x\n", (unsigned int)&pDev->rtmem->txsubs[0]); |
---|
1507 | printf(" RXMODES: 0x%x\n", (unsigned int)&pDev->rtmem->rxmodes[0]); |
---|
1508 | printf(" TXOMODES: 0x%x\n", (unsigned int)&pDev->rtmem->txmodes[0]); |
---|
1509 | printf(" RXSUBS MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->rxsuba_msgs[0]); |
---|
1510 | printf(" TXSUBS MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->txsuba_msgs[0]); |
---|
1511 | printf(" RXMODES MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->rxmode_msgs[0]); |
---|
1512 | printf(" TXMODES MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->txmode_msgs[0]); |
---|
1513 | printf(" IRQLOG: 0x%x\n", (unsigned int)&pDev->rtmem->irq_logs[0]); |
---|
1514 | break; |
---|
1515 | } |
---|
1516 | printf(" CTRL: 0x%x\n", regs->ctrl); |
---|
1517 | printf(" OPER: 0x%x\n", regs->oper); |
---|
1518 | printf(" CUR_CMD: 0x%x\n", regs->cur_cmd); |
---|
1519 | printf(" IMASK: 0x%x\n", regs->imask); |
---|
1520 | printf(" IPEND: 0x%x\n", regs->ipend); |
---|
1521 | printf(" IPOINT: 0x%x\n", regs->ipoint); |
---|
1522 | printf(" BIT_REG: 0x%x\n", regs->bit_reg); |
---|
1523 | printf(" TTAG: 0x%x\n", regs->ttag); |
---|
1524 | printf(" DPOINT: 0x%x\n", regs->dpoint); |
---|
1525 | printf(" SW: 0x%x\n", regs->sw); |
---|
1526 | printf(" INITCOUNT: 0x%x\n", regs->initcount); |
---|
1527 | printf(" MCPOINT: 0x%x\n", regs->mcpoint); |
---|
1528 | printf(" MDPOINT: 0x%x\n", regs->mdpoint); |
---|
1529 | printf(" MBC: 0x%x\n", regs->mbc); |
---|
1530 | printf(" MFILTA: 0x%x\n", regs->mfilta); |
---|
1531 | printf(" MFILTB: 0x%x\n", regs->mfiltb); |
---|
1532 | printf(" ENHANCED: 0x%x\n", regs->enhanced); |
---|
1533 | printf(" W_CTRL: 0x%x\n", regs->w_ctrl); |
---|
1534 | printf(" W_IRQCTRL: 0x%x\n", regs->w_irqctrl); |
---|
1535 | printf(" W_AHBADDR: 0x%x\n", regs->w_ahbaddr); |
---|
1536 | } |
---|
1537 | |
---|
1538 | void b1553brm_print(int options) |
---|
1539 | { |
---|
1540 | struct amba_drv_info *drv = &b1553brm_drv_info; |
---|
1541 | struct drvmgr_dev *dev; |
---|
1542 | |
---|
1543 | dev = drv->general.dev; |
---|
1544 | while(dev) { |
---|
1545 | b1553brm_print_dev(dev, options); |
---|
1546 | dev = dev->next_in_drv; |
---|
1547 | } |
---|
1548 | } |
---|