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; }