void sab8253x_startS(struct tty_struct *tty)
{
	struct sab_port *port = (struct sab_port *)tty->driver_data;
	
	if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_start"))
	{
		return;
	}
	sab8253x_start_txS(port);
}
예제 #2
0
void sab8253x_transmit_charsS(struct sab_port *port,
			      union sab8253x_irq_status *stat)
{
	if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) 
	{
		port->interrupt_mask1 |= SAB82532_IMR1_ALLS;
		WRITEB(port, imr1, port->interrupt_mask1);
		port->all_sent = 1;
	}
	sab8253x_start_txS(port);
}
void sab8253x_send_xcharS(struct tty_struct *tty, char ch)
{
	struct sab_port *port = (struct sab_port *)tty->driver_data;
	unsigned long flags;
	int stopped;
	int hw_stopped;
	
	if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_send_xcharS"))
	{
		return;
	}
	
	if (!tty)
	{
		return;
	}
	
	if(port->sabnext2.transmit == NULL)
	{
		return;
	}
	
	save_flags(flags); cli();
	
	if((port->sabnext2.transmit->Count & OWNER) == OWN_SAB) /* may overwrite a character
								 * -- but putting subsequent
								 * XONs or XOFFs later in the
								 * stream could cause problems
								 * with the XON and XOFF protocol */
	{
		port->sabnext2.transmit->sendcrc = 1;
		port->sabnext2.transmit->crcindex = 3;
		port->sabnext2.transmit->crc = (ch << 24); /* LITTLE ENDIAN */
		restore_flags(flags);
	}
	else
	{
		restore_flags(flags);
		sab8253x_writeS(tty, 0, &ch, 1);
	}
	
	stopped = tty->stopped;
	hw_stopped = tty->hw_stopped;
	tty->stopped = 0;
	tty->hw_stopped = 0;
	
	sab8253x_start_txS(port);
	
	tty->stopped = stopped;
	tty->hw_stopped = hw_stopped;
}
void sab8253x_flush_charsS(struct tty_struct *tty)
{
	struct sab_port *port = (struct sab_port *)tty->driver_data;
	
	if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_flush_chars"))
	{
		return;
	}
	
	if ((Sab8253xCountTransmit(port) <= 0) || tty->stopped || tty->hw_stopped)
	{				/* can't flush */
		return;
	}
	
	sab8253x_start_txS(port);
}
int sab8253x_writeS(struct tty_struct * tty, int from_user,
		    const unsigned char *buf, int count)
{
	struct sab_port *port = (struct sab_port *)tty->driver_data;
	struct sk_buff *skb;
	int truelength = 0;
	int do_queue = 1;
	
	if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_write"))
	{
		return 0;
	}
	
	if(count == 0)
	{
		return 0;
	}
	
	if(port->active2.transmit == NULL)
	{
		return 0;
	}
	
	if((port->active2.transmit->Count & OWNER) == OWN_SAB)
	{
		sab8253x_start_txS(port);	/* no descriptor slot */
		return 0;
	}
	
#ifndef FREEININTERRUPT
	skb = port->active2.transmit->HostVaddr; /* current slot value */
	
	if(port->buffergreedy == 0)	/* are we avoiding buffer free's */
	{				/* no */
		if((skb != NULL) || /* not OWN_SAB from above */
		   (port->active2.transmit->crcindex != 0)) 
		{
			register RING_DESCRIPTOR *freeme;
			
			freeme = port->active2.transmit;
			do
			{
				if((freeme->crcindex == 0) && (freeme->HostVaddr == NULL))
				{
					break;
				}
				if(freeme->HostVaddr)
				{
					skb_unlink((struct sk_buff*)freeme->HostVaddr);
					dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr);
					freeme->HostVaddr = NULL;
				}
				freeme->sendcrc = 0;
				freeme->crcindex = 0;
				freeme = (RING_DESCRIPTOR*) freeme->VNext;
			}
			while((freeme->Count & OWNER) != OWN_SAB);
		}
		skb = NULL;		/* buffer was freed */
	}
	
	if(skb != NULL)		/* potentially useful */
	{
		truelength = (skb->end - skb->head);
		if(truelength >= count)
		{
			skb->data = skb->head; /* this buffer is already queued */
			skb->tail = skb->head;
			do_queue = 0;
		}
		else
		{
			skb_unlink(skb);
			dev_kfree_skb_any(skb);
			skb = NULL;
			port->active2.transmit->HostVaddr = NULL;
		}
	}
	/* in all cases the following is allowed */
	port->active2.transmit->sendcrc = 0;
	port->active2.transmit->crcindex = 0;
