📄 riocmd.c
字号:
return -EIO; } return 0;}intRIOFoadWakeup(p)struct rio_info * p;{ int port; register struct Port *PortP; unsigned long flags; for ( port=0; port<RIO_PORTS; port++) { PortP = p->RIOPortp[port]; rio_spin_lock_irqsave(&PortP->portSem, flags); PortP->Config = 0; PortP->State = 0; PortP->InUse = NOT_INUSE; PortP->PortState = 0; PortP->FlushCmdBodge = 0; PortP->ModemLines = 0; PortP->ModemState = 0; PortP->CookMode = 0; PortP->ParamSem = 0; PortP->Mapped = 0; PortP->WflushFlag = 0; PortP->MagicFlags = 0; PortP->RxDataStart = 0; PortP->TxBufferIn = 0; PortP->TxBufferOut = 0; rio_spin_unlock_irqrestore(&PortP->portSem, flags); } return(0);}/*** Incoming command on the COMMAND_RUP to be processed.*/static intRIOCommandRup(p, Rup, HostP, PacketP)struct rio_info * p;uint Rup;struct Host *HostP;PKT *PacketP; { struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data; struct Port *PortP; struct UnixRup *UnixRupP; ushort SysPort; ushort ReportedModemStatus; ushort rup; ushort subCommand; unsigned long flags; func_enter ();#ifdef CHECK CheckHost( Host ); CheckHostP( HostP ); CheckPacketP( PacketP );#endif /* ** 16 port RTA note: ** Command rup packets coming from the RTA will have pkt->data[1] (which ** translates to PktCmdP->PhbNum) set to the host port number for the ** particular unit. To access the correct BaseSysPort for a 16 port RTA, ** we can use PhbNum to get the rup number for the appropriate 8 port ** block (for the first block, this should be equal to 'Rup'). */ rup = RBYTE(PktCmdP->PhbNum) / (ushort)PORTS_PER_RTA; UnixRupP = &HostP->UnixRups[rup]; SysPort = UnixRupP->BaseSysPort + (RBYTE(PktCmdP->PhbNum) % (ushort)PORTS_PER_RTA); rio_dprintk (RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);#ifdef CHECK CheckRup( rup ); CheckUnixRupP( UnixRupP );#endif if ( UnixRupP->BaseSysPort == NO_PORT ) { rio_dprintk (RIO_DEBUG_CMD, "OBSCURE ERROR!\n"); rio_dprintk (RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n"); rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n", HostP-p->RIOHosts, HostP->Name ); rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); if ( Rup >= (ushort)MAX_RUP ) { rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name); } else rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name); rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", PacketP->dest_unit, PacketP->dest_port ); rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n", PacketP->src_unit, PacketP->src_port ); rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", PacketP->len,PacketP->len ); rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control); rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum ); rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command ); return TRUE; }#ifdef CHECK CheckSysPort( SysPort );#endif PortP = p->RIOPortp[ SysPort ]; rio_spin_lock_irqsave(&PortP->portSem, flags); switch( RBYTE(PktCmdP->Command) ) { case BREAK_RECEIVED: rio_dprintk (RIO_DEBUG_CMD, "Received a break!\n"); /* If the current line disc. is not multi-threading and the current processor is not the default, reset rup_intr and return FALSE to ensure that the command packet is not freed. */ /* Call tmgr HANGUP HERE */ /* Fix this later when every thing works !!!! RAMRAJ */ gs_got_break (&PortP->gs); break; case COMPLETE: rio_dprintk (RIO_DEBUG_CMD, "Command complete on phb %d host %d\n", RBYTE(PktCmdP->PhbNum), HostP-p->RIOHosts); subCommand = 1; switch (RBYTE(PktCmdP->SubCommand)) { case MEMDUMP : rio_dprintk (RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr)); break; case READ_REGISTER : rio_dprintk (RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr)); p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST); break; default : subCommand = 0; break; } if (subCommand) break; rio_dprintk (RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", RBYTE(PktCmdP->PortStatus),PortP->PortState); if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) { rio_dprintk (RIO_DEBUG_CMD, "Mark status & wakeup\n"); PortP->PortState = RBYTE(PktCmdP->PortStatus); /* What should we do here ... wakeup( &PortP->PortState ); */ } else rio_dprintk (RIO_DEBUG_CMD, "No change\n"); /* FALLTHROUGH */ case MODEM_STATUS: /* ** Knock out the tbusy and tstop bits, as these are not relevant ** to the check for modem status change (they're just there because ** it's a convenient place to put them!). */ ReportedModemStatus = RBYTE(PktCmdP->ModemStatus); if ((PortP->ModemState & MSVR1_HOST) == (ReportedModemStatus & MSVR1_HOST)) { rio_dprintk (RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState); /* ** Update ModemState just in case tbusy or tstop states have ** changed. */ PortP->ModemState = ReportedModemStatus; } else { rio_dprintk (RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus); PortP->ModemState = ReportedModemStatus;#ifdef MODEM_SUPPORT if ( PortP->Mapped ) { /***********************************************************\ ************************************************************* *** *** *** M O D E M S T A T E C H A N G E *** *** *** ************************************************************* \***********************************************************/ /* ** If the device is a modem, then check the modem ** carrier. */ if (PortP->gs.tty == NULL) break; if (PortP->gs.tty->termios == NULL) break; if (!(PortP->gs.tty->termios->c_cflag & CLOCAL) && ((PortP->State & (RIO_MOPEN|RIO_WOPEN)))) { rio_dprintk (RIO_DEBUG_CMD, "Is there a Carrier?\n"); /* ** Is there a carrier? */ if ( PortP->ModemState & MSVR1_CD ) { /* ** Has carrier just appeared? */ if (!(PortP->State & RIO_CARR_ON)) { rio_dprintk (RIO_DEBUG_CMD, "Carrier just came up.\n"); PortP->State |= RIO_CARR_ON; /* ** wakeup anyone in WOPEN */ if (PortP->State & (PORT_ISOPEN | RIO_WOPEN) ) wake_up_interruptible (&PortP->gs.open_wait);#ifdef STATS PortP->Stat.ModemOnCnt++;#endif } } else { /* ** Has carrier just dropped? */ if (PortP->State & RIO_CARR_ON) { if (PortP->State & (PORT_ISOPEN|RIO_WOPEN|RIO_MOPEN)) tty_hangup (PortP->gs.tty); PortP->State &= ~RIO_CARR_ON; rio_dprintk (RIO_DEBUG_CMD, "Carrirer just went down\n");#ifdef STATS PortP->Stat.ModemOffCnt++;#endif } } } }#endif } break; default: rio_dprintk (RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n", RBYTE(PktCmdP->Command),HostP-p->RIOHosts); break; } rio_spin_unlock_irqrestore(&PortP->portSem, flags); func_exit (); return TRUE;}/*** The command mechanism:** Each rup has a chain of commands associated with it.** This chain is maintained by routines in this file.** Periodically we are called and we run a quick check of all the** active chains to determine if there is a command to be executed,** and if the rup is ready to accept it.***//*** Allocate an empty command block.*/struct CmdBlk *RIOGetCmdBlk(){ struct CmdBlk *CmdBlkP; CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk)); if (CmdBlkP) bzero(CmdBlkP, sizeof(struct CmdBlk)); return CmdBlkP;}/*** Return a block to the head of the free list.*/voidRIOFreeCmdBlk(CmdBlkP)struct CmdBlk *CmdBlkP;{ sysfree((void *)CmdBlkP, sizeof(struct CmdBlk));}/*** attach a command block to the list of commands to be performed for** a given rup.*/intRIOQueueCmdBlk(HostP, Rup, CmdBlkP)struct Host *HostP;uint Rup;struct CmdBlk *CmdBlkP;{ struct CmdBlk **Base; struct UnixRup *UnixRupP; unsigned long flags;#ifdef CHECK CheckHostP( HostP ); CheckRup( Rup ); CheckCmdBlkP( CmdBlkP );#endif if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) { rio_dprintk (RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n",Rup); RIOFreeCmdBlk( CmdBlkP ); return RIO_FAIL; } UnixRupP = &HostP->UnixRups[Rup]; rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); /* ** If the RUP is currently inactive, then put the request ** straight on the RUP.... */ if ( (UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE ) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg,CmdBlkP) :TRUE)) { rio_dprintk (RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]); /* ** Whammy! blat that pack! */ HostP->Copy( (caddr_t)&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt ), sizeof(PKT) ); /* ** place command packet on the pending position. */ UnixRupP->CmdPendingP = CmdBlkP; /* ** set the command register */ WWORD(UnixRupP->RupP->txcontrol , TX_PACKET_READY); rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); return RIO_SUCCESS; } rio_dprintk (RIO_DEBUG_CMD, "RUP active - en-queing\n"); if ( UnixRupP->CmdsWaitingP != NULL) rio_dprintk (RIO_DEBUG_CMD, "Rup active - command waiting\n"); if ( UnixRupP->CmdPendingP != NULL ) rio_dprintk (RIO_DEBUG_CMD, "Rup active - command pending\n"); if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE ) rio_dprintk (RIO_DEBUG_CMD, "Rup active - command rup not ready\n"); Base = &UnixRupP->CmdsWaitingP; rio_dprintk (RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int)CmdBlkP,(int)Base); while ( *Base ) { rio_dprintk (RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int)(*Base));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -