Beispiel #1
0
/****************************************
 * Put a packet onto the end of the
 * free list
 ****************************************/
void put_free_end(struct Host *HostP, struct PKT __iomem *PktP)
{
    struct rio_free_list __iomem *tmp_pointer;
    unsigned short old_end, new_end;
    unsigned long flags;

    rio_spin_lock_irqsave(&HostP->HostLock, flags);

     /*************************************************
    * Put a packet back onto the back of the free list
    *
    ************************************************/

    rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%p)\n", PktP);

    if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) {
        new_end = RIO_OFF(HostP->Caddr, PktP);
        tmp_pointer = (struct rio_free_list __iomem *) RIO_PTR(HostP->Caddr, old_end);
        writew(new_end, &tmp_pointer->next);
        writew(old_end, &((struct rio_free_list __iomem *) PktP)->prev);
        writew(TPNULL, &((struct rio_free_list __iomem *) PktP)->next);
        writew(new_end, &HostP->ParmMapP->free_list_end);
    } else {        /* First packet on the free list this should never happen! */
        rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
        writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end);
        tmp_pointer = (struct rio_free_list __iomem *) PktP;
        writew(TPNULL, &tmp_pointer->prev);
        writew(TPNULL, &tmp_pointer->next);
    }
    rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
    rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
}
Beispiel #2
0
/*
** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set
** for the next packet on the queue. It will also set PktP to point to the
** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
** then can_remove_receive() returns 0.
*/
int can_remove_receive(struct PKT __iomem **PktP, struct Port *PortP)
{
    if (readw(PortP->RxRemove) & PKT_IN_USE) {
        *PktP = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE);
        return 1;
    }
    return 0;
}
Beispiel #3
0
/*
** We can add another packet to a transmit queue if the packet pointer pointed
** to by the TxAdd pointer has PKT_IN_USE clear in its address.
*/
int can_add_transmit(struct PKT __iomem **PktP, struct Port *PortP)
{
    struct PKT __iomem *tp;

    *PktP = tp = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd));

    return !((unsigned long) tp & PKT_IN_USE);
}
Beispiel #4
0
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;

		
		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 __iomem *TxPktP;
			struct PKT __iomem *Pkt;

			PortP = p->RIOPortp[PortN];

			rio_spin_lock_irqsave(&PortP->portSem, flags);
			
			if (!PortP->TxStart) {
				rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
				break;
			}

			
			for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
				
				Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP));

				
				Pkt = (struct PKT __iomem *) ((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);
		}
		
		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);
		}
	}
Beispiel #5
0
/*
** config.rio has taken a dislike to one of the gross maps entries.
** if the entry is suitably inactive, then we can gob on it and remove
** it from the table.
*/
int RIODeleteRta(struct rio_info *p, struct Map *MapP)
{
	int host, entry, port, link;
	int SysPort;
	struct Host *HostP;
	struct Map *HostMapP;
	struct Port *PortP;
	int work_done = 0;
	unsigned long lock_flags, sem_flags;

	rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum);

	for (host = 0; host < p->RIONumHosts; host++) {
		HostP = &p->RIOHosts[host];

		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 __iomem *TxPktP;
							struct PKT __iomem *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 __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP));
								rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&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, readb(&PortP->PhbP->destination) & 0xff, (readb(&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++;
			}
		}
Beispiel #6
0
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 __iomem *TxPktP;
			struct PKT __iomem *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) {
				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 __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP));

				/*
				 ** If the packet is used, reset it.
				 */
				Pkt = (struct PKT __iomem *) ((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);
		}
	}
