home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / COMM / MISC / SRC26_2.ZIP / SRC / PORT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-04  |  18.7 KB  |  864 lines

  1. /*
  2.  * port.c: hterm serial port control
  3.  *
  4.  * Author: HIRANO Satoshi
  5.  * (C) 1989  Halca Computer Science Laboratory TM
  6.  *           University of Tokyo
  7.  *
  8.  * 2.2 89/05/16 Halca.Hirano V2.2 distribution
  9.  * 2.3 89/06/17 Halca.Hirano remove #else
  10.  *    set 8251 from port98.asm
  11.  * 2.4 89/07/20 Halca.Hirano add sending kanji conversion (Thank you ohta@ricoh)
  12.  * 2.5 89/07/26 Halca.Hirano add 7 bit space parity
  13.  * 2.6 89/07/28 Halca.Hirano support multiple port
  14.  *    ---- V2.3.-1 distribution ----
  15.  * 2.7 89/09/15 Halca.Hirano fix upload kanji bug, add RTS/CTS flow control
  16.  *    ---- V2.4.0 distribution ----
  17.  * 2.8 89/11/30 mik@uop    add NEC kanji code
  18.  * 2.9 89/11/30 Halca.Hirano send kanji in/out code only at code changing timing
  19.  * 3.0 89/12/06 Halca.Hirano drop ER/RS if requested at exit
  20.  * 3.1 90/06/24 Halca.Hirano change GetCPUClock smater
  21.  * 3.2 90/06/27 Halca.Hirano 
  22.  * I use 0x22 rather than 0xaa for reseting of i8251 
  23.  * before issue reset command on PC98 machines to avoid 
  24.  * generating illegal output character.
  25.  *
  26.  *    $Header: port.cv  1.12  90/07/04 01:04:50  hirano  Exp $
  27.  */
  28.  
  29. #include "option.h"
  30. #include <stdio.h>
  31. #include "config.h"
  32. #include "hterm.h"
  33. #include "default.h"
  34. #include "global.h"
  35.  
  36. #ifdef PC98
  37. static u_char CPUClock;            /* PC9801 CPU clock, it takes 8 or 10 (MHz) */
  38. #endif /* PC98 */
  39. static u_char oldMask;            /* original interrupt mask    */
  40. static int oldPortNo;
  41. u_char    onMask;                    /* receive on interrupt mask    */
  42. u_char    offMask;                /* receive off interrupt mask    */
  43. u_short    portAddress;            /* port address                */
  44. bool    sendingKanji;            /* sending kanji flag        */
  45. void (INTERRUPT FAR *interruptHandler)();/* hterm interrupt handler    */
  46. void (INTERRUPT FAR *oldHandler)();    /* original interrupt handler    */
  47.  
  48. /*
  49.  * serial port device address and vectors
  50.  */
  51. struct {
  52.     u_short address;        /* port address        */
  53.     u_short vector;            /* vector number    */
  54.     u_char    mask;            /* IMR mask value    */
  55. } portInfo[] = 
  56.     {{ADDR_PORT_COM1, PORT_VECTOR_COM1, INT_MASK_COM1},
  57.      {ADDR_PORT_COM2, PORT_VECTOR_COM2, INT_MASK_COM2},
  58.      {ADDR_PORT_COM3, PORT_VECTOR_COM3, INT_MASK_COM3},
  59.      {ADDR_PORT_COM4, PORT_VECTOR_COM4, INT_MASK_COM4}};
  60.  
  61. /*
  62.  * baudrate to internal baudrate expression conversion table
  63.  */
  64. struct s_baudtable {
  65.     u_short Baud, Num;
  66. } baudtable[BAUD_NUM_MAX+1] = {
  67.     {300, 1},  {1200, 2}, {2400, 3}, {4800, 4}, {9600, 5}, 
  68.     {19200, 6}, {38400, 7}, {0, 0}};
  69.  
  70. #if defined IBMPC || defined J3100
  71. /*
  72.  * IBMPC parity/stop bit register masks
  73.  */
  74. struct {
  75.     u_char parity;        /* hardware register bits    */
  76.     u_char mask;        /* character mask bits        */
  77. } parityTable[] = {
  78.     /* NO_PAR_8 */ {0x03, 0xff},
  79.     /* EV_PAR_8 */ {0x1b, 0xff},
  80.     /* NO_PAR_7 */ {0x02, 0x7f},
  81.     /* EV_PAR_7 */ {0x1a, 0x7f},
  82.     /* SP_PAR_7 */ {0x03, 0x7f}};
  83. #endif /* IBMPC || J3100 */
  84.  
  85. #ifdef PC98
  86. /*
  87.  * PC9801 baudrate to timer load value table for 10Mhz machine
  88.  */
  89. u_short baudToTimer5Mhz10Mhz[BAUD_NUM_MAX] = 
  90.     /* 300  1200  2400  4800  9600 19200 38400 */
  91.     {0x80,  0x20, 0x10, 0x20, 0x10, 0x8, 0x4};
  92. /*
  93.  * PC9801 baudrate to timer load value table for 10Mhz machine
  94.  * we can use up to 9600 baud on 8/12 MHz machine 
  95.  */
  96. u_short baudToTimer8Mhz12Mhz[BAUD_NUM_MAX] = 
  97.     /* 300  1200  2400  4800  9600 19200 38400 */
  98.     {0x68,  0x1a, 0x0d, 0x1a, 0x0d, 0x0d, 0x0d};
  99.  
  100. /*
  101.  * PC9801 parity/stop bit register masks
  102.  */
  103. struct {
  104.     u_char parity;        /* hardware register bits    */
  105.     u_char mask;        /* character mask bits        */
  106. } parityTable[] = {
  107.     /* NO_PAR_8 */ {0x0c, 0xff},
  108.     /* EV_PAR_8 */ {0x3c, 0xff},
  109.     /* NO_PAR_7 */ {0x08, 0x7f},
  110.     /* EV_PAR_7 */ {0x38, 0x7f},
  111.     /* SP_PAR_7 */ {0x0c, 0x7f}};
  112. #endif
  113.  
  114.  
  115. void outPortC(unsigned char c);
  116. void getCPUClock(void);
  117.  
  118. /*
  119. ** void portInit()
  120.  *
  121.  * initialize port device variables and hardware
  122.  */
  123. void portInit()
  124. {
  125.     baudrate = DEFAULT_BAUDRATE;
  126.     xonXoff = DEFAULT_FLOWCTRL;
  127.     paritybit = DEFAULT_PARITY;
  128.     stopbit    = DEFAULT_STOP_BIT;
  129.     oldPortNo = portNo = DEFAULT_PORT_NO;
  130.     dropER = DEFAULT_KEEP_DROP_LINE;
  131.     online = YES;            /* online                    */
  132.     downLoading = NO;        /* no down load mode         */
  133.     maskFlag = NO;            /* no mask mode                */
  134.     sendingKanji = NO;        /* sending ascii            */
  135.     cMask = 0xff;            /* mask 0xff in/out chars    */
  136.     oldHandler = 0;
  137. #ifdef PC98
  138.     getCPUClock();            /* get CPU clock            */
  139. #endif
  140.     portReInit();
  141. }
  142.  
  143. /*
  144. ** void portReInit()
  145.  *
  146.  * re-initialize interrupt vector and hardware
  147.  *
  148.  * NOTE: This function should be called after portEnd()
  149.  */
  150. void portReInit()
  151. {
  152.     oldMask = inpWait(IMR);
  153.     initPortBuffer();        /* iniz port buffer        */
  154.     interruptHandler = getPortInterruptHandlerAddress();
  155.     oldHandler = GET_DOSVECT(portInfo[portNo].vector);
  156. }
  157.  
  158. /*
  159. ** void portSetup()
  160.  *
  161.  * re-initialize hardware (parity etc.) as user's preference
  162.  */
  163. void portSetup()
  164. {
  165.     maskFlag = NO;            /* clear XOffed flag        */
  166.     kstate = 0;                /* kanji state 0        */
  167.     sendingKanji = NO;        /* not sending kanji        */
  168.  
  169. retry:
  170.     if ((baud = baudNum(baudrate)) == -1) {    /* calc baudrate    */
  171.         sprintf(tmpBuf, msg_baudrate, (long)baudrate);
  172.         conPrint(tmpBuf);
  173.         conPrint("set to 9600\r\n");
  174. #ifdef PC98
  175.         conPrint(msg_pc98baud);
  176. #endif /* PC98 */
  177.         baudrate = 9600;
  178.         goto retry;
  179.     }
  180.     parity = parcalc(paritybit, stopbit); /* set parity        */
  181.     setPort(portNo);        /* set port number and address    */
  182. }
  183.  
  184. /*
  185. ** void portEnd()
  186.  *
  187.  * de-initialize port device; restore vector, restore interrupt mask
  188.  */
  189. void portEnd()
  190. {
  191.     outpWait(IMR, oldMask);
  192.     if (oldHandler)
  193.         SET_DOSVECT(portInfo[portNo].vector, oldHandler);
  194.     oldHandler = 0;
  195. }
  196.  
  197. /*
  198. ** void outPort(c)
  199.  *
  200.  * send a char to the remote system with kanji conversion
  201.  *
  202.  * in: 
  203.  *    c    word to send
  204.  *            if kanji, xxyy
  205.  *            else 00xx
  206.  *    NOTE:    xx00 should never come here!
  207.  */
  208. void outPort(c)
  209. register u_short c;
  210. {
  211.     register u_char cu, cl;
  212.  
  213.     if (downLoading) {
  214.         outPortC(c);
  215.         return;
  216.     }
  217.  
  218. #ifdef KANJI
  219.     cu = c >> 8; cl = c & 0xff;
  220.     if (!cu) {
  221.         /*
  222.          * if not kanji
  223.          */
  224.         if (sendingKanji) {
  225.             /*
  226.              * send 'end of kanji' code
  227.              */
  228.             sendingKanji = NO;
  229.             switch (kanjiCode) {
  230.             case OJIS:
  231.             case NJIS:
  232.                 outPortC(ESC); outPortC('('); outPortC('J');
  233.                 break;
  234. #ifdef NEC_KANJI
  235.             case NECKANJI:
  236.                 outPortC(SUB); outPortC('q');
  237.                 break;
  238. #endif /* NEC_KANJI */
  239.             }
  240.         }
  241.         if (isKana(cl)) {
  242.             /*
  243.              * if hankaku kana
  244.              */
  245.             switch (kanjiCode) {
  246.             case SJIS:
  247.                 break;
  248.             case OJIS:
  249.             case NJIS:
  250. #ifdef NEC_KANJI
  251.             case NECKANJI:
  252. #endif /* NEC_KANJI */
  253.                 outPortC(SO);
  254.                 outPortC(c & 0x7f);
  255.                 cl = SI;
  256.                 break;
  257.             case EUC:
  258.                 outPortC(SS2);
  259.                 break;
  260.             }
  261.             /* kana second char is out by next outPortC() */
  262.         }
  263.         outPortC(cl);        /* else ASCII */
  264.         return;
  265.     }
  266.     /*
  267.      * kanji
  268.      */
  269.     if (sendingKanji == NO) {
  270.         /*
  271.          * send kanji in code
  272.          */
  273.         sendingKanji = YES;
  274.         switch (kanjiCode) {
  275.         case OJIS:
  276.         case NJIS:
  277.             outPortC(ESC); outPortC('$');
  278.             outPortC(kanjiCode == NJIS ? 'B': '@');
  279.             break;
  280. #ifdef NEC_KANJI
  281.         case NECKANJI:
  282.             outPortC(SUB); outPortC('p');
  283.             break;
  284. #endif /* NEC_KANJI */
  285.         }
  286.     }
  287.     /*
  288.      * send kanji body
  289.      */
  290.     switch (kanjiCode) {
  291.     case SJIS:
  292.         c = JIStoSJIS(cu, cl);
  293.         outPortC(c >> 8);
  294.         outPortC(c);
  295.         break;
  296.     case OJIS:
  297.     case NJIS:
  298. #ifdef NEC_KANJI
  299.     case NECKANJI:
  300. #endif /* NEC_KANJI */        
  301.         outPortC((c >> 8) & 0x7f);
  302.         outPortC(c & 0x7f);
  303.         break;
  304.     case EUC:
  305.         outPortC(cu | 0x80);
  306.         outPortC(cl | 0x80);
  307.         break;
  308.     }
  309. #else
  310.     outPortC(c);
  311. #endif /* KANJI */
  312. }
  313.  
  314. /*
  315. ** static void outPortC(c)
  316.  *
  317.  * send a byte to host with newline, echo back control
  318.  */
  319. static void outPortC(c)
  320. u_char c;
  321. {
  322.     if (online) {
  323.         rowOutPort(c & cMask);
  324.         if (!downLoading && newline && c == CR)
  325.             rowOutPort(LF);
  326.     }
  327.     if (echoMode || !online)
  328.         decodeAnsi(c);
  329. }
  330.  
  331. /*
  332. ** void rowOutPort(c)
  333.  *
  334.  * lowest level send a char to host with time out without code conversion
  335.  */
  336. void rowOutPort(c)
  337. u_char c;
  338. {
  339.     register u_char status;
  340.  
  341.     portTimer = timerLoadValue;
  342.     while (timerLoadValue - portTimer < TX_TIMEOUT) {
  343.         status = inpWait(portAddress+RS_STATUS);
  344.         if ((status & TX_READY) == TX_READY) {
  345.             outp(portAddress+RS_DATA, c);
  346.             return;
  347.         }
  348.         /* CAUTION!
  349.          * MSC5.1 is brain damaged for volatile variable treatment.
  350.          * timerValue is volatile. but optimizer eliminates
  351.          * condition check of while statement.
  352.          */
  353.         nullFunction();
  354.     }
  355.     conPrint("\n\rTransmit time out (CS low)\n\r");
  356. }    
  357.  
  358. /*
  359. ** void outString(char *s)
  360.  *
  361.  * send string to the remote system
  362.  */        
  363. void outString(s)
  364. register char *s;
  365. {
  366.     while (*s)
  367.         outPort(*s++);
  368. }
  369.  
  370. /*
  371. ** void rowOutPortBuffer(char *buf, int len)
  372.  *
  373.  * send buffer to the remote system
  374.  */
  375. void rowOutPortBuffer(buf, len)
  376. char    *buf;
  377. int    len;
  378. {
  379.     register int    bp;
  380.  
  381.     for (bp = 0; bp < len; bp++)
  382.         rowOutPort(buf[bp] & cMask);
  383. }
  384.  
  385. /*
  386. ** void outESC(char *s)
  387.  *
  388.  * output escape sequence
  389.  */
  390. void outESC(s)
  391. char *s;
  392. {
  393.     outPort(ESC);
  394.     outString(s);
  395. }
  396.  
  397. /*
  398. ** int baudNum(register u_short baudrate)
  399.  *
  400.  * calc from baudrate to internal number 
  401.  */
  402. int baudNum(baudrate)
  403. register u_short baudrate;
  404. {
  405.     register struct s_baudtable *p;
  406.  
  407. #ifdef PC98
  408.     getCPUClock();        /* this is needed for call from options() */
  409. #endif
  410.     if (baudrate == 0) 
  411.         return(-1);
  412. #ifdef PC98
  413.     if (CPUClock == 8 && baudrate > 9600)
  414.         return(-1);    /* we can use up to 9600 baud with 8/16Mhz clock machine */
  415. #endif /* PC98 */
  416.     for (p = baudtable; p -> Baud != 0; p++)
  417.         if (p -> Baud == baudrate) return(p -> Num);
  418.     return(-1);
  419. }
  420.  
  421. /*
  422. ** u_short numBaud(num)
  423.  *
  424.  * calc from internal number to baudrate 
  425.  */
  426. u_short numBaud(num)
  427. register unsigned int num;
  428. {
  429.     register struct s_baudtable *p;
  430.  
  431.     if (num == 0) 
  432.         return(0);
  433. #ifdef PC98
  434.     if (CPUClock == 8 && num > 5)
  435.         return(0);    /* we can use up to 9600 baud with 8/16Mhz clock machine */
  436. #endif /* PC98 */
  437.     for (p = baudtable; p -> Baud != 0; p++)
  438.         if (p -> Num == num) return(p -> Baud);
  439.     return(0);
  440. }
  441.  
  442. /*
  443. ** void setPort(num)
  444.  *
  445.  * switch port; set port address from number 'num'
  446.  */
  447. void setPort(num)
  448. int num;
  449. {
  450.     if (num > MAX_PORT)
  451.         return;
  452.     portNo = num;
  453.     portAddress = portInfo[portNo].address;
  454.     /*
  455.      * restore old vector and mask
  456.      */
  457.     outpWait(IMR, oldMask);            /* mask (really?) old port    */
  458.     SET_DOSVECT(portInfo[oldPortNo].vector, oldHandler);
  459.     /*
  460.      * get new port vector and mask
  461.      */
  462.     oldMask = inpWait(IMR);
  463.     oldHandler = GET_DOSVECT(portInfo[portNo].vector);
  464.     /*
  465.      * set new vector
  466.      */
  467.     onMask = ~portInfo[portNo].mask;    /* for interrupt handler    */
  468.     offMask = portInfo[portNo].mask;    /* for interrupt handler    */
  469.     outpWait(IMR, oldMask | offMask);        /* disable interrupt        */
  470.     SET_DOSVECT(portInfo[portNo].vector, interruptHandler);
  471.     /*
  472.      * re-initialize device
  473.      */
  474.     initPortDevice(baud, parity);    /* iniz baudrate and parity    */
  475.     oldPortNo = portNo;
  476. }
  477.  
  478. /*
  479. ** void flushInputBuffer
  480.  *
  481.  * clear input buffer
  482.  */
  483. void flushInputBuffer()
  484. {
  485.     while (getSerial() != -1)
  486.         ;
  487. }
  488.  
  489. /*
  490. ** void shortWait()
  491.  *
  492.  * do nothing but wait for a while
  493.  */
  494. void shortWait()
  495. {
  496.     nullFunction();
  497.     nullFunction();
  498. }
  499.  
  500. /*
  501. ** void nullFunction()
  502.  *
  503.  * do nothing but wait for a while
  504.  * don't remove this; this function is used for null loop 
  505.  */
  506. void nullFunction()
  507. {
  508. }
  509.  
  510. /*
  511. ** int inpWait(addr)
  512.  *
  513.  * I/O input with wait
  514.  */
  515. int inpWait(addr)
  516. u_short addr;
  517. {
  518.     int x;
  519.  
  520.     x = inp(addr);
  521.     shortWait();
  522.     return(x);
  523. }
  524.  
  525. /*
  526. ** void outpWait(addr, value)
  527.  *
  528.  * I/O output with wait
  529.  */
  530. void outpWait(addr, value)
  531. u_short addr;
  532. int value;
  533. {
  534.     outp(addr,value);
  535.     shortWait();
  536. }
  537.  
  538. #ifdef KANJI
  539. /*
  540. ** u_short SJIStoJIS(byte_1, byte_2)
  541.  *
  542.  * convert SJIS to JIS
  543.  */
  544. u_short SJIStoJIS(byte_1, byte_2)
  545. register u_short byte_1, byte_2;
  546. {
  547.     u_short c;
  548.  
  549.     byte_1 -= (byte_1 >= 0xa0) ? 0xc1 : 0x81;
  550.     if (byte_2 >= 0x9f) {
  551.         c = (byte_1 << 9) + 0x2200;
  552.         c |= byte_2 - 0x7e;
  553.     } else {
  554.         c = (byte_1 << 9) + 0x2100;
  555.         c |= byte_2 - ((byte_2 <= 0x7e) ? 0x1f : 0x20);
  556.     }
  557.     return(c);
  558. }
  559.  
  560. /*
  561. ** u_short JIStoSJIS(h, l)
  562.  *
  563.  * convert JIS to SJIS
  564.  */
  565. u_short JIStoSJIS(h, l)
  566. register u_char h, l;
  567. {
  568.     if (!(h & 1)) l += (0x7f - 0x21);
  569.     l += (0x40 - 0x21);
  570.     if (l >= 0x7f) ++l;
  571.     h -= 0x21;
  572.     h >>= 1;        /*    h /= 2; */
  573.     h += 0x81;
  574.     if (h > 0x9f) h += (0xe0 - 0xa0);
  575.     return((h<<8)|l);
  576. }
  577.  
  578. #endif /* KANJI */
  579.  
  580. /*
  581.  *
  582. ** machine dependent part
  583.  *
  584.  */
  585.  
  586. #if defined IBMPC || defined J3100
  587. /*
  588. ** u_char parcalc(paritybit, stopbit)
  589.  *
  590.  * calclate parity bit register mask from parity and stop bit
  591.  */
  592. u_char parcalc(paritybit, stopbit)
  593. u_char paritybit, stopbit;
  594. {
  595.     register u_char parity = 0;
  596.  
  597.     parity = parityTable[paritybit].parity;
  598.     cMask = parityTable[paritybit].mask;
  599.     switch (stopbit) {
  600.     case STOP_BIT_1: parity |= 0x00; break;    /* 1 stop bit        */
  601.     case STOP_BIT_2: parity |= 0x04; break;    /* 2 stop bit        */
  602.     }
  603.     return(parity);
  604. }
  605.  
  606. /*
  607. ** void initPortDevice(baud, parity)
  608.  *
  609.  * iniz hardware baudrate and parity and assert RS/ER
  610.  */
  611. void initPortDevice(baud, parity)
  612. u_char baud, parity;
  613. {
  614.     u_short baudbit;
  615.  
  616.     spl7();
  617.     initPortBuffer();        /* iniz port buffer        */
  618.     /* If you don't want to change anything except baudrate & parity,
  619.      * int14 BIOS call isn't suitable in this case. 
  620.      * Because it inactivates the interrupt facility in UART.
  621.      */
  622. /*
  623.     baudbit = (u_short)(921600L/(u_long)(numBaud(baud)));
  624.     // 921600 stands for 14.7456MHz/16 //
  625. */
  626.     baudbit = (u_short)(115200L/(u_long)(numBaud(baud)));
  627.     /* 115200 stands for 1.8432MHz/16 */
  628.  
  629.     inpWait(portAddress+THR);    /* null read receive buffer register */
  630.     inpWait(portAddress+THR);    /* null read receive buffer register */
  631.     /* 
  632.      * You may set DLAB bit (0x80) of LCR register to modify dividing
  633.      * rate of UART. When the bit is set, you can access two 8 bit
  634.      * register whose address is the same as those of RSDAT or IIR
  635.      */
  636.     outpWait(portAddress+LCR, LCR_DLAB);/* set DLAB bit to store the div rate to UART */
  637.     outpWait(portAddress+DIVL, baudbit & 0xff);
  638.     outpWait(portAddress+DIVH, baudbit >> 8);
  639.     /* 
  640.      * the argument "parity" follows the same format as LCR register
  641.      */
  642.     outpWait(portAddress+LCR, parity);    /* reset DLAB bit & set modes    */
  643.     ER_RS_On();                        /* assert ER/RS                    */
  644.     outpWait(portAddress+IER, 1);    /* enable receive interrupt    */
  645.     /*
  646.      * enable interrupt
  647.      */
  648.     outpWait(IMR, inpWait(IMR) & onMask);
  649.     splx();
  650. }
  651.  
  652. /*
  653. ** void sendBreak(shortLong)
  654.  *
  655.  * send break code to the remote system
  656.  */
  657. void sendBreak(shortLong)
  658. int shortLong;
  659. {
  660.     int i, outer;
  661.  
  662.     outpWait(portAddress+LCR, parity | LCR_SBRK);/* assert break    */
  663.     /*
  664.      * we should wait for more one char when short break
  665.      * NOTE: this code is really ABOUT!
  666.      */
  667.     if (shortLong == 1)
  668.         outer = 2;        /* short 2 msec        */
  669.     else
  670.         outer = 100;        /* long 100 msec    */
  671.     for (; outer > 0; --outer)
  672.         for (i = 2000; i > 0; --i)    /* 1msec counter    */
  673.             nullFunction();
  674.     outpWait(portAddress+LCR, parity);    /* negate break        */
  675. }
  676.  
  677. /*
  678. ** void ER_RS_On()
  679.  *
  680.  * assert ER/RS line
  681.  */
  682. void ER_RS_On()
  683. {
  684.     outpWait(portAddress+MCR, 0x0b);    /* RS on (bit1), ER on (bit0)    */
  685. }
  686.  
  687. /*
  688. ** void ER_RS_Off()
  689.  *
  690.  * drop ER/RS line, disable input/output
  691.  */
  692. void ER_RS_Off()
  693. {
  694.     outpWait(portAddress+MCR, 0x08);    /* RS off (bit1), ER off (bit0)    */
  695. }
  696. #endif /* IBMPC || J3100 */
  697.  
  698. #ifdef PC98
  699. /*
  700. ** u_char parcalc(paritybit, stopbit)
  701.  *
  702.  * calclate parity bit register mask from parity and stop bit
  703.  */
  704. u_char parcalc(paritybit, stopbit)
  705. u_char paritybit, stopbit;
  706. {
  707.     register u_char parity = 3;
  708.  
  709.     parity |= parityTable[paritybit].parity;
  710.     cMask = parityTable[paritybit].mask;
  711.     switch (stopbit) {
  712.     case STOP_BIT_1: parity |= 0x40; break;    /* 1 stop bit        */
  713.     case STOP_BIT_2: parity |= 0xc0; break;    /* 2 stop bit        */
  714.     }
  715.     return(parity);
  716. }
  717.  
  718. /*
  719. ** void initPortDevice(baud, parity)
  720.  *
  721.  * iniz hardware baudrate and parity and assert RS/ER
  722.  */
  723. void initPortDevice(baud, parity)
  724. u_char baud, parity;
  725. {
  726.     u_char devider;
  727.     u_short baudTimer;
  728.     
  729.     spl7();
  730.     initPortBuffer();        /* iniz port buffer        */
  731.     if (CPUClock == 10)
  732.         baudTimer = baudToTimer5Mhz10Mhz[baud-1];
  733.     else
  734.         baudTimer = baudToTimer8Mhz12Mhz[baud-1];
  735.     devider = (baud >= 4) ? 0xfe : 0xff;
  736.                          /* x16    x32 */
  737.  
  738.     inpWait(portAddress+RS_DATA);    /* null read data receive register */
  739.     inpWait(portAddress+RS_DATA);    /* null read data receive register */
  740.     /* 
  741.      * set timer control word for serial 1
  742.      * counter #2, load, mode = 3, not BCD
  743.      */
  744.     outpWait(TIMER_MODE, 0xb6);
  745.     outpWait(TIMER_COUNTER2, baudTimer & 0xff);/* set counter #2    */
  746.     outpWait(TIMER_COUNTER2, baudTimer / 256);    /* set counter #2    */
  747.  
  748.     /*
  749.       * 8251 command/status register
  750.      * bit  comment
  751.      * ---- ------------
  752.      * 7    EnterHunt
  753.      * 6    Internal Reset
  754.      * 5    RTS
  755.      * 4    Error Reset
  756.      * 3    Send Break
  757.      * 2    Rx Enable
  758.      * 1    DTR
  759.      * 0    Tx Enable
  760.      *
  761.      * 8251 mode register
  762.      * bit    comment
  763.      * ---- ------------
  764.      * 76    stop bit
  765.      * 5    even parity
  766.      * 4    parity enable
  767.      * 32    charactor length
  768.      * 10    baud rate devider
  769.      */
  770.     /*
  771.      * reset i8251;
  772.      *     command register := 0x22 -> 0x40 -> parity
  773.      * While it is recommended to use 0xaa instead of 0x22 in manual,
  774.      * 0xaa generates illegal output character.
  775.      *
  776.      */
  777.     outpWait(portAddress+RS_STATUS, 0x22);    /* RS on, ER on, but RxTx disable    */
  778.     outpWait(portAddress+RS_STATUS, 0x40);        /* reset 8251            */
  779.     outpWait(portAddress+RS_STATUS, parity & devider);    /* set parity        */
  780.     ER_RS_On();                                /* assert ER, RTS, RxEnable, TxEnable */
  781.     /*
  782.      * set interrupt mask register
  783.      */
  784.     /*
  785.      * enable interrupt
  786.      */
  787.     outpWait(PORT_C, 1);        /* enable RxRdy interrupt for serial 1 */
  788.     outpWait(IMR, inpWait(IMR) & onMask);
  789.     splx();
  790. }
  791.  
  792. /*
  793. ** void sendBreak(shortLong)
  794.  *
  795.  * send break code to the remote system
  796.  */
  797. void sendBreak(shortLong)
  798. int shortLong;
  799. {
  800.     int i, outer;
  801.  
  802.     outpWait(portAddress+RS_STATUS, 0x3f);        /* assert break            */
  803.     /*
  804.      * we should wait for more one char when short break
  805.      * NOTE: this code is really ABOUT!
  806.      */
  807.     if (shortLong == 1)
  808.         outer = 2;        /* short 2 msec        */
  809.     else
  810.         outer = 100;        /* long 100 msec    */
  811.     for (; outer > 0; --outer)
  812.         for (i = 2000; i > 0; --i)    /* 1msec counter    */
  813.             nullFunction();
  814.     outpWait(portAddress+RS_STATUS, 0x37);        /* negate break        */
  815. }
  816.  
  817. /*
  818. ** void ER_RS_On()
  819.  *
  820.  * assert ER/RS line
  821.  */
  822. void ER_RS_On()
  823. {
  824.     /* RS off (bit5), ER off (bit1), Rx/Tx disable(bit 2,0)    */
  825.     outpWait(portAddress+RS_STATUS, 0x37);
  826. }
  827.  
  828. /*
  829. ** void ER_RS_Off()
  830.  *
  831.  * drop ER/RS line, disable input/output
  832.  */
  833. void ER_RS_Off()
  834. {
  835.     /* RS off (bit5), ER off (bit1), Rx/Tx disable(bit 2,0)    */
  836.     outpWait(portAddress+RS_STATUS, 0x00);    
  837. }
  838.  
  839. /*
  840. ** void getCPUClock()
  841.  *
  842.  * get PC9801 CPU clock int variable 'CPUClock'
  843.  */
  844. void getCPUClock()
  845. {
  846. #ifdef PC98XA
  847.     int c = peekMemory(0, CPU_CLOCK); /* get CPU clock    */
  848.     switch (c & 0xc0) {
  849.     case 0: case 1:
  850.         CPUClock = 10;        /* 10Mhz, 5MHz...    */
  851.     case 2: case 3:
  852.         CPUClock = 8;        /* 8Mhz, 12Mhz...    */
  853.     }
  854. #else
  855.     /* Thank you Nishimura@Giken    */
  856.     if (inp(PRINTER_PORT) & 0x20)
  857.         CPUClock = 8;
  858.     else
  859.         CPUClock = 10;
  860. #endif
  861. }
  862. #endif /* PC98 */
  863.  
  864.