1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /******************************************************************************
3 *
4 * (C)Copyright 1998,1999 SysKonnect,
5 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
6 *
7 * See the file "skfddi.c" for further information.
8 *
9 * The information in this file is provided "AS IS" without warranty.
10 *
11 ******************************************************************************/
12
13 /*
14 * FBI board dependent Driver for SMT and LLC
15 */
16
17 #include "h/types.h"
18 #include "h/fddi.h"
19 #include "h/smc.h"
20 #include "h/supern_2.h"
21 #include "h/skfbiinc.h"
22 #include <linux/bitrev.h>
23 #include <linux/pci.h>
24
25 #ifndef lint
26 static const char ID_sccs[] = "@(#)drvfbi.c 1.63 99/02/11 (C) SK " ;
27 #endif
28
29 /*
30 * PCM active state
31 */
32 #define PC8_ACTIVE 8
33
34 #define LED_Y_ON 0x11 /* Used for ring up/down indication */
35 #define LED_Y_OFF 0x10
36
37
38 #define MS2BCLK(x) ((x)*12500L)
39
40 /*
41 * valid configuration values are:
42 */
43
44 /*
45 * xPOS_ID:xxxx
46 * | \ /
47 * | \/
48 * | --------------------- the patched POS_ID of the Adapter
49 * | xxxx = (Vendor ID low byte,
50 * | Vendor ID high byte,
51 * | Device ID low byte,
52 * | Device ID high byte)
53 * +------------------------------ the patched oem_id must be
54 * 'S' for SK or 'I' for IBM
55 * this is a short id for the driver.
56 */
57 #ifndef MULT_OEM
58 #ifndef OEM_CONCEPT
59 const u_char oem_id[] = "xPOS_ID:xxxx" ;
60 #else /* OEM_CONCEPT */
61 const u_char oem_id[] = OEM_ID ;
62 #endif /* OEM_CONCEPT */
63 #define ID_BYTE0 8
64 #define OEMID(smc,i) oem_id[ID_BYTE0 + i]
65 #else /* MULT_OEM */
66 const struct s_oem_ids oem_ids[] = {
67 #include "oemids.h"
68 {0}
69 };
70 #define OEMID(smc,i) smc->hw.oem_id->oi_id[i]
71 #endif /* MULT_OEM */
72
73 /* Prototypes of external functions */
74 #ifdef AIX
75 extern int AIX_vpdReadByte() ;
76 #endif
77
78
79 /* Prototype of a local function. */
80 static void smt_stop_watchdog(struct s_smc *smc);
81
82 /*
83 * FDDI card reset
84 */
card_start(struct s_smc * smc)85 static void card_start(struct s_smc *smc)
86 {
87 int i ;
88 #ifdef PCI
89 u_char rev_id ;
90 u_short word;
91 #endif
92
93 smt_stop_watchdog(smc) ;
94
95 #ifdef PCI
96 /*
97 * make sure no transfer activity is pending
98 */
99 outpw(FM_A(FM_MDREG1),FM_MINIT) ;
100 outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
101 hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
102 /*
103 * now reset everything
104 */
105 outp(ADDR(B0_CTRL),CTRL_RST_SET) ; /* reset for all chips */
106 i = (int) inp(ADDR(B0_CTRL)) ; /* do dummy read */
107 SK_UNUSED(i) ; /* Make LINT happy. */
108 outp(ADDR(B0_CTRL), CTRL_RST_CLR) ;
109
110 /*
111 * Reset all bits in the PCI STATUS register
112 */
113 outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_ON) ; /* enable for writes */
114 word = inpw(PCI_C(PCI_STATUS)) ;
115 outpw(PCI_C(PCI_STATUS), word | PCI_STATUS_ERROR_BITS);
116 outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_OFF) ; /* disable writes */
117
118 /*
119 * Release the reset of all the State machines
120 * Release Master_Reset
121 * Release HPI_SM_Reset
122 */
123 outp(ADDR(B0_CTRL), CTRL_MRST_CLR|CTRL_HPI_CLR) ;
124
125 /*
126 * determine the adapter type
127 * Note: Do it here, because some drivers may call card_start() once
128 * at very first before any other initialization functions is
129 * executed.
130 */
131 rev_id = inp(PCI_C(PCI_REVISION_ID)) ;
132 if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
133 smc->hw.hw_is_64bit = TRUE ;
134 } else {
135 smc->hw.hw_is_64bit = FALSE ;
136 }
137
138 /*
139 * Watermark initialization
140 */
141 if (!smc->hw.hw_is_64bit) {
142 outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
143 outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
144 outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
145 }
146
147 outp(ADDR(B0_CTRL),CTRL_RST_CLR) ; /* clear the reset chips */
148 outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_ON|LED_GB_OFF) ; /* ye LED on */
149
150 /* init the timer value for the watch dog 2,5 minutes */
151 outpd(ADDR(B2_WDOG_INI),0x6FC23AC0) ;
152
153 /* initialize the ISR mask */
154 smc->hw.is_imask = ISR_MASK ;
155 smc->hw.hw_state = STOPPED ;
156 #endif
157 GET_PAGE(0) ; /* necessary for BOOT */
158 }
159
card_stop(struct s_smc * smc)160 void card_stop(struct s_smc *smc)
161 {
162 smt_stop_watchdog(smc) ;
163 smc->hw.mac_ring_is_up = 0 ; /* ring down */
164
165 #ifdef PCI
166 /*
167 * make sure no transfer activity is pending
168 */
169 outpw(FM_A(FM_MDREG1),FM_MINIT) ;
170 outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
171 hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
172 /*
173 * now reset everything
174 */
175 outp(ADDR(B0_CTRL),CTRL_RST_SET) ; /* reset for all chips */
176 outp(ADDR(B0_CTRL),CTRL_RST_CLR) ; /* reset for all chips */
177 outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_OFF|LED_GB_OFF) ; /* all LEDs off */
178 smc->hw.hw_state = STOPPED ;
179 #endif
180 }
181 /*--------------------------- ISR handling ----------------------------------*/
182
mac1_irq(struct s_smc * smc,u_short stu,u_short stl)183 void mac1_irq(struct s_smc *smc, u_short stu, u_short stl)
184 {
185 int restart_tx = 0 ;
186 again:
187
188 /*
189 * parity error: note encoding error is not possible in tag mode
190 */
191 if (stl & (FM_SPCEPDS | /* parity err. syn.q.*/
192 FM_SPCEPDA0 | /* parity err. a.q.0 */
193 FM_SPCEPDA1)) { /* parity err. a.q.1 */
194 SMT_PANIC(smc,SMT_E0134, SMT_E0134_MSG) ;
195 }
196 /*
197 * buffer underrun: can only occur if a tx threshold is specified
198 */
199 if (stl & (FM_STBURS | /* tx buffer underrun syn.q.*/
200 FM_STBURA0 | /* tx buffer underrun a.q.0 */
201 FM_STBURA1)) { /* tx buffer underrun a.q.2 */
202 SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ;
203 }
204
205 if ( (stu & (FM_SXMTABT | /* transmit abort */
206 FM_STXABRS | /* syn. tx abort */
207 FM_STXABRA0)) || /* asyn. tx abort */
208 (stl & (FM_SQLCKS | /* lock for syn. q. */
209 FM_SQLCKA0)) ) { /* lock for asyn. q. */
210 formac_tx_restart(smc) ; /* init tx */
211 restart_tx = 1 ;
212 stu = inpw(FM_A(FM_ST1U)) ;
213 stl = inpw(FM_A(FM_ST1L)) ;
214 stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ;
215 if (stu || stl)
216 goto again ;
217 }
218
219 if (stu & (FM_STEFRMA0 | /* end of asyn tx */
220 FM_STEFRMS)) { /* end of sync tx */
221 restart_tx = 1 ;
222 }
223
224 if (restart_tx)
225 llc_restart_tx(smc) ;
226 }
227
228 /*
229 * interrupt source= plc1
230 * this function is called in nwfbisr.asm
231 */
plc1_irq(struct s_smc * smc)232 void plc1_irq(struct s_smc *smc)
233 {
234 u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ;
235
236 plc_irq(smc,PB,st) ;
237 }
238
239 /*
240 * interrupt source= plc2
241 * this function is called in nwfbisr.asm
242 */
plc2_irq(struct s_smc * smc)243 void plc2_irq(struct s_smc *smc)
244 {
245 u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ;
246
247 plc_irq(smc,PA,st) ;
248 }
249
250
251 /*
252 * interrupt source= timer
253 */
timer_irq(struct s_smc * smc)254 void timer_irq(struct s_smc *smc)
255 {
256 hwt_restart(smc);
257 smc->hw.t_stop = smc->hw.t_start;
258 smt_timer_done(smc) ;
259 }
260
261 /*
262 * return S-port (PA or PB)
263 */
pcm_get_s_port(struct s_smc * smc)264 int pcm_get_s_port(struct s_smc *smc)
265 {
266 SK_UNUSED(smc) ;
267 return PS;
268 }
269
270 /*
271 * Station Label = "FDDI-XYZ" where
272 *
273 * X = connector type
274 * Y = PMD type
275 * Z = port type
276 */
277 #define STATION_LABEL_CONNECTOR_OFFSET 5
278 #define STATION_LABEL_PMD_OFFSET 6
279 #define STATION_LABEL_PORT_OFFSET 7
280
read_address(struct s_smc * smc,u_char * mac_addr)281 void read_address(struct s_smc *smc, u_char *mac_addr)
282 {
283 char ConnectorType ;
284 char PmdType ;
285 int i ;
286
287 #ifdef PCI
288 for (i = 0; i < 6; i++) { /* read mac address from board */
289 smc->hw.fddi_phys_addr.a[i] =
290 bitrev8(inp(ADDR(B2_MAC_0+i)));
291 }
292 #endif
293
294 ConnectorType = inp(ADDR(B2_CONN_TYP)) ;
295 PmdType = inp(ADDR(B2_PMD_TYP)) ;
296
297 smc->y[PA].pmd_type[PMD_SK_CONN] =
298 smc->y[PB].pmd_type[PMD_SK_CONN] = ConnectorType ;
299 smc->y[PA].pmd_type[PMD_SK_PMD ] =
300 smc->y[PB].pmd_type[PMD_SK_PMD ] = PmdType ;
301
302 if (mac_addr) {
303 for (i = 0; i < 6 ;i++) {
304 smc->hw.fddi_canon_addr.a[i] = mac_addr[i] ;
305 smc->hw.fddi_home_addr.a[i] = bitrev8(mac_addr[i]);
306 }
307 return ;
308 }
309 smc->hw.fddi_home_addr = smc->hw.fddi_phys_addr ;
310
311 for (i = 0; i < 6 ;i++) {
312 smc->hw.fddi_canon_addr.a[i] =
313 bitrev8(smc->hw.fddi_phys_addr.a[i]);
314 }
315 }
316
317 /*
318 * FDDI card soft reset
319 */
init_board(struct s_smc * smc,u_char * mac_addr)320 void init_board(struct s_smc *smc, u_char *mac_addr)
321 {
322 card_start(smc) ;
323 read_address(smc,mac_addr) ;
324
325 if (!(inp(ADDR(B0_DAS)) & DAS_AVAIL))
326 smc->s.sas = SMT_SAS ; /* Single att. station */
327 else
328 smc->s.sas = SMT_DAS ; /* Dual att. station */
329
330 if (!(inp(ADDR(B0_DAS)) & DAS_BYP_ST))
331 smc->mib.fddiSMTBypassPresent = 0 ;
332 /* without opt. bypass */
333 else
334 smc->mib.fddiSMTBypassPresent = 1 ;
335 /* with opt. bypass */
336 }
337
338 /*
339 * insert or deinsert optical bypass (called by ECM)
340 */
sm_pm_bypass_req(struct s_smc * smc,int mode)341 void sm_pm_bypass_req(struct s_smc *smc, int mode)
342 {
343 DB_ECMN(1, "ECM : sm_pm_bypass_req(%s)",
344 mode == BP_INSERT ? "BP_INSERT" : "BP_DEINSERT");
345
346 if (smc->s.sas != SMT_DAS)
347 return ;
348
349 #ifdef PCI
350 switch(mode) {
351 case BP_INSERT :
352 outp(ADDR(B0_DAS),DAS_BYP_INS) ; /* insert station */
353 break ;
354 case BP_DEINSERT :
355 outp(ADDR(B0_DAS),DAS_BYP_RMV) ; /* bypass station */
356 break ;
357 }
358 #endif
359 }
360
361 /*
362 * check if bypass connected
363 */
sm_pm_bypass_present(struct s_smc * smc)364 int sm_pm_bypass_present(struct s_smc *smc)
365 {
366 return (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE : FALSE;
367 }
368
plc_clear_irq(struct s_smc * smc,int p)369 void plc_clear_irq(struct s_smc *smc, int p)
370 {
371 SK_UNUSED(p) ;
372
373 SK_UNUSED(smc) ;
374 }
375
376
377 /*
378 * led_indication called by rmt_indication() and
379 * pcm_state_change()
380 *
381 * Input:
382 * smc: SMT context
383 * led_event:
384 * 0 Only switch green LEDs according to their respective PCM state
385 * LED_Y_OFF just switch yellow LED off
386 * LED_Y_ON just switch yello LED on
387 */
led_indication(struct s_smc * smc,int led_event)388 static void led_indication(struct s_smc *smc, int led_event)
389 {
390 /* use smc->hw.mac_ring_is_up == TRUE
391 * as indication for Ring Operational
392 */
393 u_short led_state ;
394 struct s_phy *phy ;
395 struct fddi_mib_p *mib_a ;
396 struct fddi_mib_p *mib_b ;
397
398 phy = &smc->y[PA] ;
399 mib_a = phy->mib ;
400 phy = &smc->y[PB] ;
401 mib_b = phy->mib ;
402
403 #ifdef PCI
404 led_state = 0 ;
405
406 /* Ring up = yellow led OFF*/
407 if (led_event == LED_Y_ON) {
408 led_state |= LED_MY_ON ;
409 }
410 else if (led_event == LED_Y_OFF) {
411 led_state |= LED_MY_OFF ;
412 }
413 else { /* PCM state changed */
414 /* Link at Port A/S = green led A ON */
415 if (mib_a->fddiPORTPCMState == PC8_ACTIVE) {
416 led_state |= LED_GA_ON ;
417 }
418 else {
419 led_state |= LED_GA_OFF ;
420 }
421
422 /* Link at Port B = green led B ON */
423 if (mib_b->fddiPORTPCMState == PC8_ACTIVE) {
424 led_state |= LED_GB_ON ;
425 }
426 else {
427 led_state |= LED_GB_OFF ;
428 }
429 }
430
431 outp(ADDR(B0_LED), led_state) ;
432 #endif /* PCI */
433
434 }
435
436
pcm_state_change(struct s_smc * smc,int plc,int p_state)437 void pcm_state_change(struct s_smc *smc, int plc, int p_state)
438 {
439 /*
440 * the current implementation of pcm_state_change() in the driver
441 * parts must be renamed to drv_pcm_state_change() which will be called
442 * now after led_indication.
443 */
444 DRV_PCM_STATE_CHANGE(smc,plc,p_state) ;
445
446 led_indication(smc,0) ;
447 }
448
449
rmt_indication(struct s_smc * smc,int i)450 void rmt_indication(struct s_smc *smc, int i)
451 {
452 /* Call a driver special function if defined */
453 DRV_RMT_INDICATION(smc,i) ;
454
455 led_indication(smc, i ? LED_Y_OFF : LED_Y_ON) ;
456 }
457
458
459 /*
460 * llc_recover_tx called by init_tx (fplus.c)
461 */
llc_recover_tx(struct s_smc * smc)462 void llc_recover_tx(struct s_smc *smc)
463 {
464 #ifdef LOAD_GEN
465 extern int load_gen_flag ;
466
467 load_gen_flag = 0 ;
468 #endif
469 #ifndef SYNC
470 smc->hw.n_a_send= 0 ;
471 #else
472 SK_UNUSED(smc) ;
473 #endif
474 }
475
476 #ifdef MULT_OEM
is_equal_num(char comp1[],char comp2[],int num)477 static int is_equal_num(char comp1[], char comp2[], int num)
478 {
479 int i ;
480
481 for (i = 0 ; i < num ; i++) {
482 if (comp1[i] != comp2[i])
483 return 0;
484 }
485 return 1;
486 } /* is_equal_num */
487
488
489 /*
490 * set the OEM ID defaults, and test the contents of the OEM data base
491 * The default OEM is the first ACTIVE entry in the OEM data base
492 *
493 * returns: 0 success
494 * 1 error in data base
495 * 2 data base empty
496 * 3 no active entry
497 */
set_oi_id_def(struct s_smc * smc)498 int set_oi_id_def(struct s_smc *smc)
499 {
500 int sel_id ;
501 int i ;
502 int act_entries ;
503
504 i = 0 ;
505 sel_id = -1 ;
506 act_entries = FALSE ;
507 smc->hw.oem_id = 0 ;
508 smc->hw.oem_min_status = OI_STAT_ACTIVE ;
509
510 /* check OEM data base */
511 while (oem_ids[i].oi_status) {
512 switch (oem_ids[i].oi_status) {
513 case OI_STAT_ACTIVE:
514 act_entries = TRUE ; /* we have active IDs */
515 if (sel_id == -1)
516 sel_id = i ; /* save the first active ID */
517 case OI_STAT_VALID:
518 case OI_STAT_PRESENT:
519 i++ ;
520 break ; /* entry ok */
521 default:
522 return 1; /* invalid oi_status */
523 }
524 }
525
526 if (i == 0)
527 return 2;
528 if (!act_entries)
529 return 3;
530
531 /* ok, we have a valid OEM data base with an active entry */
532 smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[sel_id] ;
533 return 0;
534 }
535 #endif /* MULT_OEM */
536
driver_get_bia(struct s_smc * smc,struct fddi_addr * bia_addr)537 void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr)
538 {
539 int i ;
540
541 for (i = 0 ; i < 6 ; i++)
542 bia_addr->a[i] = bitrev8(smc->hw.fddi_phys_addr.a[i]);
543 }
544
smt_start_watchdog(struct s_smc * smc)545 void smt_start_watchdog(struct s_smc *smc)
546 {
547 SK_UNUSED(smc) ; /* Make LINT happy. */
548
549 #ifndef DEBUG
550
551 #ifdef PCI
552 if (smc->hw.wdog_used) {
553 outpw(ADDR(B2_WDOG_CRTL),TIM_START) ; /* Start timer. */
554 }
555 #endif
556
557 #endif /* DEBUG */
558 }
559
smt_stop_watchdog(struct s_smc * smc)560 static void smt_stop_watchdog(struct s_smc *smc)
561 {
562 SK_UNUSED(smc) ; /* Make LINT happy. */
563 #ifndef DEBUG
564
565 #ifdef PCI
566 if (smc->hw.wdog_used) {
567 outpw(ADDR(B2_WDOG_CRTL),TIM_STOP) ; /* Stop timer. */
568 }
569 #endif
570
571 #endif /* DEBUG */
572 }
573
574 #ifdef PCI
575
mac_do_pci_fix(struct s_smc * smc)576 void mac_do_pci_fix(struct s_smc *smc)
577 {
578 SK_UNUSED(smc) ;
579 }
580 #endif /* PCI */
581
582