cregit-Linux how code gets into the kernel

Release 4.14 drivers/isdn/hisax/enternow_pci.c

/* enternow_pci.c,v 0.99 2001/10/02
 *
 * enternow_pci.c       Card-specific routines for
 *                      Formula-n enter:now ISDN PCI ab
 *                      Gerdes AG Power ISDN PCI
 *                      Woerltronic SA 16 PCI
 *                      (based on HiSax driver by Karsten Keil)
 *
 * Author               Christoph Ersfeld <info@formula-n.de>
 *                      Formula-n Europe AG (www.formula-n.com)
 *                      previously Gerdes AG
 *
 *
 *                      This file is (c) under GNU PUBLIC LICENSE
 *
 * Notes:
 * This driver interfaces to netjet.c which performs B-channel
 * processing.
 *
 * Version 0.99 is the first release of this driver and there are
 * certainly a few bugs.
 * It isn't testet on linux 2.4 yet, so consider this code to be
 * beta.
 *
 * Please don't report me any malfunction without sending
 * (compressed) debug-logs.
 * It would be nearly impossible to retrace it.
 *
 * Log D-channel-processing as follows:
 *
 * 1. Load hisax with card-specific parameters, this example ist for
 *    Formula-n enter:now ISDN PCI and compatible
 *    (f.e. Gerdes Power ISDN PCI)
 *
 *    modprobe hisax type=41 protocol=2 id=gerdes
 *
 *    if you chose an other value for id, you need to modify the
 *    code below, too.
 *
 * 2. set debug-level
 *
 *    hisaxctrl gerdes 1 0x3ff
 *    hisaxctrl gerdes 11 0x4f
 *    cat /dev/isdnctrl >> ~/log &
 *
 * Please take also a look into /var/log/messages if there is
 * anything importand concerning HISAX.
 *
 *
 * Credits:
 * Programming the driver for Formula-n enter:now ISDN PCI and
 * necessary the driver for the used Amd 7930 D-channel-controller
 * was spnsored by Formula-n Europe AG.
 * Thanks to Karsten Keil and Petr Novak, who gave me support in
 * Hisax-specific questions.
 * I want so say special thanks to Carl-Friedrich Braun, who had to
 * answer a lot of questions about generally ISDN and about handling
 * of the Amd-Chip.
 *
 */


#include "hisax.h"
#include "isac.h"
#include "isdnl1.h"
#include "amd7930_fn.h"
#include <linux/interrupt.h>
#include <linux/ppp_defs.h>
#include <linux/pci.h>
#include <linux/init.h>
#include "netjet.h"




static const char *enternow_pci_rev = "$Revision: 1.1.4.5 $";


/* for PowerISDN PCI */

#define TJ_AMD_IRQ                                              0x20

#define TJ_LED1                                                 0x40

#define TJ_LED2                                                 0x80


/* The window to [the] AMD [chip]...
 * From address hw.njet.base + TJ_AMD_PORT onwards, the AMD
 * maps [consecutive/multiple] 8 bits into the TigerJet I/O space
 * -> 0x01 of the AMD at hw.njet.base + 0C4 */

#define TJ_AMD_PORT                                             0xC0



/* *************************** I/O-Interface functions ************************************* */


/* cs->readisac, macro rByteAMD */

static unsigned char ReadByteAmd7930(struct IsdnCardState *cs, unsigned char offset) { /* direct register */ if (offset < 8) return (inb(cs->hw.njet.isac + 4 * offset)); /* indirect register */ else { outb(offset, cs->hw.njet.isac + 4 * AMD_CR); return (inb(cs->hw.njet.isac + 4 * AMD_DR)); } }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski6885.00%133.33%
Adrian Bunk1012.50%133.33%
Jan Engelhardt22.50%133.33%
Total80100.00%3100.00%

/* cs->writeisac, macro wByteAMD */
static void WriteByteAmd7930(struct IsdnCardState *cs, unsigned char offset, unsigned char value) { /* direct register */ if (offset < 8) outb(value, cs->hw.njet.isac + 4 * offset); /* indirect register */ else { outb(offset, cs->hw.njet.isac + 4 * AMD_CR); outb(value, cs->hw.njet.isac + 4 * AMD_DR); } }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski6580.25%133.33%
Adrian Bunk1417.28%133.33%
Jan Engelhardt22.47%133.33%
Total81100.00%3100.00%


