[comp.sys.ibm.pc.rt] Patch for 6152 token ring driver

mlewis@ibmpa.UUCP (Mark S. Lewis) (08/12/89)

Subject: Fixes to 6152 token ring driver IBM/4.3 Rel 2
Index:   sys/ca_atr/if_{lan.c, lanreg.h, lanvar.h}

Description:  This patch fixes three problems.

         1)  Incorrect sequence in handling simultaneous
             interrupts.  Causes "invalid command in ARB=0xff"
             message.

         2)  Error counter overflow conditions was not
             handled properly.  Now the errors are
             logged to the console and the counters
             are reset.

         3)  Removes a timeout when ifconfig down and
             then halt.

Fix:     Apply this patch to the DEC 88 release (rcsid 12.3)
         and rebuild kernel.

Bugs:    There remains an problem when disconnecting the
         token ring cable at the adapter end only.  The
         adapter does not get reset properly.  DO NOT
         disconnect cable at adapter end or reboot will
         be necessary.

*** if_lan.c	Fri Aug 11 11:23:15 1989
--- if_lan.c.fix	Fri Aug 11 09:36:38 1989
***************
*** 1,13 ****
  /*
!  * 5799-WZQ (C) COPYRIGHT IBM CORPORATION  1986,1987,1988
   * LICENSED MATERIALS - PROPERTY OF IBM
   * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
   */
! /* $Header:if_lan.c 12.3$ */
! /* $ACIS:if_lan.c 12.3$ */
  
  #if !defined(lint) && !defined(NO_RCS_HDRS)
! static char *rcsid = "$Header:if_lan.c 12.3$";
  #endif
  
  /*
--- 1,12 ----
  /*
!  * 5799-CGZ (C) COPYRIGHT IBM CORPORATION  1986,1987,1988
   * LICENSED MATERIALS - PROPERTY OF IBM
   * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
   */
! /* $Header: if_lan.c,v 12.5 89/08/10 17:17:19 mlewis Exp $ */
  
  #if !defined(lint) && !defined(NO_RCS_HDRS)
! static char *rcsid = "$Header: if_lan.c,v 12.5 89/08/10 17:17:19 mlewis Exp $";
  #endif
  
  /*
***************
*** 280,297 ****
  
  
  	old_window = get_128_window();
! 	set_128_window(trs->sram_window);
  
  	if (unit < NLAN && (iod = trinfo[unit]) != 0 && iod->iod_alive != 0){
  /***************************************************************************
   * To do a reset we will issue a DIR CLOSE ADAPTER command                 *
   ***************************************************************************/
! 		trs->srbfree = 1;	/* indicate SRB in use */
! 		MM_OUT(&srb->close.command, DIR_CLOSE);     /* close command */
! 		/* tell adapter: command in SRB */
! 		set_128_window((int)trs->tr_window_addr);
! 		MM_OUT(&trs->aca->set.isra_l, CMD_IN_SRB);
! 		trsleep(ifp->if_unit);		/* wait for it to complete */
  		MM_OUT(&trs->aca->reset.isrp_h, ~(INT_ENABLE)); /* paranoia */
  		DEBUGF(tokdebug, printf("lan%d: reset\n", unit);)
  	}
--- 279,301 ----
  
  
  	old_window = get_128_window();
! 	set_128_window((int)trs->tr_window_addr);
  
  	if (unit < NLAN && (iod = trinfo[unit]) != 0 && iod->iod_alive != 0){
  /***************************************************************************
   * To do a reset we will issue a DIR CLOSE ADAPTER command                 *
   ***************************************************************************/
!                 if (ifp->if_flags & IFF_RUNNING) {
! 			set_128_window(trs->sram_window);
! 			trs->srbfree = 1;	/* indicate SRB in use */
! 			/* close command */
! 			MM_OUT(&srb->close.command, DIR_CLOSE);
! 			/* tell adapter: command in SRB */
! 			set_128_window((int)trs->tr_window_addr);
! 			MM_OUT(&trs->aca->set.isra_l, CMD_IN_SRB);
! 			/* wait for it to complete */
! 			trsleep(ifp->if_unit);
! 		}
  		MM_OUT(&trs->aca->reset.isrp_h, ~(INT_ENABLE)); /* paranoia */
  		DEBUGF(tokdebug, printf("lan%d: reset\n", unit);)
  	}
***************
*** 373,378 ****
--- 377,383 ----
  		for (i=0; i < sizeof(*trs->cb.srb); i++)
  			MM_OUT(((char *)(trs->cb.srb) + i), 0);
  
+ 
  		/* set open parameters in SRB */
  		MM_OUT(&srb->open_cmd.command, DIR_OPEN_ADAPTER); /* open cmd */
  		MM_OUTW(&srb->open_cmd.open_options, OPEN_PASS_BCON_MAC);
***************
*** 422,428 ****
  	/* load SRB to request transmit */
  
        	MM_OUT(&srb->xmit.command, XMIT_UI_FRM); /* xmit ui frame */
!  
   	MM_OUTW(&srb->xmit.station_id, trs->exsap_station);
  	/* tell adapter that SRB loaded and ask for SRB free interrupt */
  	set_128_window((int)trs->tr_window_addr);
--- 427,433 ----
  	/* load SRB to request transmit */
  
        	MM_OUT(&srb->xmit.command, XMIT_UI_FRM); /* xmit ui frame */
! 
   	MM_OUTW(&srb->xmit.station_id, trs->exsap_station);
  	/* tell adapter that SRB loaded and ask for SRB free interrupt */
  	set_128_window((int)trs->tr_window_addr);
***************
*** 496,595 ****
  
  		DEBUGF(tokdebug, printf("lan%d: ISRPL = %x\n", unit, status);)
  
  
- 		if (status & ASB_FREE_INT){  /* Is Adapter Status Block Free? */
- 		register union sr_asb *asb = trs->cb.asb;  /* pointer to ASB */
- 
- 		set_128_window(trs->sram_window);
- 
- 			switch (command = MM_IN(&asb->rec_resp.command)) {
- 			case REC_DATA:		/* Receive */
- 				/* Response not valid? */
- 				if (MM_IN(&asb->rec_resp.retcode) != 0xff)
- 				printf("lan%d: ASB bad receive response =%x\n",
- 				unit, MM_IN(&asb->rec_resp.retcode));
- 				break;
- 
- 			case XMIT_DIR_FRAME:	/* Transmit */
- 				/* Response not valid? */
- 				if (MM_IN(&asb->xmit_resp.retcode) != 0xff)
- 				printf("lan%d: ASB response err on xmit =%x\n",
- 				unit, MM_IN(&asb->xmit_resp.retcode));
- 				break;
- 
- 			case XMIT_UI_FRM:   	/* Transmit */
- 				/* Response not valid? */
- 				if (MM_IN(&asb->xmit_resp.retcode) != 0xff)
- 				printf("lan%d: ASB response err on xmit =%x\n",
- 				unit, MM_IN(&asb->xmit_resp.retcode));
- 				break;
- 
- 			default:
- 				printf("lan%d: Invalid command in ASB =%x\n",
- 				unit, command);
- 				break;
- 			}
- 		
- 			/* Clear this interrupt bit */
- 			set_128_window((int)trs->tr_window_addr);
- 			MM_OUT(&trs->aca->reset.isrp_l, ~(ASB_FREE_INT));
- 		}
- 
- 		if (status & ARB_CMD_INT) {	/* Command for PC to process? */
- 
- 			set_128_window(trs->sram_window);
- 			switch (command = MM_IN(&trs->cb.arb->log.command)) {
- 			case DIR_READ_LOG:	/* Read error counters */
- 				printf("lan%d: ARB read error log command\n",
- 				unit);
- 				break;
- 
- 			case DLC_STATUS:    /* DLC status change */	
- 				printf("lan%d: ARB new DLC  status = 0x%x\n",
- 					unit, MM_INW(&trs->cb.arb->dlc.status));
- 				break;
- 
- 			case REC_DATA:		/* Adapter has data for PC */
- 				/* Call receive interrupt handler */
- 				trrint(unit);
- 				break;
- 
- 			case RING_STAT_CHANGE:	/* Ring status change */
- 				if (MM_INW(&trs->cb.arb->stat.ring_status) & (SIGNAL_LOSS + LOBE_FAULT)){
- 				printf("lan%d: SIGNAL LOSS/LOBE FAULT\n",
- 					unit);
- 					ifp->if_flags &= ~IFF_RUNNING;
- 					ifp->if_flags &= ~IFF_UP;
- 					trs->wire_fault = 0x01;
- 					timeout(trinit,ifp->if_unit,hz*30);
- 				} else {
- 				if (MM_INW(&trs->cb.arb->stat.ring_status) & ~(SOFT_ERR))
- 				printf("lan%d: ARB new ring status = 0x%x\n",
- 					unit, MM_INW(&trs->cb.arb->stat.ring_status));
- 				}
- 				break;
- 
- 			case XMIT_DATA_REQ: /* Adapter wants data to transmit */
- 				/* Call transmit interrupt handler */
- 				trxint(unit);
- 
- 
- 				break;
- 
- 			default:
- 				printf("lan%d: Invalid command in ARB =%x\n",
- 				unit, command);
- 				break;
- 			}
- 
- 			/* Clear this interrupt bit */
- 			set_128_window((int)trs->tr_window_addr);
- 			MM_OUT(&trs->aca->reset.isrp_l, ~(ARB_CMD_INT)); 
- 
- 			/* Tell adapter that ARB is now free */
- 			MM_OUT(&trs->aca->set.isra_l, ARB_FREE);
- 		}
- 
  		if (status & SRB_RESP_INT) {	/* Adapter response in SRB? */
  		register union sr_srb *srb = trs->cb.srb;  /* pointer to SRB */
  
--- 501,509 ----
  
  		DEBUGF(tokdebug, printf("lan%d: ISRPL = %x\n", unit, status);)
  
+ 		/* Process SRB_RESP_INT, ASB_FREE_INT, ARB_CMD_INT
+ 		   & SSB_RESP_INT in that order, ISRP-L Hi to Lo */
  
  		if (status & SRB_RESP_INT) {	/* Adapter response in SRB? */
  		register union sr_srb *srb = trs->cb.srb;  /* pointer to SRB */
  
***************
*** 714,719 ****
--- 628,645 ----
  				break;
  			case CLOSE_SAP: /* Response to close sap cmd */
  				break;
+ 			case DIR_READ_LOG:   /* Response to read log */
+ 				/* cmd not successful? */
+ 				if (MM_IN(&srb->log.retcode) != 0)
+ 					printf("lan%d: read error log cmd err =%x\n",
+ 					unit, MM_IN(&srb->log.retcode));
+ 				printf("lan%d: ERROR LOG:\n",unit);
+ 				printf("lan%d: Line=%d, Internal=%d, Burst=%d\n",unit,(MM_IN(&srb->log.data[0])),(MM_IN(&srb->log.data[1])),(MM_IN(&srb->log.data[2])));
+ 				printf("lan%d: A/C=%d, Abort=%d, Lost frames=%d\n",unit,(MM_IN(&srb->log.data[3])),(MM_IN(&srb->log.data[4])),(MM_IN(&srb->log.data[6])));
+ 				printf("lan%d: Receive congestion=%d, Frame copied=%d, Frequency=%d\n",unit,(MM_IN(&srb->log.data[7])),(MM_IN(&srb->log.data[8])),(MM_IN(&srb->log.data[9])));
+ 				printf("lan%d: Token=%d\n",unit,(MM_IN(&srb->log.data[10])));
+ 				trs->srbfree = 0;	/* done with SRB */
+ 				break;
  			default:
  				printf("lan%d: bad SRB command encountered\n",
  				unit);
***************
*** 740,745 ****
--- 666,775 ----
  			set_128_window((int)trs->tr_window_addr);
  		}
  
+ 		if (status & ASB_FREE_INT){  /* Is Adapter Status Block Free? */
+ 		register union sr_asb *asb = trs->cb.asb;  /* pointer to ASB */
+ 
+ 		set_128_window(trs->sram_window);
+ 
+ 			switch (command = MM_IN(&asb->rec_resp.command)) {
+ 			case REC_DATA:		/* Receive */
+ 				/* Response not valid? */
+ 				if (MM_IN(&asb->rec_resp.retcode) != 0xff)
+ 				printf("lan%d: ASB bad receive response =%x\n",
+ 				unit, MM_IN(&asb->rec_resp.retcode));
+ 				break;
+ 
+ 			case XMIT_DIR_FRAME:	/* Transmit */
+ 				/* Response not valid? */
+ 				if (MM_IN(&asb->xmit_resp.retcode) != 0xff)
+ 				printf("lan%d: ASB response err on xmit =%x\n",
+ 				unit, MM_IN(&asb->xmit_resp.retcode));
+ 				break;
+ 
+ 			case XMIT_UI_FRM:   	/* Transmit */
+ 				/* Response not valid? */
+ 				if (MM_IN(&asb->xmit_resp.retcode) != 0xff)
+ 				printf("lan%d: ASB response err on xmit =%x\n",
+ 				unit, MM_IN(&asb->xmit_resp.retcode));
+ 				break;
+ 
+ 			default:
+ 				printf("lan%d: Invalid command in ASB =%x\n",
+ 				unit, command);
+ 				break;
+ 			}
+ 		
+ 			/* Clear this interrupt bit */
+ 			set_128_window((int)trs->tr_window_addr);
+ 			MM_OUT(&trs->aca->reset.isrp_l, ~(ASB_FREE_INT));
+ 		}
+ 
+ 		if (status & ARB_CMD_INT) {	/* Command for PC to process? */
+ 
+ 			set_128_window(trs->sram_window);
+ 			switch (command = MM_IN(&trs->cb.arb->stat.command)) {
+ 			case DLC_STATUS:    /* DLC status change */	
+ 				printf("lan%d: ARB new DLC  status = 0x%x\n",
+ 					unit, MM_INW(&trs->cb.arb->dlc.status));
+ 				break;
+ 
+ 			case REC_DATA:		/* Adapter has data for PC */
+ 				/* Call receive interrupt handler */
+ 				trrint(unit);
+ 				break;
+ 
+ 			case RING_STAT_CHANGE:	/* Ring status change */
+ 				if (MM_INW(&trs->cb.arb->stat.ring_status) & (SIGNAL_LOSS + LOBE_FAULT)){
+ 				printf("lan%d: SIGNAL LOSS/LOBE FAULT\n",
+ 					unit);
+ 
+ 					ifp->if_flags &= ~IFF_RUNNING;
+ 					ifp->if_flags &= ~IFF_UP;
+ 					trs->wire_fault = 0x01;
+ 					timeout(trinit,ifp->if_unit,hz*30);
+ 				} else {
+ 				if (MM_INW(&trs->cb.arb->stat.ring_status) & ~(SOFT_ERR))
+ 				printf("lan%d: ARB new ring status = 0x%x\n",
+ 					unit, MM_INW(&trs->cb.arb->stat.ring_status));
+ 				}
+ 				if (MM_INW(&trs->cb.arb->stat.ring_status) & LOG_OFLOW){
+ 					trs->srbfree = 1;	/* using SRB */
+ 					MM_OUT(&trs->cb.srb->log.command, DIR_READ_LOG);
+ 
+ 					/* read & reset err log cmnd in SRB */
+ 
+ 					set_128_window((int)trs->tr_window_addr);
+ 					/* enable PC ints so we get response */
+ 
+ 					MM_OUT(&trs->aca->set.isrp_h, INT_ENABLE);
+ 					pcvec_map[TRIRQ] = 1;
+ 					MM_OUT(&trs->aca->set.isra_l, CMD_IN_SRB);
+ 					DEBUGF(tokdebug, printf("lan%d: read adapter error log\n", unit);)
+ 				}
+ 				break;
+ 
+ 			case XMIT_DATA_REQ: /* Adapter wants data to transmit */
+ 				/* Call transmit interrupt handler */
+ 				trxint(unit);
+ 
+ 
+ 				break;
+ 
+ 			default:
+ 				printf("lan%d: Invalid command in ARB =%x\n",
+ 				unit, command);
+ 				break;
+ 			}
+ 
+ 			/* Clear this interrupt bit */
+ 			set_128_window((int)trs->tr_window_addr);
+ 			MM_OUT(&trs->aca->reset.isrp_l, ~(ARB_CMD_INT)); 
+ 
+ 			/* Tell adapter that ARB is now free */
+ 			MM_OUT(&trs->aca->set.isra_l, ARB_FREE);
+ 		}
+ 
+ 
  		if (status & SSB_RESP_INT){   /* SSB response to SRB command? */
  
  			/* pointer to SSB */
***************
*** 1013,1019 ****
  	register union sr_arb *arb = trs->cb.arb;	/* pointer to ARB */
  	register union sr_asb *asb = trs->cb.asb;	/* pointer to ASB */
  	register char *dhb;				/* pointer to DHB */
- 	register struct mbuf *m;
  	register struct mbuf *m0;	/* pointer to top of mbuf chain */
  	register unsigned short size = 0;
  	int i;
--- 1043,1048 ----
***************
*** 1596,1602 ****
    	register int error = 0;
    	register struct tr_softc *trs = &tr_softc[unit];
  
!   	printf("Token Ring open timeout\n");
    	wakeup(&trs->trsleep_event);
    	error = EIO;
    	return(error);
--- 1625,1631 ----
    	register int error = 0;
    	register struct tr_softc *trs = &tr_softc[unit];
  
!   	printf("Token Ring timeout\n");
    	wakeup(&trs->trsleep_event);
    	error = EIO;
    	return(error);
*** if_lanreg.h	Fri Aug 11 15:24:22 1989
--- if_lanreg.h.fix	Fri Aug 11 15:25:01 1989
***************
*** 1,13 ****
  /*
!  * 5799-WZQ (C) COPYRIGHT IBM CORPORATION  1986
   * LICENSED MATERIALS - PROPERTY OF IBM
   * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
   */
! /* $Header:if_lanreg.h 12.0$ */
! /* $ACIS:if_lanreg.h 12.0$ */
  
  #if !defined(lint) && !defined(LOCORE)  && defined(RCS_HDRS)
! static char *rcsidif_lanreg = "$Header:if_lanreg.h 12.0$";
  #endif
  
  /* Memory offsets of adapter control areas */
--- 1,12 ----
  /*
!  * 5799-CGZ (C) COPYRIGHT IBM CORPORATION  1986
   * LICENSED MATERIALS - PROPERTY OF IBM
   * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
   */
! /* $Header: if_lanreg.h,v 12.1 89/08/11 09:05:49 mlewis Exp $ */
  
  #if !defined(lint) && !defined(LOCORE)  && defined(RCS_HDRS)
! static char *rcsidif_lanreg = "$Header: if_lanreg.h,v 12.1 89/08/11 09:05:49 mlewis Exp $";
  #endif
  
  /* Memory offsets of adapter control areas */
***************
*** 199,204 ****
  #define RCF_BYT0		14	/* byte zero of RCF fields */
  
  /* ARB RING STATUS CHANGE */
! #define SIGNAL_LOSS	0x8000	/* signal loss              */
! #define LOBE_FAULT 	0x0800  /* lob wire fault           */
! #define SOFT_ERR   	0x2000  /* soft error         	*/
--- 198,206 ----
  #define RCF_BYT0		14	/* byte zero of RCF fields */
  
  /* ARB RING STATUS CHANGE */
! #define SIGNAL_LOSS	0x8000	/* signal loss */
! #define HARD_ERR	0x4000	/* beacon frames sent */
! #define SOFT_ERR   	0x2000  /* soft error */
! #define LOBE_FAULT 	0x0800  /* lobe wire fault */
! #define LOG_OFLOW	0x0080	/* adapter error log counter overflow */
! #define SINGLE_STATION	0x0040	/* single station or ring */
*** if_lanvar.h	Fri Aug 11 11:23:44 1989
--- if_lanvar.h.fix	Fri Aug 11 09:36:41 1989
***************
*** 1,13 ****
  /*
!  * 5799-WZQ (C) COPYRIGHT IBM CORPORATION  1986,1987
   * LICENSED MATERIALS - PROPERTY OF IBM
   * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
   */
! /* $Header:if_lanvar.h 12.0$ */
! /* $ACIS:if_lanvar.h 12.0$ */
  
  #if !defined(lint) && !defined(LOCORE)  && defined(RCS_HDRS)
! static char    *rcsidif_lanvar = "$Header:if_lanvar.h 12.0$";
  #endif
  
  /*
--- 1,12 ----
  /*
!  * 5799-CGZ (C) COPYRIGHT IBM CORPORATION  1986,1987
   * LICENSED MATERIALS - PROPERTY OF IBM
   * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
   */
! /* $Header: if_lanvar.h,v 12.1 89/08/11 09:16:31 mlewis Exp $ */
  
  #if !defined(lint) && !defined(LOCORE)  && defined(RCS_HDRS)
! static char    *rcsidif_lanvar = "$Header: if_lanvar.h,v 12.1 89/08/11 09:16:31 mlewis Exp $";
  #endif
  
  /*
***************
*** 149,161 ****
   * Structure of ARB (Adapter Request Block)
   */
  union sr_arb {
- 	struct {		/* Adapter card error log */
- 		unsigned char   command;
- 		unsigned char   res0;	/* reserved */
- 		unsigned char   retcode;	/* Set by adapter on return */
- 		unsigned char   res1[3];	/* reserved */
- 		unsigned char   data[14];	/* Log data set by adapter */
- 	}               log;
  	struct {		/* Receive-data command block */
  		unsigned char   command;
  		unsigned char   res0[3];
--- 148,153 ----
***************
*** 317,322 ****
--- 309,321 ----
  						 * allowed */
  		unsigned char   gsap1;	/* first gsap request */
  	}               open_sap;
+ 	struct {		/* Adapter card error log */
+ 		unsigned char   command;
+ 		unsigned char   res0;	/* reserved */
+ 		unsigned char   retcode;	/* Set by adapter on return */
+ 		unsigned char   res1[3];	/* reserved */
+ 		unsigned char   data[14];	/* Log data set by adapter */
+ 	}               log;
  };