コード例 #1
0
static void z8530_rx_clear(struct z8530_channel *c)
{
	/*
	 *	Data and status bytes
	 */
	u8 stat;

	read_zsdata(c);
	stat=read_zsreg(c, R1);

	if(stat&END_FR)
		write_zsctrl(c, RES_Rx_CRC);
	/*
	 *	Clear irq
	 */
	write_zsctrl(c, ERR_RES);
	write_zsctrl(c, RES_H_IUS);
}
コード例 #2
0
ファイル: pmac_zilog.c プロジェクト: 3sOx/asuswrt-merlin
static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
{
	struct tty_struct *tty = NULL;
	unsigned char ch, r1, drop, error, flag;
	int loops = 0;

	/* The interrupt can be enabled when the port isn't open, typically
	 * that happens when using one port is open and the other closed (stale
	 * interrupt) or when one port is used as a console.
	 */
	if (!ZS_IS_OPEN(uap)) {
		pmz_debug("pmz: draining input\n");
		/* Port is closed, drain input data */
		for (;;) {
			if ((++loops) > 1000)
				goto flood;
			(void)read_zsreg(uap, R1);
			write_zsreg(uap, R0, ERR_RES);
			(void)read_zsdata(uap);
			ch = read_zsreg(uap, R0);
			if (!(ch & Rx_CH_AV))
				break;
		}
		return NULL;
	}

	/* Sanity check, make sure the old bug is no longer happening */
	if (uap->port.info == NULL || uap->port.info->tty == NULL) {
		WARN_ON(1);
		(void)read_zsdata(uap);
		return NULL;
	}
	tty = uap->port.info->tty;

	while (1) {
		error = 0;
		drop = 0;

		r1 = read_zsreg(uap, R1);
		ch = read_zsdata(uap);

		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
			write_zsreg(uap, R0, ERR_RES);
			zssync(uap);
		}

		ch &= uap->parity_mask;
		if (ch == 0 && uap->flags & PMACZILOG_FLAG_BREAK) {
			uap->flags &= ~PMACZILOG_FLAG_BREAK;
		}

#if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_SERIAL_CORE_CONSOLE)
#ifdef USE_CTRL_O_SYSRQ
		/* Handle the SysRq ^O Hack */
		if (ch == '\x0f') {
			uap->port.sysrq = jiffies + HZ*5;
			goto next_char;
		}
#endif /* USE_CTRL_O_SYSRQ */
		if (uap->port.sysrq) {
			int swallow;
			spin_unlock(&uap->port.lock);
			swallow = uart_handle_sysrq_char(&uap->port, ch);
			spin_lock(&uap->port.lock);
			if (swallow)
				goto next_char;
 		}
#endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */

		/* A real serial line, record the character and status.  */
		if (drop)
			goto next_char;

		flag = TTY_NORMAL;
		uap->port.icount.rx++;

		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) {
			error = 1;
			if (r1 & BRK_ABRT) {
				pmz_debug("pmz: got break !\n");
				r1 &= ~(PAR_ERR | CRC_ERR);
				uap->port.icount.brk++;
				if (uart_handle_break(&uap->port))
					goto next_char;
			}
			else if (r1 & PAR_ERR)
				uap->port.icount.parity++;
			else if (r1 & CRC_ERR)
				uap->port.icount.frame++;
			if (r1 & Rx_OVR)
				uap->port.icount.overrun++;
			r1 &= uap->port.read_status_mask;
			if (r1 & BRK_ABRT)
				flag = TTY_BREAK;
			else if (r1 & PAR_ERR)
				flag = TTY_PARITY;
			else if (r1 & CRC_ERR)
				flag = TTY_FRAME;
		}

		if (uap->port.ignore_status_mask == 0xff ||
		    (r1 & uap->port.ignore_status_mask) == 0) {
		    	tty_insert_flip_char(tty, ch, flag);
		}
		if (r1 & Rx_OVR)
			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
	next_char:
		/* We can get stuck in an infinite loop getting char 0 when the
		 * line is in a wrong HW state, we break that here.
		 * When that happens, I disable the receive side of the driver.
		 * Note that what I've been experiencing is a real irq loop where
		 * I'm getting flooded regardless of the actual port speed.
		 * Something stange is going on with the HW
		 */
		if ((++loops) > 1000)
			goto flood;
		ch = read_zsreg(uap, R0);
		if (!(ch & Rx_CH_AV))
			break;
	}

	return tty;
 flood:
	uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
	write_zsreg(uap, R1, uap->curregs[R1]);
	zssync(uap);
	dev_err(&uap->dev->ofdev.dev, "pmz: rx irq flood !\n");
	return tty;
}
コード例 #3
0
ファイル: pmac_zilog.c プロジェクト: 3sOx/asuswrt-merlin
/*
 * Set the irda codec on the imac to the specified baud rate.
 */
