From patchwork Sat Jul 31 15:05:32 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Krzysztof Halasa X-Patchwork-Id: 60408 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 369281007D3 for ; Sun, 1 Aug 2010 01:06:30 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756546Ab0GaPGT (ORCPT ); Sat, 31 Jul 2010 11:06:19 -0400 Received: from khc.piap.pl ([195.187.100.11]:45540 "EHLO khc.piap.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756496Ab0GaPGQ (ORCPT ); Sat, 31 Jul 2010 11:06:16 -0400 Received: from intrepid.localdomain (intrepid.localdomain [10.0.0.2]) by khc.piap.pl (Postfix) with ESMTP id B25DA98A5; Sat, 31 Jul 2010 17:05:53 +0200 (CEST) From: Krzysztof Halasa To: David Miller Cc: Subject: [PATCH 09/29] LMC: shuffle protocol routines to avoid a need for prototypes. Date: Sat, 31 Jul 2010 17:05:32 +0200 Message-Id: <1280588752-9340-9-git-send-email-khc@pm.waw.pl> X-Mailer: git-send-email 1.7.1.1 In-Reply-To: References: MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Krzysztof Hałasa Signed-off-by: Krzysztof Hałasa --- drivers/net/wan/lmc/media.c | 940 +++++++++++++++++++++---------------------- 1 files changed, 450 insertions(+), 490 deletions(-) diff --git a/drivers/net/wan/lmc/media.c b/drivers/net/wan/lmc/media.c index baf6e43..9701d30 100644 --- a/drivers/net/wan/lmc/media.c +++ b/drivers/net/wan/lmc/media.c @@ -37,134 +37,318 @@ * the GNU General Public License version 2, incorporated herein by reference. */ -/* protocol independent method. */ -static void lmc_set_protocol(struct card * const, struct control *); - -/* media independent methods to check on media status, link, light LEDs, etc. */ -static void lmc_ds3_init(struct card * const); -static void lmc_ds3_default(struct card * const); -static void lmc_ds3_set_status(struct card * const, struct control *); -static void lmc_ds3_set_100ft(struct card * const, int); -static int lmc_ds3_get_link_status(struct card * const); -static void lmc_ds3_set_crc_length(struct card * const, int); -static void lmc_ds3_set_scram(struct card * const, int); -static void lmc_ds3_watchdog(struct card * const); - -static void lmc_hssi_init(struct card * const); -static void lmc_hssi_default(struct card * const); -static void lmc_hssi_set_status(struct card * const, struct control *); -static void lmc_hssi_set_clock(struct card * const, int); -static int lmc_hssi_get_link_status(struct card * const); -static void lmc_hssi_set_link_status(struct card * const, int); -static void lmc_hssi_set_crc_length(struct card * const, int); -static void lmc_hssi_watchdog(struct card * const); - -static void lmc_ssi_init(struct card * const); -static void lmc_ssi_default(struct card * const); -static void lmc_ssi_set_status(struct card * const, struct control *); -static void lmc_ssi_set_clock(struct card * const, int); -static void lmc_ssi_set_speed(struct card * const, struct control *); -static int lmc_ssi_get_link_status(struct card * const); -static void lmc_ssi_set_link_status(struct card * const, int); -static void lmc_ssi_set_crc_length(struct card * const, int); -static void lmc_ssi_watchdog(struct card * const); - -static void lmc_t1_init(struct card * const); -static void lmc_t1_default(struct card * const); -static void lmc_t1_set_status(struct card * const, struct control *); -static int lmc_t1_get_link_status(struct card * const); -static void lmc_t1_set_circuit_type(struct card * const, int); -static void lmc_t1_set_crc_length(struct card * const, int); -static void lmc_t1_set_clock(struct card * const, int); -static void lmc_t1_watchdog(struct card * const); - -static inline void write_av9110_bit(struct card *, int); -static void write_av9110(struct card *, u32, u32, u32, u32, u32); +static void lmc_set_protocol(struct card * const sc, struct control *ctl) +{ + if (!ctl) + sc->ictl.keepalive_onoff = LMC_CTL_ON; +} -struct media lmc_ds3_media = { - .init = lmc_ds3_init, - .defaults = lmc_ds3_default, - .set_status = lmc_ds3_set_status, - .set_cable_length = lmc_ds3_set_100ft, - .set_scrambler = lmc_ds3_set_scram, - .get_link_status = lmc_ds3_get_link_status, - .set_crc_length = lmc_ds3_set_crc_length, - .watchdog = lmc_ds3_watchdog, -}; -struct media lmc_hssi_media = { - .init = lmc_hssi_init, - .defaults = lmc_hssi_default, - .set_status = lmc_hssi_set_status, - .set_clock_source = lmc_hssi_set_clock, - .get_link_status = lmc_hssi_get_link_status, - .set_link_status = lmc_hssi_set_link_status, - .set_crc_length = lmc_hssi_set_crc_length, - .watchdog = lmc_hssi_watchdog, -}; +/* SSI methods */ -struct media lmc_ssi_media = { - .init = lmc_ssi_init, - .defaults = lmc_ssi_default, - .set_status = lmc_ssi_set_status, - .set_clock_source = lmc_ssi_set_clock, - .set_speed = lmc_ssi_set_speed, - .get_link_status = lmc_ssi_get_link_status, - .set_link_status = lmc_ssi_set_link_status, - .set_crc_length = lmc_ssi_set_crc_length, - .watchdog = lmc_ssi_watchdog, -}; +/* These are bits to program the ssi frequency generator */ +static inline void write_av9110_bit(struct card *sc, int c) +{ + /* set the data bit as we need it. */ + sc->lmc_gpio &= ~(LMC_GEP_CLK); + if (c & 0x01) + sc->lmc_gpio |= LMC_GEP_DATA; + else + sc->lmc_gpio &= ~(LMC_GEP_DATA); + LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); -struct media lmc_t1_media = { - .init = lmc_t1_init, - .defaults = lmc_t1_default, - .set_status = lmc_t1_set_status, - .set_clock_source = lmc_t1_set_clock, - .get_link_status = lmc_t1_get_link_status, - .set_crc_length = lmc_t1_set_crc_length, - .set_circuit_type = lmc_t1_set_circuit_type, - .watchdog = lmc_t1_watchdog, -}; + /* set the clock to high */ + sc->lmc_gpio |= LMC_GEP_CLK; + LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); -/* HSSI methods */ + /* set the clock to low again. */ + sc->lmc_gpio &= ~(LMC_GEP_CLK); + LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); +} -static void lmc_hssi_init(struct card * const sc) +static void write_av9110(struct card *sc, u32 n, u32 m, u32 v, u32 x, u32 r) { - sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5200; - lmc_gpio_mkoutput(sc, LMC_GEP_HSSI_CLOCK); + int i; + +#if 0 + printk(LMC_PRINTF_FMT ": speed %u, %d %d %d %d %d\n", + LMC_PRINTF_ARGS, sc->ictl.clock_rate, n, m, v, x, r); +#endif + + sc->lmc_gpio |= LMC_GEP_SSI_GENERATOR; + sc->lmc_gpio &= ~(LMC_GEP_DATA | LMC_GEP_CLK); + LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); + + /* Set the TXCLOCK, GENERATOR, SERIAL, and SERIALCLK as outputs. */ + lmc_gpio_mkoutput(sc, (LMC_GEP_DATA | LMC_GEP_CLK + | LMC_GEP_SSI_GENERATOR)); + + sc->lmc_gpio &= ~(LMC_GEP_SSI_GENERATOR); + LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); + + /* a shifting we will go... */ + for (i = 0; i < 7; i++) + write_av9110_bit(sc, n >> i); + for (i = 0; i < 7; i++) + write_av9110_bit(sc, m >> i); + for (i = 0; i < 1; i++) + write_av9110_bit(sc, v >> i); + for (i = 0; i < 2; i++) + write_av9110_bit(sc, x >> i); + for (i = 0; i < 2; i++) + write_av9110_bit(sc, r >> i); + for (i = 0; i < 5; i++) + write_av9110_bit(sc, 0x17 >> i); + + /* stop driving serial-related signals */ + lmc_gpio_mkinput(sc, (LMC_GEP_DATA | LMC_GEP_CLK | + LMC_GEP_SSI_GENERATOR)); } -static void lmc_hssi_default(struct card * const sc) +static void lmc_ssi_init(struct card * const sc) { - sc->lmc_miireg16 = LMC_MII16_LED_ALL; - lmc_hssi_set_link_status(sc, LMC_LINK_DOWN); - lmc_hssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_EXT); - lmc_hssi_set_crc_length(sc, LMC_CTL_CRC_LENGTH_16); + u16 mii17; + int cable; + + sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1000; + + mii17 = lmc_mii_readreg(sc, 0, 17); + + cable = (mii17 & LMC_MII17_SSI_CABLE_MASK) >> LMC_MII17_SSI_CABLE_SHIFT; + sc->ictl.cable_type = cable; + + lmc_gpio_mkoutput(sc, LMC_GEP_SSI_TXCLOCK); +} + +/* 1 == internal, 0 == external */ +static void lmc_ssi_set_clock(struct card * const sc, int ie) +{ + int old; + old = ie; + if (ie == LMC_CTL_CLOCK_SOURCE_EXT) { + sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK); + LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); + sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT; + if (ie != old) + printk(LMC_PRINTF_FMT ": clock external\n", + LMC_PRINTF_ARGS); + } else { + sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK; + LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); + sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT; + if (ie != old) + printk(LMC_PRINTF_FMT ": clock internal\n", + LMC_PRINTF_ARGS); + } +} + +static void lmc_ssi_set_speed(struct card * const sc, struct control *ctl) +{ + struct control *ictl = &sc->ictl; + lmc_av9110_t *av; + + /* original settings for clock rate of 100 Khz (8,25,0,0,2) were + incorrect. They should have been 80,125,1,3,3. There are 17 param + combinations to produce this freq. For 1.5 Mhz use 120,100,1,1,2 + (226 param. combinations) */ + if (ctl == NULL) { + av = &ictl->cardspec.ssi; + ictl->clock_rate = 1500000; + av->f = ictl->clock_rate; + av->n = 120; + av->m = 100; + av->v = 1; + av->x = 1; + av->r = 2; + write_av9110(sc, av->n, av->m, av->v, av->x, av->r); + return; + } + + av = &ctl->cardspec.ssi; + + if (av->f == 0) + return; + + ictl->clock_rate = av->f; /* really, this is the rate we are */ + ictl->cardspec.ssi = *av; + + write_av9110(sc, av->n, av->m, av->v, av->x, av->r); } /* Given a user provided state, set ourselves up to match it. This will always reset the card if needed. */ -static void lmc_hssi_set_status(struct card * const sc, struct control *ctl) +static void lmc_ssi_set_status(struct card * const sc, struct control *ctl) { if (ctl == NULL) { - lmc_hssi_set_clock(sc, sc->ictl.clock_source); + lmc_ssi_set_clock(sc, sc->ictl.clock_source); + lmc_ssi_set_speed(sc, &sc->ictl); lmc_set_protocol(sc, NULL); - return; } /* check for change in clock source */ - if (ctl->clock_source && !sc->ictl.clock_source) { - lmc_hssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_INT); + if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_INT + && sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_EXT) { + lmc_ssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_INT); sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_INT; - } else if (!ctl->clock_source && sc->ictl.clock_source) { + } else if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_EXT + && sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_INT) { + lmc_ssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_EXT); sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT; - lmc_hssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_EXT); } + if (ctl->clock_rate != sc->ictl.clock_rate) + lmc_ssi_set_speed(sc, ctl); + lmc_set_protocol(sc, ctl); } +/* Return hardware link status. 0 == link is down, 1 == link is up. */ +static int lmc_ssi_get_link_status(struct card * const sc) +{ + u16 link_status; + u32 ticks; + int ret = 1; + int hw_hdsk = 1; + + /* missing CTS? Hmm. If we require CTS on, we may never get the + link to come up, so omit it in this test. + + Also, it seems that with a loopback cable, DCD isn't asserted, + so just check for things like this: + - DSR _must_ be asserted. + - One of DCD or CTS must be asserted. */ + + /* LMC 1000 (SSI) LED definitions + - led0 green = power to adapter, Gate Array loaded & driver attached + - led1 green = DSR and DTR and RTS and CTS are set + - led2 green = Cable detected + - led3 red = No timing is available from the cable or the on-board + frequency generator. */ + + link_status = lmc_mii_readreg(sc, 0, 16); + + /* Is the transmit clock still available */ + ticks = LMC_CSR_READ(sc, csr_gp_timer); + ticks = 0x0000ffff - (ticks & 0x0000ffff); + + lmc_led_on(sc, LMC_MII16_LED0); + + /* transmit clock determination */ + if (sc->lmc_timing == LMC_CTL_CLOCK_SOURCE_INT) + lmc_led_off(sc, LMC_MII16_LED3); + else if (ticks == 0) { /* no clock found ? */ + ret = 0; + if (sc->last_led_err[3] != 1) { + sc->extra_stats.tx_lossOfClockCnt++; + printk(KERN_WARNING "%s: Lost Clock, Link Down\n", + sc->name); + } + sc->last_led_err[3] = 1; + lmc_led_on(sc, LMC_MII16_LED3); /* turn ON red LED */ + } else { + if (sc->last_led_err[3] == 1) + printk(KERN_WARNING "%s: Clock Returned\n", sc->name); + sc->last_led_err[3] = 0; + lmc_led_off(sc, LMC_MII16_LED3); /* turn OFF red LED */ + } + + if ((link_status & LMC_MII16_SSI_DSR) == 0) { /* Also HSSI CA */ + ret = 0; + hw_hdsk = 0; + } + +#ifdef CONFIG_LMC_IGNORE_HARDWARE_HANDSHAKE + if ((link_status & (LMC_MII16_SSI_CTS | LMC_MII16_SSI_DCD)) == 0) { + ret = 0; + hw_hdsk = 0; + } +#endif + + if (hw_hdsk == 0) { + if (sc->last_led_err[1] != 1) + printk(KERN_WARNING "%s: DSR not asserted\n", sc->name); + sc->last_led_err[1] = 1; + lmc_led_off(sc, LMC_MII16_LED1); + } else { + if (sc->last_led_err[1] != 0) + printk(KERN_WARNING "%s: DSR now asserted\n", sc->name); + sc->last_led_err[1] = 0; + lmc_led_on(sc, LMC_MII16_LED1); + } + + if (ret == 1) + lmc_led_on(sc, LMC_MII16_LED2); /* Over all good status? */ + + return ret; +} + +static void lmc_ssi_set_link_status(struct card * const sc, int state) +{ + if (state == LMC_LINK_UP) { + sc->lmc_miireg16 |= (LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS); + printk(LMC_PRINTF_FMT ": asserting DTR and RTS\n", + LMC_PRINTF_ARGS); + } else { + sc->lmc_miireg16 &= ~(LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS); + printk(LMC_PRINTF_FMT ": deasserting DTR and RTS\n", + LMC_PRINTF_ARGS); + } + + lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); + +} + +/* 0 == 16bit, 1 == 32bit */ +static void lmc_ssi_set_crc_length(struct card * const sc, int state) +{ + if (state == LMC_CTL_CRC_LENGTH_32) { + /* 32 bit */ + sc->lmc_miireg16 |= LMC_MII16_SSI_CRC; + sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32; + sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4; + + } else { + /* 16 bit */ + sc->lmc_miireg16 &= ~LMC_MII16_SSI_CRC; + sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16; + sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2; + } + + lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); +} + +static void lmc_ssi_default(struct card * const sc) +{ + sc->lmc_miireg16 = LMC_MII16_LED_ALL; + + /* make TXCLOCK always be an output */ + lmc_gpio_mkoutput(sc, LMC_GEP_SSI_TXCLOCK); + + lmc_ssi_set_link_status(sc, LMC_LINK_DOWN); + lmc_ssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_EXT); + lmc_ssi_set_speed(sc, NULL); + lmc_ssi_set_crc_length(sc, LMC_CTL_CRC_LENGTH_16); +} + +static void lmc_ssi_watchdog(struct card * const sc) +{ + u16 mii17 = lmc_mii_readreg(sc, 0, 17); + if (((mii17 >> 3) & 7) == 7) + lmc_led_off(sc, LMC_MII16_LED2); + else + lmc_led_on(sc, LMC_MII16_LED2); +} + + +/* HSSI methods */ + +static void lmc_hssi_init(struct card * const sc) +{ + sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5200; + lmc_gpio_mkoutput(sc, LMC_GEP_HSSI_CLOCK); +} + /* 1 == internal, 0 == external */ static void lmc_hssi_set_clock(struct card * const sc, int ie) { @@ -187,8 +371,31 @@ static void lmc_hssi_set_clock(struct card * const sc, int ie) } } +/* Given a user provided state, set ourselves up to match it. + This will always reset the card if needed. */ +static void lmc_hssi_set_status(struct card * const sc, struct control *ctl) +{ + if (ctl == NULL) { + lmc_hssi_set_clock(sc, sc->ictl.clock_source); + lmc_set_protocol(sc, NULL); + + return; + } + + /* check for change in clock source */ + if (ctl->clock_source && !sc->ictl.clock_source) { + lmc_hssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_INT); + sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_INT; + } else if (!ctl->clock_source && sc->ictl.clock_source) { + sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT; + lmc_hssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_EXT); + } + + lmc_set_protocol(sc, ctl); +} + /* Return hardware link status. 0 == link is down, 1 == link is up. */ -static int lmc_hssi_get_link_status(struct card * const sc) +static inline int lmc_hssi_get_link_status(struct card * const sc) { /* We're using the same code as SSI since they're practically the same */ @@ -226,6 +433,15 @@ static void lmc_hssi_watchdog(struct card * const sc) /* HSSI is blank */ } +static void lmc_hssi_default(struct card * const sc) +{ + sc->lmc_miireg16 = LMC_MII16_LED_ALL; + lmc_hssi_set_link_status(sc, LMC_LINK_DOWN); + lmc_hssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_EXT); + lmc_hssi_set_crc_length(sc, LMC_CTL_CRC_LENGTH_16); +} + + /* DS3 methods */ /* Set cable length */ @@ -241,13 +457,17 @@ static void lmc_ds3_set_100ft(struct card * const sc, int ie) lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); } -static void lmc_ds3_default(struct card * const sc) +/* 1 == DS3 payload scrambled, 0 == not scrambled */ +static void lmc_ds3_set_scram(struct card * const sc, int ie) { - sc->lmc_miireg16 = LMC_MII16_LED_ALL; - - lmc_ds3_set_100ft(sc, LMC_CTL_CABLE_LENGTH_LT_100FT); - lmc_ds3_set_scram(sc, LMC_CTL_OFF); - lmc_ds3_set_crc_length(sc, LMC_CTL_CRC_LENGTH_16); + if (ie == LMC_CTL_ON) { + sc->lmc_miireg16 |= LMC_MII16_DS3_SCRAM; + sc->ictl.scrambler_onoff = LMC_CTL_ON; + } else { + sc->lmc_miireg16 &= ~LMC_MII16_DS3_SCRAM; + sc->ictl.scrambler_onoff = LMC_CTL_OFF; + } + lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); } /* Given a user provided state, set ourselves up to match it. @@ -305,19 +525,6 @@ static void lmc_ds3_init(struct card * const sc) } } -/* 1 == DS3 payload scrambled, 0 == not scrambled */ -static void lmc_ds3_set_scram(struct card * const sc, int ie) -{ - if (ie == LMC_CTL_ON) { - sc->lmc_miireg16 |= LMC_MII16_DS3_SCRAM; - sc->ictl.scrambler_onoff = LMC_CTL_ON; - } else { - sc->lmc_miireg16 &= ~LMC_MII16_DS3_SCRAM; - sc->ictl.scrambler_onoff = LMC_CTL_OFF; - } - lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); -} - /* Return hardware link status. 0 == link is down, 1 == link is up. */ static int lmc_ds3_get_link_status(struct card * const sc) { @@ -339,390 +546,103 @@ static int lmc_ds3_get_link_status(struct card * const sc) lmc_led_on(sc, LMC_DS3_LED2); if ((link_status & LMC_FRAMER_REG0_DLOS) || - (link_status & LMC_FRAMER_REG0_OOFS)) { - ret = 0; - if (sc->last_led_err[3] != 1) { - u16 r1; - - /* Turn on Xbit error as our cisco does */ - lmc_mii_writereg(sc, 0, 17, 01); - r1 = lmc_mii_readreg(sc, 0, 18); - r1 &= 0xfe; - lmc_mii_writereg(sc, 0, 18, r1); - printk(KERN_WARNING - "%s: Red Alarm - Loss of Signal or Loss of Framing\n", - sc->name); - } - lmc_led_on(sc, LMC_DS3_LED3); /* turn on red LED */ - sc->last_led_err[3] = 1; - } else { - lmc_led_off(sc, LMC_DS3_LED3); /* turn on red LED */ - if (sc->last_led_err[3] == 1) { - u16 r1; - /* Turn off Xbit error */ - lmc_mii_writereg(sc, 0, 17, 01); - r1 = lmc_mii_readreg(sc, 0, 18); - r1 |= 0x01; - lmc_mii_writereg(sc, 0, 18, r1); - } - sc->last_led_err[3] = 0; - } - - lmc_mii_writereg(sc, 0, 17, 0x10); - link_status_11 = lmc_mii_readreg(sc, 0, 18); - if ((link_status & LMC_FRAMER_REG0_AIS) || - (link_status_11 & LMC_FRAMER_REG10_XBIT)) { - ret = 0; - if (sc->last_led_err[0] != 1) { - printk(KERN_WARNING - "%s: AIS Alarm or XBit Error\n", sc->name); - printk(KERN_WARNING - "%s: Remote end has loss of signal or framing\n", - sc->name); - } - lmc_led_on(sc, LMC_DS3_LED0); - sc->last_led_err[0] = 1; - } else { - lmc_led_off(sc, LMC_DS3_LED0); - sc->last_led_err[0] = 0; - } - - lmc_mii_writereg(sc, 0, 17, 9); - link_status = lmc_mii_readreg(sc, 0, 18); - - if (link_status & LMC_FRAMER_REG9_RBLUE) { - ret = 0; - if (sc->last_led_err[1] != 1) { - printk(KERN_WARNING - "%s: Blue Alarm - Receiving all 1's\n", - sc->name); - } - lmc_led_on(sc, LMC_DS3_LED1); - sc->last_led_err[1] = 1; - } else { - lmc_led_off(sc, LMC_DS3_LED1); - sc->last_led_err[1] = 0; - } - - return ret; -} - -/* 0 == 16bit, 1 == 32bit */ -static void lmc_ds3_set_crc_length(struct card * const sc, int state) -{ - if (state == LMC_CTL_CRC_LENGTH_32) { - /* 32 bit */ - sc->lmc_miireg16 |= LMC_MII16_DS3_CRC; - sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32; - } else { - /* 16 bit */ - sc->lmc_miireg16 &= ~LMC_MII16_DS3_CRC; - sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16; - } - - lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); -} - -static void lmc_ds3_watchdog(struct card * const sc) -{ -} - - -/* SSI methods */ - -static void lmc_ssi_init(struct card * const sc) -{ - u16 mii17; - int cable; - - sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1000; - - mii17 = lmc_mii_readreg(sc, 0, 17); - - cable = (mii17 & LMC_MII17_SSI_CABLE_MASK) >> LMC_MII17_SSI_CABLE_SHIFT; - sc->ictl.cable_type = cable; - - lmc_gpio_mkoutput(sc, LMC_GEP_SSI_TXCLOCK); -} - -static void lmc_ssi_default(struct card * const sc) -{ - sc->lmc_miireg16 = LMC_MII16_LED_ALL; - - /* make TXCLOCK always be an output */ - lmc_gpio_mkoutput(sc, LMC_GEP_SSI_TXCLOCK); - - lmc_ssi_set_link_status(sc, LMC_LINK_DOWN); - lmc_ssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_EXT); - lmc_ssi_set_speed(sc, NULL); - lmc_ssi_set_crc_length(sc, LMC_CTL_CRC_LENGTH_16); -} - -/* Given a user provided state, set ourselves up to match it. - This will always reset the card if needed. */ -static void lmc_ssi_set_status(struct card * const sc, struct control *ctl) -{ - if (ctl == NULL) { - lmc_ssi_set_clock(sc, sc->ictl.clock_source); - lmc_ssi_set_speed(sc, &sc->ictl); - lmc_set_protocol(sc, NULL); - return; - } - - /* check for change in clock source */ - if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_INT - && sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_EXT) { - lmc_ssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_INT); - sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_INT; - } else if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_EXT - && sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_INT) { - lmc_ssi_set_clock(sc, LMC_CTL_CLOCK_SOURCE_EXT); - sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT; - } - - if (ctl->clock_rate != sc->ictl.clock_rate) - lmc_ssi_set_speed(sc, ctl); - - lmc_set_protocol(sc, ctl); -} - -/* 1 == internal, 0 == external */ -static void lmc_ssi_set_clock(struct card * const sc, int ie) -{ - int old; - old = ie; - if (ie == LMC_CTL_CLOCK_SOURCE_EXT) { - sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK); - LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); - sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT; - if (ie != old) - printk(LMC_PRINTF_FMT ": clock external\n", - LMC_PRINTF_ARGS); - } else { - sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK; - LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); - sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT; - if (ie != old) - printk(LMC_PRINTF_FMT ": clock internal\n", - LMC_PRINTF_ARGS); - } -} - -static void lmc_ssi_set_speed(struct card * const sc, struct control *ctl) -{ - struct control *ictl = &sc->ictl; - lmc_av9110_t *av; - - /* original settings for clock rate of 100 Khz (8,25,0,0,2) were - incorrect. They should have been 80,125,1,3,3. There are 17 param - combinations to produce this freq. For 1.5 Mhz use 120,100,1,1,2 - (226 param. combinations) */ - if (ctl == NULL) { - av = &ictl->cardspec.ssi; - ictl->clock_rate = 1500000; - av->f = ictl->clock_rate; - av->n = 120; - av->m = 100; - av->v = 1; - av->x = 1; - av->r = 2; - write_av9110(sc, av->n, av->m, av->v, av->x, av->r); - return; - } - - av = &ctl->cardspec.ssi; - - if (av->f == 0) - return; - - ictl->clock_rate = av->f; /* really, this is the rate we are */ - ictl->cardspec.ssi = *av; - - write_av9110(sc, av->n, av->m, av->v, av->x, av->r); -} - -/* Return hardware link status. 0 == link is down, 1 == link is up. */ -static int lmc_ssi_get_link_status(struct card * const sc) -{ - u16 link_status; - u32 ticks; - int ret = 1; - int hw_hdsk = 1; - - /* missing CTS? Hmm. If we require CTS on, we may never get the - link to come up, so omit it in this test. - - Also, it seems that with a loopback cable, DCD isn't asserted, - so just check for things like this: - - DSR _must_ be asserted. - - One of DCD or CTS must be asserted. */ - - /* LMC 1000 (SSI) LED definitions - - led0 green = power to adapter, Gate Array loaded & driver attached - - led1 green = DSR and DTR and RTS and CTS are set - - led2 green = Cable detected - - led3 red = No timing is available from the cable or the on-board - frequency generator. */ - - link_status = lmc_mii_readreg(sc, 0, 16); - - /* Is the transmit clock still available */ - ticks = LMC_CSR_READ(sc, csr_gp_timer); - ticks = 0x0000ffff - (ticks & 0x0000ffff); - - lmc_led_on(sc, LMC_MII16_LED0); - - /* transmit clock determination */ - if (sc->lmc_timing == LMC_CTL_CLOCK_SOURCE_INT) - lmc_led_off(sc, LMC_MII16_LED3); - else if (ticks == 0) { /* no clock found ? */ + (link_status & LMC_FRAMER_REG0_OOFS)) { ret = 0; if (sc->last_led_err[3] != 1) { - sc->extra_stats.tx_lossOfClockCnt++; - printk(KERN_WARNING "%s: Lost Clock, Link Down\n", + u16 r1; + + /* Turn on Xbit error as our cisco does */ + lmc_mii_writereg(sc, 0, 17, 01); + r1 = lmc_mii_readreg(sc, 0, 18); + r1 &= 0xfe; + lmc_mii_writereg(sc, 0, 18, r1); + printk(KERN_WARNING + "%s: Red Alarm - Loss of Signal or Loss of Framing\n", sc->name); } + lmc_led_on(sc, LMC_DS3_LED3); /* turn on red LED */ sc->last_led_err[3] = 1; - lmc_led_on(sc, LMC_MII16_LED3); /* turn ON red LED */ } else { - if (sc->last_led_err[3] == 1) - printk(KERN_WARNING "%s: Clock Returned\n", sc->name); + lmc_led_off(sc, LMC_DS3_LED3); /* turn on red LED */ + if (sc->last_led_err[3] == 1) { + u16 r1; + /* Turn off Xbit error */ + lmc_mii_writereg(sc, 0, 17, 01); + r1 = lmc_mii_readreg(sc, 0, 18); + r1 |= 0x01; + lmc_mii_writereg(sc, 0, 18, r1); + } sc->last_led_err[3] = 0; - lmc_led_off(sc, LMC_MII16_LED3); /* turn OFF red LED */ } - if ((link_status & LMC_MII16_SSI_DSR) == 0) { /* Also HSSI CA */ + lmc_mii_writereg(sc, 0, 17, 0x10); + link_status_11 = lmc_mii_readreg(sc, 0, 18); + if ((link_status & LMC_FRAMER_REG0_AIS) || + (link_status_11 & LMC_FRAMER_REG10_XBIT)) { ret = 0; - hw_hdsk = 0; + if (sc->last_led_err[0] != 1) { + printk(KERN_WARNING + "%s: AIS Alarm or XBit Error\n", sc->name); + printk(KERN_WARNING + "%s: Remote end has loss of signal or framing\n", + sc->name); + } + lmc_led_on(sc, LMC_DS3_LED0); + sc->last_led_err[0] = 1; + } else { + lmc_led_off(sc, LMC_DS3_LED0); + sc->last_led_err[0] = 0; } -#ifdef CONFIG_LMC_IGNORE_HARDWARE_HANDSHAKE - if ((link_status & (LMC_MII16_SSI_CTS | LMC_MII16_SSI_DCD)) == 0) { - ret = 0; - hw_hdsk = 0; - } -#endif + lmc_mii_writereg(sc, 0, 17, 9); + link_status = lmc_mii_readreg(sc, 0, 18); - if (hw_hdsk == 0) { - if (sc->last_led_err[1] != 1) - printk(KERN_WARNING "%s: DSR not asserted\n", sc->name); + if (link_status & LMC_FRAMER_REG9_RBLUE) { + ret = 0; + if (sc->last_led_err[1] != 1) { + printk(KERN_WARNING + "%s: Blue Alarm - Receiving all 1's\n", + sc->name); + } + lmc_led_on(sc, LMC_DS3_LED1); sc->last_led_err[1] = 1; - lmc_led_off(sc, LMC_MII16_LED1); } else { - if (sc->last_led_err[1] != 0) - printk(KERN_WARNING "%s: DSR now asserted\n", sc->name); + lmc_led_off(sc, LMC_DS3_LED1); sc->last_led_err[1] = 0; - lmc_led_on(sc, LMC_MII16_LED1); } - if (ret == 1) - lmc_led_on(sc, LMC_MII16_LED2); /* Over all good status? */ - return ret; } -static void lmc_ssi_set_link_status(struct card * const sc, int state) -{ - if (state == LMC_LINK_UP) { - sc->lmc_miireg16 |= (LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS); - printk(LMC_PRINTF_FMT ": asserting DTR and RTS\n", - LMC_PRINTF_ARGS); - } else { - sc->lmc_miireg16 &= ~(LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS); - printk(LMC_PRINTF_FMT ": deasserting DTR and RTS\n", - LMC_PRINTF_ARGS); - } - - lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); - -} - /* 0 == 16bit, 1 == 32bit */ -static void lmc_ssi_set_crc_length(struct card * const sc, int state) +static void lmc_ds3_set_crc_length(struct card * const sc, int state) { if (state == LMC_CTL_CRC_LENGTH_32) { /* 32 bit */ - sc->lmc_miireg16 |= LMC_MII16_SSI_CRC; + sc->lmc_miireg16 |= LMC_MII16_DS3_CRC; sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32; - sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4; - } else { /* 16 bit */ - sc->lmc_miireg16 &= ~LMC_MII16_SSI_CRC; + sc->lmc_miireg16 &= ~LMC_MII16_DS3_CRC; sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16; - sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2; } lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); } -/* These are bits to program the ssi frequency generator */ -static inline void write_av9110_bit(struct card *sc, int c) +static void lmc_ds3_watchdog(struct card * const sc) { - /* set the data bit as we need it. */ - sc->lmc_gpio &= ~(LMC_GEP_CLK); - if (c & 0x01) - sc->lmc_gpio |= LMC_GEP_DATA; - else - sc->lmc_gpio &= ~(LMC_GEP_DATA); - LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); - - /* set the clock to high */ - sc->lmc_gpio |= LMC_GEP_CLK; - LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); - - /* set the clock to low again. */ - sc->lmc_gpio &= ~(LMC_GEP_CLK); - LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); } -static void write_av9110(struct card *sc, u32 n, u32 m, u32 v, u32 x, u32 r) +static void lmc_ds3_default(struct card * const sc) { - int i; - -#if 0 - printk(LMC_PRINTF_FMT ": speed %u, %d %d %d %d %d\n", - LMC_PRINTF_ARGS, sc->ictl.clock_rate, n, m, v, x, r); -#endif - - sc->lmc_gpio |= LMC_GEP_SSI_GENERATOR; - sc->lmc_gpio &= ~(LMC_GEP_DATA | LMC_GEP_CLK); - LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); - - /* Set the TXCLOCK, GENERATOR, SERIAL, and SERIALCLK as outputs. */ - lmc_gpio_mkoutput(sc, (LMC_GEP_DATA | LMC_GEP_CLK - | LMC_GEP_SSI_GENERATOR)); - - sc->lmc_gpio &= ~(LMC_GEP_SSI_GENERATOR); - LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); - - /* a shifting we will go... */ - for (i = 0; i < 7; i++) - write_av9110_bit(sc, n >> i); - for (i = 0; i < 7; i++) - write_av9110_bit(sc, m >> i); - for (i = 0; i < 1; i++) - write_av9110_bit(sc, v >> i); - for (i = 0; i < 2; i++) - write_av9110_bit(sc, x >> i); - for (i = 0; i < 2; i++) - write_av9110_bit(sc, r >> i); - for (i = 0; i < 5; i++) - write_av9110_bit(sc, 0x17 >> i); + sc->lmc_miireg16 = LMC_MII16_LED_ALL; - /* stop driving serial-related signals */ - lmc_gpio_mkinput(sc, (LMC_GEP_DATA | LMC_GEP_CLK | - LMC_GEP_SSI_GENERATOR)); + lmc_ds3_set_100ft(sc, LMC_CTL_CABLE_LENGTH_LT_100FT); + lmc_ds3_set_scram(sc, LMC_CTL_OFF); + lmc_ds3_set_crc_length(sc, LMC_CTL_CRC_LENGTH_16); } -static void lmc_ssi_watchdog(struct card * const sc) -{ - u16 mii17 = lmc_mii_readreg(sc, 0, 17); - if (((mii17 >> 3) & 7) == 7) - lmc_led_off(sc, LMC_MII16_LED2); - else - lmc_led_on(sc, LMC_MII16_LED2); -} /* T1 methods */ @@ -742,6 +662,21 @@ static int lmc_t1_read(struct card * const sc, int a) } */ +/* 1 == T1 Circuit Type , 0 == E1 Circuit Type */ +static void lmc_t1_set_circuit_type(struct card * const sc, int ie) +{ + if (ie == LMC_CTL_CIRCUIT_TYPE_T1) { + sc->lmc_miireg16 |= LMC_MII16_T1_Z; + sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_T1; + printk(KERN_INFO "%s: In T1 Mode\n", sc->name); + } else { + sc->lmc_miireg16 &= ~LMC_MII16_T1_Z; + sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_E1; + printk(KERN_INFO "%s: In E1 Mode\n", sc->name); + } + + lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); +} static void lmc_t1_init(struct card * const sc) { @@ -802,14 +737,6 @@ static void lmc_t1_init(struct card * const sc) sc->lmc_miireg16 = mii16; } -static void lmc_t1_default(struct card * const sc) -{ - sc->lmc_miireg16 = LMC_MII16_LED_ALL; - lmc_t1_set_circuit_type(sc, LMC_CTL_CIRCUIT_TYPE_T1); - lmc_t1_set_crc_length(sc, LMC_CTL_CRC_LENGTH_16); - /* Right now we can only clock from out internal source */ - sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT; -} /* Given a user provided state, set ourselves up to match it. This will always reset the card if needed. */ static void lmc_t1_set_status(struct card * const sc, struct control *ctl) @@ -939,22 +866,6 @@ static int lmc_t1_get_link_status(struct card * const sc) return ret; } -/* 1 == T1 Circuit Type , 0 == E1 Circuit Type */ -static void lmc_t1_set_circuit_type(struct card * const sc, int ie) -{ - if (ie == LMC_CTL_CIRCUIT_TYPE_T1) { - sc->lmc_miireg16 |= LMC_MII16_T1_Z; - sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_T1; - printk(KERN_INFO "%s: In T1 Mode\n", sc->name); - } else { - sc->lmc_miireg16 &= ~LMC_MII16_T1_Z; - sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_E1; - printk(KERN_INFO "%s: In E1 Mode\n", sc->name); - } - - lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); -} - /* 0 == 16bit, 1 == 32bit */ static void lmc_t1_set_crc_length(struct card * const sc, int state) { @@ -1000,8 +911,57 @@ static void lmc_t1_watchdog(struct card * const sc) { } -static void lmc_set_protocol(struct card * const sc, struct control *ctl) +static void lmc_t1_default(struct card * const sc) { - if (!ctl) - sc->ictl.keepalive_onoff = LMC_CTL_ON; + sc->lmc_miireg16 = LMC_MII16_LED_ALL; + lmc_t1_set_circuit_type(sc, LMC_CTL_CIRCUIT_TYPE_T1); + lmc_t1_set_crc_length(sc, LMC_CTL_CRC_LENGTH_16); + /* Right now we can only clock from out internal source */ + sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT; } + + +struct media lmc_ssi_media = { + .init = lmc_ssi_init, + .defaults = lmc_ssi_default, + .set_status = lmc_ssi_set_status, + .set_clock_source = lmc_ssi_set_clock, + .set_speed = lmc_ssi_set_speed, + .get_link_status = lmc_ssi_get_link_status, + .set_link_status = lmc_ssi_set_link_status, + .set_crc_length = lmc_ssi_set_crc_length, + .watchdog = lmc_ssi_watchdog, +}; + +struct media lmc_hssi_media = { + .init = lmc_hssi_init, + .defaults = lmc_hssi_default, + .set_status = lmc_hssi_set_status, + .set_clock_source = lmc_hssi_set_clock, + .get_link_status = lmc_hssi_get_link_status, + .set_link_status = lmc_hssi_set_link_status, + .set_crc_length = lmc_hssi_set_crc_length, + .watchdog = lmc_hssi_watchdog, +}; + +struct media lmc_ds3_media = { + .init = lmc_ds3_init, + .defaults = lmc_ds3_default, + .set_status = lmc_ds3_set_status, + .set_cable_length = lmc_ds3_set_100ft, + .set_scrambler = lmc_ds3_set_scram, + .get_link_status = lmc_ds3_get_link_status, + .set_crc_length = lmc_ds3_set_crc_length, + .watchdog = lmc_ds3_watchdog, +}; + +struct media lmc_t1_media = { + .init = lmc_t1_init, + .defaults = lmc_t1_default, + .set_status = lmc_t1_set_status, + .set_clock_source = lmc_t1_set_clock, + .get_link_status = lmc_t1_get_link_status, + .set_crc_length = lmc_t1_set_crc_length, + .set_circuit_type = lmc_t1_set_circuit_type, + .watchdog = lmc_t1_watchdog, +};