riotable.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 945 行 · 第 1/2 页

C
945
字号
		rio_spin_lock_irqsave(&HostP->HostLock, lock_flags);		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {			rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);			continue;		}		for (entry = 0; entry < MAX_RUP; entry++) {			if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) {				HostMapP = &HostP->Mapping[entry];				rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name);				/*				 ** Check all four links of the unit are disconnected				 */				for (link = 0; link < LINKS_PER_UNIT; link++) {					if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) {						rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");						p->RIOError.Error = UNIT_IS_IN_USE;						rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);						return -EBUSY;					}				}				/*				 ** Slot has been allocated, BUT not booted/routed/				 ** connected/selected or anything else-ed				 */				SysPort = HostMapP->SysPort;				if (SysPort != NO_PORT) {					for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) {						PortP = p->RIOPortp[port];						rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n");						rio_spin_lock_irqsave(&PortP->portSem, sem_flags);						PortP->Mapped = 0;						if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {							rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n");							PortP->TxBufferIn = PortP->TxBufferOut = 0;							/* What should I do 							   wakeup( &PortP->TxBufferIn );							   wakeup( &PortP->TxBufferOut);							 */							PortP->InUse = NOT_INUSE;							/* What should I do 							   wakeup( &PortP->InUse );							   signal(PortP->TtyP->t_pgrp,SIGKILL);							   ttyflush(PortP->TtyP,(FREAD|FWRITE));							 */							PortP->State |= RIO_CLOSING | RIO_DELETED;						}						/*						 ** For the second slot of a 16 port RTA, the						 ** driver needs to reset the changes made to						 ** the phb to port mappings in RIORouteRup.						 */						if (PortP->SecondBlock) {							u16 dest_unit = HostMapP->ID;							u16 dest_port = port - SysPort;							u16 *TxPktP;							struct PKT *Pkt;							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));								rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", *TxPktP, Pkt->dest_unit, Pkt->dest_port, dest_unit, dest_port);								writew(dest_unit, &Pkt->dest_unit);								writew(dest_port, &Pkt->dest_port);							}							rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, PortP->PhbP->destination & 0xff, (PortP->PhbP->destination >> 8) & 0xff, dest_unit, dest_port);							writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);						}						rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);					}				}				rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n");				memset(HostMapP, 0, sizeof(struct Map));				work_done++;			}		}		rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);	}	/* XXXXX lock me up */	for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {		if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {			memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));			work_done++;		}		if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {			memset(&p->RIOConnectTable[entry], 0, sizeof(struct Map));			work_done++;		}	}	if (work_done)		return 0;	rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");	p->RIOError.Error = COULDNT_FIND_ENTRY;	return -ENXIO;}int RIOAssignRta(struct rio_info *p, struct Map *MapP){	int host;	struct Map *HostMapP;	char *sptr;	int link;	rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);	if ((MapP->ID != (u16) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) {		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;		return -EINVAL;	}	if (MapP->RtaUniqueNum == 0) {		rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n");		p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;		return -EINVAL;	}	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA);		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;		return -EINVAL;	}	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort);		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;		return -EINVAL;	}	/*	 ** Copy the name across to the map entry.	 */	MapP->Name[MAX_NAME_LEN - 1] = '\0';	sptr = MapP->Name;	while (*sptr) {		if (*sptr < ' ' || *sptr > '~') {			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");			p->RIOError.Error = BAD_CHARACTER_IN_NAME;			return -EINVAL;		}		sptr++;	}	for (host = 0; host < p->RIONumHosts; host++) {		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {				p->RIOError.Error = HOST_NOT_RUNNING;				return -ENXIO;			}			/*			 ** Now we have a host we need to allocate an ID			 ** if the entry does not already have one.			 */			if (MapP->ID == (u16) - 1) {				int nNewID;				rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name);				/*				 ** The idea here is to allow RTA's to be assigned				 ** before they actually appear on the network.				 ** This allows the addition of RTA's without having				 ** to plug them in.				 ** What we do is:				 **  - Find a free ID and allocate it to the RTA.				 **  - If this map entry is the second half of a				 **    16 port entry then find the other half and				 **    make sure the 2 cross reference each other.				 */				if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) {					p->RIOError.Error = COULDNT_FIND_ENTRY;					return -EBUSY;				}				MapP->ID = (u16) nNewID + 1;				rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);				HostMapP = &p->RIOHosts[host].Mapping[nNewID];				HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;				HostMapP->HostUniqueNum = MapP->HostUniqueNum;				HostMapP->ID = MapP->ID;				for (link = 0; link < LINKS_PER_UNIT; link++) {					HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;					HostMapP->Topology[link].Link = NO_LINK;				}				if (MapP->Flags & RTA16_SECOND_SLOT) {					int unit;					for (unit = 0; unit < MAX_RUP; unit++)						if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum)							break;					if (unit == MAX_RUP) {						p->RIOError.Error = COULDNT_FIND_ENTRY;						return -EBUSY;					}					HostMapP->Flags |= RTA16_SECOND_SLOT;					HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;					p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;					rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID);				}			}			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];			if (HostMapP->Flags & SLOT_IN_USE) {				rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);				p->RIOError.Error = ID_ALREADY_IN_USE;				return -EBUSY;			}			/*			 ** Assign the sys ports and the name, and mark the slot as			 ** being in use.			 */			HostMapP->SysPort = MapP->SysPort;			if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)				memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);			HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;#ifdef NEED_TO_FIX			RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]);#endif			if (MapP->Flags & RTA16_SECOND_SLOT)				HostMapP->Flags |= RTA16_SECOND_SLOT;			RIOReMapPorts(p, &p->RIOHosts[host], HostMapP);			/*			 ** Adjust 2nd block of 8 phbs			 */			if (MapP->Flags & RTA16_SECOND_SLOT)				RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);			if (HostMapP->SysPort != NO_PORT) {				if (HostMapP->SysPort < p->RIOFirstPortsBooted)					p->RIOFirstPortsBooted = HostMapP->SysPort;				if (HostMapP->SysPort > p->RIOLastPortsBooted)					p->RIOLastPortsBooted = HostMapP->SysPort;			}			if (MapP->Flags & RTA16_SECOND_SLOT)				rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);			else				rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);			return 0;		}	}	p->RIOError.Error = UNKNOWN_HOST_NUMBER;	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);	return -ENXIO;}int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP){	struct Port *PortP;	unsigned int SubEnt;	unsigned int HostPort;	unsigned int SysPort;	u16 RtaType;	unsigned long flags;	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID);	/*	 ** We need to tell the UnixRups which sysport the rup corresponds to	 */	HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort;	if (HostMapP->SysPort == NO_PORT)		return (0);	RtaType = GetUnitType(HostMapP->RtaUniqueNum);	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1);	/*	 ** now map each of its eight ports	 */	for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) {		rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort);		SysPort = HostMapP->SysPort + SubEnt;	/* portnumber within system */		/* portnumber on host */		HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt;		rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);		PortP = p->RIOPortp[SysPort];		rio_dprintk(RIO_DEBUG_TABLE, "Map port\n");		/*		 ** Point at all the real neat data structures		 */		rio_spin_lock_irqsave(&PortP->portSem, flags);		PortP->HostP = HostP;		PortP->Caddr = HostP->Caddr;		/*		 ** The PhbP cannot be filled in yet		 ** unless the host has been booted		 */		if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {			struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];			PortP->TxAdd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add));			PortP->TxStart = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start));			PortP->TxEnd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end));			PortP->RxRemove = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove));			PortP->RxStart = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start));			PortP->RxEnd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end));		} else			PortP->PhbP = NULL;		/*		 ** port related flags		 */		PortP->HostPort = HostPort;		/*		 ** For each part of a 16 port RTA, RupNum is ID - 1.		 */		PortP->RupNum = HostMapP->ID - 1;		if (HostMapP->Flags & RTA16_SECOND_SLOT) {			PortP->ID2 = HostMapP->ID2 - 1;			PortP->SecondBlock = 1;		} else {			PortP->ID2 = 0;			PortP->SecondBlock = 0;		}		PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;		/*		 ** If the port was already mapped then thats all we need to do.		 */		if (PortP->Mapped) {			rio_spin_unlock_irqrestore(&PortP->portSem, flags);			continue;		} else			HostMapP->Flags &= ~RTA_NEWBOOT;		PortP->State = 0;		PortP->Config = 0;		/*		 ** Check out the module type - if it is special (read only etc.)		 ** then we need to set flags in the PortP->Config.		 ** Note: For 16 port RTA, all ports are of the same type.		 */		if (RtaType == TYPE_RTA16) {			PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];		} else {			if (SubEnt < PORTS_PER_MODULE)				PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];			else				PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];		}		/*		 ** more port related flags		 */		PortP->PortState = 0;		PortP->ModemLines = 0;		PortP->ModemState = 0;		PortP->CookMode = COOK_WELL;		PortP->ParamSem = 0;		PortP->FlushCmdBodge = 0;		PortP->WflushFlag = 0;		PortP->MagicFlags = 0;		PortP->Lock = 0;		PortP->Store = 0;		PortP->FirstOpen = 1;		/*		 ** Buffers 'n things		 */		PortP->RxDataStart = 0;		PortP->Cor2Copy = 0;		PortP->Name = &HostMapP->Name[0];		PortP->statsGather = 0;		PortP->txchars = 0;		PortP->rxchars = 0;		PortP->opens = 0;		PortP->closes = 0;		PortP->ioctls = 0;		if (PortP->TxRingBuffer)			memset(PortP->TxRingBuffer, 0, p->RIOBufferSize);		else if (p->RIOBufferSize) {			PortP->TxRingBuffer = kmalloc(p->RIOBufferSize, GFP_KERNEL);			memset(PortP->TxRingBuffer, 0, p->RIOBufferSize);		}		PortP->TxBufferOut = 0;		PortP->TxBufferIn = 0;		PortP->Debug = 0;		/*		 ** LastRxTgl stores the state of the rx toggle bit for this		 ** port, to be compared with the state of the next pkt received.		 ** If the same, we have received the same rx pkt from the RTA		 ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.		 */		PortP->LastRxTgl = ~(u8) PHB_RX_TGL;		/*		 ** and mark the port as usable		 */		PortP->Mapped = 1;		rio_spin_unlock_irqrestore(&PortP->portSem, flags);	}	if (HostMapP->SysPort < p->RIOFirstPortsMapped)		p->RIOFirstPortsMapped = HostMapP->SysPort;	if (HostMapP->SysPort > p->RIOLastPortsMapped)		p->RIOLastPortsMapped = HostMapP->SysPort;	return 0;}int RIOChangeName(struct rio_info *p, struct Map *MapP){	int host;	struct Map *HostMapP;	char *sptr;	rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);	if (MapP->ID > MAX_RUP) {		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;		return -EINVAL;	}	MapP->Name[MAX_NAME_LEN - 1] = '\0';	sptr = MapP->Name;	while (*sptr) {		if (*sptr < ' ' || *sptr > '~') {			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");			p->RIOError.Error = BAD_CHARACTER_IN_NAME;			return -EINVAL;		}		sptr++;	}	for (host = 0; host < p->RIONumHosts; host++) {		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {				p->RIOError.Error = HOST_NOT_RUNNING;				return -ENXIO;			}			if (MapP->ID == 0) {				memcpy(p->RIOHosts[host].Name, MapP->Name, MAX_NAME_LEN);				return 0;			}			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];			if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) {				p->RIOError.Error = RTA_NUMBER_WRONG;				return -ENXIO;			}			memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);			return 0;		}	}	p->RIOError.Error = UNKNOWN_HOST_NUMBER;	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);	return -ENXIO;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?