rioroute.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,045 行 · 第 1/3 页
C
1,045 行
** 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 1; } } /* ** 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) printk(KERN_DEBUG "rio: 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); rio_fill_host_slot(ThisUnit, ThisUnit2, RtaUniq, HostP); } } else { if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) { RIODefaultName(p, HostP, ThisUnit); rio_fill_host_slot(ThisUnit, 0, RtaUniq, HostP); } } PktReplyP->Command = ROUTE_USED; HostP->Copy("RT_USED", PktReplyP->CommandText, 7); } RIOQueueCmdBlk(HostP, Rup, CmdBlkP); return 1;}void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit){ unsigned short 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) { unsigned short 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 = readw(&PortP->PhbP->link); for (port = 0; port < PORTS_PER_RTA; port++, PortN++) { unsigned short dest_port = port + 8; u16 *TxPktP; struct 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 = (struct PKT *) RIO_PTR(HostP->Caddr, readw(TxPktP)); /* ** If the packet is used, reset it. */ Pkt = (struct PKT *) ((unsigned long) Pkt & ~PKT_IN_USE); writeb(dest_unit, &Pkt->dest_unit); writeb(dest_port, &Pkt->dest_port); } rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", readw(&PortP->PhbP->destination) & 0xff, (readw(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port); writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination); writew(link, &PortP->PhbP->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) > readw(&HostP->LinkStrP[link].last_port)) { rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7); writew((unit * 8) + 7, &HostP->LinkStrP[link].last_port); } }}/*** 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 int RIOCheckIsolated(struct rio_info *p, struct Host *HostP, unsigned int UnitId){ unsigned long flags; rio_spin_lock_irqsave(&HostP->HostLock, flags); 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 int RIOIsolate(struct rio_info *p, struct Host *HostP, unsigned int UnitId){ unsigned int link, unit; 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 int RIOCheck(struct Host *HostP, unsigned int UnitId){ unsigned char link;/* 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)); */ return 0; } HostP->Mapping[UnitId].Flags |= BEEN_HERE; for (link = 0; link < LINKS_PER_UNIT; link++) { /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */ if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) { /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */ HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; return 1; } } HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */ return 0;}/*** Returns the type of unit (host, 16/8 port RTA)*/unsigned int GetUnitType(unsigned int Uniq){ switch ((Uniq >> 28) & 0xf) { case RIO_AT:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?