source: rtems/c/src/lib/libbsp/m68k/gen68360/console/console.c @ 96c73ab

4.104.114.84.95
Last change on this file since 96c73ab was 96c73ab, checked in by Joel Sherrill <joel.sherrill@…>, on Feb 19, 1998 at 11:02:16 PM

Patch from Eric Norum:

While trying to work through this problem I decided that the
build-time selection of the console I/O operation (polling or
interrupt) was too clumsy. Here's a patch that allows run-time
(actually init-time) selection of the console I/O mode.

It also shows the need for another flags' or options' field in
the rtems_driver_address_table structure...

  • Property mode set to 100644
File size: 6.9 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 * Interrupt-driven input buffer
35 */
36#define RXBUFSIZE       16
37
38/*
39 * Interrupt-driven callback
40 */
41static int m360_smc1_interrupt = 1;
42static void *smc1ttyp;
43
44/*
45 * I/O buffers and pointers to buffer descriptors
46 */
47static volatile char rxBuf[RXBUFSIZE];
48static volatile m360BufferDescriptor_t *smcRxBd, *smcTxBd;
49
50/*
51 * Device-specific routines
52 */
53static rtems_isr
54smc1InterruptHandler (rtems_vector_number v)
55{
56        /*
57         * Buffer received?
58         */
59        if (m360.smc1.smce & 0x1) {
60                m360.smc1.smce = 0x1;
61                while ((smcRxBd->status & M360_BD_EMPTY) == 0) {
62                        rtems_termios_enqueue_raw_characters (smc1ttyp,
63                                                        (char *)smcRxBd->buffer,
64                                                        smcRxBd->length);
65                        smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT;
66                }
67        }
68
69        /*
70         * Buffer transmitted?
71         */
72        if (m360.smc1.smce & 0x2) {
73                m360.smc1.smce = 0x2;
74                if ((smcTxBd->status & M360_BD_READY) == 0)
75                        rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
76        }
77        m360.cisr = 1UL << 4;   /* Clear SMC1 interrupt-in-service bit */
78}
79
80static void
81smc1Initialize (void)
82{
83        /*
84         * Allocate buffer descriptors
85         */
86        smcRxBd = M360AllocateBufferDescriptors (1);
87        smcTxBd = M360AllocateBufferDescriptors (1);
88
89        /*
90         * Configure port B pins to enable SMTXD1 and SMRXD1 pins
91         */
92        m360.pbpar |=  0xC0;
93        m360.pbdir &= ~0xC0;
94        m360.pbodr &= ~0xC0;
95
96        /*
97         * Set up BRG1 (9,600 baud)
98         */
99        m360.brgc1 = M360_BRG_RST;
100        m360.brgc1 = M360_BRG_EN | M360_BRG_EXTC_BRGCLK | M360_BRG_9600;
101
102        /*
103         * Put SMC1 in NMSI mode, connect SMC1 to BRG1
104         */
105        m360.simode |= M360_SI_SMC1_BRG1;
106         
107        /*
108         * Set up SMC1 parameter RAM common to all protocols
109         */
110        m360.smc1p.rbase = (char *)smcRxBd - (char *)&m360;
111        m360.smc1p.tbase = (char *)smcTxBd - (char *)&m360;
112        m360.smc1p.rfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE;
113        m360.smc1p.tfcr = M360_TFCR_MOT | M360_TFCR_DMA_SPACE;
114        if (m360_smc1_interrupt)
115                m360.smc1p.mrblr = RXBUFSIZE;
116        else
117                m360.smc1p.mrblr = 1;
118         
119        /*
120         * Set up SMC1 parameter RAM UART-specific parameters
121         */
122        m360.smc1p.un.uart.max_idl = 10;
123        m360.smc1p.un.uart.brklen = 0;
124        m360.smc1p.un.uart.brkec = 0;
125        m360.smc1p.un.uart.brkcr = 0;
126         
127        /*
128         * Set up the Receive Buffer Descriptor
129         */
130        smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT;
131        smcRxBd->length = 0;
132        smcRxBd->buffer = rxBuf;
133         
134        /*
135         * Setup the Transmit Buffer Descriptor
136         */
137        smcTxBd->status = M360_BD_WRAP;
138         
139        /*
140         * Set up SMC1 general and protocol-specific mode registers
141         */
142        m360.smc1.smce = ~0;    /* Clear any pending events */
143        m360.smc1.smcm = 0;     /* Mask all interrupt/event sources */
144        m360.smc1.smcmr = M360_SMCMR_CLEN(9) | M360_SMCMR_SM_UART;
145
146        /*
147         * Send "Init parameters" command
148         */
149        M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SMC1);
150
151        /*
152         * Enable receiver and transmitter
153         */
154        m360.smc1.smcmr |= M360_SMCMR_TEN | M360_SMCMR_REN;
155
156        if (m360_smc1_interrupt) {
157        rtems_isr_entry old_handler;
158        rtems_status_code sc;
159
160        sc = rtems_interrupt_catch (smc1InterruptHandler,
161                                                (m360.cicr & 0xE0) | 0x04,
162                                                &old_handler);
163        m360.smc1.smcm = 3;     /* Enable SMC1 TX and RX interrupts */
164        m360.cimr |= 1UL << 4;  /* Enable SMC1 interrupts */
165        }
166}
167
168static int
169smc1Read (int minor)
170{
171        unsigned char c;
172
173        if (smcRxBd->status & M360_BD_EMPTY)
174                return -1;
175        c = rxBuf[0];
176        smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP;
177        return c;
178}
179
180/*
181 * Device-dependent write routine
182 * Interrupt-driven devices:
183 *      Begin transmission of as many characters as possible (minimum is 1).
184 * Polling devices:
185 *      Transmit all characters.
186 */
187static int
188smc1InterruptWrite (int minor, const char *buf, int len)
189{
190        smcTxBd->buffer = (char *)buf;
191        smcTxBd->length = len;
192        smcTxBd->status = M360_BD_READY | M360_BD_WRAP | M360_BD_INTERRUPT;
193        return 0;
194}
195
196static int
197smc1PollWrite (int minor, const char *buf, int len)
198{
199        while (len--) {
200                static char txBuf;
201                while (smcTxBd->status & M360_BD_READY)
202                        continue;
203                txBuf = *buf++;
204                smcTxBd->buffer = &txBuf;
205                smcTxBd->length = 1;
206                smcTxBd->status = M360_BD_READY | M360_BD_WRAP;
207        }
208        return 0;
209}
210
211/*
212 ***************
213 * BOILERPLATE *
214 ***************
215 */
216
217/*
218 * Reserve resources consumed by this driver
219 */
220void console_reserve_resources(
221  rtems_configuration_table *configuration
222)
223{
224        rtems_termios_reserve_resources (configuration, 1);
225}
226
227/*
228 * Initialize and register the device
229 */
230rtems_device_driver console_initialize(
231  rtems_device_major_number  major,
232  rtems_device_minor_number  minor,
233  void                      *arg
234)
235{
236        rtems_status_code status;
237
238        /*
239         * Set up TERMIOS
240         */
241        rtems_termios_initialize ();
242
243        /*
244         * Do device-specific initialization
245         */
246        smc1Initialize ();
247
248        /*
249         * Register the device
250         */
251        status = rtems_io_register_name ("/dev/console", major, 0);
252        if (status != RTEMS_SUCCESSFUL)
253                rtems_fatal_error_occurred (status);
254        return RTEMS_SUCCESSFUL;
255}
256
257/*
258 * Open the device
259 */
260rtems_device_driver console_open(
261  rtems_device_major_number major,
262  rtems_device_minor_number minor,
263  void                    * arg
264)
265{
266        rtems_status_code sc;
267
268        if (m360_smc1_interrupt) {
269                rtems_libio_open_close_args_t *args = arg;
270
271                sc = rtems_termios_open (major, minor, arg,
272                                        NULL,
273                                        NULL,
274                                        NULL,
275                                        smc1InterruptWrite,
276                                        1);
277                smc1ttyp = args->iop->data1;
278        }
279        else {
280                sc = rtems_termios_open (major, minor, arg,
281                                        NULL,
282                                        NULL,
283                                        smc1Read,
284                                        smc1PollWrite,
285                                        0);
286        }
287        return sc;
288}
289 
290/*
291 * Close the device
292 */
293rtems_device_driver console_close(
294  rtems_device_major_number major,
295  rtems_device_minor_number minor,
296  void                    * arg
297)
298{
299        return rtems_termios_close (arg);
300}
301
302/*
303 * Read from the device
304 */
305rtems_device_driver console_read(
306  rtems_device_major_number major,
307  rtems_device_minor_number minor,
308  void                    * arg
309)
310{
311        return rtems_termios_read (arg);
312}
313
314/*
315 * Write to the device
316 */
317rtems_device_driver console_write(
318  rtems_device_major_number major,
319  rtems_device_minor_number minor,
320  void                    * arg
321)
322{
323        return rtems_termios_write (arg);
324}
325
326/*
327 * Handle ioctl request.
328 * Should set hardware line speed, bits/char, etc.
329 */
330rtems_device_driver console_control(
331  rtems_device_major_number major,
332  rtems_device_minor_number minor,
333  void                    * arg
334)
335{ 
336        return rtems_termios_ioctl (arg);
337}
Note: See TracBrowser for help on using the repository browser.