1 /* RS232 Device Driver (2 channel v1.0).
\r
2 Next version adds flow control XON/XOFF & CTS/RTS */
\r
4 /* Copyright 1991,1992,1993,1994 R.A. Burgess */
\r
7 #define U32 unsigned long
\r
9 #define U16 unsigned int
\r
11 #define U8 unsigned char
\r
18 /* MMURTL OS Prototypes */
\r
20 extern far U32 AllocExch(U32 *pExchRet);
\r
22 extern far U32 InitDevDr(U32 dDevNum,
\r
27 extern far U32 AllocOSPage(U32 nPages, U8 **ppMemRet);
\r
28 extern far U32 DeAllocPage(U8 *pOrigMem, U32 nPages);
\r
30 extern far U32 UnMaskIRQ(U32 IRQNum);
\r
31 extern far U32 MaskIRQ(U32 IRQNum);
\r
32 extern far U32 SetIRQVector(U32 IRQNum, S8 *pIRQ);
\r
33 extern far U32 EndOfIRQ(U32 IRQNum);
\r
34 extern far U32 SendMsg(U32 Exch, U32 msg1, U32 msg2);
\r
35 extern far U32 ISendMsg(U32 Exch, U32 msg1, U32 msg2);
\r
36 extern far U32 WaitMsg(U32 Exch, S8 *pMsgRet);
\r
37 extern far U32 CheckMsg(U32 Exch, S8 *pMsgRet);
\r
38 extern far U32 GetTimerTick(U32 *pTickRet);
\r
39 extern far U32 Alarm(U32 Exch, U32 count);
\r
40 extern far U32 KillAlarm(U32 Exch);
\r
41 extern far U32 Sleep(U32 count);
\r
42 extern far void MicroDelay(U32 us15count);
\r
43 extern far void OutByte(U8 Byte, U16 wPort);
\r
44 extern far U8 InByte(U16 wPort);
\r
45 extern far void CopyData(U8 *pSource, U8 *pDestination, U32 dBytes);
\r
47 extern far long GetJobNum(long *pJobNumRet);
\r
49 /* local prototypes. These will be called form the device driver interface. */
\r
51 static U32 comdev_stat(U32 dDevice,
\r
56 static S32 comdev_init(U32 dDevice,
\r
60 static U32 comdev_op(U32 dDevice,
\r
67 #define CmdReadRec 1 /* Read one or more bytes */
\r
68 #define CmdWriteRec 2 /* Write one or more bytes */
\r
70 #define CmdOpenC 10 /* Open Comm Channel */
\r
71 #define CmdCloseC 11 /* Close Comm Channel */
\r
72 #define CmdDiscardRcv 12
\r
73 #define CmdSetRTO 13
\r
74 #define CmdSetXTO 14
\r
75 #define CmdSetDTR 15 /* Set DTR (On) */
\r
76 #define CmdSetRTS 16 /* Set CTS (On) */
\r
77 #define CmdReSetDTR 17 /* Set DTR (On) */
\r
78 #define CmdReSetRTS 18 /* Set CTS (On) */
\r
81 #define CmdGetDSR 21
\r
82 #define CmdGetCTS 22
\r
86 #define CmdWriteB 32
\r
88 /* The following definitions are used to identify, set
\r
89 and reset signal line condition and functions.
\r
92 #define CTS 0x10 /* Clear To Send */
\r
93 #define DSR 0x20 /* Data Set Ready */
\r
94 #define RI 0x40 /* Ring Indicator */
\r
95 #define CD 0x80 /* Carrier Detect */
\r
97 #define DTR 0x01 /* Data Terminal Ready */
\r
98 #define RTS 0x02 /* Request To Send */
\r
99 #define OUT2 0x08 /* Not used */
\r
101 /* Values from IIR register */
\r
103 #define MDMSTAT 0x00
\r
105 #define TXEMPTY 0x02
\r
106 #define RVCDATA 0x04
\r
107 #define RCVSTAT 0x06
\r
109 /* For errors returned from Comms calls see COMMDRV.H */
\r
111 #define SSENDBUF 4096 /* 1 Page Send Buf Default */
\r
112 #define SRECVBUF 4096 /* 1 Page Recv Buf Default */
\r
114 static U32 recv_timeout[2] = 1; /* 10ms intervals */
\r
115 static U32 xmit_timeout[2] = 10; /* 10ms intervals */
\r
117 /* variables for ISRs */
\r
119 static U8 f16550[2];
\r
120 static U8 stat_byte[2];
\r
121 static U8 mstat_byte[2];
\r
122 static U8 int_id[2];
\r
123 static U8 fExpectInt[2];
\r
125 static U32 recv_error[2]; /* NON-ZERO = an error has occurred */
\r
127 static U8 *pSendBuf[2]; /* pointers to Xmit bufs */
\r
128 static U32 head_send[2]; /* Next char to send */
\r
129 static U32 tail_send[2]; /* Where next char goes in buf */
\r
130 static U32 cSendBuf[2]; /* Count of bytes in buf */
\r
131 static U32 sSendBuf[2]; /* Size of buffer (allocated) */
\r
133 static U8 *pRecvBuf[2]; /* pointers to Recv bufs */
\r
134 static U32 head_recv[2]; /* Next char from chip */
\r
135 static U32 tail_recv[2]; /* Next char to read for caller */
\r
136 static U32 cRecvBuf[2]; /* Count of bytes in buf */
\r
137 static U32 sRecvBuf[2]; /* Size of buffer (allocated) */
\r
139 static U8 control_byte[2] = 0;
\r
141 /* array of registers from port base for each channel */
\r
143 static U16 THR[2]; /* Transmitter Holding Register */
\r
144 static U16 IER[2]; /* Interrupt Enable Register */
\r
145 static U16 IIR[2]; /* Interrupt Id Register */
\r
146 static U16 FCR[2]; /* FIFO control for 16550 */
\r
147 static U16 LCR[2]; /* Line Control Register */
\r
148 static U16 MCR[2]; /* Modem Control Register */
\r
149 static U16 LSR[2]; /* Line Status Register */
\r
150 static U16 MSR[2]; /* Modem Status Register */
\r
151 static U16 DLAB_LO[2]; /* same address as THR */
\r
152 static U16 DLAB_HI[2]; /* same address as IER */
\r
154 /* Complete description of Register bits follows:
\r
156 THR -- TX data, RX data, Divisor Latch LSB
\r
158 IER -- Interrupt Enable, Divisor Latch MSB
\r
161 | | | | | | | \_ Data Available
\r
162 | | | | | | \___ Xmit Holding Reg Empty
\r
163 | | | | | \_____ Receiver Line Status
\r
164 | | | | \_______ Modem Status
\r
165 \ _ _ _\_________ Always 0000
\r
167 IIR -- Interrupt Identification Register
\r
170 | | | | \_\_\_\__________ 0001 = no interrupt
\r
171 | | | | 0110 = rcvr status
\r
172 | | | | 0100 = rcvd data
\r
173 | | | | 0010 = THR empty
\r
174 | | | | 0000 = Modem status
\r
175 | | | | 1101 = Rcv Fifo Timeout (16550)
\r
176 | | | \_________ = 0.
\r
177 | | \___________ = 0.
\r
178 \ \_____________ = (16550 only)
\r
179 00 = FIFOs disabled
\r
180 non-zero = 16550 enabled
\r
182 FCR -- FIFO Control Register (16550 only)
\r
183 This is a write only port at the same
\r
184 address as the IIR on an 8250/16450
\r
187 | | | | | | | \__= 1 = FIFO Enable
\r
188 | | | | | | \___ = 1 = Recv FIFO Reset
\r
189 | | | | | \_____ = 1 = Xmit FIFO Reset
\r
190 | | | | \_______ = (DMA) 0 = Single char, 1 = Multichar
\r
191 | | | \_________ = 0.
\r
192 | | \___________ = 0.
\r
193 \__\_____________ = FIFO Rcv Trigger Level
\r
199 LCR -- Line Control Register
\r
202 | | | | | | | \_ Word Length Select Bit 0.
\r
203 | | | | | | \___ Word Length Select Bit 1.
\r
204 | | | | | \_____ Number Stop Bits (0=1, 1=2)
\r
205 | | | | \_______ Parity Enable
\r
206 | | | \_________ Even Parity Select
\r
207 | | \___________ Stick Parity
\r
208 | \_____________ Set Break
\r
209 \_______________ Divisor Latch Access Bit
\r
211 MCR -- Modem Control Register
\r
214 | | | | | | | \_ Data Terminal Ready
\r
215 | | | | | | \___ Request to Send
\r
216 | | | | | \_____ Out 1
\r
217 | | | | \_______ Out 2 (= 1 to enable ints.)
\r
218 | | | \_________ Loop
\r
219 \ _ _\___________ = Always 0
\r
221 LSR -- Line Status Register
\r
224 | | | | | | | \_ Data Ready
\r
225 | | | | | | \___ Overrun Error
\r
226 | | | | | \_____ Parity Error
\r
227 | | | | \_______ Framing Error
\r
228 | | | \_________ Break interrupt
\r
229 | | \___________ Transmitter Holding Reg Empty
\r
230 | \_____________ Transmitter Shift Reg Empty
\r
231 \_______________ Recv FIFO Error (16550 Only)
\r
233 MSR -- Modem Status Register
\r
236 | | | | | | | \_ Delta Clear to Send
\r
237 | | | | | | \___ Delta Data Set Ready
\r
238 | | | | | \_____ Trailing Edge Ring Indicator
\r
239 | | | | \_______ Delta Rx Line Signal Detect
\r
240 | | | \_________ Clear to Send
\r
241 | | \___________ Data Set Ready
\r
242 | \_____________ Ring Indicator
\r
243 \_______________ Receive Line Signal Detect
\r
248 /* Record for 64 byte status and init record */
\r
249 /* This structure is peculiar to the comms driver */
\r
253 static struct statRecC comstat[2];
\r
254 static struct statRecC *pCS;
\r
256 static struct dcbtype
\r
278 static struct dcbtype comdcb[2]; /* Two RS-232 ports */
\r
281 /* THE COMMS INTERRUPT FUNCTION PROTOTYPES */
\r
283 static void interrupt comISR0(void);
\r
284 static void interrupt comISR1(void);
\r
287 /*********************************************************
\r
288 This is called ONCE to initialize the 2 default
\r
289 comms channels with the OS device driver interface.
\r
290 It sets up defaults for both channels to 9600, 8N1.
\r
291 *********************************************************/
\r
293 U32 coms_setup(void)
\r
297 /* first we set up the 2 DCBs in anticipation of calling InitDevDr */
\r
299 comdcb[0].Name[0] = 'C';
\r
300 comdcb[0].Name[1] = 'O';
\r
301 comdcb[0].Name[2] = 'M';
\r
302 comdcb[0].Name[3] = '1';
\r
303 comdcb[0].sbName = 4;
\r
304 comdcb[0].type = 2; /* Sequential */
\r
305 comdcb[0].nBPB = 1; /* 1 byte per block */
\r
306 comdcb[0].nBlocks = 0; /* 0 for Sequential devices */
\r
307 comdcb[0].pDevOp = &comdev_op;
\r
308 comdcb[0].pDevInit = &comdev_init;
\r
309 comdcb[0].pDevSt = &comdev_stat;
\r
311 comdcb[1].Name[0] = 'C';
\r
312 comdcb[1].Name[1] = 'O';
\r
313 comdcb[1].Name[2] = 'M';
\r
314 comdcb[1].Name[3] = '2';
\r
315 comdcb[1].sbName = 4;
\r
316 comdcb[1].type = 2; /* Sequential */
\r
317 comdcb[1].nBPB = 1; /* 1 byte per block */
\r
318 comdcb[1].nBlocks = 0; /* 0 for Sequential devices */
\r
319 comdcb[1].pDevOp = &comdev_op;
\r
320 comdcb[1].pDevInit = &comdev_init;
\r
321 comdcb[1].pDevSt = &comdev_stat;
\r
323 /* Set default comms params in stat records */
\r
325 comstat[0].Baudrate = 9600;
\r
326 comstat[0].parity = 0; /* none */
\r
327 comstat[0].databits = 8;
\r
328 comstat[0].stopbits = 1;
\r
329 comstat[0].XTimeOut = 100;
\r
330 comstat[0].RTimeOut = 2;
\r
331 comstat[0].IOBase = 0x3F8;
\r
332 comstat[0].IRQNum = 4;
\r
333 comstat[0].XBufSize = 4096;
\r
334 comstat[0].RBufSize = 4096;
\r
335 sSendBuf[0] = 4096;
\r
336 sRecvBuf[0] = 4096;
\r
338 comstat[1].Baudrate = 9600;
\r
339 comstat[1].parity = 0; /* none */
\r
340 comstat[1].databits = 8;
\r
341 comstat[1].stopbits = 1;
\r
342 comstat[1].XTimeOut = 100;
\r
343 comstat[1].RTimeOut = 2;
\r
344 comstat[1].IOBase = 0x2F8;
\r
345 comstat[1].IRQNum = 3;
\r
346 comstat[1].XBufSize = 4096;
\r
347 comstat[1].RBufSize = 4096;
\r
348 sSendBuf[1] = 4096;
\r
349 sRecvBuf[1] = 4096;
\r
354 SetIRQVector(4, &comISR0); /* COM1 */
\r
355 SetIRQVector(3, &comISR1); /* COM2 */
\r
357 return(erc = InitDevDr(5, &comdcb, 2, 1));
\r
361 /*********************************************************
\r
362 This does the grunt work for each of the two ISRs
\r
363 This MUST remain reentrant for two ISRs.
\r
364 *********************************************************/
\r
366 static void handleISR(U32 i) /* i is the device */
\r
370 pRBuf = pRecvBuf[i];
\r
371 pXBuf = pSendBuf[i];
\r
375 int_id[i] = InByte (IIR[i]); /* Get ID Byte from IIR */
\r
376 switch (int_id[i])
\r
379 stat_byte[i] = InByte(LSR[i]); /* clear error conditions */
\r
383 if (cRecvBuf[i] == sRecvBuf[i])
\r
385 recv_error[i] = ErcRcvBufOvr; /* Do not put in buf */
\r
386 InByte (THR[i]); /* trash the byte */
\r
393 pRBuf[head_recv[i]] =
\r
394 InByte (THR[i]); /* Get the byte */
\r
396 if (++head_recv[i] == SRECVBUF)
\r
411 OutByte(pXBuf[tail_send[i]], THR[i]); /* Send the byte */
\r
412 if (++tail_send[i] == sSendBuf[i])
\r
415 fExpectInt[i] = TRUE;
\r
418 fExpectInt[i] = FALSE;
\r
425 mstat_byte[i] = InByte (MSR[i]); /* Get Modem Status */
\r
429 stat_byte[i] = InByte(LSR[i]); /* clear error conditions */
\r
437 static void interrupt comISR0(void)
\r
439 ; /* ; needed if asm is first in function */
\r
449 static void interrupt comISR1(void)
\r
451 ; /* ; needed if asm is first in function */
\r
460 /********************************************/
\r
463 static long ReadByteC(U32 device, unsigned char *pByteRet)
\r
468 pRBuf = pRecvBuf[device];
\r
469 if (recv_error[device]) return (recv_error[device]);
\r
471 if (cRecvBuf[device])
\r
473 *pByteRet = pRBuf[tail_recv[device]];
\r
474 if (++tail_recv[device] == sRecvBuf[device])
\r
475 tail_recv[device] = 0;
\r
476 --cRecvBuf[device];
\r
480 counter = comstat[device].RTimeOut; /* set up for timeout */
\r
484 if (cRecvBuf[device])
\r
486 *pByteRet = pRBuf[tail_recv[device]];
\r
487 if (++tail_recv[device] == sRecvBuf[device])
\r
488 tail_recv[device] = 0;
\r
489 --cRecvBuf[device];
\r
493 return (ErcRecvTimeout);
\r
496 /********************************************/
\r
499 static long ReadRecordC(U32 device,
\r
500 unsigned char *pDataRet,
\r
501 unsigned int sDataMax,
\r
502 unsigned int *pcbRet)
\r
508 while ((cb < sDataMax) && (!erc))
\r
510 erc = ReadByteC(device, pDataRet++);
\r
513 *pcbRet = cb; /* tell em how many bytes */
\r
519 /********************************************/
\r
520 static long WriteByteC(U32 device, unsigned char b)
\r
527 pXBuf = pSendBuf[device];
\r
528 counter = comstat[device].XTimeOut; /* set up for timeout */
\r
530 while (cSendBuf[device] == sSendBuf[device])
\r
535 return (ErcXmitTimeout); /* never got sent */
\r
542 if (!fExpectInt[device])
\r
543 { /* Xmit buf empty, send ourself */
\r
544 OutByte(b, THR[device]);
\r
545 fExpectInt[device] = TRUE;
\r
549 pXBuf[head_send[device]] = b;
\r
550 if (++head_send[device] == sSendBuf[device])
\r
551 head_send[device] = 0;
\r
552 ++cSendBuf[device]; /* one more in buf */
\r
561 /********************************************/
\r
562 static long WriteRecordC(U32 device,
\r
563 unsigned char *pSendData,
\r
564 unsigned int cbSendData)
\r
569 while ((cbSendData) && (!erc))
\r
571 erc = WriteByteC(device, *pSendData++);
\r
578 /********************************************/
\r
580 static long DiscardRecvC(U32 device)
\r
585 saveto = comstat[device].RTimeOut;
\r
586 comstat[device].RTimeOut = 1;
\r
589 erc = ReadByteC(device, &b);
\r
590 comstat[device].RTimeOut = saveto;
\r
596 /********************************************
\r
597 This sets comms params prior to opening, or
\r
598 while a channel is in use.
\r
599 ********************************************/
\r
601 static U32 SetParams(U32 device)
\r
604 U32 divisor, speed;
\r
605 U8 c, parity, bits, stop_bit, temp;
\r
607 parity = comstat[device].parity;
\r
608 bits = comstat[device].databits;
\r
609 stop_bit = comstat[device].stopbits;
\r
610 speed = comstat[device].Baudrate;
\r
612 /* Set up baud rate */
\r
614 divisor = 115200/speed;
\r
619 c=InByte (LCR[device]);
\r
620 OutByte ((c | 0x80), LCR[device]);
\r
621 OutByte ((divisor & 0x00ff), DLAB_LO[device]);
\r
622 OutByte (((divisor>>8) & 0x00ff), DLAB_HI[device]);
\r
623 OutByte (c, LCR[device]);
\r
628 /* set coms params */
\r
631 temp |= ((stop_bit == 1) ? 0x00 : 0x04);
\r
635 case NO_PAR : temp |= 0x00; break;
\r
636 case OD_PAR : temp |= 0x08; break;
\r
637 case EV_PAR : temp |= 0x18; break;
\r
643 OutByte (temp, LCR[device]);
\r
652 /********************************************
\r
653 This allocates buffers, sets up the ISR
\r
654 and IRQ values and open the channel for use.
\r
655 *********************************************/
\r
657 static U32 OpenCommC(U32 device)
\r
664 if (comstat[device].commJob)
\r
665 return(ErcChannelOpen);
\r
667 GetJobNum(&comstat[device].commJob);
\r
669 erc = AllocOSPage(comstat[device].XBufSize/4096,
\r
670 &pSendBuf[device]);
\r
674 erc = AllocOSPage(comstat[device].RBufSize/4096,
\r
675 &pRecvBuf[device]);
\r
677 if (erc) /* get rid of Xmit buf if we can't recv */
\r
678 DeAllocPage(pSendBuf[device],
\r
679 comstat[device].XBufSize/4096);
\r
684 comstat[device].commJob = 0;
\r
688 port_base = comstat[device].IOBase;
\r
690 /* Set up buffer variables for this port */
\r
692 cSendBuf[device] = 0;
\r
693 head_send[device] = 0;
\r
694 tail_send[device] = 0;
\r
696 cRecvBuf[device] = 0;
\r
697 head_recv[device] = 0;
\r
698 tail_recv[device] = 0;
\r
699 recv_error[device] = 0;
\r
702 THR[device] = port_base;
\r
703 IER[device] = port_base + 1;
\r
704 IIR[device] = port_base + 2;
\r
705 FCR[device] = port_base + 2;
\r
706 LCR[device] = port_base + 3;
\r
707 MCR[device] = port_base + 4;
\r
708 LSR[device] = port_base + 5;
\r
709 MSR[device] = port_base + 6;
\r
710 DLAB_HI[device] = port_base + 1;
\r
711 DLAB_LO[device] = port_base;
\r
713 InByte(THR[device]); /* reset any pending ints on chip */
\r
714 InByte(LSR[device]);
\r
719 control_byte[device] = RTS | DTR | OUT2;
\r
720 OutByte(control_byte[device], MCR[device]); /* Mod Ctrl Reg */
\r
721 OutByte(0x0F, IER[device]); /* Int Enable Reg */
\r
723 /* See if we have a 16550 and set it up if we do!! */
\r
725 OutByte(0x03, FCR[device]);
\r
726 c = InByte(IIR[device]);
\r
727 if (c & 0xC0) /* we have a 16550 and it's set to go! */
\r
728 f16550[device] = 1;
\r
730 f16550[device] = 0; /* 8250 or 16450 */
\r
738 UnMaskIRQ(comstat[device].IRQNum);
\r
742 /********************************************
\r
743 This closes the port, sets the owner to 0
\r
744 and deallocates the buffers.
\r
745 ********************************************/
\r
747 static int CloseCommC (U32 device)
\r
751 MaskIRQ(comstat[device].IRQNum);
\r
752 OutByte(0, MCR[device]);
\r
753 OutByte(0, IER[device]);
\r
754 erc = DeAllocPage(pSendBuf[device],
\r
755 comstat[device].XBufSize/4096);
\r
756 erc = DeAllocPage(pRecvBuf[device],
\r
757 comstat[device].RBufSize/4096);
\r
758 comstat[device].commJob = 0;
\r
762 /***************************************************************************
\r
763 Now begins the PUBLIC routines that are interfaced to for all DEVICE DRIVERS
\r
764 ****************************************************************************/
\r
766 /******************************************
\r
767 Called for all device operations. This
\r
768 assigns physical device from logical number
\r
769 that outside callers use. For RS-232, 5=0
\r
771 *******************************************/
\r
773 static U32 comdev_op(U32 dDevice,
\r
783 /* Set internal drive number */
\r
784 /* 5 RS-232 1 COM1 (OS built-in) */
\r
785 /* 6 RS-232 2 COM2 (OS built-in) */
\r
794 if ((!comstat[device].commJob) && (dOpNum != CmdOpenC))
\r
795 return(ErcNotOpen);
\r
797 if (comstat[device].commJob)
\r
799 if ((comstat[device].commJob != Job) &&
\r
801 return(ErcNotOwner);
\r
804 erc = 0; /* default error */
\r
810 break; /* Null Command */
\r
812 erc = ReadByteC(device, pData);
\r
815 erc = WriteByteC(device, *pData);
\r
818 erc = ReadRecordC(device, pData, dnBlocks,
\r
819 &comstat[device].LastTotal);
\r
822 erc = WriteRecordC(device, pData, dnBlocks);
\r
825 comstat[device].RTimeOut = dLBA; /* 10ms intervals */
\r
828 comstat[device].XTimeOut = dLBA; /* 10ms intervals */
\r
831 erc = OpenCommC(device);
\r
834 erc = CloseCommC(device);
\r
836 case CmdDiscardRcv:
\r
837 erc = DiscardRecvC(device);
\r
840 control_byte[device] |= DTR;
\r
841 OutByte(control_byte[device], LCR[device]);
\r
844 control_byte[device] |= RTS;
\r
845 OutByte(control_byte[device], MCR[device]);
\r
848 control_byte[device] &= ~DTR;
\r
849 OutByte(control_byte[device], LCR[device]);
\r
851 control_byte[device] &= ~RTS;
\r
852 OutByte(control_byte[device], MCR[device]);
\r
855 c = InByte(LCR[device]);
\r
856 OutByte((c | 0x40), LCR[device]);
\r
858 OutByte(c, LCR[device]);
\r
861 *pData = mstat_byte[device] & CD;
\r
864 *pData = mstat_byte[device] & DSR;
\r
867 *pData = mstat_byte[device] & CTS;
\r
870 *pData = mstat_byte[device] & RI;
\r
876 comstat[device].LastErc = erc;
\r
881 /******************************************
\r
882 Called for status report on coms channel.
\r
883 Returns 64 byte block for channel specified.
\r
884 This is called by the PUBLIC call DeviceStat
\r
885 *******************************************/
\r
887 static U32 comdev_stat(U32 dDevice,
\r
894 /* Set internal device number */
\r
899 if (dStatusMax > 64)
\r
906 CopyData(&comstat[0], pStatRet, i); /* copy the status data */
\r
910 CopyData(&comstat[1], pStatRet, i); /* copy the status data */
\r
913 *pdStatusRet = dStatusMax; /* give em the size returned */
\r
918 /******************************************
\r
919 Called to set parameters for the comms
\r
920 channels prior to opening or while in use.
\r
921 If an invalid value is passed in, all params
\r
922 remain the same as before.
\r
923 Some comms channel params may not be changed
\r
924 while the channel is in use.
\r
925 This is called by the PUBLIC call DeviceInit.
\r
926 *******************************************/
\r
928 static S32 comdev_init(U32 dDevice,
\r
933 U32 erc, Xbufsize, Rbufsize, device;
\r
934 U32 speed, XTO, RTO;
\r
936 U8 parity, bits, stop_bit, IRQNUM;
\r
939 device = 0; /* Set internal device number */
\r
943 if (sdInitData < 40)
\r
944 return(ErcBadInitSize);
\r
948 /* Get the callers new params */
\r
950 speed = pCS->Baudrate; /* Non Volatile */
\r
951 parity = pCS->parity; /* Non Volatile */
\r
952 bits = pCS->databits; /* Non Volatile */
\r
953 stop_bit = pCS->stopbits; /* Non Volatile */
\r
954 XTO = pCS->XTimeOut; /* Non Volatile */
\r
955 RTO = pCS->RTimeOut; /* Non Volatile */
\r
957 port_base = pCS->IOBase;
\r
958 Xbufsize = pCS->XBufSize;
\r
959 Rbufsize = pCS->RBufSize;
\r
960 IRQNUM = pCS->IRQNum;
\r
962 /* Non Volatile params can be set whether or not the
\r
963 channel is open. Do these first and return errors. */
\r
965 if ((speed > MAX_BAUD) || (speed < MIN_BAUD))
\r
966 return (ErcBadBaud);
\r
968 if ((parity < NO_PAR) || (parity > OD_PAR))
\r
969 return (ErcBadParity);
\r
971 if ((bits < 5) || (bits > 8))
\r
972 return (ErcBadDataBits);
\r
974 if ((stop_bit < 1) || (stop_bit > 2))
\r
975 return (ErcBadStopBits);
\r
980 comstat[device].Baudrate = speed;
\r
981 comstat[device].parity = parity;
\r
982 comstat[device].databits = bits;
\r
983 comstat[device].stopbits = stop_bit;
\r
984 comstat[device].XTimeOut = XTO;
\r
985 comstat[device].RTimeOut = RTO;
\r
987 /* If we got here, the params are OK. Now we check
\r
988 to see if the channel is open and call SetParams
\r
989 if so. The channel is open if the JobNumber
\r
990 in the commstat record is NON-ZERO.
\r
993 if (comstat[device].commJob)
\r
994 { /* Channel Open! */
\r
998 /* Channel is not open so we check and set rest of params */
\r
1004 return (ErcBadIOBase);
\r
1006 return (ErcBadCommIRQ);
\r
1008 /* We now round up buffer sizes to whole pages */
\r
1010 Xbufsize = Xbufsize/4096 * 4096;
\r
1011 if (Xbufsize % 4096) Xbufsize+=4096; /* another page */
\r
1014 Rbufsize = Rbufsize/4096 * 4096;
\r
1015 if (Rbufsize % 4096) Rbufsize+=4096; /* another page */
\r
1018 comstat[device].IOBase = port_base;
\r
1019 comstat[device].IRQNum = IRQNUM;
\r
1020 comstat[device].XBufSize = Xbufsize;
\r
1021 comstat[device].RBufSize = Rbufsize;
\r
1023 /* Local copies so we don't work from a structure in ISR */
\r
1025 sSendBuf[device] = Xbufsize; /* Size of buffer (allocated) */
\r
1026 sRecvBuf[device] = Rbufsize; /* Size of buffer (allocated) */
\r