static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
{
	u8 cmdbyte;
	int t, version;

	switch (*baud) {
	/* SIR modes */
	case 2400:
		cmdbyte = 0x53;
		break;
	case 4800:
		cmdbyte = 0x52;
		break;
	case 9600:
		cmdbyte = 0x51;
		break;
	case 19200:
		cmdbyte = 0x50;
		break;
	case 38400:
		cmdbyte = 0x4f;
		break;
	case 57600:
		cmdbyte = 0x4e;
		break;
	case 115200:
		cmdbyte = 0x4d;
		break;
	/* The FIR modes aren't really supported at this point, how
	 * do we select the speed ? via the FCR on KeyLargo ?
	 */
	case 1152000:
		cmdbyte = 0;
		break;
	case 4000000:
		cmdbyte = 0;
		break;
	default: /* 9600 */
		cmdbyte = 0x51;
		*baud = 9600;
		break;
	}

	/* Wait for transmitter to drain */
	t = 10000;
	while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0
	       || (read_zsreg(uap, R1) & ALL_SNT) == 0) {
		if (--t <= 0) {
			dev_err(&uap->dev->ofdev.dev, "transmitter didn't drain\n");
			return;
		}
		udelay(10);
	}

	/* Drain the receiver too */
	t = 100;
	(void)read_zsdata(uap);
	(void)read_zsdata(uap);
	(void)read_zsdata(uap);
	mdelay(10);
	while (read_zsreg(uap, R0) & Rx_CH_AV) {
		read_zsdata(uap);
		mdelay(10);
		if (--t <= 0) {
			dev_err(&uap->dev->ofdev.dev, "receiver didn't drain\n");
			return;
		}
	}

	/* Switch to command mode */
	uap->curregs[R5] |= DTR;
	write_zsreg(uap, R5, uap->curregs[R5]);
	zssync(uap);
       	mdelay(1);

	/* Switch SCC to 19200 */
	pmz_convert_to_zs(uap, CS8, 0, 19200);		
	pmz_load_zsregs(uap, uap->curregs);
       	mdelay(1);

	/* Write get_version command byte */
	write_zsdata(uap, 1);
	t = 5000;
	while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) {
		if (--t <= 0) {
			dev_err(&uap->dev->ofdev.dev,
				"irda_setup timed out on get_version byte\n");
			goto out;
		}
		udelay(10);
	}
	version = read_zsdata(uap);

	if (version < 4) {
		dev_info(&uap->dev->ofdev.dev, "IrDA: dongle version %d not supported\n",
			 version);
		goto out;
	}

	/* Send speed mode */
	write_zsdata(uap, cmdbyte);
	t = 5000;
	while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) {
		if (--t <= 0) {
			dev_err(&uap->dev->ofdev.dev,
				"irda_setup timed out on speed mode byte\n");
			goto out;
		}
		udelay(10);
	}
	t = read_zsdata(uap);
	if (t != cmdbyte)
		dev_err(&uap->dev->ofdev.dev,
			"irda_setup speed mode byte = %x (%x)\n", t, cmdbyte);

	dev_info(&uap->dev->ofdev.dev, "IrDA setup for %ld bps, dongle version: %d\n",
		 *baud, version);

	(void)read_zsdata(uap);
	(void)read_zsdata(uap);
	(void)read_zsdata(uap);

 out:
	/* Switch back to data mode */
	uap->curregs[R5] &= ~DTR;
	write_zsreg(uap, R5, uap->curregs[R5]);
	zssync(uap);

	(void)read_zsdata(uap);
	(void)read_zsdata(uap);
	(void)read_zsdata(uap);
}
コード例 #4
0
static void z8530_rx(struct z8530_channel *c)
{
	u8 ch,stat;

	while(1)
	{
		/* FIFO empty ? */
		if(!(read_zsreg(c, R0)&1))
			break;
		ch=read_zsdata(c);
		stat=read_zsreg(c, R1);

		/*
		 *	Overrun ?
		 */
		if(c->count < c->max)
		{
			*c->dptr++=ch;
			c->count++;
		}

		if(stat&END_FR)
		{

			/*
			 *	Error ?
			 */
			if(stat&(Rx_OVR|CRC_ERR))
			{
				/* Rewind the buffer and return */
				if(c->skb)
					c->dptr=c->skb->data;
				c->count=0;
				if(stat&Rx_OVR)
				{
					printk(KERN_WARNING "%s: overrun\n", c->dev->name);
					c->rx_overrun++;
				}
				if(stat&CRC_ERR)
				{
					c->rx_crc_err++;
					/* printk("crc error\n"); */
				}
				/* Shove the frame upstream */
			}
			else
			{
				/*
				 *	Drop the lock for RX processing, or
		 		 *	there are deadlocks
		 		 */
				z8530_rx_done(c);
				write_zsctrl(c, RES_Rx_CRC);
			}
		}
	}
	/*
	 *	Clear irq
	 */
	write_zsctrl(c, ERR_RES);
	write_zsctrl(c, RES_H_IUS);
}
コード例 #5
0
ファイル: pmac_zilog.c プロジェクト: BackupTheBerlios/tuxap
static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
					    struct pt_regs *regs)
{
	struct tty_struct *tty = NULL;
	unsigned char ch, r1, drop, error;
	int loops = 0;

