]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/serial/freescale/esci/drv/v2_0/src/ser_esci.c
Initial revision
[karo-tx-redboot.git] / packages / devs / serial / freescale / esci / drv / v2_0 / src / ser_esci.c
1 //==========================================================================
2 //
3 //      ser_esci.c
4 //
5 //      Freescale sSCI Serial I/O Interface Module (interrupt driven)
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2996 eCosCentric Ltd
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 // -------------------------------------------
37 //####ECOSGPLCOPYRIGHTEND####
38 //==========================================================================
39 //#####DESCRIPTIONBEGIN####
40 //
41 // Author(s):   Ilija Koco <ilijak@siva.com.mk>
42 // Contributors:
43 // Date:        2006-04-20
44 // Purpose:     eSCI Serial I/O module (interrupt driven version)
45 // Description: 
46 //
47 //   
48 //####DESCRIPTIONEND####
49 //==========================================================================
50 #include <pkgconf/io_serial.h>
51 #include <pkgconf/io.h>
52
53 #include <cyg/io/io.h>
54 #include <cyg/hal/hal_intr.h>
55 #include <cyg/hal/hal_arbiter.h>
56 #include <cyg/hal/var_io.h>
57 #include <cyg/io/devtab.h>
58 #include <cyg/infra/diag.h>
59 #include <cyg/io/serial.h>
60 #include <cyg/devs/ser_esci.h>
61
62 // Only build this driver for if ESCI is needed.
63 #ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI
64
65 typedef struct esci_serial_info {
66     CYG_ADDRWORD   esci_base;          // Base address of the esci port
67     CYG_WORD       interrupt_num;      // INTC interrupt vector
68     cyg_priority_t interrupt_priority; // INTC interupt priority
69     cyg_interrupt  interrupt_obj;      // Interrupt object
70     cyg_handle_t   interrupt_handle;   // Interrupt handle
71 } esci_serial_info;
72
73 static bool esci_serial_init(struct cyg_devtab_entry * tab);
74 static bool esci_serial_putc(serial_channel * chan, unsigned char c);
75 static Cyg_ErrNo esci_serial_lookup(struct cyg_devtab_entry ** tab, 
76                                     struct cyg_devtab_entry * sub_tab, 
77                                     const char * name);
78 static unsigned char esci_serial_getc(serial_channel *chan);
79 static Cyg_ErrNo esci_serial_set_config(serial_channel *chan, cyg_uint32 key, 
80                                         const void *xbuf, cyg_uint32 *len);
81 static void esci_serial_start_xmit(serial_channel *chan);
82 static void esci_serial_stop_xmit(serial_channel *chan);
83
84 // Interrupt servers
85 static cyg_uint32 esci_serial_ISR(cyg_vector_t vector, cyg_addrword_t data);
86 static void       esci_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, 
87                                   cyg_addrword_t data);
88
89 static SERIAL_FUNS(esci_serial_funs, 
90                    esci_serial_putc, 
91                    esci_serial_getc,
92                    esci_serial_set_config,
93                    esci_serial_start_xmit,
94                    esci_serial_stop_xmit);
95
96 // Available baud rates
97 static unsigned short select_baud[] = {
98     0,                            // Unused
99     0,                            // 50     bps unsupported
100     0,                            // 75     bps unsupported
101     0,                            // 110    bps unsupported
102     0,                            // 134_5  bps unsupported
103     0,                            // 150    bps unsupported
104     0,                            // 200    bps unsupported
105     FREESCALE_ESCI_BAUD(300),     // 300    bps
106     FREESCALE_ESCI_BAUD(600),     // 600    bps
107     FREESCALE_ESCI_BAUD(1200),    // 1200   bps
108     0,                            // 1800   bps unsupported
109     FREESCALE_ESCI_BAUD(2400),    // 2400   bps
110     0,                            // 3600   bps unsupported
111     FREESCALE_ESCI_BAUD(4800),    // 4800   bps
112     0,                            // 7200   bps unsupported
113     FREESCALE_ESCI_BAUD(9600),    // 9600   bps
114     FREESCALE_ESCI_BAUD(14400),   // 14400  bps
115     FREESCALE_ESCI_BAUD(19200),   // 19200  bps
116     FREESCALE_ESCI_BAUD(38400),   // 38400  bps
117     FREESCALE_ESCI_BAUD(57600),   // 57600  bps
118     FREESCALE_ESCI_BAUD(115200),  // 115200 bps
119     0                             // 230400 bps unsupported
120 };
121
122 #if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_A
123 static esci_serial_info esci_serial_info0 = {
124     esci_base          : CYGADDR_IO_SERIAL_FREESCALE_ESCI_A_BASE,
125     interrupt_num      : CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_INT_VECTOR,
126     interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_INT_PRIORITY
127 };
128 #if CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE > 0
129 static unsigned char 
130     esci_serial_out_buf0[CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE]; 
131 static unsigned char 
132     esci_serial_in_buf0[CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE];
133
134 static 
135 SERIAL_CHANNEL_USING_INTERRUPTS(
136                                 esci_serial_channel0,
137                                 esci_serial_funs,
138                                 esci_serial_info0,
139                                 CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BAUD),
140                                 CYG_SERIAL_STOP_DEFAULT,
141                                 CYG_SERIAL_PARITY_DEFAULT,
142                                 CYG_SERIAL_WORD_LENGTH_DEFAULT,
143                                 CYG_SERIAL_FLAGS_DEFAULT,
144                                 &esci_serial_out_buf0[0],
145                                 sizeof(esci_serial_out_buf0),
146                                 &esci_serial_in_buf0[0],
147                                 sizeof(esci_serial_in_buf0));
148 #else 
149 static 
150 SERIAL_CHANNEL(esci_serial_channel0,
151                esci_serial_funs,
152                esci_serial_info0,
153                CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BAUD),
154                CYG_SERIAL_STOP_DEFAULT,
155                CYG_SERIAL_PARITY_DEFAULT,
156                CYG_SERIAL_WORD_LENGTH_DEFAULT,
157                CYG_SERIAL_FLAGS_DEFAULT);
158 #endif
159 DEVTAB_ENTRY(esci_serial_io0,
160              CYGDAT_IO_SERIAL_FREESCALE_ESCI_A_NAME,
161              0, // does not depend on a lower level device driver
162              &cyg_io_serial_devio,
163              esci_serial_init,
164              esci_serial_lookup,
165              &esci_serial_channel0);
166 #endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_A
167
168 #if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_B
169 static esci_serial_info esci_serial_info1 = {
170     esci_base          : CYGADDR_IO_SERIAL_FREESCALE_ESCI_B_BASE,
171     interrupt_num      : CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_INT_VECTOR,
172     interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_INT_PRIORITY
173 };
174 #if CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE > 0
175 static unsigned char 
176     esci_serial_out_buf1[CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE]; 
177 static unsigned char 
178     esci_serial_in_buf1[CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE];
179
180 static 
181 SERIAL_CHANNEL_USING_INTERRUPTS(esci_serial_channel1,
182                                 esci_serial_funs,
183                                 esci_serial_info1,
184                                 CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BAUD),
185                                 CYG_SERIAL_STOP_DEFAULT,
186                                 CYG_SERIAL_PARITY_DEFAULT,
187                                 CYG_SERIAL_WORD_LENGTH_DEFAULT,
188                                 CYG_SERIAL_FLAGS_DEFAULT,
189                                 &esci_serial_out_buf1[0],
190                                 sizeof(esci_serial_out_buf1),
191                                 &esci_serial_in_buf1[0],
192                                 sizeof(esci_serial_in_buf1));
193 #else 
194 static 
195 SERIAL_CHANNEL(esci_serial_channel1,
196                esci_serial_funs,
197                esci_serial_info1,
198                CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BAUD),
199                CYG_SERIAL_STOP_DEFAULT,
200                CYG_SERIAL_PARITY_DEFAULT,
201                CYG_SERIAL_WORD_LENGTH_DEFAULT,
202                CYG_SERIAL_FLAGS_DEFAULT);
203 #endif
204 DEVTAB_ENTRY(esci_serial_io1,
205              CYGDAT_IO_SERIAL_FREESCALE_ESCI_B_NAME,
206              0, // does not depend on a lower level device driver
207              &cyg_io_serial_devio,
208              esci_serial_init,
209              esci_serial_lookup,
210              &esci_serial_channel1);
211 #endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_B
212
213 #if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_C
214 static esci_serial_info esci_serial_info2 = {
215     esci_base          : CYGADDR_IO_SERIAL_FREESCALE_ESCI_C_BASE,
216     interrupt_num      : CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_INT_VECTOR,
217     interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_INT_PRIORITY
218 };
219 #if CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE > 0
220 static unsigned char 
221     esci_serial_out_buf2[CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE]; 
222 static unsigned char 
223     esci_serial_in_buf2[CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE];
224
225 static 
226 SERIAL_CHANNEL_USING_INTERRUPTS(esci_serial_channel2,
227                                 esci_serial_funs,
228                                 esci_serial_info2,
229                                 CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BAUD),
230                                 CYG_SERIAL_STOP_DEFAULT,
231                                 CYG_SERIAL_PARITY_DEFAULT,
232                                 CYG_SERIAL_WORD_LENGTH_DEFAULT,
233                                 CYG_SERIAL_FLAGS_DEFAULT,
234                                 &esci_serial_out_buf2[0],
235                                 sizeof(esci_serial_out_buf2),
236                                 &esci_serial_in_buf2[0],
237                                 sizeof(esci_serial_in_buf2));
238 #else 
239 static 
240 SERIAL_CHANNEL(esci_serial_channel2,
241                esci_serial_funs,
242                esci_serial_info2,
243                CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BAUD),
244                CYG_SERIAL_STOP_DEFAULT,
245                CYG_SERIAL_PARITY_DEFAULT,
246                CYG_SERIAL_WORD_LENGTH_DEFAULT,
247                CYG_SERIAL_FLAGS_DEFAULT);
248 #endif
249 DEVTAB_ENTRY(esci_serial_io2,
250              CYGDAT_IO_SERIAL_FREESCALE_ESCI_C_NAME,
251              0, // does not depend on a lower level device driver
252              &cyg_io_serial_devio,
253              esci_serial_init,
254              esci_serial_lookup,
255              &esci_serial_channel2);
256 #endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_C
257
258
259 #if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_D
260 static esci_serial_info esci_serial_info3 = {
261     esci_base          : CYGADDR_IO_SERIAL_FREESCALE_ESCI_D_BASE,
262     interrupt_num      : CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_INT_VECTOR,
263     interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_INT_PRIORITY
264 };
265 #if CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE > 0
266 static unsigned char 
267     esci_serial_out_buf3[CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE]; 
268 static unsigned char 
269     esci_serial_in_buf3[CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE];
270
271 static 
272 SERIAL_CHANNEL_USING_INTERRUPTS(esci_serial_channel3,
273                                 esci_serial_funs,
274                                 esci_serial_info3,
275                                 CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BAUD),
276                                 CYG_SERIAL_STOP_DEFAULT,
277                                 CYG_SERIAL_PARITY_DEFAULT,
278                                 CYG_SERIAL_WORD_LENGTH_DEFAULT,
279                                 CYG_SERIAL_FLAGS_DEFAULT,
280                                 &esci_serial_out_buf3[0],
281                                 sizeof(esci_serial_out_buf3),
282                                 &esci_serial_in_buf3[0],
283                                 sizeof(esci_serial_in_buf3));
284 #else 
285 static 
286 SERIAL_CHANNEL(esci_serial_channel3,
287                esci_serial_funs,
288                esci_serial_info3,
289                CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BAUD),
290                CYG_SERIAL_STOP_DEFAULT,
291                CYG_SERIAL_PARITY_DEFAULT,
292                CYG_SERIAL_WORD_LENGTH_DEFAULT,
293                CYG_SERIAL_FLAGS_DEFAULT);
294 #endif
295 DEVTAB_ENTRY(esci_serial_io3,
296              CYGDAT_IO_SERIAL_FREESCALE_ESCI_D_NAME,
297              0, // does not depend on a lower level device driver
298              &cyg_io_serial_devio,
299              esci_serial_init,
300              esci_serial_lookup,
301              &esci_serial_channel3);
302 #endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_D
303
304 //----------------------------------------------------------------------------
305 // Internal function to actually configure the hardware to desired
306 // baud rate, etc.
307 //----------------------------------------------------------------------------
308 static bool
309 esci_serial_config_port(serial_channel * chan, cyg_serial_info_t * new_config,
310                         bool init)
311 {
312     esci_serial_info * esci_chan = (esci_serial_info *)(chan->dev_priv);
313     cyg_addrword_t esci_base = esci_chan->esci_base;
314     cyg_uint16 baud_rate = ((new_config->baud >= 0) && 
315                             (new_config->baud < (sizeof(select_baud)/
316                                                  sizeof(select_baud[0]))))
317       ? select_baud[new_config->baud] : 0;
318     
319     cyg_uint16 esci_cr12=0, esci_cr12_old;
320     
321     HAL_WRITE_UINT8(FREESCALE_ESCI_CR3(esci_base), 0);
322     HAL_WRITE_UINT16(FREESCALE_ESCI_LINCTRL(esci_base), 0);
323     HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), 0);
324     
325     if(!baud_rate) return false;    // Invalid baud rate selected
326     
327     switch(new_config->word_length){
328     case 8: break;
329     default: return false;
330     }
331     
332     switch(new_config->parity){
333     case CYGNUM_SERIAL_PARITY_ODD:
334         esci_cr12 |= FREESCALE_ESCI_CR12_PT;
335     case CYGNUM_SERIAL_PARITY_EVEN:
336         esci_cr12 |= FREESCALE_ESCI_CR12_PE;        
337     case CYGNUM_SERIAL_PARITY_NONE:
338         break;
339     default: return false;
340     }
341     
342     if(new_config->stop!=CYGNUM_SERIAL_STOP_1) return false;
343     
344     // Enable the device
345     esci_cr12 |= FREESCALE_ESCI_CR12_TE | FREESCALE_ESCI_CR12_RE;
346     
347     if(init){ // Enable the receiver interrupt
348         esci_cr12 |= FREESCALE_ESCI_CR12_RIE;
349     }else{    // Restore the old interrupt state
350         HAL_READ_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12_old);
351         esci_cr12 |= (esci_cr12_old & FREESCALE_ESCI_CR12_RIE);
352     }
353     HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
354     
355     if(new_config != &chan->config)
356         chan->config = *new_config;
357
358     return true;
359 }
360
361 //--------------------------------------------------------------
362 // Function to initialize the device.  Called at bootstrap time.
363 //--------------------------------------------------------------
364 static bool
365 esci_serial_init(struct cyg_devtab_entry * tab)
366 {
367     serial_channel * chan = (serial_channel *)tab->priv;
368     esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
369
370     // Really only required for interrupt driven devices
371     (chan->callbacks->serial_init)(chan);  
372     if(chan->out_cbuf.len != 0){ 
373         cyg_drv_interrupt_create(esci_chan->interrupt_num,
374                                  esci_chan->interrupt_priority,
375                                  // Data item passed to interrupt handler
376                                  (cyg_addrword_t)chan,   
377                                  esci_serial_ISR,
378                                  esci_serial_DSR,
379                                  &esci_chan->interrupt_handle,
380                                  &esci_chan->interrupt_obj);
381         
382         cyg_drv_interrupt_attach(esci_chan->interrupt_handle);
383         cyg_drv_interrupt_unmask(esci_chan->interrupt_num);
384     }
385     return esci_serial_config_port(chan, &chan->config, true);
386 }
387
388 //----------------------------------------------------------------------
389 // This routine is called when the device is "looked" up (i.e. attached)
390 //----------------------------------------------------------------------
391 static Cyg_ErrNo
392 esci_serial_lookup(struct cyg_devtab_entry ** tab, 
393                    struct cyg_devtab_entry * sub_tab, const char * name)
394 {
395     serial_channel * chan = (serial_channel *)(*tab)->priv;
396     // Really only required for interrupt driven devices
397     (chan->callbacks->serial_init)(chan);  
398
399     return ENOERR;
400 }
401
402 //-----------------------------------------------------------------
403 // Send a character to Tx
404 //-----------------------------------------------------------------
405 static bool
406 esci_serial_putc(serial_channel * chan, unsigned char ch_out)
407 {
408     esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
409     cyg_addrword_t esci_base = esci_chan->esci_base;
410     cyg_uint16 esci_sr;
411     
412     HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr);
413     if(esci_sr & FREESCALE_ESCI_SR_TDRE){
414         HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_TDRE);
415         HAL_WRITE_UINT8(FREESCALE_ESCI_DRL(esci_base), ch_out);
416         return true;
417     }else
418         return false;
419 }
420
421 //---------------------------------------------------------------------
422 // Fetch a character Rx (for polled operation only)
423 //---------------------------------------------------------------------
424 static unsigned char
425 esci_serial_getc(serial_channel * chan)
426 {
427     cyg_uint8 ch_in;
428     esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
429     cyg_addrword_t esci_base = esci_chan->esci_base;
430     
431     cyg_uint16 esci_sr;
432     
433     do{
434         HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr);
435     }while(esci_sr & FREESCALE_ESCI_SR_RDRF);
436     
437     HAL_READ_UINT8(FREESCALE_ESCI_DRL(esci_base), ch_in);
438     HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_RDRF);
439     
440     return ch_in;
441 }
442
443 //---------------------------------------------------
444 // Set up the device characteristics; baud rate, etc.
445 //---------------------------------------------------
446 static bool
447 esci_serial_set_config(serial_channel * chan, cyg_uint32 key, 
448                        const void *xbuf, cyg_uint32 * len)
449 {
450     switch(key) {
451     case CYG_IO_SET_CONFIG_SERIAL_INFO:{
452             cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
453             if(*len < sizeof(cyg_serial_info_t)) {
454                 return -EINVAL;
455             }
456             *len = sizeof(cyg_serial_info_t);
457             if(true != esci_serial_config_port(chan, config, false))
458             return -EINVAL;
459         }
460         break;
461     default:
462         return -EINVAL;
463     }
464     return ENOERR;
465 }
466
467 //-------------------------------------
468 // Enable the transmitter on the device
469 //-------------------------------------
470 static void esci_serial_start_xmit(serial_channel * chan)
471 {
472     esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
473     cyg_addrword_t esci_base = esci_chan->esci_base;
474     cyg_uint16 esci_cr12;
475     
476     HAL_READ_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
477     esci_cr12 |= FREESCALE_ESCI_CR12_TIE;
478     HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
479 }
480
481 //--------------------------------------
482 // Disable the transmitter on the device
483 //--------------------------------------
484 static void esci_serial_stop_xmit(serial_channel * chan)
485 {
486     esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
487
488     cyg_addrword_t esci_base = esci_chan->esci_base;
489     cyg_uint16 esci_cr12;
490     
491     HAL_READ_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
492     esci_cr12 &= ~FREESCALE_ESCI_CR12_TIE;
493     HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
494 }
495
496 //-----------------------------------------
497 // The low level interrupt handler
498 //-----------------------------------------
499 static
500 cyg_uint32 esci_serial_ISR(cyg_vector_t vector, cyg_addrword_t data)
501 {
502     serial_channel * chan = (serial_channel *)data;
503     esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
504
505     cyg_drv_interrupt_mask(esci_chan->interrupt_num);
506     cyg_drv_interrupt_acknowledge(esci_chan->interrupt_num);
507
508     return CYG_ISR_CALL_DSR; // cause the DSR to run
509 }
510
511
512 //------------------------------------------
513 // The high level interrupt handler
514 //------------------------------------------
515
516 #define FREESCALE_ESCI_SR_ERRORS (FREESCALE_ESCI_SR_OR | \
517                                   FREESCALE_ESCI_SR_NF | \
518                                   FREESCALE_ESCI_SR_FE | \
519                                   FREESCALE_ESCI_SR_PF)
520
521 static void
522 esci_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
523 {
524     serial_channel * chan = (serial_channel *)data;
525     esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
526     cyg_addrword_t esci_base = esci_chan->esci_base;
527     cyg_uint16 esci_sr;
528     cyg_uint8 esci_dr;
529
530     HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr);
531     if(esci_sr & FREESCALE_ESCI_SR_RDRF){ // Receiver full
532         HAL_READ_UINT8(FREESCALE_ESCI_DRL(esci_base), esci_dr);
533         HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_RDRF);
534         if(esci_sr &= (cyg_uint16)FREESCALE_ESCI_SR_ERRORS){
535             HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr);
536         }else{
537             (chan->callbacks->rcv_char)(chan, (cyg_uint8)esci_dr);
538         }
539     }else if(esci_sr & FREESCALE_ESCI_SR_TDRE){ //Transmitter empty
540         (chan->callbacks->xmt_char)(chan);
541     }
542     
543     cyg_drv_interrupt_unmask(esci_chan->interrupt_num);
544 }
545
546 #endif // CYGPKG_IO_SERIAL_FREESCALE_ESCI_[ABCD]
547 // EOF ser_esci.c