void process_receive(struct s_smc *smc)
{
	int i ;
	int n ;
	int frag_count ;		/* number of RxDs of the curr rx buf */
	int used_frags ;		/* number of RxDs of the curr frame */
	struct s_smt_rx_queue *queue ;	/* points to the queue ctl struct */
	struct s_smt_fp_rxd volatile *r ;	/* rxd pointer */
	struct s_smt_fp_rxd volatile *rxd ;	/* first rxd of rx frame */
	u_long rbctrl ;			/* receive buffer control word */
	u_long rfsw ;			/* receive frame status word */
	u_short rx_used ;
	u_char far *virt ;
	char far *data ;
	SMbuf *mb ;
	u_char fc ;			/* Frame control */
	int len ;			/* Frame length */

	smc->os.hwm.detec_count = 0 ;
	queue = smc->hw.fp.rx[QUEUE_R1] ;
	NDD_TRACE("RHxB",0,0,0) ;
	for ( ; ; ) {
		r = queue->rx_curr_get ;
		rx_used = queue->rx_used ;
		frag_count = 0 ;

#ifdef	USE_BREAK_ISR
		if (smc->os.hwm.leave_isr) {
			goto rx_end ;
		}
#endif
#ifdef	NDIS_OS2
		if (offDepth) {
			smc->os.hwm.rx_break = 1 ;
			goto rx_end ;
		}
		smc->os.hwm.rx_break = 0 ;
#endif
#ifdef	ODI2
		if (smc->os.hwm.rx_break) {
			goto rx_end ;
		}
#endif
		n = 0 ;
		do {
			DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ;
			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
			rbctrl = le32_to_cpu(CR_READ(r->rxd_rbctrl));

			if (rbctrl & BMU_OWN) {
				NDD_TRACE("RHxE",r,rfsw,rbctrl) ;
				DB_RX("End of RxDs",0,0,4) ;
				goto rx_end ;
			}
			/*
			 * out of RxD detection
			 */
			if (!rx_used) {
				SK_BREAK() ;
				SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ;
				/* Either we don't have an RxD or all
				 * RxDs are filled. Therefore it's allowed
				 * for to set the STOPPED flag */
				smc->hw.hw_state = STOPPED ;
				mac_drv_clear_rx_queue(smc) ;
				smc->hw.hw_state = STARTED ;
				mac_drv_fill_rxd(smc) ;
				smc->os.hwm.detec_count = 0 ;
				goto rx_end ;
			}
			rfsw = le32_to_cpu(r->rxd_rfsw) ;
			if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {
				/*
				 * The BMU_STF bit is deleted, 1 frame is
				 * placed into more than 1 rx buffer
				 *
				 * skip frame by setting the rx len to 0
				 *
				 * if fragment count == 0
				 *	The missing STF bit belongs to the
				 *	current frame, search for the
				 *	EOF bit to complete the frame
				 * else
				 *	the fragment belongs to the next frame,
				 *	exit the loop and process the frame
				 */
				SK_BREAK() ;
				rfsw = 0 ;
				if (frag_count) {
					break ;
				}
			}
			n += rbctrl & 0xffff ;
			r = r->rxd_next ;
			frag_count++ ;
			rx_used-- ;
		} while (!(rbctrl & BMU_EOF)) ;
		used_frags = frag_count ;
		DB_RX("EOF set in RxD, used_frags = %d ",used_frags,0,5) ;

		/* may be next 2 DRV_BUF_FLUSH() can be skipped, because */
		/* BMU_ST_BUF will not be changed by the ASIC */
		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
		while (rx_used && !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
			DB_RX("Check STF bit in %x",(void *)r,0,5) ;
			r = r->rxd_next ;
			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
			frag_count++ ;
			rx_used-- ;
		}
		DB_RX("STF bit found",0,0,5) ;

		/*
		 * The received frame is finished for the process receive
		 */
		rxd = queue->rx_curr_get ;
		queue->rx_curr_get = r ;
		queue->rx_free += frag_count ;
		queue->rx_used = rx_used ;

		/*
		 * ASIC Errata no. 7 (STF - Bit Bug)
		 */
		rxd->rxd_rbctrl &= cpu_to_le32(~BMU_STF) ;

		for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){
			DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
			dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
		}
		smc->hw.fp.err_stats.err_valid++ ;
		smc->mib.m[MAC0].fddiMACCopied_Ct++ ;

		/* the length of the data including the FC */
		len = (rfsw & RD_LENGTH) - 4 ;

		DB_RX("frame length = %d",len,0,4) ;
		/*
		 * check the frame_length and all error flags
		 */
		if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){
			if (rfsw & RD_S_MSRABT) {
				DB_RX("Frame aborted by the FORMAC",0,0,2) ;
				smc->hw.fp.err_stats.err_abort++ ;
			}
			/*
			 * check frame status
			 */
			if (rfsw & RD_S_SEAC2) {
				DB_RX("E-Indicator set",0,0,2) ;
				smc->hw.fp.err_stats.err_e_indicator++ ;
			}
			if (rfsw & RD_S_SFRMERR) {
				DB_RX("CRC error",0,0,2) ;
				smc->hw.fp.err_stats.err_crc++ ;
			}
			if (rfsw & RX_FS_IMPL) {
				DB_RX("Implementer frame",0,0,2) ;
				smc->hw.fp.err_stats.err_imp_frame++ ;
			}
			goto abort_frame ;
		}
		if (len > FDDI_RAW_MTU-4) {
			DB_RX("Frame too long error",0,0,2) ;
			smc->hw.fp.err_stats.err_too_long++ ;
			goto abort_frame ;
		}
		/*
		 * SUPERNET 3 Bug: FORMAC delivers status words
		 * of aborded frames to the BMU
		 */
		if (len <= 4) {
			DB_RX("Frame length = 0",0,0,2) ;
			goto abort_frame ;
		}

		if (len != (n-4)) {
			DB_RX("BMU: rx len differs: [%d:%d]",len,n,4);
			smc->os.hwm.rx_len_error++ ;
			goto abort_frame ;
		}

		/*
		 * Check SA == MA
		 */
		virt = (u_char far *) rxd->rxd_virt ;
		DB_RX("FC = %x",*virt,0,2) ;
		if (virt[12] == MA[5] &&
		    virt[11] == MA[4] &&
		    virt[10] == MA[3] &&
		    virt[9] == MA[2] &&
		    virt[8] == MA[1] &&
		    (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) {
			goto abort_frame ;
		}

		/*
		 * test if LLC frame
		 */
		if (rfsw & RX_FS_LLC) {
			/*
			 * if pass_llc_promisc is disable
			 *	if DA != Multicast or Broadcast or DA!=MA
			 *		abort the frame
			 */
			if (!smc->os.hwm.pass_llc_promisc) {
				if(!(virt[1] & GROUP_ADDR_BIT)) {
					if (virt[6] != MA[5] ||
					    virt[5] != MA[4] ||
					    virt[4] != MA[3] ||
					    virt[3] != MA[2] ||
					    virt[2] != MA[1] ||
					    virt[1] != MA[0]) {
						DB_RX("DA != MA and not multi- or broadcast",0,0,2) ;
						goto abort_frame ;
					}
				}
			}

			/*
			 * LLC frame received
			 */
			DB_RX("LLC - receive",0,0,4) ;
			mac_drv_rx_complete(smc,rxd,frag_count,len) ;
		}
		else {
			if (!(mb = smt_get_mbuf(smc))) {
				smc->hw.fp.err_stats.err_no_buf++ ;
				DB_RX("No SMbuf; receive terminated",0,0,4) ;
				goto abort_frame ;
			}
			data = smtod(mb,char *) - 1 ;

			/*
			 * copy the frame into a SMT_MBuf
			 */
#ifdef USE_OS_CPY
			hwm_cpy_rxd2mb(rxd,data,len) ;
#else
			for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){
				n = le32_to_cpu(r->rxd_rbctrl) & RD_LENGTH ;
				DB_RX("cp SMT frame to mb: len = %d",n,0,6) ;
				memcpy(data,r->rxd_virt,n) ;
				data += n ;
			}
			data = smtod(mb,char *) - 1 ;
#endif
			fc = *(char *)mb->sm_data = *data ;
			mb->sm_len = len - 1 ;		/* len - fc */
			data++ ;

			/*
			 * SMT frame received
			 */
			switch(fc) {
			case FC_SMT_INFO :
				smc->hw.fp.err_stats.err_smt_frame++ ;
				DB_RX("SMT frame received ",0,0,5) ;

				if (smc->os.hwm.pass_SMT) {
					DB_RX("pass SMT frame ",0,0,5) ;
					mac_drv_rx_complete(smc, rxd,
						frag_count,len) ;
				}
				else {
					DB_RX("requeue RxD",0,0,5) ;
					mac_drv_requeue_rxd(smc,rxd,frag_count);
				}

				smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
				break ;
			case FC_SMT_NSA :
				smc->hw.fp.err_stats.err_smt_frame++ ;
				DB_RX("SMT frame received ",0,0,5) ;

				/* if pass_NSA set pass the NSA frame or */
				/* pass_SMT set and the A-Indicator */
				/* is not set, pass the NSA frame */
				if (smc->os.hwm.pass_NSA ||
					(smc->os.hwm.pass_SMT &&
					!(rfsw & A_INDIC))) {
					DB_RX("pass SMT frame ",0,0,5) ;
					mac_drv_rx_complete(smc, rxd,
						frag_count,len) ;
				}
				else {
					DB_RX("requeue RxD",0,0,5) ;
					mac_drv_requeue_rxd(smc,rxd,frag_count);
				}

				smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
				break ;
			case FC_BEACON :
				if (smc->os.hwm.pass_DB) {
					DB_RX("pass DB frame ",0,0,5) ;
					mac_drv_rx_complete(smc, rxd,
						frag_count,len) ;
				}
				else {
					DB_RX("requeue RxD",0,0,5) ;
					mac_drv_requeue_rxd(smc,rxd,frag_count);
				}
				smt_free_mbuf(smc,mb) ;
				break ;
			default :
				/*
				 * unknown FC abord the frame
				 */
				DB_RX("unknown FC error",0,0,2) ;
				smt_free_mbuf(smc,mb) ;
				DB_RX("requeue RxD",0,0,5) ;
				mac_drv_requeue_rxd(smc,rxd,frag_count) ;
				if ((fc & 0xf0) == FC_MAC)
					smc->hw.fp.err_stats.err_mac_frame++ ;
				else
					smc->hw.fp.err_stats.err_imp_frame++ ;

				break ;
			}
		}

		DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
		NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ;

		continue ;
	/*--------------------------------------------------------------------*/
