示例#1
0
文件: riotty.c 项目: Tigrouzen/k1099
/*
** RIOClose the port.
** The operating system thinks that this is last close for the device.
** As there are two interfaces to the port (Modem and tty), we need to
** check that both are closed before we close the device.
*/
int riotclose(void *ptr)
{
	struct Port *PortP = ptr;	/* pointer to the port structure */
	int deleted = 0;
	int try = -1;		/* Disable the timeouts by setting them to -1 */
	int repeat_this = -1;	/* Congrats to those having 15 years of
				   uptime! (You get to break the driver.) */
	unsigned long end_time;
	struct tty_struct *tty;
	unsigned long flags;
	int rv = 0;

	rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum);

	/* PortP = p->RIOPortp[SysPort]; */
	rio_dprintk(RIO_DEBUG_TTY, "Port is at address %p\n", PortP);
	/* tp = PortP->TtyP; *//* Get tty */
	tty = PortP->gs.tty;
	rio_dprintk(RIO_DEBUG_TTY, "TTY is at address %p\n", tty);

	if (PortP->gs.closing_wait)
		end_time = jiffies + PortP->gs.closing_wait;
	else
		end_time = jiffies + MAX_SCHEDULE_TIMEOUT;

	rio_spin_lock_irqsave(&PortP->portSem, flags);

	/*
	 ** Setting this flag will make any process trying to open
	 ** this port block until we are complete closing it.
	 */
	PortP->State |= RIO_CLOSING;

	if ((PortP->State & RIO_DELETED)) {
		rio_dprintk(RIO_DEBUG_TTY, "Close on deleted RTA\n");
		deleted = 1;
	}

	if (p->RIOHalted) {
		RIOClearUp(PortP);
		rv = -EIO;
		goto close_end;
	}

	rio_dprintk(RIO_DEBUG_TTY, "Clear bits\n");
	/*
	 ** clear the open bits for this device
	 */
	PortP->State &= ~RIO_MOPEN;
	PortP->State &= ~RIO_CARR_ON;
	PortP->ModemState &= ~MSVR1_CD;
	/*
	 ** If the device was open as both a Modem and a tty line
	 ** then we need to wimp out here, as the port has not really
	 ** been finally closed (gee, whizz!) The test here uses the
	 ** bit for the OTHER mode of operation, to see if THAT is
	 ** still active!
	 */
	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
		/*
		 ** The port is still open for the other task -
		 ** return, pretending that we are still active.
		 */
		rio_dprintk(RIO_DEBUG_TTY, "Channel %d still open !\n", PortP->PortNum);
		PortP->State &= ~RIO_CLOSING;
		if (PortP->firstOpen)
			PortP->firstOpen--;
		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
		return -EIO;
	}

	rio_dprintk(RIO_DEBUG_TTY, "Closing down - everything must go!\n");

	PortP->State &= ~RIO_DYNOROD;

	/*
	 ** This is where we wait for the port
	 ** to drain down before closing. Bye-bye....
	 ** (We never meant to do this)
	 */
	rio_dprintk(RIO_DEBUG_TTY, "Timeout 1 starts\n");

	if (!deleted)
		while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) {
			if (repeat_this-- <= 0) {
				rv = -EINTR;
				rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
				RIOPreemptiveCmd(p, PortP, FCLOSE);
				goto close_end;
			}
			rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
			if (RIODelay_ni(PortP, HUNDRED_MS * 10) == RIO_FAIL) {
				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
				rv = -EINTR;
				rio_spin_lock_irqsave(&PortP->portSem, flags);
				goto close_end;
			}
			rio_spin_lock_irqsave(&PortP->portSem, flags);
		}

	PortP->TxBufferIn = PortP->TxBufferOut = 0;
	repeat_this = 0xff;

	PortP->InUse = 0;
	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
		/*
		 ** The port has been re-opened for the other task -
		 ** return, pretending that we are still active.
		 */
		rio_dprintk(RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
		PortP->State &= ~RIO_CLOSING;
		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
		if (PortP->firstOpen)
			PortP->firstOpen--;
		return -EIO;
	}

	if (p->RIOHalted) {
		RIOClearUp(PortP);
		goto close_end;
	}

	/* Can't call RIOShortCommand with the port locked. */
	rio_spin_unlock_irqrestore(&PortP->portSem, flags);

	if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
		RIOPreemptiveCmd(p, PortP, FCLOSE);
		rio_spin_lock_irqsave(&PortP->portSem, flags);
		goto close_end;
	}

	if (!deleted)
		while (try && (PortP->PortState & PORT_ISOPEN)) {
			try--;
			if (time_after(jiffies, end_time)) {
				rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n");
				RIOPreemptiveCmd(p, PortP, FCLOSE);
				break;
			}
			rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN);

			if (p->RIOHalted) {
				RIOClearUp(PortP);
				rio_spin_lock_irqsave(&PortP->portSem, flags);
				goto close_end;
			}
			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
				RIOPreemptiveCmd(p, PortP, FCLOSE);
				break;
			}
		}
	rio_spin_lock_irqsave(&PortP->portSem, flags);
	rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try);

	/* RIOPreemptiveCmd(p, PortP, FCLOSE); */

