Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / net / skfp / drvfbi.c
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  * FBI board dependent Driver for SMT and LLC
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 "h/skfbiinc.h"
26 #include <linux/bitrev.h>
27
28 #ifndef lint
29 static const char ID_sccs[] = "@(#)drvfbi.c     1.63 99/02/11 (C) SK " ;
30 #endif
31
32 /*
33  * PCM active state
34  */
35 #define PC8_ACTIVE      8
36
37 #define LED_Y_ON        0x11    /* Used for ring up/down indication */
38 #define LED_Y_OFF       0x10
39
40
41 #define MS2BCLK(x)      ((x)*12500L)
42
43 /*
44  * valid configuration values are:
45  */
46 #ifdef  ISA
47 const int opt_ints[] = {8,      3, 4, 5, 9, 10, 11, 12, 15} ;
48 const int opt_iops[] = {8,
49         0x100, 0x120, 0x180, 0x1a0, 0x220, 0x240, 0x320, 0x340};
50 const int opt_dmas[] = {4,      3, 5, 6, 7} ;
51 const int opt_eproms[] = {15,   0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce,
52                         0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc} ;
53 #endif
54 #ifdef  EISA
55 const int opt_ints[] = {5, 9, 10, 11} ;
56 const int opt_dmas[] = {0, 5, 6, 7} ;
57 const int opt_eproms[] = {0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce,
58                                 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc} ;
59 #endif
60
61 #ifdef  MCA
62 int     opt_ints[] = {3, 11, 10, 9} ;                   /* FM1 */
63 int     opt_eproms[] = {0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc} ;
64 #endif  /* MCA */
65
66 /*
67  *      xPOS_ID:xxxx
68  *      |       \  /
69  *      |        \/
70  *      |         --------------------- the patched POS_ID of the Adapter
71  *      |                               xxxx = (Vendor ID low byte,
72  *      |                                       Vendor ID high byte,
73  *      |                                       Device ID low byte,
74  *      |                                       Device ID high byte)
75  *      +------------------------------ the patched oem_id must be
76  *                                      'S' for SK or 'I' for IBM
77  *                                      this is a short id for the driver.
78  */
79 #ifndef MULT_OEM
80 #ifndef OEM_CONCEPT
81 #ifndef MCA
82 const u_char oem_id[] = "xPOS_ID:xxxx" ;
83 #else
84 const u_char oem_id[] = "xPOSID1:xxxx" ;        /* FM1 card id. */
85 #endif
86 #else   /* OEM_CONCEPT */
87 #ifndef MCA
88 const u_char oem_id[] = OEM_ID ;
89 #else
90 const u_char oem_id[] = OEM_ID1 ;       /* FM1 card id. */
91 #endif  /* MCA */
92 #endif  /* OEM_CONCEPT */
93 #define ID_BYTE0        8
94 #define OEMID(smc,i)    oem_id[ID_BYTE0 + i]
95 #else   /* MULT_OEM */
96 const struct s_oem_ids oem_ids[] = {
97 #include "oemids.h"
98 {0}
99 };
100 #define OEMID(smc,i)    smc->hw.oem_id->oi_id[i]
101 #endif  /* MULT_OEM */
102
103 /* Prototypes of external functions */
104 #ifdef AIX
105 extern int AIX_vpdReadByte() ;
106 #endif
107
108
109 /* Prototype of a local function. */
110 static void smt_stop_watchdog(struct s_smc *smc);
111
112 #ifdef MCA
113 static int read_card_id() ;
114 static void DisableSlotAccess() ;
115 static void EnableSlotAccess() ;
116 #ifdef AIX
117 extern int attach_POS_addr() ;
118 extern int detach_POS_addr() ;
119 extern u_char read_POS() ;
120 extern void write_POS() ;
121 extern int AIX_vpdReadByte() ;
122 #else
123 #define read_POS(smc,a1,a2)     ((u_char) inp(a1))
124 #define write_POS(smc,a1,a2,a3) outp((a1),(a3))
125 #endif
126 #endif  /* MCA */
127
128
129 /*
130  * FDDI card reset
131  */
132 static void card_start(struct s_smc *smc)
133 {
134         int i ;
135 #ifdef  PCI
136         u_char  rev_id ;
137         u_short word;
138 #endif
139
140         smt_stop_watchdog(smc) ;
141
142 #ifdef  ISA
143         outpw(CSR_A,0) ;                        /* reset for all chips */
144         for (i = 10 ; i ; i--)                  /* delay for PLC's */
145                 (void)inpw(ISR_A) ;
146         OUT_82c54_TIMER(3,COUNT(2) | RW_OP(3) | TMODE(2)) ;
147                                         /* counter 2, mode 2 */
148         OUT_82c54_TIMER(2,97) ;         /* LSB */
149         OUT_82c54_TIMER(2,0) ;          /* MSB ( 15.6 us ) */
150         outpw(CSR_A,CS_CRESET) ;
151 #endif
152 #ifdef  EISA
153         outpw(CSR_A,0) ;                        /* reset for all chips */
154         for (i = 10 ; i ; i--)                  /* delay for PLC's */
155                 (void)inpw(ISR_A) ;
156         outpw(CSR_A,CS_CRESET) ;
157         smc->hw.led = (2<<6) ;
158         outpw(CSR_A,CS_CRESET | smc->hw.led) ;
159 #endif
160 #ifdef  MCA
161         outp(ADDR(CARD_DIS),0) ;                /* reset for all chips */
162         for (i = 10 ; i ; i--)                  /* delay for PLC's */
163                 (void)inpw(ISR_A) ;
164         outp(ADDR(CARD_EN),0) ;
165         /* first I/O after reset must not be a access to FORMAC or PLC */
166
167         /*
168          * bus timeout (MCA)
169          */
170         OUT_82c54_TIMER(3,COUNT(2) | RW_OP(3) | TMODE(3)) ;
171                                         /* counter 2, mode 3 */
172         OUT_82c54_TIMER(2,(2*24)) ;     /* 3.9 us * 2 square wave */
173         OUT_82c54_TIMER(2,0) ;          /* MSB */
174
175         /* POS 102 indicated an activ Check Line or Buss Error monitoring */
176         if (inpw(CSA_A) & (POS_EN_CHKINT | POS_EN_BUS_ERR)) {
177                 outp(ADDR(IRQ_CHCK_EN),0) ;
178         }
179
180         if (!((i = inpw(CSR_A)) & CS_SAS)) {
181                 if (!(i & CS_BYSTAT)) {
182                         outp(ADDR(BYPASS(STAT_INS)),0) ;/* insert station */
183                 }
184         }
185         outpw(LEDR_A,LED_1) ;   /* yellow */
186 #endif  /* MCA */
187 #ifdef  PCI
188         /*
189          * make sure no transfer activity is pending
190          */
191         outpw(FM_A(FM_MDREG1),FM_MINIT) ;
192         outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
193         hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
194         /*
195          * now reset everything
196          */
197         outp(ADDR(B0_CTRL),CTRL_RST_SET) ;      /* reset for all chips */
198         i = (int) inp(ADDR(B0_CTRL)) ;          /* do dummy read */
199         SK_UNUSED(i) ;                          /* Make LINT happy. */
200         outp(ADDR(B0_CTRL), CTRL_RST_CLR) ;
201
202         /*
203          * Reset all bits in the PCI STATUS register
204          */
205         outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_ON) ;     /* enable for writes */
206         word = inpw(PCI_C(PCI_STATUS)) ;
207         outpw(PCI_C(PCI_STATUS), word | PCI_ERRBITS) ;
208         outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_OFF) ;    /* disable writes */
209
210         /*
211          * Release the reset of all the State machines
212          * Release Master_Reset
213          * Release HPI_SM_Reset
214          */
215         outp(ADDR(B0_CTRL), CTRL_MRST_CLR|CTRL_HPI_CLR) ;
216
217         /*
218          * determine the adapter type
219          * Note: Do it here, because some drivers may call card_start() once
220          *       at very first before any other initialization functions is
221          *       executed.
222          */
223         rev_id = inp(PCI_C(PCI_REV_ID)) ;
224         if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
225                 smc->hw.hw_is_64bit = TRUE ;
226         } else {
227                 smc->hw.hw_is_64bit = FALSE ;
228         }
229
230         /*
231          * Watermark initialization
232          */
233         if (!smc->hw.hw_is_64bit) {
234                 outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
235                 outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
236                 outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
237         }
238
239         outp(ADDR(B0_CTRL),CTRL_RST_CLR) ;      /* clear the reset chips */
240         outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_ON|LED_GB_OFF) ; /* ye LED on */
241
242         /* init the timer value for the watch dog 2,5 minutes */
243         outpd(ADDR(B2_WDOG_INI),0x6FC23AC0) ;
244
245         /* initialize the ISR mask */
246         smc->hw.is_imask = ISR_MASK ;
247         smc->hw.hw_state = STOPPED ;
248 #endif
249         GET_PAGE(0) ;           /* necessary for BOOT */
250 }
251
252 void card_stop(struct s_smc *smc)
253 {
254         smt_stop_watchdog(smc) ;
255         smc->hw.mac_ring_is_up = 0 ;            /* ring down */
256 #ifdef  ISA
257         outpw(CSR_A,0) ;                        /* reset for all chips */
258 #endif
259 #ifdef  EISA
260         outpw(CSR_A,0) ;                        /* reset for all chips */
261 #endif
262 #ifdef  MCA
263         outp(ADDR(CARD_DIS),0) ;                /* reset for all chips */
264 #endif
265 #ifdef  PCI
266         /*
267          * make sure no transfer activity is pending
268          */
269         outpw(FM_A(FM_MDREG1),FM_MINIT) ;
270         outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
271         hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
272         /*
273          * now reset everything
274          */
275         outp(ADDR(B0_CTRL),CTRL_RST_SET) ;      /* reset for all chips */
276         outp(ADDR(B0_CTRL),CTRL_RST_CLR) ;      /* reset for all chips */
277         outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_OFF|LED_GB_OFF) ; /* all LEDs off */
278         smc->hw.hw_state = STOPPED ;
279 #endif
280 }
281 /*--------------------------- ISR handling ----------------------------------*/
282
283 void mac1_irq(struct s_smc *smc, u_short stu, u_short stl)
284 {
285         int     restart_tx = 0 ;
286 again:
287 #ifndef PCI
288 #ifndef ISA
289 /*
290  * FORMAC+ bug modified the queue pointer if many read/write accesses happens!?
291  */
292         if (stl & (FM_SPCEPDS  |        /* parit/coding err. syn.q.*/
293                    FM_SPCEPDA0 |        /* parit/coding err. a.q.0 */
294                    FM_SPCEPDA1 |        /* parit/coding err. a.q.1 */
295                    FM_SPCEPDA2)) {      /* parit/coding err. a.q.2 */
296                 SMT_PANIC(smc,SMT_E0132, SMT_E0132_MSG) ;
297         }
298         if (stl & (FM_STBURS  | /* tx buffer underrun syn.q.*/
299                    FM_STBURA0 | /* tx buffer underrun a.q.0 */
300                    FM_STBURA1 | /* tx buffer underrun a.q.1 */
301                    FM_STBURA2)) {       /* tx buffer underrun a.q.2 */
302                 SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ;
303         }
304 #endif
305         if ( (stu & (FM_SXMTABT |               /* transmit abort */
306 #ifdef  SYNC
307                      FM_STXABRS |       /* syn. tx abort */
308 #endif  /* SYNC */
309                      FM_STXABRA0)) ||   /* asyn. tx abort */
310              (stl & (FM_SQLCKS |                /* lock for syn. q. */
311                      FM_SQLCKA0)) ) {   /* lock for asyn. q. */
312                 formac_tx_restart(smc) ;                /* init tx */
313                 restart_tx = 1 ;
314                 stu = inpw(FM_A(FM_ST1U)) ;
315                 stl = inpw(FM_A(FM_ST1L)) ;
316                 stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ;
317                 if (stu || stl)
318                         goto again ;
319         }
320
321 #ifndef SYNC
322         if (stu & (FM_STECFRMA0 | /* end of chain asyn tx */
323                    FM_STEFRMA0)) { /* end of frame asyn tx */
324                 /* free tx_queue */
325                 smc->hw.n_a_send = 0 ;
326                 if (++smc->hw.fp.tx_free < smc->hw.fp.tx_max) {
327                         start_next_send(smc);
328                 }
329                 restart_tx = 1 ;
330         }
331 #else   /* SYNC */
332         if (stu & (FM_STEFRMA0 |        /* end of asyn tx */
333                     FM_STEFRMS)) {      /* end of sync tx */
334                 restart_tx = 1 ;
335         }
336 #endif  /* SYNC */
337         if (restart_tx)
338                 llc_restart_tx(smc) ;
339 }
340 #else   /* PCI */
341
342         /*
343          * parity error: note encoding error is not possible in tag mode
344          */
345         if (stl & (FM_SPCEPDS  |        /* parity err. syn.q.*/
346                    FM_SPCEPDA0 |        /* parity err. a.q.0 */
347                    FM_SPCEPDA1)) {      /* parity err. a.q.1 */
348                 SMT_PANIC(smc,SMT_E0134, SMT_E0134_MSG) ;
349         }
350         /*
351          * buffer underrun: can only occur if a tx threshold is specified
352          */
353         if (stl & (FM_STBURS  |         /* tx buffer underrun syn.q.*/
354                    FM_STBURA0 |         /* tx buffer underrun a.q.0 */
355                    FM_STBURA1)) {       /* tx buffer underrun a.q.2 */
356                 SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ;
357         }
358
359         if ( (stu & (FM_SXMTABT |               /* transmit abort */
360                      FM_STXABRS |               /* syn. tx abort */
361                      FM_STXABRA0)) ||           /* asyn. tx abort */
362              (stl & (FM_SQLCKS |                /* lock for syn. q. */
363                      FM_SQLCKA0)) ) {           /* lock for asyn. q. */
364                 formac_tx_restart(smc) ;        /* init tx */
365                 restart_tx = 1 ;
366                 stu = inpw(FM_A(FM_ST1U)) ;
367                 stl = inpw(FM_A(FM_ST1L)) ;
368                 stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ;
369                 if (stu || stl)
370                         goto again ;
371         }
372
373         if (stu & (FM_STEFRMA0 |        /* end of asyn tx */
374                     FM_STEFRMS)) {      /* end of sync tx */
375                 restart_tx = 1 ;
376         }
377
378         if (restart_tx)
379                 llc_restart_tx(smc) ;
380 }
381 #endif  /* PCI */
382 /*
383  * interrupt source= plc1
384  * this function is called in nwfbisr.asm
385  */
386 void plc1_irq(struct s_smc *smc)
387 {
388         u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ;
389
390 #if     (defined(ISA) || defined(EISA))
391         /* reset PLC Int. bits */
392         outpw(PLC1_I,inpw(PLC1_I)) ;
393 #endif
394         plc_irq(smc,PB,st) ;
395 }
396
397 /*
398  * interrupt source= plc2
399  * this function is called in nwfbisr.asm
400  */
401 void plc2_irq(struct s_smc *smc)
402 {
403         u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ;
404
405 #if     (defined(ISA) || defined(EISA))
406         /* reset PLC Int. bits */
407         outpw(PLC2_I,inpw(PLC2_I)) ;
408 #endif
409         plc_irq(smc,PA,st) ;
410 }
411
412
413 /*
414  * interrupt source= timer
415  */
416 void timer_irq(struct s_smc *smc)
417 {
418         hwt_restart(smc);
419         smc->hw.t_stop = smc->hw.t_start;
420         smt_timer_done(smc) ;
421 }
422
423 /*
424  * return S-port (PA or PB)
425  */
426 int pcm_get_s_port(struct s_smc *smc)
427 {
428         SK_UNUSED(smc) ;
429         return(PS) ;
430 }
431
432 /*
433  * Station Label = "FDDI-XYZ" where
434  *
435  *      X = connector type
436  *      Y = PMD type
437  *      Z = port type
438  */
439 #define STATION_LABEL_CONNECTOR_OFFSET  5
440 #define STATION_LABEL_PMD_OFFSET        6
441 #define STATION_LABEL_PORT_OFFSET       7
442
443 void read_address(struct s_smc *smc, u_char *mac_addr)
444 {
445         char ConnectorType ;
446         char PmdType ;
447         int     i ;
448
449 #if     (defined(ISA) || defined(MCA))
450         for (i = 0; i < 4 ;i++) {       /* read mac address from board */
451                 smc->hw.fddi_phys_addr.a[i] =
452                         bitrev8(inpw(PR_A(i+SA_MAC)));
453         }
454         for (i = 4; i < 6; i++) {
455                 smc->hw.fddi_phys_addr.a[i] =
456                         bitrev8(inpw(PR_A(i+SA_MAC+PRA_OFF)));
457         }
458 #endif
459 #ifdef  EISA
460         /*
461          * Note: We get trouble on an Alpha machine if we make a inpw()
462          * instead of inp()
463          */
464         for (i = 0; i < 4 ;i++) {       /* read mac address from board */
465                 smc->hw.fddi_phys_addr.a[i] =
466                         bitrev8(inp(PR_A(i+SA_MAC)));
467         }
468         for (i = 4; i < 6; i++) {
469                 smc->hw.fddi_phys_addr.a[i] =
470                         bitrev8(inp(PR_A(i+SA_MAC+PRA_OFF)));
471         }
472 #endif
473 #ifdef  PCI
474         for (i = 0; i < 6; i++) {       /* read mac address from board */
475                 smc->hw.fddi_phys_addr.a[i] =
476                         bitrev8(inp(ADDR(B2_MAC_0+i)));
477         }
478 #endif
479 #ifndef PCI
480         ConnectorType = inpw(PR_A(SA_PMD_TYPE)) & 0xff ;
481         PmdType = inpw(PR_A(SA_PMD_TYPE+1)) & 0xff ;
482 #else
483         ConnectorType = inp(ADDR(B2_CONN_TYP)) ;
484         PmdType = inp(ADDR(B2_PMD_TYP)) ;
485 #endif
486
487         smc->y[PA].pmd_type[PMD_SK_CONN] =
488         smc->y[PB].pmd_type[PMD_SK_CONN] = ConnectorType ;
489         smc->y[PA].pmd_type[PMD_SK_PMD ] =
490         smc->y[PB].pmd_type[PMD_SK_PMD ] = PmdType ;
491
492         if (mac_addr) {
493                 for (i = 0; i < 6 ;i++) {
494                         smc->hw.fddi_canon_addr.a[i] = mac_addr[i] ;
495                         smc->hw.fddi_home_addr.a[i] = bitrev8(mac_addr[i]);
496                 }
497                 return ;
498         }
499         smc->hw.fddi_home_addr = smc->hw.fddi_phys_addr ;
500
501         for (i = 0; i < 6 ;i++) {
502                 smc->hw.fddi_canon_addr.a[i] =
503                         bitrev8(smc->hw.fddi_phys_addr.a[i]);
504         }
505 }
506
507 /*
508  * FDDI card soft reset
509  */
510 void init_board(struct s_smc *smc, u_char *mac_addr)
511 {
512         card_start(smc) ;
513         read_address(smc,mac_addr) ;
514
515 #ifndef PCI
516         if (inpw(CSR_A) & CS_SAS)
517 #else
518         if (!(inp(ADDR(B0_DAS)) & DAS_AVAIL))
519 #endif
520                 smc->s.sas = SMT_SAS ;  /* Single att. station */
521         else
522                 smc->s.sas = SMT_DAS ;  /* Dual att. station */
523
524 #ifndef PCI
525         if (inpw(CSR_A) & CS_BYSTAT)
526 #else
527         if (!(inp(ADDR(B0_DAS)) & DAS_BYP_ST))
528 #endif
529                 smc->mib.fddiSMTBypassPresent = 0 ;
530                 /* without opt. bypass */
531         else
532                 smc->mib.fddiSMTBypassPresent = 1 ;
533                 /* with opt. bypass */
534 }
535
536 /*
537  * insert or deinsert optical bypass (called by ECM)
538  */
539 void sm_pm_bypass_req(struct s_smc *smc, int mode)
540 {
541 #if     (defined(ISA) || defined(EISA))
542         int csra_v ;
543 #endif
544
545         DB_ECMN(1,"ECM : sm_pm_bypass_req(%s)\n",(mode == BP_INSERT) ?
546                                         "BP_INSERT" : "BP_DEINSERT",0) ;
547
548         if (smc->s.sas != SMT_DAS)
549                 return ;
550
551 #if     (defined(ISA) || defined(EISA))
552
553         csra_v = inpw(CSR_A) & ~CS_BYPASS ;
554 #ifdef  EISA
555         csra_v |= smc->hw.led ;
556 #endif
557
558         switch(mode) {
559         case BP_INSERT :
560                 outpw(CSR_A,csra_v | CS_BYPASS) ;
561                 break ;
562         case BP_DEINSERT :
563                 outpw(CSR_A,csra_v) ;
564                 break ;
565         }
566 #endif  /* ISA / EISA */
567 #ifdef  MCA
568         switch(mode) {
569         case BP_INSERT :
570                 outp(ADDR(BYPASS(STAT_INS)),0) ;/* insert station */
571                 break ;
572         case BP_DEINSERT :
573                 outp(ADDR(BYPASS(STAT_BYP)),0) ;        /* bypass station */
574                 break ;
575         }
576 #endif
577 #ifdef  PCI
578         switch(mode) {
579         case BP_INSERT :
580                 outp(ADDR(B0_DAS),DAS_BYP_INS) ;        /* insert station */
581                 break ;
582         case BP_DEINSERT :
583                 outp(ADDR(B0_DAS),DAS_BYP_RMV) ;        /* bypass station */
584                 break ;
585         }
586 #endif
587 }
588
589 /*
590  * check if bypass connected
591  */
592 int sm_pm_bypass_present(struct s_smc *smc)
593 {
594 #ifndef PCI
595         return( (inpw(CSR_A) & CS_BYSTAT) ? FALSE : TRUE ) ;
596 #else
597         return( (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE: FALSE) ;
598 #endif
599 }
600
601 void plc_clear_irq(struct s_smc *smc, int p)
602 {
603         SK_UNUSED(p) ;
604
605 #if     (defined(ISA) || defined(EISA))
606         switch (p) {
607         case PA :
608                 /* reset PLC Int. bits */
609                 outpw(PLC2_I,inpw(PLC2_I)) ;
610                 break ;
611         case PB :
612                 /* reset PLC Int. bits */
613                 outpw(PLC1_I,inpw(PLC1_I)) ;
614                 break ;
615         }
616 #else
617         SK_UNUSED(smc) ;
618 #endif
619 }
620
621
622 /*
623  * led_indication called by rmt_indication() and
624  * pcm_state_change()
625  *
626  * Input:
627  *      smc:    SMT context
628  *      led_event:
629  *      0       Only switch green LEDs according to their respective PCM state
630  *      LED_Y_OFF       just switch yellow LED off
631  *      LED_Y_ON        just switch yello LED on
632  */
633 static void led_indication(struct s_smc *smc, int led_event)
634 {
635         /* use smc->hw.mac_ring_is_up == TRUE 
636          * as indication for Ring Operational
637          */
638         u_short                 led_state ;
639         struct s_phy            *phy ;
640         struct fddi_mib_p       *mib_a ;
641         struct fddi_mib_p       *mib_b ;
642
643         phy = &smc->y[PA] ;
644         mib_a = phy->mib ;
645         phy = &smc->y[PB] ;
646         mib_b = phy->mib ;
647
648 #ifdef  EISA
649         /* Ring up = yellow led OFF*/
650         if (led_event == LED_Y_ON) {
651                 smc->hw.led |= CS_LED_1 ;
652         }
653         else if (led_event == LED_Y_OFF) {
654                 smc->hw.led &= ~CS_LED_1 ;
655         }
656         else {
657                 /* Link at Port A or B = green led ON */
658                 if (mib_a->fddiPORTPCMState == PC8_ACTIVE ||
659                     mib_b->fddiPORTPCMState == PC8_ACTIVE) {
660                         smc->hw.led |= CS_LED_0 ;
661                 }
662                 else {
663                         smc->hw.led &= ~CS_LED_0 ;
664                 }
665         }
666 #endif
667 #ifdef  MCA
668         led_state = inpw(LEDR_A) ;
669         
670         /* Ring up = yellow led OFF*/
671         if (led_event == LED_Y_ON) {
672                 led_state |= LED_1 ;
673         }
674         else if (led_event == LED_Y_OFF) {
675                 led_state &= ~LED_1 ;
676         }
677         else {
678                 led_state &= ~(LED_2|LED_0) ;
679
680                 /* Link at Port A = green led A ON */
681                 if (mib_a->fddiPORTPCMState == PC8_ACTIVE) {    
682                         led_state |= LED_2 ;
683                 }
684                 
685                 /* Link at Port B/S = green led B ON */
686                 if (mib_b->fddiPORTPCMState == PC8_ACTIVE) {
687                         led_state |= LED_0 ;
688                 }
689         }
690
691         outpw(LEDR_A, led_state) ;
692 #endif  /* MCA */
693 #ifdef  PCI
694         led_state = 0 ;
695         
696         /* Ring up = yellow led OFF*/
697         if (led_event == LED_Y_ON) {
698                 led_state |= LED_MY_ON ;
699         }
700         else if (led_event == LED_Y_OFF) {
701                 led_state |= LED_MY_OFF ;
702         }
703         else {  /* PCM state changed */
704                 /* Link at Port A/S = green led A ON */
705                 if (mib_a->fddiPORTPCMState == PC8_ACTIVE) {    
706                         led_state |= LED_GA_ON ;
707                 }
708                 else {
709                         led_state |= LED_GA_OFF ;
710                 }
711                 
712                 /* Link at Port B = green led B ON */
713                 if (mib_b->fddiPORTPCMState == PC8_ACTIVE) {
714                         led_state |= LED_GB_ON ;
715                 }
716                 else {
717                         led_state |= LED_GB_OFF ;
718                 }
719         }
720
721         outp(ADDR(B0_LED), led_state) ;
722 #endif  /* PCI */
723
724 }
725
726
727 void pcm_state_change(struct s_smc *smc, int plc, int p_state)
728 {
729         /*
730          * the current implementation of pcm_state_change() in the driver
731          * parts must be renamed to drv_pcm_state_change() which will be called
732          * now after led_indication.
733          */
734         DRV_PCM_STATE_CHANGE(smc,plc,p_state) ;
735         
736         led_indication(smc,0) ;
737 }
738
739
740 void rmt_indication(struct s_smc *smc, int i)
741 {
742         /* Call a driver special function if defined */
743         DRV_RMT_INDICATION(smc,i) ;
744
745         led_indication(smc, i ? LED_Y_OFF : LED_Y_ON) ;
746 }
747
748
749 /*
750  * llc_recover_tx called by init_tx (fplus.c)
751  */
752 void llc_recover_tx(struct s_smc *smc)
753 {
754 #ifdef  LOAD_GEN
755         extern  int load_gen_flag ;
756
757         load_gen_flag = 0 ;
758 #endif
759 #ifndef SYNC
760         smc->hw.n_a_send= 0 ;
761 #else
762         SK_UNUSED(smc) ;
763 #endif
764 }
765
766 #ifdef MULT_OEM
767 static int is_equal_num(char comp1[], char comp2[], int num)
768 {
769         int i ;
770
771         for (i = 0 ; i < num ; i++) {
772                 if (comp1[i] != comp2[i])
773                         return (0) ;
774         }
775                 return (1) ;
776 }       /* is_equal_num */
777
778
779 /*
780  * set the OEM ID defaults, and test the contents of the OEM data base
781  * The default OEM is the first ACTIVE entry in the OEM data base 
782  *
783  * returns:     0       success
784  *              1       error in data base
785  *              2       data base empty
786  *              3       no active entry 
787  */
788 int set_oi_id_def(struct s_smc *smc)
789 {
790         int sel_id ;
791         int i ;
792         int act_entries ;
793
794         i = 0 ;
795         sel_id = -1 ;
796         act_entries = FALSE ;
797         smc->hw.oem_id = 0 ;
798         smc->hw.oem_min_status = OI_STAT_ACTIVE ;
799         
800         /* check OEM data base */
801         while (oem_ids[i].oi_status) {
802                 switch (oem_ids[i].oi_status) {
803                 case OI_STAT_ACTIVE:
804                         act_entries = TRUE ;    /* we have active IDs */
805                         if (sel_id == -1)
806                                 sel_id = i ;    /* save the first active ID */
807                 case OI_STAT_VALID:
808                 case OI_STAT_PRESENT:
809                         i++ ;
810                         break ;                 /* entry ok */
811                 default:
812                         return (1) ;            /* invalid oi_status */
813                 }
814         }
815
816         if (i == 0)
817                 return (2) ;
818         if (!act_entries)
819                 return (3) ;
820
821         /* ok, we have a valid OEM data base with an active entry */
822         smc->hw.oem_id = (struct s_oem_ids *)  &oem_ids[sel_id] ;
823         return (0) ;
824 }
825 #endif  /* MULT_OEM */
826
827
828 #ifdef  MCA
829 /************************
830  *
831  * BEGIN_MANUAL_ENTRY()
832  *
833  *      exist_board
834  *
835  *      Check if an MCA board is present in the specified slot.
836  *
837  *      int exist_board(
838  *              struct s_smc *smc,
839  *              int slot) ;
840  * In
841  *      smc - A pointer to the SMT Context struct.
842  *
843  *      slot - The number of the slot to inspect.
844  * Out
845  *      0 = No adapter present.
846  *      1 = Found FM1 adapter.
847  *
848  * Pseudo
849  *      Read MCA ID
850  *      for all valid OEM_IDs
851  *              compare with ID read
852  *              if equal, return 1
853  *      return(0
854  *
855  * Note
856  *      The smc pointer must be valid now.
857  *
858  * END_MANUAL_ENTRY()
859  *
860  ************************/
861 #define LONG_CARD_ID(lo, hi)    ((((hi) & 0xff) << 8) | ((lo) & 0xff))
862 int exist_board(struct s_smc *smc, int slot)
863 {
864 #ifdef MULT_OEM
865         SK_LOC_DECL(u_char,id[2]) ;
866         int idi ;
867 #endif  /* MULT_OEM */
868
869         /* No longer valid. */
870         if (smc == NULL)
871                 return(0) ;
872
873 #ifndef MULT_OEM
874         if (read_card_id(smc, slot)
875                 == LONG_CARD_ID(OEMID(smc,0), OEMID(smc,1)))
876                 return (1) ;    /* Found FM adapter. */
877
878 #else   /* MULT_OEM */
879         idi = read_card_id(smc, slot) ;
880         id[0] = idi & 0xff ;
881         id[1] = idi >> 8 ;
882
883         smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[0] ;
884         for (; smc->hw.oem_id->oi_status != OI_STAT_LAST; smc->hw.oem_id++) {
885                 if (smc->hw.oem_id->oi_status < smc->hw.oem_min_status)
886                         continue ;
887
888                 if (is_equal_num(&id[0],&OEMID(smc,0),2))
889                         return (1) ;
890         }
891 #endif  /* MULT_OEM */
892         return (0) ;    /* No adapter found. */
893 }
894
895 /************************
896  *
897  *      read_card_id
898  *
899  *      Read the MCA card id from the specified slot.
900  * In
901  *      smc - A pointer to the SMT Context struct.
902  *      CAVEAT: This pointer may be NULL and *must not* be used within this
903  *      function. It's only purpose is for drivers that need some information
904  *      for the inp() and outp() macros.
905  *
906  *      slot - The number of the slot for which the card id is returned.
907  * Out
908  *      Returns the card id read from the specified slot. If an illegal slot
909  *      number is specified, the function returns zero.
910  *
911  ************************/
912 static int read_card_id(struct s_smc *smc, int slot)
913 /* struct s_smc *smc ;  Do not use. */
914 {
915         int card_id ;
916
917         SK_UNUSED(smc) ;        /* Make LINT happy. */
918         if ((slot < 1) || (slot > 15))  /* max 16 slots, 0 = motherboard */
919                 return (0) ;    /* Illegal slot number specified. */
920
921         EnableSlotAccess(smc, slot) ;
922
923         card_id = ((read_POS(smc,POS_ID_HIGH,slot - 1) & 0xff) << 8) |
924                                 (read_POS(smc,POS_ID_LOW,slot - 1) & 0xff) ;
925
926         DisableSlotAccess(smc) ;
927
928         return (card_id) ;
929 }
930
931 /************************
932  *
933  * BEGIN_MANUAL_ENTRY()
934  *
935  *      get_board_para
936  *
937  *      Get adapter configuration information. Fill all board specific
938  *      parameters within the 'smc' structure.
939  *
940  *      int get_board_para(
941  *              struct s_smc *smc,
942  *              int slot) ;
943  * In
944  *      smc - A pointer to the SMT Context struct, to which this function will
945  *      write some adapter configuration data.
946  *
947  *      slot - The number of the slot, in which the adapter is installed.
948  * Out
949  *      0 = No adapter present.
950  *      1 = Ok.
951  *      2 = Adapter present, but card enable bit not set.
952  *
953  * END_MANUAL_ENTRY()
954  *
955  ************************/
956 int get_board_para(struct s_smc *smc, int slot)
957 {
958         int val ;
959         int i ;
960
961         /* Check if adapter present & get type of adapter. */
962         switch (exist_board(smc, slot)) {
963         case 0: /* Adapter not present. */
964                 return (0) ;
965         case 1: /* FM Rev. 1 */
966                 smc->hw.rev = FM1_REV ;
967                 smc->hw.VFullRead = 0x0a ;
968                 smc->hw.VFullWrite = 0x05 ;
969                 smc->hw.DmaWriteExtraBytes = 8 ;        /* 2 extra words. */
970                 break ;
971         }
972         smc->hw.slot = slot ;
973
974         EnableSlotAccess(smc, slot) ;
975
976         if (!(read_POS(smc,POS_102, slot - 1) & POS_CARD_EN)) {
977                 DisableSlotAccess(smc) ;
978                 return (2) ;    /* Card enable bit not set. */
979         }
980
981         val = read_POS(smc,POS_104, slot - 1) ; /* I/O, IRQ */
982
983 #ifndef MEM_MAPPED_IO   /* is defined by the operating system */
984         i = val & POS_IOSEL ;   /* I/O base addr. (0x0200 .. 0xfe00) */
985         smc->hw.iop = (i + 1) * 0x0400 - 0x200 ;
986 #endif
987         i = ((val & POS_IRQSEL) >> 6) & 0x03 ;  /* IRQ <0, 1> */
988         smc->hw.irq = opt_ints[i] ;
989
990         /* FPROM base addr. */
991         i = ((read_POS(smc,POS_103, slot - 1) & POS_MSEL) >> 4) & 0x07 ;
992         smc->hw.eprom = opt_eproms[i] ;
993
994         DisableSlotAccess(smc) ;
995
996         /* before this, the smc->hw.iop must be set !!! */
997         smc->hw.slot_32 = inpw(CSF_A) & SLOT_32 ;
998
999         return (1) ;
1000 }
1001
1002 /* Enable access to specified MCA slot. */
1003 static void EnableSlotAccess(struct s_smc *smc, int slot)
1004 {
1005         SK_UNUSED(slot) ;
1006
1007 #ifndef AIX
1008         SK_UNUSED(smc) ;
1009
1010         /* System mode. */
1011         outp(POS_SYS_SETUP, POS_SYSTEM) ;
1012
1013         /* Select slot. */
1014         outp(POS_CHANNEL_POS, POS_CHANNEL_BIT | (slot-1)) ;
1015 #else
1016         attach_POS_addr (smc) ;
1017 #endif
1018 }
1019
1020 /* Disable access to MCA slot formerly enabled via EnableSlotAccess(). */
1021 static void DisableSlotAccess(struct s_smc *smc)
1022 {
1023 #ifndef AIX
1024         SK_UNUSED(smc) ;
1025
1026         outp(POS_CHANNEL_POS, 0) ;
1027 #else
1028         detach_POS_addr (smc) ;
1029 #endif
1030 }
1031 #endif  /* MCA */
1032
1033 #ifdef  EISA
1034 #ifndef MEM_MAPPED_IO
1035 #define SADDR(slot)     (((slot)<<12)&0xf000)
1036 #else   /* MEM_MAPPED_IO */
1037 #define SADDR(slot)     (smc->hw.iop)
1038 #endif  /* MEM_MAPPED_IO */
1039
1040 /************************
1041  *
1042  * BEGIN_MANUAL_ENTRY()
1043  *
1044  *      exist_board
1045  *
1046  *      Check if an EISA board is present in the specified slot.
1047  *
1048  *      int exist_board(
1049  *              struct s_smc *smc,
1050  *              int slot) ;
1051  * In
1052  *      smc - A pointer to the SMT Context struct.
1053  *
1054  *      slot - The number of the slot to inspect.
1055  * Out
1056  *      0 = No adapter present.
1057  *      1 = Found adapter.
1058  *
1059  * Pseudo
1060  *      Read EISA ID
1061  *      for all valid OEM_IDs
1062  *              compare with ID read
1063  *              if equal, return 1
1064  *      return(0
1065  *
1066  * Note
1067  *      The smc pointer must be valid now.
1068  *
1069  ************************/
1070 int exist_board(struct s_smc *smc, int slot)
1071 {
1072         int i ;
1073 #ifdef MULT_OEM
1074         SK_LOC_DECL(u_char,id[4]) ;
1075 #endif  /* MULT_OEM */
1076
1077         /* No longer valid. */
1078         if (smc == NULL)
1079                 return(0);
1080
1081         SK_UNUSED(slot) ;
1082
1083 #ifndef MULT_OEM
1084         for (i = 0 ; i < 4 ; i++) {
1085                 if (inp(SADDR(slot)+PRA(i)) != OEMID(smc,i))
1086                         return(0) ;
1087         }
1088         return(1) ;
1089 #else   /* MULT_OEM */
1090         for (i = 0 ; i < 4 ; i++)
1091                 id[i] = inp(SADDR(slot)+PRA(i)) ;
1092
1093         smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[0] ;
1094
1095         for (; smc->hw.oem_id->oi_status != OI_STAT_LAST; smc->hw.oem_id++) {
1096                 if (smc->hw.oem_id->oi_status < smc->hw.oem_min_status)
1097                         continue ;
1098
1099                 if (is_equal_num(&id[0],&OEMID(smc,0),4))
1100                         return (1) ;
1101         }
1102         return (0) ;    /* No adapter found. */
1103 #endif  /* MULT_OEM */
1104 }
1105
1106
1107 int get_board_para(struct s_smc *smc, int slot)
1108 {
1109         int     i ;
1110
1111         if (!exist_board(smc,slot))
1112                 return(0) ;
1113
1114         smc->hw.slot = slot ;
1115 #ifndef MEM_MAPPED_IO           /* if defined by the operating system */
1116         smc->hw.iop = SADDR(slot) ;
1117 #endif
1118
1119         if (!(inp(C0_A(0))&CFG_CARD_EN)) {
1120                 return(2) ;                     /* CFG_CARD_EN bit not set! */
1121         }
1122
1123         smc->hw.irq = opt_ints[(inp(C1_A(0)) & CFG_IRQ_SEL)] ;
1124         smc->hw.dma = opt_dmas[((inp(C1_A(0)) & CFG_DRQ_SEL)>>3)] ;
1125
1126         if ((i = inp(C2_A(0)) & CFG_EPROM_SEL) != 0x0f)
1127                 smc->hw.eprom = opt_eproms[i] ;
1128         else
1129                 smc->hw.eprom = 0 ;
1130
1131         smc->hw.DmaWriteExtraBytes = 8 ;
1132
1133         return(1) ;
1134 }
1135 #endif  /* EISA */
1136
1137 #ifdef  ISA
1138 #ifndef MULT_OEM
1139 const u_char sklogo[6] = SKLOGO_STR ;
1140 #define SIZE_SKLOGO(smc)        sizeof(sklogo)
1141 #define SKLOGO(smc,i)           sklogo[i]
1142 #else   /* MULT_OEM */
1143 #define SIZE_SKLOGO(smc)        smc->hw.oem_id->oi_logo_len
1144 #define SKLOGO(smc,i)           smc->hw.oem_id->oi_logo[i]
1145 #endif  /* MULT_OEM */
1146
1147
1148 int exist_board(struct s_smc *smc, HW_PTR port)
1149 {
1150         int     i ;
1151 #ifdef MULT_OEM
1152         int     bytes_read ;
1153         u_char  board_logo[15] ;
1154         SK_LOC_DECL(u_char,id[4]) ;
1155 #endif  /* MULT_OEM */
1156
1157         /* No longer valid. */
1158         if (smc == NULL)
1159                 return(0);
1160
1161         SK_UNUSED(smc) ;
1162 #ifndef MULT_OEM
1163         for (i = SADDRL ; i < (signed) (SADDRL+SIZE_SKLOGO(smc)) ; i++) {
1164                 if ((u_char)inpw((PRA(i)+port)) != SKLOGO(smc,i-SADDRL)) {
1165                         return(0) ;
1166                 }
1167         }
1168
1169         /* check MAC address (S&K or other) */
1170         for (i = 0 ; i < 3 ; i++) {
1171                 if ((u_char)inpw((PRA(i)+port)) != OEMID(smc,i))
1172                         return(0) ;
1173         }
1174         return(1) ;
1175 #else   /* MULT_OEM */
1176         smc->hw.oem_id = (struct s_oem_ids *)  &oem_ids[0] ;
1177         board_logo[0] = (u_char)inpw((PRA(SADDRL)+port)) ;
1178         bytes_read = 1 ;
1179
1180         for (; smc->hw.oem_id->oi_status != OI_STAT_LAST; smc->hw.oem_id++) {
1181                 if (smc->hw.oem_id->oi_status < smc->hw.oem_min_status)
1182                         continue ;
1183
1184                 /* Test all read bytes with current OEM_entry */
1185                 /* for (i=0; (i<bytes_read) && (i < SIZE_SKLOGO(smc)); i++) { */
1186                 for (i = 0; i < bytes_read; i++) {
1187                         if (board_logo[i] != SKLOGO(smc,i))
1188                                 break ;
1189                 }
1190
1191                 /* If mismatch, switch to next OEM entry */
1192                 if ((board_logo[i] != SKLOGO(smc,i)) && (i < bytes_read))
1193                         continue ;
1194
1195                 --i ;
1196                 while (bytes_read < SIZE_SKLOGO(smc)) {
1197                         //   inpw next byte SK_Logo
1198                         i++ ;
1199                         board_logo[i] = (u_char)inpw((PRA(SADDRL+i)+port)) ;
1200                         bytes_read++ ;
1201                         if (board_logo[i] != SKLOGO(smc,i))
1202                                 break ;
1203                 }
1204
1205                 for (i = 0 ; i < 3 ; i++)
1206                         id[i] = (u_char)inpw((PRA(i)+port)) ;
1207
1208                 if ((board_logo[i] == SKLOGO(smc,i))
1209                         && (bytes_read == SIZE_SKLOGO(smc))) {
1210
1211                         if (is_equal_num(&id[0],&OEMID(smc,0),3))
1212                                 return(1);
1213                 }
1214         }       /* for */
1215         return(0) ;
1216 #endif  /* MULT_OEM */
1217 }
1218
1219 int get_board_para(struct s_smc *smc, int slot)
1220 {
1221         SK_UNUSED(smc) ;
1222         SK_UNUSED(slot) ;
1223         return(0) ;     /* for ISA not supported */
1224 }
1225 #endif  /* ISA */
1226
1227 #ifdef PCI
1228 #ifdef USE_BIOS_FUN
1229 int exist_board(struct s_smc *smc, int slot)
1230 {
1231         u_short dev_id ;
1232         u_short ven_id ;
1233         int found ; 
1234         int i ;
1235
1236         found = FALSE ;         /* make sure we returned with adatper not found*/
1237                                 /* if an empty oemids.h was included */
1238
1239 #ifdef MULT_OEM
1240         smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[0] ;
1241         for (; smc->hw.oem_id->oi_status != OI_STAT_LAST; smc->hw.oem_id++) {
1242                 if (smc->hw.oem_id->oi_status < smc->hw.oem_min_status)
1243                         continue ;
1244 #endif
1245                 ven_id = OEMID(smc,0) + (OEMID(smc,1) << 8) ; 
1246                 dev_id = OEMID(smc,2) + (OEMID(smc,3) << 8) ; 
1247                 for (i = 0; i < slot; i++) {
1248                         if (pci_find_device(i,&smc->hw.pci_handle,
1249                                 dev_id,ven_id) != 0) {
1250
1251                                 found = FALSE ;
1252                         } else {
1253                                 found = TRUE ;
1254                         }
1255                 }
1256                 if (found) {
1257                         return(1) ;     /* adapter was found */
1258                 }
1259 #ifdef MULT_OEM
1260         }
1261 #endif
1262         return(0) ;     /* adapter was not found */
1263 }
1264 #endif  /* PCI */
1265 #endif  /* USE_BIOS_FUNC */
1266
1267 void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr)
1268 {
1269         int i ;
1270
1271         for (i = 0 ; i < 6 ; i++)
1272                 bia_addr->a[i] = bitrev8(smc->hw.fddi_phys_addr.a[i]);
1273 }
1274
1275 void smt_start_watchdog(struct s_smc *smc)
1276 {
1277         SK_UNUSED(smc) ;        /* Make LINT happy. */
1278
1279 #ifndef DEBUG
1280
1281 #ifdef  PCI
1282         if (smc->hw.wdog_used) {
1283                 outpw(ADDR(B2_WDOG_CRTL),TIM_START) ;   /* Start timer. */
1284         }
1285 #endif
1286
1287 #endif  /* DEBUG */
1288 }
1289
1290 static void smt_stop_watchdog(struct s_smc *smc)
1291 {
1292         SK_UNUSED(smc) ;        /* Make LINT happy. */
1293 #ifndef DEBUG
1294
1295 #ifdef  PCI
1296         if (smc->hw.wdog_used) {
1297                 outpw(ADDR(B2_WDOG_CRTL),TIM_STOP) ;    /* Stop timer. */
1298         }
1299 #endif
1300
1301 #endif  /* DEBUG */
1302 }
1303
1304 #ifdef  PCI
1305
1306 void mac_do_pci_fix(struct s_smc *smc)
1307 {
1308         SK_UNUSED(smc) ;
1309 }
1310 #endif  /* PCI */
1311