source: rtems/c/src/lib/libbsp/powerpc/eth_comm/canbus/canbus.c @ ee733965

4.104.114.84.95
Last change on this file since ee733965 was ee733965, checked in by Joel Sherrill <joel.sherrill@…>, on 02/17/99 at 20:24:53

Jay Monkman <jmonkman@…> submitted the eth_comm BSP for a PPC860
based board.

  • Property mode set to 100644
File size: 16.2 KB
Line 
1/*
2 * RTEMS CANBUS driver for eth-comm BSP
3 *
4 * Written by Jay Monkman (jmonkman@frasca.com)
5 *
6 *  COPYRIGHT (c) 1998
7 *  Frasca International, Inc.
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.OARcorp.com/rtems/license.html.
12 *
13 *  Note: All of this code assumes a 10Mhz clock input to the 82527
14 *
15 *  $Id:
16 */
17#include <stdio.h>
18#include <bsp.h>
19#include <mpc860.h>
20#include <rtems/error.h>
21#include <canbus.h>
22/* How many CAN interfaces are there? */
23#define NUM_CAN_DEVS 3
24
25/* How many received messages should be buffered for each channel */
26#define RX_CAN_BUF_SIZE 16
27
28int rxMsgBufHead[NUM_CAN_DEVS];
29int rxMsgBufTail[NUM_CAN_DEVS];
30i82527_msg_t rxMsgBuf[NUM_CAN_DEVS][RX_CAN_BUF_SIZE];
31
32volatile i82527_t *candev[NUM_CAN_DEVS];
33
34
35static rtems_isr
36canInterruptHandler (rtems_vector_number v)
37{
38  int dev;
39  int tmpTail;
40
41  switch (v) {
42  case PPC_IRQ_IRQ3: dev = 0; break;
43  case PPC_IRQ_IRQ4: dev = 1; break;
44  case PPC_IRQ_IRQ2: dev = 2; break;
45  default:           return;    /* something screwed up */
46  }
47
48  /* we only do rx interrupts right now */
49  if (!(candev[dev]->msg15.ctrl1 & I82527_MSG_CTRL_NEWDAT)) {
50    /* Hmmm, that's odd. Why were we triggered? */
51    candev[dev]->msg15.ctrl0 = 0xff & (I82527_MSG_CTRL_INTPND_CLR |
52                                       I82527_MSG_CTRL_MSGVAL_SET);
53    candev[dev]->msg15.ctrl1 = 0xff & (I82527_MSG_CTRL_RMTPND_CLR |
54                                       I82527_MSG_CTRL_MSGLST_CLR |
55                                       I82527_MSG_CTRL_NEWDAT_CLR);
56    return;
57  }
58  tmpTail = rxMsgBufTail[dev];
59  while (1) {
60    if ((tmpTail == rxMsgBufHead[dev]) &&
61        (rxMsgBuf[dev][tmpTail].ctrl1 & I82527_MSG_CTRL_NEWDAT)) {
62      break;  /* Buf is full */
63    }
64
65    if (!(rxMsgBuf[dev][tmpTail].ctrl1 & I82527_MSG_CTRL_NEWDAT)) {
66      int pkt_len;
67      int i;
68
69      rxMsgBuf[dev][tmpTail].ctrl0 = candev[dev]->msg15.ctrl0;
70      rxMsgBuf[dev][tmpTail].ctrl1 = candev[dev]->msg15.ctrl1;
71      rxMsgBuf[dev][tmpTail].arb = candev[dev]->msg15.arb;
72      rxMsgBuf[dev][tmpTail].cfg = candev[dev]->msg15.cfg;
73     
74      pkt_len = (rxMsgBuf[dev][tmpTail].cfg >> 4) & 0xf;
75      for (i=0; i<pkt_len; i++) {
76        rxMsgBuf[dev][tmpTail].data[i] = candev[dev]->msg15.data[i];
77      }
78
79      tmpTail++;
80      if (tmpTail == RX_CAN_BUF_SIZE) {
81        tmpTail = 0;
82      }
83
84      rxMsgBufTail[dev] = tmpTail;
85
86      break;
87    }
88
89    tmpTail++;
90    if (tmpTail == RX_CAN_BUF_SIZE) {
91      tmpTail = 0;
92    }
93    if (tmpTail == rxMsgBufTail[dev]) {
94      break;
95    }
96  }
97
98
99  candev[dev]->msg15.ctrl0  = 0xff & (I82527_MSG_CTRL_MSGVAL_SET |
100                                      I82527_MSG_CTRL_INTPND_CLR);
101  candev[dev]->msg15.ctrl1  = 0xff & (I82527_MSG_CTRL_NEWDAT_CLR |
102                                      I82527_MSG_CTRL_RMTPND_CLR);
103  candev[dev]->status = 0x0;
104}
105
106rtems_device_driver canbus_initialize(
107  rtems_device_major_number  major,
108  rtems_device_minor_number  minor,
109  void                      *arg
110)
111{
112  int i,j;
113  char dev_str[16]; /* This allows us to have a device name up to */
114                    /* 15 chars long. If we only use names like   */
115                    /* /dev/can0 (9 chars) we will be fine up to  */
116                    /* /dev/can9999999 */
117  rtems_status_code status;
118  rtems_isr_entry old_handler;
119 
120#if (NUM_CAN_DEVS > 0)
121  candev[0]=&canbus0;
122  rtems_interrupt_catch (canInterruptHandler,
123                         PPC_IRQ_IRQ3,
124                         &old_handler);
125
126#if (NUM_CAN_DEVS > 1)
127  candev[1]=&canbus1;
128  rtems_interrupt_catch (canInterruptHandler,
129                         PPC_IRQ_IRQ4,
130                         &old_handler);
131
132#if (NUM_CAN_DEVS > 2)
133  candev[2]=&canbus2;
134  rtems_interrupt_catch (canInterruptHandler,
135                         PPC_IRQ_IRQ2,
136                         &old_handler);
137 
138  /* Right now, we only support 3 CAN interfaces */
139#else
140#error NUM_CAN_DEVS is too big. Fix it, damnit!
141#endif /* NUM_CAN_DEVS > 2 */
142#endif /* NUM_CAN_DEVS > 1 */
143#else
144#error NUM_CAN_DEVS is 0. It needs to be at least 1
145#endif /* NUM_CAN_DEVS > 0 */
146
147
148  for (i=0; i < NUM_CAN_DEVS; i++) {
149   
150    /* clear rx buffers */
151    rxMsgBufHead[i] = 0;
152    rxMsgBufTail[i] = 0;
153    for (j=0; j < RX_CAN_BUF_SIZE; j++) {
154      rxMsgBuf[i][j].ctrl0 = 0x55; /* all flags are cleared */
155      rxMsgBuf[i][j].ctrl1 = 0x55; /* all flags are cleared */
156    }
157
158    candev[i]->ctrl = I82527_CTRL_CCE | /* Enable cfg reg writes */
159                      I82527_CTRL_INIT; /* Disable external xfers */
160 
161    candev[i]->cir = I82527_CIR_DMC;    /* Divide memory clock by 2 */
162
163   
164    /* We want 250 kbps so assuming an input clock rate of 10 MHz:
165     *   DSC = 0  =>  SCLK = 10 MHz, tSCLK = 100ns
166     *   BRP = 1  =>  tq = 200ns
167     *   tSYNC_SEG = 1 tq
168     *   tSEG1 = TSEG1+1 = 14+1 = 15
169     *   tSEG2 = TSEG2+1 = 3+1  = 4
170     *
171     *  bittime = tSYNC_SEG + tSEG1 + tSEG2
172     *          = 1 + 15 + 4 = 20
173     *  baudrate = 1/(bittime * tq) = 1/(20 * 200ns) = 1/(4000ns) = 250 kbps
174     */
175    candev[i]->btr0 = 0xc1;  /* Baud rate prescaler=0, Sync jump width=3 */
176
177    candev[i]->btr1 = I82527_BTR1_SPL | /* go for noise immunity */
178                      (0x3 << 4) |      /* TSEG2 = 3 */
179                      (0xe);            /* TSEG1 = 14 */
180
181    candev[i]->gms = 0xffff;            /* addresses must match exactly */
182    candev[i]->gml = 0xffffffff;        /* addresses must match exactly */
183   
184    candev[i]->mlm = 0x0;               /* all addresses accepted */
185
186    candev[i]->p2conf = 0xff;           /* make all outputs */
187
188    candev[i]->msg1.cfg    = I82527_MSG_CFG_DIR ;        /* dir is xmit */
189    candev[i]->msg1.ctrl0  = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
190                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
191                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
192                             I82527_MSG_CTRL_INTPND_CLR;
193
194    candev[i]->msg2.cfg    = I82527_MSG_CFG_DIR ;        /* dir is xmit */
195    candev[i]->msg2.ctrl0  = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
196                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
197                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
198                             I82527_MSG_CTRL_INTPND_CLR;
199
200    candev[i]->msg3.cfg    = I82527_MSG_CFG_DIR ;        /* dir is xmit */
201    candev[i]->msg3.ctrl0  = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
202                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
203                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
204                             I82527_MSG_CTRL_INTPND_CLR;
205
206    candev[i]->msg4.cfg    = I82527_MSG_CFG_DIR ;        /* dir is xmit */
207    candev[i]->msg4.ctrl0  = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
208                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
209                             I82527_MSG_CTRL_RXIE_CLR  | /* no rx interrupts */
210                             I82527_MSG_CTRL_INTPND_CLR;
211
212    candev[i]->msg5.cfg    = I82527_MSG_CFG_DIR ;        /* dir is xmit */
213    candev[i]->msg5.ctrl0  = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
214                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
215                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
216                             I82527_MSG_CTRL_INTPND_CLR;
217
218    candev[i]->msg6.cfg    = I82527_MSG_CFG_DIR ;        /* dir is xmit */
219    candev[i]->msg6.ctrl0  = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
220                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
221                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
222                             I82527_MSG_CTRL_INTPND_CLR;
223
224    candev[i]->msg7.cfg    = I82527_MSG_CFG_DIR ;        /* dir is xmit */
225    candev[i]->msg7.ctrl0  = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
226                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
227                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
228                             I82527_MSG_CTRL_INTPND_CLR;
229
230    candev[i]->msg8.cfg    = I82527_MSG_CFG_DIR ;        /* dir is xmit */
231    candev[i]->msg8.ctrl0  = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
232                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
233                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
234                             I82527_MSG_CTRL_INTPND_CLR;
235
236    candev[i]->msg9.cfg    = I82527_MSG_CFG_DIR ;        /* dir is xmit */
237    candev[i]->msg9.ctrl0  = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
238                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
239                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
240                             I82527_MSG_CTRL_INTPND_CLR;
241
242    candev[i]->msg10.cfg   = I82527_MSG_CFG_DIR ;        /* dir is xmit */
243    candev[i]->msg10.ctrl0 = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
244                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
245                             I82527_MSG_CTRL_RXIE_CLR  | /* no rx interrupts */
246                             I82527_MSG_CTRL_INTPND_CLR;
247
248    candev[i]->msg11.cfg   = I82527_MSG_CFG_DIR ;        /* dir is xmit */
249    candev[i]->msg11.ctrl0 = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
250                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
251                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
252                             I82527_MSG_CTRL_INTPND_CLR;
253
254    candev[i]->msg12.cfg   = I82527_MSG_CFG_DIR ;        /* dir is xmit */
255    candev[i]->msg12.ctrl0 = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
256                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
257                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
258                             I82527_MSG_CTRL_INTPND_CLR;
259
260    candev[i]->msg13.cfg   = I82527_MSG_CFG_DIR ;        /* dir is xmit */
261    candev[i]->msg13.ctrl0 = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
262                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
263                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
264                             I82527_MSG_CTRL_INTPND_CLR;
265
266    candev[i]->msg14.cfg   = I82527_MSG_CFG_DIR ;        /* dir is xmit */
267    candev[i]->msg14.ctrl0 = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
268                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
269                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
270                             I82527_MSG_CTRL_INTPND_CLR;
271
272    candev[i]->msg15.cfg   = 0 ;        /* dir is rcv */
273    candev[i]->msg15.ctrl0 = I82527_MSG_CTRL_MSGVAL_CLR |/* this msg invalid */
274                             I82527_MSG_CTRL_TXIE_CLR   |/* no tx interrupts */
275                             I82527_MSG_CTRL_RXIE_CLR   |/* no rx interrupts */
276                             I82527_MSG_CTRL_INTPND_CLR;
277    candev[i]->msg15.ctrl1 = I82527_MSG_CTRL_RMTPND_CLR |
278                             I82527_MSG_CTRL_TXRQ_CLR   |
279                             I82527_MSG_CTRL_MSGLST_CLR |
280                             I82527_MSG_CTRL_NEWDAT_CLR;
281
282  }
283
284  if ((status=rtems_io_register_name ("/dev/can0", major, 0)) !=
285      RTEMS_SUCCESSFUL) {
286    rtems_fatal_error_occurred (status);
287  }
288  if ((status=rtems_io_register_name ("/dev/can1", major, 1)) !=
289      RTEMS_SUCCESSFUL) {
290    rtems_fatal_error_occurred (status);
291  }
292  if ((status=rtems_io_register_name ("/dev/can2", major, 2)) !=
293      RTEMS_SUCCESSFUL) {
294    rtems_fatal_error_occurred (status);
295  }
296  return RTEMS_SUCCESSFUL;
297}
298
299rtems_device_driver canbus_open(
300  rtems_device_major_number major,
301  rtems_device_minor_number minor,
302  void                    * arg
303)
304{
305    /* msg is in use, rx interrupts are enabled */
306  candev[minor]->msg15.ctrl0 = 0xff & (I82527_MSG_CTRL_MSGVAL_SET |
307                                       I82527_MSG_CTRL_RXIE_SET);
308   
309  candev[minor]->ctrl |= I82527_CTRL_IE;
310  candev[minor]->ctrl &= ~(I82527_CTRL_CCE | I82527_CTRL_INIT);
311  switch (minor) {
312  case 0: m860.simask |= M860_SIMASK_IRM3; break;
313  case 1: m860.simask |= M860_SIMASK_IRM4; break;
314  case 2: m860.simask |= M860_SIMASK_IRM2; break;
315  default: return;
316  }
317
318  return RTEMS_SUCCESSFUL;
319}
320
321rtems_device_driver canbus_close(
322  rtems_device_major_number major,
323  rtems_device_minor_number minor,
324  void                    * arg
325)
326{
327  /* msg is not in use, rx & txinterrupts are disbled */
328  candev[minor]->msg15.ctrl0 = 0xff & (I82527_MSG_CTRL_MSGVAL_CLR |
329                                       I82527_MSG_CTRL_RXIE_CLR |
330                                       I82527_MSG_CTRL_TXIE_CLR);
331   
332  /* Take transceiver off the bus, enable cfg. reg. writes */
333  candev[minor]->ctrl |= (I82527_CTRL_CCE | I82527_CTRL_INIT);
334   
335  return RTEMS_SUCCESSFUL;
336}
337
338
339rtems_device_driver canbus_read(
340  rtems_device_major_number major,
341  rtems_device_minor_number minor,
342  void                    * arg
343)
344{
345  i82527_msg_t *msg;
346  int i;
347  int tmpHead;
348
349  msg = arg;
350  tmpHead = rxMsgBufHead[minor];
351
352  while (1){
353    if ((tmpHead == rxMsgBufTail[minor]) &&
354        !(rxMsgBuf[minor][tmpHead].ctrl1 & I82527_MSG_CTRL_NEWDAT)) {
355      break;
356    }
357    if (rxMsgBuf[minor][tmpHead].ctrl1 & I82527_MSG_CTRL_NEWDAT) {
358      int pkt_len;
359      msg->ctrl0 = rxMsgBuf[minor][tmpHead].ctrl0;
360      msg->ctrl1 = rxMsgBuf[minor][tmpHead].ctrl1;
361      msg->arb = rxMsgBuf[minor][tmpHead].arb;
362      msg->cfg = rxMsgBuf[minor][tmpHead].cfg;
363     
364      pkt_len = (msg->cfg >> 4) & 0xf;
365      for (i=0; i<pkt_len; i++) {
366        msg->data[i] = rxMsgBuf[minor][tmpHead].data[i];
367      }
368      rxMsgBuf[minor][tmpHead].ctrl1 = 0xff & I82527_MSG_CTRL_NEWDAT_CLR;
369
370      tmpHead++;
371      if (tmpHead == RX_CAN_BUF_SIZE) {
372        tmpHead = 0;
373      }
374      rxMsgBufHead[minor] = tmpHead;
375
376      return RTEMS_SUCCESSFUL;
377
378    }
379
380    tmpHead++;
381    if (tmpHead == RX_CAN_BUF_SIZE) {
382      tmpHead = 0;
383    }
384    if (tmpHead == rxMsgBufHead[minor]) {
385      break;
386    }
387  }
388
389  return RTEMS_UNSATISFIED;
390
391}
392   
393rtems_device_driver canbus_write(
394  rtems_device_major_number major,
395  rtems_device_minor_number minor,
396  void                    * arg
397)
398{
399  i82527_msg_t *msg;
400  int i;
401
402  msg = arg;
403  while(candev[minor]->msg1.ctrl1 & I82527_MSG_CTRL_TXRQ){
404    continue;
405  }
406  candev[minor]->msg1.ctrl1  = 0xff & I82527_MSG_CTRL_CPUUPD_SET;
407
408  candev[minor]->msg1.cfg = msg->cfg;
409  candev[minor]->msg1.arb = msg->arb;
410
411  for (i=0; i < ((msg->cfg >> 4) & 0xff);  i++) {
412    candev[minor]->msg1.data[i] = msg->data[i];
413  }
414
415  candev[minor]->msg1.ctrl0  = 0xff & (I82527_MSG_CTRL_INTPND_CLR |
416                                       I82527_MSG_CTRL_MSGVAL_SET |
417                                       I82527_MSG_CTRL_TXIE_CLR);
418  candev[minor]->msg1.cfg    |= I82527_MSG_CFG_DIR;
419  candev[minor]->msg1.ctrl1  = 0xff & (I82527_MSG_CTRL_NEWDAT_SET |
420                                       I82527_MSG_CTRL_CPUUPD_CLR |
421                                       I82527_MSG_CTRL_TXRQ_SET);
422
423
424
425  return RTEMS_SUCCESSFUL;
426}
427rtems_device_driver canbus_control(
428  rtems_device_major_number major,
429  rtems_device_minor_number minor,
430  void                    * arg
431)
432{
433  return RTEMS_SUCCESSFUL;
434}
435
436
437/* part of old canbus_read */
438#if 0
439  for (i=0; i < RX_CAN_BUF_SIZE) {
440    if (rxMsgBuf[minor][i].ctrl1 & I82527_MSG_CTRL_NEWDAT)
441      break;
442  }
443
444  if (i < RX_CAN_BUF_SIZE) {
445    int pkt_len;
446    int j;
447    msg.arb = rxMsgBuf[minor][i].arb;
448    msg.cfg = rxMsgBuf[minor][i].cfg;
449   
450    pkt_len = (msg.cfg >> 4) & 0xf;
451
452    for (j=0; j < pkt_len; j++)
453      msg.data[j] = rxMsgBuf[minor][i].data[j];
454 
455 
456  /* wait until there is a msg */
457  while (!(candev->msg15.ctrl1 & I82527_MSG_CTRL_NEWDAT))
458     continue;
459 
460  msg->ctrl1 = candev->msg15.ctrl1;
461  msg->cfg = candev->msg15.cfg;
462  msg->arb = candev->msg15.arb;
463
464  for (i=0; i < ((candev->msg15.cfg >> 4) & 0xff);  i++) {
465    msg->data[i] = candev->msg15.data[i];
466  }
467
468  candev->msg15.ctrl0  = 0xff & (I82527_MSG_CTRL_MSGVAL_SET |
469                                 I82527_MSG_CTRL_INTPND_CLR);
470  candev->msg15.ctrl1  = 0xff & (I82527_MSG_CTRL_NEWDAT_CLR |
471                                 I82527_MSG_CTRL_RMTPND_CLR);
472
473  candev->status = 0x0;
474
475
476  return RTEMS_SUCCESSFUL;
477#endif
478
479
Note: See TracBrowser for help on using the repository browser.