 retry:
	/* The interrupt can be enabled when the port isn't open, typically
	 * that happens when using one port is open and the other closed (stale
	 * interrupt) or when one port is used as a console.
	 */
	if (!ZS_IS_OPEN(uap)) {
		pmz_debug("pmz: draining input\n");
		/* Port is closed, drain input data */
		for (;;) {
			if ((++loops) > 1000)
				goto flood;
			(void)read_zsreg(uap, R1);
			write_zsreg(uap, R0, ERR_RES);
			(void)read_zsdata(uap);
			ch = read_zsreg(uap, R0);
			if (!(ch & Rx_CH_AV))
				break;
		}
		return NULL;
	}

	/* Sanity check, make sure the old bug is no longer happening */
	if (uap->port.info == NULL || uap->port.info->tty == NULL) {
		WARN_ON(1);
		(void)read_zsdata(uap);
		return NULL;
	}
	tty = uap->port.info->tty;

	while (1) {
		error = 0;
		drop = 0;

		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
			/* Have to drop the lock here */
			pmz_debug("pmz: flip overflow\n");
			spin_unlock(&uap->port.lock);
			tty->flip.work.func((void *)tty);
			spin_lock(&uap->port.lock);
			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
				drop = 1;
			if (ZS_IS_ASLEEP(uap))
				return NULL;
			if (!ZS_IS_OPEN(uap))
				goto retry;
		}

