Category : OS/2 Files
Archive   : DD_IN_C.ZIP
Filename : SERIAL.C

 
Output of file : SERIAL.C contained in archive : DD_IN_C.ZIP
/* file sample.c
sample OS/2 serial device driver
*/

#include "drvlib.h"
#include "uart.h"
#include "serial.h"

extern void near STRAT(); /* name of strat rout.*/
extern void near TIM_HNDLR(); /* timer handler */
extern int near INT_HNDLR(); /* interrupt hand */

DEVICEHDR devhdr = {
(void far *) 0xFFFFFFFF, /* link */
(DAW_CHR | DAW_OPN | DAW_LEVEL1),/* attribute */
(OFF) STRAT, /* &strategy */
(OFF) 0, /* &IDCroutine */
"DEVICE1 "
};

CHARQUEUE rx_queue; /* receiver queue */
CHARQUEUE tx_queue; /* transmitter queue */
FPFUNCTION DevHlp=0; /* for DevHlp calls */
LHANDLE lock_seg_han; /* handle for locking*/
PHYSADDR appl_buffer=0; /* address of caller */
PREQPACKET p=0L; /* Request Packet ptr*/
ERRCODE err=0; /* error return */
void far *ptr; /* temp far pointer */
DEVICEHDR *hptr; /* pointer to Device */
USHORT i; /* general counter */
UARTREGS uart_regs; /* uart registers */
ULONG WriteID=0L; /* ID for write Block*/
ULONG ReadID=0L; /* ID for read Block */
PREQPACKET ThisReadRP=0L; /* for read Request */
PREQPACKET ThisWriteRP=0L;/* for write Request */
char inchar,outchar;/* temp chars */
USHORT baud_rate; /* current baud rate */
unsigned int savepid; /* PID of driver own */
UCHAR opencount; /* number of times */
ULONG tickcount; /* for timeouts */
unsigned int com_error_word; /* UART status */
USHORT port; /* port variable */
USHORT temp_bank; /* holds UART bank */
QUEUE rqueue; /* receive queue info*/

void near init();
void near enable_write();
void near disable_write();
void near set_dlab();
void near reset_dlab();
void near config_82050();

char IntFailMsg[] = " interrupt handler failed to install.\r\n";
char MainMsg[] = " OS/2 Serial Device Driver V1.0 installed.\r\n";

/* common entry point to strat routines */

int main(PREQPACKET rp, int dev )
{
void far *ptr;
int far *pptr;
PLINFOSEG liptr; /* pointer to local info */
int i;
ULONG addr;

switch(rp->RPcommand)
{
case RPINIT: /* 0x00 */

/* init called by kernel in prot mode */

return Init(rp,dev);

case RPOPEN: /* 0x0d */

/* get current processes id */

if (GetDOSVar(2,&ptr))
return (RPDONE|RPERR|ERROR_BAD_COMMAND);

/* get process info */

liptr = *((PLINFOSEG far *) ptr);

/* if this device never opened */

if (opencount == 0) /* 1st time dev op'd*/
{
ThisReadRP=0L;
ThisWriteRP=0L;
opencount=1; /* set open counter */
savepid = liptr->pidCurrent; /* PID */
QueueInit(&rx_queue);/* init driver */
QueueInit(&tx_queue);
}
else
{
if (savepid != liptr->pidCurrent)
return (RPDONE | RPERR | RPBUSY );
++opencount; /* bump counter */
}
return (RPDONE);

case RPCLOSE: /* 0x0e */

/* get process info of caller */

if (GetDOSVar(2,&ptr))
return (RPDONE|RPERR|ERROR_BAD_COMMAND); /* no info */

/* get process info from os/2 */

liptr= *((PLINFOSEG far *) ptr); /* PID */
if (savepid != liptr->pidCurrent ||
opencount == 0)
return (RPDONE|RPERR|ERROR_BAD_COMMAND);
--opencount; /* close counts down open*/

if (ThisReadRP !=0 && opencount == 0) {
Run((ULONG) ThisReadRP); /* dangling*/
ThisReadRP=0L;
}
return (RPDONE); /* return 'done' */

case RPREAD: /* 0x04 */

/* Try to read a character */

ThisReadRP = rp;
if (opencount == 0)/* drvr was closed */
{
rp->s.ReadWrite.count = 0; /* EOF */
return(RPDONE);
}
com_error_word=0;/* start off no errors */
ReadID = (ULONG) rp;
if (Block(ReadID, -1L, 0, &err))
if (err == 2) /* interrupted */
return(RPDONE|RPERR|ERROR_CHAR_CALL_INTERRUPTED);

if (rx_queue.qcount == 0) {
rp->s.ReadWrite.count=0;
return (RPDONE|RPERR|ERROR_NOT_READY);
}

i=0;
do {
if (MoveData((FARPOINTER)&inchar,
(FARPOINTER) (rp->s.ReadWrite.buffer+i),
1,
MOVE_VIRTTOPHYS))
return(RPDONE|RPERR|ERROR_GEN_FAILURE);
}
while (++i < rp->s.ReadWrite.count
&& !QueueRead(&rx_queue,&inchar));
rp->s.ReadWrite.count = i;
QueueInit(&rx_queue);
return(rp->RPstatus);

case RPWRITE: /* 0x08 */

ThisWriteRP = rp;

/* transfer characters from user buffer */

addr=rp->s.ReadWrite.buffer;/* get addr */
for (i = rp->s.ReadWrite.count; i; --i,++addr)
{
if (MoveData((FARPOINTER)addr,
(FARPOINTER)&outchar,
1,
MOVE_PHYSTOVIRT))
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

if (QueueWrite(&tx_queue,outchar))
return (RPDONE|RPERR|ERROR_GEN_FAILURE);
}
WriteID = (ULONG) rp;
enable_write();

if (Block(WriteID, -1L, 0, &err))
if (err == 2) /* interrupted */
return(RPDONE|RPERR|ERROR_CHAR_CALL_INTERRUPTED);

tickcount=MIN_TIMEOUT; /* reset timeout */
QueueInit(&tx_queue);
return (rp->RPstatus);

case RPINPUT_FLUSH: /* 0x07 */

QueueFlush(&rx_queue);
return (RPDONE);

case RPOUTPUT_FLUSH: /* 0x0b */

QueueFlush(&tx_queue);
return (RPDONE);

case RPIOCTL: /* 0x10 */

if (!((rp->s.IOCtl.category == SAMPLE_CAT)
|| (rp->s.IOCtl.category == 0x01)))
return (RPDONE);

switch (rp->s.IOCtl.function)
{
case 0x41: /* set baud rate */
/* set baud rate to 1.2, 2.4, 9.6, 19.2 */
/* verify caller owns the buffer area */

if(VerifyAccess(
SELECTOROF(rp->s.IOCtl.parameters),
OFFSETOF(rp->s.IOCtl.parameters),
2, /* two bytes */
1) ) /* read/write */
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

/* lock the segment down temp */

if(LockSeg(
SELECTOROF(rp->s.IOCtl.parameters),
0, /* lock for < 2 sec */
0, /* wait for seg lock */
(PLHANDLE) &lock_seg_han)) /* handle */
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

/* get physical address of buffer */
if (VirtToPhys(
(FARPOINTER) rp->s.IOCtl.parameters,
(FARPOINTER) &appl_buffer))
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

/* move data to local driver buffer */

if(MoveData(
(FARPOINTER) appl_buffer, /* source */
(FARPOINTER)&baud_rate, /* destination */
2, /* 2 bytes */
MOVE_PHYSTOVIRT))
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

if (UnPhysToVirt()) /* release selector*/
return(RPDONE|RPERR|ERROR_GEN_FAILURE);

/* unlock segment */

if(UnLockSeg(lock_seg_han))
return(RPDONE|RPERR|ERROR_GEN_FAILURE);

switch (baud_rate)
{
case 1200:

uart_regs.Bal=0xe0;
uart_regs.Bah=0x01;
break;

case 2400:

uart_regs.Bal=0xf0;
uart_regs.Bah=0x00;
break;

case 9600:

uart_regs.Bal=0x3c;
uart_regs.Bah=0x00;
break;

case 19200:

uart_regs.Bal=0x1e;
uart_regs.Bah=0x00;
break;

case 38400:

uart_regs.Bal=0x0f;
uart_regs.Bah=0x00;
break;

error:
return (RPDONE|RPERR|ERROR_BAD_COMMAND);

}
init(); /* reconfigure uart */
return (RPDONE);

case 0x68: /* get number of chars */

/* verify caller owns the buffer */

if(VerifyAccess(
SELECTOROF(rp->s.IOCtl.buffer),
OFFSETOF(rp->s.IOCtl.buffer),
4, /* 4 bytes */
1) ) /* read/write */
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

/* lock the segment down temp */

if(LockSeg(
SELECTOROF(rp->s.IOCtl.buffer),
0, /* lock for < 2 sec */
0, /* wait for seg lock */
(PLHANDLE) &lock_seg_han)) /* handle*/
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

/* get physical address of buffer */

if (VirtToPhys(
(FARPOINTER) rp->s.IOCtl.buffer,
(FARPOINTER) &appl_buffer))
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

rqueue.cch=rx_queue.qcount;
rqueue.cb=rx_queue.qsize;

/* move data to local driver buffer */

if(MoveData(
(FARPOINTER)&rx_queue, /* source */
(FARPOINTER) appl_buffer, /* dest */
4, /* 4 bytes */
MOVE_PHYSTOVIRT))
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

if (UnPhysToVirt())
return(RPDONE|RPERR|ERROR_GEN_FAILURE);

/* unlock segment */

if(UnLockSeg(lock_seg_han))
return(RPDONE|RPERR|ERROR_GEN_FAILURE);

return (RPDONE);

case 0x6d: /* get COM error info */

/* verify caller owns the buffer */

if(VerifyAccess(
SELECTOROF(rp->s.IOCtl.buffer),
OFFSETOF(rp->s.IOCtl.buffer),
2, /* two bytes */
1) ) /* read/write */
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

/* lock the segment down temp */

if(LockSeg(
SELECTOROF(rp->s.IOCtl.buffer),
0, /* lock for < 2 sec */
0, /* wait for seg lock */
(PLHANDLE) &lock_seg_han)) /* handle*/
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

/* get physical address of buffer */

if (VirtToPhys(
(FARPOINTER) rp->s.IOCtl.buffer,
(FARPOINTER) &appl_buffer))
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

/* move data to application buffer */

if(MoveData(
(FARPOINTER)&com_error_word, /* source */
(FARPOINTER) appl_buffer, /* dest */
2, /* 2 bytes */
MOVE_VIRTTOPHYS))
return (RPDONE|RPERR|ERROR_GEN_FAILURE);

if (UnPhysToVirt())
return(RPDONE|RPERR|ERROR_GEN_FAILURE);

/* unlock segment */

if(UnLockSeg(lock_seg_han))
return(RPDONE|RPERR|ERROR_GEN_FAILURE);

return (RPDONE);

default:
return(RPDONE|RPERR|ERROR_GEN_FAILURE);
}

/* don't allow deinstall */

case RPDEINSTALL: /* 0x14 */
return(RPDONE|RPERR|ERROR_BAD_COMMAND);

/* all other commands are ignored */

default:
return(RPDONE);

}
}

void enable_write()


/* enable write interrupts on uart */

{
int port;
int reg_val;

port=UART_PORT_ADDRESS;
reg_val=inp(port+2) & 0x60;
set_bank(00);
outp((port+1),inp(port+1) | 0x12);
outp((port+2),reg_val);

}
void disable_write()

/* turn off write interrupts on uart */

{
int port;
int reg_val;

port=UART_PORT_ADDRESS;
reg_val=inp(port+2) & 0x60;
set_bank(00);
outp((port+1),inp(port+1) & 0xed);
outp((port+2),reg_val);

}

void init ()

/* intializes software and configures 82050 */

{
config_82050 (); /* Configure 82050 */
set_bank(01);
}

void config_82050()

/* Configure the 82050 */

{
int port;
int inval;

Disable(); /* disable interrupts */
port=UART_PORT_ADDRESS;

/* set stick bit */

set_bank(01); /* stick bit */
outp((port+7),0x10); /* reset port */
outp ((port+1), uart_regs.Txf); /* stick bit */

set_bank (02); /* general config */
outp ((port + 4), uart_regs.Imd); /*auto rupt */
outp ((port + 7), uart_regs.Rmd);
outp ((port + 5), uart_regs.Acr1); /* cntl-z */
outp ((port + 3), uart_regs.Tmd); /* no 9 bit */
outp ((port + 1), uart_regs.Fmd); /* rx fifo */
outp ((port + 6), uart_regs.Rie); /* enable */

set_bank (03); /* modemconfiguration */

outp ((port + 0), uart_regs.Clcf); /* clock */
set_dlab (03); /* */
outp ((port + 0), uart_regs.Bbl); /* BRGB lsb */
outp ((port + 1), uart_regs.Bbh); /* BRGB msb */
reset_dlab (03); /* */
outp ((port + 3), uart_regs.Bbcf); /* BRGB */
outp ((port + 6), uart_regs.Tmie); /* timer b */

set_bank (00); /* general cfg */
outp ((port + 1), uart_regs.Ger); /* enable */
outp ((port + 3), uart_regs.Lcr); /* 8 bit */
outp ((port + 7), uart_regs.Acr0); /* CR */
outp ((port + 4), uart_regs.Mcr_0); /* no DTR */
set_dlab (00); /* */
outp ((port + 0), uart_regs.Bal); /* BRGA lsb */
outp ((port + 1), uart_regs.Bah); /* BRGA msb */
reset_dlab (00);
set_bank(01);

Enable(); /* turn on */
}

void set_dlab (bank)

/* Set DLAB bit to allow access to divisior registers */

int bank;
{
int inval;
int port;

port=UART_PORT_ADDRESS;
set_bank (00);
inval=inp(port +3);
inval =inval | 0x80; /* set dlab in LCR */
outp ((port+3),inval);
set_bank (bank);
}

getsrc()


{
int v,src;
int port;

port=UART_PORT_ADDRESS; /* get base address */
v=inp(port+2); /* get data */
src=v & 0x0e; /* mask bits */
src=src/2; /* divide by 2 */
return(src); /* and pass it back */
}

set_bank(bank_num)

/* set bank of 82050 uart */

int bank_num;

{
int reg_val;
int port;

reg_val=bank_num*0x20; /* select bank numb */
port=UART_PORT_ADDRESS; /* get real port */
outp(port+gir_addr,reg_val); /* output */
}

void reset_dlab (bank)

/* Reset DLAB bit of LCR */

int bank;

{
int inval;
int port;

port=UART_PORT_ADDRESS;
set_bank (00);
inval=inp (port +3);
inval = (inval & 0x7f); /* dlab = 0 in LCR */
outp ((port+3),inval);
set_bank (bank);
}

/* 82050 interrupt handler */

void interrupt_handler ()
{
int rupt_dev;
int source;
int cmd_b;
int st_b;
int port;
int temp;
int rxlevel;


port=UART_PORT_ADDRESS;
outp((port+2),0x20); /* switch to bank 1 */
source = getsrc (); /* get vector */
switch (source)
{

/* optional timer service routine */

case timer :

st_b=inp (port+3); /* dec transmit count */
if ( ThisReadRP == 0) /* nobody waiting */
break;
ThisReadRP->RPstatus=(RPDONE|RPERR|ERROR_NOT_READY);
Run ((ULONG) ThisWriteRP); /* run thread */
ThisWriteRP=0;
break;

case txm :
case txf :

/* spurious write interrupt */

if ( ThisWriteRP == 0) {
temp=inp(port+2);
break;
}

/* keep transmitting until no data left */

if (!(QueueRead(&tx_queue,&outchar)))
{
outp((port), outchar);
tickcount=MIN_TIMEOUT;
break;
}

/* done writing, run blocked thread */

tickcount=MIN_TIMEOUT;
disable_write();
ThisWriteRP->RPstatus = (RPDONE);
Run ((ULONG) ThisWriteRP);
ThisWriteRP=0;
break;

case ccr :

/* control character, treat as normal */

inchar=inp(port+5);

case rxf :

/* rx fifo service routine */

if ( ThisReadRP == 0)
inchar=inp (port); /* get character */
else
{
temp=inp(port+4);
rxlevel=(temp & 0x70) / 0x10;

/* empty out chip FIFO */

while (rxlevel !=0) {

inchar=inp (port); /* get character */
rxlevel--;
tickcount=MIN_TIMEOUT;

/* write input data to queue */

if(QueueWrite(&rx_queue,inchar))

/* error, queue must be full */

{
ThisReadRP->RPstatus=(RPDONE|RPERR|ERROR_GEN_FAILURE);
Run ((ULONG) ThisReadRP);
ThisReadRP=0;
break;
}
com_error_word |= inp(port+5);

} /* while rxlevel */
} /* else */
} /* switch (source) */
}
void timer_handler()
{
if (ThisReadRP == 0)
return;

tickcount--;
if(tickcount == 0) {
ThisReadRP->RPstatus=(RPDONE);
Run ((ULONG) ThisReadRP);
ThisReadRP=0L;
tickcount=MIN_TIMEOUT;
}
}

/* Device Initialization Routine */

int Init(PREQPACKET rp, int dev)
{
register char far *p;

/* store DevHlp entry point */

DevHlp = rp->s.Init.DevHlp;

/* install interrupt hook in vector */

if (SetTimer((PFUNCTION)TIM_HNDLR))
goto fail;

rx_queue.qsize=QUEUE_SIZE;
tx_queue.qsize=QUEUE_SIZE; /* init queue */
init(); /* init the port */
tickcount=MIN_TIMEOUT; /* set timeout */

if(SetIRQ(5,(PFUNCTION)INT_HNDLR,0)) {

/* if we failed, deinstall driver cs+ds=0 */
fail:
DosPutMessage(1, 8, devhdr.DHname);
DosPutMessage (1,strlen(IntFailMsg),IntFailMsg);
rp->s.InitExit.finalCS = (OFF) 0;
rp->s.InitExit.finalDS = (OFF) 0;
return (RPDONE | RPERR | ERROR_BAD_COMMAND);
}

/* output initialization message */

DosPutMessage(1, 8, devhdr.DHname);
DosPutMessage(1, strlen(MainMsg), MainMsg);

/* send back our cs and ds values to os/2 */

if (SegLimit(HIUSHORT((void far *) Init),&rp->s.InitExit.finalCS)
|| SegLimit(HIUSHORT((void far *) MainMsg),
&rp->s.InitExit.finalDS))
Abort();
return(RPDONE);
}




  3 Responses to “Category : OS/2 Files
Archive   : DD_IN_C.ZIP
Filename : SERIAL.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/