static void enpci_setIrqMask(struct IsdnCardState *cs, unsigned char val) { if (!val) outb(0x00, cs->hw.njet.base + NETJET_IRQMASK1); else outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1); }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski4282.35%150.00%
Adrian Bunk917.65%150.00%
Total51100.00%2100.00%


static unsigned char dummyrr(struct IsdnCardState *cs, int chan, unsigned char off) { return (5); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton2083.33%150.00%
Adrian Bunk416.67%150.00%
Total24100.00%2100.00%


static void dummywr(struct IsdnCardState *cs, int chan, unsigned char off, unsigned char value) { }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton1780.95%150.00%
Adrian Bunk419.05%150.00%
Total21100.00%2100.00%

/* ******************************************************************************** */
static void reset_enpci(struct IsdnCardState *cs) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "enter:now PCI: reset"); /* Reset on, (also for AMD) */ cs->hw.njet.ctrl_reg = 0x07; outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL); mdelay(20); /* Reset off */ cs->hw.njet.ctrl_reg = 0x30; outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL); /* 20ms delay */ mdelay(20); cs->hw.njet.auxd = 0; // LED-status cs->hw.njet.dmactrl = 0; outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL); outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1); outb(cs->hw.njet.auxd, cs->hw.njet.auxa); // LED off }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski14784.97%133.33%
Adrian Bunk2011.56%133.33%
Andrew Morton63.47%133.33%
Total173100.00%3100.00%


static int enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) { u_long flags; unsigned char *chan; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "enter:now PCI: card_msg: 0x%04X", mt); switch (mt) { case CARD_RESET: spin_lock_irqsave(&cs->lock, flags); reset_enpci(cs); Amd7930_init(cs); spin_unlock_irqrestore(&cs->lock, flags); break; case CARD_RELEASE: release_io_netjet(cs); break; case CARD_INIT: reset_enpci(cs); inittiger(cs); /* irq must be on here */ Amd7930_init(cs); break; case CARD_TEST: break; case MDL_ASSIGN: /* TEI assigned, LED1 on */ cs->hw.njet.auxd = TJ_AMD_IRQ << 1; outb(cs->hw.njet.auxd, cs->hw.njet.base + NETJET_AUXDATA); break; case MDL_REMOVE: /* TEI removed, LEDs off */ cs->hw.njet.auxd = 0; outb(0x00, cs->hw.njet.base + NETJET_AUXDATA); break; case MDL_BC_ASSIGN: /* activate B-channel */ chan = (unsigned char *)arg; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", *chan); cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (*chan + 1)), "MDL_BC_ASSIGN"); /* at least one b-channel in use, LED 2 on */ cs->hw.njet.auxd |= TJ_AMD_IRQ << 2; outb(cs->hw.njet.auxd, cs->hw.njet.base + NETJET_AUXDATA); break; case MDL_BC_RELEASE: /* deactivate B-channel */ chan = (unsigned char *)arg; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", *chan); cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(*chan + 1)), "MDL_BC_RELEASE"); /* no b-channel active -> LED2 off */ if (!(cs->dc.amd7930.lmr1 & 3)) { cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2); outb(cs->hw.njet.auxd, cs->hw.njet.base + NETJET_AUXDATA); } break; default: break; } return (0); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton19748.76%125.00%
Kai Germaschewski18345.30%250.00%
Adrian Bunk245.94%125.00%
Total404100.00%4100.00%


