source: rtems/c/src/lib/libbsp/m68k/gen68360/console/console.c @ 36a14a96

4.104.114.84.95
Last change on this file since 36a14a96 was 36a14a96, checked in by Joel Sherrill <joel.sherrill@…>, on May 4, 1998 at 12:38:53 PM

Patch from Eric Norum to switch to termios callback structure and
add support for changing the baudrate.

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