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; }
void RIOServiceHost(struct rio_info *p, struct Host *HostP, int From) { rio_spin_lock(&HostP->HostLock); if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { static int t = 0; rio_spin_unlock(&HostP->HostLock); if ((t++ % 200) == 0) rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags); return; } rio_spin_unlock(&HostP->HostLock); if (readw(&HostP->ParmMapP->rup_intr)) { writew(0, &HostP->ParmMapP->rup_intr); p->RIORupCount++; RupIntr++; rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %Zd\n", HostP - p->RIOHosts); RIOPollHostCommands(p, HostP); } if (readw(&HostP->ParmMapP->rx_intr)) { int port; writew(0, &HostP->ParmMapP->rx_intr); p->RIORxCount++; RxIntr++; rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %Zd\n", HostP - p->RIOHosts); /* ** Loop through every port. If the port is mapped into ** the system ( i.e. has /dev/ttyXXXX associated ) then it is ** worth checking. If the port isn't open, grab any packets ** hanging on its receive queue and stuff them on the free ** list; check for commands on the way. */ for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) { struct Port *PortP = p->RIOPortp[port]; struct tty_struct *ttyP; struct PKT __iomem *PacketP; /* ** not mapped in - most of the RIOPortp[] information ** has not been set up! ** Optimise: ports come in bundles of eight. */ if (!PortP->Mapped) { port += 7; continue; /* with the next port */ } /* ** If the host board isn't THIS host board, check the next one. ** optimise: ports come in bundles of eight. */ if (PortP->HostP != HostP) { port += 7; continue; } /* ** Let us see - is the port open? If not, then don't service it. */ if (!(PortP->PortState & PORT_ISOPEN)) { continue; } /* ** find corresponding tty structure. The process of mapping ** the ports puts these here. */ ttyP = PortP->gs.tty; /* ** Lock the port before we begin working on it. */ rio_spin_lock(&PortP->portSem); /* ** Process received data if there is any. */ if (can_remove_receive(&PacketP, PortP)) RIOReceive(p, PortP); /* ** If there is no data left to be read from the port, and ** it's handshake bit is set, then we must clear the handshake, ** so that that downstream RTA is re-enabled. */ if (!can_remove_receive(&PacketP, PortP) && (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) { /* ** MAGIC! ( Basically, handshake the RX buffer, so that ** the RTAs upstream can be re-enabled. ) */ rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n"); writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake); } rio_spin_unlock(&PortP->portSem); } } if (readw(&HostP->ParmMapP->tx_intr)) { int port; writew(0, &HostP->ParmMapP->tx_intr); p->RIOTxCount++; TxIntr++; rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %Zd\n", HostP - p->RIOHosts); /* ** Loop through every port. ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX ** associated ) then it is worth checking. */ for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) { struct Port *PortP = p->RIOPortp[port]; struct tty_struct *ttyP; struct PKT __iomem *PacketP; /* ** not mapped in - most of the RIOPortp[] information ** has not been set up! */ if (!PortP->Mapped) { port += 7; continue; /* with the next port */ } /* ** If the host board isn't running, then its data structures ** are no use to us - continue quietly. */ if (PortP->HostP != HostP) { port += 7; continue; /* with the next port */ } /* ** Let us see - is the port open? If not, then don't service it. */ if (!(PortP->PortState & PORT_ISOPEN)) { continue; } rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port); /* ** Lock the port before we begin working on it. */ rio_spin_lock(&PortP->portSem); /* ** If we can't add anything to the transmit queue, then ** we need do none of this processing. */ if (!can_add_transmit(&PacketP, PortP)) { rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n"); rio_spin_unlock(&PortP->portSem); continue; } /* ** find corresponding tty structure. The process of mapping ** the ports puts these here. */ ttyP = PortP->gs.tty; /* If ttyP is NULL, the port is getting closed. Forget about it. */ if (!ttyP) { rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n"); rio_spin_unlock(&PortP->portSem); continue; } /* ** If there is more room available we start up the transmit ** data process again. This can be direct I/O, if the cookmode ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch ** characters via the line discipline. We must always call ** the line discipline, ** so that user input characters can be echoed correctly. ** ** ++++ Update +++++ ** With the advent of double buffering, we now see if ** TxBufferOut-In is non-zero. If so, then we copy a packet ** to the output place, and set it going. If this empties ** the buffer, then we must issue a wakeup( ) on OUT. ** If it frees space in the buffer then we must issue ** a wakeup( ) on IN. ** ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we ** have to send a WFLUSH command down the PHB, to mark the ** end point of a WFLUSH. We also need to clear out any ** data from the double buffer! ( note that WflushFlag is a ** *count* of the number of WFLUSH commands outstanding! ) ** ** ++++ And there's more! ** If an RTA is powered off, then on again, and rebooted, ** whilst it has ports open, then we need to re-open the ports. ** ( reasonable enough ). We can't do this when we spot the ** re-boot, in interrupt time, because the queue is probably ** full. So, when we come in here, we need to test if any ** ports are in this condition, and re-open the port before ** we try to send any more data to it. Now, the re-booted ** RTA will be discarding packets from the PHB until it ** receives this open packet, but don't worry tooo much ** about that. The one thing that is interesting is the ** combination of this effect and the WFLUSH effect! */ /* For now don't handle RTA reboots. -- REW. Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */ if (PortP->MagicFlags) { if (PortP->MagicFlags & MAGIC_REBOOT) { /* ** well, the RTA has been rebooted, and there is room ** on its queue to add the open packet that is required. ** ** The messy part of this line is trying to decide if ** we need to call the Param function as a tty or as ** a modem. ** DONT USE CLOCAL AS A TEST FOR THIS! ** ** If we can't param the port, then move on to the ** next port. */ PortP->InUse = NOT_INUSE; rio_spin_unlock(&PortP->portSem); if (RIOParam(PortP, OPEN, ((PortP->Cor2Copy & (COR2_RTSFLOW | COR2_CTSFLOW)) == (COR2_RTSFLOW | COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL) { continue; /* with next port */ } rio_spin_lock(&PortP->portSem); PortP->MagicFlags &= ~MAGIC_REBOOT; } /* ** As mentioned above, this is a tacky hack to cope ** with WFLUSH */ if (PortP->WflushFlag) { rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n"); if (PortP->InUse) rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n"); } while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) { int p; struct PktCmd __iomem *PktCmdP; rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n"); /* ** make it look just like a WFLUSH command */ PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0]; writeb(WFLUSH, &PktCmdP->Command); p = PortP->HostPort % (u16) PORTS_PER_RTA; /* ** If second block of ports for 16 port RTA, add 8 ** to index 8-15. */ if (PortP->SecondBlock) p += PORTS_PER_RTA; writeb(p, &PktCmdP->PhbNum); /* ** to make debuggery easier */ writeb('W', &PacketP->data[2]); writeb('F', &PacketP->data[3]); writeb('L', &PacketP->data[4]); writeb('U', &PacketP->data[5]); writeb('S', &PacketP->data[6]); writeb('H', &PacketP->data[7]); writeb(' ', &PacketP->data[8]); writeb('0' + PortP->WflushFlag, &PacketP->data[9]); writeb(' ', &PacketP->data[10]); writeb(' ', &PacketP->data[11]); writeb('\0', &PacketP->data[12]); /* ** its two bytes long! */ writeb(PKT_CMD_BIT | 2, &PacketP->len); /* ** queue it! */ if (!(PortP->State & RIO_DELETED)) { add_transmit(PortP); /* ** Count chars tx'd for port statistics reporting */ if (PortP->statsGather) PortP->txchars += 2; } if (--(PortP->WflushFlag) == 0) { PortP->MagicFlags &= ~MAGIC_FLUSH; } rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag); } if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) { if (PortP->MagicFlags & MAGIC_FLUSH) { PortP->MagicFlags |= MORE_OUTPUT_EYGOR; } else { if (!can_add_transmit(&PacketP, PortP)) { rio_spin_unlock(&PortP->portSem); continue; } rio_spin_unlock(&PortP->portSem); RIOTxEnable((char *) PortP); rio_spin_lock(&PortP->portSem); PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR; } } } /* ** If we can't add anything to the transmit queue, then ** we need do none of the remaining processing. */ if (!can_add_transmit(&PacketP, PortP)) { rio_spin_unlock(&PortP->portSem); continue; } rio_spin_unlock(&PortP->portSem); RIOTxEnable((char *) PortP); } } }