• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *	(C)Copyright 1998,1999 SysKonnect,
4  *	a business unit of Schneider & Koch & Co. Datensysteme GmbH.
5  *
6  *	See the file "skfddi.c" for further information.
7  *
8  *	This program is free software; you can redistribute it and/or modify
9  *	it under the terms of the GNU General Public License as published by
10  *	the Free Software Foundation; either version 2 of the License, or
11  *	(at your option) any later version.
12  *
13  *	The information in this file is provided "AS IS" without warranty.
14  *
15  ******************************************************************************/
16 
17 /*
18  * FORMAC+ Driver for tag mode
19  */
20 
21 #include "h/types.h"
22 #include "h/fddi.h"
23 #include "h/smc.h"
24 #include "h/supern_2.h"
25 #include <linux/bitrev.h>
26 
27 #ifndef	lint
28 static const char ID_sccs[] = "@(#)fplustm.c	1.32 99/02/23 (C) SK " ;
29 #endif
30 
31 #ifndef UNUSED
32 #ifdef  lint
33 #define UNUSED(x)	(x) = (x)
34 #else
35 #define UNUSED(x)
36 #endif
37 #endif
38 
39 #define FM_ADDRX	 (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
40 #define MS2BCLK(x)	((x)*12500L)
41 #define US2BCLK(x)	((x)*1250L)
42 
43 /*
44  * prototypes for static function
45  */
46 static void build_claim_beacon(struct s_smc *smc, u_long t_request);
47 static int init_mac(struct s_smc *smc, int all);
48 static void rtm_init(struct s_smc *smc);
49 static void smt_split_up_fifo(struct s_smc *smc);
50 
51 #if (!defined(NO_SMT_PANIC) || defined(DEBUG))
52 static	char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n";
53 static	char cam_warning [] = "E_SMT_004: CAM still busy\n";
54 #endif
55 
56 #define	DUMMY_READ()	smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP))
57 
58 #define	CHECK_NPP() {	unsigned k = 10000 ;\
59 			while ((inpw(FM_A(FM_STMCHN)) & FM_SNPPND) && k) k--;\
60 			if (!k) { \
61 				SMT_PANIC(smc,SMT_E0130, SMT_E0130_MSG) ; \
62 			}	\
63 		}
64 
65 #define	CHECK_CAM() {	unsigned k = 10 ;\
66 			while (!(inpw(FM_A(FM_AFSTAT)) & FM_DONE) && k) k--;\
67 			if (!k) { \
68 				SMT_PANIC(smc,SMT_E0131, SMT_E0131_MSG) ; \
69 			}	\
70 		}
71 
72 const struct fddi_addr fddi_broadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
73 static const struct fddi_addr null_addr = {{0,0,0,0,0,0}};
74 static const struct fddi_addr dbeacon_multi = {{0x01,0x80,0xc2,0x00,0x01,0x00}};
75 
76 static const u_short my_said = 0xffff ;	/* short address (n.u.) */
77 static const u_short my_sagp = 0xffff ;	/* short group address (n.u.) */
78 
79 /*
80  * define my address
81  */
82 #ifdef	USE_CAN_ADDR
83 #define MA	smc->hw.fddi_canon_addr
84 #else
85 #define MA	smc->hw.fddi_home_addr
86 #endif
87 
88 
89 /*
90  * useful interrupt bits
91  */
92 static const int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;
93 static const int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|
94 			FM_STBURS | FM_STBURA0 ;
95 
96 	/* delete FM_SRBFL after tests */
97 static const int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |
98 			FM_SMYCLM ;
99 static const int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |
100 			FM_SERRCTR | FM_SLSTCTR |
101 			FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ;
102 
103 static const int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;
104 static const int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;
105 
106 static const int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |
107 			FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;
108 
109 
mac_get_tneg(struct s_smc * smc)110 static u_long mac_get_tneg(struct s_smc *smc)
111 {
112 	u_long	tneg ;
113 
114 	tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ;
115 	return (u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
116 		0xffe00000L) ;
117 }
118 
mac_update_counter(struct s_smc * smc)119 void mac_update_counter(struct s_smc *smc)
120 {
121 	smc->mib.m[MAC0].fddiMACFrame_Ct =
122 		(smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L)
123 		+ (u_short) inpw(FM_A(FM_FCNTR)) ;
124 	smc->mib.m[MAC0].fddiMACLost_Ct =
125 		(smc->mib.m[MAC0].fddiMACLost_Ct & 0xffff0000L)
126 		+ (u_short) inpw(FM_A(FM_LCNTR)) ;
127 	smc->mib.m[MAC0].fddiMACError_Ct =
128 		(smc->mib.m[MAC0].fddiMACError_Ct & 0xffff0000L)
129 		+ (u_short) inpw(FM_A(FM_ECNTR)) ;
130 	smc->mib.m[MAC0].fddiMACT_Neg = mac_get_tneg(smc) ;
131 #ifdef SMT_REAL_TOKEN_CT
132 	/*
133 	 * If the token counter is emulated it is updated in smt_event.
134 	 */
135 	TBD
136 #else
137 	smt_emulate_token_ct( smc, MAC0 );
138 #endif
139 }
140 
141 /*
142  * write long value into buffer memory over memory data register (MDR),
143  */
write_mdr(struct s_smc * smc,u_long val)144 static void write_mdr(struct s_smc *smc, u_long val)
145 {
146 	CHECK_NPP() ;
147 	MDRW(val) ;
148 }
149 
150 #if 0
151 /*
152  * read long value from buffer memory over memory data register (MDR),
153  */
154 static u_long read_mdr(struct s_smc *smc, unsigned int addr)
155 {
156 	long p ;
157 	CHECK_NPP() ;
158 	MARR(addr) ;
159 	outpw(FM_A(FM_CMDREG1),FM_IRMEMWO) ;
160 	CHECK_NPP() ;	/* needed for PCI to prevent from timeing violations */
161 /*	p = MDRR() ; */	/* bad read values if the workaround */
162 			/* smc->hw.mc_dummy = *((short volatile far *)(addr)))*/
163 			/* is used */
164 	p = (u_long)inpw(FM_A(FM_MDRU))<<16 ;
165 	p += (u_long)inpw(FM_A(FM_MDRL)) ;
166 	return p;
167 }
168 #endif
169 
170 /*
171  * clear buffer memory
172  */
init_ram(struct s_smc * smc)173 static void init_ram(struct s_smc *smc)
174 {
175 	u_short i ;
176 
177 	smc->hw.fp.fifo.rbc_ram_start = 0 ;
178 	smc->hw.fp.fifo.rbc_ram_end =
179 		smc->hw.fp.fifo.rbc_ram_start + RBC_MEM_SIZE ;
180 	CHECK_NPP() ;
181 	MARW(smc->hw.fp.fifo.rbc_ram_start) ;
182 	for (i = smc->hw.fp.fifo.rbc_ram_start;
183 		i < (u_short) (smc->hw.fp.fifo.rbc_ram_end-1); i++)
184 		write_mdr(smc,0L) ;
185 	/* Erase the last byte too */
186 	write_mdr(smc,0L) ;
187 }
188 
189 /*
190  * set receive FIFO pointer
191  */
set_recvptr(struct s_smc * smc)192 static void set_recvptr(struct s_smc *smc)
193 {
194 	/*
195 	 * initialize the pointer for receive queue 1
196 	 */
197 	outpw(FM_A(FM_RPR1),smc->hw.fp.fifo.rx1_fifo_start) ;	/* RPR1 */
198 	outpw(FM_A(FM_SWPR1),smc->hw.fp.fifo.rx1_fifo_start) ;	/* SWPR1 */
199 	outpw(FM_A(FM_WPR1),smc->hw.fp.fifo.rx1_fifo_start) ;	/* WPR1 */
200 	outpw(FM_A(FM_EARV1),smc->hw.fp.fifo.tx_s_start-1) ;	/* EARV1 */
201 
202 	/*
203 	 * initialize the pointer for receive queue 2
204 	 */
205 	if (smc->hw.fp.fifo.rx2_fifo_size) {
206 		outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
207 		outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
208 		outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
209 		outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
210 	}
211 	else {
212 		outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
213 		outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
214 		outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
215 		outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
216 	}
217 }
218 
219 /*
220  * set transmit FIFO pointer
221  */
set_txptr(struct s_smc * smc)222 static void set_txptr(struct s_smc *smc)
223 {
224 	outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ;	/* reset transmit queues */
225 
226 	/*
227 	 * initialize the pointer for asynchronous transmit queue
228 	 */
229 	outpw(FM_A(FM_RPXA0),smc->hw.fp.fifo.tx_a0_start) ;	/* RPXA0 */
230 	outpw(FM_A(FM_SWPXA0),smc->hw.fp.fifo.tx_a0_start) ;	/* SWPXA0 */
231 	outpw(FM_A(FM_WPXA0),smc->hw.fp.fifo.tx_a0_start) ;	/* WPXA0 */
232 	outpw(FM_A(FM_EAA0),smc->hw.fp.fifo.rx2_fifo_start-1) ;	/* EAA0 */
233 
234 	/*
235 	 * initialize the pointer for synchronous transmit queue
236 	 */
237 	if (smc->hw.fp.fifo.tx_s_size) {
238 		outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_s_start) ;
239 		outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_s_start) ;
240 		outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_s_start) ;
241 		outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
242 	}
243 	else {
244 		outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
245 		outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
246 		outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
247 		outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
248 	}
249 }
250 
251 /*
252  * init memory buffer management registers
253  */
init_rbc(struct s_smc * smc)254 static void init_rbc(struct s_smc *smc)
255 {
256 	u_short	rbc_ram_addr ;
257 
258 	/*
259 	 * set unused pointers or permanent pointers
260 	 */
261 	rbc_ram_addr = smc->hw.fp.fifo.rx2_fifo_start - 1 ;
262 
263 	outpw(FM_A(FM_RPXA1),rbc_ram_addr) ;	/* a1-send pointer */
264 	outpw(FM_A(FM_WPXA1),rbc_ram_addr) ;
265 	outpw(FM_A(FM_SWPXA1),rbc_ram_addr) ;
266 	outpw(FM_A(FM_EAA1),rbc_ram_addr) ;
267 
268 	set_recvptr(smc) ;
269 	set_txptr(smc) ;
270 }
271 
272 /*
273  * init rx pointer
274  */
init_rx(struct s_smc * smc)275 static void init_rx(struct s_smc *smc)
276 {
277 	struct s_smt_rx_queue	*queue ;
278 
279 	/*
280 	 * init all tx data structures for receive queue 1
281 	 */
282 	smc->hw.fp.rx[QUEUE_R1] = queue = &smc->hw.fp.rx_q[QUEUE_R1] ;
283 	queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R1_CSR) ;
284 	queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R1_DA) ;
285 
286 	/*
287 	 * init all tx data structures for receive queue 2
288 	 */
289 	smc->hw.fp.rx[QUEUE_R2] = queue = &smc->hw.fp.rx_q[QUEUE_R2] ;
290 	queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R2_CSR) ;
291 	queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R2_DA) ;
292 }
293 
294 /*
295  * set the TSYNC register of the FORMAC to regulate synchronous transmission
296  */
set_formac_tsync(struct s_smc * smc,long sync_bw)297 void set_formac_tsync(struct s_smc *smc, long sync_bw)
298 {
299 	outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ;
300 }
301 
302 /*
303  * init all tx data structures
304  */
init_tx(struct s_smc * smc)305 static void init_tx(struct s_smc *smc)
306 {
307 	struct s_smt_tx_queue	*queue ;
308 
309 	/*
310 	 * init all tx data structures for the synchronous queue
311 	 */
312 	smc->hw.fp.tx[QUEUE_S] = queue = &smc->hw.fp.tx_q[QUEUE_S] ;
313 	queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XS_CSR) ;
314 	queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XS_DA) ;
315 
316 #ifdef ESS
317 	set_formac_tsync(smc,smc->ess.sync_bw) ;
318 #endif
319 
320 	/*
321 	 * init all tx data structures for the asynchronous queue 0
322 	 */
323 	smc->hw.fp.tx[QUEUE_A0] = queue = &smc->hw.fp.tx_q[QUEUE_A0] ;
324 	queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XA_CSR) ;
325 	queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XA_DA) ;
326 
327 
328 	llc_recover_tx(smc) ;
329 }
330 
mac_counter_init(struct s_smc * smc)331 static void mac_counter_init(struct s_smc *smc)
332 {
333 	int i ;
334 	u_long *ec ;
335 
336 	/*
337 	 * clear FORMAC+ frame-, lost- and error counter
338 	 */
339 	outpw(FM_A(FM_FCNTR),0) ;
340 	outpw(FM_A(FM_LCNTR),0) ;
341 	outpw(FM_A(FM_ECNTR),0) ;
342 	/*
343 	 * clear internal error counter structure
344 	 */
345 	ec = (u_long *)&smc->hw.fp.err_stats ;
346 	for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--)
347 		*ec++ = 0L ;
348 	smc->mib.m[MAC0].fddiMACRingOp_Ct = 0 ;
349 }
350 
351 /*
352  * set FORMAC address, and t_request
353  */
set_formac_addr(struct s_smc * smc)354 static	void set_formac_addr(struct s_smc *smc)
355 {
356 	long	t_requ = smc->mib.m[MAC0].fddiMACT_Req ;
357 
358 	outpw(FM_A(FM_SAID),my_said) ;	/* set short address */
359 	outpw(FM_A(FM_LAIL),(unsigned)((smc->hw.fddi_home_addr.a[4]<<8) +
360 					smc->hw.fddi_home_addr.a[5])) ;
361 	outpw(FM_A(FM_LAIC),(unsigned)((smc->hw.fddi_home_addr.a[2]<<8) +
362 					smc->hw.fddi_home_addr.a[3])) ;
363 	outpw(FM_A(FM_LAIM),(unsigned)((smc->hw.fddi_home_addr.a[0]<<8) +
364 					smc->hw.fddi_home_addr.a[1])) ;
365 
366 	outpw(FM_A(FM_SAGP),my_sagp) ;	/* set short group address */
367 
368 	outpw(FM_A(FM_LAGL),(unsigned)((smc->hw.fp.group_addr.a[4]<<8) +
369 					smc->hw.fp.group_addr.a[5])) ;
370 	outpw(FM_A(FM_LAGC),(unsigned)((smc->hw.fp.group_addr.a[2]<<8) +
371 					smc->hw.fp.group_addr.a[3])) ;
372 	outpw(FM_A(FM_LAGM),(unsigned)((smc->hw.fp.group_addr.a[0]<<8) +
373 					smc->hw.fp.group_addr.a[1])) ;
374 
375 	/* set r_request regs. (MSW & LSW of TRT ) */
376 	outpw(FM_A(FM_TREQ1),(unsigned)(t_requ>>16)) ;
377 	outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ;
378 }
379 
set_int(char * p,int l)380 static void set_int(char *p, int l)
381 {
382 	p[0] = (char)(l >> 24) ;
383 	p[1] = (char)(l >> 16) ;
384 	p[2] = (char)(l >> 8) ;
385 	p[3] = (char)(l >> 0) ;
386 }
387 
388 /*
389  * copy TX descriptor to buffer mem
390  * append FC field and MAC frame
391  * if more bit is set in descr
392  *	append pointer to descriptor (endless loop)
393  * else
394  *	append 'end of chain' pointer
395  */
copy_tx_mac(struct s_smc * smc,u_long td,struct fddi_mac * mac,unsigned off,int len)396 static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
397 			unsigned off, int len)
398 /* u_long td;		 transmit descriptor */
399 /* struct fddi_mac *mac; mac frame pointer */
400 /* unsigned off;	 start address within buffer memory */
401 /* int len ;		 length of the frame including the FC */
402 {
403 	int	i ;
404 	__le32	*p ;
405 
406 	CHECK_NPP() ;
407 	MARW(off) ;		/* set memory address reg for writes */
408 
409 	p = (__le32 *) mac ;
410 	for (i = (len + 3)/4 ; i ; i--) {
411 		if (i == 1) {
412 			/* last word, set the tag bit */
413 			outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;
414 		}
415 		write_mdr(smc,le32_to_cpu(*p)) ;
416 		p++ ;
417 	}
418 
419 	outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;	/* set the tag bit */
420 	write_mdr(smc,td) ;	/* write over memory data reg to buffer */
421 }
422 
423 /*
424 	BEGIN_MANUAL_ENTRY(module;tests;3)
425 	How to test directed beacon frames
426 	----------------------------------------------------------------
427 
428 	o Insert a break point in the function build_claim_beacon()
429 	  before calling copy_tx_mac() for building the claim frame.
430 	o Modify the RM3_DETECT case so that the RM6_DETECT state
431 	  will always entered from the RM3_DETECT state (function rmt_fsm(),
432 	  rmt.c)
433 	o Compile the driver.
434 	o Set the parameter TREQ in the protocol.ini or net.cfg to a
435 	  small value to make sure your station will win the claim
436 	  process.
437 	o Start the driver.
438 	o When you reach the break point, modify the SA and DA address
439 	  of the claim frame (e.g. SA = DA = 10005affffff).
440 	o When you see RM3_DETECT and RM6_DETECT, observe the direct
441 	  beacon frames on the UPPSLANA.
442 
443 	END_MANUAL_ENTRY
444  */
directed_beacon(struct s_smc * smc)445 static void directed_beacon(struct s_smc *smc)
446 {
447 	SK_LOC_DECL(__le32,a[2]) ;
448 
449 	/*
450 	 * set UNA in frame
451 	 * enable FORMAC to send endless queue of directed beacon
452 	 * important: the UNA starts at byte 1 (not at byte 0)
453 	 */
454 	* (char *) a = (char) ((long)DBEACON_INFO<<24L) ;
455 	a[1] = 0 ;
456 	memcpy((char *)a+1,(char *) &smc->mib.m[MAC0].fddiMACUpstreamNbr,6) ;
457 
458 	CHECK_NPP() ;
459 	 /* set memory address reg for writes */
460 	MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;
461 	write_mdr(smc,le32_to_cpu(a[0])) ;
462 	outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;	/* set the tag bit */
463 	write_mdr(smc,le32_to_cpu(a[1])) ;
464 
465 	outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;
466 }
467 
468 /*
469 	setup claim & beacon pointer
470 	NOTE :
471 		special frame packets end with a pointer to their own
472 		descriptor, and the MORE bit is set in the descriptor
473 */
build_claim_beacon(struct s_smc * smc,u_long t_request)474 static void build_claim_beacon(struct s_smc *smc, u_long t_request)
475 {
476 	u_int	td ;
477 	int	len ;
478 	struct fddi_mac_sf *mac ;
479 
480 	/*
481 	 * build claim packet
482 	 */
483 	len = 17 ;
484 	td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
485 	mac = &smc->hw.fp.mac_sfb ;
486 	mac->mac_fc = FC_CLAIM ;
487 	/* DA == SA in claim frame */
488 	mac->mac_source = mac->mac_dest = MA ;
489 	/* 2's complement */
490 	set_int((char *)mac->mac_info,(int)t_request) ;
491 
492 	copy_tx_mac(smc,td,(struct fddi_mac *)mac,
493 		smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ;
494 	/* set CLAIM start pointer */
495 	outpw(FM_A(FM_SACL),smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF) ;
496 
497 	/*
498 	 * build beacon packet
499 	 */
500 	len = 17 ;
501 	td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
502 	mac->mac_fc = FC_BEACON ;
503 	mac->mac_source = MA ;
504 	mac->mac_dest = null_addr ;		/* DA == 0 in beacon frame */
505 	set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ;
506 
507 	copy_tx_mac(smc,td,(struct fddi_mac *)mac,
508 		smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ;
509 	/* set beacon start pointer */
510 	outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF) ;
511 
512 	/*
513 	 * build directed beacon packet
514 	 * contains optional UNA
515 	 */
516 	len = 23 ;
517 	td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
518 	mac->mac_fc = FC_BEACON ;
519 	mac->mac_source = MA ;
520 	mac->mac_dest = dbeacon_multi ;		/* multicast */
521 	set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ;
522 	set_int((char *) mac->mac_info+4,0) ;
523 	set_int((char *) mac->mac_info+8,0) ;
524 
525 	copy_tx_mac(smc,td,(struct fddi_mac *)mac,
526 		smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ;
527 
528 	/* end of claim/beacon queue */
529 	outpw(FM_A(FM_EACB),smc->hw.fp.fifo.rx1_fifo_start-1) ;
530 
531 	outpw(FM_A(FM_WPXSF),0) ;
532 	outpw(FM_A(FM_RPXSF),0) ;
533 }
534 
formac_rcv_restart(struct s_smc * smc)535 static void formac_rcv_restart(struct s_smc *smc)
536 {
537 	/* enable receive function */
538 	SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
539 
540 	outpw(FM_A(FM_CMDREG1),FM_ICLLR) ;	/* clear receive lock */
541 }
542 
formac_tx_restart(struct s_smc * smc)543 void formac_tx_restart(struct s_smc *smc)
544 {
545 	outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;	/* clear s-frame lock */
546 	outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ;	/* clear a-frame lock */
547 }
548 
enable_formac(struct s_smc * smc)549 static void enable_formac(struct s_smc *smc)
550 {
551 	/* set formac IMSK : 0 enables irq */
552 	outpw(FM_A(FM_IMSK1U),(unsigned short)~mac_imsk1u);
553 	outpw(FM_A(FM_IMSK1L),(unsigned short)~mac_imsk1l);
554 	outpw(FM_A(FM_IMSK2U),(unsigned short)~mac_imsk2u);
555 	outpw(FM_A(FM_IMSK2L),(unsigned short)~mac_imsk2l);
556 	outpw(FM_A(FM_IMSK3U),(unsigned short)~mac_imsk3u);
557 	outpw(FM_A(FM_IMSK3L),(unsigned short)~mac_imsk3l);
558 }
559 
560 #if 0	/* Removed because the driver should use the ASICs TX complete IRQ. */
561 	/* The FORMACs tx complete IRQ should be used any longer */
562 
563 /*
564 	BEGIN_MANUAL_ENTRY(if,func;others;4)
565 
566 	void enable_tx_irq(smc, queue)
567 	struct s_smc *smc ;
568 	u_short	queue ;
569 
570 Function	DOWNCALL	(SMT, fplustm.c)
571 		enable_tx_irq() enables the FORMACs transmit complete
572 		interrupt of the queue.
573 
574 Para	queue	= QUEUE_S:	synchronous queue
575 		= QUEUE_A0:	asynchronous queue
576 
577 Note	After any ring operational change the transmit complete
578 	interrupts are disabled.
579 	The operating system dependent module must enable
580 	the transmit complete interrupt of a queue,
581 		- when it queues the first frame,
582 		  because of no transmit resources are beeing
583 		  available and
584 		- when it escapes from the function llc_restart_tx
585 		  while some frames are still queued.
586 
587 	END_MANUAL_ENTRY
588  */
589 void enable_tx_irq(struct s_smc *smc, u_short queue)
590 /* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
591 {
592 	u_short	imask ;
593 
594 	imask = ~(inpw(FM_A(FM_IMSK1U))) ;
595 
596 	if (queue == 0) {
597 		outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMS)) ;
598 	}
599 	if (queue == 1) {
600 		outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMA0)) ;
601 	}
602 }
603 
604 /*
605 	BEGIN_MANUAL_ENTRY(if,func;others;4)
606 
607 	void disable_tx_irq(smc, queue)
608 	struct s_smc *smc ;
609 	u_short	queue ;
610 
611 Function	DOWNCALL	(SMT, fplustm.c)
612 		disable_tx_irq disables the FORMACs transmit complete
613 		interrupt of the queue
614 
615 Para	queue	= QUEUE_S:	synchronous queue
616 		= QUEUE_A0:	asynchronous queue
617 
618 Note	The operating system dependent module should disable
619 	the transmit complete interrupts if it escapes from the
620 	function llc_restart_tx and no frames are queued.
621 
622 	END_MANUAL_ENTRY
623  */
624 void disable_tx_irq(struct s_smc *smc, u_short queue)
625 /* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
626 {
627 	u_short	imask ;
628 
629 	imask = ~(inpw(FM_A(FM_IMSK1U))) ;
630 
631 	if (queue == 0) {
632 		outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMS)) ;
633 	}
634 	if (queue == 1) {
635 		outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMA0)) ;
636 	}
637 }
638 #endif
639 
disable_formac(struct s_smc * smc)640 static void disable_formac(struct s_smc *smc)
641 {
642 	/* clear formac IMSK : 1 disables irq */
643 	outpw(FM_A(FM_IMSK1U),MW) ;
644 	outpw(FM_A(FM_IMSK1L),MW) ;
645 	outpw(FM_A(FM_IMSK2U),MW) ;
646 	outpw(FM_A(FM_IMSK2L),MW) ;
647 	outpw(FM_A(FM_IMSK3U),MW) ;
648 	outpw(FM_A(FM_IMSK3L),MW) ;
649 }
650 
651 
mac_ring_up(struct s_smc * smc,int up)652 static void mac_ring_up(struct s_smc *smc, int up)
653 {
654 	if (up) {
655 		formac_rcv_restart(smc) ;	/* enable receive function */
656 		smc->hw.mac_ring_is_up = TRUE ;
657 		llc_restart_tx(smc) ;		/* TX queue */
658 	}
659 	else {
660 		/* disable receive function */
661 		SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
662 
663 		/* abort current transmit activity */
664 		outpw(FM_A(FM_CMDREG2),FM_IACTR) ;
665 
666 		smc->hw.mac_ring_is_up = FALSE ;
667 	}
668 }
669 
670 /*--------------------------- ISR handling ----------------------------------*/
671 /*
672  * mac1_irq is in drvfbi.c
673  */
674 
675 /*
676  * mac2_irq:	status bits for the receive queue 1, and ring status
677  * 		ring status indication bits
678  */
mac2_irq(struct s_smc * smc,u_short code_s2u,u_short code_s2l)679 void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l)
680 {
681 	u_short	change_s2l ;
682 	u_short	change_s2u ;
683 
684 	/* (jd) 22-Feb-1999
685 	 * Restart 2_DMax Timer after end of claiming or beaconing
686 	 */
687 	if (code_s2u & (FM_SCLM|FM_SHICLM|FM_SBEC|FM_SOTRBEC)) {
688 		queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
689 	}
690 	else if (code_s2l & (FM_STKISS)) {
691 		queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
692 	}
693 
694 	/*
695 	 * XOR current st bits with the last to avoid useless RMT event queuing
696 	 */
697 	change_s2l = smc->hw.fp.s2l ^ code_s2l ;
698 	change_s2u = smc->hw.fp.s2u ^ code_s2u ;
699 
700 	if ((change_s2l & FM_SRNGOP) ||
701 		(!smc->hw.mac_ring_is_up && ((code_s2l & FM_SRNGOP)))) {
702 		if (code_s2l & FM_SRNGOP) {
703 			mac_ring_up(smc,1) ;
704 			queue_event(smc,EVENT_RMT,RM_RING_OP) ;
705 			smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
706 		}
707 		else {
708 			mac_ring_up(smc,0) ;
709 			queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
710 		}
711 		goto mac2_end ;
712 	}
713 	if (code_s2l & FM_SMISFRM) {	/* missed frame */
714 		smc->mib.m[MAC0].fddiMACNotCopied_Ct++ ;
715 	}
716 	if (code_s2u & (FM_SRCVOVR |	/* recv. FIFO overflow */
717 			FM_SRBFL)) {	/* recv. buffer full */
718 		smc->hw.mac_ct.mac_r_restart_counter++ ;
719 /*		formac_rcv_restart(smc) ;	*/
720 		smt_stat_counter(smc,1) ;
721 /*		goto mac2_end ;			*/
722 	}
723 	if (code_s2u & FM_SOTRBEC)
724 		queue_event(smc,EVENT_RMT,RM_OTHER_BEACON) ;
725 	if (code_s2u & FM_SMYBEC)
726 		queue_event(smc,EVENT_RMT,RM_MY_BEACON) ;
727 	if (change_s2u & code_s2u & FM_SLOCLM) {
728 		DB_RMTN(2,"RMT : lower claim received\n",0,0) ;
729 	}
730 	if ((code_s2u & FM_SMYCLM) && !(code_s2l & FM_SDUPCLM)) {
731 		/*
732 		 * This is my claim and that claim is not detected as a
733 		 * duplicate one.
734 		 */
735 		queue_event(smc,EVENT_RMT,RM_MY_CLAIM) ;
736 	}
737 	if (code_s2l & FM_SDUPCLM) {
738 		/*
739 		 * If a duplicate claim frame (same SA but T_Bid != T_Req)
740 		 * this flag will be set.
741 		 * In the RMT state machine we need a RM_VALID_CLAIM event
742 		 * to do the appropriate state change.
743 		 * RM(34c)
744 		 */
745 		queue_event(smc,EVENT_RMT,RM_VALID_CLAIM) ;
746 	}
747 	if (change_s2u & code_s2u & FM_SHICLM) {
748 		DB_RMTN(2,"RMT : higher claim received\n",0,0) ;
749 	}
750 	if ( (code_s2l & FM_STRTEXP) ||
751 	     (code_s2l & FM_STRTEXR) )
752 		queue_event(smc,EVENT_RMT,RM_TRT_EXP) ;
753 	if (code_s2l & FM_SMULTDA) {
754 		/*
755 		 * The MAC has found a 2. MAC with the same address.
756 		 * Signal dup_addr_test = failed to RMT state machine.
757 		 * RM(25)
758 		 */
759 		smc->r.dup_addr_test = DA_FAILED ;
760 		queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
761 	}
762 	if (code_s2u & FM_SBEC)
763 		smc->hw.fp.err_stats.err_bec_stat++ ;
764 	if (code_s2u & FM_SCLM)
765 		smc->hw.fp.err_stats.err_clm_stat++ ;
766 	if (code_s2l & FM_STVXEXP)
767 		smc->mib.m[MAC0].fddiMACTvxExpired_Ct++ ;
768 	if ((code_s2u & (FM_SBEC|FM_SCLM))) {
769 		if (!(change_s2l & FM_SRNGOP) && (smc->hw.fp.s2l & FM_SRNGOP)) {
770 			mac_ring_up(smc,0) ;
771 			queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
772 
773 			mac_ring_up(smc,1) ;
774 			queue_event(smc,EVENT_RMT,RM_RING_OP) ;
775 			smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
776 		}
777 	}
778 	if (code_s2l & FM_SPHINV)
779 		smc->hw.fp.err_stats.err_phinv++ ;
780 	if (code_s2l & FM_SSIFG)
781 		smc->hw.fp.err_stats.err_sifg_det++ ;
782 	if (code_s2l & FM_STKISS)
783 		smc->hw.fp.err_stats.err_tkiss++ ;
784 	if (code_s2l & FM_STKERR)
785 		smc->hw.fp.err_stats.err_tkerr++ ;
786 	if (code_s2l & FM_SFRMCTR)
787 		smc->mib.m[MAC0].fddiMACFrame_Ct += 0x10000L ;
788 	if (code_s2l & FM_SERRCTR)
789 		smc->mib.m[MAC0].fddiMACError_Ct += 0x10000L ;
790 	if (code_s2l & FM_SLSTCTR)
791 		smc->mib.m[MAC0].fddiMACLost_Ct  += 0x10000L ;
792 	if (code_s2u & FM_SERRSF) {
793 		SMT_PANIC(smc,SMT_E0114, SMT_E0114_MSG) ;
794 	}
795 mac2_end:
796 	/* notice old status */
797 	smc->hw.fp.s2l = code_s2l ;
798 	smc->hw.fp.s2u = code_s2u ;
799 	outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ;
800 }
801 
802 /*
803  * mac3_irq:	receive queue 2 bits and address detection bits
804  */
mac3_irq(struct s_smc * smc,u_short code_s3u,u_short code_s3l)805 void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l)
806 {
807 	UNUSED(code_s3l) ;
808 
809 	if (code_s3u & (FM_SRCVOVR2 |	/* recv. FIFO overflow */
810 			FM_SRBFL2)) {	/* recv. buffer full */
811 		smc->hw.mac_ct.mac_r_restart_counter++ ;
812 		smt_stat_counter(smc,1);
813 	}
814 
815 
816 	if (code_s3u & FM_SRPERRQ2) {	/* parity error receive queue 2 */
817 		SMT_PANIC(smc,SMT_E0115, SMT_E0115_MSG) ;
818 	}
819 	if (code_s3u & FM_SRPERRQ1) {	/* parity error receive queue 2 */
820 		SMT_PANIC(smc,SMT_E0116, SMT_E0116_MSG) ;
821 	}
822 }
823 
824 
825 /*
826  * take formac offline
827  */
formac_offline(struct s_smc * smc)828 static void formac_offline(struct s_smc *smc)
829 {
830 	outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */
831 
832 	/* disable receive function */
833 	SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
834 
835 	/* FORMAC+ 'Initialize Mode' */
836 	SETMASK(FM_A(FM_MDREG1),FM_MINIT,FM_MMODE) ;
837 
838 	disable_formac(smc) ;
839 	smc->hw.mac_ring_is_up = FALSE ;
840 	smc->hw.hw_state = STOPPED ;
841 }
842 
843 /*
844  * bring formac online
845  */
formac_online(struct s_smc * smc)846 static void formac_online(struct s_smc *smc)
847 {
848 	enable_formac(smc) ;
849 	SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT |
850 		smc->hw.fp.rx_mode, FM_MMODE | FM_SELRA | FM_ADDRX) ;
851 }
852 
853 /*
854  * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon)
855  */
init_fplus(struct s_smc * smc)856 int init_fplus(struct s_smc *smc)
857 {
858 	smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
859 	smc->hw.fp.rx_mode = FM_MDAMA ;
860 	smc->hw.fp.group_addr = fddi_broadcast ;
861 	smc->hw.fp.func_addr = 0 ;
862 	smc->hw.fp.frselreg_init = 0 ;
863 
864 	init_driver_fplus(smc) ;
865 	if (smc->s.sas == SMT_DAS)
866 		smc->hw.fp.mdr3init |= FM_MENDAS ;
867 
868 	smc->hw.mac_ct.mac_nobuf_counter = 0 ;
869 	smc->hw.mac_ct.mac_r_restart_counter = 0 ;
870 
871 	smc->hw.fp.fm_st1u = (HW_PTR) ADDR(B0_ST1U) ;
872 	smc->hw.fp.fm_st1l = (HW_PTR) ADDR(B0_ST1L) ;
873 	smc->hw.fp.fm_st2u = (HW_PTR) ADDR(B0_ST2U) ;
874 	smc->hw.fp.fm_st2l = (HW_PTR) ADDR(B0_ST2L) ;
875 	smc->hw.fp.fm_st3u = (HW_PTR) ADDR(B0_ST3U) ;
876 	smc->hw.fp.fm_st3l = (HW_PTR) ADDR(B0_ST3L) ;
877 
878 	smc->hw.fp.s2l = smc->hw.fp.s2u = 0 ;
879 	smc->hw.mac_ring_is_up = 0 ;
880 
881 	mac_counter_init(smc) ;
882 
883 	/* convert BCKL units to symbol time */
884 	smc->hw.mac_pa.t_neg = (u_long)0 ;
885 	smc->hw.mac_pa.t_pri = (u_long)0 ;
886 
887 	/* make sure all PCI settings are correct */
888 	mac_do_pci_fix(smc) ;
889 
890 	return init_mac(smc, 1);
891 	/* enable_formac(smc) ; */
892 }
893 
init_mac(struct s_smc * smc,int all)894 static int init_mac(struct s_smc *smc, int all)
895 {
896 	u_short	t_max,x ;
897 	u_long	time=0 ;
898 
899 	/*
900 	 * clear memory
901 	 */
902 	outpw(FM_A(FM_MDREG1),FM_MINIT) ;	/* FORMAC+ init mode */
903 	set_formac_addr(smc) ;
904 	outpw(FM_A(FM_MDREG1),FM_MMEMACT) ;	/* FORMAC+ memory activ mode */
905 	/* Note: Mode register 2 is set here, incase parity is enabled. */
906 	outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
907 
908 	if (all) {
909 		init_ram(smc) ;
910 	}
911 	else {
912 		/*
913 		 * reset the HPI, the Master and the BMUs
914 		 */
915 		outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
916 		time = hwt_quick_read(smc) ;
917 	}
918 
919 	/*
920 	 * set all pointers, frames etc
921 	 */
922 	smt_split_up_fifo(smc) ;
923 
924 	init_tx(smc) ;
925 	init_rx(smc) ;
926 	init_rbc(smc) ;
927 
928 	build_claim_beacon(smc,smc->mib.m[MAC0].fddiMACT_Req) ;
929 
930 	/* set RX threshold */
931 	/* see Errata #SN2 Phantom receive overflow */
932 	outpw(FM_A(FM_FRMTHR),14<<12) ;		/* switch on */
933 
934 	/* set formac work mode */
935 	outpw(FM_A(FM_MDREG1),MDR1INIT | FM_SELRA | smc->hw.fp.rx_mode) ;
936 	outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
937 	outpw(FM_A(FM_MDREG3),smc->hw.fp.mdr3init) ;
938 	outpw(FM_A(FM_FRSELREG),smc->hw.fp.frselreg_init) ;
939 
940 	/* set timer */
941 	/*
942 	 * errata #22 fplus:
943 	 * T_MAX must not be FFFE
944 	 * or one of FFDF, FFB8, FF91 (-0x27 etc..)
945 	 */
946 	t_max = (u_short)(smc->mib.m[MAC0].fddiMACT_Max/32) ;
947 	x = t_max/0x27 ;
948 	x *= 0x27 ;
949 	if ((t_max == 0xfffe) || (t_max - x == 0x16))
950 		t_max-- ;
951 	outpw(FM_A(FM_TMAX),(u_short)t_max) ;
952 
953 	/* BugFix for report #10204 */
954 	if (smc->mib.m[MAC0].fddiMACTvxValue < (u_long) (- US2BCLK(52))) {
955 		outpw(FM_A(FM_TVX), (u_short) (- US2BCLK(52))/255 & MB) ;
956 	} else {
957 		outpw(FM_A(FM_TVX),
958 			(u_short)((smc->mib.m[MAC0].fddiMACTvxValue/255) & MB)) ;
959 	}
960 
961 	outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;	/* clear s-frame lock */
962 	outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ;	/* clear a-frame lock */
963 	outpw(FM_A(FM_CMDREG1),FM_ICLLR);	/* clear receive lock */
964 
965 	/* Auto unlock receice threshold for receive queue 1 and 2 */
966 	outpw(FM_A(FM_UNLCKDLY),(0xff|(0xff<<8))) ;
967 
968 	rtm_init(smc) ;				/* RT-Monitor */
969 
970 	if (!all) {
971 		/*
972 		 * after 10ms, reset the BMUs and repair the rings
973 		 */
974 		hwt_wait_time(smc,time,MS2BCLK(10)) ;
975 		outpd(ADDR(B0_R1_CSR),CSR_SET_RESET) ;
976 		outpd(ADDR(B0_XA_CSR),CSR_SET_RESET) ;
977 		outpd(ADDR(B0_XS_CSR),CSR_SET_RESET) ;
978 		outp(ADDR(B0_CTRL), CTRL_HPI_CLR) ;
979 		outpd(ADDR(B0_R1_CSR),CSR_CLR_RESET) ;
980 		outpd(ADDR(B0_XA_CSR),CSR_CLR_RESET) ;
981 		outpd(ADDR(B0_XS_CSR),CSR_CLR_RESET) ;
982 		if (!smc->hw.hw_is_64bit) {
983 			outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
984 			outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
985 			outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
986 		}
987 		smc->hw.hw_state = STOPPED ;
988 		mac_drv_repair_descr(smc) ;
989 	}
990 	smc->hw.hw_state = STARTED ;
991 
992 	return 0;
993 }
994 
995 
996 /*
997  * called by CFM
998  */
config_mux(struct s_smc * smc,int mux)999 void config_mux(struct s_smc *smc, int mux)
1000 {
1001 	plc_config_mux(smc,mux) ;
1002 
1003 	SETMASK(FM_A(FM_MDREG1),FM_SELRA,FM_SELRA) ;
1004 }
1005 
1006 /*
1007  * called by RMT
1008  * enable CLAIM/BEACON interrupts
1009  * (only called if these events are of interest, e.g. in DETECT state
1010  * the interrupt must not be permanently enabled
1011  * RMT calls this function periodically (timer driven polling)
1012  */
sm_mac_check_beacon_claim(struct s_smc * smc)1013 void sm_mac_check_beacon_claim(struct s_smc *smc)
1014 {
1015 	/* set formac IMSK : 0 enables irq */
1016 	outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ;
1017 	/* the driver must receive the directed beacons */
1018 	formac_rcv_restart(smc) ;
1019 	process_receive(smc) ;
1020 }
1021 
1022 /*-------------------------- interface functions ----------------------------*/
1023 /*
1024  * control MAC layer	(called by RMT)
1025  */
sm_ma_control(struct s_smc * smc,int mode)1026 void sm_ma_control(struct s_smc *smc, int mode)
1027 {
1028 	switch(mode) {
1029 	case MA_OFFLINE :
1030 		/* Add to make the MAC offline in RM0_ISOLATED state */
1031 		formac_offline(smc) ;
1032 		break ;
1033 	case MA_RESET :
1034 		(void)init_mac(smc,0) ;
1035 		break ;
1036 	case MA_BEACON :
1037 		formac_online(smc) ;
1038 		break ;
1039 	case MA_DIRECTED :
1040 		directed_beacon(smc) ;
1041 		break ;
1042 	case MA_TREQ :
1043 		/*
1044 		 * no actions necessary, TREQ is already set
1045 		 */
1046 		break ;
1047 	}
1048 }
1049 
sm_mac_get_tx_state(struct s_smc * smc)1050 int sm_mac_get_tx_state(struct s_smc *smc)
1051 {
1052 	return (inpw(FM_A(FM_STMCHN))>>4) & 7;
1053 }
1054 
1055 /*
1056  * multicast functions
1057  */
1058 
mac_get_mc_table(struct s_smc * smc,struct fddi_addr * user,struct fddi_addr * own,int del,int can)1059 static struct s_fpmc* mac_get_mc_table(struct s_smc *smc,
1060 				       struct fddi_addr *user,
1061 				       struct fddi_addr *own,
1062 				       int del, int can)
1063 {
1064 	struct s_fpmc	*tb ;
1065 	struct s_fpmc	*slot ;
1066 	u_char	*p ;
1067 	int i ;
1068 
1069 	/*
1070 	 * set own = can(user)
1071 	 */
1072 	*own = *user ;
1073 	if (can) {
1074 		p = own->a ;
1075 		for (i = 0 ; i < 6 ; i++, p++)
1076 			*p = bitrev8(*p);
1077 	}
1078 	slot = NULL;
1079 	for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
1080 		if (!tb->n) {		/* not used */
1081 			if (!del && !slot)	/* if !del save first free */
1082 				slot = tb ;
1083 			continue ;
1084 		}
1085 		if (memcmp((char *)&tb->a,(char *)own,6))
1086 			continue ;
1087 		return tb;
1088 	}
1089 	return slot;			/* return first free or NULL */
1090 }
1091 
1092 /*
1093 	BEGIN_MANUAL_ENTRY(if,func;others;2)
1094 
1095 	void mac_clear_multicast(smc)
1096 	struct s_smc *smc ;
1097 
1098 Function	DOWNCALL	(SMT, fplustm.c)
1099 		Clear all multicast entries
1100 
1101 	END_MANUAL_ENTRY()
1102  */
mac_clear_multicast(struct s_smc * smc)1103 void mac_clear_multicast(struct s_smc *smc)
1104 {
1105 	struct s_fpmc	*tb ;
1106 	int i ;
1107 
1108 	smc->hw.fp.os_slots_used = 0 ;	/* note the SMT addresses */
1109 					/* will not be deleted */
1110 	for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
1111 		if (!tb->perm) {
1112 			tb->n = 0 ;
1113 		}
1114 	}
1115 }
1116 
1117 /*
1118 	BEGIN_MANUAL_ENTRY(if,func;others;2)
1119 
1120 	int mac_add_multicast(smc,addr,can)
1121 	struct s_smc *smc ;
1122 	struct fddi_addr *addr ;
1123 	int can ;
1124 
1125 Function	DOWNCALL	(SMC, fplustm.c)
1126 		Add an entry to the multicast table
1127 
1128 Para	addr	pointer to a multicast address
1129 	can	= 0:	the multicast address has the physical format
1130 		= 1:	the multicast address has the canonical format
1131 		| 0x80	permanent
1132 
1133 Returns	0: success
1134 	1: address table full
1135 
1136 Note	After a 'driver reset' or a 'station set address' all
1137 	entries of the multicast table are cleared.
1138 	In this case the driver has to fill the multicast table again.
1139 	After the operating system dependent module filled
1140 	the multicast table it must call mac_update_multicast
1141 	to activate the new multicast addresses!
1142 
1143 	END_MANUAL_ENTRY()
1144  */
mac_add_multicast(struct s_smc * smc,struct fddi_addr * addr,int can)1145 int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
1146 {
1147 	SK_LOC_DECL(struct fddi_addr,own) ;
1148 	struct s_fpmc	*tb ;
1149 
1150 	/*
1151 	 * check if there are free table entries
1152 	 */
1153 	if (can & 0x80) {
1154 		if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) {
1155 			return 1;
1156 		}
1157 	}
1158 	else {
1159 		if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) {
1160 			return 1;
1161 		}
1162 	}
1163 
1164 	/*
1165 	 * find empty slot
1166 	 */
1167 	if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80)))
1168 		return 1;
1169 	tb->n++ ;
1170 	tb->a = own ;
1171 	tb->perm = (can & 0x80) ? 1 : 0 ;
1172 
1173 	if (can & 0x80)
1174 		smc->hw.fp.smt_slots_used++ ;
1175 	else
1176 		smc->hw.fp.os_slots_used++ ;
1177 
1178 	return 0;
1179 }
1180 
1181 /*
1182  * mode
1183  */
1184 
1185 #define RX_MODE_PROM		0x1
1186 #define RX_MODE_ALL_MULTI	0x2
1187 
1188 /*
1189 	BEGIN_MANUAL_ENTRY(if,func;others;2)
1190 
1191 	void mac_update_multicast(smc)
1192 	struct s_smc *smc ;
1193 
1194 Function	DOWNCALL	(SMT, fplustm.c)
1195 		Update FORMAC multicast registers
1196 
1197 	END_MANUAL_ENTRY()
1198  */
mac_update_multicast(struct s_smc * smc)1199 void mac_update_multicast(struct s_smc *smc)
1200 {
1201 	struct s_fpmc	*tb ;
1202 	u_char	*fu ;
1203 	int	i ;
1204 
1205 	/*
1206 	 * invalidate the CAM
1207 	 */
1208 	outpw(FM_A(FM_AFCMD),FM_IINV_CAM) ;
1209 
1210 	/*
1211 	 * set the functional address
1212 	 */
1213 	if (smc->hw.fp.func_addr) {
1214 		fu = (u_char *) &smc->hw.fp.func_addr ;
1215 		outpw(FM_A(FM_AFMASK2),0xffff) ;
1216 		outpw(FM_A(FM_AFMASK1),(u_short) ~((fu[0] << 8) + fu[1])) ;
1217 		outpw(FM_A(FM_AFMASK0),(u_short) ~((fu[2] << 8) + fu[3])) ;
1218 		outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
1219 		outpw(FM_A(FM_AFCOMP2), 0xc000) ;
1220 		outpw(FM_A(FM_AFCOMP1), 0x0000) ;
1221 		outpw(FM_A(FM_AFCOMP0), 0x0000) ;
1222 		outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
1223 	}
1224 
1225 	/*
1226 	 * set the mask and the personality register(s)
1227 	 */
1228 	outpw(FM_A(FM_AFMASK0),0xffff) ;
1229 	outpw(FM_A(FM_AFMASK1),0xffff) ;
1230 	outpw(FM_A(FM_AFMASK2),0xffff) ;
1231 	outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
1232 
1233 	for (i = 0, tb = smc->hw.fp.mc.table; i < FPMAX_MULTICAST; i++, tb++) {
1234 		if (tb->n) {
1235 			CHECK_CAM() ;
1236 
1237 			/*
1238 			 * write the multicast address into the CAM
1239 			 */
1240 			outpw(FM_A(FM_AFCOMP2),
1241 				(u_short)((tb->a.a[0]<<8)+tb->a.a[1])) ;
1242 			outpw(FM_A(FM_AFCOMP1),
1243 				(u_short)((tb->a.a[2]<<8)+tb->a.a[3])) ;
1244 			outpw(FM_A(FM_AFCOMP0),
1245 				(u_short)((tb->a.a[4]<<8)+tb->a.a[5])) ;
1246 			outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
1247 		}
1248 	}
1249 }
1250 
1251 /*
1252 	BEGIN_MANUAL_ENTRY(if,func;others;3)
1253 
1254 	void mac_set_rx_mode(smc,mode)
1255 	struct s_smc *smc ;
1256 	int mode ;
1257 
1258 Function	DOWNCALL/INTERN	(SMT, fplustm.c)
1259 		This function enables / disables the selected receive.
1260 		Don't call this function if the hardware module is
1261 		used -- use mac_drv_rx_mode() instead of.
1262 
1263 Para	mode =	1	RX_ENABLE_ALLMULTI	enable all multicasts
1264 		2	RX_DISABLE_ALLMULTI	disable "enable all multicasts"
1265 		3	RX_ENABLE_PROMISC	enable promiscuous
1266 		4	RX_DISABLE_PROMISC	disable promiscuous
1267 		5	RX_ENABLE_NSA		enable reception of NSA frames
1268 		6	RX_DISABLE_NSA		disable reception of NSA frames
1269 
1270 Note	The selected receive modes will be lost after 'driver reset'
1271 	or 'set station address'
1272 
1273 	END_MANUAL_ENTRY
1274  */
mac_set_rx_mode(struct s_smc * smc,int mode)1275 void mac_set_rx_mode(struct s_smc *smc, int mode)
1276 {
1277 	switch (mode) {
1278 	case RX_ENABLE_ALLMULTI :
1279 		smc->hw.fp.rx_prom |= RX_MODE_ALL_MULTI ;
1280 		break ;
1281 	case RX_DISABLE_ALLMULTI :
1282 		smc->hw.fp.rx_prom &= ~RX_MODE_ALL_MULTI ;
1283 		break ;
1284 	case RX_ENABLE_PROMISC :
1285 		smc->hw.fp.rx_prom |= RX_MODE_PROM ;
1286 		break ;
1287 	case RX_DISABLE_PROMISC :
1288 		smc->hw.fp.rx_prom &= ~RX_MODE_PROM ;
1289 		break ;
1290 	case RX_ENABLE_NSA :
1291 		smc->hw.fp.nsa_mode = FM_MDAMA ;
1292 		smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
1293 			smc->hw.fp.nsa_mode ;
1294 		break ;
1295 	case RX_DISABLE_NSA :
1296 		smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
1297 		smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
1298 			smc->hw.fp.nsa_mode ;
1299 		break ;
1300 	}
1301 	if (smc->hw.fp.rx_prom & RX_MODE_PROM) {
1302 		smc->hw.fp.rx_mode = FM_MLIMPROM ;
1303 	}
1304 	else if (smc->hw.fp.rx_prom & RX_MODE_ALL_MULTI) {
1305 		smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode | FM_EXGPA0 ;
1306 	}
1307 	else
1308 		smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode ;
1309 	SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
1310 	mac_update_multicast(smc) ;
1311 }
1312 
1313 /*
1314 	BEGIN_MANUAL_ENTRY(module;tests;3)
1315 	How to test the Restricted Token Monitor
1316 	----------------------------------------------------------------
1317 
1318 	o Insert a break point in the function rtm_irq()
1319 	o Remove all stations with a restricted token monitor from the
1320 	  network.
1321 	o Connect a UPPS ISA or EISA station to the network.
1322 	o Give the FORMAC of UPPS station the command to send
1323 	  restricted tokens until the ring becomes instable.
1324 	o Now connect your test test client.
1325 	o The restricted token monitor should detect the restricted token,
1326 	  and your break point will be reached.
1327 	o You can ovserve how the station will clean the ring.
1328 
1329 	END_MANUAL_ENTRY
1330  */
rtm_irq(struct s_smc * smc)1331 void rtm_irq(struct s_smc *smc)
1332 {
1333 	outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ;		/* clear IRQ */
1334 	if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) {
1335 		outpw(FM_A(FM_CMDREG1),FM_ICL) ;	/* force claim */
1336 		DB_RMT("RMT: fddiPATHT_Rmode expired\n",0,0) ;
1337 		AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
1338 				(u_long) FDDI_SMT_EVENT,
1339 				(u_long) FDDI_RTT, smt_get_event_word(smc));
1340 	}
1341 	outpw(ADDR(B2_RTM_CRTL),TIM_START) ;	/* enable RTM monitoring */
1342 }
1343 
rtm_init(struct s_smc * smc)1344 static void rtm_init(struct s_smc *smc)
1345 {
1346 	outpd(ADDR(B2_RTM_INI),0) ;		/* timer = 0 */
1347 	outpw(ADDR(B2_RTM_CRTL),TIM_START) ;	/* enable IRQ */
1348 }
1349 
rtm_set_timer(struct s_smc * smc)1350 void rtm_set_timer(struct s_smc *smc)
1351 {
1352 	/*
1353 	 * MIB timer and hardware timer have the same resolution of 80nS
1354 	 */
1355 	DB_RMT("RMT: setting new fddiPATHT_Rmode, t = %d ns\n",
1356 		(int) smc->mib.a[PATH0].fddiPATHT_Rmode,0) ;
1357 	outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ;
1358 }
1359 
smt_split_up_fifo(struct s_smc * smc)1360 static void smt_split_up_fifo(struct s_smc *smc)
1361 {
1362 
1363 /*
1364 	BEGIN_MANUAL_ENTRY(module;mem;1)
1365 	-------------------------------------------------------------
1366 	RECEIVE BUFFER MEMORY DIVERSION
1367 	-------------------------------------------------------------
1368 
1369 	R1_RxD == SMT_R1_RXD_COUNT
1370 	R2_RxD == SMT_R2_RXD_COUNT
1371 
1372 	SMT_R1_RXD_COUNT must be unequal zero
1373 
1374 		   | R1_RxD R2_RxD |R1_RxD R2_RxD | R1_RxD R2_RxD
1375 		   |   x      0	   |  x	    1-3	  |   x     < 3
1376 	----------------------------------------------------------------------
1377 		   |   63,75 kB	   |    54,75	  |	R1_RxD
1378 	rx queue 1 | RX_FIFO_SPACE | RX_LARGE_FIFO| ------------- * 63,75 kB
1379 		   |		   |		  | R1_RxD+R2_RxD
1380 	----------------------------------------------------------------------
1381 		   |		   |    9 kB	  |     R2_RxD
1382 	rx queue 2 |	0 kB	   | RX_SMALL_FIFO| ------------- * 63,75 kB
1383 		   |  (not used)   |		  | R1_RxD+R2_RxD
1384 
1385 	END_MANUAL_ENTRY
1386 */
1387 
1388 	if (SMT_R1_RXD_COUNT == 0) {
1389 		SMT_PANIC(smc,SMT_E0117, SMT_E0117_MSG) ;
1390 	}
1391 
1392 	switch(SMT_R2_RXD_COUNT) {
1393 	case 0:
1394 		smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE ;
1395 		smc->hw.fp.fifo.rx2_fifo_size = 0 ;
1396 		break ;
1397 	case 1:
1398 	case 2:
1399 	case 3:
1400 		smc->hw.fp.fifo.rx1_fifo_size = RX_LARGE_FIFO ;
1401 		smc->hw.fp.fifo.rx2_fifo_size = RX_SMALL_FIFO ;
1402 		break ;
1403 	default:	/* this is not the real defaule */
1404 		smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE *
1405 		SMT_R1_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
1406 		smc->hw.fp.fifo.rx2_fifo_size = RX_FIFO_SPACE *
1407 		SMT_R2_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
1408 		break ;
1409 	}
1410 
1411 /*
1412 	BEGIN_MANUAL_ENTRY(module;mem;1)
1413 	-------------------------------------------------------------
1414 	TRANSMIT BUFFER MEMORY DIVERSION
1415 	-------------------------------------------------------------
1416 
1417 
1418 		 | no sync bw	| sync bw available and | sync bw available and
1419 		 | available	| SynchTxMode = SPLIT	| SynchTxMode = ALL
1420 	-----------------------------------------------------------------------
1421 	sync tx	 |     0 kB	|	32 kB		|	55 kB
1422 	queue	 |		|   TX_MEDIUM_FIFO	|   TX_LARGE_FIFO
1423 	-----------------------------------------------------------------------
1424 	async tx |    64 kB	|	32 kB		|	 9 k
1425 	queue	 | TX_FIFO_SPACE|   TX_MEDIUM_FIFO	|   TX_SMALL_FIFO
1426 
1427 	END_MANUAL_ENTRY
1428 */
1429 
1430 	/*
1431 	 * set the tx mode bits
1432 	 */
1433 	if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
1434 #ifdef ESS
1435 		smc->hw.fp.fifo.fifo_config_mode |=
1436 			smc->mib.fddiESSSynchTxMode | SYNC_TRAFFIC_ON ;
1437 #endif
1438 	}
1439 	else {
1440 		smc->hw.fp.fifo.fifo_config_mode &=
1441 			~(SEND_ASYNC_AS_SYNC|SYNC_TRAFFIC_ON) ;
1442 	}
1443 
1444 	/*
1445 	 * split up the FIFO
1446 	 */
1447 	if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON) {
1448 		if (smc->hw.fp.fifo.fifo_config_mode & SEND_ASYNC_AS_SYNC) {
1449 			smc->hw.fp.fifo.tx_s_size = TX_LARGE_FIFO ;
1450 			smc->hw.fp.fifo.tx_a0_size = TX_SMALL_FIFO ;
1451 		}
1452 		else {
1453 			smc->hw.fp.fifo.tx_s_size = TX_MEDIUM_FIFO ;
1454 			smc->hw.fp.fifo.tx_a0_size = TX_MEDIUM_FIFO ;
1455 		}
1456 	}
1457 	else {
1458 			smc->hw.fp.fifo.tx_s_size = 0 ;
1459 			smc->hw.fp.fifo.tx_a0_size = TX_FIFO_SPACE ;
1460 	}
1461 
1462 	smc->hw.fp.fifo.rx1_fifo_start = smc->hw.fp.fifo.rbc_ram_start +
1463 		RX_FIFO_OFF ;
1464 	smc->hw.fp.fifo.tx_s_start = smc->hw.fp.fifo.rx1_fifo_start +
1465 		smc->hw.fp.fifo.rx1_fifo_size ;
1466 	smc->hw.fp.fifo.tx_a0_start = smc->hw.fp.fifo.tx_s_start +
1467 		smc->hw.fp.fifo.tx_s_size ;
1468 	smc->hw.fp.fifo.rx2_fifo_start = smc->hw.fp.fifo.tx_a0_start +
1469 		smc->hw.fp.fifo.tx_a0_size ;
1470 
1471 	DB_SMT("FIFO split: mode = %x\n",smc->hw.fp.fifo.fifo_config_mode,0) ;
1472 	DB_SMT("rbc_ram_start =	%x	 rbc_ram_end = 	%x\n",
1473 		smc->hw.fp.fifo.rbc_ram_start, smc->hw.fp.fifo.rbc_ram_end) ;
1474 	DB_SMT("rx1_fifo_start = %x	 tx_s_start = 	%x\n",
1475 		smc->hw.fp.fifo.rx1_fifo_start, smc->hw.fp.fifo.tx_s_start) ;
1476 	DB_SMT("tx_a0_start =	%x	 rx2_fifo_start = 	%x\n",
1477 		smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start) ;
1478 }
1479 
formac_reinit_tx(struct s_smc * smc)1480 void formac_reinit_tx(struct s_smc *smc)
1481 {
1482 	/*
1483 	 * Split up the FIFO and reinitialize the MAC if synchronous
1484 	 * bandwidth becomes available but no synchronous queue is
1485 	 * configured.
1486 	 */
1487 	if (!smc->hw.fp.fifo.tx_s_size && smc->mib.a[PATH0].fddiPATHSbaPayload){
1488 		(void)init_mac(smc,0) ;
1489 	}
1490 }
1491 
1492