static irqreturn_t enpci_interrupt(int intno, void *dev_id) { struct IsdnCardState *cs = dev_id; unsigned char s0val, s1val, ir; u_long flags; spin_lock_irqsave(&cs->lock, flags); s1val = inb(cs->hw.njet.base + NETJET_IRQSTAT1); /* AMD threw an interrupt */ if (!(s1val & TJ_AMD_IRQ)) { /* read and clear interrupt-register */ ir = ReadByteAmd7930(cs, 0x00); Amd7930_interrupt(cs, ir); s1val = 1; } else s1val = 0; s0val = inb(cs->hw.njet.base + NETJET_IRQSTAT0); if ((s0val | s1val) == 0) { // shared IRQ spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; } if (s0val) outb(s0val, cs->hw.njet.base + NETJET_IRQSTAT0); /* DMA-Interrupt: B-channel-stuff */ /* set bits in sval to indicate which page is free */ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) /* the 2nd write page is free */ s0val = 0x08; else /* the 1st write page is free */ s0val = 0x04; if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) /* the 2nd read page is free */ s0val = s0val | 0x02; else /* the 1st read page is free */ s0val = s0val | 0x01; if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */ { if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } cs->hw.njet.irqstat0 = s0val; if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) /* we have a read dma int */ read_tiger(cs); if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) != (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE)) /* we have a write dma int */ write_tiger(cs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski23462.07%350.00%
Andrew Morton13636.07%233.33%
Adrian Bunk71.86%116.67%
Total377100.00%6100.00%


static int en_pci_probe(struct pci_dev *dev_netjet, struct IsdnCardState *cs) { if (pci_enable_device(dev_netjet)) return (0); cs->irq = dev_netjet->irq; if (!cs->irq) { printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n"); return (0); } cs->hw.njet.base = pci_resource_start(dev_netjet, 0); if (!cs->hw.njet.base) { printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n"); return (0); } /* checks Sub-Vendor ID because system crashes with Traverse-Card */ if ((dev_netjet->subsystem_vendor != 0x55) || (dev_netjet->subsystem_device != 0x02)) { printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n"); printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n"); return (0); } return (1); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton8259.42%125.00%
Kai Germaschewski4935.51%250.00%
Jeff Garzik75.07%125.00%
Total138100.00%4100.00%


static void en_cs_init(struct IsdnCard *card, struct IsdnCardState *cs) { cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD /* Reset an */ cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL); /* 20 ms Pause */ mdelay(20); cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL); mdelay(10); cs->hw.njet.auxd = 0x00; // war 0xc0 cs->hw.njet.dmactrl = 0; outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL); outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1); outb(cs->hw.njet.auxd, cs->hw.njet.auxa); }

Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski15979.50%120.00%
Adrian Bunk2010.00%120.00%
Jeff Garzik157.50%120.00%
Andrew Morton52.50%120.00%
Al Viro10.50%120.00%
Total200100.00%5100.00%


static int en_cs_init_rest(struct IsdnCard *card, struct IsdnCardState *cs) { const int bytecnt = 256; printk(KERN_INFO "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", cs->hw.njet.base, cs->irq); if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) { printk(KERN_WARNING "HiSax: enter:now config port %lx-%lx already in use\n", cs->hw.njet.base, cs->hw.njet.base + bytecnt); return (0); } setup_Amd7930(cs); cs->hw.njet.last_is0 = 0; /* macro rByteAMD */ cs->readisac = &ReadByteAmd7930; /* macro wByteAMD */ cs->writeisac = &WriteByteAmd7930; cs->dc.amd7930.setIrqMask = &enpci_setIrqMask; cs->BC_Read_Reg = &dummyrr; cs->BC_Write_Reg = &dummywr; cs->BC_Send_Data = &netjet_fill_dma; cs->cardmsg = &enpci_card_msg; cs->irq_func = &enpci_interrupt; cs->irq_flags |= IRQF_SHARED; return (1); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton9251.98%114.29%
Kai Germaschewski6436.16%457.14%
Jeff Garzik2011.30%114.29%
Thomas Gleixner10.56%114.29%
Total177100.00%7100.00%

static struct pci_dev *dev_netjet = NULL; /* called by config.c */
int setup_enternow_pci(struct IsdnCard *card) { int ret; struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, enternow_pci_rev); printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_ENTERNOW) return (0); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); for (;;) { if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { ret = en_pci_probe(dev_netjet, cs); if (!ret) return (0); } else { printk(KERN_WARNING "enter:now PCI: No PCI card found\n"); return (0); } en_cs_init(card, cs); break; } return en_cs_init_rest(card, cs); }

Contributors

PersonTokensPropCommitsCommitProp
Jeff Garzik14898.67%133.33%
Greg Kroah-Hartman10.67%133.33%
Tilman Schmidt10.67%133.33%
Total150100.00%3100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Kai Germaschewski104853.94%533.33%
Andrew Morton55628.62%213.33%
Jeff Garzik19910.24%16.67%
Adrian Bunk1296.64%16.67%
Jan Engelhardt60.31%16.67%
Tilman Schmidt10.05%16.67%
Greg Kroah-Hartman10.05%16.67%
Al Viro10.05%16.67%
Thomas Gleixner10.05%16.67%
Michael Hayes10.05%16.67%
Total1943100.00%15100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.