static inline void ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) { writereg(cs, cs->hw.elsa.isac, offset, value); }
static void WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset | 0x80, value); }
static irqreturn_t elsa_interrupt(int intno, void *dev_id) { struct IsdnCardState *cs = dev_id; u_long flags; u_char val; int icnt = 5; if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) { /* The card tends to generate interrupts while being removed causing us to just crash the kernel. bad. */ printk(KERN_WARNING "Elsa: card not available!\n"); return IRQ_NONE; } spin_lock_irqsave(&cs->lock, flags); #if ARCOFI_USE if (cs->hw.elsa.MFlag) { val = serial_inp(cs, UART_IIR); if (!(val & UART_IIR_NO_INT)) { debugl1(cs, "IIR %02x", val); rs_interrupt_elsa(cs); } } #endif val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); Start_HSCX: if (val) { hscx_int_main(cs, val); } val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA); Start_ISAC: if (val) { isac_interrupt(cs, val); } val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); if (val && icnt) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HSCX IntStat after IntRoutine"); icnt--; goto Start_HSCX; } val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA); if (val && icnt) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC IntStat after IntRoutine"); icnt--; goto Start_ISAC; } if (!icnt) printk(KERN_WARNING"ELSA IRQ LOOP\n"); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0xFF); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0xFF); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0xFF); if (cs->hw.elsa.status & ELIRQF_TIMER_AKTIV) { if (!TimerRun(cs)) { /* Timer Restart */ byteout(cs->hw.elsa.timer, 0); cs->hw.elsa.counter++; } } #if ARCOFI_USE if (cs->hw.elsa.MFlag) { val = serial_inp(cs, UART_MCR); val ^= 0x8; serial_outp(cs, UART_MCR, val); val = serial_inp(cs, UART_MCR); val ^= 0x8; serial_outp(cs, UART_MCR, val); } #endif if (cs->hw.elsa.trig) byteout(cs->hw.elsa.trig, 0x00); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0); spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; }
static void WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value) { writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value); }
int __devinit setup_sct_quadro(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; u_int found = 0; u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5; strcpy(tmp, sct_quadro_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { cs->subtyp = SCT_1; } else return (0); if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4) cs->subtyp = card->para[0]; else { printk(KERN_WARNING "HiSax: Scitel Quadro: Invalid " "subcontroller in configuration, default to 1\n"); return (0); } if ((cs->subtyp != SCT_1) && ((sub_sys_id != PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) || (sub_vendor_id != PCI_VENDOR_ID_BERKOM))) return (0); if (cs->subtyp == SCT_1) { while ((dev_a8 = hisax_find_pci_device(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, dev_a8))) { sub_vendor_id = dev_a8->subsystem_vendor; sub_sys_id = dev_a8->subsystem_device; if ((sub_sys_id == PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) && (sub_vendor_id == PCI_VENDOR_ID_BERKOM)) { if (pci_enable_device(dev_a8)) return (0); pci_ioaddr1 = pci_resource_start(dev_a8, 1); pci_irq = dev_a8->irq; pci_bus = dev_a8->bus->number; pci_device_fn = dev_a8->devfn; found = 1; break; } } if (!found) { printk(KERN_WARNING "HiSax: Scitel Quadro (%s): " "Card not found\n", sct_quadro_subtypes[cs->subtyp]); return (0); } #ifdef ATTEMPT_PCI_REMAPPING if ((pci_ioaddr1 & 0x80) && (dev_a8->revision == 1)) { printk(KERN_WARNING "HiSax: Scitel Quadro (%s): " "PLX rev 1, remapping required!\n", sct_quadro_subtypes[cs->subtyp]); pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, (u_int)-1); pci_ioaddr1 += 0x80; pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, pci_ioaddr1); dev_a8->resource[1].start = pci_ioaddr1; } #endif } if (!pci_irq) { printk(KERN_WARNING "HiSax: Scitel Quadro (%s): No IRQ\n", sct_quadro_subtypes[cs->subtyp]); return (0); } pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_1, &pci_ioaddr1); pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_2, &pci_ioaddr2); pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_3, &pci_ioaddr3); pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_4, &pci_ioaddr4); pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_5, &pci_ioaddr5); if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) { printk(KERN_WARNING "HiSax: Scitel Quadro (%s): " "No IO base address(es)\n", sct_quadro_subtypes[cs->subtyp]); return (0); } pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; pci_ioaddr2 &= PCI_BASE_ADDRESS_IO_MASK; pci_ioaddr3 &= PCI_BASE_ADDRESS_IO_MASK; pci_ioaddr4 &= PCI_BASE_ADDRESS_IO_MASK; pci_ioaddr5 &= PCI_BASE_ADDRESS_IO_MASK; cs->irq = pci_irq; cs->irq_flags |= IRQF_SHARED; cs->hw.ax.plx_adr = pci_ioaddr1; switch (cs->subtyp) { case 1: cs->hw.ax.base = pci_ioaddr5 + 0x00; if (sct_alloc_io(pci_ioaddr1, 128)) return (0); if (sct_alloc_io(pci_ioaddr5, 64)) return (0); writereg(pci_ioaddr5, pci_ioaddr5 + 4, IPAC_MASK, 0xFF); writereg(pci_ioaddr4 + 0x08, pci_ioaddr4 + 0x0c, IPAC_MASK, 0xFF); writereg(pci_ioaddr3 + 0x10, pci_ioaddr3 + 0x14, IPAC_MASK, 0xFF); writereg(pci_ioaddr2 + 0x20, pci_ioaddr2 + 0x24, IPAC_MASK, 0xFF); break; case 2: cs->hw.ax.base = pci_ioaddr4 + 0x08; if (sct_alloc_io(pci_ioaddr4, 64)) return (0); break; case 3: cs->hw.ax.base = pci_ioaddr3 + 0x10; if (sct_alloc_io(pci_ioaddr3, 64)) return (0); break; case 4: cs->hw.ax.base = pci_ioaddr2 + 0x20; if (sct_alloc_io(pci_ioaddr2, 64)) return (0); break; } cs->hw.ax.data_adr = cs->hw.ax.base + 4; printk(KERN_INFO "HiSax: Scitel Quadro (%s) configured at " "0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n", sct_quadro_subtypes[cs->subtyp], cs->hw.ax.plx_adr, cs->hw.ax.base, cs->hw.ax.data_adr, cs->irq); test_and_set_bit(HW_IPAC, &cs->HW_Flags); cs->readisac = &ReadISAC; cs->writeisac = &WriteISAC; cs->readisacfifo = &ReadISACfifo; cs->writeisacfifo = &WriteISACfifo; cs->BC_Read_Reg = &ReadHSCX; cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &BKM_card_msg; cs->irq_func = &bkm_interrupt_ipac; printk(KERN_INFO "HiSax: Scitel Quadro (%s): IPAC Version %d\n", sct_quadro_subtypes[cs->subtyp], readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID)); return (1); }
/* Open/initialize the board. This is called (in the current kernel) sometime after booting when the 'ifconfig' program is run. This routine should set everything up anew at each open, even registers that "should" only need to be set once at boot, so that there is non-reboot way to recover if something goes wrong. */ static int net_open(struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int result = 0; // int i; write_irq(dev, lp->chip_type, 0); irq2dev_map[/* FIXME */ 0] = dev; writereg(dev, PP_BusCTL, 0); /* ints off! */ #ifdef CONFIG_UCSIMM *(volatile unsigned short *)0xfffff302 |= 0x0080; /* +ve pol irq */ if (request_irq(IRQ_MACHSPEC | IRQ5_IRQ_NUM, cs8900_interrupt, IRQ_FLG_STD, "CrystalLAN_cs8900a", NULL)) panic("Unable to attach cs8900 intr\n"); #endif #ifdef CONFIG_ARCH_ATMEL /* We use IRQ_IRQ1 for the network interrupt */ if (request_irq(IRQ_MACHSPEC | IRQ_IRQ1, cs8900_interrupt, IRQ_FLG_STD, "CrystalLAN_cs8900a", NULL)) panic("Unable to attach cs8900 intr\n"); #endif #ifdef CONFIG_ALMA_ANS /* We use positive polarity IRQ3 as a network interrupt */ ICR |= ICR_POL3; if (request_irq(IRQ_MACHSPEC | IRQ3_IRQ_NUM, cs8900_interrupt, IRQ_FLG_STD, "CrystalLAN_cs8900a", NULL)) panic("Unable to attach cs8900 intr\n"); #endif #ifdef CONFIG_MWI /* We use vector position 28 as network interrupt */ if (request_irq(IRQ_MACHSPEC| 28, cs8900_interrupt, IRQ_FLG_STD, "cs8900a", NULL)) panic("Unable to attach cs8900 intr\n"); /* setup porte */ *(volatile unsigned char *)0xfffa15 &= 0xfb; *(volatile unsigned char *)0xfffa17 |= 0x04; /* setup portf */ *(volatile unsigned char *)0xfffa1d &= 0x7f; *(volatile unsigned char *)0xfffa1f |= 0x10; #endif /* set the Ethernet address */ set_mac_address(dev, dev->dev_addr); /* Set the LineCTL */ lp->linectl = 0; /* check to make sure that they have the "right" hardware available */ switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) { case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break; case A_CNF_MEDIA_AUI: result = lp->adapter_cnf & A_CNF_AUI; break; case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); } if (!result) { printk("%s: EEPROM is configured for unavailable media\n", dev->name); release_irq: writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON)); irq2dev_map[dev->irq] = 0; return -EAGAIN; } /* set the hardware to the configured choice */ switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) { case A_CNF_MEDIA_10B_T: result = detect_tp(dev); if (!result) printk("%s: 10Base-T (RJ-45) has no cable\n", dev->name); if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */ result = A_CNF_MEDIA_10B_T; /* Yes! I don't care if I see a link pulse */ break; case A_CNF_MEDIA_AUI: printk("AUI? What stinking AUI?\n"); break; case A_CNF_MEDIA_10B_2: printk("10Base2? What stinking 10Base2?\n"); break; case A_CNF_MEDIA_AUTO: writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET); if (lp->adapter_cnf & A_CNF_10B_T) if ((result = detect_tp(dev)) != 0) break; printk("%s: no media detected\n", dev->name); goto release_irq; } switch(result) { case 0: printk("%s: no network cable attached to configured media\n", dev->name); goto release_irq; case A_CNF_MEDIA_10B_T: printk("%s: using 10Base-T (RJ-45)\n", dev->name);break; case A_CNF_MEDIA_AUI: printk("%s: using 10Base-5 (AUI)\n", dev->name);break; case A_CNF_MEDIA_10B_2: printk("%s: using 10Base-2 (BNC)\n", dev->name);break; default: printk("%s: unexpected result was %x\n", dev->name, result); goto release_irq; } /* Turn on both receive and transmit operations */ writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON); /* Receive only error free packets addressed to this card */ lp->rx_mode = 0; writereg(dev, PP_RxCTL, DEF_RX_ACCEPT); lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL; if (lp->isa_config & STREAM_TRANSFER) lp->curr_rx_cfg |= RX_STREAM_ENBL; writereg(dev, PP_RxCFG, lp->curr_rx_cfg); writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL); writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL); /* now that we've got our act together, enable everything */ writereg(dev, PP_BusCTL, ENABLE_IRQ ); dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; return 0; }
static void WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { cs->hw.hfc.cip = offset; writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset, value); }
static inline void isac_interrupt(struct IsdnCardState *sp, u_char val) { u_char exval; struct sk_buff *skb; unsigned int count; char tmp[32]; if (sp->debug & L1_DEB_ISAC) { sprintf(tmp, "ISAC interrupt %x", val); debugl1(sp, tmp); } if (val & 0x80) { /* RME */ exval = readreg(sp->isac, ISAC_RSTA); if ((exval & 0x70) != 0x20) { if (exval & 0x40) if (sp->debug & L1_DEB_WARN) debugl1(sp, "ISAC RDO"); if (!(exval & 0x20)) if (sp->debug & L1_DEB_WARN) debugl1(sp, "ISAC CRC error"); writereg(sp->isac, ISAC_CMDR, 0x80); } else { count = readreg(sp->isac, ISAC_RBCL) & 0x1f; if (count == 0) count = 32; isac_empty_fifo(sp, count); if ((count = sp->rcvidx) > 0) { if (!(skb = alloc_skb(count, GFP_ATOMIC))) printk(KERN_WARNING "AVM: D receive out of memory\n"); else { SET_SKB_FREE(skb); memcpy(skb_put(skb, count), sp->rcvbuf, count); skb_queue_tail(&sp->rq, skb); } } } sp->rcvidx = 0; isac_sched_event(sp, ISAC_RCVBUFREADY); } if (val & 0x40) { /* RPF */ isac_empty_fifo(sp, 32); } if (val & 0x20) { /* RSC */ /* never */ if (sp->debug & L1_DEB_WARN) debugl1(sp, "ISAC RSC interrupt"); } if (val & 0x10) { /* XPR */ if (sp->tx_skb) if (sp->tx_skb->len) { isac_fill_fifo(sp); goto afterXPR; } else { dev_kfree_skb(sp->tx_skb, FREE_WRITE); sp->tx_cnt = 0; sp->tx_skb = NULL; } if ((sp->tx_skb = skb_dequeue(&sp->sq))) { sp->tx_cnt = 0; isac_fill_fifo(sp); } else isac_sched_event(sp, ISAC_XMTBUFREADY); } afterXPR: if (val & 0x04) { /* CISQ */ sp->ph_state = (readreg(sp->isac, ISAC_CIX0) >> 2) & 0xf; if (sp->debug & L1_DEB_ISAC) { sprintf(tmp, "l1state %d", sp->ph_state); debugl1(sp, tmp); } isac_new_ph(sp); }
/*---------------------------------------------------------------------------*/ static void setregbank(uint8_t bank) { writereg(ECON1, (readreg(ECON1) & 0xfc) | (bank & 0x03)); }
static int eim_init(void) { int ret = 0; const int CSREC = 3; const int PSZ = 0; const int AUS = 1; const int BCS = 0; const int BCD = 0; const int BL = 3; const int WFL = 1; const int RFL = 1; const int WC = 0; const int ADH = 0; const int RWSC = 3; const int WWSC = 1; const int ADVA = 0; /* RADVA and WADVA */ const int ADVN = 0; /* RADVN and WADVN */ const int OEA = 0; const int CSA = 0; /* RCSA and WCSA */ const int RL = 0; const int BEA = 0; const int BE = 1; const int WEA = 0; const int INTPOL = 1; /* Interrupt polarity */ const int INTEN = 0; /* Interrupt enable */ const int GBCD = 0; /* Burst clock divisor */ const int BCM = 1; /* Burst clock mode (set c ontinuous here) */ u32 GCR1, GCR2, RCR1, RCR2, WCR1, WEIMCR; u32 temp_clk; const int emi_slow_podf = 7; iomux_v3_cfg_t iomux_cs2 = MX51_PAD_EIM_CS2__EIM_CS2; iomux_v3_cfg_t iomux_dtack = MX51_PAD_EIM_DTACK__GPIO2_31; iomux_v3_cfg_t iomux_event = MX51_PAD_GPIO1_5__SDMA_EXT_EVENT; mxc_iomux_v3_setup_pad(iomux_cs2); mxc_iomux_v3_setup_pad(iomux_dtack); mxc_iomux_v3_setup_pad(iomux_event); /* * Change the clock divider for EMI bus from divide-by-7 to divide-by-8, so * that the bus frequency is below 90 MHz, in accordance with footnote 4 in * section 4.6.7.3 in the datasheet. This is necessary to prevent bus errors * as the device heats up. */ temp_clk = __raw_readl( MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)+ MXC_CCM_CBCDR ); __raw_writel( (temp_clk & (~0x1c00000)) | bitfield(22, 3, emi_slow_podf), MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)+ MXC_CCM_CBCDR ); if (gpio_request(event_gpio_num, "xillybus")) { printk(KERN_ERR THIS "GPIO pin %i is already in use\n", event_gpio_num); return -ENODEV; } gpio_direction_input(event_gpio_num); GCR1 = 0x0111008f | bitfield(28, 4, PSZ) | bitfield(23, 1, AUS) | bitfield(20, 3, CSREC) | bitfield(14, 2, BCS) | bitfield(12, 2, BCD) | bitfield(11, 1, WC) | bitfield(8, 3, BL) | bitfield(5, 1, RFL) | bitfield(4, 1, WFL); GCR2 = bitfield(0, 2, ADH); RCR1 = bitfield(24, 6, RWSC) | bitfield(20, 3, ADVA) | bitfield(16, 3, ADVN) | bitfield(12, 3, OEA) | bitfield(4, 3, CSA); RCR2 = bitfield(8, 2, RL) | bitfield(4, 3, BEA) | bitfield(3, 1, BE); WCR1 = bitfield(30, 1, !BE) | bitfield(24, 6, WWSC) | bitfield(21, 3, ADVA) | bitfield(18, 3, ADVN) | bitfield(15, 3, BEA) | bitfield(9, 3, WEA) | bitfield(3, 3, CSA); WEIMCR = bitfield(5, 1, INTPOL) | bitfield(4, 1, INTEN) | bitfield(1, 2, GBCD) | bitfield(0, 1, BCM); writereg(0x30, GCR1); writereg(0x34, GCR2); writereg(0x38, RCR1); writereg(0x3c, RCR2); writereg(0x40, WCR1); writereg(0x90, WEIMCR); if (!request_mem_region(MX51_CS2_BASE_ADDR, SZ_64K, "xillybus_sdma")) { printk(KERN_ERR THIS "request_mem_region failed. Aborting.\n"); return -ENODEV; } cs2_base = ioremap_nocache(MX51_CS2_BASE_ADDR, SZ_64K); if (!cs2_base) { printk(KERN_WARNING THIS "Failed to obtain I/O space\n"); ret = -ENODEV; goto failed_ioremap; } return 0; failed_ioremap: release_mem_region(MX51_CS2_BASE_ADDR, SZ_64K); return ret; }
static int Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) { u_long flags; switch (mt) { case CARD_RESET: spin_lock_irqsave(&cs->lock, flags); reset_sedlbauer(cs); spin_unlock_irqrestore(&cs->lock, flags); return(0); case CARD_RELEASE: if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { spin_lock_irqsave(&cs->lock, flags); writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); reset_sedlbauer(cs); writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); spin_unlock_irqrestore(&cs->lock, flags); } release_io_sedlbauer(cs); return(0); case CARD_INIT: spin_lock_irqsave(&cs->lock, flags); reset_sedlbauer(cs); if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { clear_pending_isac_ints(cs); writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0); initisac(cs); initisar(cs); /* Reenable all IRQ */ cs->writeisac(cs, ISAC_MASK, 0); /* RESET Receiver and Transmitter */ cs->writeisac(cs, ISAC_CMDR, 0x41); } else { inithscxisac(cs, 3); } spin_unlock_irqrestore(&cs->lock, flags); return(0); case CARD_TEST: return(0); case MDL_INFO_CONN: if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) return(0); spin_lock_irqsave(&cs->lock, flags); if ((long) arg) cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2; else cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1; byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); spin_unlock_irqrestore(&cs->lock, flags); break; case MDL_INFO_REL: if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) return(0); spin_lock_irqsave(&cs->lock, flags); if ((long) arg) cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2; else cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1; byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); spin_unlock_irqrestore(&cs->lock, flags); break; } return(0); }
/* Open/initialize the board. This is called (in the current kernel) sometime after booting when the 'ifconfig' program is run. This routine should set everything up anew at each open, even registers that "should" only need to be set once at boot, so that there is non-reboot way to recover if something goes wrong. */ static int net_open(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int result = 0; write_irq(dev, lp->chip_type, 0); /* irq2dev_map[0] = dev; */ writereg(dev, PP_BusCTL, 0); /* ints off! */ #ifdef CONFIG_UCSIMM *(volatile unsigned short *)0xfffff302 |= 0x0080; /* +ve pol irq */ dev->irq = IRQ5_IRQ_NUM; if (request_irq(dev->irq | IRQ_MACHSPEC, cs8900_interrupt, IRQ_FLG_STD, "CrystalLAN_cs8900a", NULL)) panic("Unable to attach cs8900 intr\n"); #endif #ifdef CONFIG_ARCH_ATMEL /* Set IRQ1 with high level sensitive & priority level 6. */ *(volatile unsigned int *) AIC_SMR(IRQ_IRQ1) = 0x46; /* We use IRQ_IRQ1 for the network interrupt */ dev->irq = IRQ_IRQ1; if (request_irq(dev->irq, cs8900_interrupt, IRQ_FLG_STD, "CrystalLAN_cs8900a", NULL)) panic("Unable to attach cs8900 intr\n"); #endif #if defined (CONFIG_BOARD_UCLINKII) || \ defined (CONFIG_BOARD_EVS3C4530LII) || \ defined (CONFIG_BOARD_EVS3C4530HEI) *(volatile unsigned int *)IOPCON0 |= (xINTREQ0_ENABLE | xINTREQ0_ACT_HI); dev->irq = _IRQ0; if (request_irq (dev->irq, cs8900_interrupt, 0, "Crystal_CS8900", dev)) panic("Unable to attach cs8900 intr\n"); #endif #ifdef CONFIG_ALMA_ANS /* We use positive polarity IRQ3 as a network interrupt */ ICR |= ICR_POL3; dev->irq = IRQ3_IRQ_NUM; if (request_irq(dev->irq | IRQ_MACHSPEC, cs8900_interrupt, IRQ_FLG_STD, "CrystalLAN_cs8900a", NULL)) panic("Unable to attach cs8900 intr\n"); #endif /* set the Ethernet address */ set_mac_address(dev, dev->dev_addr); /* Set the LineCTL */ lp->linectl = 0; /* check to make sure that they have the "right" hardware available */ switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) { case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break; case A_CNF_MEDIA_AUI: result = lp->adapter_cnf & A_CNF_AUI; break; case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); } if (!result) { printk("%s: EEPROM is configured for unavailable media\n", dev->name); release_irq: writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON)); /* so subsequent opens don't fail we release the IRQ ...MaTed--- */ free_irq( dev->irq, dev); /* irq2dev_map[dev->irq] = 0; */ return -EAGAIN; } /* set the hardware to the configured choice */ switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) { case A_CNF_MEDIA_10B_T: result = detect_tp(dev); if (!result) { printk("%s: 10Base-T (RJ-45) has no cable\n", dev->name); if (lp->auto_neg_cnf & IMM_BIT) { /* check "ignore missing media" bit */ printk("%s: but ignore the fact.\n", dev->name); result = A_CNF_MEDIA_10B_T; /* Yes! I don't care if I see a link pulse */ } } break; case A_CNF_MEDIA_AUI: printk("AUI is not supported by uCcs8900\n"); break; case A_CNF_MEDIA_10B_2: printk("10Base2 is not supported by uCcs8900\n"); break; case A_CNF_MEDIA_AUTO: writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET); if (lp->adapter_cnf & A_CNF_10B_T) if ((result = detect_tp(dev)) != 0) break; printk("%s: no media detected\n", dev->name); goto release_irq; } switch(result) { case 0: printk("%s: no network cable attached to configured media\n", dev->name); goto release_irq; case A_CNF_MEDIA_10B_T: printk("%s: using 10Base-T (RJ-45)\n", dev->name);break; case A_CNF_MEDIA_AUI: printk("%s: using 10Base-5 (AUI)\n", dev->name);break; case A_CNF_MEDIA_10B_2: printk("%s: using 10Base-2 (BNC)\n", dev->name);break; default: printk("%s: unexpected result was %x\n", dev->name, result); goto release_irq; } /* Turn on both receive and transmit operations */ writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON); /* Receive only error free packets addressed to this card */ lp->rx_mode = 0; writereg(dev, PP_RxCTL, DEF_RX_ACCEPT); lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL; if (lp->isa_config & STREAM_TRANSFER) lp->curr_rx_cfg |= RX_STREAM_ENBL; writereg(dev, PP_RxCFG, lp->curr_rx_cfg); writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL); writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL); /* now that we've got our act together, enable everything */ writereg(dev, PP_BusCTL, ENABLE_IRQ ); netif_start_queue(dev); return 0; }
/*---------------------------------------------------------------------------*/ int enc28j60_send(const uint8_t *data, uint16_t datalen) { uint16_t dataend; if(!initialized) { return -1; } /* 1. Appropriately program the ETXST pointer to point to an unused location in memory. It will point to the per packet control byte. In the example, it would be programmed to 0120h. It is recommended that an even address be used for ETXST. 2. Use the WBM SPI command to write the per packet control byte, the destination address, the source MAC address, the type/length and the data payload. 3. Appropriately program the ETXND pointer. It should point to the last byte in the data payload. In the example, it would be programmed to 0156h. 4. Clear EIR.TXIF, set EIE.TXIE and set EIE.INTIE to enable an interrupt when done (if desired). 5. Start the transmission process by setting ECON1.TXRTS. */ setregbank(ERXTX_BANK); /* Set up the transmit buffer pointer */ writereg(ETXSTL, TX_BUF_START & 0xff); writereg(ETXSTH, TX_BUF_START >> 8); writereg(EWRPTL, TX_BUF_START & 0xff); writereg(EWRPTH, TX_BUF_START >> 8); /* Write the transmission control register as the first byte of the output packet. We write 0x00 to indicate that the default configuration (the values in MACON3) will be used. */ writedatabyte(0x00); /* MACON3 */ writedata(data, datalen); /* Write a pointer to the last data byte. */ dataend = TX_BUF_START + datalen; writereg(ETXNDL, dataend & 0xff); writereg(ETXNDH, dataend >> 8); /* Clear EIR.TXIF */ clearregbitfield(EIR, EIR_TXIF); /* Don't care about interrupts for now */ /* Send the packet */ setregbitfield(ECON1, ECON1_TXRTS); while((readreg(ECON1) & ECON1_TXRTS) > 0); #if DEBUG if((readreg(ESTAT) & ESTAT_TXABRT) != 0) { uint16_t erdpt; uint8_t tsv[7]; erdpt = (readreg(ERDPTH) << 8) | readreg(ERDPTL); writereg(ERDPTL, (dataend + 1) & 0xff); writereg(ERDPTH, (dataend + 1) >> 8); readdata(tsv, sizeof(tsv)); writereg(ERDPTL, erdpt & 0xff); writereg(ERDPTH, erdpt >> 8); PRINTF("enc28j60: tx err: %d: %02x:%02x:%02x:%02x:%02x:%02x\n" " tsv: %02x%02x%02x%02x%02x%02x%02x\n", datalen, 0xff & data[0], 0xff & data[1], 0xff & data[2], 0xff & data[3], 0xff & data[4], 0xff & data[5], tsv[6], tsv[5], tsv[4], tsv[3], tsv[2], tsv[1], tsv[0]); } else {
/*---------------------------------------------------------------------------*/ static void setregbank(uint8_t new_bank) { writereg(ECON1, (readreg(ECON1) & 0xfc) | (new_bank & 0x03)); bank = new_bank; }
int __init setup_sct_quadro(struct IsdnCard *card) { #ifdef CONFIG_PCI struct IsdnCardState *cs = card->cs; char tmp[64]; u_char pci_rev_id; u_int found = 0; u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5; strcpy(tmp, sct_quadro_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { cs->subtyp = SCT_1; /* Preset */ } else return (0); /* Identify subtype by para[0] */ if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4) cs->subtyp = card->para[0]; else { printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n", CardType[card->typ]); return (0); } if ((cs->subtyp != SCT_1) && ((sub_sys_id != PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) || (sub_vendor_id != PCI_VENDOR_ID_BERKOM))) return (0); if (cs->subtyp == SCT_1) { while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, dev_a8))) { sub_vendor_id = dev_a8->subsystem_vendor; sub_sys_id = dev_a8->subsystem_device; if ((sub_sys_id == PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) && (sub_vendor_id == PCI_VENDOR_ID_BERKOM)) { if (pci_enable_device(dev_a8)) return(0); pci_ioaddr1 = pci_resource_start(dev_a8, 1); pci_irq = dev_a8->irq; pci_bus = dev_a8->bus->number; pci_device_fn = dev_a8->devfn; found = 1; break; } } if (!found) { printk(KERN_WARNING "HiSax: %s (%s): Card not found\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp]); return (0); } #ifdef ATTEMPT_PCI_REMAPPING /* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */ pci_read_config_byte(dev_a8, PCI_REVISION_ID, &pci_rev_id); if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) { printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp]); /* Restart PCI negotiation */ pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, (u_int) - 1); /* Move up by 0x80 byte */ pci_ioaddr1 += 0x80; pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, pci_ioaddr1); dev_a8->resource[ 1].start = pci_ioaddr1; } #endif /* End HACK */ } if (!pci_irq) { /* IRQ range check ?? */ printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp]); return (0); } pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_1, &pci_ioaddr1); pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_2, &pci_ioaddr2); pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_3, &pci_ioaddr3); pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_4, &pci_ioaddr4); pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_5, &pci_ioaddr5); if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) { printk(KERN_WARNING "HiSax: %s (%s): No IO base address(es)\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp]); return (0); } pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; pci_ioaddr2 &= PCI_BASE_ADDRESS_IO_MASK; pci_ioaddr3 &= PCI_BASE_ADDRESS_IO_MASK; pci_ioaddr4 &= PCI_BASE_ADDRESS_IO_MASK; pci_ioaddr5 &= PCI_BASE_ADDRESS_IO_MASK; /* Take over */ cs->irq = pci_irq; cs->irq_flags |= SA_SHIRQ; /* pci_ioaddr1 is unique to all subdevices */ /* pci_ioaddr2 is for the fourth subdevice only */ /* pci_ioaddr3 is for the third subdevice only */ /* pci_ioaddr4 is for the second subdevice only */ /* pci_ioaddr5 is for the first subdevice only */ cs->hw.ax.plx_adr = pci_ioaddr1; /* Enter all ipac_base addresses */ switch(cs->subtyp) { case 1: cs->hw.ax.base = pci_ioaddr5 + 0x00; if (sct_alloc_io(pci_ioaddr1, 128)) return(0); if (sct_alloc_io(pci_ioaddr5, 64)) return(0); /* disable all IPAC */ writereg(pci_ioaddr5, pci_ioaddr5 + 4, IPAC_MASK, 0xFF); writereg(pci_ioaddr4 + 0x08, pci_ioaddr4 + 0x0c, IPAC_MASK, 0xFF); writereg(pci_ioaddr3 + 0x10, pci_ioaddr3 + 0x14, IPAC_MASK, 0xFF); writereg(pci_ioaddr2 + 0x20, pci_ioaddr2 + 0x24, IPAC_MASK, 0xFF); break; case 2: cs->hw.ax.base = pci_ioaddr4 + 0x08; if (sct_alloc_io(pci_ioaddr4, 64)) return(0); break; case 3: cs->hw.ax.base = pci_ioaddr3 + 0x10; if (sct_alloc_io(pci_ioaddr3, 64)) return(0); break; case 4: cs->hw.ax.base = pci_ioaddr2 + 0x20; if (sct_alloc_io(pci_ioaddr2, 64)) return(0); break; } /* For isac and hscx data path */ cs->hw.ax.data_adr = cs->hw.ax.base + 4; printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp], cs->hw.ax.plx_adr, cs->hw.ax.base, cs->hw.ax.data_adr, cs->irq); test_and_set_bit(HW_IPAC, &cs->HW_Flags); cs->readisac = &ReadISAC; cs->writeisac = &WriteISAC; cs->readisacfifo = &ReadISACfifo; cs->writeisacfifo = &WriteISACfifo; cs->BC_Read_Reg = &ReadHSCX; cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &BKM_card_msg; cs->irq_func = &bkm_interrupt_ipac; printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp], readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID)); return (1); #else printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n"); #endif /* CONFIG_PCI */ }
/*---------------------------------------------------------------------------*/ static void reset(void) { PRINTF("enc28j60: resetting chip\n"); enc28j60_arch_spi_init(); /* 6.0 INITIALIZATION Before the ENC28J60 can be used to transmit and receive packets, certain device settings must be initialized. Depending on the application, some configuration options may need to be changed. Normally, these tasks may be accomplished once after Reset and do not need to be changed thereafter. 6.1 Receive Buffer Before receiving any packets, the receive buffer must be initialized by programming the ERXST and ERXND pointers. All memory between and including the ERXST and ERXND addresses will be dedicated to the receive hardware. It is recommended that the ERXST pointer be programmed with an even address. Applications expecting large amounts of data and frequent packet delivery may wish to allocate most of the memory as the receive buffer. Applications that may need to save older packets or have several packets ready for transmission should allocate less memory. When programming the ERXST pointer, the ERXWRPT registers will automatically be updated with the same values. The address in ERXWRPT will be used as the starting location when the receive hardware begins writing received data. For tracking purposes, the ERXRDPT registers should additionally be programmed with the same value. To program ERXRDPT, the host controller must write to ERXRDPTL first, followed by ERXRDPTH. See Section 7.2.4 “Freeing Receive Buffer Space for more information 6.2 Transmission Buffer All memory which is not used by the receive buffer is considered the transmission buffer. Data which is to be transmitted should be written into any unused space. After a packet is transmitted, however, the hardware will write a seven-byte status vector into memory after the last byte in the packet. Therefore, the host controller should leave at least seven bytes between each packet and the beginning of the receive buffer. No explicit action is required to initialize the transmission buffer. 6.3 Receive Filters The appropriate receive filters should be enabled or disabled by writing to the ERXFCON register. See Section 8.0 “Receive Filters for information on how to configure it. 6.4 Waiting For OST If the initialization procedure is being executed immediately following a Power-on Reset, the ESTAT.CLKRDY bit should be polled to make certain that enough time has elapsed before proceeding to modify the MAC and PHY registers. For more information on the OST, see Section 2.2 “Oscillator Start-up Timer. */ /* Wait for OST */ while((readreg(ESTAT) & ESTAT_CLKRDY) == 0); softreset(); setregbank(ERXTX_BANK); /* Set up receive buffer */ writereg(ERXSTL, RX_BUF_START & 0xff); writereg(ERXSTH, RX_BUF_START >> 8); writereg(ERXNDL, RX_BUF_END & 0xff); writereg(ERXNDH, RX_BUF_END >> 8); writereg(ERDPTL, RX_BUF_START & 0xff); writereg(ERDPTH, RX_BUF_START >> 8); writereg(ERXRDPTL, RX_BUF_START & 0xff); writereg(ERXRDPTH, RX_BUF_START >> 8); /* Receive filters */ setregbank(EPKTCNT_BANK); /* writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_MCEN | ERXFCON_BCEN);*/ /* XXX: can't seem to get the unicast filter to work right now, using promiscous mode for now. */ writereg(ERXFCON, 0); /* 6.5 MAC Initialization Settings Several of the MAC registers require configuration during initialization. This only needs to be done once; the order of programming is unimportant. 1. Clear the MARST bit in MACON2 to pull the MAC out of Reset. 2. Set the MARXEN bit in MACON1 to enable the MAC to receive frames. If using full duplex, most applications should also set TXPAUS and RXPAUS to allow IEEE defined flow control to function. 3. Configure the PADCFG, TXCRCEN and FULDPX bits of MACON3. Most applications should enable automatic padding to at least 60 bytes and always append a valid CRC. For convenience, many applications may wish to set the FRMLNEN bit as well to enable frame length status reporting. The FULDPX bit should be set if the application will be connected to a full-duplex configured remote node; otherwise, it should be left clear. 4. Configure the bits in MACON4. Many applications may not need to modify the Reset default. 5. Program the MAMXFL registers with the maximum frame length to be permitted to be received or transmitted. Normal network nodes are designed to handle packets that are 1518 bytes or less. 6. Configure the Back-to-Back Inter-Packet Gap register, MABBIPG. Most applications will program this register with 15h when Full-Duplex mode is used and 12h when Half-Duplex mode is used. 7. Configure the Non-Back-to-Back Inter-Packet Gap register low byte, MAIPGL. Most applications will program this register with 12h. 8. If half duplex is used, the Non-Back-to-Back Inter-Packet Gap register high byte, MAIPGH, should be programmed. Most applications will program this register to 0Ch. 9. If Half-Duplex mode is used, program the Retransmission and Collision Window registers, MACLCON1 and MACLCON2. Most applications will not need to change the default Reset values. If the network is spread over exceptionally long cables, the default value of MACLCON2 may need to be increased. 10. Program the local MAC address into the MAADR0:MAADR5 registers. */ setregbank(MACONX_BANK); /* Pull MAC out of reset */ writereg(MACON2, 0);//readreg(MACON2) & (~MACON2_MARST)); /* Turn on reception and IEEE-defined flow control */ writereg(MACON1, readreg(MACON1) | (MACON1_MARXEN + MACON1_TXPAUS + MACON1_RXPAUS)); /* Set padding, crc, full duplex */ writereg(MACON3, readreg(MACON3) | (MACON3_PADCFG_FULL + MACON3_TXCRCEN + MACON3_FULDPX + MACON3_FRMLNEN)); /* Don't modify MACON4 */ /* Set maximum frame length in MAMXFL */ writereg(MAMXFLL, MAX_MAC_LENGTH & 0xff); writereg(MAMXFLH, MAX_MAC_LENGTH >> 8); /* Set back-to-back inter packet gap */ writereg(MABBIPG, 0x15); /* Set non-back-to-back packet gap */ writereg(MAIPGL, 0x12); writereg(MAIPGH, 0x0c); /* Set MAC address */ setregbank(MAADRX_BANK); writereg(MAADR6, enc_mac_addr[5]); writereg(MAADR5, enc_mac_addr[4]); writereg(MAADR4, enc_mac_addr[3]); writereg(MAADR3, enc_mac_addr[2]); writereg(MAADR2, enc_mac_addr[1]); writereg(MAADR1, enc_mac_addr[0]); /* Receive filters */ setregbank(EPKTCNT_BANK); writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN); /* 6.6 PHY Initialization Settings Depending on the application, bits in three of the PHY module’s registers may also require configuration. The PHCON1.PDPXMD bit partially controls the device’s half/full-duplex configuration. Normally, this bit is initialized correctly by the external circuitry (see Section 2.6 “LED Configuration). If the external circuitry is not present or incorrect, however, the host controller must program the bit properly. Alternatively, for an externally configurable system, the PDPXMD bit may be read and the FULDPX bit be programmed to match. For proper duplex operation, the PHCON1.PDPXMD bit must also match the value of the MACON3.FULDPX bit. If using half duplex, the host controller may wish to set the PHCON2.HDLDIS bit to prevent automatic loopback of the data which is transmitted. The PHY register, PHLCON, controls the outputs of LEDA and LEDB. If an application requires a LED configuration other than the default, PHLCON must be altered to match the new requirements. The settings for LED operation are discussed in Section 2.6 “LED Configuration. The PHLCON register is shown in Register 2-2 (page 9). */ /* Don't worry about PHY configuration for now */ /* Turn on autoincrement for buffer access */ writereg(ECON2, readreg(ECON2) | ECON2_AUTOINC); /* Turn on reception */ writereg(ECON1, ECON1_RXEN); }
void write_irq(struct device *dev, int chip_type, int irq) { /* we only hooked up 0 :-) */ writereg(dev, PP_CS8900_ISAINT, 0); }
/*---------------------------------------------------------------------------*/ int enc28j60_send(uint8_t *data, uint16_t datalen) { int padding = 0; if(!initialized) { return -1; } /* 1. Appropriately program the ETXST pointer to point to an unused location in memory. It will point to the per packet control byte. In the example, it would be programmed to 0120h. It is recommended that an even address be used for ETXST. 2. Use the WBM SPI command to write the per packet control byte, the destination address, the source MAC address, the type/length and the data payload. 3. Appropriately program the ETXND pointer. It should point to the last byte in the data payload. In the example, it would be programmed to 0156h. 4. Clear EIR.TXIF, set EIE.TXIE and set EIE.INTIE to enable an interrupt when done (if desired). 5. Start the transmission process by setting ECON1.TXRTS. */ setregbank(ERXTX_BANK); /* Set up the transmit buffer pointer */ writereg(ETXSTL, TX_BUF_START & 0xff); writereg(ETXSTH, TX_BUF_START >> 8); writereg(EWRPTL, TX_BUF_START & 0xff); writereg(EWRPTH, TX_BUF_START >> 8); /* Write the transmission control register as the first byte of the output packet. We write 0x00 to indicate that the default configuration (the values in MACON3) will be used. */ #define WITH_MANUAL_PADDING 1 #if WITH_MANUAL_PADDING #define PADDING_MIN_SIZE 60 writedatabyte(0x0B); /* POVERRIDE, PCRCEN, PHUGEEN. Not PPADEN */ if(datalen < PADDING_MIN_SIZE) { padding = PADDING_MIN_SIZE - datalen; } else { padding = 0; } #else /* WITH_MANUAL_PADDING */ writedatabyte(0x00); /* MACON3 */ padding = 0; #endif /* WITH_MANUAL_PADDING */ /* Write a pointer to the last data byte. */ writereg(ETXNDL, (TX_BUF_START + datalen + 0 + padding) & 0xff); writereg(ETXNDH, (TX_BUF_START + datalen + 0 + padding) >> 8); writedata(data, datalen); if(padding > 0) { uint8_t padding_buf[60]; memset(padding_buf, 0, padding); writedata(padding_buf, padding); } /* Clear EIR.TXIF */ writereg(EIR, readreg(EIR) & (~EIR_TXIF)); /* Don't care about interrupts for now */ /* Send the packet */ writereg(ECON1, readreg(ECON1) | ECON1_TXRTS); while((readreg(ECON1) & ECON1_TXRTS) > 0); if((readreg(ESTAT) & ESTAT_TXABRT) != 0) { PRINTF("enc28j60: tx err: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", datalen, 0xff&data[0], 0xff&data[1], 0xff&data[2], 0xff&data[3], 0xff&data[4], 0xff&data[5]); } else { PRINTF("enc28j60: tx: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", datalen, 0xff&data[0], 0xff&data[1], 0xff&data[2], 0xff&data[3], 0xff&data[4], 0xff&data[5]); } sent_packets++; PRINTF("enc28j60: sent_packets %d\n", sent_packets); return datalen; }
static void WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.mic.adr, cs->hw.mic.isac, offset, value); }
/*---------------------------------------------------------------------------*/ int enc28j60_read(uint8_t *buffer, uint16_t bufsize) { int n, len, next, err; uint8_t nxtpkt[2]; uint8_t status[2]; uint8_t length[2]; err = 0; setregbank(EPKTCNT_BANK); n = readreg(EPKTCNT); if(n == 0) { return 0; } PRINTF("enc28j60: EPKTCNT 0x%02x\n", n); setregbank(ERXTX_BANK); /* Read the next packet pointer */ nxtpkt[0] = readdatabyte(); nxtpkt[1] = readdatabyte(); PRINTF("enc28j60: nxtpkt 0x%02x%02x\n", nxtpkt[1], nxtpkt[0]); length[0] = readdatabyte(); length[1] = readdatabyte(); PRINTF("enc28j60: length 0x%02x%02x\n", length[1], length[0]); status[0] = readdatabyte(); status[1] = readdatabyte(); /* This statement is just to avoid a compiler warning: */ status[0] = status[0]; PRINTF("enc28j60: status 0x%02x%02x\n", status[1], status[0]); len = (length[1] << 8) + length[0]; if(bufsize >= len) { readdata(buffer, len); } else { uint16_t i; err = 1; /* flush rx fifo */ for(i = 0; i < len; i++) { readdatabyte(); } } /* Read an additional byte at odd lengths, to avoid FIFO corruption */ if((len % 2) != 0) { readdatabyte(); } /* Errata #14 */ next = (nxtpkt[1] << 8) + nxtpkt[0]; if(next == RX_BUF_START) { next = RX_BUF_END; } else { next = next - 1; } writereg(ERXRDPTL, next & 0xff); writereg(ERXRDPTH, next >> 8); writereg(ECON2, readreg(ECON2) | ECON2_PKTDEC); if(err) { PRINTF("enc28j60: rx err: flushed %d\n", len); return 0; } PRINTF("enc28j60: rx: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", len, 0xff&buffer[0], 0xff&buffer[1], 0xff&buffer[2], 0xff&buffer[3], 0xff&buffer[4], 0xff&buffer[5]); received_packets++; PRINTF("enc28j60: received_packets %d\n", received_packets); return len; }
static void WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value); }
static void hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) { writereg(cs, cs->hw.saphir.hscx, offset + (hscx ? 0x40 : 0), value); }
static void WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0), value); }
static void isac_write(struct IsdnCardState *cs, u8 offset, u8 value) { writereg(cs, cs->hw.saphir.isac, offset, value); }
static void WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80, value); }
static void WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value); }
static void WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0), value); }
static void WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { writereg(cs->hw.teles3.hscx[hscx], offset, value); }
static irqreturn_t elsa_interrupt_ipac(int intno, void *dev_id) { struct IsdnCardState *cs = dev_id; u_long flags; u_char ista, val; int icnt = 5; spin_lock_irqsave(&cs->lock, flags); if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) { val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */ if (!(val & ELSA_PCI_IRQ_MASK)) { spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; } } #if ARCOFI_USE if (cs->hw.elsa.MFlag) { val = serial_inp(cs, UART_IIR); if (!(val & UART_IIR_NO_INT)) { debugl1(cs, "IIR %02x", val); rs_interrupt_elsa(cs); } } #endif ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA); Start_IPAC: if (cs->debug & L1_DEB_IPAC) debugl1(cs, "IPAC ISTA %02X", ista); if (ista & 0x0f) { val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); if (ista & 0x01) val |= 0x01; if (ista & 0x04) val |= 0x02; if (ista & 0x08) val |= 0x04; if (val) hscx_int_main(cs, val); } if (ista & 0x20) { val = 0xfe & readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA + 0x80); if (val) { isac_interrupt(cs, val); } } if (ista & 0x10) { val = 0x01; isac_interrupt(cs, val); } ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA); if ((ista & 0x3f) && icnt) { icnt--; goto Start_IPAC; } if (!icnt) printk(KERN_WARNING "ELSA IRQ LOOP\n"); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xFF); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xC0); spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; }
static void isac_write(struct IsdnCardState *cs, u8 offset, u8 value) { writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset, value); }