/*
** 15.10.1998 ARG - ESIL 0761 part fix
** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.
*/
	PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);

	/*
	 ** Count opens for port statistics reporting
	 */
	if (PortP->statsGather)
		PortP->closes++;

close_end:
	/* XXX: Why would a "DELETED" flag be reset here? I'd have
	   thought that a "deleted" flag means that the port was
	   permanently gone, but here we can make it reappear by it
	   being in close during the "deletion".
	 */
	PortP->State &= ~(RIO_CLOSING | RIO_DELETED);
	if (PortP->firstOpen)
		PortP->firstOpen--;
	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
	rio_dprintk(RIO_DEBUG_TTY, "Return from close\n");
	return rv;
}



static void RIOClearUp(struct Port *PortP)
{
	rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n");
	PortP->Config = 0;	/* Direct semaphore */
	PortP->PortState = 0;
	PortP->firstOpen = 0;
	PortP->FlushCmdBodge = 0;
	PortP->ModemState = PortP->CookMode = 0;
	PortP->Mapped = 0;
	PortP->WflushFlag = 0;
	PortP->MagicFlags = 0;
	PortP->RxDataStart = 0;
	PortP->TxBufferIn = 0;
	PortP->TxBufferOut = 0;
}

/*
** Put a command onto a port.
** The PortPointer, command, length and arg are passed.
** The len is the length *inclusive* of the command byte,
** and so for a command that takes no data, len==1.
** The arg is a single byte, and is only used if len==2.
** Other values of len aren't allowed, and will cause
** a panic.
*/
int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg)
{
	struct PKT __iomem *PacketP;
	int retries = 20;	/* at 10 per second -> 2 seconds */
	unsigned long flags;

	rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");

	if (PortP->State & RIO_DELETED) {
		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
		return RIO_FAIL;
	}
	rio_spin_lock_irqsave(&PortP->portSem, flags);

	/*
	 ** If the port is in use for pre-emptive command, then wait for it to
	 ** be free again.
	 */
	while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted) {
		rio_dprintk(RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries);
		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
		if (retries-- <= 0) {
			return RIO_FAIL;
		}
		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
			return RIO_FAIL;
		}
		rio_spin_lock_irqsave(&PortP->portSem, flags);
	}
	if (PortP->State & RIO_DELETED) {
		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
		return RIO_FAIL;
	}

	while (!can_add_transmit(&PacketP, PortP) && !p->RIOHalted) {
		rio_dprintk(RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
		if (retries-- <= 0) {
			rio_dprintk(RIO_DEBUG_TTY, "out of tries. Failing\n");
			return RIO_FAIL;
		}
		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
			return RIO_FAIL;
		}
		rio_spin_lock_irqsave(&PortP->portSem, flags);
	}

	if (p->RIOHalted) {
		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
		return RIO_FAIL;
	}

	/*
	 ** set the command byte and the argument byte
	 */
	writeb(command, &PacketP->data[0]);

	if (len == 2)
		writeb(arg, &PacketP->data[1]);

	/*
	 ** set the length of the packet and set the command bit.
	 */
	writeb(PKT_CMD_BIT | len, &PacketP->len);

	add_transmit(PortP);
	/*
	 ** Count characters transmitted for port statistics reporting
	 */
	if (PortP->statsGather)
		PortP->txchars += len;

	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
	return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL;
}
示例#2
0
文件: riotty.c 项目: Tigrouzen/k1099
int riotopen(struct tty_struct *tty, struct file *filp)
{
	unsigned int SysPort;
	int repeat_this = 250;
	struct Port *PortP;	/* pointer to the port structure */
	unsigned long flags;
	int retval = 0;

	func_enter();

	/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
	   is going to oops.
	 */
	tty->driver_data = NULL;

	SysPort = rio_minor(tty);

	if (p->RIOFailed) {
		rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n");
		func_exit();
		return -ENXIO;
	}

	rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (mapped:%d)\n", SysPort, p->RIOPortp[SysPort]->Mapped);

	/*
	 ** Validate that we have received a legitimate request.
	 ** Currently, just check that we are opening a port on
	 ** a host card that actually exists, and that the port
	 ** has been mapped onto a host.
	 */
	if (SysPort >= RIO_PORTS) {	/* out of range ? */
		rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort);
		func_exit();
		return -ENXIO;
	}

	/*
	 ** Grab pointer to the port stucture
	 */
	PortP = p->RIOPortp[SysPort];	/* Get control struc */
	rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP);
	if (!PortP->Mapped) {	/* we aren't mapped yet! */
		/*
		 ** The system doesn't know which RTA this port
		 ** corresponds to.
		 */
		rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n");
		func_exit();
		return -ENXIO;
	}

	tty->driver_data = PortP;

	PortP->gs.tty = tty;
	PortP->gs.count++;

	rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt);

	retval = gs_init_port(&PortP->gs);
	if (retval) {
		PortP->gs.count--;
		return -ENXIO;
	}
	/*
	 ** If the host hasn't been booted yet, then
	 ** fail
	 */
	if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) {
		rio_dprintk(RIO_DEBUG_TTY, "Host not running\n");
		func_exit();
		return -ENXIO;
	}

	/*
	 ** If the RTA has not booted yet and the user has choosen to block
	 ** until the RTA is present then we must spin here waiting for
	 ** the RTA to boot.
	 */
	/* I find the above code a bit hairy. I find the below code
	   easier to read and shorter. Now, if it works too that would
	   be great... -- REW 
	 */
	rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
	while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
		if (!PortP->WaitUntilBooted) {
			rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n");
			func_exit();
			return -ENXIO;
		}

		/* Under Linux you'd normally use a wait instead of this
		   busy-waiting. I'll stick with the old implementation for
		   now. --REW
		 */
		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
			rio_dprintk(RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
			func_exit();
			return -EINTR;
		}
		if (repeat_this-- <= 0) {
			rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
			func_exit();
			return -EIO;
		}
	}
	rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
	rio_spin_lock_irqsave(&PortP->portSem, flags);
	if (p->RIOHalted) {
		goto bombout;
	}

	/*
	 ** If the port is in the final throws of being closed,
	 ** we should wait here (politely), waiting
	 ** for it to finish, so that it doesn't close us!
	 */
	while ((PortP->State & RIO_CLOSING) && !p->RIOHalted) {
		rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
		if (repeat_this-- <= 0) {
			rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
			RIOPreemptiveCmd(p, PortP, FCLOSE);
			retval = -EINTR;
			goto bombout;
		}
		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
			rio_spin_lock_irqsave(&PortP->portSem, flags);
			retval = -EINTR;
			goto bombout;
		}
		rio_spin_lock_irqsave(&PortP->portSem, flags);
	}

	if (!PortP->Mapped) {
		rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n");
		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
		retval = -ENXIO;
		func_exit();
		return retval;
	}

	if (p->RIOHalted) {
		goto bombout;
	}

