source: rtems/c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c @ 7a4c4f4

4.115
Last change on this file since 7a4c4f4 was 7a4c4f4, checked in by Joel Sherrill <joel.sherrill@…>, on 10/13/14 at 15:28:44

powerpc/ep1a: Fix warnings

  • Property mode set to 100644
File size: 25.4 KB
RevLine 
[e36390a6]1/*  This file contains the termios TTY driver for the
2 *  Motorola MC68360 SCC ports.
[cc7c922]3 */
4
5/*
[e36390a6]6 *  COPYRIGHT (c) 1989-2008.
[0329aae]7 *  On-Line Applications Research Corporation (OAR).
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
[c499856]11 *  http://www.rtems.org/license/LICENSE.
[0329aae]12 */
13
14#include <stdio.h>
15#include <termios.h>
16#include <bsp.h>
17#include <libcpu/io.h>
18#include <rtems/libio.h>
19#include <bsp/pci.h>
20#include <bsp/irq.h>
21#include <libchip/serial.h>
22#include "m68360.h"
23#include <libchip/sersupp.h>
24#include <stdlib.h>
25#include <rtems/bspIo.h>
26#include <string.h>
27
[e160e41]28/* #define DEBUG_360 */
[e36390a6]29
30#if 1   /* XXX */
31int EP1A_READ_LENGTH_GREATER_THAN_1 = 0;
32
33#define MC68360_LENGTH_SIZE 400
34int mc68360_length_array[ MC68360_LENGTH_SIZE ];
[0329aae]35int mc68360_length_count=0;
[cc7c922]36#endif
[e36390a6]37
[0329aae]38
39M68360_t    M68360_chips = NULL;
40
41#define SYNC     eieio
[cc7c922]42#define mc68360_scc_Is_422( _minor ) \
43  (Console_Port_Tbl[minor]->sDeviceName[7] == '4' )
[e36390a6]44
[cc7c922]45static void scc_write8(
[0329aae]46  const char       *name,
47  volatile uint8_t *address,
48  uint8_t           value
49)
50{
51#ifdef DEBUG_360
52  printk( "WR8 %s 0x%08x 0x%02x\n", name, address, value );
53#endif
54  *address = value;
55}
56
[cc7c922]57static uint16_t scc_read16(
[0329aae]58  const char        *name,
59  volatile uint16_t *address
60)
61{
62  uint16_t value;
63
64#ifdef DEBUG_360
65  printk( "RD16 %s 0x%08x ", name, address );
66#endif
67  value = *address;
68#ifdef DEBUG_360
69  printk( "0x%04x\n", value );
70#endif
71
72  return value;
73}
74
[cc7c922]75static void scc_write16(
[0329aae]76  const char        *name,
77  volatile uint16_t *address,
78  uint16_t           value
79)
80{
81#ifdef DEBUG_360
82  printk( "WR16 %s 0x%08x 0x%04x\n", name, address, value );
83#endif
84  *address = value;
85}
86
[cc7c922]87static uint32_t scc_read32(
[0329aae]88  const char        *name,
89  volatile uint32_t *address
90)
91{
92  uint32_t value;
93
94#ifdef DEBUG_360
95  printk( "RD32 %s 0x%08x ", name, address );
96#endif
97  value = *address;
98#ifdef DEBUG_360
99  printk( "0x%08x\n", value );
100#endif
101
102  return value;
103}
104
[cc7c922]105static void scc_write32(
[0329aae]106  const char        *name,
107  volatile uint32_t *address,
108  uint32_t           value
109)
110{
111#ifdef DEBUG_360
112  printk( "WR32 %s 0x%08x 0x%08x\n", name, address, value );
113#endif
114  *address = value;
115}
116
117#define TX_BUFFER_ADDRESS( _ptr ) \
118  ((char *)ptr->txBuf - (char *)ptr->chip->board_data->baseaddr)
119#define RX_BUFFER_ADDRESS( _ptr ) \
120  ((char *)ptr->rxBuf - (char *)ptr->chip->board_data->baseaddr)
121
122
123/**************************************************************************
124 * Function: mc68360_sccBRGC                                             *
125 **************************************************************************
126 * Description:                                                           *
127 *                                                                        *
128 *    This function is called to compute the divisor register values for  *
129 *    a given baud rate.                                                  *
130 *                                                                        *
131 *                                                                        *
132 * Inputs:                                                                *
133 *                                                                        *
134 *    int baud  - Baud rate (in bps).                                     *
135 *                                                                        *
136 * Output:                                                                *
137 *                                                                        *
138 *    int  - baud rate generator configuration.                           *
139 *                                                                        *
140 **************************************************************************/
141static int
142mc68360_sccBRGC(int baud, int m360_clock_rate)
143{
[e160e41]144  int data;
[0329aae]145
146  /*
147   * configure baud rate generator for 16x bit rate, where.....
148   * b    =   desired baud rate
149   * clk  =   system clock (33mhz)
150   * d    =   clock dividor value
151   *
152   * for b > 300  :   d = clk/(b*16)
153   * for b<= 300  :   d = (clk/ (b*16*16))-1)
154   */
155
156  SYNC();
157  if( baud > 300 ) data = 33333333 / (baud * 16 );
158  else             data = (33333333 / (baud * 16 * 16) ) - 1;
159  data *= 2;
160  data &= 0x00001ffe ;
[ac7af4a]161
[0329aae]162  /* really data = 0x010000 | data | ((baud>300)? 0 : 1 ) ; */
163  data |= ((baud>300)? 0 : 1 ) ;
164  data |= 0x010000 ;
[ac7af4a]165
[0329aae]166  return data;
167}
168
169
[7a4c4f4]170/*
171 * sccInterruptHandler
172 *
173 * This is the interrupt service routine for the console UART.  It
174 * handles both receive and transmit interrupts.  The bulk of the
175 * work is done by termios.
176 *
177 */
178static void mc68360_sccInterruptHandler( M68360_t chip )
[0329aae]179{
180  volatile m360_t    *m360;
181  int                port;
182  uint16_t           status;
183  uint16_t           length;
184  int                i;
185  char               data;
186  int                clear_isr;
187
[e36390a6]188
189#ifdef DEBUG_360
190  printk("mc68360_sccInterruptHandler\n");
191#endif
[0329aae]192  for (port=0; port<4; port++) {
193
194      clear_isr = FALSE;
195      m360  = chip->m360;
196
[e36390a6]197      /*
198       * XXX - Can we add something here to check if this is our interrupt.
199       * XXX - We need a parameter here so that we know which 360 instead of
200       *       looping through them all!
201       */
202
[0329aae]203      /*
204       * Handle a RX interrupt.
205       */
206      if ( scc_read16("scce", &chip->port[port].pSCCR->scce) & 0x1)
207      {
208        clear_isr = TRUE;
209        scc_write16("scce", &chip->port[port].pSCCR->scce, 0x1 );
210        status =scc_read16( "sccRxBd->status", &chip->port[port].sccRxBd->status);
211        while ((status & M360_BD_EMPTY) == 0)
212        {
213           length= scc_read16("sccRxBd->length",&chip->port[port].sccRxBd->length);
[e36390a6]214if (length > 1)
215  EP1A_READ_LENGTH_GREATER_THAN_1 = length;
216
[0329aae]217           for (i=0;i<length;i++) {
218             data= chip->port[port].rxBuf[i];
219             rtems_termios_enqueue_raw_characters(
220               Console_Port_Data[ chip->port[port].minor ].termios_data,
221               &data,
222               1);
223           }
[ac7af4a]224           scc_write16( "sccRxBd->status", &chip->port[port].sccRxBd->status,
[0329aae]225                        M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT );
226           status =scc_read16( "sccRxBd->status", &chip->port[port].sccRxBd->status);
227        }
228      }
229
230      /*
231       * Handle a TX interrupt.
232       */
233      if (scc_read16("scce", &chip->port[port].pSCCR->scce) & 0x2)
234      {
235        clear_isr = TRUE;
236        scc_write16("scce", &chip->port[port].pSCCR->scce, 0x2);
237        status = scc_read16("sccTxBd->status", &chip->port[port].sccTxBd->status);
238        if ((status & M360_BD_EMPTY) == 0)
239        {
240           scc_write16("sccTxBd->status",&chip->port[port].sccTxBd->status,0);
[e36390a6]241#if 1
[0329aae]242           rtems_termios_dequeue_characters(
[ac7af4a]243             Console_Port_Data[chip->port[port].minor].termios_data,
[0329aae]244             chip->port[port].sccTxBd->length);
[e36390a6]245#else
[ac7af4a]246           mc68360_scc_write_support_int(chip->port[port].minor,"*****", 5);
[e36390a6]247#endif
[0329aae]248        }
249      }
250
251      /*
252       * Clear SCC interrupt-in-service bit.
253       */
254      if ( clear_isr )
255        scc_write32( "cisr", &m360->cisr, (0x80000000 >> chip->port[port].channel) );
256  }
257}
258
259/*
260 *  mc68360_scc_open
261 *
262 *  This function opens a port for communication.
263 *
264 *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
265 */
[cc7c922]266static int mc68360_scc_open(
[0329aae]267  int      major,
268  int      minor,
269  void    * arg
270)
271{
[e36390a6]272  M68360_serial_ports_t  ptr;
273  uint32_t               data;
274
275#ifdef DEBUG_360
276  printk("mc68360_scc_open %d\n", minor);
277#endif
278
[7a4c4f4]279  ptr = Console_Port_Tbl[minor]->pDeviceParams;
[e36390a6]280
281  /*
282   * Enable the receiver and the transmitter.
283   */
284  SYNC();
285  data = scc_read32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l);
286  scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l,
287    (data | M360_GSMR_ENR | M360_GSMR_ENT) );
288
289  data  = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK );
290  data &= (~PMCQ1_INT_MASK_QUICC);
291  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK, data );
292
293  data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS );
294  data &= (~PMCQ1_INT_STATUS_QUICC);
295  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS, data );
[0329aae]296
297  return RTEMS_SUCCESSFUL;
298}
299
[7a4c4f4]300static uint32_t mc68360_scc_calculate_pbdat( M68360_t chip )
[e36390a6]301{
302  uint32_t               i;
303  uint32_t               pbdat_data;
304  int                    minor;
305  uint32_t               type422data[4] = {
306    0x00440,  0x00880,  0x10100,  0x20200
307  };
308
309  pbdat_data = 0x3;
310  for (i=0; i<4; i++) {
311    minor = chip->port[i].minor;
[ac7af4a]312    if mc68360_scc_Is_422( minor )
[e36390a6]313      pbdat_data |= type422data[i];
314  }
315
316  return pbdat_data;
317}
318
[0329aae]319/*
320 *  mc68360_scc_initialize_interrupts
321 *
322 *  This routine initializes the console's receive and transmit
323 *  ring buffers and loads the appropriate vectors to handle the interrupts.
324 */
[7a4c4f4]325static void mc68360_scc_initialize_interrupts(int minor)
[0329aae]326{
327  M68360_serial_ports_t  ptr;
328  volatile m360_t       *m360;
329  uint32_t               data;
330  uint32_t               buffers_start;
331  uint32_t               tmp_u32;
332
333#ifdef DEBUG_360
334  printk("mc68360_scc_initialize_interrupts: minor %d\n", minor );
[00991a3]335  printk("Console_Port_Tbl[minor]->pDeviceParams 0x%08x\n",
336    Console_Port_Tbl[minor]->pDeviceParams );
[0329aae]337#endif
338
[00991a3]339  ptr   = Console_Port_Tbl[minor]->pDeviceParams;
[0329aae]340  m360  = ptr->chip->m360;
[ac7af4a]341
[0329aae]342#ifdef DEBUG_360
343  printk("m360 0x%08x baseaddr 0x%08x\n",
344     m360, ptr->chip->board_data->baseaddr);
345#endif
346
347  buffers_start = ptr->chip->board_data->baseaddr + 0x00200000 +
348            ( (M68360_RX_BUF_SIZE + M68360_TX_BUF_SIZE) * (ptr->channel-1));
349  ptr->rxBuf = (uint8_t *) buffers_start;
350  ptr->txBuf = (uint8_t *)(buffers_start + M68360_RX_BUF_SIZE);
351#ifdef DEBUG_360
352  printk("rxBuf 0x%08x  txBuf 0x%08x\n", ptr->rxBuf, ptr->txBuf );
353#endif
354  /*
355   * Set Channel Drive Enable bits in EPLD
356   */
357  data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE );
358  SYNC();
[e36390a6]359  data = data & ~(PMCQ1_DRIVER_ENABLE_3 | PMCQ1_DRIVER_ENABLE_2 |
360                  PMCQ1_DRIVER_ENABLE_1 | PMCQ1_DRIVER_ENABLE_0);
[0329aae]361  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE, data);
362  data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE );
363  SYNC();
364
365  /*
366   * Disable the receiver and the transmitter.
367   */
368
369  SYNC();
370  tmp_u32 = scc_read32( "gsmr_l", &ptr->pSCCR->gsmr_l );
371  tmp_u32 &= (~(M360_GSMR_ENR | M360_GSMR_ENT ) ) ;
372  scc_write32( "gsmr_l", &ptr->pSCCR->gsmr_l, tmp_u32 );
373
374  /*
375   * Disable Interrupt Error and Interrupt Breakpoint
376   * Set SAID to 4 XXX - Shouldn't it be 7 for slave mode
377   * Set SAISM to 7
378   */
379  SYNC();
380  scc_write16( "sdcr", &m360->sdcr, 0x0740 );
381
382  /*
383   * Clear status -- reserved interrupt, SDMA channel error, SDMA breakpoint
384   */
385  scc_write8( "sdsr", &m360->sdsr, 0x07 );
386  SYNC();
387
388  /*
389   * Initialize timer information in RISC Controller Configuration Register
390   */
391  scc_write16( "rccr", &m360->rccr, 0x8100 );
392  SYNC();
393
394  /*
395   * XXX
396   */
397  scc_write16( "papar", &m360->papar, 0xffff );
398  scc_write16( "padir", &m360->padir, 0x5500 ); /* From Memo    */
399  scc_write16( "paodr", &m360->paodr, 0x0000 );
400  SYNC();
401
402  /*
403   * XXX
404   */
[e36390a6]405
406#if 0
[0329aae]407  scc_write32( "pbpar", &m360->pbpar, 0x00000000 );
408  scc_write32( "pbdir", &m360->pbdir, 0x0003ffff );
409  scc_write32( "pbdat", &m360->pbdat, 0x0000003f );
410  SYNC();
[e36390a6]411#else
412  data = mc68360_scc_calculate_pbdat( ptr->chip );
413  scc_write32( "pbpar", &m360->pbpar, 0x00000000 );
414  scc_write32( "pbdat", &m360->pbdat, data );
415  SYNC();
416  scc_write32( "pbdir", &m360->pbdir, 0x0003fc3 );
417  SYNC();
418#endif
419
[0329aae]420
421  /*
422   * XXX
423   */
424  scc_write16( "pcpar", &m360->pcpar, 0x0000 );
425  scc_write16( "pcdir", &m360->pcdir, 0x0000 );
426  scc_write16( "pcso", &m360->pcso, 0x0000 );
427  SYNC();
428
429  /*
430   * configure baud rate generator for 16x bit rate, where.....
431   * b    =   desired baud rate
432   * clk  =   system clock (33mhz)
433   * d    =   clock dividor value
434   *
435   * for b > 300  :   d = clk/(b*16)
436   * for b<= 300  :   d = (clk/ (b*16*16))-1)
437   */
438  SYNC();
439  if( ptr->baud > 300 ) data = 33333333 / (ptr->baud * 16 );
440  else                  data = (33333333 / (ptr->baud * 16 * 16) ) - 1;
441  data *= 2 ;
442  data &= 0x00001ffe ;
443
444  /* really data = 0x010000 | data | ((baud>300)? 0 : 1 ) ; */
445  data |= ((ptr->baud>300)? 0 : 1 ) ;
446  data |= 0x010000 ;
447
448  scc_write32( "pBRGC", ptr->pBRGC, data );
449
450  data =  (((ptr->channel-1)*8) | (ptr->channel-1)) ;
451  data = data << ((ptr->channel-1)*8) ;
452  data |= scc_read32( "sicr", &m360->sicr );
453  scc_write32( "sicr", &m360->sicr, data );
454
455  /*
456   * initialise SCC parameter ram
457   */
458  SYNC();
459  scc_write16( "pSCCB->rbase", &ptr->pSCCB->rbase,
460               (char *)(ptr->sccRxBd) - (char *)m360 );
461  scc_write16( "pSCCB->tbase", &ptr->pSCCB->tbase,
462               (char *)(ptr->sccTxBd) - (char *)m360 );
463
464  scc_write8( "pSCCB->rfcr", &ptr->pSCCB->rfcr, 0x15 ); /* 0x15 0x18 */
465  scc_write8( "pSCCB->tfcr", &ptr->pSCCB->tfcr, 0x15 ); /* 0x15 0x18 */
466
467  scc_write16( "pSCCB->mrblr", &ptr->pSCCB->mrblr, M68360_RX_BUF_SIZE );
468
469  /*
470   * initialise tx and rx scc parameters
471   */
472  SYNC();
473  data  = M360_CR_INIT_TX_RX_PARAMS | 0x01;
474  data |= (M360_CR_CH_NUM * (ptr->channel-1) );
475  scc_write16( "CR", &m360->cr, data );
476
477  /*
478   * initialise uart specific parameter RAM
479   */
480  SYNC();
481  scc_write16( "pSCCB->un.uart.max_idl", &ptr->pSCCB->un.uart.max_idl, 15000 );
482  scc_write16( "pSCCB->un.uart.brkcr", &ptr->pSCCB->un.uart.brkcr, 0x0001 );
483  scc_write16( "pSCCB->un.uart.parec", &ptr->pSCCB->un.uart.parec, 0x0000 );
484
485  scc_write16( "pSCCB->un,uart.frmec", &ptr->pSCCB->un.uart.frmec, 0x0000 );
486
487  scc_write16( "pSCCB->un.uart.nosec", &ptr->pSCCB->un.uart.nosec, 0x0000 );
488  scc_write16( "pSCCB->un.uart.brkec", &ptr->pSCCB->un.uart.brkec, 0x0000 );
489  scc_write16( "pSCCB->un.uart.uaddr0", &ptr->pSCCB->un.uart.uaddr[0], 0x0000 );
490  scc_write16( "pSCCB->un.uart.uaddr1", &ptr->pSCCB->un.uart.uaddr[1], 0x0000 );
491  scc_write16( "pSCCB->un.uart.toseq", &ptr->pSCCB->un.uart.toseq, 0x0000 );
492  scc_write16( "pSCCB->un.uart.char0",
493               &ptr->pSCCB->un.uart.character[0], 0x0039 );
494  scc_write16( "pSCCB->un.uart.char1",
495               &ptr->pSCCB->un.uart.character[1], 0x8000 );
496  scc_write16( "pSCCB->un.uart.char2",
497               &ptr->pSCCB->un.uart.character[2], 0x8000 );
498  scc_write16( "pSCCB->un.uart.char3",
499               &ptr->pSCCB->un.uart.character[3], 0x8000 );
500  scc_write16( "pSCCB->un.uart.char4",
501               &ptr->pSCCB->un.uart.character[4], 0x8000 );
502  scc_write16( "pSCCB->un.uart.char5",
503               &ptr->pSCCB->un.uart.character[5], 0x8000 );
504  scc_write16( "pSCCB->un.uart.char6",
505               &ptr->pSCCB->un.uart.character[6], 0x8000 );
506  scc_write16( "pSCCB->un.uart.char7",
507               &ptr->pSCCB->un.uart.character[7], 0x8000 );
508
509  scc_write16( "pSCCB->un.uart.rccm", &ptr->pSCCB->un.uart.rccm, 0xc0ff );
510
511  /*
512   * setup buffer descriptor stuff
513   */
514  SYNC();
515  scc_write16( "sccRxBd->status", &ptr->sccRxBd->status, 0x0000 );
516  SYNC();
517  scc_write16( "sccRxBd->length", &ptr->sccRxBd->length, 0x0000 );
[ac7af4a]518  scc_write16( "sccRxBd->status", &ptr->sccRxBd->status,
[0329aae]519               M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT );
520  /* XXX Radstone Example writes RX buffer ptr as two u16's */
521  scc_write32( "sccRxBd->buffer", &ptr->sccRxBd->buffer,
522               RX_BUFFER_ADDRESS( ptr ) );
523
524  SYNC();
525  scc_write16( "sccTxBd->status", &ptr->sccTxBd->status, 0x0000 );
526  SYNC();
527  scc_write16( "sccTxBd->length", &ptr->sccTxBd->length, 0x0000 );
528  /* XXX Radstone Example writes TX buffer ptr as two u16's */
529  scc_write32( "sccTxBd->buffer", &ptr->sccTxBd->buffer,
530               TX_BUFFER_ADDRESS( ptr ) );
531
532  /*
533   * clear previous events and set interrupt priorities
534   */
535  scc_write16( "pSCCR->scce", &ptr->pSCCR->scce, 0x1bef ); /* From memo   */
536  SYNC();
537  SYNC();
538  scc_write32( "cicr", &m360->cicr, 0x001b9f40 );
539  SYNC();
540
541  /* scc_write32( "cicr", &m360->cicr, scc_read32( "cicr", &m360->cicr ) ); */
542
543  scc_write16( "pSCCR->sccm", &ptr->pSCCR->sccm, M360_SCCE_TX | M360_SCCE_RX );
544
[ac7af4a]545  data = scc_read32("cimr", &m360->cimr);
[0329aae]546  data |= (0x80000000 >> ptr->channel);
547  scc_write32( "cimr", &m360->cimr, data );
548  SYNC();
549  scc_write32( "cipr", &m360->cipr, scc_read32( "cipr", &m360->cipr ) );
550
551  scc_write32( "pSCCR->gsmr_h", &ptr->pSCCR->gsmr_h, M360_GSMR_RFW );
[ac7af4a]552  scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l,
[0329aae]553        (M360_GSMR_TDCR_16X | M360_GSMR_RDCR_16X | M360_GSMR_MODE_UART) );
554
555  scc_write16( "pSCCR->dsr", &ptr->pSCCR->dsr, 0x7e7e );
556  SYNC();
557
558  scc_write16( "pSCCR->psmr", &ptr->pSCCR->psmr,
559               (M360_PSMR_CL8 | M360_PSMR_UM_NORMAL | M360_PSMR_TPM_ODD) );
560  SYNC();
561
[e36390a6]562#if 0          /* XXX - ??? */
[0329aae]563  /*
564   * Enable the receiver and the transmitter.
565   */
566
567  SYNC();
568  data = scc_read32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l);
569  scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l,
[e36390a6]570    (data | M360_GSMR_ENR | M360_GSMR_ENT) );
[0329aae]571
572  data  = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK );
573  data &= (~PMCQ1_INT_MASK_QUICC);
[ac7af4a]574  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK, data );
575
[0329aae]576  data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS );
577  data &= (~PMCQ1_INT_STATUS_QUICC);
578  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS, data );
[ac7af4a]579#endif
[0329aae]580}
581
582/*
583 *  mc68360_scc_write_support_int
584 *
585 *  Console Termios output entry point when using interrupt driven output.
586 */
[7a4c4f4]587static ssize_t mc68360_scc_write_support_int(
[0329aae]588  int         minor,
589  const char *buf,
[cc7c922]590  size_t      len
[0329aae]591)
592{
593  rtems_interrupt_level  Irql;
594  M68360_serial_ports_t  ptr;
595
[e36390a6]596#if 1
[0329aae]597  mc68360_length_array[ mc68360_length_count ] = len;
598  mc68360_length_count++;
[e36390a6]599  if ( mc68360_length_count >= MC68360_LENGTH_SIZE )
[0329aae]600    mc68360_length_count=0;
[e36390a6]601#endif
[0329aae]602
[00991a3]603  ptr   = Console_Port_Tbl[minor]->pDeviceParams;
[0329aae]604
605  /*
606   *  We are using interrupt driven output and termios only sends us
607   *  one character at a time.
608   */
609
610  if ( !len )
611    return 0;
612
613  /*
614   *
615   */
616#ifdef DEBUG_360
617  printk("mc68360_scc_write_support_int: char 0x%x length %d\n",
618       (unsigned int)*buf, len );
619#endif
620  /*
621   *  We must copy the data from the global memory space to MC68360 space
622   */
623
624  rtems_interrupt_disable(Irql);
625
626  scc_write16( "sccTxBd->status", &ptr->sccTxBd->status, 0 );
627  memcpy((void *) ptr->txBuf, buf, len);
[ac7af4a]628  scc_write32( "sccTxBd->buffer", &ptr->sccTxBd->buffer,
[0329aae]629               TX_BUFFER_ADDRESS(ptr->txBuf) );
630  scc_write16( "sccTxBd->length", &ptr->sccTxBd->length, len );
[ac7af4a]631  scc_write16( "sccTxBd->status", &ptr->sccTxBd->status,
[0329aae]632               (M360_BD_READY | M360_BD_WRAP | M360_BD_INTERRUPT) );
633
634  rtems_interrupt_enable(Irql);
635
636  return len;
637}
638
639/*
640 *  mc68360_scc_write_polled
641 *
642 *  This routine polls out the requested character.
643 */
[7a4c4f4]644static void mc68360_scc_write_polled(
[0329aae]645  int   minor,
646  char  cChar
647)
648{
649#ifdef DEBUG_360
650  printk("mc68360_scc_write_polled: %c\n", cChar);
651#endif
652}
653
654/*
655 *  mc68681_set_attributes
656 *
657 *  This function sets the DUART channel to reflect the requested termios
658 *  port settings.
659 */
[7a4c4f4]660static int mc68360_scc_set_attributes(
[0329aae]661  int minor,
662  const struct termios *t
663)
664{
[7a4c4f4]665  int                    baud;
666  M68360_serial_ports_t  ptr;
667  uint16_t               value;
[e36390a6]668
669#ifdef DEBUG_360
670printk("mc68360_scc_set_attributes\n");
671#endif
[0329aae]672
[7a4c4f4]673  ptr = Console_Port_Tbl[minor]->pDeviceParams;
674
675  switch (t->c_cflag & CBAUD) {
676    case B50:      baud = 50;      break;
677    case B75:      baud = 75;      break;
678    case B110:     baud = 110;     break;
679    case B134:     baud = 134;     break;
680    case B150:     baud = 150;     break;
681    case B200:     baud = 200;     break;
682    case B300:     baud = 300;     break;
683    case B600:     baud = 600;     break;
684    case B1200:    baud = 1200;    break;
685    case B1800:    baud = 1800;    break;
686    case B2400:    baud = 2400;    break;
687    case B4800:    baud = 4800;    break;
688    case B9600:    baud = 9600;    break;
689    case B19200:   baud = 19200;   break;
690    case B38400:   baud = 38400;   break;
691    case B57600:   baud = 57600;   break;
692    case B115200:  baud = 115200;  break;
693    case B230400:  baud = 230400;  break;
694    case B460800:  baud = 460800;  break;
695    default:       baud = -1;      break;
696  }
697
698  if (baud > 0) {
699    scc_write32(
700      "pBRGC",
701      ptr->pBRGC,
702      mc68360_sccBRGC(baud, ptr->chip->m360_clock_rate)
703    );
704  }
[0329aae]705
[e36390a6]706  /* Initial value of PSMR should be 0 */
707  value = M360_PSMR_UM_NORMAL;
708
709  /* set the number of data bits, 8 is most common */
[7a4c4f4]710  if (t->c_cflag & CSIZE) {                   /* was it specified? */
[e36390a6]711    switch (t->c_cflag & CSIZE) {
712      case CS5: value |= M360_PSMR_CL5; break;
713      case CS6: value |= M360_PSMR_CL6; break;
714      case CS7: value |= M360_PSMR_CL7; break;
715      case CS8: value |= M360_PSMR_CL8; break;
716    }
717  } else {
718    value |= M360_PSMR_CL8;         /* default to 8 data bits */
719  }
720
721  /* the number of stop bits */
722  if (t->c_cflag & CSTOPB)
723    value |= M360_PSMR_SL_2;   /* Two stop bits */
724  else
725    value |= M360_PSMR_SL_1;   /* One stop bit  */
726
[ac7af4a]727  /* Set Parity M360_PSMR_PEN bit should be clear on no parity so
728   * do nothing in that case
[e36390a6]729   */
[7a4c4f4]730  if (t->c_cflag & PARENB) {              /* enable parity detection? */
[ac7af4a]731    value |= M360_PSMR_PEN;
[e36390a6]732    if (t->c_cflag & PARODD){
733      value |= M360_PSMR_RPM_ODD;        /* select odd parity */
[ac7af4a]734      value |= M360_PSMR_TPM_ODD;
[e36390a6]735    } else {
736      value |= M360_PSMR_RPM_EVEN;       /* select even parity */
[ac7af4a]737      value |= M360_PSMR_TPM_EVEN;
[e36390a6]738    }
739  }
740
741  SYNC();
742  scc_write16( "pSCCR->psmr", &ptr->pSCCR->psmr, value );
743  SYNC();
744
[0329aae]745  return 0;
746}
747
748/*
749 *  mc68360_scc_close
750 *
751 *  This function shuts down the requested port.
752 */
[7a4c4f4]753static int mc68360_scc_close(
[0329aae]754  int      major,
755  int      minor,
756  void    *arg
757)
758{
[7a4c4f4]759  return RTEMS_SUCCESSFUL;
[0329aae]760}
761
762/*
763 *  mc68360_scc_inbyte_nonblocking_polled
764 *
765 *  Console Termios polling input entry point.
766 */
[7a4c4f4]767static int mc68360_scc_inbyte_nonblocking_polled(
[0329aae]768  int minor
769)
770{
[7a4c4f4]771  return -1;
[0329aae]772}
773
774/*
775 *  mc68360_scc_write_support_polled
776 *
777 *  Console Termios output entry point when using polled output.
778 *
779 */
[7a4c4f4]780static ssize_t mc68360_scc_write_support_polled(
[0329aae]781  int         minor,
782  const char *buf,
[39a9f8e]783  size_t      len
[0329aae]784)
785{
[ac7af4a]786  printk("mc68360_scc_write_support_polled: minor %d char %c len %d\n",
[0329aae]787         minor, buf, len );
[39a9f8e]788  return len;
[0329aae]789}
790
791/*
792 *  mc68360_scc_init
793 *
794 *  This function initializes the DUART to a quiecsent state.
795 */
[7a4c4f4]796static void mc68360_scc_init(int minor)
[0329aae]797{
798#ifdef DEBUG_360
799  printk("mc68360_scc_init\n");
800#endif
801}
802
803int mc68360_scc_create_chip( PPMCQ1BoardData BoardData, uint8_t int_vector )
804{
805  M68360_t   chip;
806  int        i;
807
808#ifdef DEBUG_360
809  printk("mc68360_scc_create_chip\n");
810#endif
811
812  /*
813   * Create console structure for this card
814   * XXX - Note Does this need to be moved up to if a QUICC is fitted
815   *       section?
816   */
817  if ((chip = malloc(sizeof(struct _m68360_per_chip))) == NULL)
818  {
819    printk("Error Unable to allocate memory for _m68360_per_chip\n");
820    return RTEMS_IO_ERROR;
821  }
822
823  chip->next                    = M68360_chips;
824  chip->m360                    = (void *)BoardData->baseaddr;
825  chip->m360_interrupt          = int_vector;
826  chip->m360_clock_rate         = 25000000;
827  chip->board_data              = BoardData;
828  M68360_chips                  = chip;
829
830  for (i=1; i<=4; i++) {
831    chip->port[i-1].channel     = i;
832    chip->port[i-1].chip        = chip;
833    chip->port[i-1].baud        = 9600;
834
835    switch( i ) {
836      case 1:
837        chip->port[i-1].pBRGC = &chip->m360->brgc1;
838        chip->port[i-1].pSCCB = (m360SCCparms_t *) &chip->m360->scc1p;
839        chip->port[i-1].pSCCR = &chip->m360->scc1;
840        M360SetupMemory( chip );            /* Do this first time through */
841        break;
842      case 2:
843        chip->port[i-1].pBRGC = &chip->m360->brgc2;
844        chip->port[i-1].pSCCB = &chip->m360->scc2p;
845        chip->port[i-1].pSCCR = &chip->m360->scc2;
846        break;
847      case 3:
848        chip->port[i-1].pBRGC = &chip->m360->brgc3;
849        chip->port[i-1].pSCCB = &chip->m360->scc3p;
850        chip->port[i-1].pSCCR = &chip->m360->scc3;
851        break;
852      case 4:
853        chip->port[i-1].pBRGC = &chip->m360->brgc4;
854        chip->port[i-1].pSCCB = &chip->m360->scc4p;
855        chip->port[i-1].pSCCR = &chip->m360->scc4;
856        break;
857      default:
858        printk("Invalid mc68360 channel %d\n", i);
859        return RTEMS_IO_ERROR;
860    }
861
862    /*
863     * Allocate buffer descriptors.
864     */
865
866    chip->port[i-1].sccRxBd = M360AllocateBufferDescriptors(chip, 1);
867    chip->port[i-1].sccTxBd = M360AllocateBufferDescriptors(chip, 1);
868  }
869
870  rsPMCQ1QuiccIntConnect(
871    chip->board_data->busNo,
872    chip->board_data->slotNo,
873    chip->board_data->funcNo,
[7a4c4f4]874    (FUNCTION_PTR) &mc68360_sccInterruptHandler,
[cc7c922]875    (uintptr_t) chip
[0329aae]876  );
877
878  return RTEMS_SUCCESSFUL;
879}
880
[c8bd3cd]881const console_fns mc68360_scc_fns = {
[0329aae]882  libchip_serial_default_probe,        /* deviceProbe */
883  mc68360_scc_open,                    /* deviceFirstOpen */
884  NULL,                                /* deviceLastClose */
885  NULL,                                /* deviceRead */
886  mc68360_scc_write_support_int,       /* deviceWrite */
887  mc68360_scc_initialize_interrupts,   /* deviceInitialize */
888  mc68360_scc_write_polled,            /* deviceWritePolled */
889  mc68360_scc_set_attributes,          /* deviceSetAttributes */
890  TRUE                                 /* deviceOutputUsesInterrupts */
891};
892
[c8bd3cd]893const console_fns mc68360_scc_polled = {
[0329aae]894  libchip_serial_default_probe,             /* deviceProbe */
895  mc68360_scc_open,                         /* deviceFirstOpen */
896  mc68360_scc_close,                        /* deviceLastClose */
897  mc68360_scc_inbyte_nonblocking_polled,    /* deviceRead */
898  mc68360_scc_write_support_polled,         /* deviceWrite */
899  mc68360_scc_init,                         /* deviceInitialize */
900  mc68360_scc_write_polled,                 /* deviceWritePolled */
901  mc68360_scc_set_attributes,               /* deviceSetAttributes */
902  FALSE                                     /* deviceOutputUsesInterrupts */
903};
904
Note: See TracBrowser for help on using the repository browser.