⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commdrv.c

📁 MMURTL(tm) Computer Operating System Ver x0.8, source code.
💻 C
📖 第 1 页 / 共 2 页
字号:
long WriteByteC(U32 device, unsigned char b)
{

U32 erc, counter;
U8 *pXBuf;

	erc = 0;
	pXBuf = pSendBuf[device];
	counter = comstat[device].XTimeOut;		/* set up for timeout */

	while (cSendBuf[device] == sSendBuf[device]) {
		Sleep(1);
		counter--;
		if  (!counter)
			return (ErcXmitTimeout);		/* never got sent */
	}

#asm
	CLI
#endasm

	if (!fExpectInt[device]) {			/* Xmit buf empty, send ourself */
        OutByte(b, THR[device]);
		fExpectInt[device] = TRUE;
		}
	else {
        pXBuf[head_send[device]] = b;
        if (++head_send[device] == sSendBuf[device])
            head_send[device]  = 0;
		++cSendBuf[device];				/* one more in buf */
	     }
#asm
	STI
#endasm
	return (erc);
}


/********************************************/
long WriteRecordC(U32 device,
				 unsigned char *pSendData,
                 unsigned int cbSendData)
{
int erc;

	erc = 0;
    while ((cbSendData) && (!erc)) {
		erc = WriteByteC(device, *pSendData++);
		--cbSendData;
		}
	return (erc);
}


/********************************************/

long DiscardRecvC(U32 device)
{
U32	saveto, erc;
U8  b;

	saveto = comstat[device].RTimeOut;
	comstat[device].RTimeOut = 1;
	erc = 0;
	while (!erc)
		erc = ReadByteC(device, &b);
	comstat[device].RTimeOut = saveto;
	return (0);
}



/********************************************
 This sets comms params prior to opening, or
 while a channel is in use.
********************************************/

U32 SetParams(U32 device)

{
U32  divisor, speed;
U8   c, parity, bits, stop_bit, temp;

	parity = comstat[device].parity;
	bits = comstat[device].databits;
	stop_bit = comstat[device].stopbits;
	speed = comstat[device].Baudrate;

	/* Set up baud rate */

    divisor = 115200/speed;

#asm
	CLI
#endasm
    c=InByte (LCR[device]);
    OutByte  ((c | 0x80), LCR[device]);
    OutByte  ((divisor & 0x00ff), DLAB_LO[device]);
    OutByte  (((divisor>>8) & 0x00ff), DLAB_HI[device]);
    OutByte  (c, LCR[device]);
#asm
	STI
#endasm

	/* set coms params */

    temp = bits - 5;
    temp |= ((stop_bit == 1) ? 0x00 : 0x04);

    switch (parity)
        {
        case NO_PAR : temp |= 0x00; break;
        case OD_PAR : temp |= 0x08; break;
        case EV_PAR : temp |= 0x18; break;
        }

#asm
	CLI
#endasm
    OutByte (temp, LCR[device]);
#asm
	STI
#endasm

	return (0);
}


/********************************************
 This allocates buffers, sets up the ISR
 and IRQ values and open the channel for use.
*********************************************/

U32  OpenCommC(U32 device)

{
U32  erc;
U16  port_base;

	if (comstat[device].commJob)
		return(ErcChannelOpen);

	GetJobNum(&comstat[device].commJob);

	erc = AllocOSPage(comstat[device].XBufSize/4096,
					  &pSendBuf[device]);

	if (!erc) {
		erc = AllocOSPage(comstat[device].RBufSize/4096,
						  &pRecvBuf[device]);

		if (erc)  /* get rid of Xmit buf if we can't recv */
            DeAllocPage(pSendBuf[device],
            			comstat[device].XBufSize/4096);
	}

	if (erc) {
		comstat[device].commJob = 0;
		return (erc);
	}

   	port_base = comstat[device].IOBase;

	/* Set up buffer variables for this port */

	cSendBuf[device] = 0;
	head_send[device] = 0;
	tail_send[device] = 0;

	cRecvBuf[device] = 0;
	head_recv[device] = 0;
	tail_recv[device] = 0;
	recv_error[device] = 0;


    THR[device]     = port_base;
    IER[device]     = port_base + 1;
    IIR[device]     = port_base + 2;
    LCR[device]     = port_base + 3;
    MCR[device]     = port_base + 4;
    LSR[device]     = port_base + 5;
    MSR[device]     = port_base + 6;
    DLAB_HI[device] = port_base + 1;
    DLAB_LO[device] = port_base;

    InByte(THR[device]);	/* reset any pending ints on chip */
    InByte(LSR[device]);

#asm
	CLI
#endasm
	control_byte[device] = RTS | DTR | OUT2;
    OutByte(control_byte[device], MCR[device]);	/* Mod Ctrl Reg   */
    OutByte(0x0F, IER[device]);					/* Int Enable Reg */
#asm
	STI
#endasm

	SetParams(device);
	UnMaskIRQ(comstat[device].IRQNum);
	return (0);
}


