📄 riointr.c
字号:
** to make debuggery easier */ WBYTE( PacketP->data[ 2], 'W' ); WBYTE( PacketP->data[ 3], 'F' ); WBYTE( PacketP->data[ 4], 'L' ); WBYTE( PacketP->data[ 5], 'U' ); WBYTE( PacketP->data[ 6], 'S' ); WBYTE( PacketP->data[ 7], 'H' ); WBYTE( PacketP->data[ 8], ' ' ); WBYTE( PacketP->data[ 9], '0'+PortP->WflushFlag ); WBYTE( PacketP->data[10], ' ' ); WBYTE( PacketP->data[11], ' ' ); WBYTE( PacketP->data[12], '\0' ); /* ** its two bytes long! */ WBYTE( PacketP->len , PKT_CMD_BIT | 2 ); /* ** 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); } }}/*** Routine for handling received data for clist drivers.** NB: Called with the tty locked. The spl from the lockb( ) is passed.** we return the ttySpl level that we re-locked at.*/static voidRIOReceive(p, PortP)struct rio_info * p;struct Port * PortP;{ struct tty_struct *TtyP; register ushort transCount; struct PKT *PacketP; register uint DataCnt; uchar * ptr; 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 succesfully 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) {#ifdef STATS PortP->Stat.RxIntCnt++;#endif /* STATS */ RxIntCnt++; /* ** check that it is not a command! */ if ( 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", PacketP->dest_unit); rio_dprintk (RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port); rio_dprintk (RIO_DEBUG_INTR, " src_unit = %d\n", PacketP->src_unit); rio_dprintk (RIO_DEBUG_INTR, " src_port = %d\n", PacketP->src_port); rio_dprintk (RIO_DEBUG_INTR, " len = %d\n", PacketP->len); rio_dprintk (RIO_DEBUG_INTR, " control = %d\n", PacketP->control); rio_dprintk (RIO_DEBUG_INTR, " csum = %d\n", 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", 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 = min_t(unsigned int, PacketP->len & PKT_LEN_MASK, TTY_FLIPBUF_SIZE - TtyP->flip.count); 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). */#undef ___DEBUG_IT___#ifdef ___DEBUG_IT___ kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ", intCount, RxIntCnt, PortP->PortNum, TtyP->rxqueue.count, transCount, TtyP->flags );#endif ptr = (uchar *) PacketP->data + PortP->RxDataStart; rio_memcpy_fromio (TtyP->flip.char_buf_ptr, ptr, transCount); memset(TtyP->flip.flag_buf_ptr, TTY_NORMAL, transCount);#ifdef STATS /* ** keep a count for statistical purposes */ PortP->Stat.RxCharCnt += transCount;#endif PortP->RxDataStart += transCount; PacketP->len -= transCount; copied += transCount; TtyP->flip.count += transCount; TtyP->flip.char_buf_ptr += transCount; TtyP->flip.flag_buf_ptr += transCount;#ifdef ___DEBUG_IT___ kkprintf("T:%d L:%d\n", DataCnt, PacketP->len );#endif if ( 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;#ifdef STATS /* ** more lies ( oops, I mean statistics ) */ PortP->Stat.RxPktCnt++;#endif /* STATS */ } } } 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;}#ifdef FUTURE_RELEASE/*** The proc routine called by the line discipline to do the work for it.** The proc routine works hand in hand with the interrupt routine.*/intriotproc(p, tp, cmd, port)struct rio_info * p;register struct ttystatics *tp;int cmd;int port;{ register struct Port *PortP; int SysPort; struct PKT *PacketP; SysPort = port; /* Believe me, it works. */ if ( SysPort < 0 || SysPort >= RIO_PORTS ) { rio_dprintk (RIO_DEBUG_INTR, "Illegal port %d derived from TTY in riotproc()\n",SysPort); return 0; } PortP = p->RIOPortp[SysPort]; if ((uint)PortP->PhbP < (uint)PortP->Caddr || (uint)PortP->PhbP >= (uint)PortP->Caddr+SIXTY_FOUR_K ) { rio_dprintk (RIO_DEBUG_INTR, "RIO: NULL or BAD PhbP on sys port %d in proc routine\n", SysPort); rio_dprintk (RIO_DEBUG_INTR, " PortP = 0x%x\n",PortP); rio_dprintk (RIO_DEBUG_INTR, " PortP->PhbP = 0x%x\n",PortP->PhbP); rio_dprintk (RIO_DEBUG_INTR, " PortP->Caddr = 0x%x\n",PortP->PhbP); rio_dprintk (RIO_DEBUG_INTR, " PortP->HostPort = 0x%x\n",PortP->HostPort); return 0; } switch(cmd) { case T_WFLUSH: rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH\n"); /* ** Because of the spooky way the RIO works, we don't need ** to issue a flush command on any of the SET*F commands, ** as that causes trouble with getty and login, which issue ** these commands to incur a READ flush, and rely on the fact ** that the line discipline does a wait for drain for them. ** As the rio doesn't wait for drain, the write flush would ** destroy the Password: prompt. This isn't very friendly, so ** here we only issue a WFLUSH command if we are in the interrupt ** routine, or we aren't executing a SET*F command. */ if ( PortP->HostP->InIntr || !PortP->FlushCmdBodge ) { /* ** form a wflush packet - 1 byte long, no data */ if ( PortP->State & RIO_DELETED ) { rio_dprintk (RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n"); } else { if ( RIOPreemptiveCmd(p, PortP, WFLUSH ) == RIO_FAIL ) { rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command failed\n"); } else rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command\n"); } /* ** WFLUSH operation - flush the data! */ PortP->TxBufferIn = PortP->TxBufferOut = 0; } else { rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n"); } /* ** sort out the line discipline */ if (PortP->CookMode == COOK_WELL) goto start; break; case T_RESUME: rio_dprintk (RIO_DEBUG_INTR, "T_RESUME\n"); /* ** send pre-emptive resume packet */ if ( PortP->State & RIO_DELETED ) { rio_dprintk (RIO_DEBUG_INTR, "RESUME on deleted RTA\n"); } else { if ( RIOPreemptiveCmd(p, PortP, RESUME ) == RIO_FAIL ) { rio_dprintk (RIO_DEBUG_INTR, "T_RESUME Command failed\n"); } } /* ** and re-start the sender software! */ if (PortP->CookMode == COOK_WELL) goto start; break; case T_TIME: rio_dprintk (RIO_DEBUG_INTR, "T_TIME\n"); /* ** T_TIME is called when xDLY is set in oflags and ** the line discipline timeout has expired. It's ** function in life is to clear the TIMEOUT flag ** and to re-start output to the port. */ /* ** Fall through and re-start output */ case T_OUTPUT:start: if ( PortP->MagicFlags & MAGIC_FLUSH ) { PortP->MagicFlags |= MORE_OUTPUT_EYGOR; return 0; } RIOTxEnable((char *)PortP); PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR; /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n");*/ break; case T_SUSPEND: rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND\n"); /* ** send a suspend pre-emptive packet. */ if ( PortP->State & RIO_DELETED ) { rio_dprintk (RIO_DEBUG_INTR, "SUSPEND deleted RTA\n"); } else { if ( RIOPreemptiveCmd(p, PortP, SUSPEND ) == RIO_FAIL ) { rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND Command failed\n"); } } /* ** done! */ break; case T_BLOCK: rio_dprintk (RIO_DEBUG_INTR, "T_BLOCK\n"); break; case T_RFLUSH: rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH\n"); if ( PortP->State & RIO_DELETED ) { rio_dprintk (RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n"); PortP->RxDataStart = 0; } else { if ( RIOPreemptiveCmd( p, PortP, RFLUSH ) == RIO_FAIL ) { rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH Command failed\n"); return 0; } PortP->RxDataStart = 0; while ( can_remove_receive(&PacketP, PortP) ) { remove_receive(PortP); ShowPacket(DBG_PROC, PacketP ); put_free_end(PortP->HostP, PacketP ); } if ( PortP->PhbP->handshake == PHB_HANDSHAKE_SET ) { /* ** MAGIC! */ rio_dprintk (RIO_DEBUG_INTR, "Set receive handshake bit\n"); PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET; } } break; /* FALLTHROUGH */ case T_UNBLOCK: rio_dprintk (RIO_DEBUG_INTR, "T_UNBLOCK\n"); /* ** If there is any data to receive set a timeout to service it. */ RIOReceive(p, PortP); break; case T_BREAK: rio_dprintk (RIO_DEBUG_INTR, "T_BREAK\n"); /* ** Send a break command. For Sys V ** this is a timed break, so we ** send a SBREAK[time] packet */ /* ** Build a BREAK command */ if ( PortP->State & RIO_DELETED ) { rio_dprintk (RIO_DEBUG_INTR, "BREAK on deleted RTA\n"); } else { if (RIOShortCommand(PortP,SBREAK,2, p->RIOConf.BreakInterval)==RIO_FAIL) { rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); } } /* ** done! */ break; case T_INPUT: rio_dprintk (RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n"); break; case T_PARM: rio_dprintk (RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n"); break; case T_SWTCH: rio_dprintk (RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n"); break; default: rio_dprintk (RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n",cmd); } /* ** T_OUTPUT returns without passing through this point! */ /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n");*/ return(0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -