dxx-rebirth/arch/dos/comm/dzcomm.c
Bradley Bell 9bd1ba7c47 This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches.
2001-01-19 03:30:16 +00:00

890 lines
23 KiB
C

/*
* DZcomm : serial communication add-on for Allegro.
* version : 0.6
* Copyright (c) 1997 Dim Zegebart, Moscow Russia.
* zager@post.comstar.ru
* file : dzcomm.c
*
*/
#include <stdio.h>
#include <sys/movedata.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>
#include <string.h>
#include <io.h>
#include <ctype.h>
#include "dzcomm.h"
#include "allegro.h"
typedef unsigned int uint;
typedef unsigned short int usint;
typedef unsigned char byte;
#define com_(N) comm_port *com##N
com_(1);
com_(2);
com_(3);
com_(4);
com_(5);
com_(6);
com_(7);
com_(8);
#define com_wrapper_(N) static int com##N##_wrapper(void) \
{ DISABLE(); /* adb -- why this? */ \
dz_comm_port_interrupt_handler(com##N##); \
return(0); \
} \
END_OF_FUNCTION(com##N##_wrapper);
com_wrapper_(1);
com_wrapper_(2);
com_wrapper_(3);
com_wrapper_(4);
com_wrapper_(5);
com_wrapper_(6);
com_wrapper_(7);
com_wrapper_(8);
static comm_port *irq_bot_com_port[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static int (*com_wrapper[8])();
static comm_port **com_port[8];
char szDZCommErr[50];
inline void dz_make_comm_err(char *szErr) {strcpy(szDZCommErr,szErr);}
//comm port functions
static inline void comm_port_rdr(comm_port *port);
static inline void comm_port_trx(comm_port *port);
static inline void interrupt_on(comm_port *port,byte _interrupt_);
static inline void interrupt_off(comm_port *port,byte _interrupt_);
extern void lock_queue_functions(void);
void comm_port_fifo_init(comm_port *port);
inline void comm_port_rtmout(comm_port *port);
void comm_port_uninstall(comm_port *port);
//const byte THREOFF=0xfd;
const byte THREINT=0x02;
const byte RDAINT=0x04;
//-------------------------- PRINT BIN --------------------------
void print_bin_s(int c,char *s)
{ int i,j;
int mask=0x01;
sprintf (s,"%c : ",c);
for (i=0;i<4;i++)
{ for(j=0;j<8;j++)
if (c&(mask<<(j+i*8))) strcat(s,"1");
else strcat(s,"0");
strcat(s,".");
}
}
//------------------------- INTERRUPT ON -----------------------------
static inline void interrupt_on(comm_port *port,byte _interrupt_)
{ byte i;
i=inportb(port->IER);
if (!(i&_interrupt_)) outportb(port->IER,i|_interrupt_);
}
END_OF_FUNCTION(interrupt_on);
//------------------------- INTERRUPT OFF -----------------------------
static inline void interrupt_off(comm_port *port,byte _interrupt_)
{ byte i;
i=inportb(port->IER);
if (i&_interrupt_) outportb(port->IER,i&~_interrupt_);
}
END_OF_FUNCTION(interrupt_off);
//------------------------- COMM PORT INIT --------------------------
comm_port *comm_port_init(comm com)
{ comm_port *port=(comm_port*)malloc(sizeof(comm_port));
szDZCommErr[0]=0;
if (port==NULL)
{ dz_make_comm_err("Out of memory !");
return(NULL);
}
if ((port->InBuf=queue_new_(4096,1))==NULL)
{ dz_make_comm_err("Out of memory !");
return(NULL);
}
if ((port->OutBuf=queue_new_(4096,1))==NULL)
{ dz_make_comm_err("Out of memory !");
queue_delete(port->InBuf);
return(NULL);
}
port->nPort=0;
//getting comport base address
//0x400+com*2 - memory address where stored default comm base address
dosmemget(0x400+com*2,2,&port->nPort);
if (port->nPort==0) //probably you have notebook or some brand named PC
{ if (com==_com1||com==_com3||com==_com5||com==_com7) port->nPort=0x3f8; //default I/O address for com1 or com3
else port->nPort=0x2f8; //com2 or com4
}
//set default values (user may change it later)
if (com==_com1||com==_com3||com==_com5||com==_com7) port->nIRQ=4;
else port->nIRQ=3; //com2 or com4
strcpy(port->szName,"COM ");
port->szName[3]=com+49;
port->installed=NO;
port->nComm=com;
port->nBaud=_2400;
port->nData=BITS_8;
port->nStop=STOP_1;
port->nParity=NO_PARITY;
port->comm_handler=com_wrapper[com];
port->control_type=XON_XOFF;
port->msr_handler=NULL; //#d#pointer to modem status register handler.
port->lsr_handler=NULL; //#d#pointer to line status register handler.
_go32_dpmi_lock_data(port,sizeof(comm_port));
*(com_port[com])=port;
return(port);
}
//-------------------- COMM_PORT_FIFO_INIT ----------------------
void comm_port_fifo_init(comm_port *port)
{
//setting up FIFO if possible
int c=inportb(port->SCR);
outportb(port->SCR,0x55);
port->fifo = 0;
if(inportb(port->SCR)==0x55) // greater then 8250
{ outportb(port->SCR,c);
outportb(port->FCR,0x87);//try to enable FIFO with 8 byte trigger level
if ((c=inportb(port->IIR)&0xc0)!=0xc0) //If not 16550A
outportb(port->FCR,c&0xfe); //Disable FIFO
else port->fifo = 1;
// else printf("\nFIFO OK\n");
}
}
//----------------------- COMM PORT INSTALL HANDLER ------------------
//modifyed by Neil Townsend to support IRQ sharing
int comm_port_install_handler(comm_port *port)
{
if (port==NULL)
{ dz_make_comm_err("Set up comm parametrs first ! Call comm_port_new() first.");
return(0);
}
if (port->installed==YES)
{ dz_make_comm_err("Comm already installed !");
return(0);
}
if (port->nIRQ>15)
{ dz_make_comm_err("IRQ number out of range ! Must be 0 ... 15 .");
return(0);
}
if (port->comm_handler==NULL)
{ dz_make_comm_err("Specify comm's handler (see 'comm_handler' member's description) !");
return(0);
}
if (port->nBaud==0)
{ dz_make_comm_err("Invalid baud rate !");
return(0);
}
switch(port->control_type)
{ case XON_XOFF :
port->xon=0;
port->xoff=0;
port->xonxoff_rcvd=XON_RCVD;
port->xonxoff_send=XON_SENT;
break;
case RTS_CTS :
port->cts=CTS_ON;
port->rts=RTS_ON; //fixed by SET (was RTS_OFF)
break;
default :
break;
}
port->THR=port->nPort;
port->RDR=port->nPort;
port->BRDL=port->nPort;
port->BRDH=1+port->nPort;
port->IER=1+port->nPort;
port->IIR=2+port->nPort;
port->FCR=2+port->nPort;
port->LCR=3+port->nPort;
port->MCR=4+port->nPort;
port->LSR=5+port->nPort;
port->MSR=6+port->nPort;
port->SCR=7+port->nPort;
{ byte i;
for(i=0;i<8;i++) outportb(port->RDR+i,0);
}
comm_port_fifo_init(port);
{ unsigned char temp;
do
{ temp=inportb(port->RDR);
temp=inportb(port->LSR);
temp=inportb(port->MSR);
temp=inportb(port->IIR);
}
while(!(temp & 1));
}
//set communication parametrs
//MOVED forwards so done before interupts enabled
{ int divisor=115200/port->nBaud;
byte divlow,divhigh;
byte comm_param=port->nData|(port->nStop<<2)|(port->nParity<<3);
// Set Port Toggle to BRDL/BRDH registers
outportb(port->LCR,comm_param|0x80);
divlow=divisor&0x000000ff;
divhigh=(divisor>>8)&0x000000ff;
outportb(port->BRDL,divlow); // Set Baud Rate
outportb(port->BRDH,divhigh);
outportb(port->LCR,comm_param&0x7F); // Set LCR and Port Toggle
}
//set interrupt parametrs
{ const byte IMR_8259_0=0x21;
const byte IMR_8259_1=0xa1;
const byte ISR_8259_0=0x20;
const byte ISR_8259_1=0xa0;
const byte IERALL = 0x0f; //mask for all communications interrupts
const byte MCRALL = 0x0f; //DTR,RTS,OUT1=OUT2=1 is ON
//calculating mask for 8259 controller's IMR
//and number of interrupt hadler for given irq level
if (port->nIRQ<=7) //if 0<=irq<=7 first IMR address used
{ port->interrupt_enable_mask=~(0x01<<port->nIRQ);
port->nIRQVector=port->nIRQ+8;
port->IMR_8259=IMR_8259_0;
port->ISR_8259=ISR_8259_0;
}
else
{ port->interrupt_enable_mask=~(0x01<<(port->nIRQ%8));
port->nIRQVector=0x70+(port->nIRQ-8);
port->IMR_8259=IMR_8259_1;
port->ISR_8259=ISR_8259_1;
}
port->next_port = NULL;
port->last_port = irq_bot_com_port[port->nIRQ];
if (irq_bot_com_port[port->nIRQ] != NULL) irq_bot_com_port[port->nIRQ]->next_port = port;
irq_bot_com_port[port->nIRQ] = port;
DISABLE();
if (port->last_port == NULL)
{ // DZ orig lines in here
_install_irq(port->nIRQVector,port->comm_handler);
//enable interrupt port->nIRQ level
outportb(port->IMR_8259,inportb(port->IMR_8259)&
port->interrupt_enable_mask);
}
// DZ again:
outportb(port->MCR,MCRALL); //setup modem
outportb(port->IER,IERALL); //enable all communication's interrupts
// to here
ENABLE();
}
port->installed=YES;
return(1);
}
//------------------ DZ COMM PORT INTERRUPT HANDLER ---------------
// always return zero
inline int dz_comm_port_interrupt_handler(comm_port *port)
{ int int_id;
int c;
// putch('1');
while (1) //loop while !end of all interrupts
{ int_id=inportb(port->IIR); //get interrupt id
//next loop added by Neil Townsend
while ((int_id&0x01)==1) //no interrupts (left) to handle on this port
{ if (port->next_port==NULL)
{ outportb(0x20,0x20);
if (port->nIRQ>7) //Thanks for SET for this fix
outportb(0xA0,0x20); //now IRQ8-IRQ15 handled properly.
return(0);
}
port=(comm_port*)port->next_port;
int_id=inportb(port->IIR);
}
switch (int_id)
{
case 0xcc: //Character Timeout Indication N.Lohmann 6.3.98
// only possible if FiFo's are enabled.
comm_port_rtmout(port);
break;
case 0xc6: //FiFo LSINT
case 0x06: //LSINT:
c=inportb(port->LSR);
if (port->lsr_handler!=NULL) port->lsr_handler(c);
break;
case 0xc4: //FiFo RDAINT
case 0x04: //RDAINT
comm_port_rdr(port);
break;
case 0xc2: //FiFo THREINT
case 0x02: //THREINT :
comm_port_trx(port);
break;
case 0xc0: //FiFo MSINT
case 0x00: //MSINT :
c=inportb(port->MSR);
if (port->msr_handler!=NULL) port->msr_handler(c);
if (port->control_type==RTS_CTS)
{ if (port->cts==CTS_OFF && c&0x10)
{ port->cts=CTS_ON;
if (port->rts==RTS_ON)
interrupt_on(port,THREINT);
}
else
if (port->cts==CTS_ON && !c&0x10)
{ port->cts=CTS_OFF;
interrupt_off(port,THREINT);
}
}
break;
}//end case
} //end while 1
return(0);
}
END_OF_FUNCTION(dz_comm_port_interrupt_handler);
//----------------------- COMM PORT RTMOUT ------------------------
//Nils Lohmann 8.3.98
//Time Out Indication, service routine triggered after 4 Char-times
//if there is at least one Byte in FiFo and no read-Cykle happened.
inline void comm_port_rtmout(comm_port *port)
{
comm_port_rdr(port);
}
END_OF_FUNCTION(comm_port_rtmout);
//----------------------- COMM PORT DELETE ------------------------
void comm_port_delete(comm_port *port)
{
if (port->installed==NO) return;
comm_port_uninstall(port);
free(port);
}
//------------------------- COMM PORT OUT -----------------------------
inline void comm_port_out(comm_port *port,byte c)
{
queue_put_(port->OutBuf,&c);
switch (port->control_type)
{ case NO_CONTROL :
interrupt_on(port,THREINT);
break;
case XON_XOFF : // XON/XOFF
if (port->xonxoff_rcvd!=XOFF_RCVD)
{ interrupt_on(port,THREINT);
}
case RTS_CTS : // RTS_CTR
if (port->cts==CTS_ON) //modem is 'clear to send'
{ if (port->rts==RTS_ON) //Fixed by SET (was RTS_OFF)
{ interrupt_on(port,THREINT);
}
}
break;
default:
break;
}
}
//------------------------- COMM PORT TEST -----------------------------
inline int comm_port_test(comm_port *port)
{ byte c;
switch (port->control_type)
{ case NO_CONTROL :
break;
case XON_XOFF : // XON/XOFF
if (((port->InBuf)->tail<(port->InBuf)->fill_level)&&(port->xonxoff_send!=XON_SENT))
{ port->xon=1;
interrupt_on(port,THREINT);
}
break;
case RTS_CTS :
if (((port->InBuf)->tail<(port->InBuf)->fill_level)&&(port->rts==RTS_OFF))
{ outportb(port->MCR,inportb(port->MCR)|0x02); //setting RTS
port->rts=RTS_ON;
interrupt_on(port,THREINT);
}
break;
default:
break;
}
if (queue_empty(port->InBuf))
{ return(-1);
}
queue_get_(port->InBuf, &c);
return(c);
}
//----------------------- COMM PORT STRING SEND -------------------------
void comm_port_string_send(comm_port *port,char *s)
{
int i;
if (s==NULL) return;
for (i=0;s[i]!=0;i++) comm_port_out(port,s[i]);
}
//---------------------- COMM PORT COMMAND SEND -------------------------
void comm_port_command_send(comm_port *port,char *s)
{
int i;
if (s==NULL) return;
for (i=0;s[i]!=0;i++)comm_port_out(port,s[i]);
comm_port_out(port,'\r');
}
//------------------- MODEM HANG UP -----------------
void modem_hangup(comm_port *port)
{
comm_port_out(port,2);
delay(3000);
comm_port_string_send(port,"+++");
delay(3000);
comm_port_string_send(port,"ATH0\r");
}
//---------------------- COMM PORT HAND ---------------------------
void comm_port_hand(comm_port *port,int m)
{ int c;
c=inportb(port->MCR);
outportb(port->MCR,c&m);
}
inline int comm_port_send_xoff(comm_port *port)
{
if (port->xonxoff_send!=XOFF_SENT)
{ port->xoff=1;
interrupt_on(port,THREINT);
}
return(1);
}
inline int comm_port_send_xon(comm_port *port)
{
if (port->xonxoff_send!=XON_SENT)
{ port->xon=1;
interrupt_on(port,THREINT);
}
return(1);
}
//-------------------- COMM PORT LOAD SETTINGS ---------------------
#ifdef __DEVICE__
int comm_port_load_settings(device *dev,char *ini_name)
#else
int comm_port_load_settings(comm_port *port,char *ini_name)
#endif
{
#ifdef __DEVICE__
comm_port *port=dev->device_user_data;
#endif
FILE *ini;
int l,i;
char *buf,*buf_end,*s,v[64];
comm com=port->nComm;
char com_name[7]={'[','c','o','m',com+49,']',0};
char com_end[11]={'[','c','o','m',com+49,' ','e','n','d',']',0};
if ((ini=fopen(ini_name,"rt"))==NULL) return(0);
l=filelength(fileno(ini));
if ((buf=(char*)alloca(l))==NULL)
{ fclose(ini);
return(0);
}
l=fread(buf,1,l,ini);
fclose(ini);
buf[l]=0;
strlwr(buf);
s=strstr(buf,com_name);
buf_end=strstr(buf,com_end);
if (s==NULL||buf_end==NULL) return(-1);
*buf_end=0;
//get baud rate
if ((s=strstr(buf,"baud"))!=NULL)
{ if (not_commented(s)&&(s=strchr(s,'='))!=NULL)
{ s++;i=0;
while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9))
if (!isspace(*s)) v[i++]=*s++;
v[i]=0;
if ((i=atoi(v))!=0) port->nBaud=i;
}
}
//get irq number
if ((s=strstr(buf,"irq"))!=NULL)
{ if (not_commented(s)&&(s=strchr(s,'='))!=NULL)
{ s++;i=0;
while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9))
if (!isspace(*s)) v[i++]=*s++;
v[i]=0;
if ((i=atoi(v))!=0) port->nIRQ=i;
}
}
//get comm address
if ((s=strstr(buf,"address"))!=NULL)
{ if (not_commented(s)&&(s=strchr(s,'='))!=NULL)
{ s++;i=0;
while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9))
if (!isspace(*s)) v[i++]=*s++;
v[i]=0;
if ((i=strtol(v,NULL,0))!=0) port->nPort=strtol(v,NULL,0);
}
}
//get data bits
if ((s=strstr(buf,"data"))!=NULL)
{ if (not_commented(s)&&(s=strchr(s,'='))!=NULL)
{ s++;i=0;
while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9))
if (!isspace(*s)) v[i++]=*s++;
v[i]=0;
if ((i=atoi(v))!=0)
switch (i)
{ case 8 :
port->nData=BITS_8;
break;
case 7 :
port->nData=BITS_7;
break;
case 6 :
port->nData=BITS_6;
break;
case 5 :
port->nData=BITS_5;
break;
}
}
}
//get parity bits
if ((s=strstr(buf,"parity"))!=NULL)
{ if (not_commented(s)&&(s=strchr(s,'='))!=NULL)
{ s++;i=0;
while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9))
if (!isspace(*s)) v[i++]=*s++;
v[i]=0;
if (strcmp(v,"even")==0) port->nParity=EVEN_PARITY;
else
if (strcmp(v,"odd")==0) port->nParity=ODD_PARITY;
else
if (strcmp(v,"no")==0||strcmp(v,"none")==0) port->nParity=NO_PARITY;
}
}
//get control type
if ((s=strstr(buf,"control"))!=NULL)
{ if (not_commented(s)&&(s=strchr(s,'='))!=NULL)
{ s++;i=0;
while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9))
if (!isspace(*s)) v[i++]=*s++;
v[i]=0;
if (strcmp(v,"xon_xoff")==0||strcmp(v,"xon/xoff")==0) port->control_type=XON_XOFF;
else
if (strcmp(v,"no")==0||strcmp(v,"none")==0) port->control_type=NO_CONTROL;
else
if (strcmp(v,"rts_cts")==0||strcmp(v,"rts/cts")==0) port->control_type=RTS_CTS;
}
}
if ((s=strstr(buf,"stop"))!=NULL) //get stop bits
{ if (not_commented(s)&&(s=strchr(s,'='))!=NULL)
{ s++;i=0;
while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<9))
if (!isspace(*s)) v[i++]=*s++;
v[i]=0;
if ((i=atoi(v))!=0)
switch (i)
{ case 1 :
port->nStop=STOP_1;
break;
case 2 :
port->nStop=STOP_2;
break;
}
}
}
if ((s=strstr(buf,"name"))!=NULL)
{ if (not_commented(s)&&(s=strchr(s,'='))!=NULL)
{ s++;i=0;
while ((*s!=';')&&(*s!='\n')&&(*s!=0)&&(i<64))
v[i++]=*s++;
v[i]=0;
strcpy(port->szName,v);
}
}
return(1);
}
//----------------------- COMM PORT RDR ------------------------
static inline void comm_port_rdr(comm_port *port)
{ byte c;
int n;
do {
c = inportb(port->RDR);
switch (port->control_type)
{ case NO_CONTROL :
queue_put_(port->InBuf,&c);
port->in_cnt++;
break;
case XON_XOFF : // XON/XOFF
if (c==XON_ASCII)
{ port->xonxoff_rcvd=XON_RCVD;
interrupt_on(port,THREINT);
return;
}
if (c==XOFF_ASCII)
{ port->xonxoff_rcvd=XOFF_RCVD;
interrupt_off(port,THREINT);
return;
}
n=queue_put_(port->InBuf,&c);
port->in_cnt++;
if (n) //buffer is near full
{ if (port->xonxoff_send!=XOFF_SENT)
{ port->xoff=1;
interrupt_on(port,THREINT);
}
}
break;
case RTS_CTS:
n=queue_put_(port->InBuf,&c);
port->in_cnt++;
if (n) //buffer is near full
{ outportb(port->MCR,inportb(port->MCR)&(~0x02)); //dropping RTS
port->rts=RTS_OFF;
}
break;
default :
break;
}
c =inportb(port->LSR);
} while (c & 1);
// these lines are a cure for the well-known problem of TX interrupt
// lock-ups when receiving and transmitting at the same time
if (c & 0x40)
comm_port_trx(port);
}
static END_OF_FUNCTION(comm_port_rdr)
//----------------------- COMM PORT TRX ------------------------
static inline void comm_port_trx(comm_port *port)
{ byte c;
int i, count = port->fifo ? 16 : 1;
for (i = count; i--; ) {
switch (port->control_type)
{ case NO_CONTROL :
if (queue_empty(port->OutBuf))//queue empty, nothig to send
{ interrupt_off(port,THREINT);
return;
}
queue_get_(port->OutBuf, &c);
port->out_cnt++;
outportb(port->THR,c);
break;
case XON_XOFF : // XON/XOFF
if (port->xoff==1)
{ outportb(port->THR,XOFF_ASCII);
port->xoff=0;
port->xonxoff_send=XOFF_SENT;
}
else if (port->xon==1)
{ outportb(port->THR,XON_ASCII);
port->xon=0;
port->xonxoff_send=XON_SENT;
return;
}
if (queue_empty(port->OutBuf))//queue empty, nothig to send
{ interrupt_off(port,THREINT);
return;
}
queue_get_(port->OutBuf, &c);
outportb(port->THR,c);
port->out_cnt++;
break;
case RTS_CTS:
if (port->cts==CTS_OFF)
{ return;
}
if (port->rts==RTS_OFF)
{ port->rts=RTS_ON;
outportb(port->MCR,inportb(port->MCR)|0x02); //setting RTS
}
if (queue_empty(port->OutBuf))//queue empty, nothig to send
{ outportb(port->MCR,inportb(port->MCR)&(~0x02)); //dropping RTS
port->rts=RTS_OFF;
interrupt_off(port,THREINT);
return;
}
queue_get_(port->OutBuf, &c);
outportb(port->THR,c);
port->out_cnt++;
break;
default :
break;
}
}
}
static END_OF_FUNCTION(comm_port_trx);
//------------------------- COMM PORT INIT -----------------------------
void dzcomm_init(void)
{
LOCK_FUNCTION(dz_comm_port_interrupt_handler);
LOCK_FUNCTION(comm_port_rdr);
LOCK_FUNCTION(comm_port_trx);
LOCK_FUNCTION(interrupt_on);
LOCK_FUNCTION(interrupt_off);
LOCK_FUNCTION(com1_wrapper);
LOCK_FUNCTION(com2_wrapper);
LOCK_FUNCTION(com3_wrapper);
LOCK_FUNCTION(com4_wrapper);
LOCK_FUNCTION(com5_wrapper);
LOCK_FUNCTION(com6_wrapper);
LOCK_FUNCTION(com7_wrapper);
LOCK_FUNCTION(com8_wrapper);
LOCK_VARIABLE(com1);
LOCK_VARIABLE(com2);
LOCK_VARIABLE(com3);
LOCK_VARIABLE(com4);
LOCK_VARIABLE(com5);
LOCK_VARIABLE(com6);
LOCK_VARIABLE(com7);
LOCK_VARIABLE(com8);
com1=NULL;
com2=NULL;
com3=NULL;
com4=NULL;
com5=NULL;
com6=NULL;
com7=NULL;
com8=NULL;
com_wrapper[0]=com1_wrapper;
com_wrapper[1]=com2_wrapper;
com_wrapper[2]=com3_wrapper;
com_wrapper[3]=com4_wrapper;
com_wrapper[4]=com5_wrapper;
com_wrapper[5]=com6_wrapper;
com_wrapper[6]=com7_wrapper;
com_wrapper[7]=com8_wrapper;
com_port[0]=&com1;
com_port[1]=&com2;
com_port[2]=&com3;
com_port[3]=&com4;
com_port[4]=&com5;
com_port[5]=&com6;
com_port[6]=&com7;
com_port[7]=&com8;
}
//----------------------- COMM PORT UNINSTALL ---------------------
// New routine to allow uninstalling without deleting
// and to simplyfy _delete and _reinstall
// by Neil Townsend
void comm_port_uninstall(comm_port *port)
{ comm_port *i_port;
if (port->installed==NO) return;
i_port = irq_bot_com_port[port->nIRQ];
DISABLE();
if (i_port == port)
{ irq_bot_com_port[port->nIRQ] = (comm_port *) port->last_port;
if (irq_bot_com_port[port->nIRQ]) irq_bot_com_port[port->nIRQ]->next_port = NULL;
i_port = NULL;
}
else i_port = (comm_port *) i_port->last_port;
while (i_port)
{ if (i_port == port)
{ if (i_port->last_port) ((comm_port *)i_port->last_port)->next_port = i_port->next_port;
if (i_port->next_port) ((comm_port *)i_port->next_port)->last_port = i_port->last_port;
i_port = NULL;
}
if (i_port) i_port = i_port->last_port;
}
if (irq_bot_com_port[port->nIRQ] == NULL) _remove_irq(port->nIRQVector);
{ const byte IEROFF=0x00;
const byte MCROFF=0x00;
outportb(port->IER,IEROFF);
outportb(port->MCR,MCROFF);
outportb(port->IMR_8259,inportb(port->IMR_8259)&~(port->interrupt_enable_mask));
}
ENABLE();
port->installed = NO;
}
//----------------------- COMM PORT REINSTALL ---------------------------
int comm_port_reinstall(comm_port *port)
{
if (port->installed==NO) return(0);
comm_port_uninstall(port);
return (comm_port_install_handler(port));
}