📄 rioroute.c
字号:
*/ if ( (HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq) ) { if (RtaType == TYPE_RTA16) { ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1; rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq,ThisUnit,ThisUnit2); } else rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq,ThisUnit); /* ** If we have no knowledge of booting it, then the host has ** been re-booted, and so we must kill the RTA, so that it ** will be booted again (potentially with new bins) ** and it will then re-ask for an ID, which we will service. */ if ( (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED) ) { if ( !(HostP->Mapping[ThisUnit].Flags & MSG_DONE) ) { if ( !p->RIONoMessage ) cprintf("RTA '%s' is being updated.\n",HostP->Mapping[ThisUnit].Name); HostP->Mapping[ThisUnit].Flags |= MSG_DONE; } PktReplyP->Command = ROUTE_FOAD; HostP->Copy("RT_FOAD",PktReplyP->CommandText,7); RIOQueueCmdBlk(HostP, Rup, CmdBlkP); return TRUE; } /* ** Send the ID (entry) to this RTA. The ID number is implicit as ** the offset into the table. It is worth noting at this stage ** that offset zero in the table contains the entries for the ** RTA with ID 1!!!! */ PktReplyP->Command = ROUTE_ALLOCATE; PktReplyP->IDNum = ThisUnit+1; if (RtaType == TYPE_RTA16) { if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) /* ** Adjust the phb and tx pkt dest_units for 2nd block of 8 ** only if the RTA has ports associated (SLOT_IN_USE) */ RIOFixPhbs(p, HostP, ThisUnit2); PktReplyP->IDNum2 = ThisUnit2+1; rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2); } else { PktReplyP->IDNum2 = ROUTE_NO_ID; rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name,PktReplyP->IDNum); } HostP->Copy("RT_ALLOCAT",PktReplyP->CommandText,10); RIOQueueCmdBlk( HostP, Rup, CmdBlkP); /* ** If this is a freshly booted RTA, then we need to re-open ** the ports, if any where open, so that data may once more ** flow around the system! */ if ( (HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT) ) { /* ** look at the ports associated with this beast and ** see if any where open. If they was, then re-open ** them, using the info from the tty flags. */ for ( port=0; port<PORTS_PER_RTA; port++ ) { PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]; if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) { rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n"); rio_spin_lock_irqsave(&PortP->portSem, flags); PortP->MagicFlags |= MAGIC_REBOOT; rio_spin_unlock_irqrestore(&PortP->portSem, flags); } } if (RtaType == TYPE_RTA16) { for ( port=0; port<PORTS_PER_RTA; port++ ) { PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]; if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) { rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n"); rio_spin_lock_irqsave(&PortP->portSem, flags); PortP->MagicFlags |= MAGIC_REBOOT; rio_spin_unlock_irqrestore(&PortP->portSem, flags); } } } } /* ** keep a copy of the module types! */ HostP->UnixRups[ThisUnit].ModTypes = Mod; if (RtaType == TYPE_RTA16) HostP->UnixRups[ThisUnit2].ModTypes = Mod; /* ** If either of the modules on this unit is read-only or write-only ** or none-xprint, then we need to transfer that info over to the ** relevant ports. */ if ( HostP->Mapping[ThisUnit].SysPort != NO_PORT ) { for ( port=0; port<PORTS_PER_MODULE; port++ ) { p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK; p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port]; p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK; p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port]; } if (RtaType == TYPE_RTA16) { for ( port=0; port<PORTS_PER_MODULE; port++ ) { p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK; p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port]; p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK; p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port]; } } } /* ** Job done, get on with the interrupts! */ return TRUE; } } /* ** There is no table entry for this RTA at all. ** ** Lets check to see if we actually booted this unit - if not, ** then we reset it and it will go round the loop of being booted ** we can then worry about trying to fit it into the table. */ for ( ThisUnit=0; ThisUnit<HostP->NumExtraBooted; ThisUnit++ ) if ( HostP->ExtraUnits[ThisUnit] == RtaUniq ) break; if ( ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS ) { /* ** if the unit wasn't in the table, and the table wasn't full, then ** we reset the unit, because we didn't boot it. ** However, if the table is full, it could be that we did boot ** this unit, and so we won't reboot it, because it isn't really ** all that disasterous to keep the old bins in most cases. This ** is a rather tacky feature, but we are on the edge of reallity ** here, because the implication is that someone has connected ** 16+MAX_EXTRA_UNITS onto one host. */ static int UnknownMesgDone = 0; if ( !UnknownMesgDone ) { if (! p->RIONoMessage) cprintf("One or more unknown RTAs are being updated.\n"); UnknownMesgDone = 1; } PktReplyP->Command = ROUTE_FOAD; HostP->Copy("RT_FOAD",PktReplyP->CommandText,7); } else { /* ** we did boot it (as an extra), and there may now be a table ** slot free (because of a delete), so we will try to make ** a tentative entry for it, so that the configurator can see it ** and fill in the details for us. */ if (RtaType == TYPE_RTA16) { if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) { RIODefaultName(p, HostP, ThisUnit); FillSlot(ThisUnit, ThisUnit2, RtaUniq, HostP); } } else { if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) { RIODefaultName(p, HostP, ThisUnit); FillSlot(ThisUnit, 0, RtaUniq, HostP); } } PktReplyP->Command = ROUTE_USED; HostP->Copy("RT_USED",PktReplyP->CommandText,7); } RIOQueueCmdBlk( HostP, Rup, CmdBlkP); return TRUE;}voidRIOFixPhbs(p, HostP, unit)struct rio_info *p;struct Host *HostP;uint unit;{ ushort link, port; struct Port *PortP; unsigned long flags; int PortN = HostP->Mapping[unit].SysPort; rio_dprintk (RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN); if (PortN != -1) { ushort dest_unit = HostP->Mapping[unit].ID2; /* ** Get the link number used for the 1st 8 phbs on this unit. */ PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort]; link = RWORD(PortP->PhbP->link); for (port = 0; port < PORTS_PER_RTA; port++, PortN++) { ushort dest_port = port + 8;#if 0 uint PktInt;#endif WORD *TxPktP; PKT *Pkt; PortP = p->RIOPortp[PortN]; rio_spin_lock_irqsave(&PortP->portSem, flags); /* ** If RTA is not powered on, the tx packets will be ** unset, so go no further. */ if (PortP->TxStart == 0) { rio_dprintk (RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n"); rio_spin_unlock_irqrestore(&PortP->portSem, flags); break; } /* ** For the second slot of a 16 port RTA, the driver needs to ** sort out the phb to port mappings. The dest_unit for this ** group of 8 phbs is set to the dest_unit of the accompanying ** 8 port block. The dest_port of the second unit is set to ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6 ** (being the second map ID) will be sent to dest_unit 5, port ** 14. When this RTA is deleted, dest_unit for ID 6 will be ** restored, and the dest_port will be reduced by 8. ** Transmit packets also have a destination field which needs ** adjusting in the same manner. ** Note that the unit/port bytes in 'dest' are swapped. ** We also need to adjust the phb and rup link numbers for the ** second block of 8 ttys. */ for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) { /* ** *TxPktP is the pointer to the transmit packet on the host ** card. This needs to be translated into a 32 bit pointer ** so it can be accessed from the driver. */ Pkt = (PKT *) RIO_PTR(HostP->Caddr,RINDW(TxPktP)); /* ** If the packet is used, reset it. */ Pkt = (PKT *)((uint)Pkt & ~PKT_IN_USE); WBYTE(Pkt->dest_unit, dest_unit); WBYTE(Pkt->dest_port, dest_port); } rio_dprintk (RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", RWORD(PortP->PhbP->destination) & 0xff, (RWORD(PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port); WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8)); WWORD(PortP->PhbP->link, link); rio_spin_unlock_irqrestore(&PortP->portSem, flags); } /* ** Now make sure the range of ports to be serviced includes ** the 2nd 8 on this 16 port RTA. */ if (link > 3) return; if (((unit * 8) + 7) > RWORD(HostP->LinkStrP[link].last_port)) { rio_dprintk (RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7); WWORD(HostP->LinkStrP[link].last_port, (unit * 8) + 7); } }}/*** Check to see if the new disconnection has isolated this unit.** If it has, then invalidate all its link information, and tell** the world about it. This is done to ensure that the configurator** only gets up-to-date information about what is going on.*/static intRIOCheckIsolated(p, HostP, UnitId)struct rio_info * p;struct Host *HostP;uint UnitId;{ unsigned long flags; rio_spin_lock_irqsave(&HostP->HostLock, flags);#ifdef CHECK CheckHostP( HostP ); CheckUnitId( UnitId );#endif if ( RIOCheck( HostP, UnitId ) ) { rio_dprintk (RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId); rio_spin_unlock_irqrestore(&HostP->HostLock, flags); return(0); } RIOIsolate(p, HostP, UnitId ); RIOSetChange(p); rio_spin_unlock_irqrestore(&HostP->HostLock, flags); return 1;}/*** Invalidate all the link interconnectivity of this unit, and of** all the units attached to it. This will mean that the entire** subnet will re-introduce itself.*/static intRIOIsolate(p, HostP, UnitId)struct rio_info * p;struct Host * HostP;uint UnitId; { uint link, unit;#ifdef CHECK CheckHostP( HostP ); CheckUnitId( UnitId );#endif UnitId--; /* this trick relies on the Unit Id being UNSIGNED! */ if ( UnitId >= MAX_RUP ) /* dontcha just lurv unsigned maths! */ return(0); if ( HostP->Mapping[UnitId].Flags & BEEN_HERE ) return(0); HostP->Mapping[UnitId].Flags |= BEEN_HERE; if ( p->RIOPrintDisabled == DO_PRINT ) rio_dprintk (RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name); for ( link=0; link<LINKS_PER_UNIT; link++) { unit = HostP->Mapping[UnitId].Topology[link].Unit; HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT; HostP->Mapping[UnitId].Topology[link].Link = NO_LINK; RIOIsolate(p, HostP, unit ); } HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; return 1;}static intRIOCheck(HostP, UnitId)struct Host *HostP;uint UnitId;{ unsigned char link;#ifdef CHECK CheckHostP( HostP ); CheckUnitId( UnitId );#endif/* rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */ rio_dprintk (RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId); if ( UnitId == HOST_ID ) { /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */ return 1; } UnitId--; if ( UnitId >= MAX_RUP ) { /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */ return 0; } for ( link=0; link<LINKS_PER_UNIT; link++ ) { if ( HostP->Mapping[UnitId].Topology[link].Unit==HOST_ID ) { /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", UnitId, 'A'+link)); */ return 1; } } if ( HostP->Mapping[UnitId].Flags & BEEN_HERE ) { /* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -