source: rtems/bsps/m68k/gen68360/console/console.c @ d7d66d7

5
Last change on this file since d7d66d7 was d7d66d7, checked in by Sebastian Huber <sebastian.huber@…>, on 04/19/18 at 04:28:01

bsps: Move console drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 8.4 KB
RevLine 
[457b6ae]1/*
[4106f7f]2 *  SMC1 raw console serial I/O.
[457b6ae]3 *
[96c73ab]4 *  This driver is an example of `POLLING' or `INTERRUPT' I/O.
[457b6ae]5 *
[96c73ab]6 *  To run with interrupt-driven I/O, ensure m360_smc1_interrupt
7 *  is set before calling the initialization routine.
[c186f2ed]8 */
9
10/*
[4106f7f]11 *  Author:
12 *    W. Eric Norum
13 *    Saskatchewan Accelerator Laboratory
14 *    University of Saskatchewan
15 *    Saskatoon, Saskatchewan, CANADA
16 *    eric@skatter.usask.ca
[457b6ae]17 *
[08311cc3]18 *  COPYRIGHT (c) 1989-1999.
[457b6ae]19 *  On-Line Applications Research Corporation (OAR).
20 *
[98e4ebf5]21 *  The license and distribution terms for this file may be
22 *  found in the file LICENSE in this distribution or at
[c499856]23 *  http://www.rtems.org/license/LICENSE.
[457b6ae]24 */
25
[4106f7f]26#include <termios.h>
[457b6ae]27#include <bsp.h>
28#include <rtems/libio.h>
[9e79b3f]29#include <rtems/console.h>
[8d2cfda]30#include <rtems/termiostypes.h>
[424f3027]31#include <rtems/m68k/m68360.h>
[457b6ae]32
[36a14a96]33/*
34 * Declare clock speed -- may be overwritten by downloader or debugger
35 */
[c186f2ed]36int m360_clock_rate  = 25000000;
[36a14a96]37
[96c73ab]38/*
39 * Interrupt-driven input buffer
[69405459]40 * Declare console baud rate -- may also be overwritten
41 */
42int console_baud_rate = 9600;
43
44/*
[96c73ab]45 */
[c186f2ed]46#define RXBUFSIZE  16
[96c73ab]47
48/*
49 * Interrupt-driven callback
50 */
51static int m360_smc1_interrupt = 1;
[4106f7f]52static void *smc1ttyp;
[457b6ae]53
54/*
[4106f7f]55 * I/O buffers and pointers to buffer descriptors
[457b6ae]56 */
[d24ceb3]57static volatile char rxBuf[RXBUFSIZE];
[4106f7f]58static volatile m360BufferDescriptor_t *smcRxBd, *smcTxBd;
[457b6ae]59
[4106f7f]60/*
61 * Device-specific routines
62 */
[36a14a96]63
64/*
65 * Compute baud-rate-generator configuration register value
66 */
67static int
68smc1BRGC (int baud)
69{
[c186f2ed]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;
[36a14a96]79}
80
81/*
82 * Hardware-dependent portion of tcsetattr().
83 */
84static int
85smc1SetAttributes (int minor, const struct termios *t)
86{
[6825d06]87  int baud;
[36a14a96]88
[1c6926c1]89  baud = rtems_termios_baud_to_number(t->c_ospeed);
[6825d06]90  if (baud > 0)
91    m360.brgc1 = smc1BRGC (baud);
92  return 0;
[36a14a96]93}
94
95/*
96 * Interrupt handler
97 */
[4106f7f]98static rtems_isr
99smc1InterruptHandler (rtems_vector_number v)
[457b6ae]100{
[c186f2ed]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 */
[4106f7f]123}
[457b6ae]124
[cb620844]125static int
126smc1Initialize (int major, int minor, void *arg)
[4106f7f]127{
[c186f2ed]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;
[457b6ae]212}
213
[4106f7f]214static int
[36a14a96]215smc1PollRead (int minor)
[457b6ae]216{
[c186f2ed]217  unsigned char c;
[457b6ae]218
[c186f2ed]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;
[4106f7f]224}
[457b6ae]225
[d24ceb3]226/*
227 * Device-dependent write routine
228 * Interrupt-driven devices:
[c186f2ed]229 *  Begin transmission of as many characters as possible (minimum is 1).
[d24ceb3]230 * Polling devices:
[c186f2ed]231 *  Transmit all characters.
[d24ceb3]232 */
[39a9f8e]233static ssize_t
234smc1InterruptWrite (int minor, const char *buf, size_t len)
[457b6ae]235{
[c186f2ed]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  }
[e18db9f]241
[c186f2ed]242  return 0;
[96c73ab]243}
244
[39a9f8e]245static ssize_t
246smc1PollWrite (int minor, const char *buf, size_t len)
[96c73ab]247{
[c186f2ed]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;
[457b6ae]259}
260
[4106f7f]261/*
262 ***************
263 * BOILERPLATE *
264 ***************
[457b6ae]265 */
266
[d24ceb3]267/*
268 * Reserve resources consumed by this driver
[7ee88c16]269 *
270 * NOTE: This is in another file to reduce dependencies on the minimum size.
[d24ceb3]271 */
272
[4106f7f]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
[457b6ae]280)
281{
[c186f2ed]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;
[457b6ae]296}
297
298/*
[4106f7f]299 * Open the device
[457b6ae]300 */
301rtems_device_driver console_open(
302  rtems_device_major_number major,
303  rtems_device_minor_number minor,
304  void                    * arg
305)
306{
[c186f2ed]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;
[457b6ae]342}
[6128a4a]343
[457b6ae]344/*
[4106f7f]345 * Close the device
[457b6ae]346 */
347rtems_device_driver console_close(
348  rtems_device_major_number major,
349  rtems_device_minor_number minor,
350  void                    * arg
351)
352{
[c186f2ed]353  return rtems_termios_close (arg);
[457b6ae]354}
355
356/*
[4106f7f]357 * Read from the device
[457b6ae]358 */
359rtems_device_driver console_read(
360  rtems_device_major_number major,
361  rtems_device_minor_number minor,
362  void                    * arg
363)
364{
[c186f2ed]365  return rtems_termios_read (arg);
[457b6ae]366}
367
368/*
[4106f7f]369 * Write to the device
[457b6ae]370 */
371rtems_device_driver console_write(
372  rtems_device_major_number major,
373  rtems_device_minor_number minor,
374  void                    * arg
375)
376{
[c186f2ed]377  return rtems_termios_write (arg);
[457b6ae]378}
379
380/*
[4106f7f]381 * Handle ioctl request.
[457b6ae]382 */
383rtems_device_driver console_control(
384  rtems_device_major_number major,
385  rtems_device_minor_number minor,
386  void                    * arg
387)
[6128a4a]388{
[c186f2ed]389  return rtems_termios_ioctl (arg);
[457b6ae]390}
Note: See TracBrowser for help on using the repository browser.