diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/ap400/ap400_drv.c dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/ap400_drv.c --- dahdi-linux-2.1.0.3/drivers/dahdi/ap400/ap400_drv.c 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/ap400_drv.c 2010-07-16 13:13:15.744373151 -0300 @@ -0,0 +1,2641 @@ +/* + * AP400 PCI Card Driver + * + * Written by Ronaldo Valiati and Wagner Gegler + * + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon and Mark Spencer . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2005, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ap400.h" + +//#define AP400_DEBUG +#ifdef AP400_DEBUG +#define PDEBUG(fmt, args...) { \ + printk(KERN_DEBUG "AP400 (%d): ",__LINE__); \ + printk(fmt "\n", ## args); \ +} +#else +#define PDEBUG(fmt, args...) +#endif + +/* Enable HDLC support by hardware */ +#ifdef AP400_HDLC +#include "ap400_hdlc/ap400_hdlc.c" +#endif + +#define AP4_SPAN_MAX 8 + +//#define APEC_SUPPORT +#ifdef APEC_SUPPORT +#include "apec.h" +#endif + +//#define AP400_E1_TEST + +/* Workarounds */ +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif +#ifndef IRQF_DISABLED +#define IRQF_DISABLED SA_INTERRUPT +#endif +#ifndef __iomem +#define __iomem +#endif + +/* Define to get more attention-grabbing but slightly more I/O using + alarm status */ +#define FANCY_ALARM + +#define DEBUG_MAIN (1 << 0) +#define DEBUG_DTMF (1 << 1) +#define DEBUG_REGS (1 << 2) +#define DEBUG_TSI (1 << 3) +#define DEBUG_ECHOCAN (1 << 4) +#define DEBUG_RBS (1 << 5) +#define DEBUG_FRAMER (1 << 6) + +static int clock_source = -1; +static int tdm_loop = 0; +static int apec_enable = 1; +static int r2_double_answer = 0; + +module_param(clock_source, int, 0400); +module_param(tdm_loop, int, 0600); +module_param(apec_enable, int, 0600); +module_param(r2_double_answer, int, 0600); + +//#define AP4_CYCLES_STATS +#ifdef AP4_CYCLES_STATS +#include +static int rx_mean_cycles = 0; +static int tx_mean_cycles = 0; +module_param(rx_mean_cycles, int, 0600); +module_param(tx_mean_cycles, int, 0600); +static int rx_max_cycles = 0; +static int tx_max_cycles = 0; +module_param(rx_max_cycles, int, 0600); +module_param(tx_max_cycles, int, 0600); +static int rx_min_cycles = 0; +static int tx_min_cycles = 0; +module_param(rx_min_cycles, int, 0600); +module_param(tx_min_cycles, int, 0600); +#define MEAN_CYCLES_SHIFT 8 + +static int irq_interval_mean_cycles = 0; +module_param(irq_interval_mean_cycles, int, 0600); + +static cycles_t last_cycles; + +static inline void ap4_update_rx_cycles_stats(cycles_t start) +{ + int irq_interval; + int cycles = (int) (get_cycles() - start); + //printk("%lld - %lld = %d\n", start, get_cycles(), cycles); + if (cycles > rx_max_cycles) + rx_max_cycles = cycles; + if ((cycles < rx_min_cycles) || (rx_min_cycles == 0)) + rx_min_cycles = cycles; + rx_mean_cycles += (cycles - rx_mean_cycles) >> MEAN_CYCLES_SHIFT; + irq_interval = (int) (start - last_cycles); + irq_interval_mean_cycles += + (irq_interval - irq_interval_mean_cycles) >> MEAN_CYCLES_SHIFT; + last_cycles = start; +} + +static inline void ap4_update_tx_cycles_stats(cycles_t start) +{ + int cycles = (int) (get_cycles() - start); + if (cycles > tx_max_cycles) + tx_max_cycles = cycles; + if ((cycles < tx_min_cycles) || (tx_min_cycles == 0)) + tx_min_cycles = cycles; + tx_mean_cycles += (cycles - tx_mean_cycles) >> MEAN_CYCLES_SHIFT; +} +#endif + +static int debug=0; +static int timingcable; +static int highestorder; +static int t1e1override = -1; +static int j1mode = 0; +static int loopback = 0; +static int alarmdebounce = 0; + +/* Enabling bursting can more efficiently utilize PCI bus bandwidth, but + can also cause PCI bus starvation, especially in combination with other + aggressive cards. Please note that burst mode has no effect on CPU + utilization / max number of calls / etc. */ +static int noburst = 1; +static int debugslips = 0; +static int polling = 0; + +#ifdef FANCY_ALARM +static int altab[] = { +0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, +}; +#endif + +#define FLAG_STARTED (1 << 0) +#define FLAG_NMF (1 << 1) +#define FLAG_SENDINGYELLOW (1 << 2) + +#define TYPE_T1 1 /* is a T1 card */ +#define TYPE_E1 2 /* is an E1 card */ +#define TYPE_J1 3 /* is a running J1 */ + +#define AP4_CAS_SYNC_MASK 0xF0 +#define AP4_CAS_SYNC_WORD 0x00 +#define AP4_CAS_FRAME_WORD 0x0B + +struct devtype { + char *desc; + unsigned int flags; +}; + +static struct devtype ap401 = { "Aligera AP401", 0 }; +static struct devtype ap402 = { "Aligera AP402", 0 }; +static struct devtype ap404 = { "Aligera AP404", 0 }; +static struct devtype ap408 = { "Aligera AP408", 0 }; +static struct devtype ape401 = { "Aligera APE401", 0 }; +static struct devtype ape402 = { "Aligera APE402", 0 }; +static struct devtype ape404 = { "Aligera APE404", 0 }; + +struct ap4; + +struct ap4_span { + struct ap4 *owner; + unsigned int *writechunk; /* Double-word aligned write memory */ + unsigned int *readchunk; /* Double-word aligned read memory */ + int spantype; /* card type, T1 or E1 or J1 */ + int sync; + int psync; + int alarmtimer; + int redalarms; + int alarmcount; + int spanflags; + int syncpos; + int e1check; /* E1 check */ + int reload_cas; + int casenable; + int cassync; + unsigned char casbuf[16]; + unsigned int slipcount; + struct dahdi_span span; + unsigned char txsigs[16]; /* Transmit sigs */ + int loopupcnt; + int loopdowncnt; + unsigned char ec_chunk1[31][DAHDI_CHUNKSIZE]; /* first EC chunk buffer */ + unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE]; /* second EC chunk buffer */ + int irqmisses; + struct dahdi_chan *chans[31]; /* Individual channels */ +#ifdef APEC_SUPPORT + struct apec_s *apec; +#endif +}; + +struct ap4_tdm_errors { + volatile u8 cv; + volatile u8 crc; + volatile u8 slip; + u8 __unused; +} __attribute__ ((packed)); + +struct ap4_tdm_regs { + volatile u8 config; + volatile u8 status; + volatile u8 led; + u8 __unused; + struct ap4_tdm_errors errors; + u32 __reserved[2]; +} __attribute__ ((packed)); + +struct ap4_echo_regs { + volatile u32 ctrl; // 40h R16 + volatile u32 data; // 44h R17 +} __attribute__ ((packed)); + +struct ap4_regs { + volatile u32 card_id; // 00h R0 + volatile u16 fpga_ver; // 04h R1 + volatile u16 span_num; // 06h R1 + volatile u32 __unused; // 08h R2 + volatile u32 liu_config; // 0Ch R3 + volatile u32 e1_config; // 10h R4 + volatile u32 e1_status; // 14h R5 + volatile u32 leds; // 18h R6 + volatile u32 clock_source; // 1Ch R7 + volatile u32 hw_id; // 20h R8 + volatile u32 irq_config; // 24h R9 + volatile u8 tdm_page; // 28h R10 + volatile u8 tdm_page_num; // 29h R10 + volatile u16 tdm_page_bytes; // 2Ah R10 + volatile u32 irq_count; // 2Ch R11 + volatile u32 cvs; // 30h R12 + volatile u32 crc_errors; // 34h R13 + volatile u32 irq_clear; // 38h R14 + volatile u32 slips; // 3Ch R15 + //volatile u32 echo_ctrl; // 40h R16 + //volatile u32 echo_data; // 44h R17 + struct ap4_echo_regs echo; // 40h-44h R16-17 + volatile u32 t1_status; // 48h R18 + volatile u32 t1_config; // 4Ch R19 + volatile u32 __reserved[12]; // 50-7Ch R20-31 + struct ap4_tdm_regs tdm[8]; // 80h +} __attribute__ ((packed)); + +struct ap4 { + /* This structure exists one per card */ + struct pci_dev *dev; /* Pointer to PCI device */ + struct ap4_regs *hw_regs; + struct ap4_echo_regs *echo_regs; + struct ap4_tdm_regs *tdm_regs; + unsigned int intcount; + int flag_1st_irq; + int num; /* Which card we are */ + int fpgaver; /* version of FPGA */ + int hwid; /* hardware ID */ + int syncsrc; /* active sync source */ + struct ap4_span *tspans[AP4_SPAN_MAX]; /* Individual spans */ + int numspans; /* Number of spans on the card */ + int t1_support; + int blinktimer[4]; +#ifdef FANCY_ALARM + int alarmpos[4]; +#endif + int irq; /* IRQ used by device */ + int order; /* Order */ + int flags; /* Device flags */ + int ledreg; /* LED Register */ + int e1recover; /* E1 recovery timer */ + volatile unsigned int *membase; /* Base address of card */ + volatile u32 *database; /* Data base address of card */ + int spansstarted; /* number of spans started */ + /* spinlock_t lock; */ /* lock context */ + spinlock_t reglock; /* lock register access */ + volatile unsigned int *writechunk; /* Double-word aligned write memory */ + volatile unsigned int *readchunk; /* Double-word aligned read memory */ + unsigned int readpage; + unsigned int writepage; + unsigned int numpages; + unsigned int pagebytes; + unsigned int pagesize; + unsigned int pageoffset; + unsigned int passno; /* number of interrupt passes */ + struct devtype *dt; + char *variety; + int last0; /* for detecting double-missed IRQ */ + int checktiming; /* Set >0 to cause the timing source to be checked */ +#ifdef AP400_HDLC + struct card_s *hdlc_card; +#endif +#ifdef AP400_E1_TEST + int e1_test; + int e1_result[AP4_SPAN_MAX]; +#endif +#ifdef APEC_SUPPORT + int apec_enable; + struct apec_s *apec[2]; +#endif +}; + +static int ap4_startup(struct dahdi_span *span); +static int ap4_shutdown(struct dahdi_span *span); +static int ap4_maint(struct dahdi_span *span, int cmd); +static int ap4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data); +static int __ap4_rbsbits(struct dahdi_chan *chan, int bits); +static int ap4_rbsbits(struct dahdi_chan *chan, int bits); +static int ap4_chanconfig(struct dahdi_chan *chan, int sigtype); +static int ap4_open(struct dahdi_chan *chan); +static int ap4_close(struct dahdi_chan *chan); +static void __ap4_set_timing_source(struct ap4 *wc, int unit); +static void __ap4_check_alarms(struct ap4 *wc, int span); +static void __ap4_check_sigbits(struct ap4 *wc, int span); + +#define MAX_AP4_CARDS 64 + +static struct ap4 *cards[MAX_AP4_CARDS]; + +//#define ap_debugk(fmt,args...) printk("ap400 -> %s: "fmt, __PRETTY_FUNCTION__, ##args) +#define ap_debugk(fmt,args...) + +#define AP4_PCI_DEVICE_ID 0x1004 + +static inline void __ap4_set_led(struct ap4 *wc, int span, int color) +{ + if (wc->tdm_regs) { + wc->tdm_regs[span].led = color; + } else { + wc->ledreg &= ~(1 << span); + wc->ledreg |= color << span; + wc->hw_regs->leds &= ~0x0000000F; + wc->hw_regs->leds |= (wc->ledreg) & 0x0F; + } +} + +static inline void ap4_irq_enable(struct ap4 *wc) { + /* Enable interrupt */ + wc->hw_regs->irq_config |= AP_INT_CTL_ENABLE; +} + +static inline void ap4_irq_disable(struct ap4 *wc) { + /* Disable interrupt */ + wc->hw_regs->irq_config &= ~AP_INT_CTL_ENABLE; +} + +static inline volatile u32 *ap4_get_page_address(struct ap4 * wc, + int page, int span, int chan) +{ + /* Select page */ + unsigned int offset = wc->pageoffset * page; + /* Select span */ + offset += span * wc->pagesize * 32; + offset += chan * wc->pagesize; + return &wc->database[offset]; +} + +static inline unsigned int ap4_next_read_page(struct ap4 *wc) { + return wc->readpage = (wc->hw_regs->tdm_page + 1) % 2; +} + +static inline unsigned int ap4_next_write_page(struct ap4 *wc) { + return wc->writepage = (wc->hw_regs->tdm_page + 1) % 2; +} + +static inline unsigned int ap4_cas_read(struct ap4 *wc, int span, int caspos) +{ + volatile u32 *caspage = ap4_get_page_address(wc, caspos / 2, span, 16); + return (unsigned int) caspage[caspos % 2]; +} + +static inline void ap4_cas_write(struct ap4 *wc, int span, int caspos) +{ + unsigned int *casdata = (unsigned int *) wc->tspans[span]->txsigs; + volatile u32 *caspage = ap4_get_page_address(wc, caspos / 2, span, 16); + caspage[caspos % 2] = casdata[caspos % 4]; +} + +#define APEC_CTRL_RESET_WORD 0xE0000000 + +#ifdef APEC_SUPPORT + +#define APEC_CTRL_RESET 0x80000000 +#define APEC_CTRL_DDR_NCKE 0x40000000 +#define APEC_CTRL_EC_DISABLE 0x20000000 +#define APEC_CTRL_EC0_ENABLE 0x01000000 +#define APEC_CTRL_EC1_ENABLE 0x02000000 +#define APEC_CTRL_DAS 0x00080000 +#define APEC_CTRL_RD 0x00040000 +#define APEC_CTRL_REQ 0x00020000 +#define APEC_CTRL_READY 0x00010000 +#define APEC_CTRL_ACCESS_MASK 0x000FFFFF + +#define APEC_ACCESS_TIMEOUT 1000 + +/* Poll echo machine ready bit until timeout */ +static inline int oct_ready_poll(struct ap4_echo_regs *echo_regs) +{ + int i = APEC_ACCESS_TIMEOUT; + while ((echo_regs->ctrl & APEC_CTRL_READY) == 0 && i-- > 0); + return 0; +} + +static void oct_set_mod(struct ap4_echo_regs *echo_regs, unsigned mod_num) +{ + // Poll ready bit + oct_ready_poll(echo_regs); + echo_regs->ctrl &= 0xFF0FFFFF; + echo_regs->ctrl |= (mod_num & 0x3) << 20; +} + +static inline u16 oct_raw_read (struct ap4_echo_regs *echo_regs, unsigned short addr) +{ + unsigned short data; + // Poll ready bit + oct_ready_poll(echo_regs); + // Write control bits and address + echo_regs->ctrl &= ~APEC_CTRL_ACCESS_MASK; + echo_regs->ctrl |= APEC_CTRL_RD | APEC_CTRL_REQ | (addr & 0xFFFF); + // Poll ready bit + oct_ready_poll(echo_regs); + data = echo_regs->data & 0xFFFF; + //PDEBUG("Raw Read 0x%04hX @ 0x%08X", data, addr); + return data; +} + +static inline void oct_raw_write (struct ap4_echo_regs *echo_regs, + unsigned short addr, unsigned short data) +{ + // Poll ready bit + oct_ready_poll(echo_regs); + // Write data, then control bits and address + echo_regs->data = data & 0xFFFF; + echo_regs->ctrl &= ~APEC_CTRL_ACCESS_MASK; + echo_regs->ctrl |= APEC_CTRL_REQ | (addr & 0xFFFF); + // Poll ready bit + oct_ready_poll(echo_regs); + //PDEBUG("Raw Write 0x%04hX @ 0x%08X", data, addr); + //oct_raw_read(regs, addr); +} + +static inline int oct_ext_wait (struct ap4_echo_regs *echo_regs) +{ + int i = APEC_ACCESS_TIMEOUT; + while ((oct_raw_read(echo_regs, 0x0) & 0x100) && (i-- > 0)); + if (i == -1) { + printk(KERN_WARNING "Wait access request timeout\n"); + return -1; + } + return 0; +} + +static inline u16 oct_ind_read (struct ap4_echo_regs *echo_regs, unsigned int addr) +{ + // Poll access_req bit + if (oct_ext_wait(echo_regs)) + return 0; + // Write extended indirect registers + oct_raw_write(echo_regs, 0x8, (addr >> 20) & 0x1FFF); + oct_raw_write(echo_regs, 0xA, (addr >> 4) & 0xFFFF); + oct_raw_write(echo_regs, 0x0, ((addr & 0xE) << 8) | 0x101); + // Poll access_req bit + if (oct_ext_wait(echo_regs)) + return 0; + // Return data + return oct_raw_read(echo_regs, 0x4); +} + +static inline void oct_ind_write (struct ap4_echo_regs *echo_regs, + unsigned int addr, unsigned short data) +{ + // Poll access_req bit + if (oct_ext_wait(echo_regs)) + return; + oct_raw_write(echo_regs, 0x8, (addr >> 20) & 0x1FFF); + oct_raw_write(echo_regs, 0xA, (addr >> 4) & 0xFFFF); + oct_raw_write(echo_regs, 0x4, data); + oct_raw_write(echo_regs, 0x0, ((addr & 0xE) << 8) | 0x3101); + // Poll access_req bit + if (oct_ext_wait(echo_regs)) + return; +} + +static inline u16 oct_dir_read (struct ap4_echo_regs *echo_regs, unsigned int addr) +{ + // Poll access_req bit + if (oct_ext_wait(echo_regs)) + return 0; + // Write extended direct registers + oct_raw_write(echo_regs, 0x8, (addr >> 20) & 0x1FFF); + oct_raw_write(echo_regs, 0xA, (addr >> 4) & 0xFFFF); + oct_raw_write(echo_regs, 0x0, 0x1); + echo_regs->ctrl = APEC_CTRL_DAS | APEC_CTRL_RD | APEC_CTRL_REQ | (addr & 0xFFFF); + while ((echo_regs->ctrl & APEC_CTRL_READY) == 0); + // Return data + return echo_regs->data; +} + +static inline void oct_dir_write (struct ap4_echo_regs *echo_regs, + unsigned int addr, unsigned short data) +{ + // Poll access_req bit + if (oct_ext_wait(echo_regs)) + return; + // Write extended direct registers + oct_raw_write(echo_regs, 0x8, (addr >> 20) & 0x1FFF); + oct_raw_write(echo_regs, 0xA, (addr >> 4) & 0xFFFF); + oct_raw_write(echo_regs, 0x0, 0x3001); + echo_regs->data = data & 0xFFFF; + echo_regs->ctrl = APEC_CTRL_DAS | APEC_CTRL_REQ | (addr & 0xFFFF); + while ((echo_regs->ctrl & APEC_CTRL_READY) == 0); +} + +unsigned int oct_read (void *card, unsigned int addr) +{ + struct ap4 *wc = card; + unsigned long flags; + unsigned short data; + spin_lock_irqsave(&wc->reglock, flags); + data = oct_ind_read(wc->echo_regs, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + PDEBUG("Read 0x%04hX @ 0x%08X", data, addr); + return data; +} + +void oct_write (void *card, unsigned int addr, unsigned int data) +{ + struct ap4 *wc = card; + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + oct_ind_write(wc->echo_regs, addr, data); + spin_unlock_irqrestore(&wc->reglock, flags); + PDEBUG("Write 0x%04hX @ 0x%08X", data, addr); +} + +static int ap4_apec_init_one(struct ap4 *wc, int offset) +{ + int laws[AP4_SPAN_MAX]; + int i; + unsigned int apec_capacity; + struct firmware embedded_firmware; + const struct firmware *firmware = &embedded_firmware; +#if !defined(HOTPLUG_FIRMWARE) + extern void _binary_OCT6104E_64D_ima_size; + extern u8 _binary_OCT6104E_64D_ima_start[]; + extern void _binary_OCT6104E_128D_ima_size; + extern u8 _binary_OCT6104E_128D_ima_start[]; +#else + static const char oct64_firmware[] = "OCT6104E-64D.ima"; + static const char oct128_firmware[] = "OCT6104E-128D.ima"; +#endif + + /* Setup alaw vs ulaw rules */ + for (i = 4 * offset; i < wc->numspans; i++) { + if (wc->tspans[i]->span.channels > 24) + laws[i - 4 * offset] = 1; // E1: alaw + else + laws[i - 4 * offset] = 0; // T1: ulaw + } + /* Set APEC module CS */ + oct_set_mod(wc->echo_regs, offset); + + switch (apec_capacity = apec_capacity_get(wc)) { + case 64: +#if defined(HOTPLUG_FIRMWARE) + if ((request_firmware(&firmware, oct64_firmware, &wc->dev->dev) != 0) || + !firmware) { + printk("%s: firmware %s not available from userspace\n", + wc->variety, oct64_firmware); + return -1; + } +#else + embedded_firmware.data = _binary_OCT6104E_64D_ima_start; + /* Yes... this is weird. objcopy gives us a symbol containing + the size of the firmware, not a pointer to a variable containing + the size. The only way we can get the value of the symbol + is to take its address, so we define it as a pointer and + then cast that value to the proper type. + */ + embedded_firmware.size = (size_t) &_binary_OCT6104E_64D_ima_size; +#endif + break; + case 128: +#if defined(HOTPLUG_FIRMWARE) + if ((request_firmware(&firmware, oct128_firmware, &wc->dev->dev) != 0) || + !firmware) { + printk("%s: firmware %s not available from userspace\n", + wc->variety, oct128_firmware); + return -1; + } +#else + embedded_firmware.data = _binary_OCT6104E_128D_ima_start; + /* Yes... this is weird. objcopy gives us a symbol containing + the size of the firmware, not a pointer to a variable containing + the size. The only way we can get the value of the symbol + is to take its address, so we define it as a pointer and + then cast that value to the proper type. + */ + embedded_firmware.size = (size_t) &_binary_OCT6104E_128D_ima_size; +#endif + break; + default: + printk(KERN_INFO "Unsupported channel capacity found on" + "echo cancellation module (%d).\n", apec_capacity); + return -1; + } + + if (!(wc->apec[offset] = apec_init(wc, laws, apec_capacity / 32, firmware))) { + printk(KERN_WARNING "APEC: Failed to initialize\n"); + if (firmware != &embedded_firmware) + release_firmware(firmware); + return -1; + } + + if (firmware != &embedded_firmware) + release_firmware(firmware); + + printk(KERN_INFO "APEC%d: Present and operational servicing %d span(s)\n", + offset, apec_capacity / 32); + return apec_capacity / 32; +} + +void ap4_apec_release(struct ap4 *wc) +{ + int i; + /* Disable DDR and reset Octasic */ + wc->echo_regs->ctrl = APEC_CTRL_RESET_WORD; + for (i = 0; i < 2; ++i) { + oct_set_mod(wc->echo_regs, i); + if (wc->apec[i]) + apec_release(wc->apec[i]); + } +} + +static int ap4_apec_init(struct ap4 *wc) +{ + int i; + int apec_capacity; + + /* Test if already initiated */ + if (wc->apec[0] || wc->apec[1]) + return 0; + + /* Enable DDR and Reset Octasic */ + wc->echo_regs->ctrl = APEC_CTRL_RESET_WORD; + udelay(500); + wc->echo_regs->ctrl &= ~APEC_CTRL_RESET_WORD; + + apec_capacity = ap4_apec_init_one(wc, 0); + if (apec_capacity > 0) + wc->echo_regs->ctrl |= APEC_CTRL_EC0_ENABLE; + for (i = 0; i < apec_capacity; ++i) { + wc->tspans[i]->apec = wc->apec[0]; + } + + if (wc->numspans > 4) { + apec_capacity = ap4_apec_init_one(wc, 1); + if (apec_capacity > 0) + wc->echo_regs->ctrl |= APEC_CTRL_EC1_ENABLE; + for (i = 0; i < apec_capacity; ++i) { + wc->tspans[i+4]->apec = wc->apec[1]; + } + } + + if (!wc->apec[0] && !wc->apec[1]) { + printk(KERN_INFO "%s: No echo cancelation module found for this card\n", + wc->variety); + ap4_apec_release(wc); + return -1; + } + + return 0; +} + +static int ap4_echocan(struct dahdi_chan *chan, int eclen) +{ + struct ap4 *wc = chan->pvt; + struct apec_s *apec = wc->tspans[chan->span->offset]->apec; + int channel; + + if (!apec) + return -ENODEV; + if (debug) + printk(KERN_DEBUG "AP400: ap4_echocan @ Span %d Channel %d Length: %d\n", + chan->span->offset, chan->chanpos, eclen); + oct_set_mod(wc->echo_regs, chan->span->offset / 4); + channel = (chan->chanpos << 2) | (chan->span->offset % 4); + apec_setec(apec, channel, eclen); + return 0; +} + +#endif // APEC_SUPPORT + + +static int ap4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) +{ + struct ap4 *wc = chan->pvt; + int span = 0; + int alarms = 0; + unsigned char config, status; + + PDEBUG("AP4_IOCTL: %d", cmd); + switch(cmd) { + case AP4_GET_ALARMS: + if (copy_from_user(&span, (int *)data, sizeof(int))) + return -EFAULT; + // span starts in zero + span--; + if (wc->tspans[span]->spantype == TYPE_E1) { + /* Read status and configuration from span */ + if (wc->tdm_regs) { + status = wc->tdm_regs[span].status; + config = wc->tdm_regs[span].config; + } else { + status = wc->hw_regs->e1_status >> (8 * span); + config = wc->hw_regs->e1_config >> (8 * span); + } + if (status & AP_E1_LOS_STATUS) { + alarms = 0x01; + } else if (status & AP_E1_AIS_STATUS) { + alarms = 0x02; + } else if (!(status & AP_E1_BFAE_STATUS)) { + alarms = 0x04; + if (status & AP_E1_RAI_STATUS) + alarms |= 0x08; + // Erro de MFA: 00 - MFA desabilitado, 01 - erro de MFA, 10 - MFA OK + if ((status & AP_E1_MFAE_STATUS) && (config & AP_E1_CRCEN_CONFIG)) + alarms |= 0x10; + else if ((!(status & AP_E1_MFAE_STATUS)) && (config & AP_E1_CRCEN_CONFIG)) + alarms |= 0x20; + // Erro de CAS: 00 - desabilitado, 01 - erro de CAS, 10 - CAS OK + if ((!(status & AP_E1_CAS_STATUS)) && (config & AP_E1_PCM30_CONFIG)) + alarms |= 0x40; + else if ((status & AP_E1_CAS_STATUS) && (config & AP_E1_PCM30_CONFIG)) + alarms |= 0x80; + } + } else { + /* Read status and configuration from span */ + status = wc->hw_regs->e1_status >> (8 * span); + if (status & AP_E1_LOS_STATUS) + alarms = 0x01; + else { + status = wc->hw_regs->t1_status >> (8*span); + if (!(status & AP4_T1_FRAME_SYNC)) + alarms = 0x04; + } + } + if (debug) + printk("AP4_GET_ALARMS: span = %d, alarms = 0x%02x\n", span+1, alarms); + if (copy_to_user((int *)data, &alarms, sizeof(int))) + return -EFAULT; + break; + + case AP4_GET_SLIPS: + if (copy_from_user(&span, (int *)data, sizeof(int))) + return -EFAULT; + // span starts in zero + span--; + if((span < wc->numspans) && (span >=0)) + alarms = wc->tspans[span]->slipcount; + if (debug) + printk("AP4_GET_SLIPS: span = %d, slips = 0x%02x\n", span+1, alarms); + if (copy_to_user((int *)data, &alarms, sizeof(int))) + return -EFAULT; + break; + + default: + PDEBUG("%s: Unknown IOCTL CODE (0x%8X!", wc->variety, cmd); + return -ENOTTY; + } + return 0; +} + +static int ap4_maint(struct dahdi_span *span, int cmd) +{ + struct ap4_span *ts = span->pvt; + struct ap4 *wc = ts->owner; + + PDEBUG("AP4_MAINT %d", cmd); + if (ts->spantype == TYPE_E1) { + switch(cmd) { + case DAHDI_MAINT_NONE: + printk("XXX Turn off local and remote loops E1 XXX\n"); + if (wc->tdm_regs) + wc->tdm_regs[span->offset].config &= ~AP_E1_LOOP_CONFIG; + else + wc->hw_regs->e1_config &= ~(AP_E1_LOOP_CONFIG << (span->offset * 8)); + break; + case DAHDI_MAINT_LOCALLOOP: + printk("XXX Turn on local loopback E1 XXX\n"); + break; + case DAHDI_MAINT_REMOTELOOP: + printk("XXX Turn on remote loopback E1 XXX\n"); + break; + case DAHDI_MAINT_LOOPUP: + printk("XXX Turn on local loopback on E1 #%d instead of send loopup code XXX\n", span->spanno); + if (wc->tdm_regs) + wc->tdm_regs[span->offset].config |= AP_E1_LOOP_CONFIG; + else + wc->hw_regs->e1_config |= AP_E1_LOOP_CONFIG << (span->offset * 8); + break; + case DAHDI_MAINT_LOOPDOWN: + printk("XXX Turn on local loopback on E1 #%d instead of send loopdown code XXX\n", span->spanno); + if (wc->tdm_regs) + wc->tdm_regs[span->offset].config |= AP_E1_LOOP_CONFIG; + else + wc->hw_regs->e1_config |= AP_E1_LOOP_CONFIG << (span->offset * 8); + break; + case DAHDI_MAINT_LOOPSTOP: + printk("XXX Stop sending loop codes on E1 #%d XXX\n", span->spanno); + if (wc->tdm_regs) + wc->tdm_regs[span->offset].config &= ~AP_E1_LOOP_CONFIG; + else + wc->hw_regs->e1_config &= ~(AP_E1_LOOP_CONFIG << (span->offset * 8)); + break; + default: + printk("%s: Unknown E1 maint command: %d\n", wc->variety, cmd); + break; + } + } else { + switch(cmd) { + case DAHDI_MAINT_NONE: + printk("XXX Turn off local and remote loops T1 XXX\n"); + break; + case DAHDI_MAINT_LOCALLOOP: + printk("XXX Turn on local loop and no remote loop XXX\n"); + break; + case DAHDI_MAINT_REMOTELOOP: + printk("XXX Turn on remote loopup XXX\n"); + break; + case DAHDI_MAINT_LOOPUP: + break; + case DAHDI_MAINT_LOOPDOWN: + break; + case DAHDI_MAINT_LOOPSTOP: + break; + default: + printk("%s: Unknown T1 maint command: %d\n", wc->variety, cmd); + break; + } + } + return 0; +} + +static int ap4_rbsbits(struct dahdi_chan *chan, int bits) +{ + struct ap4 *wc = chan->pvt; + unsigned long flags; + int res; + spin_lock_irqsave(&wc->reglock, flags); + res = __ap4_rbsbits(chan, bits); + spin_unlock_irqrestore(&wc->reglock, flags); + return res; +} + +static int __ap4_rbsbits(struct dahdi_chan *chan, int bits) +{ + u_char m,c; + int k,n,b; + struct ap4 *wc = chan->pvt; + struct ap4_span *ts = wc->tspans[chan->span->offset]; + volatile unsigned int *writecas; + unsigned int allspansbits; + + if (wc->database) { + if (ts->spantype != TYPE_E1) + return 0; + if (chan->chanpos < 1 || chan->chanpos > 32) + return 0; + if (chan->chanpos < 16) { + ts->txsigs[chan->chanpos] &= 0x0F; + ts->txsigs[chan->chanpos] |= (bits & 0x0F) << 4; + } else { + ts->txsigs[chan->chanpos % 16] &= 0xF0; + ts->txsigs[chan->chanpos % 16] |= bits & 0x0F; + } + ap4_cas_write(wc, chan->span->offset, (chan->chanpos % 16) / 4); + return 0; + } + + writecas = wc->membase + AP_CAS_BASE; + if (debug & DEBUG_RBS) + printk("Setting bits to %d on channel %s\n", bits, chan->name); + k = chan->span->offset; + if (ts->spantype == TYPE_E1) { /* do it E1 way */ + if (chan->chanpos == 16) { + return 0; + } + n = chan->chanpos - 1; + if (chan->chanpos > 15) n--; + b = (n % 15); + c = ts->txsigs[b]; + m = (n / 15) << 2; /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + ts->txsigs[b] = c; + /* monta a word de 32 bits com informacao de todos os spans */ + allspansbits = wc->tspans[0]->txsigs[b]; + if (wc->numspans > 1) { + allspansbits |= (wc->tspans[1]->txsigs[b] << 8); + } + if (wc->numspans == 4) { + allspansbits |= (wc->tspans[2]->txsigs[b] << 16) | + (wc->tspans[3]->txsigs[b] << 24); + } + /* output them to the chip */ + writecas[b] = allspansbits; + ap_debugk("escrito 0x%08x para ser transmitido pelo CAS (b = %d)\n", allspansbits, b); +#if 0 + } else if (ts->span.lineconfig & DAHDI_CONFIG_D4) { + n = chan->chanpos - 1; + b = (n/4); + c = ts->txsigs[b]; + m = ((3 - (n % 4)) << 1); /* nibble selector */ + c &= ~(0x3 << m); /* keep the other nibble */ + c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ + ts->txsigs[b] = c; + /* output them to the chip */ + //__ap4_out( ... ); + } else if (ts->span.lineconfig & DAHDI_CONFIG_ESF) { +#endif + } else { + n = chan->chanpos - 1; + b = (n/2); + c = ts->txsigs[b]; + m = ((n % 2) << 2); /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + ts->txsigs[b] = c; + /* output them to the chip */ + /* monta a word de 32 bits com informacao de todos os spans */ + allspansbits = wc->tspans[0]->txsigs[b]; + if (wc->numspans > 1) { + allspansbits |= (wc->tspans[1]->txsigs[b] << 8); + } + if (wc->numspans == 4) { + allspansbits |= (wc->tspans[2]->txsigs[b] << 16) | + (wc->tspans[3]->txsigs[b] << 24); + } + /* output them to the chip */ + writecas[b] = allspansbits; + ap_debugk("escrito 0x%08x para ser transmitido pelo CAS (b = %d)\n", allspansbits, b); + } + if (debug & DEBUG_RBS) + printk(KERN_DEBUG "Finished setting RBS bits\n"); + return 0; +} + +static int ap4_shutdown(struct dahdi_span *span) +{ + int tspan; + int wasrunning; + unsigned long flags; + struct ap4_span *ts = span->pvt; + struct ap4 *wc = ts->owner; + int i; + int running; + + tspan = span->offset + 1; + if (tspan < 0) { + printk("%s: '%d' isn't us?\n", wc->variety, span->spanno); + return -1; + } + + spin_lock_irqsave(&wc->reglock, flags); + wasrunning = span->flags & DAHDI_FLAG_RUNNING; + + span->flags &= ~DAHDI_FLAG_RUNNING; + if (wasrunning) + wc->spansstarted--; + /* Turn off LED from interface */ + __ap4_set_led(wc, span->offset, AP4_LED_OFF); + if (wc->tdm_regs) + wc->tdm_regs[span->offset].config = AP_E1_RESET_CONFIG; + + /* Test if are there any other spans running */ + running = 0; + for (i = 0; i < wc->numspans; ++i) { + running |= wc->tspans[i]->span.flags & DAHDI_FLAG_RUNNING; + } + + /* Disable interrupts or re-check timing source */ + if (!running) { + printk(KERN_NOTICE "%s: Disabling interrupts since there are " + "no active spans\n", wc->variety); + ap4_irq_disable(wc); + } else + wc->checktiming = 1; + + spin_unlock_irqrestore(&wc->reglock, flags); + + if (debug & DEBUG_MAIN) + printk(KERN_DEBUG "Span %d (%s) shutdown\n", span->spanno, span->name); + return 0; +} + +static int ap4_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) +{ + int i; + struct ap4_span *ts = span->pvt; + struct ap4 *wc = ts->owner; + unsigned int temp; + + printk(KERN_INFO "About to enter spanconfig!\n"); + if (debug & DEBUG_MAIN) + printk(KERN_DEBUG "%s: Configuring span %d\n", wc->variety, span->spanno); + /* XXX We assume lineconfig is okay and shouldn't XXX */ + span->lineconfig = lc->lineconfig; + span->txlevel = lc->lbo; + span->rxlevel = 0; + if (lc->sync < 0) + lc->sync = 0; + if (lc->sync > wc->numspans) + lc->sync = 0; + + /* remove this span number from the current sync sources, if there */ + for(i = 0; i < wc->numspans; i++) { + if (wc->tspans[i]->sync == span->spanno) { + wc->tspans[i]->sync = 0; + wc->tspans[i]->psync = 0; + } + } + wc->tspans[span->offset]->syncpos = lc->sync; + /* if a sync src, put it in proper place */ + if (lc->sync) { + wc->tspans[lc->sync - 1]->sync = span->spanno; + wc->tspans[lc->sync - 1]->psync = span->offset + 1; + } + wc->checktiming = 1; + /* If we're already running, then go ahead and apply the changes */ + if (span->flags & DAHDI_FLAG_RUNNING) + return ap4_startup(span); + +#ifdef APEC_SUPPORT + if (apec_enable && wc->apec_enable) + ap4_apec_init(wc); + else + wc->hw_regs->echo.ctrl = APEC_CTRL_RESET_WORD; +#else + wc->hw_regs->echo.ctrl = APEC_CTRL_RESET_WORD; +#endif + + /* Clear error registers */ + if (wc->tdm_regs) { + temp = readl((u32 *) &wc->tdm_regs->errors); + } else { + temp = wc->hw_regs->slips; + temp = wc->hw_regs->crc_errors; + temp = wc->hw_regs->cvs; + } + + printk(KERN_INFO "Done with spanconfig!\n"); + return 0; +} + +static int ap4_chanconfig(struct dahdi_chan *chan, int sigtype) +{ + int alreadyrunning; + struct ap4 *wc = chan->pvt; + + PDEBUG("AP4_chanconfig on channel %d", chan->chanpos); + alreadyrunning = wc->tspans[chan->span->offset]->span.flags & DAHDI_FLAG_RUNNING; + if (debug & DEBUG_MAIN) { + if (alreadyrunning) + printk(KERN_DEBUG "%s: Reconfigured channel %d (%s) sigtype %d\n", + wc->variety, chan->channo, chan->name, sigtype); + else + printk(KERN_DEBUG "%s: Configured channel %d (%s) sigtype %d\n", + wc->variety, chan->channo, chan->name, sigtype); + } + return 0; +} + +static int ap4_open(struct dahdi_chan *chan) +{ + try_module_get(THIS_MODULE); + return 0; +} + +static int ap4_close(struct dahdi_chan *chan) +{ + module_put(THIS_MODULE); + return 0; +} + +static void ap4_init_spans(struct ap4 *wc) +{ + int i, j; + struct ap4_span *ts; + + for (i = 0; i < wc->numspans; i++) { + ts = wc->tspans[i]; + snprintf(ts->span.name, sizeof(ts->span.name) - 1, "AP4%d%d/%d/%d", + 0, wc->numspans, wc->num + 1, i + 1); + snprintf(ts->span.desc, sizeof(ts->span.desc) - 1, + "AP4%d%d Card %d Span %d", + 0, wc->numspans, wc->num + 1, i + 1); + snprintf(ts->span.location, sizeof(ts->span.location) - 1, + "PCI Bus %02d Slot %02d", + wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); + ts->span.manufacturer = "Aligera"; + dahdi_copy_string(ts->span.devicetype, wc->variety, + sizeof(ts->span.devicetype)); + ts->span.spanconfig = ap4_spanconfig; + ts->span.chanconfig = ap4_chanconfig; + ts->span.startup = ap4_startup; + ts->span.shutdown = ap4_shutdown; + ts->span.rbsbits = ap4_rbsbits; + ts->span.maint = ap4_maint; + ts->span.open = ap4_open; + ts->span.close = ap4_close; + ts->span.channels = 31; + ts->span.deflaw = DAHDI_LAW_ALAW; + ts->span.spantype = "E1"; + ts->span.chans = ts->chans; + ts->span.flags = DAHDI_FLAG_RBS; + ts->span.linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | + DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | + DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF; + ts->span.ioctl = ap4_ioctl; +#ifdef APEC_SUPPORT + ts->span.echocan = ap4_echocan; +#endif + ts->span.pvt = ts; + ts->owner = wc; + ts->span.offset = i; + ts->writechunk = (void *)(wc->writechunk + i * 32 * 2); + ts->readchunk = (void *)(wc->readchunk + i * 32 * 2); + init_waitqueue_head(&ts->span.maintq); + for (j = 0; j < wc->tspans[i]->span.channels; j++) { + struct dahdi_chan *mychans = ts->chans[j]; + sprintf(mychans->name, "AP4%d%d/%d/%d/%d", 0, wc->numspans, wc->num, i + 1, j + 1); + mychans->sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | + DAHDI_SIG_FXSLS | DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | + DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | + DAHDI_SIG_CAS | DAHDI_SIG_EM_E1 | DAHDI_SIG_DACS_RBS | + DAHDI_SIG_MTP2; + mychans->pvt = wc; + mychans->chanpos = j + 1; + } + } + printk("%s: Spans initialized\n", wc->variety); +} + +static void __ap4_set_timing_source(struct ap4 *wc, int unit) +{ + int i; + + if (unit != wc->syncsrc) { + if ((unit > 0) && (unit <= wc->numspans)) { + /* Set clock source to span select by unit */ + wc->hw_regs->clock_source = unit; + } else { + /* Set clock to internal */ + wc->hw_regs->clock_source = 0; + } + if ((unit < 0) || (unit > wc->numspans)) + unit = 0; + wc->syncsrc = unit; + for (i = 0; i < wc->numspans; i++) + wc->tspans[i]->span.syncsrc = unit; + } else { + if (debug & DEBUG_MAIN) + printk(KERN_DEBUG "%s: Timing source already set to %d\n", + wc->variety, unit); + } + printk("%s: Timing source set to %d (clksrc_reg = 0x%08x)\n", + wc->variety, unit, wc->hw_regs->clock_source); +} + +static void __ap4_set_timing_source_auto(struct ap4 *wc) +{ + int i; + struct ap4_span *tsync; + int alarms; + + wc->checktiming = 0; + for (i = 0; i < wc->numspans; i++) { + if (wc->tspans[i]->sync) { + tsync = wc->tspans[wc->tspans[i]->psync - 1]; + alarms = tsync->span.alarms; + if ((tsync->span.flags & DAHDI_FLAG_RUNNING) && + !(alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE) )) { + /* Valid timing source */ + __ap4_set_timing_source(wc, wc->tspans[i]->psync); + return; + } + } + } + __ap4_set_timing_source(wc, 0); +} + +static void __ap4_configure_t1(struct ap4 *wc, int unit, int lineconfig, int txlevel) +{ + char *framing, *line; + unsigned int config = 0; + unsigned int param = 0; + unsigned int linecode = 0; + + wc->tspans[unit]->spantype = TYPE_T1; + wc->tspans[unit]->span.channels = 24; + wc->tspans[unit]->span.deflaw = DAHDI_LAW_MULAW; + wc->tspans[unit]->span.spantype = "T1"; + + /* Frame configuration */ + param = AP4_T1_NE1_SEL | AP4_T1_CAS_ENABLE; + if (lineconfig & DAHDI_CONFIG_D4) { + framing = "D4"; + } else { + framing = "ESF"; + param |= AP4_T1_ESF_NSF; + } + config = wc->hw_regs->t1_config; + config &= ~(0x000000ff << (8 * unit)); + config |= (param << (8 * unit)); + wc->hw_regs->t1_config = config; + + /* Configure line code */ + if (unit < 2) + linecode = AP_LIU1_LINECODE; + else + linecode = AP_LIU2_LINECODE; + + if (lineconfig & DAHDI_CONFIG_AMI) { + wc->hw_regs->leds |= linecode; + line = "AMI"; + } else { + wc->hw_regs->leds &= ~linecode; + line = "B8ZS"; + } + + /* Configure LIU Signaling for T1 */ + config = wc->hw_regs->liu_config; + config &= ~(0x000000ff << (8 * unit)); + config |= (AP_PULS_DSX1_0FT << (8 * unit)); + wc->hw_regs->liu_config = config; + + if (!polling) { + __ap4_check_alarms(wc, unit); + __ap4_check_sigbits(wc, unit); + } + printk("%s: Span %d configured for %s/%s\n", wc->variety, unit + 1, framing, line); +} + +static void __ap4_configure_e1(struct ap4 *wc, int unit, int lineconfig) +{ + char *crc4 = ""; + char *framing, *line; + unsigned int config = 0; + unsigned int param = 0; + unsigned int linecode = 0; + + wc->tspans[unit]->spantype = TYPE_E1; + wc->tspans[unit]->span.channels = 31; + wc->tspans[unit]->span.deflaw = DAHDI_LAW_ALAW; + wc->tspans[unit]->span.spantype = "E1"; + + /* Frame configuration */ + param = AP_E1_FRAME_CONFIG; + if (lineconfig & DAHDI_CONFIG_CCS) { + framing = "CCS"; + wc->tspans[unit]->casenable = 0; + } else { + framing = "CAS"; + param |= AP_E1_CASEN_CONFIG | AP_E1_PCM30_CONFIG; + wc->tspans[unit]->txsigs[0] = AP4_CAS_FRAME_WORD; + wc->tspans[unit]->cassync = -1; + wc->tspans[unit]->casenable = 1; + } + + if (lineconfig & DAHDI_CONFIG_CRC4) { + crc4 = "/CRC4"; + param |= AP_E1_CRCEN_CONFIG; + } + + if (wc->tdm_regs) { + wc->tdm_regs[unit].config = param; + } else { + config = wc->hw_regs->e1_config; + config &= ~(0x000000ff << (8 * unit)); + config |= (param << (8 * unit)); + wc->hw_regs->e1_config = config; + } + + /* Disable T1 framer */ + config = wc->hw_regs->t1_config; + config &= ~(0x000000ff << (8 * unit)); + wc->hw_regs->t1_config = config; + + /* Line interface Configuration */ + if (unit < 2) + linecode = AP_LIU1_LINECODE; + else + linecode = AP_LIU2_LINECODE; + + if (lineconfig & DAHDI_CONFIG_AMI) { + wc->hw_regs->leds |= linecode; + line = "AMI"; + } else { + wc->hw_regs->leds &= ~linecode; + line = "HDB3"; + } + + /* Configure LIU Signaling for E1 */ + config = wc->hw_regs->liu_config; + config &= ~(0x000000ff << (8 * unit)); + config |= (AP_PULS_E1_120 << (8 * unit)); + wc->hw_regs->liu_config = config; + + if (!polling) { + __ap4_check_alarms(wc, unit); + __ap4_check_sigbits(wc, unit); + } + printk(KERN_NOTICE "%s: Span %d configured for %s/%s%s\n", + wc->variety, unit + 1, framing, line, crc4); +} + +static int ap4_startup(struct dahdi_span *span) +{ + int i; + int tspan; + unsigned long flags; + int alreadyrunning; + struct ap4_span *ts = span->pvt; + struct ap4 *wc = ts->owner; + unsigned int temp; + + printk(KERN_INFO "About to enter startup!\n"); + tspan = span->offset + 1; + if (tspan < 0) { + printk("%s: Span '%d' isn't us?\n", wc->variety, span->spanno); + return -1; + } + + spin_lock_irqsave(&wc->reglock, flags); + + alreadyrunning = span->flags & DAHDI_FLAG_RUNNING; + + /* initialize the start value for the entire chunk of last ec buffer */ + for(i = 0; i < span->channels; i++) { + memset(ts->ec_chunk1[i], + DAHDI_LIN2X(0, span->chans[i]), DAHDI_CHUNKSIZE); + memset(ts->ec_chunk2[i], + DAHDI_LIN2X(0, span->chans[i]), DAHDI_CHUNKSIZE); + } + + /* Force re-evaluation of timing source */ + wc->syncsrc = -1; + + if ((span->lineconfig & DAHDI_CONFIG_D4) || (span->lineconfig & DAHDI_CONFIG_ESF)) { + /* T1 configuration */ +#if 0 + if (!wc->t1_support) { + printk("%s: T1 is not supported on this card\n", wc->variety); + return -1; + } +#endif + __ap4_configure_t1(wc, span->offset, span->lineconfig, span->txlevel); + } else { /* E1 configuration */ + __ap4_configure_e1(wc, span->offset, span->lineconfig); + } + + if (!alreadyrunning) { + span->flags |= DAHDI_FLAG_RUNNING; + if (!wc->spansstarted) { + // Enable interrupt + ap4_irq_enable(wc); + // Disregard first IRQ misses + wc->flag_1st_irq = 16; + // Clear IRQ status + temp = wc->hw_regs->irq_clear; + } + wc->spansstarted++; + if (!polling) { + __ap4_check_alarms(wc, span->offset); + __ap4_check_sigbits(wc, span->offset); + } + } + spin_unlock_irqrestore(&wc->reglock, flags); + +#if 1 + for (i = 0; i < wc->numspans; ++i) { + if (wc->tspans[i]->sync == span->spanno) + printk("SPAN %d: Sync Source %d\n", span->spanno, i + 1); + } +#else + if (wc->tspans[0]->sync == span->spanno) + printk("SPAN %d: Primary Sync Source\n",span->spanno); + if (wc->numspans == 2 && wc->tspans[1]->sync == span->spanno) + printk("SPAN %d: Secondary Sync Source\n",span->spanno); + if (wc->numspans == 4) { + if (wc->tspans[2]->sync == span->spanno) + printk("SPAN %d: Tertiary Sync Source\n",span->spanno); + if (wc->tspans[3]->sync == span->spanno) + printk("SPAN %d: Quaternary Sync Source\n",span->spanno); + } + if (wc->numspans == 8) { + if (wc->tspans[4]->sync == span->spanno) + printk("SPAN %d: Quinary Sync Source\n",span->spanno); + if (wc->tspans[5]->sync == span->spanno) + printk("SPAN %d: Senary Sync Source\n",span->spanno); + if (wc->tspans[6]->sync == span->spanno) + printk("SPAN %d: Septenary Sync Source\n",span->spanno); + if (wc->tspans[7]->sync == span->spanno) + printk("SPAN %d: Octonary Sync Source\n",span->spanno); + } +#endif + + printk(KERN_INFO "Completed startup!\n"); + return 0; +} + +static void ap4_receiveprep(struct ap4 *wc) +{ +#ifdef AP4_CYCLES_STATS + cycles_t start = get_cycles(); +#endif + volatile unsigned int *readdata; + unsigned int buffer[32]; + unsigned char *byte = (unsigned char *) buffer; + int i, j, k; + struct ap4_span *ts; + + if (wc->database) { /* New way */ + /* Update read page number */ + wc->readpage = ap4_next_read_page(wc); + for (i = 0; i < wc->numspans; ++i) { + /* Get read page address from channel 1 from each span */ + readdata = ap4_get_page_address(wc, wc->readpage, i, 1); + ts = wc->tspans[i]; + /* Read data only from opened channel on running span */ + if (ts->span.flags & DAHDI_FLAG_RUNNING) { + for (j = 0; j < ts->span.channels; ++j) { + if (ts->span.chans[j]->flags & DAHDI_FLAG_OPEN) + memcpy_fromio(ts->span.chans[j]->readchunk, + readdata, DAHDI_CHUNKSIZE); + readdata += DAHDI_CHUNKSIZE / 4; + } + } + } + } else { /* Old way */ + readdata = wc->membase + AP_DATA_BASE; + for (i = 0; i < DAHDI_CHUNKSIZE; i++) { + /* Prefetch Card data */ + for (j = 0; j < 32; ++j) { + buffer[j] = readdata[j]; + } + for (j = 0; j < wc->numspans; j++) { + ts = wc->tspans[j]; + /* Set first timeslot for first channel */ + if (ts->spantype == TYPE_E1) { + for (k = 0; k < 31; ++k) { + /* Skip first timeslot from E1 */ + ts->span.chans[k]->readchunk[i] = + byte[4*(k+1)+j]; + } + } else { + for (k = 0; k < 24; ++k) { + ts->span.chans[k]->readchunk[i] = + byte[4*k+j]; + } + } + } + readdata += 32; + } + } +#ifdef AP4_CYCLES_STATS + ap4_update_rx_cycles_stats(start); +#endif + + for (i = 0; i < wc->numspans; i++) { + if (wc->tspans[i]->span.flags & DAHDI_FLAG_RUNNING) { + for (j = 0; j < wc->tspans[i]->span.channels; j++) { + /* Echo cancel double buffered data */ + dahdi_ec_chunk(wc->tspans[i]->span.chans[j], + wc->tspans[i]->span.chans[j]->readchunk, + wc->tspans[i]->ec_chunk2[j]); + memcpy(wc->tspans[i]->ec_chunk2[j],wc->tspans[i]->ec_chunk1[j], + DAHDI_CHUNKSIZE); + memcpy(wc->tspans[i]->ec_chunk1[j], + wc->tspans[i]->span.chans[j]->writechunk, + DAHDI_CHUNKSIZE); + } + dahdi_receive(&wc->tspans[i]->span); + } + } +} + +#if (DAHDI_CHUNKSIZE != 8) +#error Sorry, AP400 driver does not support chunksize != 8 +#endif + +static void ap4_transmitprep(struct ap4 *wc) +{ + volatile unsigned int *writedata; + int i, j, k; + unsigned int tmp; + struct ap4_span *ts; +#ifdef AP4_CYCLES_STATS + cycles_t start; +#endif + for (i = 0; i < wc->numspans; i++) { + if (wc->tspans[i]->span.flags & DAHDI_FLAG_RUNNING) + dahdi_transmit(&wc->tspans[i]->span); + } +#ifdef AP4_CYCLES_STATS + start = get_cycles(); +#endif + + if (wc->database) { /* New way */ + /* Update write page number */ + wc->writepage = ap4_next_write_page(wc); + for (i = 0; i < wc->numspans; ++i) { + /* Get write page address from channel 1 from each span */ + writedata = ap4_get_page_address(wc, wc->writepage, i, 1); + ts = wc->tspans[i]; + /* Write data only on opened channel on running span */ + if (ts->span.flags & DAHDI_FLAG_RUNNING) { + for (j = 0; j < ts->span.channels; ++j) { + if (ts->span.chans[j]->flags & DAHDI_FLAG_OPEN) { + memcpy_toio(writedata, + ts->span.chans[j]->writechunk, + DAHDI_CHUNKSIZE); + } + writedata += DAHDI_CHUNKSIZE / 4; + } + } + } + } else { /* Old way */ + writedata = wc->membase + AP_DATA_BASE; + for (i = 0; i < DAHDI_CHUNKSIZE; i++) { + // Once per chunk + for (k = 0; k < 32; k++) { + // All channels + tmp = 0; + for (j = 0; j < wc->numspans; ++j) { + ts = wc->tspans[j]; + if (ts->spantype == TYPE_T1 && k < 24) + tmp |= ts->span.chans[k]->writechunk[i] << (8 * j); + else if (k > 0) /* Span Type is E1, skip first timeslot */ + tmp |= ts->span.chans[k-1]->writechunk[i] << (8 * j); + } + writedata[k] = tmp; + } + // Advance pointer by 4 TDM frame lengths + writedata += 32; + } + } +#ifdef AP4_CYCLES_STATS + ap4_update_tx_cycles_stats(start); +#endif +} + +static void ap4_tdm_loop(struct ap4 *wc) +{ + volatile unsigned int *buf_ptr; + volatile unsigned int *readdata; + volatile unsigned int *writedata; + int i, j; + unsigned int tmp; + + if (wc->database) { + wc->readpage = ap4_next_read_page(wc); + wc->writepage = ap4_next_write_page(wc); + readdata = &wc->database[wc->readpage * wc->pageoffset]; + writedata = &wc->database[wc->writepage * wc->pageoffset]; + for (i = 0; i < wc->pageoffset; ++i) + writedata[i] = readdata[i]; + } else { + buf_ptr = wc->membase + AP_DATA_BASE; + for (i = 0; i < DAHDI_CHUNKSIZE; i++) { + // Once per chunk + for (j = 0; j < 32; j++) { + tmp = buf_ptr[j]; + buf_ptr[j] = tmp; + } + buf_ptr += 32; + } + } +} + +#ifdef AP400_E1_TEST +#define AP4_E1_TEST_SET_TIME 2000 +#define AP4_E1_TEST_END_TIME 3000 + +static void ap4_e1_test(struct ap4 *wc) +{ + volatile unsigned int *data; + unsigned int buffer[32]; + unsigned char *byte = (unsigned char *) buffer; + int i, j, k; + + /* Write data */ + if (wc->e1_test < AP4_E1_TEST_SET_TIME) { + if (wc->database) { /* New way */ + wc->writepage = ap4_next_write_page(wc); + data = ap4_get_page_address(wc, wc->writepage, 0, 0); + for (i = 0; i < 256; ++i) { + if (i % 32 == 0) + continue; + data[2 * i] = (i % 32) * 0x01010101; + data[2 * i + 1] = (i % 32) * 0x01010101; + } + } else { /* Old way */ + data = wc->membase + AP_DATA_BASE; + for (i = 0; i < DAHDI_CHUNKSIZE; i++) { + for (j = 1; j < 32; j++) { + data[j] = j * 0x01010101; + } + data += 32; /* Advance pointer to next E1 Frame */ + } + } + } + /* Read and check data */ + if ((wc->e1_test >= AP4_E1_TEST_SET_TIME) + && (wc->e1_test < AP4_E1_TEST_END_TIME)) { + if (wc->database) { /* New Way */ + wc->readpage = ap4_next_read_page(wc); + data = ap4_get_page_address(wc, wc->readpage, 0, 0); + for (i = 0; i < 256; ++i) { + if (i % 32 == 0) + continue; + if ((data[2 * i + 1] != (i % 32) * 0x01010101) || + (data[2 * i] != (i % 32) * 0x01010101)) { + wc->e1_result[(i / 32) % 8]++; + } + } + } else { /* Old Way */ + data = wc->membase + AP_DATA_BASE; + for (i = 0; i < DAHDI_CHUNKSIZE; i++) { + /* Prefetch Card data */ + for (k = 0; k < 32; ++k) + buffer[k] = data[k]; + for (j = 0; j < wc->numspans; j++) { + /* Set first timeslot for first channel */ + for (k = 1; k < 32; ++k) { + /* Skip first timeslot from E1 */ + if ((int) (byte[4 * k + j]) != k) + wc->e1_result[j]++; + } + } + data += 32; + } + } + } + /* Increment test time */ + wc->e1_test++; + /* Report fails */ + if (wc->e1_test >= AP4_E1_TEST_END_TIME) { + for (i = 0; i < wc->numspans; i++) { + if (wc->e1_result[i]) { + printk(KERN_ERR "Falha teste E1: " + "Problema com span %d \n", i + 1); + } else { + printk(KERN_ERR "Teste E1: " + "Span %d OK\n", i + 1); + } + wc->e1_result[i] = 0; + } + tdm_loop = 0; + wc->e1_test = 0; + } +} +#endif + +static void ap4_r2_da_handler(struct dahdi_chan *chan, int rxsig) +{ + struct ap4 *wc = chan->pvt; + struct ap4_span *ts; + struct dahdi_chan *conf; + + if (r2_double_answer != 1) + return; + + if (!chan->confna) + return; + + if (((rxsig & 0xC) != 0x4) && ((rxsig & 0xC) != 0xC)) + return; + + ts = wc->tspans[(chan->confna - 1) / 31]; + conf = ts->chans[(chan->confna - 1) % 31]; + __ap4_rbsbits(conf, rxsig); +} + +static inline int ap4_cas_sync(unsigned char *buf) +{ + int i; + int offset = -1; /* Returns -1, if no sync found */ + for (i = 0; i < 16; ++i) { + if ((buf[i] & AP4_CAS_SYNC_MASK) == AP4_CAS_SYNC_WORD) { + if (offset > -1) + return -2; /* Two sync words found */ + else + offset = i; /* Set offset from sync */ + } + } + return offset; +} + +static inline void ap4_cas_handle(struct ap4 *wc, int span) +{ + struct ap4_span *ts = wc->tspans[span]; + int i, j; + unsigned int oldcas, newcas, rxs; + unsigned char *oldcasbuf = ts->casbuf; + unsigned char newcasbuf[16]; + int newsync; + + /* Span in alarm, send blocked signaling */ + if (ts->reload_cas) { + for (i = 0; i < 31; ++i) { + if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { + if (ts->span.chans[i]->rxsig != 0xd) { + dahdi_rbsbits(ts->span.chans[i], 0xd); + } + } + } + } + /* Read new CAS from E1 */ + for (i = 0; i < 4; i++) { + newcas = ap4_cas_read(wc, span, i); + for (j = 0; j < 4; ++j) { + newcasbuf[4 * i + j] = newcas & 0xFF; + newcas >>= 8; + } + } + /* Search new CAS sync */ + newsync = ap4_cas_sync(newcasbuf); + if (newsync < 0) { /* No CAS sync found */ + return; + } + /* Check CAS data, if CAS OK */ + if (ts->cassync == newsync) { /* CAS OK */ + for (i = 0; i < 15; ++i) { + /* Fetch CAS data with sync offset */ + oldcas = oldcasbuf[(i + 1 + newsync) % 16]; + newcas = newcasbuf[(i + 1 + newsync) % 16]; + /* Test if old and new CAS data are equal to prevent glitches */ + /* Check first nibble */ + if ((newcas & 0xF) == (oldcas & 0xF)) { + rxs = newcas & 0xF; + if (!(ts->span.chans[i+16]->sig & DAHDI_SIG_CLEAR) && + (ts->span.chans[i+16]->rxsig != rxs)) { + dahdi_rbsbits(ts->span.chans[i+16], rxs); + ap4_r2_da_handler(ts->span.chans[i+16], rxs); + } + } + /* Check second nibble */ + if ((newcas & 0xF0) == (oldcas & 0xF0)) { + rxs = (newcas >> 4) & 0xF; + if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR) && + (ts->span.chans[i]->rxsig != rxs)) { + dahdi_rbsbits(ts->span.chans[i], rxs); + ap4_r2_da_handler(ts->span.chans[i], rxs); + } + } + } + } + /* Copy new data over old data */ + ts->cassync = newsync; + memcpy(oldcasbuf, newcasbuf, 16); + return; +} + +static void __ap4_check_sigbits(struct ap4 *wc, int span) +{ + int a,i,rxs; + struct ap4_span *ts = wc->tspans[span]; + volatile unsigned int *readcas = (wc->membase+AP_CAS_BASE); + + if (!(ts->span.flags & DAHDI_FLAG_RUNNING)) + return; + /* If Alarm is RED or Blue, set timeout to change CAS from block */ + if( (ts->span.alarms & DAHDI_ALARM_RED) || (ts->span.alarms & DAHDI_ALARM_BLUE) ) { + ts->reload_cas = 4; + } else if(ts->reload_cas > 0) { + ts->reload_cas--; + } + + if (wc->database) { + if (ts->spantype != TYPE_E1) + return; + ap4_cas_handle(wc, span); + return; + } + + if (ts->spantype == TYPE_E1) { + for (i = 0; i < 15; i++) { + /* if Span is in alarm, send blocked 1101 */ + if(ts->reload_cas) { + a = 0xdd; + } else { + a = (int) ts->casbuf[i+1]; + } + ts->casbuf[i+1] = (unsigned char) (readcas[i] >> (8*span)) & 0xff; + + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(ts->span.chans[i+16]->sig & DAHDI_SIG_CLEAR)) { + if (ts->span.chans[i+16]->rxsig != rxs) { + ap_debugk("CAS no canal %d mudou de 0x%02x para 0x%02x\n", i+16, ts->span.chans[i+16]->rxsig, rxs); + dahdi_rbsbits(ts->span.chans[i+16], rxs); + ap4_r2_da_handler(ts->span.chans[i+16], rxs); + } + } + rxs = (a >> 4) & 0xf; + if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { + if (ts->span.chans[i]->rxsig != rxs) { + ap_debugk("CAS no canal %d mudou de 0x%02x para 0x%02x\n", i, ts->span.chans[i]->rxsig, rxs); + dahdi_rbsbits(ts->span.chans[i], rxs); + ap4_r2_da_handler(ts->span.chans[i], rxs); + } + } + } + } else if (ts->span.lineconfig & DAHDI_CONFIG_D4) { + for (i = 0; i < 12; i++) { + a = (unsigned char) (readcas[i] >> (8*span)) & 0xcc; + rxs = a & 0xc; + //rxs = (a & 0xc) >> 2; + if (!(ts->span.chans[2*i]->sig & DAHDI_SIG_CLEAR)) { + if (ts->span.chans[2*i]->rxsig != rxs) { + dahdi_rbsbits(ts->span.chans[2*i], rxs); + } + } + rxs = (a >> 4) & 0xc; + //rxs = ((a >> 4) & 0xc) >> 2; + if (!(ts->span.chans[2*i+1]->sig & DAHDI_SIG_CLEAR)) { + if (ts->span.chans[2*i+1]->rxsig != rxs) { + dahdi_rbsbits(ts->span.chans[2*i+1], rxs); + } + } + } + } else { // ESF + for (i = 0; i < 12; i++) { + a = (unsigned char) (readcas[i] >> (8*span)) & 0xff; + rxs = (a & 0xf); + if (!(ts->span.chans[2*i+1]->sig & DAHDI_SIG_CLEAR)) { + if (ts->span.chans[2*i+1]->rxsig != rxs) { + dahdi_rbsbits(ts->span.chans[2*i+1], rxs); + } + } + rxs = (a >> 4) & 0xf; + if (!(ts->span.chans[2*i]->sig & DAHDI_SIG_CLEAR)) { + if (ts->span.chans[2*i]->rxsig != rxs) { + dahdi_rbsbits(ts->span.chans[2*i], rxs); + } + } + } + } +} + +static void __ap4_check_alarms(struct ap4 *wc, int span) +{ + unsigned char status; + unsigned char config; + int alarms; + int i, j; + struct ap4_span *ts = wc->tspans[span]; + + if (!(ts->span.flags & DAHDI_FLAG_RUNNING)) + return; + + /* Assume no alarms */ + alarms = DAHDI_ALARM_NONE; + + /* And consider only carrier alarms */ + ts->span.alarms &= DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_NOTOPEN; + + if (ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN) { + for (i = 0, j = 0; i < ts->span.channels; i++) + if ((ts->span.chans[i]->flags & DAHDI_FLAG_OPEN) || + (ts->span.chans[i]->flags & DAHDI_FLAG_NETDEV)) + j++; + if (!j) + alarms |= DAHDI_ALARM_NOTOPEN; + } + + /* Read status and configuration from span */ + if (wc->tspans[span]->spantype == TYPE_E1) { + if (wc->tdm_regs) { + status = wc->tdm_regs[span].status; + config = wc->tdm_regs[span].config; + } else { + status = wc->hw_regs->e1_status >> (8 * span); + config = wc->hw_regs->e1_config >> (8 * span); + } + + if ((status & AP_E1_LOS_STATUS) || + (status & AP_E1_BFAE_STATUS) || + (status & AP_E1_AIS_STATUS)) { + if (ts->alarmcount >= alarmdebounce) + alarms |= DAHDI_ALARM_RED; + else + ts->alarmcount++; + } else + ts->alarmcount = 0; + + if ((status & AP_E1_MFAE_STATUS) && (config & AP_E1_CRCEN_CONFIG)) + alarms |= DAHDI_ALARM_BLUE; + + if ((!(status & AP_E1_CAS_STATUS)) && (config & AP_E1_PCM30_CONFIG)) + alarms |= DAHDI_ALARM_BLUE; + +#if 0 + if (ts->casenable && (ts->cassync < 0)) { + alarms |= DAHDI_ALARM_BLUE; + } +#endif + } else { + status = wc->hw_regs->e1_status >> (8 * span); + if (status & AP_E1_LOS_STATUS) { + if (ts->alarmcount >= alarmdebounce) + alarms |= DAHDI_ALARM_RED; + else + ts->alarmcount++; + } else + ts->alarmcount = 0; + status = wc->hw_regs->t1_status >> (8 * span); + if (!(status & AP4_T1_FRAME_SYNC)) + alarms |= DAHDI_ALARM_RED; + } + + if (((!ts->span.alarms) && alarms) || (ts->span.alarms && (!alarms))) + wc->checktiming = 1; + + /* Keep track of recovering */ + if ((!alarms) && ts->span.alarms) + ts->alarmtimer = DAHDI_ALARMSETTLE_TIME; + if (ts->alarmtimer) + alarms |= DAHDI_ALARM_RECOVER; + + + // If receiving alarms, go into Yellow alarm state + if (alarms && !(ts->spanflags & FLAG_SENDINGYELLOW)) { + printk(KERN_WARNING "Setting yellow alarm on span %d\n", span + 1); + if (wc->tdm_regs) + wc->tdm_regs[span].config |= AP_E1_RAI_CONFIG; + else + wc->hw_regs->e1_config |= AP_E1_RAI_CONFIG << (8 * span); + ts->spanflags |= FLAG_SENDINGYELLOW; + } else if ((!alarms) && (ts->spanflags & FLAG_SENDINGYELLOW)) { + printk(KERN_NOTICE "Clearing yellow alarm on span %d\n", span + 1); + if (wc->tdm_regs) + wc->tdm_regs[span].config &= ~AP_E1_RAI_CONFIG; + else + wc->hw_regs->e1_config &= ~(AP_E1_RAI_CONFIG << (8 * span)); + ts->spanflags &= ~FLAG_SENDINGYELLOW; + } + + // Re-check the timing source when we enter/leave alarm, not withstanding yellow alarm + if (status & AP_E1_RAI_STATUS) + alarms |= DAHDI_ALARM_YELLOW; + + if (ts->span.mainttimer || ts->span.maintstat) + alarms |= DAHDI_ALARM_LOOPBACK; + + ts->span.alarms = alarms; + dahdi_alarm_notify(&ts->span); +} + +static void __ap4_do_counters(struct ap4 *wc) +{ + int span; + + for (span = 0; span < wc->numspans; span++) { + struct ap4_span *ts = wc->tspans[span]; + int docheck=0; + if (ts->loopupcnt || ts->loopdowncnt) + docheck++; + if (ts->alarmtimer) { + if (!--ts->alarmtimer) { + docheck++; + ts->span.alarms &= ~(DAHDI_ALARM_RECOVER); + } + } + if (docheck) { + if (!polling) + __ap4_check_alarms(wc, span); + dahdi_alarm_notify(&ts->span); + } + } +} + +#define MAX_BLINKTIMER 0x14 + +static inline void __handle_leds(struct ap4 *wc) +{ + int i; + unsigned char status; + struct ap4_span *ts; + + if (wc->tdm_regs) { + for (i = 0; i < wc->numspans; i++) { + status = wc->tdm_regs[i].status; + ts = wc->tspans[i]; + if (ts->span.flags & DAHDI_FLAG_RUNNING) { + if (status & AP_E1_LOS_STATUS) { + __ap4_set_led(wc, i, AP4_LED_SLOW); + } else if (ts->span.alarms + & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE)) { + __ap4_set_led(wc, i, AP4_LED_FAST); + } else /* No Alarm */ + __ap4_set_led(wc, i, AP4_LED_ON); + } + } + } else { + for (i = 0; i < wc->numspans; i++) { + ts = wc->tspans[i]; + /* Read Status from E1 Interface */ + status = wc->hw_regs->e1_status >> (8 * i); + if (ts->span.flags & DAHDI_FLAG_RUNNING) { + if (status & AP_E1_LOS_STATUS) { + if (wc->blinktimer[i] >= altab[wc->alarmpos[i]]) + __ap4_set_led(wc, i, AP4_LED_ON); + if (wc->blinktimer[i] >= (MAX_BLINKTIMER - 1)) + __ap4_set_led(wc, i, AP4_LED_OFF); + wc->blinktimer[i] += 1; + } else if (ts->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE)) { + if (wc->blinktimer[i] >= altab[wc->alarmpos[i]]) + __ap4_set_led(wc, i, AP4_LED_ON); + if (wc->blinktimer[i] >= (MAX_BLINKTIMER-2)) + __ap4_set_led(wc, i, AP4_LED_OFF); + wc->blinktimer[i] += 3; + } else { + /* No Alarm */ + __ap4_set_led(wc, i, AP4_LED_ON); + } + } else { + /* Interface not running */ + __ap4_set_led(wc, i, AP4_LED_OFF); + } + if (wc->blinktimer[i] > MAX_BLINKTIMER) { + wc->blinktimer[i] = 0; + wc->alarmpos[i]++; + if (wc->alarmpos[i] >= (sizeof(altab) / sizeof(altab[0]))) + wc->alarmpos[i] = 0; + } + } + } +} + +static inline void ap4_update_stats(struct ap4 *wc) +{ + int i; + unsigned int temp; + + clock_source = wc->hw_regs->clock_source; + + if (wc->tdm_regs) { + for (i = 0; i < wc->numspans; i++) { + wc->tspans[i]->span.bpvcount += wc->tdm_regs[i].errors.cv; + wc->tspans[i]->span.crc4count += wc->tdm_regs[i].errors.crc; + temp = wc->tdm_regs[i].errors.slip; + if (temp) { + wc->tspans[i]->slipcount += temp; + if (debug) + printk(KERN_DEBUG "Slip detected on span %d: " + "slipcount = %d\n", + i + 1, wc->tspans[i]->slipcount); + } + } + } else { + temp = wc->hw_regs->cvs; + for (i = 0; i < wc->numspans; i++) + wc->tspans[i]->span.bpvcount += (temp >> (8 * i)) & 0xff; + temp = wc->hw_regs->crc_errors; + for (i = 0; i < wc->numspans; i++) + wc->tspans[i]->span.crc4count += (temp >> (8 * i)) & 0xff; + temp = wc->hw_regs->slips; + for (i = 0; i < wc->numspans; i++) { + if (((temp >> (8 * i)) & 0xff) && + (!(wc->tspans[i]->span.alarms & DAHDI_ALARM_RED))) { + wc->tspans[i]->slipcount++; + if (debug) + printk(KERN_DEBUG "Slip detected on span %d: " + "slipcount = %d\n", + i + 1, wc->tspans[i]->slipcount); + } + } + } +} + +DAHDI_IRQ_HANDLER(ap4_interrupt) +{ + struct ap4 *wc = dev_id; + int i; + int ret = 0; + unsigned int temp; + + /* Check if it is our IRQ */ + temp = wc->hw_regs->irq_config; + if ((temp & AP_INT_CTL_ENABLE) == 0 || (temp & AP_INT_CTL_ACTIVE) == 0) { + ret = 0; + goto out; + } + + /* Acknowledge IRQ */ + temp = wc->hw_regs->irq_clear; + + /* Update IRQ misses counter */ + if (wc->flag_1st_irq > 0) { + /* Disregard first 16 IRQ misses */ + temp = wc->hw_regs->irq_count; + if (temp > 0) { + wc->flag_1st_irq--; + wc->hw_regs->irq_count = 0; + for (i = 0; i < wc->numspans; i++) + wc->tspans[i]->span.irqmisses = 0; + } + /* Disregard first CRC errors */ + temp = wc->hw_regs->crc_errors; + } else { + /* Read IRQ counter, should be 1, else we missed some IRQ */ + temp = wc->hw_regs->irq_count; + /* Reset counter */ + wc->hw_regs->irq_count = 0; + /* Increment IRQ misses */ + if (temp > 0) { + for (i = 0; i < wc->numspans; i++) + wc->tspans[i]->span.irqmisses += (temp - 1); + } + } + + if (!wc->spansstarted) { + /* Not prepped yet! */ + ret = 0; + goto out; + } + + wc->intcount++; + + if (!tdm_loop) { + ap4_receiveprep(wc); + ap4_transmitprep(wc); +#ifdef AP400_E1_TEST + } else if (tdm_loop < 0) { + ap4_e1_test(wc); +#endif + } else { + ap4_tdm_loop(wc); + } + + /* Update stats every 128ms */ + if (!(wc->intcount & 0x7f)) + ap4_update_stats(wc); + + __handle_leds(wc); + + __ap4_do_counters(wc); + + /* Check alarms and sigbits */ + if (wc->intcount % 2) + __ap4_check_alarms(wc, (wc->intcount / 2) % wc->numspans); + else + __ap4_check_sigbits(wc, (wc->intcount / 2) % wc->numspans); + + if (wc->checktiming > 0) + __ap4_set_timing_source_auto(wc); + + /* IRQ was treated */ + ret = 1; +out: +#ifdef AP400_HDLC + /* Call AP400_HDLC_CARD IRQ handler before leave */ + ret |= ap400_intr_handler(irq, wc->hdlc_card); +#endif + + return IRQ_RETVAL(ret); +} + +static int __devinit ap4_launch(struct ap4 *wc) +{ + int i; + + /* Test if spans already registered */ + if (wc->tspans[0]->span.flags & DAHDI_FLAG_REGISTERED) + return 0; + + /* Register Spans */ + printk("%s: Launching card: %d\n", wc->variety, wc->order); + + for (i = 0; i < wc->numspans; ++i) { + if (dahdi_register(&wc->tspans[i]->span, 0)) { + printk(KERN_ERR "Unable to register span %s\n", + wc->tspans[i]->span.name); + return -1; + } + } + + /* Check timing on next interruption */ + wc->checktiming = 1; + + return 0; +} + +static inline int ap4_liu_reset(struct ap4 *wc) +{ + unsigned int jiffies_hold = jiffies; + wc->hw_regs->leds |= AP_LIU_RESET_BIT; + while (jiffies <= (jiffies_hold + 2)); + wc->hw_regs->leds &= ~AP_LIU_RESET_BIT; + return 0; +} + +static int ap4_bus_test(struct ap4 *wc) +{ + int tst_result = 0; + unsigned int val; + + *(wc->membase+AP_E1_CONFIG_REG) = 0xAAAAAAAA; + *wc->membase = 0; // flush + val = *(wc->membase+AP_E1_CONFIG_REG); + if(val != 0xAAAAAAAA) { + printk("Escrito 0xAAAAAAAA, lido 0x%08X!\n", val); + tst_result++; + } + *(wc->membase+AP_E1_CONFIG_REG) = 0x55555555; + *wc->membase = 0; // flush + val = *(wc->membase+AP_E1_CONFIG_REG); + if(val != 0x55555555) { + printk("Escrito 0x55555555, lido 0x%08X!\n", val); + tst_result++; + } + *(wc->membase+AP_E1_CONFIG_REG) = 0xFFFFFFFF; + *wc->membase = 0; // flush + val = *(wc->membase+AP_E1_CONFIG_REG); + if(val != 0xFFFFFFFF) { + printk("Escrito 0xFFFFFFFF, lido 0x%08X!\n", val); + tst_result++; + } + *(wc->membase+AP_E1_CONFIG_REG) = 0x00000000; + *wc->membase = 0xFFFFFFFF; // flush + val = *(wc->membase+AP_E1_CONFIG_REG); + if(val != 0x00000000) { + printk("Escrito 0x00000000, lido 0x%08X!\n", val); + tst_result++; + } + return tst_result; +} + +static inline int ap4_card_detect (struct ap4 *wc) { + int i; + if ((wc->hw_regs->card_id != AP4XX_CARD_ID) && + (wc->hw_regs->card_id != APE4XX_CARD_ID)) { + printk("AP400: Unknown card ID(0x%08X)! Aborting...\n", wc->hw_regs->card_id); + return -EPERM; + } + // Test bus integrity + for (i=0; i < 1000; i++) { + if (ap4_bus_test(wc)) { + printk("AP400: Bus integrity test failed! Aborting...\n"); + return -EIO; + } + } + printk("AP400: Bus integrity OK!\n"); + + wc->fpgaver = wc->hw_regs->fpga_ver; + wc->numspans = wc->hw_regs->span_num; + wc->hwid = wc->hw_regs->hw_id & AP_HWID_MASK; + + if ((wc->hwid == AP_HWID_1E1_RJ && wc->numspans != 1) || + (wc->hwid == AP_HWID_2E1_RJ && wc->numspans != 2) || + (wc->hwid == AP_HWID_4E1_RJ && wc->numspans != 4) || + (wc->hwid == AP_HWID_8E1_RJ && wc->numspans != 8)) { + printk("AP400: Incompatible Hardware ID(0x%02x)! Aborting...\n", wc->hwid); + return -EIO; + } + + wc->echo_regs = &wc->hw_regs->echo; + +#ifdef APEC_SUPPORT + if (wc->fpgaver >= 0x0400) + wc->apec_enable = 1; +#endif + + if ((wc->fpgaver >= 0x0500) && (wc->hwid & AP_HWID_T1)) + wc->t1_support = 1; + + if (wc->fpgaver >= 0x0600) { + wc->tdm_regs = wc->hw_regs->tdm; + wc->database = ioremap_nocache(pci_resource_start(wc->dev, 1), + pci_resource_len(wc->dev, 1)); + if (wc->database == NULL) { + printk("AP400: ioremap failed!\n"); + return -EIO; + } + wc->numpages = wc->hw_regs->tdm_page_num; + wc->pagebytes = wc->hw_regs->tdm_page_bytes; + wc->pagesize = wc->pagebytes / 4; + wc->pageoffset = wc->pagesize * wc->numspans * 32; + } + + if (wc->hw_regs->card_id == AP4XX_CARD_ID) + switch (wc->numspans) { + case 1: + wc->dt = (struct devtype *) &ap401; + break; + case 2: + wc->dt = (struct devtype *) &ap402; + break; + case 4: + wc->dt = (struct devtype *) &ap404; + break; + case 8: + wc->dt = (struct devtype *) &ap408; + break; + default: + printk("AP400: Unsupported spans number(%d)! Aborting...\n", + wc->numspans); + return -EPERM; + } + else + switch (wc->numspans) { + case 1: + wc->dt = (struct devtype *) &ape401; + break; + case 2: + wc->dt = (struct devtype *) &ape402; + break; + case 4: + wc->dt = (struct devtype *) &ape404; + break; + default: + printk("APE400: Unsupported spans number(%d)! Aborting...\n", + wc->numspans); + return -EPERM; + } + + wc->variety = wc->dt->desc; + printk("Found a %s (firmware version %d.%d) at %p\n", wc->variety, + wc->fpgaver >> 8, wc->fpgaver & 0xFF, wc->membase); + return 0; +} + +static void __devexit ap4_remove_one(struct pci_dev *pdev); + +static int __devinit ap4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int res; + struct ap4 *wc; + int i, j; + int basesize; + + /* Initialize PCI Device */ + if ((res = pci_enable_device(pdev)) != 0) { + goto out; + } + + // Allocate card struct + wc = kmalloc(sizeof(struct ap4), GFP_KERNEL); + if (wc == NULL) { + res = -ENOMEM; + goto out; + } + + memset(wc, 0x0, sizeof(struct ap4)); + spin_lock_init(&wc->reglock); + + wc->dev = pdev; + + // Request PCI regions + if ((res = pci_request_regions(pdev, "ap400")) != 0) { + printk("AP400: Unable to request regions!\n"); + goto out; + } + + // Remap PCI address + wc->membase = ioremap_nocache(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); + if (wc->membase == NULL) { + printk("AP400: ioremap failed!\n"); + res = -EIO; + goto out; + } + wc->hw_regs = (struct ap4_regs *) wc->membase; + + // Detect Card model + if ((res = ap4_card_detect(wc)) != 0) + goto out; + + basesize = DAHDI_MAX_CHUNKSIZE * 32 * 2 * wc->numspans; + + ap4_liu_reset(wc); + + // This rids of the Double missed interrupt message after loading + wc->last0 = 1; + + // 32 channels, Double-buffer, Read/Write, n spans + wc->writechunk = kmalloc(basesize * 2, GFP_KERNEL); + if (!wc->writechunk) { + printk("%s: Unable to allocate memory!\n", wc->variety); + res = -ENOMEM; + goto out; + } + + // Read is after the whole write piece (in words) + wc->readchunk = wc->writechunk + basesize / 4; + + // Initialize Write/Buffers to all blank data + memset((void *) wc->writechunk, 0x00, basesize); + memset((void *) wc->readchunk, 0xff, basesize); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + /* inicializa contador de interrupcao */ + wc->intcount = 0; + + for(i = 0; i < MAX_AP4_CARDS; i++) { + if (!cards[i]) break; + } + + if (i >= MAX_AP4_CARDS) { + printk("No cards[] slot available!!\n"); + res = -ENOMEM; + goto out; + } + + wc->num = i; + cards[i] = wc; + + /* Allocate pieces we need here, consider 31 channels for E1*/ + for (i = 0; i < wc->numspans; i++) { + wc->tspans[i] = kmalloc(sizeof(struct ap4_span), GFP_KERNEL); + if (wc->tspans[i]) { + memset(wc->tspans[i], 0, sizeof(struct ap4_span)); + wc->tspans[i]->spantype = TYPE_E1; + } else { + res = -ENOMEM; + goto out; + } + for (j = 0; j < 31; j++) { + if (!(wc->tspans[i]->chans[j] = + kmalloc(sizeof(*wc->tspans[i]->chans[j]), GFP_KERNEL))) { + res = -ENOMEM; + goto out; + } + memset(wc->tspans[i]->chans[j], 0, sizeof(*wc->tspans[i]->chans[j])); + } + wc->tspans[i]->spanflags |= wc->dt->flags; + } + + if (request_irq(pdev->irq, ap4_interrupt, IRQF_DISABLED | IRQF_SHARED, + "ap400", wc)) { + printk("%s: Unable to request IRQ %d\n", wc->variety, pdev->irq); + res = -EIO; + goto out; + } + + ap4_init_spans(wc); + + /* Launch cards as appropriate */ + i = 0; + for(;;) { + /* Find a card to activate */ + j = 0; + for (i = 0; cards[i]; i++) { + if (cards[i]->order <= highestorder) { + ap4_launch(cards[i]); + if (cards[i]->order == highestorder) + j = 1; + } + } + /* If we found at least one, increment the highest order and search again, otherwise stop */ + if (j) + highestorder++; + else + break; + } + + /* Initialize HDLC_CARD */ +#ifdef AP400_HDLC + u8 __iomem *base_addr[3]; + unsigned int bar_size[3]; + int i; + base_addr[2] = (void *) wc->membase; + bar_size[2] = wc->memlen; + for (i = 0; i < 2; i++) { + bar_size[i] = (u32) pci_resource_len(pdev, i); + base_addr[i] = ioremap_nocache(pci_resource_start(pdev, i), + bar_size[i]); + if (base_addr[i] == NULL) { + printk(KERN_ERR "Memory map failed\n"); + res = -ENODEV; + goto out; + } + } + ap400_card_init(&wc->hdlc_card, base_addr, bar_size); + ap400_intr_enable(wc->hdlc_card); +#endif + + res = 0; +out: + if (res != 0) { + ap4_remove_one(pdev); + } + return res; +} + +static void __devexit ap4_remove_one(struct pci_dev *pdev) +{ + struct ap4 *wc = pci_get_drvdata(pdev); + int i; + + if (wc) { + // Disable Interrupt + ap4_irq_disable(wc); + +#ifdef APEC_SUPPORT + // Stop echo cancellation module + ap4_apec_release(wc); +#endif + + /* Unregister Spans */ + for (i = 0; i < wc->numspans; ++i) { + if (wc->tspans[i]->span.flags & DAHDI_FLAG_REGISTERED) { + dahdi_unregister(&wc->tspans[i]->span); + } + } + + if (wc->database) + iounmap(wc->database); + + wc->hw_regs = NULL; + if (wc->membase) + iounmap((void *)wc->membase); + + /* Immediately free resources */ + kfree((void *) wc->writechunk); + +#ifdef AP400_HDLC + /* Remove HDLC Card */ + ap400_card_remove(wc->hdlc_card); + if (wc->hdlc_card->cfg_base_addr) + iounmap(wc->hdlc_card->cfg_base_addr); + if (wc->hdlc_card->buf_base_addr) + iounmap(wc->hdlc_card->buf_base_addr); + kfree(wc->hdlc_card); +#endif + free_irq(pdev->irq, wc); + + cards[wc->num] = NULL; + for (i = 0; i < wc->numspans; i++) { + if (wc->tspans[i]) + kfree(wc->tspans[i]); + } + kfree(wc); + } + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + printk(KERN_INFO "AP400 driver removed\n"); +} + +static struct pci_device_id ap4_pci_tbl[] __devinitdata = +{ + { PCI_DEVICE(PCI_VENDOR_ID_XILINX, AP4_PCI_DEVICE_ID), }, + { 0, } +}; + +static struct pci_driver ap4_driver = { + name: "Unified ap400 driver", + probe: ap4_init_one, + remove: __devexit_p(ap4_remove_one), + suspend: NULL, + resume: NULL, + id_table: ap4_pci_tbl, +}; + +static int __init ap4_init(void) +{ + int res; + printk("Unified AP400 PCI Card Driver\n"); + res = dahdi_pci_module(&ap4_driver); + if (res) { + return -ENODEV; + } + /* Initialize global array with all AP4 cards */ + memset(cards, 0, (sizeof(struct ap4 *)) * MAX_AP4_CARDS); + return 0; +} + +static void __exit ap4_cleanup(void) +{ + printk("Unified AP400 PCI Card Driver Cleanup\n"); + pci_unregister_driver(&ap4_driver); +} + +MODULE_AUTHOR("Aligera AP400 Maintainer (ap400@aligera.com.br)"); +MODULE_DESCRIPTION("Unified AP400 PCI Card Driver"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_param(debug, int, 0600); +module_param(loopback, int, 0600); +module_param(noburst, int, 0600); +module_param(debugslips, int, 0600); +module_param(polling, int, 0600); +module_param(timingcable, int, 0600); +module_param(t1e1override, int, 0600); +module_param(alarmdebounce, int, 0600); +module_param(j1mode, int, 0600); + +MODULE_DEVICE_TABLE(pci, ap4_pci_tbl); + +module_init(ap4_init); +module_exit(ap4_cleanup); diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/ap400/ap400.h dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/ap400.h --- dahdi-linux-2.1.0.3/drivers/dahdi/ap400/ap400.h 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/ap400.h 2010-07-16 13:13:15.744373151 -0300 @@ -0,0 +1,112 @@ +/* + * AP400 T1/E1 PCI Driver + * + * Written by Ronaldo Valiati and Wagner Gegler + * + * Based on previous works, designs, and archetectures conceived and + * written by Jim Dixon and Mark Spencer . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2005, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + + +#define AP4_GET_ALARMS _IOW (DAHDI_CODE, 60, int) +#define AP4_GET_SLIPS _IOW (DAHDI_CODE, 61, int) + +#define AP4XX_CARD_ID 0x41434532 // "ACE2" +#define APE4XX_CARD_ID 0x41504534 // "APE4" + +#define AP_CAS_BASE 0x0080 +#define AP_DATA_BASE 0x0100 + +#define AP_CARD_TYPE_REG 0x0001 +#define AP_T1E1_CONFIG_REG 0x0003 +#define AP_E1_CONFIG_REG 0x0004 +#define AP_E1_STATUS_REG 0x0005 +#define AP_LEDS_REG 0x0006 +#define AP_CLKSRC_REG 0x0007 +#define AP_HWCONFIG_REG 0x0008 +#define AP_INT_CONTROL_REG 0x0009 +#define AP_CNT_IRQ_REG 0x000B +#define AP_CNT_CV_REG 0x000C +#define AP_CNT_CRC_REG 0x000D +#define AP_CLEAR_IRQ_REG 0x000E +#define AP_CNT_SLIP_REG 0x000F + +#define AP_LIU1_LINECODE 0x0080 +#define AP_LIU2_LINECODE 0x0100 +#define AP_LIU_RESET_BIT 0x0200 + +#define AP_E1_AIS_STATUS 0x01 +#define AP_E1_BFAE_STATUS 0x02 +#define AP_E1_MFAE_STATUS 0x04 +#define AP_E1_SYNC_STATUS 0x08 +#define AP_E1_CAS_STATUS 0x10 +#define AP_E1_LOS_STATUS 0x20 +#define AP_E1_RAI_STATUS 0x40 + +#define AP_E1_RAI_CONFIG 0x01 +#define AP_E1_FRAME_CONFIG 0x06 +#define AP_E1_LOOP_CONFIG 0x10 +#define AP_E1_CASEN_CONFIG 0x20 +#define AP_E1_PCM30_CONFIG 0x40 +#define AP_E1_CRCEN_CONFIG 0x80 +#define AP_E1_RESET_CONFIG 0x00 + +#define AP_INT_CTL_ENABLE 0x01 +#define AP_INT_CTL_ACTIVE 0x02 + +#define AP_HWID_MASK 0xF0 +#define AP_HWID_1E1_RJ 0x10 +#define AP_HWID_2E1_RJ 0x00 +#define AP_HWID_4E1_RJ 0x20 +#define AP_HWID_8E1_RJ 0x30 +#define AP_HWID_T1 0x40 + +#define AP4_T1_NE1_SEL 0x04 +#define AP4_T1_ESF_NSF 0x02 +#define AP4_T1_CAS_ENABLE 0x01 + +#define AP4_T1_FRAME_SYNC 0x01 + +typedef enum { + AP_PULS_E1_75 = 0, + AP_PULS_E1_120, + AP_PULS_DSX1_0FT, + AP_PULS_DSX1_133FT, + AP_PULS_DSX1_266FT, + AP_PULS_DSX1_399FT, + AP_PULS_DSX1_533FT, + AP_PULS_J1_110, + AP_PULS_DS1_0DB, + AP_PULS_DS1_M075DB, + AP_PULS_DS1_M150DB, + AP_PULS_DS1_M225DB +} liu_mode; + +typedef enum { + AP4_LED_OFF = 0, + AP4_LED_ON, + AP4_LED_SLOW, + AP4_LED_FAST +} led_mode; diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/ap400/apec.c dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/apec.c --- dahdi-linux-2.1.0.3/drivers/dahdi/ap400/apec.c 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/apec.c 2010-07-16 13:13:15.744373151 -0300 @@ -0,0 +1,390 @@ +/* + * AP400 Echo Cancelation Hardware support + * + * Written by Wagner Gegler + * + * Based on previous work written by Mark Spencer + * + * Copyright (C) 2005-2006 Digium, Inc. + * + * Mark Spencer + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "apec.h" +#include "oct6100api/oct6100_api.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#include +#else +#include +#endif + +/* API for Octasic access */ +UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime) +{ + /* Why couldn't they just take a timeval like everyone else? */ + struct timeval tv; + unsigned long long total_usecs; + unsigned int mask = ~0; + + do_gettimeofday(&tv); + total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) + + (((unsigned long long)(tv.tv_usec))); + f_pTime->aulWallTimeUs[0] = (total_usecs & mask); + f_pTime->aulWallTimeUs[1] = (total_usecs >> 32); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength) +{ + memset(f_pAddress, f_ulPattern, f_ulLength); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, UINT32 f_ulLength) +{ + memcpy(f_pDestination, f_pSource, f_ulLength); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate) +{ + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy) +{ +#ifdef OCTASIC_DEBUG + printk("I should never be called! (destroy serialize object)\n"); +#endif + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize) +{ + /* Not needed */ + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease) +{ + /* Not needed */ + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams) +{ + oct_write(f_pWriteParams->pProcessContext, f_pWriteParams->ulWriteAddress, f_pWriteParams->usWriteData); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams) +{ + unsigned int x; + for (x=0;xulWriteLength;x++) { + oct_write(f_pSmearParams->pProcessContext, f_pSmearParams->ulWriteAddress + (x << 1), f_pSmearParams->usWriteData); + } + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams) +{ + unsigned int x; + for (x=0;xulWriteLength;x++) { + oct_write(f_pBurstParams->pProcessContext, f_pBurstParams->ulWriteAddress + (x << 1), f_pBurstParams->pusWriteData[x]); + } + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams) +{ + *(f_pReadParams->pusReadData) = oct_read(f_pReadParams->pProcessContext, f_pReadParams->ulReadAddress); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams) +{ + unsigned int x; + for (x=0;xulReadLength;x++) { + f_pBurstParams->pusReadData[x] = oct_read(f_pBurstParams->pProcessContext, f_pBurstParams->ulReadAddress + (x << 1)); + } + return cOCT6100_ERR_OK; +} + +#if 0 +#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_HT_FREEZE +#else +#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_POWER_DOWN +#endif + +struct apec_s { + tPOCT6100_INSTANCE_API pApiInstance; + UINT32 aulEchoChanHndl[128]; + int chanflags[128]; + int ecmode[128]; + int numchans; +}; + +#define FLAG_DTMF (1 << 0) +#define FLAG_MUTE (1 << 1) +#define FLAG_ECHO (1 << 2) + +static void apec_setecmode(struct apec_s *apec, int channel, int mode) +{ + tOCT6100_CHANNEL_MODIFY *modify; + UINT32 ulResult; + + if (apec->ecmode[channel] == mode) + return; + modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC); + if (!modify) { + printk("APEC: Unable to allocate memory for setec!\n"); + return; + } + Oct6100ChannelModifyDef(modify); + modify->ulEchoOperationMode = mode; + modify->ulChannelHndl = apec->aulEchoChanHndl[channel]; + ulResult = Oct6100ChannelModify(apec->pApiInstance, modify); + if (ulResult != GENERIC_OK) { + printk("Failed to apply echo can changes on channel %d!\n", channel); + } else { +#ifdef OCTASIC_DEBUG + printk("Echo can on channel %d set to %d\n", channel, mode); +#endif + apec->ecmode[channel] = mode; + } + kfree(modify); +} + +void apec_setec(struct apec_s *apec, int channel, int eclen) +{ + if (eclen) { + apec->chanflags[channel] |= FLAG_ECHO; + apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); + apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_NORMAL); + } else { + apec->chanflags[channel] &= ~FLAG_ECHO; + if (apec->chanflags[channel] & (FLAG_DTMF | FLAG_MUTE)) { + apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); + apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE); + } else + apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_DIGITAL); + } + printk("APEC: Setting EC on channel %d to %d\n", channel, eclen); +} + +int apec_checkirq(struct apec_s *apec) +{ + tOCT6100_INTERRUPT_FLAGS InterruptFlags; + + Oct6100InterruptServiceRoutineDef(&InterruptFlags); + Oct6100InterruptServiceRoutine(apec->pApiInstance, &InterruptFlags); + + return InterruptFlags.fToneEventsPending ? 1 : 0; +} + +unsigned int apec_capacity_get(void *wc) +{ + UINT32 ulResult; + + tOCT6100_API_GET_CAPACITY_PINS CapacityPins; + + Oct6100ApiGetCapacityPinsDef(&CapacityPins); + CapacityPins.pProcessContext = wc; + CapacityPins.ulMemoryType = cOCT6100_MEM_TYPE_DDR; + CapacityPins.fEnableMemClkOut = TRUE; + CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; + + ulResult = Oct6100ApiGetCapacityPins(&CapacityPins); + if (ulResult != cOCT6100_ERR_OK) { + printk("Failed to get chip capacity, code %08x!\n", ulResult); + return 0; + } + return CapacityPins.ulCapacityValue; +} + +struct apec_s *apec_init(void *wc, int *isalaw, int numspans, const struct firmware *firmware) +{ + tOCT6100_CHIP_OPEN *ChipOpen; + tOCT6100_GET_INSTANCE_SIZE InstanceSize; + tOCT6100_CHANNEL_OPEN *ChannelOpen; + UINT32 ulResult; + struct apec_s *apec; + int x, law; +#ifdef CONFIG_4KSTACKS + unsigned long flags; +#endif + + if (!(apec = kmalloc(sizeof(struct apec_s), GFP_KERNEL))) + return NULL; + + memset(apec, 0, sizeof(struct apec_s)); + + if (!(ChipOpen = kmalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL))) { + kfree(apec); + return NULL; + } + + memset(ChipOpen, 0, sizeof(tOCT6100_CHIP_OPEN)); + + if (!(ChannelOpen = kmalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL))) { + kfree(apec); + kfree(ChipOpen); + return NULL; + } + + memset(ChannelOpen, 0, sizeof(tOCT6100_CHANNEL_OPEN)); + + for (x=0;x<128;x++) + apec->ecmode[x] = -1; + + apec->numchans = numspans * 32; + printk("APEC: echo cancellation for %d channels\n", apec->numchans); + + Oct6100ChipOpenDef(ChipOpen); + + /* Setup Chip Open Parameters */ + ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; + Oct6100GetInstanceSizeDef(&InstanceSize); + + ChipOpen->pProcessContext = wc; + + ChipOpen->pbyImageFile = firmware->data; + ChipOpen->ulImageSize = firmware->size; + + ChipOpen->fEnableMemClkOut = TRUE; + ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; + ChipOpen->ulMaxChannels = apec->numchans; + ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR; + ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB; + ChipOpen->ulNumMemoryChips = 1; + ChipOpen->ulMaxTdmStreams = 4; + ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ; + ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE; +#if 0 + ChipOpen->fEnableAcousticEcho = TRUE; +#endif + + ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize); + if (ulResult != cOCT6100_ERR_OK) { + printk("Failed to get instance size, code %08x!\n", ulResult); + kfree(apec); + return NULL; + } + + + apec->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize); + if (!apec->pApiInstance) { + printk("Out of memory (can't allocate %d bytes)!\n", InstanceSize.ulApiInstanceSize); + kfree(apec); + kfree(ChipOpen); + kfree(ChannelOpen); + return NULL; + } + + /* I don't know what to curse more in this comment, the problems caused by + * the 4K kernel stack limit change or the octasic API for being so darn + * stack unfriendly. Stupid, stupid, stupid. So we disable IRQs so we + * don't run the risk of overflowing the stack while we initialize the + * octasic. */ +#ifdef CONFIG_4KSTACKS + local_irq_save(flags); +#endif + ulResult = Oct6100ChipOpen(apec->pApiInstance, ChipOpen); + if (ulResult != cOCT6100_ERR_OK) { + printk("Failed to open chip, code %08x!\n", ulResult); +#ifdef CONFIG_4KSTACKS + local_irq_restore(flags); +#endif + kfree(apec); + kfree(ChipOpen); + kfree(ChannelOpen); + return NULL; + } + for (x=0; x < 128; x++) { + /* execute this loop always on 4 span cards but + * on 2 span cards only execute for the channels related to our spans */ + if ((x & 0x3) < numspans) { + /* span timeslots are interleaved 12341234... + * therefore, the lower 2 bits tell us which span this + * timeslot/channel + */ + if (isalaw[x & 0x03]) + law = cOCT6100_PCM_A_LAW; + else + law = cOCT6100_PCM_U_LAW; + Oct6100ChannelOpenDef(ChannelOpen); + ChannelOpen->pulChannelHndl = &apec->aulEchoChanHndl[x]; + ChannelOpen->ulUserChanId = x; + ChannelOpen->TdmConfig.ulRinPcmLaw = law; + ChannelOpen->TdmConfig.ulRinStream = 0; + ChannelOpen->TdmConfig.ulRinTimeslot = x; + ChannelOpen->TdmConfig.ulSinPcmLaw = law; + ChannelOpen->TdmConfig.ulSinStream = 1; + ChannelOpen->TdmConfig.ulSinTimeslot = x; + ChannelOpen->TdmConfig.ulSoutPcmLaw = law; + ChannelOpen->TdmConfig.ulSoutStream = 2; + ChannelOpen->TdmConfig.ulSoutTimeslot = x; + ChannelOpen->TdmConfig.ulRoutPcmLaw = law; + ChannelOpen->TdmConfig.ulRoutStream = 3; + ChannelOpen->TdmConfig.ulRoutTimeslot = x; + ChannelOpen->VqeConfig.fEnableNlp = TRUE; + ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE; + ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE; + + ChannelOpen->fEnableToneDisabler = TRUE; + ChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_DIGITAL; + + ulResult = Oct6100ChannelOpen(apec->pApiInstance, ChannelOpen); + if (ulResult != GENERIC_OK) { + printk("Failed to open channel %d!\n", x); + } + } + } + +#ifdef CONFIG_4KSTACKS + local_irq_restore(flags); +#endif + kfree(ChipOpen); + kfree(ChannelOpen); + return apec; +} + +void apec_release(struct apec_s *apec) +{ + UINT32 ulResult; + tOCT6100_CHIP_CLOSE ChipClose; + + Oct6100ChipCloseDef(&ChipClose); + ulResult = Oct6100ChipClose(apec->pApiInstance, &ChipClose); + if (ulResult != cOCT6100_ERR_OK) { + printk("Failed to close chip, code %08x!\n", ulResult); + } + vfree(apec->pApiInstance); + kfree(apec); + printk(KERN_INFO "APEC: Releasing...\n"); +} diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/ap400/apec.h dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/apec.h --- dahdi-linux-2.1.0.3/drivers/dahdi/ap400/apec.h 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/apec.h 2010-07-16 13:13:15.744373151 -0300 @@ -0,0 +1,48 @@ +/* + * AP400 Echo Cancelation Hardware support + * + * Written by Wagner Gegler + * + * Based on previous work written by Mark Spencer + * + * Copyright (C) 2005-2006 Digium, Inc. + * + * Mark Spencer + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _APEC_H_ +#define _APEC_H_ + +#include + +struct apec_s; + +/* From AP400 */ +unsigned int oct_read(void *card, unsigned int addr); +void oct_write(void *card, unsigned int addr, unsigned int data); + +/* From APEC */ +struct apec_s *apec_init(void *wc, int *isalaw, int numspans, const struct firmware *firmware); +unsigned int apec_capacity_get(void *wc); +void apec_setec(struct apec_s *instance, int channel, int eclen); +int apec_checkirq(struct apec_s *apec); +void apec_release(struct apec_s *instance); + +#endif /*_APEC_H_*/ diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/ap400/Kbuild dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/Kbuild --- dahdi-linux-2.1.0.3/drivers/dahdi/ap400/Kbuild 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/Kbuild 2010-07-16 13:13:15.744373151 -0300 @@ -0,0 +1,26 @@ +obj-m += ap400.o + +EXTRA_CFLAGS := -I$(src)/.. + +ap400-objs := ap400_drv.o + +# APEC_SUPPORT +ECHO_FIRMWARE := $(wildcard $(src)/OCT61*.ima) +ifneq ($(strip $(ECHO_FIRMWARE)),) + EXTRA_CFLAGS+=-DAPEC_SUPPORT $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef + ap400-objs += apec.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x) firmware_oct6104e-64d.o firmware_oct6104e-128d.o +endif + +$(obj)/apec.o: $(src)/apec.h $(src)/../oct612x/include/oct6100api/oct6100_api.h + +$(obj)/firmware_oct6104e-64d.o: $(src)/OCT6104E-64D.ima $(obj)/ap400_drv.o $(src)/../firmware/make_firmware_object + @echo Making firmware object file for $(notdir $<) + @cd $(src) && ../firmware/make_firmware_object $(notdir $<) $@ $(obj)/ap400_drv.o + +$(obj)/firmware_oct6104e-128d.o: $(src)/OCT6104E-128D.ima $(obj)/ap400_drv.o $(src)/../firmware/make_firmware_object + @echo Making firmware object file for $(notdir $<) + @cd $(src) && ../firmware/make_firmware_object $(notdir $<) $@ $(obj)/ap400_drv.o + +$(src)/../firmware/make_firmware_object: + make -C $(src)/../firmware make_firmware_object + diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/ap400/Makefile dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/Makefile --- dahdi-linux-2.1.0.3/drivers/dahdi/ap400/Makefile 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/ap400/Makefile 2010-07-16 13:13:15.744373151 -0300 @@ -0,0 +1,29 @@ +ifneq ($(KBUILD_EXTMOD),) +# We only get here on kernels 2.6.0-2.6.9 . +# For newer kernels, Kbuild will be included directly by the kernel +# build system. +include $(src)/Kbuild + +else + +OCTASIC_OBJS:=$(shell ../oct612x/octasic-helper objects ../oct612x) +OCTASIC_CFLAGS:=$(shell ../oct612x/octasic-helper cflags ../oct612x) -Wno-undef + +all: ap400.o + +%.o: %.c + $(CC) $(KFLAGS) $(OCTASIC_CFLAGS) -o $@ -c $< + +ap400_drv.o: ../zaptel.h apec.h ap400.h + +apec.o: apec.h ../oct612x/include/oct6100api/oct6100_api.h + +firmware_oct6104e-128d.o: $(src)/OCT6104E-128D.ima $(obj)/ap400_drv.o + @echo Making firmware object file for $(notdir $<) + @cd $(src) && ../build_tools/make_firmware_object $(notdir $<) $@ $(obj)/ap400_drv.o + +clean: + rm -f *.o + rm -f $(OCTASIC_OBJS) + +endif \ No newline at end of file diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/Kbuild dahdi-linux-2.1.0.3-ap400/drivers/dahdi/Kbuild --- dahdi-linux-2.1.0.3/drivers/dahdi/Kbuild 2010-03-22 11:22:10.044056000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/Kbuild 2010-04-09 14:32:53.656295358 -0300 @@ -5,21 +5,22 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETH) += dahdi_dynamic_eth.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TRANSCODE) += dahdi_transcode.o -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/ -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/ -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/ -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/ -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/ - -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT1XXP) += wct1xxp.o -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE11XP) += wcte11xp.o - -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCFXO) += wcfxo.o -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TOR2) += tor2.o -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_PCIRADIO) += pciradio.o +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/ +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/ +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/ +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/ +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/ + +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT1XXP) += wct1xxp.o +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE11XP) += wcte11xp.o + +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCFXO) += wcfxo.o +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TOR2) += tor2.o +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_PCIRADIO) += pciradio.o -obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/ +#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/ +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_AP400) += ap400/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_JPAH) += dahdi_echocan_jpah.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE) += dahdi_echocan_sec.o @@ -84,7 +85,7 @@ hostprogs-y := $(obj)/makefw -$(obj)/tor2fw.h: $(src)/tormenta2.rbt $(obj)/makefw +$(obj)/tor2fw.h: $(src)/tormenta2.rbt $(obj)/makefw $(obj)/makefw $< tor2fw > $@ $(obj)/radfw.h: $(src)/pciradio.rbt $(obj)/makefw diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/modules.order dahdi-linux-2.1.0.3-ap400/drivers/dahdi/modules.order --- dahdi-linux-2.1.0.3/drivers/dahdi/modules.order 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/modules.order 2010-03-22 11:21:06.631056000 -0300 @@ -0,0 +1,28 @@ +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_dummy.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_dynamic.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_dynamic_loc.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_dynamic_eth.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_transcode.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wct4xxp/wct4xxp.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wctc4xxp/wctc4xxp.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wctdm24xxp/wctdm24xxp.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wcte12xp/wcte12xp.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wctdm.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wcb4xxp/wcb4xxp.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wct1xxp.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wcte11xp.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wcfxo.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/tor2.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/pciradio.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpp.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpd_fxs.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpd_fxo.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpd_pri.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpp_usb.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/ap400/ap400.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_echocan_jpah.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_echocan_sec.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_echocan_sec2.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_echocan_kb1.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/dahdi_echocan_mg2.ko diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/wcb4xxp/modules.order dahdi-linux-2.1.0.3-ap400/drivers/dahdi/wcb4xxp/modules.order --- dahdi-linux-2.1.0.3/drivers/dahdi/wcb4xxp/modules.order 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/wcb4xxp/modules.order 2010-03-22 11:21:04.986556000 -0300 @@ -0,0 +1 @@ +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wcb4xxp/wcb4xxp.ko diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/wct4xxp/modules.order dahdi-linux-2.1.0.3-ap400/drivers/dahdi/wct4xxp/modules.order --- dahdi-linux-2.1.0.3/drivers/dahdi/wct4xxp/modules.order 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/wct4xxp/modules.order 2010-03-22 11:21:04.922717000 -0300 @@ -0,0 +1 @@ +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wct4xxp/wct4xxp.ko diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/wctdm24xxp/modules.order dahdi-linux-2.1.0.3-ap400/drivers/dahdi/wctdm24xxp/modules.order --- dahdi-linux-2.1.0.3/drivers/dahdi/wctdm24xxp/modules.order 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/wctdm24xxp/modules.order 2010-03-22 11:21:05.931436000 -0300 @@ -0,0 +1 @@ +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wctdm24xxp/wctdm24xxp.ko diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/wcte12xp/modules.order dahdi-linux-2.1.0.3-ap400/drivers/dahdi/wcte12xp/modules.order --- dahdi-linux-2.1.0.3/drivers/dahdi/wcte12xp/modules.order 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/wcte12xp/modules.order 2010-03-22 11:21:06.062556000 -0300 @@ -0,0 +1 @@ +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/wcte12xp/wcte12xp.ko diff -Naur dahdi-linux-2.1.0.3/drivers/dahdi/xpp/modules.order dahdi-linux-2.1.0.3-ap400/drivers/dahdi/xpp/modules.order --- dahdi-linux-2.1.0.3/drivers/dahdi/xpp/modules.order 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/drivers/dahdi/xpp/modules.order 2010-03-22 11:21:05.690556000 -0300 @@ -0,0 +1,5 @@ +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpp.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpd_fxs.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpd_fxo.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpd_pri.ko +kernel//media/oldroot/home/wgegler/Work/dahdi-linux-2.1.0.3/drivers/dahdi/xpp/xpp_usb.ko diff -Naur dahdi-linux-2.1.0.3/include/dahdi/version.h dahdi-linux-2.1.0.3-ap400/include/dahdi/version.h --- dahdi-linux-2.1.0.3/include/dahdi/version.h 1969-12-31 21:00:00.000000000 -0300 +++ dahdi-linux-2.1.0.3-ap400/include/dahdi/version.h 2010-03-22 11:21:07.024157000 -0300 @@ -0,0 +1,6 @@ +/* + * version.h + * Automatically generated + */ +#define DAHDI_VERSION "2.1.0.3" +