#endif
	
	if(skb == NULL)
	{
		if(port->DoingInterrupt)
		{
			skb = alloc_skb(count, GFP_ATOMIC);
		}
		else
		{
			skb = alloc_skb(count, GFP_KERNEL);
		}
	}
	
	if(skb == NULL)
	{
		printk(KERN_ALERT "sab8253xs: no skbuffs available.\n");
		return 0;
	}
	if(from_user)
	{
		copy_from_user(skb->data, buf, count);
	}
	else
	{
		memcpy(skb->data, buf, count);
	}
	skb->tail = (skb->data + count);
	skb->data_len = count;
	skb->len = count;
	
	if(do_queue)
	{
		skb_queue_head(port->sab8253xbuflist, skb);
	}
	
	port->active2.transmit->HostVaddr = skb;
	port->active2.transmit->sendcrc = 0;
	port->active2.transmit->crcindex = 0;
	port->active2.transmit->Count = (OWN_SAB|count);
	port->active2.transmit = port->active2.transmit->VNext;
	
	sab8253x_start_txS(port);
	return count;
}
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;
				}
			}
		}
	}
}
예제 #7
0
				/* not do -- makes minimum  64 bytes add crc, etc*/
int 
sab8253xn_write2(struct sk_buff *skb, struct net_device *dev)
{
	size_t cnt;
	unsigned int flags;
	SAB_PORT *priv = (SAB_PORT*) dev->priv;
	struct sk_buff *substitute;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
	if(dev->tbusy != 0)		/* something of an error */
	{
		++(priv->Counters.tx_drops);
		dev_kfree_skb_any(skb);
		return -EBUSY;		/* only during release */
	}
#endif

	if(priv->active2.transmit == NULL)
	{
		return -ENOMEM;
	}
	
	DEBUGPRINT((KERN_ALERT "sab8253x: sending IP packet(bytes):\n"));

	DEBUGPRINT((KERN_ALERT "sab8253x: start address is %p.\n", skb->data));
	
	cnt = skb->tail - skb->data;
	cnt = MIN(cnt, sab8253xn_rbufsize);
	if(cnt < ETH_ZLEN)
	{
		if((skb->end - skb->data) >= ETH_ZLEN)
		{
			skb->tail = (skb->data + ETH_ZLEN);
			cnt = ETH_ZLEN;
		}
		else
		{
			substitute = dev_alloc_skb(ETH_ZLEN);
			if(substitute == NULL)
			{
				dev_kfree_skb_any(skb);
				return 0;
			}
			substitute->tail = (substitute->data + ETH_ZLEN);
			memcpy(substitute->data, skb->data, cnt);
			cnt = ETH_ZLEN;
			dev_kfree_skb_any(skb);
			skb = substitute;
		}
	}
	
	save_flags(flags); cli();
	if((priv->active2.transmit->Count & OWNER) == OWN_SAB)
	{
		++(priv->Counters.tx_drops);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
		dev->tbusy = 1;
#else
		netif_stop_queue (dev);
#endif
		priv->tx_full = 1;
		restore_flags(flags);
		return 1;
	}
	restore_flags(flags);
#ifndef FREEINTERRUPT
	if(priv->active2.transmit->HostVaddr != NULL)
	{
		register RING_DESCRIPTOR *freeme;
		
		freeme = priv->active2.transmit;
		do
		{
			skb_unlink((struct sk_buff*)freeme->HostVaddr);
			dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr);
			freeme->HostVaddr = NULL;
			freeme = (RING_DESCRIPTOR*) freeme->VNext;
		}
		while(((freeme->Count & OWNER) != OWN_SAB) &&
		      (freeme->HostVaddr != NULL));
	}
#endif
	dev->trans_start = jiffies;
	skb_queue_head(priv->sab8253xbuflist, skb);
	priv->active2.transmit->HostVaddr = skb;
	priv->active2.transmit->sendcrc = 1;
	priv->active2.transmit->crcindex = 0;
	priv->active2.transmit->crc = fn_calc_memory_crc32(skb->data, cnt);
	priv->active2.transmit->Count = (OWN_SAB|cnt); /* must be this order */
	priv->active2.transmit = 
		(RING_DESCRIPTOR*) priv->active2.transmit->VNext;
	priv->Counters.transmitbytes += cnt;
	sab8253x_start_txS(priv);
	return 0;
}
예제 #8
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
}