/*
** 15.10.1998 ARG - ESIL 0761 part fix
** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,
** we need to make sure that the flags are clear when the port is opened.
*/
	/* Uh? Suppose I turn these on and then another process opens
	   the port again? The flags get cleared! Not good. -- REW */
	if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
		PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
	}

	if (!(PortP->firstOpen)) {	/* First time ? */
		rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n");


		PortP->firstOpen++;
		PortP->CookMode = 0;	/* XXX RIOCookMode(tp); */
		PortP->InUse = NOT_INUSE;

		/* Tentative fix for bug PR27. Didn't work. */
		/* PortP->gs.xmit_cnt = 0; */

		rio_spin_unlock_irqrestore(&PortP->portSem, flags);

		/* Someone explain to me why this delay/config is
		   here. If I read the docs correctly the "open"
		   command piggybacks the parameters immediately.
		   -- REW */
		RIOParam(PortP, OPEN, 1, OK_TO_SLEEP);	/* Open the port */
		rio_spin_lock_irqsave(&PortP->portSem, flags);

		/*
		 ** wait for the port to be not closed.
		 */
		while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) {
			rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState);
			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
				rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
				RIOPreemptiveCmd(p, PortP, FCLOSE);
				func_exit();
				return -EINTR;
			}
			rio_spin_lock_irqsave(&PortP->portSem, flags);
		}

		if (p->RIOHalted) {
			retval = -EIO;
		      bombout:
			/*                    RIOClearUp( PortP ); */
			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
			return retval;
		}
		rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
	}
	rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n");
	/*
	 ** ACTION
	 ** insert test for carrier here. -- ???
	 ** I already see that test here. What's the deal? -- REW
	 */
	if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) {
		rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
		/*
		   tp->tm.c_state |= CARR_ON;
		   wakeup((caddr_t) &tp->tm.c_canq);
		 */
		PortP->State |= RIO_CARR_ON;
		wake_up_interruptible(&PortP->gs.open_wait);
	} else {	/* no carrier - wait for DCD */
			/*
		   while (!(PortP->gs.tty->termios->c_state & CARR_ON) &&
		   !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
		 */
		while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) {
				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort);
			/*
			   PortP->gs.tty->termios->c_state |= WOPEN;
			 */
			PortP->State |= RIO_WOPEN;
			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
				rio_spin_lock_irqsave(&PortP->portSem, flags);
				/*
				 ** ACTION: verify that this is a good thing
				 ** to do here. -- ???
				 ** I think it's OK. -- REW
				 */
				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort);
				RIOPreemptiveCmd(p, PortP, FCLOSE);
				/*
				   tp->tm.c_state &= ~WOPEN;
				 */
				PortP->State &= ~RIO_WOPEN;
				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
				func_exit();
				return -EINTR;
			}
			rio_spin_lock_irqsave(&PortP->portSem, flags);
		}
		PortP->State &= ~RIO_WOPEN;
	}
	if (p->RIOHalted)
		goto bombout;
	rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
	PortP->State |= RIO_MOPEN;

	if (p->RIOHalted)
		goto bombout;

	rio_dprintk(RIO_DEBUG_TTY, "high level open done\n");

	/*
	 ** Count opens for port statistics reporting
	 */
	if (PortP->statsGather)
		PortP->opens++;

	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
	rio_dprintk(RIO_DEBUG_TTY, "Returning from open\n");
	func_exit();
	return 0;
}
示例#3
0
文件: rioparam.c 项目: 274914765/C
/* 
** RIOParam is used to open or configure a port. You pass it a PortP,
** which will have a tty struct attached to it. You also pass a command,
** either OPEN or CONFIG. The port's setup is taken from the t_ fields
** of the tty struct inside the PortP, and the port is either opened
** or re-configured. You must also tell RIOParam if the device is a modem
** device or not (i.e. top bit of minor number set or clear - take special
** care when deciding on this!).
** RIOParam neither flushes nor waits for drain, and is NOT preemptive.
**
** RIOParam assumes it will be called at splrio(), and also assumes
** that CookMode is set correctly in the port structure.
**
** NB. for MPX
**    tty lock must NOT have been previously acquired.
*/
int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
{
    struct tty_struct *TtyP;
    int retval;
    struct phb_param __iomem *phb_param_ptr;
    struct PKT __iomem *PacketP;
    int res;
    u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0;
    u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0;
    u8 LNext = 0, TxBaud = 0, RxBaud = 0;
    int retries = 0xff;
    unsigned long flags;

    func_enter();

    TtyP = PortP->gs.tty;

    rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);

    if (!TtyP) {
        rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");

        func_exit();

        return RIO_FAIL;
    }
    rio_spin_lock_irqsave(&PortP->portSem, flags);

    if (cmd == RIOC_OPEN) {
        /*
         ** If the port is set to store or lock the parameters, and it is
         ** paramed with OPEN, we want to restore the saved port termio, but
         ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
         */
    }

    /*
     ** wait for space
     */
    while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) {
        if (retries-- <= 0) {
            break;
        }
        if (PortP->InUse != NOT_INUSE) {
            rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
        }

        if (!res) {
            rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
        }

        if (SleepFlag != OK_TO_SLEEP) {
            rio_spin_unlock_irqrestore(&PortP->portSem, flags);
            func_exit();

            return RIO_FAIL;
        }

        rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
        retval = RIODelay(PortP, HUNDRED_MS);
        rio_spin_lock_irqsave(&PortP->portSem, flags);
        if (retval == RIO_FAIL) {
            rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
            rio_spin_unlock_irqrestore(&PortP->portSem, flags);
            func_exit();
            return -EINTR;
        }
        if (PortP->State & RIO_DELETED) {
            rio_spin_unlock_irqrestore(&PortP->portSem, flags);
            func_exit();
            return 0;
        }
    }

    if (!res) {
        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
        func_exit();

        return RIO_FAIL;
    }

    rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res);
    rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP);

    phb_param_ptr = (struct phb_param __iomem *) PacketP->data;


    switch (TtyP->termios->c_cflag & CSIZE) {
    case CS5:
        {
            rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
            Cor1 |= RIOC_COR1_5BITS;
            break;
        }
    case CS6:
        {
            rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
            Cor1 |= RIOC_COR1_6BITS;
            break;
        }
    case CS7:
        {
            rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
            Cor1 |= RIOC_COR1_7BITS;
            break;
        }
    case CS8:
        {
            rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
            Cor1 |= RIOC_COR1_8BITS;
            break;
        }
    }

    if (TtyP->termios->c_cflag & CSTOPB) {
        rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
        Cor1 |= RIOC_COR1_2STOP;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
        Cor1 |= RIOC_COR1_1STOP;
    }

    if (TtyP->termios->c_cflag & PARENB) {
        rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
        Cor1 |= RIOC_COR1_NORMAL;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
        Cor1 |= RIOC_COR1_NOP;
    }
    if (TtyP->termios->c_cflag & PARODD) {
        rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
        Cor1 |= RIOC_COR1_ODD;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
        Cor1 |= RIOC_COR1_EVEN;
    }

    /*
     ** COR 2
     */
    if (TtyP->termios->c_iflag & IXON) {
        rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
        Cor2 |= RIOC_COR2_IXON;
    } else {
        if (PortP->Config & RIO_IXON) {
            rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
            Cor2 |= RIOC_COR2_IXON;
        } else
            rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
    }

    if (TtyP->termios->c_iflag & IXANY) {
        if (PortP->Config & RIO_IXANY) {
            rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
            Cor2 |= RIOC_COR2_IXANY;
        } else
            rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
    }

    if (TtyP->termios->c_iflag & IXOFF) {
        rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
        Cor2 |= RIOC_COR2_IXOFF;
    }

    if (TtyP->termios->c_cflag & HUPCL) {
        rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
        Cor2 |= RIOC_COR2_HUPCL;
    }

    if (C_CRTSCTS(TtyP)) {
        rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
        Cor2 |= RIOC_COR2_CTSFLOW;
        Cor2 |= RIOC_COR2_RTSFLOW;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
        Cor2 &= ~RIOC_COR2_CTSFLOW;
        Cor2 &= ~RIOC_COR2_RTSFLOW;
    }


    if (TtyP->termios->c_cflag & CLOCAL) {
        rio_dprintk(RIO_DEBUG_PARAM, "Local line\n");
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n");
    }

    /*
     ** COR 4 (there is no COR 3)
     */
    if (TtyP->termios->c_iflag & IGNBRK) {
        rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
        Cor4 |= RIOC_COR4_IGNBRK;
    }
    if (!(TtyP->termios->c_iflag & BRKINT)) {
        rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
        Cor4 |= RIOC_COR4_NBRKINT;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on    break condition\n");
    }

    if (TtyP->termios->c_iflag & INLCR) {
        rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
        Cor4 |= RIOC_COR4_INLCR;
    }

    if (TtyP->termios->c_iflag & IGNCR) {
        rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
        Cor4 |= RIOC_COR4_IGNCR;
    }

    if (TtyP->termios->c_iflag & ICRNL) {
        rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
        Cor4 |= RIOC_COR4_ICRNL;
    }
    if (TtyP->termios->c_iflag & IGNPAR) {
        rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
        Cor4 |= RIOC_COR4_IGNPAR;
    }
    if (TtyP->termios->c_iflag & PARMRK) {
        rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
        Cor4 |= RIOC_COR4_PARMRK;
    }

    /*
     ** Set the RAISEMOD flag to ensure that the modem lines are raised
     ** on reception of a config packet.
     ** The download code handles the zero baud condition.
     */
    Cor4 |= RIOC_COR4_RAISEMOD;

    /*
     ** COR 5
     */

    Cor5 = RIOC_COR5_CMOE;

    /*
     ** Set to monitor tbusy/tstop (or not).
     */

    if (PortP->MonitorTstate)
        Cor5 |= RIOC_COR5_TSTATE_ON;
    else
        Cor5 |= RIOC_COR5_TSTATE_OFF;

    /*
     ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
     */
    if (TtyP->termios->c_iflag & ISTRIP) {
        rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
        if (!(PortP->State & RIO_TRIAD_MODE)) {
            Cor5 |= RIOC_COR5_ISTRIP;
        }
    }

    if (TtyP->termios->c_oflag & ONLCR) {
        rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
        if (PortP->CookMode == COOK_MEDIUM)
            Cor5 |= RIOC_COR5_ONLCR;
    }
    if (TtyP->termios->c_oflag & OCRNL) {
        rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
        if (PortP->CookMode == COOK_MEDIUM)
            Cor5 |= RIOC_COR5_OCRNL;
    }
    if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
        rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
        if (PortP->CookMode == COOK_MEDIUM)
            Cor5 |= RIOC_COR5_TAB3;
    }

    /*
     ** Flow control bytes.
     */
    TxXon = TtyP->termios->c_cc[VSTART];
    TxXoff = TtyP->termios->c_cc[VSTOP];
    RxXon = TtyP->termios->c_cc[VSTART];
    RxXoff = TtyP->termios->c_cc[VSTOP];
    /*
     ** LNEXT byte
     */
    LNext = 0;

    /*
     ** Baud rate bytes
     */
    rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD);

    switch (TtyP->termios->c_cflag & CBAUD) {
#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
        e(50);
        e(75);
        e(110);
        e(134);
        e(150);
        e(200);
        e(300);
        e(600);
        e(1200);
        e(1800);
        e(2400);
        e(4800);
        e(9600);
        e(19200);
        e(38400);
        e(57600);
        e(115200);    /* e(230400);e(460800); e(921600);  */
    }

    rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);


    /*
     ** Leftovers
     */
    if (TtyP->termios->c_cflag & CREAD)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n");
