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

📄 tsksio.c

📁 一个多任务操作系统CTask的源代码 用C语言编写
💻 C
📖 第 1 页 / 共 2 页
字号:
         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 + -