📄 tsksio.c
字号:
portp = portp->next;
}
if (portp->sio != LNULL) /* Port already in use ? */
return LNULL;
if (port < STATIC_PORTS)
portp->sio = sio = &sio_data [port];
else
#if (TSK_DYNAMIC)
if ((portp->sio = sio = (sioptr)tsk_palloc (sizeof (sio_datarec))) == LNULL)
return LNULL;
#else
return LNULL;
#endif
pbase = sio->port_base = portp->base;
sio->port = portp;
/* Check if port accessible by modifying the modem control register */
i = sio->cmodcontrol = sio->save_mcon = tsk_inp (pbase + modemcontrol);
if (i & 0xe0)
return ret_error (sio);
tsk_nop ();
tsk_outp (pbase + modemcontrol, 0xe0 | i);
tsk_nop ();
if (tsk_inp (pbase + modemcontrol) != (byte) i)
return ret_error (sio);
/* Port seems OK */
if (create_pipe (&sio->xmit_pipe, xmitbuf, xmitsize TN(xname)) == LNULL)
return ret_error (sio);
if (create_wpipe (&sio->rcv_pipe, rcvbuf, rcvsize TN(rname)) == LNULL)
{
delete_pipe (&sio->xmit_pipe);
return ret_error (sio);
}
sio->civect = portp->vector;
sio->irqbit = (byte)(1 << (portp->irq & 0x07));
sio->wait_xmit = sio->xmit_pending = 0;
sio->overrun = 0;
sio->flags = 0;
sio->modem_flags = 0;
sio->r_xoff = sio->t_xoff = 0;
sio->rtsoff = 0;
sio->clcontrol = sio->save_lcon = tsk_inp (pbase + linecontrol);
tsk_nop ();
sio->save_inten = tsk_inp (pbase + intenable);
tsk_nop ();
if (init)
{
sio->clcontrol = dflt_lcon;
sio->cmodcontrol = dflt_modcon;
}
tsk_outp (pbase + linecontrol, sio->clcontrol | 0x80);
tsk_nop ();
sio->save_bd1 = tsk_inp (pbase + baudreg_dll);
tsk_nop ();
sio->save_bd2 = tsk_inp (pbase + baudreg_dlm);
tsk_nop ();
tsk_outp (pbase + linecontrol, sio->clcontrol);
tsk_nop ();
tsk_outp (pbase + intenable, 0);
if (irq_array [portp->irq] == LNULL)
{
intptr = (intprocptr far *)TMK_FP (0, sio->civect * 4);
tsk_cli ();
sio->savvect = *intptr;
*intptr = irq_procs [portp->irq];
tsk_sti ();
}
if (init)
{
tsk_outp (pbase + linecontrol, dflt_lcon | 0x80);
tsk_nop ();
tsk_outp (pbase + baudreg_dll, dflt_baud);
tsk_nop ();
tsk_outp (pbase + baudreg_dlm, dflt_baud >> 8);
tsk_nop ();
tsk_outp (pbase + linecontrol, dflt_lcon);
tsk_nop ();
tsk_outp (pbase + modemcontrol, dflt_modcon);
tsk_nop ();
}
else
{
i = tsk_inp (pbase + modemcontrol) | OUT2;
tsk_nop ();
tsk_outp (pbase + modemcontrol, i);
tsk_nop ();
}
while (tsk_inp (pbase + linestatus) & rxreadybit)
{
tsk_nop ();
tsk_inp (pbase + receivedata);
tsk_nop ();
}
tsk_nop ();
tsk_inp (pbase + linestatus);
tsk_nop ();
sio->modstat = tsk_inp (pbase + modemstatus);
tsk_nop ();
tsk_inp (pbase + intid);
tsk_nop ();
inta = (portp->irq > 7) ? inta11 : inta01;
if (irq_array [portp->irq] == LNULL)
{
if (portp->irq > 7)
{
i = tsk_inp (inta01) & ~CHAIN_IRQBIT;
tsk_nop ();
tsk_outp (inta01, i);
}
sio->save_irq = (byte)((i = tsk_inp (inta)) & sio->irqbit);
tsk_nop ();
tsk_outp (inta, i & ~sio->irqbit);
}
else
sio->save_irq = (irq_array [portp->irq])->save_irq;
tsk_cli ();
sio->next = irq_array [portp->irq];
irq_array [portp->irq] = sio;
tsk_sti ();
if (remove_chain.func == LNULL)
chain_removefunc (v24_chain_remove, &remove_chain, NULL);
/* Enable interrupts with correction for possible loss of the
first tranmit interrupt on INS8250 and INS8250-B chips */
for (;;)
{
if (tsk_inp (pbase + linestatus) & txreadybit)
{
break;
}
tsk_nop ();
}
tsk_nop ();
tsk_cli ();
tsk_outp (pbase + intenable, intdata);
tsk_nop ();
tsk_outp (pbase + intenable, intdata);
tsk_sti ();
return sio;
}
void Globalfunc v24_remove (sioptr sio, int restore)
{
intprocptr far *intptr;
int pbase, i, inta;
portptr portp;
sioptr curr, last;
pbase = sio->port_base;
portp = sio->port;
last = LNULL;
curr = irq_array [portp->irq];
while (curr != sio && curr != LNULL)
{
last = curr;
curr = curr->next;
}
if (curr == LNULL)
return;
tsk_outp (pbase + intenable, 0);
tsk_cli ();
if (last == LNULL)
irq_array [portp->irq] = sio->next;
else
last->next = sio->next;
tsk_sti ();
inta = (portp->irq > 7) ? inta11 : inta01;
if (restore)
{
tsk_outp (pbase + modemcontrol, sio->save_mcon);
tsk_nop ();
tsk_outp (pbase + linecontrol, sio->save_lcon | 0x80);
tsk_nop ();
tsk_outp (pbase + baudreg_dll, sio->save_bd1);
tsk_nop ();
tsk_outp (pbase + baudreg_dlm, sio->save_bd2);
tsk_nop ();
tsk_outp (pbase + linecontrol, sio->save_lcon);
tsk_nop ();
if (irq_array [portp->irq] == LNULL)
{
tsk_cli ();
tsk_outp (pbase + intenable, sio->save_inten);
i = tsk_inp (inta) & ~sio->irqbit;
tsk_nop ();
tsk_outp (inta, i | sio->save_irq);
}
}
else if (irq_array [portp->irq] == LNULL)
{
tsk_cli ();
i = tsk_inp (inta) | sio->irqbit;
tsk_nop ();
tsk_outp (inta, i);
}
if (irq_array [portp->irq] == LNULL)
{
tsk_cli ();
intptr = (intprocptr far *)TMK_FP (0, sio->civect * 4);
*intptr = sio->savvect;
}
tsk_sti ();
portp->sio = LNULL;
delete_pipe (&sio->xmit_pipe);
delete_wpipe (&sio->rcv_pipe);
#if (TSK_DYNAMIC)
if (portp->pnum >= STATIC_PORTS)
tsk_pfree (sio);
#endif
}
void Taskfunc v24_remove_all (void)
{
int i;
sioptr sio;
unchain_removefunc (&remove_chain);
for (i = 0; i < MAX_IRQ; i++)
{
while ((sio = irq_array [i]) != LNULL)
v24_remove (sio, RESTORE_DEFAULT);
}
}
/*-------------------------------------------------------------------------*/
/*
void v24_change_rts (sioptr sio, int on)
*/
void Globalfunc v24_change_rts (sioptr sio, int on)
{
sio->cmodcontrol = (byte)((sio->cmodcontrol & ~RTS) | ((on) ? RTS : 0));
tsk_outp (sio->port_base + modemcontrol, sio->cmodcontrol);
}
/*
void v24_change_dtr (sioptr sio, int on)
*/
void Globalfunc v24_change_dtr (sioptr sio, int on)
{
sio->cmodcontrol = (byte)((sio->cmodcontrol & ~DTR) | ((on) ? DTR : 0));
tsk_outp (sio->port_base + modemcontrol, sio->cmodcontrol);
}
/*
void Globalfunc v24_change_baud (sioptr sio, int rate)
*/
void Globalfunc v24_change_baud (sioptr sio, long rate)
{
int i;
v24_wait_complete (sio, 0L);
for (i = 0; baud_table [i]; i += 2)
if (baud_table [i] == rate)
break;
if ((i = (int)baud_table [i + 1]) == 0)
return;
tsk_outp (sio->port_base + linecontrol, sio->clcontrol | (byte)0x80);
tsk_nop ();
tsk_outp (sio->port_base + baudreg_dll, (byte)i);
tsk_nop ();
tsk_outp (sio->port_base + baudreg_dlm, (byte)(i >> 8));
tsk_nop ();
tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
}
void Globalfunc v24_change_parity (sioptr sio, int par)
{
v24_wait_complete (sio, 0L);
sio->clcontrol = (byte)((sio->clcontrol & 0xc7) | par);
tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
}
void Globalfunc v24_change_wordlength (sioptr sio, int len)
{
int i;
v24_wait_complete (sio, 0L);
switch (len)
{
case 5: i = 0x00; break;
case 6: i = 0x01; break;
case 7: i = 0x02; break;
case 8: i = 0x03; break;
default: return;
}
sio->clcontrol = (byte)((sio->clcontrol & 0xfc) | i);
tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
}
void Globalfunc v24_change_stopbits (sioptr sio, int n)
{
int i;
v24_wait_complete (sio, 0L);
switch (n)
{
case 1: i = 0x00; break;
case 2: i = 0x04; break;
default: return;
}
sio->clcontrol = (byte)((sio->clcontrol & 0xfb) | i);
tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
}
void Globalfunc v24_watch_modem (sioptr sio, byte flags)
{
sio->modem_flags = (byte)(flags & (CTS | DSR | RI | CD));
}
void Globalfunc v24_protocol (sioptr sio, int prot, word offthresh, word onthresh)
{
byte old;
old = sio->flags;
sio->flags = (byte)prot;
if (prot)
{
if (!offthresh)
offthresh = 10;
sio->xoff_threshold = offthresh;
if (onthresh <= offthresh)
onthresh = offthresh + 10;
sio->xon_threshold = onthresh;
}
if ((old & RTSCTS) != ((byte)prot & RTSCTS))
{
change_rts (sio, 1);
sio->modem_flags = (byte)((sio->modem_flags & ~CTS) |
((prot & RTSCTS) ? CTS : 0));
}
if (!(prot & XONXOFF))
{
if (sio->r_xoff)
sio->r_xoff = -2;
sio->t_xoff = 0;
}
if (!sio->xmit_pending)
transmit_ready (sio);
}
/*-------------------------------------------------------------------------*/
int Globalfunc v24_send (sioptr sio, byte ch, dword timeout)
{
int res;
if ((res = write_pipe (&sio->xmit_pipe, ch, timeout)) < 0)
return res;
tsk_cli ();
if (!sio->xmit_pending)
transmit_ready (sio);
tsk_sti ();
return 0;
}
int Globalfunc v24_receive (sioptr sio, dword timeout)
{
int res;
if ((res = (int)read_wpipe (&sio->rcv_pipe, timeout)) < 0)
return res;
if (!sio->flags)
return res;
if (wpipe_free (&sio->rcv_pipe) > sio->xon_threshold)
{
tsk_cli ();
if (sio->r_xoff)
{
sio->r_xoff = -2;
if (!sio->xmit_pending)
transmit_ready (sio);
}
tsk_sti ();
if (sio->rtsoff)
change_rts (sio, 1);
}
return res;
}
int Globalfunc v24_overrun (sioptr sio)
{
int res;
res = sio->overrun;
sio->overrun = 0;
return res;
}
int Globalfunc v24_check (sioptr sio)
{
return check_wpipe (&sio->rcv_pipe);
}
int Globalfunc v24_modem_status (sioptr sio)
{
return sio->modstat;
}
int Globalfunc v24_complete (sioptr sio)
{
return (check_pipe (&sio->xmit_pipe) == -1);
}
int Globalfunc v24_wait_complete (sioptr sio, dword timeout)
{
int rc;
rc = wait_pipe_empty (&sio->xmit_pipe, timeout);
if (!rc)
{
while (!(tsk_inp (sio->port_base + linestatus) & TSRE))
yield ();
}
return rc;
}
void Globalfunc v24_flush_receive (sioptr sio)
{
flush_wpipe (&sio->rcv_pipe);
}
void Globalfunc v24_flush_transmit (sioptr sio)
{
flush_pipe (&sio->xmit_pipe);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -