OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [m68k/] [gen68360/] [console/] [console.c] - Blame information for rev 30

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
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: console.c,v 1.2 2001-09-27 12:00:08 chris Exp $
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
 */
35
int m360_clock_rate     = 25000000;
36
 
37
/*
38
 * Interrupt-driven input buffer
39
 * Declare console baud rate -- may also be overwritten
40
 */
41
int console_baud_rate = 9600;
42
 
43
/*
44
 */
45
#define RXBUFSIZE       16
46
 
47
/*
48
 * Interrupt-driven callback
49
 */
50
static int m360_smc1_interrupt = 1;
51
static void *smc1ttyp;
52
 
53
/*
54
 * I/O buffers and pointers to buffer descriptors
55
 */
56
static volatile char rxBuf[RXBUFSIZE];
57
static volatile m360BufferDescriptor_t *smcRxBd, *smcTxBd;
58
 
59
/*
60
 * Device-specific routines
61
 */
62
 
63
/*
64
 * Compute baud-rate-generator configuration register value
65
 */
66
static int
67
smc1BRGC (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
 */
83
static int
84
smc1SetAttributes (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
 */
118
static rtems_isr
119
smc1InterruptHandler (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
 
145
static int
146
smc1Initialize (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
 
235
static int
236
smc1PollRead (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
 */
254
static int
255
smc1InterruptWrite (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
 
263
static int
264
smc1PollWrite (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
 */
293
rtems_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
 */
318
rtems_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
 
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
 */
364
rtems_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
 */
376
rtems_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
 */
388
rtems_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
 */
400
rtems_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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.