source: rtems/c/src/lib/libbsp/m68k/gen68360/console/console.c @ 1c6926c1

Last change on this file since 1c6926c1 was 1c6926c1, checked in by Kevin Kirspel <kevin-kirspel@…>, on Mar 21, 2017 at 7:39:48 PM

termios: Synchronize with latest FreeBSD headers

Adding modified FreeBSD headers to synchronize RTEMS termios with
FreeBSD. Modify termios to support dedicated input and output baud for
termios structure. Updated BSPs to use dedicated input and output baud
in termios structure. Updated tools to use dedicated input and output
baud in termios structure. Updated termios testsuites to use dedicated
input and output baud in termios structure.

Close #2897.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/*
2 *  SMC1 raw console serial I/O.
3 *
4 *  This driver is an example of `POLLING' or `INTERRUPT' I/O.
5 *
6 *  To run with interrupt-driven I/O, ensure m360_smc1_interrupt
7 *  is set before calling the initialization routine.
8 */
9
10/*
11 *  Author:
12 *    W. Eric Norum
13 *    Saskatchewan Accelerator Laboratory
14 *    University of Saskatchewan
15 *    Saskatoon, Saskatchewan, CANADA
16 *    eric@skatter.usask.ca
17 *
18 *  COPYRIGHT (c) 1989-1999.
19 *  On-Line Applications Research Corporation (OAR).
20 *
21 *  The license and distribution terms for this file may be
22 *  found in the file LICENSE in this distribution or at
23 *  http://www.rtems.org/license/LICENSE.
24 */
25
26#include <termios.h>
27#include <bsp.h>
28#include <rtems/libio.h>
29#include <rtems/console.h>
30#include <rtems/termiostypes.h>
31#include <rtems/m68k/m68360.h>
32
33/*
34 * Declare clock speed -- may be overwritten by downloader or debugger
35 */
36int m360_clock_rate  = 25000000;
37
38/*
39 * Interrupt-driven input buffer
40 * Declare console baud rate -- may also be overwritten
41 */
42int console_baud_rate = 9600;
43
44/*
45 */
46#define RXBUFSIZE  16
47
48/*
49 * Interrupt-driven callback
50 */
51static int m360_smc1_interrupt = 1;
52static void *smc1ttyp;
53
54/*
55 * I/O buffers and pointers to buffer descriptors
56 */
57static volatile char rxBuf[RXBUFSIZE];
58static volatile m360BufferDescriptor_t *smcRxBd, *smcTxBd;
59
60/*
61 * Device-specific routines
62 */
63
64/*
65 * Compute baud-rate-generator configuration register value
66 */
67static int
68smc1BRGC (int baud)
69{
70  int divisor;
71  int div16 = 0;
72
73  divisor = ((m360_clock_rate / 16) + (baud / 2)) / baud;
74  if (divisor > 4096) {
75    div16 = 1;
76    divisor = (divisor + 8) / 16;
77  }
78  return M360_BRG_EN | M360_BRG_EXTC_BRGCLK | ((divisor - 1) << 1) | div16;
79}
80
81/*
82 * Hardware-dependent portion of tcsetattr().
83 */
84static int
85smc1SetAttributes (int minor, const struct termios *t)
86{
87  int baud;
88
89  baud = rtems_termios_baud_to_number(t->c_ospeed);
90  if (baud > 0)
91    m360.brgc1 = smc1BRGC (baud);
92  return 0;
93}
94
95/*
96 * Interrupt handler
97 */
98static rtems_isr
99smc1InterruptHandler (rtems_vector_number v)
100{
101  /*
102   * Buffer received?
103   */
104  if (m360.smc1.smce & 0x1) {
105    m360.smc1.smce = 0x1;
106    while ((smcRxBd->status & M360_BD_EMPTY) == 0) {
107      rtems_termios_enqueue_raw_characters (smc1ttyp,
108              (char *)smcRxBd->buffer,
109              smcRxBd->length);
110      smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT;
111    }
112  }
113
114  /*
115   * Buffer transmitted?
116   */
117  if (m360.smc1.smce & 0x2) {
118    m360.smc1.smce = 0x2;
119    if ((smcTxBd->status & M360_BD_READY) == 0)
120      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
121  }
122  m360.cisr = 1UL << 4;  /* Clear SMC1 interrupt-in-service bit */
123}
124
125static int
126smc1Initialize (int major, int minor, void *arg)
127{
128  /*
129   * Allocate buffer descriptors
130   */
131  smcRxBd = M360AllocateBufferDescriptors (1);
132  smcTxBd = M360AllocateBufferDescriptors (1);
133
134  /*
135   * Configure port B pins to enable SMTXD1 and SMRXD1 pins
136   */
137  m360.pbpar |=  0xC0;
138  m360.pbdir &= ~0xC0;
139  m360.pbodr &= ~0xC0;
140
141  /*
142   * Set up BRG1 (9,600 baud)
143   */
144  m360.brgc1 = M360_BRG_RST;
145  m360.brgc1 = smc1BRGC (console_baud_rate);
146
147  /*
148   * Put SMC1 in NMSI mode, connect SMC1 to BRG1
149   */
150  m360.simode |= M360_SI_SMC1_BRG1;
151
152  /*
153   * Set up SMC1 parameter RAM common to all protocols
154   */
155  m360.smc1p.rbase = (char *)smcRxBd - (char *)&m360;
156  m360.smc1p.tbase = (char *)smcTxBd - (char *)&m360;
157  m360.smc1p.rfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE;
158  m360.smc1p.tfcr = M360_TFCR_MOT | M360_TFCR_DMA_SPACE;
159  if (m360_smc1_interrupt)
160    m360.smc1p.mrblr = RXBUFSIZE;
161  else
162    m360.smc1p.mrblr = 1;
163
164  /*
165   * Set up SMC1 parameter RAM UART-specific parameters
166   */
167  m360.smc1p.un.uart.max_idl = 10;
168  m360.smc1p.un.uart.brklen = 0;
169  m360.smc1p.un.uart.brkec = 0;
170  m360.smc1p.un.uart.brkcr = 0;
171
172  /*
173   * Set up the Receive Buffer Descriptor
174   */
175  smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT;
176  smcRxBd->length = 0;
177  smcRxBd->buffer = rxBuf;
178
179  /*
180   * Setup the Transmit Buffer Descriptor
181   */
182  smcTxBd->status = M360_BD_WRAP;
183
184  /*
185   * Set up SMC1 general and protocol-specific mode registers
186   */
187  m360.smc1.smce = ~0;  /* Clear any pending events */
188  m360.smc1.smcm = 0;  /* Mask all interrupt/event sources */
189  m360.smc1.smcmr = M360_SMCMR_CLEN(9) | M360_SMCMR_SM_UART;
190
191  /*
192   * Send "Init parameters" command
193   */
194  M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SMC1);
195
196  /*
197   * Enable receiver and transmitter
198   */
199  m360.smc1.smcmr |= M360_SMCMR_TEN | M360_SMCMR_REN;
200
201  if (m360_smc1_interrupt) {
202  rtems_isr_entry old_handler;
203
204  (void) rtems_interrupt_catch (smc1InterruptHandler,
205            (m360.cicr & 0xE0) | 0x04,
206            &old_handler);
207  m360.smc1.smcm = 3;  /* Enable SMC1 TX and RX interrupts */
208  m360.cimr |= 1UL << 4;  /* Enable SMC1 interrupts */
209  }
210
211  return 0;
212}
213
214static int
215smc1PollRead (int minor)
216{
217  unsigned char c;
218
219  if (smcRxBd->status & M360_BD_EMPTY)
220    return -1;
221  c = rxBuf[0];
222  smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP;
223  return c;
224}
225
226/*
227 * Device-dependent write routine
228 * Interrupt-driven devices:
229 *  Begin transmission of as many characters as possible (minimum is 1).
230 * Polling devices:
231 *  Transmit all characters.
232 */
233static ssize_t
234smc1InterruptWrite (int minor, const char *buf, size_t len)
235{
236  if (len > 0) {
237    smcTxBd->buffer = (char *)buf;
238    smcTxBd->length = len;
239    smcTxBd->status = M360_BD_READY | M360_BD_WRAP | M360_BD_INTERRUPT;
240  }
241
242  return 0;
243}
244
245static ssize_t
246smc1PollWrite (int minor, const char *buf, size_t len)
247{
248  size_t retval = len;
249  while (len--) {
250    static char txBuf;
251    while (smcTxBd->status & M360_BD_READY)
252      continue;
253    txBuf = *buf++;
254    smcTxBd->buffer = &txBuf;
255    smcTxBd->length = 1;
256    smcTxBd->status = M360_BD_READY | M360_BD_WRAP;
257  }
258  return retval;
259}
260
261/*
262 ***************
263 * BOILERPLATE *
264 ***************
265 */
266
267/*
268 * Reserve resources consumed by this driver
269 *
270 * NOTE: This is in another file to reduce dependencies on the minimum size.
271 */
272
273/*
274 * Initialize and register the device
275 */
276rtems_device_driver console_initialize(
277  rtems_device_major_number  major,
278  rtems_device_minor_number  minor,
279  void                      *arg
280)
281{
282  rtems_status_code status;
283
284  /*
285   * Set up TERMIOS
286   */
287  rtems_termios_initialize ();
288
289  /*
290   * Register the device
291   */
292  status = rtems_io_register_name ("/dev/console", major, 0);
293  if (status != RTEMS_SUCCESSFUL)
294    rtems_fatal_error_occurred (status);
295  return RTEMS_SUCCESSFUL;
296}
297
298/*
299 * Open the device
300 */
301rtems_device_driver console_open(
302  rtems_device_major_number major,
303  rtems_device_minor_number minor,
304  void                    * arg
305)
306{
307  rtems_status_code sc;
308  static const rtems_termios_callbacks intrCallbacks = {
309    smc1Initialize,    /* firstOpen */
310    NULL,      /* lastClose */
311    NULL,      /* pollRead */
312    smc1InterruptWrite,  /* write */
313    smc1SetAttributes,  /* setAttributes */
314    NULL,      /* stopRemoteTx */
315    NULL,      /* startRemoteTx */
316    1      /* outputUsesInterrupts */
317  };
318  static const rtems_termios_callbacks pollCallbacks = {
319    smc1Initialize,    /* firstOpen */
320    NULL,      /* lastClose */
321    smc1PollRead,    /* pollRead */
322    smc1PollWrite,    /* write */
323    smc1SetAttributes,  /* setAttributes */
324    NULL,      /* stopRemoteTx */
325    NULL,      /* startRemoteTx */
326    0      /* outputUsesInterrupts */
327  };
328
329  /*
330   * Do generic termios initialization
331   */
332  if (m360_smc1_interrupt) {
333    rtems_libio_open_close_args_t *args = arg;
334
335    sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
336    smc1ttyp = args->iop->data1;
337  }
338  else {
339    sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
340  }
341  return sc;
342}
343
344/*
345 * Close the device
346 */
347rtems_device_driver console_close(
348  rtems_device_major_number major,
349  rtems_device_minor_number minor,
350  void                    * arg
351)
352{
353  return rtems_termios_close (arg);
354}
355
356/*
357 * Read from the device
358 */
359rtems_device_driver console_read(
360  rtems_device_major_number major,
361  rtems_device_minor_number minor,
362  void                    * arg
363)
364{
365  return rtems_termios_read (arg);
366}
367
368/*
369 * Write to the device
370 */
371rtems_device_driver console_write(
372  rtems_device_major_number major,
373  rtems_device_minor_number minor,
374  void                    * arg
375)
376{
377  return rtems_termios_write (arg);
378}
379
380/*
381 * Handle ioctl request.
382 */
383rtems_device_driver console_control(
384  rtems_device_major_number major,
385  rtems_device_minor_number minor,
386  void                    * arg
387)
388{
389  return rtems_termios_ioctl (arg);
390}
Note: See TracBrowser for help on using the repository browser.