1 /* $NetBSD: if_lmc_media.c,v 1.15 2003/02/22 04:57:49 tsutsui Exp $ */
2
3 /*-
4 * Copyright (c) 1997-1999 LAN Media Corporation (LMC)
5 * All rights reserved. www.lanmedia.com
6 *
7 * This code is written by Michael Graff <graff@vix.com> for LMC.
8 * The code is derived from permitted modifications to software created
9 * by Matt Thomas (matt@3am-software.com).
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following disclaimer
18 * in the documentation and/or other materials provided with the
19 * distribution.
20 * 3. All marketing or advertising materials mentioning features or
21 * use of this software must display the following acknowledgement:
22 * This product includes software developed by LAN Media Corporation
23 * and its contributors.
24 * 4. Neither the name of LAN Media Corporation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY LAN MEDIA CORPORATION AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
38 * THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: if_lmc_media.c,v 1.15 2003/02/22 04:57:49 tsutsui Exp $");
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/mbuf.h>
47 #include <sys/socket.h>
48 #include <sys/ioctl.h>
49 #include <sys/errno.h>
50 #include <sys/malloc.h>
51 #include <sys/kernel.h>
52 #include <sys/proc.h> /* only for declaration of wakeup() used by vm.h */
53 #if defined(__FreeBSD__)
54 #include <machine/clock.h>
55 #elif defined(__bsdi__) || defined(__NetBSD__)
56 #include <sys/device.h>
57 #endif
58
59 #if defined(__NetBSD__)
60 #include <dev/pci/pcidevs.h>
61 #include "rnd.h"
62 #if NRND > 0
63 #include <sys/rnd.h>
64 #endif
65 #endif
66
67 #include <net/if.h>
68 #include <net/if_types.h>
69 #include <net/if_dl.h>
70 #include <net/netisr.h>
71
72 #include "bpfilter.h"
73 #if NBPFILTER > 0
74 #include <net/bpf.h>
75 #include <net/bpfdesc.h>
76 #endif
77
78 #if defined(__FreeBSD__)
79 #include <net/if_sppp.h>
80 #elif defined(__NetBSD__)
81 #include <net/if_spppvar.h>
82 #endif
83
84 #if defined(__bsdi__)
85 #if INET
86 #include <netinet/in.h>
87 #include <netinet/in_systm.h>
88 #include <netinet/ip.h>
89 #endif
90
91 #include <net/netisr.h>
92 #include <net/if.h>
93 #include <net/netisr.h>
94 #include <net/if_types.h>
95 #include <net/if_p2p.h>
96 #include <net/if_c_hdlc.h>
97 #endif
98
99 #if defined(__FreeBSD__)
100 #include <vm/vm.h>
101 #include <vm/pmap.h>
102 #include <pci.h>
103 #if NPCI > 0
104 #include <pci/pcivar.h>
105 #include <pci/dc21040reg.h>
106 #endif
107 #endif /* __FreeBSD__ */
108
109 #if defined(__bsdi__)
110 #include <vm/vm.h>
111 #include <i386/pci/ic/dc21040.h>
112 #include <i386/isa/isa.h>
113 #include <i386/isa/icu.h>
114 #include <i386/isa/dma.h>
115 #include <i386/isa/isavar.h>
116 #include <i386/pci/pci.h>
117
118 #endif /* __bsdi__ */
119
120 #if defined(__NetBSD__)
121 #include <machine/bus.h>
122 #if defined(__alpha__)
123 #include <machine/intr.h>
124 #endif
125 #include <dev/pci/pcireg.h>
126 #include <dev/pci/pcivar.h>
127 #include <dev/ic/dc21040reg.h>
128 #endif /* __NetBSD__ */
129
130 /*
131 * Sigh. Every OS puts these in different places.
132 */
133 #if defined(__NetBSD__)
134 #include <dev/pci/if_lmc_types.h>
135 #include <dev/pci/if_lmcioctl.h>
136 #include <dev/pci/if_lmcvar.h>
137 #elif defined(__FreeBSD__)
138 #include "pci/if_lmc_types.h"
139 #include "pci/if_lmcioctl.h"
140 #include "pci/if_lmcvar.h"
141 #else /* BSDI */
142 #include "i386/pci/if_lmctypes.h"
143 #include "i386/pci/if_lmcioctl.h"
144 #include "i386/pci/if_lmcvar.h"
145 #endif
146
147 /*
148 * For lack of a better place, put the T1 cable stuff here.
149 */
150 char *lmc_t1_cables[] = {
151 "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
152 "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL
153 };
154
155 /*
156 * protocol independent method.
157 */
158 static void lmc_set_protocol(lmc_softc_t * const, lmc_ctl_t *);
159
160 /*
161 * media independent methods to check on media status, link, light LEDs,
162 * etc.
163 */
164 static void lmc_ds3_init(lmc_softc_t * const);
165 static void lmc_ds3_default(lmc_softc_t * const);
166 static void lmc_ds3_set_status(lmc_softc_t * const, lmc_ctl_t *);
167 static void lmc_ds3_set_100ft(lmc_softc_t * const, int);
168 static int lmc_ds3_get_link_status(lmc_softc_t * const);
169 static void lmc_ds3_set_crc_length(lmc_softc_t * const, int);
170 static void lmc_ds3_set_scram(lmc_softc_t * const, int);
171 static void lmc_ds3_watchdog(lmc_softc_t * const);
172
173 static void lmc_hssi_init(lmc_softc_t * const);
174 static void lmc_hssi_default(lmc_softc_t * const);
175 static void lmc_hssi_set_status(lmc_softc_t * const, lmc_ctl_t *);
176 static void lmc_hssi_set_clock(lmc_softc_t * const, int);
177 static int lmc_hssi_get_link_status(lmc_softc_t * const);
178 static void lmc_hssi_set_link_status(lmc_softc_t * const, int);
179 static void lmc_hssi_set_crc_length(lmc_softc_t * const, int);
180 static void lmc_hssi_watchdog(lmc_softc_t * const);
181
182 static void lmc_ssi_init(lmc_softc_t * const);
183 static void lmc_ssi_default(lmc_softc_t * const);
184 static void lmc_ssi_set_status(lmc_softc_t * const, lmc_ctl_t *);
185 static void lmc_ssi_set_clock(lmc_softc_t * const, int);
186 static void lmc_ssi_set_speed(lmc_softc_t * const, lmc_ctl_t *);
187 static int lmc_ssi_get_link_status(lmc_softc_t * const);
188 static void lmc_ssi_set_link_status(lmc_softc_t * const, int);
189 static void lmc_ssi_set_crc_length(lmc_softc_t * const, int);
190 static void lmc_ssi_watchdog(lmc_softc_t * const);
191
192 static void lmc_t1_init(lmc_softc_t * const);
193 static void lmc_t1_default(lmc_softc_t * const);
194 static void lmc_t1_set_status(lmc_softc_t * const, lmc_ctl_t *);
195 static int lmc_t1_get_link_status(lmc_softc_t * const);
196 static void lmc_t1_set_circuit_type(lmc_softc_t * const, int);
197 static void lmc_t1_set_crc_length(lmc_softc_t * const, int);
198 static void lmc_t1_set_clock(lmc_softc_t * const, int);
199 static void lmc_t1_watchdog(lmc_softc_t * const);
200
201 static void lmc_dummy_set_1(lmc_softc_t * const, int);
202 static void lmc_dummy_set2_1(lmc_softc_t * const, lmc_ctl_t *);
203
204 static inline void write_av9110_bit(lmc_softc_t *, int);
205 static void write_av9110(lmc_softc_t *, u_int32_t, u_int32_t, u_int32_t,
206 u_int32_t, u_int32_t);
207
208 lmc_media_t lmc_ds3_media = {
209 lmc_ds3_init, /* special media init stuff */
210 lmc_ds3_default, /* reset to default state */
211 lmc_ds3_set_status, /* reset status to state provided */
212 lmc_dummy_set_1, /* set clock source */
213 lmc_dummy_set2_1, /* set line speed */
214 lmc_ds3_set_100ft, /* set cable length */
215 lmc_ds3_set_scram, /* set scrambler */
216 lmc_ds3_get_link_status, /* get link status */
217 lmc_dummy_set_1, /* set link status */
218 lmc_ds3_set_crc_length, /* set CRC length */
219 lmc_dummy_set_1, /* set T1 or E1 circuit type */
220 lmc_ds3_watchdog
221 };
222
223 lmc_media_t lmc_hssi_media = {
224 lmc_hssi_init, /* special media init stuff */
225 lmc_hssi_default, /* reset to default state */
226 lmc_hssi_set_status, /* reset status to state provided */
227 lmc_hssi_set_clock, /* set clock source */
228 lmc_dummy_set2_1, /* set line speed */
229 lmc_dummy_set_1, /* set cable length */
230 lmc_dummy_set_1, /* set scrambler */
231 lmc_hssi_get_link_status, /* get link status */
232 lmc_hssi_set_link_status, /* set link status */
233 lmc_hssi_set_crc_length, /* set CRC length */
234 lmc_dummy_set_1, /* set T1 or E1 circuit type */
235 lmc_hssi_watchdog
236 };
237
238 lmc_media_t lmc_ssi_media = {
239 lmc_ssi_init, /* special media init stuff */
240 lmc_ssi_default, /* reset to default state */
241 lmc_ssi_set_status, /* reset status to state provided */
242 lmc_ssi_set_clock, /* set clock source */
243 lmc_ssi_set_speed, /* set line speed */
244 lmc_dummy_set_1, /* set cable length */
245 lmc_dummy_set_1, /* set scrambler */
246 lmc_ssi_get_link_status, /* get link status */
247 lmc_ssi_set_link_status, /* set link status */
248 lmc_ssi_set_crc_length, /* set CRC length */
249 lmc_dummy_set_1, /* set T1 or E1 circuit type */
250 lmc_ssi_watchdog
251 };
252
253 lmc_media_t lmc_t1_media = {
254 lmc_t1_init, /* special media init stuff */
255 lmc_t1_default, /* reset to default state */
256 lmc_t1_set_status, /* reset status to state provided */
257 lmc_t1_set_clock, /* set clock source */
258 lmc_dummy_set2_1, /* set line speed */
259 lmc_dummy_set_1, /* set cable length */
260 lmc_dummy_set_1, /* set scrambler */
261 lmc_t1_get_link_status, /* get link status */
262 lmc_dummy_set_1, /* set link status */
263 lmc_t1_set_crc_length, /* set CRC length */
264 lmc_t1_set_circuit_type, /* set T1 or E1 circuit type */
265 lmc_t1_watchdog
266 };
267
268 static void
269 lmc_dummy_set_1(lmc_softc_t * const sc, int a)
270 {
271 }
272
273 static void
274 lmc_dummy_set2_1(lmc_softc_t * const sc, lmc_ctl_t *a)
275 {
276 }
277
278 /*
279 * HSSI methods
280 */
281
282 static void
283 lmc_hssi_init(lmc_softc_t * const sc)
284 {
285 sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5200;
286
287 lmc_gpio_mkoutput(sc, LMC_GEP_HSSI_CLOCK);
288 }
289
290 static void
291 lmc_hssi_default(lmc_softc_t * const sc)
292 {
293 sc->lmc_miireg16 = LMC_MII16_LED_ALL;
294
295 sc->lmc_media->set_link_status(sc, LMC_LINK_DOWN);
296 sc->lmc_media->set_clock_source(sc, LMC_CTL_CLOCK_SOURCE_EXT);
297 sc->lmc_media->set_crc_length(sc, LMC_CTL_CRC_LENGTH_16);
298 }
299
300 /*
301 * Given a user provided state, set ourselves up to match it. This will
302 * always reset the card if needed.
303 */
304 static void
305 lmc_hssi_set_status(lmc_softc_t * const sc, lmc_ctl_t *ctl)
306 {
307 if (ctl == NULL) {
308 sc->lmc_media->set_clock_source(sc, sc->ictl.clock_source);
309 lmc_set_protocol(sc, NULL);
310
311 return;
312 }
313
314 /*
315 * check for change in clock source
316 */
317 if (ctl->clock_source && !sc->ictl.clock_source) {
318 sc->lmc_media->set_clock_source(sc, LMC_CTL_CLOCK_SOURCE_INT);
319 sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_INT;
320 } else if (!ctl->clock_source && sc->ictl.clock_source) {
321 sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT;
322 sc->lmc_media->set_clock_source(sc, LMC_CTL_CLOCK_SOURCE_EXT);
323 }
324
325 lmc_set_protocol(sc, ctl);
326 }
327
328 /*
329 * 1 == internal, 0 == external
330 */
331 static void
332 lmc_hssi_set_clock(lmc_softc_t * const sc, int ie)
333 {
334 if (ie == LMC_CTL_CLOCK_SOURCE_EXT) {
335 sc->lmc_gpio |= LMC_GEP_HSSI_CLOCK;
336 LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
337 sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
338 printf(LMC_PRINTF_FMT ": clock external\n",
339 LMC_PRINTF_ARGS);
340 } else {
341 sc->lmc_gpio &= ~(LMC_GEP_HSSI_CLOCK);
342 LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
343 sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
344 printf(LMC_PRINTF_FMT ": clock internal\n",
345 LMC_PRINTF_ARGS);
346 }
347 }
348
349 /*
350 * return hardware link status.
351 * 0 == link is down, 1 == link is up.
352 */
353 static int
354 lmc_hssi_get_link_status(lmc_softc_t * const sc)
355 {
356 u_int16_t link_status;
357
358 link_status = lmc_mii_readreg(sc, 0, 16);
359
360 if ((link_status & LMC_MII16_HSSI_CA) == LMC_MII16_HSSI_CA)
361 return 1;
362 else
363 return 0;
364 }
365
366 static void
367 lmc_hssi_set_link_status(lmc_softc_t * const sc, int state)
368 {
369 if (state)
370 sc->lmc_miireg16 |= LMC_MII16_HSSI_TA;
371 else
372 sc->lmc_miireg16 &= ~LMC_MII16_HSSI_TA;
373
374 lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
375 }
376
377 /*
378 * 0 == 16bit, 1 == 32bit
379 */
380 static void
381 lmc_hssi_set_crc_length(lmc_softc_t * const sc, int state)
382 {
383 if (state == LMC_CTL_CRC_LENGTH_32) {
384 /* 32 bit */
385 sc->lmc_miireg16 |= LMC_MII16_HSSI_CRC;
386 sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
387 } else {
388 /* 16 bit */
389 sc->lmc_miireg16 &= ~LMC_MII16_HSSI_CRC;
390 sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
391 }
392
393 lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
394 }
395
396 static void
397 lmc_hssi_watchdog (lmc_softc_t * const sc)
398 {
399 /* HSSI is blank */
400 }
401
402 static void
403 lmc_ds3_watchdog (lmc_softc_t * const sc)
404 {
405 sc->lmc_miireg16 = lmc_mii_readreg (sc, 0, 16);
406 if (sc->lmc_miireg16 & 0x0018)
407 {
408 #if 1
409 printf("%s: AIS Received\n", sc->lmc_xname);
410 #endif
411 lmc_led_on (sc, LMC_DS3_LED1 | LMC_DS3_LED2);
412 }
413 }
414
415
416 /*
417 * DS3 methods
418 */
419
420 /*
421 * Set cable length
422 */
423 static void
424 lmc_ds3_set_100ft(lmc_softc_t * const sc, int ie)
425 {
426 if (ie == LMC_CTL_CABLE_LENGTH_GT_100FT) {
427 sc->lmc_miireg16 &= ~LMC_MII16_DS3_ZERO;
428 sc->ictl.cable_length = LMC_CTL_CABLE_LENGTH_GT_100FT;
429 } else if (ie == LMC_CTL_CABLE_LENGTH_LT_100FT) {
430 sc->lmc_miireg16 |= LMC_MII16_DS3_ZERO;
431 sc->ictl.cable_length = LMC_CTL_CABLE_LENGTH_LT_100FT;
432 }
433 lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
434 }
435
436 static void
437 lmc_ds3_default(lmc_softc_t * const sc)
438 {
439 sc->lmc_miireg16 = LMC_MII16_LED_ALL;
440
441 sc->lmc_media->set_link_status(sc, LMC_LINK_DOWN);
442 sc->lmc_media->set_cable_length(sc, LMC_CTL_CABLE_LENGTH_LT_100FT);
443 sc->lmc_media->set_scrambler(sc, LMC_CTL_OFF);
444 sc->lmc_media->set_crc_length(sc, LMC_CTL_CRC_LENGTH_16);
445 }
446
447 /*
448 * Given a user provided state, set ourselves up to match it. This will
449 * always reset the card if needed.
450 */
451 static void
452 lmc_ds3_set_status(lmc_softc_t * const sc, lmc_ctl_t *ctl)
453 {
454 if (ctl == NULL) {
455 sc->lmc_media->set_cable_length(sc, sc->ictl.cable_length);
456 sc->lmc_media->set_scrambler(sc, sc->ictl.scrambler_onoff);
457 lmc_set_protocol(sc, NULL);
458
459 return;
460 }
461
462 /*
463 * check for change in cable length setting
464 */
465 if (ctl->cable_length && !sc->ictl.cable_length)
466 lmc_ds3_set_100ft(sc, LMC_CTL_CABLE_LENGTH_GT_100FT);
467 else if (!ctl->cable_length && sc->ictl.cable_length)
468 lmc_ds3_set_100ft(sc, LMC_CTL_CABLE_LENGTH_LT_100FT);
469
470 /*
471 * Check for change in scrambler setting (requires reset)
472 */
473 if (ctl->scrambler_onoff && !sc->ictl.scrambler_onoff)
474 lmc_ds3_set_scram(sc, LMC_CTL_ON);
475 else if (!ctl->scrambler_onoff && sc->ictl.scrambler_onoff)
476 lmc_ds3_set_scram(sc, LMC_CTL_OFF);
477
478 lmc_set_protocol(sc, ctl);
479 }
480
481 static void
482 lmc_ds3_init(lmc_softc_t * const sc)
483 {
484 int i;
485
486 sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5245;
487
488 /* writes zeros everywhere */
489 for (i = 0 ; i < 21 ; i++) {
490 lmc_mii_writereg(sc, 0, 17, i);
491 lmc_mii_writereg(sc, 0, 18, 0);
492 }
493
494 /* set some essential bits */
495 lmc_mii_writereg(sc, 0, 17, 1);
496 lmc_mii_writereg(sc, 0, 18, 0x05); /* ser, xtx */
497
498 lmc_mii_writereg(sc, 0, 17, 5);
499 lmc_mii_writereg(sc, 0, 18, 0x80); /* emode */
500
501 lmc_mii_writereg(sc, 0, 17, 14);
502 lmc_mii_writereg(sc, 0, 18, 0x30); /* rcgen, tcgen */
503
504 /* clear counters and latched bits */
505 for (i = 0 ; i < 21 ; i++) {
506 lmc_mii_writereg(sc, 0, 17, i);
507 lmc_mii_readreg(sc, 0, 18);
508 }
509 }
510
511 /*
512 * 1 == DS3 payload scrambled, 0 == not scrambled
513 */
514 static void
515 lmc_ds3_set_scram(lmc_softc_t * const sc, int ie)
516 {
517 if (ie == LMC_CTL_ON) {
518 sc->lmc_miireg16 |= LMC_MII16_DS3_SCRAM;
519 sc->ictl.scrambler_onoff = LMC_CTL_ON;
520 } else {
521 sc->lmc_miireg16 &= ~LMC_MII16_DS3_SCRAM;
522 sc->ictl.scrambler_onoff = LMC_CTL_OFF;
523 }
524 lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
525 }
526
527 /*
528 * return hardware link status.
529 * 0 == link is down, 1 == link is up.
530 */
531 static int
532 lmc_ds3_get_link_status(lmc_softc_t * const sc)
533 {
534 u_int16_t link_status;
535
536 lmc_mii_writereg(sc, 0, 17, 7);
537 link_status = lmc_mii_readreg(sc, 0, 18);
538 // printf("lmc_ds3_get_link_status: %x\n", link_status);
539 if ((link_status & LMC_FRAMER_REG0_DLOS) == 0)
540 return 1;
541 else
542 return 0;
543 }
544
545 /*
546 * 0 == 16bit, 1 == 32bit
547 */
548 static void
549 lmc_ds3_set_crc_length(lmc_softc_t * const sc, int state)
550 {
551 if (state == LMC_CTL_CRC_LENGTH_32) {
552 /* 32 bit */
553 sc->lmc_miireg16 |= LMC_MII16_DS3_CRC;
554 sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
555 } else {
556 /* 16 bit */
557 sc->lmc_miireg16 &= ~LMC_MII16_DS3_CRC;
558 sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
559 }
560
561 lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
562 }
563
564
565 /*
566 * SSI methods
567 */
568
569 static void
570 lmc_ssi_init(lmc_softc_t * const sc)
571 {
572 u_int16_t mii17;
573 int cable;
574
575 sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1000;
576
577 mii17 = lmc_mii_readreg(sc, 0, 17);
578
579 cable = (mii17 & LMC_MII17_SSI_CABLE_MASK) >> LMC_MII17_SSI_CABLE_SHIFT;
580 sc->ictl.cable_type = cable;
581
582 lmc_gpio_mkoutput(sc, LMC_GEP_SSI_TXCLOCK);
583 }
584
585 static void
586 lmc_ssi_default(lmc_softc_t * const sc)
587 {
588 sc->lmc_miireg16 = LMC_MII16_LED_ALL;
589
590 /*
591 * make TXCLOCK always be an output
592 */
593 lmc_gpio_mkoutput(sc, LMC_GEP_SSI_TXCLOCK);
594
595 sc->lmc_media->set_link_status(sc, LMC_LINK_DOWN);
596 sc->lmc_media->set_clock_source(sc, LMC_CTL_CLOCK_SOURCE_EXT);
597 sc->lmc_media->set_speed(sc, NULL);
598 sc->lmc_media->set_crc_length(sc, LMC_CTL_CRC_LENGTH_16);
599 }
600
601 /*
602 * Given a user provided state, set ourselves up to match it. This will
603 * always reset the card if needed.
604 */
605 static void
606 lmc_ssi_set_status(lmc_softc_t * const sc, lmc_ctl_t *ctl)
607 {
608 if (ctl == NULL) {
609 sc->lmc_media->set_clock_source(sc, sc->ictl.clock_source);
610 sc->lmc_media->set_speed(sc, &sc->ictl);
611 lmc_set_protocol(sc, NULL);
612
613 return;
614 }
615
616 /*
617 * check for change in clock source
618 */
619 if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_INT &&
620 sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_EXT) {
621 sc->lmc_media->set_clock_source(sc, LMC_CTL_CLOCK_SOURCE_INT);
622 sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_INT;
623 } else if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_EXT &&
624 sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_INT) {
625 sc->lmc_media->set_clock_source(sc, LMC_CTL_CLOCK_SOURCE_EXT);
626 sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT;
627 }
628
629 if (ctl->clock_rate != sc->ictl.clock_rate)
630 sc->lmc_media->set_speed(sc, ctl);
631
632 lmc_set_protocol(sc, ctl);
633 }
634
635 /*
636 * 1 == internal, 0 == external
637 */
638 static void
639 lmc_ssi_set_clock(lmc_softc_t * const sc, int ie)
640 {
641 if (ie == LMC_CTL_CLOCK_SOURCE_EXT) {
642 sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK);
643 LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
644 sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
645 printf(LMC_PRINTF_FMT ": clock external\n",
646 LMC_PRINTF_ARGS);
647 } else {
648 sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK;
649 LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
650 sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
651 printf(LMC_PRINTF_FMT ": clock internal\n",
652 LMC_PRINTF_ARGS);
653 }
654 }
655
656 static void
657 lmc_ssi_set_speed(lmc_softc_t * const sc, lmc_ctl_t *ctl)
658 {
659 lmc_ctl_t *ictl = &sc->ictl;
660 lmc_av9110_t *av;
661
662 /*
663 * original settings for clock rate of:
664 * 100 KHz (8,25,0,0,2) were incorrect
665 * they should have been 80,125,1,3,3
666 * There are 17 param combinations to produce this freq.
667 * For 1.5 MHz use 120,100,1,1,2 (226 param. combinations)
668 */
669 if (ctl == NULL) {
670 av = &ictl->cardspec.ssi;
671 ictl->clock_rate = 1500000;
672 av->f = ictl->clock_rate;
673 av->n = 120;
674 av->m = 100;
675 av->v = 1;
676 av->x = 1;
677 av->r = 2;
678
679 write_av9110(sc, av->n, av->m, av->v, av->x, av->r);
680 return;
681 }
682
683 av = &ctl->cardspec.ssi;
684
685 if (av->f == 0)
686 return;
687
688 ictl->clock_rate = av->f; /* really, this is the rate we are */
689 ictl->cardspec.ssi = *av;
690
691 write_av9110(sc, av->n, av->m, av->v, av->x, av->r);
692 }
693
694 /*
695 * return hardware link status.
696 * 0 == link is down, 1 == link is up.
697 */
698 static int
699 lmc_ssi_get_link_status(lmc_softc_t * const sc)
700 {
701 u_int16_t link_status;
702
703 /*
704 * missing CTS? Hmm. If we require CTS on, we may never get the
705 * link to come up, so omit it in this test.
706 *
707 * Also, it seems that with a loopback cable, DCD isn't asserted,
708 * so just check for things like this:
709 * DSR _must_ be asserted.
710 * One of DCD or CTS must be asserted.
711 */
712
713 #ifdef CONFIG_LMC_IGNORE_HARDWARE_HANDSHAKE
714 link_status = LMC_CSR_READ(sc, csr_gp_timer);
715 link_status = 0x0000ffff - (link_status & 0x0000ffff);
716
717 return(link_status);
718 #else
719
720 link_status = lmc_mii_readreg(sc, 0, 16);
721
722 if ((link_status & LMC_MII16_SSI_DSR) == 0)
723 return (0);
724
725 if ((link_status & (LMC_MII16_SSI_CTS | LMC_MII16_SSI_DCD)) == 0)
726 return (0);
727
728 return (1);
729 #endif
730 }
731
732 static void
733 lmc_ssi_set_link_status(lmc_softc_t * const sc, int state)
734 {
735 if (state) {
736 sc->lmc_miireg16 |= (LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS);
737 printf(LMC_PRINTF_FMT ": asserting DTR and RTS\n",
738 LMC_PRINTF_ARGS);
739 } else {
740 sc->lmc_miireg16 &= ~(LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS);
741 printf(LMC_PRINTF_FMT ": deasserting DTR and RTS\n",
742 LMC_PRINTF_ARGS);
743 }
744
745 lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
746
747 }
748
749 /*
750 * 0 == 16bit, 1 == 32bit
751 */
752 static void
753 lmc_ssi_set_crc_length(lmc_softc_t * const sc, int state)
754 {
755 if (state == LMC_CTL_CRC_LENGTH_32) {
756 /* 32 bit */
757 sc->lmc_miireg16 |= LMC_MII16_SSI_CRC;
758 sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
759 sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4;
760 } else {
761 /* 16 bit */
762 sc->lmc_miireg16 &= ~LMC_MII16_SSI_CRC;
763 sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
764 sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2;
765 }
766
767 lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
768 }
769
770 /*
771 * These are bits to program the ssi frequency generator
772 */
773 static inline void
774 write_av9110_bit(lmc_softc_t *sc, int c)
775 {
776 /*
777 * set the data bit as we need it.
778 */
779 sc->lmc_gpio &= ~(LMC_GEP_SERIALCLK);
780 if (c & 0x01)
781 sc->lmc_gpio |= LMC_GEP_SERIAL;
782 else
783 sc->lmc_gpio &= ~(LMC_GEP_SERIAL);
784 LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
785
786 /*
787 * set the clock to high
788 */
789 sc->lmc_gpio |= LMC_GEP_SERIALCLK;
790 LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
791
792 /*
793 * set the clock to low again.
794 */
795 sc->lmc_gpio &= ~(LMC_GEP_SERIALCLK);
796 LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
797 }
798
799 static void
800 write_av9110(lmc_softc_t *sc, u_int32_t n, u_int32_t m, u_int32_t v,
801 u_int32_t x, u_int32_t r)
802 {
803 int i;
804
805 #if 0
806 printf(LMC_PRINTF_FMT ": speed %u, %d %d %d %d %d\n",
807 LMC_PRINTF_ARGS, sc->ictl.clock_rate,
808 n, m, v, x, r);
809 #endif
810
811 sc->lmc_gpio |= LMC_GEP_SSI_GENERATOR;
812 sc->lmc_gpio &= ~(LMC_GEP_SERIAL | LMC_GEP_SERIALCLK);
813 LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
814
815 /*
816 * Set the TXCLOCK, GENERATOR, SERIAL, and SERIALCLK
817 * as outputs.
818 */
819 lmc_gpio_mkoutput(sc, (LMC_GEP_SERIAL | LMC_GEP_SERIALCLK
820 | LMC_GEP_SSI_GENERATOR));
821
822 sc->lmc_gpio &= ~(LMC_GEP_SSI_GENERATOR);
823 LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
824
825 /*
826 * a shifting we will go...
827 */
828 for (i = 0 ; i < 7 ; i++)
829 write_av9110_bit(sc, n >> i);
830 for (i = 0 ; i < 7 ; i++)
831 write_av9110_bit(sc, m >> i);
832 for (i = 0 ; i < 1 ; i++)
833 write_av9110_bit(sc, v >> i);
834 for (i = 0 ; i < 2 ; i++)
835 write_av9110_bit(sc, x >> i);
836 for (i = 0 ; i < 2 ; i++)
837 write_av9110_bit(sc, r >> i);
838 for (i = 0 ; i < 5 ; i++)
839 write_av9110_bit(sc, 0x17 >> i);
840
841 /*
842 * stop driving serial-related signals
843 */
844 lmc_gpio_mkinput(sc,
845 (LMC_GEP_SERIAL | LMC_GEP_SERIALCLK
846 | LMC_GEP_SSI_GENERATOR));
847 }
848
849 static void
850 lmc_ssi_watchdog(lmc_softc_t * const sc)
851 {
852 union {
853 u_int16_t mii17;
854 struct ssicsr2 {
855 unsigned short dtr:1, dsr:1, rts:1, cable:3, crc:1,
856 led0:1, led1:1, led2:1, led3:1, fifo:1, ll:1,
857 rl:1, tm:1, loop:1;
858 } ssicsr;
859 } ssicr_un;
860
861 ssicr_un.mii17 = lmc_mii_readreg (sc, 0, 17);
862 if (ssicr_un.ssicsr.cable == 7) {
863 lmc_led_off (sc, LMC_MII16_LED2);
864 }
865 else {
866 lmc_led_on (sc, LMC_MII16_LED2);
867 }
868
869 }
870
871 /*
872 * T1 methods
873 */
874
875 /*
876 * The framer regs are multiplexed through MII regs 17 & 18
877 * write the register address to MII reg 17 and the
878 * data to MII reg 18.
879 */
880 static void
881 lmc_t1_write(lmc_softc_t * const sc, int a, int d)
882 {
883 lmc_mii_writereg(sc, 0, 17, a);
884 lmc_mii_writereg(sc, 0, 18, d);
885 }
886
887 static int
888 lmc_t1_read(lmc_softc_t * const sc, int a)
889 {
890 lmc_mii_writereg(sc, 0, 17, a);
891 return lmc_mii_readreg(sc, 0, 18);
892 }
893
894 static void
895 lmc_t1_init(lmc_softc_t * const sc)
896 {
897 u_int16_t mii16;
898 int i;
899
900 sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1200;
901 mii16 = lmc_mii_readreg(sc, 0, 16);
902
903 mii16 &= ~LMC_MII16_T1_XOE;
904 lmc_mii_writereg (sc, 0, 16, mii16);
905 sc->lmc_miireg16 = mii16;
906
907 /* reset 8370 */
908 mii16 &= ~LMC_MII16_T1_RST;
909 lmc_mii_writereg(sc, 0, 16, mii16 | LMC_MII16_T1_RST);
910 lmc_mii_writereg(sc, 0, 16, mii16);
911
912 /* set T1 line impedance */
913 mii16 |= LMC_MII16_T1_Z;
914 lmc_mii_writereg(sc, 0, 16, mii16);
915
916
917 /* CR0 - Set framing to ESF + Force CRC - Set T1 */
918 lmc_t1_write(sc, 0x01, 0x1b);
919
920 /* Reset Elastic store to center - 64 bit elastic store */
921 lmc_t1_write(sc, 0x02, 0x4b);
922
923 /* Release Elastic store reset */
924 lmc_t1_write(sc, 0x02, 0x43);
925
926 /* Disable all interrupts except BOP receive */
927 lmc_t1_write(sc, 0x0C, 0x00);
928 lmc_t1_write(sc, 0x0D, 0x00);
929 lmc_t1_write(sc, 0x0E, 0x00);
930 lmc_t1_write(sc, 0x0F, 0x00);
931 lmc_t1_write(sc, 0x10, 0x00);
932 lmc_t1_write(sc, 0x11, 0x00);
933 lmc_t1_write(sc, 0x12, 0x80);
934 lmc_t1_write(sc, 0x13, 0x00);
935
936 lmc_t1_write(sc, 0x14, 0x00); /* LOOP - loopback config */
937 lmc_t1_write(sc, 0x15, 0x00); /* DL3_TS - xtrnl datalink timeslot */
938 lmc_t1_write(sc, 0x18, 0xFF); /* PIO - programmable I/O */
939 lmc_t1_write(sc, 0x19, 0x30); /* POE - programmable OE */
940 lmc_t1_write(sc, 0x1A, 0x0F); /* CMUX - clock input mux */
941
942 lmc_t1_write(sc, 0x20, 0xC1); /* LIU_CR - RX LIU config */
943 lmc_t1_write(sc, 0x20, 0x41); /* LIU_CR - RX LIU config */
944
945 lmc_t1_write(sc, 0x22, 0xB1); /* RLIU_CR - RX LIU config */
946 lmc_t1_write(sc, 0x24, 0x21); /* VGA_MAX -20db sesitivity */
947 lmc_t1_write(sc, 0x2A, 0xA6); /* Force off the pre-equalizer */
948
949 /* Equalizer Gain threshholds */
950 lmc_t1_write(sc, 0x38, 0x24); /* RX_TH0 - RX gain threshold 0 */
951 lmc_t1_write(sc, 0x39, 0x28); /* RX_TH1 - RX gain threshold 0 */
952 lmc_t1_write(sc, 0x3A, 0x2C); /* RX_TH2 - RX gain threshold 0 */
953 lmc_t1_write(sc, 0x3B, 0x30); /* RX_TH3 - RX gain threshold 0 */
954 lmc_t1_write(sc, 0x3C, 0x34); /* RX_TH4 - RX gain threshold 0 */
955
956 /* Reset LIU */
957 lmc_t1_write(sc, 0x20, 0x81); /* LIU_CR - RX LIU (reset RLIU) */
958 lmc_t1_write(sc, 0x20, 0x01); /* LIU_CR - RX LIU (clear reset) */
959
960 lmc_t1_write(sc, 0x40, 0x03); /* RCR0 - RX config */
961 lmc_t1_write(sc, 0x41, 0x00); /* Zero test pattern generator */
962
963 lmc_t1_write(sc, 0x42, 0x09); /* DN_LEN is 8, UP_LEN is 5 */
964 lmc_t1_write(sc, 0x43, 0x08); /* Loopback activate */
965 lmc_t1_write(sc, 0x44, 0x24); /* Loopback deactivate */
966
967 lmc_t1_write(sc, 0x45, 0x00); /* RALM - RX alarm config */
968 lmc_t1_write(sc, 0x46, 0x08); /* LATCH - RX alarm/err/cntr latch */
969
970 lmc_t1_write(sc, 0x68, 0x4E); /* TLIU_CR - TX LIU config */
971 lmc_t1_write(sc, 0x70, 0x0D); /* TCR0 - TX framer config */
972 lmc_t1_write(sc, 0x71, 0x05); /* TCR1 - TX config */
973 lmc_t1_write(sc, 0x72, 0x0B); /* TFRM - TX frame format */
974 lmc_t1_write(sc, 0x73, 0x00); /* TERROR - TX error insert */
975 lmc_t1_write(sc, 0x74, 0x00); /* TMAN - TX manual Sa/FEBE config */
976 lmc_t1_write(sc, 0x75, 0x00); /* TALM - TX alarm signal config */
977 lmc_t1_write(sc, 0x76, 0x00); /* TPATT - TX test pattern config */
978 lmc_t1_write(sc, 0x77, 0x00); /* TLB - TX inband loopback confg */
979 lmc_t1_write(sc, 0x90, 0x06); /* CLAD_CR - clock rate adapter confg */
980 lmc_t1_write(sc, 0x91, 0x05); /* CSEL - clad freq sel */
981 lmc_t1_write(sc, 0x92, 0x00); /* CLAD Phase Det */
982 lmc_t1_write(sc, 0x93, 0x00); /* No CLAD Test */
983
984 /* Activate BOP */
985 lmc_t1_write(sc, 0xA0, 0xea); /* BOP - Bit oriented protocol xcvr */
986
987 lmc_t1_write(sc, 0xA4, 0x40); /* DL1_TS - DL1 time slot enable */
988 lmc_t1_write(sc, 0xA5, 0x00); /* DL1_BIT - DL1 bit enable */
989 lmc_t1_write(sc, 0xA6, 0x03); /* DL1_CTL - DL1 control */
990 lmc_t1_write(sc, 0xA7, 0x00); /* RDL1_FFC - DL1 FIFO Size */
991 lmc_t1_write(sc, 0xAB, 0x00); /* TDL1_FFC - DL1 Empty Control */
992
993 lmc_t1_write(sc, 0xAA, 0x00); /* PRM - no perf report messages */
994 lmc_t1_write(sc, 0xB1, 0x00); /* DL2_CTL - DL2 control */
995 lmc_t1_write(sc, 0xD0, 0x47); /* SBI_CR - sys bus iface config */
996 lmc_t1_write(sc, 0xD1, 0x70); /* RSB_CR - RX sys bus config */
997 lmc_t1_write(sc, 0xD4, 0x30); /* TSB_CR - TX sys bus config */
998
999 for (i = 0; i < 32; i++) {
1000 lmc_t1_write(sc, 0x0E0+i, 0x00); /*SBCn sysbus perchannel ctl */
1001 lmc_t1_write(sc, 0x100+i, 0x00); /* TPCn - TX per-channel ctl */
1002 lmc_t1_write(sc, 0x180+i, 0x00); /* RPCn - RX per-channel ctl */
1003 }
1004 for (i = 1; i < 25; i++) {
1005 /* SBCn - sys bus per-channel ctl */
1006 lmc_t1_write(sc, 0x0E0+i, 0x0D);
1007 }
1008
1009 /* PFM */
1010 lmc_t1_write(sc, 0xA4, 0x40); /* DL1_TS - DL1 time slot enable */
1011 lmc_t1_write(sc, 0xA5, 0x00); /* DL1_BIT - DL1 bit enable */
1012 lmc_t1_write(sc, 0xA6, 0x03); /* DL1_CTL - DL1 control */
1013 lmc_t1_write(sc, 0xA7, 0x00); /* RDL1_FFC - DL1 FIFO Size */
1014 lmc_t1_write(sc, 0xAB, 0x00); /* TDL1_FFC - DL1 Empty Control */
1015
1016
1017 mii16 |= LMC_MII16_T1_XOE;
1018 lmc_mii_writereg (sc, 0, 16, mii16);
1019 sc->lmc_miireg16 = mii16;
1020 }
1021
1022 static void
1023 lmc_t1_default(lmc_softc_t * const sc)
1024 {
1025 sc->lmc_miireg16 = LMC_MII16_LED_ALL;
1026 sc->lmc_media->set_link_status(sc, LMC_LINK_DOWN);
1027 sc->lmc_media->set_circuit_type(sc, LMC_CTL_CIRCUIT_TYPE_T1);
1028 sc->lmc_media->set_crc_length(sc, LMC_CTL_CRC_LENGTH_16);
1029 }
1030
1031 /*
1032 * Given a user provided state, set ourselves up to match it. This will
1033 * always reset the card if needed.
1034 */
1035
1036 static void
1037 lmc_t1_set_status(lmc_softc_t * const sc, lmc_ctl_t *ctl){
1038 if (ctl == NULL) {
1039 sc->lmc_media->set_circuit_type(sc, sc->ictl.circuit_type);
1040 lmc_set_protocol(sc, NULL);
1041
1042 return;
1043 }
1044
1045 /*
1046 * check for change in circuit type
1047 */
1048
1049 if (ctl->circuit_type == LMC_CTL_CIRCUIT_TYPE_T1
1050 && sc->ictl.circuit_type == LMC_CTL_CIRCUIT_TYPE_E1)
1051 sc->lmc_media->set_circuit_type(sc, LMC_CTL_CIRCUIT_TYPE_E1);
1052 else if (ctl->circuit_type == LMC_CTL_CIRCUIT_TYPE_E1
1053 && sc->ictl.circuit_type == LMC_CTL_CIRCUIT_TYPE_T1)
1054 sc->lmc_media->set_circuit_type(sc, LMC_CTL_CIRCUIT_TYPE_T1);
1055 lmc_set_protocol(sc, ctl);
1056 }
1057
1058 /*
1059 * return hardware link status.
1060 * 0 == link is down, 1 == link is up.
1061 */
1062
1063 static int
1064 lmc_t1_get_link_status(lmc_softc_t * const sc)
1065 {
1066 u_int16_t link_status;
1067 lmc_mii_writereg(sc, 0, 17, T1FRAMER_ALARM1_STATUS);
1068 link_status = lmc_mii_readreg(sc, 0, 18);
1069
1070 /*
1071 * LMC 1200 LED definitions
1072 * led0 yellow = far-end adapter is in Red alarm condition
1073 * led1 blue = received an Alarm Indication signal (upstream failure)
1074 * led2 Green = power to adapter, Gate Array loaded & driver attached
1075 * led3 red = Loss of Signal (LOS) or out of frame (OOF) conditions
1076 * detected on T3 receive signal
1077 */
1078
1079 /* detect a change in Blue alarm indication signal */
1080
1081 if ((sc->t1_alarm1_status & T1F_RAIS) != (link_status & T1F_RAIS)) {
1082 if (link_status & T1F_RAIS) {
1083 /* turn on blue LED */
1084 /* DEBUG */
1085 printf(" link status: RAIS turn ON Blue %x\n",
1086 link_status);
1087 lmc_led_on(sc, LMC_DS3_LED1);
1088 } else {
1089 /* turn off blue LED */
1090 /* DEBUG */
1091 printf(" link status: RAIS turn OFF Blue %x\n",
1092 link_status);
1093 lmc_led_off(sc, LMC_DS3_LED1);
1094 }
1095 }
1096 /*
1097 * T1F_RYEL wiggles quite a bit,
1098 * taking it out until I understand why -baz 6/22/99
1099 */
1100 /* Yellow alarm indication */
1101 if ((sc->t1_alarm1_status & T1F_RMYEL) !=
1102 (link_status & T1F_RMYEL)) {
1103 if ((link_status & (T1F_RYEL | T1F_RMYEL)) == 0) {
1104 /* turn off yellow LED */
1105 /* DEBUG */
1106 printf(" link status: RYEL turn OFF Yellow %x\n",
1107 link_status);
1108 lmc_led_off(sc, LMC_DS3_LED0);
1109
1110 } else {
1111 /* turn on yellow LED */
1112 /* DEBUG */
1113 printf(" link status: RYEL turn ON Yellow %x\n",
1114 link_status);
1115 lmc_led_on(sc, LMC_DS3_LED0);
1116 }
1117 }
1118
1119 sc->t1_alarm1_status = link_status;
1120
1121 lmc_mii_writereg(sc, 0, 17, T1FRAMER_ALARM2_STATUS);
1122 sc->t1_alarm2_status = lmc_mii_readreg(sc, 0, 18);
1123
1124 /*
1125 * link status based upon T1 receive loss of frame or
1126 * loss of signal - RED alarm indication
1127 */
1128 if ((link_status & (T1F_RLOF | T1F_RLOS)) == 0)
1129 return 1;
1130 else
1131 return 0;
1132 }
1133
1134 /*
1135 * 1 == T1 Circuit Type , 0 == E1 Circuit Type
1136 */
1137 static void
1138 lmc_t1_set_circuit_type(lmc_softc_t * const sc, int ie)
1139 {
1140 if (ie == LMC_CTL_CIRCUIT_TYPE_T1) {
1141 sc->lmc_miireg16 |= LMC_MII16_T1_Z;
1142 sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_T1;
1143 } else {
1144 sc->lmc_miireg16 &= ~LMC_MII16_T1_Z;
1145 sc->ictl.scrambler_onoff = LMC_CTL_CIRCUIT_TYPE_E1;
1146 }
1147 lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
1148 }
1149
1150 /*
1151 * 0 == 16bit, 1 == 32bit
1152 */
1153 static void
1154 lmc_t1_set_crc_length(lmc_softc_t * const sc, int state)
1155 {
1156 if (state == LMC_CTL_CRC_LENGTH_32) {
1157 /* 32 bit */
1158 sc->lmc_miireg16 |= LMC_MII16_T1_CRC;
1159 sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
1160 sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4;
1161
1162 } else {
1163 /* 16 bit */
1164 sc->lmc_miireg16 &= ~LMC_MII16_T1_CRC;
1165 sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
1166 sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2;
1167 }
1168
1169 lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
1170 }
1171
1172 /*
1173 * 1 == internal, 0 == external
1174 */
1175 static void
1176 lmc_t1_set_clock(lmc_softc_t * const sc, int ie)
1177 {
1178 if (ie == LMC_CTL_CLOCK_SOURCE_EXT) {
1179 sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK);
1180 LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
1181 sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
1182 printf (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
1183 }
1184 else {
1185 sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK;
1186 LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
1187 sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
1188 printf (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
1189 }
1190 }
1191
1192 static void
1193 lmc_t1_watchdog(lmc_softc_t * const sc)
1194 {
1195 int t1stat;
1196
1197 /* read alarm 1 status (receive) */
1198 t1stat = lmc_t1_read (sc, 0x47);
1199 /* blue alarm -- RAIS */
1200 if (t1stat & 0x08) {
1201 #if 0
1202 if (sc->lmc_blue != 1)
1203 printf ("%s: AIS Received\n", sc->lmc_xname);
1204 #endif
1205 lmc_led_on (sc, LMC_DS3_LED1 | LMC_DS3_LED2);
1206 sc->lmc_blue = 1;
1207 } else {
1208 #if 0
1209 if (sc->lmc_blue == 1)
1210 printf ("%s: AIS ok\n", sc->lmc_xname);
1211 #endif
1212 lmc_led_off (sc, LMC_DS3_LED1);
1213 lmc_led_on (sc, LMC_DS3_LED2);
1214 sc->lmc_blue = 0;
1215 }
1216
1217 /* Red alarm -- LOS | LOF */
1218 if (t1stat & 0x04) {
1219 /* Only print the error once */
1220 if (sc->lmc_red != 1)
1221 printf ("%s: Red Alarm\n", sc->lmc_xname);
1222 lmc_led_on (sc, LMC_DS3_LED2 | LMC_DS3_LED3);
1223 sc->lmc_red = 1;
1224 } else {
1225 if (sc->lmc_red == 1)
1226 printf ("%s: Red Alarm ok\n", sc->lmc_xname);
1227 lmc_led_off (sc, LMC_DS3_LED3);
1228 lmc_led_on (sc, LMC_DS3_LED2);
1229 sc->lmc_red = 0;
1230 }
1231
1232 /* check for Receive Multiframe Yellow Alarm
1233 * Ignore Receive Yellow Alarm
1234 */
1235 if (t1stat & 0x80) {
1236 if (sc->lmc_yel != 1) {
1237 printf ("%s: Receive Yellow Alarm\n", sc->lmc_xname);
1238 }
1239 lmc_led_on (sc, LMC_DS3_LED0 | LMC_DS3_LED2);
1240 sc->lmc_yel = 1;
1241 }
1242 else {
1243 if (sc->lmc_yel == 1)
1244 printf ("%s: Yellow Alarm ok\n", sc->lmc_xname);
1245 lmc_led_off (sc, LMC_DS3_LED0);
1246 lmc_led_on (sc, LMC_DS3_LED2);
1247 sc->lmc_yel = 0;
1248 }
1249 }
1250
1251
1252 static void
1253 lmc_set_protocol(lmc_softc_t * const sc, lmc_ctl_t *ctl)
1254 {
1255 if (ctl == 0) {
1256 sc->ictl.keepalive_onoff = LMC_CTL_ON;
1257
1258 return;
1259 }
1260
1261 #if defined(__NetBSD__) || defined(__FreeBSD__)
1262 if (ctl->keepalive_onoff != sc->ictl.keepalive_onoff) {
1263 switch (ctl->keepalive_onoff) {
1264 case LMC_CTL_ON:
1265 printf(LMC_PRINTF_FMT ": enabling keepalive\n",
1266 LMC_PRINTF_ARGS);
1267 sc->ictl.keepalive_onoff = LMC_CTL_ON;
1268 sc->lmc_sppp.pp_flags = PP_CISCO | PP_KEEPALIVE;
1269 break;
1270 case LMC_CTL_OFF:
1271 printf(LMC_PRINTF_FMT ": disabling keepalive\n",
1272 LMC_PRINTF_ARGS);
1273 sc->ictl.keepalive_onoff = LMC_CTL_OFF;
1274 sc->lmc_sppp.pp_flags = PP_CISCO;
1275 }
1276 }
1277
1278 #if NBPFILTER > 0
1279 /* just in case we are going to change encap type */
1280 if ((sc->lmc_sppp.pp_flags & PP_CISCO) != 0)
1281 bpf_change_type(&sc->lmc_if, DLT_HDLC, PPP_HEADER_LEN);
1282 else
1283 bpf_change_type(&sc->lmc_if, DLT_PPP, PPP_HEADER_LEN);
1284 #endif /* NBPFILTER > 0 */
1285 #endif
1286 }
Cache object: 7b3698fd6e86aa073c89dca9c081eead
|