From 070605848175b85e1231c5aab39d3266eedfeb99 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 23 Nov 2007 15:21:32 -0500 Subject: [PATCH] Linux 2.2.17pre2 o Fix memory leak in appletalk drivers (Hu Chengjun) o Fix bridge + rtl8139 bug (Jeff Garzik) o ICH audio hack for slow to reset codecs (Vladimir V. Klenov) o One liner fix to the kswapd logic (Rik van Riel) o Fix dtr on close bug in the SX serial driver (Patrick van de Lageweg) o Fix saving of db6 on debug traps (James Cownie) o Teach setup code about transmeta processors (H Peter Anvin) o Fix some SMP races in parport (Tim Waugh) o Fix CDROMPLAYTRKIND, rpc2 region info query (Jens Axboe) o Small AFFS fixes (Dave Jones) o Test fsuid before DAC_OVERRIDE in procfs (Solar Designer) o Add Cyclades PC300 driver (Ivan Passos) o List Andries as partitioning maintainer (Andries Brouwer) o Remove __LIBRARY__ from unistd.h syscall tests (Erik Troan) o Resync 2.2 and 2.4 i810 drivers (Alan Cox) o Upgrade aic7xxx driver to 5.1.30. This should (Doug Ledford) fix the problems with EISA/VLB cards o Resync the ixj telephony driver with Quicknet (Alan Cox) | Word of warning: Stuff built against the 2.2 ixj | driver is back compatible. Stuff built against their | release we merged with is not as they clashed with | ioctls already allocated for other uses. --- Documentation/Configure.help | 28 + MAINTAINERS | 14 + Makefile | 2 +- arch/i386/kernel/setup.c | 121 +- arch/i386/kernel/traps.c | 3 + drivers/cdrom/cdrom.c | 45 +- drivers/char/sx.c | 38 +- drivers/misc/parport_share.c | 83 +- drivers/net/Config.in | 4 + drivers/net/Makefile | 8 + drivers/net/hdlc.c | 7 +- drivers/net/pc300.c | 2815 ++++++++++++++++++++++++++++++ drivers/net/rtl8139.c | 4 +- drivers/pci/oldproc.c | 4 + drivers/scsi/aic7xxx.c | 665 ++++--- drivers/scsi/aic7xxx/aic7xxx.seq | 183 +- drivers/scsi/aic7xxx_seq.c | 705 ++++---- drivers/scsi/sym53c8xx.c | 2 +- drivers/sound/ac97_codec.c | 5 + drivers/sound/i810_audio.c | 75 +- drivers/telephony/ixj.c | 2703 ++++++++++++++++++++-------- drivers/telephony/ixj.h | 324 +++- fs/affs/file.c | 4 +- fs/proc/array.c | 2 +- include/asm-alpha/unistd.h | 4 +- include/asm-i386/processor.h | 2 + include/linux/cdrom.h | 1 + include/linux/falc-lh.h | 1231 +++++++++++++ include/linux/hd64572.h | 437 +++++ include/linux/hdlc.h | 2 + include/linux/ixjuser.h | 90 +- include/linux/pc300.h | 374 ++++ include/linux/pci.h | 4 + include/linux/telephony.h | 70 +- mm/page_alloc.c | 2 +- net/appletalk/ddp.c | 6 +- net/core/dev.c | 4 + 37 files changed, 8374 insertions(+), 1697 deletions(-) create mode 100644 drivers/net/pc300.c create mode 100644 include/linux/falc-lh.h create mode 100644 include/linux/hd64572.h create mode 100644 include/linux/pc300.h diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 73eaf4f0aa54..4a88f1703449 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -5755,6 +5755,34 @@ CONFIG_WANXL If unsure, say N here. +Cyclades-PC300 support +CONFIG_PC300 + This is a driver for the Cyclades-PC300 synchronous communication + boards. These boards provide synchronous serial interfaces to your + Linux box. All protocols supported by the HDLC generic driver + (currently synchronous PPP, Cisco HDLC and Frame Relay) are available + by default. If you wish to support other protocols, please select one + of the available options below this one. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called pc300.o. + + If unsure, say N here. + +Cyclades-PC300 X.25 Support +CONFIG_PC300_X25 + Say Y to this option if you intend to use the Cyclades-PC300 to + provide X.25 interfaces to your Linux box. + + IMPORTANT: Additional X.25 support must be enabled in the kernel + for this support to be functional (say Y to "CCITT X.25 Packet Layer" + and "LAPB Data Link Driver", in the "Networking Options" + configuration section). + + If unsure, say N here. + Ethernet (10 or 100Mbit) CONFIG_NET_ETHERNET Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common diff --git a/MAINTAINERS b/MAINTAINERS index 8bbe69644a01..80e91b564d8c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -220,6 +220,12 @@ M: ivan@cyclades.com W: http://www.cyclades.com/ S: Supported +CYCLADES PC300 DRIVER +P: Ivan Passos +M: ivan@cyclades.com +W: http://www.cyclades.com/ +S: Supported + DAMA SLAVE for AX.25 P: Joerg Reuter M: jreuter@poboxes.com @@ -262,6 +268,14 @@ L: linux-net@vger.rutgers.edu W: http://www.dgii.com/linux/ S: Maintained +DISK GEOMETRY AND PARTITION HANDLING +P: Andries Brouwer +M: aeb@veritas.com +W: http://www.win.tue.nl/~aeb/linux/Large-Disk.html +W: http://www.win.tue.nl/~aeb/linux/zip/zip-1.html +W: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html +S: Maintained + DISKQUOTA: P: Marco van Wieringen M: mvw@planets.elm.net diff --git a/Makefile b/Makefile index 3109dfc15924..815dba3f9051 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 17 -EXTRAVERSION = -pre1 +EXTRAVERSION = pre2 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index e5313252849e..3803766c65ca 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -27,6 +27,8 @@ * Added proper Cascades CPU and L2 cache detection for Cascades * and 8-way type cache happy bunch from Intel:^) * Dragan Stancevic , May 2000 + * + * Transmeta CPU detection. H. Peter Anvin , May 2000 */ /* @@ -436,8 +438,10 @@ __initfunc(static int get_model_name(struct cpuinfo_x86 *c)) { unsigned int n, dummy, *v, ecx, edx; - /* Actually we must have cpuid or we could never have - * figured out that this was AMD from the vendor info :-). + /* + * Actually we must have cpuid or we could never have + * figured out that this was AMD/Cyrix/Transmeta + * from the vendor info :-). */ cpuid(0x80000000, &n, &dummy, &dummy, &dummy); @@ -450,8 +454,9 @@ __initfunc(static int get_model_name(struct cpuinfo_x86 *c)) cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); c->x86_model_id[48] = 0; - if(c->x86_vendor == X86_VENDOR_AMD) + switch(c->x86_vendor) { + case X86_VENDOR_AMD: /* Set MTRR capability flag if appropriate */ if(boot_cpu_data.x86 == 5) { if((boot_cpu_data.x86_model == 9) || @@ -459,7 +464,10 @@ __initfunc(static int get_model_name(struct cpuinfo_x86 *c)) (boot_cpu_data.x86_mask >= 8))) c->x86_capability |= X86_FEATURE_MTRR; } + /* Fall through */ + case X86_VENDOR_TRANSMETA: + /* Cache information */ if (n >= 0x80000005){ cpuid(0x80000005, &dummy, &dummy, &ecx, &edx); printk("CPU: L1 I Cache: %dK L1 D Cache: %dK\n", @@ -471,6 +479,10 @@ __initfunc(static int get_model_name(struct cpuinfo_x86 *c)) printk("CPU: L2 Cache: %dK\n", ecx>>16); c->x86_cache_size = ecx>>16; } + break; + + default: /* Cyrix */ + break; } return 1; } @@ -735,6 +747,70 @@ __initfunc(static void cyrix_model(struct cpuinfo_x86 *c)) return; } +__initfunc(static void transmeta_model(struct cpuinfo_x86 *c)) +{ + unsigned int cap_mask, uk, max, dummy, n, ecx, edx; + unsigned int cms_rev1, cms_rev2; + unsigned int cpu_rev, cpu_freq, cpu_flags; + char cpu_info[65]; + + get_model_name(c); /* Same as AMD/Cyrix */ + + /* Print CMS and CPU revision */ + cpuid(0x80860000, &max, &dummy, &dummy, &dummy); + if ( max >= 0x80860001 ) { + cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags); + printk("CPU: Processor revision %u.%u.%u.%u, %u MHz%s%s\n", + (cpu_rev >> 24) & 0xff, + (cpu_rev >> 16) & 0xff, + (cpu_rev >> 8) & 0xff, + cpu_rev & 0xff, + cpu_freq, + (cpu_flags & 1) ? " [recovery]" : "", + (cpu_flags & 2) ? " [longrun]" : ""); + } + if ( max >= 0x80860002 ) { + cpuid(0x80860002, &dummy, &cms_rev1, &cms_rev2, &dummy); + printk("CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n", + (cms_rev1 >> 24) & 0xff, + (cms_rev1 >> 16) & 0xff, + (cms_rev1 >> 8) & 0xff, + cms_rev1 & 0xff, + cms_rev2); + } + if ( max >= 0x80860006 ) { + cpuid(0x80860003, + (void *)&cpu_info[0], + (void *)&cpu_info[4], + (void *)&cpu_info[8], + (void *)&cpu_info[12]); + cpuid(0x80860004, + (void *)&cpu_info[16], + (void *)&cpu_info[20], + (void *)&cpu_info[24], + (void *)&cpu_info[28]); + cpuid(0x80860005, + (void *)&cpu_info[32], + (void *)&cpu_info[36], + (void *)&cpu_info[40], + (void *)&cpu_info[44]); + cpuid(0x80860006, + (void *)&cpu_info[48], + (void *)&cpu_info[52], + (void *)&cpu_info[56], + (void *)&cpu_info[60]); + cpu_info[64] = '\0'; + printk("CPU: %s\n", cpu_info); + } + + /* Unhide possibly hidden flags */ + rdmsr(0x80860004, cap_mask, uk); + wrmsr(0x80860004, ~0, uk); + cpuid(0x00000001, &dummy, &dummy, &dummy, &c->x86_capability); + wrmsr(0x80860004, cap_mask, uk); +} + + __initfunc(void get_cpu_vendor(struct cpuinfo_x86 *c)) { char *v = c->x86_vendor_id; @@ -751,6 +827,10 @@ __initfunc(void get_cpu_vendor(struct cpuinfo_x86 *c)) c->x86_vendor = X86_VENDOR_CENTAUR; else if (!strcmp(v, "NexGenDriven")) c->x86_vendor = X86_VENDOR_NEXGEN; + else if (!strcmp(v, "RiseRiseRise")) + c->x86_vendor = X86_VENDOR_RISE; + else if (!strcmp(v, "GenuineTMx86")) + c->x86_vendor = X86_VENDOR_TRANSMETA; else c->x86_vendor = X86_VENDOR_UNKNOWN; } @@ -815,6 +895,18 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c)) c->cpuid_level < 0) return; + /* It should be possible for the user to override this. */ + if(c->cpuid_level > 0 && + (c->x86_vendor == X86_VENDOR_INTEL || c->x86_vendor == X86_VENDOR_TRANSMETA) && + c->x86_capability&(1<<18)) { + /* Disable processor serial number */ + unsigned long lo,hi; + rdmsr(0x119,lo,hi); + lo |= 0x200000; + wrmsr(0x119,lo,hi); + printk(KERN_INFO "CPU serial number disabled.\n"); + } + if (c->x86_vendor == X86_VENDOR_CYRIX) { cyrix_model(c); return; @@ -823,18 +915,9 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c)) if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c)) return; - if (c->cpuid_level > 0 && c->x86_vendor == X86_VENDOR_INTEL) - { - if(c->x86_capability&(1<<18)) - { - /* Disable processor serial number on Intel Pentium III - from code by Phil Karn */ - unsigned long lo,hi; - rdmsr(0x119,lo,hi); - lo |= 0x200000; - wrmsr(0x119,lo,hi); - printk(KERN_INFO "Pentium-III serial number disabled.\n"); - } + if (c->x86_vendor == X86_VENDOR_TRANSMETA) { + transmeta_model(c); + return; } if (c->cpuid_level > 1) { @@ -928,7 +1011,7 @@ __initfunc(void dodgy_tsc(void)) static char *cpu_vendor_names[] __initdata = { - "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" }; + "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise", "Transmeta" }; __initfunc(void print_cpu_info(struct cpuinfo_x86 *c)) @@ -940,7 +1023,7 @@ __initfunc(void print_cpu_info(struct cpuinfo_x86 *c)) else if (c->cpuid_level >= 0) vendor = c->x86_vendor_id; - if (vendor) + if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor))) printk("%s ", vendor); if (!c->x86_model_id[0]) @@ -1050,8 +1133,8 @@ int get_cpuinfo(char * buffer) break; default: - /* Unknown CPU manufacturer. Transmeta ? :-) */ - break; + /* Unknown CPU manufacturer or no specal action needed */ + break; } sep_bug = c->x86_vendor == X86_VENDOR_INTEL && diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index db20eb29996e..8855ab73e54e 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -367,6 +367,9 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code) __asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); + /* Ensure the debug status register is visible to ptrace (or the process itself) */ + tsk->tss.debugreg[6] = condition; + /* Mask out spurious TF errors due to lazy TF clearing */ if (condition & DR_STEP) { /* diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index afdf83727031..4c242a73bc4f 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -214,15 +214,19 @@ that case switch block size and issue plain READ_10 again, then switch back. - 3.09 Jun 10, 2000 - Jens Axboe + 3.10 Jun 10, 2000 - Jens Axboe -- Fix volume control on CD's - old SCSI-II drives now use their own code, as doing MODE6 stuff in here is really not my intention. -- Use READ_DISC_INFO for more reliable end-of-disc. + + 3.11 Jun 12, 2000 - Jens Axboe + -- Fix bug in getting rpc phase 2 region info. + -- Reinstate "correct" CDROMPLAYTRKIND -------------------------------------------------------------------------*/ -#define REVISION "Revision: 3.10" -#define VERSION "Id: cdrom.c 3.10 2000/06/10" +#define REVISION "Revision: 3.11" +#define VERSION "Id: cdrom.c 3.11 2000/06/12" /* I use an error-log mask to give fine grain control over the type of messages dumped to the system logs. The available masks include: */ @@ -1101,8 +1105,8 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) case DVD_LU_SEND_RPC_STATE: cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n"); setup_report_key(&cgc, 0, 8); + memset(&rpc_state, 0, sizeof(rpc_state_t)); - init_cdrom_command(&cgc, &rpc_state, 0); if ((ret = cdo->generic_packet(cdi, &cgc))) return ret; @@ -1113,7 +1117,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme; break; - /* Set region settings */ + /* Set region settings */ case DVD_HOST_SEND_RPC_STATE: cdinfo(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n"); setup_send_key(&cgc, 0, 6); @@ -1964,36 +1968,15 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, } case CDROMPLAYTRKIND: { struct cdrom_ti ti; - struct cdrom_tocentry entry; - struct cdrom_tochdr tochdr; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); IOCTL_IN(arg, struct cdrom_ti, ti); - entry.cdte_format = CDROM_MSF; - - /* get toc entry for start and end track */ - if (cdo->audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr)) - return -EINVAL; - if ((entry.cdte_track = ti.cdti_trk0) > tochdr.cdth_trk1) - return -EINVAL; - if (cdo->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) - return -EINVAL; - - cgc.cmd[3] = entry.cdte_addr.msf.minute; - cgc.cmd[4] = entry.cdte_addr.msf.second; - cgc.cmd[5] = entry.cdte_addr.msf.frame; - - entry.cdte_track = ti.cdti_trk1 + 1; - if (entry.cdte_track > tochdr.cdth_trk1) - entry.cdte_track = CDROM_LEADOUT; - if (cdo->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) - return -EINVAL; - - cgc.cmd[6] = entry.cdte_addr.msf.minute; - cgc.cmd[7] = entry.cdte_addr.msf.second; - cgc.cmd[8] = entry.cdte_addr.msf.frame; - cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF; + cgc.cmd[0] = GPCMD_PLAY_AUDIO_TI; + cgc.cmd[4] = ti.cdti_trk0; + cgc.cmd[5] = ti.cdti_ind0; + cgc.cmd[7] = ti.cdti_trk1; + cgc.cmd[8] = ti.cdti_ind1; return cdo->generic_packet(cdi, &cgc); } case CDROMPLAYMSF: { diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 077091310678..b12eb75bcfe5 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -896,6 +896,9 @@ static int sx_set_real_termios (void *ptr) func_enter2(); + if (!port->gs.tty) + return 0; + /* What is this doing here? -- REW Ha! figured it out. It is to allow you to get DTR active again if you've dropped it with stty 0. Moved to set_baud, where it @@ -1545,7 +1548,34 @@ static int sx_open (struct tty_struct * tty, struct file * filp) exit minicom. I expect an "oops". -- REW */ static void sx_hungup (void *ptr) { +/* func_enter (); + MOD_DEC_USE_COUNT; + func_exit (); +*/ + /* + * Got this from the 2.4.0-test1 serie. The port was closed before + * the lines were set in the proper condition. -- pvdl + */ + struct sx_port *port = ptr; + func_enter (); + + /* + * Set the lines in the proper codition before closing the port. + * Got the from 2.4.0-test1 series. -- pvdl + */ + sx_setsignals (port, 0, 0); + sx_reconfigure_port(port); + sx_send_command (port, HS_CLOSE, -1, HS_IDLE_CLOSED); + + if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) { + if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) { + printk (KERN_ERR + "sx: sent the force_close command, but card didn't react\n"); + } else + sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n"); + } + MOD_DEC_USE_COUNT; func_exit (); } @@ -1558,6 +1588,9 @@ static void sx_close (void *ptr) int to = 5 * HZ; func_enter (); + + sx_setsignals (port, 0, 0); + sx_reconfigure_port(port); sx_send_command (port, HS_CLOSE, 0, 0); while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) { @@ -1920,7 +1953,10 @@ static int sx_init_board (struct sx_board *board) func_enter(); /* This is preceded by downloading the download code. */ - + /* + * The board should be set to initialized to make sure + * we can boot the other cards. --pvdl + */ board->flags |= SX_BOARD_INITIALIZED; if (read_sx_byte (board, 0)) diff --git a/drivers/misc/parport_share.c b/drivers/misc/parport_share.c index d9e54eb49986..a66453e5c598 100644 --- a/drivers/misc/parport_share.c +++ b/drivers/misc/parport_share.c @@ -125,7 +125,18 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, * This function must not run from an irq handler so we don' t need * to clear irq on the local CPU. -arca */ + spin_lock(&parportlist_lock); + + /* We are locked against anyone else performing alterations, but + * because of parport_enumerate people can still _read_ the list + * while we are changing it, so be careful.. + * + * It's okay to have portlist_tail a little bit out of sync + * since it's only used for changing the list, not for reading + * from it. + */ + if (portlist_tail) portlist_tail->next = tmp; portlist_tail = tmp; @@ -144,6 +155,10 @@ void parport_unregister_port(struct parport *port) struct parport *p; spin_lock(&parportlist_lock); + + /* We are protected from other people changing the list, but + * they can still see it (using parport_enumerate). So be + * careful about the order of writes.. */ if (portlist == port) { if ((portlist = port->next) == NULL) portlist_tail = NULL; @@ -212,17 +227,25 @@ struct pardevice *parport_register_device(struct parport *port, const char *name } } + /* We up our own module reference count, and that of the port + on which a device is to be registered, to ensure that + neither of us gets unloaded while we sleep in (e.g.) + kmalloc. To be absolutely safe, we have to require that + our caller doesn't sleep in between parport_enumerate and + parport_register_device.. */ + inc_parport_count (); + port->ops->inc_use_count (); + tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL); if (tmp == NULL) { printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name); - return NULL; + goto out; } tmp->state = kmalloc(sizeof(struct parport_state), GFP_KERNEL); if (tmp->state == NULL) { printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name); - kfree(tmp); - return NULL; + goto out_free_pardevice; } /* We may need to claw back the port hardware. */ @@ -231,9 +254,7 @@ struct pardevice *parport_register_device(struct parport *port, const char *name printk(KERN_WARNING "%s: unable to get hardware to register %s.\n", port->name, name); - kfree (tmp->state); - kfree (tmp); - return NULL; + goto out_free_all; } port->flags &= ~PARPORT_FLAG_COMA; } @@ -259,17 +280,18 @@ struct pardevice *parport_register_device(struct parport *port, const char *name if (flags & PARPORT_DEV_EXCL) { if (port->devices) { spin_unlock (&port->pardevice_lock); - kfree (tmp->state); - kfree (tmp); printk (KERN_DEBUG "%s: cannot grant exclusive access for " "device %s\n", port->name, name); - return NULL; + goto out_free_all; } port->flags |= PARPORT_FLAG_EXCL; } tmp->next = port->devices; + wmb(); /* Make sure that tmp->next is written before it's + added to the list; see comments marked 'no locking + required' */ if (port->devices) port->devices->prev = tmp; port->devices = tmp; @@ -283,11 +305,21 @@ struct pardevice *parport_register_device(struct parport *port, const char *name tmp->waitnext = tmp->waitprev = NULL; return tmp; + + out_free_all: + kfree (tmp->state); + out_free_pardevice: + kfree (tmp); + out: + dec_parport_count (); + port->ops->dec_use_count (); + return NULL; } void parport_unregister_device(struct pardevice *dev) { struct parport *port; + unsigned long flags; #ifdef PARPORT_PARANOID if (dev == NULL) { @@ -298,11 +330,14 @@ void parport_unregister_device(struct pardevice *dev) port = dev->port; + read_lock_irqsave (&port->cad_lock, flags); if (port->cad == dev) { + read_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_DEBUG "%s: %s forgot to release port\n", port->name, dev->name); parport_release (dev); } + read_unlock_irqrestore (&port->cad_lock, flags); spin_lock(&port->pardevice_lock); if (dev->next) @@ -336,14 +371,17 @@ int parport_claim(struct pardevice *dev) struct parport *port = dev->port; unsigned long flags; + read_lock_irqsave (&port->cad_lock, flags); if (port->cad == dev) { + read_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_INFO "%s: %s already owner\n", dev->port->name,dev->name); return 0; } + read_unlock_irqrestore (&port->cad_lock, flags); -try_again: /* Preempt any current device */ + write_lock_irqsave (&port->cad_lock, flags); if ((oldcad = port->cad) != NULL) { if (oldcad->preempt) { if (oldcad->preempt(oldcad->private)) @@ -366,7 +404,7 @@ try_again: dev->waiting = 0; /* Take ourselves out of the wait list again. */ - spin_lock_irqsave (&port->waitlist_lock, flags); + spin_lock_irq (&port->waitlist_lock); if (dev->waitprev) dev->waitprev->waitnext = dev->waitnext; else @@ -375,7 +413,7 @@ try_again: dev->waitnext->waitprev = dev->waitprev; else port->waittail = dev->waitprev; - spin_unlock_irqrestore (&port->waitlist_lock, flags); + spin_unlock_irq (&port->waitlist_lock); dev->waitprev = dev->waitnext = NULL; } @@ -399,6 +437,7 @@ try_again: /* Restore control registers */ port->ops->restore_state(port, dev->state); + write_unlock_irqrestore (&port->cad_lock, flags); dev->time = jiffies; return 0; @@ -406,13 +445,10 @@ blocked: /* If this is the first time we tried to claim the port, register an interest. This is only allowed for devices sleeping in parport_claim_or_block(), or those with a wakeup function. */ + + /* The cad_lock is still held for writing here */ if (dev->waiting & 2 || dev->wakeup) { - spin_lock_irqsave (&port->waitlist_lock, flags); - if (port->cad == NULL) { - /* The port got released in the meantime. */ - spin_unlock_irqrestore (&port->waitlist_lock, flags); - goto try_again; - } + spin_lock (&port->waitlist_lock); if (test_and_set_bit(0, &dev->waiting) == 0) { /* First add ourselves to the end of the wait list. */ dev->waitnext = NULL; @@ -423,8 +459,9 @@ blocked: } else port->waithead = port->waittail = dev; } - spin_unlock_irqrestore (&port->waitlist_lock, flags); + spin_unlock (&port->waitlist_lock); } + write_unlock_irqrestore (&port->cad_lock, flags); return -EAGAIN; } @@ -474,12 +511,14 @@ void parport_release(struct pardevice *dev) unsigned long flags; /* Make sure that dev is the current device */ + write_lock_irqsave (&port->cad_lock, flags); if (port->cad != dev) { + write_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_WARNING "%s: %s tried to release parport " "when not owner\n", port->name, dev->name); return; } - write_lock_irqsave(&port->cad_lock, flags); + port->cad = NULL; write_unlock_irqrestore(&port->cad_lock, flags); @@ -503,7 +542,7 @@ void parport_release(struct pardevice *dev) return; } else if (pd->wakeup) { pd->wakeup(pd->private); - if (dev->port->cad) + if (dev->port->cad) /* racy but no matter */ return; } else { printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name); @@ -511,7 +550,7 @@ void parport_release(struct pardevice *dev) } /* Nobody was waiting, so walk the list to see if anyone is - interested in being woken up. */ + interested in being woken up. (Note: no locking required) */ for (pd = port->devices; (port->cad == NULL) && pd; pd = pd->next) { if (pd->wakeup && pd != dev) pd->wakeup(pd->private); diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 75e79180bb75..dbb376dd232b 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -319,6 +319,10 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_PCI" != "n" ]; then dep_tristate ' SBE wanXL support' CONFIG_WANXL $CONFIG_HDLC + dep_tristate ' Cyclades-PC300 support' CONFIG_PC300 $CONFIG_HDLC + if [ "$CONFIG_PC300" != "n" ]; then + bool ' Cyclades-PC300 X.25 support (please read help)' CONFIG_PC300_X25 + fi fi fi fi diff --git a/drivers/net/Makefile b/drivers/net/Makefile index c461650b37e0..3983a614f74f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -1003,6 +1003,14 @@ else endif endif +ifeq ($(CONFIG_PC300),y) +L_OBJS += pc300.o +else + ifeq ($(CONFIG_PC300),m) + M_OBJS += pc300.o + endif +endif + # If anything built-in uses syncppp, then build it into the kernel also. # If not, but a module uses it, build as a module. diff --git a/drivers/net/hdlc.c b/drivers/net/hdlc.c index 17d67f05c87e..3472b3bf6387 100644 --- a/drivers/net/hdlc.c +++ b/drivers/net/hdlc.c @@ -884,7 +884,12 @@ static int hdlc_open(struct device *dev) dev->do_ioctl = hdlc_ioctl; hdlc->pppdev.sppp.pp_flags&=~PP_CISCO; dev->type=ARPHRD_PPP; - sppp_open(dev); + result = sppp_open(dev); + if (result) { + sppp_detach(dev); + hdlc->close(hdlc); + return result; + } } return 0; diff --git a/drivers/net/pc300.c b/drivers/net/pc300.c new file mode 100644 index 000000000000..4574b4d14471 --- /dev/null +++ b/drivers/net/pc300.c @@ -0,0 +1,2815 @@ +#define USE_PCI_CLOCK +static char rcsid[] = +"$Revision: 3.1.0.0 $$Date: 2000/05/26 $"; + +/* + * pc300.c Cyclades-PC300(tm) Driver. + * + * Author: Ivan Passos + * + * Copyright: (c) 1999-2000 Cyclades Corp. + * + * 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. + * + * $Log: pc300.c,v $ + * Revision 3.1.0.0 $$Date: 2000/05/26 ivan + * Added Frame-Relay support. + * Driver now uses HDLC generic driver to provide protocol support. + * Added logic in the SCA interrupt handler so that no board can monopolize + * the driver. + * Request PLX I/O region, although driver doesn't use it, to avoid + * problems with other drivers accessing it. + * + * Revision 3.0.0.0 $$Date: 2000/05/15 ivan + * Did some changes in the DMA programming implementation to avoid the + * occurrence of a SCA-II bug in the second channel. + * Implemented workaround for PLX9050 bug that would cause a system lockup + * in certain systems, depending on the MMIO addresses allocated to the + * board. + * Fixed the FALC chip programming to avoid synchronization problems in the + * second channel (TE only). + * Implemented a cleaner and faster Tx DMA descriptor cleanup procedure in + * cpc_queue_xmit(). + * Changed the built-in driver implementation so that the driver can use the + * general 'hdlcN' naming convention instead of proprietary device names. + * Driver load messages are now device-centric, instead of board-centric. + * Dynamic allocation of device structures. + * + * Revision 2.0.0.0 $$Date: 2000/04/15 ivan + * Added support for the PC300/TE boards (T1/FT1/E1/FE1). + * + * Revision 1.1.0.0 2000/02/28 ivan + * Major changes in the driver architecture. + * Driver now reports physical instead of virtual memory addresses. + * Added cpc_change_mtu function. + * + * Revision 1.0.0.0 1999/12/16 ivan + * First official release. + * Support for 1- and 2-channel boards (which use distinct PCI Device ID's). + * Support for monolythic installation (i.e., drv built into the kernel). + * X.25 additional checking when lapb_[dis]connect_request returns an error. + * SCA programming now covers X.21 as well. + * + * Revision 0.3.1.0 1999/11/18 ivan + * Made X.25 support configuration-dependent (as it depends on external + * modules to work). + * Changed X.25-specific function names to comply with adopted convention. + * Fixed typos in X.25 functions that would cause compile errors (Daniela). + * Fixed bug in ch_config that would disable interrupts on a previously + * enabled channel if the other channel on the same board was enabled later. + * + * Revision 0.3.0.0 1999/11/16 Daniela Squassoni + * X.25 support. + * + * Revision 0.2.3.0 1999/11/15 ivan + * Function cpc_ch_status now provides more detailed information. + * Added support for X.21 clock configuration. + * Changed TNR1 setting in order to prevent Tx FIFO overaccesses by the SCA. + * Now using PCI clock instead of internal oscillator clock for the SCA. + * + * Revision 0.2.2.0 1999/11/10 ivan + * Changed the *_dma_buf_check functions so that they would print only + * the useful info instead of the whole buffer descriptor bank. + * Fixed bug in cpc_queue_xmit that would eventually crash the system + * in case of a packet drop. + * Implemented TX underrun handling. + * Improved SCA fine tuning to boost up its performance. + * + * Revision 0.2.1.0 1999/11/03 ivan + * Added functions *dma_buf_pt_init to allow independent initialization + * of the next-descr. and DMA buffer pointers on the DMA descriptors. + * Kernel buffer release and tbusy clearing is now done in the interrupt + * handler. + * Fixed bug in cpc_open that would cause an interface reopen to fail. + * Added a protocol-specific code section in cpc_net_rx. + * Removed printk level defs (they might be added back after the beta phase). + * + * Revision 0.2.0.0 1999/10/28 ivan + * Revisited the code so that new protocols can be easily added / supported. + * + * Revision 0.1.0.1 1999/10/20 ivan + * Mostly "esthetic" changes. + * + * Revision 0.1.0.0 1999/10/11 ivan + * Initial version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PC300_X25 +#include +#endif /* CONFIG_PC300_X25 */ + +#include "syncppp.h" + +#include + +#include + +#define CPC_LOCK(card,flags) \ + do { \ + spin_lock_irqsave(&card->card_lock, flags); \ + } while (0) + +#define CPC_UNLOCK(card,flags) \ + do { \ + spin_unlock_irqrestore(&card->card_lock, flags); \ + } while (0) + +#undef PC300_DEBUG_PCI +#undef PC300_DEBUG_INTR +#undef PC300_DEBUG_TX +#undef PC300_DEBUG_RX + +/* Hardware configuration options. + * These are arrays of configuration options used by verification routines. + * The first element of each array is its size (i.e. number of options). + */ +static unsigned short cpc_pci_dev_id[] = { + PCI_DEVICE_ID_PC300_RX_1, /* PC300/RSV or PC300/X21, 1 chan */ + PCI_DEVICE_ID_PC300_RX_2, /* PC300/RSV or PC300/X21, 2 chan */ + PCI_DEVICE_ID_PC300_TE_1, /* PC300/TE, 1 chan */ + PCI_DEVICE_ID_PC300_TE_2, /* PC300/TE, 2 chan */ + 0 /* end of table */ +}; + +/* This is the per-card data structure containing mem. addresses, irq, etc. + * This driver supports a maximum of PC300_MAXCARDS cards. + */ +static pc300_t cpc_card[PC300_MAXCARDS]; + +static ucshort cpc_nboards = 0; + +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + +/************************/ +/*** DMA Routines ***/ +/************************/ +static void +tx_dma_buf_pt_init(pc300_t *card, int ch) +{ + int i; + int ch_factor = ch * N_DMA_TX_BUF; + volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *)(card->hw.rambase + + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); + + for (i = 0 ; i < N_DMA_TX_BUF ; i++, ptdescr++) { + cpc_writel(&ptdescr->next, (uclong) (DMA_TX_BD_BASE + + (ch_factor + ((i + 1) & (N_DMA_TX_BUF - 1))) * + sizeof(pcsca_bd_t))); + cpc_writel(&ptdescr->ptbuf, + (uclong)(DMA_TX_BASE + (ch_factor + i)*BD_DEF_LEN)); + } +} + +static void +tx_dma_buf_init(pc300_t *card, int ch) +{ + int i; + int ch_factor = ch * N_DMA_TX_BUF; + volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *)(card->hw.rambase + + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); + + for (i = 0 ; i < N_DMA_TX_BUF ; i++, ptdescr++) { + memset_io(ptdescr, 0, sizeof (pcsca_bd_t)); + cpc_writew(&ptdescr->len, 0); + cpc_writeb(&ptdescr->status, 0); + } + tx_dma_buf_pt_init(card, ch); +} + +static void +rx_dma_buf_pt_init(pc300_t *card, int ch) +{ + int i; + int ch_factor = ch * N_DMA_RX_BUF; + volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *)(card->hw.rambase + + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); + + for (i = 0 ; i < N_DMA_RX_BUF ; i++, ptdescr++) { + cpc_writel(&ptdescr->next, (uclong) (DMA_RX_BD_BASE + + (ch_factor + ((i + 1) & (N_DMA_RX_BUF - 1))) * + sizeof(pcsca_bd_t))); + cpc_writel(&ptdescr->ptbuf, + (uclong)(DMA_RX_BASE + (ch_factor + i)*BD_DEF_LEN)); + } +} + +static void +rx_dma_buf_init(pc300_t *card, int ch) +{ + int i; + int ch_factor = ch * N_DMA_RX_BUF; + volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *)(card->hw.rambase + + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); + + for (i = 0 ; i < N_DMA_RX_BUF ; i++, ptdescr++) { + memset_io(ptdescr, 0, sizeof (pcsca_bd_t)); + cpc_writew(&ptdescr->len, 0); + cpc_writeb(&ptdescr->status, 0); + } + rx_dma_buf_pt_init(card, ch); +} + +static void +tx_dma_buf_check(pc300_t *card, int ch) +{ + volatile pcsca_bd_t *ptdescr; + int i; + ucshort first_bd = card->chan[ch].tx_first_bd; + ucshort next_bd = card->chan[ch].tx_next_bd; + + printk("#CH%d: f_bd = %d(0x%08x), n_bd = %d(0x%08x)\n", ch, + first_bd, TX_BD_ADDR(ch, first_bd), + next_bd, TX_BD_ADDR(ch, next_bd)); + for (i = first_bd, + ptdescr = (pcsca_bd_t *)(card->hw.rambase + TX_BD_ADDR(ch, first_bd)); + i != ((next_bd + 1) & (N_DMA_TX_BUF - 1)) ; + i = (i + 1) & (N_DMA_TX_BUF - 1), + ptdescr = (pcsca_bd_t *)(card->hw.rambase + TX_BD_ADDR(ch, i))) { + printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d", + ch, i, + (uclong)cpc_readl(&ptdescr->next), + (uclong)cpc_readl(&ptdescr->ptbuf), + cpc_readb(&ptdescr->status), + cpc_readw(&ptdescr->len)); + } + printk("\n"); +} + +static void +rx_dma_buf_check(pc300_t *card, int ch) +{ + volatile pcsca_bd_t *ptdescr; + int i; + ucshort first_bd = card->chan[ch].rx_first_bd; + ucshort last_bd = card->chan[ch].rx_last_bd; + int ch_factor; + + ch_factor = ch * N_DMA_RX_BUF; + printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd); + for (i = 0, ptdescr = (pcsca_bd_t *)(card->hw.rambase + + DMA_RX_BD_BASE + ch_factor*sizeof(pcsca_bd_t)); + i < N_DMA_RX_BUF ; + i++, ptdescr++) { + if (cpc_readb(&ptdescr->status) & DST_OSB) + printk("\n CH%d RX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d", + ch, i, + (uclong)cpc_readl(&ptdescr->next), + (uclong)cpc_readl(&ptdescr->ptbuf), + cpc_readb(&ptdescr->status), + cpc_readw(&ptdescr->len)); + } + printk("\n"); +} + +int +dma_get_rx_frame_size(pc300_t *card, int ch) +{ + volatile pcsca_bd_t *ptdescr; + ucshort first_bd = card->chan[ch].rx_first_bd; + int rcvd = 0; + volatile ucchar status; + + ptdescr = (pcsca_bd_t *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd)); + while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { + rcvd += cpc_readw(&ptdescr->len); + first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1); + if (status & DST_EOM) + return (rcvd); + ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next)); + } + return (-1); +} + +/* + * dma_buf_write: writes a frame to the Tx DMA buffers + * NOTE: this function writes one frame at a time. + */ +int +dma_buf_write(pc300_t *card, int ch, ucchar *ptdata, int len) +{ + int i, nchar; + volatile pcsca_bd_t *ptdescr; + int tosend = len; + ucchar nbuf = ((len - 1)/BD_DEF_LEN) + 1; + + for (i = 0 ; i < nbuf ; i++) { + ptdescr = (pcsca_bd_t *)(card->hw.rambase + + TX_BD_ADDR(ch, card->chan[ch].tx_next_bd)); + nchar = min(BD_DEF_LEN,tosend); + if (!(cpc_readb(&ptdescr->status) & DST_OSB)) { + memcpy_toio((void *)(card->hw.rambase + + cpc_readl(&ptdescr->ptbuf)), + &ptdata[len - tosend], + nchar); + if ((i + 1) == nbuf) { + /* This must be the last BD to be used */ + cpc_writeb(&ptdescr->status, (DST_EOM | DST_EOT)); + } else { + cpc_writeb(&ptdescr->status, 0); + } + cpc_writew(&ptdescr->len, nchar); + } else { + return -ENOMEM; + } + tosend -= nchar; + card->chan[ch].tx_next_bd = + (card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1); + } + /* If it gets to here, it means we have sent the whole frame */ + return 0; +} + +/* + * dma_buf_read: reads a frame from the Rx DMA buffers + * NOTE: this function reads one frame at a time. + */ +int +dma_buf_read(pc300_t *card, int ch, struct sk_buff *skb) +{ + int nchar; + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + volatile pcsca_bd_t *ptdescr; + int rcvd = 0; + volatile ucchar status; + + ptdescr = (pcsca_bd_t *)(card->hw.rambase + + RX_BD_ADDR(ch, chan->rx_first_bd)); + while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { + if (status & (DST_OVR | DST_CRC | DST_RBIT | DST_SHRT | DST_ABT)) { + rcvd = -status; + /* Discard remaining descriptors used by the bad frame */ + while(chan->rx_first_bd != chan->rx_last_bd) { + cpc_writeb(&ptdescr->status, 0); + chan->rx_first_bd = + (chan->rx_first_bd + 1) & (N_DMA_RX_BUF - 1); + if(status & DST_EOM) + break; + ptdescr = (pcsca_bd_t *)(card->hw.rambase + + cpc_readl(&ptdescr->next)); + status = cpc_readb(&ptdescr->status); + } + break; + } + if ((nchar = cpc_readw(&ptdescr->len)) != 0) { + memcpy_fromio(skb_put(skb, nchar), + (void *)(card->hw.rambase + + cpc_readl(&ptdescr->ptbuf)), + nchar); + rcvd += nchar; + } + cpc_writeb(&ptdescr->status, 0); + cpc_writeb(&ptdescr->len, 0); + chan->rx_first_bd = (chan->rx_first_bd + 1) & (N_DMA_RX_BUF - 1); + + if (status & DST_EOM) break; + + ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next)); + } + + if (rcvd != 0) { + /* Update pointer */ + chan->rx_last_bd = (chan->rx_first_bd - 1) & (N_DMA_RX_BUF - 1); + /* Update EDA */ + cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), + RX_BD_ADDR(ch, chan->rx_last_bd)); + } + return (rcvd); +} + +void +tx_dma_stop(pc300_t *card, int ch) +{ + uclong scabase = card->hw.scabase; + ucchar drr_ena_bit = 1<<(5 + 2*ch); + ucchar drr_rst_bit = 1<<(1 + 2*ch); + + /* Disable DMA */ + cpc_writeb(scabase + DRR, drr_ena_bit); + cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit); +} + +void +rx_dma_stop(pc300_t *card, int ch) +{ + uclong scabase = card->hw.scabase; + ucchar drr_ena_bit = 1<<(4 + 2*ch); + ucchar drr_rst_bit = 1<<(2*ch); + + /* Disable DMA */ + cpc_writeb(scabase + DRR, drr_ena_bit); + cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit); +} + +/*************************/ +/*** FALC Routines ***/ +/*************************/ +void +falc_issue_cmd(pc300_t *card, int ch, ucchar cmd) +{ + uclong falcbase = card->hw.falcbase; + unsigned long i = 0; + + while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) { + if (i++ >= PC300_FALC_MAXLOOP) { + printk("%s: FALC command locked(cmd=0x%x).\n", + card->chan[ch].d.name, cmd); + break; + } + } + cpc_writeb(falcbase + F_REG(CMDR, ch), cmd); +} + +void +falc_intr_enable(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + + /* Interrupt pins are open-drain */ + cpc_writeb(falcbase + F_REG(IPC, ch), + cpc_readb(falcbase + F_REG(IPC, ch)) & ~IPC_IC0); + /* Conters updated each second */ + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_ECM); + /* Enable SEC and ES interrupts */ + cpc_writeb(falcbase + F_REG(IMR3, ch), + cpc_readb(falcbase + F_REG(IMR3, ch)) & ~(IMR3_SEC | IMR3_ES)); + cpc_writeb(falcbase + F_REG(IMR4, ch), + cpc_readb(falcbase + F_REG(IMR4, ch)) & + ~(IMR4_LFA | IMR4_AIS | IMR4_LOS | IMR4_SLIP)); + if (conf->media == LINE_T1) { + cpc_writeb(falcbase + F_REG(IMR3, ch), + cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC); + } else { + cpc_writeb(falcbase + F_REG(IPC, ch), + cpc_readb(falcbase + F_REG(IPC, ch)) | IPC_SCI); + cpc_writeb(falcbase + F_REG(IMR2, ch), + cpc_readb(falcbase + F_REG(IMR2, ch)) & + ~(IMR2_FAR | IMR2_LFA | IMR2_AIS | IMR2_LOS)); + cpc_writeb(falcbase + F_REG(IMR1, ch), + cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_LLBSC); + if (pfalc->multiframe_mode) { + cpc_writeb(falcbase + F_REG(IMR2, ch), + cpc_readb(falcbase + F_REG(IMR2, ch)) & + ~(IMR2_T400MS | IMR2_MFAR)); + } else { + cpc_writeb(falcbase + F_REG(IMR2, ch), + cpc_readb(falcbase + F_REG(IMR2, ch)) | + IMR2_T400MS | IMR2_MFAR); + } + } +} + +void +falc_open_timeslot(pc300_t *card, int ch, int timeslot) +{ + uclong falcbase = card->hw.falcbase; + ucchar tshf = card->chan[ch].falc.offset; + + cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf)/8), ch), + cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf)/8), ch)) & + ~(0x80 >> ((timeslot - tshf) & 0x07))); + cpc_writeb(falcbase + F_REG((TTR1 + timeslot/8), ch), + cpc_readb(falcbase + F_REG((TTR1 + timeslot/8), ch)) | + (0x80 >> (timeslot & 0x07))); + cpc_writeb(falcbase + F_REG((RTR1 + timeslot/8), ch), + cpc_readb(falcbase + F_REG((RTR1 + timeslot/8), ch)) | + (0x80 >> (timeslot & 0x07))); +} + +void +falc_close_timeslot(pc300_t *card, int ch, int timeslot) +{ + uclong falcbase = card->hw.falcbase; + ucchar tshf = card->chan[ch].falc.offset; + + cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf)/8), ch), + cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf)/8), ch)) | + (0x80 >> ((timeslot - tshf) & 0x07))); + cpc_writeb(falcbase + F_REG((TTR1 + timeslot/8), ch), + cpc_readb(falcbase + F_REG((TTR1 + timeslot/8), ch)) & + ~(0x80 >> (timeslot & 0x07))); + cpc_writeb(falcbase + F_REG((RTR1 + timeslot/8), ch), + cpc_readb(falcbase + F_REG((RTR1 + timeslot/8), ch)) & + ~(0x80 >> (timeslot & 0x07))); +} + +void +falc_close_all_timeslots(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + uclong falcbase = card->hw.falcbase; + + cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff); + cpc_writeb(falcbase + F_REG(TTR1, ch), 0); + cpc_writeb(falcbase + F_REG(RTR1, ch), 0); + cpc_writeb(falcbase + F_REG(ICB2, ch), 0xff); + cpc_writeb(falcbase + F_REG(TTR2, ch), 0); + cpc_writeb(falcbase + F_REG(RTR2, ch), 0); + cpc_writeb(falcbase + F_REG(ICB3, ch), 0xff); + cpc_writeb(falcbase + F_REG(TTR3, ch), 0); + cpc_writeb(falcbase + F_REG(RTR3, ch), 0); + if (conf->media == LINE_E1) { + cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff); + cpc_writeb(falcbase + F_REG(TTR4, ch), 0); + cpc_writeb(falcbase + F_REG(RTR4, ch), 0); + } +} + +void +falc_open_all_timeslots(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + uclong falcbase = card->hw.falcbase; + + /* Timeslot 0 is never enabled */ + cpc_writeb(falcbase + F_REG(ICB1, ch), 0); + cpc_writeb(falcbase + F_REG(TTR1, ch), 0x7f); + cpc_writeb(falcbase + F_REG(RTR1, ch), 0x7f); + cpc_writeb(falcbase + F_REG(ICB2, ch), 0); + cpc_writeb(falcbase + F_REG(TTR2, ch), 0xff); + cpc_writeb(falcbase + F_REG(RTR2, ch), 0xff); + cpc_writeb(falcbase + F_REG(ICB3, ch), 0); + cpc_writeb(falcbase + F_REG(TTR3, ch), 0xff); + cpc_writeb(falcbase + F_REG(RTR3, ch), 0xff); + if (conf->media == LINE_E1) { + cpc_writeb(falcbase + F_REG(ICB4, ch), 0); + cpc_writeb(falcbase + F_REG(TTR4, ch), 0xff); + cpc_writeb(falcbase + F_REG(RTR4, ch), 0xff); + } else { + cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff); + cpc_writeb(falcbase + F_REG(TTR4, ch), 0x80); + cpc_writeb(falcbase + F_REG(RTR4, ch), 0x80); + } +} + +void +falc_init_timeslot(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + falc_t *pfalc = (falc_t *)&chan->falc; + int tslot; + + for (tslot = 0 ; tslot < pfalc->num_channels ; tslot++) { + if (conf->tslot_bitmap & (1<chan[ch]; + falc_t *pfalc = (falc_t *)&chan->falc; + + if (pfalc->full_bandwidth) { + falc_open_all_timeslots(card, ch); + } else { + falc_init_timeslot(card, ch); + } + // CTS/DCD ON + cpc_writeb(card->hw.falcbase + CPLD_REG1, + cpc_readb(card->hw.falcbase + CPLD_REG1) | + ((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2*ch))); +} + +void +falc_disable_comm(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + falc_t *pfalc = (falc_t *)&chan->falc; + + if (pfalc->loop_active != 2) { + falc_close_all_timeslots(card, ch); + } + // CTS/DCD OFF + cpc_writeb(card->hw.falcbase + CPLD_REG1, + cpc_readb(card->hw.falcbase + CPLD_REG1) & + ~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2*ch))); +} + +void +falc_init_t1(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + ucchar dja = (ch ? (LIM2_DJA2|LIM2_DJA1) : 0); + + /* Switch to T1 mode (PCM 24) */ + cpc_writeb(falcbase + F_REG(FMR1, ch), FMR1_PMOD); + + /* Wait 20 us for setup */ + udelay(20); + + /* Transmit Buffer Size (1 frame) */ + cpc_writeb(falcbase + F_REG(SIC1, ch), SIC1_XBS0); + + /* Clock mode */ + if (conf->clkrate) { /* Master mode */ + cpc_writeb(falcbase + F_REG(LIM0, ch), + cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS); + } else { /* Slave mode */ + cpc_writeb(falcbase + F_REG(LIM0, ch), + cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS); + cpc_writeb(falcbase + F_REG(LOOP, ch), + cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_RTM); + } + + cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI); + cpc_writeb(falcbase + F_REG(FMR0, ch), + cpc_readb(falcbase + F_REG(FMR0, ch)) & + ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1)); + + switch (conf->lcode) { + case PC300_LC_AMI: + cpc_writeb(falcbase + F_REG(FMR0, ch), + cpc_readb(falcbase + F_REG(FMR0, ch)) | + FMR0_XC1 | FMR0_RC1); + /* Clear Channel register to ON for all channels */ + cpc_writeb(falcbase + F_REG(CCB1, ch), 0xff); + cpc_writeb(falcbase + F_REG(CCB2, ch), 0xff); + cpc_writeb(falcbase + F_REG(CCB3, ch), 0xff); + break; + + case PC300_LC_B8ZS: + cpc_writeb(falcbase + F_REG(FMR0, ch), + cpc_readb(falcbase + F_REG(FMR0, ch)) | + FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1); + break; + + case PC300_LC_NRZ: + cpc_writeb(falcbase + F_REG(FMR0, ch), + cpc_readb(falcbase + F_REG(FMR0, ch)) | 0x00); + break; + } + + cpc_writeb(falcbase + F_REG(LIM0, ch), + cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_ELOS); + cpc_writeb(falcbase + F_REG(LIM0, ch), + cpc_readb(falcbase + F_REG(LIM0, ch)) & + ~(LIM0_SCL1 | LIM0_SCL0)); + /* Set interface mode to 2 MBPS */ + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD); + + switch (conf->fr_mode) { + case PC300_FR_ESF: + pfalc->multiframe_mode = 0; + cpc_writeb(falcbase + F_REG(FMR4, ch), + cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_FM1); + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) | + FMR1_CRC | FMR1_EDL); + cpc_writeb(falcbase + F_REG(XDL1, ch), 0); + cpc_writeb(falcbase + F_REG(XDL2, ch), 0); + cpc_writeb(falcbase + F_REG(XDL3, ch), 0); + cpc_writeb(falcbase + F_REG(FMR0, ch), + cpc_readb(falcbase + F_REG(FMR0, ch)) & ~FMR0_SRAF); + cpc_writeb(falcbase + F_REG(FMR2, ch), + cpc_readb(falcbase + F_REG(FMR2, ch)) | + FMR2_MCSP | FMR2_SSP); + break; + + case PC300_FR_D4: + pfalc->multiframe_mode = 1; + cpc_writeb(falcbase + F_REG(FMR4, ch), + cpc_readb(falcbase + F_REG(FMR4, ch)) & + ~(FMR4_FM1 | FMR4_FM0)); + cpc_writeb(falcbase + F_REG(FMR0, ch), + cpc_readb(falcbase + F_REG(FMR0, ch)) | FMR0_SRAF); + cpc_writeb(falcbase + F_REG(FMR2, ch), + cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_SSP); + break; + } + + /* Enable Automatic Resynchronization */ + cpc_writeb(falcbase + F_REG(FMR4, ch), + cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_AUTO); + + /* Transmit Automatic Remote Alarm */ + cpc_writeb(falcbase + F_REG(FMR2, ch), + cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA); + + /* Channel translation mode 1 : one to one */ + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_CTM); + + /* No signaling */ + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_SIGM); + cpc_writeb(falcbase + F_REG(FMR5, ch), + cpc_readb(falcbase + F_REG(FMR5, ch)) & + ~(FMR5_EIBR | FMR5_SRS)); + cpc_writeb(falcbase + F_REG(CCR1, ch), 0); + + cpc_writeb(falcbase + F_REG(LIM1, ch), + cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1); + + switch (conf->lbo) { + /* Provides proper Line Build Out */ + case PC300_LBO_0_DB: + cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja)); + cpc_writeb(falcbase + F_REG(XPM0, ch), 0x5a); + cpc_writeb(falcbase + F_REG(XPM1, ch), 0x8f); + cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20); + break; + case PC300_LBO_7_5_DB: + cpc_writeb(falcbase + F_REG(LIM2, ch), (0x40 | LIM2_LOS1 | dja)); + cpc_writeb(falcbase + F_REG(XPM0, ch), 0x11); + cpc_writeb(falcbase + F_REG(XPM1, ch), 0x02); + cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20); + break; + case PC300_LBO_15_DB: + cpc_writeb(falcbase + F_REG(LIM2, ch), (0x80 | LIM2_LOS1 | dja)); + cpc_writeb(falcbase + F_REG(XPM0, ch), 0x8e); + cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01); + cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20); + break; + case PC300_LBO_22_5_DB: + cpc_writeb(falcbase + F_REG(LIM2, ch), (0xc0 | LIM2_LOS1 | dja)); + cpc_writeb(falcbase + F_REG(XPM0, ch), 0x09); + cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01); + cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20); + break; + } + + /* Transmit Clock-Slot Offset */ + cpc_writeb(falcbase + F_REG(XC0, ch), + cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01); + /* Transmit Time-slot Offset */ + cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e); + /* Receive Clock-Slot offset */ + cpc_writeb(falcbase + F_REG(RC0, ch), 0x05); + /* Receive Time-slot offset */ + cpc_writeb(falcbase + F_REG(RC1, ch), 0x00); + + /* LOS Detection after 176 consecutive 0s */ + cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a); + /* LOS Recovery after 22 ones in the time window of PCD */ + cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15); + + cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f); + + if (conf->fr_mode == PC300_FR_ESF_JAPAN) { + cpc_writeb(falcbase + F_REG(RC1, ch), + cpc_readb(falcbase + F_REG(RC1, ch)) | 0x80); + } + + falc_close_all_timeslots(card, ch); +} + +void +falc_init_e1(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + ucchar dja = (ch ? (LIM2_DJA2|LIM2_DJA1) : 0); + + /* Switch to E1 mode (PCM 30) */ + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_PMOD); + + /* Clock mode */ + if (conf->clkrate) { /* Master mode */ + cpc_writeb(falcbase + F_REG(LIM0, ch), + cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS); + } else { /* Slave mode */ + cpc_writeb(falcbase + F_REG(LIM0, ch), + cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS); + } + cpc_writeb(falcbase + F_REG(LOOP, ch), + cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_RTM); + + cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI); + cpc_writeb(falcbase + F_REG(FMR0, ch), + cpc_readb(falcbase + F_REG(FMR0, ch)) & + ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1)); + + switch (conf->lcode) { + case PC300_LC_AMI: + cpc_writeb(falcbase + F_REG(FMR0, ch), + cpc_readb(falcbase + F_REG(FMR0, ch)) | + FMR0_XC1 | FMR0_RC1); + break; + + case PC300_LC_HDB3: + cpc_writeb(falcbase + F_REG(FMR0, ch), + cpc_readb(falcbase + F_REG(FMR0, ch)) | + FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1); + break; + + case PC300_LC_NRZ: + break; + } + + cpc_writeb(falcbase + F_REG(LIM0, ch), + cpc_readb(falcbase + F_REG(LIM0, ch)) & + ~(LIM0_SCL1 | LIM0_SCL0)); + /* Set interface mode to 2 MBPS */ + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD); + + cpc_writeb(falcbase + F_REG(XPM0, ch), 0x18); + cpc_writeb(falcbase + F_REG(XPM1, ch), 0x03); + cpc_writeb(falcbase + F_REG(XPM2, ch), 0x00); + + switch (conf->fr_mode) { + case PC300_FR_MF_CRC4: + pfalc->multiframe_mode = 1; + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_XFS); + cpc_writeb(falcbase + F_REG(FMR2, ch), + cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_RFS1); + cpc_writeb(falcbase + F_REG(FMR2, ch), + cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_RFS0); + cpc_writeb(falcbase + F_REG(FMR3, ch), + cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_EXTIW); + + /* MultiFrame Resynchronization */ + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_MFCS); + + /* Automatic Loss of Multiframe > 914 CRC errors */ + cpc_writeb(falcbase + F_REG(FMR2, ch), + cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_ALMF); + + /* S1 and SI1/SI2 spare Bits set to 1 */ + cpc_writeb(falcbase + F_REG(XSP, ch), + cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_AXS); + cpc_writeb(falcbase + F_REG(XSP, ch), + cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_EBP); + cpc_writeb(falcbase + F_REG(XSP, ch), + cpc_readb(falcbase + F_REG(XSP, ch)) | + XSP_XS13 | XSP_XS15); + break; + + case PC300_FR_MF_NON_CRC4: + case PC300_FR_D4: + pfalc->multiframe_mode = 0; + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_XFS); + cpc_writeb(falcbase + F_REG(FMR2, ch), + cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_RFS1); + cpc_writeb(falcbase + F_REG(FMR2, ch), + cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_RFS0); + cpc_writeb(falcbase + F_REG(XSW, ch), + cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XSIS); + cpc_writeb(falcbase + F_REG(XSP, ch), + cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_XSIF); + break; + } + + /* Automatic Force Resynchronization */ + cpc_writeb(falcbase + F_REG(FMR1, ch), + cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_AFR); + + /* Transmit Automatic Remote Alarm */ + cpc_writeb(falcbase + F_REG(FMR2, ch), + cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA); + + /* No signaling */ + cpc_writeb(falcbase + F_REG(XSP, ch), + cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_CASEN); + cpc_writeb(falcbase + F_REG(CCR1, ch), 0); + + cpc_writeb(falcbase + F_REG(LIM1, ch), + cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1); + cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja)); + + /* Transmit Clock-Slot Offset */ + cpc_writeb(falcbase + F_REG(XC0, ch), + cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01); + /* Transmit Time-slot Offset */ + cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e); + /* Receive Clock-Slot offset */ + cpc_writeb(falcbase + F_REG(RC0, ch), 0x05); + /* Receive Time-slot offset */ + cpc_writeb(falcbase + F_REG(RC1, ch), 0x00); + + /* LOS Detection after 176 consecutive 0s */ + cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a); + /* LOS Recovery after 22 ones in the time window of PCD */ + cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15); + + /* Transmit Spare Bits for National Use (Y-Bits, Sn-Bits, Sa-Bits) */ + cpc_writeb(falcbase + F_REG(XSW, ch), + cpc_readb(falcbase + F_REG(XSW, ch)) | + XSW_XY0 | XSW_XY1 | XSW_XY2 | XSW_XY3 | XSW_XY4); + + cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f); + + falc_close_all_timeslots(card, ch); +} + +void +falc_init_hdlc(pc300_t *card, int ch) +{ + uclong falcbase = card->hw.falcbase; + + /* Enable transparent data transfer */ + cpc_writeb(falcbase + F_REG(MODE, ch), + cpc_readb(falcbase + F_REG(MODE, ch)) | MODE_HRAC | MODE_MDS2); + cpc_writeb(falcbase + F_REG(RAH2, ch), 0xff); + cpc_writeb(falcbase + F_REG(RAH1, ch), 0xff); + cpc_writeb(falcbase + F_REG(RAL2, ch), 0xff); + cpc_writeb(falcbase + F_REG(RAL1, ch), 0xff); + + /* Tx/Rx reset */ + falc_issue_cmd(card, ch, CMDR_RRES | CMDR_XRES | CMDR_SRES); + + /* Enable interrupt sources */ + falc_intr_enable(card, ch); +} + +void +te_config(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + ucchar dummy; + unsigned long flags; + + memset(pfalc, 0, sizeof(falc_t)); + switch (conf->media) { + case LINE_T1: + pfalc->num_channels = NUM_OF_T1_CHANNELS; + pfalc->offset = 1; + break; + case LINE_E1: + pfalc->num_channels = NUM_OF_E1_CHANNELS; + pfalc->offset = 0; + break; + } + if (conf->tslot_bitmap == 0xffffffffUL) + pfalc->full_bandwidth = 1; + else + pfalc->full_bandwidth = 0; + + CPC_LOCK(card, flags); + /* Reset the FALC chip */ + cpc_writeb(card->hw.falcbase + CPLD_REG1, + cpc_readb(card->hw.falcbase + CPLD_REG1) | + (CPLD_REG1_FALC_RESET << (2*ch))); + udelay(10000); + cpc_writeb(card->hw.falcbase + CPLD_REG1, + cpc_readb(card->hw.falcbase + CPLD_REG1) & + ~(CPLD_REG1_FALC_RESET << (2*ch))); + + if (conf->media == LINE_T1) { + falc_init_t1(card, ch); + } else { + falc_init_e1(card, ch); + } + falc_init_hdlc(card, ch); + if (conf->rx_sens == PC300_RX_SENS_SH) { + cpc_writeb(falcbase + F_REG(LIM0, ch), + cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_EQON); + } else { + cpc_writeb(falcbase + F_REG(LIM0, ch), + cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_EQON); + } + cpc_writeb(card->hw.falcbase + CPLD_REG2, + cpc_readb(card->hw.falcbase + CPLD_REG2) | + ((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK) << (2*ch))); + + /* Clear all interrupt registers */ + dummy = cpc_readb(falcbase + F_REG(FISR0, ch)) + + cpc_readb(falcbase + F_REG(FISR1, ch)) + + cpc_readb(falcbase + F_REG(FISR2, ch)) + + cpc_readb(falcbase + F_REG(FISR3, ch)); + CPC_UNLOCK(card, flags); +} + +void +falc_check_status (pc300_t *card, int ch, unsigned char frs0) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + + /* Verify AIS alarm */ + if (frs0 & FRS0_AIS) { + if (!pfalc->blue_alarm) { + pfalc->blue_alarm = 1; + pfalc->ais++; + // EVENT_AIS + if (conf->media == LINE_T1) { + /* Disable this interrupt as it may otherwise interfere with + other working boards. */ + cpc_writeb(falcbase + F_REG(IMR0, ch), + cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN); + } + falc_disable_comm(card, ch); + // EVENT_AIS + } + } else { + pfalc->blue_alarm = 0; + } + + /* Verify LOS */ + if (frs0 & FRS0_LOS) { + if (! pfalc->red_alarm) { + pfalc->red_alarm = 1; + pfalc->los++; + if (!pfalc->blue_alarm) { + // EVENT_FALC_ABNORMAL + if (conf->media == LINE_T1) { + /* Disable this interrupt as it may otherwise interfere + with other working boards. */ + cpc_writeb(falcbase + F_REG(IMR0, ch), + cpc_readb(falcbase + F_REG(IMR0, ch)) | + IMR0_PDEN); + } + falc_disable_comm(card, ch); + // EVENT_FALC_ABNORMAL + } + } + } else { + if (pfalc->red_alarm) { + pfalc->red_alarm = 0; + pfalc->losr++; + } + } + + /* Verify LFA */ + if (frs0 & FRS0_LFA) { + if (!pfalc->loss_fa) { + pfalc->loss_fa = 1; + pfalc->lfa++; + if (!pfalc->blue_alarm && !pfalc->red_alarm) { + // EVENT_FALC_ABNORMAL + if (conf->media == LINE_T1) { + /* Disable this interrupt as it may otherwise interfere + with other working boards. */ + cpc_writeb(falcbase + F_REG(IMR0, ch), + cpc_readb(falcbase + F_REG(IMR0, ch)) | + IMR0_PDEN); + } + falc_disable_comm(card, ch); + // EVENT_FALC_ABNORMAL + } + } + } else { + if (pfalc->loss_fa) { + pfalc->loss_fa = 0; + pfalc->farec++; + } + } + + /* Verify LMFA */ + if ((pfalc->multiframe_mode) && (frs0 & FRS0_LMFA)) { + /* D4 or CRC4 frame mode */ + if (! pfalc->loss_mfa) { + pfalc->loss_mfa = 1; + pfalc->lmfa++; + if (!pfalc->blue_alarm && !pfalc->red_alarm && !pfalc->loss_fa) { + // EVENT_FALC_ABNORMAL + if (conf->media == LINE_T1) { + /* Disable this interrupt as it may otherwise interfere + with other working boards. */ + cpc_writeb(falcbase + F_REG(IMR0, ch), + cpc_readb(falcbase + F_REG(IMR0, ch)) | + IMR0_PDEN); + } + falc_disable_comm(card, ch); + // EVENT_FALC_ABNORMAL + } + } + } else { + pfalc->loss_mfa = 0; + } + + if (pfalc->red_alarm || pfalc->loss_fa || + pfalc->loss_mfa || pfalc->blue_alarm) { + if (pfalc->sync) { + pfalc->sync = 0; + cpc_writeb(falcbase + CPLD_REG2, + cpc_readb(falcbase + CPLD_REG2) & + ~(CPLD_REG2_FALC_LED2 << (2*ch))); + } + } else { + if ((!pfalc->sync)) { + pfalc->sync = 1; + cpc_writeb(falcbase + CPLD_REG2, + cpc_readb(falcbase + CPLD_REG2) | + (CPLD_REG2_FALC_LED2 << (2*ch))); + } + } + + /* Verify Remote Alarm */ + if (frs0 & FRS0_RRA) { + if (! pfalc->yellow_alarm) { + pfalc->yellow_alarm = 1; + pfalc->rai++; + if (pfalc->sync) { + // EVENT_RAI + falc_disable_comm(card, ch); + // EVENT_RAI + } + } + } else { + pfalc->yellow_alarm = 0; + } + + if ((pfalc->sync) && (!(pfalc->yellow_alarm))) { + if (! pfalc->active) { + // EVENT_FALC_NORMAL + if (pfalc->loop_active) { + return; + } + if (conf->media == LINE_T1) { + cpc_writeb(falcbase + F_REG(IMR0, ch), + cpc_readb(falcbase + F_REG(IMR0, ch)) & ~IMR0_PDEN); + } + falc_enable_comm(card, ch); + // EVENT_FALC_NORMAL + pfalc->active = 1; + } + } else { + if (pfalc->active) { + pfalc->active = 0; + } + } +} + +void +falc_update_stats(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + ucshort counter; + + counter = cpc_readb(falcbase + F_REG(FECL, ch)); + counter |= cpc_readb(falcbase + F_REG(FECH, ch)) << 8; + pfalc->fec += counter; + + counter = cpc_readb(falcbase + F_REG(CVCL, ch)); + counter |= cpc_readb(falcbase + F_REG(CVCH, ch)) << 8; + pfalc->cvc += counter; + + counter = cpc_readb(falcbase + F_REG(CECL, ch)); + counter |= cpc_readb(falcbase + F_REG(CECH, ch)) << 8; + pfalc->cec += counter; + + counter = cpc_readb(falcbase + F_REG(EBCL, ch)); + counter |= cpc_readb(falcbase + F_REG(EBCH, ch)) << 8; + pfalc->ebc += counter; + + if (cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) { + counter = cpc_readb(falcbase + F_REG(BECL, ch)); + counter |= cpc_readb(falcbase + F_REG(BECH, ch)) << 8; + pfalc->bec += counter; + + if (((conf->media == LINE_T1) && + (cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_LLBAD) && + (!(cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_PDEN))) + || + ((conf->media == LINE_E1) && + (cpc_readb(falcbase + F_REG(RSP, ch)) & RSP_LLBAD))) { + pfalc->prbs = 2; + } else { + pfalc->prbs = 1; + } + } +} + +void +falc_remote_loop(pc300_t *card, int ch, int loop_on) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + + if (loop_on) { + // EVENT_FALC_ABNORMAL + if (conf->media == LINE_T1) { + /* Disable this interrupt as it may otherwise interfere with + other working boards. */ + cpc_writeb(falcbase + F_REG(IMR0, ch), + cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN); + } + falc_disable_comm(card, ch); + // EVENT_FALC_ABNORMAL + cpc_writeb(falcbase + F_REG(LIM1, ch), + cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RL); + pfalc->loop_active = 1; + } else { + cpc_writeb(falcbase + F_REG(LIM1, ch), + cpc_readb(falcbase + F_REG(LIM1, ch)) & ~LIM1_RL); + pfalc->sync = 0; + cpc_writeb(falcbase + CPLD_REG2, + cpc_readb(falcbase + CPLD_REG2) & + ~(CPLD_REG2_FALC_LED2 << (2*ch))); + pfalc->active = 0; + falc_issue_cmd(card, ch, CMDR_XRES); + pfalc->loop_active = 0; + } +} + +/**********************************/ +/*** Net Interface Routines ***/ +/**********************************/ +int cpc_queue_xmit(struct sk_buff *skb, struct device *dev) +{ + pc300dev_t *d = (pc300dev_t *)dev->priv; + pc300ch_t *chan = (pc300ch_t *)d->chan; + pc300_t *card = (pc300_t *)chan->card; + struct enet_statistics *stats = &d->hdlc->stats; + int ch = chan->channel; + volatile pcsca_bd_t *ptdescr; + uclong flags; +#ifdef PC300_DEBUG_TX + int i; +#endif + + if (dev->tbusy) { + ucchar ilar; + + if (time_before(jiffies, dev->trans_start + PC300_TX_TIMEOUT)) + return 1; + + stats->tx_errors++; + stats->tx_aborted_errors++; + printk("%s: transmit timed out, restarting channel.", dev->name); + CPC_LOCK(card, flags); + if ((ilar = cpc_readb(card->hw.scabase + ILAR)) != 0) { + printk("(ILAR=0x%x)", ilar); + cpc_writeb(card->hw.scabase + ILAR, ilar); + cpc_writeb(card->hw.scabase + DMER, 0x80); + } + printk("\n"); + cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_BUF_CLR); + if (d->tx_skb) { + dev_kfree_skb(d->tx_skb); + d->tx_skb = NULL; + } + if (card->hw.type == PC300_TE) { + cpc_writeb(card->hw.falcbase + CPLD_REG2, + cpc_readb(card->hw.falcbase + CPLD_REG2) & + ~(CPLD_REG2_FALC_LED1 << (2*ch))); + } + CPC_UNLOCK(card, flags); + dev->tbusy = 0; + } + if (test_and_set_bit(0, (void*)&dev->tbusy)) { + printk("%s: transmitter access conflict.\n", dev->name); + return 1; + } + + /* Clean up descriptors from previous transmission */ + while (chan->tx_first_bd != chan->tx_next_bd) { + ptdescr = (pcsca_bd_t *) + (card->hw.rambase + TX_BD_ADDR(ch, chan->tx_first_bd)); + cpc_writeb(&ptdescr->status, 0); + chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1); + } + + /* Write buffer to DMA buffers */ + if(dma_buf_write(card, ch, (ucchar *)skb->data, skb->len) != 0) { + CPC_LOCK(card, flags); +// printk("%s: write error. Dropping TX packet.\n", dev->name); + dev->tbusy = 0; + CPC_UNLOCK(card, flags); + stats->tx_dropped++; + return 1; + } + +#ifdef PC300_DEBUG_TX + printk("%s T:", dev->name); + for(i = 0 ; i < skb->len ; i++) + printk(" %02x", *(skb->data + i)); + printk("\n"); +#endif + + d->tx_skb = skb; + dev->trans_start = jiffies; + + /* Start transmission */ + CPC_LOCK(card, flags); + cpc_writel(card->hw.scabase + DTX_REG(EDAL, ch), + TX_BD_ADDR(ch, chan->tx_next_bd)); + cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA); + cpc_writeb(card->hw.scabase + DSR_TX(ch), DSR_DE); + if (card->hw.type == PC300_TE) { + cpc_writeb(card->hw.falcbase + CPLD_REG2, + cpc_readb(card->hw.falcbase + CPLD_REG2) | + (CPLD_REG2_FALC_LED1 << (2*ch))); + } + CPC_UNLOCK(card, flags); + + return 0; +} + +void +cpc_net_rx(hdlc_device *hdlc) +{ + struct device *dev = hdlc_to_dev(hdlc); + pc300dev_t *d = (pc300dev_t *)dev->priv; + pc300ch_t *chan = (pc300ch_t *)d->chan; + pc300_t *card = (pc300_t *)chan->card; + struct enet_statistics *stats = &hdlc->stats; + int ch = chan->channel; +#ifdef PC300_DEBUG_RX + int i; +#endif + int rxb; + struct sk_buff *skb; + + while (1) { + if ((rxb = dma_get_rx_frame_size(card, ch)) == -1) + return; + + skb = dev_alloc_skb(rxb); + if (skb == NULL) { + printk("%s: Memory squeeze!!\n", dev->name); + return; + } + skb->dev = dev; + + if((rxb = dma_buf_read(card, ch, skb)) <= 0) { + if (rxb < 0) { /* Invalid frame */ + rxb = -rxb; + stats->rx_errors++; + if (rxb & DST_OVR) { + stats->rx_fifo_errors++; + } + if (rxb & DST_CRC) { + stats->rx_crc_errors++; + } + if (rxb & (DST_RBIT | DST_SHRT | DST_ABT)) { + stats->rx_frame_errors++; + } + } + dev_kfree_skb(skb); + continue; + } + +#ifdef PC300_DEBUG_RX + printk("%s R:", dev->name); + for(i = 0 ; i < skb->len ; i++) + printk(" %02x", *(skb->data + i)); + printk("\n"); +#endif + + switch(hdlc->mode & ~MODE_SOFT) { +#ifdef CONFIG_PC300_X25 + case MODE_X25: + { + int err; + + skb->protocol=htons(ETH_P_X25); + skb->mac.raw=skb->data; + skb->dev=hdlc_to_dev(d->hdlc); + + /* Send it to the upper layer */ + if ((err = lapb_data_received(d, skb)) != LAPB_OK) { + printk("%s: lapb_data_received err - %d\n", dev->name, err); + dev_kfree_skb(skb); + } + stats->rx_bytes += rxb; + stats->rx_packets++; + break; + } +#endif /* CONFIG_PC300_X25 */ + default: + hdlc_netif_rx(hdlc, skb, 0); + break; + } + } +} + +#ifdef CONFIG_PC300_X25 +/*********************************/ +/*** X.25 Support Routines ***/ +/*********************************/ +int +cpc_x25_packetlayer_xmit(struct sk_buff *skb, struct device *dev) +{ + pc300dev_t *d = (pc300dev_t *)dev->priv; + int err; + + switch (skb->data[0]) { + case 0x00: + break; + + case 0x01: + if ((err = lapb_connect_request(d)) != LAPB_OK) { + if (err == LAPB_CONNECTED) { + /* Send connect confirm. msg to level 3 */ + cpc_lapb_connected(d, 0); + } else { + printk("%s: lapb_connect_request error - %d\n", + dev->name, err); + } + } + dev_kfree_skb(skb); + return 0; + + case 0x02: + if ((err = lapb_disconnect_request(d)) != LAPB_OK) { + if (err == LAPB_NOTCONNECTED) { + /* Send disconnect confirm. msg to level 3 */ + cpc_lapb_disconnected(d, 0); + } else { + printk("%s: lapb_disconnect_request error - %d\n", + dev->name, err); + } + } + dev_kfree_skb(skb); + return 0; + + default: + dev_kfree_skb(skb); + return 0; + } + + skb_pull(skb, 1); + + if ((err = lapb_data_request(d, skb)) != LAPB_OK) { + printk("%s: lapb_data_request error - %d\n", dev->name, err); + dev_kfree_skb(skb); + return -ENOMEM; + } + + return 0; +} + +void +cpc_lapb_connected(void *token, int reason) +{ + pc300dev_t *d = (pc300dev_t *)token; + struct sk_buff *skb; + unsigned char *ptr; + + if ((skb = dev_alloc_skb(1)) == NULL) { + printk("%s: out of memory\n", d->name); + return; + } + + ptr = skb_put(skb, 1); + *ptr = 0x01; + + skb->dev = hdlc_to_dev(d->hdlc); + skb->protocol = htons(ETH_P_X25); + skb->mac.raw = skb->data; + skb->pkt_type = PACKET_HOST; + + netif_rx(skb); +} + +void +cpc_lapb_disconnected(void *token, int reason) +{ + pc300dev_t *d = (pc300dev_t *)token; + struct sk_buff *skb; + unsigned char *ptr; + + if ((skb = dev_alloc_skb(1)) == NULL) { + printk("%s: out of memory\n", d->name); + return; + } + + ptr = skb_put(skb, 1); + *ptr = 0x02; + + skb->dev = hdlc_to_dev(d->hdlc); + skb->protocol = htons(ETH_P_X25); + skb->mac.raw = skb->data; + skb->pkt_type = PACKET_HOST; + + netif_rx(skb); +} + +void +cpc_lapb_data_indication(void *token, struct sk_buff *skb) +{ + pc300dev_t *d = (pc300dev_t *)token; + unsigned char *ptr; + + ptr = skb_push(skb, 1); + *ptr = 0x00; + + skb->dev = hdlc_to_dev(d->hdlc); + skb->protocol = htons(ETH_P_X25); + skb->mac.raw = skb->data; + skb->pkt_type = PACKET_HOST; + + netif_rx(skb); +} + +void +cpc_lapb_data_transmit(void *token, struct sk_buff *skb) +{ + pc300dev_t *d = (pc300dev_t *)token; + struct device *dev = hdlc_to_dev(d->hdlc); + + cpc_queue_xmit (skb, dev); +} +#endif /* CONFIG_PC300_X25 */ + +/************************************/ +/*** PC300 Interrupt Routines ***/ +/************************************/ +static void +sca_intr(pc300_t *card) +{ + uclong scabase = card->hw.scabase; + volatile uclong status; + int ch; + int intr_count = 0; + + while ((status = cpc_readl(scabase + ISR0)) != 0) { + for (ch = 0 ; ch < card->hw.nchan ; ch++) { + pc300ch_t *chan = &card->chan[ch]; + pc300dev_t *d = &chan->d; + hdlc_device *hdlc = d->hdlc; + struct device *dev = hdlc_to_dev(hdlc); + + dev->interrupt = 1; + + /**** Reception ****/ + if (status & IR0_DRX((IR0_DMIA|IR0_DMIB), ch)) { + ucchar drx_stat = cpc_readb(scabase + DSR_RX(ch)); + + /* Clear RX interrupts */ + cpc_writeb(scabase + DSR_RX(ch), drx_stat | DSR_DWE); + +#ifdef PC300_DEBUG_INTR + printk("sca_intr: RX intr (st=0x%08lx, dsr=0x%02x)\n", + status, drx_stat); +#endif + if (status & IR0_DRX(IR0_DMIA, ch)) { + if (drx_stat & DSR_BOF) { + chan->rx_first_bd = 0; + chan->rx_last_bd = N_DMA_RX_BUF - 1; + cpc_writel(scabase + DRX_REG(CDAL, ch), + RX_BD_ADDR(ch, chan->rx_first_bd)); + cpc_writel(scabase + DRX_REG(EDAL, ch), + RX_BD_ADDR(ch, chan->rx_last_bd)); + cpc_writew(scabase + DRX_REG(BFLL, ch), BD_DEF_LEN); + cpc_writeb(scabase + DSR_RX(ch), DSR_DE); + } + } + if (status & IR0_DRX(IR0_DMIB, ch)) { + if (drx_stat & DSR_EOM) { + if (card->hw.type == PC300_TE) { + cpc_writeb(card->hw.falcbase + CPLD_REG2, + cpc_readb(card->hw.falcbase + CPLD_REG2) + | (CPLD_REG2_FALC_LED1 << (2*ch))); + } + cpc_net_rx(hdlc); + if (card->hw.type == PC300_TE) { + cpc_writeb(card->hw.falcbase + CPLD_REG2, + cpc_readb(card->hw.falcbase + CPLD_REG2) + & ~(CPLD_REG2_FALC_LED1 << (2*ch))); + } + } + } + } + + /**** Transmission ****/ + if (status & IR0_DTX((IR0_EFT|IR0_DMIA|IR0_DMIB), ch)) { + ucchar dtx_stat = cpc_readb(scabase + DSR_TX(ch)); + + /* Clear TX interrupts */ + cpc_writeb(scabase + DSR_TX(ch), dtx_stat | DSR_DWE); + +#ifdef PC300_DEBUG_INTR + printk("sca_intr: TX intr (st=0x%08lx, dsr=0x%02x)\n", + status, dtx_stat); +#endif + if (status & IR0_DTX(IR0_EFT, ch)) { + if (dtx_stat & DSR_UDRF) { + if (cpc_readb(scabase + M_REG(TBN, ch)) != 0) { + cpc_writeb(scabase + M_REG(CMD, ch), + CMD_TX_BUF_CLR); + } + if (card->hw.type == PC300_TE) { + cpc_writeb(card->hw.falcbase + CPLD_REG2, + cpc_readb(card->hw.falcbase + CPLD_REG2) + & ~(CPLD_REG2_FALC_LED1 << (2*ch))); + } + if (d->tx_skb) { + struct sk_buff *skb = d->tx_skb; + + dev_kfree_skb(skb); + d->tx_skb = NULL; + hdlc->stats.tx_errors++; + hdlc->stats.tx_fifo_errors++; + /* Tell the upper layer we are ready to transmit + more packets */ + dev->tbusy = 0; + mark_bh(NET_BH); + } + } + } + if (status & IR0_DTX(IR0_DMIA, ch)) { + if (dtx_stat & DSR_BOF) { + } + } + if (status & IR0_DTX(IR0_DMIB, ch)) { + if (dtx_stat & DSR_EOM) { + if (card->hw.type == PC300_TE) { + cpc_writeb(card->hw.falcbase + CPLD_REG2, + cpc_readb(card->hw.falcbase + CPLD_REG2) + & ~(CPLD_REG2_FALC_LED1 << (2*ch))); + } + if (d->tx_skb) { + struct sk_buff *skb = d->tx_skb; + + dev_kfree_skb(skb); + d->tx_skb = NULL; + hdlc->stats.tx_bytes += skb->len; + hdlc->stats.tx_packets++; + /* Tell the upper layer we are ready to transmit + more packets */ + dev->tbusy = 0; + mark_bh(NET_BH); + } + } + } + } + dev->interrupt = 0; + } + if (++intr_count == 10) + /* Too much work at this board. Force exit */ + break; + } +} + +static void +falc_t1_loop_detection(pc300_t *card, int ch, ucchar frs1) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + + if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && + !pfalc->loop_gen) { + if (frs1 & FRS1_LLBDD) { + // A Line Loop Back Deactuation signal detected + if (pfalc->loop_active) { + falc_remote_loop(card, ch, 0); + } + } else { + if ((frs1 & FRS1_LLBAD) && + ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) { + // A Line Loop Back Actuation signal detected + if (!pfalc->loop_active) { + falc_remote_loop(card, ch, 1); + } + } + } + } +} + +static void +falc_e1_loop_detection(pc300_t *card, int ch, ucchar rsp) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + + if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && + !pfalc->loop_gen) { + if (rsp & RSP_LLBDD) { + // A Line Loop Back Deactuation signal detected + if (pfalc->loop_active) { + falc_remote_loop(card, ch, 0); + } + } else { + if ((rsp & RSP_LLBAD) && + ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) { + // A Line Loop Back Actuation signal detected + if (!pfalc->loop_active) { + falc_remote_loop(card, ch, 1); + } + } + } + } +} + +static void +falc_t1_intr(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + ucchar isr0, isr3, gis; + ucchar dummy; + + while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) { + if (gis & GIS_ISR0) { + isr0 = cpc_readb(falcbase + F_REG(FISR0, ch)); + if (isr0 & FISR0_PDEN) { + /* Read the bit to clear the situation */ + if (cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_PDEN) { + pfalc->pden++; + } + } + } + + if (gis & GIS_ISR1) { + dummy = cpc_readb(falcbase + F_REG(FISR1, ch)); + } + + if (gis & GIS_ISR2) { + dummy = cpc_readb(falcbase + F_REG(FISR2, ch)); + } + + if (gis & GIS_ISR3) { + isr3 = cpc_readb(falcbase + F_REG(FISR3, ch)); + if (isr3 & FISR3_SEC) { + pfalc->sec++; + falc_update_stats(card, ch); + falc_check_status(card, ch, + cpc_readb(falcbase + F_REG(FRS0, ch))); + } + if (isr3 & FISR3_ES) { + pfalc->es++; + } + if (isr3 & FISR3_LLBSC) { + falc_t1_loop_detection(card, ch, + cpc_readb(falcbase + F_REG(FRS1, ch))); + } + } + } +} + +static void +falc_e1_intr(pc300_t *card, int ch) +{ + pc300ch_t *chan = (pc300ch_t *)&card->chan[ch]; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong falcbase = card->hw.falcbase; + ucchar isr1, isr2, isr3, gis, rsp; + ucchar dummy; + + while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) { + rsp = cpc_readb(falcbase + F_REG(RSP, ch)); + + if (gis & GIS_ISR0) { + dummy = cpc_readb(falcbase + F_REG(FISR0, ch)); + } + if (gis & GIS_ISR1) { + isr1 = cpc_readb(falcbase + F_REG(FISR1, ch)); + if (isr1 & FISR1_XMB) { + if ((pfalc->xmb_cause & 2) && pfalc->multiframe_mode) { + if (cpc_readb(falcbase + F_REG(FRS0, ch)) & + (FRS0_LOS | FRS0_AIS | FRS0_LFA)) { + cpc_writeb(falcbase + F_REG(XSP, ch), + cpc_readb(falcbase + F_REG(XSP, ch)) & + ~XSP_AXS); + } else { + cpc_writeb(falcbase + F_REG(XSP, ch), + cpc_readb(falcbase + F_REG(XSP, ch)) | + XSP_AXS); + } + } + pfalc->xmb_cause = 0; + cpc_writeb(falcbase + F_REG(IMR1, ch), + cpc_readb(falcbase + F_REG(IMR1, ch)) | IMR1_XMB); + } + if (isr1 & FISR1_LLBSC) { + falc_e1_loop_detection(card, ch, rsp); + } + } + if (gis & GIS_ISR2) { + isr2 = cpc_readb(falcbase + F_REG(FISR2, ch)); + if (isr2 & FISR2_T400MS) { + cpc_writeb(falcbase + F_REG(XSW, ch), + cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XRA); + } + if (isr2 & FISR2_MFAR) { + cpc_writeb(falcbase + F_REG(XSW, ch), + cpc_readb(falcbase + F_REG(XSW, ch)) & ~XSW_XRA); + } + if (isr2 & (FISR2_FAR | FISR2_LFA | FISR2_AIS | FISR2_LOS)) { + pfalc->xmb_cause |= 2; + cpc_writeb(falcbase + F_REG(IMR1, ch), + cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_XMB); + } + } + if (gis & GIS_ISR3) { + isr3 = cpc_readb(falcbase + F_REG(FISR3, ch)); + if (isr3 & FISR3_SEC) { + pfalc->sec++; + falc_update_stats(card, ch); + falc_check_status(card, ch, + cpc_readb(falcbase + F_REG(FRS0, ch))); + } + if (isr3 & FISR3_ES) { + pfalc->es++; + } + } + } +} + +static void +falc_intr(pc300_t *card) +{ + int ch; + + for (ch = 0 ; ch < card->hw.nchan ; ch++) { + pc300ch_t *chan = &card->chan[ch]; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + + if (conf->media == LINE_T1) { + falc_t1_intr(card, ch); + } else { + falc_e1_intr(card, ch); + } + } +} + +static void +cpc_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + pc300_t *card; + volatile ucchar plx_status; + + if((card = (pc300_t *)dev_id) == 0){ +#ifdef PC300_DEBUG_INTR + printk("cpc_intr: spurious intr %d\n", irq); +#endif + return; /* spurious intr */ + } + + switch (card->hw.type) { + case PC300_RSV: + case PC300_X21: + sca_intr(card); + break; + + case PC300_TE: + while ((plx_status = (cpc_readb(card->hw.plxbase + 0x4c) & + (PLX_9050_LINT1_STATUS|PLX_9050_LINT2_STATUS))) != 0) { + if (plx_status & PLX_9050_LINT1_STATUS) { /* SCA Interrupt */ + sca_intr(card); + } + if (plx_status & PLX_9050_LINT2_STATUS) { /* FALC Interrupt */ + falc_intr(card); + } + } + break; + } +} + +void +cpc_sca_status(pc300_t *card, int ch) +{ + ucchar ilar; + uclong scabase = card->hw.scabase; + uclong flags; + + tx_dma_buf_check(card, ch); + rx_dma_buf_check(card, ch); + ilar = cpc_readb(scabase + ILAR); + printk("ILAR=0x%02x, WCRL=0x%02x, PCR=0x%02x, BTCR=0x%02x, BOLR=0x%02x\n", + ilar, cpc_readb(scabase + WCRL), + cpc_readb(scabase + PCR), + cpc_readb(scabase + BTCR), + cpc_readb(scabase + BOLR)); + printk("TX_CDA=0x%08lx, TX_EDA=0x%08lx\n", + (uclong)cpc_readl(scabase + DTX_REG(CDAL, ch)), + (uclong)cpc_readl(scabase + DTX_REG(EDAL, ch))); + printk("RX_CDA=0x%08lx, RX_EDA=0x%08lx, BFL=0x%04x\n", + (uclong)cpc_readl(scabase + DRX_REG(CDAL, ch)), + (uclong)cpc_readl(scabase + DRX_REG(EDAL, ch)), + cpc_readw(scabase + DRX_REG(BFLL, ch))); + printk("DMER=0x%02x, DSR_TX=0x%02x, DSR_RX=0x%02x\n", + cpc_readb(scabase + DMER), + cpc_readb(scabase + DSR_TX(ch)), + cpc_readb(scabase + DSR_RX(ch))); + printk("DMR_TX=0x%02x, DMR_RX=0x%02x, DIR_TX=0x%02x, DIR_RX=0x%02x\n", + cpc_readb(scabase + DMR_TX(ch)), + cpc_readb(scabase + DMR_RX(ch)), + cpc_readb(scabase + DIR_TX(ch)), + cpc_readb(scabase + DIR_RX(ch))); + printk("DCR_TX=0x%02x, DCR_RX=0x%02x, FCT_TX=0x%02x, FCT_RX=0x%02x\n", + cpc_readb(scabase + DCR_TX(ch)), + cpc_readb(scabase + DCR_RX(ch)), + cpc_readb(scabase + FCT_TX(ch)), + cpc_readb(scabase + FCT_RX(ch))); + printk("MD0=0x%02x, MD1=0x%02x, MD2=0x%02x, MD3=0x%02x, IDL=0x%02x\n", + cpc_readb(scabase + M_REG(MD0, ch)), + cpc_readb(scabase + M_REG(MD1, ch)), + cpc_readb(scabase + M_REG(MD2, ch)), + cpc_readb(scabase + M_REG(MD3, ch)), + cpc_readb(scabase + M_REG(IDL, ch))); + printk("CMD=0x%02x, SA0=0x%02x, SA1=0x%02x, TFN=0x%02x, CTL=0x%02x\n", + cpc_readb(scabase + M_REG(CMD, ch)), + cpc_readb(scabase + M_REG(SA0, ch)), + cpc_readb(scabase + M_REG(SA1, ch)), + cpc_readb(scabase + M_REG(TFN, ch)), + cpc_readb(scabase + M_REG(CTL, ch))); + printk("ST0=0x%02x, ST1=0x%02x, ST2=0x%02x, ST3=0x%02x, ST4=0x%02x\n", + cpc_readb(scabase + M_REG(ST0, ch)), + cpc_readb(scabase + M_REG(ST1, ch)), + cpc_readb(scabase + M_REG(ST2, ch)), + cpc_readb(scabase + M_REG(ST3, ch)), + cpc_readb(scabase + M_REG(ST4, ch))); + printk("CST0=0x%02x, CST1=0x%02x, CST2=0x%02x, CST3=0x%02x, FST=0x%02x\n", + cpc_readb(scabase + M_REG(CST0, ch)), + cpc_readb(scabase + M_REG(CST1, ch)), + cpc_readb(scabase + M_REG(CST2, ch)), + cpc_readb(scabase + M_REG(CST3, ch)), + cpc_readb(scabase + M_REG(FST, ch))); + printk("TRC0=0x%02x, TRC1=0x%02x, RRC=0x%02x, TBN=0x%02x, RBN=0x%02x\n", + cpc_readb(scabase + M_REG(TRC0, ch)), + cpc_readb(scabase + M_REG(TRC1, ch)), + cpc_readb(scabase + M_REG(RRC, ch)), + cpc_readb(scabase + M_REG(TBN, ch)), + cpc_readb(scabase + M_REG(RBN, ch))); + printk("TFS=0x%02x, TNR0=0x%02x, TNR1=0x%02x, RNR=0x%02x\n", + cpc_readb(scabase + M_REG(TFS, ch)), + cpc_readb(scabase + M_REG(TNR0, ch)), + cpc_readb(scabase + M_REG(TNR1, ch)), + cpc_readb(scabase + M_REG(RNR, ch))); + printk("TCR=0x%02x, RCR=0x%02x, TNR1=0x%02x, RNR=0x%02x\n", + cpc_readb(scabase + M_REG(TCR, ch)), + cpc_readb(scabase + M_REG(RCR, ch)), + cpc_readb(scabase + M_REG(TNR1, ch)), + cpc_readb(scabase + M_REG(RNR, ch))); + printk("TXS=0x%02x, RXS=0x%02x, EXS=0x%02x, TMCT=0x%02x, TMCR=0x%02x\n", + cpc_readb(scabase + M_REG(TXS, ch)), + cpc_readb(scabase + M_REG(RXS, ch)), + cpc_readb(scabase + M_REG(EXS, ch)), + cpc_readb(scabase + M_REG(TMCT, ch)), + cpc_readb(scabase + M_REG(TMCR, ch))); + printk("IE0=0x%02x, IE1=0x%02x, IE2=0x%02x, IE4=0x%02x, FIE=0x%02x\n", + cpc_readb(scabase + M_REG(IE0, ch)), + cpc_readb(scabase + M_REG(IE1, ch)), + cpc_readb(scabase + M_REG(IE2, ch)), + cpc_readb(scabase + M_REG(IE4, ch)), + cpc_readb(scabase + M_REG(FIE, ch))); + printk("IER0=0x%08lx\n", (uclong)cpc_readl(scabase + IER0)); + + if (ilar != 0) { + CPC_LOCK(card, flags); + cpc_writeb(scabase + ILAR, ilar); + cpc_writeb(scabase + DMER, 0x80); + CPC_UNLOCK(card, flags); + } +} + +void +cpc_falc_status(pc300_t *card, int ch) +{ + pc300ch_t *chan = &card->chan[ch]; + falc_t *pfalc = (falc_t *)&chan->falc; + uclong flags; + + CPC_LOCK(card, flags); + printk("CH%d: %s %s %d channels\n", + ch, (pfalc->sync ? "SYNC":""), (pfalc->active ? "ACTIVE":""), + pfalc->num_channels); + + printk(" pden=%d, los=%d, losr=%d, lfa=%d, farec=%d\n", + pfalc->pden, pfalc->los, pfalc->losr, pfalc->lfa, pfalc->farec); + printk(" lmfa=%d, ais=%d, sec=%d, es=%d, rai=%d\n", + pfalc->lmfa, pfalc->ais, pfalc->sec, pfalc->es, pfalc->rai); + printk(" bec=%d, fec=%d, cvc=%d, cec=%d, ebc=%d\n", + pfalc->bec, pfalc->fec, pfalc->cvc, pfalc->cec, pfalc->ebc); + + printk("\n"); + printk(" STATUS: %s %s %s %s %s %s\n", + (pfalc->red_alarm ? "RED":""), + (pfalc->blue_alarm ? "BLU":""), + (pfalc->yellow_alarm ? "YEL":""), + (pfalc->loss_fa ? "LFA":""), + (pfalc->loss_mfa ? "LMF":""), + (pfalc->prbs ? "PRB":"")); + CPC_UNLOCK(card, flags); +} + +int +cpc_ioctl(hdlc_device *hdlc, struct ifreq *ifr, int cmd) +{ + struct device *dev = hdlc_to_dev(hdlc); + pc300dev_t *d = (pc300dev_t *)dev->priv; + pc300ch_t *chan = (pc300ch_t *)d->chan; + pc300_t *card = (pc300_t *)chan->card; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + int ch = chan->channel; + int value; + void *arg = (void *) ifr->ifr_data; + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + + switch(cmd) { + case SIOCGPC300CONF: + conf->proto = hdlc->mode; + if (!arg || copy_to_user(arg, conf, sizeof(pc300chconf_t))) + return -EINVAL; + return 0; + case SIOCSPC300CONF: + if (!suser()) + return -EPERM; + if (!arg || copy_from_user(conf, arg, sizeof(pc300chconf_t))) + return -EINVAL; + return 0; + case SIOCGPC300STATUS: + cpc_sca_status(card, ch); + return 0; + case SIOCGPC300FALCSTATUS: + cpc_falc_status(card, ch); + return 0; + case HDLCSETLINE: + value = ifr->ifr_ifru.ifru_ivalue; + switch (value) { + case LINE_V35: + case LINE_X21: + case LINE_RS232: + case LINE_T1: + case LINE_E1: + /* Media */ + conf->media = value; + return 0; + + default: + /* Clock rate */ + conf->clkrate = value; + return 0; + } + + default: + switch(hdlc->mode & ~MODE_SOFT) { +#ifdef CONFIG_PC300_X25 + case MODE_X25: + /* There are no X.25-specific ioctls */ + return -EINVAL; +#endif /* CONFIG_PC300_X25 */ + default: + return -EINVAL; + } + } +} + +static int +clock_rate_calc(uclong rate, uclong clock, int *br_io) +{ + int br, tc; + int br_pwr, error; + + if (rate == 0) + return (0); + + for (br = 0, br_pwr = 1 ; br <= 9 ; br++, br_pwr <<= 1) { + if ((tc = clock / br_pwr / rate) <= 0xff) { + *br_io = br; + break; + } + } + + if (tc <= 0xff) { + error = ((rate - (clock / br_pwr / rate)) / rate) * 1000; + /* Errors bigger than +/- 1% won't be tolerated */ + if (error < -10 || error > 10) + return (-1); + else + return (tc); + } else { + return (-1); + } +} + +int +ch_config(pc300dev_t *d) +{ + pc300ch_t *chan = (pc300ch_t *)d->chan; + pc300chconf_t *conf = (pc300chconf_t *)&chan->conf; + pc300_t *card = (pc300_t *)chan->card; + uclong scabase = card->hw.scabase; + uclong plxbase = card->hw.plxbase; + int ch = chan->channel; + uclong clkrate = chan->conf.clkrate; + int tmc, br; + + /* Reset the channel */ + cpc_writeb(scabase + M_REG(CMD, ch), CMD_CH_RST); + + /* Configure the SCA registers */ + cpc_writeb(scabase + M_REG(MD0, ch), + (MD0_CRC_CCITT|MD0_CRCC0|MD0_BIT_SYNC)); + cpc_writeb(scabase + M_REG(MD1, ch), 0); + cpc_writeb(scabase + M_REG(MD2, ch), (MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_NRZ)); + cpc_writeb(scabase + M_REG(IDL, ch), 0x7e); + cpc_writeb(scabase + M_REG(CTL, ch), CTL_URSKP|CTL_IDLC); + + /* Configure HW media */ + switch(card->hw.type) { + case PC300_RSV: + if(conf->media == LINE_V35) { + cpc_writel((plxbase+0x50), + cpc_readl(plxbase+0x50) | PC300_CHMEDIA_MASK(ch)); + } else { + cpc_writel((plxbase+0x50), + cpc_readl(plxbase+0x50) & ~PC300_CHMEDIA_MASK(ch)); + } + break; + + case PC300_X21: + break; + + case PC300_TE: + te_config(card, ch); + break; + } + + switch(card->hw.type) { + case PC300_RSV: + case PC300_X21: + if (clkrate) { + /* Calculate the clkrate rate parameters */ + tmc = clock_rate_calc(clkrate, card->hw.clock, &br); + cpc_writeb(scabase + M_REG(TMCT, ch), tmc); + cpc_writeb(scabase + M_REG(TXS, ch), (TXS_DTRXC|TXS_IBRG|br)); + cpc_writeb(scabase + M_REG(TMCR, ch), tmc); + cpc_writeb(scabase + M_REG(RXS, ch), (RXS_IBRG|br)); + if (card->hw.type == PC300_X21) + cpc_writeb(scabase + M_REG(GPO, ch), 1); + } else { + cpc_writeb(scabase + M_REG(TMCT, ch), 1); + cpc_writeb(scabase + M_REG(TXS, ch), TXS_DTRXC); + cpc_writeb(scabase + M_REG(TMCR, ch), 1); + cpc_writeb(scabase + M_REG(RXS, ch), 0); + if (card->hw.type == PC300_X21) + cpc_writeb(scabase + M_REG(GPO, ch), 0); + } + cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1|EXS_RES1); + break; + + case PC300_TE: + /* SCA always receives clock from the FALC chip */ + cpc_writeb(scabase + M_REG(TMCT, ch), 1); + cpc_writeb(scabase + M_REG(TXS, ch), 0); + cpc_writeb(scabase + M_REG(TMCR, ch), 1); + cpc_writeb(scabase + M_REG(RXS, ch), 0); + cpc_writeb(scabase + M_REG(EXS, ch), 0); + break; + } + + /* Enable Interrupts */ + cpc_writel(scabase + IER0, + cpc_readl(scabase + IER0) | + IR0_DRX(IR0_EFT|IR0_DMIA|IR0_DMIB, ch) | + IR0_DTX(IR0_EFT|IR0_DMIA|IR0_DMIB, ch) ); + + return 0; +} + +int +rx_config(pc300dev_t *d) +{ + pc300ch_t *chan = (pc300ch_t *)d->chan; + pc300_t *card = (pc300_t *)chan->card; + uclong scabase = card->hw.scabase; + int ch = chan->channel; + + cpc_writeb(scabase + DSR_RX(ch), 0); + + /* General RX settings */ + cpc_writeb(scabase + M_REG(RRC, ch), 0); + cpc_writeb(scabase + M_REG(RNR, ch), 16); + + /* Enable reception */ + cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_CRC_INIT); + cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_ENA); + + /* Initialize DMA stuff */ + chan->rx_first_bd = 0; + chan->rx_last_bd = N_DMA_RX_BUF - 1; + rx_dma_buf_init(card, ch); + cpc_writeb(scabase + DCR_RX(ch), DCR_FCT_CLR); + cpc_writeb(scabase + DMR_RX(ch), (DMR_TMOD | DMR_NF)); + cpc_writeb(scabase + DIR_RX(ch), (DIR_EOM | DIR_BOF)); + + /* Start DMA */ + cpc_writel(scabase + DRX_REG(CDAL, ch), RX_BD_ADDR(ch, chan->rx_first_bd)); + cpc_writel(scabase + DRX_REG(EDAL, ch), RX_BD_ADDR(ch, chan->rx_last_bd)); + cpc_writew(scabase + DRX_REG(BFLL, ch), BD_DEF_LEN); + cpc_writeb(scabase + DSR_RX(ch), DSR_DE); + + return 0; +} + +int +tx_config(pc300dev_t *d) +{ + pc300ch_t *chan = (pc300ch_t *)d->chan; + pc300_t *card = (pc300_t *)chan->card; + uclong scabase = card->hw.scabase; + int ch = chan->channel; + + cpc_writeb(scabase + DSR_TX(ch), 0); + + /* General TX settings */ + cpc_writeb(scabase + M_REG(TRC0, ch), 0); + cpc_writeb(scabase + M_REG(TFS, ch), 32); + cpc_writeb(scabase + M_REG(TNR0, ch), 20); + cpc_writeb(scabase + M_REG(TNR1, ch), 48); + cpc_writeb(scabase + M_REG(TCR, ch), 8); + + /* Enable transmission */ + cpc_writeb(scabase + M_REG(CMD, ch), CMD_TX_CRC_INIT); + + /* Initialize DMA stuff */ + chan->tx_first_bd = 0; + chan->tx_next_bd = 0; + tx_dma_buf_init(card, ch); + cpc_writeb(scabase + DCR_TX(ch), DCR_FCT_CLR); + cpc_writeb(scabase + DMR_TX(ch), (DMR_TMOD | DMR_NF)); + cpc_writeb(scabase + DIR_TX(ch), (DIR_EOM | DIR_BOF | DIR_UDRF)); + cpc_writel(scabase + DTX_REG(CDAL, ch), TX_BD_ADDR(ch, chan->tx_first_bd)); + cpc_writel(scabase + DTX_REG(EDAL, ch), TX_BD_ADDR(ch, chan->tx_next_bd)); + + return 0; +} + +int +cpc_opench(pc300dev_t *d) +{ + pc300ch_t *chan = (pc300ch_t *)d->chan; + pc300_t *card = (pc300_t *)chan->card; + int ch = chan->channel; + uclong scabase = card->hw.scabase; + int err = -1; + + err = ch_config(d); + if (err) + return err; + + err = rx_config(d); + if (err) + return err; + + err = tx_config(d); + if (err) + return err; + + /* Assert RTS and DTR */ + cpc_writeb(scabase + M_REG(CTL, ch), + cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR)); + + return 0; +} + +void +cpc_closech(pc300dev_t *d) +{ + pc300ch_t *chan = (pc300ch_t *)d->chan; + pc300_t *card = (pc300_t *)chan->card; + falc_t *pfalc = (falc_t *)&chan->falc; + int ch = chan->channel; + + cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_CH_RST); + if (card->hw.type == PC300_TE) { + memset(pfalc, 0, sizeof(falc_t)); + cpc_writeb(card->hw.falcbase + CPLD_REG2, + cpc_readb(card->hw.falcbase + CPLD_REG2) & + ~((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK | + CPLD_REG2_FALC_LED2) << (2*ch))); + /* Reset the FALC chip */ + cpc_writeb(card->hw.falcbase + CPLD_REG1, + cpc_readb(card->hw.falcbase + CPLD_REG1) | + (CPLD_REG1_FALC_RESET << (2*ch))); + udelay(10000); + cpc_writeb(card->hw.falcbase + CPLD_REG1, + cpc_readb(card->hw.falcbase + CPLD_REG1) & + ~(CPLD_REG1_FALC_RESET << (2*ch))); + } +} + +int +cpc_open(hdlc_device *hdlc) +{ + struct device *dev = hdlc_to_dev(hdlc); + pc300dev_t *d = (pc300dev_t *)dev->priv; + int err = -1; + + err = cpc_opench(d); + if (err) + return err; + + switch(hdlc->mode & ~MODE_SOFT) { +#ifdef CONFIG_PC300_X25 + case MODE_X25: + { + struct lapb_register_struct cpc_lapb_callbacks; + + hdlc->ioctl = cpc_ioctl; + cpc_lapb_callbacks.connect_confirmation = cpc_lapb_connected; + cpc_lapb_callbacks.connect_indication = cpc_lapb_connected; + cpc_lapb_callbacks.disconnect_confirmation = cpc_lapb_disconnected; + cpc_lapb_callbacks.disconnect_indication = cpc_lapb_disconnected; + cpc_lapb_callbacks.data_indication = cpc_lapb_data_indication; + cpc_lapb_callbacks.data_transmit = cpc_lapb_data_transmit; + + if ((err = lapb_register(d, &cpc_lapb_callbacks)) != LAPB_OK) { + printk("%s: lapb_register error - %d\n", dev->name, err); + dev->tbusy = 1; + dev->start = 0; + return -ENODEV; + } + dev->hard_start_xmit = cpc_x25_packetlayer_xmit; + dev->type = ARPHRD_X25; + dev->hard_header_len = 2; + dev->addr_len = 0; + break; + } +#endif /* CONFIG_PC300_X25 */ + default: + break; + } + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + MOD_INC_USE_COUNT; + return 0; +} + +void +cpc_close(hdlc_device *hdlc) +{ + struct device *dev = hdlc_to_dev(hdlc); + pc300dev_t *d = (pc300dev_t *)dev->priv; + pc300ch_t *chan = (pc300ch_t *)d->chan; + pc300_t *card = (pc300_t *)chan->card; + uclong flags; + + CPC_LOCK(card, flags); + switch(hdlc->mode & ~MODE_SOFT) { +#ifdef CONFIG_PC300_X25 + case MODE_X25: + { + int err; + + if ((err = lapb_unregister(d)) != LAPB_OK) { + printk("%s: lapb_unregister error - %d\n", dev->name, err); + } + break; + } +#endif /* CONFIG_PC300_X25 */ + default: + break; + } + if (d->tx_skb) { + dev_kfree_skb(d->tx_skb); + d->tx_skb = NULL; + } + dev->tbusy = 1; + dev->start = 0; + cpc_closech(d); + CPC_UNLOCK(card, flags); + + MOD_DEC_USE_COUNT; +} + +static uclong +detect_ram(pc300_t *card) +{ + uclong i; + ucchar data; + uclong rambase = card->hw.rambase; + + card->hw.ramsize = PC300_RAMSIZE; + /* Let's find out how much RAM is present on this board */ + for (i = 0; i < card->hw.ramsize ; i++) { + data = (ucchar)(i & 0xff); + cpc_writeb(rambase + i, data); + if (cpc_readb(rambase + i) != data) { + break; + } + } + return (i); +} + +static void +plx_init(pc300_t *card) +{ + struct RUNTIME_9050 *plx_ctl = (struct RUNTIME_9050 *)card->hw.plxbase; + + /* Reset PLX */ + cpc_writel(&plx_ctl->init_ctrl, cpc_readl(&plx_ctl->init_ctrl)|0x40000000); + udelay(10000L); + cpc_writel(&plx_ctl->init_ctrl, cpc_readl(&plx_ctl->init_ctrl)&~0x40000000); + + /* Reload Config. Registers from EEPROM */ + cpc_writel(&plx_ctl->init_ctrl, cpc_readl(&plx_ctl->init_ctrl)|0x20000000); + udelay(10000L); + cpc_writel(&plx_ctl->init_ctrl, cpc_readl(&plx_ctl->init_ctrl)&~0x20000000); + +} + +__initfunc(static int +cpc_detect(void)) +{ +#ifdef CONFIG_PCI + static struct pci_dev *pdev = NULL; + ucchar cpc_rev_id; + ucchar cpc_irq = 0; + uclong cpc_plxphys, cpc_ramphys, cpc_scaphys, cpc_falcphys, cpc_iophys; + uclong cpc_plxbase, cpc_rambase, cpc_scabase, cpc_falcbase; + ucshort i, j, eeprom_outdated = 0; + ucshort device_id, dev_index = 0; + pc300_t *card; + + if(pci_present() == 0) { /* PCI bus not present */ + return 0; + } + for (i = 0 ; i < PC300_MAXCARDS ; i++) { + /* look for a Cyclades card by vendor and device id */ + while((device_id = cpc_pci_dev_id[dev_index]) != 0) { + if((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES, + device_id, pdev)) == NULL) { + dev_index++; /* try next device id */ + } else { + break; /* found a board */ + } + } + if (device_id == 0) + break; + + /* read PCI configuration area */ + cpc_irq = pdev->irq; + cpc_iophys = pdev->base_address[1]; + cpc_scaphys = pdev->base_address[2]; + cpc_ramphys = pdev->base_address[3]; + cpc_falcphys = pdev->base_address[4]; + cpc_plxphys = pdev->base_address[5]; + pci_read_config_byte(pdev, PCI_REVISION_ID, &cpc_rev_id); + + if ((device_id == PCI_DEVICE_ID_PC300_RX_1) || + (device_id == PCI_DEVICE_ID_PC300_RX_2) || + (device_id == PCI_DEVICE_ID_PC300_TE_1) || + (device_id == PCI_DEVICE_ID_PC300_TE_2)) { +#ifdef PC300_DEBUG_PCI + printk("cpc (bus=0x0%x, pci_id=0x%x, ", + pdev->bus->number, pdev->devfn); + printk("rev_id=%d) IRQ%d\n", cpc_rev_id, (int)cpc_irq); + printk("cpc:found ramaddr=0x%lx plxaddr=0x%lx " + "ctladdr=0x%lx falcaddr=0x%lx\n", + (ulong)cpc_ramphys, (ulong)cpc_plxphys, + (ulong)cpc_scaphys, (ulong)cpc_falcphys); +#endif + cpc_iophys &= PCI_BASE_ADDRESS_IO_MASK; + cpc_plxphys &= PCI_BASE_ADDRESS_MEM_MASK; + cpc_ramphys &= PCI_BASE_ADDRESS_MEM_MASK; + cpc_scaphys &= PCI_BASE_ADDRESS_MEM_MASK; + cpc_falcphys &= PCI_BASE_ADDRESS_MEM_MASK; + + /* Although we don't use this I/O region, we should + request it from the kernel anyway, to avoid problems + with other drivers accessing it. */ + request_region(cpc_iophys, PC300_PLX_WIN, "Cyclades-PC300"); + + if (cpc_plxphys) { + pdev->base_address[0] = cpc_plxphys; + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, cpc_plxphys); + } else { + eeprom_outdated = 1; + cpc_plxphys = pdev->base_address[0]; + cpc_plxphys &= PCI_BASE_ADDRESS_MEM_MASK; + } + + cpc_plxbase = (uclong) ioremap(cpc_plxphys, PC300_PLX_WIN); + cpc_rambase = (uclong) ioremap(cpc_ramphys, PC300_RAMSIZE); + cpc_scabase = (uclong) ioremap(cpc_scaphys, PC300_SCASIZE); + switch(device_id) { + case PCI_DEVICE_ID_PC300_TE_1: + case PCI_DEVICE_ID_PC300_TE_2: + cpc_falcbase = (uclong) ioremap(cpc_falcphys, + PC300_FALCSIZE); + break; + + case PCI_DEVICE_ID_PC300_RX_1: + case PCI_DEVICE_ID_PC300_RX_2: + default: + cpc_falcbase = 0; + break; + } + +#ifdef PC300_DEBUG_PCI + printk("cpc: relocate ramaddr=0x%lx plxaddr=0x%lx " + "ctladdr=0x%lx falcaddr=0x%lx\n", + (ulong)cpc_rambase, (ulong)cpc_plxbase, + (ulong)cpc_scabase, (ulong)cpc_falcbase); +#endif + /* Fill the next card structure available */ + for (j = 0 ; j < PC300_MAXCARDS ; j++) { + if (cpc_card[j].hw.rambase == 0) break; + } + + if (j == PC300_MAXCARDS) { /* No more cards available */ + printk("PC300 found at RAM 0x%lx, " + "but no more cards can be used.\n", + (ulong) cpc_ramphys); + printk("Change PC300_MAXCARDS in pc300drv.c and " + "recompile your kernel.\n"); + return(i); + } + + /* Allocate IRQ */ + if(request_irq(cpc_irq, cpc_intr, SA_SHIRQ, "Cyclades-PC300", + &cpc_card[j])) + { + printk("PC300 found at RAM 0x%lx, " + "but could not allocate IRQ%d.\n", + (ulong) cpc_ramphys, cpc_irq); + return(i); + } + + card = &cpc_card[j]; + + /* Set PC300 HW structure */ + card->hw.plxphys = cpc_plxphys; + card->hw.plxbase = cpc_plxbase; + card->hw.plxsize = (uclong)PC300_PLX_WIN; + card->hw.scaphys = cpc_scaphys; + card->hw.scabase = cpc_scabase; + card->hw.scasize = (uclong)PC300_SCASIZE; + card->hw.ramphys = cpc_ramphys; + card->hw.rambase = cpc_rambase; + card->hw.ramsize = detect_ram(card); + card->hw.falcphys = cpc_falcphys; + card->hw.falcbase = cpc_falcbase; + card->hw.falcsize = (uclong)PC300_FALCSIZE; + card->hw.irq = (int)cpc_irq; + switch(device_id) { + case PCI_DEVICE_ID_PC300_RX_1: + case PCI_DEVICE_ID_PC300_TE_1: + card->hw.nchan = 1; + break; + + case PCI_DEVICE_ID_PC300_RX_2: + case PCI_DEVICE_ID_PC300_TE_2: + default: + card->hw.nchan = PC300_MAXCHAN; + break; + } + + /* Enable interrupts on the PCI bridge */ + plx_init(&cpc_card[j]); + cpc_writew(card->hw.plxbase+0x4c, + cpc_readw(card->hw.plxbase+0x4c) | 0x0040); + +#ifdef USE_PCI_CLOCK + /* Set board clock to PCI clock */ + cpc_writel(card->hw.plxbase+0x50, + cpc_readl(card->hw.plxbase+0x50) | 0x00000004UL); + card->hw.clock = PC300_PCI_CLOCK; +#else + /* Set board clock to internal oscillator clock */ + cpc_writel(card->hw.plxbase+0x50, + cpc_readl(card->hw.plxbase+0x50) & ~0x00000004UL); + card->hw.clock = PC300_OSC_CLOCK; +#endif + + /* Set Global SCA-II registers */ + cpc_writeb(card->hw.scabase + PCR, PCR_PR2); + cpc_writeb(card->hw.scabase + BTCR, 0x10); + cpc_writeb(card->hw.scabase + WCRL, 0); + cpc_writeb(card->hw.scabase + DMER, 0x80); + + /* Set board type */ + switch(device_id) { + case PCI_DEVICE_ID_PC300_TE_1: + case PCI_DEVICE_ID_PC300_TE_2: + card->hw.type = PC300_TE; + /* Enable the board's global clock */ + cpc_writeb(card->hw.falcbase + CPLD_REG1, + cpc_readb(card->hw.falcbase + CPLD_REG1) | + CPLD_REG1_GLOBAL_CLK); + break; + + case PCI_DEVICE_ID_PC300_RX_1: + case PCI_DEVICE_ID_PC300_RX_2: + default: + if((cpc_readl(card->hw.plxbase+0x50) & PC300_CTYPE_MASK)) { + card->hw.type = PC300_X21; + } else { + card->hw.type = PC300_RSV; + } + break; + } + } + } + if (eeprom_outdated) + printk("WARNING: detected at least one PC300 with an outdated " + "EEPROM.\n"); + return i; +#else + printk("cpc: WARNING: your kernel does not have PCI support.\n"); + return 0; +#endif /* CONFIG_PCI */ +} + +/* + * This routine prints out the appropriate serial driver version number + * and identifies which options were configured into this driver. + */ +static inline void +show_version(void) +{ + char *rcsvers, *rcsdate, *tmp; + rcsvers = strchr(rcsid, ' '); rcsvers++; + tmp = strchr(rcsvers, ' '); *tmp++ = '\0'; + rcsdate = strchr(tmp, ' '); rcsdate++; + tmp = strrchr(rcsdate, ' '); *tmp = '\0'; + printk("Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate); + printk(" built %s %s\n", __DATE__, __TIME__); +} /* show_version */ + +__initfunc(int +cpc_init(void)) +{ + int i, j, devcount = 0; + + show_version(); + memset(&cpc_card, 0, (PC300_MAXCARDS * sizeof(pc300_t))); + if((cpc_nboards = cpc_detect()) == 0) { + printk("** No boards were found.\n"); + return -ENODEV; + } + + /* Fill in valid structures and invalidate the remaining */ + for (i = 0 ; i < PC300_MAXCARDS ; i++) { + pc300_t *card = &cpc_card[i]; + + if (card->hw.rambase != 0) { + for(j = 0; j < card->hw.nchan; j++) { + pc300ch_t *chan = &card->chan[j]; + pc300dev_t *d = &chan->d; + hdlc_device *hdlc; + struct device *dev; + + memset(chan, 0, sizeof(pc300ch_t)); + + chan->card = card; + chan->channel = j; + chan->conf.clkrate = 64000; + switch(card->hw.type) { + case PC300_TE: + chan->conf.media = LINE_T1; + chan->conf.lcode = PC300_LC_B8ZS; + chan->conf.fr_mode = PC300_FR_ESF; + chan->conf.lbo = PC300_LBO_0_DB; + chan->conf.rx_sens = PC300_RX_SENS_SH; + chan->conf.tslot_bitmap = 0xffffffffUL; + break; + + case PC300_X21: + chan->conf.media = LINE_X21; + break; + + case PC300_RSV: + default: + chan->conf.media = LINE_RS232; + break; + } + chan->tx_first_bd = 0; + chan->tx_next_bd = 0; + chan->rx_first_bd = 0; + chan->rx_last_bd = N_DMA_RX_BUF - 1; + + d->chan = chan; + d->tx_skb = NULL; + + d->hdlc = (hdlc_device *) + kmalloc(sizeof(hdlc_device), GFP_KERNEL); + if (d->hdlc == NULL) + continue; + memset(d->hdlc, 0, sizeof(hdlc_device)); + + hdlc = d->hdlc; + hdlc->open = cpc_open; + hdlc->close = cpc_close; + hdlc->ioctl = cpc_ioctl; + d->if_ptr = &hdlc->pppdev; + + dev = hdlc_to_dev(d->hdlc); + dev->mem_start = card->hw.ramphys; + dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1; + dev->irq = card->hw.irq; + dev->interrupt = 0; + dev->start = 0; + dev->tx_queue_len = PC300_TX_QUEUE_LEN; + dev->hard_start_xmit = cpc_queue_xmit; + dev->set_multicast_list = NULL; + dev->set_mac_address = NULL; + + if(register_hdlc_device(hdlc) == 0) { + dev->priv = d; /* We need 'priv', hdlc doesn't */ + printk("%s: PC300/", hdlc->name); + switch(card->hw.type) { + case PC300_TE: + printk("TE "); + break; + + case PC300_X21: + printk("X21"); + break; + + case PC300_RSV: + default: + printk("RSV"); + break; + } + printk(" #%d, %ldKB of RAM at 0x%lx, IRQ%d, channel %d.\n", + i + 1, card->hw.ramsize/1024, card->hw.ramphys, + card->hw.irq, j + 1); + devcount++; + } else { + *(d->name) = 0; + kfree(d->hdlc); + continue; + } + } + spin_lock_init(&card->card_lock); + } else { + memset(&card->hw, 0, sizeof (pc300hw_t)); + } + } + + return 0; +} + +#ifdef MODULE +int init_module (void) +{ + return (cpc_init()); +} /* init_module */ + +void cleanup_module (void) +{ + int i, j; + + for (i = 0 ; i < PC300_MAXCARDS ; i++) { + pc300_t *card = &cpc_card[i]; + + if (card->hw.rambase != 0) { + for(j = 0 ; j < card->hw.nchan ; j++) { + unregister_hdlc_device(card->chan[j].d.hdlc); + } + + iounmap((void *)card->hw.plxbase); + iounmap((void *)card->hw.scabase); + iounmap((void *)card->hw.rambase); + if (card->hw.type == PC300_TE) + iounmap((void *)card->hw.falcbase); + if (card->hw.irq) + free_irq(card->hw.irq, card); + } + } +} +#endif + diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 710e1d345c81..4f1e965853c4 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -1265,8 +1265,8 @@ static int rtl8129_rx(struct device *dev) } else { #if 1 /* USE_IP_COPYSUM */ eth_copy_and_sum(skb, &rx_ring[ring_offset + 4], - rx_size, 0); - skb_put(skb, rx_size); + rx_size - 4, 0); + skb_put(skb, rx_size - 4); #else memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4], rx_size); diff --git a/drivers/pci/oldproc.c b/drivers/pci/oldproc.c index 038d67ddc32a..ac43b28f9ebc 100644 --- a/drivers/pci/oldproc.c +++ b/drivers/pci/oldproc.c @@ -458,6 +458,10 @@ struct pci_dev_info dev_info[] = { DEVICE( CYCLADES, CYCLOM_8Y_Hi, "Cyclom-8Y above 1Mbyte"), DEVICE( CYCLADES, CYCLOM_Z_Lo, "Cyclades-Z below 1Mbyte"), DEVICE( CYCLADES, CYCLOM_Z_Hi, "Cyclades-Z above 1Mbyte"), + DEVICE( CYCLADES, PC300_RX_2, "PC300/RSV or /X21 (2 ports)"), + DEVICE( CYCLADES, PC300_RX_1, "PC300/RSV or /X21 (1 port)"), + DEVICE( CYCLADES, PC300_TE_2, "PC300/TE (2 ports)"), + DEVICE( CYCLADES, PC300_TE_1, "PC300/TE (1 port)"), DEVICE( ESSENTIAL, ESSENTIAL_ROADRUNNER,"Roadrunner serial HIPPI"), DEVICE( O2, O2_6832, "6832"), DEVICE( 3DFX, 3DFX_VOODOO, "Voodoo"), diff --git a/drivers/scsi/aic7xxx.c b/drivers/scsi/aic7xxx.c index 6ecde9a1524e..7e3969021131 100644 --- a/drivers/scsi/aic7xxx.c +++ b/drivers/scsi/aic7xxx.c @@ -270,7 +270,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = { 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -#define AIC7XXX_C_VERSION "5.1.28" +#define AIC7XXX_C_VERSION "5.1.30" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -576,7 +576,7 @@ static const char *board_names[] = { * AIC-7770 I/O range to reserve for a card */ #define MINREG 0xC00 -#define MAXREG 0xCBF +#define MAXREG 0xCFF #define INTDEF 0x5C /* Interrupt Definition Register */ @@ -1491,10 +1491,10 @@ aic_outb(struct aic7xxx_host *p, unsigned char val, long port) { outb(val, p->base + port); mb(); /* locked operation in order to force ordering */ - inb(p->base + HCNTRL); /* dummy read to flush the write */ } #else outb(val, p->base + port); + mb(); /* locked operation in order to force ordering */ #endif } @@ -1664,6 +1664,10 @@ pause_sequencer(struct aic7xxx_host *p) { ; } + if(p->features & AHC_ULTRA2) + { + aic_inb(p, CCSCBCTL); + } } /*+F************************************************************************* @@ -2133,7 +2137,7 @@ aic7xxx_find_syncrate(struct aic7xxx_host *p, unsigned int *period, * Use async transfers for this target */ *options = 0; - *period = 0; + *period = 255; syncrate = NULL; } return (syncrate); @@ -2901,6 +2905,7 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb) #define WIDE_INQUIRY_BITS 0x60 #define SYNC_INQUIRY_BITS 0x10 #define SCSI_VERSION_BITS 0x07 +#define SCSI_DT_BIT 0x04 if ( (buffer[7] & WIDE_INQUIRY_BITS) && (p->features & AHC_WIDE) ) { @@ -2919,61 +2924,66 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb) AHC_TRANS_CUR) ); unpause_sequencer(p, FALSE); } - if (buffer[7] & SYNC_INQUIRY_BITS) + if ( (buffer[7] & SYNC_INQUIRY_BITS) && + p->transinfo[tindex].user_offset ) { - p->needsdtr |= (1<needsdtr_copy |= (1<transinfo[tindex].goal_period = p->transinfo[tindex].user_period; p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options; - if (p->transinfo[tindex].user_offset) + if (p->features & AHC_ULTRA2) + p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2; + else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT) + p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT; + else + p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT; + if ( (((buffer[2] & SCSI_VERSION_BITS) == 3) || + (buffer[56] & SCSI_DT_BIT) || + (p->dev_flags[tindex] & DEVICE_SCSI_3) ) && + (p->transinfo[tindex].user_period <= 9) && + (p->transinfo[tindex].user_options) ) { - if (p->features & AHC_ULTRA2) - p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2; - else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT) - p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT; - else - p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT; + p->needppr |= (1<needppr_copy |= (1<needsdtr &= ~(1<needsdtr_copy &= ~(1<needwdtr &= ~(1<needwdtr_copy &= ~(1<dev_flags[tindex] |= DEVICE_SCSI_3; + } + else + { + p->needsdtr |= (1<needsdtr_copy |= (1<transinfo[tindex].goal_period = + MAX(10, p->transinfo[tindex].goal_period); + p->transinfo[tindex].goal_options = 0; } } else { p->needsdtr &= ~(1<needsdtr_copy &= ~(1<transinfo[tindex].goal_period = 0; + p->transinfo[tindex].goal_period = 255; p->transinfo[tindex].goal_offset = 0; p->transinfo[tindex].goal_options = 0; } - if ( (buffer[2] & SCSI_VERSION_BITS) == 3 ) + /* + * This is needed to work around a sequencer bug for now. Regardless + * of the controller in use, if we have a Quantum drive, we need to + * limit the speed to 80MByte/sec. As soon as I get a fixed version + * of the sequencer, this code will get yanked. + */ + if(!strncmp(buffer + 8, "QUANTUM", 7) && + p->transinfo[tindex].goal_options ) { - p->dev_flags[tindex] |= DEVICE_SCSI_3; - /* - * OK, we are a SCSI 3 device and we are in need of negotiation. - * Use PPR messages instead of WDTR and SDTR messages. - */ - if ( (p->needsdtr & (1<needwdtr & (1<needppr |= (1<needppr_copy |= (1<needwdtr &= ~(1<needwdtr_copy &= ~(1<needsdtr &= ~(1<needsdtr_copy &= ~(1<transinfo[tindex].goal_options ) - { - p->transinfo[tindex].goal_period = - MAX(p->transinfo[tindex].goal_period, 10); - p->transinfo[tindex].goal_options = 0; - } + p->transinfo[tindex].goal_period = + MAX(p->transinfo[tindex].goal_period, 10); + p->transinfo[tindex].goal_options = 0; + p->needppr &= ~(1<needppr_copy &= ~(1<needsdtr |= (1<needsdtr_copy |= (1<needwdtr |= (1<needwdtr_copy |= (1<flags & SCB_MSGOUT_BITS) != 0) @@ -4639,7 +4650,9 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) * As per the draft specs, any device capable of supporting any of * the option values other than 0 are not allowed to reject the * PPR message. Instead, they must negotiate out what they do - * support instead of rejecting our offering. + * support instead of rejecting our offering or else they cause + * a parity error during msg_out phase to signal that they don't + * like our settings. */ p->needppr &= ~target_mask; p->needppr_copy &= ~target_mask; @@ -4817,51 +4830,6 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) scb->sg_count = hscb->SG_segment_count = 1; scb->sg_length = sizeof(cmd->sense_buffer); scb->tag_action = 0; - /* - * This problem could be caused if the target has lost power - * or found some other way to loose the negotiation settings, - * so if needed, we'll re-negotiate while doing the sense cmd. - * However, if this SCB already was attempting to negotiate, - * then we assume this isn't the problem and skip this part. - */ - if ( (scb->cmd->cmnd[0] != TEST_UNIT_READY) && - (p->dev_flags[tindex] & DEVICE_SCANNED) && - !(p->dtr_pending & target_mask) ) - { - p->needppr |= (p->needppr_copy & target_mask); - p->needwdtr |= (p->needwdtr_copy & target_mask); - p->needsdtr |= (p->needsdtr_copy & target_mask); - } - else if ( scb->cmd == p->dev_dtr_cmnd[tindex] ) - { - /* - * This is already a negotiation command, so we must have - * already done PPR, WDTR or SDTR. Since our negotiation - * could have gotten rejected, we don't really know the - * full state of things. Don't do anything here, and allow - * the negotiation_complete() handler to do the right - * thing. - */ - - /* - * This is the important part though. We are getting sense - * info back from this device. It's going into a fake - * command. We need to put that into the real command - * instead so that the mid level SCSI code can act upon it. - * So, when we set up these fake commands, the next pointer - * is used to point to the real command. Use that to change - * the address of our sense_buffer[] to the real command. - * However, don't do this if the real command is also a - * TEST_UNIT_READY as it will most likely pull down its own - * SENSE information anyway. - */ - if (cmd->next->cmnd[0] != TEST_UNIT_READY) - { - scb->sg_list[0].address = - cpu_to_le32(VIRT_TO_BUS(&cmd->next->sense_buffer[0])); - hscb->data_pointer = scb->sg_list[0].address; - } - } scb->flags |= SCB_SENSE; /* * Ensure the target is busy since this will be an @@ -4884,7 +4852,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) aic7xxx_error(cmd) = DID_OK; break; } /* first time sense, no errors */ - aic7xxx_error(cmd) = DID_OK; + aic7xxx_error(cmd) = DID_ERROR; scb->flags &= ~SCB_SENSE; break; @@ -5135,51 +5103,14 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) } else if (scb->flags & SCB_MSGOUT_PPR) { - unsigned int max_sync, period; - unsigned char options = 0; - - if (p->features & AHC_ULTRA2) - { - if ( (aic_inb(p, SBLKCTL) & ENAB40) && - !(aic_inb(p, SSTAT2) & EXP_ACTIVE) ) - { - if( (p->features & AHC_ULTRA3) && - (p->dev_flags[tindex] & DEVICE_SCSI_3) && - (p->transinfo[tindex].goal_width == - MSG_EXT_WDTR_BUS_16_BIT) && - (p->transinfo[tindex].goal_options != 0) ) - { - max_sync = AHC_SYNCRATE_ULTRA3; - options = p->transinfo[tindex].goal_options; - } - else - { - max_sync = AHC_SYNCRATE_ULTRA2; - } - } - else - { - max_sync = AHC_SYNCRATE_ULTRA; - } - } - else if (p->features & AHC_ULTRA) - { - max_sync = AHC_SYNCRATE_ULTRA; - } - else - { - max_sync = AHC_SYNCRATE_FAST; - } - period = p->transinfo[tindex].goal_period; - aic7xxx_find_syncrate(p, &period, max_sync, &options); - p->transinfo[tindex].goal_period = period; - p->transinfo[tindex].goal_options = options; if (aic7xxx_verbose & VERBOSE_NEGOTIATION2) { printk(INFO_LEAD "Sending PPR (%d/%d/%d/%d) message.\n", - p->host_no, CTL_OF_SCB(scb), period, + p->host_no, CTL_OF_SCB(scb), + p->transinfo[tindex].goal_period, p->transinfo[tindex].goal_offset, - p->transinfo[tindex].goal_width, options); + p->transinfo[tindex].goal_width, + p->transinfo[tindex].goal_options); } aic7xxx_construct_ppr(p, scb); } @@ -5225,8 +5156,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) if (aic7xxx_verbose & VERBOSE_NEGOTIATION2) { printk(INFO_LEAD "Sending SDTR %d/%d message.\n", p->host_no, - CTL_OF_SCB(scb), - p->transinfo[tindex].goal_period, + CTL_OF_SCB(scb), period, p->transinfo[tindex].goal_offset); } aic7xxx_construct_sdtr(p, period, @@ -5339,7 +5269,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) resid_sgcnt = aic_inb(p, SCB_RESID_SGCNT); resid_dcnt = aic_inb(p, SCB_RESID_DCNT) | (aic_inb(p, SCB_RESID_DCNT + 1) << 8) | - (aic_inb(p, SCB_RESID_DCNT + 2) << 24); + (aic_inb(p, SCB_RESID_DCNT + 2) << 16); index = scb->sg_count - (resid_sgcnt + 1); native_addr = le32_to_cpu(scb->sg_list[index].address); native_length = le32_to_cpu(scb->sg_list[index].length); @@ -5347,7 +5277,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) * Make sure this is a valid sg_seg for the given pointer */ if(cur_addr < native_addr || - cur_addr > (native_addr + native_length)) + cur_addr > (native_addr + native_length + 1)) { printk(WARN_LEAD "invalid cur_addr:0x%x during WIDE_RESIDUE\n", p->host_no, CTL_OF_SCB(scb), cur_addr); @@ -5364,16 +5294,31 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) p->host_no, CTL_OF_SCB(scb), le32_to_cpu(scb->sg_list[index + 1].address), le32_to_cpu(scb->sg_list[index + 1].length)); + printk(WARN_LEAD " cur_address:0x%x resid_dcnt:0x%06x\n", + p->host_no, CTL_OF_SCB(scb), + cur_addr, resid_dcnt); break; } - /* - * If our current address matches the sg_seg->address then we - * have to back up the sg array to the previous segment and set - * it up to have only one byte of transfer left to go. - */ - if(cur_addr == native_addr) + if( (resid_sgcnt == 0) && + ((resid_dcnt == 0) || (resid_dcnt == 0xffffff))) { + /* + * We are at the end of the transfer and this is about a byte + * we ignored already (because the sequencer knew this was + * the last segment and set the adapter to ignore any wide + * residue bytes that might come through, which is only done + * on the last scatter gather segment of transfers). + */ + break; + } + else if(cur_addr == native_addr) + { + /* + * If our current address matches the sg_seg->address then we + * have to back up the sg array to the previous segment and set + * it up to have only one byte of transfer left to go. + */ if(index == 0) { printk(WARN_LEAD "bogus WIDE_RESIDUE message, no data has been " @@ -5403,39 +5348,6 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1); aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2); aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3); - /* - * The sequencer actually wants to find the new address and byte - * count in the SHCNT and SHADDR register sets. These registers - * are a shadow of the regular HCNT and HADDR registers. On the - * Ultra2 controllers, these registers are read only and the way - * we have to set their values is to put the values we want into - * the HCNT and HADDR registers and then output PRELOADEN into - * the DFCNTRL register which causes the card to latch the current - * values in the HADDR and HCNT registers and drop it through to - * the shadow registers. On older cards we copy them directly - * across by hand. - */ - if(p->features & AHC_ULTRA2) - { - aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL); - i=0; - udelay(1); - while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000)) - { - aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL); - udelay(1); - } - } - else - { - aic_outb(p, 1, STCNT); - aic_outb(p, 0, STCNT + 1); - aic_outb(p, 0, STCNT + 2); - aic_outb(p, cur_addr & 0xff, SHADDR); - aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1); - aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2); - aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3); - } } else { @@ -5455,28 +5367,46 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat) aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1); aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2); aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3); - if(p->features & AHC_ULTRA2) + } + /* + * The sequencer actually wants to find the new address and byte + * count in the SHCNT and SHADDR register sets. These registers + * are a shadow of the regular HCNT and HADDR registers. On the + * Ultra2 controllers, these registers are read only and the way + * we have to set their values is to put the values we want into + * the HCNT and HADDR registers and then output PRELOADEN into + * the DFCNTRL register which causes the card to latch the current + * values in the HADDR and HCNT registers and drop it through to + * the shadow registers. On older cards we copy them directly + * across by hand. + */ + if(p->features & AHC_ULTRA2) + { + aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL); + i=0; + udelay(1); + while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000)) { - aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL); - i=0; udelay(1); - while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000)) - { - aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL); - udelay(1); - } } - else + aic_outb(p, aic_inb(p, DMAPARAMS) & ~(SCSIEN|HDMAEN), DFCNTRL); + i=0; + udelay(1); + while(((aic_inb(p, DFCNTRL) & (SCSIEN|HDMAEN)) != 0) && (i++ < 1000)) { - aic_outb(p, resid_dcnt & 0xff, STCNT); - aic_outb(p, (resid_dcnt >> 8) & 0xff, STCNT + 1); - aic_outb(p, (resid_dcnt >> 16) & 0xff, STCNT + 2); - aic_outb(p, cur_addr & 0xff, SHADDR); - aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1); - aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2); - aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3); + udelay(1); } } + else + { + aic_outb(p, resid_dcnt & 0xff, STCNT); + aic_outb(p, (resid_dcnt >> 8) & 0xff, STCNT + 1); + aic_outb(p, (resid_dcnt >> 16) & 0xff, STCNT + 2); + aic_outb(p, cur_addr & 0xff, SHADDR); + aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1); + aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2); + aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3); + } } break; @@ -5885,6 +5815,7 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb) reply = TRUE; scb->flags &= ~SCB_MSGOUT_BITS; scb->flags |= SCB_MSGOUT_PPR; + p->dev_flags[tindex] |= DEVICE_SCSI_3; if (!(p->dev_flags[tindex] & DEVICE_SCANNED)) { /* @@ -5918,7 +5849,6 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb) p->transinfo[tindex].user_width; p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options; - p->needppr_copy |= target_mask; } if (aic7xxx_verbose & VERBOSE_NEGOTIATION2) { @@ -5952,6 +5882,25 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb) break; } } + if ( (p->transinfo[tindex].goal_period > 9) || + (p->transinfo[tindex].goal_options == 0) ) + { + scb->flags &= ~SCB_MSGOUT_BITS; + reject = TRUE; + reply = FALSE; + p->needppr &= ~(1 << tindex); + p->needppr_copy &= ~(1 << tindex); + if ( p->transinfo[tindex].goal_offset ) + { + p->needsdtr |= (1 << tindex); + p->needsdtr_copy |= (1 << tindex); + } + if ( p->transinfo[tindex].goal_width ) + { + p->needwdtr |= (1 << tindex); + p->needwdtr_copy |= (1 << tindex); + } + } } else { @@ -5959,7 +5908,7 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb) { default: { - reply = TRUE; + reject = TRUE; if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) && ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) || (aic7xxx_verbose > 0xffff)) ) @@ -5985,27 +5934,18 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb) } } - aic7xxx_set_width(p, target, channel, lun, bus_width, - AHC_TRANS_ACTIVE|AHC_TRANS_CUR); - syncrate = aic7xxx_find_syncrate(p, &period, maxsync, - &new_trans_options); - aic7xxx_validate_offset(p, syncrate, &offset, bus_width); - aic7xxx_set_syncrate(p, syncrate, target, channel, period, - offset, new_trans_options, - AHC_TRANS_ACTIVE|AHC_TRANS_CUR); - - if( (offset != saved_offset) || - (trans_options != new_trans_options) || - ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) != - (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) ) + if ( !reject ) { aic7xxx_set_width(p, target, channel, lun, bus_width, - AHC_TRANS_GOAL|AHC_TRANS_QUITE); + AHC_TRANS_ACTIVE|AHC_TRANS_CUR); + syncrate = aic7xxx_find_syncrate(p, &period, maxsync, + &new_trans_options); + aic7xxx_validate_offset(p, syncrate, &offset, bus_width); aic7xxx_set_syncrate(p, syncrate, target, channel, period, offset, new_trans_options, - AHC_TRANS_GOAL|AHC_TRANS_QUITE); - reply = TRUE; + AHC_TRANS_ACTIVE|AHC_TRANS_CUR); } + p->dtr_pending &= ~target_mask; p->needppr &= ~target_mask; if(reply) @@ -6411,20 +6351,14 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat) /* * Keep the sequencer from trying to restart any selections */ - aic_outb(p, 0, SCSISEQ); + aic_outb(p, aic_inb(p, SCSISEQ) & ~ENSELO, SCSISEQ); /* * Make sure the data bits on the bus are released + * Don't do this on 7770 chipsets, it makes them give us + * a BRKADDRINT and kills the card. */ - if(p->features & AHC_WIDE) - aic_outb(p, 0, SCSIBUSH); - aic_outb(p, 0, SCSIBUSL); - /* - * Clear the target id bit from the SCSI bus - */ - if(p->features & AHC_ULTRA2) - aic_outb(p, aic_inb(p, SCSIID_ULTRA2) & 0x0f, SCSIID_ULTRA2); - else - aic_outb(p, aic_inb(p, SCSIID) & 0x0f, SCSIID); + if( (p->chip & ~AHC_CHIPID_MASK) == AHC_PCI ) + aic_outb(p, 0, SCSIBUSL); /* * Delay for the selection timeout delay period then stop the selection @@ -6507,7 +6441,9 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat) * A parity error has occurred during a data * transfer phase. Flag it and continue. */ - if( (aic_inb(p, SCSIRATE) & AHC_SYNCRATE_CRC) && (lastphase == P_DATAIN) ) + if( (p->features & AHC_ULTRA3) && + (aic_inb(p, SCSIRATE) & AHC_SYNCRATE_CRC) && + (lastphase == P_DATAIN) ) { printk(WARN_LEAD "CRC error during %s phase.\n", p->host_no, CTL_OF_SCB(scb), phase); @@ -6532,13 +6468,50 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat) p->host_no, CTL_OF_SCB(scb)); } } - else + else if( (lastphase == P_MESGOUT) && + (cmd == p->dev_dtr_cmnd[tindex]) && + (scb->flags & SCB_MSGOUT_PPR) ) { - printk(WARN_LEAD "Parity error during %s phase.\n", - p->host_no, CTL_OF_SCB(scb), phase); + /* + * As per the draft specs, any device capable of supporting any of + * the option values other than 0 are not allowed to reject the + * PPR message. Instead, they must negotiate out what they do + * support instead of rejecting our offering or else they cause + * a parity error during msg_out phase to signal that they don't + * like our settings. + */ + p->needppr &= ~(1 << tindex); + p->needppr_copy &= ~(1 << tindex); + aic7xxx_set_width(p, scb->cmd->target, scb->cmd->channel, scb->cmd->lun, + MSG_EXT_WDTR_BUS_8_BIT, + (AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE)); + aic7xxx_set_syncrate(p, NULL, scb->cmd->target, scb->cmd->channel, 0, 0, + 0, AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE); + p->transinfo[tindex].goal_options = 0; + p->dtr_pending &= ~(1 << tindex); + scb->flags &= ~SCB_MSGOUT_BITS; + if(aic7xxx_verbose & VERBOSE_NEGOTIATION2) + { + printk(INFO_LEAD "parity error during PPR message, reverting " + "to WDTR/SDTR\n", p->host_no, CTL_OF_SCB(scb)); + } + if ( p->transinfo[tindex].goal_width ) + { + p->needwdtr |= (1 << tindex); + p->needwdtr_copy |= (1 << tindex); + } + if ( p->transinfo[tindex].goal_offset ) + { + if( p->transinfo[tindex].goal_period <= 9 ) + { + p->transinfo[tindex].goal_period = 10; + } + p->needsdtr |= (1 << tindex); + p->needsdtr_copy |= (1 << tindex); + } + scb = NULL; } - - if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR) + else if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR) { struct aic7xxx_syncrate *syncrate; unsigned int period = p->transinfo[tindex].cur_period; @@ -6550,6 +6523,8 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat) * instead of slowing down if those exist. That's hard to do with simple * checksums though. */ + printk(WARN_LEAD "Parity error during %s phase.\n", + p->host_no, CTL_OF_SCB(scb), phase); if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL) { syncrate++; @@ -6557,20 +6532,59 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat) (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) ) { p->transinfo[tindex].goal_period = syncrate->period; - if( !(syncrate->sxfr_ultra2 & 0x40) ) + if( p->transinfo[tindex].goal_period > 9 ) { p->transinfo[tindex].goal_options = 0; + p->needppr &= ~(1<needsdtr |= (1<needppr_copy &= ~(1<needsdtr_copy |= (1<transinfo[tindex].goal_width) + { + p->needwdtr |= (1<needwdtr_copy |= (1<transinfo[tindex].goal_width) + { + p->transinfo[tindex].goal_width = 0; + p->needwdtr &= ~(1<needwdtr_copy &= ~(1<transinfo[tindex].goal_offset = + p->transinfo[tindex].user_offset; + p->transinfo[tindex].goal_period = + p->transinfo[tindex].user_period; + p->transinfo[tindex].goal_options = + p->transinfo[tindex].user_options; + if( p->transinfo[tindex].goal_period <= 9 ) + { + p->needppr |= (1<needsdtr &= ~(1<needppr_copy |= (1<needsdtr_copy &= ~(1<needppr &= ~(1<needsdtr |= (1<needppr_copy &= ~(1<needsdtr_copy |= (1<transinfo[tindex].goal_offset = 0; - p->transinfo[tindex].goal_period = 0; + p->transinfo[tindex].goal_period = 255; p->transinfo[tindex].goal_options = 0; + p->transinfo[tindex].goal_width = 0; + p->needppr &= ~(1<needsdtr &= ~(1<needwdtr &= ~(1<needppr_copy &= ~(1<needsdtr_copy &= ~(1<needwdtr_copy &= ~(1<needppr |= (p->needppr_copy & (1<needsdtr |= (p->needsdtr_copy & (1<needwdtr |= (p->needwdtr_copy & (1<dev_flags[tindex] &= ~DEVICE_PARITY_ERROR; } @@ -6588,6 +6602,7 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat) if (mesg_out != MSG_NOOP) { aic_outb(p, mesg_out, MSG_OUT); + aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO); scb = NULL; } aic_outb(p, CLRSCSIPERR, CLRSINT1); @@ -6779,7 +6794,7 @@ aic7xxx_handle_command_completion_intr(struct aic7xxx_host *p) { struct aic7xxx_scb *scb = NULL; Scsi_Cmnd *cmd; - unsigned char scb_index; + unsigned char scb_index, tindex; #ifdef AIC7XXX_VERBOSE_DEBUGGING if( (p->isr_count < 16) && (aic7xxx_verbose > 0xffff) ) @@ -6805,23 +6820,21 @@ aic7xxx_handle_command_completion_intr(struct aic7xxx_host *p) scb_index = p->qoutfifo[p->qoutfifonext]; p->qoutfifo[p->qoutfifonext++] = SCB_LIST_NULL; if ( scb_index >= p->scb_data->numscbs ) - scb = NULL; - else - scb = p->scb_data->scb_array[scb_index]; - if (scb == NULL) { printk(WARN_LEAD "CMDCMPLT with invalid SCB index %d\n", p->host_no, -1, -1, -1, scb_index); continue; } - else if (!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL)) + scb = p->scb_data->scb_array[scb_index]; + if (!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL)) { printk(WARN_LEAD "CMDCMPLT without command for SCB %d, SCB flags " "0x%x, cmd 0x%lx\n", p->host_no, -1, -1, -1, scb_index, scb->flags, (unsigned long) scb->cmd); continue; } - else if (scb->flags & SCB_QUEUED_ABORT) + tindex = TARGET_INDEX(scb->cmd); + if (scb->flags & SCB_QUEUED_ABORT) { pause_sequencer(p); if ( ((aic_inb(p, LASTPHASE) & PHASE_MASK) != P_BUSFREE) && @@ -6844,6 +6857,43 @@ aic7xxx_handle_command_completion_intr(struct aic7xxx_host *p) */ scb->flags &= ~(SCB_ABORT|SCB_RESET); } + else if (scb->flags & SCB_SENSE) + { + char *buffer = &scb->cmd->sense_buffer[0]; + if (scb->cmd == p->dev_dtr_cmnd[tindex]) + { + struct aic7xxx_scb *old_scb; + /* + * We have valid sense data, send it back immediately. + */ + old_scb = p->scb_data->scb_array[scb->cmd->next->tag]; + *old_scb->cmd->sense_buffer = *scb->cmd->sense_buffer; + old_scb->hscb->target_status = scb->hscb->target_status; + old_scb->cmd->result = scb->hscb->target_status; + old_scb->cmd->result |= (DID_ERROR << 16); + aic7xxx_status(old_scb->cmd) = scb->hscb->target_status; + scbq_remove(&p->waiting_scbs, old_scb); + scbq_remove(&p->delayed_scbs[tindex], old_scb); + scb->cmd->next = NULL; + aic7xxx_done(p, scb); + aic7xxx_done(p, old_scb); + continue; + } + else if (buffer[12] == 0x47 || buffer[12] == 0x54) + { + /* + * SCSI errors, run domain validation and re-run negotiation + */ + p->needdv |= (1<needppr |= (p->needppr_copy & (1<needsdtr |= (p->needsdtr_copy & (1<needwdtr |= (p->needwdtr_copy & (1<hscb->target_status)) { case QUEUE_FULL: @@ -6973,6 +7023,13 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs) if (intstat & SEQINT) { + /* + * Read the CCSCBCTL register to work around a bug in the Ultra2 cards + */ + if(p->features & AHC_ULTRA2) + { + aic_inb(p, CCSCBCTL); + } aic7xxx_handle_seqint(p, intstat); } @@ -7055,7 +7112,7 @@ do_aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs) * with queue depths for individual devices. It also allows tagged * queueing to be [en|dis]abled for a specific adapter. *-F*************************************************************************/ -static void +static int aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device) { int default_depth = 3; @@ -7065,6 +7122,14 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device) tindex = device->id | (device->channel << 3); target_mask = (1 << tindex); + if (p->dev_max_queue_depth[tindex] > 1) + { + /* + * We've already scanned this device, leave it alone + */ + return(p->dev_max_queue_depth[tindex]); + } + device->queue_depth = default_depth; p->dev_temp_queue_depth[tindex] = 1; p->dev_max_queue_depth[tindex] = 1; @@ -7133,6 +7198,7 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device) } } } + return(p->dev_max_queue_depth[tindex]); } /*+F************************************************************************* @@ -7160,8 +7226,7 @@ aic7xxx_select_queue_depth(struct Scsi_Host *host, { if (device->host == host) { - aic7xxx_device_queue_depth(p, device); - scbnum += device->queue_depth; + scbnum += aic7xxx_device_queue_depth(p, device); } } while (scbnum > p->scb_data->numscbs) @@ -8371,23 +8436,8 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p, } aic_outb(p, 0, SEQ_FLAGS); - /* - * We are starting to do real work on the card....it's possible we could - * generate some spurious interrupts at this point, especially in the - * event of a PCI error or some such. If there are other devices already - * registered on the same interrupt as us, this could cause the machine - * to lock up. So, we disable the interrupt this card is on until we - * finish our card setup. We only need to do this for modules, if we are - * compiled into the kernel then interrupts are already off during this - * part of the code. - */ -#ifdef MODULE - disable_irq(p->irq); -#endif - detect_maxscb(p); - printk("%d/%d SCBs\n", p->scb_data->maxhscbs, p->scb_data->maxscbs); if (aic7xxx_verbose & VERBOSE_PROBE2) { @@ -8616,9 +8666,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p, printk("(scsi%d) Unable to allocate hardware SCB array; " "failing detection.\n", p->host_no); aic_outb(p, 0, SIMODE1); -#ifdef MODULE - enable_irq(p->irq); -#endif p->irq = 0; return(0); } @@ -8796,9 +8843,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p, printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring " "controller.\n", p->host_no, p->irq); aic_outb(p, 0, SIMODE1); -#ifdef MODULE - enable_irq(p->irq); -#endif p->irq = 0; return (0); } @@ -8808,10 +8852,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p, p->host_no, -1, -1 , -1); aic7xxx_clear_intstat(p); -#ifdef MODULE - enable_irq(p->irq); -#endif - unpause_sequencer(p, /* unpause_always */ TRUE); return (found); @@ -8920,7 +8960,7 @@ aic7xxx_alloc(Scsi_Host_Template *sht, struct aic7xxx_host *temp) p->orderedtag = 0; for (i=0; itransinfo[i].goal_period = 0; + p->transinfo[i].goal_period = 255; p->transinfo[i].goal_offset = 0; p->transinfo[i].goal_options = 0; p->transinfo[i].goal_width = MSG_EXT_WDTR_BUS_8_BIT; @@ -9709,7 +9749,8 @@ aic7xxx_detect(Scsi_Host_Template *template) { if ( ((current_p->pci_bus == temp_p->pci_bus) && (current_p->pci_device_fn == temp_p->pci_device_fn)) || - (current_p->base == temp_p->base) ) + (temp_p->base && (current_p->base == temp_p->base)) || + (temp_p->mbase && (current_p->mbase == temp_p->mbase)) ) { /* duplicate PCI entry, skip it */ kfree(temp_p); @@ -9769,7 +9810,8 @@ aic7xxx_detect(Scsi_Host_Template *template) { if ( ((current_p->pci_bus == temp_p->pci_bus) && (current_p->pci_device_fn == temp_p->pci_device_fn)) || - (current_p->base == temp_p->base) ) + (temp_p->base && (current_p->base == temp_p->base)) || + (temp_p->mbase && (current_p->mbase == temp_p->mbase)) ) { /* duplicate PCI entry, skip it */ kfree(temp_p); @@ -9812,7 +9854,7 @@ aic7xxx_detect(Scsi_Host_Template *template) #endif /* AIC7XXX_STRICT_PCI_SETUP */ #endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */ - if(check_region(temp_p->base, MAXREG - MINREG)) + if(temp_p->base && check_region(temp_p->base, MAXREG - MINREG)) { printk("aic7xxx: <%s> at PCI %d/%d/%d\n", board_names[aic_pdevs[i].board_name_index], @@ -9843,7 +9885,7 @@ aic7xxx_detect(Scsi_Host_Template *template) } #ifdef MMAPIO - if ( !(temp_p->flags & AHC_MULTI_CHANNEL) || + if ( !(temp_p->base) || !(temp_p->flags & AHC_MULTI_CHANNEL) || ((temp_p->chip != (AHC_AIC7870 | AHC_PCI)) && (temp_p->chip != (AHC_AIC7880 | AHC_PCI))) ) { @@ -9881,6 +9923,18 @@ aic7xxx_detect(Scsi_Host_Template *template) vfree((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK)); #endif temp_p->maddr = 0; + if(temp_p->base == 0) + { + printk("aic7xxx: <%s> at PCI %d/%d/%d\n", + board_names[aic_pdevs[i].board_name_index], + temp_p->pci_bus, + PCI_SLOT(temp_p->pci_device_fn), + PCI_FUNC(temp_p->pci_device_fn)); + printk("aic7xxx: Controller disabled by BIOS, ignoring.\n"); + kfree(temp_p); + temp_p = NULL; + continue; + } } } } @@ -9889,7 +9943,8 @@ aic7xxx_detect(Scsi_Host_Template *template) /* * Lock out other contenders for our i/o space. */ - request_region(temp_p->base, MAXREG - MINREG, "aic7xxx"); + if(temp_p->base) + request_region(temp_p->base, MAXREG - MINREG, "aic7xxx"); /* * We HAVE to make sure the first pause_sequencer() and all other @@ -10801,20 +10856,59 @@ aic7xxx_negotiation_complete(Scsi_Cmnd *cmd) (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) ) { p->transinfo[tindex].goal_period = syncrate->period; - if( !(syncrate->sxfr_ultra2 & 0x40) ) + if( p->transinfo[tindex].goal_period > 9 ) { p->transinfo[tindex].goal_options = 0; + p->needppr &= ~(1<needsdtr |= (1<needppr_copy &= ~(1<needsdtr_copy |= (1<transinfo[tindex].goal_width) + { + p->needwdtr |= (1<needwdtr_copy |= (1<transinfo[tindex].goal_width) + { + p->transinfo[tindex].goal_width = 0; + p->needwdtr &= ~(1<needwdtr_copy &= ~(1<transinfo[tindex].goal_offset = + p->transinfo[tindex].user_offset; + p->transinfo[tindex].goal_period = + p->transinfo[tindex].user_period; + p->transinfo[tindex].goal_options = + p->transinfo[tindex].user_options; + if( p->transinfo[tindex].goal_period <= 9 ) + { + p->needppr |= (1<needsdtr &= ~(1<needppr_copy |= (1<needsdtr_copy &= ~(1<needppr &= ~(1<needsdtr |= (1<needppr_copy &= ~(1<needsdtr_copy |= (1<transinfo[tindex].goal_offset = 0; - p->transinfo[tindex].goal_period = 0; + p->transinfo[tindex].goal_period = 255; p->transinfo[tindex].goal_options = 0; + p->transinfo[tindex].goal_width = 0; + p->needppr &= ~(1<needsdtr &= ~(1<needwdtr &= ~(1<needppr_copy &= ~(1<needsdtr_copy &= ~(1<needwdtr_copy &= ~(1<needppr |= (p->needppr_copy & (1<needsdtr |= (p->needsdtr_copy & (1<needwdtr |= (p->needwdtr_copy & (1<needdv &= ~(1<next entry so that the real SCSI command + * can be sent back to the mid layer code with SENSE data intact. We'll + * finish things up when the cmd gets sent back down to us, so no worries. */ - aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex); + if(cmd->next) + { + aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex); + } return; } @@ -10988,13 +11090,13 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd, */ hscb->control = 0; scb->tag_action = 0; + cmd->tag = hscb->tag; if (p->discenable & mask) { hscb->control |= DISCENB; if ( (p->tagenable & mask) && (cmd->cmnd[0] != TEST_UNIT_READY) ) { - cmd->tag = hscb->tag; p->dev_commands_sent[tindex]++; if (p->dev_commands_sent[tindex] < 200) { @@ -12275,7 +12377,8 @@ aic7xxx_release(struct Scsi_Host *host) if(p->irq) free_irq(p->irq, p); - release_region(p->base, MAXREG - MINREG); + if(p->base) + release_region(p->base, MAXREG - MINREG); #ifdef MMAPIO if(p->maddr) { diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq index 248e8ee383ae..023ebbf41638 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.seq +++ b/drivers/scsi/aic7xxx/aic7xxx.seq @@ -60,11 +60,7 @@ reset: clr SCSISIGO; /* De-assert BSY */ and SXFRCTL1, ~BITBUCKET; /* Always allow reselection */ - if ((p->flags & AHC_TARGETMODE) != 0) { - mvi SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP; - } else { - mvi SCSISEQ, ENRSELI|ENAUTOATNP; - } + mvi SCSISEQ, ENRSELI|ENAUTOATNP; if ((p->features & AHC_CMD_CHAN) != 0) { /* Ensure that no DMA operations are in progress */ @@ -236,118 +232,6 @@ ndx_dtr_2: selection: test SSTAT0,SELDO jnz select_out; -select_in: - if ((p->flags & AHC_TARGETMODE) != 0) { - test SSTAT0, TARGET jz initiator_reselect; - /* - * We've just been selected. Assert BSY and - * setup the phase for receiving the messages - * from the target. - */ - mvi SCSISIGO, P_MESGOUT|BSYO; - mvi CLRSINT0, CLRSELDO; - - /* - * If ATN isn't asserted, go directly to bus free. - */ - test SCSISIGI, ATNI jz target_busfree; - - /* - * Setup the DMA for sending the identify and - * command information. - */ - mov A, TMODE_CMDADDR_NEXT; - mvi DINDEX, HADDR; - mvi TMODE_CMDADDR call set_32byte_addr; - mvi DFCNTRL, FIFORESET; - - clr SINDEX; - /* Watch ATN closely now */ -message_loop: - or SXFRCTL0, SPIOEN; - test SSTAT0, SPIORDY jz .; - and SXFRCTL0, ~SPIOEN; - mov DINDEX, SCSIDATL; - mov DFDAT, DINDEX; - inc SINDEX; - - /* Message Testing... */ - test DINDEX, MSG_IDENTIFYFLAG jz . + 2; - mov ARG_1, DINDEX; - - test SCSISIGI, ATNI jnz message_loop; - add A, -4, SINDEX; - jc target_cmdphase; - mvi DFDAT, SCB_LIST_NULL; /* Terminate the message list */ - -target_cmdphase: - add HCNT[0], 1, A; - clr HCNT[1]; - clr HCNT[2]; - mvi SCSISIGO, P_COMMAND|BSYO; - or SXFRCTL0, SPIOEN; - test SSTAT0, SPIORDY jz .; - mov A, SCSIDATL; - mov DFDAT, A; /* Store for host */ - - /* - * Determine the number of bytes to read - * based on the command group code. Count is - * one less than the total since we've already - * fetched the first byte. - */ - clr SINDEX; - shr A, CMD_GROUP_CODE_SHIFT; - add SEQADDR0, A; - - add SINDEX, CMD_GROUP0_BYTE_DELTA; - nop; /* Group 1 and 2 are the same */ - add SINDEX, CMD_GROUP2_BYTE_DELTA; - nop; /* Group 3 is reserved */ - add SINDEX, CMD_GROUP4_BYTE_DELTA; - add SINDEX, CMD_GROUP5_BYTE_DELTA; - /* Group 6 and 7 are not handled yet */ - - mov A, SINDEX; - add HCNT[0], A; - -command_loop: - test SSTAT0, SPIORDY jz .; - cmp SINDEX, 1 jne . + 2; - and SXFRCTL0, ~SPIOEN; /* Last Byte */ - mov DFDAT, SCSIDATL; - dec SINDEX; - test SINDEX, 0xFF jnz command_loop; - - or DFCNTRL, HDMAEN|FIFOFLUSH; - - call dma_finish; - - test ARG_1, MSG_IDENTIFY_DISCFLAG jz selectin_post; - - mvi SCSISIGO, P_MESGIN|BSYO; - - or SXFRCTL0, SPIOEN; - - mvi MSG_DISCONNECT call target_outb; - -selectin_post: - inc TMODE_CMDADDR_NEXT; - cmp TMODE_CMDADDR_NEXT, TMODE_NUMCMDS jne . + 2; - clr TMODE_CMDADDR_NEXT; - mvi QOUTFIFO, SCB_LIST_NULL; - mvi INTSTAT,CMDCMPLT; - - test ARG_1, MSG_IDENTIFY_DISCFLAG jnz target_busfree; - - /* Busy loop on something then go to data or status phase */ - -target_busfree: - clr SCSISIGO; - jmp poll_for_work; - - } - /* * Reselection has been initiated by a target. Make a note that we've been * reselected, but haven't seen an IDENTIFY message from the target yet. @@ -453,14 +337,14 @@ clear_target_state: * STCNT may have been cleared, so restore it from the residual field. */ data_phase_reinit: - if ((p->features & AHC_CMD_CHAN) != 0) { - if ((p->features & AHC_ULTRA2) != 0) { - bmov HADDR, SHADDR, 4; - bmov HCNT, SCB_RESID_DCNT, 3; - } else { - bmov STCNT, SCB_RESID_DCNT, 3; - } - } else { + if ((p->features & AHC_ULTRA2) != 0) { + bmov HADDR, SHADDR, 4; + bmov HCNT, SCB_RESID_DCNT, 3; + } + if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { + bmov STCNT, SCB_RESID_DCNT, 3; + } + if ((p->features & AHC_CMD_CHAN) == 0) { mvi DINDEX, STCNT; mvi SCB_RESID_DCNT call bcopy_3; } @@ -687,10 +571,13 @@ ultra2_dmafifoflush: test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; test DFSTATUS, MREQPEND jnz .; ultra2_dmahalt: - and DFCNTRL, ~HDMAEN; - test DFCNTRL, HDMAEN jnz .; - and DFCNTRL, ~SCSIEN; - test DFCNTRL, SCSIEN jnz .; + test SCSIOFFSET, 0x7f jnz ultra2_shutdown; +ultra2_await_nreq: + test SCSISIGI, REQI jz ultra2_shutdown; + test SSTAT1, PHASEMIS jz ultra2_await_nreq; +ultra2_shutdown: + and DFCNTRL, ~(HDMAEN|SCSIEN); + test DFCNTRL, (HDMAEN|SCSIEN) jnz .; bmov SCB_RESID_DCNT, STCNT, 3; mov SCB_RESID_SGCNT, SG_COUNT; or SXFRCTL0, CLRSTCNT|CLRCHN; @@ -729,10 +616,11 @@ p_command_dma_loop: test SSTAT0, SDONE jnz p_command_ultra2_dma_done; test SSTAT1,PHASEMIS jz p_command_dma_loop; /* ie. underrun */ p_command_ultra2_dma_done: - and DFCNTRL, ~HDMAEN; - test DFCNTRL, HDMAEN jnz .; - and DFCNTRL, ~SCSIEN; - test DFCNTRL, SCSIEN jnz .; + test SCSISIGI, REQI jz p_command_ultra2_shutdown; + test SSTAT1, PHASEMIS jz p_command_ultra2_dma_done; +p_command_ultra2_shutdown: + and DFCNTRL, ~(HDMAEN|SCSIEN); + test DFCNTRL, (HDMAEN|SCSIEN) jnz .; or SXFRCTL0, CLRSTCNT|CLRCHN; } jmp ITloop; @@ -1078,23 +966,13 @@ mesgin_reject: mesgin_wide_residue: mvi ARG_1 call inb_next; /* ACK the wide_residue and get */ /* the size byte */ -/* - * See if we'll ignore this wide residue (because it's an overrun byte) - */ - test SCB_RESID_SGCNT,0xff jnz wide_residue_int; - test SCB_RESID_DCNT[0],0xff jnz wide_residue_int; - test SCB_RESID_DCNT[1],0xff jnz wide_residue_int; - test SCB_RESID_DCNT[2],0xff jnz wide_residue_int; - jmp mesgin_done; - -wide_residue_int: /* * In order for this to be reliable, we have to do all sorts of horrible * magic in terms of resetting the datafifo and reloading the shadow layer * with the correct new values (so that a subsequent save data pointers * message will do the right thing). We let the kernel do that work. */ - mvi INTSTAT,WIDE_RESIDUE; + mvi INTSTAT, WIDE_RESIDUE; jmp mesgin_done; /* @@ -1143,17 +1021,6 @@ inb_first: inb_last: mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/ -if ((p->flags & AHC_TARGETMODE) != 0) { - /* - * Send a byte to an initiator in Automatic PIO mode. - * SPIOEN must be on prior to calling this routine. - */ -target_outb: - mov SCSIDATL, SINDEX; - test SSTAT0, SPIORDY jz .; - ret; -} - mesgin_phasemis: /* * We expected to receive another byte, but the target changed phase @@ -1198,6 +1065,12 @@ dma_fifoempty: * actually off first lest we get an ILLSADDR. */ dma_dmadone: + cmp LASTPHASE, P_COMMAND je dma_await_nreq; + test SCSIRATE, 0x0f jnz dma_shutdown; +dma_await_nreq: + test SCSISIGI, REQI jz dma_shutdown; + test SSTAT1, PHASEMIS jz dma_await_nreq; +dma_shutdown: and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN); dma_halt: /* diff --git a/drivers/scsi/aic7xxx_seq.c b/drivers/scsi/aic7xxx_seq.c index 343f29f79065..c1b92913a881 100644 --- a/drivers/scsi/aic7xxx_seq.c +++ b/drivers/scsi/aic7xxx_seq.c @@ -4,34 +4,33 @@ static unsigned char seqprog[] = { 0xff, 0x6a, 0x06, 0x08, 0x7f, 0x02, 0x04, 0x08, - 0x32, 0x6a, 0x00, 0x00, 0x12, 0x6a, 0x00, 0x00, 0xff, 0x6a, 0xd6, 0x09, 0xff, 0x6a, 0xdc, 0x09, - 0x00, 0x65, 0x44, 0x59, + 0x00, 0x65, 0xca, 0x58, 0xf7, 0x01, 0x02, 0x08, 0xff, 0x4e, 0xc8, 0x08, 0xbf, 0x60, 0xc0, 0x08, - 0x60, 0x0b, 0x88, 0x68, - 0x40, 0x00, 0x0e, 0x68, + 0x60, 0x0b, 0x86, 0x68, + 0x40, 0x00, 0x0c, 0x68, 0x08, 0x1f, 0x3e, 0x10, - 0x60, 0x0b, 0x88, 0x68, - 0x40, 0x00, 0x0e, 0x68, + 0x60, 0x0b, 0x86, 0x68, + 0x40, 0x00, 0x0c, 0x68, 0x08, 0x1f, 0x3e, 0x10, - 0xff, 0x3e, 0x4a, 0x60, - 0x40, 0xfa, 0x12, 0x78, + 0xff, 0x3e, 0x48, 0x60, + 0x40, 0xfa, 0x10, 0x78, 0xff, 0xf6, 0xd4, 0x08, 0x01, 0x4e, 0x9c, 0x18, 0x40, 0x60, 0xc0, 0x00, - 0x00, 0x4d, 0x12, 0x70, + 0x00, 0x4d, 0x10, 0x70, 0x01, 0x4e, 0x9c, 0x18, 0xbf, 0x60, 0xc0, 0x08, - 0x00, 0x6a, 0xbe, 0x5c, + 0x00, 0x6a, 0x3e, 0x5c, 0xff, 0x4e, 0xc8, 0x18, - 0x02, 0x6a, 0xd4, 0x5b, + 0x02, 0x6a, 0x54, 0x5b, 0xff, 0x52, 0x20, 0x09, 0x0d, 0x6a, 0x6a, 0x00, - 0x00, 0x52, 0x4a, 0x5c, + 0x00, 0x52, 0xca, 0x5b, 0x03, 0xb0, 0x52, 0x31, 0xff, 0xb0, 0x52, 0x09, 0xff, 0xb1, 0x54, 0x09, @@ -40,8 +39,8 @@ static unsigned char seqprog[] = { 0xff, 0x3e, 0x74, 0x09, 0xff, 0x90, 0x7c, 0x08, 0xff, 0x3e, 0x20, 0x09, - 0x00, 0x65, 0x50, 0x58, - 0x00, 0x65, 0x0e, 0x40, + 0x00, 0x65, 0x4e, 0x58, + 0x00, 0x65, 0x0c, 0x40, 0xf7, 0x1f, 0xca, 0x08, 0x08, 0xa1, 0xc8, 0x08, 0x00, 0x65, 0xca, 0x00, @@ -56,88 +55,28 @@ static unsigned char seqprog[] = { 0x5a, 0x6a, 0x00, 0x04, 0x12, 0x65, 0x02, 0x00, 0x31, 0x6a, 0xca, 0x00, - 0x80, 0x37, 0x70, 0x68, + 0x80, 0x37, 0x6e, 0x68, 0xff, 0x65, 0xca, 0x18, 0xff, 0x37, 0xdc, 0x08, 0xff, 0x6e, 0xc8, 0x08, - 0x00, 0x6c, 0x78, 0x78, + 0x00, 0x6c, 0x76, 0x78, 0x20, 0x01, 0x02, 0x00, 0x4c, 0x37, 0xc8, 0x28, - 0x08, 0x1f, 0x80, 0x78, + 0x08, 0x1f, 0x7e, 0x78, 0x08, 0x37, 0x6e, 0x00, 0x08, 0x64, 0xc8, 0x00, 0x70, 0x64, 0xca, 0x18, 0xff, 0x6c, 0x0a, 0x08, 0x20, 0x64, 0xca, 0x18, 0xff, 0x6c, 0x08, 0x0c, - 0x40, 0x0b, 0x10, 0x69, - 0x80, 0x0b, 0x02, 0x79, - 0xa4, 0x6a, 0x06, 0x00, - 0x40, 0x6a, 0x16, 0x00, - 0x10, 0x03, 0xfe, 0x78, - 0xff, 0x50, 0xc8, 0x08, - 0x88, 0x6a, 0xcc, 0x00, - 0x49, 0x6a, 0x3a, 0x5c, - 0x01, 0x6a, 0x26, 0x01, - 0xff, 0x6a, 0xca, 0x08, - 0x08, 0x01, 0x02, 0x00, - 0x02, 0x0b, 0x9e, 0x78, - 0xf7, 0x01, 0x02, 0x08, - 0xff, 0x06, 0xcc, 0x08, - 0xff, 0x66, 0x32, 0x09, - 0x01, 0x65, 0xca, 0x18, - 0x80, 0x66, 0xac, 0x78, - 0xff, 0x66, 0xa2, 0x08, - 0x10, 0x03, 0x9c, 0x68, - 0xfc, 0x65, 0xc8, 0x18, - 0x00, 0x65, 0xb4, 0x48, - 0xff, 0x6a, 0x32, 0x01, - 0x01, 0x64, 0x18, 0x19, - 0xff, 0x6a, 0x1a, 0x09, - 0xff, 0x6a, 0x1c, 0x09, - 0x84, 0x6a, 0x06, 0x00, - 0x08, 0x01, 0x02, 0x00, - 0x02, 0x0b, 0xbe, 0x78, - 0xff, 0x06, 0xc8, 0x08, - 0xff, 0x64, 0x32, 0x09, - 0xff, 0x6a, 0xca, 0x08, - 0x5b, 0x64, 0xc8, 0x28, - 0x00, 0x62, 0xc4, 0x18, - 0xfc, 0x65, 0xca, 0x18, - 0xff, 0x6a, 0xd4, 0x08, - 0xfa, 0x65, 0xca, 0x18, - 0xff, 0x6a, 0xd4, 0x08, - 0x04, 0x65, 0xca, 0x18, - 0x0b, 0x65, 0xca, 0x18, - 0xff, 0x65, 0xc8, 0x08, - 0x00, 0x8c, 0x18, 0x19, - 0x02, 0x0b, 0xda, 0x78, - 0x01, 0x65, 0xe0, 0x60, - 0xf7, 0x01, 0x02, 0x08, - 0xff, 0x06, 0x32, 0x09, - 0xff, 0x65, 0xca, 0x18, - 0xff, 0x65, 0xda, 0x68, - 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xb0, 0x5c, - 0x40, 0x51, 0xf2, 0x78, - 0xe4, 0x6a, 0x06, 0x00, - 0x08, 0x01, 0x02, 0x00, - 0x04, 0x6a, 0x6c, 0x5b, - 0x01, 0x50, 0xa0, 0x18, - 0x00, 0x50, 0xf8, 0xe0, - 0xff, 0x6a, 0xa0, 0x08, - 0xff, 0x6a, 0x3a, 0x01, - 0x02, 0x6a, 0x22, 0x01, - 0x40, 0x51, 0xfe, 0x68, - 0xff, 0x6a, 0x06, 0x08, - 0x00, 0x65, 0x0e, 0x40, + 0x40, 0x0b, 0x96, 0x68, 0x20, 0x6a, 0x16, 0x00, 0xf0, 0x19, 0x6e, 0x08, 0x08, 0x6a, 0x18, 0x00, 0x08, 0x11, 0x22, 0x00, - 0x08, 0x6a, 0x68, 0x58, + 0x08, 0x6a, 0x66, 0x58, 0x08, 0x6a, 0x68, 0x00, - 0x00, 0x65, 0x24, 0x41, + 0x00, 0x65, 0xaa, 0x40, 0x12, 0x6a, 0x00, 0x00, 0x40, 0x6a, 0x16, 0x00, 0xff, 0x3e, 0x20, 0x09, @@ -145,24 +84,24 @@ static unsigned char seqprog[] = { 0xff, 0xa1, 0x6e, 0x08, 0x08, 0x6a, 0x18, 0x00, 0x08, 0x11, 0x22, 0x00, - 0x08, 0x6a, 0x68, 0x58, + 0x08, 0x6a, 0x66, 0x58, 0x80, 0x6a, 0x68, 0x00, 0x80, 0x36, 0x6c, 0x00, - 0x00, 0x65, 0x1e, 0x5c, + 0x00, 0x65, 0x9e, 0x5b, 0xff, 0x3d, 0xc8, 0x08, - 0xbf, 0x64, 0x5c, 0x79, - 0x80, 0x64, 0x24, 0x72, - 0xa0, 0x64, 0x54, 0x72, - 0xc0, 0x64, 0x4c, 0x72, - 0xe0, 0x64, 0x94, 0x72, + 0xbf, 0x64, 0xe2, 0x78, + 0x80, 0x64, 0xac, 0x71, + 0xa0, 0x64, 0xdc, 0x71, + 0xc0, 0x64, 0xd4, 0x71, + 0xe0, 0x64, 0x1c, 0x72, 0x01, 0x6a, 0x22, 0x01, - 0x00, 0x65, 0x24, 0x41, + 0x00, 0x65, 0xaa, 0x40, 0xf7, 0x11, 0x22, 0x08, - 0x00, 0x65, 0x44, 0x59, + 0x00, 0x65, 0xca, 0x58, 0xff, 0x06, 0xd4, 0x08, 0xf7, 0x01, 0x02, 0x08, - 0x09, 0x0c, 0x3e, 0x79, - 0x08, 0x0c, 0x0e, 0x68, + 0x09, 0x0c, 0xc4, 0x78, + 0x08, 0x0c, 0x0c, 0x68, 0x01, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0x26, 0x09, 0x02, 0x6a, 0x08, 0x30, @@ -174,25 +113,25 @@ static unsigned char seqprog[] = { 0x03, 0xa9, 0x18, 0x31, 0x03, 0xa9, 0x10, 0x30, 0x08, 0x6a, 0xcc, 0x00, - 0xa9, 0x6a, 0x34, 0x5c, - 0x00, 0x65, 0x7c, 0x41, + 0xa9, 0x6a, 0xb4, 0x5b, + 0x00, 0x65, 0x02, 0x41, 0xa8, 0x6a, 0x6a, 0x00, 0x79, 0x6a, 0x6a, 0x00, - 0x40, 0x3d, 0x64, 0x69, + 0x40, 0x3d, 0xea, 0x68, 0x04, 0x35, 0x6a, 0x00, - 0x00, 0x65, 0x8e, 0x5b, + 0x00, 0x65, 0x0e, 0x5b, 0x80, 0x6a, 0xd4, 0x01, - 0x10, 0x36, 0x50, 0x69, + 0x10, 0x36, 0xd6, 0x68, 0x10, 0x36, 0x6c, 0x00, 0x07, 0xac, 0x10, 0x31, 0x03, 0x8c, 0x10, 0x30, 0x05, 0xa3, 0x70, 0x30, 0x88, 0x6a, 0xcc, 0x00, - 0xac, 0x6a, 0x2c, 0x5c, - 0x00, 0x65, 0x26, 0x5c, + 0xac, 0x6a, 0xac, 0x5b, + 0x00, 0x65, 0xa6, 0x5b, 0x38, 0x6a, 0xcc, 0x00, - 0xa3, 0x6a, 0x30, 0x5c, - 0xff, 0x38, 0x8c, 0x69, + 0xa3, 0x6a, 0xb0, 0x5b, + 0xff, 0x38, 0x12, 0x69, 0x80, 0x02, 0x04, 0x00, 0xe7, 0x35, 0x6a, 0x08, 0x03, 0x69, 0x18, 0x31, @@ -200,337 +139,334 @@ static unsigned char seqprog[] = { 0xff, 0x6a, 0x10, 0x00, 0xff, 0x6a, 0x12, 0x00, 0xff, 0x6a, 0x14, 0x00, - 0x01, 0x38, 0x92, 0x61, + 0x01, 0x38, 0x18, 0x61, 0xbf, 0x35, 0x6a, 0x08, 0x02, 0x6a, 0xf8, 0x01, 0xff, 0x69, 0xca, 0x08, 0xff, 0x35, 0x26, 0x09, - 0x04, 0x0b, 0x96, 0x69, - 0x04, 0x0b, 0xa2, 0x69, - 0x10, 0x0c, 0x98, 0x79, - 0x04, 0x0b, 0xa2, 0x69, + 0x04, 0x0b, 0x1c, 0x69, + 0x04, 0x0b, 0x28, 0x69, + 0x10, 0x0c, 0x1e, 0x79, + 0x04, 0x0b, 0x28, 0x69, 0xff, 0x6a, 0xca, 0x08, - 0x00, 0x35, 0x76, 0x5b, - 0x80, 0x02, 0xf6, 0x69, - 0xff, 0x65, 0xe6, 0x79, + 0x00, 0x35, 0xee, 0x5a, + 0x80, 0x02, 0x7c, 0x69, + 0xff, 0x65, 0x6c, 0x79, 0xff, 0x38, 0x70, 0x18, - 0xff, 0x38, 0xe6, 0x79, - 0x80, 0xea, 0xc2, 0x61, + 0xff, 0x38, 0x6c, 0x79, + 0x80, 0xea, 0x48, 0x61, 0xef, 0x38, 0xc8, 0x18, 0x80, 0x6a, 0xc8, 0x00, - 0x00, 0x65, 0xb4, 0x49, + 0x00, 0x65, 0x3a, 0x49, 0x33, 0x38, 0xc8, 0x28, 0xff, 0x64, 0xd0, 0x09, 0x04, 0x39, 0xc0, 0x31, 0x09, 0x6a, 0xd6, 0x01, - 0x80, 0xeb, 0xba, 0x79, + 0x80, 0xeb, 0x40, 0x79, 0xf7, 0xeb, 0xd6, 0x09, - 0x08, 0xeb, 0xbe, 0x69, + 0x08, 0xeb, 0x44, 0x69, 0x01, 0x6a, 0xd6, 0x01, 0x08, 0xe9, 0x10, 0x31, 0x03, 0x8c, 0x10, 0x30, 0x88, 0x6a, 0xcc, 0x00, - 0x39, 0x6a, 0x32, 0x5c, + 0x39, 0x6a, 0xb2, 0x5b, 0x08, 0x6a, 0x18, 0x01, 0xff, 0x6a, 0x1a, 0x09, 0xff, 0x6a, 0x1c, 0x09, 0x0d, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xb0, 0x5c, - 0x88, 0x6a, 0xa0, 0x5c, - 0x00, 0x65, 0x26, 0x5c, + 0x00, 0x65, 0x30, 0x5c, + 0x88, 0x6a, 0x20, 0x5c, + 0x00, 0x65, 0xa6, 0x5b, 0xff, 0x6a, 0xc8, 0x08, 0x08, 0x39, 0x72, 0x18, 0x00, 0x3a, 0x74, 0x20, - 0x01, 0x0c, 0xde, 0x79, - 0x10, 0x0c, 0x7c, 0x79, + 0x01, 0x0c, 0x64, 0x79, + 0x10, 0x0c, 0x02, 0x79, 0xff, 0x35, 0x26, 0x09, - 0x04, 0x0b, 0xe4, 0x69, - 0x00, 0x65, 0xfe, 0x59, + 0x04, 0x0b, 0x6a, 0x69, + 0x00, 0x65, 0x84, 0x59, 0x03, 0x08, 0x52, 0x31, 0xff, 0x38, 0x50, 0x09, 0xff, 0x08, 0x52, 0x09, 0xff, 0x09, 0x54, 0x09, 0xff, 0x0a, 0x56, 0x09, 0xff, 0x38, 0x50, 0x09, - 0x00, 0x65, 0x24, 0x41, - 0x00, 0x65, 0xfe, 0x59, + 0x00, 0x65, 0xaa, 0x40, + 0x00, 0x65, 0x84, 0x59, 0x7f, 0x02, 0x04, 0x08, 0xe1, 0x6a, 0x22, 0x01, - 0x00, 0x65, 0x24, 0x41, - 0x04, 0x93, 0x14, 0x6a, + 0x00, 0x65, 0xaa, 0x40, + 0x04, 0x93, 0x9a, 0x69, 0xdf, 0x93, 0x26, 0x09, - 0x20, 0x93, 0x02, 0x6a, + 0x20, 0x93, 0x88, 0x69, 0x02, 0x93, 0x26, 0x01, - 0x01, 0x94, 0x04, 0x7a, - 0x01, 0x94, 0x04, 0x7a, - 0x01, 0x94, 0x04, 0x7a, - 0x01, 0x94, 0x04, 0x7a, - 0x01, 0x94, 0x04, 0x7a, - 0x01, 0x94, 0x04, 0x7a, - 0x10, 0x94, 0x12, 0x6a, - 0xf7, 0x93, 0x26, 0x09, - 0x08, 0x93, 0x16, 0x6a, - 0xdf, 0x93, 0x26, 0x09, - 0x20, 0x93, 0x1a, 0x6a, + 0x01, 0x94, 0x8a, 0x79, + 0x01, 0x94, 0x8a, 0x79, + 0x01, 0x94, 0x8a, 0x79, + 0x01, 0x94, 0x8a, 0x79, + 0x01, 0x94, 0x8a, 0x79, + 0x01, 0x94, 0x8a, 0x79, + 0x10, 0x94, 0x98, 0x69, + 0x7f, 0x05, 0xa0, 0x69, + 0x02, 0x03, 0xa0, 0x79, + 0x10, 0x0c, 0x9c, 0x79, + 0xd7, 0x93, 0x26, 0x09, + 0x28, 0x93, 0xa2, 0x69, 0x03, 0x08, 0x52, 0x31, 0xff, 0x38, 0x50, 0x09, 0x12, 0x01, 0x02, 0x00, 0xff, 0x6a, 0xd4, 0x0c, - 0x00, 0x65, 0x8e, 0x5b, + 0x00, 0x65, 0x0e, 0x5b, 0x05, 0xb4, 0x10, 0x31, 0x02, 0x6a, 0x1a, 0x31, 0x03, 0x8c, 0x10, 0x30, 0x88, 0x6a, 0xcc, 0x00, - 0xb4, 0x6a, 0x30, 0x5c, + 0xb4, 0x6a, 0xb0, 0x5b, 0xff, 0x6a, 0x1a, 0x09, 0xff, 0x6a, 0x1c, 0x09, - 0x00, 0x65, 0x26, 0x5c, - 0x3d, 0x6a, 0x76, 0x5b, + 0x00, 0x65, 0xa6, 0x5b, + 0x3d, 0x6a, 0xee, 0x5a, 0xac, 0x6a, 0x26, 0x01, - 0x04, 0x0b, 0x3a, 0x6a, - 0x04, 0x0b, 0x40, 0x6a, - 0x10, 0x0c, 0x3c, 0x7a, - 0xf7, 0x93, 0x26, 0x09, - 0x08, 0x93, 0x42, 0x6a, - 0xdf, 0x93, 0x26, 0x09, - 0x20, 0x93, 0x46, 0x6a, + 0x04, 0x0b, 0xc2, 0x69, + 0x04, 0x0b, 0xc8, 0x69, + 0x10, 0x0c, 0xc4, 0x79, + 0x02, 0x03, 0xcc, 0x79, + 0x10, 0x0c, 0xc8, 0x79, + 0xd7, 0x93, 0x26, 0x09, + 0x28, 0x93, 0xce, 0x69, 0x12, 0x01, 0x02, 0x00, - 0x00, 0x65, 0x24, 0x41, - 0x00, 0x65, 0x8e, 0x5b, + 0x00, 0x65, 0xaa, 0x40, + 0x00, 0x65, 0x0e, 0x5b, 0xff, 0x06, 0x44, 0x09, - 0x00, 0x65, 0x24, 0x41, + 0x00, 0x65, 0xaa, 0x40, 0x10, 0x3d, 0x06, 0x00, 0xff, 0x34, 0xca, 0x08, - 0x80, 0x65, 0x78, 0x62, + 0x80, 0x65, 0x00, 0x62, 0x0f, 0xa1, 0xca, 0x08, 0x07, 0xa1, 0xca, 0x08, 0x40, 0xa0, 0xc8, 0x08, 0x00, 0x65, 0xca, 0x00, 0x80, 0x65, 0xca, 0x00, - 0x80, 0xa0, 0x68, 0x7a, + 0x80, 0xa0, 0xf0, 0x79, 0xff, 0x65, 0x0c, 0x08, - 0x00, 0x65, 0x7a, 0x42, - 0x20, 0xa0, 0x80, 0x7a, + 0x00, 0x65, 0x02, 0x42, + 0x20, 0xa0, 0x08, 0x7a, 0xff, 0x65, 0x0c, 0x08, - 0x00, 0x65, 0x1e, 0x5c, - 0xa0, 0x3d, 0x88, 0x62, + 0x00, 0x65, 0x9e, 0x5b, + 0xa0, 0x3d, 0x10, 0x62, 0x23, 0xa0, 0x0c, 0x08, - 0x00, 0x65, 0x1e, 0x5c, - 0xa0, 0x3d, 0x88, 0x62, - 0x00, 0xb9, 0x80, 0x42, - 0xff, 0x65, 0x80, 0x62, + 0x00, 0x65, 0x9e, 0x5b, + 0xa0, 0x3d, 0x10, 0x62, + 0x00, 0xb9, 0x08, 0x42, + 0xff, 0x65, 0x08, 0x62, 0xa1, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, - 0x10, 0x51, 0x88, 0x72, + 0x10, 0x51, 0x10, 0x72, 0x40, 0x6a, 0x18, 0x00, 0xff, 0x65, 0x0c, 0x08, - 0x00, 0x65, 0x1e, 0x5c, - 0xa0, 0x3d, 0x52, 0x72, + 0x00, 0x65, 0x9e, 0x5b, + 0xa0, 0x3d, 0xda, 0x71, 0x40, 0x6a, 0x18, 0x00, 0xff, 0x34, 0xa6, 0x08, - 0x80, 0x34, 0x90, 0x62, + 0x80, 0x34, 0x18, 0x62, 0x7f, 0xa0, 0x40, 0x09, 0x08, 0x6a, 0x68, 0x00, - 0x00, 0x65, 0x24, 0x41, - 0x64, 0x6a, 0x66, 0x5b, - 0x80, 0x64, 0x06, 0x6b, - 0x04, 0x64, 0xe8, 0x72, - 0x02, 0x64, 0xee, 0x72, - 0x00, 0x6a, 0xb0, 0x72, - 0x03, 0x64, 0x02, 0x73, - 0x01, 0x64, 0xe4, 0x72, - 0x07, 0x64, 0x44, 0x73, - 0x08, 0x64, 0xac, 0x72, - 0x23, 0x64, 0x48, 0x73, + 0x00, 0x65, 0xaa, 0x40, + 0x64, 0x6a, 0xe4, 0x5a, + 0x80, 0x64, 0x8e, 0x6a, + 0x04, 0x64, 0x70, 0x72, + 0x02, 0x64, 0x76, 0x72, + 0x00, 0x6a, 0x38, 0x72, + 0x03, 0x64, 0x8a, 0x72, + 0x01, 0x64, 0x6c, 0x72, + 0x07, 0x64, 0xcc, 0x72, + 0x08, 0x64, 0x34, 0x72, + 0x23, 0x64, 0xd0, 0x72, 0x11, 0x6a, 0x22, 0x01, - 0x07, 0x6a, 0x58, 0x5b, + 0x07, 0x6a, 0xd6, 0x5a, 0xff, 0x06, 0xd4, 0x08, - 0x00, 0x65, 0x24, 0x41, - 0xff, 0xa8, 0xb4, 0x6a, - 0xff, 0xa2, 0xcc, 0x7a, + 0x00, 0x65, 0xaa, 0x40, + 0xff, 0xa8, 0x3c, 0x6a, + 0xff, 0xa2, 0x54, 0x7a, 0x01, 0x6a, 0x6a, 0x00, - 0x00, 0xb9, 0x4a, 0x5c, - 0xff, 0xa2, 0xcc, 0x7a, + 0x00, 0xb9, 0xca, 0x5b, + 0xff, 0xa2, 0x54, 0x7a, 0x71, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, - 0x40, 0x51, 0xcc, 0x62, + 0x40, 0x51, 0x54, 0x62, 0x0d, 0x6a, 0x6a, 0x00, - 0x00, 0xb9, 0x4a, 0x5c, + 0x00, 0xb9, 0xca, 0x5b, 0xff, 0x3e, 0x74, 0x09, 0xff, 0x90, 0x7c, 0x08, - 0x00, 0x65, 0x50, 0x58, - 0x00, 0x65, 0x36, 0x41, - 0x20, 0xa0, 0xd4, 0x6a, + 0x00, 0x65, 0x4e, 0x58, + 0x00, 0x65, 0xbc, 0x40, + 0x20, 0xa0, 0x5c, 0x6a, 0xff, 0x37, 0xc8, 0x08, - 0x00, 0x6a, 0xf4, 0x5b, - 0xff, 0x6a, 0x0a, 0x5c, + 0x00, 0x6a, 0x74, 0x5b, + 0xff, 0x6a, 0x8a, 0x5b, 0xff, 0xf8, 0xc8, 0x08, 0xff, 0x4f, 0xc8, 0x08, - 0x01, 0x6a, 0xf4, 0x5b, - 0x00, 0xb9, 0x0a, 0x5c, + 0x01, 0x6a, 0x74, 0x5b, + 0x00, 0xb9, 0x8a, 0x5b, 0x01, 0x4f, 0x9e, 0x18, 0x02, 0x6a, 0x22, 0x01, - 0x00, 0x65, 0xb8, 0x5c, - 0x00, 0x65, 0x36, 0x41, + 0x00, 0x65, 0x38, 0x5c, + 0x00, 0x65, 0xbc, 0x40, 0x41, 0x6a, 0x22, 0x01, - 0x00, 0x65, 0x24, 0x41, + 0x00, 0x65, 0xaa, 0x40, 0x04, 0xa0, 0x40, 0x01, - 0x00, 0x65, 0xd0, 0x5c, - 0x00, 0x65, 0x36, 0x41, - 0x10, 0x36, 0xac, 0x7a, + 0x00, 0x65, 0x50, 0x5c, + 0x00, 0x65, 0xbc, 0x40, + 0x10, 0x36, 0x34, 0x7a, 0x05, 0x38, 0x46, 0x31, 0x04, 0x14, 0x58, 0x31, 0x03, 0xa9, 0x60, 0x31, 0xa3, 0x6a, 0xcc, 0x00, - 0x38, 0x6a, 0x30, 0x5c, + 0x38, 0x6a, 0xb0, 0x5b, 0xac, 0x6a, 0xcc, 0x00, - 0x14, 0x6a, 0x32, 0x5c, - 0xa9, 0x6a, 0x34, 0x5c, - 0x00, 0x65, 0xac, 0x42, + 0x14, 0x6a, 0xb2, 0x5b, + 0xa9, 0x6a, 0xb4, 0x5b, + 0x00, 0x65, 0x34, 0x42, 0xef, 0x36, 0x6c, 0x08, - 0x00, 0x65, 0xac, 0x42, + 0x00, 0x65, 0x34, 0x42, 0x0f, 0x64, 0xc8, 0x08, 0x07, 0x64, 0xc8, 0x08, 0x00, 0x37, 0x6e, 0x00, 0xff, 0x6a, 0xa4, 0x00, - 0x00, 0x65, 0xc4, 0x5b, - 0xff, 0x51, 0x18, 0x73, - 0x20, 0x36, 0x22, 0x7b, - 0x00, 0x90, 0xb2, 0x5b, - 0x00, 0x65, 0x24, 0x43, + 0x00, 0x65, 0x44, 0x5b, + 0xff, 0x51, 0xa0, 0x72, + 0x20, 0x36, 0xaa, 0x7a, + 0x00, 0x90, 0x32, 0x5b, + 0x00, 0x65, 0xac, 0x42, 0xff, 0x06, 0xd4, 0x08, - 0x00, 0x65, 0x1e, 0x5c, - 0xe0, 0x3d, 0x3e, 0x63, - 0x20, 0x12, 0x3e, 0x63, - 0x51, 0x6a, 0x5c, 0x5b, - 0x00, 0x65, 0xac, 0x5b, + 0x00, 0x65, 0x9e, 0x5b, + 0xe0, 0x3d, 0xc6, 0x62, + 0x20, 0x12, 0xc6, 0x62, + 0x51, 0x6a, 0xda, 0x5a, + 0x00, 0x65, 0x2c, 0x5b, 0xff, 0x37, 0xc8, 0x08, - 0x00, 0xa1, 0x36, 0x63, - 0x04, 0xa0, 0x36, 0x7b, + 0x00, 0xa1, 0xbe, 0x62, + 0x04, 0xa0, 0xbe, 0x7a, 0xfb, 0xa0, 0x40, 0x09, 0x80, 0x36, 0x6c, 0x00, - 0x80, 0xa0, 0xac, 0x7a, + 0x80, 0xa0, 0x34, 0x7a, 0x7f, 0xa0, 0x40, 0x09, - 0xff, 0x6a, 0x58, 0x5b, - 0x00, 0x65, 0xac, 0x42, - 0x04, 0xa0, 0x3c, 0x7b, - 0x00, 0x65, 0xd0, 0x5c, - 0x00, 0x65, 0x3e, 0x43, - 0x00, 0x65, 0xb8, 0x5c, + 0xff, 0x6a, 0xd6, 0x5a, + 0x00, 0x65, 0x34, 0x42, + 0x04, 0xa0, 0xc4, 0x7a, + 0x00, 0x65, 0x50, 0x5c, + 0x00, 0x65, 0xc6, 0x42, + 0x00, 0x65, 0x38, 0x5c, 0x31, 0x6a, 0x22, 0x01, - 0x0c, 0x6a, 0x58, 0x5b, - 0x00, 0x65, 0xac, 0x42, + 0x0c, 0x6a, 0xd6, 0x5a, + 0x00, 0x65, 0x34, 0x42, 0x61, 0x6a, 0x22, 0x01, - 0x00, 0x65, 0xac, 0x42, - 0x51, 0x6a, 0x5c, 0x5b, - 0xff, 0xa8, 0x54, 0x6b, - 0xff, 0xa9, 0x54, 0x6b, - 0xff, 0xaa, 0x54, 0x6b, - 0xff, 0xab, 0x54, 0x6b, - 0x00, 0x65, 0xac, 0x42, + 0x00, 0x65, 0x34, 0x42, + 0x51, 0x6a, 0xda, 0x5a, 0x51, 0x6a, 0x22, 0x01, - 0x00, 0x65, 0xac, 0x42, + 0x00, 0x65, 0x34, 0x42, 0x10, 0x3d, 0x06, 0x00, 0xff, 0x65, 0x68, 0x0c, 0xff, 0x06, 0xd4, 0x08, - 0x01, 0x0c, 0x5e, 0x7b, - 0x04, 0x0c, 0x60, 0x6b, + 0x01, 0x0c, 0xdc, 0x7a, + 0x04, 0x0c, 0xde, 0x6a, 0xe0, 0x03, 0x7a, 0x08, - 0xe0, 0x3d, 0x72, 0x63, + 0xe0, 0x3d, 0xea, 0x62, 0xff, 0x65, 0xcc, 0x08, 0xff, 0x12, 0xda, 0x0c, 0xff, 0x06, 0xd4, 0x0c, - 0xff, 0x65, 0x0c, 0x08, - 0x02, 0x0b, 0x6e, 0x7b, - 0xff, 0x6a, 0xd4, 0x0c, 0xd1, 0x6a, 0x22, 0x01, - 0x00, 0x65, 0x24, 0x41, + 0x00, 0x65, 0xaa, 0x40, 0xff, 0x65, 0x26, 0x09, - 0x01, 0x0b, 0x86, 0x6b, - 0x10, 0x0c, 0x78, 0x7b, - 0x04, 0x0b, 0x80, 0x6b, + 0x01, 0x0b, 0xfe, 0x6a, + 0x10, 0x0c, 0xf0, 0x7a, + 0x04, 0x0b, 0xf8, 0x6a, 0xff, 0x6a, 0xca, 0x08, - 0x04, 0x93, 0x84, 0x6b, - 0x01, 0x94, 0x82, 0x7b, - 0x10, 0x94, 0x84, 0x6b, + 0x04, 0x93, 0xfc, 0x6a, + 0x01, 0x94, 0xfa, 0x7a, + 0x10, 0x94, 0xfc, 0x6a, + 0x80, 0x3d, 0x02, 0x73, + 0x0f, 0x04, 0x06, 0x6b, + 0x02, 0x03, 0x06, 0x7b, + 0x10, 0x0c, 0x02, 0x7b, 0xc7, 0x93, 0x26, 0x09, 0xff, 0x99, 0xd4, 0x08, - 0x38, 0x93, 0x88, 0x6b, + 0x38, 0x93, 0x08, 0x6b, 0xff, 0x6a, 0xd4, 0x0c, - 0x80, 0x36, 0x8c, 0x6b, + 0x80, 0x36, 0x0c, 0x6b, 0x21, 0x6a, 0x22, 0x05, 0xff, 0x65, 0x20, 0x09, - 0xff, 0x51, 0x9a, 0x63, + 0xff, 0x51, 0x1a, 0x63, 0xff, 0x37, 0xc8, 0x08, - 0xa1, 0x6a, 0xa6, 0x43, + 0xa1, 0x6a, 0x26, 0x43, 0xff, 0x51, 0xc8, 0x08, - 0xb9, 0x6a, 0xa6, 0x43, + 0xb9, 0x6a, 0x26, 0x43, 0xff, 0x90, 0xa4, 0x08, - 0xff, 0xba, 0xaa, 0x73, + 0xff, 0xba, 0x2a, 0x73, 0xff, 0xba, 0x20, 0x09, 0xff, 0x65, 0xca, 0x18, - 0x00, 0x6c, 0x9e, 0x63, + 0x00, 0x6c, 0x1e, 0x63, 0xff, 0x90, 0xca, 0x0c, 0xff, 0x6a, 0xca, 0x04, - 0x20, 0x36, 0xbe, 0x7b, - 0x00, 0x90, 0x92, 0x5b, - 0xff, 0x65, 0xbe, 0x73, - 0xff, 0x52, 0xbc, 0x73, + 0x20, 0x36, 0x3e, 0x7b, + 0x00, 0x90, 0x12, 0x5b, + 0xff, 0x65, 0x3e, 0x73, + 0xff, 0x52, 0x3c, 0x73, 0xff, 0xba, 0xcc, 0x08, 0xff, 0x52, 0x20, 0x09, 0xff, 0x66, 0x74, 0x09, 0xff, 0x65, 0x20, 0x0d, 0xff, 0xba, 0x7e, 0x0c, - 0x00, 0x6a, 0xbe, 0x5c, + 0x00, 0x6a, 0x3e, 0x5c, 0x0d, 0x6a, 0x6a, 0x00, - 0x00, 0x51, 0x4a, 0x44, - 0xff, 0x3f, 0x18, 0x74, + 0x00, 0x51, 0xca, 0x43, + 0xff, 0x3f, 0x98, 0x73, 0xff, 0x6a, 0xa2, 0x00, - 0x00, 0x3f, 0x92, 0x5b, - 0xff, 0x65, 0x18, 0x74, + 0x00, 0x3f, 0x12, 0x5b, + 0xff, 0x65, 0x98, 0x73, 0x20, 0x36, 0x6c, 0x00, - 0x20, 0xa0, 0xd2, 0x6b, + 0x20, 0xa0, 0x52, 0x6b, 0xff, 0xb9, 0xa2, 0x0c, 0xff, 0x6a, 0xa2, 0x04, 0xff, 0x65, 0xa4, 0x08, 0xe0, 0x6a, 0xcc, 0x00, - 0x45, 0x6a, 0x3e, 0x5c, + 0x45, 0x6a, 0xbe, 0x5b, 0x01, 0x6a, 0xd0, 0x01, 0x09, 0x6a, 0xd6, 0x01, - 0x80, 0xeb, 0xde, 0x7b, + 0x80, 0xeb, 0x5e, 0x7b, 0x01, 0x6a, 0xd6, 0x01, 0x01, 0xe9, 0xa4, 0x34, 0x88, 0x6a, 0xcc, 0x00, - 0x45, 0x6a, 0x3e, 0x5c, + 0x45, 0x6a, 0xbe, 0x5b, 0x01, 0x6a, 0x18, 0x01, 0xff, 0x6a, 0x1a, 0x09, 0xff, 0x6a, 0x1c, 0x09, 0x0d, 0x6a, 0x26, 0x01, - 0x00, 0x65, 0xb0, 0x5c, + 0x00, 0x65, 0x30, 0x5c, 0xff, 0x99, 0xa4, 0x0c, 0xff, 0x65, 0xa4, 0x08, 0xe0, 0x6a, 0xcc, 0x00, - 0x45, 0x6a, 0x3e, 0x5c, + 0x45, 0x6a, 0xbe, 0x5b, 0x01, 0x6a, 0xd0, 0x01, 0x01, 0x6a, 0xdc, 0x05, 0x88, 0x6a, 0xcc, 0x00, - 0x45, 0x6a, 0x3e, 0x5c, + 0x45, 0x6a, 0xbe, 0x5b, 0x01, 0x6a, 0x18, 0x01, 0xff, 0x6a, 0x1a, 0x09, 0xff, 0x6a, 0x1c, 0x09, 0x01, 0x6a, 0x26, 0x05, 0x01, 0x65, 0xd8, 0x31, 0x09, 0xee, 0xdc, 0x01, - 0x80, 0xee, 0x0e, 0x7c, + 0x80, 0xee, 0x8e, 0x7b, 0xff, 0x6a, 0xdc, 0x0d, 0xff, 0x65, 0x32, 0x09, 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xb0, 0x44, + 0x00, 0x65, 0x30, 0x44, 0xff, 0x37, 0xc8, 0x08, - 0x00, 0x6a, 0xd4, 0x5b, + 0x00, 0x6a, 0x54, 0x5b, 0xff, 0x52, 0xa2, 0x0c, - 0x01, 0x0c, 0x1e, 0x7c, - 0x04, 0x0c, 0x1e, 0x6c, + 0x01, 0x0c, 0x9e, 0x7b, + 0x04, 0x0c, 0x9e, 0x6b, 0xe0, 0x03, 0x06, 0x08, 0xe0, 0x03, 0x7a, 0x0c, 0xff, 0x8c, 0x10, 0x08, @@ -553,29 +489,29 @@ static unsigned char seqprog[] = { 0x00, 0x6c, 0xda, 0x24, 0xff, 0x65, 0xc8, 0x08, 0xe0, 0x6a, 0xcc, 0x00, - 0x41, 0x6a, 0x3a, 0x5c, + 0x41, 0x6a, 0xba, 0x5b, 0xff, 0x90, 0xe2, 0x09, 0x20, 0x6a, 0xd0, 0x01, - 0x04, 0x35, 0x5c, 0x7c, + 0x04, 0x35, 0xdc, 0x7b, 0x1d, 0x6a, 0xdc, 0x01, - 0xdc, 0xee, 0x58, 0x64, - 0x00, 0x65, 0x68, 0x44, + 0xdc, 0xee, 0xd8, 0x63, + 0x00, 0x65, 0xe8, 0x43, 0x01, 0x6a, 0xdc, 0x01, 0x20, 0xa0, 0xd8, 0x31, 0x09, 0xee, 0xdc, 0x01, - 0x80, 0xee, 0x62, 0x7c, + 0x80, 0xee, 0xe2, 0x7b, 0x19, 0x6a, 0xdc, 0x01, - 0xd8, 0xee, 0x66, 0x64, + 0xd8, 0xee, 0xe6, 0x63, 0xff, 0x6a, 0xdc, 0x09, - 0x18, 0xee, 0x6a, 0x6c, + 0x18, 0xee, 0xea, 0x6b, 0xff, 0x6a, 0xd4, 0x0c, 0x88, 0x6a, 0xcc, 0x00, - 0x41, 0x6a, 0x3a, 0x5c, + 0x41, 0x6a, 0xba, 0x5b, 0x20, 0x6a, 0x18, 0x01, 0xff, 0x6a, 0x1a, 0x09, 0xff, 0x6a, 0x1c, 0x09, 0xff, 0x35, 0x26, 0x09, - 0x04, 0x35, 0x94, 0x6c, + 0x04, 0x35, 0x14, 0x6c, 0xa0, 0x6a, 0xca, 0x00, 0x20, 0x65, 0xc8, 0x18, 0xff, 0x6c, 0x32, 0x09, @@ -586,14 +522,14 @@ static unsigned char seqprog[] = { 0xff, 0x6c, 0x32, 0x09, 0xff, 0x6c, 0x32, 0x09, 0xff, 0x6c, 0x32, 0x09, - 0x00, 0x65, 0x80, 0x64, + 0x00, 0x65, 0x00, 0x64, 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xb0, 0x5c, - 0x04, 0x35, 0x8c, 0x7b, - 0xa0, 0x6a, 0xa0, 0x5c, - 0x00, 0x65, 0xa2, 0x5c, - 0x00, 0x65, 0xa2, 0x5c, - 0x00, 0x65, 0xa2, 0x44, + 0x00, 0x65, 0x30, 0x5c, + 0x04, 0x35, 0x0c, 0x7b, + 0xa0, 0x6a, 0x20, 0x5c, + 0x00, 0x65, 0x22, 0x5c, + 0x00, 0x65, 0x22, 0x5c, + 0x00, 0x65, 0x22, 0x44, 0xff, 0x65, 0xcc, 0x08, 0xff, 0x99, 0xda, 0x08, 0xff, 0x99, 0xda, 0x08, @@ -602,19 +538,19 @@ static unsigned char seqprog[] = { 0xff, 0x99, 0xda, 0x08, 0xff, 0x99, 0xda, 0x08, 0xff, 0x99, 0xda, 0x0c, - 0x08, 0x94, 0xb0, 0x7c, + 0x08, 0x94, 0x30, 0x7c, 0xf7, 0x93, 0x26, 0x09, - 0x08, 0x93, 0xb4, 0x6c, + 0x08, 0x93, 0x34, 0x6c, 0xff, 0x6a, 0xd4, 0x0c, 0xff, 0x40, 0x74, 0x09, 0xff, 0x90, 0x80, 0x08, 0xff, 0x6a, 0x72, 0x05, - 0xff, 0x40, 0xcc, 0x64, - 0xff, 0x3f, 0xc4, 0x64, + 0xff, 0x40, 0x4c, 0x64, + 0xff, 0x3f, 0x44, 0x64, 0xff, 0x6a, 0xca, 0x04, 0xff, 0x3f, 0x20, 0x09, 0x01, 0x6a, 0x6a, 0x00, - 0x00, 0xb9, 0x4a, 0x5c, + 0x00, 0xb9, 0xca, 0x5b, 0xff, 0xba, 0x7e, 0x0c, 0xff, 0x40, 0x20, 0x09, 0xff, 0xba, 0x80, 0x0c, @@ -622,20 +558,12 @@ static unsigned char seqprog[] = { 0xff, 0x90, 0x7e, 0x0c, }; -static int aic7xxx_patch13_func(struct aic7xxx_host *p); - -static int -aic7xxx_patch13_func(struct aic7xxx_host *p) -{ - return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895); -} - static int aic7xxx_patch12_func(struct aic7xxx_host *p); static int aic7xxx_patch12_func(struct aic7xxx_host *p) { - return ((p->features & AHC_CMD_CHAN) == 0); + return ((p->features & AHC_WIDE) != 0); } static int aic7xxx_patch11_func(struct aic7xxx_host *p); @@ -643,7 +571,7 @@ static int aic7xxx_patch11_func(struct aic7xxx_host *p); static int aic7xxx_patch11_func(struct aic7xxx_host *p) { - return ((p->features & AHC_WIDE) != 0); + return ((p->features & AHC_ULTRA2) == 0); } static int aic7xxx_patch10_func(struct aic7xxx_host *p); @@ -651,7 +579,7 @@ static int aic7xxx_patch10_func(struct aic7xxx_host *p); static int aic7xxx_patch10_func(struct aic7xxx_host *p) { - return ((p->features & AHC_ULTRA2) == 0); + return ((p->features & AHC_CMD_CHAN) == 0); } static int aic7xxx_patch9_func(struct aic7xxx_host *p); @@ -659,7 +587,7 @@ static int aic7xxx_patch9_func(struct aic7xxx_host *p); static int aic7xxx_patch9_func(struct aic7xxx_host *p) { - return ((p->features & AHC_ULTRA) != 0); + return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895); } static int aic7xxx_patch8_func(struct aic7xxx_host *p); @@ -667,7 +595,7 @@ static int aic7xxx_patch8_func(struct aic7xxx_host *p); static int aic7xxx_patch8_func(struct aic7xxx_host *p) { - return ((p->features & AHC_ULTRA2) != 0); + return ((p->features & AHC_ULTRA) != 0); } static int aic7xxx_patch7_func(struct aic7xxx_host *p); @@ -675,7 +603,7 @@ static int aic7xxx_patch7_func(struct aic7xxx_host *p); static int aic7xxx_patch7_func(struct aic7xxx_host *p) { - return ((p->flags & AHC_PAGESCBS) == 0); + return ((p->features & AHC_ULTRA2) != 0); } static int aic7xxx_patch6_func(struct aic7xxx_host *p); @@ -683,7 +611,7 @@ static int aic7xxx_patch6_func(struct aic7xxx_host *p); static int aic7xxx_patch6_func(struct aic7xxx_host *p) { - return ((p->flags & AHC_PAGESCBS) != 0); + return ((p->flags & AHC_PAGESCBS) == 0); } static int aic7xxx_patch5_func(struct aic7xxx_host *p); @@ -691,7 +619,7 @@ static int aic7xxx_patch5_func(struct aic7xxx_host *p); static int aic7xxx_patch5_func(struct aic7xxx_host *p) { - return ((p->features & AHC_QUEUE_REGS) != 0); + return ((p->flags & AHC_PAGESCBS) != 0); } static int aic7xxx_patch4_func(struct aic7xxx_host *p); @@ -699,7 +627,7 @@ static int aic7xxx_patch4_func(struct aic7xxx_host *p); static int aic7xxx_patch4_func(struct aic7xxx_host *p) { - return ((p->features & AHC_TWIN) != 0); + return ((p->features & AHC_QUEUE_REGS) != 0); } static int aic7xxx_patch3_func(struct aic7xxx_host *p); @@ -707,7 +635,7 @@ static int aic7xxx_patch3_func(struct aic7xxx_host *p); static int aic7xxx_patch3_func(struct aic7xxx_host *p) { - return ((p->features & AHC_QUEUE_REGS) == 0); + return ((p->features & AHC_TWIN) != 0); } static int aic7xxx_patch2_func(struct aic7xxx_host *p); @@ -715,7 +643,7 @@ static int aic7xxx_patch2_func(struct aic7xxx_host *p); static int aic7xxx_patch2_func(struct aic7xxx_host *p) { - return ((p->features & AHC_CMD_CHAN) != 0); + return ((p->features & AHC_QUEUE_REGS) == 0); } static int aic7xxx_patch1_func(struct aic7xxx_host *p); @@ -723,7 +651,7 @@ static int aic7xxx_patch1_func(struct aic7xxx_host *p); static int aic7xxx_patch1_func(struct aic7xxx_host *p) { - return ((p->flags & AHC_TARGETMODE) != 0); + return ((p->features & AHC_CMD_CHAN) != 0); } static int aic7xxx_patch0_func(struct aic7xxx_host *p); @@ -740,83 +668,78 @@ struct sequencer_patch { skip_instr :10, skip_patch :12; } sequencer_patches[] = { - { aic7xxx_patch1_func, 2, 1, 2 }, - { aic7xxx_patch0_func, 3, 1, 1 }, - { aic7xxx_patch2_func, 4, 2, 1 }, - { aic7xxx_patch3_func, 8, 1, 1 }, - { aic7xxx_patch3_func, 9, 1, 1 }, - { aic7xxx_patch4_func, 12, 4, 1 }, - { aic7xxx_patch5_func, 17, 3, 2 }, - { aic7xxx_patch0_func, 20, 4, 1 }, - { aic7xxx_patch6_func, 24, 1, 1 }, - { aic7xxx_patch7_func, 27, 1, 1 }, - { aic7xxx_patch2_func, 30, 1, 2 }, - { aic7xxx_patch0_func, 31, 3, 1 }, - { aic7xxx_patch4_func, 40, 4, 1 }, - { aic7xxx_patch8_func, 44, 3, 2 }, - { aic7xxx_patch0_func, 47, 3, 1 }, - { aic7xxx_patch9_func, 53, 7, 1 }, - { aic7xxx_patch4_func, 61, 3, 1 }, - { aic7xxx_patch8_func, 64, 2, 1 }, - { aic7xxx_patch1_func, 69, 60, 1 }, - { aic7xxx_patch8_func, 163, 1, 2 }, - { aic7xxx_patch0_func, 164, 2, 1 }, - { aic7xxx_patch2_func, 168, 3, 4 }, - { aic7xxx_patch8_func, 168, 2, 2 }, - { aic7xxx_patch0_func, 170, 1, 1 }, - { aic7xxx_patch0_func, 171, 2, 1 }, - { aic7xxx_patch8_func, 174, 1, 2 }, - { aic7xxx_patch0_func, 175, 1, 1 }, - { aic7xxx_patch2_func, 179, 1, 1 }, - { aic7xxx_patch2_func, 182, 3, 2 }, - { aic7xxx_patch0_func, 185, 5, 1 }, - { aic7xxx_patch2_func, 193, 2, 3 }, - { aic7xxx_patch8_func, 193, 1, 1 }, - { aic7xxx_patch0_func, 195, 3, 1 }, - { aic7xxx_patch10_func, 199, 1, 2 }, - { aic7xxx_patch0_func, 200, 1, 1 }, - { aic7xxx_patch8_func, 201, 7, 2 }, - { aic7xxx_patch0_func, 208, 1, 1 }, - { aic7xxx_patch2_func, 213, 14, 3 }, - { aic7xxx_patch10_func, 226, 1, 1 }, - { aic7xxx_patch0_func, 227, 9, 1 }, - { aic7xxx_patch8_func, 241, 2, 1 }, - { aic7xxx_patch8_func, 243, 1, 1 }, - { aic7xxx_patch10_func, 244, 6, 3 }, - { aic7xxx_patch2_func, 244, 2, 2 }, - { aic7xxx_patch0_func, 246, 4, 1 }, - { aic7xxx_patch8_func, 251, 1, 1 }, - { aic7xxx_patch8_func, 255, 19, 1 }, - { aic7xxx_patch2_func, 275, 3, 3 }, - { aic7xxx_patch10_func, 277, 1, 1 }, - { aic7xxx_patch0_func, 278, 5, 1 }, - { aic7xxx_patch10_func, 283, 1, 2 }, - { aic7xxx_patch0_func, 284, 9, 1 }, - { aic7xxx_patch11_func, 300, 1, 2 }, - { aic7xxx_patch0_func, 301, 1, 1 }, - { aic7xxx_patch5_func, 362, 1, 2 }, - { aic7xxx_patch0_func, 363, 1, 1 }, - { aic7xxx_patch3_func, 366, 1, 1 }, - { aic7xxx_patch2_func, 376, 3, 2 }, - { aic7xxx_patch0_func, 379, 5, 1 }, - { aic7xxx_patch11_func, 387, 1, 2 }, - { aic7xxx_patch0_func, 388, 1, 1 }, - { aic7xxx_patch6_func, 393, 1, 1 }, - { aic7xxx_patch1_func, 438, 3, 1 }, - { aic7xxx_patch10_func, 443, 11, 1 }, - { aic7xxx_patch2_func, 491, 7, 2 }, - { aic7xxx_patch0_func, 498, 8, 1 }, - { aic7xxx_patch2_func, 507, 4, 2 }, - { aic7xxx_patch0_func, 511, 6, 1 }, - { aic7xxx_patch2_func, 517, 4, 2 }, - { aic7xxx_patch0_func, 521, 3, 1 }, - { aic7xxx_patch12_func, 531, 10, 1 }, - { aic7xxx_patch2_func, 550, 17, 4 }, - { aic7xxx_patch13_func, 558, 4, 2 }, - { aic7xxx_patch0_func, 562, 2, 1 }, - { aic7xxx_patch0_func, 567, 33, 1 }, - { aic7xxx_patch12_func, 600, 4, 1 }, - { aic7xxx_patch6_func, 604, 2, 1 }, - { aic7xxx_patch6_func, 607, 9, 1 }, + { aic7xxx_patch1_func, 3, 2, 1 }, + { aic7xxx_patch2_func, 7, 1, 1 }, + { aic7xxx_patch2_func, 8, 1, 1 }, + { aic7xxx_patch3_func, 11, 4, 1 }, + { aic7xxx_patch4_func, 16, 3, 2 }, + { aic7xxx_patch0_func, 19, 4, 1 }, + { aic7xxx_patch5_func, 23, 1, 1 }, + { aic7xxx_patch6_func, 26, 1, 1 }, + { aic7xxx_patch1_func, 29, 1, 2 }, + { aic7xxx_patch0_func, 30, 3, 1 }, + { aic7xxx_patch3_func, 39, 4, 1 }, + { aic7xxx_patch7_func, 43, 3, 2 }, + { aic7xxx_patch0_func, 46, 3, 1 }, + { aic7xxx_patch8_func, 52, 7, 1 }, + { aic7xxx_patch3_func, 60, 3, 1 }, + { aic7xxx_patch7_func, 63, 2, 1 }, + { aic7xxx_patch7_func, 102, 1, 2 }, + { aic7xxx_patch0_func, 103, 2, 1 }, + { aic7xxx_patch7_func, 107, 2, 1 }, + { aic7xxx_patch9_func, 109, 1, 1 }, + { aic7xxx_patch10_func, 110, 2, 1 }, + { aic7xxx_patch7_func, 113, 1, 2 }, + { aic7xxx_patch0_func, 114, 1, 1 }, + { aic7xxx_patch1_func, 118, 1, 1 }, + { aic7xxx_patch1_func, 121, 3, 2 }, + { aic7xxx_patch0_func, 124, 5, 1 }, + { aic7xxx_patch1_func, 132, 2, 3 }, + { aic7xxx_patch7_func, 132, 1, 1 }, + { aic7xxx_patch0_func, 134, 3, 1 }, + { aic7xxx_patch11_func, 138, 1, 2 }, + { aic7xxx_patch0_func, 139, 1, 1 }, + { aic7xxx_patch7_func, 140, 7, 2 }, + { aic7xxx_patch0_func, 147, 1, 1 }, + { aic7xxx_patch1_func, 152, 14, 3 }, + { aic7xxx_patch11_func, 165, 1, 1 }, + { aic7xxx_patch0_func, 166, 9, 1 }, + { aic7xxx_patch7_func, 180, 2, 1 }, + { aic7xxx_patch7_func, 182, 1, 1 }, + { aic7xxx_patch11_func, 183, 6, 3 }, + { aic7xxx_patch1_func, 183, 2, 2 }, + { aic7xxx_patch0_func, 185, 4, 1 }, + { aic7xxx_patch7_func, 190, 1, 1 }, + { aic7xxx_patch7_func, 194, 20, 1 }, + { aic7xxx_patch1_func, 215, 3, 3 }, + { aic7xxx_patch11_func, 217, 1, 1 }, + { aic7xxx_patch0_func, 218, 5, 1 }, + { aic7xxx_patch11_func, 223, 1, 2 }, + { aic7xxx_patch0_func, 224, 9, 1 }, + { aic7xxx_patch12_func, 240, 1, 2 }, + { aic7xxx_patch0_func, 241, 1, 1 }, + { aic7xxx_patch4_func, 302, 1, 2 }, + { aic7xxx_patch0_func, 303, 1, 1 }, + { aic7xxx_patch2_func, 306, 1, 1 }, + { aic7xxx_patch1_func, 316, 3, 2 }, + { aic7xxx_patch0_func, 319, 5, 1 }, + { aic7xxx_patch12_func, 327, 1, 2 }, + { aic7xxx_patch0_func, 328, 1, 1 }, + { aic7xxx_patch5_func, 333, 1, 1 }, + { aic7xxx_patch11_func, 375, 15, 1 }, + { aic7xxx_patch1_func, 427, 7, 2 }, + { aic7xxx_patch0_func, 434, 8, 1 }, + { aic7xxx_patch1_func, 443, 4, 2 }, + { aic7xxx_patch0_func, 447, 6, 1 }, + { aic7xxx_patch1_func, 453, 4, 2 }, + { aic7xxx_patch0_func, 457, 3, 1 }, + { aic7xxx_patch10_func, 467, 10, 1 }, + { aic7xxx_patch1_func, 486, 17, 4 }, + { aic7xxx_patch9_func, 494, 4, 2 }, + { aic7xxx_patch0_func, 498, 2, 1 }, + { aic7xxx_patch0_func, 503, 33, 1 }, + { aic7xxx_patch10_func, 536, 4, 1 }, + { aic7xxx_patch5_func, 540, 2, 1 }, + { aic7xxx_patch5_func, 543, 9, 1 }, }; diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c index 9c93fd674d6a..4fd92ebe8cc4 100644 --- a/drivers/scsi/sym53c8xx.c +++ b/drivers/scsi/sym53c8xx.c @@ -9021,7 +9021,7 @@ fail: ** code will get more complex later). */ -#ifdef SCSI_NCR_USE_64BIT_DAC +#if BITS_PER_LONG > 32 #define SCATTER_ONE(data, badd, len) \ (data)->addr = cpu_to_scr(badd); \ (data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); diff --git a/drivers/sound/ac97_codec.c b/drivers/sound/ac97_codec.c index 8cb577212ebe..751370135f0a 100644 --- a/drivers/sound/ac97_codec.c +++ b/drivers/sound/ac97_codec.c @@ -530,6 +530,11 @@ int ac97_probe_codec(struct ac97_codec *codec) /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should be read zero. Probing of AC97 in this way is not reliable, it is not even SAFE !! */ codec->codec_write(codec, AC97_RESET, 0L); + + /* We need a codec->codec_reset() function here but the delay is a + reasonable hack for the moment */ + + schedule_timeout((5*HZ)/100); if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) { printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n", codec->id ? "Secondary" : "Primary"); diff --git a/drivers/sound/i810_audio.c b/drivers/sound/i810_audio.c index b6675080a7ba..8554ed483d44 100644 --- a/drivers/sound/i810_audio.c +++ b/drivers/sound/i810_audio.c @@ -46,6 +46,18 @@ * There is no midi support, no synth support. Use timidity. To get * esd working you need to use esd -r 48000 as it won't probe 48KHz * by default. mpg123 can't handle 48Khz only audio so use xmms. + * + * Fix The Sound On Dell + * + * Not everyone uses 48KHz. We know of no way to detect this reliably + * and certainly not to get the right data. If your i810 audio sounds + * stupid you may need to investigate other speeds. According to Analog + * they tend to use a 14.318MHz clock which gives you a base rate of + * 41194Hz. + * + * This is available via the 'ftsodell=1' option. + * + * If you need to force a specific rate set the clocking= option */ #include @@ -74,10 +86,16 @@ #ifndef PCI_DEVICE_ID_INTEL_82901 #define PCI_DEVICE_ID_INTEL_82901 0x2425 #endif +#ifndef PCI_DEVICE_ID_INTEL_ICH2 +#define PCI_DEVICE_ID_INTEL_ICH2 0x2445 +#endif #ifndef PCI_DEVICE_ID_INTEL_440MX #define PCI_DEVICE_ID_INTEL_440MX 0x7195 #endif +static int ftsodell=0; +static int clocking=48000; + #define ADC_RUNNING 1 #define DAC_RUNNING 2 @@ -180,7 +198,8 @@ static const unsigned sample_shift[] = { 0, 1, 1, 2 }; enum { ICH82801AA = 0, ICH82901AB, - INTEL440MX + INTEL440MX, + INTELICH2 }; /* "software" or virtual channel, an instance of opened /dev/dsp */ @@ -345,14 +364,26 @@ static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int ra if(!(state->card->ac97_features&0x0001)) { - dmabuf->rate=48000; - return 48000; + dmabuf->rate=clocking; + return clocking; } if (rate > 48000) rate = 48000; - if (rate < 4000) - rate = 4000; + if (rate < 8000) + rate = 8000; + + /* + * Adjust for misclocked crap + */ + + rate = ( rate * clocking)/48000; + + /* Analog codecs can go lower via magic registers but others + might not */ + + if(rate < 8000) + rate = 8000; /* Power down the DAC */ dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); @@ -365,7 +396,7 @@ static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int ra // printk("DAC rate set to %d Returned %d\n", // rate, (int)rp); - rate=rp; + rate=(rp*48000) / clocking; /* Power it back up */ i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); @@ -387,14 +418,26 @@ static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int ra if(!(state->card->ac97_features&0x0001)) { - dmabuf->rate = 48000; - return 48000; + dmabuf->rate = clocking; + return clocking; } if (rate > 48000) rate = 48000; - if (rate < 4000) - rate = 4000; + if (rate < 8000) + rate = 8000; + + /* + * Adjust for misclocked crap + */ + + rate = ( rate * clocking)/48000; + + /* Analog codecs can go lower via magic registers but others + might not */ + + if(rate < 8000) + rate = 8000; /* Power down the ADC */ dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); @@ -407,7 +450,7 @@ static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int ra // printk("ADC rate set to %d Returned %d\n", // rate, (int)rp); - rate=rp; + rate = (rp * 48000) / clocking; /* Power it back up */ i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); @@ -1806,6 +1849,8 @@ static void i810_remove(struct i810_card *card) MODULE_AUTHOR("Assorted"); MODULE_DESCRIPTION("Intel 810 audio support"); +MODULE_PARM(ftsodell, "i"); +MODULE_PARM(clocking, "i"); int __init i810_probe(void) { @@ -1815,6 +1860,9 @@ int __init i810_probe(void) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; + if(ftsodell=1) + clocking=41194; + printk(KERN_INFO "Intel 810 + AC97 Audio, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); @@ -1831,6 +1879,11 @@ int __init i810_probe(void) foundone++; } + while( (pcidev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH2, pcidev))!=NULL ) { + if (i810_install(pcidev, INTELICH2, "Intel ICH2")==0) + foundone++; + } + printk(KERN_INFO "i810_audio: Found %d audio device(s).\n", foundone); return foundone; diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index 1e0ae9c0dd1e..eaa3c9928a71 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c @@ -1,10 +1,10 @@ -/* +/**************************************************************************** * ixj.c * * Device Driver for the Internet PhoneJACK and * Internet LineJACK Telephony Cards. * - * (c) Copyright 1999 Quicknet Technologies, Inc. + * (c) Copyright 1999-2000 Quicknet Technologies, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -12,25 +12,42 @@ * 2 of the License, or (at your option) any later version. * * Author: Ed Okerson, - * + * * Contributors: Greg Herlein, * David W. Erhart, * John Sellers, * Mike Preston, - * + * * Fixes: - * - * More information about the hardware related to this driver can be found + * + * More information about the hardware related to this driver can be found * at our website: http://www.quicknet.net * - */ + * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET + * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION + * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + ***************************************************************************/ -static char ixj_c_rcsid[] = "$Id: ixj.c,v 3.4 1999/12/16 22:18:36 root Exp root $"; +static char ixj_c_rcsid[] = "$Id: ixj.c,v 3.31 2000/04/14 19:24:47 jaugenst Exp $"; +static char ixj_c_revision[] = "$Revision: 3.31 $"; //#define PERFMON_STATS #define IXJDEBUG 0 #define MAXRINGS 5 +#ifdef CONFIG_PCMCIA +#include +#include +#endif + #include #include @@ -54,8 +71,18 @@ static char ixj_c_rcsid[] = "$Id: ixj.c,v 3.4 1999/12/16 22:18:36 root Exp root #include #ifdef CONFIG_ISAPNP -#include "../pnp/pnpio.h" -#include "../pnp/isapnp.h" +#include "../isapnp/pnpio.h" +#include "../isapnp/isapnp.h" +#endif + +#ifdef CONFIG_PCMCIA +#include +#include +#include +#include +#include +#include +#include #endif #include "ixj.h" @@ -100,14 +127,17 @@ static void ixj_read_frame(int board); static void ixj_write_frame(int board); static void ixj_init_timer(void); static void ixj_add_timer(void); -static void ixj_del_timer(void); static void ixj_timeout(unsigned long ptr); static int read_filters(int board); static int LineMonitor(int board); static int ixj_fasync(int fd, struct file *, int mode); +static int ixj_set_port(int board, int arg); +static int ixj_set_pots(int board, int arg); static int ixj_hookstate(int board); static int ixj_record_start(int board); static void ixj_record_stop(int board); +static void set_rec_volume(int board, int volume); +static void ixj_vad(int board, int arg); static int ixj_play_start(int board); static void ixj_play_stop(int board); static int ixj_set_tone_on(unsigned short arg, int board); @@ -124,6 +154,7 @@ static void ixj_cpt_stop(int board); static char daa_int_read(int board); static int daa_set_mode(int board, int mode); static int ixj_linetest(int board); +static int ixj_daa_write(int board); static int ixj_daa_cid_read(int board); static void DAA_Coeff_US(int board); static void DAA_Coeff_UK(int board); @@ -134,12 +165,18 @@ static void DAA_Coeff_Japan(int board); static int ixj_init_filter(int board, IXJ_FILTER * jf); static int ixj_init_tone(int board, IXJ_TONE * ti); static int ixj_build_cadence(int board, IXJ_CADENCE * cp); +static int ixj_build_filter_cadence(int board, IXJ_FILTER_CADENCE * cp); // Serial Control Interface funtions static int SCI_Control(int board, int control); static int SCI_Prepare(int board); static int SCI_WaitHighSCI(int board); static int SCI_WaitLowSCI(int board); static DWORD PCIEE_GetSerialNumber(WORD wAddress); +static int ixj_PCcontrol_wait(int board); +static void ixj_write_cid(int board); +static void ixj_write_cid_bit(int board, int bit); +static int set_base_frame(int board, int size); +static int set_play_codec(int board, int rate); /************************************************************************ CT8020/CT8021 Host Programmers Model @@ -160,12 +197,19 @@ extern __inline__ void ixj_read_HSR(int board) ixj[board].hsr.bytes.low = inb_p(ixj[board].DSPbase + 8); ixj[board].hsr.bytes.high = inb_p(ixj[board].DSPbase + 9); } + extern __inline__ int IsControlReady(int board) { ixj_read_HSR(board); return ixj[board].hsr.bits.controlrdy ? 1 : 0; } +extern __inline__ int IsPCControlReady(int board) +{ + ixj[board].pccr1.byte = inb_p(ixj[board].XILINXbase + 3); + return ixj[board].pccr1.bits.crr ? 1 : 0; +} + extern __inline__ int IsStatusReady(int board) { ixj_read_HSR(board); @@ -175,21 +219,54 @@ extern __inline__ int IsStatusReady(int board) extern __inline__ int IsRxReady(int board) { ixj_read_HSR(board); +#ifdef PERFMON_STATS + ++ixj[board].rxreadycheck; +#endif return ixj[board].hsr.bits.rxrdy ? 1 : 0; } extern __inline__ int IsTxReady(int board) { ixj_read_HSR(board); +#ifdef PERFMON_STATS + ++ixj[board].txreadycheck; +#endif return ixj[board].hsr.bits.txrdy ? 1 : 0; } +extern __inline__ void set_play_volume(int board, int volume) +{ + ixj_WriteDSPCommand(0xCF02, board); + ixj_WriteDSPCommand(volume, board); +} + +extern __inline__ int get_play_volume(int board) +{ + ixj_WriteDSPCommand(0xCF00, board); + return ixj[board].ssr.high << 8 | ixj[board].ssr.low; +} + extern __inline__ BYTE SLIC_GetState(int board) { IXJ *j = &ixj[board]; - j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01); - + if (j->cardtype == 600) { + j->pccr1.byte = 0; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 1; + outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(board); + j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF; + ixj_PCcontrol_wait(board); + if (j->pslic.bits.powerdown) + return PLD_SLIC_STATE_OC; + else if (!j->pslic.bits.ring0 && !j->pslic.bits.ring1) + return PLD_SLIC_STATE_ACTIVE; + else + return PLD_SLIC_STATE_RINGING; + } else { + j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01); + } return j->pld_slicr.bits.state; } @@ -198,78 +275,122 @@ static BOOL SLIC_SetState(BYTE byState, int board) BOOL fRetVal = FALSE; IXJ *j = &ixj[board]; - // Set the C1, C2, C3 & B2EN signals. - switch (byState) { - case PLD_SLIC_STATE_OC: - j->pld_slicw.bits.c1 = 0; - j->pld_slicw.bits.c2 = 0; - j->pld_slicw.bits.c3 = 0; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = TRUE; - break; - case PLD_SLIC_STATE_RINGING: - j->pld_slicw.bits.c1 = 1; - j->pld_slicw.bits.c2 = 0; - j->pld_slicw.bits.c3 = 0; - j->pld_slicw.bits.b2en = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = TRUE; - break; - case PLD_SLIC_STATE_ACTIVE: - j->pld_slicw.bits.c1 = 0; - j->pld_slicw.bits.c2 = 1; - j->pld_slicw.bits.c3 = 0; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = TRUE; - break; - case PLD_SLIC_STATE_OHT: // On-hook transmit + if (j->cardtype == 600) { + if (j->flags.pcmciasct) { + switch (byState) { + case PLD_SLIC_STATE_TIPOPEN: + case PLD_SLIC_STATE_OC: + j->pslic.bits.powerdown = 1; + j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0; + fRetVal = TRUE; + break; + case PLD_SLIC_STATE_RINGING: + if (j->readers || j->writers) { + j->pslic.bits.powerdown = 0; + j->pslic.bits.ring0 = 1; + j->pslic.bits.ring1 = 0; + fRetVal = TRUE; + } + break; + case PLD_SLIC_STATE_OHT: // On-hook transmit - j->pld_slicw.bits.c1 = 1; - j->pld_slicw.bits.c2 = 1; - j->pld_slicw.bits.c3 = 0; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = TRUE; - break; - case PLD_SLIC_STATE_TIPOPEN: - j->pld_slicw.bits.c1 = 0; - j->pld_slicw.bits.c2 = 0; - j->pld_slicw.bits.c3 = 1; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = TRUE; - break; - case PLD_SLIC_STATE_STANDBY: - j->pld_slicw.bits.c1 = 1; - j->pld_slicw.bits.c2 = 0; - j->pld_slicw.bits.c3 = 1; - j->pld_slicw.bits.b2en = 1; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = TRUE; - break; - case PLD_SLIC_STATE_APR: // Active polarity reversal + case PLD_SLIC_STATE_STANDBY: + case PLD_SLIC_STATE_ACTIVE: + if (j->readers || j->writers) { + j->pslic.bits.powerdown = 0; + } else { + j->pslic.bits.powerdown = 1; + } + j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0; + fRetVal = TRUE; + break; + case PLD_SLIC_STATE_APR: // Active polarity reversal - j->pld_slicw.bits.c1 = 0; - j->pld_slicw.bits.c2 = 1; - j->pld_slicw.bits.c3 = 1; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = TRUE; - break; - case PLD_SLIC_STATE_OHTPR: // OHT polarity reversal + case PLD_SLIC_STATE_OHTPR: // OHT polarity reversal - j->pld_slicw.bits.c1 = 1; - j->pld_slicw.bits.c2 = 1; - j->pld_slicw.bits.c3 = 1; - j->pld_slicw.bits.b2en = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - fRetVal = TRUE; - break; - default: - fRetVal = FALSE; - break; + default: + fRetVal = FALSE; + break; + } + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 0; + outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(board); + } + } else { + // Set the C1, C2, C3 & B2EN signals. + switch (byState) { + case PLD_SLIC_STATE_OC: + j->pld_slicw.bits.c1 = 0; + j->pld_slicw.bits.c2 = 0; + j->pld_slicw.bits.c3 = 0; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = TRUE; + break; + case PLD_SLIC_STATE_RINGING: + j->pld_slicw.bits.c1 = 1; + j->pld_slicw.bits.c2 = 0; + j->pld_slicw.bits.c3 = 0; + j->pld_slicw.bits.b2en = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = TRUE; + break; + case PLD_SLIC_STATE_ACTIVE: + j->pld_slicw.bits.c1 = 0; + j->pld_slicw.bits.c2 = 1; + j->pld_slicw.bits.c3 = 0; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = TRUE; + break; + case PLD_SLIC_STATE_OHT: // On-hook transmit + + j->pld_slicw.bits.c1 = 1; + j->pld_slicw.bits.c2 = 1; + j->pld_slicw.bits.c3 = 0; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = TRUE; + break; + case PLD_SLIC_STATE_TIPOPEN: + j->pld_slicw.bits.c1 = 0; + j->pld_slicw.bits.c2 = 0; + j->pld_slicw.bits.c3 = 1; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = TRUE; + break; + case PLD_SLIC_STATE_STANDBY: + j->pld_slicw.bits.c1 = 1; + j->pld_slicw.bits.c2 = 0; + j->pld_slicw.bits.c3 = 1; + j->pld_slicw.bits.b2en = 1; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = TRUE; + break; + case PLD_SLIC_STATE_APR: // Active polarity reversal + + j->pld_slicw.bits.c1 = 0; + j->pld_slicw.bits.c2 = 1; + j->pld_slicw.bits.c3 = 1; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = TRUE; + break; + case PLD_SLIC_STATE_OHTPR: // OHT polarity reversal + + j->pld_slicw.bits.c1 = 1; + j->pld_slicw.bits.c2 = 1; + j->pld_slicw.bits.c3 = 1; + j->pld_slicw.bits.b2en = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + fRetVal = TRUE; + break; + default: + fRetVal = FALSE; + break; + } } return fRetVal; @@ -361,51 +482,42 @@ static void ixj_add_timer(void) add_timer(&ixj_timer); } -static void ixj_del_timer(void) -{ - del_timer(&ixj_timer); -} - static void ixj_tone_timeout(int board) { IXJ *j = &ixj[board]; IXJ_TONE ti; - + j->tone_state++; if (j->tone_state == 3) { j->tone_state = 0; if (j->cadence_t) { j->tone_cadence_state++; - if (j->tone_cadence_state >= j->cadence_t->elements_used) - { - switch (j->cadence_t->termination) - { - case PLAY_ONCE: - ixj_cpt_stop(board); - break; - case REPEAT_LAST_ELEMENT: - j->tone_cadence_state--; - ixj_play_tone(board, j->cadence_t->ce[j->tone_cadence_state].index); - break; - case REPEAT_ALL: - j->tone_cadence_state = 0; - if (j->cadence_t->ce[j->tone_cadence_state].freq0) - { - ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index; - ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0; - ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0; - ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1; - ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1; - ixj_init_tone(board, &ti); - } - ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, board); - ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, board); - ixj_play_tone(board, j->cadence_t->ce[0].index); - break; + if (j->tone_cadence_state >= j->cadence_t->elements_used) { + switch (j->cadence_t->termination) { + case PLAY_ONCE: + ixj_cpt_stop(board); + break; + case REPEAT_LAST_ELEMENT: + j->tone_cadence_state--; + ixj_play_tone(board, j->cadence_t->ce[j->tone_cadence_state].index); + break; + case REPEAT_ALL: + j->tone_cadence_state = 0; + if (j->cadence_t->ce[j->tone_cadence_state].freq0) { + ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index; + ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0; + ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0; + ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1; + ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1; + ixj_init_tone(board, &ti); + } + ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, board); + ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, board); + ixj_play_tone(board, j->cadence_t->ce[0].index); + break; } } else { - if (j->cadence_t->ce[j->tone_cadence_state].gain0) - { + if (j->cadence_t->ce[j->tone_cadence_state].gain0) { ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index; ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0; ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0; @@ -421,50 +533,50 @@ static void ixj_tone_timeout(int board) } } +extern __inline__ void ixj_kill_fasync(int board) +{ + if (ixj[board].async_queue) + kill_fasync(ixj[board].async_queue, SIGIO); // Send apps notice of change + +} static void ixj_timeout(unsigned long ptr) { int board; unsigned long jifon; IXJ *j; - for (board = 0; board < IXJMAX; board++) - { + for (board = 0; board < IXJMAX; board++) { j = &ixj[board]; - if (j->DSPbase) - { + if (j->DSPbase) { #ifdef PERFMON_STATS j->timerchecks++; #endif - if (j->tone_state) - { - if (!ixj_hookstate(board)) - { + if (j->tone_state) { + if (!ixj_hookstate(board)) { ixj_cpt_stop(board); - if (j->m_hook) - { + if (j->m_hook) { j->m_hook = 0; j->ex.bits.hookstate = 1; - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO); // Send apps notice of change + ixj_kill_fasync(board); } - goto timer_end; + continue; } if (j->tone_state == 1) jifon = (hertz * j->tone_on_time * 25 / 100000); else jifon = (hertz * j->tone_on_time * 25 / 100000) + (hertz * j->tone_off_time * 25 / 100000); - if (jiffies < j->tone_start_jif + jifon) { + if (time_before(jiffies, j->tone_start_jif + jifon)) { if (j->tone_state == 1) { ixj_play_tone(board, j->tone_index); if (j->dsp.low == 0x20) { - goto timer_end; + continue; } } else { ixj_play_tone(board, 0); if (j->dsp.low == 0x20) { - goto timer_end; + continue; } } } else { @@ -475,13 +587,13 @@ static void ixj_timeout(unsigned long ptr) if (j->flags.busytone) { ixj_busytone(board); if (j->dsp.low == 0x20) { - goto timer_end; + continue; } } if (j->flags.ringback) { ixj_ringback(board); if (j->dsp.low == 0x20) { - goto timer_end; + continue; } } if (!j->tone_state) { @@ -498,7 +610,7 @@ static void ixj_timeout(unsigned long ptr) if (IsRxReady(board)) { ixj_read_frame(board); } - if (IsTxReady(board)) { + if (IsTxReady(board) && !j->flags.cidplay) { ixj_write_frame(board); } } @@ -507,7 +619,12 @@ static void ixj_timeout(unsigned long ptr) j->flags.cringing = 0; ixj_ring_off(board); } else { - if (jiffies - j->ring_cadence_jif >= (hertz/2)) { + if (jiffies - j->ring_cadence_jif >= (.5 * hertz)) { + if (j->flags.cidring && !j->flags.cidsent) { + j->flags.cidsent = 1; + ixj_write_cid(board); + j->flags.cidring = 0; + } j->ring_cadence_t--; if (j->ring_cadence_t == -1) j->ring_cadence_t = 15; @@ -517,16 +634,15 @@ static void ixj_timeout(unsigned long ptr) ixj_ring_on(board); } else { ixj_ring_off(board); + j->flags.cidring = 1; } - goto timer_end; + continue; } } if (!j->flags.ringing) { if (ixj_hookstate(board)) { - if ((j->dsp.low == 0x21 || j->dsp.low == 0x22 )&& - j->pld_slicr.bits.state != PLD_SLIC_STATE_ACTIVE) - // Internet LineJACK - { + if (j->dsp.low != 0x20 && + SLIC_GetState(board) != PLD_SLIC_STATE_ACTIVE) { SLIC_SetState(PLD_SLIC_STATE_ACTIVE, board); } LineMonitor(board); @@ -535,13 +651,12 @@ static void ixj_timeout(unsigned long ptr) j->proc_load = j->ssr.high << 8 | j->ssr.low; if (!j->m_hook) { j->m_hook = j->ex.bits.hookstate = 1; - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO); // Send apps notice of change + ixj_kill_fasync(board); } } else { - if ((j->dsp.low == 0x21 || j->dsp.low == 0x22) && - j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE) - // Internet LineJACK + if (j->dsp.low != 0x20 && + SLIC_GetState(board) == PLD_SLIC_STATE_ACTIVE) + // Internet LineJACK { SLIC_SetState(PLD_SLIC_STATE_STANDBY, board); } @@ -551,15 +666,14 @@ static void ixj_timeout(unsigned long ptr) if (j->m_hook) { j->m_hook = 0; j->ex.bits.hookstate = 1; - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO); // Send apps notice of change + ixj_kill_fasync(board); } } } - if (j->cardtype == 300) { + if (j->cardtype == 300 && !j->flags.incheck) { if (j->flags.pstn_present) { j->pld_scrr.byte = inb_p(j->XILINXbase); - if (jiffies >= j->pstn_sleeptil && j->pld_scrr.bits.daaflag) { + if (j->pld_scrr.bits.daaflag) { daa_int_read(board); if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.RING) { if (!j->flags.pstn_ringing) { @@ -568,22 +682,38 @@ static void ixj_timeout(unsigned long ptr) daa_set_mode(board, SOP_PU_RINGING); } } - if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { + if (time_after(jiffies, j->pstn_sleeptil) && j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { j->pstn_winkstart = 0; + j->pstn_ring_stop = 0; + ixj[board].pld_scrw.bits.led1 = 1; if (j->flags.pstn_ringing && !j->pstn_envelope) { + if (j->daa_mode != SOP_PU_RINGING) { + j->flags.pstn_ringing = 0; + } else { + ixj[board].pld_scrw.bits.led2 = 0; + j->pstn_envelope = 1; + j->pstn_ring_start = jiffies; + j->pstn_ring_stop = 0; + } j->ex.bits.pstn_ring = 0; - j->pstn_envelope = 1; - j->pstn_ring_start = jiffies; } + outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase); } else { - if (j->flags.pstn_ringing && j->pstn_envelope && - jiffies > j->pstn_ring_start + ((hertz * 15) / 10)) { - j->ex.bits.pstn_ring = 1; - j->pstn_envelope = 0; + ixj[board].pld_scrw.bits.led1 = 0; + ixj[board].pld_scrw.bits.led2 = 1; + outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase); + if (j->flags.pstn_ringing && j->pstn_envelope) { + if(!j->pstn_ring_stop) { + j->pstn_ring_stop = jiffies; + } else if (time_after(jiffies, j->pstn_ring_stop + ((hertz * 5) / 100))){ + j->pstn_ring_stop = 0; + j->ex.bits.pstn_ring = 1; + j->pstn_envelope = 0; + } } else if (j->daa_mode == SOP_PU_CONVERSATION) { if (!j->pstn_winkstart) { j->pstn_winkstart = jiffies; - } else if (jiffies > j->pstn_winkstart + (hertz * j->winktime / 1000)) { + } else if (time_after(jiffies, j->pstn_winkstart + (hertz * j->winktime / 1000))) { daa_set_mode(board, SOP_PU_SLEEP); j->pstn_winkstart = 0; j->ex.bits.pstn_wink = 1; @@ -620,13 +750,23 @@ static void ixj_timeout(unsigned long ptr) j->ex.bits.caller_id = 0; } if (!j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { + ixj[board].pld_scrw.bits.led1 = 0; + ixj[board].pld_scrw.bits.led2 = 1; + outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase); if (j->flags.pstn_ringing && j->pstn_envelope) { - j->ex.bits.pstn_ring = 1; - j->pstn_envelope = 0; + if(!j->pstn_ring_stop) { + j->pstn_ring_stop = jiffies; + } else if (time_after(jiffies, j->pstn_ring_stop + ((hertz * 5) / 100))){ + j->pstn_ring_stop = 0; + j->ex.bits.pstn_ring = 1; + j->pstn_envelope = 0; + } + ixj[board].pld_scrw.bits.led1 = 0; + outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase); } else if (j->daa_mode == SOP_PU_CONVERSATION) { if (!j->pstn_winkstart) { j->pstn_winkstart = jiffies; - } else if (jiffies > j->pstn_winkstart + (hertz * 320 / 1000)) { + } else if (time_after(jiffies, j->pstn_winkstart + (hertz * j->winktime / 1000))) { daa_set_mode(board, SOP_PU_SLEEP); j->pstn_winkstart = 0; j->ex.bits.pstn_wink = 1; @@ -636,19 +776,15 @@ static void ixj_timeout(unsigned long ptr) } } } - if ((j->ex.bits.f0 || j->ex.bits.f1 || j->ex.bits.f2 || j->ex.bits.f3) - && j->filter_cadence) { - } if (j->ex.bytes) { wake_up_interruptible(&j->poll_q); // Wake any blocked selects - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO); // Send apps notice of change + + ixj_kill_fasync(board); } } else { break; } } -timer_end: ixj_add_timer(); } @@ -665,6 +801,19 @@ static int ixj_status_wait(int board) return 0; } +static int ixj_PCcontrol_wait(int board) +{ + unsigned long jif; + + jif = jiffies; + while (!IsPCControlReady(board)) { + if (jiffies - jif > (60 * (hertz / 100))) { + return -1; + } + } + return 0; +} + int ixj_WriteDSPCommand(unsigned short cmd, int board) { BYTES bytes; @@ -710,7 +859,7 @@ extern __inline__ int ixj_gpio_read(int board) extern __inline__ void LED_SetState(int state, int board) { - if (ixj[board].dsp.low == 0x21) { + if (ixj[board].cardtype == 300) { ixj[board].pld_scrw.bits.led1 = state & 0x1 ? 1 : 0; ixj[board].pld_scrw.bits.led2 = state & 0x2 ? 1 : 0; ixj[board].pld_scrw.bits.led3 = state & 0x4 ? 1 : 0; @@ -748,12 +897,19 @@ static int ixj_set_port(int board, int arg) case PORT_POTS: j->port = PORT_POTS; switch (j->cardtype) { + case 600: + if (j->flags.pcmciasct == 1) + SLIC_SetState(PLD_SLIC_STATE_ACTIVE, board); + else + return 11; + break; case 500: j->pld_slicw.pcib.mic = 0; j->pld_slicw.pcib.spk = 0; outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); break; case 300: + ixj_set_pots(board, 0); if (ixj_WriteDSPCommand(0xC528, board)) /* Write CODEC config to Software Control Register */ return 2; @@ -791,12 +947,21 @@ static int ixj_set_port(int board, int arg) case PORT_SPEAKER: j->port = PORT_SPEAKER; switch (j->cardtype) { + case 600: + if (j->flags.pcmciasct) { + SLIC_SetState(PLD_SLIC_STATE_OC, board); +// while(SLIC_GetState(board) != PLD_SLIC_STATE_OC) { + // SLIC_SetState(PLD_SLIC_STATE_OC,board); + // } + } + break; case 500: j->pld_slicw.pcib.mic = 1; j->pld_slicw.pcib.spk = 1; outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); break; case 300: + ixj_set_pots(board, 0); break; case 100: j->gpio.bytes.high = 0x0B; @@ -861,8 +1026,7 @@ static void ixj_ring_on(int board) j->gpio.bits.gpio2 = 1; j->gpio.bits.gpio5 = 0; ixj_WriteDSPCommand(j->gpio.word, board); /* send the ring signal */ - } else // Internet LineJACK, Internet PhoneJACK Lite or - // Internet PhoneJACK PCI + } else // Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI { if (ixjdebug > 0) printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", board); @@ -871,6 +1035,212 @@ static void ixj_ring_on(int board) } } +static int ixj_pcmcia_cable_check(int board) +{ + IXJ *j = &ixj[board]; + + j->pccr1.byte = inb_p(j->XILINXbase + 0x03); + if (!j->flags.pcmciastate) { + j->pccr2.byte = inb_p(j->XILINXbase + 0x02); + if (j->pccr1.bits.drf || j->pccr2.bits.rstc) { + j->flags.pcmciastate = 4; + return 0; + } + if (j->pccr1.bits.ed) { + j->pccr1.bits.ed = 0; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 1; + outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(board); + j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF; + j->pslic.bits.led2 = j->pslic.bits.det ? 1 : 0; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 0; + outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(board); + return j->pslic.bits.led2 ? 1 : 0; + } else if (j->flags.pcmciasct) { + return j->r_hook; + } else { + return 1; + } + } else if (j->flags.pcmciastate == 4) { + if (!j->pccr1.bits.drf) { + j->flags.pcmciastate = 3; + } + return 0; + } else if (j->flags.pcmciastate == 3) { + j->pccr2.bits.pwr = 0; + j->pccr2.bits.rstc = 1; + outb_p(j->pccr2.byte, j->XILINXbase + 0x02); + j->checkwait = jiffies + hertz * 2; + j->flags.incheck = 1; + j->flags.pcmciastate = 2; + return 0; + } else if (j->flags.pcmciastate == 2) { + if (j->flags.incheck) { + if (time_before(jiffies, j->checkwait)) { + return 0; + } else { + j->flags.incheck = 0; + } + } + j->pccr2.bits.pwr = 0; + j->pccr2.bits.rstc = 0; + outb_p(j->pccr2.byte, j->XILINXbase + 0x02); + j->flags.pcmciastate = 1; + return 0; + } else if (j->flags.pcmciastate == 1) { + j->flags.pcmciastate = 0; + if (!j->pccr1.bits.drf) { + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 1; + outb_p(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(board); + j->flags.pcmciascp = 1; // Set Cable Present Flag + + j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03; // Get Cable Type + + if (j->flags.pcmciasct == 3) { + j->flags.pcmciastate = 4; + return 0; + } else if (j->flags.pcmciasct == 0) { + j->pccr2.bits.pwr = 1; + j->pccr2.bits.rstc = 0; + outb_p(j->pccr2.byte, j->XILINXbase + 0x02); + j->port = PORT_SPEAKER; + } else { + j->port = PORT_POTS; + } + j->sic1.bits.cpd = 0; // Chip Power Down + + j->sic1.bits.mpd = 0; // MIC Bias Power Down + + j->sic1.bits.hpd = 0; // Handset Bias Power Down + + j->sic1.bits.lpd = 0; // Line Bias Power Down + + j->sic1.bits.spd = 1; // Speaker Drive Power Down + + j->psccr.bits.addr = 1; // R/W Smart Cable Register Address + + j->psccr.bits.rw = 0; // Read / Write flag + + j->psccr.bits.dev = 0; + outb(j->sic1.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(board); + j->sic2.bits.al = 0; // Analog Loopback DAC analog -> ADC analog + + j->sic2.bits.dl2 = 0; // Digital Loopback DAC -> ADC one bit + + j->sic2.bits.dl1 = 0; // Digital Loopback ADC -> DAC one bit + + j->sic2.bits.pll = 0; // 1 = div 10, 0 = div 5 + + j->sic2.bits.hpd = 0; // HPF disable + + j->psccr.bits.addr = 2; // R/W Smart Cable Register Address + + j->psccr.bits.rw = 0; // Read / Write flag + + j->psccr.bits.dev = 0; + outb(j->sic2.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(board); + j->psccr.bits.addr = 3; // R/W Smart Cable Register Address + + j->psccr.bits.rw = 0; // Read / Write flag + + j->psccr.bits.dev = 0; + outb(0x00, j->XILINXbase + 0x00); // PLL Divide N1 + + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(board); + j->psccr.bits.addr = 4; // R/W Smart Cable Register Address + + j->psccr.bits.rw = 0; // Read / Write flag + + j->psccr.bits.dev = 0; + outb(0x09, j->XILINXbase + 0x00); // PLL Multiply M1 + + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(board); + j->sirxg.bits.lig = 1; // Line In Gain + + j->sirxg.bits.lim = 1; // Line In Mute + + j->sirxg.bits.mcg = 0; // MIC In Gain // was 3 + + j->sirxg.bits.mcm = 0; // MIC In Mute + + j->sirxg.bits.him = 0; // Handset In Mute + + j->sirxg.bits.iir = 1; // IIR + + j->psccr.bits.addr = 5; // R/W Smart Cable Register Address + + j->psccr.bits.rw = 0; // Read / Write flag + + j->psccr.bits.dev = 0; + outb(j->sirxg.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(board); + j->siadc.bits.hom = 0; // Handset Out Mute + + j->siadc.bits.lom = 0; // Line Out Mute + + j->siadc.bits.rxg = 23; //(0xC000 - 0x41C8) / 0x4EF; // RX PGA Gain + + j->psccr.bits.addr = 6; // R/W Smart Cable Register Address + + j->psccr.bits.rw = 0; // Read / Write flag + + j->psccr.bits.dev = 0; + outb(j->siadc.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(board); + j->sidac.bits.srm = 1; // Speaker Right Mute + + j->sidac.bits.slm = 1; // Speaker Left Mute + + j->sidac.bits.txg = (0xC000 - 0x45E4) / 0x5D3; // TX PGA Gain + + j->psccr.bits.addr = 7; // R/W Smart Cable Register Address + + j->psccr.bits.rw = 0; // Read / Write flag + + j->psccr.bits.dev = 0; + outb(j->sidac.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(board); + j->siaatt.bits.sot = 0; + j->psccr.bits.addr = 9; // R/W Smart Cable Register Address + + j->psccr.bits.rw = 0; // Read / Write flag + + j->psccr.bits.dev = 0; + outb(j->siaatt.byte, j->XILINXbase + 0x00); + outb(j->psccr.byte, j->XILINXbase + 0x01); + ixj_PCcontrol_wait(board); + + if (j->flags.pcmciasct == 1 && !j->readers && !j->writers) { + j->psccr.byte = j->pslic.byte = 0; + j->pslic.bits.powerdown = 1; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 0; + outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(board); + } + } + return 0; + } else { + j->flags.pcmciascp = 0; + return 0; + } + return 0; +} + static int ixj_hookstate(int board) { unsigned long det; @@ -887,12 +1257,9 @@ static int ixj_hookstate(int board) case 500: SLIC_GetState(board); if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE || - j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) - { - if (j->flags.ringing) - { - if(!in_interrupt()) - { + j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) { + if (j->flags.ringing) { + if (!in_interrupt()) { det = jiffies + (hertz / 50); while (time_before(jiffies, det)) { current->state = TASK_INTERRUPTIBLE; @@ -911,14 +1278,17 @@ static int ixj_hookstate(int board) fOffHook = j->pld_slicr.bits.det ? 1 : 0; } break; + case 600: + fOffHook = ixj_pcmcia_cable_check(board); + break; } if (j->r_hook != fOffHook) { j->r_hook = fOffHook; if (j->port != PORT_POTS) { j->ex.bits.hookstate = 1; - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO); // Send apps notice of change - + ixj_kill_fasync(board); + } else if (!fOffHook) { + j->flash_end = jiffies + (hertz / 10 * 6); } } if (j->port == PORT_PSTN && j->daa_mode == SOP_PU_CONVERSATION) @@ -930,7 +1300,10 @@ static int ixj_hookstate(int board) if (j->port == PORT_HANDSET) fOffHook |= 2; - return fOffHook; + if (fOffHook && time_before(jiffies, j->flash_end)) + return 0; + else + return fOffHook; } static void ixj_ring_off(board) @@ -952,7 +1325,7 @@ static void ixj_ring_off(board) if (ixjdebug > 0) printk(KERN_INFO "IXJ Ring Off\n"); - SLIC_SetState(PLD_SLIC_STATE_STANDBY, board); + SLIC_SetState(PLD_SLIC_STATE_STANDBY, board); SLIC_GetState(board); } @@ -1002,7 +1375,7 @@ static int ixj_ring(int board) } current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); - if(signal_pending(current)) + if (signal_pending(current)) break; } jif = jiffies + (3 * hertz); @@ -1013,7 +1386,7 @@ static int ixj_ring(int board) while (time_before(jiffies, det)) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); - if(signal_pending(current)) + if (signal_pending(current)) break; } if (ixj_hookstate(board) & 1) { @@ -1023,7 +1396,7 @@ static int ixj_ring(int board) } current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); - if(signal_pending(current)) + if (signal_pending(current)) break; } } @@ -1034,40 +1407,70 @@ static int ixj_ring(int board) int ixj_open(struct phone_device *p, struct file *file_p) { - IXJ *j = &ixj[p->board]; + IXJ *j = file_p->private_data = &ixj[p->board]; if (!j->DSPbase) return -ENODEV; - if (file_p->f_mode & FMODE_READ) - j->readers++; - if (file_p->f_mode & FMODE_WRITE) - j->writers++; + if (file_p->f_mode & FMODE_READ) { + if(!j->readers) { + j->readers++; + } else { + return -EBUSY; + } + } + + if (file_p->f_mode & FMODE_WRITE) { + if(!j->writers) { + j->writers++; + } else { + if (file_p->f_mode & FMODE_READ){ + j->readers--; + } + return -EBUSY; + } + } + if (j->cardtype == 600) { + j->pslic.bits.powerdown = 0; + j->psccr.bits.dev = 3; + j->psccr.bits.rw = 0; + outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00); + ixj_PCcontrol_wait(p->board); + } MOD_INC_USE_COUNT; if (ixjdebug > 0) -// printk(KERN_INFO "Opening board %d\n", NUM(inode->i_rdev)); printk(KERN_INFO "Opening board %d\n", p->board); + j->framesread = j->frameswritten = 0; return 0; } int ixj_release(struct inode *inode, struct file *file_p) { IXJ_TONE ti; - int board = NUM(inode->i_rdev); - IXJ *j = &ixj[board]; +// int board = NUM(inode->i_rdev); + IXJ *j = file_p->private_data; + int board = j->p.board; +// IXJ *j = &ixj[board]; if (ixjdebug > 0) printk(KERN_INFO "Closing board %d\n", NUM(inode->i_rdev)); daa_set_mode(board, SOP_PU_SLEEP); - ixj_set_port(board, PORT_POTS); + if (j->cardtype == 600) + ixj_set_port(board, PORT_SPEAKER); + else + ixj_set_port(board, PORT_POTS); aec_stop(board); ixj_play_stop(board); ixj_record_stop(board); + set_play_volume(board, 0x100); + set_rec_volume(board, 0x100); + ixj_ring_off(board); + // Restore the tone table to default settings. ti.tone_index = 10; ti.gain0 = 1; ti.freq0 = hz941; @@ -1176,6 +1579,10 @@ int ixj_release(struct inode *inode, struct file *file_p) idle(board); +// if(j->cardtype == 600) { // && j->flags.pcmciasct == 1 && j->readers == 1 && j->writers == 1) { + SLIC_SetState(PLD_SLIC_STATE_OC, board); +// } + if (file_p->f_mode & FMODE_READ) j->readers--; if (file_p->f_mode & FMODE_WRITE) @@ -1193,8 +1600,16 @@ int ixj_release(struct inode *inode, struct file *file_p) } j->rec_codec = j->play_codec = 0; j->rec_frame_size = j->play_frame_size = 0; + j->flags.cidsent = j->flags.cidring = 0; ixj_fasync(-1, file_p, 0); // remove from list of async notification + if(j->cardtype == 300 && !j->readers && !j->writers) { + ixj_set_port(board, PORT_PSTN); + ixj_set_pots(board, 1); + } + ixj_WriteDSPCommand(0x0FE3, board); // Put the DSP in 1/5 power mode. + + file_p->private_data = NULL; MOD_DEC_USE_COUNT; return 0; } @@ -1202,6 +1617,7 @@ int ixj_release(struct inode *inode, struct file *file_p) static int read_filters(int board) { unsigned short fc, cnt; + int var; IXJ *j = &ixj[board]; if (ixj_WriteDSPCommand(0x5144, board)) @@ -1213,6 +1629,11 @@ static int read_filters(int board) j->frame_count = fc; + if (j->dtmf_proc) + return 1; + + var = 10; + for (cnt = 0; cnt < 4; cnt++) { if (ixj_WriteDSPCommand(0x5154 + cnt, board)) return -1; @@ -1221,8 +1642,108 @@ static int read_filters(int board) return -1; j->filter_hist[cnt] = j->ssr.high << 8 | j->ssr.low; - if ((j->filter_hist[cnt] & 1 && !(j->filter_hist[cnt] & 2)) || - (j->filter_hist[cnt] & 2 && !(j->filter_hist[cnt] & 1))) { + + if (j->cadence_f[cnt].enable) { + if (j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) { + if (j->cadence_f[cnt].state == 0) { + j->cadence_f[cnt].state = 1; + j->cadence_f[cnt].on1min = jiffies + (j->cadence_f[cnt].on1 * hertz * (100 - var) / 10000); + j->cadence_f[cnt].on1dot = jiffies + (j->cadence_f[cnt].on1 * hertz * (100) / 10000); + j->cadence_f[cnt].on1max = jiffies + (j->cadence_f[cnt].on1 * hertz * (100 + var) / 10000); + } else if (j->cadence_f[cnt].state == 2 && + (time_after(jiffies, j->cadence_f[cnt].off1min) && + time_before(jiffies, j->cadence_f[cnt].off1max))) { + if (j->cadence_f[cnt].on2) { + j->cadence_f[cnt].state = 3; + j->cadence_f[cnt].on2min = jiffies + (j->cadence_f[cnt].on2 * hertz * (100 - var) / 10000); + j->cadence_f[cnt].on2dot = jiffies + (j->cadence_f[cnt].on2 * hertz * (100) / 10000); + j->cadence_f[cnt].on2max = jiffies + (j->cadence_f[cnt].on2 * hertz * (100 + var) / 10000); + } else { + j->cadence_f[cnt].state = 6; + } + } else if (j->cadence_f[cnt].state == 4 && + (time_after(jiffies, j->cadence_f[cnt].off2min) && + time_before(jiffies, j->cadence_f[cnt].off2max))) { + if (j->cadence_f[cnt].on2) { + j->cadence_f[cnt].state = 5; + j->cadence_f[cnt].on3min = jiffies + (j->cadence_f[cnt].on3 * hertz * (100 - var) / 10000); + j->cadence_f[cnt].on3dot = jiffies + (j->cadence_f[cnt].on3 * hertz * (100) / 10000); + j->cadence_f[cnt].on3max = jiffies + (j->cadence_f[cnt].on3 * hertz * (100 + var) / 10000); + } else { + j->cadence_f[cnt].state = 6; + } + } else { + j->cadence_f[cnt].state = 0; + } + } else if (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)) { + if (j->cadence_f[cnt].state == 1 && + (time_after(jiffies, j->cadence_f[cnt].on1min) && + time_before(jiffies, j->cadence_f[cnt].on1max))) { + j->cadence_f[cnt].state = 2; + j->cadence_f[cnt].off1min = jiffies + (j->cadence_f[cnt].off1 * hertz * (100 - var) / 10000); + j->cadence_f[cnt].off1max = jiffies + (j->cadence_f[cnt].off1 * hertz * (100 + var) / 10000); + } else if (j->cadence_f[cnt].state == 3 && + (time_after(jiffies, j->cadence_f[cnt].on2min) && + time_before(jiffies, j->cadence_f[cnt].on2max))) { + j->cadence_f[cnt].state = 4; + j->cadence_f[cnt].off2min = jiffies + (j->cadence_f[cnt].off2 * hertz * (100 - var) / 10000); + j->cadence_f[cnt].off2max = jiffies + (j->cadence_f[cnt].off2 * hertz * (100 + var) / 10000); + } else if (j->cadence_f[cnt].state == 5 && + (time_after(jiffies, j->cadence_f[cnt].on3min) && + time_before(jiffies, j->cadence_f[cnt].on3max))) { + j->cadence_f[cnt].state = 6; + j->cadence_f[cnt].off3min = jiffies + (j->cadence_f[cnt].off3 * hertz * (100 - var) / 10000); + j->cadence_f[cnt].off3max = jiffies + (j->cadence_f[cnt].off3 * hertz * (100 + var) / 10000); + } else { + j->cadence_f[cnt].state = 0; + } + } else { + switch(j->cadence_f[cnt].state) { + case 1: + if(time_after(jiffies, j->cadence_f[cnt].on1dot) && + !j->cadence_f[cnt].off1 && + !j->cadence_f[cnt].on2 && !j->cadence_f[cnt].off2 && + !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) { + j->cadence_f[cnt].state = 6; + } + break; + case 3: + if(time_after(jiffies, j->cadence_f[cnt].on2dot) && + !j->cadence_f[cnt].off2 && + !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) { + j->cadence_f[cnt].state = 6; + } + break; + case 5: + if(time_after(jiffies, j->cadence_f[cnt].on3dot) && + !j->cadence_f[cnt].off3) { + j->cadence_f[cnt].state = 6; + } + break; + } + } + } + if (j->cadence_f[cnt].state == 6) { + j->cadence_f[cnt].state = 0; + if (j->cadence_f[cnt].enable == 1) + j->cadence_f[cnt].enable = 0; + switch (cnt) { + case 0: + j->ex.bits.fc0 = 1; + break; + case 1: + j->ex.bits.fc1 = 1; + break; + case 2: + j->ex.bits.fc2 = 1; + break; + case 3: + j->ex.bits.fc3 = 1; + break; + } + } + if (j->filter_en[cnt] && ((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) || + (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)))) { switch (cnt) { case 0: j->ex.bits.f0 = 1; @@ -1263,11 +1784,16 @@ static int LineMonitor(int board) } if (j->dtmf_state && !j->dtmf.bits.dtmf_valid) // && j->dtmf_wp != j->dtmf_rp) { - j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current; - j->dtmf_wp++; - if (j->dtmf_wp == 79) - j->dtmf_wp = 0; - j->ex.bits.dtmf_ready = 1; + if(!j->flags.cidplay) { + j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current; + j->dtmf_wp++; + if (j->dtmf_wp == 79) + j->dtmf_wp = 0; + j->ex.bits.dtmf_ready = 1; + } + else if(j->dtmf_current == 25 || j->dtmf_current == 31) { + j->flags.cidcw_ack = 1; + } j->dtmf_state = 0; } j->dtmf_proc = 0; @@ -1282,26 +1808,38 @@ ssize_t ixj_read(struct file * file_p, char *buf, size_t length, loff_t * ppos) struct wait_queue wait = {current, NULL}; + if (j->flags.inread) + return -EALREADY; + + j->flags.inread = 1; + add_wait_queue(&j->read_q, &wait); current->state = TASK_INTERRUPTIBLE; mb(); while (!j->read_buffer_ready || (j->dtmf_state && j->flags.dtmf_oob)) { ++j->read_wait; + if(j->tone_state) { + j->flags.inread = 0; + return -EAGAIN; + } if (file_p->f_flags & O_NONBLOCK) { current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); + j->flags.inread = 0; return -EAGAIN; } if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) { current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); + j->flags.inread = 0; return 0; } interruptible_sleep_on(&j->read_q); if (signal_pending(current)) { current->state = TASK_RUNNING; remove_wait_queue(&j->read_q, &wait); + j->flags.inread = 0; return -EINTR; } } @@ -1311,10 +1849,13 @@ ssize_t ixj_read(struct file * file_p, char *buf, size_t length, loff_t * ppos) /* Don't ever copy more than the user asks */ i = copy_to_user(buf, j->read_buffer, min(length, j->read_buffer_size)); j->read_buffer_ready = 0; - if (i) + if (i) { + j->flags.inread = 0; return -EFAULT; - else + } else { + j->flags.inread = 0; return min(length, j->read_buffer_size); + } } ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length, @@ -1342,51 +1883,63 @@ ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length, return read_retval; } -ssize_t ixj_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos) +ssize_t ixj_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos) { unsigned long i = *ppos; - int board = NUM(file_p->f_dentry->d_inode->i_rdev); - IXJ *j = &ixj[board]; + IXJ *j = file_p->private_data; struct wait_queue wait = {current, NULL}; - add_wait_queue(&j->read_q, &wait); + if (j->flags.inwrite) + return -EALREADY; + + j->flags.inwrite = 1; + + add_wait_queue(&j->write_q, &wait); current->state = TASK_INTERRUPTIBLE; mb(); while (!j->write_buffers_empty) { ++j->write_wait; + if(j->tone_state) { + j->flags.inwrite = 0; + return -EAGAIN; + } if (file_p->f_flags & O_NONBLOCK) { current->state = TASK_RUNNING; - remove_wait_queue(&j->read_q, &wait); + remove_wait_queue(&j->write_q, &wait); + j->flags.inwrite = 0; return -EAGAIN; } if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) { current->state = TASK_RUNNING; - remove_wait_queue(&j->read_q, &wait); + remove_wait_queue(&j->write_q, &wait); + j->flags.inwrite = 0; return 0; } interruptible_sleep_on(&j->write_q); if (signal_pending(current)) { current->state = TASK_RUNNING; - remove_wait_queue(&j->read_q, &wait); + remove_wait_queue(&j->write_q, &wait); + j->flags.inwrite = 0; return -EINTR; } } current->state = TASK_RUNNING; - remove_wait_queue(&j->read_q, &wait); + remove_wait_queue(&j->write_q, &wait); if (j->write_buffer_wp + count >= j->write_buffer_end) j->write_buffer_wp = j->write_buffer; i = copy_from_user(j->write_buffer_wp, buf, min(count, j->write_buffer_size)); - if (i) + if (i) { + j->flags.inwrite = 0; return -EFAULT; - + } + j->flags.inwrite = 0; return min(count, j->write_buffer_size); } -ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count, - loff_t * ppos) +ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos) { int pre_retval; ssize_t write_retval = 0; @@ -1443,9 +1996,7 @@ static void ixj_read_frame(int board) *(j->read_buffer + cnt) = inb_p(j->DSPbase + 0x0E); *(j->read_buffer + cnt + 1) = inb_p(j->DSPbase + 0x0F); } -#ifdef PERFMON_STATS ++j->framesread; -#endif if (j->intercom != -1) { if (IsTxReady(j->intercom)) { for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) { @@ -1462,9 +2013,7 @@ static void ixj_read_frame(int board) outb_p(*(j->read_buffer + cnt), ixj[j->intercom].DSPbase + 0x0C); outb_p(*(j->read_buffer + cnt + 1), ixj[j->intercom].DSPbase + 0x0D); } -#ifdef PERFMON_STATS ++ixj[j->intercom].frameswritten; -#endif } } else { j->read_buffer_ready = 1; @@ -1472,13 +2021,472 @@ static void ixj_read_frame(int board) wake_up_interruptible(&j->poll_q); // Wake any blocked selects - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO); // Send apps notice of frame + ixj_kill_fasync(board); + } + } +} + +static short fsk[][6][20] = +{ + { + { + 0, 17846, 29934, 32364, 24351, 8481, -10126, -25465, -32587, -29196, + -16384, 1715, 19260, 30591, 32051, 23170, 6813, -11743, -26509, -32722 + }, + { + -28377, -14876, 3425, 20621, 31163, 31650, 21925, 5126, -13328, -27481, + -32767, -27481, -13328, 5126, 21925, 31650, 31163, 20621, 3425, -14876 + }, + { + -28377, -32722, -26509, -11743, 6813, 23170, 32051, 30591, 19260, 1715, + -16384, -29196, -32587, -25465, -10126, 8481, 24351, 32364, 29934, 17846 + }, + { + 0, -17846, -29934, -32364, -24351, -8481, 10126, 25465, 32587, 29196, + 16384, -1715, -19260, -30591, -32051, -23170, -6813, 11743, 26509, 32722 + }, + { + 28377, 14876, -3425, -20621, -31163, -31650, -21925, -5126, 13328, 27481, + 32767, 27481, 13328, -5126, -21925, -31650, -31163, -20621, -3425, 14876 + }, + { + 28377, 32722, 26509, 11743, -6813, -23170, -32051, -30591, -19260, -1715, + 16384, 29196, 32587, 25465, 10126, -8481, -24351, -32364, -29934, -17846 + } + }, + { + { + 0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126, + 0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126 + }, + { + -28377, -21925, -13328, -3425, 6813, 16384, 24351, 29934, 32587, 32051, + 28377, 21925, 13328, 3425, -6813, -16384, -24351, -29934, -32587, -32051 + }, + { + -28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925, + 28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925 + }, + { + 0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126, + 0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126 + }, + { + 28377, 21925, 13328, 3425, -6813, -16383, -24351, -29934, -32587, -32051, + -28377, -21925, -13328, -3425, 6813, 16383, 24351, 29934, 32587, 32051 + }, + { + 28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925, + -28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925 + } + } +}; + + +static void ixj_write_cid_bit(int board, int bit) +{ + int dly; + IXJ_WORD dat; + IXJ *j = &ixj[board]; + while (j->fskcnt < 20) { + if (!IsTxReady(board)) { + dly = 0; + while (!IsTxReady(board)) { + if (dly++ > 5) { + dly = 0; + // break; + // printk("CID delay\n"); + } + udelay(10); + } } + dat.word = j->fskdata[j->fskdcnt++] = + fsk[bit][j->fskz][j->fskcnt]; + outb_p(dat.bytes.low, j->DSPbase + 0x0C); + outb_p(dat.bytes.high, j->DSPbase + 0x0D); + j->fskcnt += 3; + } + j->fskcnt %= 20; + + if (!bit) + j->fskz++; + if (j->fskz >= 6) + j->fskz = 0; + +} + +static void ixj_write_cid_byte(int board, char byte) +{ + IXJ_CBYTE cb; + +// printk("Writing CID data %x - %c\n", byte, byte); + cb.cbyte = byte; + ixj_write_cid_bit(board, 0); + ixj_write_cid_bit(board, cb.cbits.b0 ? 1 : 0); + ixj_write_cid_bit(board, cb.cbits.b1 ? 1 : 0); + ixj_write_cid_bit(board, cb.cbits.b2 ? 1 : 0); + ixj_write_cid_bit(board, cb.cbits.b3 ? 1 : 0); + ixj_write_cid_bit(board, cb.cbits.b4 ? 1 : 0); + ixj_write_cid_bit(board, cb.cbits.b5 ? 1 : 0); + ixj_write_cid_bit(board, cb.cbits.b6 ? 1 : 0); + ixj_write_cid_bit(board, cb.cbits.b7 ? 1 : 0); + ixj_write_cid_bit(board, 1); +} + +static void ixj_write_cid_seize(int board) +{ + int cnt; + + for (cnt = 0; cnt < 150; cnt++) { + ixj_write_cid_bit(board, 0); + ixj_write_cid_bit(board, 1); + } + for (cnt = 0; cnt < 180; cnt++) { + ixj_write_cid_bit(board, 1); + } +} + +static void ixj_write_cidcw_seize(int board) +{ + int cnt; + + for (cnt = 0; cnt < 80; cnt++) { + ixj_write_cid_bit(board, 1); } } +static int ixj_write_cid_string(int board, char *s, int checksum) +{ + int cnt; + + for (cnt = 0; cnt < strlen(s); cnt++) { + ixj_write_cid_byte(board, s[cnt]); + checksum = (checksum + s[cnt]); + } + return checksum; +} + +static void ixj_pad_fsk(int board, int pad) +{ + int cnt, dly; + IXJ *j = &ixj[board]; + + for (cnt = 0; cnt < pad; cnt++) { + if (!IsTxReady(board)) { + dly = 0; + while (!IsTxReady(board)) { + if (dly++ > 5) { + dly = 0; + } + udelay(10); + } + } + outb_p(0x00, j->DSPbase + 0x0C); + outb_p(0x00, j->DSPbase + 0x0D); + } + for (cnt = 0; cnt < 720; cnt++) { + if (!IsTxReady(board)) { + dly = 0; + while (!IsTxReady(board)) { + if (dly++ > 5) { + dly = 0; + } + udelay(10); + } + } + outb_p(0x00, j->DSPbase + 0x0C); + outb_p(0x00, j->DSPbase + 0x0D); + } +} + +static void ixj_write_cid(int board) +{ + IXJ *j = &ixj[board]; + + char sdmf1[50]; + char sdmf2[50]; + char sdmf3[80]; + char mdmflen, len1, len2, len3; + int pad; + + int checksum = 0; + + if (ixj[board].dsp.low == 0x20) + return; + + ixj[board].fskz = ixj[board].fskphase = ixj[board].fskcnt = + ixj[board].fskdcnt = 0; + + ixj[board].flags.cidplay = 1; + + strcpy(sdmf1, j->cid_send.month); + strcat(sdmf1, j->cid_send.day); + strcat(sdmf1, j->cid_send.hour); + strcat(sdmf1, j->cid_send.min); + strcpy(sdmf2, j->cid_send.number); + strcpy(sdmf3, j->cid_send.name); + + len1 = strlen(sdmf1); + len2 = strlen(sdmf2); + len3 = strlen(sdmf3); + mdmflen = len1 + len2 + len3 + 6; + + printk("CID Lengths = %d %d %d %d\n", len1, len2, len3, mdmflen); + + set_base_frame(board, 30); + set_play_codec(board, LINEAR16); + + if (ixj[board].port == PORT_POTS) + if(!j->r_hook) + SLIC_SetState(PLD_SLIC_STATE_OHT, board); + + set_play_volume(board, 0x1B); + ixj_play_start(board); + ixj_write_cid_seize(board); + + ixj_write_cid_byte(board, 0x80); + checksum = 0x80; + ixj_write_cid_byte(board, mdmflen); + checksum = checksum + mdmflen; + + ixj_write_cid_byte(board, 0x01); + checksum = checksum + 0x01; + ixj_write_cid_byte(board, len1); + checksum = checksum + len1; + checksum = ixj_write_cid_string(board, sdmf1, checksum); + + ixj_write_cid_byte(board, 0x02); + checksum = checksum + 0x02; + ixj_write_cid_byte(board, len2); + checksum = checksum + len2; + checksum = ixj_write_cid_string(board, sdmf2, checksum); + + ixj_write_cid_byte(board, 0x07); + checksum = checksum + 0x07; + ixj_write_cid_byte(board, len3); + checksum = checksum + len3; + checksum = ixj_write_cid_string(board, sdmf3, checksum); + + checksum %= 256; + checksum ^= 0xFF; + checksum += 1; + printk("14Checksum = %d\n", checksum); + + ixj_write_cid_byte(board, (char) checksum); + + pad = j->fskdcnt % 240; + if (pad) { + pad = 240 - pad; + } + ixj_pad_fsk(board, pad); + SLIC_SetState(PLD_SLIC_STATE_STANDBY, board); + ixj[board].flags.cidplay = 0; + ixj_play_stop(board); +} + +static void ixj_write_cidcw(int board) +{ + IXJ_TONE ti; + + IXJ *j = &ixj[board]; + + char sdmf1[50]; + char sdmf2[50]; + char sdmf3[80]; + char mdmflen, len1, len2, len3; + int pad; + + int checksum = 0; + + if (ixj[board].dsp.low == 0x20) + return; + + ixj[board].fskz = ixj[board].fskphase = ixj[board].fskcnt = ixj[board].fskdcnt = 0; + + ixj[board].flags.cidplay = 1; + + ti.tone_index = 23; + ti.gain0 = 1; + ti.freq0 = hz440; + ti.gain1 = 0; + ti.freq1 = 0; + ixj_init_tone(board, &ti); + + ti.tone_index = 24; + ti.gain0 = 1; + ti.freq0 = hz2130; + ti.gain1 = 0; + ti.freq1 = hz2750; + ixj_init_tone(board, &ti); + + ixj_set_tone_on(1200, board); + ixj_play_tone(board, 23); + + while(j->tone_state) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + + ixj_set_tone_on(320, board); + ixj_play_tone(board, 24); + + while(j->tone_state) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + + j->cidcw_wait = jiffies + (200 * hertz / 100000); + + while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait)) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + + if(!j->flags.cidcw_ack) { + return; + } + + strcpy(sdmf1, j->cid_send.month); + strcat(sdmf1, j->cid_send.day); + strcat(sdmf1, j->cid_send.hour); + strcat(sdmf1, j->cid_send.min); + strcpy(sdmf2, j->cid_send.number); + strcpy(sdmf3, j->cid_send.name); + + len1 = strlen(sdmf1); + len2 = strlen(sdmf2); + len3 = strlen(sdmf3); + mdmflen = len1 + len2 + len3 + 6; + + printk("CID Lengths = %d %d %d %d\n", len1, len2, len3, mdmflen); + + j->cid_play_codec = j->play_codec; + ixj_play_stop(board); + + switch(j->baseframe.low) { + case 0xA0: + j->cid_base_frame_size = 20; + break; + case 0x50: + j->cid_base_frame_size = 10; + break; + default: + j->cid_base_frame_size = 30; + break; + } + set_base_frame(board, 30); + set_play_codec(board, LINEAR16); + + set_play_volume(board, 0x1B); + ixj_play_start(board); + ixj_write_cidcw_seize(board); + + ixj_write_cid_byte(board, 0x80); + checksum = 0x80; + ixj_write_cid_byte(board, mdmflen); + checksum = checksum + mdmflen; + + ixj_write_cid_byte(board, 0x01); + checksum = checksum + 0x01; + ixj_write_cid_byte(board, len1); + checksum = checksum + len1; + checksum = ixj_write_cid_string(board, sdmf1, checksum); + + ixj_write_cid_byte(board, 0x02); + checksum = checksum + 0x02; + ixj_write_cid_byte(board, len2); + checksum = checksum + len2; + checksum = ixj_write_cid_string(board, sdmf2, checksum); + + ixj_write_cid_byte(board, 0x07); + checksum = checksum + 0x07; + ixj_write_cid_byte(board, len3); + checksum = checksum + len3; + checksum = ixj_write_cid_string(board, sdmf3, checksum); + + checksum %= 256; + checksum ^= 0xFF; + checksum += 1; + printk("14Checksum = %d\n", checksum); + + ixj_write_cid_byte(board, (char) checksum); + + pad = j->fskdcnt % 240; + if (pad) { + pad = 240 - pad; + } + ixj_pad_fsk(board, pad); + ixj[board].flags.cidplay = 0; + ixj_play_stop(board); + + set_base_frame(board, j->cid_base_frame_size); + set_play_codec(board, j->cid_play_codec); +} + +static void ixj_write_vmwi(int board, int msg) +{ + IXJ *j = &ixj[board]; + + char mdmflen; + int pad; + + int checksum = 0; + + if (ixj[board].dsp.low == 0x20) + return; + + ixj[board].fskz = ixj[board].fskphase = ixj[board].fskcnt = ixj[board].fskdcnt = 0; + + ixj[board].flags.cidplay = 1; + + mdmflen = 3; + + set_base_frame(board, 30); + set_play_codec(board, LINEAR16); + + if (ixj[board].port == PORT_POTS) + SLIC_SetState(PLD_SLIC_STATE_OHT, board); + + set_play_volume(board, 0x1B); + ixj_play_start(board); + ixj_write_cid_seize(board); + + ixj_write_cid_byte(board, 0x82); + checksum = 0x82; + ixj_write_cid_byte(board, mdmflen); + checksum = checksum + mdmflen; + + ixj_write_cid_byte(board, 0x0B); + checksum = checksum + 0x0B; + ixj_write_cid_byte(board, 1); + checksum = checksum + 1; + + if(msg) { + ixj_write_cid_byte(board, 0xFF); + checksum = checksum + 0xFF; + } + else { + ixj_write_cid_byte(board, 0x00); + checksum = checksum + 0x00; + } + + checksum %= 256; + checksum ^= 0xFF; + checksum += 1; + + ixj_write_cid_byte(board, (char) checksum); + + pad = j->fskdcnt % 240; + if (pad) { + pad = 240 - pad; + } + ixj_pad_fsk(board, pad); + SLIC_SetState(PLD_SLIC_STATE_STANDBY, board); + ixj[board].flags.cidplay = 0; + ixj_play_stop(board); +} + static void ixj_write_frame(int board) { int cnt, frame_count, dly; @@ -1554,15 +2562,12 @@ static void ixj_write_frame(int board) j->write_buffer_rp = j->write_buffer; } j->write_buffers_empty++; - wake_up_interruptible(&(j->write_q)); // Wake any blocked writers + wake_up_interruptible(&j->write_q); // Wake any blocked writers wake_up_interruptible(&j->poll_q); // Wake any blocked selects - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO); // Send apps notice of empty buffer -#ifdef PERFMON_STATS + ixj_kill_fasync(board); ++j->frameswritten; -#endif } } else { j->drybuffer++; @@ -1795,6 +2800,12 @@ static int ixj_record_start(int board) unsigned short cmd = 0x0000; IXJ *j = &ixj[board]; + if (j->read_buffer) { + ixj_record_stop(board); + } + j->flags.recording = 1; + ixj_WriteDSPCommand(0x0FE0, board); // Put the DSP in full power mode. + if (!j->rec_mode) { switch (j->rec_codec) { case G723_63: @@ -1893,10 +2904,26 @@ static void ixj_record_stop(int board) { IXJ *j = &ixj[board]; + if (j->read_buffer) { + kfree(j->read_buffer); + j->read_buffer = NULL; + j->read_buffer_size = 0; + } if (j->rec_mode > -1) { ixj_WriteDSPCommand(0x5120, board); j->rec_mode = -1; } + j->flags.recording = 0; + if (!j->flags.playing) + ixj_WriteDSPCommand(0x0FE3, board); // Put the DSP in 1/5 power mode. + +} +static void ixj_vad(int board, int arg) +{ + if (arg) + ixj_WriteDSPCommand(0x513F, board); + else + ixj_WriteDSPCommand(0x513E, board); } static void set_rec_depth(int board, int depth) @@ -1911,16 +2938,26 @@ static void set_rec_depth(int board, int depth) static void set_rec_volume(int board, int volume) { ixj_WriteDSPCommand(0xCF03, board); - ixj_WriteDSPCommand(volume, board); + ixj_WriteDSPCommand(volume, board); +} + +static int get_rec_volume(int board) +{ + ixj_WriteDSPCommand(0xCF03, board); + return ixj[board].ssr.high << 8 | ixj[board].ssr.low; } static int get_rec_level(int board) { + int retval; + IXJ *j = &ixj[board]; ixj_WriteDSPCommand(0xCF88, board); - return j->ssr.high << 8 | j->ssr.low; + retval = j->ssr.high << 8 | j->ssr.low; + retval = (retval * 256) / 240; + return retval; } static void ixj_aec_start(int board, int level) @@ -1929,7 +2966,7 @@ static void ixj_aec_start(int board, int level) j->aec_level = level; if (!level) { - ixj_WriteDSPCommand(0xB002, board); + aec_stop(board); } else { if (j->rec_codec == G729 || j->play_codec == G729) { ixj_WriteDSPCommand(0xE022, board); // Move AEC filter buffer @@ -1941,26 +2978,41 @@ static void ixj_aec_start(int board, int level) ixj_WriteDSPCommand(0xE013, board); // Advanced AEC C1 switch (level) { - case 1: + case AEC_LOW: ixj_WriteDSPCommand(0x0000, board); // Advanced AEC C2 = off ixj_WriteDSPCommand(0xE011, board); ixj_WriteDSPCommand(0xFFFF, board); break; - case 2: + case AEC_MED: ixj_WriteDSPCommand(0x0600, board); // Advanced AEC C2 = on medium ixj_WriteDSPCommand(0xE011, board); ixj_WriteDSPCommand(0x0080, board); break; - case 3: + case AEC_HIGH: ixj_WriteDSPCommand(0x0C00, board); // Advanced AEC C2 = on high ixj_WriteDSPCommand(0xE011, board); ixj_WriteDSPCommand(0x0080, board); break; + + case AEC_AUTO: + ixj_WriteDSPCommand(0x0002, board); // Attenuation scaling factor of 2 + + ixj_WriteDSPCommand(0xE011, board); + ixj_WriteDSPCommand(0x0100, board); // Higher Threshold Floor + + ixj_WriteDSPCommand(0xE012, board); // Set Train and Lock + + ixj_WriteDSPCommand(0x0023, board); + + ixj_WriteDSPCommand(0xE014, board); + ixj_WriteDSPCommand(0x0003, board); // Lock threashold at 3dB + + break; } } } @@ -1974,7 +3026,7 @@ static void aec_stop(int board) ixj_WriteDSPCommand(0x0700, board); } - if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1) + if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1); { ixj_WriteDSPCommand(0xB002, board); // AEC Stop @@ -2148,6 +3200,12 @@ static int ixj_play_start(int board) unsigned short cmd = 0x0000; IXJ *j = &ixj[board]; + if (j->write_buffer) { + ixj_play_stop(board); + } + j->flags.playing = 1; + ixj_WriteDSPCommand(0x0FE0, board); // Put the DSP in full power mode. + j->flags.play_first_frame = 1; j->drybuffer = 0; @@ -2183,12 +3241,10 @@ static int ixj_play_start(int board) if (ixj_WriteDSPCommand(cmd, board)) return -1; } + j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC); if (!j->write_buffer) { - j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC); - if (!j->write_buffer) { - printk("Write buffer allocation for ixj board %d failed!\n", board); - return -ENOMEM; - } + printk("Write buffer allocation for ixj board %d failed!\n", board); + return -ENOMEM; } j->write_buffers_empty = 2; j->write_buffer_size = j->play_frame_size * 2; @@ -2250,11 +3306,20 @@ static void ixj_play_stop(int board) { IXJ *j = &ixj[board]; + if (j->write_buffer) { + kfree(j->write_buffer); + j->write_buffer = NULL; + j->write_buffer_size = 0; + } if (j->play_mode > -1) { - ixj_WriteDSPCommand(0x5221, board); // Stop playback + ixj_WriteDSPCommand(0x5221, board); // Stop playback and flush buffers. 8022 reference page 9-40 j->play_mode = -1; } + j->flags.playing = 0; + if (!j->flags.recording) + ixj_WriteDSPCommand(0x0FE3, board); // Put the DSP in 1/5 power mode. + } extern __inline__ void set_play_depth(int board, int depth) @@ -2266,16 +3331,15 @@ extern __inline__ void set_play_depth(int board, int depth) ixj_WriteDSPCommand(0x5280 + depth, board); } -extern __inline__ void set_play_volume(int board, int volume) -{ - ixj_WriteDSPCommand(0xCF02, board); - ixj_WriteDSPCommand(volume, board); -} - extern __inline__ int get_play_level(int board) { - ixj_WriteDSPCommand(0xCF8F, board); + int retval; + + ixj_WriteDSPCommand(0xCF8F, board); // 8022 Reference page 9-38 return ixj[board].ssr.high << 8 | ixj[board].ssr.low; + retval = ixj[board].ssr.high << 8 | ixj[board].ssr.low; + retval = (retval * 256) / 240; + return retval; } static unsigned int ixj_poll(struct file *file_p, poll_table * wait) @@ -2484,6 +3548,8 @@ static int ixj_daa_cr4(int board, char reg) break; } + j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = reg; + switch (j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGX) { case 0: j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 0; @@ -2653,7 +3719,7 @@ static int ixj_daa_cid_read(int board) } pIn += 5, pOut += 4; } - memset(&j->cid, 0, sizeof(IXJ_CID)); + memset(&j->cid, 0, sizeof(PHONE_CID)); pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID; pOut += 4; strncpy(j->cid.month, pOut, 2); @@ -2729,7 +3795,6 @@ static int daa_set_mode(int board, int mode) // ALIS-A part. // - BYTES bytes; IXJ *j = &ixj[board]; @@ -2738,6 +3803,19 @@ static int daa_set_mode(int board, int mode) switch (mode) { case SOP_PU_SLEEP: + if(j->daa_mode == SOP_PU_CONVERSATION) + { + j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync + + outb_p(j->pld_scrw.byte, j->XILINXbase); + j->pld_slicw.bits.rly2 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + bytes.high = 0x10; + bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg; + daa_load(&bytes, board); + if (!SCI_Prepare(board)) + return 0; + } j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync outb_p(j->pld_scrw.byte, j->XILINXbase); @@ -2748,10 +3826,15 @@ static int daa_set_mode(int board, int mode) daa_load(&bytes, board); if (!SCI_Prepare(board)) return 0; + j->daa_mode = SOP_PU_SLEEP; j->flags.pstn_ringing = 0; - j->pstn_sleeptil = jiffies + (hertz * 3); - break; + j->ex.bits.pstn_ring = 0; + j->pstn_sleeptil = jiffies + (hertz / 2); + wake_up_interruptible(&j->read_q); // Wake any blocked readers + wake_up_interruptible(&j->write_q); // Wake any blocked writers + wake_up_interruptible(&j->poll_q); // Wake any blocked selects + break; case SOP_PU_RINGING: j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync @@ -3289,14 +4372,11 @@ static int ixj_daa_write(int board) int ixj_set_tone_off(unsigned short arg, int board) { ixj[board].tone_off_time = arg; - if (ixj_WriteDSPCommand(0x6E05, board)) // Set Tone Off Period return -1; - if (ixj_WriteDSPCommand(arg, board)) return -1; - return 0; } @@ -3305,7 +4385,6 @@ static int ixj_get_tone_on(int board) if (ixj_WriteDSPCommand(0x6E06, board)) // Get Tone On Period return -1; - return 0; } @@ -3314,7 +4393,6 @@ static int ixj_get_tone_off(int board) if (ixj_WriteDSPCommand(0x6E07, board)) // Get Tone Off Period return -1; - return 0; } @@ -3323,7 +4401,6 @@ static void ixj_busytone(int board) ixj[board].flags.ringback = 0; ixj[board].flags.dialtone = 0; ixj[board].flags.busytone = 1; - ixj_set_tone_on(0x07D0, board); ixj_set_tone_off(0x07D0, board); ixj_play_tone(board, 27); @@ -3334,13 +4411,11 @@ static void ixj_dialtone(int board) ixj[board].flags.ringback = 0; ixj[board].flags.dialtone = 1; ixj[board].flags.busytone = 0; - if (ixj[board].dsp.low == 0x20) { return; } else { ixj_set_tone_on(0xFFFF, board); ixj_set_tone_off(0x0000, board); - ixj_play_tone(board, 25); } } @@ -3348,28 +4423,24 @@ static void ixj_dialtone(int board) static void ixj_cpt_stop(board) { IXJ *j = &ixj[board]; - - j->flags.dialtone = 0; - j->flags.busytone = 0; - j->flags.ringback = 0; - - ixj_set_tone_on(0x0001, board); - ixj_set_tone_off(0x0000, board); - - ixj_play_tone(board, 0); - - j->tone_state = 0; - - ixj_del_timer(); - if (j->cadence_t) { - if (j->cadence_t->ce) { - kfree(j->cadence_t->ce); + if(j->tone_state) + { + j->flags.dialtone = 0; + j->flags.busytone = 0; + j->flags.ringback = 0; + ixj_set_tone_on(0x0001, board); + ixj_set_tone_off(0x0000, board); + ixj_play_tone(board, 0); + j->tone_state = 0; + if (j->cadence_t) { + if (j->cadence_t->ce) { + kfree(j->cadence_t->ce); + } + kfree(j->cadence_t); + j->cadence_t = NULL; } - kfree(j->cadence_t); - j->cadence_t = NULL; } - ixj_add_timer(); - if (j->dsp.low == 0x20 || (j->play_mode == -1 && j->rec_mode == -1)) + if (j->play_mode == -1 && j->rec_mode == -1) idle(board); if (j->play_mode != -1) ixj_play_start(board); @@ -3382,7 +4453,6 @@ static void ixj_ringback(int board) ixj[board].flags.busytone = 0; ixj[board].flags.dialtone = 0; ixj[board].flags.ringback = 1; - ixj_set_tone_on(0x0FA0, board); ixj_set_tone_off(0x2EE0, board); ixj_play_tone(board, 26); @@ -3399,14 +4469,11 @@ static int ixj_build_cadence(int board, IXJ_CADENCE * cp) IXJ_CADENCE_ELEMENT *lcep; IXJ_TONE ti; IXJ *j = &ixj[board]; - lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL); if (lcp == NULL) return -ENOMEM; - if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE))) return -EFAULT; - lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL); if (lcep == NULL) { kfree(lcp); @@ -3414,13 +4481,10 @@ static int ixj_build_cadence(int board, IXJ_CADENCE * cp) } if (copy_from_user(lcep, lcp->ce, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used)) return -EFAULT; - - if(j->cadence_t) - { + if (j->cadence_t) { kfree(j->cadence_t->ce); kfree(j->cadence_t); } - lcp->ce = (void *) lcep; j->cadence_t = lcp; j->tone_cadence_state = 0; @@ -3435,16 +4499,50 @@ static int ixj_build_cadence(int board, IXJ_CADENCE * cp) ixj_init_tone(board, &ti); } ixj_play_tone(board, lcp->ce[0].index); - return 1; } +static int ixj_build_filter_cadence(int board, IXJ_FILTER_CADENCE * cp) +{ + IXJ_FILTER_CADENCE *lcp; + IXJ *j = &ixj[board]; + lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL); + if (lcp == NULL) + return -ENOMEM; + if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE))) + return -EFAULT; + if (lcp->filter > 4) + return -1; + j->cadence_f[lcp->filter].state = 0; + j->cadence_f[lcp->filter].enable = lcp->enable; + j->filter_en[lcp->filter] = j->cadence_f[lcp->filter].en_filter = lcp->en_filter; + j->cadence_f[lcp->filter].on1 = lcp->on1; + j->cadence_f[lcp->filter].on1min = 0; + j->cadence_f[lcp->filter].on1max = 0; + j->cadence_f[lcp->filter].off1 = lcp->off1; + j->cadence_f[lcp->filter].off1min = 0; + j->cadence_f[lcp->filter].off1max = 0; + j->cadence_f[lcp->filter].on2 = lcp->on2; + j->cadence_f[lcp->filter].on2min = 0; + j->cadence_f[lcp->filter].on2max = 0; + j->cadence_f[lcp->filter].off2 = lcp->off2; + j->cadence_f[lcp->filter].off2min = 0; + j->cadence_f[lcp->filter].off2max = 0; + j->cadence_f[lcp->filter].on3 = lcp->on3; + j->cadence_f[lcp->filter].on3min = 0; + j->cadence_f[lcp->filter].on3max = 0; + j->cadence_f[lcp->filter].off3 = lcp->off3; + j->cadence_f[lcp->filter].off3min = 0; + j->cadence_f[lcp->filter].off3max = 0; + kfree(lcp); + return 0; +} + static void add_caps(int board) { IXJ *j = &ixj[board]; j->caps = 0; - - j->caplist[j->caps].cap = vendor; + j->caplist[j->caps].cap = PHONE_VENDOR_QUICKNET; strcpy(j->caplist[j->caps].desc, "Quicknet Technologies, Inc. (www.quicknet.net)"); j->caplist[j->caps].captype = vendor; j->caplist[j->caps].handle = j->caps++; @@ -3540,10 +4638,9 @@ static int capabilities_check(int board, struct phone_capability *pcreq) int cnt; IXJ *j = &ixj[board]; int retval = 0; - for (cnt = 0; cnt < j->caps; cnt++) { - if (pcreq->captype == j->caplist[cnt].captype && - pcreq->cap == j->caplist[cnt].cap) { + if (pcreq->captype == j->caplist[cnt].captype + && pcreq->cap == j->caplist[cnt].cap) { retval = 1; break; } @@ -3551,8 +4648,7 @@ static int capabilities_check(int board, struct phone_capability *pcreq) return retval; } -int ixj_ioctl(struct inode *inode, struct file *file_p, - unsigned int cmd, unsigned long arg) +int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg) { IXJ_TONE ti; IXJ_FILTER jf; @@ -3560,16 +4656,13 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, int board = NUM(inode->i_rdev); IXJ *j = &ixj[NUM(inode->i_rdev)]; int retval = 0; - if (ixjdebug > 1) printk(KERN_DEBUG "phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); if (minor >= IXJMAX) return -ENODEV; - /* * Check ioctls only root can use. */ - if (!capable(CAP_SYS_ADMIN)) { switch (cmd) { case IXJCTL_TESTRAM: @@ -3588,10 +4681,33 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, case IXJCTL_SERIAL: retval = j->serial; break; + case IXJCTL_VERSION: + if (copy_to_user((char *) arg, ixj_c_revision, strlen(ixj_c_revision))) + return -EFAULT; + break; case PHONE_RING_CADENCE: j->ring_cadence = arg; break; + case IXJCTL_CIDCW: + if(arg) { + copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID)); + } + else { + memcpy(&j->cid_send, 0, sizeof(PHONE_CID)); + } + ixj_write_cidcw(board); + break; + /* Binary compatbility */ + case OLD_PHONE_RING_START: + arg = 0; + /* Fall through */ case PHONE_RING_START: + if(arg) { + copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID)); + } + else { + memcpy(&j->cid_send, 0, sizeof(PHONE_CID)); + } ixj_ring_start(board); break; case PHONE_RING_STOP: @@ -3603,7 +4719,19 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, break; case PHONE_EXCEPTION: retval = j->ex.bytes; - j->ex.bytes &= 0x03; + j->ex.bits.flash = 0; + j->ex.bits.pstn_ring = 0; + j->ex.bits.caller_id = 0; + j->ex.bits.pstn_wink = 0; + j->ex.bits.f0 = 0; + j->ex.bits.f1 = 0; + j->ex.bits.f2 = 0; + j->ex.bits.f3 = 0; + j->ex.bits.fc0 = 0; + j->ex.bits.fc1 = 0; + j->ex.bits.fc2 = 0; + j->ex.bits.fc3 = 0; + j->ex.bits.reserved = 0; break; case PHONE_HOOKSTATE: j->ex.bits.hookstate = 0; @@ -3618,6 +4746,9 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, case PHONE_REC_CODEC: retval = set_rec_codec(board, arg); break; + case PHONE_VAD: + ixj_vad(board, arg); + break; case PHONE_REC_START: ixj_record_start(board); break; @@ -3628,7 +4759,13 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, set_rec_depth(board, arg); break; case PHONE_REC_VOLUME: - set_rec_volume(board, arg); + if(arg == -1) { + retval = get_rec_volume(board); + } + else { + set_rec_volume(board, arg); + retval = arg; + } break; case PHONE_REC_LEVEL: retval = get_rec_level(board); @@ -3646,7 +4783,7 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, retval = set_play_codec(board, arg); break; case PHONE_PLAY_START: - ixj_play_start(board); + retval = ixj_play_start(board); break; case PHONE_PLAY_STOP: ixj_play_stop(board); @@ -3655,7 +4792,13 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, set_play_depth(board, arg); break; case PHONE_PLAY_VOLUME: - set_play_volume(board, arg); + if(arg == -1) { + retval = get_play_volume(board); + } + else { + set_play_volume(board, arg); + retval = arg; + } break; case PHONE_PLAY_LEVEL: retval = get_play_level(board); @@ -3836,41 +4979,45 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, switch (arg) { case DAA_US: DAA_Coeff_US(board); - ixj_daa_write(board); + retval = ixj_daa_write(board); break; case DAA_UK: DAA_Coeff_UK(board); - ixj_daa_write(board); + retval = ixj_daa_write(board); break; case DAA_FRANCE: DAA_Coeff_France(board); - ixj_daa_write(board); + retval = ixj_daa_write(board); break; case DAA_GERMANY: DAA_Coeff_Germany(board); - ixj_daa_write(board); + retval = ixj_daa_write(board); break; case DAA_AUSTRALIA: DAA_Coeff_Australia(board); - ixj_daa_write(board); + retval = ixj_daa_write(board); break; case DAA_JAPAN: DAA_Coeff_Japan(board); - ixj_daa_write(board); + retval = ixj_daa_write(board); break; default: + retval = 1; break; } + j->country = arg; break; case IXJCTL_DAA_AGAIN: ixj_daa_cr4(board, arg | 0x02); break; case IXJCTL_PSTN_LINETEST: - case PHONE_PSTN_LINETEST: retval = ixj_linetest(board); break; + case IXJCTL_VMWI: + ixj_write_vmwi(board, arg); + break; case IXJCTL_CID: - if (copy_to_user((char *) arg, &j->cid, sizeof(IXJ_CID))) + if (copy_to_user((char *) arg, &j->cid, sizeof(PHONE_CID))) return -EFAULT; j->ex.bits.caller_id = 0; break; @@ -3891,7 +5038,7 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, break; case PHONE_CAPABILITIES_LIST: if (copy_to_user((char *) arg, j->caplist, sizeof(struct phone_capability) * j->caps)) - return -EFAULT; + return -EFAULT; break; case PHONE_CAPABILITIES_CHECK: retval = capabilities_check(board, (struct phone_capability *) arg); @@ -3904,7 +5051,7 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, j->ex.bits.pstn_ring = 0; break; case IXJCTL_SET_FILTER: - if (copy_from_user(&jf, (char *) arg, sizeof(ti))) + if (copy_from_user(&jf, (char *) arg, sizeof(jf))) return -EFAULT; retval = ixj_init_filter(board, &jf); break; @@ -3918,6 +5065,9 @@ int ixj_ioctl(struct inode *inode, struct file *file_p, case IXJCTL_TONE_CADENCE: retval = ixj_build_cadence(board, (IXJ_CADENCE *) arg); break; + case IXJCTL_FILTER_CADENCE: + retval = ixj_build_filter_cadence(board, (IXJ_FILTER_CADENCE *) arg); + break; case IXJCTL_INTERCOM_STOP: ixj[board].intercom = -1; ixj[arg].intercom = -1; @@ -3967,14 +5117,14 @@ struct file_operations ixj_fops = NULL, /* revalidate */ NULL /* lock */ }; - static int ixj_linetest(int board) { unsigned long jifwait; IXJ *j = &ixj[board]; + j->flags.incheck = 1; // Testing if (!j->flags.pots_correct) { - j->flags.pots_correct = 1; // Testing + j->flags.pots_correct = 1; daa_int_read(board); //Clear DAA Interrupt flags // @@ -4026,23 +5176,23 @@ static int ixj_linetest(int board) } } } - if (!j->flags.pstn_present) { - j->pld_slicw.bits.rly3 = 0; - outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); - daa_set_mode(board, SOP_PU_CONVERSATION); - jifwait = jiffies + hertz; - while (time_before(jiffies, jifwait)) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - daa_int_read(board); - daa_set_mode(board, SOP_PU_SLEEP); - if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { - j->flags.pstn_present = 1; - } else { - j->flags.pstn_present = 0; - } +// if (!j->flags.pstn_present) { + j->pld_slicw.bits.rly3 = 0; + outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01); + daa_set_mode(board, SOP_PU_CONVERSATION); + jifwait = jiffies + hertz; + while (time_before(jiffies, jifwait)) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + daa_int_read(board); + daa_set_mode(board, SOP_PU_SLEEP); + if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) { + j->flags.pstn_present = 1; + } else { + j->flags.pstn_present = 0; } +// } if (j->flags.pstn_present) { if (j->flags.pots_correct) { LED_SetState(0xA, board); @@ -4056,6 +5206,7 @@ static int ixj_linetest(int board) LED_SetState(0x5, board); } } + j->flags.incheck = 0; // Testing return j->flags.pstn_present; } @@ -4063,46 +5214,39 @@ static int ixj_selfprobe(int board) { unsigned short cmd; unsigned long jif; + int cnt; BYTES bytes; IXJ *j = &ixj[board]; - if (ixjdebug > 0) printk(KERN_INFO "Write IDLE to Software Control Register\n"); + ixj_WriteDSPCommand(0x0FE0, board); // Put the DSP in full power mode. if (ixj_WriteDSPCommand(0x0000, board)) /* Write IDLE to Software Control Register */ return -1; - // The read values of the SSR should be 0x00 for the IDLE command if (j->ssr.low || j->ssr.high) return -1; - if (ixjdebug > 0) printk(KERN_INFO "Get Device ID Code\n"); - if (ixj_WriteDSPCommand(0x3400, board)) /* Get Device ID Code */ return -1; - j->dsp.low = j->ssr.low; j->dsp.high = j->ssr.high; - if (ixjdebug > 0) printk(KERN_INFO "Get Device Version Code\n"); - if (ixj_WriteDSPCommand(0x3800, board)) /* Get Device Version Code */ return -1; - j->ver.low = j->ssr.low; j->ver.high = j->ssr.high; - if (!j->cardtype) { if (j->dsp.low == 0x21) { // j->XILINXbase = j->DSPbase + 0x10; bytes.high = bytes.low = inb_p(j->XILINXbase + 0x02); outb_p(bytes.low ^ 0xFF, j->XILINXbase + 0x02); - // Test for Internet LineJACK or Internet PhoneJACK Lite +// Test for Internet LineJACK or Internet PhoneJACK Lite bytes.low = inb_p(j->XILINXbase + 0x02); if (bytes.low == bytes.high) // Register is read only on - // Internet PhoneJack Lite + // Internet PhoneJack Lite { j->cardtype = 400; // Internet PhoneJACK Lite @@ -4162,19 +5306,19 @@ static int ixj_selfprobe(int board) request_region(j->XILINXbase, 4, "ixj control"); j->pld_slicw.pcib.e1 = 1; outb_p(j->pld_slicw.byte, j->XILINXbase); + break; + case 600: //Internet PhoneCARD + break; } } if (j->dsp.low == 0x20 || j->cardtype == 400 || j->cardtype == 500) { if (ixjdebug > 0) printk(KERN_INFO "Write CODEC config to Software Control Register\n"); - if (ixj_WriteDSPCommand(0xC462, board)) /* Write CODEC config to Software Control Register */ return -1; - if (ixjdebug > 0) printk(KERN_INFO "Write CODEC timing to Software Control Register\n"); - if (j->cardtype == 100) { cmd = 0x9FF2; } else { @@ -4185,17 +5329,17 @@ static int ixj_selfprobe(int board) } else { if (set_base_frame(board, 30) != 30) return -1; - + if (ixjdebug > 0) + printk(KERN_INFO "Write CODEC config to Software Control Register\n"); + if (j->cardtype == 600) { + if (ixj_WriteDSPCommand(0xC528, board)) /* Write CODEC config to Software Control Register */ + return -1; + } if (j->cardtype == 300) { - if (ixjdebug > 0) - printk(KERN_INFO "Write CODEC config to Software Control Register\n"); - if (ixj_WriteDSPCommand(0xC528, board)) /* Write CODEC config to Software Control Register */ return -1; - if (ixjdebug > 0) printk(KERN_INFO "Turn on the PLD Clock at 8Khz\n"); - j->pld_clock.byte = 0; outb_p(j->pld_clock.byte, j->XILINXbase + 0x04); } @@ -4204,7 +5348,6 @@ static int ixj_selfprobe(int board) if (j->dsp.low == 0x20) { if (ixjdebug > 0) printk(KERN_INFO "Configure GPIO pins\n"); - j->gpio.bytes.high = 0x09; /* bytes.low = 0xEF; 0xF7 */ j->gpio.bits.gpio1 = 1; @@ -4215,10 +5358,8 @@ static int ixj_selfprobe(int board) j->gpio.bits.gpio6 = 1; j->gpio.bits.gpio7 = 1; ixj_WriteDSPCommand(ixj[board].gpio.word, board); /* Set GPIO pin directions */ - if (ixjdebug > 0) printk(KERN_INFO "Enable SLIC\n"); - j->gpio.bytes.high = 0x0B; j->gpio.bytes.low = 0x00; j->gpio.bits.gpio1 = 0; @@ -4253,23 +5394,16 @@ static int ixj_selfprobe(int board) schedule_timeout(1); } LED_SetState(0x0, board); - daa_get_version(board); - if (ixjdebug > 0) printk("Loading DAA Coefficients\n"); - DAA_Coeff_US(board); if (!ixj_daa_write(board)) printk("DAA write failed on board %d\n", board); - ixj_daa_cid_reset(board); - j->flags.pots_correct = 0; j->flags.pstn_present = 0; - ixj_linetest(board); - if (j->flags.pots_correct) { j->pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync @@ -4280,9 +5414,10 @@ static int ixj_selfprobe(int board) SLIC_SetState(PLD_SLIC_STATE_STANDBY, board); j->port = PORT_POTS; } + ixj_set_port(board, PORT_PSTN); + ixj_set_pots(board, 1); if (ixjdebug > 0) printk(KERN_INFO "Enable Mixer\n"); - ixj_mixer(0x0000, board); //Master Volume Left unmute 0db ixj_mixer(0x0100, board); //Master Volume Right unmute 0db @@ -4306,43 +5441,43 @@ static int ixj_selfprobe(int board) ixj_mixer(0x1800, board); //ADC Source select } else { - j->port = PORT_POTS; - SLIC_SetState(PLD_SLIC_STATE_STANDBY, board); + if (j->cardtype == 600) { + ixj_WriteDSPCommand(0xCF07, board); + ixj_WriteDSPCommand(0x00B0, board); + ixj_set_port(board, PORT_SPEAKER); + } else { + ixj_set_port(board, PORT_POTS); + SLIC_SetState(PLD_SLIC_STATE_STANDBY, board); + } } } j->intercom = -1; j->framesread = j->frameswritten = 0; + j->read_wait = j->write_wait = 0; j->rxreadycheck = j->txreadycheck = 0; - + set_play_volume(board, 0x100); + set_rec_volume(board, 0x100); if (ixj_WriteDSPCommand(0x0000, board)) /* Write IDLE to Software Control Register */ return -1; - // The read values of the SSR should be 0x00 for the IDLE command if (j->ssr.low || j->ssr.high) return -1; - if (ixjdebug > 0) printk(KERN_INFO "Enable Line Monitor\n"); - if (ixjdebug > 0) printk(KERN_INFO "Set Line Monitor to Asyncronous Mode\n"); - if (ixj_WriteDSPCommand(0x7E01, board)) // Asynchronous Line Monitor return -1; - if (ixjdebug > 0) printk(KERN_INFO "Enable DTMF Detectors\n"); - if (ixj_WriteDSPCommand(0x5151, board)) // Enable DTMF detection return -1; - if (ixj_WriteDSPCommand(0x6E01, board)) // Set Asyncronous Tone Generation return -1; - set_rec_depth(board, 2); // Set Record Channel Limit to 2 frames set_play_depth(board, 2); // Set Playback Channel Limit to 2 frames @@ -4350,7 +5485,6 @@ static int ixj_selfprobe(int board) j->ex.bits.dtmf_ready = 0; j->dtmf_state = 0; j->dtmf_wp = ixj[board].dtmf_rp = 0; - j->rec_mode = ixj[board].play_mode = -1; j->flags.ringing = 0; j->maxrings = MAXRINGS; @@ -4358,15 +5492,16 @@ static int ixj_selfprobe(int board) j->drybuffer = 0; j->winktime = 320; j->flags.dtmf_oob = 0; - + for (cnt = 0; cnt < 4; cnt++) + j->cadence_f[cnt].enable = 0; /* must be a device on the specified address */ + ixj_WriteDSPCommand(0x0FE3, board); // Put the DSP in 1/5 power mode. /* Register with the Telephony for Linux subsystem */ j->p.f_op = &ixj_fops; j->p.open = ixj_open; + j->p.board = board; phone_register_device(&j->p, PHONE_UNIT_ANY); - add_caps(board); - return 0; } @@ -4375,11 +5510,9 @@ int ixj_read_proc(char *buf, char **start, off_t offset, int len, int unused) int cnt; IXJ *j; len = 0; - len += sprintf(buf + len, "\n%s", ixj_c_rcsid); len += sprintf(buf + len, "\n%s", ixj_h_rcsid); len += sprintf(buf + len, "\n%s", ixjuser_h_rcsid); - for (cnt = 0; cnt < IXJMAX; cnt++) { j = &ixj[cnt]; if (j->DSPbase) { @@ -4398,6 +5531,7 @@ int ixj_read_proc(char *buf, char **start, off_t offset, int len, int unused) len += sprintf(buf + len, "\nCard Type = Internet LineJACK"); if (j->flags.g729_loaded) len += sprintf(buf + len, " w/G.729 A/B"); + len += sprintf(buf + len, " Country = %d", j->country); break; case (400): len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK Lite"); @@ -4409,18 +5543,35 @@ int ixj_read_proc(char *buf, char **start, off_t offset, int len, int unused) if (j->flags.g729_loaded) len += sprintf(buf + len, " w/G.729 A/B"); break; + case (600): + len += sprintf(buf + len, "\nCard Type = Internet PhoneCARD"); + if (j->flags.g729_loaded) + len += sprintf(buf + len, " w/G.729 A/B"); + len += sprintf(buf + len, "\nSmart Cable %spresent", j->pccr1.bits.drf ? "not " : ""); + if (!j->pccr1.bits.drf) + len += sprintf(buf + len, "\nSmart Cable type %d", j->flags.pcmciasct); + len += sprintf(buf + len, "\nSmart Cable state %d", j->flags.pcmciastate); + break; default: len += sprintf(buf + len, "\nCard Type = %d", j->cardtype); break; } + len += sprintf(buf + len, "\nReaders %d", j->readers); + len += sprintf(buf + len, "\nWriters %d", j->writers); + len += sprintf(buf + len, "\nFSK words %d", ixj[2].fskdcnt); len += sprintf(buf + len, "\nCapabilities %d", j->caps); if (j->dsp.low != 0x20) len += sprintf(buf + len, "\nDSP Processor load %d", j->proc_load); -// if(j->intercom != -1) - // len += sprintf(buf+len, "\nIntercom call to board %2.2x", j->intercom); + if (j->flags.cidsent) + len += sprintf(buf + len, "\nCaller ID data sent"); + else + len += sprintf(buf + len, "\nCaller ID data not sent"); + + len += sprintf(buf + len, "\nCaller ID Date %s%s", j->cid_send.month, j->cid_send.day); + len += sprintf(buf + len, "\nCaller ID Time %s%s", j->cid_send.hour, j->cid_send.min); + len += sprintf(buf + len, "\nCaller ID Name %s", j->cid_send.name); + len += sprintf(buf + len, "\nCaller ID Number %s", j->cid_send.number); -// len += sprintf(buf+len, "\nRead buffer size %d", j->read_buffer_size); - // len += sprintf(buf+len, "\nWrite buffer size %d", j->write_buffer_size); len += sprintf(buf + len, "\nPlay CODEC "); switch (j->play_codec) { case G723_63: @@ -4463,9 +5614,6 @@ int ixj_read_proc(char *buf, char **start, off_t offset, int len, int unused) len += sprintf(buf + len, "NO CODEC CHOSEN"); break; } -// len += sprintf(buf+len, "\nPlay Frame Size %d", j->play_frame_size); - // len += sprintf(buf+len, "\nInfo_write.convert_mode = %d", j->Info_write.convert_mode); - // len += sprintf(buf+len, "\nInfo_write.convert_dir = %d", j->Info_write.convert_dir); len += sprintf(buf + len, "\nRecord CODEC "); switch (j->rec_codec) { case G723_63: @@ -4508,7 +5656,6 @@ int ixj_read_proc(char *buf, char **start, off_t offset, int len, int unused) len += sprintf(buf + len, "NO CODEC CHOSEN"); break; } -// len += sprintf(buf+len, "\nRecord Frame Size %d", j->rec_frame_size); switch (j->aec_level) { case AEC_OFF: len += sprintf(buf + len, "\n AEC OFF"); @@ -4523,16 +5670,13 @@ int ixj_read_proc(char *buf, char **start, off_t offset, int len, int unused) len += sprintf(buf + len, "\n AEC HIGH"); break; } -// len += sprintf(buf+len, "\nInfo_read.convert_mode = %d", j->Info_read.convert_mode); - // len += sprintf(buf+len, "\nInfo_read.convert_dir = %d", j->Info_read.convert_dir); len += sprintf(buf + len, "\nHook state %d", j->r_hook); // ixj_hookstate(cnt)); if (j->cardtype == 300) { len += sprintf(buf + len, "\nPOTS Correct %d", j->flags.pots_correct); len += sprintf(buf + len, "\nPSTN Present %d", j->flags.pstn_present); len += sprintf(buf + len, "\nPOTS to PSTN %d", j->flags.pots_pstn); -// len += sprintf(buf+len, "\nDAA Interrupt flags %d", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg); - // len += sprintf(buf+len, "\nDAA version %d", j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg); + len += sprintf(buf + len, "\nPSTN sleeptil %ld - jiffies %ld", j->pstn_sleeptil, jiffies); switch (j->daa_mode) { case SOP_PU_SLEEP: len += sprintf(buf + len, "\nDAA PSTN On Hook"); @@ -4547,7 +5691,6 @@ int ixj_read_proc(char *buf, char **start, off_t offset, int len, int unused) len += sprintf(buf + len, "\nDAA PSTN Pulse Dialing"); break; } -// len += sprintf(buf+len, "\nDAA PSTN Ring flag = %d", j->pstn_ringing); } switch (j->port) { case PORT_POTS: @@ -4598,23 +5741,8 @@ int ixj_read_proc(char *buf, char **start, off_t offset, int len, int unused) break; } } -// len += sprintf(buf+len, "\nRead buffers ready %d", j->read_buffer_ready); - // len += sprintf(buf+len, "\nWrite buffers empty %d",j->write_buffers_empty); - -// len += sprintf(buf+len, "\nDTMF ready %d", j->ex.bits.dtmf_ready); - // len += sprintf(buf+len, "\nDTMF proc %d", j->dtmf_proc); - // len += sprintf(buf+len, "\nDTMF wp %d", j->dtmf_wp); - // len += sprintf(buf+len, "\nDTMF rp %d", j->dtmf_rp); - // len += sprintf(buf+len, "\nDTMF digits "); - // for(x=j->dtmf_rp; x dtmf_wp; x++) - // { - // if(x == 79) - // x = 0; - // len += sprintf(buf+len, "%x", j->dtmfbuffer[x]); - // } #ifdef PERFMON_STATS len += sprintf(buf + len, "\nTimer Checks %ld", j->timerchecks); - len += sprintf(buf + len, "\nRX Ready Checks %ld", j->rxreadycheck); len += sprintf(buf + len, "\nTX Ready Checks %ld", j->txreadycheck); len += sprintf(buf + len, "\nBase Frame %2.2x.%2.2x", j->baseframe.high, j->baseframe.low); @@ -4629,7 +5757,15 @@ int ixj_read_proc(char *buf, char **start, off_t offset, int len, int unused) } return len; } - +int ixj_read_proc_fsk(char *buf, char **start, off_t offset, int len, int unused) +{ + len = 0; + if (ixj[2].fskdcnt) { + memcpy(buf, &ixj[2].fskdata, (ixj[2].fskdcnt) * 2); + len += ixj[2].fskdcnt * 2; + } + return len; +} static struct proc_dir_entry ixj_proc_entry = { 0, @@ -4640,14 +5776,310 @@ static struct proc_dir_entry ixj_proc_entry = NULL, &ixj_read_proc }; +static struct proc_dir_entry ixjfsk_proc_entry = +{ + 0, + 6, "ixjfsk", + S_IFREG | S_IRUGO, + 1, 0, 0, + 0, + NULL, + &ixj_read_proc_fsk +}; + +MODULE_DESCRIPTION("Internet Phone/Internet LineJack module - www.quicknet.net"); +MODULE_AUTHOR("Ed Okerson "); +#ifdef CONFIG_PCMCIA +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +#else +#define DEBUG(n, args...) +#endif +typedef struct ixj_info_t { + int ndev; + dev_node_t node; + struct ixj *port; +} ixj_info_t; +static dev_link_t *ixj_attach(void); +static void ixj_detach(dev_link_t *); +static void ixj_config(dev_link_t * link); +static void ixj_cs_release(u_long arg); +static int ixj_event(event_t event, int priority, event_callback_args_t * args); +static dev_info_t dev_info = "ixj_cs"; +static dev_link_t *dev_list = NULL; +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = + { + func, ret + }; + CardServices(ReportError, handle, &err); +} + +static dev_link_t *ixj_attach(void) +{ + client_reg_t client_reg; + dev_link_t *link; + int ret; + DEBUG(0, "ixj_attach()\n"); + /* Create new ixj device */ + link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + memset(link, 0, sizeof(struct dev_link_t)); + link->release.function = &ixj_cs_release; + link->release.data = (u_long) link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = 3; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL); + memset(link->priv, 0, sizeof(struct ixj_info_t)); + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &ixj_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + ixj_detach(link); + return NULL; + } + return link; +} + +static void ixj_detach(dev_link_t * link) +{ + dev_link_t **linkp; + long flags; + int ret; + DEBUG(0, "ixj_detach(0x%p)\n", link); + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + if (*linkp == NULL) + return; + save_flags(flags); + cli(); + if (link->state & DEV_RELEASE_PENDING) { + del_timer(&link->release); + link->state &= ~DEV_RELEASE_PENDING; + } + restore_flags(flags); + if (link->state & DEV_CONFIG) + ixj_cs_release((u_long) link); + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + /* Unlink device structure, free bits */ + *linkp = link->next; + kfree_s(link->priv, sizeof(ixj_info_t)); + kfree_s(link, sizeof(struct dev_link_t)); +} + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed + +#define CFG_CHECK(fn, args...) \ +if (CardServices(fn, args) != 0) goto next_entry + +void ixj_get_serial(dev_link_t * link, IXJ * j) +{ + client_handle_t handle; + tuple_t tuple; + u_short buf[128]; + char *str; + int last_ret, last_fn, i, place; + handle = link->handle; + DEBUG(0, "ixj_get_serial(0x%p)\n", link); + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 80; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_VERS_1; + CS_CHECK(GetFirstTuple, handle, &tuple); + CS_CHECK(GetTupleData, handle, &tuple); + str = (char *) buf; + printk("PCMCIA Version %d.%d\n", str[0], str[1]); + str += 2; + printk("%s", str); + str = str + strlen(str) + 1; + printk(" %s", str); + str = str + strlen(str) + 1; + place = 1; + for (i = strlen(str) - 1; i >= 0; i--) { + switch (str[i]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + j->serial += (str[i] - 48) * place; + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + j->serial += (str[i] - 55) * place; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + j->serial += (str[i] - 87) * place; + break; + } + place = place * 0x10; + } + str = str + strlen(str) + 1; + printk(" version %s\n", str); + cs_failed: + return; +} + +void ixj_config(dev_link_t * link) +{ + client_handle_t handle; + ixj_info_t *info; + tuple_t tuple; + u_short buf[128]; + cisparse_t parse; + config_info_t conf; + cistpl_cftable_entry_t *cfg = &parse.cftable_entry; + cistpl_cftable_entry_t dflt = + { + 0 + }; + int last_ret, last_fn; + handle = link->handle; + info = link->priv; + DEBUG(0, "ixj_config(0x%p)\n", link); + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CONFIG; + CS_CHECK(GetFirstTuple, handle, &tuple); + CS_CHECK(GetTupleData, handle, &tuple); + CS_CHECK(ParseTuple, handle, &tuple, &parse); + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + link->state |= DEV_CONFIG; + CS_CHECK(GetConfigurationInfo, handle, &conf); + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple.Attributes = 0; + CS_CHECK(GetFirstTuple, handle, &tuple); + while (1) { + CFG_CHECK(GetTupleData, handle, &tuple); + CFG_CHECK(ParseTuple, handle, &tuple, &parse); + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->conf.ConfigIndex = cfg->index; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin == 2) { + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + CFG_CHECK(RequestIO, link->handle, &link->io); + /* If we've got this far, we're done */ + break; + } + next_entry: + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + CS_CHECK(GetNextTuple, handle, &tuple); + } + + CS_CHECK(RequestConfiguration, handle, &link->conf); + ixj[0].DSPbase = link->io.BasePort1; + ixj[0].XILINXbase = link->io.BasePort1 + 0x10; + ixj[0].cardtype = 600; + ixj_selfprobe(0); + info->ndev = 1; + info->node.major = PHONE_MAJOR; + link->dev = &info->node; + ixj_get_serial(link, &ixj[0]); + link->state &= ~DEV_CONFIG_PENDING; + return; + cs_failed: + cs_error(link->handle, last_fn, last_ret); + ixj_cs_release((u_long) link); +} + +void ixj_cs_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *) arg; + ixj_info_t *info = link->priv; + DEBUG(0, "ixj_cs_release(0x%p)\n", link); + info->ndev = 0; + link->dev = NULL; + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + link->state &= ~DEV_CONFIG; +} + +int ixj_event(event_t event, int priority, event_callback_args_t * args) +{ + dev_link_t *link = args->client_data; + DEBUG(1, "ixj_event(0x%06x)\n", event); + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + link->release.expires = RUN_AT(HZ / 20); + link->state |= DEV_RELEASE_PENDING; + add_timer(&link->release); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + ixj_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link)) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + return 0; +} + +#endif // PCMCIA static void cleanup(void) { int cnt; - del_timer(&ixj_timer); -// if (ixj_major) - // unregister_chrdev(ixj_major, "ixj"); for (cnt = 0; cnt < IXJMAX; cnt++) { if (ixj[cnt].cardtype == 300) { ixj[cnt].pld_scrw.bits.daafsyncen = 0; // Turn off DAA Frame Sync @@ -4658,7 +6090,6 @@ static void cleanup(void) ixj[cnt].pld_slicw.bits.rly3 = 0; outb_p(ixj[cnt].pld_slicw.byte, ixj[cnt].XILINXbase + 0x01); LED_SetState(0x0, cnt); - release_region(ixj[cnt].XILINXbase, 8); } if (ixj[cnt].cardtype == 400 || ixj[cnt].cardtype == 500) { @@ -4675,18 +6106,23 @@ static void cleanup(void) #ifdef CONFIG_ISAPNP if (ixj[cnt].dev) ixj[cnt].dev->deactivate(ixj[cnt].dev); +#endif +#ifdef CONFIG_PCMCIA + DEBUG(0, "ixj_cs: unloading\n"); + unregister_pcmcia_driver(&dev_info); + while (dev_list != NULL) + ixj_detach(dev_list); #endif } proc_unregister(&proc_root, ixj_proc_entry.low_ino); + proc_unregister(&proc_root, ixjfsk_proc_entry.low_ino); } - // Typedefs typedef struct { BYTE length; DWORD bits; } DATABLOCK; - static void PCIEE_WriteBit(WORD wEEPROMAddress, BYTE lastLCC, BYTE byData) { lastLCC = lastLCC & 0xfb; @@ -4699,7 +6135,6 @@ static void PCIEE_WriteBit(WORD wEEPROMAddress, BYTE lastLCC, BYTE byData) byData = byData << 1; lastLCC = lastLCC & 0xfe; - udelay(1000); outb(lastLCC, wEEPROMAddress); //after delay, SK falling edge @@ -4724,11 +6159,8 @@ static BOOL PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult) WORD wEEPROMAddress = wAddress + 3; DWORD i; BYTE byResult; - *pwResult = 0; - lastLCC = inb(wEEPROMAddress); - lastLCC = lastLCC | 0x02; lastLCC = lastLCC & 0xfe; outb(lastLCC, wEEPROMAddress); // CS hi, SK lo @@ -4738,7 +6170,6 @@ static BOOL PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult) PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1); PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1); PCIEE_WriteBit(wEEPROMAddress, lastLCC, 0); - for (i = 0; i < 8; i++) { PCIEE_WriteBit(wEEPROMAddress, lastLCC, wLoc & 0x80 ? 1 : 0); wLoc <<= 1; @@ -4760,27 +6191,29 @@ static BOOL PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult) static DWORD PCIEE_GetSerialNumber(WORD wAddress) { WORD wLo, wHi; - if (PCIEE_ReadWord(wAddress, 62, &wLo)) return 0; - if (PCIEE_ReadWord(wAddress, 63, &wHi)) return 0; - return (((DWORD) wHi << 16) | wLo); } -static int dspio[IXJMAX + 1] = {0,}; -static int xio[IXJMAX + 1] = {0,}; - -MODULE_DESCRIPTION("Internet PhoneJACK/Internet LineJACK module - www.quicknet.net"); -MODULE_AUTHOR("Ed Okerson "); +#ifndef CONFIG_PCMCIA +#ifndef CONFIG_ISAPNP +static int dspio[IXJMAX + 1] = +{ + 0, +}; +static int xio[IXJMAX + 1] = +{ + 0, +}; MODULE_PARM(dspio, "1-" __MODULE_STRING(IXJMAX) "i"); MODULE_PARM(xio, "1-" __MODULE_STRING(IXJMAX) "i"); - +#endif +#endif #ifdef MODULE - void cleanup_module(void) { cleanup(); @@ -4792,23 +6225,35 @@ int __init ixj_init(void) #endif { int result; - - int func = 0x110, i = 0; + int i = 0; int cnt = 0; int probe = 0; +#ifdef CONFIG_ISAPNP + int func = 0x110; struct pnp_dev *dev = NULL, *old_dev = NULL; +#endif +#ifdef CONFIG_PCI struct pci_dev *pci = NULL; - +#endif +#ifdef CONFIG_PCMCIA + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "ixj_cs: Card Services release does not match!\n"); + return -1; + } + register_pcmcia_driver(&dev_info, &ixj_attach, &ixj_detach); + probe = 0; +#else #ifdef CONFIG_ISAPNP while (1) { do { old_dev = dev; dev = isapnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'), ISAPNP_FUNCTION(func), old_dev); -//(old_dev==NULL?NULL:old_dev)); if (!dev) break; - printk("preparing %x\n", func); result = dev->prepare(dev); if (result < 0) { printk("preparing failed %d \n", result); @@ -4826,7 +6271,6 @@ int __init ixj_init(void) ixj[cnt].DSPbase = dev->resource[0].start; /* get real port */ if (func != 0x110) ixj[cnt].XILINXbase = dev->resource[1].start; /* get real port */ - result = check_region(ixj[cnt].DSPbase, 16); if (result) { printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase); @@ -4846,13 +6290,21 @@ int __init ixj_init(void) break; } probe = ixj_selfprobe(cnt); - ixj[cnt].serial = dev->bus->serial; ixj[cnt].dev = dev; - printk(KERN_INFO "ixj: found card at 0x%x\n", ixj[cnt].DSPbase); + switch (func) { + case 0x110: + printk(KERN_INFO "ixj: found Internet PhoneJACK at 0x%x\n", ixj[cnt].DSPbase); + break; + case 0x310: + printk(KERN_INFO "ixj: found Internet LineJACK at 0x%x\n", ixj[cnt].DSPbase); + break; + case 0x410: + printk(KERN_INFO "ixj: found Internet PhoneJACK Lite at 0x%x\n", ixj[cnt].DSPbase); + break; + } cnt++; } while (dev); - if (func == 0x410) break; if (func == 0x310) @@ -4863,11 +6315,10 @@ int __init ixj_init(void) } #else //CONFIG_ISAPNP /* Use passed parameters for older kernels without PnP */ - - for (cnt = 0; cnt < IXJMAX; cnt++) { - if (dspio[cnt]) { - ixj[cnt].DSPbase = dspio[cnt]; - ixj[cnt].XILINXbase = xio[cnt]; + for (i = 0; i < IXJMAX; i++) { + if (dspio[i]) { + ixj[cnt].DSPbase = dspio[i]; + ixj[cnt].XILINXbase = xio[i]; ixj[cnt].cardtype = 0; result = check_region(ixj[cnt].DSPbase, 16); if (result) { @@ -4878,9 +6329,11 @@ int __init ixj_init(void) request_region(ixj[cnt].DSPbase, 16, "ixj DSP"); probe = ixj_selfprobe(cnt); ixj[cnt].dev = NULL; + cnt++; } } -#endif +#endif // !CONFIG_ISAPNP +#endif // CONFIG_PCMCIA #ifdef CONFIG_PCI if (pci_present()) { for (i = 0; i < IXJMAX - cnt; i++) { @@ -4891,7 +6344,6 @@ int __init ixj_init(void) ixj[cnt].DSPbase = pci->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; ixj[cnt].XILINXbase = ixj[cnt].DSPbase + 0x10; ixj[cnt].serial = PCIEE_GetSerialNumber(pci->base_address[2] & PCI_BASE_ADDRESS_IO_MASK); - result = check_region(ixj[cnt].DSPbase, 16); if (result) { printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase); @@ -4901,43 +6353,35 @@ int __init ixj_init(void) request_region(ixj[cnt].DSPbase, 16, "ixj DSP"); ixj[cnt].cardtype = 500; probe = ixj_selfprobe(cnt); + if (probe) + printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", ixj[cnt].DSPbase); cnt++; } } } #endif printk("%s\n", ixj_c_rcsid); - -// result = register_chrdev(ixj_major, "ixj", &ixj_fops); - // if (result < 0) { - // printk(KERN_INFO "ixj: can't get major number\n"); - // cleanup(); - // return result; - // } - // if (ixj_major == 0) - // ixj_major = result; /* dynamic */ - proc_register(&proc_root, &ixj_proc_entry); - + proc_register(&proc_root, &ixjfsk_proc_entry); ixj_init_timer(); - ixj_add_timer(); + ixj_add_timer(); return probe; } static void DAA_Coeff_US(int board) { IXJ *j = &ixj[board]; - int i; + j->daa_country = DAA_US; //----------------------------------------------- // CAO for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } - // Bytes for IM-filter part 1 (04): 0E,32,E2,2F,C2,5A,C0,00 - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x0E; +// Bytes for IM-filter part 1 (04): 0E,32,E2,2F,C2,5A,C0,00 + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x0E; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xE2; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2F; @@ -4945,7 +6389,6 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xC0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; - // Bytes for IM-filter part 2 (05): 72,85,00,0E,2B,3A,D0,08 j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x72; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x85; @@ -4955,7 +6398,6 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x3A; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xD0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; - // Bytes for FRX-filter (08): 03,8F,48,F2,8F,48,70,08 j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x03; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x8F; @@ -4965,7 +6407,6 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x48; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x70; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; - // Bytes for FRR-filter (07): 04,8F,38,7F,9B,EA,B0,08 j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x04; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; @@ -4975,19 +6416,16 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xEA; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; - // Bytes for AX-filter (0A): 16,55,DD,CA j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x16; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0x55; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; - // Bytes for AR-filter (09): 52,D3,11,42 j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xD3; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0x42; - // Bytes for TH-filter part 1 (00): 00,42,48,81,B3,80,00,98 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; @@ -4997,7 +6435,6 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; - // Bytes for TH-filter part 2 (01): 02,F2,33,A0,68,AB,8A,AD j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xF2; @@ -5007,7 +6444,6 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAB; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x8A; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xAD; - // Bytes for TH-filter part 3 (02): 00,88,DA,54,A4,BA,2D,BB j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; @@ -5017,7 +6453,6 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xBA; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x2D; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xBB; - // ; (10K, 0.68uF) // // Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 @@ -5029,7 +6464,6 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x1C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; - // Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x13; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x42; @@ -5039,14 +6473,12 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x73; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; - // // Levelmetering Ringing (0D):B2,45,0F,8E j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xB2; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; - // Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; @@ -5056,7 +6488,6 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; - // Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; @@ -5066,64 +6497,52 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; - // // ;CR Registers // Config. Reg. 0 (filters) (cr0):FE ; CLK gen. by crystal - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE; - + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; // Config. Reg. 1 (dialing) (cr1):05 j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; - // Config. Reg. 2 (caller ID) (cr2):04 j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; - // Config. Reg. 3 (testloops) (cr3):03 ; SEL Bit==0, HP-disabled j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x03; - // Config. Reg. 4 (analog gain) (cr4):01 j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - -// Config. Reg. 5 (Version) (cr5):02 + // Config. Reg. 5 (Version) (cr5):02 // Config. Reg. 6 (Reserved) (cr6):00 // Config. Reg. 7 (Reserved) (cr7):00 // - -// ;xr Registers + // ;xr Registers // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. + // Ext. Reg. 1 (Interrupt enable) (xr1):1C // Cadence, RING, Caller ID, VDD_OK -// Ext. Reg. 1 (Interrupt enable) (xr1):1C // Cadence, RING, Caller ID, VDD_OK j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x3C; - // Ext. Reg. 2 (Cadence Time Out) (xr2):7D j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; - // Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off == 1 j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x12; //0x32; + // Ext. Reg. 4 (Cadence) (xr4):00 -// Ext. Reg. 4 (Cadence) (xr4):00 j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; - // Ext. Reg. 5 (Ring timer) (xr5):22 j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; - // Ext. Reg. 6 (Power State) (xr6):00 j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; - // Ext. Reg. 7 (Vdd) (xr7):40 j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; // 0x40 ??? Should it be 0x00? - -// + // // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz // 12,33,5A,C3 ; 770 Hz // 13,3C,5B,32 ; 852 Hz // 1D,1B,5C,CC ; 941 Hz + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; - // DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz // EC,1D,52,22 ; 1336 Hz // AA,AC,51,D2 ; 1477 Hz @@ -5132,23 +6551,22 @@ static void DAA_Coeff_US(int board) j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; - } static void DAA_Coeff_UK(int board) { IXJ *j = &ixj[board]; - int i; + j->daa_country = DAA_UK; //----------------------------------------------- // CAO for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } - // Bytes for IM-filter part 1 (04): 00,C2,BB,A8,CB,81,A0,00 - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; +// Bytes for IM-filter part 1 (04): 00,C2,BB,A8,CB,81,A0,00 + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xC2; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xA8; @@ -5156,8 +6574,7 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; - - // Bytes for IM-filter part 2 (05): 40,00,00,0A,A4,33,E0,08 +// Bytes for IM-filter part 2 (05): 40,00,00,0A,A4,33,E0,08 j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x40; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00; @@ -5166,7 +6583,6 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; - // Bytes for FRX-filter (08): 07,9B,ED,24,B2,A2,A0,08 j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9B; @@ -5176,7 +6592,6 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0xA2; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; - // Bytes for FRR-filter (07): 0F,92,F2,B2,87,D2,30,08 j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x92; @@ -5186,19 +6601,16 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xD2; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x30; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; - // Bytes for AX-filter (0A): 1B,A5,DD,CA j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xA5; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; - // Bytes for AR-filter (09): E2,27,10,D6 j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x27; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; - // Bytes for TH-filter part 1 (00): 80,2D,38,8B,D0,00,00,98 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x2D; @@ -5208,7 +6620,6 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; - // Bytes for TH-filter part 2 (01): 02,5A,53,F0,0B,5F,84,D4 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x5A; @@ -5218,7 +6629,6 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5F; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x84; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xD4; - // Bytes for TH-filter part 3 (02): 00,88,6A,A4,8F,52,F5,32 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; @@ -5228,10 +6638,8 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xF5; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x32; - // ; idle - -// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 + // Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; @@ -5240,7 +6648,6 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; - // Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; @@ -5250,13 +6657,11 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; - // Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V less possible? j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; - // Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; @@ -5266,7 +6671,6 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; - // Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; @@ -5276,61 +6680,49 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; - // ;CR Registers // Config. Reg. 0 (filters) (cr0):FF - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; //0xFE; - + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE; // Config. Reg. 1 (dialing) (cr1):05 j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; - // Config. Reg. 2 (caller ID) (cr2):04 j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; - // Config. Reg. 3 (testloops) (cr3):00 ; j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; - // Config. Reg. 4 (analog gain) (cr4):01 j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - -// Config. Reg. 5 (Version) (cr5):02 + // Config. Reg. 5 (Version) (cr5):02 // Config. Reg. 6 (Reserved) (cr6):00 // Config. Reg. 7 (Reserved) (cr7):00 - -// ;xr Registers + // ;xr Registers // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. + // Ext. Reg. 1 (Interrupt enable) (xr1):1C -// Ext. Reg. 1 (Interrupt enable) (xr1):1C j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK + // Ext. Reg. 2 (Cadence Time Out) (xr2):7D -// Ext. Reg. 2 (Cadence Time Out) (xr2):7D j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; - // Ext. Reg. 3 (DC Char) (xr3):36 ; j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36; - // Ext. Reg. 4 (Cadence) (xr4):00 j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; - // Ext. Reg. 5 (Ring timer) (xr5):22 j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; - // Ext. Reg. 6 (Power State) (xr6):00 j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; - // Ext. Reg. 7 (Vdd) (xr7):46 j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; // 0x46 ??? Should it be 0x00? - -// DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz + // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz // 12,33,5A,C3 ; 770 Hz // 13,3C,5B,32 ; 852 Hz // 1D,1B,5C,CC ; 941 Hz + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; - // DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz // EC,1D,52,22 ; 1336 Hz // AA,AC,51,D2 ; 1477 Hz @@ -5339,24 +6731,23 @@ static void DAA_Coeff_UK(int board) j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; - } static void DAA_Coeff_France(int board) { IXJ *j = &ixj[board]; - int i; + j->daa_country = DAA_FRANCE; //----------------------------------------------- // CAO for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } - // Bytes for IM-filter part 1 (04): 02,A2,43,2C,22,AF,A0,00 - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x02; +// Bytes for IM-filter part 1 (04): 02,A2,43,2C,22,AF,A0,00 + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA2; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x43; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2C; @@ -5364,7 +6755,6 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xAF; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; - // Bytes for IM-filter part 2 (05): 67,CE,00,0C,22,33,E0,08 j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x67; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xCE; @@ -5374,7 +6764,6 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; - // Bytes for FRX-filter (08): 07,9A,28,F6,23,4A,B0,08 j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9A; @@ -5384,7 +6773,6 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x4A; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xB0; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; - // Bytes for FRR-filter (07): 03,8F,F9,2F,9E,FA,20,08 j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; @@ -5394,19 +6782,16 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xFA; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; - // Bytes for AX-filter (0A): 16,B5,DD,CA j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x16; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; - // Bytes for AR-filter (09): 52,C7,10,D6 j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; - // Bytes for TH-filter part 1 (00): 00,42,48,81,A6,80,00,98 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; @@ -5416,7 +6801,6 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; - // Bytes for TH-filter part 2 (01): 02,AC,2A,30,78,AC,8A,2C j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAC; @@ -5426,7 +6810,6 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAC; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x8A; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x2C; - // Bytes for TH-filter part 3 (02): 00,88,DA,A5,22,BA,2C,45 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; @@ -5436,10 +6819,8 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xBA; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x2C; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x45; - // ; idle - -// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 + // Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; @@ -5448,7 +6829,6 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; - // Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; @@ -5458,13 +6838,11 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; - // Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84; - // Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; @@ -5474,7 +6852,6 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; - // Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; @@ -5484,61 +6861,49 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; - // ;CR Registers // Config. Reg. 0 (filters) (cr0):FF - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; - + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE; // Config. Reg. 1 (dialing) (cr1):05 j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; - // Config. Reg. 2 (caller ID) (cr2):04 j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; - // Config. Reg. 3 (testloops) (cr3):00 ; j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; - // Config. Reg. 4 (analog gain) (cr4):01 j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - -// Config. Reg. 5 (Version) (cr5):02 + // Config. Reg. 5 (Version) (cr5):02 // Config. Reg. 6 (Reserved) (cr6):00 // Config. Reg. 7 (Reserved) (cr7):00 - -// ;xr Registers + // ;xr Registers // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. + // Ext. Reg. 1 (Interrupt enable) (xr1):1C -// Ext. Reg. 1 (Interrupt enable) (xr1):1C j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK + // Ext. Reg. 2 (Cadence Time Out) (xr2):7D -// Ext. Reg. 2 (Cadence Time Out) (xr2):7D j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; - // Ext. Reg. 3 (DC Char) (xr3):36 ; j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36; - // Ext. Reg. 4 (Cadence) (xr4):00 j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; - // Ext. Reg. 5 (Ring timer) (xr5):22 j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; - // Ext. Reg. 6 (Power State) (xr6):00 j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; - // Ext. Reg. 7 (Vdd) (xr7):46 j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46; // 0x46 ??? Should it be 0x00? - -// DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz + // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz // 12,33,5A,C3 ; 770 Hz // 13,3C,5B,32 ; 852 Hz // 1D,1B,5C,CC ; 941 Hz + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; - // DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz // EC,1D,52,22 ; 1336 Hz // AA,AC,51,D2 ; 1477 Hz @@ -5547,24 +6912,23 @@ static void DAA_Coeff_France(int board) j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; - } static void DAA_Coeff_Germany(int board) { IXJ *j = &ixj[board]; - int i; + j->daa_country = DAA_GERMANY; //----------------------------------------------- // CAO for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } - // Bytes for IM-filter part 1 (04): 00,CE,BB,B8,D2,81,B0,00 - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; +// Bytes for IM-filter part 1 (04): 00,CE,BB,B8,D2,81,B0,00 + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xCE; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xB8; @@ -5572,7 +6936,6 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xB0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; - // Bytes for IM-filter part 2 (05): 45,8F,00,0C,D2,3A,D0,08 j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x8F; @@ -5582,7 +6945,6 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x3A; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xD0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; - // Bytes for FRX-filter (08): 07,AA,E2,34,24,89,20,08 j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xAA; @@ -5592,7 +6954,6 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x89; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x20; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; - // Bytes for FRR-filter (07): 02,87,FA,37,9A,CA,B0,08 j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87; @@ -5602,19 +6963,16 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; - // Bytes for AX-filter (0A): 72,D5,DD,CA j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x72; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xD5; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; - // Bytes for AR-filter (09): 72,42,13,4B j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x72; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x42; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x13; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0x4B; - // Bytes for TH-filter part 1 (00): 80,52,48,81,AD,80,00,98 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52; @@ -5624,7 +6982,6 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; - // Bytes for TH-filter part 2 (01): 02,42,5A,20,E8,1A,81,27 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x42; @@ -5634,7 +6991,6 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x1A; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x27; - // Bytes for TH-filter part 3 (02): 00,88,63,26,BD,4B,A3,C2 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; @@ -5644,10 +7000,8 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x4B; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xC2; - // ; (10K, 0.68uF) - -// Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 + // Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x9B; @@ -5656,7 +7010,6 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x1C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; - // Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x13; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x42; @@ -5666,13 +7019,11 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x73; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; - // Levelmetering Ringing (0D):B2,45,0F,8E j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xB2; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; - // Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; @@ -5682,7 +7033,6 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; - // Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; @@ -5692,61 +7042,49 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; - // ;CR Registers // Config. Reg. 0 (filters) (cr0):FF ; all Filters enabled, CLK from ext. source - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; - + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE; // Config. Reg. 1 (dialing) (cr1):05 ; Manual Ring, Ring metering enabled j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; - // Config. Reg. 2 (caller ID) (cr2):04 ; Analog Gain 0dB, FSC internal j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; - // Config. Reg. 3 (testloops) (cr3):00 ; SEL Bit==0, HP-enabled j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; - // Config. Reg. 4 (analog gain) (cr4):01 j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - -// Config. Reg. 5 (Version) (cr5):02 + // Config. Reg. 5 (Version) (cr5):02 // Config. Reg. 6 (Reserved) (cr6):00 // Config. Reg. 7 (Reserved) (cr7):00 - -// ;xr Registers + // ;xr Registers // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. + // Ext. Reg. 1 (Interrupt enable) (xr1):1C ; Ring, CID, VDDOK Interrupts enabled -// Ext. Reg. 1 (Interrupt enable) (xr1):1C ; Ring, CID, VDDOK Interrupts enabled j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK + // Ext. Reg. 2 (Cadence Time Out) (xr2):7D -// Ext. Reg. 2 (Cadence Time Out) (xr2):7D j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; - // Ext. Reg. 3 (DC Char) (xr3):32 ; B-Filter Off==1, U0=3.5V, R=200Ohm j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x32; - // Ext. Reg. 4 (Cadence) (xr4):00 j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; - // Ext. Reg. 5 (Ring timer) (xr5):22 j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; - // Ext. Reg. 6 (Power State) (xr6):00 j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; - // Ext. Reg. 7 (Vdd) (xr7):40 ; VDD=4.25 V j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; // 0x40 ??? Should it be 0x00? - -// DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz + // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz // 12,33,5A,C3 ; 770 Hz // 13,3C,5B,32 ; 852 Hz // 1D,1B,5C,CC ; 941 Hz + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; - // DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz // EC,1D,52,22 ; 1336 Hz // AA,AC,51,D2 ; 1477 Hz @@ -5755,24 +7093,23 @@ static void DAA_Coeff_Germany(int board) j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; - } static void DAA_Coeff_Australia(int board) { IXJ *j = &ixj[board]; - int i; + j->daa_country = DAA_AUSTRALIA; //----------------------------------------------- // CAO for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } - // Bytes for IM-filter part 1 (04): 00,A3,AA,28,B3,82,D0,00 - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; +// Bytes for IM-filter part 1 (04): 00,A3,AA,28,B3,82,D0,00 + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xAA; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x28; @@ -5780,7 +7117,6 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x82; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xD0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; - // Bytes for IM-filter part 2 (05): 70,96,00,09,32,6B,C0,08 j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x70; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x96; @@ -5790,7 +7126,6 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x6B; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xC0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; - // Bytes for FRX-filter (08): 07,96,E2,34,32,9B,30,08 j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x96; @@ -5800,7 +7135,6 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x9B; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; - // Bytes for FRR-filter (07): 0F,9A,E9,2F,22,CC,A0,08 j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x9A; @@ -5810,19 +7144,16 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCC; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; - // Bytes for AX-filter (0A): CB,45,DD,CA j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0xCB; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; - // Bytes for AR-filter (09): 1B,67,10,D6 j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x67; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; - // Bytes for TH-filter part 1 (00): 80,52,48,81,AF,80,00,98 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52; @@ -5832,7 +7163,6 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; - // Bytes for TH-filter part 2 (01): 02,DB,52,B0,38,01,82,AC j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xDB; @@ -5842,7 +7172,6 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x01; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x82; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xAC; - // Bytes for TH-filter part 3 (02): 00,88,4A,3E,2C,3B,24,46 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; @@ -5852,10 +7181,8 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x3B; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x24; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x46; - // ; idle - -// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 + // Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; @@ -5864,7 +7191,6 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; - // Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; @@ -5874,13 +7200,11 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; - // Levelmetering Ringing (0D):32,45,B5,84 ; 50Hz 20V j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84; - // Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; @@ -5890,7 +7214,6 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; - // Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; @@ -5900,61 +7223,49 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; - // ;CR Registers // Config. Reg. 0 (filters) (cr0):FF j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; - // Config. Reg. 1 (dialing) (cr1):05 j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; - // Config. Reg. 2 (caller ID) (cr2):04 j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; - // Config. Reg. 3 (testloops) (cr3):00 ; j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; - // Config. Reg. 4 (analog gain) (cr4):01 j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - -// Config. Reg. 5 (Version) (cr5):02 + // Config. Reg. 5 (Version) (cr5):02 // Config. Reg. 6 (Reserved) (cr6):00 // Config. Reg. 7 (Reserved) (cr7):00 - -// ;xr Registers + // ;xr Registers // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. + // Ext. Reg. 1 (Interrupt enable) (xr1):1C -// Ext. Reg. 1 (Interrupt enable) (xr1):1C j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK + // Ext. Reg. 2 (Cadence Time Out) (xr2):7D -// Ext. Reg. 2 (Cadence Time Out) (xr2):7D j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; - // Ext. Reg. 3 (DC Char) (xr3):2B ; j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x2B; - // Ext. Reg. 4 (Cadence) (xr4):00 j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; - // Ext. Reg. 5 (Ring timer) (xr5):22 j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; - // Ext. Reg. 6 (Power State) (xr6):00 j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; - // Ext. Reg. 7 (Vdd) (xr7):40 j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; // 0x40 ??? Should it be 0x00? - -// DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz + // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz // 12,33,5A,C3 ; 770 Hz // 13,3C,5B,32 ; 852 Hz // 1D,1B,5C,CC ; 941 Hz + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; - // DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz // EC,1D,52,22 ; 1336 Hz // AA,AC,51,D2 ; 1477 Hz @@ -5963,23 +7274,22 @@ static void DAA_Coeff_Australia(int board) j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; - } static void DAA_Coeff_Japan(int board) { IXJ *j = &ixj[board]; - int i; + j->daa_country = DAA_JAPAN; //----------------------------------------------- // CAO for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) { j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0; } - // Bytes for IM-filter part 1 (04): 06,BD,E2,2D,BA,F9,A0,00 - j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x06; +// Bytes for IM-filter part 1 (04): 06,BD,E2,2D,BA,F9,A0,00 + j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x06; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xBD; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xE2; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2D; @@ -5987,7 +7297,6 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xF9; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00; - // Bytes for IM-filter part 2 (05): 6F,F7,00,0E,34,33,E0,08 j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x6F; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xF7; @@ -5997,7 +7306,6 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0; j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08; - // Bytes for FRX-filter (08): 02,8F,68,77,9C,58,F0,08 j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x8F; @@ -6007,7 +7315,6 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x58; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xF0; j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08; - // Bytes for FRR-filter (07): 03,8F,38,73,87,EA,20,08 j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F; @@ -6017,19 +7324,16 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xEA; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20; j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08; - // Bytes for AX-filter (0A): 51,C5,DD,CA j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x51; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xC5; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD; j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA; - // Bytes for AR-filter (09): 25,A7,10,D6 j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xA7; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10; j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6; - // Bytes for TH-filter part 1 (00): 00,42,48,81,AE,80,00,98 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42; @@ -6039,7 +7343,6 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98; - // Bytes for TH-filter part 2 (01): 02,AB,2A,20,99,5B,89,28 j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAB; @@ -6049,7 +7352,6 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5B; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x89; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x28; - // Bytes for TH-filter part 3 (02): 00,88,DA,25,34,C5,4C,BA j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88; @@ -6059,10 +7361,8 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xC5; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x4C; j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xBA; - // ; idle - -// Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 + // Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93; @@ -6071,7 +7371,6 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23; - // Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2; @@ -6081,13 +7380,11 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5; - // Levelmetering Ringing (0D):AA,35,0F,8E ; 25Hz 30V ????????? j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; - // Caller ID 1st Tone (0E):CA,0E,CA,09,99,99,99,99 j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E; @@ -6097,7 +7394,6 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99; j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99; - // Caller ID 2nd Tone (0F):FD,B5,BA,07,DA,00,00,00 j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5; @@ -6107,76 +7403,62 @@ static void DAA_Coeff_Japan(int board) j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00; j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00; - // ;CR Registers // Config. Reg. 0 (filters) (cr0):FF - j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF; - + j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFE; // Config. Reg. 1 (dialing) (cr1):05 j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05; - // Config. Reg. 2 (caller ID) (cr2):04 j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04; - // Config. Reg. 3 (testloops) (cr3):00 ; j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00; - // Config. Reg. 4 (analog gain) (cr4):01 j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02; //0x01; - -// Config. Reg. 5 (Version) (cr5):02 + // Config. Reg. 5 (Version) (cr5):02 // Config. Reg. 6 (Reserved) (cr6):00 // Config. Reg. 7 (Reserved) (cr7):00 - -// ;xr Registers + // ;xr Registers // Ext. Reg. 0 (Interrupt Reg.) (xr0):02 + j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02; // SO_1 set to '1' because it is inverted. + // Ext. Reg. 1 (Interrupt enable) (xr1):1C -// Ext. Reg. 1 (Interrupt enable) (xr1):1C j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C; // RING, Caller ID, VDD_OK + // Ext. Reg. 2 (Cadence Time Out) (xr2):7D -// Ext. Reg. 2 (Cadence Time Out) (xr2):7D j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D; - // Ext. Reg. 3 (DC Char) (xr3):22 ; j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x22; - // Ext. Reg. 4 (Cadence) (xr4):00 j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00; - // Ext. Reg. 5 (Ring timer) (xr5):22 j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22; - // Ext. Reg. 6 (Power State) (xr6):00 j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00; - // Ext. Reg. 7 (Vdd) (xr7):40 j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40; // 0x40 ??? Should it be 0x00? - -// DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz + // DTMF Tone 1 (0B): 11,B3,5A,2C ; 697 Hz // 12,33,5A,C3 ; 770 Hz // 13,3C,5B,32 ; 852 Hz // 1D,1B,5C,CC ; 941 Hz + j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A; j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C; - // DTMF Tone 2 (0C): 32,32,52,B3 ; 1209 Hz // EC,1D,52,22 ; 1336 Hz // AA,AC,51,D2 ; 1477 Hz // 9B,3B,51,25 ; 1633 Hz - j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52; j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3; - } static s16 tone_table[][19] = { - { // f20_50[] + { // f20_50[] 11 32538, // A1 = 1.985962 -32325, // A2 = -0.986511 -343, // B2 = -0.010493 @@ -6197,7 +7479,7 @@ static s16 tone_table[][19] = 21, // 21/32 in-band to broad-band ratio 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 }, - { // f133_200[] + { // f133_200[] 12 32072, // A1 = 1.95752 -31896, // A2 = -0.973419 -435, // B2 = -0.013294 @@ -6218,7 +7500,7 @@ static s16 tone_table[][19] = 21, // 21/32 in-band to broad-band ratio 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 }, - { // 300.txt + { // 300.txt 13 31769, // A1 = -1.939026 -32584, // A2 = 0.994385 -475, // B2 = -0.014522 @@ -6239,7 +7521,7 @@ static s16 tone_table[][19] = 21, // 21/32 in-band to broad-band ratio 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 }, - { // f300_420[] + { // f300_420[] 14 30750, // A1 = 1.876892 -31212, // A2 = -0.952515 -804, // B2 = -0.024541 @@ -6260,7 +7542,7 @@ static s16 tone_table[][19] = 21, // 21/32 in-band to broad-band ratio 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 }, - { // 330.txt + { // 330.txt 15 31613, // A1 = -1.929565 -32646, // A2 = 0.996277 -185, // B2 = -0.005657 @@ -6281,7 +7563,7 @@ static s16 tone_table[][19] = 21, // 21/32 in-band to broad-band ratio 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 }, - { // f300_425[] + { // f300_425[] 16 30741, // A1 = 1.876282 -31475, // A2 = -0.960541 -703, // B2 = -0.021484 @@ -6302,7 +7584,7 @@ static s16 tone_table[][19] = 21, // 21/32 in-band to broad-band ratio 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 }, - { // f330_440[] + { // f330_440[] 17 30627, // A1 = 1.869324 -31338, // A2 = -0.95636 -843, // B2 = -0.025749 @@ -6323,7 +7605,7 @@ static s16 tone_table[][19] = 21, // 21/32 in-band to broad-band ratio 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 }, - { // 340.txt + { // 340.txt 18 31546, // A1 = -1.925476 -32646, // A2 = 0.996277 -445, // B2 = -0.013588 @@ -6344,7 +7626,7 @@ static s16 tone_table[][19] = 21, // 21/32 in-band to broad-band ratio 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 }, - { // f350_400[] + { // f350_400[] 19 31006, // A1 = 1.892517 -32029, // A2 = -0.977448 -461, // B2 = -0.014096 @@ -7708,21 +8990,19 @@ static s16 tone_table[][19] = 159, // Minimum in-band energy threshold 21, // 21/32 in-band to broad-band ratio 0x0FF5 // shift-mask 0x0FF (look at 16 half-frames) bit count = 5 - },}; - + }, +}; static int ixj_init_filter(int board, IXJ_FILTER * jf) { unsigned short cmd; int cnt, max; IXJ *j = &ixj[board]; - if (jf->filter > 3) { return -1; } if (ixj_WriteDSPCommand(0x5154 + jf->filter, board)) // Select Filter return -1; - if (!jf->enable) { if (ixj_WriteDSPCommand(0x5152, board)) // Disable Filter @@ -7733,7 +9013,6 @@ static int ixj_init_filter(int board, IXJ_FILTER * jf) if (ixj_WriteDSPCommand(0x5153, board)) // Enable Filter return -1; - // Select the filter (f0 - f3) to use. if (ixj_WriteDSPCommand(0x5154 + jf->filter, board)) return -1; @@ -7750,7 +9029,6 @@ static int ixj_init_filter(int board, IXJ_FILTER * jf) // frequency we want. if (ixj_WriteDSPCommand(0x5170 + jf->filter, board)) return -1; - if (j->ver.low != 0x12) { cmd = 0x515B; max = 19; @@ -7760,23 +9038,12 @@ static int ixj_init_filter(int board, IXJ_FILTER * jf) } if (ixj_WriteDSPCommand(cmd, board)) return -1; - for (cnt = 0; cnt < max; cnt++) { - if (ixj_WriteDSPCommand(tone_table[jf->freq][cnt], board)) + if (ixj_WriteDSPCommand(tone_table[jf->freq - 12][cnt], board)) return -1; } -/* if(j->ver.low != 0x12) - { - if(ixj_WriteDSPCommand(7, board)) - return -1; - if(ixj_WriteDSPCommand(159, board)) - return -1; - if(ixj_WriteDSPCommand(21, board)) - return -1; - if(ixj_WriteDSPCommand(0x0FF5, board)) - return -1; - } */ } + j->filter_en[jf->filter] = jf->enable; return 0; } @@ -7784,7 +9051,6 @@ static int ixj_init_tone(int board, IXJ_TONE * ti) { int freq0, freq1; unsigned short data; - if (ti->freq0) { freq0 = ti->freq0; } else { @@ -7797,18 +9063,15 @@ static int ixj_init_tone(int board, IXJ_TONE * ti) freq1 = 0x7FFF; } -// if(ti->tone_index > 12 && ti->tone_index < 28) + if(ti->tone_index > 12 && ti->tone_index < 28) { if (ixj_WriteDSPCommand(0x6800 + ti->tone_index, board)) return -1; - if (ixj_WriteDSPCommand(0x6000 + (ti->gain0 << 4) + ti->gain1, board)) return -1; - data = freq0; if (ixj_WriteDSPCommand(data, board)) return -1; - data = freq1; if (ixj_WriteDSPCommand(data, board)) return -1; diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h index 4a928c1803f6..ca4e264e62a5 100644 --- a/drivers/telephony/ixj.h +++ b/drivers/telephony/ixj.h @@ -1,4 +1,4 @@ -/* +/****************************************************************************** * ixj.h * * Device Driver for the Internet PhoneJACK and @@ -22,8 +22,20 @@ * at our website: http://www.quicknet.net * * Fixes: - */ -static char ixj_h_rcsid[] = "$Id: ixj.h,v 3.4 1999/12/16 22:18:36 root Exp root $"; + * + * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET + * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION + * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + *****************************************************************************/ +static char ixj_h_rcsid[] = "$Id: ixj.h,v 3.14 2000/03/30 22:06:48 eokerson Exp $"; #ifndef _I386_TYPES_H #include @@ -60,6 +72,27 @@ typedef struct { unsigned char high; } BYTES; +typedef union { + BYTES bytes; + short word; +} IXJ_WORD; + +typedef struct{ + unsigned int b0:1; + unsigned int b1:1; + unsigned int b2:1; + unsigned int b3:1; + unsigned int b4:1; + unsigned int b5:1; + unsigned int b6:1; + unsigned int b7:1; +} IXJ_CBITS; + +typedef union{ + IXJ_CBITS cbits; + char cbyte; +} IXJ_CBYTE; + int ixj_WriteDSPCommand(unsigned short, int board); /****************************************************************************** @@ -325,6 +358,199 @@ typedef struct { unsigned short micpreamp; } MIX; +/****************************************************************************** +* +* These structures deal with the control logic on the Internet PhoneCARD +* +******************************************************************************/ +typedef struct { + unsigned int x0:4; // unused bits + + unsigned int ed:1; // Event Detect + + unsigned int drf:1; // Smart Cable Removal Flag 1=no cable + + unsigned int dspf:1; // DSP Flag 1=DSP Ready + + unsigned int crr:1; // Control Register Ready + +} COMMAND_REG1; + +typedef union { + COMMAND_REG1 bits; + unsigned char byte; +} PCMCIA_CR1; + +typedef struct { + unsigned int x0:4; // unused bits + + unsigned int rstc:1; // Smart Cable Reset + + unsigned int pwr:1; // Smart Cable Power + + unsigned int x1:2; // unused bits + +} COMMAND_REG2; + +typedef union { + COMMAND_REG2 bits; + unsigned char byte; +} PCMCIA_CR2; + +typedef struct { + unsigned int addr:5; // R/W Smart Cable Register Address + + unsigned int rw:1; // Read / Write flag + + unsigned int dev:2; // 2 bit Smart Cable Device Address + +} CONTROL_REG; + +typedef union { + CONTROL_REG bits; + unsigned char byte; +} PCMCIA_SCCR; + +typedef struct { + unsigned int hsw:1; + unsigned int det:1; + unsigned int led2:1; + unsigned int led1:1; + unsigned int ring1:1; + unsigned int ring0:1; + unsigned int x:1; + unsigned int powerdown:1; +} PCMCIA_SLIC_REG; + +typedef union { + PCMCIA_SLIC_REG bits; + unsigned char byte; +} PCMCIA_SLIC; + +typedef struct { + unsigned int cpd:1; // Chip Power Down + + unsigned int mpd:1; // MIC Bias Power Down + + unsigned int hpd:1; // Handset Drive Power Down + + unsigned int lpd:1; // Line Drive Power Down + + unsigned int spd:1; // Speaker Drive Power Down + + unsigned int x:2; // unused bits + + unsigned int sr:1; // Software Reset + +} Si3CONTROL1; + +typedef union { + Si3CONTROL1 bits; + unsigned char byte; +} Si3C1; + +typedef struct { + unsigned int al:1; // Analog Loopback DAC analog -> ADC analog + + unsigned int dl2:1; // Digital Loopback DAC -> ADC one bit + + unsigned int dl1:1; // Digital Loopback ADC -> DAC one bit + + unsigned int pll:1; // 1 = div 10, 0 = div 5 + + unsigned int hpd:1; // HPF disable + + unsigned int x:3; // unused bits + +} Si3CONTROL2; + +typedef union { + Si3CONTROL2 bits; + unsigned char byte; +} Si3C2; + +typedef struct { + unsigned int iir:1; // 1 enables IIR, 0 enables FIR + + unsigned int him:1; // Handset Input Mute + + unsigned int mcm:1; // MIC In Mute + + unsigned int mcg:2; // MIC In Gain + + unsigned int lim:1; // Line In Mute + + unsigned int lig:2; // Line In Gain + +} Si3RXGAIN; + +typedef union { + Si3RXGAIN bits; + unsigned char byte; +} Si3RXG; + +typedef struct { + unsigned int hom:1; // Handset Out Mute + + unsigned int lom:1; // Line Out Mute + + unsigned int rxg:5; // RX PGA Gain + + unsigned int x:1; // unused bit + +} Si3ADCVOLUME; + +typedef union { + Si3ADCVOLUME bits; + unsigned char byte; +} Si3ADC; + +typedef struct { + unsigned int srm:1; // Speaker Right Mute + + unsigned int slm:1; // Speaker Left Mute + + unsigned int txg:5; // TX PGA Gain + + unsigned int x:1; // unused bit + +} Si3DACVOLUME; + +typedef union { + Si3DACVOLUME bits; + unsigned char byte; +} Si3DAC; + +typedef struct { + unsigned int x:5; // unused bit + + unsigned int losc:1; // Line Out Short Circuit + + unsigned int srsc:1; // Speaker Right Short Circuit + + unsigned int slsc:1; // Speaker Left Short Circuit + +} Si3STATUSREPORT; + +typedef union { + Si3STATUSREPORT bits; + unsigned char byte; +} Si3STAT; + +typedef struct { + unsigned int sot:2; // Speaker Out Attenuation + + unsigned int lot:2; // Line Out Attenuation + + unsigned int x:4; // unused bits + +} Si3ANALOGATTN; + +typedef union { + Si3ANALOGATTN bits; + unsigned char byte; +} Si3AATT; + /****************************************************************************** * * These structures deal with the DAA on the Internet LineJACK @@ -853,11 +1079,50 @@ enum IXJ_EXTENSIONS { POST_IOCTL }; +typedef struct { + char enable; + char en_filter; + unsigned int filter; + unsigned int state; // State 0 when cadence has not started. + + unsigned int on1; // State 1 + + unsigned long on1min; // State 1 - 10% + jiffies + unsigned long on1dot; // State 1 + jiffies + + unsigned long on1max; // State 1 + 10% + jiffies + + unsigned int off1; // State 2 + + unsigned long off1min; + unsigned long off1max; + unsigned int on2; // State 3 + + unsigned long on2min; + unsigned long on2dot; + unsigned long on2max; + unsigned int off2; // State 4 + + unsigned long off2min; + unsigned long off2max; + unsigned int on3; // State 5 + + unsigned long on3min; + unsigned long on3dot; + unsigned long on3max; + unsigned int off3; // State 6 + + unsigned long off3min; + unsigned long off3max; +} IXJ_CADENCE_F; + typedef struct { unsigned int busytone:1; unsigned int dialtone:1; unsigned int ringback:1; unsigned int ringing:1; + unsigned int playing:1; + unsigned int recording:1; unsigned int cringing:1; unsigned int play_first_frame:1; unsigned int pstn_present:1; @@ -868,6 +1133,28 @@ typedef struct { unsigned int ts85_loaded:1; unsigned int dtmf_oob:1; // DTMF Out-Of-Band + unsigned int pcmciascp:1; // Smart Cable Present + + unsigned int pcmciasct:2; // Smart Cable Type + + unsigned int pcmciastate:3; // Smart Cable Init State + + unsigned int inwrite:1; // Currently writing + + unsigned int inread:1; // Currently reading + + unsigned int incheck:1; // Currently checking the smart cable + + unsigned int cidplay:1; // Currently playing Caller ID + + unsigned int cidring:1; // This is the ring for Caller ID + + unsigned int cidsent:1; // Caller ID has been sent + + unsigned int cidcw_ack:1; // Caller ID CW ACK (from CPE) + + unsigned int x:6; // unsed bits + } IXJ_FLAGS; /****************************************************************************** @@ -884,15 +1171,19 @@ typedef struct { unsigned int serial; struct phone_capability caplist[30]; unsigned int caps; + unsigned int country; struct pnp_dev *dev; unsigned int cardtype; unsigned int rec_codec; char rec_mode; unsigned int play_codec; + unsigned int cid_play_codec; char play_mode; IXJ_FLAGS flags; unsigned int rec_frame_size; unsigned int play_frame_size; + unsigned int cid_base_frame_size; + unsigned long cidcw_wait; int aec_level; int readers, writers; struct wait_queue *poll_q; @@ -919,6 +1210,7 @@ typedef struct { char maxrings; IXJ_CADENCE *cadence_t; int tone_cadence_state; + IXJ_CADENCE_F cadence_f[4]; DTMF dtmf; CPTF cptf; BYTES dsp; @@ -933,30 +1225,50 @@ typedef struct { PLD_SLICW pld_slicw; PLD_SLICR pld_slicr; PLD_CLOCK pld_clock; + PCMCIA_CR1 pccr1; + PCMCIA_CR2 pccr2; + PCMCIA_SCCR psccr; + PCMCIA_SLIC pslic; + char pscdd; + Si3C1 sic1; + Si3C2 sic2; + Si3RXG sirxg; + Si3ADC siadc; + Si3DAC sidac; + Si3STAT sistat; + Si3AATT siaatt; MIX mix; unsigned short ring_cadence; int ring_cadence_t; unsigned long ring_cadence_jif; + unsigned long checkwait; int intercom; int m_hook; int r_hook; char pstn_envelope; char pstn_cid_intr; + unsigned char fskz; + unsigned char fskphase; + unsigned char fskcnt; unsigned pstn_cid_recieved; - IXJ_CID cid; + PHONE_CID cid; + PHONE_CID cid_send; unsigned long pstn_ring_start; + unsigned long pstn_ring_stop; unsigned long pstn_winkstart; unsigned int winktime; + unsigned long flash_end; char port; union telephony_exception ex; char daa_mode; + char daa_country; unsigned long pstn_sleeptil; DAA_REGS m_DAAShadowRegs; Proc_Info_Type Info_read; Proc_Info_Type Info_write; unsigned short frame_count; - unsigned int filter_cadence; unsigned int filter_hist[4]; + unsigned char filter_en[4]; unsigned short proc_load; unsigned long framesread; unsigned long frameswritten; @@ -965,6 +1277,8 @@ typedef struct { unsigned long timerchecks; unsigned long txreadycheck; unsigned long rxreadycheck; + short fskdata[8000]; + int fskdcnt; } IXJ; typedef int (*IXJ_REGFUNC) (IXJ * j, unsigned long arg); diff --git a/fs/affs/file.c b/fs/affs/file.c index 1961b4ec3493..2707844779d4 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -221,6 +221,8 @@ calc_key(struct inode *inode, int *ext) for (index = 0; index < 4; index++) { kc = &inode->u.affs_i.i_ec->kc[index]; + if (kc->kc_last == -1) /* don't look in cache if invalid */ + continue; if (*ext == kc->kc_this_seq) { return kc->kc_this_key; } else if (*ext == kc->kc_this_seq + 1) { @@ -893,7 +895,7 @@ out_truncate: /* Invalidate cache */ if (inode->u.affs_i.i_ec) { inode->u.affs_i.i_ec->max_ext = 0; - for (key = 0; key < 3; key++) { + for (key = 0; key < 4; key++) { inode->u.affs_i.i_ec->kc[key].kc_next_key = 0; inode->u.affs_i.i_ec->kc[key].kc_last = -1; } diff --git a/fs/proc/array.c b/fs/proc/array.c index 750443e1f806..75ddf916e8d6 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -1486,7 +1486,7 @@ static int process_unauthorized(int type, int pid) case PROC_PID_CPU: return 0; } - if(capable(CAP_DAC_OVERRIDE) || (current->fsuid == euid && ok)) + if((current->fsuid == euid && ok) || capable(CAP_DAC_OVERRIDE)) return 0; return 1; } diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h index 0338d70f1dac..b89c68148cf1 100644 --- a/include/asm-alpha/unistd.h +++ b/include/asm-alpha/unistd.h @@ -315,7 +315,7 @@ #define __NR_mincore 375 /* implemented in 2.3 */ #define __NR_pciconfig_iobase 376 -#if defined(__LIBRARY__) && defined(__GNUC__) +#if defined(__GNUC__) #define _syscall_return(type) \ return (_sc_err ? errno = _sc_ret, _sc_ret = -1L : 0), (type) _sc_ret @@ -495,7 +495,7 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6)\ _syscall_return(type); \ } -#endif /* __LIBRARY__ && __GNUC__ */ +#endif /* __GNUC__ */ #ifdef __KERNEL_SYSCALLS__ diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index b98893662383..8cf99ea4ad0d 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -48,6 +48,8 @@ struct cpuinfo_x86 { #define X86_VENDOR_UMC 3 #define X86_VENDOR_NEXGEN 4 #define X86_VENDOR_CENTAUR 5 +#define X86_VENDOR_RISE 6 +#define X86_VENDOR_TRANSMETA 7 #define X86_VENDOR_UNKNOWN 0xff /* diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h index aa9cbbac59cc..286970f5a123 100644 --- a/include/linux/cdrom.h +++ b/include/linux/cdrom.h @@ -443,6 +443,7 @@ struct cdrom_generic_command #define GPCMD_PAUSE_RESUME 0x4b #define GPCMD_PLAY_AUDIO_10 0x45 #define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TI 0x48 #define GPCMD_PLAY_CD 0xbc #define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e #define GPCMD_READ_10 0x28 diff --git a/include/linux/falc-lh.h b/include/linux/falc-lh.h new file mode 100644 index 000000000000..b076927d5ca7 --- /dev/null +++ b/include/linux/falc-lh.h @@ -0,0 +1,1231 @@ +/* + * falc.h Description of the Siemens FALC T1/E1 framer. + * + * Author: Ivan Passos + * + * Copyright: (c) 2000 Cyclades Corp. + * + * 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. + * + * $Log: falc.h,v $ + * Revision 1.1 2000/05/15 ivan + * Included DJA bits for the LIM2 register. + * + * Revision 1.0 2000/02/22 ivan + * Initial version. + * + */ + +#ifndef _FALC_LH_H +#define _FALC_LH_H + +#define NUM_OF_T1_CHANNELS 24 +#define NUM_OF_E1_CHANNELS 32 + +/*>>>>>>>>>>>>>>>>> FALC Register Bits (Transmit Mode) <<<<<<<<<<<<<<<<<<< */ + +/* CMDR (Command Register) + ---------------- E1 & T1 ------------------------------ */ +#define CMDR_RMC 0x80 +#define CMDR_RRES 0x40 +#define CMDR_XREP 0x20 +#define CMDR_XRES 0x10 +#define CMDR_XHF 0x08 +#define CMDR_XTF 0x04 +#define CMDR_XME 0x02 +#define CMDR_SRES 0x01 + +/* MODE (Mode Register) + ----------------- E1 & T1 ----------------------------- */ +#define MODE_MDS2 0x80 +#define MODE_MDS1 0x40 +#define MODE_MDS0 0x20 +#define MODE_BRAC 0x10 +#define MODE_HRAC 0x08 + +/* IPC (Interrupt Port Configuration) + ----------------- E1 & T1 ----------------------------- */ +#define IPC_VIS 0x80 +#define IPC_SCI 0x04 +#define IPC_IC1 0x02 +#define IPC_IC0 0x01 + +/* CCR1 (Common Configuration Register 1) + ----------------- E1 & T1 ----------------------------- */ +#define CCR1_SFLG 0x80 +#define CCR1_XTS16RA 0x40 +#define CCR1_BRM 0x40 +#define CCR1_CASSYM 0x20 +#define CCR1_EDLX 0x20 +#define CCR1_EITS 0x10 +#define CCR1_ITF 0x08 +#define CCR1_RFT1 0x02 +#define CCR1_RFT0 0x01 + +/* CCR3 (Common Configuration Register 3) + ---------------- E1 & T1 ------------------------------ */ + +#define CCR3_PRE1 0x80 +#define CCR3_PRE0 0x40 +#define CCR3_EPT 0x20 +#define CCR3_RADD 0x10 +#define CCR3_RCRC 0x04 +#define CCR3_XCRC 0x02 + + +/* RTR1-4 (Receive Timeslot Register 1-4) + ---------------- E1 & T1 ------------------------------ */ + +#define RTR1_TS0 0x80 +#define RTR1_TS1 0x40 +#define RTR1_TS2 0x20 +#define RTR1_TS3 0x10 +#define RTR1_TS4 0x08 +#define RTR1_TS5 0x04 +#define RTR1_TS6 0x02 +#define RTR1_TS7 0x01 + +#define RTR2_TS8 0x80 +#define RTR2_TS9 0x40 +#define RTR2_TS10 0x20 +#define RTR2_TS11 0x10 +#define RTR2_TS12 0x08 +#define RTR2_TS13 0x04 +#define RTR2_TS14 0x02 +#define RTR2_TS15 0x01 + +#define RTR3_TS16 0x80 +#define RTR3_TS17 0x40 +#define RTR3_TS18 0x20 +#define RTR3_TS19 0x10 +#define RTR3_TS20 0x08 +#define RTR3_TS21 0x04 +#define RTR3_TS22 0x02 +#define RTR3_TS23 0x01 + +#define RTR4_TS24 0x80 +#define RTR4_TS25 0x40 +#define RTR4_TS26 0x20 +#define RTR4_TS27 0x10 +#define RTR4_TS28 0x08 +#define RTR4_TS29 0x04 +#define RTR4_TS30 0x02 +#define RTR4_TS31 0x01 + + +/* TTR1-4 (Transmit Timeslot Register 1-4) + ---------------- E1 & T1 ------------------------------ */ + +#define TTR1_TS0 0x80 +#define TTR1_TS1 0x40 +#define TTR1_TS2 0x20 +#define TTR1_TS3 0x10 +#define TTR1_TS4 0x08 +#define TTR1_TS5 0x04 +#define TTR1_TS6 0x02 +#define TTR1_TS7 0x01 + +#define TTR2_TS8 0x80 +#define TTR2_TS9 0x40 +#define TTR2_TS10 0x20 +#define TTR2_TS11 0x10 +#define TTR2_TS12 0x08 +#define TTR2_TS13 0x04 +#define TTR2_TS14 0x02 +#define TTR2_TS15 0x01 + +#define TTR3_TS16 0x80 +#define TTR3_TS17 0x40 +#define TTR3_TS18 0x20 +#define TTR3_TS19 0x10 +#define TTR3_TS20 0x08 +#define TTR3_TS21 0x04 +#define TTR3_TS22 0x02 +#define TTR3_TS23 0x01 + +#define TTR4_TS24 0x80 +#define TTR4_TS25 0x40 +#define TTR4_TS26 0x20 +#define TTR4_TS27 0x10 +#define TTR4_TS28 0x08 +#define TTR4_TS29 0x04 +#define TTR4_TS30 0x02 +#define TTR4_TS31 0x01 + + + +/* IMR0-4 (Interrupt Mask Register 0-4) + + ----------------- E1 & T1 ----------------------------- */ + +#define IMR0_RME 0x80 +#define IMR0_RFS 0x40 +#define IMR0_T8MS 0x20 +#define IMR0_ISF 0x20 +#define IMR0_RMB 0x10 +#define IMR0_CASC 0x08 +#define IMR0_RSC 0x08 +#define IMR0_CRC6 0x04 +#define IMR0_CRC4 0x04 +#define IMR0_PDEN 0x02 +#define IMR0_RPF 0x01 + +#define IMR1_CASE 0x80 +#define IMR1_RDO 0x40 +#define IMR1_ALLS 0x20 +#define IMR1_XDU 0x10 +#define IMR1_XMB 0x08 +#define IMR1_XLSC 0x02 +#define IMR1_XPR 0x01 +#define IMR1_LLBSC 0x80 + +#define IMR2_FAR 0x80 +#define IMR2_LFA 0x40 +#define IMR2_MFAR 0x20 +#define IMR2_T400MS 0x10 +#define IMR2_LMFA 0x10 +#define IMR2_AIS 0x08 +#define IMR2_LOS 0x04 +#define IMR2_RAR 0x02 +#define IMR2_RA 0x01 + +#define IMR3_ES 0x80 +#define IMR3_SEC 0x40 +#define IMR3_LMFA16 0x20 +#define IMR3_AIS16 0x10 +#define IMR3_RA16 0x08 +#define IMR3_API 0x04 +#define IMR3_XSLP 0x20 +#define IMR3_XSLN 0x10 +#define IMR3_LLBSC 0x08 +#define IMR3_XRS 0x04 +#define IMR3_SLN 0x02 +#define IMR3_SLP 0x01 + +#define IMR4_LFA 0x80 +#define IMR4_FER 0x40 +#define IMR4_CER 0x20 +#define IMR4_AIS 0x10 +#define IMR4_LOS 0x08 +#define IMR4_CVE 0x04 +#define IMR4_SLIP 0x02 +#define IMR4_EBE 0x01 + +/* FMR0-5 for E1 and T1 (Framer Mode Register ) */ + +#define FMR0_XC1 0x80 +#define FMR0_XC0 0x40 +#define FMR0_RC1 0x20 +#define FMR0_RC0 0x10 +#define FMR0_EXTD 0x08 +#define FMR0_ALM 0x04 +#define E1_FMR0_FRS 0x02 +#define T1_FMR0_FRS 0x08 +#define FMR0_SRAF 0x04 +#define FMR0_EXLS 0x02 +#define FMR0_SIM 0x01 + +#define FMR1_MFCS 0x80 +#define FMR1_AFR 0x40 +#define FMR1_ENSA 0x20 +#define FMR1_CTM 0x80 +#define FMR1_SIGM 0x40 +#define FMR1_EDL 0x20 +#define FMR1_PMOD 0x10 +#define FMR1_XFS 0x08 +#define FMR1_CRC 0x08 +#define FMR1_ECM 0x04 +#define FMR1_IMOD 0x02 +#define FMR1_XAIS 0x01 + +#define FMR2_RFS1 0x80 +#define FMR2_RFS0 0x40 +#define FMR2_MCSP 0x40 +#define FMR2_RTM 0x20 +#define FMR2_SSP 0x20 +#define FMR2_DAIS 0x10 +#define FMR2_SAIS 0x08 +#define FMR2_PLB 0x04 +#define FMR2_AXRA 0x02 +#define FMR2_ALMF 0x01 +#define FMR2_EXZE 0x01 + +#define LOOP_RTM 0x40 +#define LOOP_SFM 0x40 +#define LOOP_ECLB 0x20 +#define LOOP_CLA 0x1f + +/*--------------------- E1 ----------------------------*/ +#define FMR3_XLD 0x20 +#define FMR3_XLU 0x10 + +/*--------------------- T1 ----------------------------*/ +#define FMR4_AIS3 0x80 +#define FMR4_TM 0x40 +#define FMR4_XRA 0x20 +#define FMR4_SSC1 0x10 +#define FMR4_SSC0 0x08 +#define FMR4_AUTO 0x04 +#define FMR4_FM1 0x02 +#define FMR4_FM0 0x01 + +#define FMR5_SRS 0x80 +#define FMR5_EIBR 0x40 +#define FMR5_XLD 0x20 +#define FMR5_XLU 0x10 + + +/* LOOP (Channel Loop Back) + + ------------------ E1 & T1 ---------------------------- */ + +#define LOOP_SFM 0x40 +#define LOOP_ECLB 0x20 +#define LOOP_CLA4 0x10 +#define LOOP_CLA3 0x08 +#define LOOP_CLA2 0x04 +#define LOOP_CLA1 0x02 +#define LOOP_CLA0 0x01 + + + +/* XSW (Transmit Service Word Pulseframe) + + ------------------- E1 --------------------------- */ + +#define XSW_XSIS 0x80 +#define XSW_XRA 0x20 +#define XSW_XY0 0x10 +#define XSW_XY1 0x08 +#define XSW_XY2 0x04 +#define XSW_XY3 0x02 +#define XSW_XY4 0x01 + + +/* XSP (Transmit Spare Bits) + + ------------------- E1 --------------------------- */ + +#define XSP_XAP 0x80 +#define XSP_CASEN 0x40 +#define XSP_TT0 0x20 +#define XSP_EBP 0x10 +#define XSP_AXS 0x08 +#define XSP_XSIF 0x04 +#define XSP_XS13 0x02 +#define XSP_XS15 0x01 + + +/* XC0/1 (Transmit Control 0/1) + ------------------ E1 & T1 ---------------------------- */ + +#define XC0_SA8E 0x80 +#define XC0_SA7E 0x40 +#define XC0_SA6E 0x20 +#define XC0_SA5E 0x10 +#define XC0_SA4E 0x08 +#define XC0_BRM 0x80 +#define XC0_MFBS 0x40 +#define XC0_SFRZ 0x10 +#define XC0_XCO2 0x04 +#define XC0_XCO1 0x02 +#define XC0_XCO0 0x01 + +#define XC1_XTO5 0x20 +#define XC1_XTO4 0x10 +#define XC1_XTO3 0x08 +#define XC1_XTO2 0x04 +#define XC1_XTO1 0x02 +#define XC1_XTO0 0x01 + + +/* RC0/1 (Receive Control 0/1) + ------------------ E1 & T1 ---------------------------- */ + +#define RC0_SICS 0x40 +#define RC0_CRCI 0x20 +#define RC0_XCRCI 0x10 +#define RC0_RDIS 0x08 +#define RC0_RCO2 0x04 +#define RC0_RCO1 0x02 +#define RC0_RCO0 0x01 + +#define RC1_SWD 0x80 +#define RC1_ASY4 0x40 +#define RC1_RRAM 0x40 +#define RC1_RTO5 0x20 +#define RC1_RTO4 0x10 +#define RC1_RTO3 0x08 +#define RC1_RTO2 0x04 +#define RC1_RTO1 0x02 +#define RC1_RTO0 0x01 + + + +/* XPM0-2 (Transmit Pulse Mask 0-2) + --------------------- E1 & T1 ------------------------- */ + +#define XPM0_XP12 0x80 +#define XPM0_XP11 0x40 +#define XPM0_XP10 0x20 +#define XPM0_XP04 0x10 +#define XPM0_XP03 0x08 +#define XPM0_XP02 0x04 +#define XPM0_XP01 0x02 +#define XPM0_XP00 0x01 + +#define XPM1_XP30 0x80 +#define XPM1_XP24 0x40 +#define XPM1_XP23 0x20 +#define XPM1_XP22 0x10 +#define XPM1_XP21 0x08 +#define XPM1_XP20 0x04 +#define XPM1_XP14 0x02 +#define XPM1_XP13 0x01 + +#define XPM2_XLHP 0x80 +#define XPM2_XLT 0x40 +#define XPM2_DAXLT 0x20 +#define XPM2_XP34 0x08 +#define XPM2_XP33 0x04 +#define XPM2_XP32 0x02 +#define XPM2_XP31 0x01 + + +/* TSWM (Transparent Service Word Mask) + ------------------ E1 ---------------------------- */ + +#define TSWM_TSIS 0x80 +#define TSWM_TSIF 0x40 +#define TSWM_TRA 0x20 +#define TSWM_TSA4 0x10 +#define TSWM_TSA5 0x08 +#define TSWM_TSA6 0x04 +#define TSWM_TSA7 0x02 +#define TSWM_TSA8 0x01 + +/* IDLE + + ------------------ E1 & T1 ----------------------- */ + +#define IDLE_IDL7 0x80 +#define IDLE_IDL6 0x40 +#define IDLE_IDL5 0x20 +#define IDLE_IDL4 0x10 +#define IDLE_IDL3 0x08 +#define IDLE_IDL2 0x04 +#define IDLE_IDL1 0x02 +#define IDLE_IDL0 0x01 + + +/* XSA4-8 + -------------------E1 ----------------------------- */ + +#define XSA4_XS47 0x80 +#define XSA4_XS46 0x40 +#define XSA4_XS45 0x20 +#define XSA4_XS44 0x10 +#define XSA4_XS43 0x08 +#define XSA4_XS42 0x04 +#define XSA4_XS41 0x02 +#define XSA4_XS40 0x01 + +#define XSA5_XS57 0x80 +#define XSA5_XS56 0x40 +#define XSA5_XS55 0x20 +#define XSA5_XS54 0x10 +#define XSA5_XS53 0x08 +#define XSA5_XS52 0x04 +#define XSA5_XS51 0x02 +#define XSA5_XS50 0x01 + +#define XSA6_XS67 0x80 +#define XSA6_XS66 0x40 +#define XSA6_XS65 0x20 +#define XSA6_XS64 0x10 +#define XSA6_XS63 0x08 +#define XSA6_XS62 0x04 +#define XSA6_XS61 0x02 +#define XSA6_XS60 0x01 + +#define XSA7_XS77 0x80 +#define XSA7_XS76 0x40 +#define XSA7_XS75 0x20 +#define XSA7_XS74 0x10 +#define XSA7_XS73 0x08 +#define XSA7_XS72 0x04 +#define XSA7_XS71 0x02 +#define XSA7_XS70 0x01 + +#define XSA8_XS87 0x80 +#define XSA8_XS86 0x40 +#define XSA8_XS85 0x20 +#define XSA8_XS84 0x10 +#define XSA8_XS83 0x08 +#define XSA8_XS82 0x04 +#define XSA8_XS81 0x02 +#define XSA8_XS80 0x01 + + +/* XDL1-3 (Transmit DL-Bit Register1-3 (read/write)) + ----------------------- T1 --------------------- */ + +#define XDL1_XDL17 0x80 +#define XDL1_XDL16 0x40 +#define XDL1_XDL15 0x20 +#define XDL1_XDL14 0x10 +#define XDL1_XDL13 0x08 +#define XDL1_XDL12 0x04 +#define XDL1_XDL11 0x02 +#define XDL1_XDL10 0x01 + +#define XDL2_XDL27 0x80 +#define XDL2_XDL26 0x40 +#define XDL2_XDL25 0x20 +#define XDL2_XDL24 0x10 +#define XDL2_XDL23 0x08 +#define XDL2_XDL22 0x04 +#define XDL2_XDL21 0x02 +#define XDL2_XDL20 0x01 + +#define XDL3_XDL37 0x80 +#define XDL3_XDL36 0x40 +#define XDL3_XDL35 0x20 +#define XDL3_XDL34 0x10 +#define XDL3_XDL33 0x08 +#define XDL3_XDL32 0x04 +#define XDL3_XDL31 0x02 +#define XDL3_XDL30 0x01 + + +/* ICB1-4 (Idle Channel Register 1-4) + ------------------ E1 ---------------------------- */ + +#define E1_ICB1_IC0 0x80 +#define E1_ICB1_IC1 0x40 +#define E1_ICB1_IC2 0x20 +#define E1_ICB1_IC3 0x10 +#define E1_ICB1_IC4 0x08 +#define E1_ICB1_IC5 0x04 +#define E1_ICB1_IC6 0x02 +#define E1_ICB1_IC7 0x01 + +#define E1_ICB2_IC8 0x80 +#define E1_ICB2_IC9 0x40 +#define E1_ICB2_IC10 0x20 +#define E1_ICB2_IC11 0x10 +#define E1_ICB2_IC12 0x08 +#define E1_ICB2_IC13 0x04 +#define E1_ICB2_IC14 0x02 +#define E1_ICB2_IC15 0x01 + +#define E1_ICB3_IC16 0x80 +#define E1_ICB3_IC17 0x40 +#define E1_ICB3_IC18 0x20 +#define E1_ICB3_IC19 0x10 +#define E1_ICB3_IC20 0x08 +#define E1_ICB3_IC21 0x04 +#define E1_ICB3_IC22 0x02 +#define E1_ICB3_IC23 0x01 + +#define E1_ICB4_IC24 0x80 +#define E1_ICB4_IC25 0x40 +#define E1_ICB4_IC26 0x20 +#define E1_ICB4_IC27 0x10 +#define E1_ICB4_IC28 0x08 +#define E1_ICB4_IC29 0x04 +#define E1_ICB4_IC30 0x02 +#define E1_ICB4_IC31 0x01 + +/* ICB1-4 (Idle Channel Register 1-4) + ------------------ T1 ---------------------------- */ + +#define T1_ICB1_IC1 0x80 +#define T1_ICB1_IC2 0x40 +#define T1_ICB1_IC3 0x20 +#define T1_ICB1_IC4 0x10 +#define T1_ICB1_IC5 0x08 +#define T1_ICB1_IC6 0x04 +#define T1_ICB1_IC7 0x02 +#define T1_ICB1_IC8 0x01 + +#define T1_ICB2_IC9 0x80 +#define T1_ICB2_IC10 0x40 +#define T1_ICB2_IC11 0x20 +#define T1_ICB2_IC12 0x10 +#define T1_ICB2_IC13 0x08 +#define T1_ICB2_IC14 0x04 +#define T1_ICB2_IC15 0x02 +#define T1_ICB2_IC16 0x01 + +#define T1_ICB3_IC17 0x80 +#define T1_ICB3_IC18 0x40 +#define T1_ICB3_IC19 0x20 +#define T1_ICB3_IC20 0x10 +#define T1_ICB3_IC21 0x08 +#define T1_ICB3_IC22 0x04 +#define T1_ICB3_IC23 0x02 +#define T1_ICB3_IC24 0x01 + +/* FMR3 (Framer Mode Register 3) + --------------------E1------------------------ */ + +#define FMR3_CMI 0x08 +#define FMR3_SYNSA 0x04 +#define FMR3_CFRZ 0x02 +#define FMR3_EXTIW 0x01 + + + +/* CCB1-3 (Clear Channel Register) + ------------------- T1 ----------------------- */ + +#define CCB1_CH1 0x80 +#define CCB1_CH2 0x40 +#define CCB1_CH3 0x20 +#define CCB1_CH4 0x10 +#define CCB1_CH5 0x08 +#define CCB1_CH6 0x04 +#define CCB1_CH7 0x02 +#define CCB1_CH8 0x01 + +#define CCB2_CH9 0x80 +#define CCB2_CH10 0x40 +#define CCB2_CH11 0x20 +#define CCB2_CH12 0x10 +#define CCB2_CH13 0x08 +#define CCB2_CH14 0x04 +#define CCB2_CH15 0x02 +#define CCB2_CH16 0x01 + +#define CCB3_CH17 0x80 +#define CCB3_CH18 0x40 +#define CCB3_CH19 0x20 +#define CCB3_CH20 0x10 +#define CCB3_CH21 0x08 +#define CCB3_CH22 0x04 +#define CCB3_CH23 0x02 +#define CCB3_CH24 0x01 + + +/* LIM0/1 (Line Interface Mode 0/1) + ------------------- E1 & T1 --------------------------- */ + +#define LIM0_XFB 0x80 +#define LIM0_XDOS 0x40 +#define LIM0_SCL1 0x20 +#define LIM0_SCL0 0x10 +#define LIM0_EQON 0x08 +#define LIM0_ELOS 0x04 +#define LIM0_LL 0x02 +#define LIM0_MAS 0x01 + +#define LIM1_EFSC 0x80 +#define LIM1_RIL2 0x40 +#define LIM1_RIL1 0x20 +#define LIM1_RIL0 0x10 +#define LIM1_DCOC 0x08 +#define LIM1_JATT 0x04 +#define LIM1_RL 0x02 +#define LIM1_DRS 0x01 + + +/* PCDR (Pulse Count Detection Register(Read/Write)) + ------------------ E1 & T1 ------------------------- */ + +#define PCDR_PCD7 0x80 +#define PCDR_PCD6 0x40 +#define PCDR_PCD5 0x20 +#define PCDR_PCD4 0x10 +#define PCDR_PCD3 0x08 +#define PCDR_PCD2 0x04 +#define PCDR_PCD1 0x02 +#define PCDR_PCD0 0x01 + +#define PCRR_PCR7 0x80 +#define PCRR_PCR6 0x40 +#define PCRR_PCR5 0x20 +#define PCRR_PCR4 0x10 +#define PCRR_PCR3 0x08 +#define PCRR_PCR2 0x04 +#define PCRR_PCR1 0x02 +#define PCRR_PCR0 0x01 + + +/* LIM2 (Line Interface Mode 2) + + ------------------ E1 & T1 ---------------------------- */ + +#define LIM2_DJA2 0x20 +#define LIM2_DJA1 0x10 +#define LIM2_LOS2 0x02 +#define LIM2_LOS1 0x01 + +/* LCR1 (Loop Code Register 1) */ + +#define LCR1_EPRM 0x80 +#define LCR1_XPRBS 0x40 + +/* SIC1 (System Interface Control 1) */ +#define SIC1_SRSC 0x80 +#define SIC1_RBS1 0x20 +#define SIC1_RBS0 0x10 +#define SIC1_SXSC 0x08 +#define SIC1_XBS1 0x02 +#define SIC1_XBS0 0x01 + +/* DEC (Disable Error Counter) + ------------------ E1 & T1 ---------------------------- */ + +#define DEC_DCEC3 0x20 +#define DEC_DBEC 0x10 +#define DEC_DCEC1 0x08 +#define DEC_DCEC 0x08 +#define DEC_DEBC 0x04 +#define DEC_DCVC 0x02 +#define DEC_DFEC 0x01 + + +/* FALC Register Bits (Receive Mode) + ---------------------------------------------------------------------------- */ + + +/* FRS0/1 (Framer Receive Status Register 0/1) + ----------------- E1 & T1 ---------------------------------- */ + +#define FRS0_LOS 0x80 +#define FRS0_AIS 0x40 +#define FRS0_LFA 0x20 +#define FRS0_RRA 0x10 +#define FRS0_API 0x08 +#define FRS0_NMF 0x04 +#define FRS0_LMFA 0x02 +#define FRS0_FSRF 0x01 + +#define FRS1_TS16RA 0x40 +#define FRS1_TS16LOS 0x20 +#define FRS1_TS16AIS 0x10 +#define FRS1_TS16LFA 0x08 +#define FRS1_EXZD 0x80 +#define FRS1_LLBDD 0x10 +#define FRS1_LLBAD 0x08 +#define FRS1_XLS 0x02 +#define FRS1_XLO 0x01 +#define FRS1_PDEN 0x40 + +/* FRS2/3 (Framer Receive Status Register 2/3) + ----------------- T1 ---------------------------------- */ + +#define FRS2_ESC2 0x80 +#define FRS2_ESC1 0x40 +#define FRS2_ESC0 0x20 + +#define FRS3_FEH5 0x20 +#define FRS3_FEH4 0x10 +#define FRS3_FEH3 0x08 +#define FRS3_FEH2 0x04 +#define FRS3_FEH1 0x02 +#define FRS3_FEH0 0x01 + + +/* RSW (Receive Service Word Pulseframe) + ----------------- E1 ------------------------------ */ + +#define RSW_RSI 0x80 +#define RSW_RRA 0x20 +#define RSW_RYO 0x10 +#define RSW_RY1 0x08 +#define RSW_RY2 0x04 +#define RSW_RY3 0x02 +#define RSW_RY4 0x01 + + +/* RSP (Receive Spare Bits / Additional Status) + ---------------- E1 ------------------------------- */ + +#define RSP_SI1 0x80 +#define RSP_SI2 0x40 +#define RSP_LLBDD 0x10 +#define RSP_LLBAD 0x08 +#define RSP_RSIF 0x04 +#define RSP_RS13 0x02 +#define RSP_RS15 0x01 + + +/* FECL (Framing Error Counter) + ---------------- E1 & T1 -------------------------- */ + +#define FECL_FE7 0x80 +#define FECL_FE6 0x40 +#define FECL_FE5 0x20 +#define FECL_FE4 0x10 +#define FECL_FE3 0x08 +#define FECL_FE2 0x04 +#define FECL_FE1 0x02 +#define FECL_FE0 0x01 + +#define FECH_FE15 0x80 +#define FECH_FE14 0x40 +#define FECH_FE13 0x20 +#define FECH_FE12 0x10 +#define FECH_FE11 0x08 +#define FECH_FE10 0x04 +#define FECH_FE9 0x02 +#define FECH_FE8 0x01 + + +/* CVCl (Code Violation Counter) + ----------------- E1 ------------------------- */ + +#define CVCL_CV7 0x80 +#define CVCL_CV6 0x40 +#define CVCL_CV5 0x20 +#define CVCL_CV4 0x10 +#define CVCL_CV3 0x08 +#define CVCL_CV2 0x04 +#define CVCL_CV1 0x02 +#define CVCL_CV0 0x01 + +#define CVCH_CV15 0x80 +#define CVCH_CV14 0x40 +#define CVCH_CV13 0x20 +#define CVCH_CV12 0x10 +#define CVCH_CV11 0x08 +#define CVCH_CV10 0x04 +#define CVCH_CV9 0x02 +#define CVCH_CV8 0x01 + + +/* CEC1-3L (CRC Error Counter) + ------------------ E1 ----------------------------- */ + +#define CEC1L_CR7 0x80 +#define CEC1L_CR6 0x40 +#define CEC1L_CR5 0x20 +#define CEC1L_CR4 0x10 +#define CEC1L_CR3 0x08 +#define CEC1L_CR2 0x04 +#define CEC1L_CR1 0x02 +#define CEC1L_CR0 0x01 + +#define CEC1H_CR15 0x80 +#define CEC1H_CR14 0x40 +#define CEC1H_CR13 0x20 +#define CEC1H_CR12 0x10 +#define CEC1H_CR11 0x08 +#define CEC1H_CR10 0x04 +#define CEC1H_CR9 0x02 +#define CEC1H_CR8 0x01 + +#define CEC2L_CR7 0x80 +#define CEC2L_CR6 0x40 +#define CEC2L_CR5 0x20 +#define CEC2L_CR4 0x10 +#define CEC2L_CR3 0x08 +#define CEC2L_CR2 0x04 +#define CEC2L_CR1 0x02 +#define CEC2L_CR0 0x01 + +#define CEC2H_CR15 0x80 +#define CEC2H_CR14 0x40 +#define CEC2H_CR13 0x20 +#define CEC2H_CR12 0x10 +#define CEC2H_CR11 0x08 +#define CEC2H_CR10 0x04 +#define CEC2H_CR9 0x02 +#define CEC2H_CR8 0x01 + +#define CEC3L_CR7 0x80 +#define CEC3L_CR6 0x40 +#define CEC3L_CR5 0x20 +#define CEC3L_CR4 0x10 +#define CEC3L_CR3 0x08 +#define CEC3L_CR2 0x04 +#define CEC3L_CR1 0x02 +#define CEC3L_CR0 0x01 + +#define CEC3H_CR15 0x80 +#define CEC3H_CR14 0x40 +#define CEC3H_CR13 0x20 +#define CEC3H_CR12 0x10 +#define CEC3H_CR11 0x08 +#define CEC3H_CR10 0x04 +#define CEC3H_CR9 0x02 +#define CEC3H_CR8 0x01 + + +/* CECL (CRC Error Counter) + + ------------------ T1 ----------------------------- */ + +#define CECL_CR7 0x80 +#define CECL_CR6 0x40 +#define CECL_CR5 0x20 +#define CECL_CR4 0x10 +#define CECL_CR3 0x08 +#define CECL_CR2 0x04 +#define CECL_CR1 0x02 +#define CECL_CR0 0x01 + +#define CECH_CR15 0x80 +#define CECH_CR14 0x40 +#define CECH_CR13 0x20 +#define CECH_CR12 0x10 +#define CECH_CR11 0x08 +#define CECH_CR10 0x04 +#define CECH_CR9 0x02 +#define CECH_CR8 0x01 + +/* EBCL (E Bit Error Counter) + ------------------- E1 & T1 ------------------------- */ + +#define EBCL_EB7 0x80 +#define EBCL_EB6 0x40 +#define EBCL_EB5 0x20 +#define EBCL_EB4 0x10 +#define EBCL_EB3 0x08 +#define EBCL_EB2 0x04 +#define EBCL_EB1 0x02 +#define EBCL_EB0 0x01 + +#define EBCH_EB15 0x80 +#define EBCH_EB14 0x40 +#define EBCH_EB13 0x20 +#define EBCH_EB12 0x10 +#define EBCH_EB11 0x08 +#define EBCH_EB10 0x04 +#define EBCH_EB9 0x02 +#define EBCH_EB8 0x01 + + +/* RSA4-8 (Receive Sa4-8-Bit Register) + -------------------- E1 --------------------------- */ + +#define RSA4_RS47 0x80 +#define RSA4_RS46 0x40 +#define RSA4_RS45 0x20 +#define RSA4_RS44 0x10 +#define RSA4_RS43 0x08 +#define RSA4_RS42 0x04 +#define RSA4_RS41 0x02 +#define RSA4_RS40 0x01 + +#define RSA5_RS57 0x80 +#define RSA5_RS56 0x40 +#define RSA5_RS55 0x20 +#define RSA5_RS54 0x10 +#define RSA5_RS53 0x08 +#define RSA5_RS52 0x04 +#define RSA5_RS51 0x02 +#define RSA5_RS50 0x01 + +#define RSA6_RS67 0x80 +#define RSA6_RS66 0x40 +#define RSA6_RS65 0x20 +#define RSA6_RS64 0x10 +#define RSA6_RS63 0x08 +#define RSA6_RS62 0x04 +#define RSA6_RS61 0x02 +#define RSA6_RS60 0x01 + +#define RSA7_RS77 0x80 +#define RSA7_RS76 0x40 +#define RSA7_RS75 0x20 +#define RSA7_RS74 0x10 +#define RSA7_RS73 0x08 +#define RSA7_RS72 0x04 +#define RSA7_RS71 0x02 +#define RSA7_RS70 0x01 + +#define RSA8_RS87 0x80 +#define RSA8_RS86 0x40 +#define RSA8_RS85 0x20 +#define RSA8_RS84 0x10 +#define RSA8_RS83 0x08 +#define RSA8_RS82 0x04 +#define RSA8_RS81 0x02 +#define RSA8_RS80 0x01 + +/* RSA6S (Receive Sa6 Bit Status Register) + ------------------------ T1 ------------------------- */ + +#define RSA6S_SX 0x20 +#define RSA6S_SF 0x10 +#define RSA6S_SE 0x08 +#define RSA6S_SC 0x04 +#define RSA6S_SA 0x02 +#define RSA6S_S8 0x01 + + +/* RDL1-3 Receive DL-Bit Register1-3) + ------------------------ T1 ------------------------- */ + +#define RDL1_RDL17 0x80 +#define RDL1_RDL16 0x40 +#define RDL1_RDL15 0x20 +#define RDL1_RDL14 0x10 +#define RDL1_RDL13 0x08 +#define RDL1_RDL12 0x04 +#define RDL1_RDL11 0x02 +#define RDL1_RDL10 0x01 + +#define RDL2_RDL27 0x80 +#define RDL2_RDL26 0x40 +#define RDL2_RDL25 0x20 +#define RDL2_RDL24 0x10 +#define RDL2_RDL23 0x08 +#define RDL2_RDL22 0x04 +#define RDL2_RDL21 0x02 +#define RDL2_RDL20 0x01 + +#define RDL3_RDL37 0x80 +#define RDL3_RDL36 0x40 +#define RDL3_RDL35 0x20 +#define RDL3_RDL34 0x10 +#define RDL3_RDL33 0x08 +#define RDL3_RDL32 0x04 +#define RDL3_RDL31 0x02 +#define RDL3_RDL30 0x01 + + +/* SIS (Signaling Status Register) + + -------------------- E1 & T1 -------------------------- */ + +#define SIS_XDOV 0x80 +#define SIS_XFW 0x40 +#define SIS_XREP 0x20 +#define SIS_RLI 0x08 +#define SIS_CEC 0x04 +#define SIS_BOM 0x01 + + +/* RSIS (Receive Signaling Status Register) + + -------------------- E1 & T1 --------------------------- */ + +#define RSIS_VFR 0x80 +#define RSIS_RDO 0x40 +#define RSIS_CRC16 0x20 +#define RSIS_RAB 0x10 +#define RSIS_HA1 0x08 +#define RSIS_HA0 0x04 +#define RSIS_HFR 0x02 +#define RSIS_LA 0x01 + + +/* RBCL/H (Receive Byte Count Low/High) + + ------------------- E1 & T1 ----------------------- */ + +#define RBCL_RBC7 0x80 +#define RBCL_RBC6 0x40 +#define RBCL_RBC5 0x20 +#define RBCL_RBC4 0x10 +#define RBCL_RBC3 0x08 +#define RBCL_RBC2 0x04 +#define RBCL_RBC1 0x02 +#define RBCL_RBC0 0x01 + +#define RBCH_OV 0x10 +#define RBCH_RBC11 0x08 +#define RBCH_RBC10 0x04 +#define RBCH_RBC9 0x02 +#define RBCH_RBC8 0x01 + + +/* ISR1-3 (Interrupt Status Register 1-3) + + ------------------ E1 & T1 ------------------------------ */ + +#define FISR0_RME 0x80 +#define FISR0_RFS 0x40 +#define FISR0_T8MS 0x20 +#define FISR0_ISF 0x20 +#define FISR0_RMB 0x10 +#define FISR0_CASC 0x08 +#define FISR0_RSC 0x08 +#define FISR0_CRC6 0x04 +#define FISR0_CRC4 0x04 +#define FISR0_PDEN 0x02 +#define FISR0_RPF 0x01 + +#define FISR1_CASE 0x80 +#define FISR1_LLBSC 0x80 +#define FISR1_RDO 0x40 +#define FISR1_ALLS 0x20 +#define FISR1_XDU 0x10 +#define FISR1_XMB 0x08 +#define FISR1_XLSC 0x02 +#define FISR1_XPR 0x01 + +#define FISR2_FAR 0x80 +#define FISR2_LFA 0x40 +#define FISR2_MFAR 0x20 +#define FISR2_T400MS 0x10 +#define FISR2_LMFA 0x10 +#define FISR2_AIS 0x08 +#define FISR2_LOS 0x04 +#define FISR2_RAR 0x02 +#define FISR2_RA 0x01 + +#define FISR3_ES 0x80 +#define FISR3_SEC 0x40 +#define FISR3_LMFA16 0x20 +#define FISR3_AIS16 0x10 +#define FISR3_RA16 0x08 +#define FISR3_API 0x04 +#define FISR3_XSLP 0x20 +#define FISR3_XSLN 0x10 +#define FISR3_LLBSC 0x08 +#define FISR3_XRS 0x04 +#define FISR3_SLN 0x02 +#define FISR3_SLP 0x01 + + +/* GIS (Global Interrupt Status Register) + + --------------------- E1 & T1 --------------------- */ + +#define GIS_ISR3 0x08 +#define GIS_ISR2 0x04 +#define GIS_ISR1 0x02 +#define GIS_ISR0 0x01 + + +/* VSTR (Version Status Register) + + --------------------- E1 & T1 --------------------- */ + +#define VSTR_VN3 0x08 +#define VSTR_VN2 0x04 +#define VSTR_VN1 0x02 +#define VSTR_VN0 0x01 + + +/*>>>>>>>>>>>>>>>>>>>>> Local Control Structures <<<<<<<<<<<<<<<<<<<<<<<<< */ + +/* Write-only Registers (E1/T1 control mode write registers) */ +#define XFIFOH 0x00 /* Tx FIFO High Byte */ +#define XFIFOL 0x01 /* Tx FIFO Low Byte */ +#define CMDR 0x02 /* Command Reg */ +#define DEC 0x60 /* Disable Error Counter */ +#define TEST2 0x62 /* Manuf. Test Reg 2 */ +#define XS(nbr) (0x70 + (nbr)) /* Tx CAS Reg (0 to 15) */ + +/* Read-write Registers (E1/T1 status mode read registers) */ +#define MODE 0x03 /* Mode Reg */ +#define RAH1 0x04 /* Receive Address High 1 */ +#define RAH2 0x05 /* Receive Address High 2 */ +#define RAL1 0x06 /* Receive Address Low 1 */ +#define RAL2 0x07 /* Receive Address Low 2 */ +#define IPC 0x08 /* Interrupt Port Configuration */ +#define CCR1 0x09 /* Common Configuration Reg 1 */ +#define CCR3 0x0A /* Common Configuration Reg 3 */ +#define PRE 0x0B /* Preamble Reg */ +#define RTR1 0x0C /* Receive Timeslot Reg 1 */ +#define RTR2 0x0D /* Receive Timeslot Reg 2 */ +#define RTR3 0x0E /* Receive Timeslot Reg 3 */ +#define RTR4 0x0F /* Receive Timeslot Reg 4 */ +#define TTR1 0x10 /* Transmit Timeslot Reg 1 */ +#define TTR2 0x11 /* Transmit Timeslot Reg 2 */ +#define TTR3 0x12 /* Transmit Timeslot Reg 3 */ +#define TTR4 0x13 /* Transmit Timeslot Reg 4 */ +#define IMR0 0x14 /* Interrupt Mask Reg 0 */ +#define IMR1 0x15 /* Interrupt Mask Reg 1 */ +#define IMR2 0x16 /* Interrupt Mask Reg 2 */ +#define IMR3 0x17 /* Interrupt Mask Reg 3 */ +#define IMR4 0x18 /* Interrupt Mask Reg 4 */ +#define IMR5 0x19 /* Interrupt Mask Reg 5 */ +#define FMR0 0x1A /* Framer Mode Reigster 0 */ +#define FMR1 0x1B /* Framer Mode Reigster 1 */ +#define FMR2 0x1C /* Framer Mode Reigster 2 */ +#define LOOP 0x1D /* Channel Loop Back */ +#define XSW 0x1E /* Transmit Service Word */ +#define FMR4 0x1E /* Framer Mode Reg 4 */ +#define XSP 0x1F /* Transmit Spare Bits */ +#define FMR5 0x1F /* Framer Mode Reg 5 */ +#define XC0 0x20 /* Transmit Control 0 */ +#define XC1 0x21 /* Transmit Control 1 */ +#define RC0 0x22 /* Receive Control 0 */ +#define RC1 0x23 /* Receive Control 1 */ +#define XPM0 0x24 /* Transmit Pulse Mask 0 */ +#define XPM1 0x25 /* Transmit Pulse Mask 1 */ +#define XPM2 0x26 /* Transmit Pulse Mask 2 */ +#define TSWM 0x27 /* Transparent Service Word Mask */ +#define TEST1 0x28 /* Manuf. Test Reg 1 */ +#define IDLE 0x29 /* Idle Channel Code */ +#define XSA4 0x2A /* Transmit SA4 Bit Reg */ +#define XDL1 0x2A /* Transmit DL-Bit Reg 2 */ +#define XSA5 0x2B /* Transmit SA4 Bit Reg */ +#define XDL2 0x2B /* Transmit DL-Bit Reg 2 */ +#define XSA6 0x2C /* Transmit SA4 Bit Reg */ +#define XDL3 0x2C /* Transmit DL-Bit Reg 2 */ +#define XSA7 0x2D /* Transmit SA4 Bit Reg */ +#define CCB1 0x2D /* Clear Channel Reg 1 */ +#define XSA8 0x2E /* Transmit SA4 Bit Reg */ +#define CCB2 0x2E /* Clear Channel Reg 2 */ +#define FMR3 0x2F /* Framer Mode Reg. 3 */ +#define CCB3 0x2F /* Clear Channel Reg 3 */ +#define ICB1 0x30 /* Idle Channel Reg 1 */ +#define ICB2 0x31 /* Idle Channel Reg 2 */ +#define ICB3 0x32 /* Idle Channel Reg 3 */ +#define ICB4 0x33 /* Idle Channel Reg 4 */ +#define LIM0 0x34 /* Line Interface Mode 0 */ +#define LIM1 0x35 /* Line Interface Mode 1 */ +#define PCDR 0x36 /* Pulse Count Detection */ +#define PCRR 0x37 /* Pulse Count Recovery */ +#define LIM2 0x38 /* Line Interface Mode Reg 2 */ +#define LCR1 0x39 /* Loop Code Reg 1 */ +#define LCR2 0x3A /* Loop Code Reg 2 */ +#define LCR3 0x3B /* Loop Code Reg 3 */ +#define SIC1 0x3C /* System Interface Control 1 */ + +/* Read-only Registers (E1/T1 control mode read registers) */ +#define RFIFOH 0x00 /* Receive FIFO */ +#define RFIFOL 0x01 /* Receive FIFO */ +#define FRS0 0x4C /* Framer Receive Status 0 */ +#define FRS1 0x4D /* Framer Receive Status 1 */ +#define RSW 0x4E /* Receive Service Word */ +#define FRS2 0x4E /* Framer Receive Status 2 */ +#define RSP 0x4F /* Receive Spare Bits */ +#define FRS3 0x4F /* Framer Receive Status 3 */ +#define FECL 0x50 /* Framing Error Counter */ +#define FECH 0x51 /* Framing Error Counter */ +#define CVCL 0x52 /* Code Violation Counter */ +#define CVCH 0x53 /* Code Violation Counter */ +#define CECL 0x54 /* CRC Error Counter 1 */ +#define CECH 0x55 /* CRC Error Counter 1 */ +#define EBCL 0x56 /* E-Bit Error Counter */ +#define EBCH 0x57 /* E-Bit Error Counter */ +#define BECL 0x58 /* Bit Error Counter Low */ +#define BECH 0x59 /* Bit Error Counter Low */ +#define CEC3 0x5A /* CRC Error Counter 3 (16-bit) */ +#define RSA4 0x5C /* Receive SA4 Bit Reg */ +#define RDL1 0x5C /* Receive DL-Bit Reg 1 */ +#define RSA5 0x5D /* Receive SA5 Bit Reg */ +#define RDL2 0x5D /* Receive DL-Bit Reg 2 */ +#define RSA6 0x5E /* Receive SA6 Bit Reg */ +#define RDL3 0x5E /* Receive DL-Bit Reg 3 */ +#define RSA7 0x5F /* Receive SA7 Bit Reg */ +#define RSA8 0x60 /* Receive SA8 Bit Reg */ +#define RSA6S 0x61 /* Receive SA6 Bit Status Reg */ +#define TSR0 0x62 /* Manuf. Test Reg 0 */ +#define TSR1 0x63 /* Manuf. Test Reg 1 */ +#define SIS 0x64 /* Signaling Status Reg */ +#define RSIS 0x65 /* Receive Signaling Status Reg */ +#define RBCL 0x66 /* Receive Byte Control */ +#define RBCH 0x67 /* Receive Byte Control */ +#define FISR0 0x68 /* Interrupt Status Reg 0 */ +#define FISR1 0x69 /* Interrupt Status Reg 1 */ +#define FISR2 0x6A /* Interrupt Status Reg 2 */ +#define FISR3 0x6B /* Interrupt Status Reg 3 */ +#define GIS 0x6E /* Global Interrupt Status */ +#define VSTR 0x6F /* Version Status */ +#define RS(nbr) (0x70 + (nbr)) /* Rx CAS Reg (0 to 15) */ + +#endif /* _FALC_LH_H */ + diff --git a/include/linux/hd64572.h b/include/linux/hd64572.h new file mode 100644 index 000000000000..f8b6fd7e235c --- /dev/null +++ b/include/linux/hd64572.h @@ -0,0 +1,437 @@ +/* + * hd64572.h Description of the Hitachi HD64572 (SCA-II), valid for + * CPU modes 0 & 2. + * + * Author: Ivan Passos + * + * Copyright: (c) 2000 Cyclades Corp. + * + * 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. + * + * $Log: hd64572.h,v $ + * Revision 1.0 2000/01/25 ivan + * Initial version. + * + */ + +#ifndef _HD64572_H +#define _HD64572_H + +/* Illegal Access Register */ +#define ILAR 0x00 + +/* Wait Controller Registers */ +#define PABR0L 0x20 /* Physical Addr Boundary Register 0 L */ +#define PABR0H 0x21 /* Physical Addr Boundary Register 0 H */ +#define PABR1L 0x22 /* Physical Addr Boundary Register 1 L */ +#define PABR1H 0x23 /* Physical Addr Boundary Register 1 H */ +#define WCRL 0x24 /* Wait Control Register L */ +#define WCRM 0x25 /* Wait Control Register M */ +#define WCRH 0x26 /* Wait Control Register H */ + +/* Interrupt Registers */ +#define IVR 0x60 /* Interrupt Vector Register */ +#define IMVR 0x64 /* Interrupt Modified Vector Register */ +#define ITCR 0x68 /* Interrupt Control Register */ +#define ISR0 0x6c /* Interrupt Status Register 0 */ +#define ISR1 0x70 /* Interrupt Status Register 1 */ +#define IER0 0x74 /* Interrupt Enable Register 0 */ +#define IER1 0x78 /* Interrupt Enable Register 1 */ + +/* Register Access Macros (chan is 0 or 1 in _any_ case) */ +#define M_REG(reg, chan) (reg + 0x80*chan) /* MSCI */ +#define DRX_REG(reg, chan) (reg + 0x40*chan) /* DMA Rx */ +#define DTX_REG(reg, chan) (reg + 0x20*(2*chan + 1)) /* DMA Tx */ +#define TRX_REG(reg, chan) (reg + 0x20*chan) /* Timer Rx */ +#define TTX_REG(reg, chan) (reg + 0x10*(2*chan + 1)) /* Timer Tx */ +#define ST_REG(reg, chan) (reg + 0x80*chan) /* Status Cnt */ +#define IR0_DRX(val, chan) ((val)<<(8*(chan))) /* Int DMA Rx */ +#define IR0_DTX(val, chan) ((val)<<(4*(2*chan + 1))) /* Int DMA Tx */ +#define IR0_M(val, chan) ((val)<<(8*(chan))) /* Int MSCI */ + +/* MSCI Channel Registers */ +#define MD0 0x138 /* Mode reg 0 */ +#define MD1 0x139 /* Mode reg 1 */ +#define MD2 0x13a /* Mode reg 2 */ +#define MD3 0x13b /* Mode reg 3 */ +#define CTL 0x130 /* Control reg */ +#define RXS 0x13c /* RX clock source */ +#define TXS 0x13d /* TX clock source */ +#define EXS 0x13e /* External clock input selection */ +#define TMCT 0x144 /* Time constant (Tx) */ +#define TMCR 0x145 /* Time constant (Rx) */ +#define CMD 0x128 /* Command reg */ +#define ST0 0x118 /* Status reg 0 */ +#define ST1 0x119 /* Status reg 1 */ +#define ST2 0x11a /* Status reg 2 */ +#define ST3 0x11b /* Status reg 3 */ +#define ST4 0x11c /* Status reg 4 */ +#define FST 0x11d /* frame Status reg */ +#define IE0 0x120 /* Interrupt enable reg 0 */ +#define IE1 0x121 /* Interrupt enable reg 1 */ +#define IE2 0x122 /* Interrupt enable reg 2 */ +#define IE4 0x124 /* Interrupt enable reg 4 */ +#define FIE 0x125 /* Frame Interrupt enable reg */ +#define SA0 0x140 /* Syn Address reg 0 */ +#define SA1 0x141 /* Syn Address reg 1 */ +#define IDL 0x142 /* Idle register */ +#define TRBL 0x100 /* TX/RX buffer reg L */ +#define TRBK 0x101 /* TX/RX buffer reg K */ +#define TRBJ 0x102 /* TX/RX buffer reg J */ +#define TRBH 0x103 /* TX/RX buffer reg H */ +#define TRC0 0x148 /* TX Ready control reg 0 */ +#define TRC1 0x149 /* TX Ready control reg 1 */ +#define RRC 0x14a /* RX Ready control reg */ +#define CST0 0x108 /* Current Status Register 0 */ +#define CST1 0x109 /* Current Status Register 1 */ +#define CST2 0x10a /* Current Status Register 2 */ +#define CST3 0x10b /* Current Status Register 3 */ +#define GPO 0x131 /* General Purpose Output Pin Ctl Reg */ +#define TFS 0x14b /* Tx Start Threshold Ctl Reg */ +#define TFN 0x143 /* Inter-transmit-frame Time Fill Ctl Reg */ +#define TBN 0x110 /* Tx Buffer Number Reg */ +#define RBN 0x111 /* Rx Buffer Number Reg */ +#define TNR0 0x150 /* Tx DMA Request Ctl Reg 0 */ +#define TNR1 0x151 /* Tx DMA Request Ctl Reg 1 */ +#define TCR 0x152 /* Tx DMA Critical Request Reg */ +#define RNR 0x154 /* Rx DMA Request Ctl Reg */ +#define RCR 0x156 /* Rx DMA Critical Request Reg */ + +/* Timer Registers */ +#define TCNTL 0x200 /* Timer Upcounter L */ +#define TCNTH 0x201 /* Timer Upcounter H */ +#define TCONRL 0x204 /* Timer Constant Register L */ +#define TCONRH 0x205 /* Timer Constant Register H */ +#define TCSR 0x206 /* Timer Control/Status Register */ +#define TEPR 0x207 /* Timer Expand Prescale Register */ + +/* DMA registers */ +#define PCR 0x40 /* DMA priority control reg */ +#define DRR 0x44 /* DMA reset reg */ +#define DMER 0x07 /* DMA Master Enable reg */ +#define BTCR 0x08 /* Burst Tx Ctl Reg */ +#define BOLR 0x0c /* Back-off Length Reg */ +#define DSR_RX(chan) (0x48 + 2*chan) /* DMA Status Reg (Rx) */ +#define DSR_TX(chan) (0x49 + 2*chan) /* DMA Status Reg (Tx) */ +#define DIR_RX(chan) (0x4c + 2*chan) /* DMA Interrupt Enable Reg (Rx) */ +#define DIR_TX(chan) (0x4d + 2*chan) /* DMA Interrupt Enable Reg (Tx) */ +#define FCT_RX(chan) (0x50 + 2*chan) /* Frame End Interrupt Counter (Rx) */ +#define FCT_TX(chan) (0x51 + 2*chan) /* Frame End Interrupt Counter (Tx) */ +#define DMR_RX(chan) (0x54 + 2*chan) /* DMA Mode Reg (Rx) */ +#define DMR_TX(chan) (0x55 + 2*chan) /* DMA Mode Reg (Tx) */ +#define DCR_RX(chan) (0x58 + 2*chan) /* DMA Command Reg (Rx) */ +#define DCR_TX(chan) (0x59 + 2*chan) /* DMA Command Reg (Tx) */ + +/* DMA Channel Registers */ +#define DARL 0x80 /* Dest Addr Register L (single-block, RX only) */ +#define DARH 0x81 /* Dest Addr Register H (single-block, RX only) */ +#define DARB 0x82 /* Dest Addr Register B (single-block, RX only) */ +#define DARBH 0x83 /* Dest Addr Register BH (single-block, RX only) */ +#define SARL 0x80 /* Source Addr Register L (single-block, TX only) */ +#define SARH 0x81 /* Source Addr Register H (single-block, TX only) */ +#define SARB 0x82 /* Source Addr Register B (single-block, TX only) */ +#define DARBH 0x83 /* Source Addr Register BH (single-block, TX only) */ +#define BARL 0x80 /* Buffer Addr Register L (chained-block) */ +#define BARH 0x81 /* Buffer Addr Register H (chained-block) */ +#define BARB 0x82 /* Buffer Addr Register B (chained-block) */ +#define BARBH 0x83 /* Buffer Addr Register BH (chained-block) */ +#define CDAL 0x84 /* Current Descriptor Addr Register L */ +#define CDAH 0x85 /* Current Descriptor Addr Register H */ +#define CDAB 0x86 /* Current Descriptor Addr Register B */ +#define CDABH 0x87 /* Current Descriptor Addr Register BH */ +#define EDAL 0x88 /* Error Descriptor Addr Register L */ +#define EDAH 0x89 /* Error Descriptor Addr Register H */ +#define EDAB 0x8a /* Error Descriptor Addr Register B */ +#define EDABH 0x8b /* Error Descriptor Addr Register BH */ +#define BFLL 0x90 /* RX Buffer Length L (only RX) */ +#define BFLH 0x91 /* RX Buffer Length H (only RX) */ +#define BCRL 0x8c /* Byte Count Register L */ +#define BCRH 0x8d /* Byte Count Register H */ + +/* Block Descriptor Structure */ +typedef struct { + unsigned long next; /* pointer to next block descriptor */ + unsigned long ptbuf; /* buffer pointer */ + unsigned short len; /* data length */ + unsigned char status; /* status */ + unsigned char filler[5]; /* alignment filler (16 bytes) */ +} pcsca_bd_t; + +/* + Descriptor Status definitions: + + Bit Transmission Reception + + 7 EOM EOM + 6 - Short Frame + 5 - Abort + 4 - Residual bit + 3 Underrun Overrun + 2 - CRC + 1 Ownership Ownership + 0 EOT - +*/ +#define DST_EOT 0x01 /* End of transmit command */ +#define DST_OSB 0x02 /* Ownership bit */ +#define DST_CRC 0x04 /* CRC Error */ +#define DST_OVR 0x08 /* Overrun */ +#define DST_UDR 0x08 /* Underrun */ +#define DST_RBIT 0x10 /* Residual bit */ +#define DST_ABT 0x20 /* Abort */ +#define DST_SHRT 0x40 /* Short Frame */ +#define DST_EOM 0x80 /* End of Message */ + +/* Status Counter Registers */ +#define CMCR 0x158 /* Counter Master Ctl Reg */ +#define TECNTL 0x160 /* Tx EOM Counter L */ +#define TECNTM 0x161 /* Tx EOM Counter M */ +#define TECNTH 0x162 /* Tx EOM Counter H */ +#define TECCR 0x163 /* Tx EOM Counter Ctl Reg */ +#define URCNTL 0x164 /* Underrun Counter L */ +#define URCNTH 0x165 /* Underrun Counter H */ +#define URCCR 0x167 /* Underrun Counter Ctl Reg */ +#define RECNTL 0x168 /* Rx EOM Counter L */ +#define RECNTM 0x169 /* Rx EOM Counter M */ +#define RECNTH 0x16a /* Rx EOM Counter H */ +#define RECCR 0x16b /* Rx EOM Counter Ctl Reg */ +#define ORCNTL 0x16c /* Overrun Counter L */ +#define ORCNTH 0x16d /* Overrun Counter H */ +#define ORCCR 0x16f /* Overrun Counter Ctl Reg */ +#define CECNTL 0x170 /* CRC Counter L */ +#define CECNTH 0x171 /* CRC Counter H */ +#define CECCR 0x173 /* CRC Counter Ctl Reg */ +#define ABCNTL 0x174 /* Abort frame Counter L */ +#define ABCNTH 0x175 /* Abort frame Counter H */ +#define ABCCR 0x177 /* Abort frame Counter Ctl Reg */ +#define SHCNTL 0x178 /* Short frame Counter L */ +#define SHCNTH 0x179 /* Short frame Counter H */ +#define SHCCR 0x17b /* Short frame Counter Ctl Reg */ +#define RSCNTL 0x17c /* Residual bit Counter L */ +#define RSCNTH 0x17d /* Residual bit Counter H */ +#define RSCCR 0x17f /* Residual bit Counter Ctl Reg */ + +/* Register Programming Constants */ + +#define IR0_DMIC 0x00000001 +#define IR0_DMIB 0x00000002 +#define IR0_DMIA 0x00000004 +#define IR0_EFT 0x00000008 +#define IR0_DMAREQ 0x00010000 +#define IR0_TXINT 0x00020000 +#define IR0_RXINTB 0x00040000 +#define IR0_RXINTA 0x00080000 +#define IR0_TXRDY 0x00100000 +#define IR0_RXRDY 0x00200000 + +#define MD0_CRC16_0 0x00 +#define MD0_CRC16_1 0x01 +#define MD0_CRC32 0x02 +#define MD0_CRC_CCITT 0x03 +#define MD0_CRCC0 0x04 +#define MD0_CRCC1 0x08 +#define MD0_AUTO_ENA 0x10 +#define MD0_ASYNC 0x00 +#define MD0_BY_MSYNC 0x20 +#define MD0_BY_BISYNC 0x40 +#define MD0_BY_EXT 0x60 +#define MD0_BIT_SYNC 0x80 +#define MD0_TRANSP 0xc0 + +#define MD1_NOADDR 0x00 +#define MD1_SADDR1 0x40 +#define MD1_SADDR2 0x80 +#define MD1_DADDR 0xc0 + +#define MD2_F_DUPLEX 0x00 +#define MD2_AUTO_ECHO 0x01 +#define MD2_LOOP_HI_Z 0x02 +#define MD2_LOOP_MIR 0x03 +#define MD2_ADPLL_X8 0x00 +#define MD2_ADPLL_X16 0x08 +#define MD2_ADPLL_X32 0x10 +#define MD2_NRZ 0x00 +#define MD2_NRZI 0x20 +#define MD2_NRZ_IEEE 0x40 +#define MD2_MANCH 0x00 +#define MD2_FM1 0x20 +#define MD2_FM0 0x40 +#define MD2_FM 0x80 + +#define CTL_RTS 0x01 +#define CTL_DTR 0x02 +#define CTL_SYN 0x04 +#define CTL_IDLC 0x10 +#define CTL_UDRNC 0x20 +#define CTL_URSKP 0x40 +#define CTL_URCT 0x80 + +#define RXS_BR0 0x01 +#define RXS_BR1 0x02 +#define RXS_BR2 0x04 +#define RXS_BR3 0x08 +#define RXS_ECLK 0x00 +#define RXS_ECLK_NS 0x20 +#define RXS_IBRG 0x40 +#define RXS_PLL1 0x50 +#define RXS_PLL2 0x60 +#define RXS_PLL3 0x70 +#define RXS_DRTXC 0x80 + +#define TXS_BR0 0x01 +#define TXS_BR1 0x02 +#define TXS_BR2 0x04 +#define TXS_BR3 0x08 +#define TXS_ECLK 0x00 +#define TXS_IBRG 0x40 +#define TXS_RCLK 0x60 +#define TXS_DTRXC 0x80 + +#define EXS_RES0 0x01 +#define EXS_RES1 0x02 +#define EXS_RES2 0x04 +#define EXS_TES0 0x10 +#define EXS_TES1 0x20 +#define EXS_TES2 0x40 + +#define CMD_RX_RST 0x11 +#define CMD_RX_ENA 0x12 +#define CMD_RX_DIS 0x13 +#define CMD_RX_CRC_INIT 0x14 +#define CMD_RX_MSG_REJ 0x15 +#define CMD_RX_MP_SRCH 0x16 +#define CMD_RX_CRC_EXC 0x17 +#define CMD_RX_CRC_FRC 0x18 +#define CMD_TX_RST 0x01 +#define CMD_TX_ENA 0x02 +#define CMD_TX_DISA 0x03 +#define CMD_TX_CRC_INIT 0x04 +#define CMD_TX_CRC_EXC 0x05 +#define CMD_TX_EOM 0x06 +#define CMD_TX_ABORT 0x07 +#define CMD_TX_MP_ON 0x08 +#define CMD_TX_BUF_CLR 0x09 +#define CMD_TX_DISB 0x0b +#define CMD_CH_RST 0x21 +#define CMD_SRCH_MODE 0x31 +#define CMD_NOP 0x00 + +#define ST0_RXRDY 0x01 +#define ST0_TXRDY 0x02 +#define ST0_RXINTB 0x20 +#define ST0_RXINTA 0x40 +#define ST0_TXINT 0x80 + +#define ST1_IDLE 0x01 +#define ST1_ABORT 0x02 +#define ST1_CDCD 0x04 +#define ST1_CCTS 0x08 +#define ST1_SYN_FLAG 0x10 +#define ST1_CLMD 0x20 +#define ST1_TXIDLE 0x40 +#define ST1_UDRN 0x80 + +#define ST2_CRCE 0x04 +#define ST2_ONRN 0x08 +#define ST2_RBIT 0x10 +#define ST2_ABORT 0x20 +#define ST2_SHORT 0x40 +#define ST2_EOM 0x80 + +#define ST3_RX_ENA 0x01 +#define ST3_TX_ENA 0x02 +#define ST3_DCD 0x04 +#define ST3_CTS 0x08 +#define ST3_SRCH_MODE 0x10 +#define ST3_SLOOP 0x20 +#define ST3_GPI 0x80 + +#define ST4_RDNR 0x01 +#define ST4_RDCR 0x02 +#define ST4_TDNR 0x04 +#define ST4_TDCR 0x08 +#define ST4_OCLM 0x20 +#define ST4_CFT 0x40 +#define ST4_CGPI 0x80 + +#define FST_CRCEF 0x04 +#define FST_OVRNF 0x08 +#define FST_RBIF 0x10 +#define FST_ABTF 0x20 +#define FST_SHRTF 0x40 +#define FST_EOMF 0x80 + +#define IE0_RXRDY 0x01 +#define IE0_TXRDY 0x02 +#define IE0_RXINTB 0x20 +#define IE0_RXINTA 0x40 +#define IE0_TXINT 0x80 + +#define IE1_IDLD 0x01 +#define IE1_ABTD 0x02 +#define IE1_CDCD 0x04 +#define IE1_CCTS 0x08 +#define IE1_SYNCD 0x10 +#define IE1_CLMD 0x20 +#define IE1_IDL 0x40 +#define IE1_UDRN 0x80 + +#define IE2_CRCE 0x04 +#define IE2_OVRN 0x08 +#define IE2_RBIT 0x10 +#define IE2_ABT 0x20 +#define IE2_SHRT 0x40 +#define IE2_EOM 0x80 + +#define IE4_RDNR 0x01 +#define IE4_RDCR 0x02 +#define IE4_TDNR 0x04 +#define IE4_TDCR 0x08 +#define IE4_OCLM 0x20 +#define IE4_CFT 0x40 +#define IE4_CGPI 0x80 + +#define FIE_CRCEF 0x04 +#define FIE_OVRNF 0x08 +#define FIE_RBIF 0x10 +#define FIE_ABTF 0x20 +#define FIE_SHRTF 0x40 +#define FIE_EOMF 0x80 + +#define DSR_DWE 0x01 +#define DSR_DE 0x02 +#define DSR_REF 0x04 +#define DSR_UDRF 0x04 +#define DSR_COA 0x08 +#define DSR_COF 0x10 +#define DSR_BOF 0x20 +#define DSR_EOM 0x40 +#define DSR_EOT 0x80 + +#define DIR_REF 0x04 +#define DIR_UDRF 0x04 +#define DIR_COA 0x08 +#define DIR_COF 0x10 +#define DIR_BOF 0x20 +#define DIR_EOM 0x40 +#define DIR_EOT 0x80 + +#define DMR_CNTE 0x02 +#define DMR_NF 0x04 +#define DMR_SEOME 0x08 +#define DMR_TMOD 0x10 + +#define DCR_SW_ABT 0x01 +#define DCR_FCT_CLR 0x02 + +#define PCR_PR0 0x01 +#define PCR_PR1 0x02 +#define PCR_PR2 0x04 +#define PCR_CCC 0x08 +#define PCR_BRC 0x10 +#define PCR_OSB 0x40 +#define PCR_BURST 0x80 + +#endif /* (_HD64572_H) */ diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h index 6d532715adf1..ae11e7011c42 100644 --- a/include/linux/hdlc.h +++ b/include/linux/hdlc.h @@ -38,6 +38,8 @@ #define LINE_X21 3 #define LINE_LOOPBACK 4 /* On-card loopback */ #define LINE_NOLOOPBACK 5 +#define LINE_T1 6 +#define LINE_E1 7 #define LINE_MIN_CLOCK 75 /* This & higher values are real clock rates */ diff --git a/include/linux/ixjuser.h b/include/linux/ixjuser.h index a70195334ed8..2aca5e2c8bb2 100644 --- a/include/linux/ixjuser.h +++ b/include/linux/ixjuser.h @@ -1,7 +1,8 @@ -/* +/****************************************************************************** + * * ixjuser.h * - * User-space include file for the Internet PhoneJACK and + * Device Driver for the Internet PhoneJACK and * Internet LineJACK Telephony Cards. * * (c) Copyright 1999 Quicknet Technologies, Inc. @@ -22,31 +23,48 @@ * at our website: http://www.quicknet.net * * Fixes: - */ + * + * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET + * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION + * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + *****************************************************************************/ -static char ixjuser_h_rcsid[] = "$Id: ixjuser.h,v 3.4 1999/12/16 22:18:36 root Exp root $"; +static char ixjuser_h_rcsid[] = "$Id: ixjuser.h,v 3.11 2000/03/30 22:06:48 eokerson Exp $"; -#include +#include "telephony.h" -/*************************************************************************** - If you use the IXJCTL_TESTRAM command, the card must be power - cycled to reset the SRAM values before futher use. +/****************************************************************************** +* +* IOCTL's used for the Quicknet Cards +* +* If you use the IXJCTL_TESTRAM command, the card must be power cycled to +* reset the SRAM values before futher use. +* +******************************************************************************/ -***************************************************************************/ #define IXJCTL_DSP_RESET _IO ('q', 0xC0) -#define IXJCTL_RING PHONE_RING -#define IXJCTL_HOOKSTATE PHONE_HOOKSTATE +#define IXJCTL_RING PHONE_RING +#define IXJCTL_HOOKSTATE PHONE_HOOKSTATE #define IXJCTL_MAXRINGS PHONE_MAXRINGS -#define IXJCTL_RING_CADENCE PHONE_RING_CADENCE +#define IXJCTL_RING_CADENCE PHONE_RING_CADENCE #define IXJCTL_RING_START PHONE_RING_START #define IXJCTL_RING_STOP PHONE_RING_STOP #define IXJCTL_CARDTYPE _IOR ('q', 0xC1, int) -#define IXJCTL_SERIAL _IOR ('q', 0xC2, int) -#define IXJCTL_DSP_TYPE _IOR ('q', 0xC3, int) -#define IXJCTL_DSP_VERSION _IOR ('q', 0xC4, int) +#define IXJCTL_SERIAL _IOR ('q', 0xC2, int) +#define IXJCTL_DSP_TYPE _IOR ('q', 0xC3, int) +#define IXJCTL_DSP_VERSION _IOR ('q', 0xC4, int) +#define IXJCTL_VERSION _IOR ('q', 0xDA, char *) #define IXJCTL_DSP_IDLE _IO ('q', 0xC5) #define IXJCTL_TESTRAM _IO ('q', 0xC6) @@ -104,8 +122,22 @@ typedef struct { char enable; } IXJ_FILTER; +typedef struct { + char enable; + char en_filter; + unsigned int filter; + unsigned int on1; + unsigned int off1; + unsigned int on2; + unsigned int off2; + unsigned int on3; + unsigned int off3; +} IXJ_FILTER_CADENCE; + #define IXJCTL_SET_FILTER _IOW ('q', 0xC7, IXJ_FILTER *) #define IXJCTL_GET_FILTER_HIST _IOW ('q', 0xC8, int) +#define IXJCTL_FILTER_CADENCE _IOW ('q', 0xD6, IXJ_FILTER_CADENCE *) +#define IXJCTL_PLAY_CID _IO ('q', 0xD7) /****************************************************************************** * * This IOCTL allows you to reassign values in the tone index table. The @@ -222,7 +254,9 @@ typedef enum { hz1800 = 0x1405, hz1860 = 0xe0b, hz2100 = 0xf5f6, - hz2450 = 0xd3b3 + hz2130 = 0xf2f5, + hz2450 = 0xd3b3, + hz2750 = 0xb8e4 } IXJ_FREQ; typedef enum { @@ -344,6 +378,7 @@ typedef struct { #define AEC_LOW 1 #define AEC_MED 2 #define AEC_HIGH 3 +#define AEC_AUTO 4 /****************************************************************************** * * Call Progress Tones, DTMF, etc. @@ -533,16 +568,16 @@ typedef struct { /****************************************************************************** * -* The DAA Analog GAIN sets 2 parameters at one time, the receive gain (AGRR), +* The DAA Analog GAIN sets 2 parameters at one time, the recieve gain (AGRR), * and the transmit gain (AGX). OR together the components and pass them * as the parameter to IXJCTL_DAA_AGAIN. The default setting is both at 0dB. * ******************************************************************************/ #define IXJCTL_DAA_AGAIN _IOW ('q', 0xD2, int) -#define AGRR00DB 0x00 // Analog gain in receive direction 0dB -#define AGRR3_5DB 0x10 // Analog gain in receive direction 3.5dB -#define AGRR06DB 0x30 // Analog gain in receive direction 6dB +#define AGRR00DB 0x00 // Analog gain in recieve direction 0dB +#define AGRR3_5DB 0x10 // Analog gain in recieve direction 3.5dB +#define AGRR06DB 0x30 // Analog gain in recieve direction 6dB #define AGX00DB 0x00 // Analog gain in transmit direction 0dB #define AGX_6DB 0x04 // Analog gain in transmit direction -6dB @@ -551,18 +586,9 @@ typedef struct { #define IXJCTL_PSTN_LINETEST _IO ('q', 0xD3) -typedef struct { - char month[3]; - char day[3]; - char hour[3]; - char min[3]; - int numlen; - char number[11]; - int namelen; - char name[80]; -} IXJ_CID; - -#define IXJCTL_CID _IOR ('q', 0xD4, IXJ_CID *) +#define IXJCTL_CID _IOR ('q', 0xD4, PHONE_CID *) +#define IXJCTL_VMWI _IOR ('q', 0xD8, int) +#define IXJCTL_CIDCW _IOW ('q', 0xD9, PHONE_CID *) /****************************************************************************** * * The wink duration is tunable with this ioctl. The default wink duration diff --git a/include/linux/pc300.h b/include/linux/pc300.h new file mode 100644 index 000000000000..0faa284d911a --- /dev/null +++ b/include/linux/pc300.h @@ -0,0 +1,374 @@ +/* + * pc300.h Cyclades-PC300(tm) Kernel API Definitions. + * + * Author: Ivan Passos + * + * Copyright: (c) 1999-2000 Cyclades Corp. + * + * 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. + * + * $Log: pc300.h,v $ + * Revision 2.0 2000/03/27 ivan + * Added support for the PC300/TE cards. + * + * Revision 1.1 2000/01/31 ivan + * Replaced 'pc300[drv|sca].h' former PC300 driver include files. + * + * Revision 1.0 1999/12/16 ivan + * First official release. + * Inclusion of 'nchan' field on structure 'pc300hw', to allow variable + * number of ports per card. + * Inclusion of 'if_ptr' field on structure 'pc300dev'. + * + * Revision 0.6 1999/11/17 ivan + * Changed X.25-specific function names to comply with adopted convention. + * + * Revision 0.5 1999/11/16 Daniela Squassoni + * X.25 support. + * + * Revision 0.4 1999/11/15 ivan + * Inclusion of 'clock' field on structure 'pc300hw'. + * + * Revision 0.3 1999/11/10 ivan + * IOCTL name changing. + * Inclusion of driver function prototypes. + * + * Revision 0.2 1999/11/03 ivan + * Inclusion of 'tx_skb' and union 'ifu' on structure 'pc300dev'. + * + * Revision 0.1 1999/01/15 ivan + * Initial version. + * + */ + +#ifndef _PC300_H +#define _PC300_H + +#ifndef __HDLC_H +#include +#endif +#ifndef _HD64572_H +#include +#endif +#ifndef _FALC_LH_H +#include +#endif + +#ifndef CY_TYPES +#define CY_TYPES +#if defined(__alpha__) +typedef unsigned long ucdouble; /* 64 bits, unsigned */ +typedef unsigned int uclong; /* 32 bits, unsigned */ +#else +typedef unsigned long uclong; /* 32 bits, unsigned */ +#endif +typedef unsigned short ucshort; /* 16 bits, unsigned */ +typedef unsigned char ucchar; /* 8 bits, unsigned */ +#endif /* CY_TYPES */ + +#define PC300_DEVNAME "hdlc" /* Dev. name base (for hdlc0, hdlc1, etc.) */ +#define PC300_MAXINDEX 100 /* Max dev. name index (the '0' in hdlc0) */ + +#define PC300_MAXCARDS 4 /* Max number of cards per system */ +#define PC300_MAXCHAN 2 /* Number of channels per card */ + +#define PC300_PLX_WIN 0x80 /* PLX control window size (128b) */ +#define PC300_RAMSIZE 0x80000 /* RAM window size (512Kb) */ +#define PC300_SCASIZE 0x400 /* SCA window size (1Kb) */ +#define PC300_FALCSIZE 0x400 /* FALC window size (1Kb) */ + +#define PC300_OSC_CLOCK 24576000 +#define PC300_PCI_CLOCK 33000000 + +#define BD_DEF_LEN 0x0800 /* DMA buffer length (2KB) */ +#define DMA_TX_MEMSZ 0x8000 /* Total DMA Tx memory size (32KB/ch) */ +#define DMA_RX_MEMSZ 0x10000 /* Total DMA Rx memory size (64KB/ch) */ + +#define N_DMA_TX_BUF (DMA_TX_MEMSZ / BD_DEF_LEN) /* DMA Tx buffers */ +#define N_DMA_RX_BUF (DMA_RX_MEMSZ / BD_DEF_LEN) /* DMA Rx buffers */ + +/* DMA Buffer Offsets */ +#define DMA_TX_BASE ((N_DMA_TX_BUF + N_DMA_RX_BUF) * \ + PC300_MAXCHAN * sizeof(pcsca_bd_t)) +#define DMA_RX_BASE (DMA_TX_BASE + PC300_MAXCHAN*DMA_TX_MEMSZ) + +/* DMA Descriptor Offsets */ +#define DMA_TX_BD_BASE 0x0000 +#define DMA_RX_BD_BASE (DMA_TX_BD_BASE + ((PC300_MAXCHAN*DMA_TX_MEMSZ / \ + BD_DEF_LEN) * sizeof(pcsca_bd_t))) + +/* DMA Descriptor Macros */ +#define TX_BD_ADDR(chan, n) (DMA_TX_BD_BASE + \ + ((N_DMA_TX_BUF*chan) + n) * sizeof(pcsca_bd_t)) +#define RX_BD_ADDR(chan, n) (DMA_RX_BD_BASE + \ + ((N_DMA_RX_BUF*chan) + n) * sizeof(pcsca_bd_t)) + +/* Macro to access the FALC registers (TE only) */ +#define F_REG(reg, chan) (0x200*(chan) + ((reg)<<2)) + +/*************************************** + * Memory access functions/macros * + * (required to support Alpha systems) * + ***************************************/ +#ifdef __KERNEL__ +#define cpc_writeb(port,val) {writeb((ucchar)(val),(ulong)(port)); mb();} +#define cpc_writew(port,val) {writew((ushort)(val),(ulong)(port)); mb();} +#define cpc_writel(port,val) {writel((uclong)(val),(ulong)(port)); mb();} + +#define cpc_readb(port) readb(port) +#define cpc_readw(port) readw(port) +#define cpc_readl(port) readl(port) + +#else /* __KERNEL__ */ +#define cpc_writeb(port,val) (*(volatile ucchar *)(port) = (ucchar)(val)) +#define cpc_writew(port,val) (*(volatile ucshort *)(port) = (ucshort)(val)) +#define cpc_writel(port,val) (*(volatile uclong *)(port) = (uclong)(val)) + +#define cpc_readb(port) (*(volatile ucchar *)(port)) +#define cpc_readw(port) (*(volatile ucshort *)(port)) +#define cpc_readl(port) (*(volatile uclong *)(port)) + +#endif /* __KERNEL__ */ + +/****** Data Structures *****************************************************/ + +/* + * RUNTIME_9050 - PLX PCI9050-1 local configuration and shared runtime + * registers. This structure can be used to access the 9050 registers + * (memory mapped). + */ +struct RUNTIME_9050 { + uclong loc_addr_range[4]; /* 00-0Ch : Local Address Ranges */ + uclong loc_rom_range; /* 10h : Local ROM Range */ + uclong loc_addr_base[4]; /* 14-20h : Local Address Base Addrs */ + uclong loc_rom_base; /* 24h : Local ROM Base */ + uclong loc_bus_descr[4]; /* 28-34h : Local Bus Descriptors */ + uclong rom_bus_descr; /* 38h : ROM Bus Descriptor */ + uclong cs_base[4]; /* 3C-48h : Chip Select Base Addrs */ + uclong intr_ctrl_stat; /* 4Ch : Interrupt Control/Status */ + uclong init_ctrl; /* 50h : EEPROM ctrl, Init Ctrl, etc */ +}; + +#define PLX_9050_LINT1_ENABLE 0x01 +#define PLX_9050_LINT1_POL 0x02 +#define PLX_9050_LINT1_STATUS 0x04 +#define PLX_9050_LINT2_ENABLE 0x08 +#define PLX_9050_LINT2_POL 0x10 +#define PLX_9050_LINT2_STATUS 0x20 +#define PLX_9050_INTR_ENABLE 0x40 +#define PLX_9050_SW_INTR 0x80 + +/* Masks to access the init_ctrl PLX register */ +#define PC300_CLKSEL_MASK (0x00000004UL) +#define PC300_CHMEDIA_MASK(chan) (0x00000020UL<<(chan*3)) +#define PC300_CTYPE_MASK (0x00000800UL) + +/* CPLD Registers (base addr = falcbase, TE only) */ +#define CPLD_REG1 0x140 /* Chip resets, DCD/CTS status */ +#define CPLD_REG2 0x144 /* Clock enable , LED control */ + +/* CPLD Register bit description: for the FALC bits, they should always be + set based on the channel (use (bit<<(2*ch)) to access the correct bit for + that channel) */ +#define CPLD_REG1_FALC_RESET 0x01 +#define CPLD_REG1_SCA_RESET 0x02 +#define CPLD_REG1_GLOBAL_CLK 0x08 +#define CPLD_REG1_FALC_DCD 0x10 +#define CPLD_REG1_FALC_CTS 0x20 + +#define CPLD_REG2_FALC_TX_CLK 0x01 +#define CPLD_REG2_FALC_RX_CLK 0x02 +#define CPLD_REG2_FALC_LED1 0x10 +#define CPLD_REG2_FALC_LED2 0x20 + +/* Structure with FALC-related fields (TE only) */ +#define PC300_FALC_MAXLOOP 0x0000ffff /* for falc_issue_cmd() */ + +typedef struct falc { + ucchar sync; /* If true FALC is synchronized */ + ucchar active; /* if TRUE then already active */ + ucchar loop_active; /* if TRUE a line loopback UP was received */ + ucchar loop_gen; /* if TRUE a line loopback UP was issued */ + + ucchar num_channels; + ucchar offset; /* 1 for T1, 0 for E1 */ + ucchar full_bandwidth; + + ucchar xmb_cause; + ucchar multiframe_mode; + + /* Statistics */ + ucshort pden; /* Pulse Density violation count */ + ucshort los; /* Loss of Signal count */ + ucshort losr; /* Loss of Signal recovery count */ + ucshort lfa; /* Loss of frame alignment count */ + ucshort farec; /* Frame Alignment Recovery count */ + ucshort lmfa; /* Loss of multiframe alignment count */ + ucshort ais; /* Remote Alarm indication Signal count */ + ucshort sec; /* One-second timer */ + ucshort es; /* Errored second */ + ucshort rai; /* remote alarm received */ + ucshort bec; + ucshort fec; + ucshort cvc; + ucshort cec; + ucshort ebc; + + /* Status */ + ucchar red_alarm; + ucchar blue_alarm; + ucchar loss_fa; + ucchar yellow_alarm; + ucchar loss_mfa; + ucchar prbs; +} falc_t; + +typedef struct pc300dev { + void *if_ptr; /* General purpose pointer */ + struct pc300ch *chan; +#ifdef __KERNEL__ + char name[16]; + void *private; + hdlc_device *hdlc; + struct net_device_stats stats; + struct sk_buff *tx_skb; +#endif /* __KERNEL__ */ +}pc300dev_t; + +typedef struct pc300hw { + int type; /* RSV, X21, etc. */ + int nchan; /* number of channels */ + int irq; /* interrupt request level */ + uclong clock; /* Board clock */ + uclong plxphys; /* PLX registers MMIO base (physical) */ + uclong plxbase; /* PLX registers MMIO base (virtual) */ + uclong plxsize; /* PLX registers MMIO size */ + uclong scaphys; /* SCA registers MMIO base (physical) */ + uclong scabase; /* SCA registers MMIO base (virtual) */ + uclong scasize; /* SCA registers MMIO size */ + uclong ramphys; /* On-board RAM MMIO base (physical) */ + uclong rambase; /* On-board RAM MMIO base (virtual) */ + uclong ramsize; /* On-board RAM MMIO size */ + uclong falcphys; /* FALC registers MMIO base (physical) */ + uclong falcbase; /* FALC registers MMIO base (virtual) */ + uclong falcsize; /* FALC registers MMIO size */ +} pc300hw_t; + +typedef struct pc300chconf { + ucchar media; /* HW media (RS232, V.35, etc.) */ + uclong proto; /* Protocol (PPP, X.25, etc.) */ + uclong clkrate; /* Clock rate (in bps, 0 = ext. clock) */ + + /* TE-specific parameters */ + ucchar lcode; /* Line Code (AMI, B8ZS, etc.) */ + ucchar fr_mode; /* Frame Mode (ESF, D4, etc.) */ + ucchar lbo; /* Line Build Out */ + ucchar rx_sens; /* Rx Sensitivity (long- or short-haul) */ + uclong tslot_bitmap; /* bit[i]=1 => timeslot _i_ is active */ +} pc300chconf_t; + +typedef struct pc300ch { + struct pc300 *card; + int channel; + pc300dev_t d; + pc300chconf_t conf; + ucchar tx_first_bd; /* First TX DMA block descr. w/ data */ + ucchar tx_next_bd; /* Next free TX DMA block descriptor */ + ucchar rx_first_bd; /* First free RX DMA block descriptor */ + ucchar rx_last_bd; /* Last free RX DMA block descriptor */ + falc_t falc; /* FALC structure (TE only) */ +} pc300ch_t; + +typedef struct pc300 { + pc300hw_t hw; /* hardware config. */ + pc300ch_t chan[PC300_MAXCHAN]; +#ifdef __KERNEL__ + spinlock_t card_lock; +#endif /* __KERNEL__ */ +} pc300_t; + +/* DEV ioctl() commands */ +#define N_SPPP_IOCTLS 2 + +enum pc300_ioctl_cmds { + SIOCCPCRESERVED = (SIOCDEVPRIVATE + N_SPPP_IOCTLS), + SIOCGPC300CONF, + SIOCSPC300CONF, + SIOCGPC300STATUS, + SIOCGPC300FALCSTATUS, +}; + +/* Control Constant Definitions */ +#define PC300_RSV 0x01 +#define PC300_X21 0x02 +#define PC300_TE 0x03 + +#define PC300_LC_AMI 0x01 +#define PC300_LC_B8ZS 0x02 +#define PC300_LC_NRZ 0x03 +#define PC300_LC_HDB3 0x04 + +/* Framing (T1) */ +#define PC300_FR_ESF 0x01 +#define PC300_FR_D4 0x02 +#define PC300_FR_ESF_JAPAN 0x03 + +/* Framing (E1) */ +#define PC300_FR_MF_CRC4 0x04 +#define PC300_FR_MF_NON_CRC4 0x05 + +#define PC300_LBO_0_DB 0x00 +#define PC300_LBO_7_5_DB 0x01 +#define PC300_LBO_15_DB 0x02 +#define PC300_LBO_22_5_DB 0x03 + +#define PC300_RX_SENS_SH 0x01 +#define PC300_RX_SENS_LH 0x02 + +#define PC300_TX_TIMEOUT (2*HZ) +#define PC300_TX_QUEUE_LEN 10 +#define PC300_DEF_MTU 1500 + +#ifdef __KERNEL__ +/* Function Prototypes */ +static void tx_dma_buf_pt_init(pc300_t *, int); +static void tx_dma_buf_init(pc300_t *, int); +static void rx_dma_buf_pt_init(pc300_t *, int); +static void rx_dma_buf_init(pc300_t *, int); +static void tx_dma_buf_check(pc300_t *, int); +static void rx_dma_buf_check(pc300_t *, int); +int dma_buf_write(pc300_t *, int, ucchar *, int); +int dma_buf_read(pc300_t *, int, struct sk_buff *); +void tx_dma_start(pc300_t *, int); +void rx_dma_start(pc300_t *, int); +void tx_dma_stop(pc300_t *, int); +void rx_dma_stop(pc300_t *, int); +int cpc_queue_xmit(struct sk_buff *, struct device *); +void cpc_net_rx(hdlc_device *); +#ifdef CONFIG_PC300_X25 +int cpc_x25_packetlayer_xmit(struct sk_buff *, struct device *); +void cpc_lapb_connected(void *, int); +void cpc_lapb_disconnected(void *, int); +void cpc_lapb_data_indication(void *, struct sk_buff *); +void cpc_lapb_data_transmit(void *, struct sk_buff *); +#endif /* CONFIG_PC300_X25 */ +static void cpc_intr(int, void *, struct pt_regs *); +void cpc_sca_status(pc300_t *, int); +int cpc_ioctl(hdlc_device *, struct ifreq *, int); +static int clock_rate_calc(uclong, uclong, int *); +int ch_config(pc300dev_t *); +int rx_config(pc300dev_t *); +int tx_config(pc300dev_t *); +int cpc_opench(pc300dev_t *); +void cpc_closech(pc300dev_t *); +int cpc_open(hdlc_device *); +void cpc_close(hdlc_device *); +static uclong detect_ram(pc300_t *); +static void plx_init(pc300_t *); +static int cpc_detect(void); +#endif /* __KERNEL__ */ + +#endif /* _PC300_H */ diff --git a/include/linux/pci.h b/include/linux/pci.h index c4f2a28c0e45..6efe8651cbc6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -951,6 +951,10 @@ #define PCI_DEVICE_ID_CYCLOM_8Y_Hi 0x0105 #define PCI_DEVICE_ID_CYCLOM_Z_Lo 0x0200 #define PCI_DEVICE_ID_CYCLOM_Z_Hi 0x0201 +#define PCI_DEVICE_ID_PC300_RX_2 0x0300 +#define PCI_DEVICE_ID_PC300_RX_1 0x0301 +#define PCI_DEVICE_ID_PC300_TE_2 0x0310 +#define PCI_DEVICE_ID_PC300_TE_1 0x0311 #define PCI_VENDOR_ID_ESSENTIAL 0x120f #define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER 0x0001 diff --git a/include/linux/telephony.h b/include/linux/telephony.h index c3e4c55737ae..bde4a9de8fdc 100644 --- a/include/linux/telephony.h +++ b/include/linux/telephony.h @@ -1,32 +1,33 @@ -/* - * telephony.h +/****************************************************************************** + * + * telephony.h * - * Basic Linux Telephony Interface + * Basic Linux Telephony Interface * - * (c) Copyright 1999 Quicknet Technologies, Inc. + * (c) Copyright 1999 Quicknet Technologies, Inc. * - * 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 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. * - * Authors: Ed Okerson, - * Greg Herlein, + * Authors: Ed Okerson, + * Greg Herlein, * - * Contributors: Alan Cox, - * David Erhart, + * Contributors: Alan Cox, + * David W. Erhart, * * Version: 0.1.0 - December 19, 1999 * * Fixes: - */ + * + *****************************************************************************/ #ifndef TELEPHONY_H #define TELEPHONY_H -/* vendor identification numbers */ #define PHONE_VENDOR_IXJ 1 -#define PHONE_VENDOR_QUICKNET PHONE_IXJ +#define PHONE_VENDOR_QUICKNET PHONE_VENDOR_IXJ #define PHONE_VENDOR_VOICETRONIX 2 #define PHONE_VENDOR_ACULAB 3 #define PHONE_VENDOR_DIGI 4 @@ -43,7 +44,6 @@ * *****************************************************************************/ - /****************************************************************************** * * The capabilities ioctls can inform you of the capabilities of each phone @@ -81,11 +81,23 @@ typedef enum { #define PHONE_CAPABILITIES_LIST _IOR ('q', 0x81, struct phone_capability *) #define PHONE_CAPABILITIES_CHECK _IOW ('q', 0x82, struct phone_capability *) +typedef struct { + char month[3]; + char day[3]; + char hour[3]; + char min[3]; + int numlen; + char number[11]; + int namelen; + char name[80]; +} PHONE_CID; + #define PHONE_RING _IO ('q', 0x83) #define PHONE_HOOKSTATE _IO ('q', 0x84) #define PHONE_MAXRINGS _IOW ('q', 0x85, char) #define PHONE_RING_CADENCE _IOW ('q', 0x86, short) -#define PHONE_RING_START _IO ('q', 0x87) +#define OLD_PHONE_RING_START _IO ('q', 0x87) +#define PHONE_RING_START _IOW ('q', 0x87, PHONE_CID *) #define PHONE_RING_STOP _IO ('q', 0x88) #define USA_RING_CADENCE 0xC0C0 @@ -167,6 +179,23 @@ struct phone_codec_data #define PHONE_QUERY_CODEC _IOWR ('q', 0xA7, struct phone_codec_data *) #define PHONE_PSTN_LINETEST _IO ('q', 0xA8) +/****************************************************************************** +* +* This controls the VAD/CNG functionality of G.723.1. The driver will +* always pass full size frames, any unused bytes will be padded with zeros, +* and frames passed to the driver should also be padded with zeros. The +* frame type is encoded in the least significant two bits of the first +* WORD of the frame as follows: +* +* bits 1-0 Frame Type Data Rate Significant Words +* 00 0 G.723.1 6.3 12 +* 01 1 G.723.1 5.3 10 +* 10 2 VAD/CNG 2 +* 11 3 Repeat last CNG 2 bits +* +******************************************************************************/ +#define PHONE_VAD _IOW ('q', 0xA9, int) + /****************************************************************************** * @@ -198,7 +227,12 @@ struct phone_except unsigned int f1:1; unsigned int f2:1; unsigned int f3:1; - unsigned int reserved:23; + unsigned int flash:1; + unsigned int fc0:1; + unsigned int fc1:1; + unsigned int fc2:1; + unsigned int fc3:1; + unsigned int reserved:18; }; union telephony_exception { diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ad45dddca2db..aacb80ad663b 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -227,7 +227,7 @@ unsigned long __get_free_pages(int gfp_mask, unsigned long order) } /* Do we have to help kswapd or can we proceed? */ - if (nr_free_pages < (freepages.low + freepages.low) / 2) { + if (nr_free_pages < (freepages.min + freepages.low) / 2) { wake_up_interruptible(&kswapd_wait); /* Help kswapd a bit... */ diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 84ff14766632..2c3fd3abef26 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1583,8 +1583,12 @@ static int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type * Note. ddp-> becomes invalid at the realloc. */ if(skb_headroom(skb) < 22) + { /* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */ - skb = skb_realloc_headroom(skb, 32); + struct sk_buff *nskb = skb_realloc_headroom(skb, 32); + kfree(skb); + skb=nskb; + } else skb = skb_unshare(skb, GFP_ATOMIC); diff --git a/net/core/dev.c b/net/core/dev.c index b1921a99c4b5..58cece436d8a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -98,6 +98,7 @@ extern int plip_init(void); extern void n2_init(void); extern void c101_init(void); extern int wanxl_init(void); +extern int cpc_init(void); extern void sync_ppp_init(void); NET_PROFILE_DEFINE(dev_queue_xmit) @@ -2040,6 +2041,9 @@ __initfunc(int net_dev_init(void)) #ifdef CONFIG_WANXL wanxl_init(); #endif +#ifdef CONFIG_PC300 + cpc_init(); +#endif #ifdef CONFIG_HDLC sync_ppp_init(); #endif -- 2.39.5