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

4.11
Last change on this file since e160e41 was e160e41, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 9, 2014 at 8:15:55 PM

powerpc/ep1a: Remove if 0 sections

There may be useful nuggets for debug and alternate configurations
in this code. There may be methods directly called by the application
which are beyond normal APIs. We have no way of knowing this based
on the comments in these files. There were no public prototypes
so the routines and code in question should have be unused private
methods.

These will always be in the source code control system as a deletion.
If some of the code is needed, justify it and provide a patch to restore
it along with a prototype in a public place if needed and a better name.

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