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