File indexing completed on 2025-05-11 08:23:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <stdio.h>
0035 #include <stdlib.h>
0036 #include <rtems.h>
0037 #include <rtems/error.h>
0038 #include <rtems/libio.h>
0039 #include <string.h>
0040
0041 #include <bsp.h>
0042 #include <bsp/fatal.h>
0043 #include <bsp/irq.h>
0044 #include "../mscan/mscan_int.h"
0045
0046
0047
0048 struct mpc5200_rx_cntrl mpc5200_mscan_rx_cntrl[MPC5200_CAN_NO];
0049 static struct mscan_channel_info chan_info[MPC5200_CAN_NO];
0050
0051
0052
0053
0054 static struct can_message *get_tx_buffer(struct mscan_channel_info *chan)
0055 {
0056
0057 struct can_message *tmp_mess_ptr = NULL,
0058 *temp_head_ptr;
0059
0060
0061 temp_head_ptr = chan->tx_ring_buf.head_ptr;
0062
0063
0064 if (temp_head_ptr != chan->tx_ring_buf.tail_ptr) {
0065
0066
0067 tmp_mess_ptr = temp_head_ptr;
0068
0069
0070 temp_head_ptr++;
0071
0072
0073 if (temp_head_ptr > chan->tx_ring_buf.buf_ptr + NO_OF_MSCAN_TX_BUFF) {
0074
0075
0076 temp_head_ptr = chan->tx_ring_buf.buf_ptr;
0077
0078 }
0079
0080
0081 chan->tx_ring_buf.head_ptr = temp_head_ptr;
0082 }
0083
0084
0085 return tmp_mess_ptr;
0086 }
0087
0088
0089
0090
0091 static struct can_message *fill_tx_buffer(struct mscan_channel_info *chan,
0092 struct can_message *mess_ptr)
0093 {
0094
0095 struct can_message *tmp_mess_ptr = chan->tx_ring_buf.tail_ptr + 1;
0096
0097
0098 if (tmp_mess_ptr > chan->tx_ring_buf.buf_ptr + NO_OF_MSCAN_TX_BUFF) {
0099
0100 tmp_mess_ptr = chan->tx_ring_buf.buf_ptr;
0101 }
0102
0103
0104 if (tmp_mess_ptr == chan->tx_ring_buf.head_ptr) {
0105
0106 return NULL;
0107 } else {
0108
0109 memcpy((void *) chan->tx_ring_buf.tail_ptr, (void *) mess_ptr,
0110 sizeof (struct can_message));
0111
0112
0113 chan->tx_ring_buf.tail_ptr = tmp_mess_ptr;
0114 }
0115
0116
0117 return chan->tx_ring_buf.tail_ptr;
0118 }
0119
0120
0121
0122
0123 static void mpc5200_mscan_interrupt_handler(rtems_irq_hdl_param handle)
0124 {
0125 rtems_status_code status;
0126 mscan_handle *mscan_hdl = (mscan_handle *) handle;
0127 struct mscan_channel_info *chan = &chan_info[mscan_hdl->mscan_channel];
0128 struct can_message rx_mess,
0129 *rx_mess_ptr,
0130 *tx_mess_ptr;
0131 mscan *m = chan->regs;
0132 register uint8_t idx;
0133
0134
0135
0136
0137
0138
0139 for (idx = TFLG_TXE0; idx <= TFLG_TXE2; idx = idx << 1) {
0140
0141
0142 if ((m->tflg) & idx) {
0143
0144
0145 tx_mess_ptr = get_tx_buffer(chan);
0146
0147
0148 if (tx_mess_ptr != NULL) {
0149
0150
0151 m->bsel = idx;
0152
0153
0154 if ((mscan_hdl->toucan_callback) == NULL) {
0155
0156
0157 m->txidr0 = SET_IDR0(tx_mess_ptr->mess_id);
0158 m->txidr1 = SET_IDR1(tx_mess_ptr->mess_id);
0159 m->txidr2 = 0;
0160 m->txidr3 = 0;
0161
0162 }
0163
0164
0165 if (((mscan_hdl->toucan_callback) == NULL)
0166 || (((mscan_hdl->toucan_callback) != NULL)
0167 && ((tx_mess_ptr->toucan_tx_idx) == idx))) {
0168
0169
0170 m->txdlr = (uint8_t) ((tx_mess_ptr->mess_len) & 0x000F);
0171
0172
0173 if (!(MSCAN_MESS_ID_HAS_RTR(tx_mess_ptr->mess_id))) {
0174
0175 switch (m->txdlr) {
0176 case 8:
0177 m->txdsr7 = tx_mess_ptr->mess_data[7];
0178 case 7:
0179 m->txdsr6 = tx_mess_ptr->mess_data[6];
0180 case 6:
0181 m->txdsr5 = tx_mess_ptr->mess_data[5];
0182 case 5:
0183 m->txdsr4 = tx_mess_ptr->mess_data[4];
0184 case 4:
0185 m->txdsr3 = tx_mess_ptr->mess_data[3];
0186 case 3:
0187 m->txdsr2 = tx_mess_ptr->mess_data[2];
0188 case 2:
0189 m->txdsr1 = tx_mess_ptr->mess_data[1];
0190 case 1:
0191 m->txdsr0 = tx_mess_ptr->mess_data[0];
0192 break;
0193 default:
0194 break;
0195 }
0196 }
0197
0198
0199 m->tier |= m->bsel;
0200
0201
0202 m->tflg = m->bsel;
0203
0204
0205 rtems_semaphore_release((rtems_id) (chan->tx_rb_sid));
0206
0207 } else {
0208
0209
0210 fill_tx_buffer(chan, tx_mess_ptr);
0211
0212 }
0213 } else {
0214
0215 m->tier &= ~(idx);
0216 }
0217 }
0218 }
0219
0220
0221
0222
0223
0224
0225 if (m->rier & RIER_RXFIE) {
0226
0227
0228 while (m->rflg & RFLG_RXF) {
0229
0230 if (mscan_hdl->toucan_callback == NULL) {
0231
0232
0233 rx_mess_ptr = &rx_mess;
0234
0235 } else {
0236
0237
0238
0239 idx = (m->idac) & 0x7;
0240 switch (idx) {
0241
0242 case 0:
0243 case 1:
0244 case 2:
0245 case 3:
0246 rx_mess_ptr =
0247 (struct can_message *)
0248 &(mpc5200_mscan_rx_cntrl[mscan_hdl->mscan_channel].
0249 can_rx_message[idx]);
0250 break;
0251
0252
0253 default:
0254
0255 m->rflg |= RFLG_RXF;
0256
0257 return;
0258 break;
0259 }
0260
0261 }
0262
0263
0264 rx_mess_ptr->mess_id = GET_IDR0(m->rxidr0) | GET_IDR1(m->rxidr1);
0265
0266
0267 rx_mess_ptr->mess_len = ((m->rxdlr) & 0x0F);
0268
0269
0270 rx_mess_ptr->mess_time_stamp = ((m->rxtimh << 8) | (m->rxtiml));
0271
0272
0273 if (!(MSCAN_MESS_ID_HAS_RTR(rx_mess_ptr->mess_id)))
0274 {
0275
0276
0277 switch (rx_mess_ptr->mess_len) {
0278 case 8:
0279 rx_mess_ptr->mess_data[7] = m->rxdsr7;
0280 case 7:
0281 rx_mess_ptr->mess_data[6] = m->rxdsr6;
0282 case 6:
0283 rx_mess_ptr->mess_data[5] = m->rxdsr5;
0284 case 5:
0285 rx_mess_ptr->mess_data[4] = m->rxdsr4;
0286 case 4:
0287 rx_mess_ptr->mess_data[3] = m->rxdsr3;
0288 case 3:
0289 rx_mess_ptr->mess_data[2] = m->rxdsr2;
0290 case 2:
0291 rx_mess_ptr->mess_data[1] = m->rxdsr1;
0292 case 1:
0293 rx_mess_ptr->mess_data[0] = m->rxdsr0;
0294 case 0:
0295 default:
0296 break;
0297 }
0298 }
0299
0300 if (mscan_hdl->toucan_callback == NULL) {
0301
0302 if ((status =
0303 rtems_message_queue_send(chan->rx_qid, (void *) rx_mess_ptr,
0304 sizeof (struct can_message))) !=
0305 RTEMS_SUCCESSFUL) {
0306
0307 chan->int_rx_err++;
0308
0309 }
0310
0311 } else {
0312
0313 mscan_hdl->toucan_callback((int16_t) (((m->idac) & 0x7) + 3));
0314
0315 }
0316
0317
0318 m->rflg |= RFLG_RXF;
0319
0320 }
0321
0322 }
0323
0324
0325 if (m->rflg & RFLG_CSCIF) {
0326
0327 m->rflg |= RFLG_CSCIF;
0328
0329 if (mscan_hdl->toucan_callback != NULL) {
0330
0331 mscan_hdl->toucan_callback((int16_t) (-1));
0332
0333 }
0334
0335 }
0336
0337 }
0338
0339
0340
0341
0342
0343
0344
0345
0346 static void mscan_interrupts_enable(mscan *m)
0347 {
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360 m->rier |= (RIER_CSCIE | RIER_RXFIE | RIER_RSTAT(1) | RIER_TSTAT(1));
0361
0362 return;
0363
0364 }
0365
0366
0367
0368
0369 static void mpc5200_mscan_a_on(const rtems_irq_connect_data * ptr)
0370 {
0371 mscan *m = (&chan_info[MSCAN_A])->regs;
0372
0373 mscan_interrupts_enable(m);
0374
0375 return;
0376
0377 }
0378
0379
0380
0381
0382 static void mpc5200_mscan_a_off(const rtems_irq_connect_data * ptr)
0383 {
0384 mscan *m = (&chan_info[MSCAN_A])->regs;
0385
0386 mscan_interrupts_disable(m);
0387
0388 return;
0389
0390 }
0391
0392
0393
0394
0395 static int mpc5200_mscan_a_isOn(const rtems_irq_connect_data * ptr)
0396 {
0397 mscan *m = (&chan_info[MSCAN_A])->regs;
0398
0399 if ((m->rier & RIER_CSCIE) && (m->rier & RIER_RXFIE))
0400 return RTEMS_SUCCESSFUL;
0401 else
0402 return RTEMS_UNSATISFIED;
0403
0404 return RTEMS_SUCCESSFUL;
0405
0406 }
0407
0408
0409
0410
0411 static void mpc5200_mscan_b_on(const rtems_irq_connect_data * ptr)
0412 {
0413 mscan *m = (&chan_info[MSCAN_B])->regs;
0414
0415 mscan_interrupts_enable(m);
0416
0417 return;
0418
0419 }
0420
0421
0422
0423
0424 static void mpc5200_mscan_b_off(const rtems_irq_connect_data * ptr)
0425 {
0426 mscan *m = (&chan_info[MSCAN_B])->regs;
0427
0428 mscan_interrupts_disable(m);
0429
0430 return;
0431
0432 }
0433
0434
0435
0436
0437 static int mpc5200_mscan_b_isOn(const rtems_irq_connect_data * ptr)
0438 {
0439 mscan *m = (&chan_info[MSCAN_B])->regs;
0440
0441 if ((m->rier & RIER_CSCIE) && (m->rier & RIER_RXFIE))
0442 return RTEMS_SUCCESSFUL;
0443 else
0444 return RTEMS_UNSATISFIED;
0445
0446 return RTEMS_SUCCESSFUL;
0447
0448 }
0449
0450 static mscan_handle mscan_a_handle = {
0451 MSCAN_A,
0452 NULL
0453 };
0454
0455 static mscan_handle mscan_b_handle = {
0456 MSCAN_B,
0457 NULL
0458 };
0459
0460
0461
0462
0463 static rtems_irq_connect_data mpc5200_mscan_irq_data[MPC5200_CAN_NO] = {
0464 {
0465 BSP_SIU_IRQ_MSCAN1,
0466 (rtems_irq_hdl) mpc5200_mscan_interrupt_handler,
0467 (rtems_irq_hdl_param) & mscan_a_handle,
0468 (rtems_irq_enable) mpc5200_mscan_a_on,
0469 (rtems_irq_disable) mpc5200_mscan_a_off,
0470 (rtems_irq_is_enabled) mpc5200_mscan_a_isOn
0471 }, {
0472 BSP_SIU_IRQ_MSCAN2,
0473 (rtems_irq_hdl) mpc5200_mscan_interrupt_handler,
0474 (rtems_irq_hdl_param) & mscan_b_handle,
0475 (rtems_irq_enable) mpc5200_mscan_b_on,
0476 (rtems_irq_disable) mpc5200_mscan_b_off,
0477 (rtems_irq_is_enabled) mpc5200_mscan_b_isOn
0478 }
0479 };
0480
0481
0482
0483
0484 void mpc5200_mscan_wait_sync(mscan *m)
0485 {
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498 #if 0
0499 while (!((m->ctl0) & CTL0_SYNCH));
0500 #endif
0501 return;
0502
0503 }
0504
0505
0506
0507
0508 static void mpc5200_mscan_perform_initialization_mode_settings(mscan *m)
0509 {
0510 mscan_context context;
0511
0512
0513 (void) mscan_set_bit_rate(m, MSCAN_BIT_RATE_DEFAULT);
0514
0515
0516 mscan_initialization_mode_enter( m, &context);
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528 #ifndef MSCAN_LOOPBACK
0529 m->ctl1 &= ~(CTL1_LISTEN | CTL1_LOOPB | CTL1_CLKSRC);
0530 #else
0531 m->ctl1 &= ~(CTL1_LISTEN | CTL1_CLKSRC);
0532 m->ctl1 |= (CTL1_LOOPB);
0533 #endif
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554 m->idac &= ~(IDAC_IDAM1);
0555 m->idac |= (IDAC_IDAM0);
0556
0557
0558 m->idmr0 = SET_IDMR0(0x7FF);
0559 m->idmr1 = SET_IDMR1(0x7FF);
0560 m->idmr2 = SET_IDMR2(0x7FF);
0561 m->idmr3 = SET_IDMR3(0x7FF);
0562 m->idmr4 = SET_IDMR4(0x7FF);
0563 m->idmr5 = SET_IDMR5(0x7FF);
0564 m->idmr6 = SET_IDMR6(0x7FF);
0565 m->idmr7 = SET_IDMR7(0x7FF);
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577 m->ctl1 |= (CTL1_CANE);
0578
0579
0580 mscan_initialization_mode_leave( m, &context);
0581
0582 return;
0583
0584 }
0585
0586
0587
0588
0589 void mpc5200_mscan_perform_normal_mode_settings(mscan
0590 *m)
0591 {
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603 m->ctl0 &= ~(CTL0_CSWAI);
0604 m->ctl0 |= (CTL0_TIME);
0605
0606 return;
0607
0608 }
0609
0610 rtems_status_code mpc5200_mscan_set_mode(rtems_device_minor_number minor,
0611 uint8_t mode)
0612 {
0613 struct mscan_channel_info *chan = NULL;
0614 mscan *m = NULL;
0615
0616 switch (minor) {
0617
0618 case MSCAN_A:
0619 case MSCAN_B:
0620 chan = &chan_info[minor];
0621 m = chan->regs;
0622 break;
0623
0624 default:
0625 return RTEMS_UNSATISFIED;
0626 break;
0627 }
0628
0629 if (chan->mode == mode)
0630 return RTEMS_SUCCESSFUL;
0631
0632 switch (mode) {
0633
0634 case MSCAN_INIT_NORMAL_MODE:
0635
0636 mpc5200_mscan_perform_initialization_mode_settings(m);
0637 break;
0638
0639 case MSCAN_NORMAL_MODE:
0640 if ((chan->mode) == MSCAN_INITIALIZED_MODE) {
0641
0642 mpc5200_mscan_perform_initialization_mode_settings(m);
0643 }
0644
0645 if ((chan->mode) == MSCAN_SLEEP_MODE) {
0646
0647
0648 mscan_sleep_mode_leave(m);
0649 }
0650
0651 mscan_interrupts_enable(m);
0652
0653 mpc5200_mscan_wait_sync(m);
0654 break;
0655
0656 case MSCAN_SLEEP_MODE:
0657
0658 mscan_interrupts_disable(m);
0659
0660 mscan_sleep_mode_enter(m);
0661 break;
0662
0663 default:
0664 return RTEMS_UNSATISFIED;
0665 break;
0666
0667 }
0668
0669
0670 chan->mode = mode;
0671
0672 return RTEMS_SUCCESSFUL;
0673
0674 }
0675
0676
0677
0678
0679 rtems_status_code mscan_channel_initialize(rtems_device_major_number major,
0680 rtems_device_minor_number minor)
0681 {
0682 rtems_status_code status;
0683 struct mscan_channel_info *chan = &chan_info[minor];
0684
0685
0686 switch (minor) {
0687
0688 case MSCAN_A:
0689 chan->rx_qname = rtems_build_name('C', 'N', 'A', 'Q');
0690 chan->tx_rb_sname = rtems_build_name('C', 'N', 'A', 'S');
0691
0692
0693 if ((status =
0694 rtems_io_register_name(MSCAN_A_DEV_NAME, major,
0695 MSCAN_A)) != RTEMS_SUCCESSFUL)
0696 return status;
0697
0698
0699 if ((status =
0700 rtems_io_register_name(MSCAN_0_DEV_NAME, major,
0701 MSCAN_A)) != RTEMS_SUCCESSFUL)
0702 return status;
0703
0704
0705 if (((chan->tx_ring_buf.buf_ptr) =
0706 malloc(sizeof (struct can_message) * (NO_OF_MSCAN_TX_BUFF + 1))) !=
0707 NULL) {
0708 chan->tx_ring_buf.head_ptr = chan->tx_ring_buf.tail_ptr =
0709 chan->tx_ring_buf.buf_ptr;
0710 } else {
0711 return RTEMS_UNSATISFIED;
0712 }
0713 break;
0714
0715 case MSCAN_B:
0716 chan->rx_qname = rtems_build_name('C', 'N', 'B', 'Q');
0717 chan->tx_rb_sname = rtems_build_name('C', 'N', 'B', 'S');
0718
0719
0720 if ((status =
0721 rtems_io_register_name(MSCAN_B_DEV_NAME, major,
0722 MSCAN_B)) != RTEMS_SUCCESSFUL)
0723 return status;
0724
0725
0726 if ((status =
0727 rtems_io_register_name(MSCAN_1_DEV_NAME, major,
0728 MSCAN_B)) != RTEMS_SUCCESSFUL)
0729 return status;
0730
0731
0732 if (((chan->tx_ring_buf.buf_ptr) =
0733 malloc(sizeof (struct can_message) * (NO_OF_MSCAN_TX_BUFF + 1))) !=
0734 NULL) {
0735 chan->tx_ring_buf.head_ptr = chan->tx_ring_buf.tail_ptr =
0736 chan->tx_ring_buf.buf_ptr;
0737 } else {
0738 return RTEMS_UNSATISFIED;
0739 }
0740 break;
0741
0742 default:
0743 return RTEMS_UNSATISFIED;
0744 break;
0745 }
0746
0747
0748 status =
0749 rtems_message_queue_create(chan->rx_qname, (uint32_t) NO_OF_MSCAN_RX_BUFF,
0750 (uint32_t)
0751 MSCAN_MESSAGE_SIZE(sizeof (struct can_message)),
0752 (rtems_attribute) RTEMS_LOCAL | RTEMS_FIFO,
0753 (rtems_id *) & (chan->rx_qid));
0754
0755
0756 status =
0757 rtems_semaphore_create(chan->tx_rb_sname, (uint32_t) (NO_OF_MSCAN_TX_BUFF),
0758 RTEMS_COUNTING_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY
0759 | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
0760 (rtems_task_priority) 0,
0761 (rtems_id *) & (chan->tx_rb_sid));
0762
0763
0764 if (!BSP_install_rtems_irq_handler(&(mpc5200_mscan_irq_data[minor])))
0765 rtems_panic("Can't attach MPC5x00 MSCAN interrupt handler %ld\n", minor);
0766
0767
0768 chan->regs = (mscan *) &(mpc5200.mscan[minor]);
0769 chan->int_rx_err = 0;
0770 chan->id_extended = FALSE;
0771 chan->mode = MSCAN_INITIALIZED_MODE;
0772 chan->tx_buf_no = NO_OF_MSCAN_TX_BUFF;
0773
0774 return status;
0775
0776 }
0777
0778
0779
0780
0781 rtems_device_driver mscan_initialize(rtems_device_major_number major,
0782 rtems_device_minor_number minor, void *arg)
0783 {
0784 rtems_status_code status;
0785
0786
0787 if ((status = mscan_channel_initialize(major, MSCAN_A)) != RTEMS_SUCCESSFUL)
0788 bsp_fatal(MPC5200_FATAL_MSCAN_A_INIT);
0789
0790 if ((status = mscan_channel_initialize(major, MSCAN_B)) != RTEMS_SUCCESSFUL)
0791 bsp_fatal(MPC5200_FATAL_MSCAN_B_INIT);
0792
0793 if ((status =
0794 mpc5200_mscan_set_mode(MSCAN_A,
0795 MSCAN_INIT_NORMAL_MODE)) != RTEMS_SUCCESSFUL)
0796 bsp_fatal(MPC5200_FATAL_MSCAN_A_SET_MODE);
0797
0798 if ((status =
0799 mpc5200_mscan_set_mode(MSCAN_B,
0800 MSCAN_INIT_NORMAL_MODE)) != RTEMS_SUCCESSFUL)
0801 bsp_fatal(MPC5200_FATAL_MSCAN_B_SET_MODE);
0802
0803 return status;
0804
0805 }
0806
0807
0808
0809
0810 rtems_device_driver mscan_open(rtems_device_major_number major,
0811 rtems_device_minor_number minor, void *arg)
0812 {
0813 rtems_status_code status = RTEMS_SUCCESSFUL;
0814 struct mscan_channel_info *chan = NULL;
0815
0816 switch (minor) {
0817
0818 case MSCAN_A:
0819 case MSCAN_B:
0820 chan = &chan_info[minor];
0821 break;
0822
0823 default:
0824 return RTEMS_UNSATISFIED;
0825 break;
0826 }
0827
0828
0829 if ((chan->mode) == MSCAN_SLEEP_MODE) {
0830
0831
0832 status = mpc5200_mscan_set_mode(minor, MSCAN_NORMAL_MODE);
0833 }
0834
0835 return status;
0836
0837 }
0838
0839
0840
0841
0842 rtems_device_driver mscan_close(rtems_device_major_number major,
0843 rtems_device_minor_number minor, void *arg)
0844 {
0845 rtems_status_code status;
0846
0847 switch (minor) {
0848
0849 case MSCAN_A:
0850 case MSCAN_B:
0851 break;
0852
0853 default:
0854 return RTEMS_UNSATISFIED;
0855 break;
0856 }
0857
0858
0859 status = mpc5200_mscan_set_mode(minor, MSCAN_SLEEP_MODE);
0860
0861 return status;
0862
0863 }
0864
0865
0866
0867
0868 rtems_device_driver mscan_read(rtems_device_major_number major,
0869 rtems_device_minor_number minor, void *arg)
0870 {
0871 rtems_status_code status;
0872 size_t message_size = 0;
0873 rtems_libio_rw_args_t *parms = (rtems_libio_rw_args_t *) arg;
0874 struct mscan_rx_parms *rx_parms = (struct mscan_rx_parms *) (parms->buffer);
0875 struct can_message *rx_mess = (struct can_message *) (rx_parms->rx_mess);
0876 struct mscan_channel_info *chan = NULL;
0877
0878 switch (minor) {
0879
0880 case MSCAN_A:
0881 case MSCAN_B:
0882 chan = &chan_info[minor];
0883 break;
0884
0885 default:
0886 return RTEMS_UNSATISFIED;
0887 break;
0888 }
0889
0890
0891 if ((chan->mode) == MSCAN_INIT_NORMAL_MODE) {
0892
0893
0894 mpc5200_mscan_set_mode(minor, MSCAN_NORMAL_MODE);
0895 }
0896
0897 if ((status =
0898 rtems_message_queue_receive(chan->rx_qid, (void *) (rx_mess),
0899 &message_size,
0900 (uint32_t) (rx_parms->rx_flags),
0901 (rtems_interval) (rx_parms->rx_timeout)))
0902 != RTEMS_SUCCESSFUL) {
0903
0904 parms->bytes_moved = 0;
0905
0906 } else {
0907
0908 parms->bytes_moved = sizeof (struct can_message);
0909
0910 }
0911
0912 return status;
0913
0914 }
0915
0916
0917
0918
0919 rtems_device_driver mscan_write(rtems_device_major_number major,
0920 rtems_device_minor_number minor, void *arg)
0921 {
0922 rtems_status_code status;
0923 rtems_libio_rw_args_t *parms = (rtems_libio_rw_args_t *) arg;
0924 struct mscan_tx_parms *tx_parms = (struct mscan_tx_parms *) (parms->buffer);
0925 struct can_message *tx_mess = (struct can_message *) (tx_parms->tx_mess);
0926 struct mscan_channel_info *chan = NULL;
0927 mscan *m = NULL;
0928
0929 switch (minor) {
0930 case MSCAN_A:
0931 case MSCAN_B:
0932 chan = &chan_info[minor];
0933 m = chan->regs;
0934 break;
0935
0936 default:
0937 return RTEMS_UNSATISFIED;
0938 break;
0939 }
0940
0941
0942 if ((chan->mode) == MSCAN_INIT_NORMAL_MODE) {
0943
0944
0945 mpc5200_mscan_set_mode(minor, MSCAN_NORMAL_MODE);
0946 }
0947
0948
0949 parms->bytes_moved = 0;
0950
0951
0952 if ((status =
0953 rtems_semaphore_obtain((rtems_id) (chan->tx_rb_sid), RTEMS_NO_WAIT,
0954 (rtems_interval) 0))
0955 == RTEMS_SUCCESSFUL) {
0956
0957
0958 tx_mess->toucan_tx_idx = tx_parms->tx_idx;
0959
0960
0961 fill_tx_buffer(chan, tx_mess);
0962
0963
0964 m->tier |= (TIER_TXEI0 | TIER_TXEI1 | TIER_TXEI2);
0965
0966
0967 parms->bytes_moved = (tx_mess->mess_len) & 0x000F;
0968
0969 }
0970
0971 return status;
0972
0973 }
0974
0975
0976
0977
0978 rtems_device_driver mscan_control(rtems_device_major_number major,
0979 rtems_device_minor_number minor, void *arg)
0980 {
0981 rtems_status_code status;
0982 uint16_t tx_id;
0983 rtems_libio_ioctl_args_t *parms = (rtems_libio_ioctl_args_t *) arg;
0984 struct mscan_ctrl_parms *ctrl_parms =
0985 (struct mscan_ctrl_parms *) (parms->buffer);
0986 struct mscan_channel_info *chan = NULL;
0987 mscan_handle *mscan_hdl = NULL;
0988 mscan *m = NULL;
0989 mscan_context context;
0990 uint8_t tx_buf_count = 0;
0991
0992 switch (minor) {
0993
0994 case MSCAN_A:
0995 case MSCAN_B:
0996 chan = &chan_info[minor];
0997 mscan_hdl = mpc5200_mscan_irq_data[minor].handle;
0998 m = chan->regs;
0999 break;
1000
1001 default:
1002 return RTEMS_UNSATISFIED;
1003 break;
1004 }
1005
1006 switch (parms->command) {
1007
1008
1009 case TOUCAN_MSCAN_INIT:
1010 mscan_hdl->toucan_callback = ctrl_parms->toucan_cb_fnc;
1011 break;
1012
1013
1014 case MSCAN_SET_RX_ID:
1015
1016
1017 mscan_initialization_mode_enter(m, &context);
1018
1019 switch (ctrl_parms->ctrl_reg_no) {
1020
1021 case RX_BUFFER_0:
1022 m->idar0 = SET_IDR0(ctrl_parms->ctrl_id);
1023 m->idar1 = SET_IDR1(ctrl_parms->ctrl_id);
1024 break;
1025
1026 case RX_BUFFER_1:
1027 m->idar2 = SET_IDR2(ctrl_parms->ctrl_id);
1028 m->idar3 = SET_IDR3(ctrl_parms->ctrl_id);
1029 break;
1030
1031 case RX_BUFFER_2:
1032 m->idar4 = SET_IDR4(ctrl_parms->ctrl_id);
1033 m->idar5 = SET_IDR5(ctrl_parms->ctrl_id);
1034 break;
1035
1036 case RX_BUFFER_3:
1037 m->idar6 = SET_IDR6(ctrl_parms->ctrl_id);
1038 m->idar7 = SET_IDR7(ctrl_parms->ctrl_id);
1039 break;
1040
1041 default:
1042 break;
1043
1044 }
1045
1046
1047 mscan_initialization_mode_leave(m, &context);
1048
1049
1050 mscan_interrupts_enable(m);
1051
1052
1053 mpc5200_mscan_wait_sync(m);
1054
1055 return RTEMS_SUCCESSFUL;
1056 break;
1057
1058
1059 case MSCAN_GET_RX_ID:
1060
1061 switch (ctrl_parms->ctrl_reg_no) {
1062
1063 case RX_BUFFER_0:
1064 ctrl_parms->ctrl_id = GET_IDR0(m->idar0) | GET_IDR1(m->idar1);
1065 break;
1066
1067 case RX_BUFFER_1:
1068 ctrl_parms->ctrl_id = GET_IDR2(m->idar2) | GET_IDR3(m->idar3);
1069 break;
1070
1071 case RX_BUFFER_2:
1072 ctrl_parms->ctrl_id = GET_IDR4(m->idar4) | GET_IDR5(m->idar5);
1073 break;
1074
1075 case RX_BUFFER_3:
1076 ctrl_parms->ctrl_id = GET_IDR6(m->idar6) | GET_IDR7(m->idar7);
1077 break;
1078
1079 default:
1080 break;
1081
1082 }
1083
1084 break;
1085
1086
1087 case MSCAN_SET_RX_ID_MASK:
1088
1089
1090 mscan_initialization_mode_enter(m, &context);
1091
1092 switch (ctrl_parms->ctrl_reg_no) {
1093
1094 case RX_BUFFER_0:
1095 m->idmr0 = SET_IDMR0(ctrl_parms->ctrl_id_mask);
1096 m->idmr1 = SET_IDMR1(ctrl_parms->ctrl_id_mask);
1097 break;
1098
1099 case RX_BUFFER_1:
1100 m->idmr2 = SET_IDMR2(ctrl_parms->ctrl_id_mask);
1101 m->idmr3 = SET_IDMR3(ctrl_parms->ctrl_id_mask);
1102 break;
1103
1104 case RX_BUFFER_2:
1105 m->idmr4 = SET_IDMR4(ctrl_parms->ctrl_id_mask);
1106 m->idmr5 = SET_IDMR5(ctrl_parms->ctrl_id_mask);
1107 break;
1108
1109 case RX_BUFFER_3:
1110 m->idmr6 = SET_IDMR6(ctrl_parms->ctrl_id_mask);
1111 m->idmr7 = SET_IDMR7(ctrl_parms->ctrl_id_mask);
1112 break;
1113
1114 default:
1115 break;
1116
1117 }
1118
1119
1120 mscan_initialization_mode_leave(m, &context);
1121
1122
1123 mscan_interrupts_enable(m);
1124
1125
1126 mpc5200_mscan_wait_sync(m);
1127
1128 break;
1129
1130
1131 case MSCAN_GET_RX_ID_MASK:
1132
1133 switch (ctrl_parms->ctrl_reg_no) {
1134
1135 case RX_BUFFER_0:
1136 ctrl_parms->ctrl_id_mask =
1137 (GET_IDMR0(m->idmr0) | GET_IDMR1(m->idmr1));
1138 break;
1139
1140 case RX_BUFFER_1:
1141 ctrl_parms->ctrl_id_mask =
1142 (GET_IDMR2(m->idmr2) | GET_IDMR3(m->idmr3));
1143 break;
1144
1145 case RX_BUFFER_2:
1146 ctrl_parms->ctrl_id_mask =
1147 (GET_IDMR4(m->idmr4) | GET_IDMR5(m->idmr5));
1148 break;
1149
1150 case RX_BUFFER_3:
1151 ctrl_parms->ctrl_id_mask =
1152 (GET_IDMR6(m->idmr6) | GET_IDMR7(m->idmr7));
1153 break;
1154
1155 default:
1156 break;
1157
1158 }
1159
1160
1161 case MSCAN_SET_TX_ID:
1162
1163
1164 if (!((m->tflg) & (uint8_t) (ctrl_parms->ctrl_reg_no))) {
1165
1166
1167 m->tarq = (uint8_t) (ctrl_parms->ctrl_reg_no);
1168
1169
1170 while ((m->taak) & (uint8_t) (ctrl_parms->ctrl_reg_no));
1171
1172 }
1173
1174
1175 m->bsel = (uint8_t) (ctrl_parms->ctrl_reg_no);
1176
1177
1178 tx_id = ctrl_parms->ctrl_id;
1179 m->txidr0 = SET_IDR0(tx_id);
1180 m->txidr1 = SET_IDR1(tx_id);
1181 m->txidr2 = 0;
1182 m->txidr3 = 0;
1183
1184 break;
1185
1186
1187 case MSCAN_GET_TX_ID:
1188
1189
1190 m->bsel = (uint8_t) (ctrl_parms->ctrl_reg_no);
1191
1192
1193 ctrl_parms->ctrl_id = GET_IDR0(m->txidr0) | GET_IDR1(m->txidr1);
1194
1195 break;
1196
1197
1198 case MSCAN_SET_BAUDRATE:
1199
1200 if (!mscan_set_bit_rate(m, ctrl_parms->ctrl_can_bitrate)) {
1201 return RTEMS_UNSATISFIED;
1202 }
1203
1204
1205 mscan_interrupts_enable(m);
1206
1207
1208 mpc5200_mscan_wait_sync(m);
1209
1210 break;
1211
1212 case SET_TX_BUF_NO:
1213
1214
1215 if ((tx_buf_count =
1216 chan->tx_buf_no) != (uint8_t) (ctrl_parms->ctrl_tx_buf_no)) {
1217
1218
1219 tx_buf_count = chan->tx_buf_no;
1220
1221
1222 while (tx_buf_count > 0) {
1223
1224
1225 if ((status =
1226 rtems_semaphore_obtain((rtems_id) (chan->tx_rb_sid), RTEMS_WAIT,
1227 (rtems_interval) 10))
1228 == RTEMS_SUCCESSFUL) {
1229
1230 tx_buf_count--;
1231
1232 }
1233
1234 }
1235
1236
1237 free((void *) chan->tx_ring_buf.buf_ptr);
1238
1239
1240 if (((chan->tx_ring_buf.buf_ptr) =
1241 malloc(sizeof (struct can_message) *
1242 ((uint8_t) (ctrl_parms->ctrl_tx_buf_no) + 1))) != NULL) {
1243 chan->tx_ring_buf.head_ptr = chan->tx_ring_buf.tail_ptr =
1244 chan->tx_ring_buf.buf_ptr;
1245 } else {
1246 return RTEMS_UNSATISFIED;
1247 }
1248
1249
1250 chan->tx_buf_no = (uint8_t) (ctrl_parms->ctrl_tx_buf_no);
1251
1252
1253 while (tx_buf_count < chan->tx_buf_no) {
1254
1255
1256 rtems_semaphore_release((rtems_id) (chan->tx_rb_sid));
1257
1258 tx_buf_count++;
1259
1260 }
1261
1262 } else {
1263
1264 return RTEMS_SUCCESSFUL;
1265
1266 }
1267 break;
1268
1269 default:
1270 break;
1271
1272 }
1273
1274 return RTEMS_SUCCESSFUL;
1275
1276 }