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

4.104.114.84.95
Last change on this file since f52111f was 69405459, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 5, 2000 at 6:40:14 PM

Patch from Eric Norum <eric@…> as follows:

At the request of kjoutwater@… I'm submitting the
following patch.

c/src/lib/libbsp/m68k/gen68360/console/console.c

Allow console baud rate to be set by debugger/downloader.

c/src/lib/libbsp/m68k/gen68360/startup/init68360.c

Add support for generic 68360 with static RAM.

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