Beispiel #7
0
/*
** Here we go - if there is an empty rup, fill it!
** must be called at splrio() or higher.
*/
void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
{
	struct CmdBlk *CmdBlkP;
	struct UnixRup *UnixRupP;
	struct PKT __iomem *PacketP;
	unsigned short Rup;
	unsigned long flags;


	Rup = MAX_RUP + LINKS_PER_UNIT;

	do {			/* do this loop for each RUP */
		/*
		 ** locate the rup we are processing & lock it
		 */
		UnixRupP = &HostP->UnixRups[--Rup];

		spin_lock_irqsave(&UnixRupP->RupLock, flags);

		/*
		 ** First check for incoming commands:
		 */
		if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) {
			int FreeMe;

			PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt));

			switch (readb(&PacketP->dest_port)) {
			case BOOT_RUP:
				rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", readb(&PacketP->len) & 0x80 ? "Command" : "Data", readb(&PacketP->data[0]));
				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
				FreeMe = RIOBootRup(p, Rup, HostP, PacketP);
				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
				break;

			case COMMAND_RUP:
				/*
				 ** Free the RUP lock as loss of carrier causes a
				 ** ttyflush which will (eventually) call another
				 ** routine that uses the RUP lock.
				 */
				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
				FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
				if (readb(&PacketP->data[5]) == MEMDUMP) {
					rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6])));
					rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32);
				}
				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
				break;

			case ROUTE_RUP:
				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
				FreeMe = RIORouteRup(p, Rup, HostP, PacketP);
				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
				break;

			default:
				rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", readb(&PacketP->dest_port));
				FreeMe = 1;
				break;
			}

			if (FreeMe) {
				rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n");
				put_free_end(HostP, PacketP);

				writew(RX_RUP_INACTIVE, &UnixRupP->RupP->rxcontrol);

				if (readw(&UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) {
					rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup);
					writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &UnixRupP->RupP->handshake);
				}
			}
		}

		/*
		 ** IF a command was running on the port,
		 ** and it has completed, then tidy it up.
		 */
		if ((CmdBlkP = UnixRupP->CmdPendingP) &&	/* ASSIGN! */
		    (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
			/*
			 ** we are idle.
			 ** there is a command in pending.
			 ** Therefore, this command has finished.
			 ** So, wakeup whoever is waiting for it (and tell them
			 ** what happened).
			 */
			if (CmdBlkP->Packet.dest_port == BOOT_RUP)
				rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]);

			rio_dprintk(RIO_DEBUG_CMD, "Command %p completed\n", CmdBlkP);

			/*
			 ** Clear the Rup lock to prevent mutual exclusion.
			 */
			if (CmdBlkP->PostFuncP) {
				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
				(*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP);
				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
			}

			/*
			 ** ....clear the pending flag....
			 */
			UnixRupP->CmdPendingP = NULL;

			/*
			 ** ....and return the command block to the freelist.
			 */
			RIOFreeCmdBlk(CmdBlkP);
		}

		/*
		 ** If there is a command for this rup, and the rup
		 ** is idle, then process the command
		 */
		if ((CmdBlkP = UnixRupP->CmdsWaitingP) &&	/* ASSIGN! */
		    (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
			/*
			 ** if the pre-function is non-zero, call it.
			 ** If it returns RIO_FAIL then don't
			 ** send this command yet!
			 */
			if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : 1)) {
				rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command %p\n", CmdBlkP);
			} else {
				rio_dprintk(RIO_DEBUG_CMD, "Start new command %p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]);
				/*
				 ** Whammy! blat that pack!
				 */
				HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));

				/*
				 ** remove the command from the rup command queue...
				 */
				UnixRupP->CmdsWaitingP = CmdBlkP->NextP;

				/*
				 ** ...and place it on the pending position.
				 */
				UnixRupP->CmdPendingP = CmdBlkP;

				/*
				 ** set the command register
				 */
				writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);

				/*
				 ** the command block will be freed
				 ** when the command has been processed.
				 */
			}
		}
		spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
	} while (Rup);
}
Beispiel #8
0
/*
** attach a command block to the list of commands to be performed for
** a given rup.
*/
int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
{
	struct CmdBlk **Base;
	struct UnixRup *UnixRupP;
	unsigned long flags;

	if (Rup >= (unsigned short) (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) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP)
																	     : 1)) {
		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(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));

		/*
		 ** place command packet on the pending position.
		 */
		UnixRupP->CmdPendingP = CmdBlkP;

		/*
		 ** set the command register
		 */
		writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);

		rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);

		return 0;
	}
	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 (readw(&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 %p at %p\n", CmdBlkP, Base);

	while (*Base) {
		rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk %p here\n", *Base);
		Base = &((*Base)->NextP);
		rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk %p at %p\n", CmdBlkP, Base);
	}

	rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk %p at %p\n", CmdBlkP, Base);

	*Base = CmdBlkP;

	CmdBlkP->NextP = NULL;

	rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);

	return 0;
}
Beispiel #9
0
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;

    ;

    /*
     ** 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);
    ;

    /*
     ** now map each of its eight ports
     */
    for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) {
        ;
        SysPort = HostMapP->SysPort + SubEnt;	/* portnumber within system */
        /* portnumber on host */

        HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt;

        ;
        PortP = p->RIOPortp[SysPort];
        ;

        /*
         ** 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 __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
            PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add));
            PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start));
            PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end));
            PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove));
            PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start));
            PortP->RxEnd = (u16 __iomem *) 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 = kzalloc(p->RIOBufferSize, GFP_KERNEL);
        }
        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;
}
Beispiel #10
0
/*
** config.rio has taken a dislike to one of the gross maps entries.
** if the entry is suitably inactive, then we can gob on it and remove
** it from the table.
*/
int RIODeleteRta(struct rio_info *p, struct Map *MapP)
{
    int host, entry, port, link;
    int SysPort;
    struct Host *HostP;
    struct Map *HostMapP;
    struct Port *PortP;
    int work_done = 0;
    unsigned long lock_flags, sem_flags;

    ;

    for (host = 0; host < p->RIONumHosts; host++) {
        HostP = &p->RIOHosts[host];

        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];
                ;

                /*
                 ** Check all four links of the unit are disconnected
                 */
                for (link = 0; link < LINKS_PER_UNIT; link++) {
                    if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) {
                        ;
                        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_spin_lock_irqsave(&PortP->portSem, sem_flags);

                        PortP->Mapped = 0;

                        if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {

                            ;
                            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 __iomem *TxPktP;
                            struct PKT __iomem *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 __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP));
                                ;
                                writew(dest_unit, &Pkt->dest_unit);
                                writew(dest_port, &Pkt->dest_port);
                            }
                            ;
                            writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
                        }
                        rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
                    }
                }
                ;
                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;

    ;
    p->RIOError.Error = COULDNT_FIND_ENTRY;
    return -ENXIO;
}