/********************************************
 This closes the port, sets the owner to 0
 and deallocates the buffers.
********************************************/

int  CloseCommC (U32 device)
{
U32 Job, erc;

	MaskIRQ(comstat[device].IRQNum);
    OutByte(0, MCR[device]);
    OutByte(0, IER[device]);
    erc = DeAllocPage(pSendBuf[device],
           			comstat[device].XBufSize/4096);
    erc = DeAllocPage(pRecvBuf[device],
           			comstat[device].RBufSize/4096);
	comstat[device].commJob = 0;
    return (erc);
}

/***************************************************************************
Now begins the PUBLIC routines that are interfaced to for all DEVICE DRIVERS
****************************************************************************/

/******************************************
Called for all device operations.  This
assigns physical device from logical number
that outside callers use. For RS-232, 5=0
and 6=1.
*******************************************/

U32 comdev_op(U32 dDevice,
 		    U32 dOpNum,
		    U32 dLBA,
		    U32 dnBlocks,
		    U8  *pData)
{
U32 erc;
U32 Job, device;
U8 c;

/* Set internal drive number */
/* 5	RS-232 1	COM1	(OS built-in) */
/* 6	RS-232 2	COM2	(OS built-in) */

	if (dDevice == 5)
		device = 0;
	else
	 	device = 1;

	GetJobNum(&Job);

	if ((!comstat[device].commJob) && (dOpNum != CmdOpenC))
		return(ErcNotOpen);

	if (comstat[device].commJob) {
		if ((comstat[device].commJob != Job) &&
			(Job != 1))
			return(ErcNotOwner);
	}

	erc = 0;		/* default error */

	switch(dOpNum) {

		case(0):
			break;				/* Null Command */
		case CmdReadB:
			erc = ReadByteC(device, pData);
			break;
		case CmdWriteB:
			erc = WriteByteC(device, *pData);
			break;
		case CmdReadRec:
			erc = ReadRecordC(device, pData, dnBlocks,
						&comstat[device].LastTotal);
			break;
		case CmdWriteRec:
			erc = WriteRecordC(device, pData, dnBlocks);
			break;
		case CmdSetRTO:
			comstat[device].RTimeOut = dLBA;		/* 10ms intervals */
			break;
		case CmdSetXTO:
			comstat[device].XTimeOut = dLBA;		/* 10ms intervals */
			break;
		case CmdOpenC:
			erc =  OpenCommC(device);
			break;
		case CmdCloseC:
			erc =  CloseCommC(device);
			break;
		case CmdDiscardRcv:
			erc = DiscardRecvC(device);
			break;
		case CmdSetDTR:
			control_byte[device] |= DTR;
		    OutByte(control_byte[device], LCR[device]);
			break;
		case CmdSetRTS:
			control_byte[device] |= RTS;
			OutByte(control_byte[device], MCR[device]);
			break;
		case CmdReSetDTR:
			control_byte[device] &= ~DTR;
			OutByte(control_byte[device], LCR[device]);
		case CmdReSetRTS:
			control_byte[device] &= ~RTS;
		    OutByte(control_byte[device], MCR[device]);
		    break;
		case CmdBreak:
			c = InByte(LCR[device]);
			OutByte((c | 0x40), LCR[device]);
			Sleep(dLBA);
			OutByte(c, LCR[device]);
			break;
		case CmdGetDC:
		    *pData = mstat_byte[device] & CD;
			break;
		case CmdGetDSR:
	        *pData = mstat_byte[device] & DSR;
			break;
		case CmdGetCTS:
			*pData = mstat_byte[device] & CTS;
			break;
		case CmdGetRI:
			*pData = mstat_byte[device] & RI;
			break;
		default:
			break;
	}

	comstat[device].LastErc = erc;
	return(erc);
}