		r1 = read_zsreg(uap, R1);
		ch = read_zsdata(uap);

		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
			write_zsreg(uap, R0, ERR_RES);
			zssync(uap);
		}

		ch &= uap->parity_mask;
		if (ch == 0 && uap->prev_status & BRK_ABRT)
			r1 |= BRK_ABRT;

		/* A real serial line, record the character and status.  */
		if (drop)
			goto next_char;

		*tty->flip.char_buf_ptr = ch;
		*tty->flip.flag_buf_ptr = TTY_NORMAL;
		uap->port.icount.rx++;

		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) {
			error = 1;
			if (r1 & BRK_ABRT) {
				pmz_debug("pmz: got break !\n");
				r1 &= ~(PAR_ERR | CRC_ERR);
				uap->port.icount.brk++;
				if (uart_handle_break(&uap->port)) {
					pmz_debug("pmz: do handle break !\n");
					goto next_char;
				}
			}
			else if (r1 & PAR_ERR)
				uap->port.icount.parity++;
			else if (r1 & CRC_ERR)
				uap->port.icount.frame++;
			if (r1 & Rx_OVR)
				uap->port.icount.overrun++;
			r1 &= uap->port.read_status_mask;
			if (r1 & BRK_ABRT)
				*tty->flip.flag_buf_ptr = TTY_BREAK;
			else if (r1 & PAR_ERR)
				*tty->flip.flag_buf_ptr = TTY_PARITY;
			else if (r1 & CRC_ERR)
				*tty->flip.flag_buf_ptr = TTY_FRAME;
		}
		if (uart_handle_sysrq_char(&uap->port, ch, regs)) {
			pmz_debug("pmz: sysrq swallowed the char\n");
			goto next_char;
		}

		if (uap->port.ignore_status_mask == 0xff ||
		    (r1 & uap->port.ignore_status_mask) == 0) {
			tty->flip.flag_buf_ptr++;
			tty->flip.char_buf_ptr++;
			tty->flip.count++;
		}
		if ((r1 & Rx_OVR) &&
		    tty->flip.count < TTY_FLIPBUF_SIZE) {
			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
			tty->flip.flag_buf_ptr++;
			tty->flip.char_buf_ptr++;
			tty->flip.count++;
		}
	next_char:
		/* We can get stuck in an infinite loop getting char 0 when the
		 * line is in a wrong HW state, we break that here.
		 * When that happens, I disable the receive side of the driver.
		 * Note that what I've been experiencing is a real irq loop where
		 * I'm getting flooded regardless of the actual port speed.
		 * Something stange is going on with the HW
		 */
		if ((++loops) > 1000)
			goto flood;
		ch = read_zsreg(uap, R0);
		if (!(ch & Rx_CH_AV))
			break;
	}

	return tty;
 flood:
	uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
	write_zsreg(uap, R1, uap->curregs[R1]);
	zssync(uap);
	dev_err(&uap->dev->ofdev.dev, "pmz: rx irq flood !\n");
	return tty;
}
コード例 #6
0
ファイル: asdg_ser.c プロジェクト: shattered/linux-m68k
int asdg_setup(void)
{
  int i, line1, line2;
  struct SCC *scc=NULL;
  int dummy;
  struct ConfigDev *cd=NULL;
  struct serial_struct req;
  struct async_struct *info=NULL;
  int CardFound=0; 
  
  if (!MACH_IS_AMIGA)
    return -ENODEV;
  
#ifdef DEBUG
  printk("We are a miggy\n");
#endif

  nr_asdg = 0;
  
  while((i=zorro_find(MANUF_ASDG, PROD_TWIN_X,1, 0))) {

    CardFound=1;

    board_index[nr_asdg/2] = i;
    cd = zorro_get_board(i);
    scc = (struct SCC *)ZTWO_VADDR((((volatile u_char *)cd->cd_BoardAddr)));

#ifdef DEBUG
    printk("Found ASDG DSB at %p\n", scc);
#endif
    
    req.line = -1; /* first free ttyS? device */
    req.type = SER_ASDG;
    req.port = (int) &(scc->B);
    if ((line1 = register_serial( &req )) < 0) {
      printk( "Cannot register ASDG serial port: no free device\n" );
      return -EBUSY;
    }
    lines[nr_asdg++] = line1;
    info = &rs_table[line1];
    info->sw = &asdg_ser_switch;
    info->nr_uarts = nr_asdg;
    info->board_base = scc;
    
    req.line = -1; /* first free ttyS? device */
    req.type = SER_ASDG;
    req.port = (int) &(scc->A);
    if ((line2 = register_serial( &req )) < 0) {
      printk( "Cannot register ASDG serial port: no free device\n" );
      unregister_serial( line1 );
      return -EBUSY;
    }
    lines[nr_asdg++] = line2;
    info = &rs_table[line2];
    info->sw = &asdg_ser_switch;
    info->nr_uarts = nr_asdg--;
    info->board_base = scc;
    
    nr_asdg++;
    
    zorro_config_board(i,1);

    /* Clear pointers */
    dummy = scc->A.control;
    dummy = scc->B.control;
    
#ifdef DEBUG
    printk("Pointers cleared \n");
#endif

    /* Reset card */
    write_zsreg(&scc->A, R9, FHWRES | MIE);
    udelay(10); /* Give card time to reset */
    write_zsreg(&scc->B, R9, FHWRES | MIE);
    udelay(10); /* Give card time to reset */

#ifdef DEBUG
    printk("Card reset - MIE on \n");
#endif

    /* Reset all potential interupt sources */
    write_zsreg(&scc->A, R0, RES_EXT_INT);  /* Ext ints (disabled anyways) */
    write_zsreg(&scc->B, R0, RES_EXT_INT); 

#ifdef DEBUG
    printk("Ext ints cleared\n");
#endif

    write_zsreg(&scc->A, R0, RES_Tx_P);     /* TBE int */
    write_zsreg(&scc->B, R0, RES_Tx_P);

#ifdef DEBUG
    printk("TBE Cleared\n");
#endif

    /* Clear Rx FIFO */
    while( (read_zsreg(&scc->A, R0) & Rx_CH_AV) != 0)
      dummy=read_zsdata(&scc->A);
    while( (read_zsreg(&scc->B, R0) & Rx_CH_AV) != 0) 
      dummy=read_zsdata(&scc->B);

#ifdef DEBUG
    printk("Rx buffer empty\n");
#endif
    
    /* TBE and RX int off - we will turn them on in _init()*/
    write_zsreg(&scc->A, R1, 0);
    write_zsreg(&scc->B, R1, 0);

#ifdef DEBUG    
    printk("Tx and Rx ints off \n");
#endif

    /* Interrupt vector */
    write_zsreg(&scc->A, R2, 0);
    write_zsreg(&scc->B, R2, 0);

#ifdef DEBUG
    printk("Int vector set (unused) \n");
#endif

    write_zsreg(&scc->A, R3, Rx8);
    write_zsreg(&scc->B, R3, Rx8);

#ifdef DEBUG
    printk("Rx enabled\n");
#endif

    write_zsreg(&scc->A, R4, SB1 | X16CLK);
    write_zsreg(&scc->B, R4, SB1 | X16CLK);

#ifdef DEBUG
    printk("1 stop bit, x16 clock\n");
#endif

    write_zsreg(&scc->A, R5, Tx8);
    write_zsreg(&scc->B, R5, Tx8);
    
#ifdef DEBUG
    printk("Tx enabled \n");
#endif

    write_zsreg(&scc->A, R10, NRZ); 
    write_zsreg(&scc->B, R10, NRZ); 

#ifdef DEBUG
    printk("NRZ mode\n");
#endif

    write_zsreg(&scc->A, R11, TCBR | RCBR | TRxCBR);
    write_zsreg(&scc->B, R11, TCBR | RCBR | TRxCBR);

#ifdef DEBUG
    printk("Clock source setup\n");
#endif

    /*300 bps */
    write_zsreg(&scc->A, R12, 0xfe);
    write_zsreg(&scc->A, R13, 2);
    write_zsreg(&scc->B, R12, 0xfe);
    write_zsreg(&scc->B, R13, 2);

#ifdef DEBUG
    printk("Baud rate set - 300\n");
#endif

    write_zsreg(&scc->A, R14, BRENABL | BRSRC);
    write_zsreg(&scc->B, R14, BRENABL | BRSRC);

#ifdef DEBUG
    printk("BRG enabled \n");
#endif

    write_zsreg(&scc->A, R15, 0);
    write_zsreg(&scc->A, R15, 0);

#ifdef DEBUG
    printk("Ext INT IE bits cleared \n");
#endif
  }

  if(CardFound) {
    request_irq(IRQ_AMIGA_EXTER, asdg_interrupt, 0, "ASDG serial",
		asdg_interrupt);
    return 0;
  } else {
    printk("No ASDG Cards found\n");
    return -ENODEV;
  }
}
コード例 #7
0
ファイル: asdg_ser.c プロジェクト: shattered/linux-m68k
/* Interrupt Service Routine */
static void asdg_interrupt(int irq, void *data, struct pt_regs *fp)
{
  int i;
  u_char ivec; /* Interrupt vector - not sure if it is needed */
  u_char ip;   /* IP bits from card */
  int ch; /* Received or xmitted char */
  struct SCC *scc;
  struct async_struct *infoA;
  struct async_struct *infoB;

  /* Check all cards */
  for(i=0; i<nr_asdg; i+=2) {

    infoB = &rs_table[lines[i]];
    infoA = &rs_table[lines[i+1]];
    scc = (struct SCC *)infoA->board_base;
    
    ivec=read_zsreg(&scc->B, R2); /* Get Interrupt Vector and ignore it :-) */
    ip=read_zsreg(&scc->A, R3); /* Get IP bits */

    if(ip & CHBEXT) { /* Channel B ext/status */
#ifdef INTDEBUG
      printk("Channel B Ext/Stat");
#endif
      write_zsreg(&scc->B, R0, RES_EXT_INT); 
    }

    if(ip & CHBTxIP) {        /* Channel B TBE */
#ifdef INTDEBUG
      printk("Chan B TBE\n");
#endif
      if( (ch=rs_get_tx_char(infoB)) >=0 ) {
#ifdef INTDEBUG
	//	printk("{%x}", ch);
#endif
	write_zsdata(&scc->B, ch);
      }
      else {
#ifdef INTDEBUG
	//	printk("{%x}", ch);
#endif
	write_zsreg(&scc->B, R0, RES_Tx_P);
      }
    }


    if(ip & CHBRxIP) { /* Channel B Rx Char Avail */
#ifdef INTDEBUG
            printk("Channel B Rx char avail");
#endif
      while( (read_zsreg(&scc->B, R0) & Rx_CH_AV) != 0)
	{
	  ch=read_zsdata(&scc->B);
	  rs_receive_char(infoB, ch , 0);
#ifdef INTDEBUG
	  printk("Received Char Chan B: %c\n", ch);
#endif
	}
    }

    if(ip & CHAEXT) { /* Channel A ext/status */
#ifdef INTDEBUG
      printk("Channel A Ext/Stat");
#endif
      write_zsreg(&scc->A, R0, RES_EXT_INT); 
    }

    if(ip & CHATxIP) {/* Channel A TBE */
#ifdef INTDEBUG
      printk("Chan A TBE\n");
#endif
      if( (ch=rs_get_tx_char(infoA)) >=0) {
#ifdef INTDEBUG
	//	printk("{%x}", ch);
#endif
	write_zsdata(&scc->A, ch);
      }
      else {
#ifdef INTDEBUG
	//	printk("{%x}", ch);
#endif
	write_zsreg(&scc->A, R0, RES_Tx_P);
      }
    }

    if(ip & CHARxIP) { /* Channel A Rx Char Avail */
#ifdef INTDEBUG
            printk("Channel A Rx char avail");
#endif
      while( (read_zsreg(&scc->A, R0) & Rx_CH_AV) != 0)
	{
	  ch=read_zsdata(&scc->A);
	  rs_receive_char(infoA, ch , 0);
#ifdef INTDEBUG
	  printk("Received Char Chan A: %c\n", ch);
#endif
	}
    }
  }
}