Example #1
0
/*
 * Print a string to the serial port trying not to disturb
 * any possible real use of the port...
 */
static void pmz_console_write(struct console *con, const char *s, unsigned int count)
{
	struct uart_pmac_port *uap = &pmz_ports[con->index];
	unsigned long flags;
	int i;

	spin_lock_irqsave(&uap->port.lock, flags);

	/* Turn of interrupts and enable the transmitter. */
	write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB);
	write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR);

	for (i = 0; i < count; i++) {
		/* Wait for the transmit buffer to empty. */
		while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
			udelay(5);
		write_zsdata(uap, s[i]);
		if (s[i] == 10) {
			while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
				udelay(5);
			write_zsdata(uap, R13);
		}
	}

	/* Restore the values in the registers. */
	write_zsreg(uap, R1, uap->curregs[1]);
	/* Don't disable the transmitter. */

	spin_unlock_irqrestore(&uap->port.lock, flags);
}
Example #2
0
static void asdg_enab_tx_int(struct async_struct *info, int enab_flag)
{
  
  int ch; 
  struct SCCHalf *port = (struct SCCHalf *)info->port;

#ifdef DEBUG
  printk("asdg_enab_tx_int: enab_flag= %d\n", enab_flag);
#endif 

  if(enab_flag) {
    if( (ch=rs_get_tx_char(info)) >=0)
      {
#ifdef DEBUG
	printk("{%x}", ch);
#endif
	write_zsdata(port, ch);
      }
    else {
#ifdef DEBUG
      	printk("{%x}", ch);
#endif
      write_zsreg(port, R0, RES_Tx_P);
    }
  } 
  else 
    write_zsreg(port, R0, RES_Tx_P);
}
Example #3
0
static void pmz_console_putchar(struct uart_port *port, int ch)
{
	struct uart_pmac_port *uap = (struct uart_pmac_port *)port;

	/* Wait for the transmit buffer to empty. */
	while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
		udelay(5);
	write_zsdata(uap, ch);
}
Example #4
0
/* 
 * Kick the Tx side.
 * The port lock is held and interrupts are disabled.
 */
static void pmz_start_tx(struct uart_port *port)
{
	struct uart_pmac_port *uap = to_pmz(port);
	unsigned char status;

	pmz_debug("pmz: start_tx()\n");

	uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
	uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;

	if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
		return;

	status = read_zsreg(uap, R0);

	/* TX busy?  Just wait for the TX done interrupt.  */
	if (!(status & Tx_BUF_EMP))
		return;

	/* Send the first character to jump-start the TX done
	 * IRQ sending engine.
	 */
	if (port->x_char) {
		write_zsdata(uap, port->x_char);
		zssync(uap);
		port->icount.tx++;
		port->x_char = 0;
	} else {
		struct circ_buf *xmit = &port->info->xmit;

		write_zsdata(uap, xmit->buf[xmit->tail]);
		zssync(uap);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;

		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
			uart_write_wakeup(&uap->port);
	}
	pmz_debug("pmz: start_tx() done.\n");
}
Example #5
0
static void pmz_transmit_chars(struct uart_pmac_port *uap)
{
	struct circ_buf *xmit;

	if (ZS_IS_ASLEEP(uap))
		return;
	if (ZS_IS_CONS(uap)) {
		unsigned char status = read_zsreg(uap, R0);

		/* TX still busy?  Just wait for the next TX done interrupt.
		 *
		 * It can occur because of how we do serial console writes.  It would
		 * be nice to transmit console writes just like we normally would for
		 * a TTY line. (ie. buffered and TX interrupt driven).  That is not
		 * easy because console writes cannot sleep.  One solution might be
		 * to poll on enough port->xmit space becomming free.  -DaveM
		 */
		if (!(status & Tx_BUF_EMP))
			return;
	}

	uap->flags &= ~PMACZILOG_FLAG_TX_ACTIVE;

	if (ZS_REGS_HELD(uap)) {
		pmz_load_zsregs(uap, uap->curregs);
		uap->flags &= ~PMACZILOG_FLAG_REGS_HELD;
	}

	if (ZS_TX_STOPPED(uap)) {
		uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;
		goto ack_tx_int;
	}

	if (uap->port.x_char) {
		uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
		write_zsdata(uap, uap->port.x_char);
		zssync(uap);
		uap->port.icount.tx++;
		uap->port.x_char = 0;
		return;
	}

	if (uap->port.info == NULL)
		goto ack_tx_int;
	xmit = &uap->port.info->xmit;
	if (uart_circ_empty(xmit)) {
		uart_write_wakeup(&uap->port);
		goto ack_tx_int;
	}
	if (uart_tx_stopped(&uap->port))
		goto ack_tx_int;

	uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
	write_zsdata(uap, xmit->buf[xmit->tail]);
	zssync(uap);

	xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
	uap->port.icount.tx++;

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(&uap->port);

	return;

ack_tx_int:
	write_zsreg(uap, R0, RES_Tx_P);
	zssync(uap);
}
Example #6
0
/*
 * 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);
}
Example #7
0
/* 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
	}
    }
  }
}