/******************************************
Called for status report on coms channel.
Returns 64 byte block for channel specified.
This is called by the PUBLIC call DeviceStat
*******************************************/

U32 comdev_stat(U32  dDevice,
			  S8  *pStatRet,
			  U32 dStatusMax,
			  U32 *pdStatusRet)
{
U32 i, j, device;

 /* Set internal device number */
 if (dDevice == 5)
 	device = 0;
 else device = 1;

 if (dStatusMax > 64)
 	i = 64;
 else
    i = dStatusMax;

 if (!device){
	 CopyData(&comstat[0], pStatRet, i);		/* copy the status data */
 }
 else {
	 CopyData(&comstat[1], pStatRet, i);		/* copy the status data */
 }

 *pdStatusRet = dStatusMax;		/* give em the size returned */

return(0);
}

/******************************************
Called to set parameters for the comms
channels prior to opening or while in use.
If an invalid value is passed in, all params
remain the same as before.
Some comms channel params may not be changed
while the channel is in use.
This is called by the PUBLIC call DeviceInit.
*******************************************/

S32 comdev_init(U32  dDevice,
			 S8  *pInitData,
			 U32  sdInitData)

{
U32  erc, Xbufsize, Rbufsize, device;
U32  speed, XTO, RTO;
U16  port_base;
U8   parity, bits, stop_bit, IRQNUM;

	if (dDevice == 5)
 		device = 0;   			/* Set internal device number */
	else
	 	device = 1;

	pCS = pInitData;

	/* Get the callers new params */

	speed     = pCS->Baudrate;	/* Non Volatile */
	parity    = pCS->parity;  	/* Non Volatile */
	bits      = pCS->databits;	/* Non Volatile */
	stop_bit  = pCS->stopbits;	/* Non Volatile */
	XTO       = pCS->XTimeOut;	/* Non Volatile */
	RTO       = pCS->RTimeOut;	/* Non Volatile */

   	port_base = pCS->IOBase;
	Xbufsize  = pCS->XBufSize;
	Rbufsize  = pCS->RBufSize;
	IRQNUM    = pCS->IRQNum;

	/* Non Volatile params can be set whether or not the
	   channel is open. Do these first and return errors. */

    if ((speed > MAX_BAUD) || (speed < MIN_BAUD))
       return (ErcBadBaud);

    if ((parity < NO_PAR) || (parity > OD_PAR))
    	return (ErcBadParity);

    if ((bits < 5) || (bits > 8))
    	return (ErcBadDataBits);

    if ((stop_bit < 1) || (stop_bit > 2))
    	return (ErcBadStopBits);

    if (!XTO)  XTO = 1;
    if (!RTO)  RTO = 1;

	comstat[device].Baudrate = speed;
	comstat[device].parity   = parity;
	comstat[device].databits = bits;
	comstat[device].stopbits = stop_bit;
	comstat[device].XTimeOut = XTO;
	comstat[device].RTimeOut = RTO;

	/* If we got here, the params are OK.  Now we check
	   to see if the channel is open and call SetParams
	   if so.  The channel is open if the JobNumber
	   in the commstat record is NON-ZERO.
	*/

	if (comstat[device].commJob) {  /* Channel Open! */
		SetParams(device);
	}

	/* Channel is not open so we check and set rest of params */

	else {

	    if (!port_base)
    		return (ErcBadIOBase);
	    if (IRQNUM < 3)
    		return (ErcBadCommIRQ);

		/* We now round up buffer sizes to whole pages */

		Xbufsize = Xbufsize/4096 * 4096;
		if (Xbufsize % 4096) Xbufsize+=4096; /* another page */


		Rbufsize = Rbufsize/4096 * 4096;
		if (Rbufsize % 4096) Rbufsize+=4096; /* another page */


		comstat[device].IOBase = port_base;
		comstat[device].IRQNum = IRQNUM;
		comstat[device].XBufSize = Xbufsize;
		comstat[device].RBufSize = Rbufsize;

		/* Local copies so we don't work from a structure in ISR */

		sSendBuf[device] = Xbufsize;	/* Size of buffer (allocated) */
		sRecvBuf[device] = Rbufsize;	/* Size of buffer (allocated) */

		erc = 0;
	}

 return(erc);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -