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