File indexing completed on 2025-05-11 08:24:05
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
0035
0036 #include <rtems.h>
0037 #include <rtems/libio.h>
0038 #include <rtems/score/sysstate.h>
0039 #include <stdlib.h>
0040
0041 #include <libchip/serial.h>
0042 #include <libchip/mc68681.h>
0043 #include <libchip/sersupp.h>
0044 #include "mc68681_p.h"
0045
0046
0047
0048
0049
0050 const console_fns mc68681_fns =
0051 {
0052 libchip_serial_default_probe,
0053 mc68681_open,
0054 NULL,
0055 NULL,
0056 mc68681_write_support_int,
0057 mc68681_initialize_interrupts,
0058 mc68681_write_polled,
0059 mc68681_set_attributes,
0060 true
0061 };
0062
0063 const console_fns mc68681_fns_polled =
0064 {
0065 libchip_serial_default_probe,
0066 mc68681_open,
0067 mc68681_close,
0068 mc68681_inbyte_nonblocking_polled,
0069 mc68681_write_support_polled,
0070 mc68681_init,
0071 mc68681_write_polled,
0072 mc68681_set_attributes,
0073 false,
0074 };
0075
0076
0077 #if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE)
0078 extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
0079 #endif
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 MC68681_STATIC int mc68681_baud_rate(
0094 int minor,
0095 int baud,
0096 unsigned int *baud_mask_p,
0097 unsigned int *acr_bit_p,
0098 unsigned int *command
0099 );
0100
0101
0102
0103
0104
0105
0106
0107
0108 MC68681_STATIC int mc68681_set_attributes(
0109 int minor,
0110 const struct termios *t
0111 )
0112 {
0113 uint32_t pMC68681_port;
0114 uint32_t pMC68681;
0115 unsigned int mode1;
0116 unsigned int mode2;
0117 unsigned int baud_mask;
0118 unsigned int acr_bit;
0119 unsigned int cmd = 0;
0120 setRegister_f setReg;
0121 rtems_interrupt_level Irql;
0122
0123 pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
0124 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0125 setReg = Console_Port_Tbl[minor]->setRegister;
0126
0127
0128
0129
0130
0131 if (mc68681_baud_rate( minor, t->c_cflag, &baud_mask, &acr_bit, &cmd ) == -1)
0132 return -1;
0133
0134 baud_mask |= baud_mask << 4;
0135 acr_bit <<= 7;
0136
0137
0138
0139
0140
0141 mode1 = 0;
0142 mode2 = 0;
0143
0144 if (t->c_cflag & PARENB) {
0145 if (t->c_cflag & PARODD)
0146 mode1 |= 0x04;
0147
0148
0149 } else {
0150 mode1 |= 0x10;
0151 }
0152
0153
0154
0155
0156
0157 if (t->c_cflag & CSIZE) {
0158 switch (t->c_cflag & CSIZE) {
0159 case CS5: break;
0160 case CS6: mode1 |= 0x01; break;
0161 case CS7: mode1 |= 0x02; break;
0162 case CS8: mode1 |= 0x03; break;
0163 }
0164 } else {
0165 mode1 |= 0x03;
0166 }
0167
0168
0169
0170
0171
0172 if (t->c_cflag & CSTOPB) {
0173 mode2 |= 0x0F;
0174 } else {
0175 if ((t->c_cflag & CSIZE) == CS5)
0176 return -1;
0177 mode2 |= 0x07;
0178 }
0179
0180
0181
0182
0183
0184 if(t->c_cflag & CRTSCTS) {
0185 mode1 |= 0x80;
0186 mode2 |= 0x10;
0187 }
0188
0189
0190 rtems_interrupt_disable(Irql);
0191 (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit );
0192 (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud_mask );
0193 if ( cmd ) {
0194 (*setReg)( pMC68681_port, MC68681_COMMAND, cmd );
0195 (*setReg)( pMC68681_port, MC68681_COMMAND, cmd | 0x20 );
0196 }
0197 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
0198 (*setReg)( pMC68681_port, MC68681_MODE, mode1 );
0199 (*setReg)( pMC68681_port, MC68681_MODE, mode2 );
0200 rtems_interrupt_enable(Irql);
0201 return 0;
0202 }
0203
0204
0205
0206
0207
0208
0209
0210 MC68681_STATIC void mc68681_initialize_context(
0211 int minor,
0212 mc68681_context *pmc68681Context
0213 )
0214 {
0215 int port;
0216 unsigned int pMC68681;
0217 unsigned int pMC68681_port;
0218
0219 pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
0220 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0221
0222 pmc68681Context->mate = -1;
0223
0224 for (port=0 ; port<Console_Port_Count ; port++ ) {
0225 if ( Console_Port_Tbl[port]->ulCtrlPort1 == pMC68681 &&
0226 Console_Port_Tbl[port]->ulCtrlPort2 != pMC68681_port ) {
0227 pmc68681Context->mate = port;
0228 pmc68681Context->imr = 0;
0229 break;
0230 }
0231 }
0232
0233 }
0234
0235
0236
0237
0238
0239
0240
0241 MC68681_STATIC void mc68681_init(int minor)
0242 {
0243 uint32_t pMC68681_port;
0244 mc68681_context *pmc68681Context;
0245 setRegister_f setReg;
0246
0247 pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context));
0248
0249 Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context;
0250
0251 mc68681_initialize_context( minor, pmc68681Context );
0252
0253 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0254 setReg = Console_Port_Tbl[minor]->setRegister;
0255
0256
0257
0258
0259
0260 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
0261 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
0262 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
0263 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
0264 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
0265 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
0266 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
0267
0268
0269 (*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 );
0270 (*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 );
0271
0272
0273
0274
0275
0276 mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL );
0277 }
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 MC68681_STATIC int mc68681_open(
0288 int major,
0289 int minor,
0290 void *arg
0291 )
0292 {
0293 uint32_t pMC68681;
0294 uint32_t pMC68681_port;
0295 unsigned int baud;
0296 unsigned int acr_bit;
0297 unsigned int vector;
0298 unsigned int command = 0;
0299 rtems_interrupt_level Irql;
0300 setRegister_f setReg;
0301 int status;
0302
0303
0304 pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
0305 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0306 setReg = Console_Port_Tbl[minor]->setRegister;
0307 vector = Console_Port_Tbl[minor]->ulIntVector;
0308
0309
0310
0311 status = mc68681_baud_rate( minor, B9600, &baud, &acr_bit, &command );
0312 if (status < 0) rtems_fatal_error_occurred (RTEMS_NOT_DEFINED);
0313
0314
0315
0316
0317
0318 rtems_interrupt_disable(Irql);
0319 (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit << 7 );
0320 (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud );
0321 if ( command ) {
0322 (*setReg)( pMC68681_port, MC68681_COMMAND, command );
0323 (*setReg)( pMC68681_port, MC68681_COMMAND, command | 0x20 );
0324 }
0325 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
0326 (*setReg)( pMC68681_port, MC68681_MODE, 0x13 );
0327 (*setReg)( pMC68681_port, MC68681_MODE, 0x07 );
0328 rtems_interrupt_enable(Irql);
0329
0330 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_TX );
0331 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_RX );
0332
0333 (*setReg)( pMC68681, MC68681_INTERRUPT_VECTOR_REG, vector );
0334
0335 return RTEMS_SUCCESSFUL;
0336 }
0337
0338
0339
0340
0341
0342
0343
0344 MC68681_STATIC int mc68681_close(
0345 int major,
0346 int minor,
0347 void *arg
0348 )
0349 {
0350 uint32_t pMC68681_port;
0351 setRegister_f setReg;
0352
0353 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0354 setReg = Console_Port_Tbl[minor]->setRegister;
0355
0356
0357
0358
0359 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
0360 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
0361
0362 return(RTEMS_SUCCESSFUL);
0363 }
0364
0365
0366
0367
0368
0369
0370
0371 MC68681_STATIC void mc68681_write_polled(
0372 int minor,
0373 char cChar
0374 )
0375 {
0376 uint32_t pMC68681_port;
0377 unsigned char ucLineStatus;
0378 int iTimeout;
0379 getRegister_f getReg;
0380 setRegister_f setReg;
0381
0382 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0383 getReg = Console_Port_Tbl[minor]->getRegister;
0384 setReg = Console_Port_Tbl[minor]->setRegister;
0385
0386
0387
0388
0389 iTimeout = 1000;
0390 ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
0391 while ((ucLineStatus & (MC68681_TX_READY|MC68681_TX_EMPTY)) == 0) {
0392
0393 if ((ucLineStatus & 0xF0))
0394 (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
0395
0396
0397
0398
0399
0400 #if 0
0401 if(_System_state_Is_up(_System_state_Get())) {
0402 rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
0403 }
0404 #endif
0405 ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
0406 if(!--iTimeout) {
0407 break;
0408 }
0409 }
0410
0411
0412
0413
0414
0415 (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar);
0416 }
0417
0418
0419
0420
0421
0422
0423
0424
0425 MC68681_STATIC rtems_isr mc68681_isr(
0426 rtems_vector_number vector
0427 )
0428 {
0429 int minor;
0430
0431 for(minor=0 ; minor<Console_Port_Count ; minor++) {
0432 if(Console_Port_Tbl[minor]->ulIntVector == vector &&
0433 Console_Port_Tbl[minor]->deviceType == SERIAL_MC68681 ) {
0434 mc68681_process(minor);
0435 }
0436 }
0437 }
0438
0439
0440
0441
0442
0443
0444
0445
0446 MC68681_STATIC void mc68681_initialize_interrupts(int minor)
0447 {
0448 mc68681_init(minor);
0449
0450 Console_Port_Data[minor].bActive = FALSE;
0451
0452 #if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE)
0453 set_vector(mc68681_isr, Console_Port_Tbl[minor]->ulIntVector, 1);
0454 #endif
0455
0456 mc68681_enable_interrupts(minor,MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
0457 }
0458
0459
0460
0461
0462
0463
0464
0465 MC68681_STATIC ssize_t mc68681_write_support_int(
0466 int minor,
0467 const char *buf,
0468 size_t len
0469 )
0470 {
0471 uint32_t Irql;
0472 uint32_t pMC68681_port;
0473 setRegister_f setReg;
0474
0475 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0476 setReg = Console_Port_Tbl[minor]->setRegister;
0477
0478
0479
0480
0481
0482
0483 if ( !len )
0484 return 0;
0485
0486
0487
0488
0489
0490 rtems_interrupt_disable(Irql);
0491 if ( Console_Port_Data[minor].bActive == FALSE ) {
0492 Console_Port_Data[minor].bActive = TRUE;
0493 mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL);
0494 }
0495 (*setReg)(pMC68681_port, MC68681_TX_BUFFER, *buf);
0496 rtems_interrupt_enable(Irql);
0497
0498 return 0;
0499 }
0500
0501
0502
0503
0504
0505
0506
0507
0508 MC68681_STATIC ssize_t mc68681_write_support_polled(
0509 int minor,
0510 const char *buf,
0511 size_t len
0512 )
0513 {
0514 int nwrite = 0;
0515
0516
0517
0518
0519 while (nwrite < len) {
0520
0521
0522
0523 mc68681_write_polled(minor, *buf++);
0524 nwrite++;
0525 }
0526
0527
0528
0529
0530 return nwrite;
0531 }
0532
0533
0534
0535
0536
0537
0538
0539 MC68681_STATIC int mc68681_inbyte_nonblocking_polled(
0540 int minor
0541 )
0542 {
0543 uint32_t pMC68681_port;
0544 unsigned char ucLineStatus;
0545 unsigned char cChar;
0546 getRegister_f getReg;
0547
0548 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0549 getReg = Console_Port_Tbl[minor]->getRegister;
0550
0551 ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
0552 if(ucLineStatus & MC68681_RX_READY) {
0553 cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
0554 return (int)cChar;
0555 } else {
0556 return -1;
0557 }
0558 }
0559
0560
0561
0562
0563
0564 MC68681_STATIC int mc68681_baud_rate(
0565 int minor,
0566 int baud,
0567 unsigned int *baud_mask_p,
0568 unsigned int *acr_bit_p,
0569 unsigned int *command
0570 )
0571 {
0572 unsigned int baud_mask;
0573 unsigned int acr_bit;
0574 int status;
0575 int is_extended;
0576 int baud_requested;
0577 mc68681_baud_table_t *baud_tbl;
0578
0579 baud_mask = 0;
0580 acr_bit = 0;
0581 status = 0;
0582
0583 if (Console_Port_Tbl[minor]->ulDataPort & MC68681_DATA_BAUD_RATE_SET_2)
0584 {
0585 acr_bit = 1;
0586 }
0587
0588 is_extended = 0;
0589
0590 switch (Console_Port_Tbl[minor]->ulDataPort & MC68681_XBRG_MASK) {
0591 case MC68681_XBRG_IGNORED:
0592 *command = 0x00;
0593 break;
0594 case MC68681_XBRG_ENABLED:
0595 *command = 0x80;
0596 is_extended = 1;
0597 break;
0598 case MC68681_XBRG_DISABLED:
0599 *command = 0x90;
0600 break;
0601 }
0602
0603 baud_requested = baud;
0604 if (!baud_requested)
0605 baud_requested = B9600;
0606
0607 baud_requested = rtems_termios_baud_to_index( baud_requested );
0608 if (baud_requested == -1)
0609 return -1;
0610
0611 baud_tbl = (mc68681_baud_table_t *)
0612 ((uintptr_t)Console_Port_Tbl[minor]->ulClock);
0613 if (!baud_tbl)
0614 rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS);
0615
0616 if ( is_extended )
0617 baud_mask = (unsigned int)baud_tbl[ acr_bit + 2 ][ baud_requested ];
0618 else
0619 baud_mask = baud_tbl[ acr_bit ][ baud_requested ];
0620
0621 if ( baud_mask == MC68681_BAUD_NOT_VALID )
0622 status = -1;
0623
0624
0625
0626
0627
0628 *baud_mask_p = (baud_mask << 4) | baud_mask;
0629 *acr_bit_p = acr_bit;
0630 return status;
0631 }
0632
0633
0634
0635
0636
0637
0638
0639 MC68681_STATIC void mc68681_process(
0640 int minor
0641 )
0642 {
0643 uint32_t pMC68681;
0644 uint32_t pMC68681_port;
0645 volatile uint8_t ucLineStatus;
0646 volatile uint8_t ucISRStatus;
0647 char cChar;
0648 getRegister_f getReg;
0649
0650 pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
0651 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0652 getReg = Console_Port_Tbl[minor]->getRegister;
0653
0654
0655 ucISRStatus = (*getReg)(pMC68681, MC68681_INTERRUPT_STATUS_REG);
0656
0657
0658 if (pMC68681 != pMC68681_port){
0659 ucISRStatus >>= 4;
0660 }
0661
0662
0663 if(Console_Port_Data[minor].bActive == FALSE) {
0664 ucISRStatus = ucISRStatus & ~MC68681_IR_TX_READY;
0665 }
0666
0667
0668
0669
0670 while(true) {
0671 ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
0672 if(!(ucLineStatus & MC68681_RX_READY)) {
0673 break;
0674 }
0675
0676
0677
0678 if ( ucLineStatus & MC68681_RX_ERRORS ) {
0679 do {
0680 cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
0681 ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
0682 } while ( ucLineStatus & MC68681_RX_READY );
0683 continue;
0684 }
0685 cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
0686 rtems_termios_enqueue_raw_characters(
0687 Console_Port_Data[minor].termios_data,
0688 &cChar,
0689 1
0690 );
0691 }
0692
0693
0694
0695
0696
0697 if (ucISRStatus & MC68681_IR_TX_READY) {
0698 if (!rtems_termios_dequeue_characters(
0699 Console_Port_Data[minor].termios_data, 1)) {
0700
0701 Console_Port_Data[minor].bActive = FALSE;
0702 mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
0703 }
0704 }
0705 }
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715 MC68681_STATIC unsigned int mc68681_build_imr(
0716 int minor,
0717 int enable_flag
0718 )
0719 {
0720 int mate;
0721 int is_a;
0722 unsigned int mask;
0723 unsigned int mate_mask;
0724 unsigned int pMC68681;
0725 unsigned int pMC68681_port;
0726 mc68681_context *pmc68681Context;
0727 mc68681_context *mateContext;
0728
0729 pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
0730 pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
0731 pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
0732 mate = pmc68681Context->mate;
0733
0734 mask = 0;
0735 mate_mask = 0;
0736
0737 is_a = (pMC68681 == pMC68681_port);
0738
0739
0740
0741
0742
0743 if ( mate != -1 ) {
0744 mateContext = Console_Port_Data[mate].pDeviceContext;
0745
0746 if (mateContext)
0747 mate_mask = mateContext->imr;
0748 }
0749
0750
0751
0752
0753
0754 if ( Console_Port_Tbl[minor]->pDeviceFns->deviceOutputUsesInterrupts )
0755 mask = enable_flag;
0756
0757 pmc68681Context->imr = mask;
0758
0759
0760
0761
0762
0763 if (is_a)
0764 return (mate_mask << 4) | mask;
0765
0766 return (mask << 4) | mate_mask;
0767 }
0768
0769
0770
0771
0772
0773
0774
0775 MC68681_STATIC void mc68681_enable_interrupts(
0776 int minor,
0777 int imr_mask
0778 )
0779 {
0780 uint32_t pMC68681;
0781 setRegister_f setReg;
0782
0783 pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
0784 setReg = Console_Port_Tbl[minor]->setRegister;
0785
0786
0787
0788
0789
0790 (*setReg)(
0791 pMC68681,
0792 MC68681_INTERRUPT_MASK_REG,
0793 mc68681_build_imr(minor, imr_mask)
0794 );
0795 }