File indexing completed on 2025-05-11 08:23:59
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 #include <unistd.h>
0031
0032 #include <rtems.h>
0033 #include <rtems/console.h>
0034 #include <rtems/termiostypes.h>
0035 #include <rtems/bspIo.h>
0036 #include <rtems/error.h>
0037
0038 #include <bsp.h>
0039 #include <mpc8xx.h>
0040 #include <bsp/irq.h>
0041
0042
0043
0044
0045 #define RXBUFSIZE 16
0046
0047 #define M8xx_SICR_BRG1 (0)
0048 #define M8xx_SICR_BRG2 (1)
0049 #define M8xx_SICR_BRG3 (2)
0050 #define M8xx_SICR_BRG4 (3)
0051
0052 #define M8xx_SICR_SCCRX_MSK(scc) (( 7) << (((scc))*8+3))
0053 #define M8xx_SICR_SCCRX(scc,clk) ((clk) << (((scc))*8+3))
0054
0055 #define M8xx_SICR_SCCTX_MSK(scc) (( 7) << (((scc))*8+0))
0056 #define M8xx_SICR_SCCTX(scc,clk) ((clk) << (((scc))*8+0))
0057
0058 #define M8xx_SIMODE_SMCCS(smc,clk) ((clk) << ((smc)*16+12))
0059 #define M8xx_SIMODE_SMCCS_MSK(smc) M8xx_SIMODE_SMCCS(smc,7)
0060
0061 #define CONS_CHN_CNT 6
0062 #define CONS_CHN_SCC1 0
0063 #define CONS_CHN_SCC2 1
0064 #define CONS_CHN_SCC3 2
0065 #define CONS_CHN_SCC4 3
0066 #define CONS_CHN_SMC1 4
0067 #define CONS_CHN_SMC2 5
0068 #define CONS_CHN_NONE -1
0069
0070
0071
0072
0073 #define CONS_MODE_UNUSED -1
0074 #define CONS_MODE_POLLED TERMIOS_POLLED
0075 #define CONS_MODE_IRQ TERMIOS_IRQ_DRIVEN
0076
0077 #define CHN_IS_SCC(chan) ((chan) < CONS_CHN_SMC1)
0078
0079 #define BRG_CNT 4
0080
0081 #define MAX_IDL_DEFAULT 10
0082 #define DEVICEPREFIX "tty"
0083
0084
0085
0086
0087 #define SCC_RXBD_CNT 4
0088 #define SCC_TXBD_CNT 4
0089 typedef char sccRxBuf_t[SCC_RXBD_CNT][RXBUFSIZE];
0090
0091
0092
0093
0094 typedef struct m8xx_console_chan_desc_s {
0095 rtems_termios_device_context base;
0096 volatile m8xxBufferDescriptor_t *sccFrstRxBd;
0097 volatile m8xxBufferDescriptor_t *sccCurrRxBd;
0098 volatile m8xxBufferDescriptor_t *sccFrstTxBd;
0099 volatile m8xxBufferDescriptor_t *sccPrepTxBd;
0100 volatile m8xxBufferDescriptor_t *sccDequTxBd;
0101 bool is_scc;
0102 struct {
0103 volatile m8xxSCCparms_t *sccp;
0104 volatile m8xxSMCparms_t *smcp;
0105 } parms;
0106 struct {
0107 volatile m8xxSCCRegisters_t *sccr;
0108 volatile m8xxSMCRegisters_t *smcr;
0109 } regs;
0110 int chan;
0111 rtems_termios_device_mode mode;
0112 rtems_vector_number ivec_src;
0113 int cr_chan_code;
0114 int brg_used;
0115 sccRxBuf_t *rxBuf;
0116 } m8xx_console_chan_desc_t;
0117
0118 m8xx_console_chan_desc_t m8xx_console_chan_desc[CONS_CHN_CNT] = {
0119
0120 { .is_scc = true,
0121 .parms = {(m8xxSCCparms_t *)&(m8xx.scc1p),NULL},
0122 .regs = {&(m8xx.scc1),NULL},
0123 .chan = CONS_CHN_SCC1,
0124 .ivec_src = BSP_CPM_IRQ_SCC1,
0125 .cr_chan_code = M8xx_CR_CHAN_SCC1,
0126 .brg_used = -1},
0127
0128 { .is_scc = true,
0129 .parms = {&(m8xx.scc2p),NULL},
0130 .regs = {&(m8xx.scc2),NULL},
0131 .chan = CONS_CHN_SCC2,
0132 .ivec_src = BSP_CPM_IRQ_SCC2,
0133 .cr_chan_code = M8xx_CR_CHAN_SCC2,
0134 .brg_used = -1},
0135
0136 { .is_scc = true,
0137 .parms = {&(m8xx.scc3p),NULL},
0138 .regs = {&(m8xx.scc3),NULL},
0139 .chan = CONS_CHN_SCC3,
0140 .ivec_src = BSP_CPM_IRQ_SCC3,
0141 .cr_chan_code = M8xx_CR_CHAN_SCC3,
0142 .brg_used = -1},
0143
0144 { .is_scc = true,
0145 .parms = {&(m8xx.scc4p),NULL},
0146 .regs = {&(m8xx.scc4),NULL},
0147 .chan = CONS_CHN_SCC4,
0148 .ivec_src = BSP_CPM_IRQ_SCC4,
0149 .cr_chan_code = M8xx_CR_CHAN_SCC4,
0150 .brg_used = -1},
0151
0152 { .is_scc = false,
0153 .parms = {NULL,&(m8xx.smc1p)},
0154 .regs = {NULL,&(m8xx.smc1)},
0155 .chan = CONS_CHN_SMC1,
0156 .ivec_src = BSP_CPM_IRQ_SMC1,
0157 .cr_chan_code = M8xx_CR_CHAN_SMC1,
0158 .brg_used = -1},
0159
0160 { .is_scc = false,
0161 .parms = {NULL,&(m8xx.smc2p)},
0162 .regs = {NULL,&(m8xx.smc2)},
0163 .chan = CONS_CHN_SMC2,
0164 .ivec_src = BSP_CPM_IRQ_SMC2_OR_PIP,
0165 .cr_chan_code = M8xx_CR_CHAN_SMC2,
0166 .brg_used = -1}};
0167
0168 #define CHN_PARAM_GET(cd,param) \
0169 (cd->is_scc \
0170 ? cd->parms.sccp->param \
0171 : cd->parms.smcp->param)
0172
0173 #define CHN_PARAM_SET(cd,param,value) \
0174 do {if (cd->is_scc) \
0175 cd->parms.sccp->param = value; \
0176 else \
0177 cd->parms.smcp->param = value; \
0178 } while (0)
0179
0180 #define CHN_EVENT_GET(cd) \
0181 (cd->is_scc \
0182 ? cd->regs.sccr->scce \
0183 : cd->regs.smcr->smce)
0184
0185 #define CHN_EVENT_CLR(cd,mask) \
0186 do { \
0187 if (cd->is_scc) \
0188 cd->regs.sccr->scce = (mask); \
0189 else \
0190 cd->regs.smcr->smce = (mask); \
0191 }while (0)
0192
0193 #define CHN_MASK_GET(cd) \
0194 (cd->is_scc \
0195 ? cd->regs.sccr->sccm \
0196 : cd->regs.smcr->smcm)
0197
0198 #define CHN_MASK_SET(cd,mask) \
0199 do { \
0200 if (cd->is_scc) \
0201 cd->regs.sccr->sccm = (mask); \
0202 else \
0203 cd->regs.smcr->smcm = (mask); \
0204 }while (0)
0205
0206
0207
0208
0209 static uint32_t
0210 sccBRGval (int baud)
0211 {
0212 int divisor;
0213 int div16 = 0;
0214
0215 divisor = ((BSP_bus_frequency / 16) + (baud / 2)) / baud;
0216 if (divisor > 4096) {
0217 div16 = 1;
0218 divisor = (divisor + 8) / 16;
0219 }
0220 return M8xx_BRG_EN | M8xx_BRG_EXTC_BRGCLK | ((divisor - 1) << 1) | div16;
0221 }
0222
0223 typedef struct {
0224 uint32_t reg_content;
0225 int link_cnt;
0226 }brg_state_t;
0227 brg_state_t scc_brg_state[BRG_CNT];
0228
0229
0230
0231
0232 static void sccBRGinit(void)
0233 {
0234 int brg_idx;
0235
0236 for (brg_idx = 0;brg_idx < BRG_CNT;brg_idx++) {
0237 scc_brg_state[brg_idx].reg_content = 0;
0238 scc_brg_state[brg_idx].link_cnt = 0;
0239 }
0240 #ifndef MDE360
0241
0242
0243
0244 m8xx.papar |= ((1 << 11) | (1 << 12));
0245 m8xx.padir &= ~((1 << 11) | (1 << 12));
0246 #endif
0247 }
0248
0249 #if CONS_USE_EXT_CLK
0250
0251
0252
0253 static uint32_t clkin_frq[2][4] = {
0254 #ifdef MDE360
0255 {0,0,0,0},
0256 {0,0,0,0}
0257 #else
0258 {0,0,0,1843000},
0259 {1843000,0,0,0}
0260 #endif
0261 };
0262 #endif
0263
0264
0265
0266
0267
0268
0269
0270 static bool sccBRGalloc(m8xx_console_chan_desc_t *cd,int baud)
0271 {
0272 rtems_interrupt_level level;
0273 uint32_t reg_val;
0274 int old_brg;
0275 int new_brg = -1;
0276 int brg_idx;
0277 #if CONS_USE_EXT_CLK
0278 int clk_group;
0279 int clk_sel;
0280 #endif
0281
0282 old_brg = cd->brg_used;
0283
0284 reg_val = sccBRGval(baud);
0285
0286 #if CONS_EXT_CLK
0287
0288 clk_group = ((chan == CONS_CHN_SCC3) ||
0289 (chan == CONS_CHN_SCC4) ||
0290 (chan == CONS_CHN_SMC2)) ? 1 : 0;
0291
0292 for (clk_sel = 0, new_brg = -1;
0293 (clk_sel < 4) && (new_brg < 0);
0294 clk_sel++) {
0295 if (baud == (clkin_frq[clk_group][clk_sel] / 16)) {
0296 new_brg = clk_sel + 4;
0297 }
0298 }
0299 #endif
0300
0301 rtems_interrupt_disable(level);
0302
0303 if (new_brg < 0) {
0304
0305 for (brg_idx = 0;
0306 (new_brg < 0) && (brg_idx < BRG_CNT);
0307 brg_idx++) {
0308 if (scc_brg_state[brg_idx].reg_content == reg_val) {
0309 new_brg = brg_idx;
0310 }
0311 }
0312
0313
0314
0315
0316 if ((new_brg < 0) &&
0317 (old_brg >= 0) &&
0318 (scc_brg_state[old_brg].link_cnt == 1)) {
0319 new_brg = old_brg;
0320 }
0321
0322 for (brg_idx = 0;
0323 (new_brg < 0) && (brg_idx < BRG_CNT);
0324 brg_idx++) {
0325 if (scc_brg_state[brg_idx].link_cnt == 0) {
0326 new_brg = brg_idx;
0327 }
0328 }
0329 }
0330
0331
0332 if ((old_brg >= 0) &&
0333 (old_brg < 4)) {
0334 scc_brg_state[old_brg].link_cnt--;
0335 }
0336
0337 if ((new_brg >= 0) &&
0338 (new_brg < 4)) {
0339 scc_brg_state[new_brg].link_cnt++;
0340 scc_brg_state[new_brg].reg_content = reg_val;
0341 (&m8xx.brgc1)[new_brg] = reg_val;
0342 }
0343 rtems_interrupt_enable(level);
0344
0345
0346 if (new_brg >= 0) {
0347 cd->brg_used = new_brg;
0348
0349
0350
0351 if (cd->is_scc) {
0352 m8xx.sicr = ((m8xx.sicr & ~(M8xx_SICR_SCCRX_MSK(cd->chan) |
0353 M8xx_SICR_SCCTX_MSK(cd->chan))) |
0354 M8xx_SICR_SCCRX(cd->chan,new_brg)|
0355 M8xx_SICR_SCCTX(cd->chan,new_brg));
0356 }
0357 else {
0358
0359 m8xx.simode = ((m8xx.simode & ~(M8xx_SIMODE_SMCCS_MSK(cd->chan - CONS_CHN_SMC1)))|
0360 M8xx_SIMODE_SMCCS(cd->chan - CONS_CHN_SMC1,new_brg));
0361 }
0362
0363 return true;
0364 } else {
0365 return false;
0366 }
0367 }
0368
0369
0370
0371
0372
0373 static bool
0374 sccSetAttributes (rtems_termios_device_context *base, const struct termios *t)
0375 {
0376 m8xx_console_chan_desc_t *cd = (m8xx_console_chan_desc_t *)base;
0377 speed_t speed;
0378 rtems_termios_baud_t baud;
0379
0380 speed = cfgetispeed(t);
0381 if (speed == B0) {
0382 speed = cfgetospeed(t);
0383 }
0384
0385 baud = rtems_termios_baud_to_number(speed);
0386 if (baud == 0) {
0387 return false;
0388 }
0389
0390 return sccBRGalloc(cd,baud);
0391 }
0392
0393
0394
0395
0396 static rtems_isr
0397 sccInterruptHandler (void *arg)
0398 {
0399 rtems_termios_tty *tty = arg;
0400 m8xx_console_chan_desc_t *cd = rtems_termios_get_device_context(tty);
0401 uint16_t status;
0402 uint16_t length;
0403 void *buffer;
0404
0405
0406
0407
0408 if (CHN_EVENT_GET(cd) & 0x1) {
0409
0410
0411
0412 CHN_EVENT_CLR(cd,0x01);
0413
0414
0415
0416 while (true) {
0417 status = cd->sccCurrRxBd->status;
0418
0419 if ((cd->sccCurrRxBd->status & M8xx_BD_EMPTY) != 0) {
0420 break;
0421 }
0422
0423 buffer = cd->sccCurrRxBd->buffer;
0424 length = cd->sccCurrRxBd->length;
0425 rtems_cache_invalidate_multiple_data_lines(buffer, length);
0426 rtems_termios_enqueue_raw_characters (tty, buffer, length);
0427
0428
0429
0430
0431 cd->sccCurrRxBd->status = (status & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT))
0432 | M8xx_BD_EMPTY;
0433
0434
0435
0436 if ((status & M8xx_BD_WRAP) != 0) {
0437 cd->sccCurrRxBd = cd->sccFrstRxBd;
0438 } else {
0439 cd->sccCurrRxBd++;
0440 }
0441 }
0442 }
0443
0444
0445
0446 if (CHN_EVENT_GET(cd) & 0x2) {
0447
0448
0449
0450 CHN_EVENT_CLR(cd,0x2);
0451
0452
0453
0454
0455
0456
0457 while (cd->sccDequTxBd != cd->sccPrepTxBd) {
0458 status = cd->sccDequTxBd->status;
0459
0460 if ((status & M8xx_BD_READY) != 0) {
0461 break;
0462 }
0463
0464 if ((status & M8xx_BD_INTERRUPT) != 0) {
0465 rtems_termios_dequeue_characters (tty, cd->sccDequTxBd->length);
0466 }
0467
0468
0469
0470
0471 if ((status & M8xx_BD_WRAP) != 0) {
0472 cd->sccDequTxBd = cd->sccFrstTxBd;
0473 } else {
0474 cd->sccDequTxBd++;
0475 }
0476 }
0477 }
0478 }
0479
0480 static void
0481 mpc8xx_console_irq_on(m8xx_console_chan_desc_t *cd)
0482 {
0483 CHN_MASK_SET(cd, 3);
0484 }
0485
0486 static void
0487 sccInitialize (m8xx_console_chan_desc_t *cd)
0488 {
0489 int i;
0490
0491
0492
0493
0494 cd->rxBuf = rtems_cache_aligned_malloc(sizeof(*cd->rxBuf));
0495 if (cd->rxBuf == NULL) {
0496 rtems_panic("Cannot allocate console rx buffer\n");
0497 }
0498
0499
0500
0501
0502 cd->sccCurrRxBd =
0503 cd->sccFrstRxBd = m8xx_bd_allocate(SCC_RXBD_CNT);
0504 cd->sccPrepTxBd =
0505 cd->sccDequTxBd =
0506 cd->sccFrstTxBd = m8xx_bd_allocate(SCC_TXBD_CNT);
0507 switch(cd->chan) {
0508 case CONS_CHN_SCC1:
0509
0510
0511
0512
0513 m8xx.papar |= 0x03;
0514 m8xx.padir &= ~0x03;
0515
0516
0517
0518
0519 m8xx.pcpar &= ~0x01;
0520 m8xx.pcso &= ~0x01;
0521 m8xx.pcdir |= 0x01;
0522 m8xx.pcdat &= ~0x01;
0523 break;
0524 case CONS_CHN_SCC2:
0525
0526
0527
0528
0529 m8xx.papar |= 0x0C;
0530 m8xx.padir &= ~0x0C;
0531
0532
0533
0534
0535 m8xx.pcpar &= ~0x02;
0536 m8xx.pcso &= ~0x02;
0537 m8xx.pcdir |= 0x02;
0538 m8xx.pcdat &= ~0x02;
0539 break;
0540 case CONS_CHN_SCC3:
0541
0542
0543
0544
0545 m8xx.papar |= 0x30;
0546 m8xx.padir &= ~0x30;
0547
0548
0549
0550
0551 m8xx.pcpar &= ~0x04;
0552 m8xx.pcso &= ~0x04;
0553 m8xx.pcdir |= 0x04;
0554 m8xx.pcdat &= ~0x04;
0555 break;
0556 case CONS_CHN_SCC4:
0557
0558
0559
0560
0561 m8xx.papar |= 0xC0;
0562 m8xx.padir &= ~0xC0;
0563
0564
0565
0566
0567 m8xx.pcpar &= ~0x08;
0568 m8xx.pcso &= ~0x08;
0569 m8xx.pcdir |= 0x08;
0570 m8xx.pcdat &= ~0x08;
0571 break;
0572 case CONS_CHN_SMC1:
0573
0574
0575
0576 m8xx.pbpar |= 0xC0;
0577 m8xx.pbdir &= ~0xC0;
0578 break;
0579 case CONS_CHN_SMC2:
0580
0581
0582
0583 m8xx.pbpar |= 0xC00;
0584 m8xx.pbdir &= ~0xC00;
0585 break;
0586 }
0587
0588
0589
0590 sccBRGalloc(cd,9600);
0591
0592
0593
0594
0595
0596 CHN_PARAM_SET(cd,rbase,(char *)cd->sccFrstRxBd - (char *)&m8xx);
0597 CHN_PARAM_SET(cd,tbase,(char *)cd->sccFrstTxBd - (char *)&m8xx);
0598 CHN_PARAM_SET(cd,rfcr ,M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0));
0599 CHN_PARAM_SET(cd,tfcr ,M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0));
0600 if (cd->mode != TERMIOS_POLLED)
0601 CHN_PARAM_SET(cd,mrblr,RXBUFSIZE);
0602 else
0603 CHN_PARAM_SET(cd,mrblr,1);
0604
0605
0606
0607
0608 CHN_PARAM_SET(cd,un.uart.max_idl ,MAX_IDL_DEFAULT);
0609 CHN_PARAM_SET(cd,un.uart.brkln ,0);
0610 CHN_PARAM_SET(cd,un.uart.brkec ,0);
0611 CHN_PARAM_SET(cd,un.uart.brkcr ,0);
0612 if (cd->is_scc) {
0613 cd->parms.sccp->un.uart.character[0]=0x8000;
0614 cd->parms.sccp->un.uart.rccm=0x80FF;
0615 }
0616
0617
0618
0619
0620 for (i = 0;i < SCC_RXBD_CNT;i++) {
0621 cd->sccFrstRxBd[i].status = M8xx_BD_EMPTY | M8xx_BD_INTERRUPT;
0622 if (i == SCC_RXBD_CNT-1) {
0623 cd->sccFrstRxBd[i].status |= M8xx_BD_WRAP;
0624 }
0625 cd->sccFrstRxBd[i].length = 0;
0626 cd->sccFrstRxBd[i].buffer = (*cd->rxBuf)[i];
0627 }
0628
0629
0630
0631 for (i = 0;i < SCC_TXBD_CNT;i++) {
0632 cd->sccFrstTxBd[i].status = M8xx_BD_INTERRUPT;
0633 if (i == SCC_TXBD_CNT-1) {
0634 cd->sccFrstTxBd[i].status |= M8xx_BD_WRAP;
0635 }
0636 cd->sccFrstTxBd[i].length = 0;
0637 cd->sccFrstTxBd[i].buffer = NULL;
0638 }
0639
0640
0641
0642
0643 CHN_EVENT_CLR(cd,~0);
0644 CHN_MASK_SET(cd,0);
0645
0646 if (cd->is_scc) {
0647 cd->regs.sccr->psmr = 0xb000;
0648 cd->regs.sccr->gsmr_h = 0x00000000;
0649 cd->regs.sccr->gsmr_l = 0x00028004;
0650 }
0651 else {
0652 cd->regs.smcr->smcmr = 0x4820;
0653 }
0654
0655
0656
0657 m8xx_cp_execute_cmd(M8xx_CR_OP_INIT_RX_TX | cd->cr_chan_code);
0658
0659
0660
0661
0662 if (cd->is_scc) {
0663 cd->regs.sccr->gsmr_l |= 0x00000030;
0664 }
0665 else {
0666 cd->regs.smcr->smcmr |= 0x0003;
0667 }
0668 }
0669
0670
0671
0672
0673 static int
0674 sccPollRead (rtems_termios_device_context *base)
0675 {
0676 m8xx_console_chan_desc_t *cd = (m8xx_console_chan_desc_t *)base;
0677 int c = -1;
0678
0679 while(1) {
0680 if ((cd->sccCurrRxBd->status & M8xx_BD_EMPTY) != 0) {
0681 return -1;
0682 }
0683
0684 if (0 == (cd->sccCurrRxBd->status & (M8xx_BD_OVERRUN
0685 | M8xx_BD_PARITY_ERROR
0686 | M8xx_BD_FRAMING_ERROR
0687 | M8xx_BD_BREAK
0688 | M8xx_BD_IDLE))) {
0689
0690 rtems_cache_invalidate_multiple_data_lines((void *)cd->sccCurrRxBd->buffer,
0691 cd->sccCurrRxBd->length);
0692 c = (unsigned)*((char *)cd->sccCurrRxBd->buffer);
0693
0694
0695
0696 }
0697 cd->sccCurrRxBd->status =
0698 (cd->sccCurrRxBd->status
0699 & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT))
0700 | M8xx_BD_EMPTY;
0701
0702
0703
0704 if ((cd->sccCurrRxBd->status & M8xx_BD_WRAP) != 0) {
0705 cd->sccCurrRxBd = cd->sccFrstRxBd;
0706 }
0707 else {
0708 cd->sccCurrRxBd++;
0709 }
0710 if (c >= 0) {
0711 return c;
0712 }
0713 }
0714 }
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724 static void
0725 sccInterruptWrite (rtems_termios_device_context *base, const char *buf, size_t len)
0726 {
0727 m8xx_console_chan_desc_t *cd = (m8xx_console_chan_desc_t *)base;
0728
0729 if (len > 0) {
0730 uint16_t status = cd->sccPrepTxBd->status;
0731
0732 if ((status & M8xx_BD_READY) == 0) {
0733 cd->sccPrepTxBd->buffer = RTEMS_DECONST(char*, buf);
0734 cd->sccPrepTxBd->length = len;
0735 rtems_cache_flush_multiple_data_lines(buf, len);
0736
0737
0738
0739
0740 cd->sccPrepTxBd->status = (status & M8xx_BD_WRAP)
0741 | M8xx_BD_READY | M8xx_BD_INTERRUPT;
0742
0743 if ((status & M8xx_BD_WRAP) != 0) {
0744 cd->sccPrepTxBd = cd->sccFrstTxBd;
0745 } else {
0746 cd->sccPrepTxBd++;
0747 }
0748 }
0749 }
0750 }
0751
0752 static void
0753 sccPollWrite (rtems_termios_device_context *base, const char *buf, size_t len)
0754 {
0755 m8xx_console_chan_desc_t *cd = (m8xx_console_chan_desc_t *)base;
0756 volatile m8xxBufferDescriptor_t *bd = NULL;
0757
0758 rtems_cache_flush_multiple_data_lines (buf, len);
0759
0760 while (bd == NULL) {
0761 rtems_interrupt_level level;
0762 uint16_t status;
0763
0764 rtems_interrupt_disable(level);
0765
0766 bd = cd->sccPrepTxBd;
0767 status = bd->status;
0768
0769 if ((status & M8xx_BD_READY) == 0) {
0770 bd->buffer = RTEMS_DECONST (char *, buf);
0771 bd->length = len;
0772 bd->status = (status & M8xx_BD_WRAP) | M8xx_BD_READY;
0773
0774 if ((status & M8xx_BD_WRAP) != 0) {
0775 cd->sccPrepTxBd = cd->sccFrstTxBd;
0776 } else {
0777 cd->sccPrepTxBd++;
0778 }
0779 } else {
0780 bd = NULL;
0781 }
0782
0783 rtems_interrupt_enable(level);
0784 }
0785
0786 while ((bd->status & M8xx_BD_READY) != 0) {
0787
0788 }
0789 }
0790
0791
0792
0793
0794 int BSP_output_chan = CONS_CHN_NONE;
0795
0796 static void console_debug_putc_onlcr(const char c)
0797 {
0798 rtems_interrupt_level irq_level;
0799
0800 if (BSP_output_chan != CONS_CHN_NONE) {
0801 rtems_interrupt_disable(irq_level);
0802
0803 sccPollWrite (&m8xx_console_chan_desc[BSP_output_chan].base,&c,1);
0804 rtems_interrupt_enable(irq_level);
0805 }
0806 }
0807
0808 BSP_output_char_function_type BSP_output_char = console_debug_putc_onlcr;
0809 BSP_polling_getchar_function_type BSP_poll_char = NULL;
0810
0811
0812
0813
0814
0815
0816
0817
0818 struct {
0819 rtems_device_minor_number minor;
0820 int driver_mode;
0821 } channel_list[] = {
0822 {CONS_CHN_SMC1,CONS_SMC1_MODE},
0823 {CONS_CHN_SMC2,CONS_SMC2_MODE},
0824 {CONS_CHN_SCC1,CONS_SCC1_MODE},
0825 {CONS_CHN_SCC2,CONS_SCC2_MODE},
0826 {CONS_CHN_SCC3,CONS_SCC3_MODE},
0827 {CONS_CHN_SCC4,CONS_SCC4_MODE}
0828 };
0829
0830 static bool m8xx_console_first_open(
0831 rtems_termios_tty *tty,
0832 rtems_termios_device_context *base,
0833 struct termios *term,
0834 rtems_libio_open_close_args_t *args
0835 )
0836 {
0837 m8xx_console_chan_desc_t *cd = (m8xx_console_chan_desc_t *)base;
0838
0839 if (cd->mode == TERMIOS_IRQ_DRIVEN) {
0840 rtems_status_code sc;
0841
0842 sc = rtems_interrupt_handler_install(
0843 cd->ivec_src,
0844 "SCC",
0845 RTEMS_INTERRUPT_UNIQUE,
0846 sccInterruptHandler,
0847 tty
0848 );
0849 if (sc != RTEMS_SUCCESSFUL) {
0850 return false;
0851 }
0852
0853 mpc8xx_console_irq_on(cd);
0854 }
0855
0856 return true;
0857 }
0858
0859 static const rtems_termios_device_handler m8xx_console_handler_polled = {
0860 .first_open = m8xx_console_first_open,
0861 .set_attributes = sccSetAttributes,
0862 .write = sccPollWrite,
0863 .poll_read = sccPollRead,
0864 .mode = TERMIOS_POLLED
0865 };
0866
0867 static const rtems_termios_device_handler m8xx_console_handler_irq_driven = {
0868 .first_open = m8xx_console_first_open,
0869 .set_attributes = sccSetAttributes,
0870 .write = sccInterruptWrite,
0871 .mode = TERMIOS_IRQ_DRIVEN
0872 };
0873
0874
0875
0876
0877 rtems_device_driver console_initialize(rtems_device_major_number major,
0878 rtems_device_minor_number minor,
0879 void *arg
0880 )
0881 {
0882 rtems_status_code status = RTEMS_SUCCESSFUL;
0883 int entry,ttynum;
0884 char tty_name[] = "/dev/tty00";
0885
0886
0887
0888
0889 rtems_termios_initialize ();
0890
0891
0892
0893 sccBRGinit();
0894 ttynum = 0;
0895 for (entry = 0;
0896 (entry < sizeof(channel_list)/sizeof(channel_list[0]))
0897 && (status == RTEMS_SUCCESSFUL);
0898 entry++) {
0899 if (channel_list[entry].driver_mode != CONS_MODE_UNUSED) {
0900 m8xx_console_chan_desc_t *cd =
0901 &m8xx_console_chan_desc[channel_list[entry].minor];
0902
0903
0904
0905 cd->mode = channel_list[entry].driver_mode;
0906 sccInitialize (cd);
0907
0908
0909
0910
0911 tty_name[sizeof(tty_name)-2] = '0'+ttynum;
0912 ttynum++;
0913
0914
0915
0916 status = rtems_termios_device_install(
0917 tty_name,
0918 cd->mode == TERMIOS_IRQ_DRIVEN ?
0919 &m8xx_console_handler_irq_driven : &m8xx_console_handler_polled,
0920 NULL,
0921 &cd->base
0922 );
0923 if (status != RTEMS_SUCCESSFUL) {
0924 rtems_fatal_error_occurred (status);
0925 }
0926
0927 if (cd->chan == CONSOLE_CHN) {
0928 int rv;
0929
0930 rv = link(tty_name, CONSOLE_DEVICE_NAME);
0931 if (rv != 0) {
0932 rtems_fatal_error_occurred (RTEMS_IO_ERROR);
0933 }
0934 }
0935 }
0936 }
0937
0938
0939
0940
0941 BSP_output_chan = PRINTK_CHN;
0942
0943 return RTEMS_SUCCESSFUL;
0944 }