int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP) { struct Port *PortP = (struct Port *) iPortP; struct PKT __iomem *PacketP; unsigned long flags; rio_spin_lock_irqsave(&PortP->portSem, flags); while (can_remove_receive(&PacketP, PortP)) { remove_receive(PortP); put_free_end(PortP->HostP, PacketP); } if (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_CMD, "Util: Set RX handshake bit\n"); writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake); } rio_spin_unlock_irqrestore(&PortP->portSem, flags); return RIOUnUse(iPortP, CmdBlkP); }
/* ** Routine for handling received data for tty drivers */ static void RIOReceive(struct rio_info *p, struct Port *PortP) { struct tty_struct *TtyP; unsigned short transCount; struct PKT __iomem *PacketP; register unsigned int DataCnt; unsigned char __iomem *ptr; unsigned char *buf; int copied = 0; static int intCount, RxIntCnt; /* ** The receive data process is to remove packets from the ** PHB until there aren't any more or the current cblock ** is full. When this occurs, there will be some left over ** data in the packet, that we must do something with. ** As we haven't unhooked the packet from the read list ** yet, we can just leave the packet there, having first ** made a note of how far we got. This means that we need ** a pointer per port saying where we start taking the ** data from - this will normally be zero, but when we ** run out of space it will be set to the offset of the ** next byte to copy from the packet data area. The packet ** length field is decremented by the number of bytes that ** we successfully removed from the packet. When this reaches ** zero, we reset the offset pointer to be zero, and free ** the packet from the front of the queue. */ intCount++; TtyP = PortP->gs.tty; if (!TtyP) { rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n"); return; } if (PortP->State & RIO_THROTTLE_RX) { rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n"); return; } if (PortP->State & RIO_DELETED) { while (can_remove_receive(&PacketP, PortP)) { remove_receive(PortP); put_free_end(PortP->HostP, PacketP); } } else { /* ** loop, just so long as: ** i ) there's some data ( i.e. can_remove_receive ) ** ii ) we haven't been blocked ** iii ) there's somewhere to put the data ** iv ) we haven't outstayed our welcome */ transCount = 1; while (can_remove_receive(&PacketP, PortP) && transCount) { RxIntCnt++; /* ** check that it is not a command! */ if (readb(&PacketP->len) & PKT_CMD_BIT) { rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n"); /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */ rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit)); rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port)); rio_dprintk(RIO_DEBUG_INTR, " src_unit = %d\n", readb(&PacketP->src_unit)); rio_dprintk(RIO_DEBUG_INTR, " src_port = %d\n", readb(&PacketP->src_port)); rio_dprintk(RIO_DEBUG_INTR, " len = %d\n", readb(&PacketP->len)); rio_dprintk(RIO_DEBUG_INTR, " control = %d\n", readb(&PacketP->control)); rio_dprintk(RIO_DEBUG_INTR, " csum = %d\n", readw(&PacketP->csum)); rio_dprintk(RIO_DEBUG_INTR, " data bytes: "); for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++) rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt])); remove_receive(PortP); put_free_end(PortP->HostP, PacketP); continue; /* with next packet */ } /* ** How many characters can we move 'upstream' ? ** ** Determine the minimum of the amount of data ** available and the amount of space in which to ** put it. ** ** 1. Get the packet length by masking 'len' ** for only the length bits. ** 2. Available space is [buffer size] - [space used] ** ** Transfer count is the minimum of packet length ** and available space. */ transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK); rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount); /* ** To use the following 'kkprintfs' for debugging - change the '#undef' ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the ** driver). */ ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart; tty_prepare_flip_string(TtyP, &buf, transCount); rio_memcpy_fromio(buf, ptr, transCount); PortP->RxDataStart += transCount; writeb(readb(&PacketP->len)-transCount, &PacketP->len); copied += transCount; if (readb(&PacketP->len) == 0) { /* ** If we have emptied the packet, then we can ** free it, and reset the start pointer for ** the next packet. */ remove_receive(PortP); put_free_end(PortP->HostP, PacketP); PortP->RxDataStart = 0; } } } if (copied) { rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied); tty_flip_buffer_push(TtyP); } return; }
/* ** Here we go - if there is an empty rup, fill it! ** must be called at splrio() or higher. */ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) { struct CmdBlk *CmdBlkP; struct UnixRup *UnixRupP; struct PKT __iomem *PacketP; unsigned short Rup; unsigned long flags; Rup = MAX_RUP + LINKS_PER_UNIT; do { /* do this loop for each RUP */ /* ** locate the rup we are processing & lock it */ UnixRupP = &HostP->UnixRups[--Rup]; spin_lock_irqsave(&UnixRupP->RupLock, flags); /* ** First check for incoming commands: */ if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) { int FreeMe; PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt)); switch (readb(&PacketP->dest_port)) { case BOOT_RUP: rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", readb(&PacketP->len) & 0x80 ? "Command" : "Data", readb(&PacketP->data[0])); rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); FreeMe = RIOBootRup(p, Rup, HostP, PacketP); rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); break; case COMMAND_RUP: /* ** Free the RUP lock as loss of carrier causes a ** ttyflush which will (eventually) call another ** routine that uses the RUP lock. */ rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); FreeMe = RIOCommandRup(p, Rup, HostP, PacketP); if (readb(&PacketP->data[5]) == MEMDUMP) { rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6]))); rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32); } rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); break; case ROUTE_RUP: rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); FreeMe = RIORouteRup(p, Rup, HostP, PacketP); rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); break; default: rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", readb(&PacketP->dest_port)); FreeMe = 1; break; } if (FreeMe) { rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n"); put_free_end(HostP, PacketP); writew(RX_RUP_INACTIVE, &UnixRupP->RupP->rxcontrol); if (readw(&UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) { rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup); writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &UnixRupP->RupP->handshake); } } } /* ** IF a command was running on the port, ** and it has completed, then tidy it up. */ if ((CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */ (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { /* ** we are idle. ** there is a command in pending. ** Therefore, this command has finished. ** So, wakeup whoever is waiting for it (and tell them ** what happened). */ if (CmdBlkP->Packet.dest_port == BOOT_RUP) rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]); rio_dprintk(RIO_DEBUG_CMD, "Command %p completed\n", CmdBlkP); /* ** Clear the Rup lock to prevent mutual exclusion. */ if (CmdBlkP->PostFuncP) { rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP); rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); } /* ** ....clear the pending flag.... */ UnixRupP->CmdPendingP = NULL; /* ** ....and return the command block to the freelist. */ RIOFreeCmdBlk(CmdBlkP); } /* ** If there is a command for this rup, and the rup ** is idle, then process the command */ if ((CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */ (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { /* ** if the pre-function is non-zero, call it. ** If it returns RIO_FAIL then don't ** send this command yet! */ if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : 1)) { rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command %p\n", CmdBlkP); } else { rio_dprintk(RIO_DEBUG_CMD, "Start new command %p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]); /* ** Whammy! blat that pack! */ HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT)); /* ** remove the command from the rup command queue... */ UnixRupP->CmdsWaitingP = CmdBlkP->NextP; /* ** ...and place it on the pending position. */ UnixRupP->CmdPendingP = CmdBlkP; /* ** set the command register */ writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol); /* ** the command block will be freed ** when the command has been processed. */ } } spin_unlock_irqrestore(&UnixRupP->RupLock, flags); } while (Rup); }