#ifdef RCV1EN
    if (TtyP->termios->c_cflag & RCV1EN)
        rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n");
#endif
#ifdef XMT1EN
    if (TtyP->termios->c_cflag & XMT1EN)
        rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n");
#endif
    if (TtyP->termios->c_lflag & ISIG)
        rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
    if (TtyP->termios->c_lflag & ICANON)
        rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
    if (TtyP->termios->c_lflag & XCASE)
        rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
    if (TtyP->termios->c_lflag & ECHO)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n");
    if (TtyP->termios->c_lflag & ECHOE)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n");
    if (TtyP->termios->c_lflag & ECHOK)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n");
    if (TtyP->termios->c_lflag & ECHONL)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n");
    if (TtyP->termios->c_lflag & NOFLSH)
        rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
#ifdef TOSTOP
    if (TtyP->termios->c_lflag & TOSTOP)
        rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
#endif
#ifdef XCLUDE
    if (TtyP->termios->c_lflag & XCLUDE)
        rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n");
#endif
    if (TtyP->termios->c_iflag & IUCLC)
        rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
    if (TtyP->termios->c_oflag & OPOST)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n");
    if (TtyP->termios->c_oflag & OLCUC)
        rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
    if (TtyP->termios->c_oflag & ONOCR)
        rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
    if (TtyP->termios->c_oflag & ONLRET)
        rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
    if (TtyP->termios->c_oflag & OFILL)
        rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n");
    if (TtyP->termios->c_oflag & OFDEL)
        rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n");
    if (TtyP->termios->c_oflag & NLDLY)
        rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n");
    if (TtyP->termios->c_oflag & CRDLY)
        rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n");
    if (TtyP->termios->c_oflag & TABDLY)
        rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n");
    /*
     ** These things are kind of useful in a later life!
     */
    PortP->Cor2Copy = Cor2;

    if (PortP->State & RIO_DELETED) {
        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
        func_exit();

        return RIO_FAIL;
    }

    /*
     ** Actually write the info into the packet to be sent
     */
    writeb(cmd, &phb_param_ptr->Cmd);
    writeb(Cor1, &phb_param_ptr->Cor1);
    writeb(Cor2, &phb_param_ptr->Cor2);
    writeb(Cor4, &phb_param_ptr->Cor4);
    writeb(Cor5, &phb_param_ptr->Cor5);
    writeb(TxXon, &phb_param_ptr->TxXon);
    writeb(RxXon, &phb_param_ptr->RxXon);
    writeb(TxXoff, &phb_param_ptr->TxXoff);
    writeb(RxXoff, &phb_param_ptr->RxXoff);
    writeb(LNext, &phb_param_ptr->LNext);
    writeb(TxBaud, &phb_param_ptr->TxBaud);
    writeb(RxBaud, &phb_param_ptr->RxBaud);

    /*
     ** Set the length/command field
     */
    writeb(12 | PKT_CMD_BIT, &PacketP->len);

    /*
     ** The packet is formed - now, whack it off
     ** to its final destination:
     */
    add_transmit(PortP);
    /*
     ** Count characters transmitted for port statistics reporting
     */
    if (PortP->statsGather)
        PortP->txchars += 12;

    rio_spin_unlock_irqrestore(&PortP->portSem, flags);

    rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n");
    /*
     ** job done.
     */
    func_exit();

    return 0;
}