abort_frame:
		DB_RX("requeue RxD",0,0,5) ;
		mac_drv_requeue_rxd(smc,rxd,frag_count) ;

		DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
		NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ;
	}
rx_end:
#ifdef	ALL_RX_COMPLETE
	mac_drv_all_receives_complete(smc) ;
#endif
	return ;	/* lint bug: needs return detect end of function */
}
int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
			  int fs)
{
	void			*p ;		
	struct smt_p_0016	*cmd ;		
	SMbuf			*db ;
	u_long			msg_res_type ;	
	u_long			payload, overhead ;
	int			local ;
	int			i ;

	 local = ((fs & L_INDICATOR) != 0) ;

	if (!(p = (void *) sm_to_para(smc,sm,SMT_P0015))) {
		DB_ESS("ESS: RAF frame error, parameter type not found\n",0,0) ;
		return fs;
	}
	msg_res_type = ((struct smt_p_0015 *)p)->res_type ;

	if (!(cmd = (struct smt_p_0016 *) sm_to_para(smc,sm,SMT_P0016))) {
		 DB_ESS("ESS: RAF frame error, parameter command not found\n",0,0);
		 return fs;
	}

	DB_ESSN(2,"fc %x	ft %x\n",sm->smt_class,sm->smt_type) ;
	DB_ESSN(2,"ver %x	tran %lx\n",sm->smt_version,sm->smt_tid) ;
	DB_ESSN(2,"stn_id %s\n",addr_to_string(&sm->smt_source),0) ;

	DB_ESSN(2,"infolen %x	res %x\n",sm->smt_len, msg_res_type) ;
	DB_ESSN(2,"sbacmd %x\n",cmd->sba_cmd,0) ;

	switch (cmd->sba_cmd) {

	case REQUEST_ALLOCATION :
		if (sm->smt_type == SMT_REQUEST) {
			if (!local || smc->mib.fddiESSPayload)
				return fs;
			
			p = (void *) sm_to_para(smc,sm,SMT_P0019)  ;
			for (i = 0; i < 5; i++) {
				if (((struct smt_p_0019 *)p)->alloc_addr.a[i]) {
					return fs;
				}
			}

			smc->ess.alloc_trans_id = sm->smt_tid ;
			DB_ESS("ESS: save Alloc Req Trans ID %lx\n",sm->smt_tid,0);
			p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
			((struct smt_p_320f *)p)->mib_payload =
				smc->mib.a[PATH0].fddiPATHSbaPayload ;
			p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
			((struct smt_p_3210 *)p)->mib_overhead =
				smc->mib.a[PATH0].fddiPATHSbaOverhead ;
			sm->smt_dest = smt_sba_da ;

			if (smc->ess.local_sba_active)
				return fs | I_INDICATOR;

			if (!(db = smt_get_mbuf(smc)))
				return fs;

			db->sm_len = mb->sm_len ;
			db->sm_off = mb->sm_off ;
			memcpy(((char *)(db->sm_data+db->sm_off)),(char *)sm,
				(int)db->sm_len) ;
			dump_smt(smc,
				(struct smt_header *)(db->sm_data+db->sm_off),
				"RAF") ;
			smt_send_frame(smc,db,FC_SMT_INFO,0) ;
			return fs;
		}

		if (smt_check_para(smc,sm,plist_raf_alc_res)) {
			DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
			return fs;
		}

		if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
			!= PRIMARY_RING) ||
			(msg_res_type != SYNC_BW) ||
		(((struct smt_p_reason *)sm_to_para(smc,sm,SMT_P0012))->rdf_reason
			!= SMT_RDF_SUCCESS) ||
			(sm->smt_tid != smc->ess.alloc_trans_id)) {

			DB_ESS("ESS: Allocation Response not accepted\n",0,0) ;
			return fs;
		}

		p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
                if (!p) {
                        printk(KERN_ERR "ESS: sm_to_para failed");
                        return fs;
                }       
		payload = ((struct smt_p_320f *)p)->mib_payload ;
		p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
                if (!p) {
                        printk(KERN_ERR "ESS: sm_to_para failed");
                        return fs;
                }       
		overhead = ((struct smt_p_3210 *)p)->mib_overhead ;

		DB_ESSN(2,"payload= %lx	overhead= %lx\n",payload,overhead) ;

		(void)process_bw_alloc(smc,(long)payload,(long)overhead) ;

		return fs;
		

	case CHANGE_ALLOCATION :
		if (sm->smt_type != SMT_REQUEST) {
			DB_ESS("ESS: Do not process Change Responses\n",0,0) ;
			return fs;
		}

		if (smt_check_para(smc,sm,plist_raf_chg_req)) {
			DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
			return fs;
		}

		if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
			!= PRIMARY_RING) || (msg_res_type != SYNC_BW)) {
			DB_ESS("ESS: RAF frame with para problem, ignoring\n",0,0) ;
			return fs;
		}

		p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
		payload = ((struct smt_p_320f *)p)->mib_payload ;
		p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
		overhead = ((struct smt_p_3210 *)p)->mib_overhead ;

		DB_ESSN(2,"ESS: Change Request from %s\n",
			addr_to_string(&sm->smt_source),0) ;
		DB_ESSN(2,"payload= %lx	overhead= %lx\n",payload,overhead) ;

		if(!process_bw_alloc(smc,(long)payload,(long)overhead))
			return fs;

		ess_send_response(smc,sm,CHANGE_ALLOCATION) ;

		return fs;
		

	case REPORT_ALLOCATION :
		if (sm->smt_type != SMT_REQUEST) {
			DB_ESS("ESS: Do not process a Report Reply\n",0,0) ;
			return fs;
		}

		DB_ESSN(2,"ESS: Report Request from %s\n",
			addr_to_string(&(sm->smt_source)),0) ;

		if (msg_res_type != SYNC_BW) {
			DB_ESS("ESS: ignoring RAF with para problem\n",0,0) ;
			return fs;
		}

		ess_send_response(smc,sm,REPORT_ALLOCATION) ;

		return fs;
		

	default:
		DB_ESS("ESS: ignoring RAF with bad sba_cmd\n",0,0) ;
		break ;
	}

	return fs;
}
void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
		 int frame_status)
{
	struct s_smt_fp_txd volatile *t ;
	struct s_smt_tx_queue *queue ;
	__le32	tbctrl ;

	queue = smc->os.hwm.tx_p ;

	NDD_TRACE("THfB",virt,len,frame_status) ;
	/* Bug fix: AF / May 31 1999 (#missing)
	 * snmpinfo problem reported by IBM is caused by invalid
	 * t-pointer (txd) if LAN_TX is not set but LOC_TX only.
	 * Set: t = queue->tx_curr_put  here !
	 */
	t = queue->tx_curr_put ;

	DB_TX("hwm_tx_frag: len = %d, frame_status = %x ",len,frame_status,2) ;
	if (frame_status & LAN_TX) {
		/* '*t' is already defined */
		DB_TX("LAN_TX: TxD = %x, virt = %x ",t,virt,3) ;
		t->txd_virt = virt ;
		t->txd_txdscr = cpu_to_le32(smc->os.hwm.tx_descr) ;
		t->txd_tbadr = cpu_to_le32(phys) ;
		tbctrl = cpu_to_le32((((__u32)frame_status &
			(FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
			BMU_OWN|BMU_CHECK |len) ;
		t->txd_tbctrl = tbctrl ;

#ifndef	AIX
		DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
		outpd(queue->tx_bmu_ctl,CSR_START) ;
#else	/* ifndef AIX */
		DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
		if (frame_status & QUEUE_A0) {
			outpd(ADDR(B0_XA_CSR),CSR_START) ;
		}
		else {
			outpd(ADDR(B0_XS_CSR),CSR_START) ;
		}
#endif
		queue->tx_free-- ;
		queue->tx_used++ ;
		queue->tx_curr_put = t->txd_next ;
		if (frame_status & LAST_FRAG) {
			smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
		}
	}
	if (frame_status & LOC_TX) {
		DB_TX("LOC_TX: ",0,0,3) ;
		if (frame_status & FIRST_FRAG) {
			if(!(smc->os.hwm.tx_mb = smt_get_mbuf(smc))) {
				smc->hw.fp.err_stats.err_no_buf++ ;
				DB_TX("No SMbuf; transmit terminated",0,0,4) ;
			}
			else {
				smc->os.hwm.tx_data =
					smtod(smc->os.hwm.tx_mb,char *) - 1 ;
#ifdef USE_OS_CPY
#ifdef PASS_1ST_TXD_2_TX_COMP
				hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
					smc->os.hwm.tx_len) ;
#endif
#endif
			}
		}
		if (smc->os.hwm.tx_mb) {
#ifndef	USE_OS_CPY
			DB_TX("copy fragment into MBuf ",0,0,3) ;
			memcpy(smc->os.hwm.tx_data,virt,len) ;
			smc->os.hwm.tx_data += len ;
#endif
			if (frame_status & LAST_FRAG) {
#ifdef	USE_OS_CPY
#ifndef PASS_1ST_TXD_2_TX_COMP
				/*
				 * hwm_cpy_txd2mb(txd,data,len) copies 'len' 
				 * bytes from the virtual pointer in 'rxd'
				 * to 'data'. The virtual pointer of the 
				 * os-specific tx-buffer should be written
				 * in the LAST txd.
				 */ 
				hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
					smc->os.hwm.tx_len) ;
#endif	/* nPASS_1ST_TXD_2_TX_COMP */
#endif	/* USE_OS_CPY */
				smc->os.hwm.tx_data =
					smtod(smc->os.hwm.tx_mb,char *) - 1 ;
				*(char *)smc->os.hwm.tx_mb->sm_data =
					*smc->os.hwm.tx_data ;
				smc->os.hwm.tx_data++ ;
				smc->os.hwm.tx_mb->sm_len =
					smc->os.hwm.tx_len - 1 ;
				DB_TX("pass LLC frame to SMT ",0,0,3) ;
				smt_received_pack(smc,smc->os.hwm.tx_mb,
						RD_FS_LOCAL) ;
			}
Example #4
0
/*
 * evaluate the RAF frame
 */
int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
			  int fs)
{
	void			*p ;		/* universal pointer */
	struct smt_p_0016	*cmd ;		/* para: command for the ESS */
	SMbuf			*db ;
	u_long			msg_res_type ;	/* recource type */
	u_long			payload, overhead ;
	int			local ;
	int			i ;

	/*
	 * Message Processing Code
	 */
	 local = ((fs & L_INDICATOR) != 0) ;

	/*
	 * get the resource type
	 */
	if (!(p = (void *) sm_to_para(smc,sm,SMT_P0015))) {
		DB_ESS("ESS: RAF frame error, parameter type not found\n",0,0) ;
		return fs;
	}
	msg_res_type = ((struct smt_p_0015 *)p)->res_type ;

	/*
	 * get the pointer to the ESS command
	 */
	if (!(cmd = (struct smt_p_0016 *) sm_to_para(smc,sm,SMT_P0016))) {
		/*
		 * error in frame: para ESS command was not found
		 */
		 DB_ESS("ESS: RAF frame error, parameter command not found\n",0,0);
		 return fs;
	}

	DB_ESSN(2,"fc %x	ft %x\n",sm->smt_class,sm->smt_type) ;
	DB_ESSN(2,"ver %x	tran %lx\n",sm->smt_version,sm->smt_tid) ;
	DB_ESSN(2,"stn_id %s\n",addr_to_string(&sm->smt_source),0) ;

	DB_ESSN(2,"infolen %x	res %x\n",sm->smt_len, msg_res_type) ;
	DB_ESSN(2,"sbacmd %x\n",cmd->sba_cmd,0) ;

	/*
	 * evaluate the ESS command
	 */
	switch (cmd->sba_cmd) {

	/*
	 * Process an ESS Allocation Request
	 */
	case REQUEST_ALLOCATION :
		/*
		 * check for an RAF Request (Allocation Request)
		 */
		if (sm->smt_type == SMT_REQUEST) {
			/*
			 * process the Allocation request only if the frame is
			 * local and no static allocation is used
			 */
			if (!local || smc->mib.fddiESSPayload)
				return fs;

			p = (void *) sm_to_para(smc,sm,SMT_P0019)  ;
			for (i = 0; i < 5; i++) {
				if (((struct smt_p_0019 *)p)->alloc_addr.a[i]) {
					return fs;
				}
			}

			/*
			 * Note: The Application should send a LAN_LOC_FRAME.
			 *	 The ESS do not send the Frame to the network!
			 */
			smc->ess.alloc_trans_id = sm->smt_tid ;
			DB_ESS("ESS: save Alloc Req Trans ID %lx\n",sm->smt_tid,0);
			p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
			((struct smt_p_320f *)p)->mib_payload =
				smc->mib.a[PATH0].fddiPATHSbaPayload ;
			p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
			((struct smt_p_3210 *)p)->mib_overhead =
				smc->mib.a[PATH0].fddiPATHSbaOverhead ;
			sm->smt_dest = smt_sba_da ;

			if (smc->ess.local_sba_active)
				return fs | I_INDICATOR;

			if (!(db = smt_get_mbuf(smc)))
				return fs;

			db->sm_len = mb->sm_len ;
			db->sm_off = mb->sm_off ;
			memcpy(((char *)(db->sm_data+db->sm_off)),(char *)sm,
				(int)db->sm_len) ;
			dump_smt(smc,
				(struct smt_header *)(db->sm_data+db->sm_off),
				"RAF") ;
			smt_send_frame(smc,db,FC_SMT_INFO,0) ;
			return fs;
		}

		/*
		 * The RAF frame is an Allocation Response !
		 * check the parameters
		 */
		if (smt_check_para(smc,sm,plist_raf_alc_res)) {
			DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
			return fs;
		}

		/*
		 * VERIFY THE FRAME IS WELL BUILT:
		 *
		 *	1. path index = primary ring only
		 *	2. resource type = sync bw only
		 *	3. trans action id = alloc_trans_id
		 *	4. reason code = success
		 *
		 * If any are violated, discard the RAF frame
		 */
		if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
			!= PRIMARY_RING) ||
			(msg_res_type != SYNC_BW) ||
		(((struct smt_p_reason *)sm_to_para(smc,sm,SMT_P0012))->rdf_reason
			!= SMT_RDF_SUCCESS) ||
			(sm->smt_tid != smc->ess.alloc_trans_id)) {

			DB_ESS("ESS: Allocation Response not accepted\n",0,0) ;
			return fs;
		}

		/*
		 * Extract message parameters
		 */
		p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
                if (!p) {
                        printk(KERN_ERR "ESS: sm_to_para failed");
                        return fs;
                }
		payload = ((struct smt_p_320f *)p)->mib_payload ;
		p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
                if (!p) {
                        printk(KERN_ERR "ESS: sm_to_para failed");
                        return fs;
                }
		overhead = ((struct smt_p_3210 *)p)->mib_overhead ;

		DB_ESSN(2,"payload= %lx	overhead= %lx\n",payload,overhead) ;

		/*
		 * process the bandwidth allocation
		 */
		(void)process_bw_alloc(smc,(long)payload,(long)overhead) ;

		return fs;
		/* end of Process Allocation Request */

	/*
	 * Process an ESS Change Request
	 */
	case CHANGE_ALLOCATION :
		/*
		 * except only replies
		 */
		if (sm->smt_type != SMT_REQUEST) {
			DB_ESS("ESS: Do not process Change Responses\n",0,0) ;
			return fs;
		}

		/*
		 * check the para for the Change Request
		 */
		if (smt_check_para(smc,sm,plist_raf_chg_req)) {
			DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
			return fs;
		}

		/*
		 * Verify the path index and resource
		 * type are correct. If any of
		 * these are false, don't process this
		 * change request frame.
		 */
		if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
			!= PRIMARY_RING) || (msg_res_type != SYNC_BW)) {
			DB_ESS("ESS: RAF frame with para problem, ignoring\n",0,0) ;
			return fs;
		}

		/*
		 * Extract message queue parameters
		 */
		p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
		payload = ((struct smt_p_320f *)p)->mib_payload ;
		p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
		overhead = ((struct smt_p_3210 *)p)->mib_overhead ;

		DB_ESSN(2,"ESS: Change Request from %s\n",
			addr_to_string(&sm->smt_source),0) ;
		DB_ESSN(2,"payload= %lx	overhead= %lx\n",payload,overhead) ;

		/*
		 * process the bandwidth allocation
		 */
		if(!process_bw_alloc(smc,(long)payload,(long)overhead))
			return fs;

		/*
		 * send an RAF Change Reply
		 */
		ess_send_response(smc,sm,CHANGE_ALLOCATION) ;

		return fs;
		/* end of Process Change Request */

	/*
	 * Process Report Response
	 */
	case REPORT_ALLOCATION :
		/*
		 * except only requests
		 */
		if (sm->smt_type != SMT_REQUEST) {
			DB_ESS("ESS: Do not process a Report Reply\n",0,0) ;
			return fs;
		}

		DB_ESSN(2,"ESS: Report Request from %s\n",
			addr_to_string(&(sm->smt_source)),0) ;

		/*
		 * verify that the resource type is sync bw only
		 */
		if (msg_res_type != SYNC_BW) {
			DB_ESS("ESS: ignoring RAF with para problem\n",0,0) ;
			return fs;
		}

		/*
		 * send an RAF Change Reply
		 */
		ess_send_response(smc,sm,REPORT_ALLOCATION) ;

		return fs;
		/* end of Process Report Request */

	default:
		/*
		 * error in frame
		 */
		DB_ESS("ESS: ignoring RAF with bad sba_cmd\n",0,0) ;
		break ;
	}

	return fs;
}