コード例 #1
0
static void sab8253x_check_statusS(struct sab_port *port,
			    union sab8253x_irq_status *stat)
{
	struct tty_struct *tty = port->tty;
	int modem_change = 0;
	mctlsig_t         *sig;
	
	if (!tty)
	{
		return;
	}
	
	/* check_modem:*/
	/* Checking DCD */
	sig = &port->dcd;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,dcd);
		port->icount.dcd++;
		modem_change++;
	}
	/* Checking CTS */
	sig = &port->cts;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,cts);
		port->icount.cts++;
		modem_change++;
	}
	/* Checking DSR */
	sig = &port->dsr;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,dsr);
		port->icount.dsr++;
		modem_change++;
	}
	if (modem_change)
	{
		wake_up_interruptible(&port->delta_msr_wait);
	}
	
	sig = &port->dcd;
	if ((port->flags & FLAG8253X_CHECK_CD) &&
	    (stat->images[sig->irq] & sig->irqmask)) 
	{
		
		if (sig->val)
		{
			wake_up_interruptible(&port->open_wait);
		}
		else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
			   (port->flags & FLAG8253X_CALLOUT_NOHUP))) 
		{
#if 0				/* requires more investigation */
			MOD_INC_USE_COUNT;
			if (schedule_task(&port->tqueue_hangup) == 0)
			{
				MOD_DEC_USE_COUNT;
			}
#endif
		}
	}
	
	sig = &port->cts;
	if (port->flags & FLAG8253X_CTS_FLOW) 
	{				/* not setting this yet */
		if (port->tty->hw_stopped) 
		{
			if (sig->val) 
			{
				port->tty->hw_stopped = 0;
				sab8253x_sched_event(port, SAB8253X_EVENT_WRITE_WAKEUP);
				sab8253x_start_txS(port);
			}
		} 
		
		else 
		{
			if(!(getccr2configS(port) & SAB82532_CCR2_TOE))
			{
				if (!(sig->val)) 
				{
					port->tty->hw_stopped = 1;
				}
			}
		}
	}
}
コード例 #2
0
void sab8253x_start_txS(struct sab_port *port)
{
	unsigned long flags;
	register int count;
	register int total;
	register int offset;
	char temporary[32];
	register unsigned int slopspace;
	register int sendsize;
	unsigned int totaltransmit;
	unsigned fifospace;
	unsigned loadedcount;
	struct tty_struct *tty = port->tty; /* a little gross tty flags whether
					       invoked from a tty or the network */
	
	fifospace = port->xmit_fifo_size; /* This code can handle fragmented frames
					     although currently none are generated*/
	loadedcount = 0;
	
	if(port->sabnext2.transmit == NULL)
	{
		return;
	}
	
	save_flags(flags); 
	cli();			
	
	
	if(count = port->sabnext2.transmit->Count, (count & OWNER) == OWN_SAB)
	{
		count &= ~OWN_SAB; /* OWN_SAB is really 0 but cannot guarantee in the future */
		
		if(port->sabnext2.transmit->HostVaddr)
		{
			total = (port->sabnext2.transmit->HostVaddr->tail - 
				 port->sabnext2.transmit->HostVaddr->data); /* packet size */
		}
		else
		{
			total = 0;		/* the data is only the crc/trailer */
		}
		
		if(tty && (tty->stopped || tty->hw_stopped) && (count == total))
		{			/* works for frame that only has a trailer (crc) */
			port->interrupt_mask1 |= SAB82532_IMR1_XPR;
			WRITEB(port, imr1, port->interrupt_mask1);
			restore_flags(flags);	/* can't send */
			return;
		}
		
		offset = (total - count);	/* offset to data still to send */
		
		port->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
		WRITEB(port, imr1, port->interrupt_mask1);
		port->all_sent = 0;
		
		if(READB(port,star) & SAB82532_STAR_XFW)
		{
			if(count <= fifospace)
			{
				port->xmit_cnt = count;
				slopspace = 0;
				sendsize = 0;
				if(port->sabnext2.transmit->sendcrc) 
				/* obviously should not happen for async but might use for
				   priority transmission */
				{
					slopspace = fifospace - count;
				}
				if(slopspace)
				{
					if(count)
					{
						memcpy(temporary, &port->sabnext2.transmit->HostVaddr->data[offset], 
						       count);
					}
					sendsize = MIN(slopspace, (4 - port->sabnext2.transmit->crcindex)); 
				/* how many bytes to send */
					memcpy(&temporary[count], 
					       &((unsigned char*)(&port->sabnext2.transmit->crc))
					       [port->sabnext2.transmit->crcindex], 
					       sendsize);
					port->sabnext2.transmit->crcindex += sendsize;
					if(port->sabnext2.transmit->crcindex >= 4)
					{
						port->sabnext2.transmit->sendcrc = 0;
					}
					port->xmit_buf = temporary;
				}
				else
				{
					port->xmit_buf =	/* set up wrifefifo variables */
						&port->sabnext2.transmit->HostVaddr->data[offset];
				}
				port->xmit_cnt += sendsize;
				count = 0;
			}
			else
			{
				count -= fifospace;
				port->xmit_cnt = fifospace;
				port->xmit_buf =	/* set up wrifefifo variables */
					&port->sabnext2.transmit->HostVaddr->data[offset];
				
			}
			port->xmit_tail= 0;
			loadedcount = port->xmit_cnt;
			(*port->writefifo)(port);
			totaltransmit = Sab8253xCountTransmitDescriptors(port);
			if(tty && (totaltransmit < (sab8253xs_listsize/2))) /* only makes sense on a TTY */
			{
				sab8253x_sched_event(port, SAB8253X_EVENT_WRITE_WAKEUP);
			}
			
			if((sab8253xt_listsize - totaltransmit) > (sab8253xt_listsize/2))
			{
				port->buffergreedy = 0;
			}
			else
			{
				port->buffergreedy = 1;
			}
			
			port->xmit_buf = NULL; /* this var is used to indicate whether to call kfree */
			
			/* fifospace -= loadedcount;*/
			/* Here to make mods to handle arbitrarily fragmented frames look to 8253xtty.c for help */
			
			if ((count <= 0) && (port->sabnext2.transmit->sendcrc == 0))
			{
				port->sabnext2.transmit->Count = OWN_DRIVER;
				if(!tty)
				{		/* called by network driver */
					++(port->Counters.transmitpacket);
				}
#ifdef FREEININTERRUPT		/* treat this routine as if taking place in interrupt */
				if(port->sabnext2.transmit->HostVaddr)
				{
					skb_unlink(port->sabnext2.transmit->HostVaddr);
					dev_kfree_skb_any(port->sabnext2.transmit->HostVaddr);
					port->sabnext2.transmit->HostVaddr = 0; /* no skb */
				}
				port->sabnext2.transmit->crcindex = 0; /* no single byte */
#endif
				sab8253x_cec_wait(port);
				WRITEB(port, cmdr, SAB82532_CMDR_XME|SAB82532_CMDR_XTF); /* Terminate the frame */
				
				port->sabnext2.transmit = port->sabnext2.transmit->VNext;
				
				if(!tty && port->tx_full)	/* invoked from the network driver */
				{
					port->tx_full = 0; /* there is a free slot */
					switch(port->open_type)
					{
					case OPEN_SYNC_NET:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
						port->dev->start = 1;
						port->dev->tbusy = 0;	/* maybe need mark_bh here */
#else
						netif_start_queue(port->dev);
#endif
						break;
						
					case OPEN_SYNC_CHAR:
						wake_up_interruptible(&port->write_wait);
						break;
						
					default:
						break;
					}
				}
				
				if((port->sabnext2.transmit->Count & OWNER) == OWN_SAB)
				{		/* new frame to send */
					port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
					WRITEB(port, imr1, port->interrupt_mask1);
				}
				else
				{
					port->interrupt_mask1 |= SAB82532_IMR1_XPR;
					WRITEB(port, imr1, port->interrupt_mask1);
					if((port->open_type == OPEN_SYNC_CHAR) && port->async_queue)
					{		/* if indication of transmission is needed by the */
						/* application on a per-frame basis kill_fasync */
						/* can provide it */
						kill_fasync(&port->async_queue, SIGIO, POLL_OUT);
					}
				}
				restore_flags(flags);
				return;
			}
			/* Issue a Transmit FIFO command. */
			sab8253x_cec_wait(port);
			WRITEB(port, cmdr, SAB82532_CMDR_XTF);	
			port->sabnext2.transmit->Count = (count|OWN_SAB);
		}
		port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); /* more to send */
		WRITEB(port, imr1, port->interrupt_mask1);
	}
	else
	{				/* nothing to send */
		port->interrupt_mask1 |= SAB82532_IMR1_XPR;
		WRITEB(port, imr1, port->interrupt_mask1);
	}
	restore_flags(flags);
	return;
}
コード例 #3
0
static void sab8253x_check_statusN(struct sab_port *port,
				   union sab8253x_irq_status *stat)
{
	int modem_change = 0;
	mctlsig_t         *sig;
	
	
	if (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO) 
	{
		port->icount.buf_overrun++;
	}
	
	/* Checking DCD */
	sig = &port->dcd;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,dcd);
		port->icount.dcd++;
		modem_change++;
	}
	/* Checking CTS */
	sig = &port->cts;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,cts);
		port->icount.cts++;
		modem_change++;
	}
	/* Checking DSR */
	sig = &port->dsr;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,dsr);
		port->icount.dsr++;
		modem_change++;
	}
	if (modem_change)
	{
		wake_up_interruptible(&port->delta_msr_wait);
	}
	
	sig = &port->dcd;
	if ((port->flags & FLAG8253X_CHECK_CD) &&
	    (stat->images[sig->irq] & sig->irqmask)) 
	{
		
		if (sig->val)
		{
			netif_carrier_on(port->dev);
		}
		else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
			   (port->flags & FLAG8253X_CALLOUT_NOHUP))) 
		{
			netif_carrier_off(port->dev);
		}
	}
#if 0				/* need to think about CTS/RTS stuff for a network driver */
	sig = &port->cts;
	if (port->flags & FLAG8253X_CTS_FLOW) 
	{				/* not setting this yet */
		if (port->tty->hw_stopped) 
		{
			if (sig->val) 
			{
				
				port->tty->hw_stopped = 0;
				sab8253x_sched_event(port, RS_EVENT_WRITE_WAKEUP);
				port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
				WRITEB(port, imr1, port->interrupt_mask1);
				sab8253x_start_txS(port);
			}
		} 
		else 
		{
			if (!(sig->val)) 
			{
				port->tty->hw_stopped = 1;
			}
		}
	}
#endif
}