From d146fc5b90e4f29124789a7662e4b8ef1702dc20 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 23 Nov 2007 15:23:18 -0500 Subject: [PATCH] Linux 2.2.19pre11 o Corrected version of ipc/shm.c fix (Christoph Rohland) o Update/cleanup starfire (Ion Badulescu) o Update isdn makefiles (Kai Germaschewski) o Eicon driver updates/new driver (Armin Schindler) | code o Hysdn driver (Werner Cornelius) o Hisax updates (Kai Germaschewski) --- Documentation/isdn/README.diversion | 2 +- Documentation/isdn/README.hysdn | 195 + Makefile | 2 +- aic7xxx-5.1.32.patch | 7633 --------------------------- drivers/isdn/Config.in | 75 +- drivers/isdn/Makefile | 195 +- drivers/isdn/Rules.make | 32 + drivers/isdn/act2000/Makefile | 36 +- drivers/isdn/act2000/act2000.h | 4 +- drivers/isdn/act2000/module.c | 47 +- drivers/isdn/avmb1/Makefile | 221 +- drivers/isdn/avmb1/avm_cs.c | 527 -- drivers/isdn/avmb1/b1.c | 40 +- drivers/isdn/avmb1/b1dma.c | 37 +- drivers/isdn/avmb1/b1isa.c | 28 +- drivers/isdn/avmb1/b1pci.c | 54 +- drivers/isdn/avmb1/b1pcmcia.c | 26 +- drivers/isdn/avmb1/c4.c | 84 +- drivers/isdn/avmb1/capi.c | 58 +- drivers/isdn/avmb1/capidev.h | 2 +- drivers/isdn/avmb1/capidrv.c | 26 +- drivers/isdn/avmb1/capifs.c | 58 +- drivers/isdn/avmb1/capiutil.c | 14 +- drivers/isdn/avmb1/kcapi.c | 81 +- drivers/isdn/avmb1/t1isa.c | 35 +- drivers/isdn/avmb1/t1pci.c | 51 +- drivers/isdn/divert/Makefile | 38 +- drivers/isdn/divert/divert_init.c | 13 +- drivers/isdn/divert/divert_procfs.c | 1 + drivers/isdn/eicon/Makefile | 34 +- drivers/isdn/hisax/Makefile | 295 +- drivers/isdn/hisax/avm_pci.c | 5 +- drivers/isdn/hisax/bkm_a4t.c | 5 +- drivers/isdn/hisax/bkm_a8.c | 5 +- drivers/isdn/hisax/callc.c | 5 + drivers/isdn/hisax/config.c | 79 +- drivers/isdn/hisax/diva.c | 5 +- drivers/isdn/hisax/elsa.c | 5 +- drivers/isdn/hisax/gazel.c | 5 +- drivers/isdn/hisax/hfc_pci.c | 45 +- drivers/isdn/hisax/hisax.h | 19 +- drivers/isdn/hisax/isdnl3.c | 23 +- drivers/isdn/hisax/l3ni1.c | 36 +- drivers/isdn/hisax/netjet.c | 156 +- drivers/isdn/hisax/niccy.c | 5 +- drivers/isdn/hisax/nj_s.c | 54 +- drivers/isdn/hisax/nj_u.c | 55 +- drivers/isdn/hisax/sedlbauer.c | 7 +- drivers/isdn/hisax/sportster.c | 4 +- drivers/isdn/hisax/tei.c | 2 +- drivers/isdn/hisax/telespci.c | 7 +- drivers/isdn/hisax/w6692.c | 10 +- drivers/isdn/hysdn/Makefile | 29 + drivers/isdn/hysdn/boardergo.c | 466 ++ drivers/isdn/hysdn/boardergo.h | 112 + drivers/isdn/hysdn/hycapi.c | 839 +++ drivers/isdn/hysdn/hysdn_boot.c | 413 ++ drivers/isdn/hysdn/hysdn_defs.h | 307 ++ drivers/isdn/hysdn/hysdn_init.c | 257 + drivers/isdn/hysdn/hysdn_net.c | 336 ++ drivers/isdn/hysdn/hysdn_pof.h | 89 + drivers/isdn/hysdn/hysdn_procconf.c | 467 ++ drivers/isdn/hysdn/hysdn_proclog.c | 464 ++ drivers/isdn/hysdn/hysdn_sched.c | 213 + drivers/isdn/hysdn/ince1pc.h | 132 + drivers/isdn/icn/Makefile | 19 +- drivers/isdn/icn/icn.c | 25 +- drivers/isdn/icn/icn.h | 4 +- drivers/isdn/isdn_bsdcomp.c | 15 +- drivers/isdn/isdn_cards.c | 73 - drivers/isdn/isdn_cards.h | 23 - drivers/isdn/isdn_common.c | 22 +- drivers/isdn/isdn_v110.c | 6 +- drivers/isdn/isdnloop/Makefile | 19 +- drivers/isdn/isdnloop/isdnloop.c | 32 +- drivers/isdn/isdnloop/isdnloop.h | 4 +- drivers/isdn/pcbit/Makefile | 36 +- drivers/isdn/pcbit/callbacks.c | 2 +- drivers/isdn/pcbit/capi.c | 2 +- drivers/isdn/pcbit/drv.c | 5 +- drivers/isdn/pcbit/edss1.c | 2 +- drivers/isdn/pcbit/layer2.c | 2 +- drivers/isdn/pcbit/module.c | 28 +- drivers/isdn/pcbit/pcbit.h | 2 +- drivers/isdn/sc/Makefile | 66 +- drivers/isdn/sc/includes.h | 2 +- drivers/isdn/sc/init.c | 22 +- drivers/net/Space.c | 8 +- drivers/net/starfire.c | 1012 ++-- include/linux/hysdn_if.h | 49 + include/linux/isdn.h | 5 +- include/linux/isdn_compat.h | 48 + include/linux/isdn_ppp.h | 2 +- include/linux/isdnif.h | 2 + ipc/shm.c | 2 + net/core/sock.c | 3 +- 96 files changed, 6044 insertions(+), 10103 deletions(-) create mode 100644 Documentation/isdn/README.hysdn delete mode 100644 aic7xxx-5.1.32.patch create mode 100644 drivers/isdn/Rules.make delete mode 100644 drivers/isdn/avmb1/avm_cs.c create mode 100644 drivers/isdn/hysdn/Makefile create mode 100644 drivers/isdn/hysdn/boardergo.c create mode 100644 drivers/isdn/hysdn/boardergo.h create mode 100644 drivers/isdn/hysdn/hycapi.c create mode 100644 drivers/isdn/hysdn/hysdn_boot.c create mode 100644 drivers/isdn/hysdn/hysdn_defs.h create mode 100644 drivers/isdn/hysdn/hysdn_init.c create mode 100644 drivers/isdn/hysdn/hysdn_net.c create mode 100644 drivers/isdn/hysdn/hysdn_pof.h create mode 100644 drivers/isdn/hysdn/hysdn_procconf.c create mode 100644 drivers/isdn/hysdn/hysdn_proclog.c create mode 100644 drivers/isdn/hysdn/hysdn_sched.c create mode 100644 drivers/isdn/hysdn/ince1pc.h delete mode 100644 drivers/isdn/isdn_cards.c delete mode 100644 drivers/isdn/isdn_cards.h create mode 100644 include/linux/hysdn_if.h create mode 100644 include/linux/isdn_compat.h diff --git a/Documentation/isdn/README.diversion b/Documentation/isdn/README.diversion index 98909b1bf7e4..bddcd5fb86ff 100644 --- a/Documentation/isdn/README.diversion +++ b/Documentation/isdn/README.diversion @@ -6,7 +6,7 @@ document. The diversion services may be used with all cards supported by the HiSax driver. The diversion kernel interface and controlling tool divertctrl were written by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) under the -GNU Public License. +GNU General Public License. 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 diff --git a/Documentation/isdn/README.hysdn b/Documentation/isdn/README.hysdn new file mode 100644 index 000000000000..94e9f902b999 --- /dev/null +++ b/Documentation/isdn/README.hysdn @@ -0,0 +1,195 @@ +$Id: README.hysdn,v 1.3.6.1 2001/02/10 14:41:19 kai Exp $ +The hysdn driver has been written by +by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) +for Hypercope GmbH Aachen Germany. Hypercope agreed to publish this driver +under the GNU General Public License. + +The CAPI 2.0-support was added by Ulrich Albrecht (ualbrecht@hypercope.de) +for Hypercope GmbH Aachen, Germany. + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Table of contents +================= + +1. About the driver + +2. Loading/Unloading the driver + +3. Entries in the /proc filesystem + +4. The /proc/net/hysdn/cardconfX file + +5. The /proc/net/hysdn/cardlogX file + +6. Where to get additional info and help + + +1. About the driver + + The drivers/isdn/hysdn subdir contains a driver for HYPERCOPEs active + PCI isdn cards Champ, Ergo and Metro. To enable support for this cards + enable ISDN support in the kernel config and support for HYSDN cards in + the active cards submenu. The driver may only be compiled and used if + support for loadable modules and the process filesystem have been enabled. + + These cards provide two different interfaces to the kernel. Without the + optional CAPI 2.0 support, they register as ethernet card. IP-routing + to a ISDN-destination is performed on the card itself. All necessary + handlers for various protocols like ppp and others as well as config info + and firmware may be fetched from Hypercopes WWW-Site www.hypercope.de. + + With CAPI 2.0 support enabled, the card can also be used as a CAPI 2.0 + compliant devices with either CAPI 2.0 applications + (check isdn4k-utils) or -using the capidrv module- as a regular + isdn4linux device. This is done via the same mechanism as with the + active AVM cards and in fact uses the same module. + + +2. Loading/Unloading the driver + + The module has no command line parameters and auto detects up to 10 cards + in the id-range 0-9. + If a loaded driver shall be unloaded all open files in the /proc/net/hysdn + subdir need to be closed and all ethernet interfaces allocated by this + driver must be shut down. Otherwise the module counter will avoid a module + unload. + + If you are using the CAPI 2.0-interface, make sure to load/modprobe the + kernelcapi-module first. + + If you plan to use the capidrv-link to isdn4linux, make sure to load + capidrv.o after all modules using this driver (i.e. after hysdn and + any avm-specific modules). + +3. Entries in the /proc filesystem + + When the module has been loaded it adds the directory hysdn in the + /proc/net tree. This directory contains exactly 2 file entries for each + card. One is called cardconfX and the other cardlogX, where X is the + card id number from 0 to 9. + The cards are numbered in the order found in the PCI config data. + +4. The /proc/net/hysdn/cardconfX file + + This file may be read to get by everyone to get info about the cards type, + actual state, available features and used resources. + The first 3 entries (id, bus and slot) are PCI info fields, the following + type field gives the information about the cards type: + + 4 -> Ergo card (server card with 2 b-chans) + 5 -> Metro card (server card with 4 or 8 b-chans) + 6 -> Champ card (client card with 2 b-chans) + + The following 3 fields show the hardware assignments for irq, iobase and the + dual ported memory (dp-mem). + The fields b-chans and fax-chans announce the available card resources of + this types for the user. + The state variable indicates the actual drivers state for this card with the + following assignments. + + 0 -> card has not been booted since driver load + 1 -> card booting is actually in progess + 2 -> card is in an error state due to a previous boot failure + 3 -> card is booted and active + + And the last field (device) shows the name of the ethernet device assigned + to this card. Up to the first successful boot this field only shows a - + to tell that no net device has been allocated up to now. Once a net device + has been allocated it remains assigned to this card, even if a card is + rebooted and an boot error occurs. + + Writing to the cardconfX file boots the card or transfers config lines to + the cards firmware. The type of data is automatically detected when the + first data is written. Only root has write access to this file. + The firmware boot files are normally called hyclient.pof for client cards + and hyserver.pof for server cards. + After successfully writing the boot file, complete config files or single + config lines may be copied to this file. + If an error occurs the return value given to the writing process has the + following additional codes (decimal): + + 1000 Another process is currently bootng the card + 1001 Invalid firmware header + 1002 Boards dual-port RAM test failed + 1003 Internal firmware handler error + 1004 Boot image size invalid + 1005 First boot stage (bootstrap loader) failed + 1006 Second boot stage failure + 1007 Timeout waiting for card ready during boot + 1008 Operation only allowed in booted state + 1009 Config line to long + 1010 Invalid channel number + 1011 Timeout sending config data + + Additional info about error reasons may be fetched from the log output. + +5. The /proc/net/hysdn/cardlogX file + + The cardlogX file entry may be opened multiple for reading by everyone to + get the cards and drivers log data. Card messages always start with the + keyword LOG. All other lines are output from the driver. + The driver log data may be redirected to the syslog by selecting the + appropriate bitmask. The cards log messages will always be send to this + interface but never to the syslog. + + A root user may write a decimal or hex (with 0x) value t this file to select + desired output options. As mentioned above the cards log dat is always + written to the cardlog file independent of the following options only used + to check and debug the driver itself: + + For example: + echo "0x34560078" > /proc/net/hysdn/cardlog0 + to output the hex log mask 34560078 for card 0. + + The written value is regarded as an unsigned 32-Bit value, bit ored for + desired output. The following bits are already assigned: + + 0x80000000 All driver log data is alternatively via syslog + 0x00000001 Log memory allocation errors + 0x00000010 Firmware load start and close are logged + 0x00000020 Log firmware record parser + 0x00000040 Log every firmware write actions + 0x00000080 Log all card related boot messages + 0x00000100 Output all config data sent for debugging purposes + 0x00000200 Only non comment config lines are shown wth channel + 0x00000400 Additional conf log output + 0x00001000 Log the asynchronous scheduler actions (config and log) + 0x00100000 Log all open and close actions to /proc/net/hysdn/card files + 0x00200000 Log all actions from /proc file entries + 0x00010000 Log network interface init and deinit + +6. Where to get additional info and help + + If you have any problems concerning the driver or configuration contact + the Hypercope support team (support@hypercope.de) and or the authors + Werner Cornelius (werner@isdn4linux or cornelius@titro.de) or + Ulrich Albrecht (ualbrecht@hypercope.de). + + + + + + + + + + + + + + + diff --git a/Makefile b/Makefile index d5dbbf6a5461..bb75f54df543 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 19 -EXTRAVERSION = pre10 +EXTRAVERSION = pre11 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/aic7xxx-5.1.32.patch b/aic7xxx-5.1.32.patch deleted file mode 100644 index f68d0023e92b..000000000000 --- a/aic7xxx-5.1.32.patch +++ /dev/null @@ -1,7633 +0,0 @@ -diff -U 3 -rN linux-2.2.17/drivers/scsi/Config.in linux/drivers/scsi/Config.in ---- linux-2.2.17/drivers/scsi/Config.in Wed May 3 20:16:44 2000 -+++ linux/drivers/scsi/Config.in Tue Feb 6 03:50:13 2001 -@@ -28,10 +28,9 @@ - dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI - dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI - if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then -- bool ' Enable Tagged Command Queueing (TCQ) by default' CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT -- int ' Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 8 -- bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS N -- int ' Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5 -+ bool ' Enable Tagged Command Queueing (TCQ) by default' CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT y -+ int ' Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 24 -+ bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS y - fi - dep_tristate 'IBM ServeRAID support' CONFIG_SCSI_IPS $CONFIG_SCSI - dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI -diff -U 3 -rN linux-2.2.17/drivers/scsi/README.aic7xxx linux/drivers/scsi/README.aic7xxx ---- linux-2.2.17/drivers/scsi/README.aic7xxx Wed May 3 20:16:44 2000 -+++ linux/drivers/scsi/README.aic7xxx Tue Feb 6 03:49:36 2001 -@@ -14,50 +14,17 @@ - Adaptec Cards - ---------------------------- - AHA-274x -- AHA-274xT -- AHA-2842 -- AHA-2910B -- AHA-2920C -- AHA-2930 -- AHA-2930U -- AHA-2930CU -- AHA-2930U2 -- AHA-2940 -- AHA-2940W -- AHA-2940U -- AHA-2940UW -- AHA-2940UW-PRO -- AHA-2940AU -- AHA-2940U2W -- AHA-2940U2 -- AHA-2940U2B -- AHA-2940U2BOEM -- AHA-2944D -- AHA-2944WD -- AHA-2944UD -- AHA-2944UWD -- AHA-2950U2 -- AHA-2950U2W -- AHA-2950U2B -- AHA-29160M -- AHA-3940 -- AHA-3940U -- AHA-3940W -- AHA-3940UW -- AHA-3940AUW -- AHA-3940U2W -- AHA-3950U2B -- AHA-3950U2D -- AHA-3960D -- AHA-39160M -- AHA-3985 -- AHA-3985U -- AHA-3985W -- AHA-3985UW -+ AHA-274xT -+ AHA-274xW -+ AHA-284x -+ AHA-284xW -+ All PCI based cards using any of the chipsets listed under motherboard -+ chipsets. In general, this means *all* of the Adaptec SCSI controllers -+ except the ones specifically excluded later on in this document. - - Motherboard Chipsets - ---------------------------- -- AIC-777x -+ AIC-777x - AIC-785x - AIC-786x - AIC-787x -@@ -71,15 +38,14 @@ - SCSI-1/SCSI-2 50pin devices, transfer rates up to 20MB/s. - U - Ultra SCSI, transfer rates up to 40MB/s. - U2- Ultra 2 SCSI, transfer rates up to 80MB/s. -+ U3- Ultra 3 SCSI, transfer rates up to 160MB/s. - D - Differential SCSI. - T - Twin Channel SCSI. Up to 14 SCSI devices. - - AHA-274x - EISA SCSI controller - AHA-284x - VLB SCSI controller - AHA-29xx - PCI SCSI controller -- AHA-394x - PCI controllers with two separate SCSI controllers on-board. -- AHA-398x - PCI RAID controllers with three separate SCSI controllers -- on-board. -+ AHA-39xx - PCI controllers with multiple separate SCSI channels on-board. - - Not Supported Devices - ------------------------------ -@@ -93,7 +59,7 @@ - - Motherboard Chipsets - ---------------------------- -- AIC-7810 -+ AIC-781x - - Bus Types - ---------------------------- -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.h linux/drivers/scsi/aic7xxx/aic7xxx.h ---- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.h Wed Dec 31 19:00:00 1969 -+++ linux/drivers/scsi/aic7xxx/aic7xxx.h Tue Feb 6 03:49:36 2001 -@@ -0,0 +1,114 @@ -+/*+M************************************************************************* -+ * Adaptec AIC7xxx device driver for Linux. -+ * -+ * Copyright (c) 1994 John Aycock -+ * The University of Calgary Department of Computer Science. -+ * -+ * 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, or (at your option) -+ * any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; see the file COPYING. If not, write to -+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * $Id: aic7xxx.h,v 3.2 1996/07/23 03:37:26 deang Exp $ -+ *-M*************************************************************************/ -+#ifndef _aic7xxx_h -+#define _aic7xxx_h -+ -+#define AIC7XXX_H_VERSION "3.2.4" -+ -+#ifndef LINUX_VERSION_CODE -+#include -+#endif -+ -+#ifndef KERNEL_VERSION -+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -+#endif -+ -+#if defined(__i386__) -+# define AIC7XXX_BIOSPARAM aic7xxx_biosparam -+#else -+# define AIC7XXX_BIOSPARAM NULL -+#endif -+ -+/* -+ * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields -+ * to do with card config are filled in after the card is detected. -+ */ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,65) -+#define AIC7XXX { \ -+ next: NULL, \ -+ module: NULL, \ -+ proc_dir: NULL, \ -+ proc_info: aic7xxx_proc_info, \ -+ name: NULL, \ -+ detect: aic7xxx_detect, \ -+ release: aic7xxx_release, \ -+ info: aic7xxx_info, \ -+ command: NULL, \ -+ queuecommand: aic7xxx_queue, \ -+ eh_strategy_handler: NULL, \ -+ eh_abort_handler: NULL, \ -+ eh_device_reset_handler: NULL, \ -+ eh_bus_reset_handler: NULL, \ -+ eh_host_reset_handler: NULL, \ -+ abort: aic7xxx_abort, \ -+ reset: aic7xxx_reset, \ -+ slave_attach: NULL, \ -+ bios_param: AIC7XXX_BIOSPARAM, \ -+ can_queue: 255, /* max simultaneous cmds */\ -+ this_id: -1, /* scsi id of host adapter */\ -+ sg_tablesize: 0, /* max scatter-gather cmds */\ -+ cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ -+ present: 0, /* number of 7xxx's present */\ -+ unchecked_isa_dma: 0, /* no memory DMA restrictions */\ -+ use_clustering: ENABLE_CLUSTERING, \ -+ use_new_eh_code: 0 \ -+} -+#else -+#define AIC7XXX { \ -+ next: NULL, \ -+ usage_count: NULL, \ -+ proc_dir: NULL, \ -+ proc_info: aic7xxx_proc_info, \ -+ name: NULL, \ -+ detect: aic7xxx_detect, \ -+ release: aic7xxx_release, \ -+ info: aic7xxx_info, \ -+ command: NULL, \ -+ queuecommand: aic7xxx_queue, \ -+ abort: aic7xxx_abort, \ -+ reset: aic7xxx_reset, \ -+ slave_attach: NULL, \ -+ bios_param: AIC7XXX_BIOSPARAM, \ -+ can_queue: 255, /* max simultaneous cmds */\ -+ this_id: -1, /* scsi id of host adapter */\ -+ sg_tablesize: 0, /* max scatter-gather cmds */\ -+ cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ -+ present: 0, /* number of 7xxx's present */\ -+ unchecked_isa_dma: 0, /* no memory DMA restrictions */\ -+ use_clustering: ENABLE_CLUSTERING \ -+} -+#endif -+ -+extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); -+extern int aic7xxx_biosparam(Disk *, kdev_t, int[]); -+extern int aic7xxx_detect(Scsi_Host_Template *); -+extern int aic7xxx_command(Scsi_Cmnd *); -+extern int aic7xxx_reset(Scsi_Cmnd *, unsigned int); -+extern int aic7xxx_abort(Scsi_Cmnd *); -+extern int aic7xxx_release(struct Scsi_Host *); -+ -+extern const char *aic7xxx_info(struct Scsi_Host *); -+ -+extern int aic7xxx_proc_info(char *, char **, off_t, int, int, int); -+ -+#endif /* _aic7xxx_h */ -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.reg linux/drivers/scsi/aic7xxx/aic7xxx.reg ---- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.reg Wed May 3 20:16:44 2000 -+++ linux/drivers/scsi/aic7xxx/aic7xxx.reg Tue Feb 6 03:49:36 2001 -@@ -703,7 +703,12 @@ - * it that it can fill the - * message buffer. - */ -- mask TRACEPOINT 0xb0|SEQINT -+ mask SEQ_SG_FIXUP 0xb0|SEQINT /* need help with fixing up -+ * the sg array pointer after -+ * a phasemis with no valid -+ * sg elements in the shadow -+ * pipeline. -+ */ - mask TRACEPOINT2 0xc0|SEQINT - mask MSGIN_PHASEMIS 0xd0|SEQINT /* - * Target changed phase on us -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq ---- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.seq Mon Sep 4 13:39:20 2000 -+++ linux/drivers/scsi/aic7xxx/aic7xxx.seq Tue Feb 6 03:49:36 2001 -@@ -291,7 +291,11 @@ - - mov A, LASTPHASE; - -- test A, ~P_DATAIN jz p_data; -+ if ((p->features & AHC_ULTRA2) != 0) { -+ test A, ~P_DATAIN jz u2_p_data; -+ } else { -+ test A, ~P_DATAIN jz p_data; -+ } - cmp A,P_COMMAND je p_command; - cmp A,P_MESGOUT je p_mesgout; - cmp A,P_STATUS je p_status; -@@ -332,133 +336,73 @@ - /* clear target specific flags */ - clr SEQ_FLAGS ret; - -+ if ((p->features & AHC_ULTRA2) != 0) { -+ -+ -+ -+u2_data_phase_reinit: - /* - * If we re-enter the data phase after going through another phase, the - * STCNT may have been cleared, so restore it from the residual field. -+ * On Ultra2, we have to put it into the HCNT field because we have to -+ * drop the data down into the shadow layer via the preload ability. - */ --data_phase_reinit: -- 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; -- } -- jmp data_phase_loop; -- --p_data: -- if ((p->features & AHC_ULTRA2) != 0) { -+ jmp u2_data_phase_loop; -+u2_p_data: - mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN; -- } else { -- mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET; -- } -- test LASTPHASE, IOI jnz . + 2; -- or DMAPARAMS, DIRECTION; -- call assert; /* -+ test LASTPHASE, IOI jnz . + 2; -+ or DMAPARAMS, DIRECTION; -+ call assert; /* - * Ensure entering a data - * phase is okay - seen identify, etc. - */ -- if ((p->features & AHC_CMD_CHAN) != 0) { - mvi CCSGADDR, CCSGADDR_MAX; -- } -- test SEQ_FLAGS, DPHASE jnz data_phase_reinit; -- -- /* We have seen a data phase */ -- or SEQ_FLAGS, DPHASE; -- -- /* -- * Initialize the DMA address and counter from the SCB. -- * Also set SG_COUNT and SG_NEXT in memory since we cannot -- * modify the values in the SCB itself until we see a -- * save data pointers message. -- */ -- if ((p->features & AHC_CMD_CHAN) != 0) { -+ test SEQ_FLAGS, DPHASE jnz u2_data_phase_reinit; -+ or SEQ_FLAGS, DPHASE; /* we've seen a data phase */ -+ /* -+ * Initialize the DMA address and counter from the SCB. -+ * Also set SG_COUNT and SG_NEXT in memory since we cannot -+ * modify the values in the SCB itself until we see a -+ * save data pointers message. -+ */ - bmov HADDR, SCB_DATAPTR, 7; -- bmov STCNT, HCNT, 3; - bmov SG_COUNT, SCB_SGCOUNT, 5; -- } else { -- mvi DINDEX, HADDR; -- mvi SCB_DATAPTR call bcopy_7; -- call set_stcnt_from_hcnt; -- mvi DINDEX, SG_COUNT; -- mvi SCB_SGCOUNT call bcopy_5; -- } -- --data_phase_loop: --/* Guard against overruns */ -- test SG_COUNT, 0xff jnz data_phase_inbounds; -+u2_data_phase_loop: -+ /* Guard against overruns */ -+ test SG_COUNT, 0xff jnz u2_data_phase_inbounds; - /* - * Turn on 'Bit Bucket' mode, set the transfer count to - * 16meg and let the target run until it changes phase. - * When the transfer completes, notify the host that we - * had an overrun. - */ -- or SXFRCTL1,BITBUCKET; -- and DMAPARAMS, ~(HDMAEN|SDMAEN); -- if ((p->features & AHC_CMD_CHAN) != 0) { -- if ((p->features & AHC_ULTRA2) != 0) { -- bmov HCNT, ALLONES, 3; -- } -- bmov STCNT, ALLONES, 3; -- } else { -- mvi STCNT[0], 0xFF; -- mvi STCNT[1], 0xFF; -- mvi STCNT[2], 0xFF; -- } --data_phase_inbounds: -+ or SXFRCTL1,BITBUCKET; -+ and DMAPARAMS, DIRECTION; -+ bmov HCNT, ALLONES, 3; -+u2_data_phase_inbounds: - /* If we are the last SG block, tell the hardware. */ -- cmp SG_COUNT,0x01 jne data_phase_wideodd; -- if ((p->features & AHC_ULTRA2) == 0) { -- and DMAPARAMS, ~WIDEODD; -- } else { -- mvi SG_CACHEPTR, LAST_SEG; -- } --data_phase_wideodd: -- if ((p->features & AHC_ULTRA2) != 0) { -- mov SINDEX, ALLONES; -- mov DFCNTRL, DMAPARAMS; -- test SSTAT0, SDONE jnz .; --data_phase_dma_loop: -- test SSTAT0, SDONE jnz data_phase_dma_done; -- test SSTAT1,PHASEMIS jz data_phase_dma_loop; /* ie. underrun */ --data_phase_dma_phasemis: -- test SSTAT0,SDONE jnz data_phase_dma_done; -- clr SINDEX; /* Remember the phasemiss */ -- } else { -- mov DMAPARAMS call dma; -- } -- --data_phase_dma_done: --/* Go tell the host about any overruns */ -- test SXFRCTL1,BITBUCKET jnz data_phase_overrun; -- --/* Exit if we had an underrun. dma clears SINDEX in this case. */ -- test SINDEX,0xff jz data_phase_finish; -- -+ shl A, 2, SG_COUNT; -+ cmp SG_COUNT,0x01 jne u2_data_phase_lastseg; -+ or A, LAST_SEG; -+u2_data_phase_lastseg: -+ mov SG_CACHEPTR, A; -+ mov DFCNTRL, DMAPARAMS; /* start the operation */ -+ test SXFRCTL1, BITBUCKET jnz u2_data_phase_overrun; -+u2_preload_wait: -+ test SSTAT1, PHASEMIS jnz u2_phasemis; -+ test DFSTATUS, PRELOAD_AVAIL jz u2_preload_wait; - /* -- * Advance the scatter-gather pointers if needed -+ * Advance the scatter-gather pointers - */ --sg_advance: -- dec SG_COUNT; /* one less segment to go */ -+u2_sg_advance: -+ cmp SG_COUNT, 0x01 je u2_data_phase_finish; - -- test SG_COUNT, 0xff jz data_phase_finish; /* Are we done? */ --/* -- * Load a struct scatter and set up the data address and length. -- * If the working value of the SG count is nonzero, then -- * we need to load a new set of values. -- * -- * This, like all DMA's, assumes little-endian host data storage. -- */ --sg_load: -- if ((p->features & AHC_CMD_CHAN) != 0) { - /* - * Do we have any prefetch left??? - */ -- cmp CCSGADDR, CCSGADDR_MAX jne prefetched_segs_avail; -+ cmp CCSGADDR, CCSGADDR_MAX jne u2_prefetch_avail; - - /* - * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes. -@@ -474,48 +418,263 @@ - and CCSGCTL, ~CCSGEN; - test CCSGCTL, CCSGEN jnz .; - mvi CCSGCTL, CCSGRESET; --prefetched_segs_avail: -- bmov HADDR, CCSGRAM, 8; -- if ((p->features & AHC_ULTRA2) == 0) { -- bmov STCNT, HCNT, 3; -+u2_prefetch_avail: -+ /* Test for a phasemis before we drop the stuff into the -+ * host regs. We might have actually missed the phasemis -+ * while doing the dma of the sg segs. -+ */ -+ test SSTAT1, PHASEMIS jnz u2_phasemis; -+ dec SG_COUNT; /* one less segment to go */ -+ bmov HADDR, CCSGRAM, 8; /* drop the address in place */ -+ clr A; /* Advance the SG pointer by */ -+ add SG_NEXT[0],SG_SIZEOF; /* adding SG_SIZEOF to addr0 */ -+ adc SG_NEXT[1],A; /* and adding any carry to */ -+ jmp u2_data_phase_loop; /* addr1 */ -+ -+ -+/* -+ * We've loaded all of our segments into the preload layer. Now, we simply -+ * have to wait for it to finish or for us to get a phasemis. And, since -+ * we'll get a phasemis if we do finish, all we really need to do is wait -+ * for a phasemis then check if we did actually complete all the segments. -+ */ -+u2_data_phase_finish: -+ test SSTAT1, PHASEMIS jnz u2_phasemis; -+ test SG_CACHEPTR, LAST_SEG_DONE jz u2_data_phase_finish; -+ clr SG_COUNT; -+ test SSTAT1, REQINIT jz .; -+ test SSTAT1, PHASEMIS jz u2_data_phase_loop; -+u2_phasemis: -+ call ultra2_dmafinish; -+ test SG_CACHEPTR, LAST_SEG_DONE jnz u2_phasemis_end; -+ test SSTAT2, SHVALID jnz u2_fixup_residual; -+ mvi INTSTAT, SEQ_SG_FIXUP; -+ jmp u2_phasemis_end; -+u2_fixup_residual: -+ shr ARG_1, 2, SG_CACHEPTR; -+u2_phasemis_loop: -+ and A, 0x3f, SG_COUNT; -+ cmp ARG_1, A je u2_phasemis_end; -+/* -+ * Subtract SG_SIZEOF from the SG_NEXT pointer and add 1 to the SG_COUNT -+ */ -+ clr A; -+ add SG_NEXT[0], -SG_SIZEOF; -+ adc SG_NEXT[1], 0xff; -+ inc SG_COUNT; -+ jmp u2_phasemis_loop; -+u2_phasemis_end: -+ bmov SCB_RESID_DCNT, STCNT, 3; -+ mov SCB_RESID_SGCNT, SG_COUNT; -+ or SXFRCTL0, CLRSTCNT|CLRCHN; -+ jmp ITloop; -+ -+ -+ -+/* -+ * Actually turn off the DMA hardware, save our current position into the -+ * proper residual variables, wait for the next REQ signal, then jump to -+ * the ITloop. Jumping to the ITloop ensures that if we happen to get -+ * brought into the data phase again (or are still in it after our last -+ * segment) that we will properly signal an overrun to the kernel. -+ */ -+ultra2_dmafinish: -+ test DFCNTRL, DIRECTION jnz ultra2_dmahalt; -+ and DFCNTRL, ~SCSIEN; -+ test DFCNTRL, SCSIEN jnz .; -+ if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) { -+ or DFCNTRL, FIFOFLUSH; - } -- } else { -- mvi DINDEX, HADDR; -- mvi SG_NEXT call bcopy_4; -+ultra2_dmafifoflush: -+ if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) { -+ /* -+ * hardware bug alert! This needless set of jumps -+ * works around a glitch in the silicon. When the -+ * PCI DMA fifo goes empty, but there is still SCSI -+ * data to be flushed into the PCI DMA fifo (and from -+ * there on into main memory), the FIFOEMP bit will -+ * come on between the time when the PCI DMA buffer -+ * went empty and the next bit of data is copied from -+ * the SCSI fifo into the PCI fifo. It should only -+ * come on when both FIFOs (meaning the entire FIFO -+ * chain) are emtpy. Since it can take up to 4 cycles -+ * for new data to be copied from the SCSI fifo into -+ * the PCI fifo, testing for FIFOEMP status for 4 -+ * extra times gives the needed time for any -+ * remaining SCSI fifo data to be put in the PCI fifo -+ * before we declare it *truly* empty. -+ */ -+ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -+ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -+ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -+ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -+ } -+ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -+ test DFSTATUS, MREQPEND jnz .; -+ultra2_dmahalt: -+ and DFCNTRL, ~(HDMAEN|SCSIEN); -+ test DFCNTRL, (HDMAEN|SCSIEN) jnz .; -+ ret; - -- mvi HCNT[0],SG_SIZEOF; -- clr HCNT[1]; -- clr HCNT[2]; -+u2_data_phase_overrun: -+/* -+ * Wait for the target to quit transferring data on the SCSI bus -+ */ -+ test SSTAT1, PHASEMIS jz .; -+ call ultra2_dmafinish; -+/* -+ * Turn off BITBUCKET mode and notify the host -+ */ -+ and SXFRCTL1, ~BITBUCKET; -+ mvi INTSTAT,DATA_OVERRUN; -+ jmp ITloop; -+ -+ -+ -+ } else { /* NOT Ultra2 */ - -- or DFCNTRL, HDMAEN|DIRECTION|FIFORESET; - -- call dma_finish; - -+data_phase_reinit: -+/* -+ * If we re-enter the data phase after going through another phase, the -+ * STCNT may have been cleared, so restore it from the residual field. -+ */ -+ if ((p->features & AHC_CMD_CHAN) != 0) { -+ bmov STCNT, SCB_RESID_DCNT, 3; -+ } else { -+ mvi DINDEX, STCNT; -+ mvi SCB_RESID_DCNT call bcopy_3; -+ } -+ jmp data_phase_loop; -+p_data: -+ mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET; -+ test LASTPHASE, IOI jnz . + 2; -+ or DMAPARAMS, DIRECTION; -+ call assert; /* -+ * Ensure entering a data -+ * phase is okay - seen identify, etc. -+ */ -+ if ((p->features & AHC_CMD_CHAN) != 0) { -+ mvi CCSGADDR, CCSGADDR_MAX; -+ } -+ test SEQ_FLAGS, DPHASE jnz data_phase_reinit; -+ or SEQ_FLAGS, DPHASE; /* we've seen a data phase */ - /* -- * Copy data from FIFO into SCB data pointer and data count. -- * This assumes that the SG segments are of the form: -- * struct ahc_dma_seg { -- * u_int32_t addr; four bytes, little-endian order -- * u_int32_t len; four bytes, little endian order -- * }; -+ * Initialize the DMA address and counter from the SCB. -+ * Also set SG_COUNT and SG_NEXT in memory since we cannot -+ * modify the values in the SCB itself until we see a -+ * save data pointers message. - */ -- mvi HADDR call dfdat_in_7; -- call set_stcnt_from_hcnt; -- } -+ if ((p->features & AHC_CMD_CHAN) != 0) { -+ bmov HADDR, SCB_DATAPTR, 7; -+ bmov STCNT, HCNT, 3; -+ bmov SG_COUNT, SCB_SGCOUNT, 5; -+ } else { -+ mvi DINDEX, HADDR; -+ mvi SCB_DATAPTR call bcopy_7; -+ call set_stcnt_from_hcnt; -+ mvi DINDEX, SG_COUNT; -+ mvi SCB_SGCOUNT call bcopy_5; -+ } -+data_phase_loop: -+ /* Guard against overruns */ -+ test SG_COUNT, 0xff jnz data_phase_inbounds; -+/* -+ * Turn on 'Bit Bucket' mode, set the transfer count to -+ * 16meg and let the target run until it changes phase. -+ * When the transfer completes, notify the host that we -+ * had an overrun. -+ */ -+ or SXFRCTL1,BITBUCKET; -+ and DMAPARAMS, ~(HDMAEN|SDMAEN); -+ if ((p->features & AHC_CMD_CHAN) != 0) { -+ bmov STCNT, ALLONES, 3; -+ } else { -+ mvi STCNT[0], 0xFF; -+ mvi STCNT[1], 0xFF; -+ mvi STCNT[2], 0xFF; -+ } - --/* Advance the SG pointer */ -- clr A; /* add sizeof(struct scatter) */ -- add SG_NEXT[0],SG_SIZEOF; -- adc SG_NEXT[1],A; -+data_phase_inbounds: -+/* If we are the last SG block, tell the hardware. */ -+ cmp SG_COUNT,0x01 jne data_phase_wideodd; -+ and DMAPARAMS, ~WIDEODD; -+data_phase_wideodd: -+ mov DMAPARAMS call dma; -+data_phase_dma_done: -+/* Go tell the host about any overruns */ -+ test SXFRCTL1,BITBUCKET jnz data_phase_overrun; -+ -+/* Exit if we had an underrun. dma clears SINDEX in this case. */ -+ test SINDEX,0xff jz data_phase_finish; -+/* -+ * Advance the scatter-gather pointers if needed -+ */ -+sg_advance: -+ cmp SG_COUNT, 0x01 je data_phase_finish; /* Are we done? */ -+ dec SG_COUNT; /* one less segment to go */ -+/* -+ * Load a struct scatter and set up the data address and length. -+ * If the working value of the SG count is nonzero, then -+ * we need to load a new set of values. -+ * -+ * This, like all DMA's, assumes little-endian host data storage. -+ */ -+sg_load: -+ if ((p->features & AHC_CMD_CHAN) != 0) { -+ /* -+ * Do we have any prefetch left??? -+ */ -+ cmp CCSGADDR, CCSGADDR_MAX jne prefetch_avail; -+ -+ /* -+ * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes. -+ */ -+ add A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT; -+ mvi A, CCSGADDR_MAX; -+ jc . + 2; -+ shl A, 3, SG_COUNT; -+ mov CCHCNT, A; -+ bmov CCHADDR, SG_NEXT, 4; -+ mvi CCSGCTL, CCSGEN|CCSGRESET; -+ test CCSGCTL, CCSGDONE jz .; -+ and CCSGCTL, ~CCSGEN; -+ test CCSGCTL, CCSGEN jnz .; -+ mvi CCSGCTL, CCSGRESET; -+prefetch_avail: -+ bmov HADDR, CCSGRAM, 8; -+ bmov STCNT, HCNT, 3; -+ } else { -+ mvi DINDEX, HADDR; -+ mvi SG_NEXT call bcopy_4; - -- test SSTAT1, REQINIT jz .; -- test SSTAT1,PHASEMIS jz data_phase_loop; -+ mvi HCNT[0],SG_SIZEOF; -+ clr HCNT[1]; -+ clr HCNT[2]; - --/* This drops the last SG segment down to the shadow layer for us */ -- if ((p->features & AHC_ULTRA2) != 0) { -- mov DFCNTRL, DMAPARAMS; -- test SSTAT0, SDONE jnz .; -- } -+ or DFCNTRL, HDMAEN|DIRECTION|FIFORESET; -+ -+ call dma_finish; -+ -+/* -+ * Copy data from FIFO into SCB data pointer and data count. -+ * This assumes that the SG segments are of the form: -+ * struct ahc_dma_seg { -+ * u_int32_t addr; four bytes, little-endian order -+ * u_int32_t len; four bytes, little endian order -+ * }; -+ */ -+ mvi HADDR call dfdat_in_7; -+ call set_stcnt_from_hcnt; -+ } -+/* Advance the SG pointer */ -+ clr A; /* add sizeof(struct scatter) */ -+ add SG_NEXT[0],SG_SIZEOF; -+ adc SG_NEXT[1],A; -+ -+ test SSTAT1, REQINIT jz .; -+ test SSTAT1,PHASEMIS jz data_phase_loop; - - data_phase_finish: - /* -@@ -523,10 +682,7 @@ - * We use STCNT instead of HCNT, since it's a reflection of how many bytes - * were transferred on the SCSI (as opposed to the host) bus. - */ -- if ((p->features & AHC_ULTRA2) != 0) { -- call ultra2_dmafinish; -- } -- if ((p->features & AHC_ULTRA2) == 0) { -+ clr SG_COUNT; - if ((p->features & AHC_CMD_CHAN) != 0) { - bmov SCB_RESID_DCNT, STCNT, 3; - mov SCB_RESID_SGCNT, SG_COUNT; -@@ -536,52 +692,19 @@ - mov SCB_RESID_DCNT[2],STCNT[2]; - mov SCB_RESID_SGCNT, SG_COUNT; - } -- } - -- jmp ITloop; -+ jmp ITloop; - - data_phase_overrun: -- if ((p->features & AHC_ULTRA2) != 0) { -- call ultra2_dmafinish; -- } - /* - * Turn off BITBUCKET mode and notify the host - */ -- and SXFRCTL1, ~BITBUCKET; -- mvi INTSTAT,DATA_OVERRUN; -- jmp ITloop; -+ and SXFRCTL1, ~BITBUCKET; -+ mvi INTSTAT,DATA_OVERRUN; -+ jmp ITloop; -+ -+ - --ultra2_dmafinish: -- if ((p->features & AHC_ULTRA2) != 0) { -- test DFCNTRL, DIRECTION jnz ultra2_dmahalt; -- and DFCNTRL, ~SCSIEN; -- test DFCNTRL, SCSIEN jnz .; --ultra2_dmafifoflush: -- or DFCNTRL, FIFOFLUSH; -- test DFSTATUS, FIFOEMP jz . - 1; -- /* -- * hardware bug alert! This needless set of jumps is to -- * protect against a FIFOEMP status bit glitch in the -- * silicon. -- */ -- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush; -- test DFSTATUS, MREQPEND jnz .; --ultra2_dmahalt: -- test SCSIOFFSET, 0x7f jnz ultra2_shutdown; --ultra2_await_nreq: -- test SCSISIGI, REQI jz ultra2_shutdown; -- test SSTAT1, (PHASEMIS|REQINIT) 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; -- ret; - } - - /* -@@ -1021,6 +1144,7 @@ - inb_last: - mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/ - -+ - mesgin_phasemis: - /* - * We expected to receive another byte, but the target changed phase -@@ -1080,7 +1204,9 @@ - * to drain the data fifo until there is space for the input - * latch to drain and HDMAEN de-asserts. - */ -- mov NONE, DFDAT; -+ if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) { -+ mov NONE, DFDAT; -+ } - test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt; - } - return: -@@ -1306,11 +1432,17 @@ - cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .; - jmp dma_scb_finish; - dma_scb_tohost: -- if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { -+ if ((p->features & AHC_ULTRA2) == 0) { - mvi CCSCBCTL, CCSCBRESET; - bmov CCSCBRAM, SCB_CONTROL, 32; - or CCSCBCTL, CCSCBEN|CCSCBRESET; - test CCSCBCTL, CCSCBDONE jz .; -+ } else if ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0) { -+ mvi CCSCBCTL, CCARREN|CCSCBRESET; -+ cmp CCSCBCTL, ARRDONE|CCARREN jne .; -+ mvi CCHCNT, 32; -+ mvi CCSCBCTL, CCSCBEN|CCSCBRESET; -+ cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .; - } else { - mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET; - cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .; -@@ -1342,17 +1474,81 @@ - mov DFDAT,SINDIR; - cmp SINDEX, A jne copy_scb_tofifo_loop; - or DFCNTRL, HDMAEN|FIFOFLUSH; -+ jmp dma_finish; - dma_scb_fromhost: -- call dma_finish; -- /* If we were putting the SCB, we are done */ -- test DMAPARAMS, DIRECTION jz return; -- mvi SCB_CONTROL call dfdat_in_7; -- call dfdat_in_7_continued; -- call dfdat_in_7_continued; -- jmp dfdat_in_7_continued; -+ mvi DINDEX, SCB_CONTROL; -+ if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) { -+ /* -+ * Set the A to -24. It it hits 0, then we let -+ * our code fall through to dfdat_in_8 to complete -+ * the last of the copy. -+ * -+ * Also, things happen 8 bytes at a time in this -+ * case, so we may need to drain the fifo at most -+ * 3 times to keep things flowing -+ */ -+ mvi A, -24; -+dma_scb_hang_fifo: -+ /* Wait for the first bit of data to hit the fifo */ -+ test DFSTATUS, FIFOEMP jnz .; -+dma_scb_hang_wait: -+ /* OK, now they've started to transfer into the fifo, -+ * so wait for them to stop trying to transfer any -+ * more data. -+ */ -+ test DFSTATUS, MREQPEND jnz .; -+ /* -+ * OK, they started, then they stopped, now see if they -+ * managed to complete the job before stopping. Try -+ * it multiple times to give the chip a few cycles to -+ * set the flag if it did complete. -+ */ -+ test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; -+ test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; -+ test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; -+ /* -+ * Too bad, the chip didn't complete the DMA, but there -+ * aren't any more memory requests pending, so that -+ * means it stopped part way through and hung. That's -+ * our bug, so now we drain what data there is in the -+ * fifo in order to get things going again. -+ */ -+dma_scb_hang_empty_fifo: -+ call dfdat_in_8; -+ add A, 8; -+ add SINDEX, A, HCNT; -+ /* -+ * If there are another 8 bytes of data waiting in the -+ * fifo, then the carry bit will be set as a result -+ * of the above add command (unless A is non-negative, -+ * in which case the carry bit won't be set). -+ */ -+ jc dma_scb_hang_empty_fifo; -+ /* -+ * We've emptied the fifo now, but we wouldn't have got -+ * here if the memory transfer hadn't stopped part way -+ * through, so go back up to the beginning of the -+ * loop and start over. When it succeeds in getting -+ * all the data down, HDONE will be set and we'll -+ * jump to the code just below here. -+ */ -+ jmp dma_scb_hang_fifo; -+dma_scb_hang_dma_done: -+ and DFCNTRL, ~HDMAEN; -+ test DFCNTRL, HDMAEN jnz .; -+ call dfdat_in_8; -+ add A, 8; -+ cmp A, 8 jne . - 2; -+ ret; -+ } else { -+ call dma_finish; -+ call dfdat_in_8; -+ call dfdat_in_8; -+ call dfdat_in_8; -+ } -+dfdat_in_8: -+ mov DINDIR,DFDAT; - dfdat_in_7: -- mov DINDEX,SINDEX; --dfdat_in_7_continued: - mov DINDIR,DFDAT; - mov DINDIR,DFDAT; - mov DINDIR,DFDAT; -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_proc.c linux/drivers/scsi/aic7xxx/aic7xxx_proc.c ---- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_proc.c Wed Dec 31 19:00:00 1969 -+++ linux/drivers/scsi/aic7xxx/aic7xxx_proc.c Tue Feb 6 03:49:36 2001 -@@ -0,0 +1,414 @@ -+/*+M************************************************************************* -+ * Adaptec AIC7xxx device driver proc support for Linux. -+ * -+ * Copyright (c) 1995, 1996 Dean W. Gehnert -+ * -+ * 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, or (at your option) -+ * any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; see the file COPYING. If not, write to -+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * ---------------------------------------------------------------- -+ * o Modified from the EATA-DMA /proc support. -+ * o Additional support for device block statistics provided by -+ * Matthew Jacob. -+ * o Correction of overflow by Heinz Mauelshagen -+ * o Adittional corrections by Doug Ledford -+ * -+ * Dean W. Gehnert, deang@teleport.com, 05/01/96 -+ * -+ * $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $ -+ *-M*************************************************************************/ -+ -+#include -+ -+#define BLS (&aic7xxx_buffer[size]) -+#define HDRB \ -+" < 2K 2K+ 4K+ 8K+ 16K+ 32K+ 64K+ 128K+" -+ -+#ifdef PROC_DEBUG -+extern int vsprintf(char *, const char *, va_list); -+ -+static void -+proc_debug(const char *fmt, ...) -+{ -+ va_list ap; -+ char buf[256]; -+ -+ va_start(ap, fmt); -+ vsprintf(buf, fmt, ap); -+ printk(buf); -+ va_end(ap); -+} -+#else /* PROC_DEBUG */ -+# define proc_debug(fmt, args...) -+#endif /* PROC_DEBUG */ -+ -+static int aic7xxx_buffer_size = 0; -+static char *aic7xxx_buffer = NULL; -+ -+ -+/*+F************************************************************************* -+ * Function: -+ * aic7xxx_set_info -+ * -+ * Description: -+ * Set parameters for the driver from the /proc filesystem. -+ *-F*************************************************************************/ -+int -+aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) -+{ -+ proc_debug("aic7xxx_set_info(): %s\n", buffer); -+ return (-ENOSYS); /* Currently this is a no-op */ -+} -+ -+ -+/*+F************************************************************************* -+ * Function: -+ * aic7xxx_proc_info -+ * -+ * Description: -+ * Return information to handle /proc support for the driver. -+ *-F*************************************************************************/ -+int -+aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length, -+ int hostno, int inout) -+{ -+ struct Scsi_Host *HBAptr; -+ struct aic7xxx_host *p; -+ int size = 0; -+ unsigned char i; -+ struct aic7xxx_xferstats *sp; -+ unsigned char target; -+ -+ HBAptr = NULL; -+ -+ for(p=first_aic7xxx; p->host->host_no != hostno; p=p->next) -+ ; -+ -+ if (!p) -+ { -+ size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno); -+ if (size > length) -+ { -+ return (size); -+ } -+ else -+ { -+ return (length); -+ } -+ } -+ -+ HBAptr = p->host; -+ -+ if (inout == TRUE) /* Has data been written to the file? */ -+ { -+ return (aic7xxx_set_info(buffer, length, HBAptr)); -+ } -+ -+ p = (struct aic7xxx_host *) HBAptr->hostdata; -+ -+ /* -+ * It takes roughly 1K of space to hold all relevant card info, not -+ * counting any proc stats, so we start out with a 1.5k buffer size and -+ * if proc_stats is defined, then we sweep the stats structure to see -+ * how many drives we will be printing out for and add 384 bytes per -+ * device with active stats. -+ * -+ * Hmmmm...that 1.5k seems to keep growing as items get added so they -+ * can be easily viewed for debugging purposes. So, we bumped that -+ * 1.5k to 4k so we can quit having to bump it all the time. -+ */ -+ -+ size = 4096; -+ for (target = 0; target < MAX_TARGETS; target++) -+ { -+ if (p->dev_flags[target] & DEVICE_PRESENT) -+#ifdef AIC7XXX_PROC_STATS -+ size += 512; -+#else -+ size += 256; -+#endif -+ } -+ if (aic7xxx_buffer_size != size) -+ { -+ if (aic7xxx_buffer != NULL) -+ { -+ kfree(aic7xxx_buffer); -+ aic7xxx_buffer_size = 0; -+ } -+ aic7xxx_buffer = kmalloc(size, GFP_KERNEL); -+ } -+ if (aic7xxx_buffer == NULL) -+ { -+ size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n", -+ __LINE__); -+ return size; -+ } -+ aic7xxx_buffer_size = size; -+ -+ size = 0; -+ size += sprintf(BLS, "Adaptec AIC7xxx driver version: "); -+ size += sprintf(BLS, "%s/", AIC7XXX_C_VERSION); -+ size += sprintf(BLS, "%s", AIC7XXX_H_VERSION); -+ size += sprintf(BLS, "\n"); -+ size += sprintf(BLS, "Compile Options:\n"); -+#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT -+ size += sprintf(BLS, " TCQ Enabled By Default : Enabled\n"); -+#else -+ size += sprintf(BLS, " TCQ Enabled By Default : Disabled\n"); -+#endif -+#ifdef AIC7XXX_PROC_STATS -+ size += sprintf(BLS, " AIC7XXX_PROC_STATS : Enabled\n"); -+#else -+ size += sprintf(BLS, " AIC7XXX_PROC_STATS : Disabled\n"); -+#endif -+ size += sprintf(BLS, " AIC7XXX_RESET_DELAY : %d\n", AIC7XXX_RESET_DELAY); -+ size += sprintf(BLS, "\n"); -+ size += sprintf(BLS, "Adapter Configuration:\n"); -+ size += sprintf(BLS, " SCSI Adapter: %s\n", -+ board_names[p->board_name_index]); -+ if (p->flags & AHC_TWIN) -+ size += sprintf(BLS, " Twin Channel Controller "); -+ else -+ { -+ char *channel = ""; -+ char *ultra = ""; -+ char *wide = "Narrow "; -+ if (p->flags & AHC_MULTI_CHANNEL) -+ { -+ channel = " Channel A"; -+ if (p->flags & (AHC_CHNLB|AHC_CHNLC)) -+ channel = (p->flags & AHC_CHNLB) ? " Channel B" : " Channel C"; -+ } -+ if (p->features & AHC_WIDE) -+ wide = "Wide "; -+ if (p->features & AHC_ULTRA3) -+ { -+ switch(p->chip & AHC_CHIPID_MASK) -+ { -+ case AHC_AIC7892: -+ case AHC_AIC7899: -+ ultra = "Ultra-160/m LVD/SE "; -+ break; -+ default: -+ ultra = "Ultra-3 LVD/SE "; -+ break; -+ } -+ } -+ else if (p->features & AHC_ULTRA2) -+ ultra = "Ultra-2 LVD/SE "; -+ else if (p->features & AHC_ULTRA) -+ ultra = "Ultra "; -+ size += sprintf(BLS, " %s%sController%s ", -+ ultra, wide, channel); -+ } -+ switch(p->chip & ~AHC_CHIPID_MASK) -+ { -+ case AHC_VL: -+ size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn); -+ break; -+ case AHC_EISA: -+ size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn); -+ break; -+ default: -+ size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus, -+ PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn)); -+ break; -+ } -+ if( !(p->maddr) ) -+ { -+ size += sprintf(BLS, " Programmed I/O Base: %lx\n", p->base); -+ } -+ else -+ { -+ size += sprintf(BLS, " PCI MMAPed I/O Base: 0x%lx\n", p->mbase); -+ } -+ if( (p->chip & (AHC_VL | AHC_EISA)) ) -+ { -+ size += sprintf(BLS, " BIOS Memory Address: 0x%08x\n", p->bios_address); -+ } -+ size += sprintf(BLS, " Adapter SEEPROM Config: %s\n", -+ (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." : -+ ((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." : -+ "SEEPROM not found, using leftover BIOS values.") ); -+ size += sprintf(BLS, " Adaptec SCSI BIOS: %s\n", -+ (p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled"); -+ size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); -+ size += sprintf(BLS, " SCBs: Active %d, Max Active %d,\n", -+ p->activescbs, p->max_activescbs); -+ size += sprintf(BLS, " Allocated %d, HW %d, " -+ "Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs, -+ p->scb_data->maxscbs); -+ if (p->flags & AHC_EXTERNAL_SRAM) -+ size += sprintf(BLS, " Using External SCB SRAM\n"); -+ size += sprintf(BLS, " Interrupts: %ld", p->isr_count); -+ if (p->chip & AHC_EISA) -+ { -+ size += sprintf(BLS, " %s\n", -+ (p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)"); -+ } -+ else -+ { -+ size += sprintf(BLS, "\n"); -+ } -+ size += sprintf(BLS, " BIOS Control Word: 0x%04x\n", -+ p->bios_control); -+ size += sprintf(BLS, " Adapter Control Word: 0x%04x\n", -+ p->adapter_control); -+ size += sprintf(BLS, " Extended Translation: %sabled\n", -+ (p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis"); -+ size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable); -+ if (p->features & (AHC_ULTRA | AHC_ULTRA2)) -+ { -+ size += sprintf(BLS, " Ultra Enable Flags: 0x%04x\n", p->ultraenb); -+ } -+ size += sprintf(BLS, " Tag Queue Enable Flags: 0x%04x\n", p->tagenable); -+ size += sprintf(BLS, "Ordered Queue Tag Flags: 0x%04x\n", p->orderedtag); -+ size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_DEVICE); -+ size += sprintf(BLS, " Tagged Queue By Device array for aic7xxx host " -+ "instance %d:\n", p->instance); -+ size += sprintf(BLS, " {"); -+ for(i=0; i < (MAX_TARGETS - 1); i++) -+ size += sprintf(BLS, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]); -+ size += sprintf(BLS, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]); -+ size += sprintf(BLS, " Actual queue depth per device for aic7xxx host " -+ "instance %d:\n", p->instance); -+ size += sprintf(BLS, " {"); -+ for(i=0; i < (MAX_TARGETS - 1); i++) -+ size += sprintf(BLS, "%d,", p->dev_max_queue_depth[i]); -+ size += sprintf(BLS, "%d}\n", p->dev_max_queue_depth[i]); -+ -+ size += sprintf(BLS, "\n"); -+ size += sprintf(BLS, "Statistics:\n\n"); -+ for (target = 0; target < MAX_TARGETS; target++) -+ { -+ sp = &p->stats[target]; -+ if ((p->dev_flags[target] & DEVICE_PRESENT) == 0) -+ { -+ continue; -+ } -+ if (p->features & AHC_TWIN) -+ { -+ size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n", -+ p->host_no, (target >> 3), (target & 0x7), 0); -+ } -+ else -+ { -+ size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n", -+ p->host_no, 0, target, 0); -+ } -+ size += sprintf(BLS, " Device using %s/%s", -+ (p->transinfo[target].cur_width == MSG_EXT_WDTR_BUS_16_BIT) ? -+ "Wide" : "Narrow", -+ (p->transinfo[target].cur_offset != 0) ? -+ "Sync transfers at " : "Async transfers.\n" ); -+ if (p->transinfo[target].cur_offset != 0) -+ { -+ struct aic7xxx_syncrate *sync_rate; -+ unsigned char options = p->transinfo[target].cur_options; -+ int period = p->transinfo[target].cur_period; -+ int rate = (p->transinfo[target].cur_width == -+ MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0; -+ -+ sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options); -+ if (sync_rate != NULL) -+ { -+ size += sprintf(BLS, "%s MByte/sec, offset %d\n", -+ sync_rate->rate[rate], -+ p->transinfo[target].cur_offset ); -+ } -+ else -+ { -+ size += sprintf(BLS, "3.3 MByte/sec, offset %d\n", -+ p->transinfo[target].cur_offset ); -+ } -+ } -+ size += sprintf(BLS, " Transinfo settings: "); -+ size += sprintf(BLS, "current(%d/%d/%d/%d), ", -+ p->transinfo[target].cur_period, -+ p->transinfo[target].cur_offset, -+ p->transinfo[target].cur_width, -+ p->transinfo[target].cur_options); -+ size += sprintf(BLS, "goal(%d/%d/%d/%d), ", -+ p->transinfo[target].goal_period, -+ p->transinfo[target].goal_offset, -+ p->transinfo[target].goal_width, -+ p->transinfo[target].goal_options); -+ size += sprintf(BLS, "user(%d/%d/%d/%d)\n", -+ p->transinfo[target].user_period, -+ p->transinfo[target].user_offset, -+ p->transinfo[target].user_width, -+ p->transinfo[target].user_options); -+#ifdef AIC7XXX_PROC_STATS -+ size += sprintf(BLS, " Total transfers %ld (%ld reads and %ld writes)\n", -+ sp->r_total + sp->w_total, sp->r_total, sp->w_total); -+ size += sprintf(BLS, "%s\n", HDRB); -+ size += sprintf(BLS, " Reads:"); -+ for (i = 0; i < NUMBER(sp->r_bins); i++) -+ { -+ size += sprintf(BLS, " %7ld", sp->r_bins[i]); -+ } -+ size += sprintf(BLS, "\n"); -+ size += sprintf(BLS, " Writes:"); -+ for (i = 0; i < NUMBER(sp->w_bins); i++) -+ { -+ size += sprintf(BLS, " %7ld", sp->w_bins[i]); -+ } -+ size += sprintf(BLS, "\n"); -+#else -+ size += sprintf(BLS, " Total transfers %ld (%ld reads and %ld writes)\n", -+ sp->r_total + sp->w_total, sp->r_total, sp->w_total); -+#endif /* AIC7XXX_PROC_STATS */ -+ size += sprintf(BLS, "\n\n"); -+ } -+ -+ if (size >= aic7xxx_buffer_size) -+ { -+ printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n"); -+ } -+ -+ if (offset > size - 1) -+ { -+ kfree(aic7xxx_buffer); -+ aic7xxx_buffer = NULL; -+ aic7xxx_buffer_size = length = 0; -+ *start = NULL; -+ } -+ else -+ { -+ *start = buffer; -+ length = MIN(length, size - offset); -+ memcpy(buffer, &aic7xxx_buffer[offset], length); -+ } -+ -+ return (length); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-indent-level: 2 -+ * c-brace-imaginary-offset: 0 -+ * c-brace-offset: -2 -+ * c-argdecl-indent: 2 -+ * c-label-offset: -2 -+ * c-continued-statement-offset: 2 -+ * c-continued-brace-offset: 0 -+ * indent-tabs-mode: nil -+ * tab-width: 8 -+ * End: -+ */ -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_reg.h linux/drivers/scsi/aic7xxx/aic7xxx_reg.h ---- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_reg.h Wed Dec 31 19:00:00 1969 -+++ linux/drivers/scsi/aic7xxx/aic7xxx_reg.h Tue Feb 6 03:49:36 2001 -@@ -0,0 +1,629 @@ -+/* -+ * DO NOT EDIT - This file is automatically generated. -+ */ -+ -+#define SCSISEQ 0x00 -+#define TEMODE 0x80 -+#define ENSELO 0x40 -+#define ENSELI 0x20 -+#define ENRSELI 0x10 -+#define ENAUTOATNO 0x08 -+#define ENAUTOATNI 0x04 -+#define ENAUTOATNP 0x02 -+#define SCSIRSTO 0x01 -+ -+#define SXFRCTL0 0x01 -+#define DFON 0x80 -+#define DFPEXP 0x40 -+#define FAST20 0x20 -+#define CLRSTCNT 0x10 -+#define SPIOEN 0x08 -+#define SCAMEN 0x04 -+#define CLRCHN 0x02 -+ -+#define SXFRCTL1 0x02 -+#define BITBUCKET 0x80 -+#define SWRAPEN 0x40 -+#define ENSPCHK 0x20 -+#define STIMESEL 0x18 -+#define ENSTIMER 0x04 -+#define ACTNEGEN 0x02 -+#define STPWEN 0x01 -+ -+#define SCSISIGO 0x03 -+#define CDO 0x80 -+#define IOO 0x40 -+#define MSGO 0x20 -+#define ATNO 0x10 -+#define SELO 0x08 -+#define BSYO 0x04 -+#define REQO 0x02 -+#define ACKO 0x01 -+ -+#define SCSISIGI 0x03 -+#define ATNI 0x10 -+#define SELI 0x08 -+#define BSYI 0x04 -+#define REQI 0x02 -+#define ACKI 0x01 -+ -+#define SCSIRATE 0x04 -+#define WIDEXFER 0x80 -+#define SXFR_ULTRA2 0x7f -+#define SXFR 0x70 -+#define SOFS 0x0f -+ -+#define SCSIID 0x05 -+#define SCSIOFFSET 0x05 -+#define SOFS_ULTRA2 0x7f -+ -+#define SCSIDATL 0x06 -+ -+#define SCSIDATH 0x07 -+ -+#define STCNT 0x08 -+ -+#define OPTIONMODE 0x08 -+#define AUTORATEEN 0x80 -+#define AUTOACKEN 0x40 -+#define ATNMGMNTEN 0x20 -+#define BUSFREEREV 0x10 -+#define EXPPHASEDIS 0x08 -+#define SCSIDATL_IMGEN 0x04 -+#define AUTO_MSGOUT_DE 0x02 -+#define DIS_MSGIN_DUALEDGE 0x01 -+ -+#define CLRSINT0 0x0b -+#define CLRSELDO 0x40 -+#define CLRSELDI 0x20 -+#define CLRSELINGO 0x10 -+#define CLRSWRAP 0x08 -+#define CLRSPIORDY 0x02 -+ -+#define SSTAT0 0x0b -+#define TARGET 0x80 -+#define SELDO 0x40 -+#define SELDI 0x20 -+#define SELINGO 0x10 -+#define IOERR 0x08 -+#define SWRAP 0x08 -+#define SDONE 0x04 -+#define SPIORDY 0x02 -+#define DMADONE 0x01 -+ -+#define CLRSINT1 0x0c -+#define CLRSELTIMEO 0x80 -+#define CLRATNO 0x40 -+#define CLRSCSIRSTI 0x20 -+#define CLRBUSFREE 0x08 -+#define CLRSCSIPERR 0x04 -+#define CLRPHASECHG 0x02 -+#define CLRREQINIT 0x01 -+ -+#define SSTAT1 0x0c -+#define SELTO 0x80 -+#define ATNTARG 0x40 -+#define SCSIRSTI 0x20 -+#define PHASEMIS 0x10 -+#define BUSFREE 0x08 -+#define SCSIPERR 0x04 -+#define PHASECHG 0x02 -+#define REQINIT 0x01 -+ -+#define SSTAT2 0x0d -+#define OVERRUN 0x80 -+#define SHVALID 0x40 -+#define WIDE_RES 0x20 -+#define SFCNT 0x1f -+#define EXP_ACTIVE 0x10 -+#define CRCVALERR 0x08 -+#define CRCENDERR 0x04 -+#define CRCREQERR 0x02 -+#define DUAL_EDGE_ERROR 0x01 -+ -+#define SSTAT3 0x0e -+#define SCSICNT 0xf0 -+#define OFFCNT 0x0f -+ -+#define SCSIID_ULTRA2 0x0f -+#define OID 0x0f -+ -+#define SIMODE0 0x10 -+#define ENSELDO 0x40 -+#define ENSELDI 0x20 -+#define ENSELINGO 0x10 -+#define ENIOERR 0x08 -+#define ENSWRAP 0x08 -+#define ENSDONE 0x04 -+#define ENSPIORDY 0x02 -+#define ENDMADONE 0x01 -+ -+#define SIMODE1 0x11 -+#define ENSELTIMO 0x80 -+#define ENATNTARG 0x40 -+#define ENSCSIRST 0x20 -+#define ENPHASEMIS 0x10 -+#define ENBUSFREE 0x08 -+#define ENSCSIPERR 0x04 -+#define ENPHASECHG 0x02 -+#define ENREQINIT 0x01 -+ -+#define SCSIBUSL 0x12 -+ -+#define SCSIBUSH 0x13 -+ -+#define SHADDR 0x14 -+ -+#define SELTIMER 0x18 -+#define STAGE6 0x20 -+#define STAGE5 0x10 -+#define STAGE4 0x08 -+#define STAGE3 0x04 -+#define STAGE2 0x02 -+#define STAGE1 0x01 -+ -+#define SELID 0x19 -+#define SELID_MASK 0xf0 -+#define ONEBIT 0x08 -+ -+#define SPIOCAP 0x1b -+#define SOFT1 0x80 -+#define SOFT0 0x40 -+#define SOFTCMDEN 0x20 -+#define HAS_BRDCTL 0x10 -+#define SEEPROM 0x08 -+#define EEPROM 0x04 -+#define ROM 0x02 -+#define SSPIOCPS 0x01 -+ -+#define BRDCTL 0x1d -+#define BRDDAT7 0x80 -+#define BRDDAT6 0x40 -+#define BRDDAT5 0x20 -+#define BRDDAT4 0x10 -+#define BRDSTB 0x10 -+#define BRDCS 0x08 -+#define BRDDAT3 0x08 -+#define BRDDAT2 0x04 -+#define BRDRW 0x04 -+#define BRDRW_ULTRA2 0x02 -+#define BRDCTL1 0x02 -+#define BRDSTB_ULTRA2 0x01 -+#define BRDCTL0 0x01 -+ -+#define SEECTL 0x1e -+#define EXTARBACK 0x80 -+#define EXTARBREQ 0x40 -+#define SEEMS 0x20 -+#define SEERDY 0x10 -+#define SEECS 0x08 -+#define SEECK 0x04 -+#define SEEDO 0x02 -+#define SEEDI 0x01 -+ -+#define SBLKCTL 0x1f -+#define DIAGLEDEN 0x80 -+#define DIAGLEDON 0x40 -+#define AUTOFLUSHDIS 0x20 -+#define ENAB40 0x08 -+#define ENAB20 0x04 -+#define SELWIDE 0x02 -+#define XCVR 0x01 -+ -+#define SRAM_BASE 0x20 -+ -+#define TARG_SCSIRATE 0x20 -+ -+#define ULTRA_ENB 0x30 -+ -+#define DISC_DSB 0x32 -+ -+#define MSG_OUT 0x34 -+ -+#define DMAPARAMS 0x35 -+#define PRELOADEN 0x80 -+#define WIDEODD 0x40 -+#define SCSIEN 0x20 -+#define SDMAENACK 0x10 -+#define SDMAEN 0x10 -+#define HDMAEN 0x08 -+#define HDMAENACK 0x08 -+#define DIRECTION 0x04 -+#define FIFOFLUSH 0x02 -+#define FIFORESET 0x01 -+ -+#define SEQ_FLAGS 0x36 -+#define IDENTIFY_SEEN 0x80 -+#define SCBPTR_VALID 0x20 -+#define DPHASE 0x10 -+#define AMTARGET 0x08 -+#define WIDE_BUS 0x02 -+#define TWIN_BUS 0x01 -+ -+#define SAVED_TCL 0x37 -+ -+#define SG_COUNT 0x38 -+ -+#define SG_NEXT 0x39 -+ -+#define LASTPHASE 0x3d -+#define P_MESGIN 0xe0 -+#define PHASE_MASK 0xe0 -+#define P_STATUS 0xc0 -+#define P_MESGOUT 0xa0 -+#define P_COMMAND 0x80 -+#define CDI 0x80 -+#define IOI 0x40 -+#define P_DATAIN 0x40 -+#define MSGI 0x20 -+#define P_BUSFREE 0x01 -+#define P_DATAOUT 0x00 -+ -+#define WAITING_SCBH 0x3e -+ -+#define DISCONNECTED_SCBH 0x3f -+ -+#define FREE_SCBH 0x40 -+ -+#define HSCB_ADDR 0x41 -+ -+#define SCBID_ADDR 0x45 -+ -+#define TMODE_CMDADDR 0x49 -+ -+#define KERNEL_QINPOS 0x4d -+ -+#define QINPOS 0x4e -+ -+#define QOUTPOS 0x4f -+ -+#define TMODE_CMDADDR_NEXT 0x50 -+ -+#define ARG_1 0x51 -+#define RETURN_1 0x51 -+#define SEND_MSG 0x80 -+#define SEND_SENSE 0x40 -+#define SEND_REJ 0x20 -+#define MSGOUT_PHASEMIS 0x10 -+ -+#define ARG_2 0x52 -+#define RETURN_2 0x52 -+ -+#define LAST_MSG 0x53 -+ -+#define PREFETCH_CNT 0x54 -+ -+#define SCSICONF 0x5a -+#define TERM_ENB 0x80 -+#define RESET_SCSI 0x40 -+#define HWSCSIID 0x0f -+#define HSCSIID 0x07 -+ -+#define HOSTCONF 0x5d -+ -+#define HA_274_BIOSCTRL 0x5f -+#define BIOSMODE 0x30 -+#define BIOSDISABLED 0x30 -+#define CHANNEL_B_PRIMARY 0x08 -+ -+#define SEQCTL 0x60 -+#define PERRORDIS 0x80 -+#define PAUSEDIS 0x40 -+#define FAILDIS 0x20 -+#define FASTMODE 0x10 -+#define BRKADRINTEN 0x08 -+#define STEP 0x04 -+#define SEQRESET 0x02 -+#define LOADRAM 0x01 -+ -+#define SEQRAM 0x61 -+ -+#define SEQADDR0 0x62 -+ -+#define SEQADDR1 0x63 -+#define SEQADDR1_MASK 0x01 -+ -+#define ACCUM 0x64 -+ -+#define SINDEX 0x65 -+ -+#define DINDEX 0x66 -+ -+#define ALLONES 0x69 -+ -+#define ALLZEROS 0x6a -+ -+#define NONE 0x6a -+ -+#define FLAGS 0x6b -+#define ZERO 0x02 -+#define CARRY 0x01 -+ -+#define SINDIR 0x6c -+ -+#define DINDIR 0x6d -+ -+#define FUNCTION1 0x6e -+ -+#define STACK 0x6f -+ -+#define TARG_OFFSET 0x70 -+ -+#define BCTL 0x84 -+#define ACE 0x08 -+#define ENABLE 0x01 -+ -+#define DSCOMMAND0 0x84 -+#define INTSCBRAMSEL 0x08 -+#define RAMPS 0x04 -+#define USCBSIZE32 0x02 -+#define CIOPARCKEN 0x01 -+ -+#define DSCOMMAND 0x84 -+#define CACHETHEN 0x80 -+#define DPARCKEN 0x40 -+#define MPARCKEN 0x20 -+#define EXTREQLCK 0x10 -+ -+#define BUSTIME 0x85 -+#define BOFF 0xf0 -+#define BON 0x0f -+ -+#define BUSSPD 0x86 -+#define DFTHRSH 0xc0 -+#define STBOFF 0x38 -+#define STBON 0x07 -+ -+#define DSPCISTATUS 0x86 -+#define DFTHRSH_100 0xc0 -+ -+#define HCNTRL 0x87 -+#define POWRDN 0x40 -+#define SWINT 0x10 -+#define IRQMS 0x08 -+#define PAUSE 0x04 -+#define INTEN 0x02 -+#define CHIPRST 0x01 -+#define CHIPRSTACK 0x01 -+ -+#define HADDR 0x88 -+ -+#define HCNT 0x8c -+ -+#define SCBPTR 0x90 -+ -+#define INTSTAT 0x91 -+#define SEQINT_MASK 0xf1 -+#define DATA_OVERRUN 0xe1 -+#define MSGIN_PHASEMIS 0xd1 -+#define TRACEPOINT2 0xc1 -+#define SEQ_SG_FIXUP 0xb1 -+#define AWAITING_MSG 0xa1 -+#define RESIDUAL 0x81 -+#define BAD_STATUS 0x71 -+#define REJECT_MSG 0x61 -+#define WIDE_RESIDUE 0x51 -+#define EXTENDED_MSG 0x41 -+#define NO_MATCH 0x31 -+#define NO_IDENT 0x21 -+#define SEND_REJECT 0x11 -+#define INT_PEND 0x0f -+#define BRKADRINT 0x08 -+#define SCSIINT 0x04 -+#define CMDCMPLT 0x02 -+#define BAD_PHASE 0x01 -+#define SEQINT 0x01 -+ -+#define CLRINT 0x92 -+#define CLRPARERR 0x10 -+#define CLRBRKADRINT 0x08 -+#define CLRSCSIINT 0x04 -+#define CLRCMDINT 0x02 -+#define CLRSEQINT 0x01 -+ -+#define ERROR 0x92 -+#define CIOPARERR 0x80 -+#define PCIERRSTAT 0x40 -+#define MPARERR 0x20 -+#define DPARERR 0x10 -+#define SQPARERR 0x08 -+#define ILLOPCODE 0x04 -+#define DSCTMOUT 0x02 -+#define ILLSADDR 0x02 -+#define ILLHADDR 0x01 -+ -+#define DFCNTRL 0x93 -+ -+#define DFSTATUS 0x94 -+#define PRELOAD_AVAIL 0x80 -+#define DWORDEMP 0x20 -+#define MREQPEND 0x10 -+#define HDONE 0x08 -+#define DFTHRESH 0x04 -+#define FIFOFULL 0x02 -+#define FIFOEMP 0x01 -+ -+#define DFDAT 0x99 -+ -+#define SCBCNT 0x9a -+#define SCBAUTO 0x80 -+#define SCBCNT_MASK 0x1f -+ -+#define QINFIFO 0x9b -+ -+#define QINCNT 0x9c -+ -+#define SCSIDATL_IMG 0x9c -+ -+#define QOUTFIFO 0x9d -+ -+#define CRCCONTROL1 0x9d -+#define CRCONSEEN 0x80 -+#define CRCVALCHKEN 0x40 -+#define CRCENDCHKEN 0x20 -+#define CRCREQCHKEN 0x10 -+#define TARGCRCENDEN 0x08 -+#define TARGCRCCNTEN 0x04 -+ -+#define SCSIPHASE 0x9e -+#define SP_STATUS 0x20 -+#define SP_COMMAND 0x10 -+#define SP_MSG_IN 0x08 -+#define SP_MSG_OUT 0x04 -+#define SP_DATA_IN 0x02 -+#define SP_DATA_OUT 0x01 -+ -+#define QOUTCNT 0x9e -+ -+#define SFUNCT 0x9f -+#define ALT_MODE 0x80 -+ -+#define SCB_CONTROL 0xa0 -+#define MK_MESSAGE 0x80 -+#define DISCENB 0x40 -+#define TAG_ENB 0x20 -+#define DISCONNECTED 0x04 -+#define SCB_TAG_TYPE 0x03 -+ -+#define SCB_BASE 0xa0 -+ -+#define SCB_TCL 0xa1 -+#define TID 0xf0 -+#define SELBUSB 0x08 -+#define LID 0x07 -+ -+#define SCB_TARGET_STATUS 0xa2 -+ -+#define SCB_SGCOUNT 0xa3 -+ -+#define SCB_SGPTR 0xa4 -+ -+#define SCB_RESID_SGCNT 0xa8 -+ -+#define SCB_RESID_DCNT 0xa9 -+ -+#define SCB_DATAPTR 0xac -+ -+#define SCB_DATACNT 0xb0 -+ -+#define SCB_CMDPTR 0xb4 -+ -+#define SCB_CMDLEN 0xb8 -+ -+#define SCB_TAG 0xb9 -+ -+#define SCB_NEXT 0xba -+ -+#define SCB_PREV 0xbb -+ -+#define SCB_BUSYTARGETS 0xbc -+ -+#define SEECTL_2840 0xc0 -+#define CS_2840 0x04 -+#define CK_2840 0x02 -+#define DO_2840 0x01 -+ -+#define STATUS_2840 0xc1 -+#define EEPROM_TF 0x80 -+#define BIOS_SEL 0x60 -+#define ADSEL 0x1e -+#define DI_2840 0x01 -+ -+#define CCHADDR 0xe0 -+ -+#define CCHCNT 0xe8 -+ -+#define CCSGRAM 0xe9 -+ -+#define CCSGADDR 0xea -+ -+#define CCSGCTL 0xeb -+#define CCSGDONE 0x80 -+#define CCSGEN 0x08 -+#define FLAG 0x02 -+#define CCSGRESET 0x01 -+ -+#define CCSCBRAM 0xec -+ -+#define CCSCBADDR 0xed -+ -+#define CCSCBCTL 0xee -+#define CCSCBDONE 0x80 -+#define ARRDONE 0x40 -+#define CCARREN 0x10 -+#define CCSCBEN 0x08 -+#define CCSCBDIR 0x04 -+#define CCSCBRESET 0x01 -+ -+#define CCSCBCNT 0xef -+ -+#define CCSCBPTR 0xf1 -+ -+#define HNSCB_QOFF 0xf4 -+ -+#define HESCB_QOFF 0xf5 -+ -+#define SNSCB_QOFF 0xf6 -+ -+#define SESCB_QOFF 0xf7 -+ -+#define SDSCB_QOFF 0xf8 -+ -+#define QOFF_CTLSTA 0xfa -+#define ESTABLISH_SCB_AVAIL 0x80 -+#define SCB_AVAIL 0x40 -+#define SNSCB_ROLLOVER 0x20 -+#define SDSCB_ROLLOVER 0x10 -+#define SESCB_ROLLOVER 0x08 -+#define SCB_QSIZE 0x07 -+#define SCB_QSIZE_256 0x06 -+ -+#define DFF_THRSH 0xfb -+#define WR_DFTHRSH 0x70 -+#define WR_DFTHRSH_MAX 0x70 -+#define WR_DFTHRSH_90 0x60 -+#define WR_DFTHRSH_85 0x50 -+#define WR_DFTHRSH_75 0x40 -+#define WR_DFTHRSH_63 0x30 -+#define WR_DFTHRSH_50 0x20 -+#define WR_DFTHRSH_25 0x10 -+#define RD_DFTHRSH_MAX 0x07 -+#define RD_DFTHRSH 0x07 -+#define RD_DFTHRSH_90 0x06 -+#define RD_DFTHRSH_85 0x05 -+#define RD_DFTHRSH_75 0x04 -+#define RD_DFTHRSH_63 0x03 -+#define RD_DFTHRSH_50 0x02 -+#define RD_DFTHRSH_25 0x01 -+#define WR_DFTHRSH_MIN 0x00 -+#define RD_DFTHRSH_MIN 0x00 -+ -+#define SG_CACHEPTR 0xfc -+#define SG_USER_DATA 0xfc -+#define LAST_SEG 0x02 -+#define LAST_SEG_DONE 0x01 -+ -+ -+#define CMD_GROUP2_BYTE_DELTA 0xfa -+#define MAX_OFFSET_8BIT 0x0f -+#define BUS_16_BIT 0x01 -+#define QINFIFO_OFFSET 0x02 -+#define CMD_GROUP5_BYTE_DELTA 0x0b -+#define CMD_GROUP_CODE_SHIFT 0x05 -+#define MAX_OFFSET_ULTRA2 0x7f -+#define MAX_OFFSET_16BIT 0x08 -+#define BUS_8_BIT 0x00 -+#define QOUTFIFO_OFFSET 0x01 -+#define UNTAGGEDSCB_OFFSET 0x00 -+#define CCSGRAM_MAXSEGS 0x10 -+#define SCB_LIST_NULL 0xff -+#define SG_SIZEOF 0x08 -+#define CMD_GROUP4_BYTE_DELTA 0x04 -+#define CMD_GROUP0_BYTE_DELTA 0xfc -+#define HOST_MSG 0xff -+#define BUS_32_BIT 0x02 -+#define CCSGADDR_MAX 0x80 -+ -+ -+/* Downloaded Constant Definitions */ -+#define TMODE_NUMCMDS 0x00 -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_seq.c linux/drivers/scsi/aic7xxx/aic7xxx_seq.c ---- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_seq.c Wed Dec 31 19:00:00 1969 -+++ linux/drivers/scsi/aic7xxx/aic7xxx_seq.c Tue Feb 6 03:49:36 2001 -@@ -0,0 +1,830 @@ -+/* -+ * DO NOT EDIT - This file is automatically generated. -+ */ -+static unsigned char seqprog[] = { -+ 0xff, 0x6a, 0x06, 0x08, -+ 0x7f, 0x02, 0x04, 0x08, -+ 0x12, 0x6a, 0x00, 0x00, -+ 0xff, 0x6a, 0xd6, 0x09, -+ 0xff, 0x6a, 0xdc, 0x09, -+ 0x00, 0x65, 0xcc, 0x58, -+ 0xf7, 0x01, 0x02, 0x08, -+ 0xff, 0x4e, 0xc8, 0x08, -+ 0xbf, 0x60, 0xc0, 0x08, -+ 0x60, 0x0b, 0x86, 0x68, -+ 0x40, 0x00, 0x0c, 0x68, -+ 0x08, 0x1f, 0x3e, 0x10, -+ 0x60, 0x0b, 0x86, 0x68, -+ 0x40, 0x00, 0x0c, 0x68, -+ 0x08, 0x1f, 0x3e, 0x10, -+ 0xff, 0x3e, 0x48, 0x60, -+ 0x40, 0xfa, 0x10, 0x78, -+ 0xff, 0xf6, 0xd4, 0x08, -+ 0x01, 0x4e, 0x9c, 0x18, -+ 0x40, 0x60, 0xc0, 0x00, -+ 0x00, 0x4d, 0x10, 0x70, -+ 0x01, 0x4e, 0x9c, 0x18, -+ 0xbf, 0x60, 0xc0, 0x08, -+ 0x00, 0x6a, 0xce, 0x5c, -+ 0xff, 0x4e, 0xc8, 0x18, -+ 0x02, 0x6a, 0xb8, 0x5b, -+ 0xff, 0x52, 0x20, 0x09, -+ 0x0d, 0x6a, 0x6a, 0x00, -+ 0x00, 0x52, 0x2e, 0x5c, -+ 0x03, 0xb0, 0x52, 0x31, -+ 0xff, 0xb0, 0x52, 0x09, -+ 0xff, 0xb1, 0x54, 0x09, -+ 0xff, 0xb2, 0x56, 0x09, -+ 0xff, 0xa3, 0x50, 0x09, -+ 0xff, 0x3e, 0x74, 0x09, -+ 0xff, 0x90, 0x7c, 0x08, -+ 0xff, 0x3e, 0x20, 0x09, -+ 0x00, 0x65, 0x4e, 0x58, -+ 0x00, 0x65, 0x0c, 0x40, -+ 0xf7, 0x1f, 0xca, 0x08, -+ 0x08, 0xa1, 0xc8, 0x08, -+ 0x00, 0x65, 0xca, 0x00, -+ 0xff, 0x65, 0x3e, 0x08, -+ 0xf0, 0xa1, 0xc8, 0x08, -+ 0x0f, 0x0f, 0x1e, 0x08, -+ 0x00, 0x0f, 0x1e, 0x00, -+ 0xf0, 0xa1, 0xc8, 0x08, -+ 0x0f, 0x05, 0x0a, 0x08, -+ 0x00, 0x05, 0x0a, 0x00, -+ 0xff, 0x6a, 0x0c, 0x08, -+ 0x5a, 0x6a, 0x00, 0x04, -+ 0x12, 0x65, 0x02, 0x00, -+ 0x31, 0x6a, 0xca, 0x00, -+ 0x80, 0x37, 0x6e, 0x68, -+ 0xff, 0x65, 0xca, 0x18, -+ 0xff, 0x37, 0xdc, 0x08, -+ 0xff, 0x6e, 0xc8, 0x08, -+ 0x00, 0x6c, 0x76, 0x78, -+ 0x20, 0x01, 0x02, 0x00, -+ 0x4c, 0x37, 0xc8, 0x28, -+ 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, 0x96, 0x68, -+ 0x20, 0x6a, 0x16, 0x00, -+ 0xf0, 0x19, 0x6e, 0x08, -+ 0x08, 0x6a, 0x18, 0x00, -+ 0x08, 0x11, 0x22, 0x00, -+ 0x08, 0x6a, 0x66, 0x58, -+ 0x08, 0x6a, 0x68, 0x00, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0x12, 0x6a, 0x00, 0x00, -+ 0x40, 0x6a, 0x16, 0x00, -+ 0xff, 0x3e, 0x20, 0x09, -+ 0xff, 0xba, 0x7c, 0x08, -+ 0xff, 0xa1, 0x6e, 0x08, -+ 0x08, 0x6a, 0x18, 0x00, -+ 0x08, 0x11, 0x22, 0x00, -+ 0x08, 0x6a, 0x66, 0x58, -+ 0x80, 0x6a, 0x68, 0x00, -+ 0x80, 0x36, 0x6c, 0x00, -+ 0x00, 0x65, 0x02, 0x5c, -+ 0xff, 0x3d, 0xc8, 0x08, -+ 0xbf, 0x64, 0xde, 0x78, -+ 0xbf, 0x64, 0x88, 0x79, -+ 0x80, 0x64, 0x10, 0x72, -+ 0xa0, 0x64, 0x40, 0x72, -+ 0xc0, 0x64, 0x38, 0x72, -+ 0xe0, 0x64, 0x80, 0x72, -+ 0x01, 0x6a, 0x22, 0x01, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0xf7, 0x11, 0x22, 0x08, -+ 0x00, 0x65, 0xcc, 0x58, -+ 0xff, 0x06, 0xd4, 0x08, -+ 0xf7, 0x01, 0x02, 0x08, -+ 0x09, 0x0c, 0xc6, 0x78, -+ 0x08, 0x0c, 0x0c, 0x68, -+ 0x01, 0x6a, 0x22, 0x01, -+ 0xff, 0x6a, 0x26, 0x09, -+ 0x02, 0x6a, 0x08, 0x30, -+ 0xff, 0x6a, 0x08, 0x08, -+ 0xdf, 0x01, 0x02, 0x08, -+ 0x01, 0x6a, 0x7a, 0x00, -+ 0xff, 0x6a, 0x6c, 0x0c, -+ 0x04, 0x14, 0x10, 0x31, -+ 0x03, 0xa9, 0x18, 0x31, -+ 0x00, 0x65, 0xf0, 0x40, -+ 0xa8, 0x6a, 0x6a, 0x00, -+ 0x40, 0x3d, 0xe4, 0x68, -+ 0x04, 0x35, 0x6a, 0x00, -+ 0x00, 0x65, 0x72, 0x5b, -+ 0x80, 0x6a, 0xd4, 0x01, -+ 0x10, 0x36, 0xd8, 0x68, -+ 0x10, 0x36, 0x6c, 0x00, -+ 0x07, 0xac, 0x10, 0x31, -+ 0x05, 0xa3, 0x70, 0x30, -+ 0xff, 0x38, 0xf8, 0x68, -+ 0x80, 0x02, 0x04, 0x00, -+ 0x04, 0x35, 0x6a, 0x08, -+ 0x03, 0x69, 0x18, 0x31, -+ 0x22, 0x38, 0xc8, 0x28, -+ 0x01, 0x38, 0xfe, 0x60, -+ 0x02, 0x64, 0xc8, 0x00, -+ 0xff, 0x64, 0xf8, 0x09, -+ 0xff, 0x35, 0x26, 0x09, -+ 0x80, 0x02, 0x76, 0x69, -+ 0x10, 0x0c, 0x3a, 0x69, -+ 0x80, 0x94, 0x04, 0x79, -+ 0x01, 0x38, 0x30, 0x71, -+ 0x80, 0xea, 0x22, 0x61, -+ 0xef, 0x38, 0xc8, 0x18, -+ 0x80, 0x6a, 0xc8, 0x00, -+ 0x00, 0x65, 0x14, 0x49, -+ 0x33, 0x38, 0xc8, 0x28, -+ 0xff, 0x64, 0xd0, 0x09, -+ 0x04, 0x39, 0xc0, 0x31, -+ 0x09, 0x6a, 0xd6, 0x01, -+ 0x80, 0xeb, 0x1a, 0x79, -+ 0xf7, 0xeb, 0xd6, 0x09, -+ 0x08, 0xeb, 0x1e, 0x69, -+ 0x01, 0x6a, 0xd6, 0x01, -+ 0x10, 0x0c, 0x3a, 0x69, -+ 0xff, 0x38, 0x70, 0x18, -+ 0x08, 0xe9, 0x10, 0x31, -+ 0xff, 0x6a, 0xc8, 0x08, -+ 0x08, 0x39, 0x72, 0x18, -+ 0x00, 0x3a, 0x74, 0x20, -+ 0x00, 0x65, 0xf0, 0x40, -+ 0x10, 0x0c, 0x3a, 0x69, -+ 0x01, 0xfc, 0x30, 0x79, -+ 0xff, 0x6a, 0x70, 0x08, -+ 0x01, 0x0c, 0x36, 0x79, -+ 0x10, 0x0c, 0xf0, 0x78, -+ 0x00, 0x65, 0x5c, 0x59, -+ 0x01, 0xfc, 0x54, 0x69, -+ 0x40, 0x0d, 0x44, 0x69, -+ 0xb1, 0x6a, 0x22, 0x01, -+ 0x00, 0x65, 0x54, 0x41, -+ 0x2e, 0xfc, 0xa2, 0x28, -+ 0x3f, 0x38, 0xc8, 0x08, -+ 0x00, 0x51, 0x54, 0x71, -+ 0xff, 0x6a, 0xc8, 0x08, -+ 0xf8, 0x39, 0x72, 0x18, -+ 0xff, 0x3a, 0x74, 0x20, -+ 0x01, 0x38, 0x70, 0x18, -+ 0x00, 0x65, 0x46, 0x41, -+ 0x03, 0x08, 0x52, 0x31, -+ 0xff, 0x38, 0x50, 0x09, -+ 0x12, 0x01, 0x02, 0x00, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0x04, 0x93, 0x70, 0x69, -+ 0xdf, 0x93, 0x26, 0x09, -+ 0x20, 0x93, 0x60, 0x69, -+ 0x02, 0x93, 0x26, 0x01, -+ 0x01, 0x94, 0x64, 0x79, -+ 0x01, 0x94, 0x64, 0x79, -+ 0x01, 0x94, 0x64, 0x79, -+ 0x01, 0x94, 0x64, 0x79, -+ 0x01, 0x94, 0x64, 0x79, -+ 0x10, 0x94, 0x6e, 0x69, -+ 0xd7, 0x93, 0x26, 0x09, -+ 0x28, 0x93, 0x72, 0x69, -+ 0xff, 0x6a, 0xd4, 0x0c, -+ 0x10, 0x0c, 0x76, 0x79, -+ 0x00, 0x65, 0x5c, 0x59, -+ 0x7f, 0x02, 0x04, 0x08, -+ 0xe1, 0x6a, 0x22, 0x01, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0x03, 0xa9, 0x10, 0x30, -+ 0x08, 0x6a, 0xcc, 0x00, -+ 0xa9, 0x6a, 0x18, 0x5c, -+ 0x00, 0x65, 0xa6, 0x41, -+ 0x79, 0x6a, 0x6a, 0x00, -+ 0x40, 0x3d, 0x8e, 0x69, -+ 0x04, 0x35, 0x6a, 0x00, -+ 0x00, 0x65, 0x72, 0x5b, -+ 0x80, 0x6a, 0xd4, 0x01, -+ 0x10, 0x36, 0x80, 0x69, -+ 0x10, 0x36, 0x6c, 0x00, -+ 0x07, 0xac, 0x10, 0x31, -+ 0x03, 0x8c, 0x10, 0x30, -+ 0x05, 0xa3, 0x70, 0x30, -+ 0x88, 0x6a, 0xcc, 0x00, -+ 0xac, 0x6a, 0x10, 0x5c, -+ 0x00, 0x65, 0x0a, 0x5c, -+ 0x38, 0x6a, 0xcc, 0x00, -+ 0xa3, 0x6a, 0x14, 0x5c, -+ 0xff, 0x38, 0xb4, 0x69, -+ 0x80, 0x02, 0x04, 0x00, -+ 0xe7, 0x35, 0x6a, 0x08, -+ 0x03, 0x69, 0x10, 0x30, -+ 0xff, 0x6a, 0x10, 0x00, -+ 0xff, 0x6a, 0x12, 0x00, -+ 0xff, 0x6a, 0x14, 0x00, -+ 0x01, 0x38, 0xb8, 0x61, -+ 0xbf, 0x35, 0x6a, 0x08, -+ 0x00, 0x35, 0x52, 0x5b, -+ 0x80, 0x02, 0x0a, 0x6a, -+ 0xff, 0x65, 0xfa, 0x79, -+ 0x01, 0x38, 0xfa, 0x71, -+ 0xff, 0x38, 0x70, 0x18, -+ 0x80, 0xea, 0xda, 0x61, -+ 0xef, 0x38, 0xc8, 0x18, -+ 0x80, 0x6a, 0xc8, 0x00, -+ 0x00, 0x65, 0xcc, 0x49, -+ 0x33, 0x38, 0xc8, 0x28, -+ 0xff, 0x64, 0xd0, 0x09, -+ 0x04, 0x39, 0xc0, 0x31, -+ 0x09, 0x6a, 0xd6, 0x01, -+ 0x80, 0xeb, 0xd2, 0x79, -+ 0xf7, 0xeb, 0xd6, 0x09, -+ 0x08, 0xeb, 0xd6, 0x69, -+ 0x01, 0x6a, 0xd6, 0x01, -+ 0x08, 0xe9, 0x10, 0x31, -+ 0x03, 0x8c, 0x10, 0x30, -+ 0x88, 0x6a, 0xcc, 0x00, -+ 0x39, 0x6a, 0x16, 0x5c, -+ 0x08, 0x6a, 0x18, 0x01, -+ 0xff, 0x6a, 0x1a, 0x09, -+ 0xff, 0x6a, 0x1c, 0x09, -+ 0x0d, 0x93, 0x26, 0x01, -+ 0x00, 0x65, 0xc0, 0x5c, -+ 0x88, 0x6a, 0xb2, 0x5c, -+ 0x00, 0x65, 0x0a, 0x5c, -+ 0xff, 0x6a, 0xc8, 0x08, -+ 0x08, 0x39, 0x72, 0x18, -+ 0x00, 0x3a, 0x74, 0x20, -+ 0x01, 0x0c, 0xf6, 0x79, -+ 0x10, 0x0c, 0xa6, 0x79, -+ 0xff, 0x6a, 0x70, 0x08, -+ 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, 0xaa, 0x40, -+ 0x7f, 0x02, 0x04, 0x08, -+ 0xe1, 0x6a, 0x22, 0x01, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0x00, 0x65, 0x72, 0x5b, -+ 0x05, 0xb4, 0x10, 0x31, -+ 0x02, 0x6a, 0x1a, 0x31, -+ 0x03, 0x8c, 0x10, 0x30, -+ 0x88, 0x6a, 0xcc, 0x00, -+ 0xb4, 0x6a, 0x14, 0x5c, -+ 0xff, 0x6a, 0x1a, 0x09, -+ 0xff, 0x6a, 0x1c, 0x09, -+ 0x00, 0x65, 0x0a, 0x5c, -+ 0x3d, 0x6a, 0x52, 0x5b, -+ 0xac, 0x6a, 0x26, 0x01, -+ 0x04, 0x0b, 0x26, 0x6a, -+ 0x04, 0x0b, 0x2c, 0x6a, -+ 0x10, 0x0c, 0x28, 0x7a, -+ 0x02, 0x03, 0x30, 0x7a, -+ 0x11, 0x0c, 0x2c, 0x7a, -+ 0xd7, 0x93, 0x26, 0x09, -+ 0x28, 0x93, 0x32, 0x6a, -+ 0x12, 0x01, 0x02, 0x00, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0x00, 0x65, 0x72, 0x5b, -+ 0xff, 0x06, 0x44, 0x09, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0x10, 0x3d, 0x06, 0x00, -+ 0xff, 0x34, 0xca, 0x08, -+ 0x80, 0x65, 0x64, 0x62, -+ 0x0f, 0xa1, 0xca, 0x08, -+ 0x07, 0xa1, 0xca, 0x08, -+ 0x40, 0xa0, 0xc8, 0x08, -+ 0x00, 0x65, 0xca, 0x00, -+ 0x80, 0x65, 0xca, 0x00, -+ 0x80, 0xa0, 0x54, 0x7a, -+ 0xff, 0x65, 0x0c, 0x08, -+ 0x00, 0x65, 0x66, 0x42, -+ 0x20, 0xa0, 0x6c, 0x7a, -+ 0xff, 0x65, 0x0c, 0x08, -+ 0x00, 0x65, 0x02, 0x5c, -+ 0xa0, 0x3d, 0x74, 0x62, -+ 0x23, 0xa0, 0x0c, 0x08, -+ 0x00, 0x65, 0x02, 0x5c, -+ 0xa0, 0x3d, 0x74, 0x62, -+ 0x00, 0xb9, 0x6c, 0x42, -+ 0xff, 0x65, 0x6c, 0x62, -+ 0xa1, 0x6a, 0x22, 0x01, -+ 0xff, 0x6a, 0xd4, 0x08, -+ 0x10, 0x51, 0x74, 0x72, -+ 0x40, 0x6a, 0x18, 0x00, -+ 0xff, 0x65, 0x0c, 0x08, -+ 0x00, 0x65, 0x02, 0x5c, -+ 0xa0, 0x3d, 0x3e, 0x72, -+ 0x40, 0x6a, 0x18, 0x00, -+ 0xff, 0x34, 0xa6, 0x08, -+ 0x80, 0x34, 0x7c, 0x62, -+ 0x7f, 0xa0, 0x40, 0x09, -+ 0x08, 0x6a, 0x68, 0x00, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0x64, 0x6a, 0x48, 0x5b, -+ 0x80, 0x64, 0xf2, 0x6a, -+ 0x04, 0x64, 0xd4, 0x72, -+ 0x02, 0x64, 0xda, 0x72, -+ 0x00, 0x6a, 0x9c, 0x72, -+ 0x03, 0x64, 0xee, 0x72, -+ 0x01, 0x64, 0xd0, 0x72, -+ 0x07, 0x64, 0x30, 0x73, -+ 0x08, 0x64, 0x98, 0x72, -+ 0x23, 0x64, 0x34, 0x73, -+ 0x11, 0x6a, 0x22, 0x01, -+ 0x07, 0x6a, 0x3a, 0x5b, -+ 0xff, 0x06, 0xd4, 0x08, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0xff, 0xa8, 0xa0, 0x6a, -+ 0xff, 0xa2, 0xb8, 0x7a, -+ 0x01, 0x6a, 0x6a, 0x00, -+ 0x00, 0xb9, 0x2e, 0x5c, -+ 0xff, 0xa2, 0xb8, 0x7a, -+ 0x71, 0x6a, 0x22, 0x01, -+ 0xff, 0x6a, 0xd4, 0x08, -+ 0x40, 0x51, 0xb8, 0x62, -+ 0x0d, 0x6a, 0x6a, 0x00, -+ 0x00, 0xb9, 0x2e, 0x5c, -+ 0xff, 0x3e, 0x74, 0x09, -+ 0xff, 0x90, 0x7c, 0x08, -+ 0x00, 0x65, 0x4e, 0x58, -+ 0x00, 0x65, 0xbe, 0x40, -+ 0x20, 0xa0, 0xc0, 0x6a, -+ 0xff, 0x37, 0xc8, 0x08, -+ 0x00, 0x6a, 0xd8, 0x5b, -+ 0xff, 0x6a, 0xee, 0x5b, -+ 0xff, 0xf8, 0xc8, 0x08, -+ 0xff, 0x4f, 0xc8, 0x08, -+ 0x01, 0x6a, 0xd8, 0x5b, -+ 0x00, 0xb9, 0xee, 0x5b, -+ 0x01, 0x4f, 0x9e, 0x18, -+ 0x02, 0x6a, 0x22, 0x01, -+ 0x00, 0x65, 0xc8, 0x5c, -+ 0x00, 0x65, 0xbe, 0x40, -+ 0x41, 0x6a, 0x22, 0x01, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0x04, 0xa0, 0x40, 0x01, -+ 0x00, 0x65, 0xe0, 0x5c, -+ 0x00, 0x65, 0xbe, 0x40, -+ 0x10, 0x36, 0x98, 0x7a, -+ 0x05, 0x38, 0x46, 0x31, -+ 0x04, 0x14, 0x58, 0x31, -+ 0x03, 0xa9, 0x60, 0x31, -+ 0xa3, 0x6a, 0xcc, 0x00, -+ 0x38, 0x6a, 0x14, 0x5c, -+ 0xac, 0x6a, 0xcc, 0x00, -+ 0x14, 0x6a, 0x16, 0x5c, -+ 0xa9, 0x6a, 0x18, 0x5c, -+ 0x00, 0x65, 0x98, 0x42, -+ 0xef, 0x36, 0x6c, 0x08, -+ 0x00, 0x65, 0x98, 0x42, -+ 0x0f, 0x64, 0xc8, 0x08, -+ 0x07, 0x64, 0xc8, 0x08, -+ 0x00, 0x37, 0x6e, 0x00, -+ 0xff, 0x6a, 0xa4, 0x00, -+ 0x00, 0x65, 0xa8, 0x5b, -+ 0xff, 0x51, 0x04, 0x73, -+ 0x20, 0x36, 0x0e, 0x7b, -+ 0x00, 0x90, 0x96, 0x5b, -+ 0x00, 0x65, 0x10, 0x43, -+ 0xff, 0x06, 0xd4, 0x08, -+ 0x00, 0x65, 0x02, 0x5c, -+ 0xe0, 0x3d, 0x2a, 0x63, -+ 0x20, 0x12, 0x2a, 0x63, -+ 0x51, 0x6a, 0x3e, 0x5b, -+ 0x00, 0x65, 0x90, 0x5b, -+ 0xff, 0x37, 0xc8, 0x08, -+ 0x00, 0xa1, 0x22, 0x63, -+ 0x04, 0xa0, 0x22, 0x7b, -+ 0xfb, 0xa0, 0x40, 0x09, -+ 0x80, 0x36, 0x6c, 0x00, -+ 0x80, 0xa0, 0x98, 0x7a, -+ 0x7f, 0xa0, 0x40, 0x09, -+ 0xff, 0x6a, 0x3a, 0x5b, -+ 0x00, 0x65, 0x98, 0x42, -+ 0x04, 0xa0, 0x28, 0x7b, -+ 0x00, 0x65, 0xe0, 0x5c, -+ 0x00, 0x65, 0x2a, 0x43, -+ 0x00, 0x65, 0xc8, 0x5c, -+ 0x31, 0x6a, 0x22, 0x01, -+ 0x0c, 0x6a, 0x3a, 0x5b, -+ 0x00, 0x65, 0x98, 0x42, -+ 0x61, 0x6a, 0x22, 0x01, -+ 0x00, 0x65, 0x98, 0x42, -+ 0x51, 0x6a, 0x3e, 0x5b, -+ 0x51, 0x6a, 0x22, 0x01, -+ 0x00, 0x65, 0x98, 0x42, -+ 0x10, 0x3d, 0x06, 0x00, -+ 0xff, 0x65, 0x68, 0x0c, -+ 0xff, 0x06, 0xd4, 0x08, -+ 0x01, 0x0c, 0x40, 0x7b, -+ 0x04, 0x0c, 0x42, 0x6b, -+ 0xe0, 0x03, 0x7a, 0x08, -+ 0xe0, 0x3d, 0x4e, 0x63, -+ 0xff, 0x65, 0xcc, 0x08, -+ 0xff, 0x12, 0xda, 0x0c, -+ 0xff, 0x06, 0xd4, 0x0c, -+ 0xd1, 0x6a, 0x22, 0x01, -+ 0x00, 0x65, 0xaa, 0x40, -+ 0xff, 0x65, 0x26, 0x09, -+ 0x01, 0x0b, 0x62, 0x6b, -+ 0x10, 0x0c, 0x54, 0x7b, -+ 0x04, 0x0b, 0x5c, 0x6b, -+ 0xff, 0x6a, 0xca, 0x08, -+ 0x04, 0x93, 0x60, 0x6b, -+ 0x01, 0x94, 0x5e, 0x7b, -+ 0x10, 0x94, 0x60, 0x6b, -+ 0x80, 0x3d, 0x66, 0x73, -+ 0x0f, 0x04, 0x6a, 0x6b, -+ 0x02, 0x03, 0x6a, 0x7b, -+ 0x11, 0x0c, 0x66, 0x7b, -+ 0xc7, 0x93, 0x26, 0x09, -+ 0xff, 0x99, 0xd4, 0x08, -+ 0x38, 0x93, 0x6c, 0x6b, -+ 0xff, 0x6a, 0xd4, 0x0c, -+ 0x80, 0x36, 0x70, 0x6b, -+ 0x21, 0x6a, 0x22, 0x05, -+ 0xff, 0x65, 0x20, 0x09, -+ 0xff, 0x51, 0x7e, 0x63, -+ 0xff, 0x37, 0xc8, 0x08, -+ 0xa1, 0x6a, 0x8a, 0x43, -+ 0xff, 0x51, 0xc8, 0x08, -+ 0xb9, 0x6a, 0x8a, 0x43, -+ 0xff, 0x90, 0xa4, 0x08, -+ 0xff, 0xba, 0x8e, 0x73, -+ 0xff, 0xba, 0x20, 0x09, -+ 0xff, 0x65, 0xca, 0x18, -+ 0x00, 0x6c, 0x82, 0x63, -+ 0xff, 0x90, 0xca, 0x0c, -+ 0xff, 0x6a, 0xca, 0x04, -+ 0x20, 0x36, 0xa2, 0x7b, -+ 0x00, 0x90, 0x76, 0x5b, -+ 0xff, 0x65, 0xa2, 0x73, -+ 0xff, 0x52, 0xa0, 0x73, -+ 0xff, 0xba, 0xcc, 0x08, -+ 0xff, 0x52, 0x20, 0x09, -+ 0xff, 0x66, 0x74, 0x09, -+ 0xff, 0x65, 0x20, 0x0d, -+ 0xff, 0xba, 0x7e, 0x0c, -+ 0x00, 0x6a, 0xce, 0x5c, -+ 0x0d, 0x6a, 0x6a, 0x00, -+ 0x00, 0x51, 0x2e, 0x44, -+ 0xff, 0x3f, 0xfc, 0x73, -+ 0xff, 0x6a, 0xa2, 0x00, -+ 0x00, 0x3f, 0x76, 0x5b, -+ 0xff, 0x65, 0xfc, 0x73, -+ 0x20, 0x36, 0x6c, 0x00, -+ 0x20, 0xa0, 0xb6, 0x6b, -+ 0xff, 0xb9, 0xa2, 0x0c, -+ 0xff, 0x6a, 0xa2, 0x04, -+ 0xff, 0x65, 0xa4, 0x08, -+ 0xe0, 0x6a, 0xcc, 0x00, -+ 0x45, 0x6a, 0x22, 0x5c, -+ 0x01, 0x6a, 0xd0, 0x01, -+ 0x09, 0x6a, 0xd6, 0x01, -+ 0x80, 0xeb, 0xc2, 0x7b, -+ 0x01, 0x6a, 0xd6, 0x01, -+ 0x01, 0xe9, 0xa4, 0x34, -+ 0x88, 0x6a, 0xcc, 0x00, -+ 0x45, 0x6a, 0x22, 0x5c, -+ 0x01, 0x6a, 0x18, 0x01, -+ 0xff, 0x6a, 0x1a, 0x09, -+ 0xff, 0x6a, 0x1c, 0x09, -+ 0x0d, 0x6a, 0x26, 0x01, -+ 0x00, 0x65, 0xc0, 0x5c, -+ 0xff, 0x99, 0xa4, 0x0c, -+ 0xff, 0x65, 0xa4, 0x08, -+ 0xe0, 0x6a, 0xcc, 0x00, -+ 0x45, 0x6a, 0x22, 0x5c, -+ 0x01, 0x6a, 0xd0, 0x01, -+ 0x01, 0x6a, 0xdc, 0x05, -+ 0x88, 0x6a, 0xcc, 0x00, -+ 0x45, 0x6a, 0x22, 0x5c, -+ 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, 0xf2, 0x7b, -+ 0xff, 0x6a, 0xdc, 0x0d, -+ 0xff, 0x65, 0x32, 0x09, -+ 0x0a, 0x93, 0x26, 0x01, -+ 0x00, 0x65, 0xc0, 0x44, -+ 0xff, 0x37, 0xc8, 0x08, -+ 0x00, 0x6a, 0xb8, 0x5b, -+ 0xff, 0x52, 0xa2, 0x0c, -+ 0x01, 0x0c, 0x02, 0x7c, -+ 0x04, 0x0c, 0x02, 0x6c, -+ 0xe0, 0x03, 0x06, 0x08, -+ 0xe0, 0x03, 0x7a, 0x0c, -+ 0xff, 0x8c, 0x10, 0x08, -+ 0xff, 0x8d, 0x12, 0x08, -+ 0xff, 0x8e, 0x14, 0x0c, -+ 0xff, 0x6c, 0xda, 0x08, -+ 0xff, 0x6c, 0xda, 0x08, -+ 0xff, 0x6c, 0xda, 0x08, -+ 0xff, 0x6c, 0xda, 0x08, -+ 0xff, 0x6c, 0xda, 0x08, -+ 0xff, 0x6c, 0xda, 0x08, -+ 0xff, 0x6c, 0xda, 0x0c, -+ 0x3d, 0x64, 0xa4, 0x28, -+ 0x55, 0x64, 0xc8, 0x28, -+ 0x00, 0x6c, 0xda, 0x18, -+ 0xff, 0x52, 0xc8, 0x08, -+ 0x00, 0x6c, 0xda, 0x20, -+ 0xff, 0x6a, 0xc8, 0x08, -+ 0x00, 0x6c, 0xda, 0x20, -+ 0x00, 0x6c, 0xda, 0x24, -+ 0xff, 0x65, 0xc8, 0x08, -+ 0xe0, 0x6a, 0xcc, 0x00, -+ 0x41, 0x6a, 0x1e, 0x5c, -+ 0xff, 0x90, 0xe2, 0x09, -+ 0x20, 0x6a, 0xd0, 0x01, -+ 0x04, 0x35, 0x40, 0x7c, -+ 0x1d, 0x6a, 0xdc, 0x01, -+ 0xdc, 0xee, 0x3c, 0x64, -+ 0x00, 0x65, 0x56, 0x44, -+ 0x01, 0x6a, 0xdc, 0x01, -+ 0x20, 0xa0, 0xd8, 0x31, -+ 0x09, 0xee, 0xdc, 0x01, -+ 0x80, 0xee, 0x46, 0x7c, -+ 0x11, 0x6a, 0xdc, 0x01, -+ 0x50, 0xee, 0x4a, 0x64, -+ 0x20, 0x6a, 0xd0, 0x01, -+ 0x09, 0x6a, 0xdc, 0x01, -+ 0x88, 0xee, 0x50, 0x64, -+ 0x19, 0x6a, 0xdc, 0x01, -+ 0xd8, 0xee, 0x54, 0x64, -+ 0xff, 0x6a, 0xdc, 0x09, -+ 0x18, 0xee, 0x58, 0x6c, -+ 0xff, 0x6a, 0xd4, 0x0c, -+ 0x88, 0x6a, 0xcc, 0x00, -+ 0x41, 0x6a, 0x1e, 0x5c, -+ 0x20, 0x6a, 0x18, 0x01, -+ 0xff, 0x6a, 0x1a, 0x09, -+ 0xff, 0x6a, 0x1c, 0x09, -+ 0xff, 0x35, 0x26, 0x09, -+ 0x04, 0x35, 0x84, 0x6c, -+ 0xa0, 0x6a, 0xca, 0x00, -+ 0x20, 0x65, 0xc8, 0x18, -+ 0xff, 0x6c, 0x32, 0x09, -+ 0xff, 0x6c, 0x32, 0x09, -+ 0xff, 0x6c, 0x32, 0x09, -+ 0xff, 0x6c, 0x32, 0x09, -+ 0xff, 0x6c, 0x32, 0x09, -+ 0xff, 0x6c, 0x32, 0x09, -+ 0xff, 0x6c, 0x32, 0x09, -+ 0xff, 0x6c, 0x32, 0x09, -+ 0x00, 0x65, 0x6e, 0x64, -+ 0x0a, 0x93, 0x26, 0x01, -+ 0x00, 0x65, 0xc0, 0x44, -+ 0xa0, 0x6a, 0xcc, 0x00, -+ 0xe8, 0x6a, 0xc8, 0x00, -+ 0x01, 0x94, 0x88, 0x6c, -+ 0x10, 0x94, 0x8a, 0x6c, -+ 0x08, 0x94, 0x9c, 0x6c, -+ 0x08, 0x94, 0x9c, 0x6c, -+ 0x08, 0x94, 0x9c, 0x6c, -+ 0x00, 0x65, 0xb0, 0x5c, -+ 0x08, 0x64, 0xc8, 0x18, -+ 0x00, 0x8c, 0xca, 0x18, -+ 0x00, 0x65, 0x92, 0x4c, -+ 0x00, 0x65, 0x88, 0x44, -+ 0xf7, 0x93, 0x26, 0x09, -+ 0x08, 0x93, 0x9e, 0x6c, -+ 0x00, 0x65, 0xb0, 0x5c, -+ 0x08, 0x64, 0xc8, 0x18, -+ 0x08, 0x64, 0xa0, 0x64, -+ 0xff, 0x6a, 0xd4, 0x0c, -+ 0x00, 0x65, 0xc0, 0x5c, -+ 0x00, 0x65, 0xb0, 0x5c, -+ 0x00, 0x65, 0xb0, 0x5c, -+ 0x00, 0x65, 0xb0, 0x5c, -+ 0xff, 0x99, 0xda, 0x08, -+ 0xff, 0x99, 0xda, 0x08, -+ 0xff, 0x99, 0xda, 0x08, -+ 0xff, 0x99, 0xda, 0x08, -+ 0xff, 0x99, 0xda, 0x08, -+ 0xff, 0x99, 0xda, 0x08, -+ 0xff, 0x99, 0xda, 0x08, -+ 0xff, 0x99, 0xda, 0x0c, -+ 0x08, 0x94, 0xc0, 0x7c, -+ 0xf7, 0x93, 0x26, 0x09, -+ 0x08, 0x93, 0xc4, 0x6c, -+ 0xff, 0x6a, 0xd4, 0x0c, -+ 0xff, 0x40, 0x74, 0x09, -+ 0xff, 0x90, 0x80, 0x08, -+ 0xff, 0x6a, 0x72, 0x05, -+ 0xff, 0x40, 0xdc, 0x64, -+ 0xff, 0x3f, 0xd4, 0x64, -+ 0xff, 0x6a, 0xca, 0x04, -+ 0xff, 0x3f, 0x20, 0x09, -+ 0x01, 0x6a, 0x6a, 0x00, -+ 0x00, 0xb9, 0x2e, 0x5c, -+ 0xff, 0xba, 0x7e, 0x0c, -+ 0xff, 0x40, 0x20, 0x09, -+ 0xff, 0xba, 0x80, 0x0c, -+ 0xff, 0x3f, 0x74, 0x09, -+ 0xff, 0x90, 0x7e, 0x0c, -+}; -+ -+static int aic7xxx_patch14_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch14_func(struct aic7xxx_host *p) -+{ -+ return ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0); -+} -+ -+static int aic7xxx_patch13_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch13_func(struct aic7xxx_host *p) -+{ -+ return ((p->features & AHC_CMD_CHAN) == 0); -+} -+ -+static int aic7xxx_patch12_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch12_func(struct aic7xxx_host *p) -+{ -+ return ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0); -+} -+ -+static int aic7xxx_patch11_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch11_func(struct aic7xxx_host *p) -+{ -+ return ((p->features & AHC_WIDE) != 0); -+} -+ -+static int aic7xxx_patch10_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch10_func(struct aic7xxx_host *p) -+{ -+ return ((p->features & AHC_ULTRA2) == 0); -+} -+ -+static int aic7xxx_patch9_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch9_func(struct aic7xxx_host *p) -+{ -+ return ((p->bugs & AHC_BUG_AUTOFLUSH) != 0); -+} -+ -+static int aic7xxx_patch8_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch8_func(struct aic7xxx_host *p) -+{ -+ return ((p->features & AHC_ULTRA) != 0); -+} -+ -+static int aic7xxx_patch7_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch7_func(struct aic7xxx_host *p) -+{ -+ return ((p->features & AHC_ULTRA2) != 0); -+} -+ -+static int aic7xxx_patch6_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch6_func(struct aic7xxx_host *p) -+{ -+ return ((p->flags & AHC_PAGESCBS) == 0); -+} -+ -+static int aic7xxx_patch5_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch5_func(struct aic7xxx_host *p) -+{ -+ return ((p->flags & AHC_PAGESCBS) != 0); -+} -+ -+static int aic7xxx_patch4_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch4_func(struct aic7xxx_host *p) -+{ -+ return ((p->features & AHC_QUEUE_REGS) != 0); -+} -+ -+static int aic7xxx_patch3_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch3_func(struct aic7xxx_host *p) -+{ -+ return ((p->features & AHC_TWIN) != 0); -+} -+ -+static int aic7xxx_patch2_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch2_func(struct aic7xxx_host *p) -+{ -+ return ((p->features & AHC_QUEUE_REGS) == 0); -+} -+ -+static int aic7xxx_patch1_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch1_func(struct aic7xxx_host *p) -+{ -+ return ((p->features & AHC_CMD_CHAN) != 0); -+} -+ -+static int aic7xxx_patch0_func(struct aic7xxx_host *p); -+ -+static int -+aic7xxx_patch0_func(struct aic7xxx_host *p) -+{ -+ return (0); -+} -+ -+struct sequencer_patch { -+ int (*patch_func)(struct aic7xxx_host *); -+ unsigned int begin :10, -+ skip_instr :10, -+ skip_patch :12; -+} sequencer_patches[] = { -+ { 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, 87, 1, 2 }, -+ { aic7xxx_patch0_func, 88, 1, 1 }, -+ { aic7xxx_patch7_func, 103, 1, 2 }, -+ { aic7xxx_patch0_func, 104, 2, 1 }, -+ { aic7xxx_patch7_func, 108, 84, 15 }, -+ { aic7xxx_patch9_func, 177, 1, 1 }, -+ { aic7xxx_patch9_func, 178, 4, 1 }, -+ { aic7xxx_patch0_func, 192, 72, 12 }, -+ { aic7xxx_patch1_func, 192, 1, 2 }, -+ { aic7xxx_patch0_func, 193, 2, 1 }, -+ { aic7xxx_patch1_func, 200, 1, 1 }, -+ { aic7xxx_patch1_func, 203, 3, 2 }, -+ { aic7xxx_patch0_func, 206, 5, 1 }, -+ { aic7xxx_patch1_func, 214, 1, 2 }, -+ { aic7xxx_patch0_func, 215, 3, 1 }, -+ { aic7xxx_patch1_func, 225, 14, 2 }, -+ { aic7xxx_patch0_func, 239, 9, 1 }, -+ { aic7xxx_patch1_func, 254, 2, 2 }, -+ { aic7xxx_patch0_func, 256, 4, 1 }, -+ { aic7xxx_patch1_func, 265, 3, 3 }, -+ { aic7xxx_patch10_func, 267, 1, 1 }, -+ { aic7xxx_patch0_func, 268, 5, 1 }, -+ { aic7xxx_patch10_func, 273, 1, 2 }, -+ { aic7xxx_patch0_func, 274, 9, 1 }, -+ { aic7xxx_patch11_func, 290, 1, 2 }, -+ { aic7xxx_patch0_func, 291, 1, 1 }, -+ { aic7xxx_patch4_func, 352, 1, 2 }, -+ { aic7xxx_patch0_func, 353, 1, 1 }, -+ { aic7xxx_patch2_func, 356, 1, 1 }, -+ { aic7xxx_patch1_func, 366, 3, 2 }, -+ { aic7xxx_patch0_func, 369, 5, 1 }, -+ { aic7xxx_patch11_func, 377, 1, 2 }, -+ { aic7xxx_patch0_func, 378, 1, 1 }, -+ { aic7xxx_patch5_func, 383, 1, 1 }, -+ { aic7xxx_patch10_func, 425, 15, 2 }, -+ { aic7xxx_patch12_func, 438, 1, 1 }, -+ { aic7xxx_patch1_func, 477, 7, 2 }, -+ { aic7xxx_patch0_func, 484, 8, 1 }, -+ { aic7xxx_patch1_func, 493, 4, 2 }, -+ { aic7xxx_patch0_func, 497, 6, 1 }, -+ { aic7xxx_patch1_func, 503, 4, 2 }, -+ { aic7xxx_patch0_func, 507, 3, 1 }, -+ { aic7xxx_patch13_func, 517, 10, 1 }, -+ { aic7xxx_patch1_func, 536, 22, 8 }, -+ { aic7xxx_patch10_func, 544, 4, 4 }, -+ { aic7xxx_patch0_func, 548, 7, 3 }, -+ { aic7xxx_patch14_func, 548, 5, 2 }, -+ { aic7xxx_patch0_func, 553, 2, 1 }, -+ { aic7xxx_patch0_func, 558, 50, 3 }, -+ { aic7xxx_patch12_func, 579, 17, 2 }, -+ { aic7xxx_patch0_func, 596, 4, 1 }, -+ { aic7xxx_patch13_func, 608, 4, 1 }, -+ { aic7xxx_patch5_func, 612, 2, 1 }, -+ { aic7xxx_patch5_func, 615, 9, 1 }, -+ -+}; -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c ---- linux-2.2.17/drivers/scsi/aic7xxx.c Mon Sep 4 13:39:21 2000 -+++ linux/drivers/scsi/aic7xxx.c Tue Feb 6 03:49:37 2001 -@@ -246,11 +246,11 @@ - #include "sd.h" - #include "scsi.h" - #include "hosts.h" --#include "aic7xxx.h" -+#include "aic7xxx/aic7xxx.h" - - #include "aic7xxx/sequencer.h" - #include "aic7xxx/scsi_message.h" --#include "aic7xxx_reg.h" -+#include "aic7xxx/aic7xxx_reg.h" - #include - - #include -@@ -270,7 +270,7 @@ - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL - }; - --#define AIC7XXX_C_VERSION "5.1.31" -+#define AIC7XXX_C_VERSION "5.1.32" - - #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) - #define MIN(a,b) (((a) < (b)) ? (a) : (b)) -@@ -790,6 +790,7 @@ - - typedef enum { - SCB_FREE = 0x0000, -+ SCB_DTR_SCB = 0x0001, - SCB_WAITINGQ = 0x0002, - SCB_ACTIVE = 0x0004, - SCB_SENSE = 0x0008, -@@ -896,6 +897,17 @@ - AHC_AIC7899_FE = AHC_AIC7890_FE|AHC_ULTRA3, - } ahc_feature; - -+typedef enum { -+ AHC_BUG_NONE = 0x0000, -+ AHC_BUG_TMODE_WIDEODD = 0x0001, -+ AHC_BUG_AUTOFLUSH = 0x0002, -+ AHC_BUG_CACHETHEN = 0x0004, -+ AHC_BUG_CACHETHEN_DIS = 0x0008, -+ AHC_BUG_PCI_2_1_RETRY = 0x0010, -+ AHC_BUG_PCI_MWI = 0x0020, -+ AHC_BUG_SCBCHAN_UPLOAD = 0x0040, -+} ahc_bugs; -+ - struct aic7xxx_scb { - struct aic7xxx_hwscb *hscb; /* corresponding hardware scb */ - Scsi_Cmnd *cmd; /* Scsi_Cmnd for this scb */ -@@ -1004,7 +1016,6 @@ - unsigned long isr_count; /* Interrupt count */ - unsigned long spurious_int; - scb_data_type *scb_data; -- volatile unsigned short needdv; - volatile unsigned short needppr; - volatile unsigned short needsdtr; - volatile unsigned short needwdtr; -@@ -1032,10 +1043,9 @@ - #define BUS_DEVICE_RESET_PENDING 0x02 - #define DEVICE_RESET_DELAY 0x04 - #define DEVICE_PRINT_DTR 0x08 --#define DEVICE_PARITY_ERROR 0x10 --#define DEVICE_WAS_BUSY 0x20 --#define DEVICE_SCSI_3 0x40 --#define DEVICE_SCANNED 0x80 -+#define DEVICE_WAS_BUSY 0x10 -+#define DEVICE_SCSI_3 0x20 -+#define DEVICE_DTR_SCANNED 0x40 - volatile unsigned char dev_flags[MAX_TARGETS]; - volatile unsigned char dev_active_cmds[MAX_TARGETS]; - volatile unsigned char dev_temp_queue_depth[MAX_TARGETS]; -@@ -1051,10 +1061,6 @@ - #endif - - -- Scsi_Cmnd *dev_dtr_cmnd[MAX_TARGETS]; -- -- unsigned int dev_checksum[MAX_TARGETS]; -- - unsigned char dev_last_queue_full[MAX_TARGETS]; - unsigned char dev_last_queue_full_count[MAX_TARGETS]; - unsigned char dev_max_queue_depth[MAX_TARGETS]; -@@ -1111,6 +1117,7 @@ - int host_no; /* SCSI host number */ - unsigned long mbase; /* I/O memory address */ - ahc_chip chip; /* chip type */ -+ ahc_bugs bugs; /* hardware bugs this chip has */ - - /* - * Statistics Kept: -@@ -1712,7 +1719,7 @@ - * prototype, our code has to be ordered that way, it's a left-over from - * the original driver days.....I should fix it some time DL). - */ --#include "aic7xxx_seq.c" -+#include "aic7xxx/aic7xxx_seq.c" - - /*+F************************************************************************* - * Function: -@@ -2876,138 +2883,98 @@ - { - p->flags &= ~AHC_ABORT_PENDING; - } -- if (scb->flags & SCB_RESET) -+ if (scb->flags & (SCB_RESET|SCB_ABORT)) - { -- cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff); -+ cmd->result |= (DID_RESET << 16); - } -- else if (scb->flags & SCB_ABORT) -- { -- cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff); -- } -- else if (!(p->dev_flags[tindex] & DEVICE_SCANNED)) -+ -+ if (!(p->dev_flags[tindex] & DEVICE_PRESENT)) - { - if ( (cmd->cmnd[0] == INQUIRY) && (cmd->result == DID_OK) ) - { -- char *buffer; -- -+ - p->dev_flags[tindex] |= DEVICE_PRESENT; -- if(cmd->use_sg) -- { -- struct scatterlist *sg; -- -- sg = (struct scatterlist *)cmd->request_buffer; -- buffer = (char *)sg[0].address; -- } -- else -- { -- buffer = (char *)cmd->request_buffer; -- } - #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) ) -- { -- p->needwdtr |= (1<needwdtr_copy |= (1<transinfo[tindex].goal_width = p->transinfo[tindex].user_width; -- } -- else -- { -- p->needwdtr &= ~(1<needwdtr_copy &= ~(1<target, cmd->channel, cmd->lun, -- MSG_EXT_WDTR_BUS_8_BIT, (AHC_TRANS_ACTIVE | -- AHC_TRANS_GOAL | -- AHC_TRANS_CUR) ); -- unpause_sequencer(p, FALSE); -- } -- if ( (buffer[7] & SYNC_INQUIRY_BITS) && -- 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->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; -+ if(!(p->dev_flags[tindex] & DEVICE_DTR_SCANNED)) { -+ char *buffer; -+ -+ if(cmd->use_sg) -+ { -+ struct scatterlist *sg; -+ -+ sg = (struct scatterlist *)cmd->request_buffer; -+ buffer = (char *)sg[0].address; -+ } -+ else -+ { -+ buffer = (char *)cmd->request_buffer; -+ } -+ -+ -+ if ( (buffer[7] & WIDE_INQUIRY_BITS) && -+ (p->features & AHC_WIDE) ) -+ { -+ p->needwdtr |= (1<needwdtr_copy |= (1<transinfo[tindex].goal_width = p->transinfo[tindex].user_width; -+ } - 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) ) - { -- p->needppr |= (1<needppr_copy |= (1<needsdtr &= ~(1<needsdtr_copy &= ~(1<needwdtr &= ~(1<needwdtr_copy &= ~(1<dev_flags[tindex] |= DEVICE_SCSI_3; -+ pause_sequencer(p); -+ aic7xxx_set_width(p, cmd->target, cmd->channel, cmd->lun, -+ MSG_EXT_WDTR_BUS_8_BIT, (AHC_TRANS_ACTIVE | -+ AHC_TRANS_GOAL | -+ AHC_TRANS_CUR) ); -+ unpause_sequencer(p, FALSE); - } -- else -+ if ( (buffer[7] & SYNC_INQUIRY_BITS) && -+ p->transinfo[tindex].user_offset ) - { -- p->needsdtr |= (1<needsdtr_copy |= (1<transinfo[tindex].goal_period = -- MAX(10, p->transinfo[tindex].goal_period); -- p->transinfo[tindex].goal_options = 0; -+ p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period; -+ p->transinfo[tindex].goal_options = 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; -+ 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) ) -+ { -+ 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 = 255; -- p->transinfo[tindex].goal_offset = 0; -- p->transinfo[tindex].goal_options = 0; -- } -- /* -- * 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->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<dev_dtr_cmnd[tindex] == cmd) { -- unsigned int checksum = 0; -- int *ibuffer; -- int i=0; -- -- ibuffer = (int *)buffer; -- for( i = 0; i < (cmd->request_bufflen >> 2); i++) -+ else - { -- checksum += ibuffer[i]; -+ p->needsdtr &= ~(1<needsdtr_copy &= ~(1<transinfo[tindex].goal_period = 255; -+ p->transinfo[tindex].goal_offset = 0; -+ p->transinfo[tindex].goal_options = 0; - } -- p->dev_checksum[tindex] = checksum; -- p->dev_flags[tindex] |= DEVICE_SCANNED; -+ p->dev_flags[tindex] |= DEVICE_DTR_SCANNED; - p->dev_flags[tindex] |= DEVICE_PRINT_DTR; - } - #undef WIDE_INQUIRY_BITS -@@ -3016,7 +2983,8 @@ - #undef SCSI_DT_BIT - } - } -- else if ((scb->flags & SCB_MSGOUT_BITS) != 0) -+ -+ if ((scb->flags & SCB_MSGOUT_BITS) != 0) - { - unsigned short mask; - int message_error = FALSE; -@@ -3036,7 +3004,6 @@ - - if (scb->flags & SCB_MSGOUT_WDTR) - { -- p->dtr_pending &= ~mask; - if (message_error) - { - if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) && -@@ -3055,7 +3022,6 @@ - } - if (scb->flags & SCB_MSGOUT_SDTR) - { -- p->dtr_pending &= ~mask; - if (message_error) - { - if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) && -@@ -3075,7 +3041,6 @@ - } - if (scb->flags & SCB_MSGOUT_PPR) - { -- p->dtr_pending &= ~mask; - if(message_error) - { - if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) && -@@ -3100,6 +3065,7 @@ - } - } - } -+ - queue_depth = p->dev_temp_queue_depth[tindex]; - if (queue_depth >= p->dev_active_cmds[tindex]) - { -@@ -3133,9 +3099,18 @@ - } - } - } -- if ( !(scb->tag_action) && (p->tagenable & (1<tag_action)) -+ { -+ aic7xxx_index_busy_target(p, scb->hscb->target_channel_lun, -+ /* unbusy */ TRUE); -+ if (p->tagenable & (1<dev_temp_queue_depth[tindex] = p->dev_max_queue_depth[tindex]; -+ } -+ } -+ if(scb->flags & SCB_DTR_SCB) - { -- p->dev_temp_queue_depth[tindex] = p->dev_max_queue_depth[tindex]; -+ p->dtr_pending &= ~(1 << tindex); - } - p->dev_active_cmds[tindex]--; - p->activescbs--; -@@ -3244,6 +3219,14 @@ - printk(INFO_LEAD "Aborting scb %d\n", - p->host_no, CTL_OF_SCB(scb), scb->hscb->tag); - found++; -+ /* -+ * Clear any residual information since the normal aic7xxx_done() path -+ * doesn't touch the residuals. -+ */ -+ scb->hscb->residual_SG_segment_count = 0; -+ scb->hscb->residual_data_count[0] = 0; -+ scb->hscb->residual_data_count[1] = 0; -+ scb->hscb->residual_data_count[2] = 0; - aic7xxx_done(p, scb); - } - } -@@ -3456,8 +3439,22 @@ - active_scb = aic_inb(p, SCBPTR); - - if (aic7xxx_verbose & (VERBOSE_RESET_PROCESS | VERBOSE_ABORT_PROCESS)) -+ { - printk(INFO_LEAD "Reset device, active_scb %d\n", - p->host_no, channel, target, lun, active_scb); -+ printk(INFO_LEAD "Current scb_tag %d, SEQADDR 0x%x, LASTPHASE " -+ "0x%x\n", -+ p->host_no, channel, target, lun, aic_inb(p, SCB_TAG), -+ aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8), -+ aic_inb(p, LASTPHASE)); -+ printk(INFO_LEAD "SG_CACHEPTR 0x%x, SG_COUNT %d, SCSISIGI 0x%x\n", -+ p->host_no, channel, target, lun, -+ (p->features & AHC_ULTRA2) ? aic_inb(p, SG_CACHEPTR) : 0, -+ aic_inb(p, SG_COUNT), aic_inb(p, SCSISIGI)); -+ printk(INFO_LEAD "SSTAT0 0x%x, SSTAT1 0x%x, SSTAT2 0x%x\n", -+ p->host_no, channel, target, lun, aic_inb(p, SSTAT0), -+ aic_inb(p, SSTAT1), aic_inb(p, SSTAT2)); -+ } - /* - * Deal with the busy target and linked next issues. - */ -@@ -3501,11 +3498,11 @@ - if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS)) - printk(INFO_LEAD "Cleaning up status information " - "and delayed_scbs.\n", p->host_no, channel, i, lun); -- p->dev_flags[i] &= ~(BUS_DEVICE_RESET_PENDING | DEVICE_PARITY_ERROR); -+ p->dev_flags[i] &= ~BUS_DEVICE_RESET_PENDING; - if ( tag == SCB_LIST_NULL ) - { - p->dev_flags[i] |= DEVICE_PRINT_DTR | DEVICE_RESET_DELAY; -- p->dev_expires[i] = jiffies + (4 * HZ); -+ p->dev_expires[i] = jiffies + (1 * HZ); - p->dev_timer_active |= (0x01 << i); - p->dev_last_queue_full_count[i] = 0; - p->dev_last_queue_full[i] = 0; -@@ -3550,7 +3547,7 @@ - prev_scbp->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE; - } - } -- if ( j > (p->scb_data->maxscbs + 1) ) -+ if ( j > (p->scb_data->numscbs + 1) ) - { - if (aic7xxx_verbose & (VERBOSE_ABORT | VERBOSE_RESET)) - printk(WARN_LEAD "Yikes!! There's a loop in the " -@@ -3611,7 +3608,7 @@ - prev_scbp->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE; - } - } -- if ( j > (p->scb_data->maxscbs + 1) ) -+ if ( j > (p->scb_data->numscbs + 1) ) - { - if (aic7xxx_verbose & (VERBOSE_ABORT | VERBOSE_RESET)) - printk(WARN_LEAD "Yikes!! There's a loop in the " -@@ -4375,11 +4372,25 @@ - if (actual < cmd->underflow) - { - if (aic7xxx_verbose & VERBOSE_MINOR_ERROR) -+ { - printk(INFO_LEAD "Underflow - Wanted %u, %s %u, residual SG " - "count %d.\n", p->host_no, CTL_OF_SCB(scb), cmd->underflow, - (cmd->request.cmd == WRITE) ? "wrote" : "read", actual, - hscb->residual_SG_segment_count); -+ printk(INFO_LEAD "status 0x%x.\n", p->host_no, CTL_OF_SCB(scb), -+ hscb->target_status); -+ } -+ /* -+ * In 2.4, only send back the residual information, don't flag this -+ * as an error. Before 2.4 we had to flag this as an error because -+ * the mid layer didn't check residual data counts to see if the -+ * command needs retried. -+ */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -+ cmd->resid = scb->sg_length - actual; -+#else - aic7xxx_error(cmd) = DID_RETRY_COMMAND; -+#endif - aic7xxx_status(cmd) = hscb->target_status; - } - } -@@ -4698,7 +4709,6 @@ - */ - p->needwdtr &= ~target_mask; - p->needwdtr_copy &= ~target_mask; -- p->dtr_pending &= ~target_mask; - scb->flags &= ~SCB_MSGOUT_BITS; - aic7xxx_set_width(p, target, channel, lun, MSG_EXT_WDTR_BUS_8_BIT, - (AHC_TRANS_ACTIVE|AHC_TRANS_GOAL|AHC_TRANS_CUR)); -@@ -4718,8 +4728,7 @@ - */ - p->needsdtr &= ~target_mask; - p->needsdtr_copy &= ~target_mask; -- p->dtr_pending &= ~target_mask; -- scb->flags &= ~SCB_MSGOUT_SDTR; -+ scb->flags &= ~SCB_MSGOUT_BITS; - aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0, - (AHC_TRANS_CUR|AHC_TRANS_ACTIVE|AHC_TRANS_GOAL)); - if(aic7xxx_verbose & VERBOSE_NEGOTIATION2) -@@ -4852,6 +4861,8 @@ - aic7xxx_error(cmd) = DID_OK; - break; - } /* first time sense, no errors */ -+ printk(INFO_LEAD "CHECK_CONDITION on REQUEST_SENSE, returning " -+ "an error.\n", p->host_no, CTL_OF_SCB(scb)); - aic7xxx_error(cmd) = DID_ERROR; - scb->flags &= ~SCB_SENSE; - break; -@@ -5214,12 +5225,21 @@ - printk(KERN_WARNING " %s seen Data Phase. Length=%d, NumSGs=%d.\n", - (aic_inb(p, SEQ_FLAGS) & DPHASE) ? "Have" : "Haven't", - scb->sg_length, scb->sg_count); -- for (i = 0; i < scb->sg_count; i++) -+ printk(KERN_WARNING " Raw SCSI Command: 0x"); -+ for (i = 0; i < scb->hscb->SCSI_cmd_length; i++) -+ { -+ printk("%02x ", scb->cmd->cmnd[i]); -+ } -+ printk("\n"); -+ if(aic7xxx_verbose > 0xffff) - { -- printk(KERN_WARNING " sg[%d] - Addr 0x%x : Length %d\n", -+ for (i = 0; i < scb->sg_count; i++) -+ { -+ printk(KERN_WARNING " sg[%d] - Addr 0x%x : Length %d\n", - i, - le32_to_cpu(scb->sg_list[i].address), - le32_to_cpu(scb->sg_list[i].length) ); -+ } - } - aic7xxx_error(scb->cmd) = DID_ERROR; - } -@@ -5234,7 +5254,7 @@ - unsigned char resid_sgcnt, index; - unsigned char scb_index = aic_inb(p, SCB_TAG); - unsigned int cur_addr, resid_dcnt; -- unsigned int native_addr, native_length; -+ unsigned int native_addr, native_length, sg_addr; - int i; - - if(scb_index > p->scb_data->numscbs) -@@ -5254,6 +5274,9 @@ - scb->flags, (unsigned int)scb->cmd); - break; - } -+ if(aic7xxx_verbose & VERBOSE_MINOR_ERROR) -+ printk(INFO_LEAD "Got WIDE_RESIDUE message, patching up data " -+ "pointer.\n", p->host_no, CTL_OF_SCB(scb)); - - /* - * We have a valid scb to use on this WIDE_RESIDUE message, so -@@ -5266,132 +5289,87 @@ - */ - cur_addr = aic_inb(p, SHADDR) | (aic_inb(p, SHADDR + 1) << 8) | - (aic_inb(p, SHADDR + 2) << 16) | (aic_inb(p, SHADDR + 3) << 24); -+ sg_addr = aic_inb(p, SG_COUNT + 1) | (aic_inb(p, SG_COUNT + 2) << 8) | -+ (aic_inb(p, SG_COUNT + 3) << 16) | (aic_inb(p, SG_COUNT + 4) << 24); - 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) << 16); -- index = scb->sg_count - (resid_sgcnt + 1); -+ index = scb->sg_count - ((resid_sgcnt) ? resid_sgcnt : 1); - native_addr = le32_to_cpu(scb->sg_list[index].address); - native_length = le32_to_cpu(scb->sg_list[index].length); - /* -- * Make sure this is a valid sg_seg for the given pointer -+ * If resid_dcnt == native_length, then we just loaded this SG -+ * segment and we need to back it up one... - */ -- if(cur_addr < native_addr || -- 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); -- if(index > 0) -- printk(WARN_LEAD " sg_address[-1]:0x%x sg_length[-1]:%d\n", -- 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 " sg_address:0x%x sg_length:%d\n", -- p->host_no, CTL_OF_SCB(scb), -- native_addr, native_length); -- if(resid_sgcnt > 1) -- printk(WARN_LEAD " sg_address[1]:0x%x sg_length[1]:%d\n", -- 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( (resid_sgcnt == 0) && -- ((resid_dcnt == 0) || (resid_dcnt == 0xffffff))) -+ if(resid_dcnt == native_length) - { -- /* -- * 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 " -- "transferred.\n", p->host_no, CTL_OF_SCB(scb)); -+ /* -+ * Oops, this isn't right, we can't back up to before the -+ * beginning. This must be a bogus message, ignore it. -+ */ - break; - } -- resid_sgcnt++; -- index--; -- cur_addr = le32_to_cpu(scb->sg_list[index].address) + -- le32_to_cpu(scb->sg_list[index].length) - 1; -- native_addr = aic_inb(p, SG_NEXT) | (aic_inb(p, SG_NEXT + 1) << 8) -- | (aic_inb(p, SG_NEXT + 2) << 16) | (aic_inb(p, SG_NEXT + 3) << 24); -- native_addr -= SG_SIZEOF; -- aic_outb(p, resid_sgcnt, SG_COUNT); -- aic_outb(p, resid_sgcnt, SCB_RESID_SGCNT); -- aic_outb(p, native_addr & 0xff, SG_NEXT); -- aic_outb(p, (native_addr >> 8) & 0xff, SG_NEXT + 1); -- aic_outb(p, (native_addr >> 16) & 0xff, SG_NEXT + 2); -- aic_outb(p, (native_addr >> 24) & 0xff, SG_NEXT + 3); -- aic_outb(p, 1, SCB_RESID_DCNT); -- aic_outb(p, 0, SCB_RESID_DCNT + 1); -- aic_outb(p, 0, SCB_RESID_DCNT + 2); -- aic_outb(p, 1, HCNT); -- aic_outb(p, 0, HCNT + 1); -- aic_outb(p, 0, HCNT + 2); -- aic_outb(p, cur_addr & 0xff, HADDR); -- 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); -+ resid_dcnt = 1; -+ resid_sgcnt += 1; -+ native_addr = le32_to_cpu(scb->sg_list[index - 1].address); -+ native_length = le32_to_cpu(scb->sg_list[index - 1].length); -+ cur_addr = native_addr + (native_length - 1); -+ sg_addr -= sizeof(struct hw_scatterlist); - } - else - { - /* -- * Back the data pointer up by one and add one to the remaining -- * byte count. Then store that in the HCNT and HADDR registers. -+ * resid_dcnt != native_length, so we are in the middle of a SG -+ * element. Back it up one byte and leave the rest alone. - */ -- cur_addr--; -- resid_dcnt++; -- aic_outb(p, resid_dcnt & 0xff, SCB_RESID_DCNT); -- aic_outb(p, (resid_dcnt >> 8) & 0xff, SCB_RESID_DCNT + 1); -- aic_outb(p, (resid_dcnt >> 16) & 0xff, SCB_RESID_DCNT + 2); -- aic_outb(p, resid_dcnt & 0xff, HCNT); -- aic_outb(p, (resid_dcnt >> 8) & 0xff, HCNT + 1); -- aic_outb(p, (resid_dcnt >> 16) & 0xff, HCNT + 2); -- aic_outb(p, cur_addr & 0xff, HADDR); -- 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); -+ resid_dcnt += 1; -+ cur_addr -= 1; - } -+ -+ /* -+ * Output the new addresses and counts to the right places on the -+ * card. -+ */ -+ aic_outb(p, resid_sgcnt, SG_COUNT); -+ aic_outb(p, resid_sgcnt, SCB_RESID_SGCNT); -+ aic_outb(p, sg_addr & 0xff, SG_COUNT + 1); -+ aic_outb(p, (sg_addr >> 8) & 0xff, SG_COUNT + 2); -+ aic_outb(p, (sg_addr >> 16) & 0xff, SG_COUNT + 3); -+ aic_outb(p, (sg_addr >> 24) & 0xff, SG_COUNT + 4); -+ aic_outb(p, resid_dcnt & 0xff, SCB_RESID_DCNT); -+ aic_outb(p, (resid_dcnt >> 8) & 0xff, SCB_RESID_DCNT + 1); -+ aic_outb(p, (resid_dcnt >> 16) & 0xff, SCB_RESID_DCNT + 2); -+ - /* -- * 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. -+ * The sequencer actually wants to find the new address -+ * in the SHADDR register set. On the Ultra2 and later controllers -+ * this register set is readonly. In order to get the right number -+ * into the register, you actually have to enter it in HADDR and then -+ * use the PRELOADEN bit of DFCNTRL to drop it through from the -+ * HADDR register to the SHADDR register. On non-Ultra2 controllers, -+ * we simply write it direct. - */ - if(p->features & AHC_ULTRA2) - { -- aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL); -- i=0; -+ /* -+ * We might as well be accurate and drop both the resid_dcnt and -+ * cur_addr into HCNT and HADDR and have both of them drop -+ * through to the shadow layer together. -+ */ -+ aic_outb(p, resid_dcnt & 0xff, HCNT); -+ aic_outb(p, (resid_dcnt >> 8) & 0xff, HCNT + 1); -+ aic_outb(p, (resid_dcnt >> 16) & 0xff, HCNT + 2); -+ aic_outb(p, cur_addr & 0xff, HADDR); -+ 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); -+ aic_outb(p, aic_inb(p, DMAPARAMS) | PRELOADEN, DFCNTRL); - udelay(1); -- while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000)) -- { -- udelay(1); -- } - aic_outb(p, aic_inb(p, DMAPARAMS) & ~(SCSIEN|HDMAEN), DFCNTRL); - i=0; -- udelay(1); - while(((aic_inb(p, DFCNTRL) & (SCSIEN|HDMAEN)) != 0) && (i++ < 1000)) - { - udelay(1); -@@ -5399,9 +5377,6 @@ - } - 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); -@@ -5410,15 +5385,82 @@ - } - break; - -- --#if AIC7XXX_NOT_YET -- case TRACEPOINT: -+ case SEQ_SG_FIXUP: -+ { -+ unsigned char scb_index, tmp; -+ int sg_addr, sg_length; -+ -+ scb_index = aic_inb(p, SCB_TAG); -+ -+ if(scb_index > p->scb_data->numscbs) - { -- printk(INFO_LEAD "Tracepoint #1 reached.\n", p->host_no, -- channel, target, lun); -+ printk(WARN_LEAD "invalid scb_index during SEQ_SG_FIXUP.\n", -+ p->host_no, -1, -1, -1); -+ printk(INFO_LEAD "SCSISIGI 0x%x, SEQADDR 0x%x, SSTAT0 0x%x, SSTAT1 " -+ "0x%x\n", p->host_no, -1, -1, -1, -+ aic_inb(p, SCSISIGI), -+ aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8), -+ aic_inb(p, SSTAT0), aic_inb(p, SSTAT1)); -+ printk(INFO_LEAD "SG_CACHEPTR 0x%x, SSTAT2 0x%x, STCNT 0x%x\n", -+ p->host_no, -1, -1, -1, aic_inb(p, SG_CACHEPTR), -+ aic_inb(p, SSTAT2), aic_inb(p, STCNT + 2) << 16 | -+ aic_inb(p, STCNT + 1) << 8 | aic_inb(p, STCNT)); -+ /* -+ * XXX: Add error handling here -+ */ -+ break; - } -- break; -+ scb = p->scb_data->scb_array[scb_index]; -+ if(!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL)) -+ { -+ printk(WARN_LEAD "invalid scb during SEQ_SG_FIXUP flags:0x%x " -+ "scb->cmd:0x%x\n", p->host_no, CTL_OF_SCB(scb), -+ scb->flags, (unsigned int)scb->cmd); -+ printk(INFO_LEAD "SCSISIGI 0x%x, SEQADDR 0x%x, SSTAT0 0x%x, SSTAT1 " -+ "0x%x\n", p->host_no, CTL_OF_SCB(scb), -+ aic_inb(p, SCSISIGI), -+ aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8), -+ aic_inb(p, SSTAT0), aic_inb(p, SSTAT1)); -+ printk(INFO_LEAD "SG_CACHEPTR 0x%x, SSTAT2 0x%x, STCNT 0x%x\n", -+ p->host_no, CTL_OF_SCB(scb), aic_inb(p, SG_CACHEPTR), -+ aic_inb(p, SSTAT2), aic_inb(p, STCNT + 2) << 16 | -+ aic_inb(p, STCNT + 1) << 8 | aic_inb(p, STCNT)); -+ break; -+ } -+ if(aic7xxx_verbose & VERBOSE_MINOR_ERROR) -+ printk(INFO_LEAD "Fixing up SG address for sequencer.\n", p->host_no, -+ CTL_OF_SCB(scb)); -+ /* -+ * Advance the SG pointer to the next element in the list -+ */ -+ tmp = aic_inb(p, SG_NEXT); -+ tmp += SG_SIZEOF; -+ aic_outb(p, tmp, SG_NEXT); -+ if( tmp < SG_SIZEOF ) -+ aic_outb(p, aic_inb(p, SG_NEXT + 1) + 1, SG_NEXT + 1); -+ tmp = aic_inb(p, SG_COUNT) - 1; -+ aic_outb(p, tmp, SG_COUNT); -+ sg_addr = le32_to_cpu(scb->sg_list[scb->sg_count - tmp].address); -+ sg_length = le32_to_cpu(scb->sg_list[scb->sg_count - tmp].length); -+ /* -+ * Now stuff the element we just advanced past down onto the -+ * card so it can be stored in the residual area. -+ */ -+ aic_outb(p, sg_addr & 0xff, HADDR); -+ aic_outb(p, (sg_addr >> 8) & 0xff, HADDR + 1); -+ aic_outb(p, (sg_addr >> 16) & 0xff, HADDR + 2); -+ aic_outb(p, (sg_addr >> 24) & 0xff, HADDR + 3); -+ aic_outb(p, sg_length & 0xff, HCNT); -+ aic_outb(p, (sg_length >> 8) & 0xff, HCNT + 1); -+ aic_outb(p, (sg_length >> 16) & 0xff, HCNT + 2); -+ aic_outb(p, (tmp << 2) | ((tmp == 1) ? LAST_SEG : 0), SG_CACHEPTR); -+ aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL); -+ while(aic_inb(p, SSTAT0) & SDONE) udelay(1); -+ while(aic_inb(p, DFCNTRL) & (HDMAEN|SCSIEN)) aic_outb(p, 0, DFCNTRL); -+ } -+ break; - -+#if AIC7XXX_NOT_YET - case TRACEPOINT2: - { - printk(INFO_LEAD "Tracepoint #2 reached.\n", p->host_no, -@@ -5463,6 +5505,10 @@ - unsigned char target_scsirate, tindex; - unsigned short target_mask; - unsigned char target, channel, lun; -+ unsigned char bus_width, new_bus_width; -+ unsigned char trans_options, new_trans_options; -+ unsigned int period, new_period, offset, new_offset, maxsync; -+ struct aic7xxx_syncrate *syncrate; - - target = scb->cmd->target; - channel = scb->cmd->channel; -@@ -5486,6 +5532,35 @@ - } - - /* -+ * Even if we are an Ultra3 card, don't allow Ultra3 sync rates when -+ * using the SDTR messages. We need the PPR messages to enable the -+ * higher speeds that include things like Dual Edge clocking. -+ */ -+ if (p->features & AHC_ULTRA2) -+ { -+ if ( (aic_inb(p, SBLKCTL) & ENAB40) && -+ !(aic_inb(p, SSTAT2) & EXP_ACTIVE) ) -+ { -+ if (p->features & AHC_ULTRA3) -+ maxsync = AHC_SYNCRATE_ULTRA3; -+ else -+ maxsync = AHC_SYNCRATE_ULTRA2; -+ } -+ else -+ { -+ maxsync = AHC_SYNCRATE_ULTRA; -+ } -+ } -+ else if (p->features & AHC_ULTRA) -+ { -+ maxsync = AHC_SYNCRATE_ULTRA; -+ } -+ else -+ { -+ maxsync = AHC_SYNCRATE_FAST; -+ } -+ -+ /* - * Just accept the length byte outright and perform - * more checking once we know the message type. - */ -@@ -5496,9 +5571,6 @@ - { - case MSG_EXT_SDTR: - { -- unsigned int period, offset; -- unsigned char maxsync, saved_offset, options; -- struct aic7xxx_syncrate *syncrate; - - if (p->msg_buf[1] != MSG_EXT_SDTR_LEN) - { -@@ -5511,35 +5583,18 @@ - break; - } - -- period = p->msg_buf[3]; -- saved_offset = offset = p->msg_buf[4]; -- options = 0; -+ period = new_period = p->msg_buf[3]; -+ offset = new_offset = p->msg_buf[4]; -+ trans_options = new_trans_options = 0; -+ bus_width = new_bus_width = target_scsirate & WIDEXFER; - - /* -- * Even if we are an Ultra3 card, don't allow Ultra3 sync rates when -- * using the SDTR messages. We need the PPR messages to enable the -- * higher speeds that include things like Dual Edge clocking. -+ * If our current max syncrate is in the Ultra3 range, bump it back -+ * down to Ultra2 since we can't negotiate DT transfers using SDTR - */ -- if (p->features & AHC_ULTRA2) -- { -- if ( (aic_inb(p, SBLKCTL) & ENAB40) && -- !(aic_inb(p, SSTAT2) & EXP_ACTIVE) ) -- { -- maxsync = AHC_SYNCRATE_ULTRA2; -- } -- else -- { -- maxsync = AHC_SYNCRATE_ULTRA; -- } -- } -- else if (p->features & AHC_ULTRA) -- { -- maxsync = AHC_SYNCRATE_ULTRA; -- } -- else -- { -- maxsync = AHC_SYNCRATE_FAST; -- } -+ if(maxsync == AHC_SYNCRATE_ULTRA3) -+ maxsync = AHC_SYNCRATE_ULTRA2; -+ - /* - * We might have a device that is starting negotiation with us - * before we can start up negotiation with it....be prepared to -@@ -5549,88 +5604,116 @@ - if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) != - (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) - { -- if (!(p->dev_flags[tindex] & DEVICE_SCANNED) && -- !(p->needsdtr_copy & target_mask) && -- (p->transinfo[tindex].user_offset) ) -+ if (!(p->dev_flags[tindex] & DEVICE_DTR_SCANNED)) - { - /* -- * Not only is the device starting this up, but it also hasn't -- * been scanned yet, so this would likely be our TUR or our -- * INQUIRY command at scan time, so we need to use the -- * settings from the SEEPROM if they existed. Of course, even -- * if we didn't find a SEEPROM, we stuffed default values into -- * the user settings anyway, so use those in all cases. -+ * We shouldn't get here unless this is a narrow drive, wide -+ * devices should trigger this same section of code in the WDTR -+ * handler first instead. - */ -- p->transinfo[tindex].goal_period = -- p->transinfo[tindex].user_period; -- if(p->features & AHC_ULTRA2) -- { -- p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2; -- } -- else if (p->transinfo[tindex].cur_width) -+ p->transinfo[tindex].goal_width = MSG_EXT_WDTR_BUS_8_BIT; -+ p->transinfo[tindex].goal_options = 0; -+ if(p->transinfo[tindex].user_offset) - { -- p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT; -+ p->needsdtr_copy |= target_mask; -+ p->transinfo[tindex].goal_period = -+ MAX(10,p->transinfo[tindex].user_period); -+ if(p->features & AHC_ULTRA2) -+ { -+ p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2; -+ } -+ else -+ { -+ p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT; -+ } - } - else - { -- p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT; -+ p->needsdtr_copy &= ~target_mask; -+ p->transinfo[tindex].goal_period = 255; -+ p->transinfo[tindex].goal_offset = 0; - } -- p->needsdtr_copy |= target_mask; -+ p->dev_flags[tindex] |= DEVICE_DTR_SCANNED | DEVICE_PRINT_DTR; -+ } -+ else if ((p->needsdtr_copy & target_mask) == 0) -+ { -+ /* -+ * This is a preemptive message from the target, we've already -+ * scanned this target and set our options for it, and we -+ * don't need a WDTR with this target (for whatever reason), -+ * so reject this incoming WDTR -+ */ -+ reject = TRUE; -+ break; - } -+ -+ /* The device is sending this message first and we have to reply */ -+ reply = TRUE; -+ - if (aic7xxx_verbose & VERBOSE_NEGOTIATION2) - { - printk(INFO_LEAD "Received pre-emptive SDTR message from " - "target.\n", p->host_no, CTL_OF_SCB(scb)); - } -- if ( !p->transinfo[tindex].goal_offset ) -- period = 255; -- if ( p->transinfo[tindex].goal_period > period ) -- period = p->transinfo[tindex].goal_period; -+ /* -+ * Validate the values the device passed to us against our SEEPROM -+ * settings. We don't have to do this if we aren't replying since -+ * the device isn't allowed to send values greater than the ones -+ * we first sent to it. -+ */ -+ new_period = MAX(period, p->transinfo[tindex].goal_period); -+ new_offset = MIN(offset, p->transinfo[tindex].goal_offset); - } -- -- syncrate = aic7xxx_find_syncrate(p, &period, maxsync, &options); -- aic7xxx_validate_offset(p, syncrate, &offset, -- target_scsirate & WIDEXFER); -- aic7xxx_set_syncrate(p, syncrate, target, channel, period, -- offset, options, AHC_TRANS_ACTIVE|AHC_TRANS_CUR); -+ -+ /* -+ * Use our new_period, new_offset, bus_width, and card options -+ * to determine the actual syncrate settings -+ */ -+ syncrate = aic7xxx_find_syncrate(p, &new_period, maxsync, -+ &trans_options); -+ aic7xxx_validate_offset(p, syncrate, &new_offset, bus_width); - - /* -- * Did we drop to async? Or are we sending a reply? If we are, -- * then we have to make sure that the reply value reflects the proper -- * settings so we need to set the goal values according to what -- * we need to send. -+ * Did we drop to async? If so, send a reply regardless of whether -+ * or not we initiated this negotiation. - */ -- if ( (offset != saved_offset) || -- ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) != -- (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) ) -+ if ((new_offset == 0) && (new_offset != offset)) - { -- aic7xxx_set_syncrate(p, syncrate, target, channel, period, offset, -- options, AHC_TRANS_GOAL|AHC_TRANS_QUITE); -+ p->needsdtr_copy &= ~target_mask; -+ reply = TRUE; - } - - /* -- * Did we start this, if not, or if we went to low and had to -+ * Did we start this, if not, or if we went too low and had to - * go async, then send an SDTR back to the target - */ -- p->needsdtr &= ~target_mask; -- p->dtr_pending &= ~target_mask; -- if ( ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) != -- (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) || -- (offset != saved_offset) ) -+ if(reply) - { -- reply = TRUE; -- p->dtr_pending |= target_mask; -+ /* when sending a reply, make sure that the goal settings are -+ * updated along with current and active since the code that -+ * will actually build the message for the sequencer uses the -+ * goal settings as its guidelines. -+ */ -+ aic7xxx_set_syncrate(p, syncrate, target, channel, new_period, -+ new_offset, trans_options, -+ AHC_TRANS_GOAL|AHC_TRANS_ACTIVE|AHC_TRANS_CUR); - scb->flags &= ~SCB_MSGOUT_BITS; - scb->flags |= SCB_MSGOUT_SDTR; - aic_outb(p, HOST_MSG, MSG_OUT); - aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO); - } -+ else -+ { -+ aic7xxx_set_syncrate(p, syncrate, target, channel, new_period, -+ new_offset, trans_options, -+ AHC_TRANS_ACTIVE|AHC_TRANS_CUR); -+ p->needsdtr &= ~target_mask; -+ } - done = TRUE; - break; - } - case MSG_EXT_WDTR: - { -- unsigned char bus_width; - - if (p->msg_buf[1] != MSG_EXT_WDTR_LEN) - { -@@ -5643,7 +5726,8 @@ - break; - } - -- bus_width = p->msg_buf[3]; -+ bus_width = new_bus_width = p->msg_buf[3]; -+ - if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_WDTR)) == - (SCB_MSGOUT_SENT|SCB_MSGOUT_WDTR) ) - { -@@ -5662,7 +5746,7 @@ - } /* We fall through on purpose */ - case MSG_EXT_WDTR_BUS_8_BIT: - { -- bus_width = MSG_EXT_WDTR_BUS_8_BIT; -+ p->transinfo[tindex].goal_width = MSG_EXT_WDTR_BUS_8_BIT; - p->needwdtr_copy &= ~target_mask; - break; - } -@@ -5671,29 +5755,40 @@ - break; - } - } -- p->dtr_pending &= ~target_mask; - p->needwdtr &= ~target_mask; -+ aic7xxx_set_width(p, target, channel, lun, new_bus_width, -+ AHC_TRANS_ACTIVE|AHC_TRANS_CUR); - } - else - { -- if ( !(p->dev_flags[tindex] & DEVICE_SCANNED) ) -+ if ( !(p->dev_flags[tindex] & DEVICE_DTR_SCANNED) ) - { - /* - * Well, we now know the WDTR and SYNC caps of this device since - * it contacted us first, mark it as such and copy the user stuff - * over to the goal stuff. - */ -- p->transinfo[tindex].goal_period = -- p->transinfo[tindex].user_period; -+ if( (p->features & AHC_WIDE) && p->transinfo[tindex].user_width ) -+ { -+ p->transinfo[tindex].goal_width = MSG_EXT_WDTR_BUS_16_BIT; -+ p->needwdtr_copy |= target_mask; -+ } -+ -+ /* -+ * Devices that support DT transfers don't start WDTR requests -+ */ -+ p->transinfo[tindex].goal_options = 0; -+ - if(p->transinfo[tindex].user_offset) - { -+ p->needsdtr_copy |= target_mask; -+ p->transinfo[tindex].goal_period = -+ MAX(10,p->transinfo[tindex].user_period); - if(p->features & AHC_ULTRA2) - { - p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2; - } -- else if( p->transinfo[tindex].user_width && -- (bus_width == MSG_EXT_WDTR_BUS_16_BIT) && -- p->features & AHC_WIDE ) -+ else if( p->transinfo[tindex].goal_width ) - { - p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT; - } -@@ -5701,48 +5796,76 @@ - { - p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT; - } -+ } else { -+ p->needsdtr_copy &= ~target_mask; -+ p->transinfo[tindex].goal_period = 255; -+ p->transinfo[tindex].goal_offset = 0; - } -- p->transinfo[tindex].goal_width = -- p->transinfo[tindex].user_width; -- p->needwdtr_copy |= target_mask; -- p->needsdtr_copy |= target_mask; -+ -+ p->dev_flags[tindex] |= DEVICE_DTR_SCANNED | DEVICE_PRINT_DTR; - } -- if (aic7xxx_verbose & VERBOSE_NEGOTIATION2) -+ else if ((p->needwdtr_copy & target_mask) == 0) - { -- printk(INFO_LEAD "Received pre-emptive WDTR message from " -- "target.\n", p->host_no, CTL_OF_SCB(scb)); -- } -+ /* -+ * This is a preemptive message from the target, we've already -+ * scanned this target and set our options for it, and we -+ * don't need a WDTR with this target (for whatever reason), -+ * so reject this incoming WDTR -+ */ -+ reject = TRUE; -+ break; -+ } -+ -+ /* The device is sending this message first and we have to reply */ -+ reply = TRUE; -+ -+ if (aic7xxx_verbose & VERBOSE_NEGOTIATION2) -+ { -+ printk(INFO_LEAD "Received pre-emptive WDTR message from " -+ "target.\n", p->host_no, CTL_OF_SCB(scb)); -+ } - switch(bus_width) - { -- default: -+ case MSG_EXT_WDTR_BUS_16_BIT: - { - if ( (p->features & AHC_WIDE) && - (p->transinfo[tindex].goal_width == - MSG_EXT_WDTR_BUS_16_BIT) ) - { -- bus_width = MSG_EXT_WDTR_BUS_16_BIT; -+ new_bus_width = MSG_EXT_WDTR_BUS_16_BIT; - break; - } - } /* Fall through if we aren't a wide card */ -+ default: - case MSG_EXT_WDTR_BUS_8_BIT: - { - p->needwdtr_copy &= ~target_mask; -- bus_width = MSG_EXT_WDTR_BUS_8_BIT; -- aic7xxx_set_width(p, target, channel, lun, bus_width, -- AHC_TRANS_GOAL|AHC_TRANS_QUITE); -+ new_bus_width = MSG_EXT_WDTR_BUS_8_BIT; - break; - } - } -- reply = TRUE; - scb->flags &= ~SCB_MSGOUT_BITS; - scb->flags |= SCB_MSGOUT_WDTR; - p->needwdtr &= ~target_mask; -- p->dtr_pending |= target_mask; -+ if((p->dtr_pending & target_mask) == 0) -+ { -+ /* there is no other command with SCB_DTR_SCB already set that will -+ * trigger the release of the dtr_pending bit. Both set the bit -+ * and set scb->flags |= SCB_DTR_SCB -+ */ -+ p->dtr_pending |= target_mask; -+ scb->flags |= SCB_DTR_SCB; -+ } - aic_outb(p, HOST_MSG, MSG_OUT); - aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO); -+ /* when sending a reply, make sure that the goal settings are -+ * updated along with current and active since the code that -+ * will actually build the message for the sequencer uses the -+ * goal settings as its guidelines. -+ */ -+ aic7xxx_set_width(p, target, channel, lun, new_bus_width, -+ AHC_TRANS_GOAL|AHC_TRANS_ACTIVE|AHC_TRANS_CUR); - } -- aic7xxx_set_width(p, target, channel, lun, bus_width, -- AHC_TRANS_ACTIVE|AHC_TRANS_CUR); - - /* - * By virtue of the SCSI spec, a WDTR message negates any existing -@@ -5759,10 +5882,6 @@ - } - case MSG_EXT_PPR: - { -- unsigned char bus_width, trans_options, new_trans_options; -- unsigned int period, offset; -- unsigned char maxsync, saved_offset; -- struct aic7xxx_syncrate *syncrate; - - if (p->msg_buf[1] != MSG_EXT_PPR_LEN) - { -@@ -5775,9 +5894,9 @@ - break; - } - -- period = p->msg_buf[3]; -- offset = saved_offset = p->msg_buf[5]; -- bus_width = p->msg_buf[6]; -+ period = new_period = p->msg_buf[3]; -+ offset = new_offset = p->msg_buf[5]; -+ bus_width = new_bus_width = p->msg_buf[6]; - trans_options = new_trans_options = p->msg_buf[7] & 0xf; - - if(aic7xxx_verbose & VERBOSE_NEGOTIATION2) -@@ -5787,22 +5906,6 @@ - trans_options); - } - -- if ( (aic_inb(p, SBLKCTL) & ENAB40) && -- !(aic_inb(p, SSTAT2) & EXP_ACTIVE) ) -- { -- if(p->features & AHC_ULTRA3) -- { -- maxsync = AHC_SYNCRATE_ULTRA3; -- } -- else -- { -- maxsync = AHC_SYNCRATE_ULTRA2; -- } -- } -- else -- { -- maxsync = AHC_SYNCRATE_ULTRA; -- } - /* - * We might have a device that is starting negotiation with us - * before we can start up negotiation with it....be prepared to -@@ -5811,13 +5914,22 @@ - */ - if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) != - (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR) ) -- { -- 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)) -- { -+ { -+ /* Have we scanned the device yet? */ -+ if (!(p->dev_flags[tindex] & DEVICE_DTR_SCANNED)) -+ { -+ /* The device is electing to use PPR messages, so we will too until -+ * we know better */ -+ p->needppr |= target_mask; -+ p->needppr_copy |= target_mask; -+ p->needsdtr &= ~target_mask; -+ p->needsdtr_copy &= ~target_mask; -+ p->needwdtr &= ~target_mask; -+ p->needwdtr_copy &= ~target_mask; -+ -+ /* We know the device is SCSI-3 compliant due to PPR */ -+ p->dev_flags[tindex] |= DEVICE_SCSI_3; -+ - /* - * Not only is the device starting this up, but it also hasn't - * been scanned yet, so this would likely be our TUR or our -@@ -5826,15 +5938,19 @@ - * if we didn't find a SEEPROM, we stuffed default values into - * the user settings anyway, so use those in all cases. - */ -- p->transinfo[tindex].goal_period = -- p->transinfo[tindex].user_period; -+ p->transinfo[tindex].goal_width = -+ p->transinfo[tindex].user_width; - if(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->features & AHC_ULTRA2) - { - p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2; - } -- else if( p->transinfo[tindex].user_width && -+ else if( p->transinfo[tindex].goal_width && - (bus_width == MSG_EXT_WDTR_BUS_16_BIT) && - p->features & AHC_WIDE ) - { -@@ -5845,117 +5961,142 @@ - p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT; - } - } -- p->transinfo[tindex].goal_width = -- p->transinfo[tindex].user_width; -- p->transinfo[tindex].goal_options = -- p->transinfo[tindex].user_options; -+ else -+ { -+ p->transinfo[tindex].goal_period = 255; -+ p->transinfo[tindex].goal_offset = 0; -+ p->transinfo[tindex].goal_options = 0; -+ } -+ p->dev_flags[tindex] |= DEVICE_DTR_SCANNED | DEVICE_PRINT_DTR; -+ } -+ else if ((p->needppr_copy & target_mask) == 0) -+ { -+ /* -+ * This is a preemptive message from the target, we've already -+ * scanned this target and set our options for it, and we -+ * don't need a PPR with this target (for whatever reason), -+ * so reject this incoming PPR -+ */ -+ reject = TRUE; -+ break; - } -+ -+ /* The device is sending this message first and we have to reply */ -+ reply = TRUE; -+ - if (aic7xxx_verbose & VERBOSE_NEGOTIATION2) - { - printk(INFO_LEAD "Received pre-emptive PPR message from " - "target.\n", p->host_no, CTL_OF_SCB(scb)); - } -- if ( !p->transinfo[tindex].goal_offset ) -- period = 255; -- if ( p->transinfo[tindex].goal_period > period ) -- period = p->transinfo[tindex].goal_period; -- if ( p->transinfo[tindex].goal_options == 0 ) -- new_trans_options = 0; -- switch(bus_width) -+ -+ } -+ -+ switch(bus_width) -+ { -+ case MSG_EXT_WDTR_BUS_16_BIT: - { -- default: -- { -- if ( (p->features & AHC_WIDE) && -- (p->transinfo[tindex].goal_width == -- MSG_EXT_WDTR_BUS_16_BIT) ) -- { -- bus_width = MSG_EXT_WDTR_BUS_16_BIT; -- break; -- } -- } /* Fall through if we aren't a wide card */ -- case MSG_EXT_WDTR_BUS_8_BIT: -+ if ( (p->transinfo[tindex].goal_width == -+ MSG_EXT_WDTR_BUS_16_BIT) && p->features & AHC_WIDE) - { -- p->needwdtr_copy &= ~target_mask; -- bus_width = MSG_EXT_WDTR_BUS_8_BIT; -- aic7xxx_set_width(p, target, channel, lun, bus_width, -- AHC_TRANS_GOAL|AHC_TRANS_QUITE); - break; - } - } -- if ( (p->transinfo[tindex].goal_period > 9) || -- (p->transinfo[tindex].goal_options == 0) ) -+ default: - { -- 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); -+ if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) && -+ ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) || -+ (aic7xxx_verbose > 0xffff)) ) -+ { -+ reply = TRUE; -+ printk(INFO_LEAD "Requesting %d bit transfers, rejecting.\n", -+ p->host_no, CTL_OF_SCB(scb), 8 * (0x01 << bus_width)); - } -+ } /* We fall through on purpose */ -+ case MSG_EXT_WDTR_BUS_8_BIT: -+ { -+ /* -+ * According to the spec, if we aren't wide, we also can't be -+ * Dual Edge so clear the options byte -+ */ -+ new_trans_options = 0; -+ new_bus_width = MSG_EXT_WDTR_BUS_8_BIT; -+ break; - } - } -+ -+ if(reply) -+ { -+ /* when sending a reply, make sure that the goal settings are -+ * updated along with current and active since the code that -+ * will actually build the message for the sequencer uses the -+ * goal settings as its guidelines. -+ */ -+ aic7xxx_set_width(p, target, channel, lun, new_bus_width, -+ AHC_TRANS_GOAL|AHC_TRANS_ACTIVE|AHC_TRANS_CUR); -+ syncrate = aic7xxx_find_syncrate(p, &new_period, maxsync, -+ &new_trans_options); -+ aic7xxx_validate_offset(p, syncrate, &new_offset, new_bus_width); -+ aic7xxx_set_syncrate(p, syncrate, target, channel, new_period, -+ new_offset, new_trans_options, -+ AHC_TRANS_GOAL|AHC_TRANS_ACTIVE|AHC_TRANS_CUR); -+ } - else - { -- switch(bus_width) -+ aic7xxx_set_width(p, target, channel, lun, new_bus_width, -+ AHC_TRANS_ACTIVE|AHC_TRANS_CUR); -+ syncrate = aic7xxx_find_syncrate(p, &new_period, maxsync, -+ &new_trans_options); -+ aic7xxx_validate_offset(p, syncrate, &new_offset, new_bus_width); -+ aic7xxx_set_syncrate(p, syncrate, target, channel, new_period, -+ new_offset, new_trans_options, -+ AHC_TRANS_ACTIVE|AHC_TRANS_CUR); -+ } -+ -+ /* -+ * As it turns out, if we don't *have* to have PPR messages, then -+ * configure ourselves not to use them since that makes some -+ * external drive chassis work (those chassis can't parse PPR -+ * messages and they mangle the SCSI bus until you send a WDTR -+ * and SDTR that they can understand). -+ */ -+ if(new_trans_options == 0) -+ { -+ p->needppr &= ~target_mask; -+ p->needppr_copy &= ~target_mask; -+ if(new_offset) - { -- default: -- { -- reject = TRUE; -- if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) && -- ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) || -- (aic7xxx_verbose > 0xffff)) ) -- { -- printk(INFO_LEAD "Requesting %d bit transfers, rejecting.\n", -- p->host_no, CTL_OF_SCB(scb), 8 * (0x01 << bus_width)); -- } -- } /* We fall through on purpose */ -- case MSG_EXT_WDTR_BUS_8_BIT: -- { -- /* -- * According to the spec, if we aren't wide, we also can't be -- * Dual Edge so clear the options byte -- */ -- new_trans_options = 0; -- bus_width = MSG_EXT_WDTR_BUS_8_BIT; -- break; -- } -- case MSG_EXT_WDTR_BUS_16_BIT: -- { -- break; -- } -+ p->needsdtr |= target_mask; -+ p->needsdtr_copy |= target_mask; -+ } -+ if (new_bus_width) -+ { -+ p->needwdtr |= target_mask; -+ p->needwdtr_copy |= target_mask; - } - } - -- if ( !reject ) -+ if((new_offset == 0) && (offset != 0)) - { -- 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); -+ /* -+ * Oops, the syncrate went to low for this card and we fell off -+ * to async (should never happen with a device that uses PPR -+ * messages, but have to be complete) -+ */ -+ reply = TRUE; - } - -- p->dtr_pending &= ~target_mask; -- p->needppr &= ~target_mask; - if(reply) - { -- p->dtr_pending |= target_mask; - scb->flags &= ~SCB_MSGOUT_BITS; - scb->flags |= SCB_MSGOUT_PPR; - aic_outb(p, HOST_MSG, MSG_OUT); - aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO); - } -+ else -+ { -+ p->needppr &= ~target_mask; -+ } - done = TRUE; - break; - } -@@ -6193,16 +6334,14 @@ - printerror = 0; - } - } -- if ( (scb != NULL) && -- (scb->cmd == p->dev_dtr_cmnd[TARGET_INDEX(scb->cmd)]) ) -+ if ( (scb != NULL) && (scb->flags & SCB_DTR_SCB) ) - { - /* -- * This might be a SCSI-3 device that is dropping the bus due to -- * errors and signalling that we should reduce the transfer speed. -- * All we have to do is complete this command (since it's a negotiation -- * command already) and the checksum routine should flag an error and -- * reduce the speed setting and renegotiate. We call the reset routing -- * just to clean out the hardware from this scb. -+ * Hmmm...error during a negotiation command. Either we have a -+ * borken bus, or the device doesn't like our negotiation message. -+ * Since we check the INQUIRY data of a device before sending it -+ * negotiation messages, assume the bus is borken for whatever -+ * reason. Complete the command. - */ - printerror = 0; - aic7xxx_reset_device(p, target, channel, ALL_LUNS, scb->hscb->tag); -@@ -6334,19 +6473,6 @@ - cmd->result = 0; - scb = NULL; - } -- else if (scb->cmd == p->dev_dtr_cmnd[TARGET_INDEX(scb->cmd)]) -- { -- /* -- * Turn off the needsdtr, needwdtr, and needppr bits since this device -- * doesn't seem to exist. -- */ -- p->needppr &= ~(0x01 << TARGET_INDEX(scb->cmd)); -- p->needppr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd)); -- p->needsdtr &= ~(0x01 << TARGET_INDEX(scb->cmd)); -- p->needsdtr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd)); -- p->needwdtr &= ~(0x01 << TARGET_INDEX(scb->cmd)); -- p->needwdtr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd)); -- } - } - /* - * Keep the sequencer from trying to restart any selections -@@ -6469,7 +6595,6 @@ - } - } - else if( (lastphase == P_MESGOUT) && -- (cmd == p->dev_dtr_cmnd[tindex]) && - (scb->flags & SCB_MSGOUT_PPR) ) - { - /* -@@ -6488,7 +6613,6 @@ - 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) - { -@@ -6511,87 +6635,6 @@ - } - scb = NULL; - } -- else if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR) -- { -- struct aic7xxx_syncrate *syncrate; -- unsigned int period = p->transinfo[tindex].cur_period; -- unsigned char options = p->transinfo[tindex].cur_options; -- /* -- * oops, we had a failure, lower the transfer rate and try again. It's -- * worth noting here that it might be wise to also check for typical -- * wide setting on narrow cable type problems and try disabling wide -- * 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++; -- if( (syncrate->rate[0] != NULL) && -- (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) ) -- { -- p->transinfo[tindex].goal_period = syncrate->period; -- 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 = 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<dev_flags[tindex] &= ~DEVICE_PARITY_ERROR; -- } -- else -- { -- p->dev_flags[tindex] |= DEVICE_PARITY_ERROR; -- } - - /* - * We've set the hardware to assert ATN if we get a parity -@@ -6860,34 +6903,11 @@ - 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) -+ -+ 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<hscb->target_status = 0; - scb->cmd->result = 0; -+ scb->hscb->residual_SG_segment_count = 0; -+ scb->hscb->residual_data_count[0] = 0; -+ scb->hscb->residual_data_count[1] = 0; -+ scb->hscb->residual_data_count[2] = 0; - aic7xxx_error(scb->cmd) = DID_OK; -+ aic7xxx_status(scb->cmd) = 0; -+ /* -+ * The QUEUE_FULL/BUSY handler in aic7xxx_seqint takes care of putting -+ * this command on a timer and allowing us to retry it. Here, we -+ * just 0 out a few values so that they don't carry through to when -+ * the command finally does complete. -+ */ - break; - default: - cmd = scb->cmd; -@@ -7065,33 +7096,27 @@ - if(!p) - return; - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95) -- if(test_and_set_bit(AHC_IN_ISR_BIT, &p->flags)) -- { -- return; -- } - spin_lock_irqsave(&io_request_lock, cpu_flags); -+ p->flags |= AHC_IN_ISR; - do - { - aic7xxx_isr(irq, dev_id, regs); - } while ( (aic_inb(p, INTSTAT) & INT_PEND) ); - aic7xxx_done_cmds_complete(p); - aic7xxx_run_waiting_queues(p); -- clear_bit(AHC_IN_ISR_BIT, &p->flags); -+ p->flags &= ~AHC_IN_ISR; - spin_unlock_irqrestore(&io_request_lock, cpu_flags); - #else -- if(set_bit(AHC_IN_ISR_BIT, (int *)&p->flags)) -- { -- return; -- } - DRIVER_LOCK -+ p->flags |= AHC_IN_ISR; - do - { - aic7xxx_isr(irq, dev_id, regs); - } while ( (aic_inb(p, INTSTAT) & INT_PEND) ); -+ p->flags &= ~AHC_IN_ISR; - DRIVER_UNLOCK - aic7xxx_done_cmds_complete(p); - aic7xxx_run_waiting_queues(p); -- clear_bit(AHC_IN_ISR_BIT, (int *)&p->flags); - #endif - } - -@@ -9012,22 +9037,6 @@ - kfree(p->scb_data); - } - -- /* -- * Free any alloced Scsi_Cmnd structures that might be around for -- * negotiation purposes.... -- */ -- for (i = 0; i < MAX_TARGETS; i++) -- { -- if(p->dev_dtr_cmnd[i]) -- { -- if(p->dev_dtr_cmnd[i]->request_buffer) -- { -- kfree(p->dev_dtr_cmnd[i]->request_buffer); -- } -- kfree(p->dev_dtr_cmnd[i]); -- } -- } -- - } - - /*+F************************************************************************* -@@ -9413,7 +9422,7 @@ - } - aic_outb(p, ~(p->discenable & 0xFF), DISC_DSB); - aic_outb(p, ~((p->discenable >> 8) & 0xFF), DISC_DSB + 1); -- p->needppr = p->needppr_copy = p->needdv = 0; -+ p->needppr = p->needppr_copy = 0; - p->needwdtr = p->needwdtr_copy; - p->needsdtr = p->needsdtr_copy; - p->dtr_pending = 0; -@@ -9471,53 +9480,165 @@ - - /*+F************************************************************************* - * Function: -- * aic7xxx_detect -+ * aic7xxx_configure_bugs - * - * Description: -- * Try to detect and register an Adaptec 7770 or 7870 SCSI controller. -- * -- * XXX - This should really be called aic7xxx_probe(). A sequence of -- * probe(), attach()/detach(), and init() makes more sense than -- * one do-it-all function. This may be useful when (and if) the -- * mid-level SCSI code is overhauled. -+ * Take the card passed in and set the appropriate bug flags based upon -+ * the card model. Also make any changes needed to device registers or -+ * PCI registers while we are here. - *-F*************************************************************************/ --int --aic7xxx_detect(Scsi_Host_Template *template) -+static void -+aic7xxx_configure_bugs(struct aic7xxx_host *p) - { -- struct aic7xxx_host *temp_p = NULL; -- struct aic7xxx_host *current_p = NULL; -- struct aic7xxx_host *list_p = NULL; -- int found = 0; --#if defined(__i386__) || defined(__alpha__) -- ahc_flag_type flags = 0; -- int type; --#endif -- unsigned char sxfrctl1; --#if defined(__i386__) || defined(__alpha__) -- unsigned char hcntrl, hostconf; -- unsigned int slot, base; --#endif -- --#ifdef MODULE -- /* -- * If we are called as a module, the aic7xxx pointer may not be null -- * and it would point to our bootup string, just like on the lilo -- * command line. IF not NULL, then process this config string with -- * aic7xxx_setup -- */ -- if(aic7xxx) -- aic7xxx_setup(aic7xxx, NULL); -- if(dummy_buffer[0] != 'P') -- printk(KERN_WARNING "aic7xxx: Please read the file /usr/src/linux/drivers" -- "/scsi/README.aic7xxx\n" -- "aic7xxx: to see the proper way to specify options to the aic7xxx " -- "module\n" -- "aic7xxx: Specifically, don't use any commas when passing arguments to\n" -- "aic7xxx: insmod or else it might trash certain memory areas.\n"); -+ unsigned char pci_rev; -+ unsigned short tmp_word; -+ -+ if((p->chip & ~AHC_CHIPID_MASK) == AHC_PCI) -+ { -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,92) -+ pcibios_read_config_byte(p->pci_bus, p->pci_device_fn, -+ PCI_REVISION_ID, &pci_rev); -+#else -+ pci_read_config_byte(p->pdev, PCI_REVISION_ID, &pci_rev); - #endif -+ } - -- template->proc_dir = &proc_scsi_aic7xxx; -- template->sg_tablesize = AIC7XXX_MAX_SG; -+ switch(p->chip & AHC_CHIPID_MASK) -+ { -+ case AHC_AIC7860: -+ if(pci_rev >= 1) -+ { -+ p->bugs |= AHC_BUG_PCI_2_1_RETRY; -+ } -+ /* fall through */ -+ case AHC_AIC7850: -+ case AHC_AIC7870: -+ p->bugs |= AHC_BUG_TMODE_WIDEODD | AHC_BUG_CACHETHEN | AHC_BUG_PCI_MWI; -+ break; -+ case AHC_AIC7880: -+ p->bugs |= AHC_BUG_TMODE_WIDEODD; -+ if(pci_rev >= 1) -+ { -+ p->bugs |= AHC_BUG_PCI_2_1_RETRY; -+ } -+ else -+ { -+ p->bugs |= AHC_BUG_CACHETHEN | AHC_BUG_PCI_MWI; -+ } -+ break; -+ case AHC_AIC7890: -+ if(pci_rev == 0) -+ { -+ p->bugs |= AHC_BUG_AUTOFLUSH | AHC_BUG_CACHETHEN; -+ } -+ break; -+ case AHC_AIC7892: -+ p->bugs |= AHC_BUG_SCBCHAN_UPLOAD; -+ break; -+ case AHC_AIC7895: -+ p->bugs |= AHC_BUG_TMODE_WIDEODD | AHC_BUG_PCI_2_1_RETRY | -+ AHC_BUG_CACHETHEN; -+ if(pci_rev <= 3) -+ { -+ p->bugs |= AHC_BUG_PCI_MWI; -+ } -+ break; -+ case AHC_AIC7896: -+ p->bugs |= AHC_BUG_CACHETHEN_DIS; -+ break; -+ case AHC_AIC7899: -+ p->bugs |= AHC_BUG_SCBCHAN_UPLOAD; -+ break; -+ default: -+ /* Nothing to do */ -+ break; -+ } -+ -+ /* -+ * Now handle the bugs that require PCI register or card register tweaks -+ */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,92) -+ pcibios_read_config_word(p->pci_bus, p->pci_device_fn, -+ PCI_COMMAND, &tmp_word); -+#else -+ pci_read_config_word(p->pdev, PCI_COMMAND, &tmp_word); -+#endif -+ if(p->bugs & AHC_BUG_PCI_MWI) -+ { -+ tmp_word &= ~PCI_COMMAND_INVALIDATE; -+ } -+ else -+ { -+ tmp_word |= PCI_COMMAND_INVALIDATE; -+ } -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,92) -+ pcibios_write_config_word(p->pci_bus, p->pci_device_fn, -+ PCI_COMMAND, tmp_word); -+#else -+ pci_write_config_word(p->pdev, PCI_COMMAND, tmp_word); -+#endif -+ -+ if(p->bugs & AHC_BUG_CACHETHEN) -+ { -+ aic_outb(p, aic_inb(p, DSCOMMAND0) & ~CACHETHEN, DSCOMMAND0); -+ } -+ else if (p->bugs & AHC_BUG_CACHETHEN_DIS) -+ { -+ aic_outb(p, aic_inb(p, DSCOMMAND0) | CACHETHEN, DSCOMMAND0); -+ } -+ -+ return; -+} -+ -+/*+F************************************************************************* -+ * Function: -+ * aic7xxx_detect -+ * -+ * Description: -+ * Try to detect and register an Adaptec 7770 or 7870 SCSI controller. -+ * -+ * XXX - This should really be called aic7xxx_probe(). A sequence of -+ * probe(), attach()/detach(), and init() makes more sense than -+ * one do-it-all function. This may be useful when (and if) the -+ * mid-level SCSI code is overhauled. -+ *-F*************************************************************************/ -+int -+aic7xxx_detect(Scsi_Host_Template *template) -+{ -+ struct aic7xxx_host *temp_p = NULL; -+ struct aic7xxx_host *current_p = NULL; -+ struct aic7xxx_host *list_p = NULL; -+ int found = 0; -+#if defined(__i386__) || defined(__alpha__) -+ ahc_flag_type flags = 0; -+ int type; -+#endif -+ unsigned char sxfrctl1; -+#if defined(__i386__) || defined(__alpha__) -+ unsigned char hcntrl, hostconf; -+ unsigned int slot, base; -+#endif -+ -+#ifdef MODULE -+ /* -+ * If we are called as a module, the aic7xxx pointer may not be null -+ * and it would point to our bootup string, just like on the lilo -+ * command line. IF not NULL, then process this config string with -+ * aic7xxx_setup -+ */ -+ if(aic7xxx) -+ aic7xxx_setup(aic7xxx, NULL); -+ if(dummy_buffer[0] != 'P') -+ printk(KERN_WARNING "aic7xxx: Please read the file /usr/src/linux/drivers" -+ "/scsi/README.aic7xxx\n" -+ "aic7xxx: to see the proper way to specify options to the aic7xxx " -+ "module\n" -+ "aic7xxx: Specifically, don't use any commas when passing arguments to\n" -+ "aic7xxx: insmod or else it might trash certain memory areas.\n"); -+#endif -+ -+ template->proc_dir = &proc_scsi_aic7xxx; -+ template->sg_tablesize = AIC7XXX_MAX_SG; - - - #ifdef CONFIG_PCI -@@ -10290,6 +10411,14 @@ - aic_outb(temp_p, DFTHRSH_100, DSPCISTATUS); - } - -+ /* -+ * Call our function to fixup any bugs that exist on this chipset. -+ * This may muck with PCI settings and other device settings, so -+ * make sure it's after all the other PCI and device register -+ * tweaks so it can back out bad settings on specific broken cards. -+ */ -+ aic7xxx_configure_bugs(temp_p); -+ - if ( list_p == NULL ) - { - list_p = current_p = temp_p; -@@ -10533,6 +10662,11 @@ - } - - /* -+ * All the 7770 based chipsets have this bug -+ */ -+ temp_p->bugs |= AHC_BUG_TMODE_WIDEODD; -+ -+ /* - * Set the FIFO threshold and the bus off time. - */ - hostconf = aic_inb(temp_p, HOSTCONF); -@@ -10751,297 +10885,6 @@ - return (found); - } - --static void aic7xxx_build_negotiation_cmnd(struct aic7xxx_host *p, -- Scsi_Cmnd *old_cmd, int tindex); -- --/*+F************************************************************************* -- * Function: -- * aic7xxx_allocate_negotiation_command -- * -- * Description: -- * allocate the actual command struct and fill in the gaps... -- *-F*************************************************************************/ --static Scsi_Cmnd * --aic7xxx_allocate_negotiation_command(struct aic7xxx_host *p, -- Scsi_Cmnd *old_cmd, int tindex) --{ -- Scsi_Cmnd *cmd; -- char *buffer; -- -- if (!(p->dev_dtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) ) -- { -- return(NULL); -- } -- if (!(buffer = kmalloc(256, GFP_ATOMIC))) -- { -- kfree(p->dev_dtr_cmnd[tindex]); -- p->dev_dtr_cmnd[tindex] = NULL; -- return(NULL); -- } -- cmd = p->dev_dtr_cmnd[tindex]; -- memset(cmd, 0, sizeof(Scsi_Cmnd)); -- memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd)); -- memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd)); -- memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd)); -- cmd->lun = 0; -- cmd->request_bufflen = 255; -- cmd->request_buffer = buffer; -- cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0; -- cmd->bufflen = 0; -- cmd->buffer = NULL; -- cmd->underflow = 0; -- cmd->cmd_len = 6; -- cmd->cmnd[0] = cmd->data_cmnd[0] = INQUIRY; -- cmd->cmnd[1] = cmd->data_cmnd[1] = 0; -- cmd->cmnd[2] = cmd->data_cmnd[2] = 0; -- cmd->cmnd[3] = cmd->data_cmnd[3] = 0; -- cmd->cmnd[4] = cmd->data_cmnd[4] = 255; /* match what scsi.c does here */ -- cmd->cmnd[5] = cmd->data_cmnd[5] = 0; -- return(cmd); --} -- --/*+F************************************************************************* -- * Function: -- * aic7xxx_negotiation_complete -- * -- * Description: -- * Handle completion events for our Negotiation commands. Clear out the -- * struct and get it ready for its next use. -- *-F*************************************************************************/ --static void --aic7xxx_negotiation_complete(Scsi_Cmnd *cmd) --{ -- unsigned int checksum; -- int i; -- int *ibuffer; -- struct aic7xxx_host *p = (struct aic7xxx_host *)cmd->host->hostdata; -- int tindex = TARGET_INDEX(cmd); -- struct aic7xxx_syncrate *syncrate; -- -- /* -- * perform our minimalistic domain validation -- */ -- if(p->dev_flags[tindex] & DEVICE_SCANNED) -- { -- ibuffer = (int *)cmd->request_buffer; -- checksum = 0; -- for(i = 0; i < (cmd->request_bufflen >> 2); i++) -- { -- checksum += ibuffer[i]; -- } -- if( (checksum != p->dev_checksum[tindex]) && -- (p->transinfo[tindex].cur_offset != 0) ) -- { -- unsigned int period = p->transinfo[tindex].cur_period; -- unsigned char options = p->transinfo[tindex].cur_options; -- -- if (p->needdv & (1<host_no, CTL_OF_CMD(cmd)); -- } -- if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL) -- { -- syncrate++; -- if( (syncrate->rate[0] != NULL) && -- (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) ) -- { -- p->transinfo[tindex].goal_period = syncrate->period; -- 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 = 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<needdv &= ~(1<host_no, CTL_OF_CMD(cmd)); -- } -- /* -- * Update the checksum in case the INQUIRY data has changed, maybe -- * in relation to a change in the mode pages, or whatever. -- */ -- p->dev_checksum[tindex] = checksum; -- /* -- * Signal that we are trying out the domain validation -- */ -- p->needdv |= (1<needppr |= (p->needppr_copy & (1<needsdtr |= (p->needsdtr_copy & (1<needwdtr |= (p->needwdtr_copy & (1<needdv & (1<host_no, CTL_OF_CMD(cmd)); -- } -- /* -- * We successfully did our checksum, so don't leave the needdv flag set -- * in case we might have set it last time through. -- */ -- p->needdv &= ~(1<dtr_pending &= ~(0x01 << tindex); -- /* -- * This looks recursive in the extreme, but if this was a WDTR negotiation -- * and we didn't follow up with SDTR yet, then this will get it started. -- * For all other cases, this should work out to be a no-op, unless we are -- * doing domain validation and happen to need a new negotiation command. -- * -- * In case we don't want this to go any further, the cmdcmplt interrupt -- * handler will NULL out the cmd->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. -- */ -- if(cmd->next) -- { -- aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex); -- } -- return; --} -- --/*+F************************************************************************* -- * Function: -- * aic7xxx_build_negotiation_command -- * -- * Description: -- * Build a Scsi_Cmnd structure to perform negotiation with or else send -- * a pre-built command specifically for this purpose. -- *-F*************************************************************************/ --static void --aic7xxx_build_negotiation_cmnd(struct aic7xxx_host *p, Scsi_Cmnd *old_cmd, -- int tindex) --{ -- -- if ( !(p->dtr_pending & (1<needppr & (1<needwdtr & (1<needsdtr & (1<dev_dtr_cmnd[tindex] == NULL) && -- (aic7xxx_allocate_negotiation_command(p, old_cmd, tindex) == NULL) ) -- { -- return; -- } -- /* -- * Before sending this thing out, we also make the cmd->next pointer -- * point to the real command so we can stuff any possible SENSE data -- * into the real command instead of this fake command. This has to be -- * done each time the command is built, not just the first time, hence -- * it's outside of the above if()... -- */ -- p->dev_dtr_cmnd[tindex]->next = old_cmd; -- /* -- * Clear the buffer so checksums come out right.... -- */ -- memset(p->dev_dtr_cmnd[tindex]->request_buffer, 0, -- p->dev_dtr_cmnd[tindex]->request_bufflen); -- /* -- * Remove any commands for this particular device that might be on the -- * waiting_scbs queue or qinfifo so that this command goes out first. -- * This is vital for our implementation of domain validation. -- */ -- pause_sequencer(p); -- aic7xxx_search_qinfifo(p, old_cmd->target, old_cmd->channel, ALL_LUNS, -- SCB_LIST_NULL, 0, TRUE, &p->delayed_scbs[tindex]); -- unpause_sequencer(p, FALSE); -- { -- struct aic7xxx_scb *scb, *next; -- -- scb = p->waiting_scbs.head; -- while(scb != NULL) -- { -- if( aic7xxx_match_scb(p, scb, old_cmd->target, old_cmd->channel, -- ALL_LUNS, SCB_LIST_NULL) ) -- { -- next = scb->q_next; -- scbq_remove(&p->waiting_scbs, scb); -- scbq_insert_tail(&p->delayed_scbs[tindex], scb); -- scb = next; -- } -- else -- { -- scb = scb->q_next; -- } -- } -- } -- aic7xxx_queue(p->dev_dtr_cmnd[tindex], -- aic7xxx_negotiation_complete); -- } --} -- - #ifdef AIC7XXX_VERBOSE_DEBUGGING - /*+F************************************************************************* - * Function: -@@ -11090,7 +10933,7 @@ - */ - hscb->control = 0; - scb->tag_action = 0; -- cmd->tag = hscb->tag; -+ - if (p->discenable & mask) - { - hscb->control |= DISCENB; -@@ -11119,34 +10962,29 @@ - } - } - } -- if ( cmd == p->dev_dtr_cmnd[tindex] ) -+ if ( !(p->dtr_pending & mask) && -+ ( (p->needppr & mask) || -+ (p->needwdtr & mask) || -+ (p->needsdtr & mask) ) && -+ (p->dev_flags[tindex] & DEVICE_DTR_SCANNED) ) - { - p->dtr_pending |= mask; - scb->tag_action = 0; -- if (p->dev_flags[tindex] & DEVICE_SCANNED) -+ hscb->control &= DISCENB; -+ hscb->control |= MK_MESSAGE; -+ if(p->needppr & mask) - { -- hscb->control &= DISCENB; -- hscb->control |= MK_MESSAGE; -- if(p->needppr & mask) -- { -- scb->flags |= SCB_MSGOUT_PPR; -- } -- else if(p->needwdtr & mask) -- { -- scb->flags |= SCB_MSGOUT_WDTR; -- } -- else if(p->needsdtr & mask) -- { -- scb->flags |= SCB_MSGOUT_SDTR; -- } -+ scb->flags |= SCB_MSGOUT_PPR; - } -- } -- if ( !(p->dtr_pending & mask) && -- ( (p->needppr & mask) || -- (p->needwdtr & mask) || -- (p->needsdtr & mask) ) ) -- { -- aic7xxx_build_negotiation_cmnd(p, cmd, tindex); -+ else if(p->needwdtr & mask) -+ { -+ scb->flags |= SCB_MSGOUT_WDTR; -+ } -+ else if(p->needsdtr & mask) -+ { -+ scb->flags |= SCB_MSGOUT_SDTR; -+ } -+ scb->flags |= SCB_DTR_SCB; - } - hscb->target_channel_lun = ((cmd->target << 4) & 0xF0) | - ((cmd->channel & 0x01) << 3) | (cmd->lun & 0x07); -@@ -11285,50 +11123,58 @@ - aic7xxx_allocate_scb(p); - DRIVER_UNLOCK - scb = scbq_remove_head(&p->scb_data->free_scbs); -- } -- if (scb == NULL) -- { -- printk(WARN_LEAD "Couldn't get a free SCB.\n", p->host_no, -- CTL_OF_CMD(cmd)); -- cmd->result = (DID_BUS_BUSY << 16); -+ if(scb == NULL) -+ printk(WARN_LEAD "Couldn't get a free SCB.\n", p->host_no, -+ CTL_OF_CMD(cmd)); -+ } -+ while (scb == NULL) -+ { -+ /* -+ * Well, all SCBs are currently active on the bus. So, we spin here -+ * running the interrupt handler until one completes and becomes free. -+ * We can do this safely because we either A) hold the driver lock (in -+ * 2.0 kernels) or we have the io_request_lock held (in 2.2 and later -+ * kernels) and so either way, we won't take any other interrupts and -+ * the queue path will block until we release it. Also, we would worry -+ * about running the completion queues, but obviously there are plenty -+ * of commands outstanding to trigger a later interrupt that will do -+ * that for us, so skip it here. -+ */ - DRIVER_LOCK -- aic7xxx_queue_cmd_complete(p, cmd); -+ aic7xxx_isr(p->irq, p, NULL); - DRIVER_UNLOCK -- return 0; -+ scb = scbq_remove_head(&p->scb_data->free_scbs); - } -- else -- { -- scb->cmd = cmd; -- aic7xxx_position(cmd) = scb->hscb->tag; -+ scb->cmd = cmd; -+ aic7xxx_position(cmd) = scb->hscb->tag; - -- /* -- * Construct the SCB beforehand, so the sequencer is -- * paused a minimal amount of time. -- */ -- aic7xxx_buildscb(p, cmd, scb); -+ /* -+ * Make sure the Scsi_Cmnd pointer is saved, the struct it points to -+ * is set up properly, and the parity error flag is reset, then send -+ * the SCB to the sequencer and watch the fun begin. -+ */ -+ cmd->scsi_done = fn; -+ cmd->result = DID_OK; -+ memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); -+ aic7xxx_error(cmd) = DID_OK; -+ aic7xxx_status(cmd) = 0; -+ cmd->host_scribble = NULL; - -- /* -- * Make sure the Scsi_Cmnd pointer is saved, the struct it points to -- * is set up properly, and the parity error flag is reset, then send -- * the SCB to the sequencer and watch the fun begin. -- */ -- cmd->scsi_done = fn; -- cmd->result = DID_OK; -- memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); -- aic7xxx_error(cmd) = DID_OK; -- aic7xxx_status(cmd) = 0; -- cmd->host_scribble = NULL; -+ /* -+ * Construct the SCB beforehand, so the sequencer is -+ * paused a minimal amount of time. -+ */ -+ aic7xxx_buildscb(p, cmd, scb); - -- scb->flags |= SCB_ACTIVE | SCB_WAITINGQ; -+ scb->flags |= SCB_ACTIVE | SCB_WAITINGQ; - -- DRIVER_LOCK -- scbq_insert_tail(&p->waiting_scbs, scb); -- if ( (p->flags & (AHC_IN_ISR | AHC_IN_ABORT | AHC_IN_RESET)) == 0) -- { -- aic7xxx_run_waiting_queues(p); -- } -- DRIVER_UNLOCK -+ DRIVER_LOCK -+ scbq_insert_tail(&p->waiting_scbs, scb); -+ if ( (p->flags & (AHC_IN_ISR | AHC_IN_ABORT | AHC_IN_RESET)) == 0) -+ { -+ aic7xxx_run_waiting_queues(p); - } -+ DRIVER_UNLOCK - return (0); - } - -@@ -11394,6 +11240,12 @@ - aic_inb(p, SCSISIGI), - aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8), - aic_inb(p, SSTAT0), aic_inb(p, SSTAT1)); -+ printk(INFO_LEAD "SG_CACHEPTR 0x%x, SSTAT2 0x%x, STCNT 0x%x\n", p->host_no, -+ CTL_OF_SCB(scb), -+ (p->features & AHC_ULTRA2) ? aic_inb(p, SG_CACHEPTR) : 0, -+ aic_inb(p, SSTAT2), -+ aic_inb(p, STCNT + 2) << 16 | aic_inb(p, STCNT + 1) << 8 | -+ aic_inb(p, STCNT)); - } - - channel = cmd->channel; -@@ -11687,7 +11539,6 @@ - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; - #endif -- Scsi_Cmnd *cmd_next, *cmd_prev; - - p = (struct aic7xxx_host *) cmd->host->hostdata; - scb = (p->scb_data->scb_array[aic7xxx_position(cmd)]); -@@ -11718,13 +11569,11 @@ - { - aic7xxx_isr(p->irq, p, (void *)NULL); - pause_sequencer(p); -- aic7xxx_done_cmds_complete(p); - } -+ aic7xxx_done_cmds_complete(p); - -- if ((scb == NULL) || (cmd->serial_number != cmd->serial_number_at_timeout)) -- /* Totally bogus cmd since it points beyond our */ -- { /* valid SCB range or doesn't even match it's own*/ -- /* timeout serial number. */ -+ if (scb == NULL) -+ { - if (aic7xxx_verbose & VERBOSE_ABORT_MID) - printk(INFO_LEAD "Abort called with bogus Scsi_Cmnd " - "pointer.\n", p->host_no, CTL_OF_CMD(cmd)); -@@ -11743,28 +11592,6 @@ - /* finish successfully, or to indicate that we */ - /* don't have this cmd any more and the mid level */ - /* code needs to find it. */ -- cmd_next = p->completeq.head; -- cmd_prev = NULL; -- while (cmd_next != NULL) -- { -- if (cmd_next == cmd) -- { -- if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS) -- printk(INFO_LEAD "Abort called for command " -- "on completeq, completing.\n", p->host_no, CTL_OF_CMD(cmd)); -- if ( cmd_prev == NULL ) -- p->completeq.head = (Scsi_Cmnd *)cmd_next->host_scribble; -- else -- cmd_prev->host_scribble = cmd_next->host_scribble; -- cmd_next->scsi_done(cmd_next); -- unpause_sequencer(p, FALSE); -- DRIVER_UNLOCK -- return(SCSI_ABORT_NOT_RUNNING); /* It's already back as a successful -- * completion */ -- } -- cmd_prev = cmd_next; -- cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble; -- } - if (aic7xxx_verbose & VERBOSE_ABORT_MID) - printk(INFO_LEAD "Abort called for already completed" - " command.\n", p->host_no, CTL_OF_CMD(cmd)); -@@ -11822,8 +11649,20 @@ - found = 0; - p->flags |= AHC_IN_ABORT; - if (aic7xxx_verbose & VERBOSE_ABORT) -- printk(INFO_LEAD "Aborting scb %d, flags 0x%x\n", -- p->host_no, CTL_OF_SCB(scb), scb->hscb->tag, scb->flags); -+ { -+ printk(INFO_LEAD "Aborting scb %d, flags 0x%x, SEQADDR 0x%x, LASTPHASE " -+ "0x%x\n", -+ p->host_no, CTL_OF_SCB(scb), scb->hscb->tag, scb->flags, -+ aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8), -+ aic_inb(p, LASTPHASE)); -+ printk(INFO_LEAD "SG_CACHEPTR 0x%x, SG_COUNT %d, SCSISIGI 0x%x\n", -+ p->host_no, CTL_OF_SCB(scb), (p->features & AHC_ULTRA2) ? -+ aic_inb(p, SG_CACHEPTR) : 0, aic_inb(p, SG_COUNT), -+ aic_inb(p, SCSISIGI)); -+ printk(INFO_LEAD "SSTAT0 0x%x, SSTAT1 0x%x, SSTAT2 0x%x\n", -+ p->host_no, CTL_OF_SCB(scb), aic_inb(p, SSTAT0), -+ aic_inb(p, SSTAT1), aic_inb(p, SSTAT2)); -+ } - - /* - * First, let's check to see if the currently running command is our target -@@ -11851,6 +11690,16 @@ - if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS) - printk(INFO_LEAD "SCB is currently active. " - "Waiting on completion.\n", p->host_no, CTL_OF_SCB(scb)); -+ printk(INFO_LEAD "SCSISIGI 0x%x, SEQADDR 0x%x, SSTAT0 0x%x, SSTAT1 " -+ "0x%x\n", p->host_no, CTL_OF_SCB(scb), -+ aic_inb(p, SCSISIGI), -+ aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8), -+ aic_inb(p, SSTAT0), aic_inb(p, SSTAT1)); -+ printk(INFO_LEAD "SG_CACHEPTR 0x%x, SSTAT2 0x%x, STCNT 0x%x\n", -+ p->host_no, CTL_OF_SCB(scb), -+ (p->features & AHC_ULTRA2) ? aic_inb(p, SG_CACHEPTR) : 0, -+ aic_inb(p, SSTAT2), aic_inb(p, STCNT + 2) << 16 | -+ aic_inb(p, STCNT + 1) << 8 | aic_inb(p, STCNT)); - unpause_sequencer(p, FALSE); - p->flags &= ~AHC_IN_ABORT; - scb->flags |= SCB_RECOVERY_SCB; /* Note the fact that we've been */ -@@ -11866,35 +11715,7 @@ - if ((found == 0) && (scb->flags & SCB_WAITINGQ)) - { - int tindex = TARGET_INDEX(cmd); -- unsigned short mask; -- -- mask = (1 << tindex); - -- if (p->dtr_pending & mask) -- { -- if (p->dev_dtr_cmnd[tindex]->next != cmd) -- found = 1; -- else -- found = 0; -- } -- else -- { -- found = 1; -- } -- if (found == 0) -- { -- /* -- * OK..this means the command we are currently getting an abort -- * for has an outstanding negotiation command in front of it. -- * We don't really have a way to tie back into the negotiation -- * commands, so we just send this back as pending, then it -- * will get reset in 2 seconds. -- */ -- unpause_sequencer(p, TRUE); -- scb->flags |= SCB_ABORT; -- DRIVER_UNLOCK -- return(SCSI_ABORT_PENDING); -- } - if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS) - printk(INFO_LEAD "SCB found on waiting list and " - "aborted.\n", p->host_no, CTL_OF_SCB(scb)); -@@ -12051,10 +11872,8 @@ - #define DEVICE_RESET 0x01 - #define BUS_RESET 0x02 - #define HOST_RESET 0x04 --#define FAIL 0x08 --#define RESET_DELAY 0x10 -+#define RESET_DELAY 0x08 - int action; -- Scsi_Cmnd *cmd_prev, *cmd_next; - - - if ( cmd == NULL ) -@@ -12082,86 +11901,32 @@ - DRIVER_LOCK - - pause_sequencer(p); -- while ( (aic_inb(p, INTSTAT) & INT_PEND) && !(p->flags & AHC_IN_ISR)) -- { -- aic7xxx_isr(p->irq, p, (void *)NULL ); -- pause_sequencer(p); -- aic7xxx_done_cmds_complete(p); -- } - -- if (scb == NULL) -+ if(flags & SCSI_RESET_SYNCHRONOUS) - { - if (aic7xxx_verbose & VERBOSE_RESET_MID) -- printk(INFO_LEAD "Reset called with bogus Scsi_Cmnd" -- "->SCB mapping, improvising.\n", p->host_no, CTL_OF_CMD(cmd)); -- if ( flags & SCSI_RESET_SUGGEST_HOST_RESET ) -- { -- action = HOST_RESET; -- } -- else -- { -- action = BUS_RESET; -- } -+ printk(INFO_LEAD "Reset called for a SYNCHRONOUS reset, flags 0x%x, " -+ "cmd->result 0x%x.\n", p->host_no, CTL_OF_CMD(cmd), flags, -+ cmd->result); -+ scb = NULL; -+ action = HOST_RESET; - } -- else if (scb->cmd != cmd) -+ else if ((scb == NULL) || (scb->cmd != cmd)) - { - if (aic7xxx_verbose & VERBOSE_RESET_MID) -- printk(INFO_LEAD "Reset called with recycled SCB " -- "for cmd.\n", p->host_no, CTL_OF_CMD(cmd)); -- cmd_prev = NULL; -- cmd_next = p->completeq.head; -- while ( cmd_next != NULL ) -- { -- if (cmd_next == cmd) -- { -- if (aic7xxx_verbose & VERBOSE_RESET_RETURN) -- printk(INFO_LEAD "Reset, found cmd on completeq" -- ", completing.\n", p->host_no, CTL_OF_CMD(cmd)); -- unpause_sequencer(p, FALSE); -- DRIVER_UNLOCK -- return(SCSI_RESET_NOT_RUNNING); -- } -- cmd_prev = cmd_next; -- cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble; -- } -- if ( !(flags & SCSI_RESET_SYNCHRONOUS) ) -- { -- if (aic7xxx_verbose & VERBOSE_RESET_RETURN) -- printk(INFO_LEAD "Reset, cmd not found," -- " failing.\n", p->host_no, CTL_OF_CMD(cmd)); -- unpause_sequencer(p, FALSE); -- DRIVER_UNLOCK -- return(SCSI_RESET_NOT_RUNNING); -- } -- else -- { -- if (aic7xxx_verbose & VERBOSE_RESET_MID) -- printk(INFO_LEAD "Reset called, no scb, " -- "flags 0x%x\n", p->host_no, CTL_OF_CMD(cmd), flags); -- scb = NULL; -- action = HOST_RESET; -- } -+ printk(INFO_LEAD "Reset called with bogus Scsi_Cmnd" -+ "->SCB mapping, failing.\n", p->host_no, CTL_OF_CMD(cmd)); -+ aic7xxx_done_cmds_complete(p); -+ aic7xxx_run_waiting_queues(p); -+ unpause_sequencer(p, FALSE); -+ DRIVER_UNLOCK -+ return(SCSI_RESET_NOT_RUNNING); - } - else - { - if (aic7xxx_verbose & VERBOSE_RESET_MID) - printk(INFO_LEAD "Reset called, scb %d, flags " - "0x%x\n", p->host_no, CTL_OF_SCB(scb), scb->hscb->tag, scb->flags); -- if ( aic7xxx_scb_on_qoutfifo(p, scb) ) -- { -- if(aic7xxx_verbose & VERBOSE_RESET_RETURN) -- printk(INFO_LEAD "SCB on qoutfifo, completing.\n", p->host_no, -- CTL_OF_SCB(scb)); -- if ((aic_inb(p,INTSTAT) & CMDCMPLT) == 0) -- printk(INFO_LEAD "missed CMDCMPLT interrupt!\n", p->host_no, -- CTL_OF_SCB(scb)); -- aic7xxx_handle_command_completion_intr(p); -- aic7xxx_done_cmds_complete(p); -- aic7xxx_run_waiting_queues(p); -- unpause_sequencer(p, FALSE); -- DRIVER_UNLOCK -- return(SCSI_RESET_SUCCESS); -- } - if ( flags & SCSI_RESET_SUGGEST_HOST_RESET ) - { - action = HOST_RESET; -@@ -12175,6 +11940,26 @@ - action = DEVICE_RESET; - } - } -+ -+ while((aic_inb(p, INTSTAT) & INT_PEND) && !(p->flags & AHC_IN_ISR)) -+ { -+ aic7xxx_isr(p->irq, p, (void *)NULL ); -+ pause_sequencer(p); -+ } -+ aic7xxx_done_cmds_complete(p); -+ -+ if(scb && (scb->cmd == NULL)) -+ { -+ /* -+ * We just completed the command when we ran the isr stuff, so we no -+ * longer have it. -+ */ -+ aic7xxx_run_waiting_queues(p); -+ unpause_sequencer(p, FALSE); -+ DRIVER_UNLOCK -+ return(SCSI_RESET_SUCCESS); -+ } -+ - if ( (action & DEVICE_RESET) && - (p->dev_flags[tindex] & BUS_DEVICE_RESET_PENDING) ) - { -@@ -12234,14 +12019,13 @@ - switch (action) - { - case RESET_DELAY: -+ aic7xxx_run_waiting_queues(p); - unpause_sequencer(p, FALSE); - DRIVER_UNLOCK -- return(SCSI_RESET_PENDING); -- break; -- case FAIL: -- unpause_sequencer(p, FALSE); -- DRIVER_UNLOCK -- return(SCSI_RESET_ERROR); -+ if(scb == NULL) -+ return(SCSI_RESET_PUNT); -+ else -+ return(SCSI_RESET_PENDING); - break; - case DEVICE_RESET: - p->flags |= AHC_IN_RESET; -@@ -12259,7 +12043,7 @@ - case HOST_RESET: - default: - p->flags |= AHC_IN_RESET | AHC_RESET_DELAY; -- p->dev_expires[p->scsi_id] = jiffies + (3 * HZ); -+ p->dev_expires[p->scsi_id] = jiffies + (1 * HZ); - p->dev_timer_active |= (0x01 << p->scsi_id); - if ( !(p->dev_timer_active & (0x01 << MAX_TARGETS)) || - time_after_eq(p->dev_timer.expires, p->dev_expires[p->scsi_id]) ) -@@ -12288,21 +12072,14 @@ - p->msg_index = 0; - p->msg_len = 0; - } -- aic7xxx_run_done_queue(p, TRUE); -- /* -- * If this a SCSI_RESET_SYNCHRONOUS then the command we were given is -- * in need of being re-started, so send it on through to aic7xxx_queue -- * and let it set until the delay is over. This keeps it from dying -- * entirely and avoids getting a bogus dead command back through the -- * mid-level code due to too many retries. -- */ --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132) -- if ( flags & SCSI_RESET_SYNCHRONOUS ) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) -+ if(flags & SCSI_RESET_SYNCHRONOUS) - { -- cmd->result = DID_BUS_BUSY << 16; -+ cmd->result = DID_RESET << 16; - cmd->done(cmd); - } - #endif -+ aic7xxx_run_done_queue(p, TRUE); - p->flags &= ~AHC_IN_RESET; - /* - * We can't rely on run_waiting_queues to unpause the sequencer for -@@ -12313,7 +12090,10 @@ - aic7xxx_run_waiting_queues(p); - unpause_sequencer(p, FALSE); - DRIVER_UNLOCK -- return(result); -+ if(scb == NULL) -+ return(SCSI_RESET_SUCCESS|SCSI_RESET_HOST_RESET); -+ else -+ return(result); - break; - } - } -@@ -12623,7 +12403,7 @@ - } - - --#include "aic7xxx_proc.c" -+#include "aic7xxx/aic7xxx_proc.c" - - #ifdef MODULE - /* Eventually this will go into an include file, but this will be later */ -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx.h linux/drivers/scsi/aic7xxx.h ---- linux-2.2.17/drivers/scsi/aic7xxx.h Tue May 11 13:36:28 1999 -+++ linux/drivers/scsi/aic7xxx.h Wed Dec 31 19:00:00 1969 -@@ -1,114 +0,0 @@ --/*+M************************************************************************* -- * Adaptec AIC7xxx device driver for Linux. -- * -- * Copyright (c) 1994 John Aycock -- * The University of Calgary Department of Computer Science. -- * -- * 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, or (at your option) -- * any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, write to -- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -- * -- * $Id: aic7xxx.h,v 3.2 1996/07/23 03:37:26 deang Exp $ -- *-M*************************************************************************/ --#ifndef _aic7xxx_h --#define _aic7xxx_h -- --#define AIC7XXX_H_VERSION "3.2.4" -- --#ifndef LINUX_VERSION_CODE --#include --#endif -- --#ifndef KERNEL_VERSION --#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) --#endif -- --#if defined(__i386__) --# define AIC7XXX_BIOSPARAM aic7xxx_biosparam --#else --# define AIC7XXX_BIOSPARAM NULL --#endif -- --/* -- * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields -- * to do with card config are filled in after the card is detected. -- */ --#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,65) --#define AIC7XXX { \ -- next: NULL, \ -- module: NULL, \ -- proc_dir: NULL, \ -- proc_info: aic7xxx_proc_info, \ -- name: NULL, \ -- detect: aic7xxx_detect, \ -- release: aic7xxx_release, \ -- info: aic7xxx_info, \ -- command: NULL, \ -- queuecommand: aic7xxx_queue, \ -- eh_strategy_handler: NULL, \ -- eh_abort_handler: NULL, \ -- eh_device_reset_handler: NULL, \ -- eh_bus_reset_handler: NULL, \ -- eh_host_reset_handler: NULL, \ -- abort: aic7xxx_abort, \ -- reset: aic7xxx_reset, \ -- slave_attach: NULL, \ -- bios_param: AIC7XXX_BIOSPARAM, \ -- can_queue: 255, /* max simultaneous cmds */\ -- this_id: -1, /* scsi id of host adapter */\ -- sg_tablesize: 0, /* max scatter-gather cmds */\ -- cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ -- present: 0, /* number of 7xxx's present */\ -- unchecked_isa_dma: 0, /* no memory DMA restrictions */\ -- use_clustering: ENABLE_CLUSTERING, \ -- use_new_eh_code: 0 \ --} --#else --#define AIC7XXX { \ -- next: NULL, \ -- usage_count: NULL, \ -- proc_dir: NULL, \ -- proc_info: aic7xxx_proc_info, \ -- name: NULL, \ -- detect: aic7xxx_detect, \ -- release: aic7xxx_release, \ -- info: aic7xxx_info, \ -- command: NULL, \ -- queuecommand: aic7xxx_queue, \ -- abort: aic7xxx_abort, \ -- reset: aic7xxx_reset, \ -- slave_attach: NULL, \ -- bios_param: AIC7XXX_BIOSPARAM, \ -- can_queue: 255, /* max simultaneous cmds */\ -- this_id: -1, /* scsi id of host adapter */\ -- sg_tablesize: 0, /* max scatter-gather cmds */\ -- cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ -- present: 0, /* number of 7xxx's present */\ -- unchecked_isa_dma: 0, /* no memory DMA restrictions */\ -- use_clustering: ENABLE_CLUSTERING \ --} --#endif -- --extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); --extern int aic7xxx_biosparam(Disk *, kdev_t, int[]); --extern int aic7xxx_detect(Scsi_Host_Template *); --extern int aic7xxx_command(Scsi_Cmnd *); --extern int aic7xxx_reset(Scsi_Cmnd *, unsigned int); --extern int aic7xxx_abort(Scsi_Cmnd *); --extern int aic7xxx_release(struct Scsi_Host *); -- --extern const char *aic7xxx_info(struct Scsi_Host *); -- --extern int aic7xxx_proc_info(char *, char **, off_t, int, int, int); -- --#endif /* _aic7xxx_h */ -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c ---- linux-2.2.17/drivers/scsi/aic7xxx_proc.c Wed May 3 20:16:44 2000 -+++ linux/drivers/scsi/aic7xxx_proc.c Wed Dec 31 19:00:00 1969 -@@ -1,414 +0,0 @@ --/*+M************************************************************************* -- * Adaptec AIC7xxx device driver proc support for Linux. -- * -- * Copyright (c) 1995, 1996 Dean W. Gehnert -- * -- * 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, or (at your option) -- * any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, write to -- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -- * -- * ---------------------------------------------------------------- -- * o Modified from the EATA-DMA /proc support. -- * o Additional support for device block statistics provided by -- * Matthew Jacob. -- * o Correction of overflow by Heinz Mauelshagen -- * o Adittional corrections by Doug Ledford -- * -- * Dean W. Gehnert, deang@teleport.com, 05/01/96 -- * -- * $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $ -- *-M*************************************************************************/ -- --#include -- --#define BLS (&aic7xxx_buffer[size]) --#define HDRB \ --" < 2K 2K+ 4K+ 8K+ 16K+ 32K+ 64K+ 128K+" -- --#ifdef PROC_DEBUG --extern int vsprintf(char *, const char *, va_list); -- --static void --proc_debug(const char *fmt, ...) --{ -- va_list ap; -- char buf[256]; -- -- va_start(ap, fmt); -- vsprintf(buf, fmt, ap); -- printk(buf); -- va_end(ap); --} --#else /* PROC_DEBUG */ --# define proc_debug(fmt, args...) --#endif /* PROC_DEBUG */ -- --static int aic7xxx_buffer_size = 0; --static char *aic7xxx_buffer = NULL; -- -- --/*+F************************************************************************* -- * Function: -- * aic7xxx_set_info -- * -- * Description: -- * Set parameters for the driver from the /proc filesystem. -- *-F*************************************************************************/ --int --aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) --{ -- proc_debug("aic7xxx_set_info(): %s\n", buffer); -- return (-ENOSYS); /* Currently this is a no-op */ --} -- -- --/*+F************************************************************************* -- * Function: -- * aic7xxx_proc_info -- * -- * Description: -- * Return information to handle /proc support for the driver. -- *-F*************************************************************************/ --int --aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length, -- int hostno, int inout) --{ -- struct Scsi_Host *HBAptr; -- struct aic7xxx_host *p; -- int size = 0; -- unsigned char i; -- struct aic7xxx_xferstats *sp; -- unsigned char target; -- -- HBAptr = NULL; -- -- for(p=first_aic7xxx; p->host->host_no != hostno; p=p->next) -- ; -- -- if (!p) -- { -- size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno); -- if (size > length) -- { -- return (size); -- } -- else -- { -- return (length); -- } -- } -- -- HBAptr = p->host; -- -- if (inout == TRUE) /* Has data been written to the file? */ -- { -- return (aic7xxx_set_info(buffer, length, HBAptr)); -- } -- -- p = (struct aic7xxx_host *) HBAptr->hostdata; -- -- /* -- * It takes roughly 1K of space to hold all relevant card info, not -- * counting any proc stats, so we start out with a 1.5k buffer size and -- * if proc_stats is defined, then we sweep the stats structure to see -- * how many drives we will be printing out for and add 384 bytes per -- * device with active stats. -- * -- * Hmmmm...that 1.5k seems to keep growing as items get added so they -- * can be easily viewed for debugging purposes. So, we bumped that -- * 1.5k to 4k so we can quit having to bump it all the time. -- */ -- -- size = 4096; -- for (target = 0; target < MAX_TARGETS; target++) -- { -- if (p->dev_flags[target] & DEVICE_PRESENT) --#ifdef AIC7XXX_PROC_STATS -- size += 512; --#else -- size += 256; --#endif -- } -- if (aic7xxx_buffer_size != size) -- { -- if (aic7xxx_buffer != NULL) -- { -- kfree(aic7xxx_buffer); -- aic7xxx_buffer_size = 0; -- } -- aic7xxx_buffer = kmalloc(size, GFP_KERNEL); -- } -- if (aic7xxx_buffer == NULL) -- { -- size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n", -- __LINE__); -- return size; -- } -- aic7xxx_buffer_size = size; -- -- size = 0; -- size += sprintf(BLS, "Adaptec AIC7xxx driver version: "); -- size += sprintf(BLS, "%s/", AIC7XXX_C_VERSION); -- size += sprintf(BLS, "%s", AIC7XXX_H_VERSION); -- size += sprintf(BLS, "\n"); -- size += sprintf(BLS, "Compile Options:\n"); --#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT -- size += sprintf(BLS, " TCQ Enabled By Default : Enabled\n"); --#else -- size += sprintf(BLS, " TCQ Enabled By Default : Disabled\n"); --#endif --#ifdef AIC7XXX_PROC_STATS -- size += sprintf(BLS, " AIC7XXX_PROC_STATS : Enabled\n"); --#else -- size += sprintf(BLS, " AIC7XXX_PROC_STATS : Disabled\n"); --#endif -- size += sprintf(BLS, " AIC7XXX_RESET_DELAY : %d\n", AIC7XXX_RESET_DELAY); -- size += sprintf(BLS, "\n"); -- size += sprintf(BLS, "Adapter Configuration:\n"); -- size += sprintf(BLS, " SCSI Adapter: %s\n", -- board_names[p->board_name_index]); -- if (p->flags & AHC_TWIN) -- size += sprintf(BLS, " Twin Channel Controller "); -- else -- { -- char *channel = ""; -- char *ultra = ""; -- char *wide = "Narrow "; -- if (p->flags & AHC_MULTI_CHANNEL) -- { -- channel = " Channel A"; -- if (p->flags & (AHC_CHNLB|AHC_CHNLC)) -- channel = (p->flags & AHC_CHNLB) ? " Channel B" : " Channel C"; -- } -- if (p->features & AHC_WIDE) -- wide = "Wide "; -- if (p->features & AHC_ULTRA3) -- { -- switch(p->chip & AHC_CHIPID_MASK) -- { -- case AHC_AIC7892: -- case AHC_AIC7899: -- ultra = "Ultra-160/m LVD/SE "; -- break; -- default: -- ultra = "Ultra-3 LVD/SE "; -- break; -- } -- } -- else if (p->features & AHC_ULTRA2) -- ultra = "Ultra-2 LVD/SE "; -- else if (p->features & AHC_ULTRA) -- ultra = "Ultra "; -- size += sprintf(BLS, " %s%sController%s ", -- ultra, wide, channel); -- } -- switch(p->chip & ~AHC_CHIPID_MASK) -- { -- case AHC_VL: -- size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn); -- break; -- case AHC_EISA: -- size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn); -- break; -- default: -- size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus, -- PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn)); -- break; -- } -- if( !(p->maddr) ) -- { -- size += sprintf(BLS, " Programmed I/O Base: %lx\n", p->base); -- } -- else -- { -- size += sprintf(BLS, " PCI MMAPed I/O Base: 0x%lx\n", p->mbase); -- } -- if( (p->chip & (AHC_VL | AHC_EISA)) ) -- { -- size += sprintf(BLS, " BIOS Memory Address: 0x%08x\n", p->bios_address); -- } -- size += sprintf(BLS, " Adapter SEEPROM Config: %s\n", -- (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." : -- ((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." : -- "SEEPROM not found, using leftover BIOS values.") ); -- size += sprintf(BLS, " Adaptec SCSI BIOS: %s\n", -- (p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled"); -- size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); -- size += sprintf(BLS, " SCBs: Active %d, Max Active %d,\n", -- p->activescbs, p->max_activescbs); -- size += sprintf(BLS, " Allocated %d, HW %d, " -- "Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs, -- p->scb_data->maxscbs); -- if (p->flags & AHC_EXTERNAL_SRAM) -- size += sprintf(BLS, " Using External SCB SRAM\n"); -- size += sprintf(BLS, " Interrupts: %ld", p->isr_count); -- if (p->chip & AHC_EISA) -- { -- size += sprintf(BLS, " %s\n", -- (p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)"); -- } -- else -- { -- size += sprintf(BLS, "\n"); -- } -- size += sprintf(BLS, " BIOS Control Word: 0x%04x\n", -- p->bios_control); -- size += sprintf(BLS, " Adapter Control Word: 0x%04x\n", -- p->adapter_control); -- size += sprintf(BLS, " Extended Translation: %sabled\n", -- (p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis"); -- size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable); -- if (p->features & (AHC_ULTRA | AHC_ULTRA2)) -- { -- size += sprintf(BLS, " Ultra Enable Flags: 0x%04x\n", p->ultraenb); -- } -- size += sprintf(BLS, " Tag Queue Enable Flags: 0x%04x\n", p->tagenable); -- size += sprintf(BLS, "Ordered Queue Tag Flags: 0x%04x\n", p->orderedtag); -- size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_DEVICE); -- size += sprintf(BLS, " Tagged Queue By Device array for aic7xxx host " -- "instance %d:\n", p->instance); -- size += sprintf(BLS, " {"); -- for(i=0; i < (MAX_TARGETS - 1); i++) -- size += sprintf(BLS, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]); -- size += sprintf(BLS, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]); -- size += sprintf(BLS, " Actual queue depth per device for aic7xxx host " -- "instance %d:\n", p->instance); -- size += sprintf(BLS, " {"); -- for(i=0; i < (MAX_TARGETS - 1); i++) -- size += sprintf(BLS, "%d,", p->dev_max_queue_depth[i]); -- size += sprintf(BLS, "%d}\n", p->dev_max_queue_depth[i]); -- -- size += sprintf(BLS, "\n"); -- size += sprintf(BLS, "Statistics:\n\n"); -- for (target = 0; target < MAX_TARGETS; target++) -- { -- sp = &p->stats[target]; -- if ((p->dev_flags[target] & DEVICE_PRESENT) == 0) -- { -- continue; -- } -- if (p->features & AHC_TWIN) -- { -- size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n", -- p->host_no, (target >> 3), (target & 0x7), 0); -- } -- else -- { -- size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n", -- p->host_no, 0, target, 0); -- } -- size += sprintf(BLS, " Device using %s/%s", -- (p->transinfo[target].cur_width == MSG_EXT_WDTR_BUS_16_BIT) ? -- "Wide" : "Narrow", -- (p->transinfo[target].cur_offset != 0) ? -- "Sync transfers at " : "Async transfers.\n" ); -- if (p->transinfo[target].cur_offset != 0) -- { -- struct aic7xxx_syncrate *sync_rate; -- unsigned char options = p->transinfo[target].cur_options; -- int period = p->transinfo[target].cur_period; -- int rate = (p->transinfo[target].cur_width == -- MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0; -- -- sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options); -- if (sync_rate != NULL) -- { -- size += sprintf(BLS, "%s MByte/sec, offset %d\n", -- sync_rate->rate[rate], -- p->transinfo[target].cur_offset ); -- } -- else -- { -- size += sprintf(BLS, "3.3 MByte/sec, offset %d\n", -- p->transinfo[target].cur_offset ); -- } -- } -- size += sprintf(BLS, " Transinfo settings: "); -- size += sprintf(BLS, "current(%d/%d/%d/%d), ", -- p->transinfo[target].cur_period, -- p->transinfo[target].cur_offset, -- p->transinfo[target].cur_width, -- p->transinfo[target].cur_options); -- size += sprintf(BLS, "goal(%d/%d/%d/%d), ", -- p->transinfo[target].goal_period, -- p->transinfo[target].goal_offset, -- p->transinfo[target].goal_width, -- p->transinfo[target].goal_options); -- size += sprintf(BLS, "user(%d/%d/%d/%d)\n", -- p->transinfo[target].user_period, -- p->transinfo[target].user_offset, -- p->transinfo[target].user_width, -- p->transinfo[target].user_options); --#ifdef AIC7XXX_PROC_STATS -- size += sprintf(BLS, " Total transfers %ld (%ld reads and %ld writes)\n", -- sp->r_total + sp->w_total, sp->r_total, sp->w_total); -- size += sprintf(BLS, "%s\n", HDRB); -- size += sprintf(BLS, " Reads:"); -- for (i = 0; i < NUMBER(sp->r_bins); i++) -- { -- size += sprintf(BLS, " %7ld", sp->r_bins[i]); -- } -- size += sprintf(BLS, "\n"); -- size += sprintf(BLS, " Writes:"); -- for (i = 0; i < NUMBER(sp->w_bins); i++) -- { -- size += sprintf(BLS, " %7ld", sp->w_bins[i]); -- } -- size += sprintf(BLS, "\n"); --#else -- size += sprintf(BLS, " Total transfers %ld (%ld reads and %ld writes)\n", -- sp->r_total + sp->w_total, sp->r_total, sp->w_total); --#endif /* AIC7XXX_PROC_STATS */ -- size += sprintf(BLS, "\n\n"); -- } -- -- if (size >= aic7xxx_buffer_size) -- { -- printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n"); -- } -- -- if (offset > size - 1) -- { -- kfree(aic7xxx_buffer); -- aic7xxx_buffer = NULL; -- aic7xxx_buffer_size = length = 0; -- *start = NULL; -- } -- else -- { -- *start = buffer; -- length = MIN(length, size - offset); -- memcpy(buffer, &aic7xxx_buffer[offset], length); -- } -- -- return (length); --} -- --/* -- * Overrides for Emacs so that we follow Linus's tabbing style. -- * Emacs will notice this stuff at the end of the file and automatically -- * adjust the settings for this buffer only. This must remain at the end -- * of the file. -- * --------------------------------------------------------------------------- -- * Local variables: -- * c-indent-level: 2 -- * c-brace-imaginary-offset: 0 -- * c-brace-offset: -2 -- * c-argdecl-indent: 2 -- * c-label-offset: -2 -- * c-continued-statement-offset: 2 -- * c-continued-brace-offset: 0 -- * indent-tabs-mode: nil -- * tab-width: 8 -- * End: -- */ -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx_reg.h linux/drivers/scsi/aic7xxx_reg.h ---- linux-2.2.17/drivers/scsi/aic7xxx_reg.h Wed May 3 20:16:44 2000 -+++ linux/drivers/scsi/aic7xxx_reg.h Wed Dec 31 19:00:00 1969 -@@ -1,629 +0,0 @@ --/* -- * DO NOT EDIT - This file is automatically generated. -- */ -- --#define SCSISEQ 0x00 --#define TEMODE 0x80 --#define ENSELO 0x40 --#define ENSELI 0x20 --#define ENRSELI 0x10 --#define ENAUTOATNO 0x08 --#define ENAUTOATNI 0x04 --#define ENAUTOATNP 0x02 --#define SCSIRSTO 0x01 -- --#define SXFRCTL0 0x01 --#define DFON 0x80 --#define DFPEXP 0x40 --#define FAST20 0x20 --#define CLRSTCNT 0x10 --#define SPIOEN 0x08 --#define SCAMEN 0x04 --#define CLRCHN 0x02 -- --#define SXFRCTL1 0x02 --#define BITBUCKET 0x80 --#define SWRAPEN 0x40 --#define ENSPCHK 0x20 --#define STIMESEL 0x18 --#define ENSTIMER 0x04 --#define ACTNEGEN 0x02 --#define STPWEN 0x01 -- --#define SCSISIGO 0x03 --#define CDO 0x80 --#define IOO 0x40 --#define MSGO 0x20 --#define ATNO 0x10 --#define SELO 0x08 --#define BSYO 0x04 --#define REQO 0x02 --#define ACKO 0x01 -- --#define SCSISIGI 0x03 --#define ATNI 0x10 --#define SELI 0x08 --#define BSYI 0x04 --#define REQI 0x02 --#define ACKI 0x01 -- --#define SCSIRATE 0x04 --#define WIDEXFER 0x80 --#define SXFR_ULTRA2 0x7f --#define SXFR 0x70 --#define SOFS 0x0f -- --#define SCSIID 0x05 --#define SCSIOFFSET 0x05 --#define SOFS_ULTRA2 0x7f -- --#define SCSIDATL 0x06 -- --#define SCSIDATH 0x07 -- --#define STCNT 0x08 -- --#define OPTIONMODE 0x08 --#define AUTORATEEN 0x80 --#define AUTOACKEN 0x40 --#define ATNMGMNTEN 0x20 --#define BUSFREEREV 0x10 --#define EXPPHASEDIS 0x08 --#define SCSIDATL_IMGEN 0x04 --#define AUTO_MSGOUT_DE 0x02 --#define DIS_MSGIN_DUALEDGE 0x01 -- --#define CLRSINT0 0x0b --#define CLRSELDO 0x40 --#define CLRSELDI 0x20 --#define CLRSELINGO 0x10 --#define CLRSWRAP 0x08 --#define CLRSPIORDY 0x02 -- --#define SSTAT0 0x0b --#define TARGET 0x80 --#define SELDO 0x40 --#define SELDI 0x20 --#define SELINGO 0x10 --#define IOERR 0x08 --#define SWRAP 0x08 --#define SDONE 0x04 --#define SPIORDY 0x02 --#define DMADONE 0x01 -- --#define CLRSINT1 0x0c --#define CLRSELTIMEO 0x80 --#define CLRATNO 0x40 --#define CLRSCSIRSTI 0x20 --#define CLRBUSFREE 0x08 --#define CLRSCSIPERR 0x04 --#define CLRPHASECHG 0x02 --#define CLRREQINIT 0x01 -- --#define SSTAT1 0x0c --#define SELTO 0x80 --#define ATNTARG 0x40 --#define SCSIRSTI 0x20 --#define PHASEMIS 0x10 --#define BUSFREE 0x08 --#define SCSIPERR 0x04 --#define PHASECHG 0x02 --#define REQINIT 0x01 -- --#define SSTAT2 0x0d --#define OVERRUN 0x80 --#define SHVALID 0x40 --#define WIDE_RES 0x20 --#define SFCNT 0x1f --#define EXP_ACTIVE 0x10 --#define CRCVALERR 0x08 --#define CRCENDERR 0x04 --#define CRCREQERR 0x02 --#define DUAL_EDGE_ERROR 0x01 -- --#define SSTAT3 0x0e --#define SCSICNT 0xf0 --#define OFFCNT 0x0f -- --#define SCSIID_ULTRA2 0x0f --#define OID 0x0f -- --#define SIMODE0 0x10 --#define ENSELDO 0x40 --#define ENSELDI 0x20 --#define ENSELINGO 0x10 --#define ENIOERR 0x08 --#define ENSWRAP 0x08 --#define ENSDONE 0x04 --#define ENSPIORDY 0x02 --#define ENDMADONE 0x01 -- --#define SIMODE1 0x11 --#define ENSELTIMO 0x80 --#define ENATNTARG 0x40 --#define ENSCSIRST 0x20 --#define ENPHASEMIS 0x10 --#define ENBUSFREE 0x08 --#define ENSCSIPERR 0x04 --#define ENPHASECHG 0x02 --#define ENREQINIT 0x01 -- --#define SCSIBUSL 0x12 -- --#define SCSIBUSH 0x13 -- --#define SHADDR 0x14 -- --#define SELTIMER 0x18 --#define STAGE6 0x20 --#define STAGE5 0x10 --#define STAGE4 0x08 --#define STAGE3 0x04 --#define STAGE2 0x02 --#define STAGE1 0x01 -- --#define SELID 0x19 --#define SELID_MASK 0xf0 --#define ONEBIT 0x08 -- --#define SPIOCAP 0x1b --#define SOFT1 0x80 --#define SOFT0 0x40 --#define SOFTCMDEN 0x20 --#define HAS_BRDCTL 0x10 --#define SEEPROM 0x08 --#define EEPROM 0x04 --#define ROM 0x02 --#define SSPIOCPS 0x01 -- --#define BRDCTL 0x1d --#define BRDDAT7 0x80 --#define BRDDAT6 0x40 --#define BRDDAT5 0x20 --#define BRDDAT4 0x10 --#define BRDSTB 0x10 --#define BRDCS 0x08 --#define BRDDAT3 0x08 --#define BRDDAT2 0x04 --#define BRDRW 0x04 --#define BRDRW_ULTRA2 0x02 --#define BRDCTL1 0x02 --#define BRDCTL0 0x01 --#define BRDSTB_ULTRA2 0x01 -- --#define SEECTL 0x1e --#define EXTARBACK 0x80 --#define EXTARBREQ 0x40 --#define SEEMS 0x20 --#define SEERDY 0x10 --#define SEECS 0x08 --#define SEECK 0x04 --#define SEEDO 0x02 --#define SEEDI 0x01 -- --#define SBLKCTL 0x1f --#define DIAGLEDEN 0x80 --#define DIAGLEDON 0x40 --#define AUTOFLUSHDIS 0x20 --#define ENAB40 0x08 --#define ENAB20 0x04 --#define SELWIDE 0x02 --#define XCVR 0x01 -- --#define SRAM_BASE 0x20 -- --#define TARG_SCSIRATE 0x20 -- --#define ULTRA_ENB 0x30 -- --#define DISC_DSB 0x32 -- --#define MSG_OUT 0x34 -- --#define DMAPARAMS 0x35 --#define PRELOADEN 0x80 --#define WIDEODD 0x40 --#define SCSIEN 0x20 --#define SDMAENACK 0x10 --#define SDMAEN 0x10 --#define HDMAEN 0x08 --#define HDMAENACK 0x08 --#define DIRECTION 0x04 --#define FIFOFLUSH 0x02 --#define FIFORESET 0x01 -- --#define SEQ_FLAGS 0x36 --#define IDENTIFY_SEEN 0x80 --#define SCBPTR_VALID 0x20 --#define DPHASE 0x10 --#define AMTARGET 0x08 --#define WIDE_BUS 0x02 --#define TWIN_BUS 0x01 -- --#define SAVED_TCL 0x37 -- --#define SG_COUNT 0x38 -- --#define SG_NEXT 0x39 -- --#define LASTPHASE 0x3d --#define P_MESGIN 0xe0 --#define PHASE_MASK 0xe0 --#define P_STATUS 0xc0 --#define P_MESGOUT 0xa0 --#define P_COMMAND 0x80 --#define CDI 0x80 --#define IOI 0x40 --#define P_DATAIN 0x40 --#define MSGI 0x20 --#define P_BUSFREE 0x01 --#define P_DATAOUT 0x00 -- --#define WAITING_SCBH 0x3e -- --#define DISCONNECTED_SCBH 0x3f -- --#define FREE_SCBH 0x40 -- --#define HSCB_ADDR 0x41 -- --#define SCBID_ADDR 0x45 -- --#define TMODE_CMDADDR 0x49 -- --#define KERNEL_QINPOS 0x4d -- --#define QINPOS 0x4e -- --#define QOUTPOS 0x4f -- --#define TMODE_CMDADDR_NEXT 0x50 -- --#define ARG_1 0x51 --#define RETURN_1 0x51 --#define SEND_MSG 0x80 --#define SEND_SENSE 0x40 --#define SEND_REJ 0x20 --#define MSGOUT_PHASEMIS 0x10 -- --#define ARG_2 0x52 --#define RETURN_2 0x52 -- --#define LAST_MSG 0x53 -- --#define PREFETCH_CNT 0x54 -- --#define SCSICONF 0x5a --#define TERM_ENB 0x80 --#define RESET_SCSI 0x40 --#define HWSCSIID 0x0f --#define HSCSIID 0x07 -- --#define HOSTCONF 0x5d -- --#define HA_274_BIOSCTRL 0x5f --#define BIOSMODE 0x30 --#define BIOSDISABLED 0x30 --#define CHANNEL_B_PRIMARY 0x08 -- --#define SEQCTL 0x60 --#define PERRORDIS 0x80 --#define PAUSEDIS 0x40 --#define FAILDIS 0x20 --#define FASTMODE 0x10 --#define BRKADRINTEN 0x08 --#define STEP 0x04 --#define SEQRESET 0x02 --#define LOADRAM 0x01 -- --#define SEQRAM 0x61 -- --#define SEQADDR0 0x62 -- --#define SEQADDR1 0x63 --#define SEQADDR1_MASK 0x01 -- --#define ACCUM 0x64 -- --#define SINDEX 0x65 -- --#define DINDEX 0x66 -- --#define ALLONES 0x69 -- --#define ALLZEROS 0x6a -- --#define NONE 0x6a -- --#define FLAGS 0x6b --#define ZERO 0x02 --#define CARRY 0x01 -- --#define SINDIR 0x6c -- --#define DINDIR 0x6d -- --#define FUNCTION1 0x6e -- --#define STACK 0x6f -- --#define TARG_OFFSET 0x70 -- --#define BCTL 0x84 --#define ACE 0x08 --#define ENABLE 0x01 -- --#define DSCOMMAND0 0x84 --#define INTSCBRAMSEL 0x08 --#define RAMPS 0x04 --#define USCBSIZE32 0x02 --#define CIOPARCKEN 0x01 -- --#define DSCOMMAND 0x84 --#define CACHETHEN 0x80 --#define DPARCKEN 0x40 --#define MPARCKEN 0x20 --#define EXTREQLCK 0x10 -- --#define BUSTIME 0x85 --#define BOFF 0xf0 --#define BON 0x0f -- --#define BUSSPD 0x86 --#define DFTHRSH 0xc0 --#define STBOFF 0x38 --#define STBON 0x07 -- --#define DSPCISTATUS 0x86 --#define DFTHRSH_100 0xc0 -- --#define HCNTRL 0x87 --#define POWRDN 0x40 --#define SWINT 0x10 --#define IRQMS 0x08 --#define PAUSE 0x04 --#define INTEN 0x02 --#define CHIPRST 0x01 --#define CHIPRSTACK 0x01 -- --#define HADDR 0x88 -- --#define HCNT 0x8c -- --#define SCBPTR 0x90 -- --#define INTSTAT 0x91 --#define SEQINT_MASK 0xf1 --#define DATA_OVERRUN 0xe1 --#define MSGIN_PHASEMIS 0xd1 --#define TRACEPOINT2 0xc1 --#define TRACEPOINT 0xb1 --#define AWAITING_MSG 0xa1 --#define RESIDUAL 0x81 --#define BAD_STATUS 0x71 --#define REJECT_MSG 0x61 --#define WIDE_RESIDUE 0x51 --#define EXTENDED_MSG 0x41 --#define NO_MATCH 0x31 --#define NO_IDENT 0x21 --#define SEND_REJECT 0x11 --#define INT_PEND 0x0f --#define BRKADRINT 0x08 --#define SCSIINT 0x04 --#define CMDCMPLT 0x02 --#define BAD_PHASE 0x01 --#define SEQINT 0x01 -- --#define CLRINT 0x92 --#define CLRPARERR 0x10 --#define CLRBRKADRINT 0x08 --#define CLRSCSIINT 0x04 --#define CLRCMDINT 0x02 --#define CLRSEQINT 0x01 -- --#define ERROR 0x92 --#define CIOPARERR 0x80 --#define PCIERRSTAT 0x40 --#define MPARERR 0x20 --#define DPARERR 0x10 --#define SQPARERR 0x08 --#define ILLOPCODE 0x04 --#define DSCTMOUT 0x02 --#define ILLSADDR 0x02 --#define ILLHADDR 0x01 -- --#define DFCNTRL 0x93 -- --#define DFSTATUS 0x94 --#define PRELOAD_AVAIL 0x80 --#define DWORDEMP 0x20 --#define MREQPEND 0x10 --#define HDONE 0x08 --#define DFTHRESH 0x04 --#define FIFOFULL 0x02 --#define FIFOEMP 0x01 -- --#define DFDAT 0x99 -- --#define SCBCNT 0x9a --#define SCBAUTO 0x80 --#define SCBCNT_MASK 0x1f -- --#define QINFIFO 0x9b -- --#define QINCNT 0x9c -- --#define SCSIDATL_IMG 0x9c -- --#define QOUTFIFO 0x9d -- --#define CRCCONTROL1 0x9d --#define CRCONSEEN 0x80 --#define CRCVALCHKEN 0x40 --#define CRCENDCHKEN 0x20 --#define CRCREQCHKEN 0x10 --#define TARGCRCENDEN 0x08 --#define TARGCRCCNTEN 0x04 -- --#define QOUTCNT 0x9e -- --#define SCSIPHASE 0x9e --#define SP_STATUS 0x20 --#define SP_COMMAND 0x10 --#define SP_MSG_IN 0x08 --#define SP_MSG_OUT 0x04 --#define SP_DATA_IN 0x02 --#define SP_DATA_OUT 0x01 -- --#define SFUNCT 0x9f --#define ALT_MODE 0x80 -- --#define SCB_CONTROL 0xa0 --#define MK_MESSAGE 0x80 --#define DISCENB 0x40 --#define TAG_ENB 0x20 --#define DISCONNECTED 0x04 --#define SCB_TAG_TYPE 0x03 -- --#define SCB_BASE 0xa0 -- --#define SCB_TCL 0xa1 --#define TID 0xf0 --#define SELBUSB 0x08 --#define LID 0x07 -- --#define SCB_TARGET_STATUS 0xa2 -- --#define SCB_SGCOUNT 0xa3 -- --#define SCB_SGPTR 0xa4 -- --#define SCB_RESID_SGCNT 0xa8 -- --#define SCB_RESID_DCNT 0xa9 -- --#define SCB_DATAPTR 0xac -- --#define SCB_DATACNT 0xb0 -- --#define SCB_CMDPTR 0xb4 -- --#define SCB_CMDLEN 0xb8 -- --#define SCB_TAG 0xb9 -- --#define SCB_NEXT 0xba -- --#define SCB_PREV 0xbb -- --#define SCB_BUSYTARGETS 0xbc -- --#define SEECTL_2840 0xc0 --#define CS_2840 0x04 --#define CK_2840 0x02 --#define DO_2840 0x01 -- --#define STATUS_2840 0xc1 --#define EEPROM_TF 0x80 --#define BIOS_SEL 0x60 --#define ADSEL 0x1e --#define DI_2840 0x01 -- --#define CCHADDR 0xe0 -- --#define CCHCNT 0xe8 -- --#define CCSGRAM 0xe9 -- --#define CCSGADDR 0xea -- --#define CCSGCTL 0xeb --#define CCSGDONE 0x80 --#define CCSGEN 0x08 --#define FLAG 0x02 --#define CCSGRESET 0x01 -- --#define CCSCBRAM 0xec -- --#define CCSCBADDR 0xed -- --#define CCSCBCTL 0xee --#define CCSCBDONE 0x80 --#define ARRDONE 0x40 --#define CCARREN 0x10 --#define CCSCBEN 0x08 --#define CCSCBDIR 0x04 --#define CCSCBRESET 0x01 -- --#define CCSCBCNT 0xef -- --#define CCSCBPTR 0xf1 -- --#define HNSCB_QOFF 0xf4 -- --#define HESCB_QOFF 0xf5 -- --#define SNSCB_QOFF 0xf6 -- --#define SESCB_QOFF 0xf7 -- --#define SDSCB_QOFF 0xf8 -- --#define QOFF_CTLSTA 0xfa --#define ESTABLISH_SCB_AVAIL 0x80 --#define SCB_AVAIL 0x40 --#define SNSCB_ROLLOVER 0x20 --#define SDSCB_ROLLOVER 0x10 --#define SESCB_ROLLOVER 0x08 --#define SCB_QSIZE 0x07 --#define SCB_QSIZE_256 0x06 -- --#define DFF_THRSH 0xfb --#define WR_DFTHRSH 0x70 --#define WR_DFTHRSH_MAX 0x70 --#define WR_DFTHRSH_90 0x60 --#define WR_DFTHRSH_85 0x50 --#define WR_DFTHRSH_75 0x40 --#define WR_DFTHRSH_63 0x30 --#define WR_DFTHRSH_50 0x20 --#define WR_DFTHRSH_25 0x10 --#define RD_DFTHRSH_MAX 0x07 --#define RD_DFTHRSH 0x07 --#define RD_DFTHRSH_90 0x06 --#define RD_DFTHRSH_85 0x05 --#define RD_DFTHRSH_75 0x04 --#define RD_DFTHRSH_63 0x03 --#define RD_DFTHRSH_50 0x02 --#define RD_DFTHRSH_25 0x01 --#define RD_DFTHRSH_MIN 0x00 --#define WR_DFTHRSH_MIN 0x00 -- --#define SG_CACHEPTR 0xfc --#define SG_USER_DATA 0xfc --#define LAST_SEG 0x02 --#define LAST_SEG_DONE 0x01 -- -- --#define CMD_GROUP_CODE_SHIFT 0x05 --#define BUS_8_BIT 0x00 --#define QOUTFIFO_OFFSET 0x01 --#define CCSGRAM_MAXSEGS 0x10 --#define CMD_GROUP2_BYTE_DELTA 0xfa --#define MAX_OFFSET_8BIT 0x0f --#define BUS_16_BIT 0x01 --#define QINFIFO_OFFSET 0x02 --#define CMD_GROUP5_BYTE_DELTA 0x0b --#define MAX_OFFSET_ULTRA2 0x7f --#define MAX_OFFSET_16BIT 0x08 --#define UNTAGGEDSCB_OFFSET 0x00 --#define SCB_LIST_NULL 0xff --#define SG_SIZEOF 0x08 --#define CMD_GROUP4_BYTE_DELTA 0x04 --#define CMD_GROUP0_BYTE_DELTA 0xfc --#define HOST_MSG 0xff --#define BUS_32_BIT 0x02 --#define CCSGADDR_MAX 0x80 -- -- --/* Downloaded Constant Definitions */ --#define TMODE_NUMCMDS 0x00 -diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx_seq.c linux/drivers/scsi/aic7xxx_seq.c ---- linux-2.2.17/drivers/scsi/aic7xxx_seq.c Mon Sep 4 13:39:21 2000 -+++ linux/drivers/scsi/aic7xxx_seq.c Wed Dec 31 19:00:00 1969 -@@ -1,745 +0,0 @@ --/* -- * DO NOT EDIT - This file is automatically generated. -- */ --static unsigned char seqprog[] = { -- 0xff, 0x6a, 0x06, 0x08, -- 0x7f, 0x02, 0x04, 0x08, -- 0x12, 0x6a, 0x00, 0x00, -- 0xff, 0x6a, 0xd6, 0x09, -- 0xff, 0x6a, 0xdc, 0x09, -- 0x00, 0x65, 0xca, 0x58, -- 0xf7, 0x01, 0x02, 0x08, -- 0xff, 0x4e, 0xc8, 0x08, -- 0xbf, 0x60, 0xc0, 0x08, -- 0x60, 0x0b, 0x86, 0x68, -- 0x40, 0x00, 0x0c, 0x68, -- 0x08, 0x1f, 0x3e, 0x10, -- 0x60, 0x0b, 0x86, 0x68, -- 0x40, 0x00, 0x0c, 0x68, -- 0x08, 0x1f, 0x3e, 0x10, -- 0xff, 0x3e, 0x48, 0x60, -- 0x40, 0xfa, 0x10, 0x78, -- 0xff, 0xf6, 0xd4, 0x08, -- 0x01, 0x4e, 0x9c, 0x18, -- 0x40, 0x60, 0xc0, 0x00, -- 0x00, 0x4d, 0x10, 0x70, -- 0x01, 0x4e, 0x9c, 0x18, -- 0xbf, 0x60, 0xc0, 0x08, -- 0x00, 0x6a, 0x3e, 0x5c, -- 0xff, 0x4e, 0xc8, 0x18, -- 0x02, 0x6a, 0x54, 0x5b, -- 0xff, 0x52, 0x20, 0x09, -- 0x0d, 0x6a, 0x6a, 0x00, -- 0x00, 0x52, 0xca, 0x5b, -- 0x03, 0xb0, 0x52, 0x31, -- 0xff, 0xb0, 0x52, 0x09, -- 0xff, 0xb1, 0x54, 0x09, -- 0xff, 0xb2, 0x56, 0x09, -- 0xff, 0xa3, 0x50, 0x09, -- 0xff, 0x3e, 0x74, 0x09, -- 0xff, 0x90, 0x7c, 0x08, -- 0xff, 0x3e, 0x20, 0x09, -- 0x00, 0x65, 0x4e, 0x58, -- 0x00, 0x65, 0x0c, 0x40, -- 0xf7, 0x1f, 0xca, 0x08, -- 0x08, 0xa1, 0xc8, 0x08, -- 0x00, 0x65, 0xca, 0x00, -- 0xff, 0x65, 0x3e, 0x08, -- 0xf0, 0xa1, 0xc8, 0x08, -- 0x0f, 0x0f, 0x1e, 0x08, -- 0x00, 0x0f, 0x1e, 0x00, -- 0xf0, 0xa1, 0xc8, 0x08, -- 0x0f, 0x05, 0x0a, 0x08, -- 0x00, 0x05, 0x0a, 0x00, -- 0xff, 0x6a, 0x0c, 0x08, -- 0x5a, 0x6a, 0x00, 0x04, -- 0x12, 0x65, 0x02, 0x00, -- 0x31, 0x6a, 0xca, 0x00, -- 0x80, 0x37, 0x6e, 0x68, -- 0xff, 0x65, 0xca, 0x18, -- 0xff, 0x37, 0xdc, 0x08, -- 0xff, 0x6e, 0xc8, 0x08, -- 0x00, 0x6c, 0x76, 0x78, -- 0x20, 0x01, 0x02, 0x00, -- 0x4c, 0x37, 0xc8, 0x28, -- 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, 0x96, 0x68, -- 0x20, 0x6a, 0x16, 0x00, -- 0xf0, 0x19, 0x6e, 0x08, -- 0x08, 0x6a, 0x18, 0x00, -- 0x08, 0x11, 0x22, 0x00, -- 0x08, 0x6a, 0x66, 0x58, -- 0x08, 0x6a, 0x68, 0x00, -- 0x00, 0x65, 0xaa, 0x40, -- 0x12, 0x6a, 0x00, 0x00, -- 0x40, 0x6a, 0x16, 0x00, -- 0xff, 0x3e, 0x20, 0x09, -- 0xff, 0xba, 0x7c, 0x08, -- 0xff, 0xa1, 0x6e, 0x08, -- 0x08, 0x6a, 0x18, 0x00, -- 0x08, 0x11, 0x22, 0x00, -- 0x08, 0x6a, 0x66, 0x58, -- 0x80, 0x6a, 0x68, 0x00, -- 0x80, 0x36, 0x6c, 0x00, -- 0x00, 0x65, 0x9e, 0x5b, -- 0xff, 0x3d, 0xc8, 0x08, -- 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, 0xaa, 0x40, -- 0xf7, 0x11, 0x22, 0x08, -- 0x00, 0x65, 0xca, 0x58, -- 0xff, 0x06, 0xd4, 0x08, -- 0xf7, 0x01, 0x02, 0x08, -- 0x09, 0x0c, 0xc4, 0x78, -- 0x08, 0x0c, 0x0c, 0x68, -- 0x01, 0x6a, 0x22, 0x01, -- 0xff, 0x6a, 0x26, 0x09, -- 0x02, 0x6a, 0x08, 0x30, -- 0xff, 0x6a, 0x08, 0x08, -- 0xdf, 0x01, 0x02, 0x08, -- 0x01, 0x6a, 0x7a, 0x00, -- 0xff, 0x6a, 0x6c, 0x0c, -- 0x04, 0x14, 0x10, 0x31, -- 0x03, 0xa9, 0x18, 0x31, -- 0x03, 0xa9, 0x10, 0x30, -- 0x08, 0x6a, 0xcc, 0x00, -- 0xa9, 0x6a, 0xb4, 0x5b, -- 0x00, 0x65, 0x02, 0x41, -- 0xa8, 0x6a, 0x6a, 0x00, -- 0x79, 0x6a, 0x6a, 0x00, -- 0x40, 0x3d, 0xea, 0x68, -- 0x04, 0x35, 0x6a, 0x00, -- 0x00, 0x65, 0x0e, 0x5b, -- 0x80, 0x6a, 0xd4, 0x01, -- 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, 0xac, 0x5b, -- 0x00, 0x65, 0xa6, 0x5b, -- 0x38, 0x6a, 0xcc, 0x00, -- 0xa3, 0x6a, 0xb0, 0x5b, -- 0xff, 0x38, 0x12, 0x69, -- 0x80, 0x02, 0x04, 0x00, -- 0xe7, 0x35, 0x6a, 0x08, -- 0x03, 0x69, 0x18, 0x31, -- 0x03, 0x69, 0x10, 0x30, -- 0xff, 0x6a, 0x10, 0x00, -- 0xff, 0x6a, 0x12, 0x00, -- 0xff, 0x6a, 0x14, 0x00, -- 0x01, 0x38, 0x18, 0x61, -- 0xbf, 0x35, 0x6a, 0x08, -- 0x02, 0x6a, 0xf8, 0x01, -- 0xff, 0x69, 0xca, 0x08, -- 0xff, 0x35, 0x26, 0x09, -- 0x04, 0x0b, 0x1c, 0x69, -- 0x04, 0x0b, 0x28, 0x69, -- 0x10, 0x0c, 0x1e, 0x79, -- 0x04, 0x0b, 0x28, 0x69, -- 0xff, 0x6a, 0xca, 0x08, -- 0x00, 0x35, 0xee, 0x5a, -- 0x80, 0x02, 0x7c, 0x69, -- 0xff, 0x65, 0x6c, 0x79, -- 0xff, 0x38, 0x70, 0x18, -- 0xff, 0x38, 0x6c, 0x79, -- 0x80, 0xea, 0x48, 0x61, -- 0xef, 0x38, 0xc8, 0x18, -- 0x80, 0x6a, 0xc8, 0x00, -- 0x00, 0x65, 0x3a, 0x49, -- 0x33, 0x38, 0xc8, 0x28, -- 0xff, 0x64, 0xd0, 0x09, -- 0x04, 0x39, 0xc0, 0x31, -- 0x09, 0x6a, 0xd6, 0x01, -- 0x80, 0xeb, 0x40, 0x79, -- 0xf7, 0xeb, 0xd6, 0x09, -- 0x08, 0xeb, 0x44, 0x69, -- 0x01, 0x6a, 0xd6, 0x01, -- 0x08, 0xe9, 0x10, 0x31, -- 0x03, 0x8c, 0x10, 0x30, -- 0x88, 0x6a, 0xcc, 0x00, -- 0x39, 0x6a, 0xb2, 0x5b, -- 0x08, 0x6a, 0x18, 0x01, -- 0xff, 0x6a, 0x1a, 0x09, -- 0xff, 0x6a, 0x1c, 0x09, -- 0x0d, 0x93, 0x26, 0x01, -- 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, 0x64, 0x79, -- 0x10, 0x0c, 0x02, 0x79, -- 0xff, 0x35, 0x26, 0x09, -- 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, 0xaa, 0x40, -- 0x00, 0x65, 0x84, 0x59, -- 0x7f, 0x02, 0x04, 0x08, -- 0xe1, 0x6a, 0x22, 0x01, -- 0x00, 0x65, 0xaa, 0x40, -- 0x04, 0x93, 0x9a, 0x69, -- 0xdf, 0x93, 0x26, 0x09, -- 0x20, 0x93, 0x88, 0x69, -- 0x02, 0x93, 0x26, 0x01, -- 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, -- 0x11, 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, 0x0e, 0x5b, -- 0x05, 0xb4, 0x10, 0x31, -- 0x02, 0x6a, 0x1a, 0x31, -- 0x03, 0x8c, 0x10, 0x30, -- 0x88, 0x6a, 0xcc, 0x00, -- 0xb4, 0x6a, 0xb0, 0x5b, -- 0xff, 0x6a, 0x1a, 0x09, -- 0xff, 0x6a, 0x1c, 0x09, -- 0x00, 0x65, 0xa6, 0x5b, -- 0x3d, 0x6a, 0xee, 0x5a, -- 0xac, 0x6a, 0x26, 0x01, -- 0x04, 0x0b, 0xc2, 0x69, -- 0x04, 0x0b, 0xc8, 0x69, -- 0x10, 0x0c, 0xc4, 0x79, -- 0x02, 0x03, 0xcc, 0x79, -- 0x11, 0x0c, 0xc8, 0x79, -- 0xd7, 0x93, 0x26, 0x09, -- 0x28, 0x93, 0xce, 0x69, -- 0x12, 0x01, 0x02, 0x00, -- 0x00, 0x65, 0xaa, 0x40, -- 0x00, 0x65, 0x0e, 0x5b, -- 0xff, 0x06, 0x44, 0x09, -- 0x00, 0x65, 0xaa, 0x40, -- 0x10, 0x3d, 0x06, 0x00, -- 0xff, 0x34, 0xca, 0x08, -- 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, 0xf0, 0x79, -- 0xff, 0x65, 0x0c, 0x08, -- 0x00, 0x65, 0x02, 0x42, -- 0x20, 0xa0, 0x08, 0x7a, -- 0xff, 0x65, 0x0c, 0x08, -- 0x00, 0x65, 0x9e, 0x5b, -- 0xa0, 0x3d, 0x10, 0x62, -- 0x23, 0xa0, 0x0c, 0x08, -- 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, 0x10, 0x72, -- 0x40, 0x6a, 0x18, 0x00, -- 0xff, 0x65, 0x0c, 0x08, -- 0x00, 0x65, 0x9e, 0x5b, -- 0xa0, 0x3d, 0xda, 0x71, -- 0x40, 0x6a, 0x18, 0x00, -- 0xff, 0x34, 0xa6, 0x08, -- 0x80, 0x34, 0x18, 0x62, -- 0x7f, 0xa0, 0x40, 0x09, -- 0x08, 0x6a, 0x68, 0x00, -- 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, 0xd6, 0x5a, -- 0xff, 0x06, 0xd4, 0x08, -- 0x00, 0x65, 0xaa, 0x40, -- 0xff, 0xa8, 0x3c, 0x6a, -- 0xff, 0xa2, 0x54, 0x7a, -- 0x01, 0x6a, 0x6a, 0x00, -- 0x00, 0xb9, 0xca, 0x5b, -- 0xff, 0xa2, 0x54, 0x7a, -- 0x71, 0x6a, 0x22, 0x01, -- 0xff, 0x6a, 0xd4, 0x08, -- 0x40, 0x51, 0x54, 0x62, -- 0x0d, 0x6a, 0x6a, 0x00, -- 0x00, 0xb9, 0xca, 0x5b, -- 0xff, 0x3e, 0x74, 0x09, -- 0xff, 0x90, 0x7c, 0x08, -- 0x00, 0x65, 0x4e, 0x58, -- 0x00, 0x65, 0xbc, 0x40, -- 0x20, 0xa0, 0x5c, 0x6a, -- 0xff, 0x37, 0xc8, 0x08, -- 0x00, 0x6a, 0x74, 0x5b, -- 0xff, 0x6a, 0x8a, 0x5b, -- 0xff, 0xf8, 0xc8, 0x08, -- 0xff, 0x4f, 0xc8, 0x08, -- 0x01, 0x6a, 0x74, 0x5b, -- 0x00, 0xb9, 0x8a, 0x5b, -- 0x01, 0x4f, 0x9e, 0x18, -- 0x02, 0x6a, 0x22, 0x01, -- 0x00, 0x65, 0x38, 0x5c, -- 0x00, 0x65, 0xbc, 0x40, -- 0x41, 0x6a, 0x22, 0x01, -- 0x00, 0x65, 0xaa, 0x40, -- 0x04, 0xa0, 0x40, 0x01, -- 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, 0xb0, 0x5b, -- 0xac, 0x6a, 0xcc, 0x00, -- 0x14, 0x6a, 0xb2, 0x5b, -- 0xa9, 0x6a, 0xb4, 0x5b, -- 0x00, 0x65, 0x34, 0x42, -- 0xef, 0x36, 0x6c, 0x08, -- 0x00, 0x65, 0x34, 0x42, -- 0x0f, 0x64, 0xc8, 0x08, -- 0x07, 0x64, 0xc8, 0x08, -- 0x00, 0x37, 0x6e, 0x00, -- 0xff, 0x6a, 0xa4, 0x00, -- 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, 0x9e, 0x5b, -- 0xe0, 0x3d, 0xc6, 0x62, -- 0x20, 0x12, 0xc6, 0x62, -- 0x51, 0x6a, 0xda, 0x5a, -- 0x00, 0x65, 0x2c, 0x5b, -- 0xff, 0x37, 0xc8, 0x08, -- 0x00, 0xa1, 0xbe, 0x62, -- 0x04, 0xa0, 0xbe, 0x7a, -- 0xfb, 0xa0, 0x40, 0x09, -- 0x80, 0x36, 0x6c, 0x00, -- 0x80, 0xa0, 0x34, 0x7a, -- 0x7f, 0xa0, 0x40, 0x09, -- 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, 0xd6, 0x5a, -- 0x00, 0x65, 0x34, 0x42, -- 0x61, 0x6a, 0x22, 0x01, -- 0x00, 0x65, 0x34, 0x42, -- 0x51, 0x6a, 0xda, 0x5a, -- 0x51, 0x6a, 0x22, 0x01, -- 0x00, 0x65, 0x34, 0x42, -- 0x10, 0x3d, 0x06, 0x00, -- 0xff, 0x65, 0x68, 0x0c, -- 0xff, 0x06, 0xd4, 0x08, -- 0x01, 0x0c, 0xdc, 0x7a, -- 0x04, 0x0c, 0xde, 0x6a, -- 0xe0, 0x03, 0x7a, 0x08, -- 0xe0, 0x3d, 0xea, 0x62, -- 0xff, 0x65, 0xcc, 0x08, -- 0xff, 0x12, 0xda, 0x0c, -- 0xff, 0x06, 0xd4, 0x0c, -- 0xd1, 0x6a, 0x22, 0x01, -- 0x00, 0x65, 0xaa, 0x40, -- 0xff, 0x65, 0x26, 0x09, -- 0x01, 0x0b, 0xfe, 0x6a, -- 0x10, 0x0c, 0xf0, 0x7a, -- 0x04, 0x0b, 0xf8, 0x6a, -- 0xff, 0x6a, 0xca, 0x08, -- 0x04, 0x93, 0xfc, 0x6a, -- 0x01, 0x94, 0xfa, 0x7a, -- 0x10, 0x94, 0xfc, 0x6a, -- 0x80, 0x3d, 0x02, 0x73, -- 0x0f, 0x04, 0x06, 0x6b, -- 0x02, 0x03, 0x06, 0x7b, -- 0x11, 0x0c, 0x02, 0x7b, -- 0xc7, 0x93, 0x26, 0x09, -- 0xff, 0x99, 0xd4, 0x08, -- 0x38, 0x93, 0x08, 0x6b, -- 0xff, 0x6a, 0xd4, 0x0c, -- 0x80, 0x36, 0x0c, 0x6b, -- 0x21, 0x6a, 0x22, 0x05, -- 0xff, 0x65, 0x20, 0x09, -- 0xff, 0x51, 0x1a, 0x63, -- 0xff, 0x37, 0xc8, 0x08, -- 0xa1, 0x6a, 0x26, 0x43, -- 0xff, 0x51, 0xc8, 0x08, -- 0xb9, 0x6a, 0x26, 0x43, -- 0xff, 0x90, 0xa4, 0x08, -- 0xff, 0xba, 0x2a, 0x73, -- 0xff, 0xba, 0x20, 0x09, -- 0xff, 0x65, 0xca, 0x18, -- 0x00, 0x6c, 0x1e, 0x63, -- 0xff, 0x90, 0xca, 0x0c, -- 0xff, 0x6a, 0xca, 0x04, -- 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, 0x3e, 0x5c, -- 0x0d, 0x6a, 0x6a, 0x00, -- 0x00, 0x51, 0xca, 0x43, -- 0xff, 0x3f, 0x98, 0x73, -- 0xff, 0x6a, 0xa2, 0x00, -- 0x00, 0x3f, 0x12, 0x5b, -- 0xff, 0x65, 0x98, 0x73, -- 0x20, 0x36, 0x6c, 0x00, -- 0x20, 0xa0, 0x52, 0x6b, -- 0xff, 0xb9, 0xa2, 0x0c, -- 0xff, 0x6a, 0xa2, 0x04, -- 0xff, 0x65, 0xa4, 0x08, -- 0xe0, 0x6a, 0xcc, 0x00, -- 0x45, 0x6a, 0xbe, 0x5b, -- 0x01, 0x6a, 0xd0, 0x01, -- 0x09, 0x6a, 0xd6, 0x01, -- 0x80, 0xeb, 0x5e, 0x7b, -- 0x01, 0x6a, 0xd6, 0x01, -- 0x01, 0xe9, 0xa4, 0x34, -- 0x88, 0x6a, 0xcc, 0x00, -- 0x45, 0x6a, 0xbe, 0x5b, -- 0x01, 0x6a, 0x18, 0x01, -- 0xff, 0x6a, 0x1a, 0x09, -- 0xff, 0x6a, 0x1c, 0x09, -- 0x0d, 0x6a, 0x26, 0x01, -- 0x00, 0x65, 0x30, 0x5c, -- 0xff, 0x99, 0xa4, 0x0c, -- 0xff, 0x65, 0xa4, 0x08, -- 0xe0, 0x6a, 0xcc, 0x00, -- 0x45, 0x6a, 0xbe, 0x5b, -- 0x01, 0x6a, 0xd0, 0x01, -- 0x01, 0x6a, 0xdc, 0x05, -- 0x88, 0x6a, 0xcc, 0x00, -- 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, 0x8e, 0x7b, -- 0xff, 0x6a, 0xdc, 0x0d, -- 0xff, 0x65, 0x32, 0x09, -- 0x0a, 0x93, 0x26, 0x01, -- 0x00, 0x65, 0x30, 0x44, -- 0xff, 0x37, 0xc8, 0x08, -- 0x00, 0x6a, 0x54, 0x5b, -- 0xff, 0x52, 0xa2, 0x0c, -- 0x01, 0x0c, 0x9e, 0x7b, -- 0x04, 0x0c, 0x9e, 0x6b, -- 0xe0, 0x03, 0x06, 0x08, -- 0xe0, 0x03, 0x7a, 0x0c, -- 0xff, 0x8c, 0x10, 0x08, -- 0xff, 0x8d, 0x12, 0x08, -- 0xff, 0x8e, 0x14, 0x0c, -- 0xff, 0x6c, 0xda, 0x08, -- 0xff, 0x6c, 0xda, 0x08, -- 0xff, 0x6c, 0xda, 0x08, -- 0xff, 0x6c, 0xda, 0x08, -- 0xff, 0x6c, 0xda, 0x08, -- 0xff, 0x6c, 0xda, 0x08, -- 0xff, 0x6c, 0xda, 0x0c, -- 0x3d, 0x64, 0xa4, 0x28, -- 0x55, 0x64, 0xc8, 0x28, -- 0x00, 0x6c, 0xda, 0x18, -- 0xff, 0x52, 0xc8, 0x08, -- 0x00, 0x6c, 0xda, 0x20, -- 0xff, 0x6a, 0xc8, 0x08, -- 0x00, 0x6c, 0xda, 0x20, -- 0x00, 0x6c, 0xda, 0x24, -- 0xff, 0x65, 0xc8, 0x08, -- 0xe0, 0x6a, 0xcc, 0x00, -- 0x41, 0x6a, 0xba, 0x5b, -- 0xff, 0x90, 0xe2, 0x09, -- 0x20, 0x6a, 0xd0, 0x01, -- 0x04, 0x35, 0xdc, 0x7b, -- 0x1d, 0x6a, 0xdc, 0x01, -- 0xdc, 0xee, 0xd8, 0x63, -- 0x00, 0x65, 0xe8, 0x43, -- 0x01, 0x6a, 0xdc, 0x01, -- 0x20, 0xa0, 0xd8, 0x31, -- 0x09, 0xee, 0xdc, 0x01, -- 0x80, 0xee, 0xe2, 0x7b, -- 0x19, 0x6a, 0xdc, 0x01, -- 0xd8, 0xee, 0xe6, 0x63, -- 0xff, 0x6a, 0xdc, 0x09, -- 0x18, 0xee, 0xea, 0x6b, -- 0xff, 0x6a, 0xd4, 0x0c, -- 0x88, 0x6a, 0xcc, 0x00, -- 0x41, 0x6a, 0xba, 0x5b, -- 0x20, 0x6a, 0x18, 0x01, -- 0xff, 0x6a, 0x1a, 0x09, -- 0xff, 0x6a, 0x1c, 0x09, -- 0xff, 0x35, 0x26, 0x09, -- 0x04, 0x35, 0x14, 0x6c, -- 0xa0, 0x6a, 0xca, 0x00, -- 0x20, 0x65, 0xc8, 0x18, -- 0xff, 0x6c, 0x32, 0x09, -- 0xff, 0x6c, 0x32, 0x09, -- 0xff, 0x6c, 0x32, 0x09, -- 0xff, 0x6c, 0x32, 0x09, -- 0xff, 0x6c, 0x32, 0x09, -- 0xff, 0x6c, 0x32, 0x09, -- 0xff, 0x6c, 0x32, 0x09, -- 0xff, 0x6c, 0x32, 0x09, -- 0x00, 0x65, 0x00, 0x64, -- 0x0a, 0x93, 0x26, 0x01, -- 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, -- 0xff, 0x99, 0xda, 0x08, -- 0xff, 0x99, 0xda, 0x08, -- 0xff, 0x99, 0xda, 0x08, -- 0xff, 0x99, 0xda, 0x08, -- 0xff, 0x99, 0xda, 0x0c, -- 0x08, 0x94, 0x30, 0x7c, -- 0xf7, 0x93, 0x26, 0x09, -- 0x08, 0x93, 0x34, 0x6c, -- 0xff, 0x6a, 0xd4, 0x0c, -- 0xff, 0x40, 0x74, 0x09, -- 0xff, 0x90, 0x80, 0x08, -- 0xff, 0x6a, 0x72, 0x05, -- 0xff, 0x40, 0x4c, 0x64, -- 0xff, 0x3f, 0x44, 0x64, -- 0xff, 0x6a, 0xca, 0x04, -- 0xff, 0x3f, 0x20, 0x09, -- 0x01, 0x6a, 0x6a, 0x00, -- 0x00, 0xb9, 0xca, 0x5b, -- 0xff, 0xba, 0x7e, 0x0c, -- 0xff, 0x40, 0x20, 0x09, -- 0xff, 0xba, 0x80, 0x0c, -- 0xff, 0x3f, 0x74, 0x09, -- 0xff, 0x90, 0x7e, 0x0c, --}; -- --static int aic7xxx_patch12_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch12_func(struct aic7xxx_host *p) --{ -- return ((p->features & AHC_WIDE) != 0); --} -- --static int aic7xxx_patch11_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch11_func(struct aic7xxx_host *p) --{ -- return ((p->features & AHC_ULTRA2) == 0); --} -- --static int aic7xxx_patch10_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch10_func(struct aic7xxx_host *p) --{ -- return ((p->features & AHC_CMD_CHAN) == 0); --} -- --static int aic7xxx_patch9_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch9_func(struct aic7xxx_host *p) --{ -- return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895); --} -- --static int aic7xxx_patch8_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch8_func(struct aic7xxx_host *p) --{ -- return ((p->features & AHC_ULTRA) != 0); --} -- --static int aic7xxx_patch7_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch7_func(struct aic7xxx_host *p) --{ -- return ((p->features & AHC_ULTRA2) != 0); --} -- --static int aic7xxx_patch6_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch6_func(struct aic7xxx_host *p) --{ -- return ((p->flags & AHC_PAGESCBS) == 0); --} -- --static int aic7xxx_patch5_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch5_func(struct aic7xxx_host *p) --{ -- return ((p->flags & AHC_PAGESCBS) != 0); --} -- --static int aic7xxx_patch4_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch4_func(struct aic7xxx_host *p) --{ -- return ((p->features & AHC_QUEUE_REGS) != 0); --} -- --static int aic7xxx_patch3_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch3_func(struct aic7xxx_host *p) --{ -- return ((p->features & AHC_TWIN) != 0); --} -- --static int aic7xxx_patch2_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch2_func(struct aic7xxx_host *p) --{ -- return ((p->features & AHC_QUEUE_REGS) == 0); --} -- --static int aic7xxx_patch1_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch1_func(struct aic7xxx_host *p) --{ -- return ((p->features & AHC_CMD_CHAN) != 0); --} -- --static int aic7xxx_patch0_func(struct aic7xxx_host *p); -- --static int --aic7xxx_patch0_func(struct aic7xxx_host *p) --{ -- return (0); --} -- --struct sequencer_patch { -- int (*patch_func)(struct aic7xxx_host *); -- unsigned int begin :10, -- skip_instr :10, -- skip_patch :12; --} sequencer_patches[] = { -- { 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/isdn/Config.in b/drivers/isdn/Config.in index 7b8111881a66..b97184a7b5fd 100644 --- a/drivers/isdn/Config.in +++ b/drivers/isdn/Config.in @@ -1,11 +1,15 @@ # # ISDN device configuration # + +# only included if CONFIG_ISDN != n + if [ "$CONFIG_INET" != "n" ]; then bool ' Support synchronous PPP' CONFIG_ISDN_PPP if [ "$CONFIG_ISDN_PPP" != "n" ]; then - bool ' Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ - bool ' Support generic MP (RFC 1717)' CONFIG_ISDN_MPP + bool ' Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ + bool ' Support generic MP (RFC 1717)' CONFIG_ISDN_MPP + dep_tristate ' Support BSD compression' CONFIG_ISDN_PPP_BSDCOMP $CONFIG_ISDN fi fi bool ' Support audio via ISDN' CONFIG_ISDN_AUDIO @@ -19,7 +23,7 @@ fi mainmenu_option next_comment comment 'ISDN feature submodules' dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN - bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION + dep_tristate 'Support isdn diversion services' CONFIG_ISDN_DIVERSION $CONFIG_ISDN endmenu comment 'low-level hardware drivers' @@ -45,6 +49,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then bool ' Teles S0Box' CONFIG_HISAX_S0BOX bool ' AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1 bool ' AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI + bool ' AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA bool ' Elsa cards' CONFIG_HISAX_ELSA bool ' ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2 bool ' Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA @@ -74,39 +79,53 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then fi endmenu +### Active ISDN cards + mainmenu_option next_comment comment 'Active ISDN cards' -dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN -dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN -if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN - dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN -fi + +dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN +dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN +dep_tristate 'Spellcaster support' CONFIG_ISDN_DRV_SC $CONFIG_ISDN +dep_tristate 'IBM Active 2000 support' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN + dep_tristate 'Eicon active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then bool ' Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA fi -dep_tristate 'CAPI2.0 support' CONFIG_ISDN_CAPI $CONFIG_ISDN -if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - bool 'CAPI2.0 Middleware support' CONFIG_ISDN_CAPI_MIDDLEWARE - if [ "$CONFIG_ISDN_CAPI_MIDDLEWARE" != "n" ]; then - bool 'CAPI2.0 filesystem support' CONFIG_ISDN_CAPIFS - fi -fi + +# CAPI subsystem + +tristate 'CAPI2.0 support' CONFIG_ISDN_CAPI if [ "$CONFIG_ISDN_CAPI" != "n" ]; then - bool ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA - bool ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI - if [ "$CONFIG_ISDN_DRV_AVMB1_B1PCI" != "n" ]; then - if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - bool ' AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4 + bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON + dep_bool ' CAPI2.0 Middleware support (EXPERIMENTAL)' CONFIG_ISDN_CAPI_MIDDLEWARE $CONFIG_EXPERIMENTAL + dep_tristate ' CAPI2.0 /dev/capi support' CONFIG_ISDN_CAPI_CAPI20 $CONFIG_ISDN_CAPI + if [ "$CONFIG_ISDN_CAPI_MIDDLEWARE" = "y" ]; then + dep_mbool ' CAPI2.0 filesystem support' CONFIG_ISDN_CAPI_CAPIFS_BOOL $CONFIG_ISDN_CAPI_CAPI20 + if [ "$CONFIG_ISDN_CAPI_CAPIFS_BOOL" = "y" ]; then + define_tristate CONFIG_ISDN_CAPI_CAPIFS $CONFIG_ISDN_CAPI_CAPI20 + else + define_tristate CONFIG_ISDN_CAPI_CAPIFS n fi fi - bool ' AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA - bool ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - bool ' AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI - if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - bool ' AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4 - fi - bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON + dep_tristate ' CAPI2.0 capidrv interface support' CONFIG_ISDN_CAPI_CAPIDRV $CONFIG_ISDN_CAPI $CONFIG_ISDN fi + +# CAPI drivers + +if [ "$CONFIG_ISDN_CAPI" != "n" ]; then + dep_tristate ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA $CONFIG_ISDN_CAPI + dep_tristate ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI $CONFIG_ISDN_CAPI $CONFIG_PCI + dep_mbool ' AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4 $CONFIG_ISDN_DRV_AVMB1_B1PCI + dep_tristate ' AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA $CONFIG_ISDN_CAPI + dep_tristate ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA $CONFIG_ISDN_CAPI $CONFIG_PCMCIA + dep_tristate ' AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI $CONFIG_ISDN_CAPI $CONFIG_PCI + dep_tristate ' AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4 $CONFIG_ISDN_CAPI $CONFIG_PCI +fi + +# HYSDN + +dep_tristate ' Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)' CONFIG_HYSDN m $CONFIG_PROC_FS +dep_mbool ' HYSDN CAPI 2.0 support' CONFIG_HYSDN_CAPI $CONFIG_HYSDN $CONFIG_ISDN_CAPI endmenu diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile index 2414eddd2ebc..d2663a87d35a 100644 --- a/drivers/isdn/Makefile +++ b/drivers/isdn/Makefile @@ -1,141 +1,56 @@ -SUB_DIRS := -MOD_SUB_DIRS := -ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon divert - -L_OBJS := -LX_OBJS := -M_OBJS := -MX_OBJS := -O_OBJS := -OX_OBJS := -L_TARGET := -O_TARGET := - -ifeq ($(CONFIG_ISDN),y) - L_TARGET := isdn.a - L_OBJS += isdn_net.o isdn_tty.o isdn_cards.o isdn_v110.o - LX_OBJS += isdn_common.o - ifdef CONFIG_ISDN_PPP - L_OBJS += isdn_ppp.o - endif - ifdef CONFIG_ISDN_X25 - L_OBJS += isdn_x25iface.o - L_OBJS += isdn_concap.o - endif - ifdef CONFIG_ISDN_AUDIO - L_OBJS += isdn_audio.o - ifdef CONFIG_ISDN_TTY_FAX - L_OBJS += isdn_ttyfax.o - endif - endif -else - ifeq ($(CONFIG_ISDN),m) - M_OBJS += isdn.o - O_TARGET += isdn.o - O_OBJS += isdn_net.o isdn_tty.o isdn_v110.o - OX_OBJS += isdn_common.o - ifdef CONFIG_ISDN_PPP - O_OBJS += isdn_ppp.o - M_OBJS += isdn_bsdcomp.o - endif - ifdef CONFIG_ISDN_X25 - O_OBJS += isdn_x25iface.o - O_OBJS += isdn_concap.o - endif - ifdef CONFIG_ISDN_AUDIO - O_OBJS += isdn_audio.o - ifdef CONFIG_ISDN_TTY_FAX - O_OBJS += isdn_ttyfax.o - endif - endif - endif -endif - -ifeq ($(CONFIG_ISDN_DIVERSION),y) - ifeq ($(CONFIG_MODULES),y) - MOD_SUB_DIRS += divert - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_HISAX),y) - L_OBJS += hisax/hisax.o - SUB_DIRS += hisax - MOD_SUB_DIRS += hisax -else - ifeq ($(CONFIG_ISDN_DRV_HISAX),m) - MOD_SUB_DIRS += hisax - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_ICN),y) - L_OBJS += icn/icn_obj.o - SUB_DIRS += icn - MOD_SUB_DIRS += icn -else - ifeq ($(CONFIG_ISDN_DRV_ICN),m) - MOD_SUB_DIRS += icn - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_PCBIT),y) - L_OBJS += pcbit/pcbit.o - SUB_DIRS += pcbit - MOD_SUB_DIRS += pcbit -else - ifeq ($(CONFIG_ISDN_DRV_PCBIT),m) - MOD_SUB_DIRS += pcbit - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_SC),y) - L_OBJS += sc/sc.o - SUB_DIRS += sc - MOD_SUB_DIRS += sc -else - ifeq ($(CONFIG_ISDN_DRV_SC),m) - MOD_SUB_DIRS += sc - endif -endif - -ifeq ($(CONFIG_ISDN_CAPI),y) - L_OBJS += avmb1/avmb1.o - SUB_DIRS += avmb1 - MOD_SUB_DIRS += avmb1 -else - ifeq ($(CONFIG_ISDN_CAPI),m) - MOD_SUB_DIRS += avmb1 - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_LOOP),y) - L_OBJS += isdnloop/isdnloop.o - SUB_DIRS += isdnloop - MOD_SUB_DIRS += isdnloop -else - ifeq ($(CONFIG_ISDN_DRV_LOOP),m) - MOD_SUB_DIRS += isdnloop - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_ACT2000),y) - L_OBJS += act2000/act2000.o - SUB_DIRS += act2000 - MOD_SUB_DIRS += act2000 -else - ifeq ($(CONFIG_ISDN_DRV_ACT2000),m) - MOD_SUB_DIRS += act2000 - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_EICON),y) - L_OBJS += eicon/eicon.o - SUB_DIRS += eicon - MOD_SUB_DIRS += eicon -else - ifeq ($(CONFIG_ISDN_DRV_EICON),m) - MOD_SUB_DIRS += eicon - endif -endif - -include $(TOPDIR)/Rules.make +# Makefile for the kernel ISDN subsystem and device drivers. +# The target object and module list name. + +O_TARGET := isdn.a + +# Objects that export symbols. + +export-objs := isdn_common.o + +# Multipart objects. + +list-multi := isdn.o +isdn-objs := isdn_net.o isdn_tty.o isdn_v110.o isdn_common.o + +# Optional parts of multipart objects. + +isdn-objs-$(CONFIG_ISDN_PPP) += isdn_ppp.o +isdn-objs-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o +isdn-objs-$(CONFIG_ISDN_AUDIO) += isdn_audio.o +isdn-objs-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o +isdn-objs-$(CONFIG_ISDN_WITH_ABC) += isdn_dwabc.o + +isdn-objs += $(isdn-objs-y) + +# Ordering constraints: isdn.o first, rest doesn't matter + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN) += isdn.o +obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o + +# Object files in subdirectories + +mod-subdirs := avmb1 +subdir-$(CONFIG_ISDN_DIVERSION) += divert +subdir-$(CONFIG_ISDN_DRV_HISAX) += hisax +subdir-$(CONFIG_ISDN_DRV_ICN) += icn +subdir-$(CONFIG_ISDN_DRV_PCBIT) += pcbit +subdir-$(CONFIG_ISDN_DRV_SC) += sc +subdir-$(CONFIG_ISDN_CAPI) += avmb1 +subdir-$(CONFIG_ISDN_DRV_LOOP) += isdnloop +subdir-$(CONFIG_ISDN_DRV_ACT2000) += act2000 +subdir-$(CONFIG_ISDN_DRV_EICON) += eicon +subdir-$(CONFIG_HYSDN) += hysdn + +obj-y += $(addsuffix /vmlinux-obj.o, $(subdir-y)) + +# The global Rules.make. + +include $(TOPDIR)/drivers/isdn/Rules.make + +# Link rules for multi-part drivers. + +isdn.o: $(isdn-objs) + $(LD) -r -o $@ $(isdn-objs) diff --git a/drivers/isdn/Rules.make b/drivers/isdn/Rules.make new file mode 100644 index 000000000000..a70f49dd9ca5 --- /dev/null +++ b/drivers/isdn/Rules.make @@ -0,0 +1,32 @@ +# Extract lists of the multi-part drivers. +# The 'int-*' lists are the intermediate files used to build the multi's. + +multi-y := $(filter $(list-multi), $(obj-y)) +multi-m := $(filter $(list-multi), $(obj-m)) +int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs))) +int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs))) + +# Files that are both resident and modular: remove from modular. + +obj-m := $(filter-out $(obj-y), $(obj-m)) +int-m := $(filter-out $(int-y), $(int-m)) + +# Take multi-part drivers out of obj-y and put components in. + +obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y) + +# Translate to Rules.make lists. + +O_OBJS := $(sort $(filter-out $(export-objs), $(obj-y))) +OX_OBJS := $(sort $(filter $(export-objs), $(obj-y))) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) +MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m))) +MIX_OBJS := $(sort $(filter $(export-objs), $(int-m))) + +both-m := $(filter $(mod-subdirs), $(subdir-y)) +SUB_DIRS := $(subdir-y) +MOD_SUB_DIRS := $(sort $(subdir-m) $(both-m)) +ALL_SUB_DIRS := $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-)) + +include $(TOPDIR)/Rules.make diff --git a/drivers/isdn/act2000/Makefile b/drivers/isdn/act2000/Makefile index 31312e8f6df1..5964208eb1bf 100644 --- a/drivers/isdn/act2000/Makefile +++ b/drivers/isdn/act2000/Makefile @@ -1,15 +1,21 @@ -L_OBJS := -M_OBJS := -O_OBJS := module.o capi.o act2000_isa.o - -O_TARGET := -ifeq ($(CONFIG_ISDN_DRV_ACT2000),y) - O_TARGET += act2000.o -else - ifeq ($(CONFIG_ISDN_DRV_ACT2000),m) - O_TARGET += act2000.o - M_OBJS = act2000.o - endif -endif - -include $(TOPDIR)/Rules.make +# Makefile for the act2000 ISDN device driver + +# The target object and module list name. + +O_TARGET := vmlinux-obj.o + +# Multipart objects. + +list-multi := act2000.o +act2000-objs := module.o capi.o act2000_isa.o + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000.o + +include $(TOPDIR)/drivers/isdn/Rules.make + +# Link rules for multi-part drivers. + +act2000.o: $(act2000-objs) + $(LD) -r -o $@ $(act2000-objs) diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h index 432f433cb396..95c3737e69fd 100644 --- a/drivers/isdn/act2000/act2000.h +++ b/drivers/isdn/act2000/act2000.h @@ -1,4 +1,4 @@ -/* $Id: act2000.h,v 1.8 2000/11/12 16:32:06 kai Exp $ +/* $Id: act2000.h,v 1.8.6.1 2001/02/10 14:41:20 kai Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * @@ -88,7 +88,7 @@ typedef struct act2000_fwid { #include #include #include -#include +#include #include #include #include diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index c602d945f27e..5d634f991e5c 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c @@ -1,4 +1,4 @@ -/* $Id: module.c,v 1.14 2000/11/12 16:32:06 kai Exp $ +/* $Id: module.c,v 1.14.6.2 2000/12/18 22:14:10 kai Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * @@ -24,6 +24,7 @@ #include "act2000.h" #include "act2000_isa.h" #include "capi.h" +#include static unsigned short act2000_isa_ports[] = { @@ -820,12 +821,7 @@ act2000_addcard(int bus, int port, int irq, char *id) #define DRIVERNAME "IBM Active 2000 ISDN driver" -#ifdef MODULE -#define act2000_init init_module -#endif - -int -act2000_init(void) +static int __init act2000_init(void) { printk(KERN_INFO "%s\n", DRIVERNAME); if (!cards) @@ -837,9 +833,7 @@ act2000_init(void) return 0; } -#ifdef MODULE -void -cleanup_module(void) +static void act2000_exit(void) { act2000_card *card = cards; act2000_card *last; @@ -858,34 +852,5 @@ cleanup_module(void) printk(KERN_INFO "%s unloaded\n", DRIVERNAME); } -#else -void -act2000_setup(char *str, int *ints) -{ - int i, j, argc, port, irq, bus; - - argc = ints[0]; - i = 1; - if (argc) - while (argc) { - port = irq = -1; - bus = 0; - if (argc) { - bus = ints[i]; - i++; - argc--; - } - if (argc) { - port = ints[i]; - i++; - argc--; - } - if (argc) { - irq = ints[i]; - i++; - argc--; - } - act2000_addcard(bus, port, irq, act_id); - } -} -#endif +module_init(act2000_init); +module_exit(act2000_exit); diff --git a/drivers/isdn/avmb1/Makefile b/drivers/isdn/avmb1/Makefile index 74eba296bb7d..285059036a2f 100644 --- a/drivers/isdn/avmb1/Makefile +++ b/drivers/isdn/avmb1/Makefile @@ -1,187 +1,40 @@ -# -# $Id: Makefile,v 1.18 2000/04/03 16:39:25 calle Exp $ -# -# Makefile for the CAPI and AVM-B1 device drivers. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now inherited from the -# parent makes.. -# -# $Log: Makefile,v $ -# Revision 1.18 2000/04/03 16:39:25 calle -# Makefile checked in with future things :-( -# -# Revision 1.17 2000/04/03 16:38:05 calle -# made suppress_pollack static. -# -# Revision 1.16 2000/03/17 12:15:44 calle -# ALL_SUB_DIRS were wrong. -# -# Revision 1.15 2000/03/16 15:21:03 calle -# Bugfix in c4_remove: loop 5 times instead of 4 :-( -# -# Revision 1.14 2000/03/13 17:50:55 calle -# Added avm_cs.c for 2.3.x PCMCIA support. -# -# Revision 1.13 2000/03/08 17:06:33 calle -# - changes for devfs and 2.3.49 -# - capifs now configurable (no need with devfs) -# - New Middleware ioctl CAPI_NCCI_GETUNIT -# - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs) -# -# Revision 1.12 2000/03/06 18:00:23 calle -# - Middleware extention now working with 2.3.49 (capifs). -# - Fixed typos in debug section of capi.c -# - Bugfix: Makefile corrected for b1pcmcia.c -# -# Revision 1.11 2000/03/06 09:17:07 calle -# - capifs: fileoperations now in inode (change for 2.3.49) -# - Config.in: Middleware extention not a tristate, uups. -# -# Revision 1.10 2000/03/03 16:48:38 calle -# - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI) -# It is now possible to create a connection with a CAPI2.0 applikation -# and than to handle the data connection from /dev/capi/ (capifs) and also -# using async or sync PPP on this connection. -# The two major device number 190 and 191 are not confirmed yet, -# but I want to save the code in cvs, before I go on. -# -# Revision 1.9 2000/03/03 15:50:42 calle -# - kernel CAPI: -# - Changed parameter "param" in capi_signal from __u32 to void *. -# - rewrote notifier handling in kcapi.c -# - new notifier NCCI_UP and NCCI_DOWN -# - User CAPI: -# - /dev/capi20 is now a cloning device. -# - middleware extentions prepared. -# - capidrv.c -# - locking of list operations and module count updates. -# -# Revision 1.8 2000/01/25 14:33:38 calle -# - Added Support AVM B1 PCI V4.0 (tested with prototype) -# - splitted up t1pci.c into b1dma.c for common function with b1pciv4 -# - support for revision register -# -# Revision 1.7 1999/09/15 08:16:03 calle -# Implementation of 64Bit extention complete. -# -# Revision 1.6 1999/07/20 06:41:44 calle -# Bugfix: After the redesign of the AVM B1 driver, the driver didn't even -# compile, if not selected as modules. -# -# Revision 1.5 1999/07/01 15:26:20 calle -# complete new version (I love it): -# + new hardware independed "capi_driver" interface that will make it easy to: -# - support other controllers with CAPI-2.0 (i.e. USB Controller) -# - write a CAPI-2.0 for the passive cards -# - support serial link CAPI-2.0 boxes. -# + wrote "capi_driver" for all supported cards. -# + "capi_driver" (supported cards) now have to be configured with -# make menuconfig, in the past all supported cards where included -# at once. -# + new and better informations in /proc/capi/ -# + new ioctl to switch trace of capi messages per controller -# using "avmcapictrl trace [contr] on|off|...." -# + complete testcircle with all supported cards and also the -# PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. -# -# Revision 1.4 1997/03/30 17:10:40 calle -# added support for AVM-B1-PCI card. -# -# Revision 1.3 1997/03/22 02:00:57 fritz -# -Reworked toplevel Makefile. From now on, no different Makefiles -# for standalone- and in-kernel-compilation are needed any more. -# -Added local Rules.make for above reason. -# -Experimental changes in teles3.c for enhanced IRQ-checking with -# 2.1.X and SMP kernels. -# -Removed diffstd-script, same functionality is in stddiff -r. -# -Enhanced scripts std2kern and stddiff. -# -# Revision 1.1 1997/03/05 21:26:14 fritz -# Renamed, according naming conventions in CVS tree. -# -# Revision 1.1 1997/03/04 21:50:26 calle -# Frirst version in isdn4linux -# -# Revision 2.2 1997/02/12 09:31:39 calle -# -# Revision 1.1 1997/01/31 10:32:20 calle -# Initial revision -# -# +# Makefile for the AVM ISDN device drivers and CAPI subsystem. -SUB_DIRS := -MOD_SUB_DIRS := -ALL_SUB_DIRS := -# -# Objects that don't export a symtab -# -L_OBJS := # used as component of an L_TARGET -O_OBJS := # used as component of an O_TARGET -M_OBJS := # used as module -# -# Objects that do export a symtab -# -LX_OBJS := # used as component of an L_TARGET -OX_OBJS := # used as component of an O_TARGET -MX_OBJS := # used as module -# -# Targets, created by linking others -# -O_TARGET := # used for .o targets (from O and OX objects) -L_TARGET := # used for .a targets (from L and LX objects) +# The target object and module list name. -ifeq ($(CONFIG_ISDN_CAPI),y) - O_TARGET += avmb1.o - OX_OBJS += kcapi.o - O_OBJS += capi.o - ifdef CONFIG_ISDN_CAPIFS - OX_OBJS += capifs.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA - O_OBJS += b1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI - O_OBJS += b1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA - O_OBJS += t1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI - O_OBJS += t1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_C4 - O_OBJS += c4.o - endif - OX_OBJS += capiutil.o capidrv.o b1.o b1dma.o -else - ifeq ($(CONFIG_ISDN_CAPI),m) - O_TARGET += kernelcapi.o - OX_OBJS += kcapi.o - M_OBJS += capi.o kernelcapi.o - ifdef CONFIG_ISDN_CAPIFS - MX_OBJS += capifs.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA - M_OBJS += b1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI - M_OBJS += b1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA - M_OBJS += t1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI - M_OBJS += t1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_C4 - M_OBJS += c4.o - endif - MX_OBJS += capiutil.o capidrv.o b1.o b1dma.o - endif -endif +O_TARGET := vmlinux-obj.o + +# Objects that export symbols. + +export-objs := kcapi.o capiutil.o b1dma.o b1pcmcia.o b1.o capifs.o + +# Multipart objects. + +list-multi := kernelcapi.o +kernelcapi-objs := kcapi.o + +# Ordering constraints: kernelcapi.o first + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o capiutil.o +obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o +obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o +obj-$(CONFIG_ISDN_CAPI_CAPIFS) += capifs.o +obj-$(CONFIG_ISDN_DRV_AVMB1_B1ISA) += b1isa.o b1.o +obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCI) += b1pci.o b1.o b1dma.o +obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCMCIA) += b1pcmcia.o b1.o +obj-$(CONFIG_ISDN_DRV_AVMB1_AVM_CS) += avm_cs.o +obj-$(CONFIG_ISDN_DRV_AVMB1_T1ISA) += t1isa.o b1.o +obj-$(CONFIG_ISDN_DRV_AVMB1_T1PCI) += t1pci.o b1.o b1dma.o +obj-$(CONFIG_ISDN_DRV_AVMB1_C4) += c4.o b1.o + +# The global Rules.make. + +include $(TOPDIR)/drivers/isdn/Rules.make + +# Link rules for multi-part drivers. + +kernelcapi.o: $(kernelcapi-objs) + $(LD) -r -o $@ $(kernelcapi-objs) -include $(TOPDIR)/Rules.make diff --git a/drivers/isdn/avmb1/avm_cs.c b/drivers/isdn/avmb1/avm_cs.c deleted file mode 100644 index b803e88a5327..000000000000 --- a/drivers/isdn/avmb1/avm_cs.c +++ /dev/null @@ -1,527 +0,0 @@ -/*====================================================================== - - A PCMCIA client driver for AVM B1/M1/M2 - - Written by Carsten Paeth, calle@calle.in-berlin.de - -======================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/*====================================================================*/ - -/* Parameters that can be set with 'insmod' */ - -/* This means pick from 15, 12, 11, 10, 9, 7, 5, 4, and 3 */ -static int default_irq_list[10] = { 15, 12, 11, 10, 9, 7, 5, 4, 3, -1 }; -static int irq_list[10] = { -1 }; - -MODULE_PARM(irq_list, "1-10i"); - -/*====================================================================*/ - -/* - The event() function is this driver's Card Services event handler. - It will be called by Card Services when an appropriate card status - event is received. The config() and release() entry points are - used to configure or release a socket, in response to card insertion - and ejection events. They are invoked from the skeleton event - handler. -*/ - -static void avmcs_config(dev_link_t *link); -static void avmcs_release(u_long arg); -static int avmcs_event(event_t event, int priority, - event_callback_args_t *args); - -/* - The attach() and detach() entry points are used to create and destroy - "instances" of the driver, where each instance represents everything - needed to manage one actual PCMCIA card. -*/ - -static dev_link_t *avmcs_attach(void); -static void avmcs_detach(dev_link_t *); - -/* - The dev_info variable is the "key" that is used to match up this - device driver with appropriate cards, through the card configuration - database. -*/ - -static dev_info_t dev_info = "avm_cs"; - -/* - A linked list of "instances" of the skeleton device. Each actual - PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). - - You may not want to use a linked list for this -- for example, the - memory card driver uses an array of dev_link_t pointers, where minor - device numbers are used to derive the corresponding array index. -*/ - -static dev_link_t *dev_list = NULL; - -/* - A dev_link_t structure has fields for most things that are needed - to keep track of a socket, but there will usually be some device - specific information that also needs to be kept track of. The - 'priv' pointer in a dev_link_t structure can be used to point to - a device-specific private data structure, like this. - - A driver needs to provide a dev_node_t structure for each device - on a card. In some cases, there is only one device per card (for - example, ethernet cards, modems). In other cases, there may be - many actual or logical devices (SCSI adapters, memory cards with - multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t - structure. We allocate them in the card's private data structure, - because they generally can't be allocated dynamically. -*/ - -typedef struct local_info_t { - dev_node_t node; -} local_info_t; - -/*====================================================================*/ - -static void cs_error(client_handle_t handle, int func, int ret) -{ - error_info_t err = { func, ret }; - CardServices(ReportError, handle, &err); -} - -/*====================================================================== - - avmcs_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - - The dev_link structure is initialized, but we don't actually - configure the card at this point -- we wait until we receive a - card insertion event. - -======================================================================*/ - -static dev_link_t *avmcs_attach(void) -{ - client_reg_t client_reg; - dev_link_t *link; - local_info_t *local; - int ret, i; - - /* Initialize the dev_link_t structure */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - memset(link, 0, sizeof(struct dev_link_t)); - link->release.function = &avmcs_release; - link->release.data = (u_long)link; - - /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts2 = 0; - - /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; - - link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; - if (irq_list[0] != -1) { - for (i = 0; i < 10 && irq_list[i] > 0; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; - } else { - for (i = 0; i < 10 && default_irq_list[i] > 0; i++) - link->irq.IRQInfo2 |= 1 << default_irq_list[i]; - } - - /* General socket configuration */ - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.ConfigIndex = 1; - link->conf.Present = PRESENT_OPTION; - - /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); - memset(local, 0, sizeof(local_info_t)); - link->priv = local; - - /* 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 = &avmcs_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != 0) { - cs_error(link->handle, RegisterClient, ret); - avmcs_detach(link); - return NULL; - } - - return link; -} /* avmcs_attach */ - -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ - -static void avmcs_detach(dev_link_t *link) -{ - dev_link_t **linkp; - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; - - /* - If the device is currently configured and active, we won't - actually delete it yet. Instead, it is marked so that when - the release() function is called, that will trigger a proper - detach(). - */ - if (link->state & DEV_CONFIG) { - link->state |= DEV_STALE_LINK; - return; - } - - /* Break the link with Card Services */ - if (link->handle) - CardServices(DeregisterClient, link->handle); - - /* Unlink device structure, free pieces */ - *linkp = link->next; - if (link->priv) { - kfree(link->priv); - } - kfree(link); - -} /* avmcs_detach */ - -/*====================================================================== - - avmcs_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - ethernet device available to the system. - -======================================================================*/ - -static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, - cisparse_t *parse) -{ - int i; - i = CardServices(fn, handle, tuple); - if (i != CS_SUCCESS) return i; - i = CardServices(GetTupleData, handle, tuple); - if (i != CS_SUCCESS) return i; - return CardServices(ParseTuple, handle, tuple, parse); -} - -#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) -#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) - -static void avmcs_config(dev_link_t *link) -{ - client_handle_t handle; - tuple_t tuple; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; - local_info_t *dev; - int i; - u_char buf[64]; - char devname[128]; - int cardtype; - int (*addcard)(unsigned int port, unsigned irq); - - handle = link->handle; - dev = link->priv; - - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ - do { - tuple.DesiredTuple = CISTPL_CONFIG; - i = CardServices(GetFirstTuple, handle, &tuple); - if (i != CS_SUCCESS) break; - tuple.TupleData = buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - i = CardServices(GetTupleData, handle, &tuple); - if (i != CS_SUCCESS) break; - i = CardServices(ParseTuple, handle, &tuple, &parse); - if (i != CS_SUCCESS) break; - link->conf.ConfigBase = parse.config.base; - } while (0); - if (i != CS_SUCCESS) { - cs_error(link->handle, ParseTuple, i); - link->state &= ~DEV_CONFIG_PENDING; - return; - } - - /* Configure card */ - link->state |= DEV_CONFIG; - - do { - - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = 254; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_VERS_1; - - devname[0] = 0; - if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) { - strncpy(devname,parse.version_1.str + parse.version_1.ofs[1], - sizeof(devname)); - } - /* - * find IO port - */ - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); - while (i == CS_SUCCESS) { - if (cf->io.nwin > 0) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.NumPorts1 = cf->io.win[0].len; - link->io.NumPorts2 = 0; - printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n", - link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - i = CardServices(RequestIO, link->handle, &link->io); - if (i == CS_SUCCESS) goto found_port; - } - i = next_tuple(handle, &tuple, &parse); - } - -found_port: - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); - break; - } - - /* - * allocate an interrupt line - */ - i = CardServices(RequestIRQ, link->handle, &link->irq); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); - CardServices(ReleaseIO, link->handle, &link->io); - break; - } - - /* - * configure the PCMCIA socket - */ - i = CardServices(RequestConfiguration, link->handle, &link->conf); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - CardServices(ReleaseIO, link->handle, &link->io); - CardServices(ReleaseIRQ, link->handle, &link->irq); - break; - } - - } while (0); - - /* At this point, the dev_node_t structure(s) should be - initialized and arranged in a linked list at link->dev. */ - - if (devname[0]) { - char *s = strrchr(devname, ' '); - if (!s) - s = devname; - else s++; - strcpy(dev->node.dev_name, s); - if (strcmp("M1", s) == 0) { - cardtype = AVM_CARDTYPE_M1; - } else if (strcmp("M2", s) == 0) { - cardtype = AVM_CARDTYPE_M2; - } else { - cardtype = AVM_CARDTYPE_B1; - } - } else { - strcpy(dev->node.dev_name, "b1"); - cardtype = AVM_CARDTYPE_B1; - } - - dev->node.major = 64; - dev->node.minor = 0; - link->dev = &dev->node; - - link->state &= ~DEV_CONFIG_PENDING; - /* If any step failed, release any partially configured state */ - if (i != 0) { - avmcs_release((u_long)link); - return; - } - - - switch (cardtype) { - case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break; - case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break; - default: - case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break; - } - if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) { - printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n", - dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ); - avmcs_release((u_long)link); - return; - } - dev->node.minor = i; - -} /* avmcs_config */ - -/*====================================================================== - - After a card is removed, avmcs_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ - -static void avmcs_release(u_long arg) -{ - dev_link_t *link = (dev_link_t *)arg; - - /* - If the device is currently in use, we won't release until it - is actually closed. - */ - if (link->open) { - link->state |= DEV_STALE_CONFIG; - return; - } - - b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ); - - /* Unlink the device chain */ - link->dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - CardServices(ReleaseConfiguration, link->handle); - CardServices(ReleaseIO, link->handle, &link->io); - CardServices(ReleaseIRQ, link->handle, &link->irq); - link->state &= ~DEV_CONFIG; - - if (link->state & DEV_STALE_LINK) - avmcs_detach(link); - -} /* avmcs_release */ - -/*====================================================================== - - The card status event handler. Mostly, this schedules other - stuff to run after an event is received. A CARD_REMOVAL event - also sets some flags to discourage the net drivers from trying - to talk to the card any more. - - When a CARD_REMOVAL event is received, we immediately set a flag - to block future accesses to this device. All the functions that - actually access the device should check this flag to make sure - the card is still present. - -======================================================================*/ - -static int avmcs_event(event_t event, int priority, - event_callback_args_t *args) -{ - dev_link_t *link = args->client_data; - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) { - link->release.expires = jiffies + (HZ/20); - add_timer(&link->release); - } - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - avmcs_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 (link->state & DEV_CONFIG) - CardServices(RequestConfiguration, link->handle, &link->conf); - break; - } - return 0; -} /* avmcs_event */ - -/*====================================================================*/ - -int init_module(void) -{ - servinfo_t serv; - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "avm_cs: Card Services release " - "does not match!\n"); - return -1; - } - register_pccard_driver(&dev_info, &avmcs_attach, &avmcs_detach); - return 0; -} - -void cleanup_module(void) -{ - unregister_pccard_driver(&dev_info); - while (dev_list != NULL) { - if (dev_list->state & DEV_CONFIG) - avmcs_release((u_long)dev_list); - avmcs_detach(dev_list); - } -} diff --git a/drivers/isdn/avmb1/b1.c b/drivers/isdn/avmb1/b1.c index cdd1c436d635..5cb5f07b93a3 100644 --- a/drivers/isdn/avmb1/b1.c +++ b/drivers/isdn/avmb1/b1.c @@ -1,11 +1,32 @@ /* - * $Id: b1.c,v 1.14 2000/06/19 16:51:53 keil Exp $ + * $Id: b1.c,v 1.20 2000/11/23 20:45:14 kai Exp $ * * Common module for AVM B1 cards. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1.c,v $ + * Revision 1.20 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.19 2000/11/19 17:02:47 kai + * compatibility cleanup - part 3 + * + * Revision 1.18 2000/11/19 17:01:53 kai + * compatibility cleanup - part 2 + * + * Revision 1.17 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.16 2000/08/04 15:36:31 calle + * copied wrong from file to file :-( + * + * Revision 1.15 2000/08/04 12:20:08 calle + * - Fix unsigned/signed warning in the right way ... + * * Revision 1.14 2000/06/19 16:51:53 keil * don't free skb in irq context * @@ -88,13 +109,14 @@ #include #include #include +#include #include #include "capilli.h" #include "avmcard.h" #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.20 $"; +static char *revision = "$Revision: 1.20.6.1 $"; /* ------------------------------------------------------------- */ @@ -721,12 +743,7 @@ EXPORT_SYMBOL(b1_handle_interrupt); EXPORT_SYMBOL(b1ctl_read_proc); -#ifdef MODULE -#define b1_init init_module -void cleanup_module(void); -#endif - -int b1_init(void) +static int __init b1_init(void) { char *p; char rev[10]; @@ -743,8 +760,9 @@ int b1_init(void) return 0; } -#ifdef MODULE -void cleanup_module(void) +static void b1_exit(void) { } -#endif + +module_init(b1_init); +module_exit(b1_exit); diff --git a/drivers/isdn/avmb1/b1dma.c b/drivers/isdn/avmb1/b1dma.c index f1c30a5d6668..db4f47b7970e 100644 --- a/drivers/isdn/avmb1/b1dma.c +++ b/drivers/isdn/avmb1/b1dma.c @@ -1,11 +1,31 @@ /* - * $Id: b1dma.c,v 1.5 2000/06/19 16:51:53 keil Exp $ + * $Id: b1dma.c,v 1.11 2000/11/19 17:02:47 kai Exp $ * * Common module for AVM B1 cards that support dma with AMCC * * (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1dma.c,v $ + * Revision 1.11 2000/11/19 17:02:47 kai + * compatibility cleanup - part 3 + * + * Revision 1.10 2000/11/19 17:01:53 kai + * compatibility cleanup - part 2 + * + * Revision 1.9 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.8 2000/10/10 17:44:19 kai + * changes from/for 2.2.18 + * + * Revision 1.7 2000/08/04 12:20:08 calle + * - Fix unsigned/signed warning in the right way ... + * + * Revision 1.6 2000/06/29 13:59:06 calle + * Bugfix: reinit txdma without interrupt will confuse some AMCC chips. + * * Revision 1.5 2000/06/19 16:51:53 keil * don't free skb in irq context * @@ -34,13 +54,14 @@ #include #include #include +#include #include #include "capilli.h" #include "avmcard.h" #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.11 $"; +static char *revision = "$Revision: 1.11.6.1 $"; /* ------------------------------------------------------------- */ @@ -963,11 +984,6 @@ EXPORT_SYMBOL(b1dma_release_appl); EXPORT_SYMBOL(b1dma_send_message); EXPORT_SYMBOL(b1dmactl_read_proc); -#ifdef MODULE -#define b1dma_init init_module -void cleanup_module(void); -#endif - int b1dma_init(void) { char *p; @@ -985,8 +1001,9 @@ int b1dma_init(void) return 0; } -#ifdef MODULE -void cleanup_module(void) +void b1dma_exit(void) { } -#endif + +module_init(b1dma_init); +module_exit(b1dma_exit); diff --git a/drivers/isdn/avmb1/b1isa.c b/drivers/isdn/avmb1/b1isa.c index 5515ef63adc4..784bf307edda 100644 --- a/drivers/isdn/avmb1/b1isa.c +++ b/drivers/isdn/avmb1/b1isa.c @@ -1,11 +1,20 @@ /* - * $Id: b1isa.c,v 1.8 2000/04/03 13:29:24 calle Exp $ + * $Id: b1isa.c,v 1.10 2000/11/23 20:45:14 kai Exp $ * * Module for AVM B1 ISA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1isa.c,v $ + * Revision 1.10 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.9 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.8 2000/04/03 13:29:24 calle * make Tim Waugh happy (module unload races in 2.3.99-pre3). * no real problem there, but now it is much cleaner ... @@ -67,13 +76,14 @@ #include #include #include +#include #include #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.10 $"; +static char *revision = "$Revision: 1.10.6.1 $"; /* ------------------------------------------------------------- */ @@ -260,12 +270,7 @@ static struct capi_driver b1isa_driver = { add_card: b1isa_add_card, }; -#ifdef MODULE -#define b1isa_init init_module -void cleanup_module(void); -#endif - -int b1isa_init(void) +static int __init b1isa_init(void) { struct capi_driver *driver = &b1isa_driver; char *p; @@ -292,9 +297,10 @@ int b1isa_init(void) return retval; } -#ifdef MODULE -void cleanup_module(void) +static void b1isa_exit(void) { detach_capi_driver(&b1isa_driver); } -#endif + +module_init(b1isa_init); +module_exit(b1isa_exit); diff --git a/drivers/isdn/avmb1/b1pci.c b/drivers/isdn/avmb1/b1pci.c index cae8fe28dfe5..babbccf5ffb1 100644 --- a/drivers/isdn/avmb1/b1pci.c +++ b/drivers/isdn/avmb1/b1pci.c @@ -1,11 +1,37 @@ /* - * $Id: b1pci.c,v 1.25 2000/05/29 12:29:18 keil Exp $ + * $Id: b1pci.c,v 1.29.6.1 2000/11/28 12:02:45 kai Exp $ * * Module for AVM B1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pci.c,v $ + * Revision 1.29.6.1 2000/11/28 12:02:45 kai + * MODULE_DEVICE_TABLE for 2.4 + * + * Revision 1.29.2.2 2000/11/26 17:47:53 kai + * added PCI_DEV_TABLE for 2.4 + * + * Revision 1.29.2.1 2000/11/26 17:14:19 kai + * fix device ids + * also needs patches to include/linux/pci_ids.h + * + * Revision 1.29 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.28 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.27 2000/08/08 09:24:19 calle + * calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI + * + * Revision 1.26 2000/07/20 10:21:21 calle + * Bugfix: driver will not be unregistered, if not cards were detected. + * this result in an oops in kcapi.c + * * Revision 1.25 2000/05/29 12:29:18 keil * make pci_enable_dev compatible to 2.2 kernel versions * @@ -87,7 +113,8 @@ #include #include #include -#include +#include +#include #include "capicmd.h" #include "capiutil.h" #include "capilli.h" @@ -465,11 +492,6 @@ static struct capi_driver b1pciv4_driver = { #endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */ -#ifdef MODULE -#define b1pci_init init_module -void cleanup_module(void); -#endif - static int ncards = 0; static int add_card(struct pci_dev *dev) @@ -491,9 +513,6 @@ static int add_card(struct pci_dev *dev) printk(KERN_ERR "%s: failed to enable AVM-B1 V4 at i/o %#x, irq %d, mem %#x err=%d\n", driver->name, param.port, param.irq, param.membase, retval); -#ifdef MODULE - cleanup_module(); -#endif MOD_DEC_USE_COUNT; return -EIO; } @@ -521,9 +540,6 @@ static int add_card(struct pci_dev *dev) printk(KERN_ERR "%s: failed to enable AVM-B1 at i/o %#x, irq %d, err=%d\n", driver->name, param.port, param.irq, retval); -#ifdef MODULE - cleanup_module(); -#endif MOD_DEC_USE_COUNT; return -EIO; } @@ -540,7 +556,7 @@ static int add_card(struct pci_dev *dev) return retval; } -int b1pci_init(void) +static int __init b1pci_init(void) { struct capi_driver *driver = &b1pci_driver; #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 @@ -603,9 +619,6 @@ int b1pci_init(void) while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) { retval = add_card(dev); if (retval != 0) { -#ifdef MODULE - cleanup_module(); -#endif MOD_DEC_USE_COUNT; return retval; } @@ -627,12 +640,13 @@ int b1pci_init(void) #endif } -#ifdef MODULE -void cleanup_module(void) +static void b1pci_exit(void) { detach_capi_driver(&b1pci_driver); #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 detach_capi_driver(&b1pciv4_driver); #endif } -#endif + +module_init(b1pci_init); +module_exit(b1pci_exit); diff --git a/drivers/isdn/avmb1/b1pcmcia.c b/drivers/isdn/avmb1/b1pcmcia.c index 18a325a5efd9..f64f4dc3256c 100644 --- a/drivers/isdn/avmb1/b1pcmcia.c +++ b/drivers/isdn/avmb1/b1pcmcia.c @@ -1,11 +1,20 @@ /* - * $Id: b1pcmcia.c,v 1.10 2000/05/06 00:52:36 kai Exp $ + * $Id: b1pcmcia.c,v 1.12 2000/11/23 20:45:14 kai Exp $ * * Module for AVM B1/M1/M2 PCMCIA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pcmcia.c,v $ + * Revision 1.12 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.11 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.10 2000/05/06 00:52:36 kai * merged changes from kernel tree * fixed timer and net_device->name breakage @@ -75,6 +84,7 @@ #include #include #include +#include #include #include #include @@ -300,12 +310,7 @@ EXPORT_SYMBOL(b1pcmcia_delcard); /* ------------------------------------------------------------- */ -#ifdef MODULE -#define b1pcmcia_init init_module -void cleanup_module(void); -#endif - -int b1pcmcia_init(void) +static int __init b1pcmcia_init(void) { struct capi_driver *driver = &b1pcmcia_driver; char *p; @@ -332,9 +337,10 @@ int b1pcmcia_init(void) return retval; } -#ifdef MODULE -void cleanup_module(void) +static void b1pcmcia_exit(void) { detach_capi_driver(&b1pcmcia_driver); } -#endif + +module_init(b1pcmcia_init); +module_exit(b1pcmcia_exit); diff --git a/drivers/isdn/avmb1/c4.c b/drivers/isdn/avmb1/c4.c index db8788876cf8..98e7f281b5da 100644 --- a/drivers/isdn/avmb1/c4.c +++ b/drivers/isdn/avmb1/c4.c @@ -1,11 +1,49 @@ /* - * $Id: c4.c,v 1.12 2000/06/19 16:51:53 keil Exp $ + * $Id: c4.c,v 1.20.6.1 2000/11/28 12:02:45 kai Exp $ * * Module for AVM C4 card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: c4.c,v $ + * Revision 1.20.6.1 2000/11/28 12:02:45 kai + * MODULE_DEVICE_TABLE for 2.4 + * + * Revision 1.20.2.2 2000/11/26 17:47:53 kai + * added PCI_DEV_TABLE for 2.4 + * + * Revision 1.20.2.1 2000/11/26 17:14:19 kai + * fix device ids + * also needs patches to include/linux/pci_ids.h + * + * Revision 1.20 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.19 2000/11/19 17:02:47 kai + * compatibility cleanup - part 3 + * + * Revision 1.18 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.17 2000/10/10 17:44:19 kai + * changes from/for 2.2.18 + * + * Revision 1.16 2000/08/20 07:30:13 keil + * changes for 2.4 + * + * Revision 1.15 2000/08/08 09:24:19 calle + * calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI + * + * Revision 1.14 2000/08/04 12:20:08 calle + * - Fix unsigned/signed warning in the right way ... + * + * Revision 1.13 2000/07/20 10:21:21 calle + * Bugfix: driver will not be unregistered, if not cards were detected. + * this result in an oops in kcapi.c + * * Revision 1.12 2000/06/19 16:51:53 keil * don't free skb in irq context * @@ -58,8 +96,9 @@ #include #include #include +#include #include -#include +#include #include #include #include "capicmd.h" @@ -1286,35 +1325,9 @@ static struct capi_driver c4_driver = { add_card: 0, /* no add_card function */ }; -#ifdef MODULE -#define c4_init init_module -void cleanup_module(void); -#endif - -#ifndef PCI_ANY_ID -#define PCI_ANY_ID (~0) -#endif - -static struct pci_dev * -pci_find_subsys(unsigned int vendor, unsigned int device, - unsigned int ss_vendor, unsigned int ss_device, - struct pci_dev *from) -{ - unsigned short subsystem_vendor, subsystem_device; - - while ((from = pci_find_device(vendor, device, from))) { - pci_read_config_word(from, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); - pci_read_config_word(from, PCI_SUBSYSTEM_ID, &subsystem_device); - if ((ss_vendor == PCI_ANY_ID || subsystem_vendor == ss_vendor) && - (ss_device == PCI_ANY_ID || subsystem_device == ss_device)) - return from; - } - return NULL; -} - static int ncards = 0; -int c4_init(void) +static int __init c4_init(void) { struct capi_driver *driver = &c4_driver; struct pci_dev *dev = NULL; @@ -1362,9 +1375,6 @@ int c4_init(void) printk(KERN_ERR "%s: failed to enable AVM-C4 at i/o %#x, irq %d, mem %#x err=%d\n", driver->name, param.port, param.irq, param.membase, retval); -#ifdef MODULE - cleanup_module(); -#endif MOD_DEC_USE_COUNT; return -EIO; } @@ -1377,9 +1387,6 @@ int c4_init(void) printk(KERN_ERR "%s: no AVM-C4 at i/o %#x, irq %d detected, mem %#x\n", driver->name, param.port, param.irq, param.membase); -#ifdef MODULE - cleanup_module(); -#endif MOD_DEC_USE_COUNT; return retval; } @@ -1401,9 +1408,10 @@ int c4_init(void) #endif } -#ifdef MODULE -void cleanup_module(void) +static void c4_exit(void) { detach_capi_driver(&c4_driver); } -#endif + +module_init(c4_init); +module_exit(c4_exit); diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c index f3bff38dbbab..f3724615df11 100644 --- a/drivers/isdn/avmb1/capi.c +++ b/drivers/isdn/avmb1/capi.c @@ -1,11 +1,14 @@ /* - * $Id: capi.c,v 1.44.6.3 2000/12/17 22:45:08 kai Exp $ + * $Id: capi.c,v 1.44.6.4 2001/02/10 14:41:20 kai Exp $ * * CAPI 2.0 Interface for Linux * * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capi.c,v $ + * Revision 1.44.6.4 2001/02/10 14:41:20 kai + * Changes from kernel tree + * * Revision 1.44.6.3 2000/12/17 22:45:08 kai * That's hopefully it for test13-4 * @@ -217,16 +220,18 @@ * */ +#include #include #include #include #include #include -#include +#include #include #include #include #include +#include #include #include #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -243,13 +248,14 @@ #include #include #include +#include #include "capiutil.h" #include "capicmd.h" -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE +#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) #include "capifs.h" -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ +#endif -static char *revision = "$Revision: 1.44.6.3 $"; +static char *revision = "$Revision: 1.44.6.4 $"; MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)"); @@ -308,8 +314,8 @@ struct capiminor { /* for raw device */ struct sk_buff_head recvqueue; - struct wait_queue *recvwait; - struct wait_queue *sendwait; + wait_queue_head_t recvwait; + wait_queue_head_t sendwait; /* transmit path */ struct datahandle_queue { @@ -339,7 +345,7 @@ struct capidev { unsigned userflags; struct sk_buff_head recvqueue; - struct wait_queue *recvwait; + wait_queue_head_t recvwait; /* Statistic */ unsigned long nrecvctlpkt; @@ -400,7 +406,8 @@ void capiminor_del_all_ack(struct capiminor *mp) { struct datahandle_queue **pp, *p; - for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) { + pp = &mp->ackqueue; + while (*pp) { p = *pp; *pp = (*pp)->next; kfree(p); @@ -436,6 +443,8 @@ struct capiminor *capiminor_alloc(__u16 applid, __u32 ncci) skb_queue_head_init(&mp->outqueue); skb_queue_head_init(&mp->recvqueue); + init_waitqueue_head(&mp->recvwait); + init_waitqueue_head(&mp->sendwait); for (pp = &minors; *pp; pp = &(*pp)->next) { if ((*pp)->minor < minor) @@ -517,7 +526,7 @@ static struct capincci *capincci_alloc(struct capidev *cdev, __u32 ncci) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "set mp->nccip\n"); #endif -#ifdef CONFIG_ISDN_CAPIFS +#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) kdev = MKDEV(capi_rawmajor, mp->minor); capifs_new_ncci('r', mp->minor, kdev); kdev = MKDEV(capi_ttymajor, mp->minor); @@ -542,7 +551,7 @@ static void capincci_free(struct capidev *cdev, __u32 ncci) *pp = (*pp)->next; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if ((mp = np->minorp) != 0) { -#ifdef CONFIG_ISDN_CAPIFS +#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) capifs_free_ncci('r', mp->minor); capifs_free_ncci(0, mp->minor); #endif @@ -598,6 +607,7 @@ static struct capidev *capidev_alloc(struct file *file) cdev->minor = MINOR(file->f_dentry->d_inode->i_rdev); skb_queue_head_init(&cdev->recvqueue); + init_waitqueue_head(&cdev->recvwait); pp=&capidev_openlist; while (*pp) pp = &(*pp)->next; *pp = cdev; @@ -1258,6 +1268,7 @@ capi_release(struct inode *inode, struct file *file) { struct capidev *cdev = (struct capidev *)file->private_data; + lock_kernel(); capincci_free(cdev, 0xffffffff); capidev_free(cdev); file->private_data = NULL; @@ -1266,6 +1277,7 @@ capi_release(struct inode *inode, struct file *file) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capi_release %d\n", GET_USE_COUNT(&__this_module)); #endif + unlock_kernel(); return 0; } @@ -1447,11 +1459,13 @@ capinc_raw_release(struct inode *inode, struct file *file) struct capiminor *mp = (struct capiminor *)file->private_data; if (mp) { + lock_kernel(); mp->file = 0; if (mp->nccip == 0) { capiminor_free(mp); file->private_data = NULL; } + unlock_kernel(); } #ifdef _DEBUG_REFCOUNT @@ -1485,6 +1499,8 @@ int capinc_tty_open(struct tty_struct * tty, struct file * file) return -EBUSY; skb_queue_head_init(&mp->recvqueue); + init_waitqueue_head(&mp->recvwait); + init_waitqueue_head(&mp->sendwait); tty->driver_data = (void *)mp; #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capi_tty_open %d\n", GET_USE_COUNT(&__this_module)); @@ -1943,7 +1959,7 @@ static struct procfsentries { { "capi/capi20ncci", 0 , proc_capincci_read_proc }, }; -static void proc_init(void) +static void __init proc_init(void) { int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); int i; @@ -1955,7 +1971,7 @@ static void proc_init(void) } } -static void proc_exit(void) +static void proc_exit(void) { int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); int i; @@ -1999,18 +2015,14 @@ static void lower_callback(unsigned int cmd, __u32 contr, void *data) } } -#ifdef MODULE -#define capi_init init_module -#endif - static struct capi_interface_user cuser = { - "capi20", - lower_callback, + name: "capi20", + callback: lower_callback, }; static char rev[10]; -int capi_init(void) +static int __init capi_init(void) { char *p; @@ -2069,8 +2081,7 @@ int capi_init(void) return 0; } -#ifdef MODULE -void cleanup_module(void) +static void capi_exit(void) { #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #endif @@ -2086,4 +2097,5 @@ void cleanup_module(void) printk(KERN_NOTICE "capi: Rev%s: unloaded\n", rev); } -#endif +module_init(capi_init); +module_exit(capi_exit); diff --git a/drivers/isdn/avmb1/capidev.h b/drivers/isdn/avmb1/capidev.h index 7d18213d10aa..7221784858dc 100644 --- a/drivers/isdn/avmb1/capidev.h +++ b/drivers/isdn/avmb1/capidev.h @@ -61,7 +61,7 @@ struct capidev { unsigned int minor; struct sk_buff_head recv_queue; - struct wait_queue *recv_wait; + wait_queue_head_t recv_wait; /* Statistic */ unsigned long nrecvctlpkt; diff --git a/drivers/isdn/avmb1/capidrv.c b/drivers/isdn/avmb1/capidrv.c index c0ab5e312eb9..d789e767ea53 100644 --- a/drivers/isdn/avmb1/capidrv.c +++ b/drivers/isdn/avmb1/capidrv.c @@ -1,11 +1,14 @@ /* - * $Id: capidrv.c,v 1.39 2000/11/23 20:45:14 kai Exp $ + * $Id: capidrv.c,v 1.39.6.1 2001/02/10 14:41:20 kai Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidrv.c,v $ + * Revision 1.39.6.1 2001/02/10 14:41:20 kai + * Changes from kernel tree + * * Revision 1.39 2000/11/23 20:45:14 kai * fixed module_init/exit stuff * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. @@ -198,7 +201,7 @@ #include #include #include -#include +#include #include #include #include @@ -212,13 +215,14 @@ #include #include #include +#include #include #include "capiutil.h" #include "capicmd.h" #include "capidrv.h" -static char *revision = "$Revision: 1.39 $"; +static char *revision = "$Revision: 1.39.6.1 $"; static int debugmode = 0; MODULE_AUTHOR("Carsten Paeth "); @@ -2448,7 +2452,7 @@ static struct procfsentries { { "capi/capidrv", 0 , proc_capidrv_read_proc }, }; -static void proc_init(void) +static void __init proc_init(void) { int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); int i; @@ -2460,7 +2464,7 @@ static void proc_init(void) } } -static void proc_exit(void) +static void proc_exit(void) { int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); int i; @@ -2479,11 +2483,7 @@ static struct capi_interface_user cuser = { callback: lower_callback }; -#ifdef MODULE -#define capidrv_init init_module -#endif - -int capidrv_init(void) +static int __init capidrv_init(void) { struct capi_register_params rparam; capi_profile profile; @@ -2543,8 +2543,7 @@ int capidrv_init(void) return 0; } -#ifdef MODULE -void cleanup_module(void) +static void capidrv_exit(void) { char rev[10]; char *p; @@ -2566,4 +2565,5 @@ void cleanup_module(void) printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev); } -#endif +module_init(capidrv_init); +module_exit(capidrv_exit); diff --git a/drivers/isdn/avmb1/capifs.c b/drivers/isdn/avmb1/capifs.c index 21be6c19d29b..8072e66ba364 100644 --- a/drivers/isdn/avmb1/capifs.c +++ b/drivers/isdn/avmb1/capifs.c @@ -1,11 +1,44 @@ /* - * $Id: capifs.c,v 1.7 2000/06/18 16:09:54 keil Exp $ + * $Id: capifs.c,v 1.14.6.2 2001/02/10 14:41:20 kai Exp $ * * (c) Copyright 2000 by Carsten Paeth (calle@calle.de) * * Heavily based on devpts filesystem from H. Peter Anvin * * $Log: capifs.c,v $ + * Revision 1.14.6.2 2001/02/10 14:41:20 kai + * Changes from kernel tree + * + * Revision 1.14.6.1 2000/11/28 12:02:45 kai + * MODULE_DEVICE_TABLE for 2.4 + * + * Revision 1.14.2.1 2000/11/26 17:47:53 kai + * added PCI_DEV_TABLE for 2.4 + * + * Revision 1.14 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.13 2000/11/18 16:17:25 kai + * change from 2.4 tree + * + * Revision 1.12 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.11 2000/10/24 15:08:47 calle + * Too much includes. + * + * Revision 1.10 2000/10/12 10:12:35 calle + * Bugfix: second iput(inode) on umount, destroies a foreign inode. + * + * Revision 1.9 2000/08/20 07:30:13 keil + * changes for 2.4 + * + * Revision 1.8 2000/07/20 10:23:13 calle + * Include isdn_compat.h for people that don't use -p option of std2kern. + * * Revision 1.7 2000/06/18 16:09:54 keil * more changes for 2.4 * @@ -56,14 +89,14 @@ #include #include #include -#include +#include #include #include #include MODULE_AUTHOR("Carsten Paeth "); -static char *revision = "$Revision: 1.14.6.1 $"; +static char *revision = "$Revision: 1.14.6.2 $"; struct capifs_ncci { struct inode *inode; @@ -552,7 +585,7 @@ void capifs_free_ncci(char type, unsigned int num) } } -int __init capifs_init(void) +static int __init capifs_init(void) { char rev[10]; char *p; @@ -581,7 +614,7 @@ int __init capifs_init(void) return 0; } -void capifs_exit(void) +static void capifs_exit(void) { unregister_filesystem(&capifs_fs_type); } @@ -589,16 +622,5 @@ void capifs_exit(void) EXPORT_SYMBOL(capifs_new_ncci); EXPORT_SYMBOL(capifs_free_ncci); -#ifdef MODULE - -int init_module(void) -{ - return capifs_init(); -} - -void cleanup_module(void) -{ - capifs_exit(); -} - -#endif +module_init(capifs_init); +module_exit(capifs_exit); diff --git a/drivers/isdn/avmb1/capiutil.c b/drivers/isdn/avmb1/capiutil.c index 62160445c4c1..0d237e4680c2 100644 --- a/drivers/isdn/avmb1/capiutil.c +++ b/drivers/isdn/avmb1/capiutil.c @@ -90,6 +90,7 @@ #include #include #include +#include #include #include @@ -995,15 +996,14 @@ EXPORT_SYMBOL(capi_cmsg2str); EXPORT_SYMBOL(capi_message2str); EXPORT_SYMBOL(capi_info2str); -#ifdef MODULE - -int init_module(void) -{ - return 0; +static int __init capiutil_init(void) +{ + return 0; } -void cleanup_module(void) +static void capiutil_exit(void) { } -#endif +module_init(capiutil_init); +module_exit(capiutil_exit); diff --git a/drivers/isdn/avmb1/kcapi.c b/drivers/isdn/avmb1/kcapi.c index 9d3e94a3de40..424e82e01059 100644 --- a/drivers/isdn/avmb1/kcapi.c +++ b/drivers/isdn/avmb1/kcapi.c @@ -1,11 +1,31 @@ /* - * $Id: kcapi.c,v 1.17 2000/04/21 13:00:56 calle Exp $ + * $Id: kcapi.c,v 1.21.6.1 2000/12/10 23:39:19 kai Exp $ * * Kernel CAPI 2.0 Module * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: kcapi.c,v $ + * Revision 1.21.6.1 2000/12/10 23:39:19 kai + * in 2.4 we don't have tq_scheduler anymore. + * also add one supported card to hfc_pci.c + * (from main branch) + * + * Revision 1.21 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.20 2000/11/19 17:01:53 kai + * compatibility cleanup - part 2 + * + * Revision 1.19 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.18 2000/07/20 10:22:27 calle + * - Made procfs function cleaner and removed variable "begin". + * * Revision 1.17 2000/04/21 13:00:56 calle * Bugfix: driver_proc_info was also wrong. * @@ -107,6 +127,7 @@ #include #include #include +#include #include #include "capicmd.h" #include "capiutil.h" @@ -1487,7 +1508,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) while (card->cardstate != CARD_RUNNING) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) @@ -1512,7 +1533,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) while (card->cardstate > CARD_DETECTED) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) @@ -1563,7 +1584,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) while (card->cardstate != CARD_FREE) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) @@ -1721,36 +1742,11 @@ EXPORT_SYMBOL(detach_capi_interface); EXPORT_SYMBOL(attach_capi_driver); EXPORT_SYMBOL(detach_capi_driver); -#ifndef MODULE -#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA -extern int b1isa_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI -extern int b1pci_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA -extern int t1isa_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA -extern int b1pcmcia_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI -extern int t1pci_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_C4 -extern int c4_init(void); -#endif -#endif - /* * init / exit functions */ -#ifdef MODULE -#define kcapi_init init_module -#endif - -int kcapi_init(void) +static int __init kcapi_init(void) { char *p; char rev[10]; @@ -1778,31 +1774,12 @@ int kcapi_init(void) printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev); #else printk(KERN_NOTICE "CAPI-driver Rev%s: started\n", rev); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA - (void)b1isa_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI - (void)b1pci_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA - (void)t1isa_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - (void)b1pcmcia_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI - (void)t1pci_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_C4 - (void)c4_init(); -#endif #endif MOD_DEC_USE_COUNT; return 0; } -#ifdef MODULE -void cleanup_module(void) +static void kcapi_exit(void) { char rev[10]; char *p; @@ -1818,4 +1795,6 @@ void cleanup_module(void) proc_capi_exit(); printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev); } -#endif + +module_init(kcapi_init); +module_exit(kcapi_exit); diff --git a/drivers/isdn/avmb1/t1isa.c b/drivers/isdn/avmb1/t1isa.c index fc7423d48610..5b70cb4529a7 100644 --- a/drivers/isdn/avmb1/t1isa.c +++ b/drivers/isdn/avmb1/t1isa.c @@ -1,11 +1,29 @@ /* - * $Id: t1isa.c,v 1.11 2000/04/03 13:29:25 calle Exp $ + * $Id: t1isa.c,v 1.16 2000/11/23 20:45:14 kai Exp $ * * Module for AVM T1 HEMA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: t1isa.c,v $ + * Revision 1.16 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.15 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.14 2000/10/10 17:44:19 kai + * changes from/for 2.2.18 + * + * Revision 1.13 2000/08/04 15:36:31 calle + * copied wrong from file to file :-( + * + * Revision 1.12 2000/08/04 12:20:08 calle + * - Fix unsigned/signed warning in the right way ... + * * Revision 1.11 2000/04/03 13:29:25 calle * make Tim Waugh happy (module unload races in 2.3.99-pre3). * no real problem there, but now it is much cleaner ... @@ -79,6 +97,7 @@ #include #include #include +#include #include #include "capicmd.h" #include "capiutil.h" @@ -598,12 +617,7 @@ static struct capi_driver t1isa_driver = { add_card: t1isa_add_card, }; -#ifdef MODULE -#define t1isa_init init_module -void cleanup_module(void); -#endif - -int t1isa_init(void) +static int __init t1isa_init(void) { struct capi_driver *driver = &t1isa_driver; char *p; @@ -631,9 +645,10 @@ int t1isa_init(void) return retval; } -#ifdef MODULE -void cleanup_module(void) +static void t1isa_exit(void) { detach_capi_driver(&t1isa_driver); } -#endif + +module_init(t1isa_init); +module_exit(t1isa_exit); diff --git a/drivers/isdn/avmb1/t1pci.c b/drivers/isdn/avmb1/t1pci.c index ac0c66656446..4de3e05d32d3 100644 --- a/drivers/isdn/avmb1/t1pci.c +++ b/drivers/isdn/avmb1/t1pci.c @@ -1,11 +1,37 @@ /* - * $Id: t1pci.c,v 1.9 2000/05/19 15:43:22 calle Exp $ + * $Id: t1pci.c,v 1.13.6.1 2000/11/28 12:02:45 kai Exp $ * * Module for AVM T1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: t1pci.c,v $ + * Revision 1.13.6.1 2000/11/28 12:02:45 kai + * MODULE_DEVICE_TABLE for 2.4 + * + * Revision 1.13.2.2 2000/11/26 17:47:53 kai + * added PCI_DEV_TABLE for 2.4 + * + * Revision 1.13.2.1 2000/11/26 17:14:19 kai + * fix device ids + * also needs patches to include/linux/pci_ids.h + * + * Revision 1.13 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.12 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.11 2000/08/08 09:24:19 calle + * calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI + * + * Revision 1.10 2000/07/20 10:21:21 calle + * Bugfix: driver will not be unregistered, if not cards were detected. + * this result in an oops in kcapi.c + * * Revision 1.9 2000/05/19 15:43:22 calle * added calls to pci_device_start(). * @@ -54,9 +80,10 @@ #include #include #include +#include #include +#include #include -#include #include "capicmd.h" #include "capiutil.h" #include "capilli.h" @@ -259,14 +286,9 @@ static struct capi_driver t1pci_driver = { add_card: 0, /* no add_card function */ }; -#ifdef MODULE -#define t1pci_init init_module -void cleanup_module(void); -#endif - static int ncards = 0; -int t1pci_init(void) +static int __init t1pci_init(void) { struct capi_driver *driver = &t1pci_driver; struct pci_dev *dev = NULL; @@ -312,9 +334,6 @@ int t1pci_init(void) printk(KERN_ERR "%s: failed to enable AVM-T1-PCI at i/o %#x, irq %d, mem %#x err=%d\n", driver->name, param.port, param.irq, param.membase, retval); -#ifdef MODULE - cleanup_module(); -#endif MOD_DEC_USE_COUNT; return -EIO; } @@ -327,9 +346,6 @@ int t1pci_init(void) printk(KERN_ERR "%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n", driver->name, param.port, param.irq, param.membase); -#ifdef MODULE - cleanup_module(); -#endif MOD_DEC_USE_COUNT; return retval; } @@ -351,9 +367,10 @@ int t1pci_init(void) #endif } -#ifdef MODULE -void cleanup_module(void) +static void t1pci_exit(void) { detach_capi_driver(&t1pci_driver); } -#endif + +module_init(t1pci_init); +module_exit(t1pci_exit); diff --git a/drivers/isdn/divert/Makefile b/drivers/isdn/divert/Makefile index 109c900d8ac5..8f2927bd4af5 100644 --- a/drivers/isdn/divert/Makefile +++ b/drivers/isdn/divert/Makefile @@ -1,18 +1,26 @@ -L_OBJS := -LX_OBJS := -M_OBJS := -MX_OBJS := -O_OBJS := -OX_OBJS := -L_TARGET := -O_TARGET := - -O_OBJS += isdn_divert.o divert_procfs.o -O_TARGET := dss1_divert.o -M_OBJS += dss1_divert.o -OX_OBJS += divert_init.o - -include $(TOPDIR)/Rules.make +# +# Makefile for the dss1_divert ISDN module +# + +# The target object and module list name. + +O_TARGET := vmlinux-obj.o + +# Multipart objects. + +list-multi := dss1_divert.o +dss1_divert-objs := isdn_divert.o divert_procfs.o divert_init.o + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DIVERSION) += dss1_divert.o + +include $(TOPDIR)/drivers/isdn/Rules.make + +# Link rules for multi-part drivers. + +dss1_divert.o: $(dss1_divert-objs) + $(LD) -r -o $@ $(dss1_divert-objs) diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c index 012df24ee722..8320d8d34058 100644 --- a/drivers/isdn/divert/divert_init.c +++ b/drivers/isdn/divert/divert_init.c @@ -1,5 +1,5 @@ /* - * $Id: divert_init.c,v 1.5.6.1 2000/12/17 16:47:16 kai Exp $ + * $Id: divert_init.c,v 1.5.6.2 2001/01/24 22:18:17 kai Exp $ * * Module init for DSS1 diversion services for i4l. * @@ -23,6 +23,7 @@ #include #include +#include #include "isdn_divert.h" /********************/ @@ -46,7 +47,7 @@ isdn_divert_if divert_if = /* Module interface code */ /* no cmd line parms */ /*************************/ -int init_module(void) +static int __init divert_init(void) { int i; if (divert_dev_init()) @@ -63,12 +64,12 @@ int init_module(void) #endif printk(KERN_INFO "dss1_divert module successfully installed\n"); return(0); -} /* init_module */ +} /**********************/ /* Module deinit code */ /**********************/ -void cleanup_module(void) +static void divert_exit(void) { int flags; int i; @@ -89,6 +90,8 @@ void cleanup_module(void) deleterule(-1); /* delete all rules and free mem */ deleteprocs(); printk(KERN_INFO "dss1_divert module successfully removed \n"); -} /* cleanup_module */ +} +module_init(divert_init); +module_exit(divert_exit); diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 65738a2f4d6e..0da6516d4c40 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -32,6 +32,7 @@ #include #endif #include +#include #include "isdn_divert.h" /*********************************/ diff --git a/drivers/isdn/eicon/Makefile b/drivers/isdn/eicon/Makefile index 306aac0e8265..41ea25adf251 100644 --- a/drivers/isdn/eicon/Makefile +++ b/drivers/isdn/eicon/Makefile @@ -1,13 +1,25 @@ -L_OBJS := -M_OBJS := -O_OBJS := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o - -O_TARGET := -ifeq ($(CONFIG_ISDN_DRV_EICON),y) - O_TARGET += eicon.o -else - O_TARGET += eicon.o - M_OBJS = eicon.o -endif +# Makefile for the eicon ISDN device driver + +# The target object and module list name. + +O_TARGET := vmlinux-obj.o + +# Objects that export symbols. + +export-objs := eicon_mod.o + +# Multipart objects. + +list-multi := eicon.o +eicon-objs := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DRV_EICON) += eicon.o include $(TOPDIR)/Rules.make + +# Link rules for multi-part drivers. + +eicon.o: $(eicon-objs) + $(LD) -r -o $@ $(eicon-objs) diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile index 071e3b1caa1d..fd257919b4d3 100644 --- a/drivers/isdn/hisax/Makefile +++ b/drivers/isdn/hisax/Makefile @@ -1,225 +1,70 @@ -L_OBJS := -M_OBJS := -LX_OBJS := -MX_OBJS := -O_OBJS := -OX_OBJS := -L_TARGET := -O_TARGET := - -O_OBJS := isdnl1.o tei.o isdnl2.o isdnl3.o \ - lmgr.o q931.o callc.o fsm.o cert.o - -# EXTRA_CFLAGS += -S - -ifeq ($(CONFIG_HISAX_EURO),y) - O_OBJS += l3dss1.o -endif - -ifeq ($(CONFIG_HISAX_NI1),y) - O_OBJS += l3ni1.o -endif - -ifeq ($(CONFIG_HISAX_1TR6),y) - O_OBJS += l3_1tr6.o -endif - -ISAC_OBJ := -HSCX_OBJ := -ISAR_OBJ := -HFC_OBJ := -HFC_2BDS0 := -JADE_OBJ := -W6692_OBJ := -NETJ_OBJ := -ICC_OBJ := - -ifeq ($(CONFIG_HISAX_16_0),y) - O_OBJS += teles0.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_16_3),y) - O_OBJS += teles3.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_TELESPCI),y) - O_OBJS += telespci.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_S0BOX),y) - O_OBJS += s0box.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_AVM_A1),y) - O_OBJS += avm_a1.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_AVM_A1_PCMCIA),y) - O_OBJS += avm_a1p.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_FRITZPCI),y) - O_OBJS += avm_pci.o - ISAC_OBJ := isac.o -endif - - -ifeq ($(CONFIG_HISAX_ELSA),y) - O_OBJS += elsa.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_IX1MICROR2),y) - O_OBJS += ix1_micro.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_DIEHLDIVA),y) - O_OBJS += diva.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_ASUSCOM),y) - O_OBJS += asuscom.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_TELEINT),y) - O_OBJS += teleint.o - ISAC_OBJ := isac.o - HFC_OBJ := hfc_2bs0.o -endif - -ifeq ($(CONFIG_HISAX_SEDLBAUER),y) - O_OBJS += sedlbauer.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o - ISAR_OBJ := isar.o -endif - -ifeq ($(CONFIG_HISAX_SPORTSTER),y) - O_OBJS += sportster.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_MIC),y) - O_OBJS += mic.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_NETJET),y) - O_OBJS += nj_s.o - NETJ_OBJ := netjet.o - ISAC_OBJ := isac.o -endif - -ifeq ($(CONFIG_HISAX_NETJET_U),y) - O_OBJS += nj_u.o - NETJ_OBJ := netjet.o - ICC_OBJ := icc.o -endif - -ifeq ($(CONFIG_HISAX_HFCS),y) - O_OBJS += hfcscard.o - HFC_2BDS0 := hfc_2bds0.o -endif - -ifeq ($(CONFIG_HISAX_HFC_PCI),y) - HFC_2BDS0 += hfc_pci.o -endif - -ifeq ($(CONFIG_HISAX_HFC_SX),y) - HFC_2BDS0 += hfc_sx.o -endif - -ifeq ($(CONFIG_HISAX_NICCY),y) - O_OBJS += niccy.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_ISURF),y) - O_OBJS += isurf.o - ISAC_OBJ := isac.o - ISAR_OBJ := isar.o -endif - -ifeq ($(CONFIG_HISAX_HSTSAPHIR),y) - O_OBJS += saphir.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_BKM_A4T),y) - O_OBJS += bkm_a4t.o - ISAC_OBJ := isac.o - JADE_OBJ := jade.o -endif -ifeq ($(CONFIG_HISAX_SCT_QUADRO),y) - O_OBJS += bkm_a8.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_GAZEL),y) - O_OBJS += gazel.o - ISAC_OBJ := isac.o - HSCX_OBJ := hscx.o -endif - -ifeq ($(CONFIG_HISAX_W6692),y) - W6692_OBJ := w6692.o -endif - -# ifeq ($(CONFIG_HISAX_TESTEMU),y) -# O_OBJS += testemu.o -# endif - -ifeq ($(ISAC_OBJ), isac.o) - ISAC_OBJ += arcofi.o -endif - -O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(JADE_OBJ) -O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) $(W6692_OBJ) $(NETJ_OBJ) $(ICC_OBJ) -OX_OBJS += config.o - -O_TARGET := - -ifeq ($(CONFIG_ISDN_DRV_HISAX),y) - O_TARGET += hisax.o -else - ifeq ($(CONFIG_ISDN_DRV_HISAX),m) - O_TARGET += hisax.o - M_OBJS += hisax.o - endif -endif - - -include $(TOPDIR)/Rules.make - -MD5FILES += isac.c isdnl1.c isdnl2.c isdnl3.c \ - tei.c callc.c cert.c l3dss1.c l3_1tr6.c \ - elsa.c diva.c sedlbauer.c - -CERT = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?) - -cert.o: $(MD5FILES) md5sums.asc - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D CERTIFICATION=$(CERT) -c -o cert.o cert.c +# Makefile for the hisax ISDN device driver + +# The target object and module list name. + +O_TARGET := vmlinux-obj.o + +# Objects that export symbols. + +export-objs := config.o + +# Multipart objects. + +list-multi := hisax.o +hisax-objs := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \ + lmgr.o q931.o callc.o fsm.o cert.o + +# Optional parts of multipart objects. + +hisax-objs-$(CONFIG_HISAX_EURO) += l3dss1.o +hisax-objs-$(CONFIG_HISAX_NI1) += l3ni1.o +hisax-objs-$(CONFIG_HISAX_1TR6) += l3_1tr6.o + +hisax-objs-$(CONFIG_HISAX_16_0) += teles0.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_16_3) += teles3.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_TELESPCI) += telespci.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_S0BOX) += s0box.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o +hisax-objs-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o +hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o +hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o +hisax-objs-$(CONFIG_HISAX_NETJET_U) += nj_u.o netjet.o icc.o +hisax-objs-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o +hisax-objs-$(CONFIG_HISAX_HFC_PCI) += hfc_pci.o +hisax-objs-$(CONFIG_HISAX_HFC_SX) += hfc_sx.o +hisax-objs-$(CONFIG_HISAX_NICCY) += niccy.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o +hisax-objs-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o +hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_W6692) += w6692.o +#hisax-objs-$(CONFIG_HISAX_TESTEMU) += testemu.o + +hisax-objs += $(sort $(hisax-objs-y)) + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o + +MD5FILES := isac.c isdnl1.c isdnl2.c isdnl3.c \ + tei.c callc.c cert.c l3dss1.c l3_1tr6.c \ + elsa.c diva.c sedlbauer.c +CERT := $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?) +CFLAGS_cert.o := -DCERTIFICATION=$(CERT) + +include $(TOPDIR)/drivers/isdn/Rules.make + +# Link rules for multi-part drivers. + +hisax.o: $(hisax-objs) + $(LD) -r -o $@ $(hisax-objs) diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 4f107052d963..d0282411b207 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -1,4 +1,4 @@ -/* $Id: avm_pci.c,v 1.22.6.2 2000/11/29 16:00:14 kai Exp $ +/* $Id: avm_pci.c,v 1.22.6.3 2001/02/13 10:33:58 kai Exp $ * * avm_pci.c low level stuff for AVM Fritz!PCI and ISA PnP isdn cards * Thanks to AVM, Berlin for informations @@ -15,10 +15,11 @@ #include "isac.h" #include "isdnl1.h" #include +#include #include extern const char *CardType[]; -static const char *avm_pci_rev = "$Revision: 1.22.6.2 $"; +static const char *avm_pci_rev = "$Revision: 1.22.6.3 $"; #define AVM_FRITZ_PCI 1 #define AVM_FRITZ_PNP 2 diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c index b9cb063c4f8a..dedfd07a7035 100644 --- a/drivers/isdn/hisax/bkm_a4t.c +++ b/drivers/isdn/hisax/bkm_a4t.c @@ -1,4 +1,4 @@ -/* $Id: bkm_a4t.c,v 1.13.6.2 2000/11/29 16:00:14 kai Exp $ +/* $Id: bkm_a4t.c,v 1.13.6.3 2001/02/13 10:33:58 kai Exp $ * bkm_a4t.c low level stuff for T-Berkom A4T * derived from the original file sedlbauer.c * derived from the original file niccy.c @@ -20,11 +20,12 @@ #include "jade.h" #include "isdnl1.h" #include +#include #include "bkm_ax.h" extern const char *CardType[]; -const char *bkm_a4t_revision = "$Revision: 1.13.6.2 $"; +const char *bkm_a4t_revision = "$Revision: 1.13.6.3 $"; static inline u_char diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c index 9d13c31cca8e..75cc5f06a715 100644 --- a/drivers/isdn/hisax/bkm_a8.c +++ b/drivers/isdn/hisax/bkm_a8.c @@ -1,4 +1,4 @@ -/* $Id: bkm_a8.c,v 1.14.6.2 2000/11/29 16:00:14 kai Exp $ +/* $Id: bkm_a8.c,v 1.14.6.3 2001/02/13 10:33:58 kai Exp $ * bkm_a8.c low level stuff for Scitel Quadro (4*S0, passive) * derived from the original file sedlbauer.c * derived from the original file niccy.c @@ -19,6 +19,7 @@ #include "hscx.h" #include "isdnl1.h" #include +#include #include "bkm_ax.h" #if CONFIG_PCI @@ -27,7 +28,7 @@ extern const char *CardType[]; -const char sct_quadro_revision[] = "$Revision: 1.14.6.2 $"; +const char sct_quadro_revision[] = "$Revision: 1.14.6.3 $"; static const char *sct_quadro_subtypes[] = { diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index f632f47d53fc..ced19e429a28 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -878,6 +878,7 @@ release_b_st(struct Channel *chanp) releasestack_isdnl2(st); break; case (ISDN_PROTO_L2_HDLC): + case (ISDN_PROTO_L2_HDLC_56K): case (ISDN_PROTO_L2_TRANS): case (ISDN_PROTO_L2_MODEM): case (ISDN_PROTO_L2_FAX): @@ -1271,6 +1272,9 @@ init_b_st(struct Channel *chanp, int incoming) case (ISDN_PROTO_L2_HDLC): st->l1.mode = L1_MODE_HDLC; break; + case (ISDN_PROTO_L2_HDLC_56K): + st->l1.mode = L1_MODE_HDLC_56K; + break; case (ISDN_PROTO_L2_TRANS): st->l1.mode = L1_MODE_TRANS; break; @@ -1307,6 +1311,7 @@ init_b_st(struct Channel *chanp, int incoming) st->l2.debug = chanp->debug & 64; break; case (ISDN_PROTO_L2_HDLC): + case (ISDN_PROTO_L2_HDLC_56K): case (ISDN_PROTO_L2_TRANS): case (ISDN_PROTO_L2_MODEM): case (ISDN_PROTO_L2_FAX): diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 21ddd9182865..750a455318d8 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1,5 +1,4 @@ -/* $Id: config.c,v 2.57.6.7 2000/12/17 16:47:17 kai Exp $ - * +/* $Id: config.c,v 2.57.6.8 2001/01/23 17:45:02 kai Exp $ * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * @@ -435,11 +434,9 @@ HiSax_mod_inc_use_count(void) MOD_INC_USE_COUNT; } -#ifdef MODULE -#define HiSax_init init_module -#else -__initfunc(void -HiSax_setup(char *str, int *ints)) +#ifndef MODULE +static void __init +HiSax_setup(char *str, int *ints) { int i, j, argc; argc = ints[0]; @@ -961,6 +958,7 @@ checkcard(int cardnr, char *id, int *busy_flag) cs->iif.features = ISDN_FEATURE_L2_X75I | ISDN_FEATURE_L2_HDLC | + ISDN_FEATURE_L2_HDLC_56K | ISDN_FEATURE_L2_TRANS | ISDN_FEATURE_L3_TRANS | #ifdef CONFIG_HISAX_1TR6 @@ -1318,21 +1316,21 @@ HiSax_reportcard(int cardnr, int sel) #endif } - -__initfunc(int -HiSax_init(void)) +static int __init HiSax_init(void) { int i,j; + int nzproto = 0; + + HiSaxVersion(); + CallcNew(); + Isdnl3New(); + Isdnl2New(); + TeiNew(); + Isdnl1New(); #ifdef MODULE - int nzproto = 0; if (!type[0]) { /* We 'll register drivers later, but init basic functions*/ - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); - Isdnl1New(); return 0; } #ifdef CONFIG_HISAX_ELSA @@ -1361,7 +1359,6 @@ HiSax_init(void)) #endif #endif nrcards = 0; - HiSaxVersion(); #ifdef MODULE if (id) /* If id= string used */ HiSax_id = id; @@ -1463,7 +1460,6 @@ HiSax_init(void)) } if (!nzproto) { printk(KERN_WARNING "HiSax: Warning - no protocol specified\n"); - printk(KERN_WARNING "HiSax: Note! module load syntax has changed.\n"); printk(KERN_WARNING "HiSax: using protocol %s\n", DEFAULT_PROTO_NAME); } #endif @@ -1477,15 +1473,8 @@ HiSax_init(void)) printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); - Isdnl1New(); if (HiSax_inithardware(NULL)) { /* Install only, if at least one card found */ -#ifdef MODULE -#endif /* MODULE */ return (0); } else { Isdnl1Free(); @@ -1497,9 +1486,7 @@ HiSax_init(void)) } } -#ifdef MODULE -void -cleanup_module(void) +static void HiSax_exit(void) { int cardnr = nrcards -1; long flags; @@ -1516,17 +1503,14 @@ cleanup_module(void) restore_flags(flags); printk(KERN_INFO "HiSax module removed\n"); } -#endif #ifdef CONFIG_HISAX_ELSA int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) { #ifdef MODULE int i; - int nzproto = 0; nrcards = 0; - HiSaxVersion(); /* Initialize all structs, even though we only accept two pcmcia cards */ @@ -1536,14 +1520,12 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) cards[i].typ = type[i]; if (protocol[i]) { cards[i].protocol = protocol[i]; - nzproto++; } } cards[0].para[0] = pcm_irq; cards[0].para[1] = (int)pcm_iob; cards[0].protocol = prot; - cards[0].typ = 10; - nzproto = 1; + cards[0].typ = ISDN_CTYPE_ELSA_PCMCIA; if (!HiSax_id) HiSax_id = HiSaxID; @@ -1555,11 +1537,6 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - Isdnl1New(); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); HiSax_inithardware(busy_flag); printk(KERN_NOTICE "HiSax: module installed\n"); #endif @@ -1575,7 +1552,6 @@ int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) int nzproto = 0; nrcards = 0; - HiSaxVersion(); /* Initialize all structs, even though we only accept two pcmcia cards */ @@ -1604,11 +1580,6 @@ int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - Isdnl1New(); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); HiSax_inithardware(busy_flag); printk(KERN_NOTICE "HiSax: module installed\n"); #endif @@ -1624,7 +1595,6 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) int nzproto = 0; nrcards = 0; - HiSaxVersion(); /* Initialize all structs, even though we only accept two pcmcia cards */ @@ -1653,11 +1623,6 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - Isdnl1New(); - TeiNew(); HiSax_inithardware(busy_flag); printk(KERN_NOTICE "HiSax: module installed\n"); #endif @@ -1673,7 +1638,6 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) int nzproto = 0; nrcards = 0; - HiSaxVersion(); /* Initialize all structs, even though we only accept two pcmcia cards */ @@ -1702,11 +1666,6 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - Isdnl1New(); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); HiSax_inithardware(busy_flag); printk(KERN_NOTICE "HiSax: module installed\n"); #endif @@ -1714,7 +1673,7 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) } #endif -int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card) +int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card) { u_char ids[16]; int ret = -1; @@ -1731,3 +1690,7 @@ int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card) nrcards++; return (ret); } + + +module_init(HiSax_init); +module_exit(HiSax_exit); diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index deb981074a3c..fd6960646b6d 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -1,4 +1,4 @@ -/* $Id: diva.c,v 1.25.6.2 2000/11/29 16:00:14 kai Exp $ +/* $Id: diva.c,v 1.25.6.3 2001/02/13 10:33:58 kai Exp $ * * diva.c low level stuff for Eicon.Diehl Diva Family ISDN cards * @@ -21,10 +21,11 @@ #include "ipac.h" #include "isdnl1.h" #include +#include extern const char *CardType[]; -const char *Diva_revision = "$Revision: 1.25.6.2 $"; +const char *Diva_revision = "$Revision: 1.25.6.3 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index a9ef249433e0..aad897565f1b 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -1,4 +1,4 @@ -/* $Id: elsa.c,v 2.26.6.1 2000/11/28 12:02:46 kai Exp $ +/* $Id: elsa.c,v 2.26.6.2 2001/02/13 10:33:58 kai Exp $ * * elsa.c low level stuff for Elsa isdn cards * @@ -25,12 +25,13 @@ #include "hscx.h" #include "isdnl1.h" #include +#include #include #include extern const char *CardType[]; -const char *Elsa_revision = "$Revision: 2.26.6.1 $"; +const char *Elsa_revision = "$Revision: 2.26.6.2 $"; const char *Elsa_Types[] = {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI", diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c index e64dc28d9ea0..877b2c71fc24 100644 --- a/drivers/isdn/hisax/gazel.c +++ b/drivers/isdn/hisax/gazel.c @@ -1,4 +1,4 @@ -/* $Id: gazel.c,v 2.11.6.2 2000/11/29 16:00:14 kai Exp $ +/* $Id: gazel.c,v 2.11.6.3 2001/02/13 10:33:58 kai Exp $ * * gazel.c low level stuff for Gazel isdn cards * @@ -17,9 +17,10 @@ #include "isdnl1.h" #include "ipac.h" #include +#include extern const char *CardType[]; -const char *gazel_revision = "$Revision: 2.11.6.2 $"; +const char *gazel_revision = "$Revision: 2.11.6.3 $"; #define R647 1 #define R685 2 diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index c673fd881b32..65df8159b07e 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.c,v 1.34.6.3 2000/12/10 23:39:19 kai Exp $ +/* $Id: hfc_pci.c,v 1.34.6.4 2001/02/13 10:33:58 kai Exp $ * hfc_pci.c low level driver for CCD´s hfc-pci based cards * @@ -31,11 +31,12 @@ #include "hfc_pci.h" #include "isdnl1.h" #include +#include #include extern const char *CardType[]; -static const char *hfcpci_revision = "$Revision: 1.34.6.3 $"; +static const char *hfcpci_revision = "$Revision: 1.34.6.4 $"; /* table entry in the PCI devices list */ typedef struct { @@ -1636,7 +1637,6 @@ static struct pci_dev *dev_hfcpci __initdata = NULL; int __init setup_hfcpci(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; - unsigned short cmd; char tmp[64]; int i; struct pci_dev *tmp_hfcpci = NULL; @@ -1646,15 +1646,11 @@ int __init setup_hfcpci(struct IsdnCard *card) #endif strcpy(tmp, hfcpci_revision); printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); -#if CONFIG_PCI +#ifdef CONFIG_PCI cs->hw.hfcpci.int_s1 = 0; cs->dc.hfcpci.ph_state = 0; cs->hw.hfcpci.fifo = 255; if (cs->typ == ISDN_CTYPE_HFC_PCI) { - if (!pci_present()) { - printk(KERN_ERR "HFC-PCI: no PCI bus present\n"); - return (0); - } i = 0; while (id_list[i].vendor_id) { tmp_hfcpci = pci_find_device(id_list[i].vendor_id, @@ -1687,39 +1683,6 @@ int __init setup_hfcpci(struct IsdnCard *card) printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); return (0); } - if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) { - printk(KERN_WARNING "HFC-PCI shared mem address will be corrected\n"); - pcibios_write_config_word(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_COMMAND, - 0x0103); /* set SERR */ - pcibios_read_config_word(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_COMMAND, - &cmd); - pcibios_write_config_word(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_COMMAND, - cmd & ~2); - (int) cs->hw.hfcpci.pci_io &= ~(PAGE_SIZE - 1); - pcibios_write_config_dword(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_BASE_ADDRESS_1, - (int) cs->hw.hfcpci.pci_io); - pcibios_write_config_word(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_COMMAND, - cmd); - pcibios_read_config_dword(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_BASE_ADDRESS_1, - (void *) &cs->hw.hfcpci.pci_io); - if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) { - printk(KERN_WARNING "HFC-PCI unable to align address %x\n", (unsigned) cs->hw.hfcpci.pci_io); - return (0); - } - dev_hfcpci->base_address[1] = (int) cs->hw.hfcpci.pci_io; - } if (!cs->hw.hfcpci.pci_io) { printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); return (0); diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 0cb4bd666752..52e8421e4cd8 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -1,4 +1,4 @@ -/* $Id: hisax.h,v 2.52.6.1 2000/12/06 16:59:19 kai Exp $ +/* $Id: hisax.h,v 2.52.6.2 2001/02/10 14:41:22 kai Exp $ * * Basic declarations, defines and prototypes * @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -475,6 +475,7 @@ struct amd7930_hw { #define L1_MODE_TRANS 1 #define L1_MODE_HDLC 2 #define L1_MODE_EXTRN 3 +#define L1_MODE_HDLC_56K 4 #define L1_MODE_MODEM 7 #define L1_MODE_V32 8 #define L1_MODE_FAX 9 @@ -1348,17 +1349,3 @@ char *HiSax_getrev(const char *revision); void TeiNew(void); void TeiFree(void); int certification_check(int output); -#ifdef __powerpc__ -#include -static inline int pci_enable_device(struct pci_dev *dev) -{ - u16 cmd; - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_SERR; - cmd &= ~PCI_COMMAND_FAST_BACK; - pci_write_config_word(dev, PCI_COMMAND, cmd); - return(0); -} -#else -#define pci_enable_device(dev) !dev -#endif /* __powerpc__ */ diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c index 63636d3d1f48..d305077d86da 100644 --- a/drivers/isdn/hisax/isdnl3.c +++ b/drivers/isdn/hisax/isdnl3.c @@ -1,4 +1,4 @@ -/* $Id: isdnl3.c,v 2.17 2000/11/24 17:05:38 kai Exp $ +/* $Id: isdnl3.c,v 2.17.6.1 2001/01/08 17:09:20 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -303,7 +303,10 @@ release_l3_process(struct l3_process *p) if (!skb_queue_len(&p->st->l3.squeue)) { if (p->debug) l3_debug(p->st, "release_l3_process: release link"); - FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL); + if (p->st->protocol != ISDN_PTYPE_NI1) + FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL); + else + FsmEvent(&p->st->l3.l3m, EV_RELEASE_IND, NULL); } else { if (p->debug) l3_debug(p->st, "release_l3_process: not release link"); @@ -482,6 +485,18 @@ lc_start_delay(struct FsmInst *fi, int event, void *arg) FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50); } +static void +lc_start_delay_check(struct FsmInst *fi, int event, void *arg) +/* 20/09/00 - GE timer not user for NI-1 as layer 2 should stay up */ +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L3_LC_REL_DELAY); + /* 19/09/00 - GE timer not user for NI-1 */ + if (st->protocol != ISDN_PTYPE_NI1) + FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50); +} + static void lc_release_req(struct FsmInst *fi, int event, void *arg) { @@ -530,7 +545,7 @@ static struct FsmNode L3FnList[] __initdata = {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay}, {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind}, {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind}, - {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay}, + {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay_check}, {ST_L3_LC_REL_DELAY, EV_RELEASE_IND, lc_release_ind}, {ST_L3_LC_REL_DELAY, EV_ESTABLISH_REQ, lc_connected}, {ST_L3_LC_REL_DELAY, EV_TIMEOUT, lc_release_req}, @@ -551,7 +566,7 @@ l3_msg(struct PStack *st, int pr, void *arg) } else { struct sk_buff *skb = arg; - skb_queue_head(&st->l3.squeue, skb); + skb_queue_tail(&st->l3.squeue, skb); FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); } break; diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c index 714cad9157ce..4440f44e7bd7 100644 --- a/drivers/isdn/hisax/l3ni1.c +++ b/drivers/isdn/hisax/l3ni1.c @@ -10,8 +10,8 @@ // // 2000.6.6 Initial implementation of routines for US NI1 // Layer 3 protocol based on the EURO/DSS1 D-channel protocol -// driver written by Karsten Keil et al. -// NI-1 Hall of Fame - Thanks to.... +// driver written by Karsten Keil et al. +// NI-1 Hall of Fame - Thanks to.... // Ragnar Paulson - for some handy code fragments // Will Scales - beta tester extraordinaire // Brett Whittacre - beta tester and remote devel system in Vegas @@ -446,6 +446,27 @@ l3ni1_message(struct l3_process *pc, u_char mt) l3_msg(pc->st, DL_DATA | REQUEST, skb); } +static void +l3ni1_message_plus_chid(struct l3_process *pc, u_char mt) +/* sends an l3 messages plus channel id - added GE 05/09/00 */ +{ + struct sk_buff *skb; + u_char tmp[16]; + u_char *p = tmp; + u_char chid; + + chid = (u_char)(pc->para.bchannel & 0x03) | 0x88; + MsgHead(p, pc->callref, mt); + *p++ = IE_CHANNEL_ID; + *p++ = 0x01; + *p++ = chid; + + if (!(skb = l3_alloc_skb(7))) + return; + memcpy(skb_put(skb, 7), tmp, 7); + l3_msg(pc->st, DL_DATA | REQUEST, skb); +} + static void l3ni1_message_cause(struct l3_process *pc, u_char mt, u_char cause) { @@ -1179,9 +1200,9 @@ l3ni1_setup_req(struct l3_process *pc, u_char pr, case 1: /* Telephony */ *p++ = IE_BEARER; *p++ = 0x3; /* Length */ - *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */ + *p++ = 0x90; /* 3.1khz Audio */ *p++ = 0x90; /* Circuit-Mode 64kbps */ - *p++ = 0xa3; /* A-Law Audio */ + *p++ = 0xa2; /* u-Law Audio */ break; case 5: /* Datatransmission 64k, BTX */ case 7: /* Datatransmission 64k */ @@ -1244,7 +1265,7 @@ l3ni1_setup_req(struct l3_process *pc, u_char pr, *p++ = 0x3; /* Length */ *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */ *p++ = 0x90; /* Circuit-Mode 64kbps */ - *p++ = 0xa3; /* A-Law Audio */ + *p++ = 0xa2; /* u-Law Audio */ break; case 5: /* Datatransmission 64k, BTX */ case 7: /* Datatransmission 64k */ @@ -1645,7 +1666,9 @@ l3ni1_setup_rsp(struct l3_process *pc, u_char pr, return; } newl3state(pc, 8); - l3ni1_message(pc, MT_CONNECT); + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "D-chan connect for waiting call"); + l3ni1_message_plus_chid(pc, MT_CONNECT); /* GE 05/09/00 */ L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T313, CC_T313); } @@ -2548,6 +2571,7 @@ l3ni1_global_restart(struct l3_process *pc, u_char pr, void *arg) up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); else if (up->para.bchannel == chan) up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); + up = up->next; } p = tmp; diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index 2904bb3851dc..1ca81cdb9340 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -1,4 +1,4 @@ -/* $Id: netjet.c,v 1.24.6.2 2000/12/17 22:45:11 kai Exp $ +/* $Id: netjet.c,v 1.24.6.3 2001/02/13 10:33:58 kai Exp $ * * netjet.c low level stuff for Traverse Technologie NETJet ISDN cards * @@ -16,13 +16,12 @@ #include "isac.h" #include "hscx.h" #include "isdnl1.h" -#include #include #include #include #include "netjet.h" -const char *NETjet_revision = "$Revision: 1.24.6.2 $"; +const char *NETjet_revision = "$Revision: 1.24.6.3 $"; /* Interface functions */ @@ -155,7 +154,8 @@ mode_tiger(struct BCState *bcs, int mode, int bc) break; case (L1_MODE_TRANS): break; - case (L1_MODE_HDLC): + case (L1_MODE_HDLC_56K): + case (L1_MODE_HDLC): fill_mem(bcs, bcs->hw.tiger.send, NETJET_DMA_TXSIZE, bc, 0xff); bcs->hw.tiger.r_state = HDLC_ZERO_SEARCH; @@ -170,7 +170,8 @@ mode_tiger(struct BCState *bcs, int mode, int bc) cs->hw.njet.dmactrl = 1; byteout(cs->hw.njet.base + NETJET_DMACTRL, cs->hw.njet.dmactrl); - byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x3f); + byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x0f); + /* was 0x3f now 0x0f for TJ300 and TJ320 GE 13/07/00 */ } bcs->hw.tiger.sendp = bcs->hw.tiger.send; bcs->hw.tiger.free = NETJET_DMA_TXSIZE; @@ -208,6 +209,8 @@ static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s } } +// macro for 64k + #define MAKE_RAW_BYTE for (j=0; j<8; j++) { \ bitcnt++;\ s_val >>= 1;\ @@ -236,6 +239,7 @@ static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s } static int make_raw_data(struct BCState *bcs) { +// this make_raw is for 64k register u_int i,s_cnt=0; register u_char j; register u_char val; @@ -291,6 +295,113 @@ static int make_raw_data(struct BCState *bcs) { return(0); } +// macro for 56k + +#define MAKE_RAW_BYTE_56K for (j=0; j<8; j++) { \ + bitcnt++;\ + s_val >>= 1;\ + if (val & 1) {\ + s_one++;\ + s_val |= 0x80;\ + } else {\ + s_one = 0;\ + s_val &= 0x7f;\ + }\ + if (bitcnt==7) {\ + s_val >>= 1;\ + s_val |= 0x80;\ + bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\ + bitcnt = 0;\ + }\ + if (s_one == 5) {\ + s_val >>= 1;\ + s_val &= 0x7f;\ + bitcnt++;\ + s_one = 0;\ + }\ + if (bitcnt==7) {\ + s_val >>= 1;\ + s_val |= 0x80;\ + bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\ + bitcnt = 0;\ + }\ + val >>= 1;\ + } + +static int make_raw_data_56k(struct BCState *bcs) { +// this make_raw is for 56k + register u_int i,s_cnt=0; + register u_char j; + register u_char val; + register u_char s_one = 0; + register u_char s_val = 0; + register u_char bitcnt = 0; + u_int fcs; + + if (!bcs->tx_skb) { + debugl1(bcs->cs, "tiger make_raw_56k: NULL skb"); + return(1); + } + val = HDLC_FLAG_VALUE; + for (j=0; j<8; j++) { + bitcnt++; + s_val >>= 1; + if (val & 1) + s_val |= 0x80; + else + s_val &= 0x7f; + if (bitcnt==7) { + s_val >>= 1; + s_val |= 0x80; + bcs->hw.tiger.sendbuf[s_cnt++] = s_val; + bitcnt = 0; + } + val >>= 1; + }; + fcs = PPP_INITFCS; + for (i=0; itx_skb->len; i++) { + val = bcs->tx_skb->data[i]; + fcs = PPP_FCS (fcs, val); + MAKE_RAW_BYTE_56K; + } + fcs ^= 0xffff; + val = fcs & 0xff; + MAKE_RAW_BYTE_56K; + val = (fcs>>8) & 0xff; + MAKE_RAW_BYTE_56K; + val = HDLC_FLAG_VALUE; + for (j=0; j<8; j++) { + bitcnt++; + s_val >>= 1; + if (val & 1) + s_val |= 0x80; + else + s_val &= 0x7f; + if (bitcnt==7) { + s_val >>= 1; + s_val |= 0x80; + bcs->hw.tiger.sendbuf[s_cnt++] = s_val; + bitcnt = 0; + } + val >>= 1; + } + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger make_raw_56k: in %ld out %d.%d", + bcs->tx_skb->len, s_cnt, bitcnt); + if (bitcnt) { + while (8>bitcnt++) { + s_val >>= 1; + s_val |= 0x80; + } + bcs->hw.tiger.sendbuf[s_cnt++] = s_val; + bcs->hw.tiger.sendbuf[s_cnt++] = 0xff; // NJ<->NJ thoughput bug fix + } + bcs->hw.tiger.sendcnt = s_cnt; + bcs->tx_cnt -= bcs->tx_skb->len; + bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf; + return(0); +} + static void got_frame(struct BCState *bcs, int count) { struct sk_buff *skb; @@ -320,20 +431,30 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){ register u_char r_val = bcs->hw.tiger.r_val; register u_int bitcnt = bcs->hw.tiger.r_bitcnt; u_int *p = buf; - + int bits; + u_char mask; + + if (bcs->mode == L1_MODE_HDLC) { // it's 64k + mask = 0xff; + bits = 8; + } + else { // it's 56K + mask = 0x7f; + bits = 7; + }; for (i=0;ichannel ? ((*p>>8) & 0xff) : (*p & 0xff); p++; if (p > pend) p = bcs->hw.tiger.rec; - if (val == 0xff) { + if ((val & mask) == mask) { state = HDLC_ZERO_SEARCH; bcs->hw.tiger.r_tot++; bitcnt = 0; r_one = 0; continue; } - for (j=0;j<8;j++) { + for (j=0;jbcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1; else p = cs->bcs[0].hw.tiger.rec + cnt - 1; - if (cs->bcs[0].mode == L1_MODE_HDLC) + if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K)) read_raw(cs->bcs, p, cnt); - if (cs->bcs[1].mode == L1_MODE_HDLC) + + if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K)) read_raw(cs->bcs + 1, p, cnt); cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_READ; } @@ -520,8 +642,14 @@ void netjet_fill_dma(struct BCState *bcs) bcs->Flag); if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag)) return; - if (make_raw_data(bcs)) - return; + if (bcs->mode == L1_MODE_HDLC) { // it's 64k + if (make_raw_data(bcs)) + return; + } + else { // it's 56k + if (make_raw_data_56k(bcs)) + return; + }; if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel, bcs->Flag); @@ -676,9 +804,9 @@ void write_tiger(struct IsdnCardState *cs) { p = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1; else p = cs->bcs[0].hw.tiger.send + cnt - 1; - if (cs->bcs[0].mode == L1_MODE_HDLC) + if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K)) write_raw(cs->bcs, p, cnt); - if (cs->bcs[1].mode == L1_MODE_HDLC) + if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K)) write_raw(cs->bcs + 1, p, cnt); cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_WRITE; } diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c index 6924c3325c72..c80afd716d2a 100644 --- a/drivers/isdn/hisax/niccy.c +++ b/drivers/isdn/hisax/niccy.c @@ -1,4 +1,4 @@ -/* $Id: niccy.c,v 1.15.6.2 2000/11/29 16:00:14 kai Exp $ +/* $Id: niccy.c,v 1.15.6.3 2001/02/13 10:33:58 kai Exp $ * * niccy.c low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and * compatible (SAGEM cybermodem) @@ -20,9 +20,10 @@ #include "hscx.h" #include "isdnl1.h" #include +#include extern const char *CardType[]; -const char *niccy_revision = "$Revision: 1.15.6.2 $"; +const char *niccy_revision = "$Revision: 1.15.6.3 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c index bc640a6c503f..f844e8ae1542 100644 --- a/drivers/isdn/hisax/nj_s.c +++ b/drivers/isdn/hisax/nj_s.c @@ -1,20 +1,21 @@ -// $Id: nj_s.c,v 2.7.6.1 2000/11/29 16:00:14 kai Exp $ +// $Id: nj_s.c,v 2.7.6.3 2001/02/13 10:33:58 kai Exp $ // // This file is (c) under GNU PUBLIC LICENSE // #define __NO_VERSION__ -#include #include +#include #include "hisax.h" #include "isac.h" #include "isdnl1.h" #include +#include #include #include #include "netjet.h" -const char *NETjet_S_revision = "$Revision: 2.7.6.1 $"; +const char *NETjet_S_revision = "$Revision: 2.7.6.3 $"; static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) { @@ -49,28 +50,37 @@ netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs) } save_flags(flags); cli(); - if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) { + /* start new code 13/07/00 GE */ + /* set bits in sval to indicate which page is free */ + if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < + inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) + /* the 2nd write page is free */ + sval = 0x08; + else /* the 1st write page is free */ + sval = 0x04; + if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < + inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) + /* the 2nd read page is free */ + sval = sval | 0x02; + else /* the 1st read page is free */ + sval = sval | 0x01; + if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ + { if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { restore_flags(flags); return; } cs->hw.njet.irqstat0 = sval; restore_flags(flags); -/* debugl1(cs, "tiger: ist0 %x %x %x %x/%x pulse=%d", - sval, - bytein(cs->hw.njet.base + NETJET_DMACTRL), - bytein(cs->hw.njet.base + NETJET_IRQMASK0), - inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), - inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), - bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); -*/ -/* cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30; -*/ byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0); -/* byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0); -*/ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) + if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != + (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) + /* we have a read dma int */ read_tiger(cs); - if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) + if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) != + (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE)) + /* we have a write dma int */ write_tiger(cs); + /* end new code 13/07/00 GE */ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else restore_flags(flags); @@ -95,7 +105,8 @@ reset_netjet_s(struct IsdnCardState *cs) byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ + /* now edge triggered for TJ320 GE 13/07/00 */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ @@ -139,8 +150,7 @@ setup_netjet_s(struct IsdnCard *card) struct IsdnCardState *cs = card->cs; char tmp[64]; long flags; -#if CONFIG_PCI -#endif + #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif @@ -151,10 +161,9 @@ setup_netjet_s(struct IsdnCard *card) test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); #if CONFIG_PCI + for ( ;; ) { - - if (!pci_present()) { printk(KERN_ERR "Netjet: no PCI bus present\n"); return(0); @@ -163,6 +172,7 @@ setup_netjet_s(struct IsdnCard *card) PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { if (pci_enable_device(dev_netjet)) return(0); + pci_set_master(dev_netjet); cs->irq = dev_netjet->irq; if (!cs->irq) { printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n"); diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c index 67c18a35cc1a..9977477f825c 100644 --- a/drivers/isdn/hisax/nj_u.c +++ b/drivers/isdn/hisax/nj_u.c @@ -1,21 +1,22 @@ -/* $Id: nj_u.c,v 2.8.6.1 2000/11/29 16:00:14 kai Exp $ +/* $Id: nj_u.c,v 2.8.6.3 2001/02/13 10:33:58 kai Exp $ * * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ -#include #include +#include #include "hisax.h" #include "icc.h" #include "isdnl1.h" #include +#include #include #include #include "netjet.h" -const char *NETjet_U_revision = "$Revision: 2.8.6.1 $"; +const char *NETjet_U_revision = "$Revision: 2.8.6.3 $"; static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) { @@ -50,28 +51,37 @@ netjet_u_interrupt(int intno, void *dev_id, struct pt_regs *regs) } save_flags(flags); cli(); - if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) { + /* start new code 13/07/00 GE */ + /* set bits in sval to indicate which page is free */ + if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < + inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) + /* the 2nd write page is free */ + sval = 0x08; + else /* the 1st write page is free */ + sval = 0x04; + if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < + inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) + /* the 2nd read page is free */ + sval = sval | 0x02; + else /* the 1st read page is free */ + sval = sval | 0x01; + if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ + { if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { restore_flags(flags); return; } cs->hw.njet.irqstat0 = sval; restore_flags(flags); -/* debugl1(cs, "tiger: ist0 %x %x %x %x/%x pulse=%d", - sval, - bytein(cs->hw.njet.base + NETJET_DMACTRL), - bytein(cs->hw.njet.base + NETJET_IRQMASK0), - inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), - inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), - bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); -*/ -/* cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30; -*/ byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0); -/* byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0); -*/ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) + if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != + (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) + /* we have a read dma int */ read_tiger(cs); - if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) + if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) != + (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE)) + /* we have a write dma int */ write_tiger(cs); + /* end new code 13/07/00 GE */ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else restore_flags(flags); @@ -96,7 +106,8 @@ reset_netjet_u(struct IsdnCardState *cs) byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ + /* now edge triggered for TJ320 GE 13/07/00 */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ @@ -153,18 +164,18 @@ setup_netjet_u(struct IsdnCard *card) test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); #if CONFIG_PCI + for ( ;; ) { - - if (!pci_present()) { - printk(KERN_ERR "NETspider-U: no PCI bus present\n"); + printk(KERN_ERR "Netjet: no PCI bus present\n"); return(0); } if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { if (pci_enable_device(dev_netjet)) return(0); + pci_set_master(dev_netjet); cs->irq = dev_netjet->irq; if (!cs->irq) { printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n"); @@ -244,7 +255,7 @@ setup_netjet_u(struct IsdnCard *card) cs->hw.njet.base + bytecnt); return (0); } else { - request_region(cs->hw.njet.base, bytecnt, "netjet-u isdn"); + request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn"); } reset_netjet_u(cs); cs->readisac = &NETjet_ReadIC; diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 791405f27090..013f83c2e509 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -1,4 +1,4 @@ -/* $Id: sedlbauer.c,v 1.25.6.2 2000/11/29 17:48:59 kai Exp $ +/* $Id: sedlbauer.c,v 1.25.6.3 2001/02/13 10:33:58 kai Exp $ * * sedlbauer.c low level stuff for Sedlbauer cards * includes support for the Sedlbauer speed star (speed star II), @@ -49,10 +49,11 @@ #include "isar.h" #include "isdnl1.h" #include +#include extern const char *CardType[]; -const char *Sedlbauer_revision = "$Revision: 1.25.6.2 $"; +const char *Sedlbauer_revision = "$Revision: 1.25.6.3 $"; const char *Sedlbauer_Types[] = {"None", "speed card/win", "speed star", "speed fax+", @@ -529,7 +530,7 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -static struct pci_dev *dev_sedl = NULL; +static struct pci_dev *dev_sedl = NULL; int setup_sedlbauer(struct IsdnCard *card) diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c index 2e4e10ff35fd..b72ff032c6bd 100644 --- a/drivers/isdn/hisax/sportster.c +++ b/drivers/isdn/hisax/sportster.c @@ -208,8 +208,8 @@ get_io_range(struct IsdnCardState *cs) } } -__initfunc(int -setup_sportster(struct IsdnCard *card)) +int __init +setup_sportster(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c index a85e54bb67b1..41a7446b7521 100644 --- a/drivers/isdn/hisax/tei.c +++ b/drivers/isdn/hisax/tei.c @@ -12,9 +12,9 @@ * */ #define __NO_VERSION__ -#include #include "hisax.h" #include "isdnl2.h" +#include #include const char *tei_revision = "$Revision: 2.17 $"; diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c index dda87c51e9d6..deca1d2d5a9c 100644 --- a/drivers/isdn/hisax/telespci.c +++ b/drivers/isdn/hisax/telespci.c @@ -1,4 +1,4 @@ -/* $Id: telespci.c,v 2.16.6.2 2000/11/29 16:00:14 kai Exp $ +/* $Id: telespci.c,v 2.16.6.3 2001/02/13 10:33:58 kai Exp $ * * telespci.c low level stuff for Teles PCI isdn cards * @@ -16,9 +16,10 @@ #include "hscx.h" #include "isdnl1.h" #include +#include extern const char *CardType[]; -const char *telespci_revision = "$Revision: 2.16.6.2 $"; +const char *telespci_revision = "$Revision: 2.16.6.3 $"; #define ZORAN_PO_RQ_PEN 0x02000000 #define ZORAN_PO_WR 0x00800000 @@ -275,7 +276,7 @@ TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -static struct pci_dev *dev_tel __initdata = NULL; +static struct pci_dev *dev_tel __initdata = NULL; int __init setup_telespci(struct IsdnCard *card) diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index 6a0012b37315..3586d75d4675 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c @@ -1,4 +1,4 @@ -/* $Id: w6692.c,v 1.12.6.2 2000/11/29 16:00:14 kai Exp $ +/* $Id: w6692.c,v 1.12.6.3 2001/02/13 10:33:58 kai Exp $ * * w6692.c Winbond W6692 specific routines * @@ -17,6 +17,7 @@ #include "isdnl1.h" #include #include +#include /* table entry in the PCI devices list */ typedef struct { @@ -35,7 +36,7 @@ static const PCI_ENTRY id_list[] = extern const char *CardType[]; -const char *w6692_revision = "$Revision: 1.12.6.2 $"; +const char *w6692_revision = "$Revision: 1.12.6.3 $"; #define DBUSY_TIMER_VALUE 80 @@ -955,11 +956,12 @@ w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg) return (0); } -static int id_idx = 0; +static int id_idx ; static struct pci_dev *dev_w6692 __initdata = NULL; -__initfunc(int setup_w6692(struct IsdnCard *card)) +int __init +setup_w6692(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hysdn/Makefile b/drivers/isdn/hysdn/Makefile new file mode 100644 index 000000000000..a3ab66f10c9a --- /dev/null +++ b/drivers/isdn/hysdn/Makefile @@ -0,0 +1,29 @@ +# Makefile for the hysdn ISDN device driver + +# The target object and module list name. + +O_TARGET := vmlinux-obj.o + +# Multipart objects. + +list-multi := hysdn.o +hysdn-objs := hysdn_procconf.o hysdn_proclog.o boardergo.o hysdn_boot.o \ + hysdn_sched.o hysdn_net.o hysdn_init.o + +# Optional parts of multipart objects. + +hysdn-objs-$(CONFIG_HYSDN_CAPI) += hycapi.o + +hysdn-objs += $(hysdn-objs-y) + +# Each configuration option enables a list of files. + +obj-$(CONFIG_HYSDN) += hysdn.o + +include $(TOPDIR)/drivers/isdn/Rules.make + +# Link rules for multi-part drivers. + +hysdn.o: $(hysdn-objs) + $(LD) -r -o $@ $(hysdn-objs) + diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c new file mode 100644 index 000000000000..92e96ec9b40e --- /dev/null +++ b/drivers/isdn/hysdn/boardergo.c @@ -0,0 +1,466 @@ +/* $Id: boardergo.c,v 1.5.6.1 2000/12/10 22:01:04 kai Exp $ + + * Linux driver for HYSDN cards, specific routines for ergo type boards. + * + * As all Linux supported cards Champ2, Ergo and Metro2/4 use the same + * DPRAM interface and layout with only minor differences all related + * stuff is done here, not in separate modules. + * + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define __NO_VERSION__ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hysdn_defs.h" +#include "boardergo.h" + +#define byteout(addr,val) outb(val,addr) +#define bytein(addr) inb(addr) + +/***************************************************/ +/* The cards interrupt handler. Called from system */ +/***************************************************/ +static void +ergo_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + hysdn_card *card = dev_id; /* parameter from irq */ + tErgDpram *dpr; + ulong flags; + uchar volatile b; + + if (!card) + return; /* error -> spurious interrupt */ + if (!card->irq_enabled) + return; /* other device interrupting or irq switched off */ + + save_flags(flags); + cli(); /* no further irqs allowed */ + + if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) { + restore_flags(flags); /* restore old state */ + return; /* no interrupt requested by E1 */ + } + /* clear any pending ints on the board */ + dpr = card->dpram; + b = dpr->ToPcInt; /* clear for ergo */ + b |= dpr->ToPcIntMetro; /* same for metro */ + b |= dpr->ToHyInt; /* and for champ */ + + /* start kernel task immediately after leaving all interrupts */ + if (!card->hw_lock) { + queue_task(&card->irq_queue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } + restore_flags(flags); +} /* ergo_interrupt */ + +/******************************************************************************/ +/* ergo_irq_bh is the function called by the immediate kernel task list after */ +/* being activated with queue_task and no interrupts active. This task is the */ +/* only one handling data transfer from or to the card after booting. The task */ +/* may be queued from everywhere (interrupts included). */ +/******************************************************************************/ +static void +ergo_irq_bh(hysdn_card * card) +{ + tErgDpram *dpr; + int again; + ulong flags; + + if (card->state != CARD_STATE_RUN) + return; /* invalid call */ + + dpr = card->dpram; /* point to DPRAM */ + + save_flags(flags); + cli(); + if (card->hw_lock) { + restore_flags(flags); /* hardware currently unavailable */ + return; + } + card->hw_lock = 1; /* we now lock the hardware */ + + do { + sti(); /* reenable other ints */ + again = 0; /* assume loop not to be repeated */ + + if (!dpr->ToHyFlag) { + /* we are able to send a buffer */ + + if (hysdn_sched_tx(card, dpr->ToHyBuf, &dpr->ToHySize, &dpr->ToHyChannel, + ERG_TO_HY_BUF_SIZE)) { + dpr->ToHyFlag = 1; /* enable tx */ + again = 1; /* restart loop */ + } + } /* we are able to send a buffer */ + if (dpr->ToPcFlag) { + /* a message has arrived for us, handle it */ + + if (hysdn_sched_rx(card, dpr->ToPcBuf, dpr->ToPcSize, dpr->ToPcChannel)) { + dpr->ToPcFlag = 0; /* we worked the data */ + again = 1; /* restart loop */ + } + } /* a message has arrived for us */ + cli(); /* no further ints */ + if (again) { + dpr->ToHyInt = 1; + dpr->ToPcInt = 1; /* interrupt to E1 for all cards */ + } else + card->hw_lock = 0; /* free hardware again */ + } while (again); /* until nothing more to do */ + + restore_flags(flags); +} /* ergo_irq_bh */ + + +/*********************************************************/ +/* stop the card (hardware reset) and disable interrupts */ +/*********************************************************/ +static void +ergo_stopcard(hysdn_card * card) +{ + ulong flags; + uchar val; + + hysdn_net_release(card); /* first release the net device if existing */ +#ifdef CONFIG_HYSDN_CAPI + hycapi_capi_stop(card); +#endif /* CONFIG_HYSDN_CAPI */ + save_flags(flags); + cli(); + val = bytein(card->iobase + PCI9050_INTR_REG); /* get actual value */ + val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1); /* mask irq */ + byteout(card->iobase + PCI9050_INTR_REG, val); + card->irq_enabled = 0; + byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RESET); /* reset E1 processor */ + card->state = CARD_STATE_UNUSED; + card->err_log_state = ERRLOG_STATE_OFF; /* currently no log active */ + + restore_flags(flags); +} /* ergo_stopcard */ + +/**************************************************************************/ +/* enable or disable the cards error log. The event is queued if possible */ +/**************************************************************************/ +static void +ergo_set_errlog_state(hysdn_card * card, int on) +{ + ulong flags; + + if (card->state != CARD_STATE_RUN) { + card->err_log_state = ERRLOG_STATE_OFF; /* must be off */ + return; + } + save_flags(flags); + cli(); + + if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) || + ((card->err_log_state == ERRLOG_STATE_ON) && on)) { + restore_flags(flags); + return; /* nothing to do */ + } + if (on) + card->err_log_state = ERRLOG_STATE_START; /* request start */ + else + card->err_log_state = ERRLOG_STATE_STOP; /* request stop */ + + restore_flags(flags); + queue_task(&card->irq_queue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} /* ergo_set_errlog_state */ + +/******************************************/ +/* test the cards RAM and return 0 if ok. */ +/******************************************/ +static const char TestText[36] = "This Message is filler, why read it"; + +static int +ergo_testram(hysdn_card * card) +{ + tErgDpram *dpr = card->dpram; + + memset(dpr->TrapTable, 0, sizeof(dpr->TrapTable)); /* clear all Traps */ + dpr->ToHyInt = 1; /* E1 INTR state forced */ + + memcpy(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText, + sizeof(TestText)); + if (memcmp(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText, + sizeof(TestText))) + return (-1); + + memcpy(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText, + sizeof(TestText)); + if (memcmp(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText, + sizeof(TestText))) + return (-1); + + return (0); +} /* ergo_testram */ + +/*****************************************************************************/ +/* this function is intended to write stage 1 boot image to the cards buffer */ +/* this is done in two steps. First the 1024 hi-words are written (offs=0), */ +/* then the 1024 lo-bytes are written. The remaining DPRAM is cleared, the */ +/* PCI-write-buffers flushed and the card is taken out of reset. */ +/* The function then waits for a reaction of the E1 processor or a timeout. */ +/* Negative return values are interpreted as errors. */ +/*****************************************************************************/ +static int +ergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs) +{ + uchar *dst; + tErgDpram *dpram; + int cnt = (BOOT_IMG_SIZE >> 2); /* number of words to move and swap (byte order!) */ + + if (card->debug_flags & LOG_POF_CARD) + hysdn_addlog(card, "ERGO: write bootldr offs=0x%lx ", offs); + + dst = card->dpram; /* pointer to start of DPRAM */ + dst += (offs + ERG_DPRAM_FILL_SIZE); /* offset in the DPRAM */ + while (cnt--) { + *dst++ = *(buf + 1); /* high byte */ + *dst++ = *buf; /* low byte */ + dst += 2; /* point to next longword */ + buf += 2; /* buffer only filled with words */ + } + + /* if low words (offs = 2) have been written, clear the rest of the DPRAM, */ + /* flush the PCI-write-buffer and take the E1 out of reset */ + if (offs) { + memset(card->dpram, 0, ERG_DPRAM_FILL_SIZE); /* fill the DPRAM still not cleared */ + dpram = card->dpram; /* get pointer to dpram structure */ + dpram->ToHyNoDpramErrLog = 0xFF; /* write a dpram register */ + while (!dpram->ToHyNoDpramErrLog); /* reread volatile register to flush PCI */ + + byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN); /* start E1 processor */ + /* the interrupts are still masked */ + + sti(); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + + if (((tDpramBootSpooler *) card->dpram)->Len != DPRAM_SPOOLER_DATA_SIZE) { + if (card->debug_flags & LOG_POF_CARD) + hysdn_addlog(card, "ERGO: write bootldr no answer"); + return (-ERR_BOOTIMG_FAIL); + } + } /* start_boot_img */ + return (0); /* successfull */ +} /* ergo_writebootimg */ + +/********************************************************************************/ +/* ergo_writebootseq writes the buffer containing len bytes to the E1 processor */ +/* using the boot spool mechanism. If everything works fine 0 is returned. In */ +/* case of errors a negative error value is returned. */ +/********************************************************************************/ +static int +ergo_writebootseq(struct HYSDN_CARD *card, uchar * buf, int len) +{ + tDpramBootSpooler *sp = (tDpramBootSpooler *) card->dpram; + uchar *dst; + uchar buflen; + int nr_write; + uchar tmp_rdptr; + uchar wr_mirror; + int i; + + if (card->debug_flags & LOG_POF_CARD) + hysdn_addlog(card, "ERGO: write boot seq len=%d ", len); + + dst = sp->Data; /* point to data in spool structure */ + buflen = sp->Len; /* maximum len of spooled data */ + wr_mirror = sp->WrPtr; /* only once read */ + sti(); + + /* try until all bytes written or error */ + i = 0x1000; /* timeout value */ + while (len) { + + /* first determine the number of bytes that may be buffered */ + do { + tmp_rdptr = sp->RdPtr; /* first read the pointer */ + i--; /* decrement timeout */ + } while (i && (tmp_rdptr != sp->RdPtr)); /* wait for stable pointer */ + + if (!i) { + if (card->debug_flags & LOG_POF_CARD) + hysdn_addlog(card, "ERGO: write boot seq timeout"); + return (-ERR_BOOTSEQ_FAIL); /* value not stable -> timeout */ + } + if ((nr_write = tmp_rdptr - wr_mirror - 1) < 0) + nr_write += buflen; /* now we got number of free bytes - 1 in buffer */ + + if (!nr_write) + continue; /* no free bytes in buffer */ + + if (nr_write > len) + nr_write = len; /* limit if last few bytes */ + i = 0x1000; /* reset timeout value */ + + /* now we know how much bytes we may put in the puffer */ + len -= nr_write; /* we savely could adjust len before output */ + while (nr_write--) { + *(dst + wr_mirror) = *buf++; /* output one byte */ + if (++wr_mirror >= buflen) + wr_mirror = 0; + sp->WrPtr = wr_mirror; /* announce the next byte to E1 */ + } /* while (nr_write) */ + + } /* while (len) */ + return (0); +} /* ergo_writebootseq */ + +/***********************************************************************************/ +/* ergo_waitpofready waits for a maximum of 10 seconds for the completition of the */ +/* boot process. If the process has been successfull 0 is returned otherwise a */ +/* negative error code is returned. */ +/***********************************************************************************/ +static int +ergo_waitpofready(struct HYSDN_CARD *card) +{ + tErgDpram *dpr = card->dpram; /* pointer to DPRAM structure */ + int timecnt = 10000 / 50; /* timeout is 10 secs max. */ + ulong flags; + int msg_size; + int i; + + if (card->debug_flags & LOG_POF_CARD) + hysdn_addlog(card, "ERGO: waiting for pof ready"); + while (timecnt--) { + /* wait until timeout */ + + if (dpr->ToPcFlag) { + /* data has arrived */ + + if ((dpr->ToPcChannel != CHAN_SYSTEM) || + (dpr->ToPcSize < MIN_RDY_MSG_SIZE) || + (dpr->ToPcSize > MAX_RDY_MSG_SIZE) || + ((*(ulong *) dpr->ToPcBuf) != RDY_MAGIC)) + break; /* an error occured */ + + /* Check for additional data delivered during SysReady */ + msg_size = dpr->ToPcSize - RDY_MAGIC_SIZE; + if (msg_size > 0) + if (EvalSysrTokData(card, dpr->ToPcBuf + RDY_MAGIC_SIZE, msg_size)) + break; + + if (card->debug_flags & LOG_POF_RECORD) + hysdn_addlog(card, "ERGO: pof boot success"); + save_flags(flags); + cli(); + + card->state = CARD_STATE_RUN; /* now card is running */ + /* enable the cards interrupt */ + byteout(card->iobase + PCI9050_INTR_REG, + bytein(card->iobase + PCI9050_INTR_REG) | + (PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1)); + card->irq_enabled = 1; /* we are ready to receive interrupts */ + + dpr->ToPcFlag = 0; /* reset data indicator */ + dpr->ToHyInt = 1; + dpr->ToPcInt = 1; /* interrupt to E1 for all cards */ + + restore_flags(flags); + if ((i = hysdn_net_create(card))) { + ergo_stopcard(card); + card->state = CARD_STATE_BOOTERR; + return (i); + } +#ifdef CONFIG_HYSDN_CAPI + if((i = hycapi_capi_create(card))) { + printk(KERN_WARNING "HYSDN: failed to create capi-interface.\n"); + } +#endif /* CONFIG_HYSDN_CAPI */ + return (0); /* success */ + } /* data has arrived */ + sti(); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((50 * HZ) / 1000); /* Timeout 50ms */ + } /* wait until timeout */ + + if (card->debug_flags & LOG_POF_CARD) + hysdn_addlog(card, "ERGO: pof boot ready timeout"); + return (-ERR_POF_TIMEOUT); +} /* ergo_waitpofready */ + + + +/************************************************************************************/ +/* release the cards hardware. Before releasing do a interrupt disable and hardware */ +/* reset. Also unmap dpram. */ +/* Use only during module release. */ +/************************************************************************************/ +static void +ergo_releasehardware(hysdn_card * card) +{ + ergo_stopcard(card); /* first stop the card if not already done */ + free_irq(card->irq, card); /* release interrupt */ + release_region(card->iobase + PCI9050_INTR_REG, 1); /* release all io ports */ + release_region(card->iobase + PCI9050_USER_IO, 1); + vfree(card->dpram); + card->dpram = NULL; /* release shared mem */ +} /* ergo_releasehardware */ + + +/*********************************************************************************/ +/* acquire the needed hardware ports and map dpram. If an error occurs a nonzero */ +/* value is returned. */ +/* Use only during module init. */ +/*********************************************************************************/ +int +ergo_inithardware(hysdn_card * card) +{ + if (check_region(card->iobase + PCI9050_INTR_REG, 1) || + check_region(card->iobase + PCI9050_USER_IO, 1)) + return (-1); /* ports already in use */ + + card->memend = card->membase + ERG_DPRAM_PAGE_SIZE - 1; + if (!(card->dpram = ioremap(card->membase, ERG_DPRAM_PAGE_SIZE))) + return (-1); + + request_region(card->iobase + PCI9050_INTR_REG, 1, "HYSDN"); + request_region(card->iobase + PCI9050_USER_IO, 1, "HYSDN"); + ergo_stopcard(card); /* disable interrupts */ + if (request_irq(card->irq, ergo_interrupt, SA_SHIRQ, "HYSDN", card)) { + ergo_releasehardware(card); /* return the acquired hardware */ + return (-1); + } + /* success, now setup the function pointers */ + card->stopcard = ergo_stopcard; + card->releasehardware = ergo_releasehardware; + card->testram = ergo_testram; + card->writebootimg = ergo_writebootimg; + card->writebootseq = ergo_writebootseq; + card->waitpofready = ergo_waitpofready; + card->set_errlog_state = ergo_set_errlog_state; + card->irq_queue.sync = 0; + card->irq_queue.data = card; /* init task queue for interrupt */ + card->irq_queue.routine = (void *) (void *) ergo_irq_bh; + + return (0); +} /* ergo_inithardware */ diff --git a/drivers/isdn/hysdn/boardergo.h b/drivers/isdn/hysdn/boardergo.h new file mode 100644 index 000000000000..ea3c744b4a22 --- /dev/null +++ b/drivers/isdn/hysdn/boardergo.h @@ -0,0 +1,112 @@ +/* $Id: boardergo.h,v 1.2 2000/11/13 22:51:47 kai Exp $ + + * Linux driver for HYSDN cards, definitions for ergo type boards (buffers..). + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +/************************************************/ +/* defines for the dual port memory of the card */ +/************************************************/ +#define ERG_DPRAM_PAGE_SIZE 0x2000 /* DPRAM occupies a 8K page */ +#define BOOT_IMG_SIZE 4096 +#define ERG_DPRAM_FILL_SIZE (ERG_DPRAM_PAGE_SIZE - BOOT_IMG_SIZE) + +#define ERG_TO_HY_BUF_SIZE 0x0E00 /* 3072 bytes buffer size to card */ +#define ERG_TO_PC_BUF_SIZE 0x0E00 /* 3072 bytes to PC, too */ + +/* following DPRAM layout copied from OS2-driver boarderg.h */ +typedef struct ErgDpram_tag { +/*0000 */ uchar ToHyBuf[ERG_TO_HY_BUF_SIZE]; +/*0E00 */ uchar ToPcBuf[ERG_TO_PC_BUF_SIZE]; + + /*1C00 */ uchar bSoftUart[SIZE_RSV_SOFT_UART]; + /* size 0x1B0 */ + + /*1DB0 *//* tErrLogEntry */ uchar volatile ErrLogMsg[64]; + /* size 64 bytes */ + /*1DB0 ulong ulErrType; */ + /*1DB4 ulong ulErrSubtype; */ + /*1DB8 ulong ucTextSize; */ + /*1DB9 ulong ucText[ERRLOG_TEXT_SIZE]; *//* ASCIIZ of len ucTextSize-1 */ + /*1DF0 */ + +/*1DF0 */ word volatile ToHyChannel; +/*1DF2 */ word volatile ToHySize; + /*1DF4 */ uchar volatile ToHyFlag; + /* !=0: msg for Hy waiting */ + /*1DF5 */ uchar volatile ToPcFlag; + /* !=0: msg for PC waiting */ +/*1DF6 */ word volatile ToPcChannel; +/*1DF8 */ word volatile ToPcSize; + /*1DFA */ uchar bRes1DBA[0x1E00 - 0x1DFA]; + /* 6 bytes */ + +/*1E00 */ uchar bRestOfEntryTbl[0x1F00 - 0x1E00]; +/*1F00 */ ulong TrapTable[62]; + /*1FF8 */ uchar bRes1FF8[0x1FFB - 0x1FF8]; + /* low part of reset vetor */ +/*1FFB */ uchar ToPcIntMetro; + /* notes: + * - metro has 32-bit boot ram - accessing + * ToPcInt and ToHyInt would be the same; + * so we moved ToPcInt to 1FFB. + * Because on the PC side both vars are + * readonly (reseting on int from E1 to PC), + * we can read both vars on both cards + * without destroying anything. + * - 1FFB is the high byte of the reset vector, + * so E1 side should NOT change this byte + * when writing! + */ +/*1FFC */ uchar volatile ToHyNoDpramErrLog; + /* note: ToHyNoDpramErrLog is used to inform + * boot loader, not to use DPRAM based + * ErrLog; when DOS driver is rewritten + * this becomes obsolete + */ +/*1FFD */ uchar bRes1FFD; + /*1FFE */ uchar ToPcInt; + /* E1_intclear; on CHAMP2: E1_intset */ + /*1FFF */ uchar ToHyInt; + /* E1_intset; on CHAMP2: E1_intclear */ +} tErgDpram; + +/**********************************************/ +/* PCI9050 controller local register offsets: */ +/* copied from boarderg.c */ +/**********************************************/ +#define PCI9050_INTR_REG 0x4C /* Interrupt register */ +#define PCI9050_USER_IO 0x51 /* User I/O register */ + + /* bitmask for PCI9050_INTR_REG: */ +#define PCI9050_INTR_REG_EN1 0x01 /* 1= enable (def.), 0= disable */ +#define PCI9050_INTR_REG_POL1 0x02 /* 1= active high (def.), 0= active low */ +#define PCI9050_INTR_REG_STAT1 0x04 /* 1= intr. active, 0= intr. not active (def.) */ +#define PCI9050_INTR_REG_ENPCI 0x40 /* 1= PCI interrupts enable (def.) */ + + /* bitmask for PCI9050_USER_IO: */ +#define PCI9050_USER_IO_EN3 0x02 /* 1= disable , 0= enable (def.) */ +#define PCI9050_USER_IO_DIR3 0x04 /* 1= output (def.), 0= input */ +#define PCI9050_USER_IO_DAT3 0x08 /* 1= high (def.) , 0= low */ + +#define PCI9050_E1_RESET ( PCI9050_USER_IO_DIR3) /* 0x04 */ +#define PCI9050_E1_RUN (PCI9050_USER_IO_DAT3|PCI9050_USER_IO_DIR3) /* 0x0C */ diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c new file mode 100644 index 000000000000..ddc00823f0d5 --- /dev/null +++ b/drivers/isdn/hysdn/hycapi.c @@ -0,0 +1,839 @@ +/* $Id: hycapi.c,v 1.8 2000/11/22 17:13:13 kai Exp $ + * + * Linux driver for HYSDN cards, CAPI2.0-Interface. + * written by Ulrich Albrecht (u.albrecht@hypercope.de) for Hypercope GmbH + * + * Copyright 2000 by Hypercope GmbH + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define __NO_VERSION__ +#include +#include +#include +#include +#include + + +#define VER_DRIVER 0 +#define VER_CARDTYPE 1 +#define VER_HWID 2 +#define VER_SERIAL 3 +#define VER_OPTION 4 +#define VER_PROTO 5 +#define VER_PROFILE 6 +#define VER_CAPI 7 + +#include "hysdn_defs.h" +#include + +static char hycapi_revision[]="$Revision: 1.8 $"; + +typedef struct _hycapi_appl { + unsigned int ctrl_mask; + capi_register_params rp; + struct sk_buff *listen_req[CAPI_MAXCONTR]; +} hycapi_appl; + +static hycapi_appl hycapi_applications[CAPI_MAXAPPL]; + +static inline int _hycapi_appCheck(int app_id, int ctrl_no) +{ + if((ctrl_no <= 0) || (ctrl_no > CAPI_MAXCONTR) || (app_id <= 0) || + (app_id > CAPI_MAXAPPL)) + { + printk(KERN_ERR "HYCAPI: Invalid request app_id %d for controller %d", app_id, ctrl_no); + return -1; + } + return ((hycapi_applications[app_id-1].ctrl_mask & (1 << (ctrl_no-1))) != 0); +} + +struct capi_driver_interface *hy_di = NULL; + +/****************************** +Kernel-Capi callback reset_ctr +******************************/ + +void +hycapi_reset_ctr(struct capi_ctr *ctrl) +{ +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n"); +#endif + ctrl->reseted(ctrl); +} + +/****************************** +Kernel-Capi callback remove_ctr +******************************/ + +void +hycapi_remove_ctr(struct capi_ctr *ctrl) +{ + int i; + hycapictrl_info *cinfo = NULL; + hysdn_card *card = NULL; +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "HYCAPI hycapi_remove_ctr\n"); +#endif + if(!hy_di) { + printk(KERN_ERR "No capi_driver_interface set!"); + return; + } + cinfo = (hycapictrl_info *)(ctrl->driverdata); + if(!cinfo) { + printk(KERN_ERR "No hycapictrl_info set!"); + return; + } + card = cinfo->card; + ctrl->suspend_output(ctrl); + for(i=0; icnr-1]) { + kfree_skb(hycapi_applications[i].listen_req[ctrl->cnr-1]); + hycapi_applications[i].listen_req[ctrl->cnr-1] = NULL; + } + } + hy_di->detach_ctr(ctrl); + ctrl->driverdata = 0; + kfree(card->hyctrlinfo); + + + card->hyctrlinfo = NULL; +} + +/*********************************************************** + +Queue a CAPI-message to the controller. + +***********************************************************/ + +static void +hycapi_sendmsg_internal(struct capi_ctr *ctrl, struct sk_buff *skb) +{ + hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); + hysdn_card *card = cinfo->card; + + spin_lock_irq(&cinfo->lock); +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_send_message\n"); +#endif + cinfo->skbs[cinfo->in_idx++] = skb; /* add to buffer list */ + if (cinfo->in_idx >= HYSDN_MAX_CAPI_SKB) + cinfo->in_idx = 0; /* wrap around */ + cinfo->sk_count++; /* adjust counter */ + if (cinfo->sk_count >= HYSDN_MAX_CAPI_SKB) { + /* inform upper layers we're full */ + printk(KERN_ERR "HYSDN Card%d: CAPI-buffer overrun!\n", + card->myid); + ctrl->suspend_output(ctrl); + } + cinfo->tx_skb = skb; + spin_unlock_irq(&cinfo->lock); + queue_task(&card->irq_queue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/*********************************************************** +hycapi_register_internal + +Send down the CAPI_REGISTER-Command to the controller. +This functions will also be used if the adapter has been rebooted to +re-register any applications in the private list. + +************************************************************/ + +static void +hycapi_register_internal(struct capi_ctr *ctrl, __u16 appl, + capi_register_params *rp) +{ + char ExtFeatureDefaults[] = "49 /0/0/0/0,*/1,*/2,*/3,*/4,*/5,*/6,*/7,*/8,*/9,*"; + hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); + hysdn_card *card = cinfo->card; + struct sk_buff *skb; + __u16 len; + __u8 _command = 0xa0, _subcommand = 0x80; + __u16 MessageNumber = 0x0000; + __u16 MessageBufferSize = 0; + int slen = strlen(ExtFeatureDefaults); +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_register_appl\n"); +#endif + MessageBufferSize = rp->level3cnt * rp->datablkcnt * rp->datablklen; + + len = CAPI_MSG_BASELEN + 8 + slen + 1; + if (!(skb = alloc_skb(len, GFP_ATOMIC))) { + printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n", + card->myid); + return; + } + memcpy(skb_put(skb,sizeof(__u16)), &len, sizeof(__u16)); + memcpy(skb_put(skb,sizeof(__u16)), &appl, sizeof(__u16)); + memcpy(skb_put(skb,sizeof(__u8)), &_command, sizeof(_command)); + memcpy(skb_put(skb,sizeof(__u8)), &_subcommand, sizeof(_subcommand)); + memcpy(skb_put(skb,sizeof(__u16)), &MessageNumber, sizeof(__u16)); + memcpy(skb_put(skb,sizeof(__u16)), &MessageBufferSize, sizeof(__u16)); + memcpy(skb_put(skb,sizeof(__u16)), &(rp->level3cnt), sizeof(__u16)); + memcpy(skb_put(skb,sizeof(__u16)), &(rp->datablkcnt), sizeof(__u16)); + memcpy(skb_put(skb,sizeof(__u16)), &(rp->datablklen), sizeof(__u16)); + memcpy(skb_put(skb,slen), ExtFeatureDefaults, slen); + hycapi_applications[appl-1].ctrl_mask |= (1 << (ctrl->cnr-1)); + hycapi_send_message(ctrl, skb); +} + +/************************************************************ +hycapi_restart_internal + +After an adapter has been rebootet, re-register all applications and +send a LISTEN_REQ (if there has been such a thing ) + +*************************************************************/ + +static void hycapi_restart_internal(struct capi_ctr *ctrl) +{ + int i; + struct sk_buff *skb; +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_WARNING "HYSDN: hycapi_restart_internal"); +#endif + for(i=0; icnr) == 1) { + hycapi_register_internal(ctrl, i+1, + &hycapi_applications[i].rp); + if(hycapi_applications[i].listen_req[ctrl->cnr-1]) { + skb = skb_copy(hycapi_applications[i].listen_req[ctrl->cnr-1], GFP_ATOMIC); + hycapi_sendmsg_internal(ctrl, skb); + } + } + } +} + +/************************************************************* +Register an application. +Error-checking is done for CAPI-compliance. + +The application is recorded in the internal list. +*************************************************************/ + +void +hycapi_register_appl(struct capi_ctr *ctrl, __u16 appl, + capi_register_params *rp) +{ + int MaxLogicalConnections = 0, MaxBDataBlocks = 0, MaxBDataLen = 0; + hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); + hysdn_card *card = cinfo->card; + int chk = _hycapi_appCheck(appl, ctrl->cnr); + if(chk < 0) { + return; + } + if(chk == 1) { + printk(KERN_INFO "HYSDN: apl %d allready registered\n", appl); + return; + } + MaxBDataBlocks = rp->datablkcnt > CAPI_MAXDATAWINDOW ? CAPI_MAXDATAWINDOW : rp->datablkcnt; + rp->datablkcnt = MaxBDataBlocks; + MaxBDataLen = rp->datablklen < 1024 ? 1024 : rp->datablklen ; + rp->datablklen = MaxBDataLen; + + MaxLogicalConnections = rp->level3cnt; + if (MaxLogicalConnections < 0) { + MaxLogicalConnections = card->bchans * -MaxLogicalConnections; + } + if (MaxLogicalConnections == 0) { + MaxLogicalConnections = card->bchans; + } + + rp->level3cnt = MaxLogicalConnections; + memcpy(&hycapi_applications[appl-1].rp, + rp, sizeof(capi_register_params)); + +/* MOD_INC_USE_COUNT; */ + ctrl->appl_registered(ctrl, appl); +} + +/********************************************************************* + +hycapi_release_internal + +Send down a CAPI_RELEASE to the controller. +*********************************************************************/ + +static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl) +{ + hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); + hysdn_card *card = cinfo->card; + struct sk_buff *skb; + __u16 len; + __u8 _command = 0xa1, _subcommand = 0x80; + __u16 MessageNumber = 0x0000; +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_release_appl\n"); +#endif + len = CAPI_MSG_BASELEN; + if (!(skb = alloc_skb(len, GFP_ATOMIC))) { + printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n", + card->myid); + return; + } + memcpy(skb_put(skb,sizeof(__u16)), &len, sizeof(__u16)); + memcpy(skb_put(skb,sizeof(__u16)), &appl, sizeof(__u16)); + memcpy(skb_put(skb,sizeof(__u8)), &_command, sizeof(_command)); + memcpy(skb_put(skb,sizeof(__u8)), &_subcommand, sizeof(_subcommand)); + memcpy(skb_put(skb,sizeof(__u16)), &MessageNumber, sizeof(__u16)); + hycapi_send_message(ctrl, skb); + hycapi_applications[appl-1].ctrl_mask &= ~(1 << (ctrl->cnr-1)); +} + +/****************************************************************** +hycapi_release_appl + +Release the application from the internal list an remove it's +registration at controller-level +******************************************************************/ + +void +hycapi_release_appl(struct capi_ctr *ctrl, __u16 appl) +{ + int chk; + + chk = _hycapi_appCheck(appl, ctrl->cnr); + if(chk<0) { + printk(KERN_ERR "HYCAPI: Releasing invalid appl %d on controller %d\n", appl, ctrl->cnr); + return; + } + if(hycapi_applications[appl-1].listen_req[ctrl->cnr-1]) { + kfree_skb(hycapi_applications[appl-1].listen_req[ctrl->cnr-1]); + hycapi_applications[appl-1].listen_req[ctrl->cnr-1] = NULL; + } + if(chk == 1) + { + hycapi_release_internal(ctrl, appl); + } + ctrl->appl_released(ctrl, appl); +/* MOD_DEC_USE_COUNT; */ +} + + +/************************************************************** +Kill a single controller. +**************************************************************/ + +int hycapi_capi_release(hysdn_card *card) +{ + hycapictrl_info *cinfo = card->hyctrlinfo; + struct capi_ctr *ctrl; +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_capi_release\n"); +#endif + if(cinfo) { + ctrl = cinfo->capi_ctrl; + hycapi_remove_ctr(ctrl); + } + return 0; +} + +/************************************************************** +hycapi_capi_stop + +Stop CAPI-Output on a card. (e.g. during reboot) +***************************************************************/ + +int hycapi_capi_stop(hysdn_card *card) +{ + hycapictrl_info *cinfo = card->hyctrlinfo; + struct capi_ctr *ctrl; +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_capi_stop\n"); +#endif + if(cinfo) { + if(cinfo->capi_ctrl) { + ctrl = cinfo->capi_ctrl; +/* ctrl->suspend_output(ctrl); */ + ctrl->reseted(ctrl); + + } else { + printk(KERN_NOTICE "hycapi_capi_stop: cinfo but no capi_ctrl\n"); + } + } + return 0; +} + +/*************************************************************** +hycapi_send_message + +Send a message to the controller. + +Messages are parsed for their Command/Subcommand-type, and appropriate +action's are performed. + +Note that we have to muck around with a 64Bit-DATA_REQ as there are +firmware-releases that do not check the MsgLen-Indication! + +***************************************************************/ + +void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) +{ + __u16 appl_id; + int _len, _len2; + __u8 msghead[64]; + + appl_id = CAPIMSG_APPID(skb->data); + switch(_hycapi_appCheck(appl_id, ctrl->cnr)) + { + case 0: +/* printk(KERN_INFO "Need to register\n"); */ + hycapi_register_internal(ctrl, + appl_id, + &(hycapi_applications[appl_id-1].rp)); + break; + case 1: + break; + default: + printk(KERN_ERR "HYCAPI: Controller mixup!\n"); + return; + } + switch(CAPIMSG_CMD(skb->data)) { + case CAPI_DISCONNECT_B3_RESP: + ctrl->free_ncci(ctrl, appl_id, + CAPIMSG_NCCI(skb->data)); + break; + case CAPI_DATA_B3_REQ: + _len = CAPIMSG_LEN(skb->data); + if (_len > 22) { + _len2 = _len - 22; + memcpy(msghead, skb->data, 22); + memcpy(skb->data + _len2, msghead, 22); + skb_pull(skb, _len2); + CAPIMSG_SETLEN(skb->data, 22); + } + break; + case CAPI_LISTEN_REQ: + if(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1]) + { + kfree_skb(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1]); + hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1] = NULL; + } + if (!(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1] = skb_copy(skb, GFP_ATOMIC))) + { + printk(KERN_ERR "HYSDN: memory squeeze in private_listen\n"); + } + break; + default: + break; + } + hycapi_sendmsg_internal(ctrl, skb); +} + +/********************************************************************* +hycapi_read_proc + +Informations provided in the /proc/capi-entries. + +*********************************************************************/ + +int hycapi_read_proc(char *page, char **start, off_t off, + int count, int *eof, struct capi_ctr *ctrl) +{ + hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); + hysdn_card *card = cinfo->card; + int len = 0; + char *s; +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_read_proc\n"); +#endif + len += sprintf(page+len, "%-16s %s\n", "name", cinfo->cardname); + len += sprintf(page+len, "%-16s 0x%x\n", "io", card->iobase); + len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); + + switch (card->brdtype) { + case BD_PCCARD: s = "HYSDN Hycard"; break; + case BD_ERGO: s = "HYSDN Ergo2"; break; + case BD_METRO: s = "HYSDN Metro4"; break; + case BD_CHAMP2: s = "HYSDN Champ2"; break; + case BD_PLEXUS: s = "HYSDN Plexus30"; break; + default: s = "???"; break; + } + len += sprintf(page+len, "%-16s %s\n", "type", s); + if ((s = cinfo->version[VER_DRIVER]) != 0) + len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + if ((s = cinfo->version[VER_CARDTYPE]) != 0) + len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + if ((s = cinfo->version[VER_SERIAL]) != 0) + len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + + len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); + + if (off+count >= len) + *eof = 1; + if (len < off) + return 0; + *start = page + off; + return ((count < len-off) ? count : len-off); +} + +/************************************************************** +hycapi_load_firmware + +This does NOT load any firmware, but the callback somehow is needed +on capi-interface registration. + +**************************************************************/ + +int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) +{ +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_load_firmware\n"); +#endif + return 0; +} + + +char *hycapi_procinfo(struct capi_ctr *ctrl) +{ + hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_proc_info\n"); +#endif + if (!cinfo) + return ""; + sprintf(cinfo->infobuf, "%s %s 0x%x %d %s", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->iobase : 0x0, + cinfo->card ? cinfo->card->irq : 0, + hycapi_revision + ); + return cinfo->infobuf; +} + +/****************************************************************** +hycapi_rx_capipkt + +Recieve a capi-message. + +All B3_DATA_IND are converted to 64K-extension compatible format. +New nccis are created if neccessary. +*******************************************************************/ + +void +hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len) +{ + struct sk_buff *skb; + hycapictrl_info *cinfo = card->hyctrlinfo; + struct capi_ctr *ctrl; + __u16 ApplId; + __u16 MsgLen, info; + __u16 len2, CapiCmd; + __u32 CP64[2] = {0,0}; +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_rx_capipkt\n"); +#endif + if(!cinfo) { + printk(KERN_ERR "HYSDN Card%d: no HYCAPI-controller!\n", + card->myid); + return; + } + ctrl = cinfo->capi_ctrl; + if(!ctrl) + { + printk(KERN_ERR "HYSDN Card%d: no CAPI-controller (1)!\n", + card->myid); + return; + } + if(len < CAPI_MSG_BASELEN) { + printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, lenght %d!\n", + card->myid, len); + return; + } + MsgLen = CAPIMSG_LEN(buf); + ApplId = CAPIMSG_APPID(buf); + CapiCmd = CAPIMSG_CMD(buf); + + if((CapiCmd == CAPI_DATA_B3_IND) && (MsgLen < 30)) { + len2 = len + (30 - MsgLen); + if (!(skb = alloc_skb(len2, GFP_ATOMIC))) { + printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n", + card->myid); + return; + } + memcpy(skb_put(skb, MsgLen), buf, MsgLen); + memcpy(skb_put(skb, 2*sizeof(__u32)), CP64, 2* sizeof(__u32)); + memcpy(skb_put(skb, len - MsgLen), buf + MsgLen, + len - MsgLen); + CAPIMSG_SETLEN(skb->data, 30); + } else { + if (!(skb = alloc_skb(len, GFP_ATOMIC))) { + printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n", + card->myid); + return; + } + memcpy(skb_put(skb, len), buf, len); + } + switch(CAPIMSG_CMD(skb->data)) + { + case CAPI_CONNECT_B3_CONF: +/* Check info-field for error-indication: */ + info = CAPIMSG_U16(skb->data, 12); + switch(info) + { + case 0: + ctrl->new_ncci(ctrl, ApplId, CAPIMSG_NCCI(skb->data), + hycapi_applications[ApplId-1].rp.datablkcnt); + + break; + case 0x0001: + printk(KERN_ERR "HYSDN Card%d: NCPI not supported by current " + "protocol. NCPI ignored.\n", card->myid); + break; + case 0x2001: + printk(KERN_ERR "HYSDN Card%d: Message not supported in" + " current state\n", card->myid); + break; + case 0x2002: + printk(KERN_ERR "HYSDN Card%d: illegal PLCI\n", card->myid); + break; + case 0x2004: + printk(KERN_ERR "HYSDN Card%d: out of NCCI\n", card->myid); + break; + case 0x3008: + printk(KERN_ERR "HYSDN Card%d: NCPI not supported\n", + card->myid); + break; + default: + printk(KERN_ERR "HYSDN Card%d: Info in CONNECT_B3_CONF: %d\n", + card->myid, info); + break; + } + break; + case CAPI_CONNECT_B3_IND: + ctrl->new_ncci(ctrl, ApplId, + CAPIMSG_NCCI(skb->data), + hycapi_applications[ApplId-1].rp.datablkcnt); + break; + default: + break; + } + ctrl->handle_capimsg(ctrl, ApplId, skb); +} + +/****************************************************************** +hycapi_tx_capiack + +Internally acknowledge a msg sent. This will remove the msg from the +internal queue. + +*******************************************************************/ + +void hycapi_tx_capiack(hysdn_card * card) +{ + hycapictrl_info *cinfo = card->hyctrlinfo; +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_tx_capiack\n"); +#endif + if(!cinfo) { + printk(KERN_ERR "HYSDN Card%d: no CAPI-controller (2)!\n", + card->myid); + return; + } + spin_lock_irq(&cinfo->lock); + kfree_skb(cinfo->skbs[cinfo->out_idx]); /* free skb */ + cinfo->skbs[cinfo->out_idx++] = NULL; + if (cinfo->out_idx >= HYSDN_MAX_CAPI_SKB) + cinfo->out_idx = 0; /* wrap around */ + + if (cinfo->sk_count-- == HYSDN_MAX_CAPI_SKB) /* dec usage count */ + cinfo->capi_ctrl->resume_output(cinfo->capi_ctrl); + spin_unlock_irq(&cinfo->lock); +} + +/*************************************************************** +hycapi_tx_capiget(hysdn_card *card) + +This is called when polling for messages to SEND. + +****************************************************************/ + +struct sk_buff * +hycapi_tx_capiget(hysdn_card *card) +{ + hycapictrl_info *cinfo = card->hyctrlinfo; + if(!cinfo) { + printk(KERN_ERR "HYSDN Card%d: no CAPI-controller! (3)\n", + card->myid); + return (struct sk_buff *)NULL; + } + if (!cinfo->sk_count) + return (struct sk_buff *)NULL; /* nothing available */ + + return (cinfo->skbs[cinfo->out_idx]); /* next packet to send */ +} + + +static struct capi_driver hycapi_driver = { + "hysdn", + "0.0", + hycapi_load_firmware, + hycapi_reset_ctr, + hycapi_remove_ctr, + hycapi_register_appl, + hycapi_release_appl, + hycapi_send_message, + hycapi_procinfo, + hycapi_read_proc, + 0, /* use standard driver_read_proc */ + 0, /* no add_card function */ +}; + + +/********************************************************** +int hycapi_init() + +attach the capi-driver to the kernel-capi. + +***********************************************************/ + +int hycapi_init() +{ + struct capi_driver *driver; + int i; + if(hy_di) { + printk(KERN_NOTICE "HyDI allready set\n"); + return 0; + } + driver = &hycapi_driver; + printk(KERN_NOTICE "HYSDN: Attaching capi-driver\n"); + hy_di = attach_capi_driver(driver); + if (!hy_di) { + printk(KERN_ERR "HYCAPI: failed to attach capi_driver\n"); + return(-1); + } + for(i=0;ihyctrlinfo; + if(!cinfo) return; + ctrl = cinfo->capi_ctrl; + if(!ctrl) return; + strcpy(ctrl->manu, "Hypercope"); + ctrl->version.majorversion = 2; + ctrl->version.minorversion = 0; + ctrl->version.majormanuversion = 3; + ctrl->version.minormanuversion = 2; + ctrl->profile.ncontroller = card->myid; + ctrl->profile.nbchannel = card->bchans; + ctrl->profile.goptions = GLOBAL_OPTION_INTERNAL_CONTROLLER | + GLOBAL_OPTION_B_CHANNEL_OPERATION; + ctrl->profile.support1 = B1_PROT_64KBIT_HDLC | + (card->faxchans ? B1_PROT_T30 : 0) | + B1_PROT_64KBIT_TRANSPARENT; + ctrl->profile.support2 = B2_PROT_ISO7776 | + (card->faxchans ? B2_PROT_T30 : 0) | + B2_PROT_TRANSPARENT; + ctrl->profile.support3 = B3_PROT_TRANSPARENT | + B3_PROT_T90NL | + (card->faxchans ? B3_PROT_T30 : 0) | + (card->faxchans ? B3_PROT_T30EXT : 0) | + B3_PROT_ISO8208; +} + +int +hycapi_capi_create(hysdn_card *card) +{ + hycapictrl_info *cinfo = NULL; + struct capi_ctr *ctrl = NULL; +#ifdef HYCAPI_PRINTFNAMES + printk(KERN_NOTICE "hycapi_capi_create\n"); +#endif + if (!card->hyctrlinfo) { + cinfo = (hycapictrl_info *) kmalloc(sizeof(hycapictrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n"); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(hycapictrl_info)); + card->hyctrlinfo = cinfo; + cinfo->card = card; + spin_lock_init(&cinfo->lock); + + switch (card->brdtype) { + case BD_PCCARD: strcpy(cinfo->cardname,"HYSDN Hycard"); break; + case BD_ERGO: strcpy(cinfo->cardname,"HYSDN Ergo2"); break; + case BD_METRO: strcpy(cinfo->cardname,"HYSDN Metro4"); break; + case BD_CHAMP2: strcpy(cinfo->cardname,"HYSDN Champ2"); break; + case BD_PLEXUS: strcpy(cinfo->cardname,"HYSDN Plexus30"); break; + default: strcpy(cinfo->cardname,"HYSDN ???"); break; + } + + cinfo->capi_ctrl = hy_di->attach_ctr(&hycapi_driver, + cinfo->cardname, cinfo); + ctrl = cinfo->capi_ctrl; + if (!ctrl) { + printk(KERN_ERR "%s: attach controller failed.\n", + hycapi_driver.name); + return -EBUSY; + } + /* fill in the blanks: */ + hycapi_fill_profile(card); + ctrl->ready(ctrl); + } else { + /* resume output on stopped ctrl */ + ctrl = card->hyctrlinfo->capi_ctrl; + if(ctrl) { + hycapi_fill_profile(card); + ctrl->ready(ctrl); + hycapi_restart_internal(ctrl); +/* ctrl->resume_output(ctrl); */ + } else { + printk(KERN_WARNING "HYSDN: No ctrl???? How come?\n"); + } + } + return 0; +} diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c new file mode 100644 index 000000000000..abab312ef04e --- /dev/null +++ b/drivers/isdn/hysdn/hysdn_boot.c @@ -0,0 +1,413 @@ +/* $Id: hysdn_boot.c,v 1.4.6.1 2001/02/10 14:41:22 kai Exp $ + + * Linux driver for HYSDN cards, specific routines for booting and pof handling. + * + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define __NO_VERSION__ +#include +#include +#include +#include +#include + +#include "hysdn_defs.h" +#include "hysdn_pof.h" + +/********************************/ +/* defines for pof read handler */ +/********************************/ +#define POF_READ_FILE_HEAD 0 +#define POF_READ_TAG_HEAD 1 +#define POF_READ_TAG_DATA 2 + +/************************************************************/ +/* definition of boot specific data area. This data is only */ +/* needed during boot and so allocated dynamically. */ +/************************************************************/ +struct boot_data { + word Cryptor; /* for use with Decrypt function */ + word Nrecs; /* records remaining in file */ + uchar pof_state; /* actual state of read handler */ + uchar is_crypted; /* card data is crypted */ + int BufSize; /* actual number of bytes bufferd */ + int last_error; /* last occured error */ + word pof_recid; /* actual pof recid */ + ulong pof_reclen; /* total length of pof record data */ + ulong pof_recoffset; /* actual offset inside pof record */ + union { + uchar BootBuf[BOOT_BUF_SIZE]; /* buffer as byte count */ + tPofRecHdr PofRecHdr; /* header for actual record/chunk */ + tPofFileHdr PofFileHdr; /* header from POF file */ + tPofTimeStamp PofTime; /* time information */ + } buf; +}; + +/*****************************************************/ +/* start decryption of sucessive POF file chuncks. */ +/* */ +/* to be called at start of POF file reading, */ +/* before starting any decryption on any POF record. */ +/*****************************************************/ +void +StartDecryption(struct boot_data *boot) +{ + boot->Cryptor = CRYPT_STARTTERM; +} /* StartDecryption */ + + +/***************************************************************/ +/* decrypt complete BootBuf */ +/* NOTE: decryption must be applied to all or none boot tags - */ +/* to HI and LO boot loader and (all) seq tags, because */ +/* global Cryptor is started for whole POF. */ +/***************************************************************/ +void +DecryptBuf(struct boot_data *boot, int cnt) +{ + uchar *bufp = boot->buf.BootBuf; + + while (cnt--) { + boot->Cryptor = (boot->Cryptor >> 1) ^ ((boot->Cryptor & 1U) ? CRYPT_FEEDTERM : 0); + *bufp++ ^= (uchar) boot->Cryptor; + } +} /* DecryptBuf */ + +/********************************************************************************/ +/* pof_handle_data executes the required actions dependant on the active record */ +/* id. If successfull 0 is returned, a negative value shows an error. */ +/********************************************************************************/ +static int +pof_handle_data(hysdn_card * card, int datlen) +{ + struct boot_data *boot = card->boot; /* pointer to boot specific data */ + long l; + uchar *imgp; + int img_len; + + /* handle the different record types */ + switch (boot->pof_recid) { + + case TAG_TIMESTMP: + if (card->debug_flags & LOG_POF_RECORD) + hysdn_addlog(card, "POF created %s", boot->buf.PofTime.DateTimeText); + break; + + case TAG_CBOOTDTA: + DecryptBuf(boot, datlen); /* we need to encrypt the buffer */ + case TAG_BOOTDTA: + if (card->debug_flags & LOG_POF_RECORD) + hysdn_addlog(card, "POF got %s len=%d offs=0x%lx", + (boot->pof_recid == TAG_CBOOTDTA) ? "CBOOTDATA" : "BOOTDTA", + datlen, boot->pof_recoffset); + + if (boot->pof_reclen != POF_BOOT_LOADER_TOTAL_SIZE) { + boot->last_error = EPOF_BAD_IMG_SIZE; /* invalid length */ + return (boot->last_error); + } + imgp = boot->buf.BootBuf; /* start of buffer */ + img_len = datlen; /* maximum length to transfer */ + + l = POF_BOOT_LOADER_OFF_IN_PAGE - + (boot->pof_recoffset & (POF_BOOT_LOADER_PAGE_SIZE - 1)); + if (l > 0) { + /* buffer needs to be truncated */ + imgp += l; /* advance pointer */ + img_len -= l; /* adjust len */ + } + /* at this point no special handling for data wrapping over buffer */ + /* is necessary, because the boot image always will be adjusted to */ + /* match a page boundary inside the buffer. */ + /* The buffer for the boot image on the card is filled in 2 cycles */ + /* first the 1024 hi-words are put in the buffer, then the low 1024 */ + /* word are handled in the same way with different offset. */ + + if (img_len > 0) { + /* data available for copy */ + if ((boot->last_error = + card->writebootimg(card, imgp, + (boot->pof_recoffset > POF_BOOT_LOADER_PAGE_SIZE) ? 2 : 0)) < 0) + return (boot->last_error); + } + break; /* end of case boot image hi/lo */ + + case TAG_CABSDATA: + DecryptBuf(boot, datlen); /* we need to encrypt the buffer */ + case TAG_ABSDATA: + if (card->debug_flags & LOG_POF_RECORD) + hysdn_addlog(card, "POF got %s len=%d offs=0x%lx", + (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA", + datlen, boot->pof_recoffset); + + if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen) < 0)) + return (boot->last_error); /* error writing data */ + + if (boot->pof_recoffset + datlen >= boot->pof_reclen) + return (card->waitpofready(card)); /* data completely spooled, wait for ready */ + + break; /* end of case boot seq data */ + + default: + if (card->debug_flags & LOG_POF_RECORD) + hysdn_addlog(card, "POF got data(id=0x%lx) len=%d offs=0x%lx", boot->pof_recid, + datlen, boot->pof_recoffset); + + break; /* simply skip record */ + } /* switch boot->pof_recid */ + + return (0); +} /* pof_handle_data */ + + +/******************************************************************************/ +/* pof_write_buffer is called when the buffer has been filled with the needed */ +/* number of data bytes. The number delivered is additionally supplied for */ +/* verification. The functions handles the data and returns the needed number */ +/* of bytes for the next action. If the returned value is 0 or less an error */ +/* occured and booting must be aborted. */ +/******************************************************************************/ +int +pof_write_buffer(hysdn_card * card, int datlen) +{ + struct boot_data *boot = card->boot; /* pointer to boot specific data */ + + if (!boot) + return (-EFAULT); /* invalid call */ + if (boot->last_error < 0) + return (boot->last_error); /* repeated error */ + + if (card->debug_flags & LOG_POF_WRITE) + hysdn_addlog(card, "POF write: got %d bytes ", datlen); + + switch (boot->pof_state) { + case POF_READ_FILE_HEAD: + if (card->debug_flags & LOG_POF_WRITE) + hysdn_addlog(card, "POF write: checking file header"); + + if (datlen != sizeof(tPofFileHdr)) { + boot->last_error = -EPOF_INTERNAL; + break; + } + if (boot->buf.PofFileHdr.Magic != TAGFILEMAGIC) { + boot->last_error = -EPOF_BAD_MAGIC; + break; + } + /* Setup the new state and vars */ + boot->Nrecs = (word) (boot->buf.PofFileHdr.N_PofRecs); /* limited to 65535 */ + boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ + boot->last_error = sizeof(tPofRecHdr); /* new length */ + break; + + case POF_READ_TAG_HEAD: + if (card->debug_flags & LOG_POF_WRITE) + hysdn_addlog(card, "POF write: checking tag header"); + + if (datlen != sizeof(tPofRecHdr)) { + boot->last_error = -EPOF_INTERNAL; + break; + } + boot->pof_recid = boot->buf.PofRecHdr.PofRecId; /* actual pof recid */ + boot->pof_reclen = boot->buf.PofRecHdr.PofRecDataLen; /* total length */ + boot->pof_recoffset = 0; /* no starting offset */ + + if (card->debug_flags & LOG_POF_RECORD) + hysdn_addlog(card, "POF: got record id=0x%lx length=%ld ", + boot->pof_recid, boot->pof_reclen); + + boot->pof_state = POF_READ_TAG_DATA; /* now start with tag data */ + if (boot->pof_reclen < BOOT_BUF_SIZE) + boot->last_error = boot->pof_reclen; /* limit size */ + else + boot->last_error = BOOT_BUF_SIZE; /* maximum */ + + if (!boot->last_error) { /* no data inside record */ + boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ + boot->last_error = sizeof(tPofRecHdr); /* new length */ + } + break; + + case POF_READ_TAG_DATA: + if (card->debug_flags & LOG_POF_WRITE) + hysdn_addlog(card, "POF write: getting tag data"); + + if (datlen != boot->last_error) { + boot->last_error = -EPOF_INTERNAL; + break; + } + if ((boot->last_error = pof_handle_data(card, datlen)) < 0) + return (boot->last_error); /* an error occured */ + boot->pof_recoffset += datlen; + if (boot->pof_recoffset >= boot->pof_reclen) { + boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ + boot->last_error = sizeof(tPofRecHdr); /* new length */ + } else { + if (boot->pof_reclen - boot->pof_recoffset < BOOT_BUF_SIZE) + boot->last_error = boot->pof_reclen - boot->pof_recoffset; /* limit size */ + else + boot->last_error = BOOT_BUF_SIZE; /* maximum */ + } + break; + + default: + boot->last_error = -EPOF_INTERNAL; /* unknown state */ + break; + } /* switch (boot->pof_state) */ + + return (boot->last_error); +} /* pof_write_buffer */ + + +/*******************************************************************************/ +/* pof_write_open is called when an open for boot on the cardlog device occurs. */ +/* The function returns the needed number of bytes for the next operation. If */ +/* the returned number is less or equal 0 an error specified by this code */ +/* occurred. Additionally the pointer to the buffer data area is set on success */ +/*******************************************************************************/ +int +pof_write_open(hysdn_card * card, uchar ** bufp) +{ + struct boot_data *boot; /* pointer to boot specific data */ + + if (card->boot) { + if (card->debug_flags & LOG_POF_OPEN) + hysdn_addlog(card, "POF open: already opened for boot"); + return (-ERR_ALREADY_BOOT); /* boot already active */ + } + /* error no mem available */ + if (!(boot = kmalloc(sizeof(struct boot_data), GFP_KERNEL))) { + if (card->debug_flags & LOG_MEM_ERR) + hysdn_addlog(card, "POF open: unable to allocate mem"); + return (-EFAULT); + } + card->boot = boot; + card->state = CARD_STATE_BOOTING; + memset(boot, 0, sizeof(struct boot_data)); + + card->stopcard(card); /* first stop the card */ + if (card->testram(card)) { + if (card->debug_flags & LOG_POF_OPEN) + hysdn_addlog(card, "POF open: DPRAM test failure"); + boot->last_error = -ERR_BOARD_DPRAM; + card->state = CARD_STATE_BOOTERR; /* show boot error */ + return (boot->last_error); + } + boot->BufSize = 0; /* Buffer is empty */ + boot->pof_state = POF_READ_FILE_HEAD; /* read file header */ + StartDecryption(boot); /* if POF File should be encrypted */ + + if (card->debug_flags & LOG_POF_OPEN) + hysdn_addlog(card, "POF open: success"); + + *bufp = boot->buf.BootBuf; /* point to buffer */ + return (sizeof(tPofFileHdr)); +} /* pof_write_open */ + +/********************************************************************************/ +/* pof_write_close is called when an close of boot on the cardlog device occurs. */ +/* The return value must be 0 if everything has happened as desired. */ +/********************************************************************************/ +int +pof_write_close(hysdn_card * card) +{ + struct boot_data *boot = card->boot; /* pointer to boot specific data */ + + if (!boot) + return (-EFAULT); /* invalid call */ + + card->boot = NULL; /* no boot active */ + kfree(boot); + + if (card->state == CARD_STATE_RUN) + card->set_errlog_state(card, 1); /* activate error log */ + + if (card->debug_flags & LOG_POF_OPEN) + hysdn_addlog(card, "POF close: success"); + + return (0); +} /* pof_write_close */ + +/*********************************************************************************/ +/* EvalSysrTokData checks additional records delivered with the Sysready Message */ +/* when POF has been booted. A return value of 0 is used if no error occured. */ +/*********************************************************************************/ +int +EvalSysrTokData(hysdn_card * card, uchar * cp, int len) +{ + u_char *p; + u_char crc; + + if (card->debug_flags & LOG_POF_RECORD) + hysdn_addlog(card, "SysReady Token data length %d", len); + + if (len < 2) { + hysdn_addlog(card, "SysReady Token Data to short"); + return (1); + } + for (p = cp, crc = 0; p < (cp + len - 2); p++) + if ((crc & 0x80)) + crc = (((u_char) (crc << 1)) + 1) + *p; + else + crc = ((u_char) (crc << 1)) + *p; + crc = ~crc; + if (crc != *(cp + len - 1)) { + hysdn_addlog(card, "SysReady Token Data invalid CRC"); + return (1); + } + len--; /* dont check CRC byte */ + while (len > 0) { + + if (*cp == SYSR_TOK_END) + return (0); /* End of Token stream */ + + if (len < (*(cp + 1) + 2)) { + hysdn_addlog(card, "token 0x%x invalid length %d", *cp, *(cp + 1)); + return (1); + } + switch (*cp) { + case SYSR_TOK_B_CHAN: /* 1 */ + if (*(cp + 1) != 1) + return (1); /* length invalid */ + card->bchans = *(cp + 2); + break; + + case SYSR_TOK_FAX_CHAN: /* 2 */ + if (*(cp + 1) != 1) + return (1); /* length invalid */ + card->faxchans = *(cp + 2); + break; + + case SYSR_TOK_MAC_ADDR: /* 3 */ + if (*(cp + 1) != 6) + return (1); /* length invalid */ + memcpy(card->mac_addr, cp + 2, 6); + break; + + default: + hysdn_addlog(card, "unknown token 0x%02x length %d", *cp, *(cp + 1)); + break; + } + len -= (*(cp + 1) + 2); /* adjust len */ + cp += (*(cp + 1) + 2); /* and pointer */ + } + + hysdn_addlog(card, "no end token found"); + return (1); +} /* EvalSysrTokData */ diff --git a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h new file mode 100644 index 000000000000..1b379554e4ca --- /dev/null +++ b/drivers/isdn/hysdn/hysdn_defs.h @@ -0,0 +1,307 @@ +/* $Id: hysdn_defs.h,v 1.5.6.1 2000/11/28 12:02:47 kai Exp $ + + * Linux driver for HYSDN cards, global definitions and exported vars and functions. + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef HYSDN_DEFS_H +#define HYSDN_DEFS_H + +#include +#include +#include +#include +#include +#include + +/****************************/ +/* storage type definitions */ +/****************************/ +#define uchar unsigned char +#define uint unsigned int +#define ulong unsigned long +#define word unsigned short + +#include "ince1pc.h" + +#ifdef CONFIG_HYSDN_CAPI +#include +#include "../avmb1/capicmd.h" +#include "../avmb1/capiutil.h" +#include "../avmb1/capilli.h" + +/***************************/ +/* CAPI-Profile values. */ +/***************************/ + +#define GLOBAL_OPTION_INTERNAL_CONTROLLER 0x0001 +#define GLOBAL_OPTION_EXTERNAL_CONTROLLER 0x0002 +#define GLOBAL_OPTION_HANDSET 0x0004 +#define GLOBAL_OPTION_DTMF 0x0008 +#define GLOBAL_OPTION_SUPPL_SERVICES 0x0010 +#define GLOBAL_OPTION_CHANNEL_ALLOCATION 0x0020 +#define GLOBAL_OPTION_B_CHANNEL_OPERATION 0x0040 + +#define B1_PROT_64KBIT_HDLC 0x0001 +#define B1_PROT_64KBIT_TRANSPARENT 0x0002 +#define B1_PROT_V110_ASYNCH 0x0004 +#define B1_PROT_V110_SYNCH 0x0008 +#define B1_PROT_T30 0x0010 +#define B1_PROT_64KBIT_INV_HDLC 0x0020 +#define B1_PROT_56KBIT_TRANSPARENT 0x0040 + +#define B2_PROT_ISO7776 0x0001 +#define B2_PROT_TRANSPARENT 0x0002 +#define B2_PROT_SDLC 0x0004 +#define B2_PROT_LAPD 0x0008 +#define B2_PROT_T30 0x0010 +#define B2_PROT_PPP 0x0020 +#define B2_PROT_TRANSPARENT_IGNORE_B1_FRAMING_ERRORS 0x0040 + +#define B3_PROT_TRANSPARENT 0x0001 +#define B3_PROT_T90NL 0x0002 +#define B3_PROT_ISO8208 0x0004 +#define B3_PROT_X25_DCE 0x0008 +#define B3_PROT_T30 0x0010 +#define B3_PROT_T30EXT 0x0020 + +#define HYSDN_MAXVERSION 8 + +/* Number of sendbuffers in CAPI-queue */ +#define HYSDN_MAX_CAPI_SKB 20 + +#endif /* CONFIG_HYSDN_CAPI*/ + +/************************************************/ +/* constants and bits for debugging/log outputs */ +/************************************************/ +#define LOG_MAX_LINELEN 120 +#define DEB_OUT_SYSLOG 0x80000000 /* output to syslog instead of proc fs */ +#define LOG_MEM_ERR 0x00000001 /* log memory errors like kmalloc failure */ +#define LOG_POF_OPEN 0x00000010 /* log pof open and close activities */ +#define LOG_POF_RECORD 0x00000020 /* log pof record parser */ +#define LOG_POF_WRITE 0x00000040 /* log detailed pof write operation */ +#define LOG_POF_CARD 0x00000080 /* log pof related card functions */ +#define LOG_CNF_LINE 0x00000100 /* all conf lines are put to procfs */ +#define LOG_CNF_DATA 0x00000200 /* non comment conf lines are shown with channel */ +#define LOG_CNF_MISC 0x00000400 /* additional conf line debug outputs */ +#define LOG_SCHED_ASYN 0x00001000 /* debug schedulers async tx routines */ +#define LOG_PROC_OPEN 0x00100000 /* open and close from procfs are logged */ +#define LOG_PROC_ALL 0x00200000 /* all actions from procfs are logged */ +#define LOG_NET_INIT 0x00010000 /* network init and deinit logging */ + +#define DEF_DEB_FLAGS 0x7fff000f /* everything is logged to procfs */ + +/**********************************/ +/* proc filesystem name constants */ +/**********************************/ +#define PROC_SUBDIR_NAME "hysdn" +#define PROC_CONF_BASENAME "cardconf" +#define PROC_LOG_BASENAME "cardlog" + +/***********************************/ +/* PCI 32 bit parms for IO and MEM */ +/***********************************/ +#define PCI_REG_PLX_MEM_BASE 0 +#define PCI_REG_PLX_IO_BASE 1 +#define PCI_REG_MEMORY_BASE 3 + +/**************/ +/* card types */ +/**************/ +#define BD_NONE 0U +#define BD_PERFORMANCE 1U +#define BD_VALUE 2U +#define BD_PCCARD 3U +#define BD_ERGO 4U +#define BD_METRO 5U +#define BD_CHAMP2 6U +#define BD_PLEXUS 7U + +/******************************************************/ +/* defined states for cards shown by reading cardconf */ +/******************************************************/ +#define CARD_STATE_UNUSED 0 /* never been used or booted */ +#define CARD_STATE_BOOTING 1 /* booting is in progress */ +#define CARD_STATE_BOOTERR 2 /* a previous boot was aborted */ +#define CARD_STATE_RUN 3 /* card is active */ + +/*******************************/ +/* defines for error_log_state */ +/*******************************/ +#define ERRLOG_STATE_OFF 0 /* error log is switched off, nothing to do */ +#define ERRLOG_STATE_ON 1 /* error log is switched on, wait for data */ +#define ERRLOG_STATE_START 2 /* start error logging */ +#define ERRLOG_STATE_STOP 3 /* stop error logging */ + +/*******************************/ +/* data structure for one card */ +/*******************************/ +typedef struct HYSDN_CARD { + + /* general variables for the cards */ + int myid; /* own driver card id */ + uchar bus; /* pci bus the card is connected to */ + uchar devfn; /* slot+function bit encoded */ + word subsysid; /* PCI subsystem id */ + uchar brdtype; /* type of card */ + uint bchans; /* number of available B-channels */ + uint faxchans; /* number of available fax-channels */ + uchar mac_addr[6]; /* MAC Address read from card */ + uint irq; /* interrupt number */ + uint iobase; /* IO-port base address */ + ulong plxbase; /* PLX memory base */ + ulong membase; /* DPRAM memory base */ + ulong memend; /* DPRAM memory end */ + void *dpram; /* mapped dpram */ + int state; /* actual state of card -> CARD_STATE_** */ + struct HYSDN_CARD *next; /* pointer to next card */ + + /* data areas for the /proc file system */ + void *proclog; /* pointer to proclog filesystem specific data */ + void *procconf; /* pointer to procconf filesystem specific data */ + + /* debugging and logging */ + uchar err_log_state; /* actual error log state of the card */ + ulong debug_flags; /* tells what should be debugged and where */ + void (*set_errlog_state) (struct HYSDN_CARD *, int); + + /* interrupt handler + interrupt synchronisation */ + struct tq_struct irq_queue; /* interrupt task queue */ + uchar volatile irq_enabled; /* interrupt enabled if != 0 */ + uchar volatile hw_lock; /* hardware is currently locked -> no access */ + + /* boot process */ + void *boot; /* pointer to boot private data */ + int (*writebootimg) (struct HYSDN_CARD *, uchar *, ulong); + int (*writebootseq) (struct HYSDN_CARD *, uchar *, int); + int (*waitpofready) (struct HYSDN_CARD *); + int (*testram) (struct HYSDN_CARD *); + + /* scheduler for data transfer (only async parts) */ + uchar async_data[256]; /* async data to be sent (normally for config) */ + word volatile async_len; /* length of data to sent */ + word volatile async_channel; /* channel number for async transfer */ + int volatile async_busy; /* flag != 0 sending in progress */ + int volatile net_tx_busy; /* a network packet tx is in progress */ + + /* network interface */ + void *netif; /* pointer to network structure */ + + /* init and deinit stopcard for booting, too */ + void (*stopcard) (struct HYSDN_CARD *); + void (*releasehardware) (struct HYSDN_CARD *); +#ifdef CONFIG_HYSDN_CAPI + struct hycapictrl_info { + char cardname[32]; + spinlock_t lock; + int versionlen; + char versionbuf[1024]; + char *version[HYSDN_MAXVERSION]; + + char infobuf[128]; /* for function procinfo */ + + struct HYSDN_CARD *card; + struct capi_ctr *capi_ctrl; + struct sk_buff *skbs[HYSDN_MAX_CAPI_SKB]; + int in_idx, out_idx; /* indexes to buffer ring */ + int sk_count; /* number of buffers currently in ring */ + struct sk_buff *tx_skb; /* buffer for tx operation */ + } *hyctrlinfo; +#endif /* CONFIG_HYSDN_CAPI */ +} hysdn_card; + +#ifdef CONFIG_HYSDN_CAPI +typedef struct hycapictrl_info hycapictrl_info; +#endif /* CONFIG_HYSDN_CAPI */ + + +/*****************/ +/* exported vars */ +/*****************/ +extern int cardmax; /* number of found cards */ +extern hysdn_card *card_root; /* pointer to first card */ + + + +/*************************/ +/* im/exported functions */ +/*************************/ +extern int printk(const char *fmt,...); +extern char *hysdn_getrev(const char *); + +/* hysdn_procconf.c */ +extern int hysdn_procconf_init(void); /* init proc config filesys */ +extern void hysdn_procconf_release(void); /* deinit proc config filesys */ + +/* hysdn_proclog.c */ +extern int hysdn_proclog_init(hysdn_card *); /* init proc log entry */ +extern void hysdn_proclog_release(hysdn_card *); /* deinit proc log entry */ +extern void put_log_buffer(hysdn_card *, char *); /* output log data */ +extern void hysdn_addlog(hysdn_card *, char *,...); /* output data to log */ +extern void hysdn_card_errlog(hysdn_card *, tErrLogEntry *, int); /* output card log */ + +/* boardergo.c */ +extern int ergo_inithardware(hysdn_card * card); /* get hardware -> module init */ + +/* hysdn_boot.c */ +extern int pof_write_close(hysdn_card *); /* close proc file after writing pof */ +extern int pof_write_open(hysdn_card *, uchar **); /* open proc file for writing pof */ +extern int pof_write_buffer(hysdn_card *, int); /* write boot data to card */ +extern int EvalSysrTokData(hysdn_card *, uchar *, int); /* Check Sysready Token Data */ + +/* hysdn_sched.c */ +extern int hysdn_sched_tx(hysdn_card *, uchar *, word volatile *, word volatile *, + word); +extern int hysdn_sched_rx(hysdn_card *, uchar *, word, word); +extern int hysdn_tx_cfgline(hysdn_card *, uchar *, word); /* send one cfg line */ + +/* hysdn_net.c */ +extern char *hysdn_net_revision; +extern int hysdn_net_create(hysdn_card *); /* create a new net device */ +extern int hysdn_net_release(hysdn_card *); /* delete the device */ +extern char *hysdn_net_getname(hysdn_card *); /* get name of net interface */ +extern void hysdn_tx_netack(hysdn_card *); /* acknowledge a packet tx */ +extern struct sk_buff *hysdn_tx_netget(hysdn_card *); /* get next network packet */ +extern void hysdn_rx_netpkt(hysdn_card *, uchar *, word); /* rxed packet from network */ + +#ifdef CONFIG_HYSDN_CAPI +extern struct capi_driver_interface *hy_di; +extern int hycapi_capi_create(hysdn_card *); /* create a new capi device */ +extern int hycapi_capi_release(hysdn_card *); /* delete the device */ +extern int hycapi_capi_stop(hysdn_card *card); /* suspend */ +extern int hycapi_load_firmware(struct capi_ctr *, capiloaddata *); +extern void hycapi_reset_ctr(struct capi_ctr *); +extern void hycapi_remove_ctr(struct capi_ctr *); +extern void hycapi_register_appl(struct capi_ctr *, __u16 appl, + capi_register_params *); +extern void hycapi_release_appl(struct capi_ctr *, __u16 appl); +extern void hycapi_send_message(struct capi_ctr *, struct sk_buff *skb); +extern char *hycapi_procinfo(struct capi_ctr *); +extern int hycapi_read_proc(char *page, char **start, off_t off, + int count, int *eof, struct capi_ctr *card); +extern void hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len); +extern void hycapi_tx_capiack(hysdn_card * card); +extern struct sk_buff *hycapi_tx_capiget(hysdn_card *card); +extern int hycapi_init(void); +extern void hycapi_cleanup(void); +#endif /* CONFIG_HYSDN_CAPI */ + +#endif /* HYSDN_DEFS_H */ diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c new file mode 100644 index 000000000000..25790f74d4cc --- /dev/null +++ b/drivers/isdn/hysdn/hysdn_init.c @@ -0,0 +1,257 @@ +/* $Id: hysdn_init.c,v 1.6.6.4 2001/02/10 14:41:22 kai Exp $ + + * Linux driver for HYSDN cards, init functions. + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hysdn_defs.h" + +static char *hysdn_init_revision = "$Revision: 1.6.6.4 $"; +int cardmax; /* number of found cards */ +hysdn_card *card_root = NULL; /* pointer to first card */ + +/**********************************************/ +/* table assigning PCI-sub ids to board types */ +/* the last entry contains all 0 */ +/**********************************************/ +static struct { + word subid; /* PCI sub id */ + uchar cardtyp; /* card type assigned */ +} pci_subid_map[] = { + + { + PCI_SUBDEVICE_ID_HYPERCOPE_METRO, BD_METRO + }, + { + PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, BD_CHAMP2 + }, + { + PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, BD_ERGO + }, + { + PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, BD_ERGO + }, + { + 0, 0 + } /* terminating entry */ +}; + + +/*********************************************************************/ +/* search_cards searches for available cards in the pci config data. */ +/* If a card is found, the card structure is allocated and the cards */ +/* ressources are reserved. cardmax is incremented. */ +/*********************************************************************/ +static void +search_cards(void) +{ + struct pci_dev *akt_pcidev = NULL; + hysdn_card *card, *card_last; + int i; + + card_root = NULL; + card_last = NULL; + while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, + akt_pcidev)) != NULL) { + if (pci_enable_device(akt_pcidev)) + continue; + + if (!(card = kmalloc(sizeof(hysdn_card), GFP_KERNEL))) { + printk(KERN_ERR "HYSDN: unable to alloc device mem \n"); + return; + } + memset(card, 0, sizeof(hysdn_card)); + card->myid = cardmax; /* set own id */ + card->bus = akt_pcidev->bus->number; + card->devfn = akt_pcidev->devfn; /* slot + function */ + pci_read_config_word(akt_pcidev, PCI_SUBSYSTEM_ID, &card->subsysid); + card->irq = akt_pcidev->irq; + card->iobase = akt_pcidev->base_address[ PCI_REG_PLX_IO_BASE] & PCI_BASE_ADDRESS_IO_MASK; + card->plxbase = akt_pcidev->base_address[ PCI_REG_PLX_MEM_BASE] & PCI_BASE_ADDRESS_MEM_MASK; + card->membase = akt_pcidev->base_address[ PCI_REG_MEMORY_BASE] & PCI_BASE_ADDRESS_MEM_MASK; + card->brdtype = BD_NONE; /* unknown */ + card->debug_flags = DEF_DEB_FLAGS; /* set default debug */ + card->faxchans = 0; /* default no fax channels */ + card->bchans = 2; /* and 2 b-channels */ + for (i = 0; pci_subid_map[i].subid; i++) + if (pci_subid_map[i].subid == card->subsysid) { + card->brdtype = pci_subid_map[i].cardtyp; + break; + } + if (card->brdtype != BD_NONE) { + if (ergo_inithardware(card)) { + printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase); + kfree(card); + continue; + } + } else { + printk(KERN_WARNING "HYSDN: unknown card id 0x%04x\n", card->subsysid); + kfree(card); /* release mem */ + continue; + } + cardmax++; + card->next = NULL; /*end of chain */ + if (card_last) + card_last->next = card; /* pointer to next card */ + else + card_root = card; + card_last = card; /* new chain end */ + } /* device found */ +} /* search_cards */ + +/************************************************************************************/ +/* free_resources frees the acquired PCI resources and returns the allocated memory */ +/************************************************************************************/ +static void +free_resources(void) +{ + hysdn_card *card; + + while (card_root) { + card = card_root; + if (card->releasehardware) + card->releasehardware(card); /* free all hardware resources */ + card_root = card_root->next; /* remove card from chain */ + kfree(card); /* return mem */ + + } /* while card_root */ +} /* free_resources */ + +/**************************************************************************/ +/* stop_cards disables (hardware resets) all cards and disables interrupt */ +/**************************************************************************/ +static void +stop_cards(void) +{ + hysdn_card *card; + + card = card_root; /* first in chain */ + while (card) { + if (card->stopcard) + card->stopcard(card); + card = card->next; /* remove card from chain */ + } /* while card */ +} /* stop_cards */ + + +/****************************************************************************/ +/* The module startup and shutdown code. Only compiled when used as module. */ +/* Using the driver as module is always advisable, because the booting */ +/* image becomes smaller and the driver code is only loaded when needed. */ +/* Additionally newer versions may be activated without rebooting. */ +/****************************************************************************/ + +/******************************************************/ +/* extract revision number from string for log output */ +/******************************************************/ +char * +hysdn_getrev(const char *revision) +{ + char *rev; + char *p; + + if ((p = strchr(revision, ':'))) { + rev = p + 2; + p = strchr(rev, '$'); + *--p = 0; + } else + rev = "???"; + return rev; +} + + +/****************************************************************************/ +/* init_module is called once when the module is loaded to do all necessary */ +/* things like autodetect... */ +/* If the return value of this function is 0 the init has been successfull */ +/* and the module is added to the list in /proc/modules, otherwise an error */ +/* is assumed and the module will not be kept in memory. */ +/****************************************************************************/ +static int __init +hysdn_init(void) +{ + char tmp[50]; + + strcpy(tmp, hysdn_init_revision); + printk(KERN_NOTICE "HYSDN: module Rev: %s loaded\n", hysdn_getrev(tmp)); + strcpy(tmp, hysdn_net_revision); + printk(KERN_NOTICE "HYSDN: network interface Rev: %s \n", hysdn_getrev(tmp)); + if (!pci_present()) { + printk(KERN_ERR "HYSDN: no PCI bus present, module not loaded\n"); + return (-1); + } + search_cards(); + printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax); + + if (hysdn_procconf_init()) { + free_resources(); /* proc file_sys not created */ + return (-1); + } +#ifdef CONFIG_HYSDN_CAPI + if(cardmax > 0) { + if(hycapi_init()) { + printk(KERN_ERR "HYCAPI: init failed\n"); + return(-1); + } + } +#endif /* CONFIG_HYSDN_CAPI */ + return (0); /* no error */ +} /* init_module */ + + +/***********************************************************************/ +/* cleanup_module is called when the module is released by the kernel. */ +/* The routine is only called if init_module has been successfull and */ +/* the module counter has a value of 0. Otherwise this function will */ +/* not be called. This function must release all resources still allo- */ +/* cated as after the return from this function the module code will */ +/* be removed from memory. */ +/***********************************************************************/ +static void +hysdn_exit(void) +{ +#ifdef CONFIG_HYSDN_CAPI + hysdn_card *card; +#endif /* CONFIG_HYSDN_CAPI */ + stop_cards(); +#ifdef CONFIG_HYSDN_CAPI + card = card_root; /* first in chain */ + while (card) { + hycapi_capi_release(card); + card = card->next; /* remove card from chain */ + } /* while card */ + hycapi_cleanup(); +#endif /* CONFIG_HYSDN_CAPI */ + hysdn_procconf_release(); + free_resources(); + printk(KERN_NOTICE "HYSDN: module unloaded\n"); +} /* cleanup_module */ + +module_init(hysdn_init); +module_exit(hysdn_exit); diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c new file mode 100644 index 000000000000..dc9c7af01ad4 --- /dev/null +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -0,0 +1,336 @@ +/* $Id: hysdn_net.c,v 1.8 2000/11/13 22:51:47 kai Exp $ + + * Linux driver for HYSDN cards, net (ethernet type) handling routines. + * + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * This net module has been inspired by the skeleton driver from + * Donald Becker (becker@CESDIS.gsfc.nasa.gov) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define __NO_VERSION__ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hysdn_defs.h" + +/* store the actual version for log reporting */ +char *hysdn_net_revision = "$Revision: 1.8 $"; + +#define MAX_SKB_BUFFERS 20 /* number of buffers for keeping TX-data */ + +/****************************************************************************/ +/* structure containing the complete network data. The structure is aligned */ +/* in a way that both, the device and statistics are kept inside it. */ +/* for proper access, the device structure MUST be the first var/struct */ +/* inside the definition. */ +/****************************************************************************/ +struct net_local { + struct device netdev; /* the network device */ + struct net_device_stats stats; + /* additional vars may be added here */ + char dev_name[9]; /* our own device name */ + + struct sk_buff *tx_skb; /* buffer for tx operation */ + +}; /* net_local */ + + +/*****************************************************/ +/* Get the current statistics for this card. */ +/* This may be called with the card open or closed ! */ +/*****************************************************/ +static struct net_device_stats * +net_get_stats(struct device *dev) +{ + return (&((struct net_local *) dev)->stats); +} /* net_device_stats */ + +/*********************************************************************/ +/* Open/initialize the board. This is called (in the current kernel) */ +/* sometime after booting when the 'ifconfig' program is run. */ +/* This routine should set everything up anew at each open, even */ +/* registers that "should" only need to be set once at boot, so that */ +/* there is non-reboot way to recover if something goes wrong. */ +/*********************************************************************/ +static int +net_open(struct device *dev) +{ + struct in_device *in_dev; + hysdn_card *card = dev->priv; + int i; + + dev->tbusy = 0; /* non busy state */ + dev->interrupt = 0; + if (!dev->start) + MOD_INC_USE_COUNT; /* increment only if device is down */ + dev->start = 1; /* and started */ + + /* Fill in the MAC-level header (if not already set) */ + if (!card->mac_addr[0]) { + for (i = 0; i < ETH_ALEN - sizeof(ulong); i++) + dev->dev_addr[i] = 0xfc; + if ((in_dev = dev->ip_ptr) != NULL) { + struct in_ifaddr *ifa = in_dev->ifa_list; + if (ifa != NULL) + memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ulong)), &ifa->ifa_local, sizeof(ulong)); + } + } else + memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN); + + return (0); +} /* net_open */ + + + +/*********************************************************************/ +/* close/decativate the device. The device is not removed, but only */ +/* deactivated. */ +/*********************************************************************/ +static int +net_close(struct device *dev) +{ + + dev->tbusy = 1; /* we are busy */ + + if (dev->start) + MOD_DEC_USE_COUNT; /* dec only if device has been active */ + + dev->start = 0; /* and not started */ + + return (0); /* success */ +} /* net_close */ + +/************************************/ +/* send a packet on this interface. */ +/* only for kernel versions < 2.3.33 */ +/************************************/ +static int +net_send_packet(struct sk_buff *skb, struct device *dev) +{ + struct net_local *lp = (struct net_local *) dev; + + if (dev->tbusy) { + /* + * If we get here, some higher level has decided we are broken. + * There should really be a "kick me" function call instead. + * As ISDN may have higher timeouts than real ethernet 10s timeout + */ + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < (10000 * HZ) / 1000) + return 1; + printk(KERN_WARNING "%s: transmit timed out. \n", dev->name); + dev->tbusy = 0; + dev->trans_start = jiffies; + } + /* + * Block a timer-based transmit from overlapping. This could better be + * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. + */ + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) + printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); + + else { + lp->stats.tx_bytes += skb->len; + dev->trans_start = jiffies; + lp->tx_skb = skb; /* remember skb pointer */ + queue_task(&((hysdn_card *) dev->priv)->irq_queue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } + + return (0); /* success */ +} /* net_send_packet */ + + + +/***********************************************************************/ +/* acknowlegde a packet send. The network layer will be informed about */ +/* completion */ +/***********************************************************************/ +void +hysdn_tx_netack(hysdn_card * card) +{ + struct net_local *lp = card->netif; + + if (!lp) + return; /* non existing device */ + + if (lp->tx_skb) + dev_kfree_skb(lp->tx_skb); /* free tx pointer */ + lp->tx_skb = NULL; /* reset pointer */ + + lp->stats.tx_packets++; + lp->netdev.tbusy = 0; + mark_bh(NET_BH); /* Inform upper layers. */ +} /* hysdn_tx_netack */ + +/*****************************************************/ +/* we got a packet from the network, go and queue it */ +/*****************************************************/ +void +hysdn_rx_netpkt(hysdn_card * card, uchar * buf, word len) +{ + struct net_local *lp = card->netif; + struct sk_buff *skb; + + if (!lp) + return; /* non existing device */ + + lp->stats.rx_bytes += len; + + skb = dev_alloc_skb(len); + if (skb == NULL) { + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", + lp->netdev.name); + lp->stats.rx_dropped++; + return; + } + skb->dev = &lp->netdev; + + /* copy the data */ + memcpy(skb_put(skb, len), buf, len); + + /* determine the used protocol */ + skb->protocol = eth_type_trans(skb, &lp->netdev); + + netif_rx(skb); + lp->stats.rx_packets++; /* adjust packet count */ + +} /* hysdn_rx_netpkt */ + +/*****************************************************/ +/* return the pointer to a network packet to be send */ +/*****************************************************/ +struct sk_buff * +hysdn_tx_netget(hysdn_card * card) +{ + struct net_local *lp = card->netif; + + if (!lp) + return (NULL); /* non existing device */ + + return (lp->tx_skb); /* return packet pointer */ + +} /* hysdn_tx_netget */ + + +/*******************************************/ +/* init function called by register device */ +/*******************************************/ +static int +net_init(struct device *dev) +{ + /* setup the function table */ + dev->open = net_open; + dev->stop = net_close; + dev->hard_start_xmit = net_send_packet; + dev->get_stats = net_get_stats; + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + + return (0); /* success */ +} /* net_init */ + +/*****************************************************************************/ +/* hysdn_net_create creates a new net device for the given card. If a device */ +/* already exists, it will be deleted and created a new one. The return value */ +/* 0 announces success, else a negative error code will be returned. */ +/*****************************************************************************/ +int +hysdn_net_create(hysdn_card * card) +{ + struct device *dev; + int i; + if(!card) { + printk(KERN_WARNING "No card-pt in hysdn_net_create!\n"); + return (-ENOMEM); + } + hysdn_net_release(card); /* release an existing net device */ + if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) { + printk(KERN_WARNING "HYSDN: unable to allocate mem\n"); + if (card->debug_flags & LOG_NET_INIT) + return (-ENOMEM); + } + memset(dev, 0, sizeof(struct net_local)); /* clean the structure */ + + + /* initialise necessary or informing fields */ + dev->base_addr = card->iobase; /* IO address */ + dev->irq = card->irq; /* irq */ + dev->init = net_init; /* the init function of the device */ + dev->name = ((struct net_local *) dev)->dev_name; /* device name */ + if ((i = register_netdev(dev))) { + printk(KERN_WARNING "HYSDN: unable to create network device\n"); + kfree(dev); + return (i); + } + dev->priv = card; /* remember pointer to own data structure */ + card->netif = dev; /* setup the local pointer */ + + if (card->debug_flags & LOG_NET_INIT) + hysdn_addlog(card, "network device created"); + return (0); /* and return success */ +} /* hysdn_net_create */ + +/***************************************************************************/ +/* hysdn_net_release deletes the net device for the given card. The return */ +/* value 0 announces success, else a negative error code will be returned. */ +/***************************************************************************/ +int +hysdn_net_release(hysdn_card * card) +{ + struct device *dev = card->netif; + + if (!dev) + return (0); /* non existing */ + + card->netif = NULL; /* clear out pointer */ + dev->stop(dev); /* close the device */ + + + unregister_netdev(dev); /* release the device */ + kfree(dev); /* release the memory allocated */ + if (card->debug_flags & LOG_NET_INIT) + hysdn_addlog(card, "network device deleted"); + + return (0); /* always successfull */ +} /* hysdn_net_release */ + +/*****************************************************************************/ +/* hysdn_net_getname returns a pointer to the name of the network interface. */ +/* if the interface is not existing, a "-" is returned. */ +/*****************************************************************************/ +char * +hysdn_net_getname(hysdn_card * card) +{ + struct device *dev = card->netif; + + if (!dev) + return ("-"); /* non existing */ + + return (dev->name); +} /* hysdn_net_getname */ diff --git a/drivers/isdn/hysdn/hysdn_pof.h b/drivers/isdn/hysdn/hysdn_pof.h new file mode 100644 index 000000000000..524b7a0ae9c5 --- /dev/null +++ b/drivers/isdn/hysdn/hysdn_pof.h @@ -0,0 +1,89 @@ +/* $Id: hysdn_pof.h,v 1.2 2000/11/13 22:51:47 kai Exp $ + + * Linux driver for HYSDN cards, definitions used for handling pof-files. + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/************************/ +/* POF specific defines */ +/************************/ +#define BOOT_BUF_SIZE 0x1000 /* =4096, maybe moved to other h file */ +#define CRYPT_FEEDTERM 0x8142 +#define CRYPT_STARTTERM 0x81a5 + /* max. timeout time in seconds + * from end of booting to POF is ready + */ +#define POF_READY_TIME_OUT_SEC 10 + +/**********************************/ +/* defines for 1.stage boot image */ +/**********************************/ + +/* the POF file record containing the boot loader image + * has 2 pages a 16KB: + * 1. page contains the high 16-bit part of the 32-bit E1 words + * 2. page contains the low 16-bit part of the 32-bit E1 words + * + * In each 16KB page we assume the start of the boot loader code + * in the highest 2KB part (at offset 0x3800); + * the rest (0x0000..0x37FF) is assumed to contain 0 bytes. + */ + +#define POF_BOOT_LOADER_PAGE_SIZE 0x4000 /* =16384U */ +#define POF_BOOT_LOADER_TOTAL_SIZE (2U*POF_BOOT_LOADER_PAGE_SIZE) + +#define POF_BOOT_LOADER_CODE_SIZE 0x0800 /* =2KB =2048U */ + + /* offset in boot page, where loader code may start */ + /* =0x3800= 14336U */ +#define POF_BOOT_LOADER_OFF_IN_PAGE (POF_BOOT_LOADER_PAGE_SIZE-POF_BOOT_LOADER_CODE_SIZE) + + +/*--------------------------------------POF file record structs------------*/ +typedef struct PofFileHdr_tag { /* Pof file header */ +/*00 */ ulong Magic __attribute__((packed)); +/*04 */ ulong N_PofRecs __attribute__((packed)); +/*08 */ +} tPofFileHdr; + +typedef struct PofRecHdr_tag { /* Pof record header */ +/*00 */ word PofRecId __attribute__((packed)); +/*02 */ ulong PofRecDataLen __attribute__((packed)); +/*06 */ +} tPofRecHdr; + +typedef struct PofTimeStamp_tag { +/*00 */ ulong UnixTime __attribute__((packed)); + /*04 */ uchar DateTimeText[0x28] __attribute__((packed)); + /* =40 */ +/*2C */ +} tPofTimeStamp; + + /* tPofFileHdr.Magic value: */ +#define TAGFILEMAGIC 0x464F501AUL + /* tPofRecHdr.PofRecId values: */ +#define TAG_ABSDATA 0x1000 /* abs. data */ +#define TAG_BOOTDTA 0x1001 /* boot data */ +#define TAG_COMMENT 0x0020 +#define TAG_SYSCALL 0x0021 +#define TAG_FLOWCTRL 0x0022 +#define TAG_TIMESTMP 0x0010 /* date/time stamp of version */ +#define TAG_CABSDATA 0x1100 /* crypted abs. data */ +#define TAG_CBOOTDTA 0x1101 /* crypted boot data */ diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c new file mode 100644 index 000000000000..6fb29ff09a1f --- /dev/null +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -0,0 +1,467 @@ +/* $Id: hysdn_procconf.c,v 1.8 2000/11/13 22:51:47 kai Exp $ + + * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions. + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define __NO_VERSION__ +#include +#include +#include +#include +#include + +#include "hysdn_defs.h" + +static char *hysdn_procconf_revision = "$Revision: 1.8 $"; + +#define INFO_OUT_LEN 80 /* length of info line including lf */ + +/********************************************************/ +/* defines and data structure for conf write operations */ +/********************************************************/ +#define CONF_STATE_DETECT 0 /* waiting for detect */ +#define CONF_STATE_CONF 1 /* writing config data */ +#define CONF_STATE_POF 2 /* writing pof data */ +#define CONF_LINE_LEN 80 /* 80 chars max */ + +struct conf_writedata { + hysdn_card *card; /* card the device is connected to */ + int buf_size; /* actual number of bytes in the buffer */ + int needed_size; /* needed size when reading pof */ + int state; /* actual interface states from above constants */ + uchar conf_line[CONF_LINE_LEN]; /* buffered conf line */ + word channel; /* active channel number */ + uchar *pof_buffer; /* buffer when writing pof */ +}; + +/***********************************************************************/ +/* process_line parses one config line and transfers it to the card if */ +/* necessary. */ +/* if the return value is negative an error occured. */ +/***********************************************************************/ +static int +process_line(struct conf_writedata *cnf) +{ + uchar *cp = cnf->conf_line; + int i; + + if (cnf->card->debug_flags & LOG_CNF_LINE) + hysdn_addlog(cnf->card, "conf line: %s", cp); + + if (*cp == '-') { /* option */ + cp++; /* point to option char */ + + if (*cp++ != 'c') + return (0); /* option unknown or used */ + i = 0; /* start value for channel */ + while ((*cp <= '9') && (*cp >= '0')) + i = i * 10 + *cp++ - '0'; /* get decimal number */ + if (i > 65535) { + if (cnf->card->debug_flags & LOG_CNF_MISC) + hysdn_addlog(cnf->card, "conf channel invalid %d", i); + return (-ERR_INV_CHAN); /* invalid channel */ + } + cnf->channel = i & 0xFFFF; /* set new channel number */ + return (0); /* success */ + } /* option */ + if (*cp == '*') { /* line to send */ + if (cnf->card->debug_flags & LOG_CNF_DATA) + hysdn_addlog(cnf->card, "conf chan=%d %s", cnf->channel, cp); + return (hysdn_tx_cfgline(cnf->card, cnf->conf_line + 1, + cnf->channel)); /* send the line without * */ + } /* line to send */ + return (0); +} /* process_line */ + +/*************************/ +/* dummy file operations */ +/*************************/ +static loff_t +hysdn_dummy_lseek(struct file *file, loff_t offset, int orig) +{ + return -ESPIPE; +} /* hysdn_dummy_lseek */ + +/***********************************/ +/* conf file operations and tables */ +/***********************************/ + +/****************************************************/ +/* write conf file -> boot or send cfg line to card */ +/****************************************************/ +static ssize_t +hysdn_conf_write(struct file *file, const char *buf, size_t count, loff_t * off) +{ + struct conf_writedata *cnf; + int i; + uchar ch, *cp; + + if (&file->f_pos != off) /* fs error check */ + return (-ESPIPE); + if (!count) + return (0); /* nothing to handle */ + + if (!(cnf = file->private_data)) + return (-EFAULT); /* should never happen */ + + if (cnf->state == CONF_STATE_DETECT) { /* auto detect cnf or pof data */ + if (copy_from_user(&ch, buf, 1)) /* get first char for detect */ + return (-EFAULT); + + if (ch == 0x1A) { + /* we detected a pof file */ + if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0) + return (cnf->needed_size); /* an error occured -> exit */ + cnf->buf_size = 0; /* buffer is empty */ + cnf->state = CONF_STATE_POF; /* new state */ + } else { + /* conf data has been detected */ + cnf->buf_size = 0; /* buffer is empty */ + cnf->state = CONF_STATE_CONF; /* requested conf data write */ + if (cnf->card->state != CARD_STATE_RUN) + return (-ERR_NOT_BOOTED); + cnf->conf_line[CONF_LINE_LEN - 1] = 0; /* limit string length */ + cnf->channel = 4098; /* default channel for output */ + } + } /* state was auto detect */ + if (cnf->state == CONF_STATE_POF) { /* pof write active */ + i = cnf->needed_size - cnf->buf_size; /* bytes still missing for write */ + if (i <= 0) + return (-EINVAL); /* size error handling pof */ + + if (i < count) + count = i; /* limit requested number of bytes */ + if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count)) + return (-EFAULT); /* error while copying */ + cnf->buf_size += count; + + if (cnf->needed_size == cnf->buf_size) { + cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size); /* write data */ + if (cnf->needed_size <= 0) { + cnf->card->state = CARD_STATE_BOOTERR; /* show boot error */ + return (cnf->needed_size); /* an error occured */ + } + cnf->buf_size = 0; /* buffer is empty again */ + } + } + /* pof write active */ + else { /* conf write active */ + + if (cnf->card->state != CARD_STATE_RUN) { + if (cnf->card->debug_flags & LOG_CNF_MISC) + hysdn_addlog(cnf->card, "cnf write denied -> not booted"); + return (-ERR_NOT_BOOTED); + } + i = (CONF_LINE_LEN - 1) - cnf->buf_size; /* bytes available in buffer */ + if (i > 0) { + /* copy remaining bytes into buffer */ + + if (count > i) + count = i; /* limit transfer */ + if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count)) + return (-EFAULT); /* error while copying */ + + i = count; /* number of chars in buffer */ + cp = cnf->conf_line + cnf->buf_size; + while (i) { + /* search for end of line */ + if ((*cp < ' ') && (*cp != 9)) + break; /* end of line found */ + cp++; + i--; + } /* search for end of line */ + + if (i) { + /* delimiter found */ + *cp++ = 0; /* string termination */ + count -= (i - 1); /* subtract remaining bytes from count */ + while ((i) && (*cp < ' ') && (*cp != 9)) { + i--; /* discard next char */ + count++; /* mark as read */ + cp++; /* next char */ + } + cnf->buf_size = 0; /* buffer is empty after transfer */ + if ((i = process_line(cnf)) < 0) /* handle the line */ + count = i; /* return the error */ + } + /* delimiter found */ + else { + cnf->buf_size += count; /* add chars to string */ + if (cnf->buf_size >= CONF_LINE_LEN - 1) { + if (cnf->card->debug_flags & LOG_CNF_MISC) + hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count); + return (-ERR_CONF_LONG); + } + } /* not delimited */ + + } + /* copy remaining bytes into buffer */ + else { + if (cnf->card->debug_flags & LOG_CNF_MISC) + hysdn_addlog(cnf->card, "cnf line too long"); + return (-ERR_CONF_LONG); + } + } /* conf write active */ + + return (count); +} /* hysdn_conf_write */ + +/*******************************************/ +/* read conf file -> output card info data */ +/*******************************************/ +static ssize_t +hysdn_conf_read(struct file *file, char *buf, size_t count, loff_t * off) +{ + char *cp; + int i; + + if (off != &file->f_pos) /* fs error check */ + return -ESPIPE; + + if (file->f_mode & FMODE_READ) { + if (!(cp = file->private_data)) + return (-EFAULT); /* should never happen */ + i = strlen(cp); /* get total string length */ + if (*off < i) { + /* still bytes to transfer */ + cp += *off; /* point to desired data offset */ + i -= *off; /* remaining length */ + if (i > count) + i = count; /* limit length to transfer */ + if (copy_to_user(buf, cp, i)) + return (-EFAULT); /* copy error */ + *off += i; /* adjust offset */ + } else + return (0); + } else + return (-EPERM); /* no permission to read */ + + return (i); +} /* hysdn_conf_read */ + +/******************/ +/* open conf file */ +/******************/ +static int +hysdn_conf_open(struct inode *ino, struct file *filep) +{ + hysdn_card *card; + struct proc_dir_entry *pd; + struct conf_writedata *cnf; + char *cp, *tmp; + + /* now search the addressed card */ + MOD_INC_USE_COUNT; + card = card_root; + while (card) { + pd = card->procconf; + if (pd->low_ino == (ino->i_ino & 0xFFFF)) + break; + card = card->next; /* search next entry */ + } + if (!card) { + MOD_DEC_USE_COUNT; + return (-ENODEV); /* device is unknown/invalid */ + } + if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) + hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x", + filep->f_uid, filep->f_gid, filep->f_mode); + + if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { + /* write only access -> write boot file or conf line */ + + if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) { + MOD_DEC_USE_COUNT; + return (-EFAULT); + } + cnf->card = card; + cnf->buf_size = 0; /* nothing buffered */ + cnf->state = CONF_STATE_DETECT; /* start auto detect */ + filep->private_data = cnf; + + } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { + /* read access -> output card info data */ + + if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) { + MOD_DEC_USE_COUNT; + return (-EFAULT); /* out of memory */ + } + filep->private_data = tmp; /* start of string */ + + /* first output a headline */ + sprintf(tmp, "id bus slot type irq iobase dp-mem b-chans fax-chans state device"); + cp = tmp; /* start of string */ + while (*cp) + cp++; + while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) + *cp++ = ' '; + *cp++ = '\n'; + + /* and now the data */ + sprintf(cp, "%d %3d %4d %4d %3d 0x%04x 0x%08lx %7d %9d %3d %s", + card->myid, + card->bus, + PCI_SLOT(card->devfn), + card->brdtype, + card->irq, + card->iobase, + card->membase, + card->bchans, + card->faxchans, + card->state, + hysdn_net_getname(card)); + while (*cp) + cp++; + while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) + *cp++ = ' '; + *cp++ = '\n'; + *cp = 0; /* end of string */ + } else { /* simultaneous read/write access forbidden ! */ + MOD_DEC_USE_COUNT; + return (-EPERM); /* no permission this time */ + } + return (0); +} /* hysdn_conf_open */ + +/***************************/ +/* close a config file. */ +/***************************/ +static int +hysdn_conf_close(struct inode *ino, struct file *filep) +{ + hysdn_card *card; + struct conf_writedata *cnf; + int retval = 0; + struct proc_dir_entry *pd; + + /* search the addressed card */ + card = card_root; + while (card) { + pd = card->procconf; + if (pd->low_ino == (ino->i_ino & 0xFFFF)) + break; + card = card->next; /* search next entry */ + } + if (!card) { + return (-ENODEV); /* device is unknown/invalid */ + } + if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) + hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x", + filep->f_uid, filep->f_gid, filep->f_mode); + + if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { + /* write only access -> write boot file or conf line */ + if (filep->private_data) { + cnf = filep->private_data; + + if (cnf->state == CONF_STATE_POF) + retval = pof_write_close(cnf->card); /* close the pof write */ + kfree(filep->private_data); /* free allocated memory for buffer */ + + } /* handle write private data */ + } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { + /* read access -> output card info data */ + + if (filep->private_data) + kfree(filep->private_data); /* release memory */ + } + MOD_DEC_USE_COUNT; + return (retval); +} /* hysdn_conf_close */ + +/******************************************************/ +/* table for conf filesystem functions defined above. */ +/******************************************************/ +static struct file_operations conf_fops = +{ + llseek: hysdn_dummy_lseek, + read: hysdn_conf_read, + write: hysdn_conf_write, + open: hysdn_conf_open, + release: hysdn_conf_close, +}; + +static struct inode_operations conf_inode_operations; +/*****************************/ +/* hysdn subdir in /proc/net */ +/*****************************/ +struct proc_dir_entry *hysdn_proc_entry = NULL; + +/*******************************************************************************/ +/* hysdn_procconf_init is called when the module is loaded and after the cards */ +/* have been detected. The needed proc dir and card config files are created. */ +/* The log init is called at last. */ +/*******************************************************************************/ +int +hysdn_procconf_init(void) +{ + hysdn_card *card; + uchar conf_name[20]; + + hysdn_proc_entry = create_proc_entry(PROC_SUBDIR_NAME, S_IFDIR | S_IRUGO | S_IXUGO, proc_net); + if (!hysdn_proc_entry) { + printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n"); + return (-1); + } + card = card_root; /* point to first card */ + while (card) { + + sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); + if ((card->procconf = (void *) create_proc_entry(conf_name, + S_IFREG | S_IRUGO | S_IWUSR, + hysdn_proc_entry)) != NULL) { + memset(&conf_inode_operations, 0, sizeof(struct inode_operations)); + conf_inode_operations.default_file_ops = &conf_fops; + + ((struct proc_dir_entry *) card->procconf)->ops = &conf_inode_operations; + hysdn_proclog_init(card); /* init the log file entry */ + } + card = card->next; /* next entry */ + } + + printk(KERN_NOTICE "HYSDN: procfs Rev. %s initialised\n", hysdn_getrev(hysdn_procconf_revision)); + return (0); +} /* hysdn_procconf_init */ + +/*************************************************************************************/ +/* hysdn_procconf_release is called when the module is unloaded and before the cards */ +/* resources are released. The module counter is assumed to be 0 ! */ +/*************************************************************************************/ +void +hysdn_procconf_release(void) +{ + hysdn_card *card; + uchar conf_name[20]; + + card = card_root; /* start with first card */ + while (card) { + + sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); + if (card->procconf) + remove_proc_entry(conf_name, hysdn_proc_entry); + + hysdn_proclog_release(card); /* init the log file entry */ + + card = card->next; /* point to next card */ + } + + remove_proc_entry(PROC_SUBDIR_NAME, proc_net); +} /* hysdn_procfs_release */ diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c new file mode 100644 index 000000000000..f8187ea57d69 --- /dev/null +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -0,0 +1,464 @@ +/* $Id: hysdn_proclog.c,v 1.9 2000/11/25 17:01:01 kai Exp $ + + * Linux driver for HYSDN cards, /proc/net filesystem log functions. + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define __NO_VERSION__ +#include +#include +#include +#include +#include + +#include "hysdn_defs.h" + +/* the proc subdir for the interface is defined in the procconf module */ +extern struct proc_dir_entry *hysdn_proc_entry; + +/*************************************************/ +/* structure keeping ascii log for device output */ +/*************************************************/ +struct log_data { + struct log_data *next; + ulong usage_cnt; /* number of files still to work */ + void *proc_ctrl; /* pointer to own control procdata structure */ + char log_start[2]; /* log string start (final len aligned by size) */ +}; + +/**********************************************/ +/* structure holding proc entrys for one card */ +/**********************************************/ +struct procdata { + struct proc_dir_entry *log; /* log entry */ + char log_name[15]; /* log filename */ + struct log_data *log_head, *log_tail; /* head and tail for queue */ + int if_used; /* open count for interface */ + int volatile del_lock; /* lock for delete operations */ + uchar logtmp[LOG_MAX_LINELEN]; + wait_queue_head_t rd_queue; +}; + + +/**********************************************/ +/* log function for cards error log interface */ +/**********************************************/ +void +hysdn_card_errlog(hysdn_card * card, tErrLogEntry * logp, int maxsize) +{ + char buf[ERRLOG_TEXT_SIZE + 40]; + + sprintf(buf, "LOG 0x%08lX 0x%08lX : %s\n", logp->ulErrType, logp->ulErrSubtype, logp->ucText); + put_log_buffer(card, buf); /* output the string */ +} /* hysdn_card_errlog */ + +/***************************************************/ +/* Log function using format specifiers for output */ +/***************************************************/ +void +hysdn_addlog(hysdn_card * card, char *fmt,...) +{ + struct procdata *pd = card->proclog; + char *cp; + va_list args; + + if (!pd) + return; /* log structure non existent */ + + cp = pd->logtmp; + cp += sprintf(cp, "HYSDN: card %d ", card->myid); + + va_start(args, fmt); + cp += vsprintf(cp, fmt, args); + va_end(args); + *cp++ = '\n'; + *cp = 0; + + if (card->debug_flags & DEB_OUT_SYSLOG) + printk(KERN_INFO "%s", pd->logtmp); + else + put_log_buffer(card, pd->logtmp); + +} /* hysdn_addlog */ + +/********************************************/ +/* put an log buffer into the log queue. */ +/* This buffer will be kept until all files */ +/* opened for read got the contents. */ +/* Flushes buffers not longer in use. */ +/********************************************/ +void +put_log_buffer(hysdn_card * card, char *cp) +{ + struct log_data *ib; + struct procdata *pd = card->proclog; + int i, flags; + + if (!pd) + return; + if (!cp) + return; + if (!*cp) + return; + if (pd->if_used <= 0) + return; /* no open file for read */ + + if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC))) + return; /* no memory */ + strcpy(ib->log_start, cp); /* set output string */ + ib->next = NULL; + ib->proc_ctrl = pd; /* point to own control structure */ + save_flags(flags); + cli(); + ib->usage_cnt = pd->if_used; + if (!pd->log_head) + pd->log_head = ib; /* new head */ + else + pd->log_tail->next = ib; /* follows existing messages */ + pd->log_tail = ib; /* new tail */ + i = pd->del_lock++; /* get lock state */ + restore_flags(flags); + + /* delete old entrys */ + if (!i) + while (pd->log_head->next) { + if ((pd->log_head->usage_cnt <= 0) && + (pd->log_head->next->usage_cnt <= 0)) { + ib = pd->log_head; + pd->log_head = pd->log_head->next; + kfree(ib); + } else + break; + } /* pd->log_head->next */ + pd->del_lock--; /* release lock level */ + wake_up_interruptible(&(pd->rd_queue)); /* announce new entry */ +} /* put_log_buffer */ + + +/*************************/ +/* dummy file operations */ +/*************************/ +static loff_t +hysdn_dummy_lseek(struct file *file, loff_t offset, int orig) +{ + return -ESPIPE; +} /* hysdn_dummy_lseek */ + +/******************************/ +/* file operations and tables */ +/******************************/ + +/****************************************/ +/* write log file -> set log level bits */ +/****************************************/ +static ssize_t +hysdn_log_write(struct file *file, const char *buf, size_t count, loff_t * off) +{ + ulong u = 0; + int found = 0; + uchar *cp, valbuf[128]; + long base = 10; + hysdn_card *card = (hysdn_card *) file->private_data; + + if (&file->f_pos != off) /* fs error check */ + return (-ESPIPE); + + if (count > (sizeof(valbuf) - 1)) + count = sizeof(valbuf) - 1; /* limit length */ + if (copy_from_user(valbuf, buf, count)) + return (-EFAULT); /* copy failed */ + + valbuf[count] = 0; /* terminating 0 */ + cp = valbuf; + if ((count > 2) && (valbuf[0] == '0') && (valbuf[1] == 'x')) { + cp += 2; /* pointer after hex modifier */ + base = 16; + } + /* scan the input for debug flags */ + while (*cp) { + if ((*cp >= '0') && (*cp <= '9')) { + found = 1; + u *= base; /* adjust to next digit */ + u += *cp++ - '0'; + continue; + } + if (base != 16) + break; /* end of number */ + + if ((*cp >= 'a') && (*cp <= 'f')) { + found = 1; + u *= base; /* adjust to next digit */ + u += *cp++ - 'a' + 10; + continue; + } + break; /* terminated */ + } + + if (found) { + card->debug_flags = u; /* remember debug flags */ + hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags); + } + return (count); +} /* hysdn_log_write */ + +/******************/ +/* read log file */ +/******************/ +static ssize_t +hysdn_log_read(struct file *file, char *buf, size_t count, loff_t * off) +{ + struct log_data *inf; + int len; + word ino; + struct procdata *pd; + hysdn_card *card; + + if (!*((struct log_data **) file->private_data)) { + if (file->f_flags & O_NONBLOCK) + return (-EAGAIN); + + /* sorry, but we need to search the card */ + ino = file->f_dentry->d_inode->i_ino & 0xFFFF; /* low-ino */ + card = card_root; + while (card) { + pd = card->proclog; + if (pd->log->low_ino == ino) + break; + card = card->next; /* search next entry */ + } + if (card) + interruptible_sleep_on(&(pd->rd_queue)); + else + return (-EAGAIN); + + } + if (!(inf = *((struct log_data **) file->private_data))) + return (0); + + inf->usage_cnt--; /* new usage count */ + (struct log_data **) file->private_data = &inf->next; /* next structure */ + if ((len = strlen(inf->log_start)) <= count) { + if (copy_to_user(buf, inf->log_start, len)) + return -EFAULT; + file->f_pos += len; + return (len); + } + return (0); +} /* hysdn_log_read */ + +/******************/ +/* open log file */ +/******************/ +static int +hysdn_log_open(struct inode *ino, struct file *filep) +{ + hysdn_card *card; + struct procdata *pd; + ulong flags; + + MOD_INC_USE_COUNT; + card = card_root; + while (card) { + pd = card->proclog; + if (pd->log->low_ino == (ino->i_ino & 0xFFFF)) + break; + card = card->next; /* search next entry */ + } + if (!card) { + MOD_DEC_USE_COUNT; + return (-ENODEV); /* device is unknown/invalid */ + } + filep->private_data = card; /* remember our own card */ + + if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { + /* write only access -> write log level only */ + } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { + + /* read access -> log/debug read */ + save_flags(flags); + cli(); + pd->if_used++; + if (pd->log_head) + (struct log_data **) filep->private_data = &(pd->log_tail->next); + else + (struct log_data **) filep->private_data = &(pd->log_head); + restore_flags(flags); + } else { /* simultaneous read/write access forbidden ! */ + MOD_DEC_USE_COUNT; + return (-EPERM); /* no permission this time */ + } + return (0); +} /* hysdn_log_open */ + +/*******************************************************************************/ +/* close a cardlog file. If the file has been opened for exclusive write it is */ +/* assumed as pof data input and the pof loader is noticed about. */ +/* Otherwise file is handled as log output. In this case the interface usage */ +/* count is decremented and all buffers are noticed of closing. If this file */ +/* was the last one to be closed, all buffers are freed. */ +/*******************************************************************************/ +static int +hysdn_log_close(struct inode *ino, struct file *filep) +{ + struct log_data *inf; + struct procdata *pd; + hysdn_card *card; + int flags, retval = 0; + + + if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { + /* write only access -> write debug level written */ + retval = 0; /* success */ + } else { + /* read access -> log/debug read, mark one further file as closed */ + + pd = NULL; + save_flags(flags); + cli(); + inf = *((struct log_data **) filep->private_data); /* get first log entry */ + if (inf) + pd = (struct procdata *) inf->proc_ctrl; /* still entries there */ + else { + /* no info available -> search card */ + card = card_root; + while (card) { + pd = card->proclog; + if (pd->log->low_ino == (ino->i_ino & 0xFFFF)) + break; + card = card->next; /* search next entry */ + } + if (card) + pd = card->proclog; /* pointer to procfs log */ + } + if (pd) + pd->if_used--; /* decrement interface usage count by one */ + + while (inf) { + inf->usage_cnt--; /* decrement usage count for buffers */ + inf = inf->next; + } + restore_flags(flags); + + if (pd) + if (pd->if_used <= 0) /* delete buffers if last file closed */ + while (pd->log_head) { + inf = pd->log_head; + pd->log_head = pd->log_head->next; + kfree(inf); + } + } /* read access */ + MOD_DEC_USE_COUNT; + + return (retval); +} /* hysdn_log_close */ + +/*************************************************/ +/* select/poll routine to be able using select() */ +/*************************************************/ +static unsigned int +hysdn_log_poll(struct file *file, poll_table * wait) +{ + unsigned int mask = 0; + word ino; + hysdn_card *card; + struct procdata *pd; + + if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) + return (mask); /* no polling for write supported */ + + /* we need to search the card */ + ino = file->f_dentry->d_inode->i_ino & 0xFFFF; /* low-ino */ + card = card_root; + while (card) { + pd = card->proclog; + if (pd->log->low_ino == ino) + break; + card = card->next; /* search next entry */ + } + if (!card) + return (mask); /* card not found */ + + poll_wait(file, &(pd->rd_queue), wait); + + if (*((struct log_data **) file->private_data)) + mask |= POLLIN | POLLRDNORM; + + return mask; +} /* hysdn_log_poll */ + +/**************************************************/ +/* table for log filesystem functions defined above. */ +/**************************************************/ +static struct file_operations log_fops = +{ + llseek: hysdn_dummy_lseek, + read: hysdn_log_read, + write: hysdn_log_write, + poll: hysdn_log_poll, + open: hysdn_log_open, + release: hysdn_log_close, +}; + +struct inode_operations log_inode_operations; + +/***********************************************************************************/ +/* hysdn_proclog_init is called when the module is loaded after creating the cards */ +/* conf files. */ +/***********************************************************************************/ +int +hysdn_proclog_init(hysdn_card * card) +{ + struct procdata *pd; + + /* create a cardlog proc entry */ + + if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) { + memset(pd, 0, sizeof(struct procdata)); + memset(&log_inode_operations, 0, sizeof(struct inode_operations)); + log_inode_operations.default_file_ops = &log_fops; + sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid); + if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) { + pd->log->ops = &log_inode_operations; /* set new operations table */ + } + + init_waitqueue_head(&(pd->rd_queue)); + + card->proclog = (void *) pd; /* remember procfs structure */ + } + return (0); +} /* hysdn_proclog_init */ + +/************************************************************************************/ +/* hysdn_proclog_release is called when the module is unloaded and before the cards */ +/* conf file is released */ +/* The module counter is assumed to be 0 ! */ +/************************************************************************************/ +void +hysdn_proclog_release(hysdn_card * card) +{ + struct procdata *pd; + + if ((pd = (struct procdata *) card->proclog) != NULL) { + if (pd->log) + remove_proc_entry(pd->log_name, hysdn_proc_entry); + kfree(pd); /* release memory */ + card->proclog = NULL; + } +} /* hysdn_proclog_release */ diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c new file mode 100644 index 000000000000..276f44d24db2 --- /dev/null +++ b/drivers/isdn/hysdn/hysdn_sched.c @@ -0,0 +1,213 @@ +/* $Id: hysdn_sched.c,v 1.5 2000/11/22 17:13:13 kai Exp $ + + * Linux driver for HYSDN cards, scheduler routines for handling exchange card <-> pc. + * + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define __NO_VERSION__ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hysdn_defs.h" + +/*****************************************************************************/ +/* hysdn_sched_rx is called from the cards handler to announce new data is */ +/* available from the card. The routine has to handle the data and return */ +/* with a nonzero code if the data could be worked (or even thrown away), if */ +/* no room to buffer the data is available a zero return tells the card */ +/* to keep the data until later. */ +/*****************************************************************************/ +int +hysdn_sched_rx(hysdn_card * card, uchar * buf, word len, word chan) +{ + + switch (chan) { + case CHAN_NDIS_DATA: + hysdn_rx_netpkt(card, buf, len); /* give packet to network handler */ + break; + + case CHAN_ERRLOG: + hysdn_card_errlog(card, (tErrLogEntry *) buf, len); + if (card->err_log_state == ERRLOG_STATE_ON) + card->err_log_state = ERRLOG_STATE_START; /* start new fetch */ + break; +#ifdef CONFIG_HYSDN_CAPI + case CHAN_CAPI: +/* give packet to CAPI handler */ + hycapi_rx_capipkt(card, buf, len); + break; +#endif /* CONFIG_HYSDN_CAPI */ + default: + printk(KERN_INFO "irq message channel %d len %d unhandled \n", chan, len); + break; + + } /* switch rx channel */ + + return (1); /* always handled */ +} /* hysdn_sched_rx */ + +/*****************************************************************************/ +/* hysdn_sched_tx is called from the cards handler to announce that there is */ +/* room in the tx-buffer to the card and data may be sent if needed. */ +/* If the routine wants to send data it must fill buf, len and chan with the */ +/* appropriate data and return a nonzero value. With a zero return no new */ +/* data to send is assumed. maxlen specifies the buffer size available for */ +/* sending. */ +/*****************************************************************************/ +int +hysdn_sched_tx(hysdn_card * card, uchar * buf, word volatile *len, word volatile *chan, word maxlen) +{ + struct sk_buff *skb; + + if (card->net_tx_busy) { + card->net_tx_busy = 0; /* reset flag */ + hysdn_tx_netack(card); /* acknowledge packet send */ + } /* a network packet has completely been transferred */ + /* first of all async requests are handled */ + if (card->async_busy) { + if (card->async_len <= maxlen) { + memcpy(buf, card->async_data, card->async_len); + *len = card->async_len; + *chan = card->async_channel; + card->async_busy = 0; /* reset request */ + return (1); + } + card->async_busy = 0; /* in case of length error */ + } /* async request */ + if ((card->err_log_state == ERRLOG_STATE_START) && + (maxlen >= ERRLOG_CMD_REQ_SIZE)) { + strcpy(buf, ERRLOG_CMD_REQ); /* copy the command */ + *len = ERRLOG_CMD_REQ_SIZE; /* buffer length */ + *chan = CHAN_ERRLOG; /* and channel */ + card->err_log_state = ERRLOG_STATE_ON; /* new state is on */ + return (1); /* tell that data should be send */ + } /* error log start and able to send */ + if ((card->err_log_state == ERRLOG_STATE_STOP) && + (maxlen >= ERRLOG_CMD_STOP_SIZE)) { + strcpy(buf, ERRLOG_CMD_STOP); /* copy the command */ + *len = ERRLOG_CMD_STOP_SIZE; /* buffer length */ + *chan = CHAN_ERRLOG; /* and channel */ + card->err_log_state = ERRLOG_STATE_OFF; /* new state is off */ + return (1); /* tell that data should be send */ + } /* error log start and able to send */ + /* now handle network interface packets */ + if ((skb = hysdn_tx_netget(card)) != NULL) { + if (skb->len <= maxlen) { + memcpy(buf, skb->data, skb->len); /* copy the packet to the buffer */ + *len = skb->len; + *chan = CHAN_NDIS_DATA; + card->net_tx_busy = 1; /* we are busy sending network data */ + return (1); /* go and send the data */ + } else + hysdn_tx_netack(card); /* aknowledge packet -> throw away */ + } /* send a network packet if available */ +#ifdef CONFIG_HYSDN_CAPI + if((skb = hycapi_tx_capiget(card)) != NULL) { + if (skb->len <= maxlen) { + memcpy(buf, skb->data, skb->len); + *len = skb->len; + *chan = CHAN_CAPI; + hycapi_tx_capiack(card); + return (1); /* go and send the data */ + } + } +#endif /* CONFIG_HYSDN_CAPI */ + return (0); /* nothing to send */ +} /* hysdn_sched_tx */ + + +/*****************************************************************************/ +/* send one config line to the card and return 0 if successfull, otherwise a */ +/* negative error code. */ +/* The function works with timeouts perhaps not giving the greatest speed */ +/* sending the line, but this should be meaningless beacuse only some lines */ +/* are to be sent and this happens very seldom. */ +/*****************************************************************************/ +int +hysdn_tx_cfgline(hysdn_card * card, uchar * line, word chan) +{ + int cnt = 50; /* timeout intervalls */ + ulong flags; + + if (card->debug_flags & LOG_SCHED_ASYN) + hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1); + + save_flags(flags); + cli(); + while (card->async_busy) { + sti(); + + if (card->debug_flags & LOG_SCHED_ASYN) + hysdn_addlog(card, "async tx-cfg delayed"); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + if (!--cnt) { + restore_flags(flags); + return (-ERR_ASYNC_TIME); /* timed out */ + } + cli(); + } /* wait for buffer to become free */ + + strcpy(card->async_data, line); + card->async_len = strlen(line) + 1; + card->async_channel = chan; + card->async_busy = 1; /* request transfer */ + + /* now queue the task */ + queue_task(&card->irq_queue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + sti(); + + if (card->debug_flags & LOG_SCHED_ASYN) + hysdn_addlog(card, "async tx-cfg data queued"); + + cnt++; /* short delay */ + cli(); + + while (card->async_busy) { + sti(); + + if (card->debug_flags & LOG_SCHED_ASYN) + hysdn_addlog(card, "async tx-cfg waiting for tx-ready"); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + if (!--cnt) { + restore_flags(flags); + return (-ERR_ASYNC_TIME); /* timed out */ + } + cli(); + } /* wait for buffer to become free again */ + + restore_flags(flags); + + if (card->debug_flags & LOG_SCHED_ASYN) + hysdn_addlog(card, "async tx-cfg data send"); + + return (0); /* line send correctly */ +} /* hysdn_tx_cfgline */ diff --git a/drivers/isdn/hysdn/ince1pc.h b/drivers/isdn/hysdn/ince1pc.h new file mode 100644 index 000000000000..9f9d3104dd28 --- /dev/null +++ b/drivers/isdn/hysdn/ince1pc.h @@ -0,0 +1,132 @@ +#ifndef __INCE1PC_H__ +#define __INCE1PC_H__ + +/**************************************************************************** + + FILE: ince1pc.h + + AUTHOR: M.Steinkopf + + PURPOSE: common definitions for both sides of the bus: + - conventions both spoolers must know + - channel numbers agreed upon + +*****************************************************************************/ + +/* basic scalar definitions have same meanning, + * but their declaration location depends on environment + */ + +/*--------------------------------------channel numbers---------------------*/ +#define CHAN_SYSTEM 0x0001 /* system channel (spooler to spooler) */ +#define CHAN_ERRLOG 0x0005 /* error logger */ +#define CHAN_CAPI 0x0064 /* CAPI interface */ +#define CHAN_NDIS_DATA 0x1001 /* NDIS data transfer */ + +/*--------------------------------------POF ready msg-----------------------*/ + /* NOTE: after booting POF sends system ready message to PC: */ +#define RDY_MAGIC 0x52535953UL /* 'SYSR' reversed */ +#define RDY_MAGIC_SIZE 4 /* size in bytes */ + +#define MAX_N_TOK_BYTES 255 + +#define MIN_RDY_MSG_SIZE RDY_MAGIC_SIZE +#define MAX_RDY_MSG_SIZE (RDY_MAGIC_SIZE+MAX_N_TOK_BYTES) + +#define SYSR_TOK_END 0 +#define SYSR_TOK_B_CHAN 1 /* nr. of B-Channels; DataLen=1; def: 2 */ +#define SYSR_TOK_FAX_CHAN 2 /* nr. of FAX Channels; DataLen=1; def: 0 */ +#define SYSR_TOK_MAC_ADDR 3 /* MAC-Address; DataLen=6; def: auto */ +#define SYSR_TOK_ESC 255 /* undefined data size yet */ + /* default values, if not corrected by token: */ +#define SYSR_TOK_B_CHAN_DEF 2 /* assume 2 B-Channels */ +#define SYSR_TOK_FAX_CHAN_DEF 1 /* assume 1 FAX Channel */ + +/* syntax of new SYSR token stream: + * channel: CHAN_SYSTEM + * msgsize: MIN_RDY_MSG_SIZE <= x <= MAX_RDY_MSG_SIZE + * RDY_MAGIC_SIZE <= x <= (RDY_MAGIC_SIZE+MAX_N_TOK_BYTES) + * msg : 0 1 2 3 {4 5 6 ..} + * S Y S R MAX_N_TOK_BYTES bytes of TokenStream + * + * TokenStream := empty + * | {NonEndTokenChunk} EndToken RotlCRC + * NonEndTokenChunk:= NonEndTokenId DataLen [Data] + * NonEndTokenId := 0x01 .. 0xFE 1 BYTE + * DataLen := 0x00 .. 0xFF 1 BYTE + * Data := DataLen bytes + * EndToken := 0x00 + * RotlCRC := special 1 byte CRC over all NonEndTokenChunk bytes + * s. RotlCRC algorithm + * + * RotlCRC algorithm: + * ucSum= 0 1 uchar + * for all NonEndTokenChunk bytes: + * ROTL(ucSum,1) rotate left by 1 + * ucSum += Char; add current byte with swap around + * RotlCRC= ~ucSum; invert all bits for result + * + * note: + * - for 16-bit FIFO add padding 0 byte to achieve even token data bytes! + */ + +/*--------------------------------------error logger------------------------*/ + /* note: pof needs final 0 ! */ +#define ERRLOG_CMD_REQ "ERRLOG ON" +#define ERRLOG_CMD_REQ_SIZE 10 /* with final 0 byte ! */ +#define ERRLOG_CMD_STOP "ERRLOG OFF" +#define ERRLOG_CMD_STOP_SIZE 11 /* with final 0 byte ! */ + +#define ERRLOG_ENTRY_SIZE 64 /* sizeof(tErrLogEntry) */ + /* remaining text size = 55 */ +#define ERRLOG_TEXT_SIZE (ERRLOG_ENTRY_SIZE-2*4-1) + +typedef struct ErrLogEntry_tag { + +/*00 */ ulong ulErrType; + +/*04 */ ulong ulErrSubtype; + +/*08 */ uchar ucTextSize; + + /*09 */ uchar ucText[ERRLOG_TEXT_SIZE]; + /* ASCIIZ of len ucTextSize-1 */ + +/*40 */ +} tErrLogEntry; + + +#if defined(__TURBOC__) +#if sizeof(tErrLogEntry) != ERRLOG_ENTRY_SIZE +#error size of tErrLogEntry != ERRLOG_ENTRY_SIZE +#endif /* */ +#endif /* */ + +/*--------------------------------------DPRAM boot spooler------------------*/ + /* this is the struture used between pc and + * hyperstone to exchange boot data + */ +#define DPRAM_SPOOLER_DATA_SIZE 0x20 +typedef struct DpramBootSpooler_tag { + +/*00 */ uchar Len; + +/*01 */ volatile uchar RdPtr; + +/*02 */ uchar WrPtr; + +/*03 */ uchar Data[DPRAM_SPOOLER_DATA_SIZE]; + +/*23 */ +} tDpramBootSpooler; + + +#define DPRAM_SPOOLER_MIN_SIZE 5 /* Len+RdPtr+Wrptr+2*data */ +#define DPRAM_SPOOLER_DEF_SIZE 0x23 /* current default size */ + +/*--------------------------------------HYCARD/ERGO DPRAM SoftUart----------*/ + /* at DPRAM offset 0x1C00: */ +#define SIZE_RSV_SOFT_UART 0x1B0 /* 432 bytes reserved for SoftUart */ + + +#endif /* __INCE1PC_H__ */ diff --git a/drivers/isdn/icn/Makefile b/drivers/isdn/icn/Makefile index 17c533ee8157..51915f11c9d3 100644 --- a/drivers/isdn/icn/Makefile +++ b/drivers/isdn/icn/Makefile @@ -1,8 +1,11 @@ -ifeq ($(CONFIG_ISDN_DRV_ICN),y) - O_TARGET := icn_obj.o - O_OBJS := icn.o -else - M_OBJS := icn.o -endif - -include $(TOPDIR)/Rules.make +# Makefile for the act2000 ISDN device driver + +# The target object and module list name. + +O_TARGET := vmlinux-obj.o + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DRV_ICN) += icn.o + +include $(TOPDIR)/drivers/isdn/Rules.make diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 3212a6a8abeb..d7e8d8bad47e 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1,4 +1,4 @@ -/* $Id: icn.c,v 1.65 2000/11/13 22:51:48 kai Exp $ +/* $Id: icn.c,v 1.65.6.2 2000/12/17 22:45:13 kai Exp $ * ISDN low-level module for the ICN active ISDN-Card. * @@ -21,6 +21,7 @@ */ #include "icn.h" +#include /* * Verbose bootcode- and protocol-downloading. @@ -33,7 +34,7 @@ #undef MAP_DEBUG static char -*revision = "$Revision: 1.65 $"; +*revision = "$Revision: 1.65.6.2 $"; static int icn_addcard(int, char *, char *); @@ -1638,9 +1639,7 @@ icn_addcard(int port, char *id1, char *id2) return 0; } -#ifdef MODULE -#define icn_init init_module -#else +#ifndef MODULE void icn_setup(char *str, int *ints) { @@ -1661,10 +1660,9 @@ icn_setup(char *str, int *ints) } } } -#endif /* MODULES */ +#endif /* MODULE */ -int -icn_init(void) +static int __init icn_init(void) { char *p; char rev[10]; @@ -1675,9 +1673,6 @@ icn_init(void) dev.mcard = NULL; dev.firstload = 1; - /* No symbols to export, hide all symbols */ - EXPORT_NO_SYMBOLS; - if ((p = strchr(revision, ':'))) { strcpy(rev, p + 1); p = strchr(rev, '$'); @@ -1689,9 +1684,7 @@ icn_init(void) return (icn_addcard(portbase, icn_id, icn_id2)); } -#ifdef MODULE -void -cleanup_module(void) +static void icn_exit(void) { isdn_ctrl cmd; icn_card *card = cards; @@ -1725,4 +1718,6 @@ cleanup_module(void) release_shmem((ulong) dev.shmem, 0x4000); printk(KERN_NOTICE "ICN-ISDN-driver unloaded\n"); } -#endif + +module_init(icn_init); +module_exit(icn_exit); diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h index b49887c2aadf..7cea7c2ed311 100644 --- a/drivers/isdn/icn/icn.h +++ b/drivers/isdn/icn/icn.h @@ -1,4 +1,4 @@ -/* $Id: icn.h,v 1.30 2000/11/13 22:51:48 kai Exp $ +/* $Id: icn.h,v 1.30.6.1 2001/02/10 14:41:23 kai Exp $ * ISDN lowlevel-module for the ICN active ISDN-Card. * @@ -55,7 +55,7 @@ typedef struct icn_cdef { #include #include #include -#include +#include #include #include #include diff --git a/drivers/isdn/isdn_bsdcomp.c b/drivers/isdn/isdn_bsdcomp.c index e5cc0ea30be5..d328754ab0f5 100644 --- a/drivers/isdn/isdn_bsdcomp.c +++ b/drivers/isdn/isdn_bsdcomp.c @@ -47,12 +47,8 @@ * SUCH DAMAGE. */ -#ifndef MODULE -#error This file must be compiled as a module. -#endif - #include - +#include #include #include #include @@ -61,7 +57,7 @@ #include #include #include -#include +#include #include #include #include /* used in new tty drivers */ @@ -919,7 +915,7 @@ static struct isdn_ppp_compressor ippp_bsd_compress = { * Module support routines *************************************************************/ -int init_module(void) +static int __init isdn_bsdcomp_init(void) { int answer = isdn_ppp_register_compressor (&ippp_bsd_compress); if (answer == 0) @@ -927,7 +923,10 @@ int init_module(void) return answer; } -void cleanup_module(void) +static void isdn_bsdcomp_exit(void) { isdn_ppp_unregister_compressor (&ippp_bsd_compress); } + +module_init(isdn_bsdcomp_init); +module_exit(isdn_bsdcomp_exit); diff --git a/drivers/isdn/isdn_cards.c b/drivers/isdn/isdn_cards.c deleted file mode 100644 index 14413285fc1c..000000000000 --- a/drivers/isdn/isdn_cards.c +++ /dev/null @@ -1,73 +0,0 @@ -/* $Id: isdn_cards.c,v 1.13 2000/10/28 23:03:38 kai Exp $ - - * Linux ISDN subsystem, initialization for non-modularized drivers. - * - * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include - -#ifdef CONFIG_ISDN_DRV_ICN -extern void icn_init(void); -#endif - -#ifdef CONFIG_ISDN_DRV_HISAX -extern void HiSax_init(void); -#endif - -#ifdef CONFIG_ISDN_DRV_PCBIT -extern void pcbit_init(void); -#endif - -#ifdef CONFIG_ISDN_DRV_EICON -extern void eicon_init(void); -#endif - -#ifdef CONFIG_ISDN_DRV_AVMB1 -extern void kcapi_init(void); -extern void capi_init(void); -extern void capidrv_init(void); -#endif -#if CONFIG_ISDN_DRV_ACT2000 -extern void act2000_init(void); -#endif - -void -isdn_cards_init(void) -{ -#if CONFIG_ISDN_DRV_ICN - icn_init(); -#endif -#ifdef CONFIG_ISDN_DRV_HISAX - HiSax_init(); -#endif -#if CONFIG_ISDN_DRV_PCBIT - pcbit_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1 - kcapi_init(); - capi_init(); - capidrv_init(); -#endif -#if CONFIG_ISDN_DRV_ACT2000 - act2000_init(); -#endif -#if CONFIG_ISDN_DRV_EICON - eicon_init(); -#endif -} diff --git a/drivers/isdn/isdn_cards.h b/drivers/isdn/isdn_cards.h deleted file mode 100644 index 6122ac8c4447..000000000000 --- a/drivers/isdn/isdn_cards.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: isdn_cards.h,v 1.4 2000/05/11 22:29:20 kai Exp $ - - * Linux ISDN subsystem, initialization for non-modularized drivers. - * - * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -extern void isdn_cards_init(void); diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c index 08e4bf0cc9fd..b73b6a34cc11 100644 --- a/drivers/isdn/isdn_common.c +++ b/drivers/isdn/isdn_common.c @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.114.6.3 2000/12/18 22:14:09 kai Exp $ +/* $Id: isdn_common.c,v 1.114.6.7 2001/02/10 14:41:19 kai Exp $ * Linux ISDN subsystem, common used functions (linklevel). * @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,6 @@ #include #endif CONFIG_ISDN_DIVERSION #include "isdn_v110.h" -#include "isdn_cards.h" /* Debugflags */ #undef ISDN_DEBUG_STATCALLB @@ -2230,12 +2230,6 @@ register_isdn(isdn_if * i) ***************************************************************************** */ -extern int printk(const char *fmt,...); - -#ifdef MODULE -#define isdn_init init_module -#endif - static char * isdn_getrev(const char *revision) { @@ -2255,8 +2249,7 @@ isdn_getrev(const char *revision) /* * Allocate and initialize all data, register modem-devices */ -int -isdn_init(void) +static int __init isdn_init(void) { int i; char tmprev[50]; @@ -2323,18 +2316,15 @@ isdn_init(void) printk(" loaded\n"); #else printk("\n"); - isdn_cards_init(); #endif isdn_info_update(); return 0; } -#ifdef MODULE /* * Unload module */ -void -cleanup_module(void) +static void isdn_exit(void) { int flags; int i; @@ -2377,4 +2367,6 @@ cleanup_module(void) printk(KERN_NOTICE "ISDN-subsystem unloaded\n"); } } -#endif + +module_init(isdn_init); +module_exit(isdn_exit); diff --git a/drivers/isdn/isdn_v110.c b/drivers/isdn/isdn_v110.c index 4272b69b2ef9..079918a16fc0 100644 --- a/drivers/isdn/isdn_v110.c +++ b/drivers/isdn/isdn_v110.c @@ -1,4 +1,4 @@ -/* $Id: isdn_v110.c,v 1.5.6.1 2001/01/23 17:45:02 kai Exp $ +/* $Id: isdn_v110.c,v 1.5.6.2 2001/02/10 14:41:19 kai Exp $ * Linux ISDN subsystem, V.110 related functions (linklevel). * @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include @@ -30,7 +30,7 @@ #undef ISDN_V110_DEBUG -char *isdn_v110_revision = "$Revision: 1.5.6.1 $"; +char *isdn_v110_revision = "$Revision: 1.5.6.2 $"; #define V110_38400 255 #define V110_19200 15 diff --git a/drivers/isdn/isdnloop/Makefile b/drivers/isdn/isdnloop/Makefile index 588d80760f30..cb66f9af049f 100644 --- a/drivers/isdn/isdnloop/Makefile +++ b/drivers/isdn/isdnloop/Makefile @@ -1,11 +1,14 @@ -L_OBJS := -M_OBJS := +# +# Makefile for the isdnloop ISDN device driver +# -ifeq ($(CONFIG_ISDN_DRV_LOOP),y) - L_OBJS += isdnloop.o -else - M_OBJS += isdnloop.o -endif +# The target object and module list name. -include $(TOPDIR)/Rules.make +O_TARGET := vmlinux-obj.o + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop.o + +include $(TOPDIR)/drivers/isdn/Rules.make diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index f91723bbe078..5f1b6295b618 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -1,4 +1,4 @@ -/* $Id: isdnloop.c,v 1.11 2000/11/13 22:51:50 kai Exp $ +/* $Id: isdnloop.c,v 1.11.6.1 2000/12/17 16:47:18 kai Exp $ * ISDN low-level module implementing a dummy loop driver. * @@ -21,10 +21,12 @@ */ #include +#include +#include #include "isdnloop.h" static char -*revision = "$Revision: 1.11 $"; +*revision = "$Revision: 1.11.6.1 $"; static int isdnloop_addcard(char *); @@ -1534,22 +1536,7 @@ isdnloop_addcard(char *id1) return 0; } -#ifdef MODULE -#define isdnloop_init init_module -#else -void -isdnloop_setup(char *str, int *ints) -{ - static char sid[20]; - - if (strlen(str)) { - strcpy(sid, str); - isdnloop_id = sid; - } -} -#endif - -int +static int __init isdnloop_init(void) { char *p; @@ -1568,9 +1555,8 @@ isdnloop_init(void) return (isdnloop_addcard(isdnloop_id)); } -#ifdef MODULE -void -cleanup_module(void) +static void +isdnloop_exit(void) { isdn_ctrl cmd; isdnloop_card *card = cards; @@ -1598,4 +1584,6 @@ cleanup_module(void) } printk(KERN_NOTICE "isdnloop-ISDN-driver unloaded\n"); } -#endif + +module_init(isdnloop_init); +module_exit(isdnloop_exit); diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h index e0ddaaf36a37..fe8a501104ff 100644 --- a/drivers/isdn/isdnloop/isdnloop.h +++ b/drivers/isdn/isdnloop/isdnloop.h @@ -1,4 +1,4 @@ -/* $Id: isdnloop.h,v 1.5 2000/11/13 22:51:50 kai Exp $ +/* $Id: isdnloop.h,v 1.5.6.1 2001/02/10 14:41:23 kai Exp $ * Loopback lowlevel module for testing of linklevel. * @@ -53,7 +53,7 @@ typedef struct isdnloop_sdef { #include #include #include -#include +#include #include #include #include diff --git a/drivers/isdn/pcbit/Makefile b/drivers/isdn/pcbit/Makefile index 50a67269ea74..bbdaa55f087a 100644 --- a/drivers/isdn/pcbit/Makefile +++ b/drivers/isdn/pcbit/Makefile @@ -1,15 +1,21 @@ -L_OBJS := -M_OBJS := -O_OBJS := module.o edss1.o drv.o layer2.o capi.o callbacks.o - -O_TARGET := -ifeq ($(CONFIG_ISDN_DRV_PCBIT),y) - O_TARGET += pcbit.o -else - ifeq ($(CONFIG_ISDN_DRV_PCBIT),m) - O_TARGET += pcbit.o - M_OBJS += pcbit.o - endif -endif - -include $(TOPDIR)/Rules.make +# Makefile for the pcbit ISDN device driver + +# The target object and module list name. + +O_TARGET := vmlinux-obj.o + +# Multipart objects. + +list-multi := pcbit.o +pcbit-objs := module.o edss1.o drv.o layer2.o capi.o callbacks.o + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DRV_PCBIT) += pcbit.o + +include $(TOPDIR)/drivers/isdn/Rules.make + +# Link rules for multi-part drivers. + +pcbit.o: $(pcbit-objs) + $(LD) -r -o $@ $(pcbit-objs) diff --git a/drivers/isdn/pcbit/callbacks.c b/drivers/isdn/pcbit/callbacks.c index afa22b7401a6..ed2ba29d9814 100644 --- a/drivers/isdn/pcbit/callbacks.c +++ b/drivers/isdn/pcbit/callbacks.c @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/isdn/pcbit/capi.c b/drivers/isdn/pcbit/capi.c index 1a32c0825429..57b23498fe54 100644 --- a/drivers/isdn/pcbit/capi.c +++ b/drivers/isdn/pcbit/capi.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 92b1e398af25..2c978622bdac 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include @@ -86,6 +86,7 @@ int pcbit_init_dev(int board, int mem_base, int irq) dev_pcbit[board] = dev; memset(dev, 0, sizeof(struct pcbit_dev)); + init_waitqueue_head(&dev->set_running_wq); if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) { dev->ph_mem = mem_base; @@ -118,8 +119,6 @@ int pcbit_init_dev(int board, int mem_base, int irq) memset(dev->b2, 0, sizeof(struct pcbit_chan)); dev->b2->id = 1; - - dev->qdelivery.next = NULL; dev->qdelivery.sync = 0; dev->qdelivery.routine = pcbit_deliver; dev->qdelivery.data = dev; diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c index 1b76b3462038..991f430e66d8 100644 --- a/drivers/isdn/pcbit/edss1.c +++ b/drivers/isdn/pcbit/edss1.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c index 98daf755849d..e80b12fafc21 100644 --- a/drivers/isdn/pcbit/layer2.c +++ b/drivers/isdn/pcbit/layer2.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/isdn/pcbit/module.c b/drivers/isdn/pcbit/module.c index 55dfd75ac88a..11f54d0d3ad3 100644 --- a/drivers/isdn/pcbit/module.c +++ b/drivers/isdn/pcbit/module.c @@ -12,7 +12,7 @@ */ #include - +#include #include #include #include @@ -26,21 +26,12 @@ static int mem[MAX_PCBIT_CARDS] = {0, }; static int irq[MAX_PCBIT_CARDS] = {0, }; static int num_boards; -struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS] = {0, 0, 0, 0}; - -int init_module(void); -void cleanup_module(void); +struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS] = {0, }; extern void pcbit_terminate(int board); extern int pcbit_init_dev(int board, int mem_base, int irq); -#ifdef MODULE -MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_PCBIT_CARDS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_PCBIT_CARDS) "i"); -#define pcbit_init init_module -#endif - -int pcbit_init(void) +static int __init pcbit_init(void) { int board; @@ -83,15 +74,10 @@ int pcbit_init(void) else return -EIO; } - - /* No symbols to export, hide all symbols */ - EXPORT_NO_SYMBOLS; - return 0; } -#ifdef MODULE -void cleanup_module(void) +static void pcbit_exit(void) { int board; @@ -101,7 +87,7 @@ void cleanup_module(void) "PCBIT-D module unloaded\n"); } -#else +#ifndef MODULE void pcbit_setup(char *str, int *ints) { int i, j, argc; @@ -126,5 +112,9 @@ void pcbit_setup(char *str, int *ints) } #endif +MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_PCBIT_CARDS) "i"); +MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_PCBIT_CARDS) "i"); +module_init(pcbit_init); +module_exit(pcbit_exit); diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h index 92a561d29981..99aab08ccfee 100644 --- a/drivers/isdn/pcbit/pcbit.h +++ b/drivers/isdn/pcbit/pcbit.h @@ -69,7 +69,7 @@ struct pcbit_dev { struct frame_buf *write_queue; /* Protocol start */ - struct wait_queue *set_running_wq; + wait_queue_head_t set_running_wq; struct timer_list set_running_timer; struct timer_list error_recover_timer; diff --git a/drivers/isdn/sc/Makefile b/drivers/isdn/sc/Makefile index ff87210b87d1..c27bf6c27f74 100644 --- a/drivers/isdn/sc/Makefile +++ b/drivers/isdn/sc/Makefile @@ -1,44 +1,22 @@ -# -# $Id: Makefile,v 1.1 1997/03/22 02:01:22 fritz Exp $ -# Copyright (C) 1996 SpellCaster Telecommunications 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 distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# For more information, please contact gpl-info@spellcast.com or write: -# -# SpellCaster Telecommunications Inc. -# 5621 Finch Avenue East, Unit #3 -# Scarborough, Ontario Canada -# M1B 2T9 -# +1 (416) 297-8565 -# +1 (416) 297-6433 Facsimile -# - -L_OBJS := -M_OBJS := -O_OBJS := shmem.o init.o debug.o packet.o command.o event.o \ - ioctl.o interrupt.o message.o timer.o - -O_TARGET := -ifeq ($(CONFIG_ISDN_DRV_SC),y) - O_TARGET += sc.o -else - ifeq ($(CONFIG_ISDN_DRV_SC),m) - O_TARGET += sc.o - M_OBJS += sc.o - endif -endif - -include $(TOPDIR)/Rules.make +# Makefile for the sc ISDN device driver + +# The target object and module list name. + +O_TARGET := vmlinux-obj.o + +# Multipart objects. + +list-multi := sc.o +sc-objs := shmem.o init.o debug.o packet.o command.o event.o \ + ioctl.o interrupt.o message.o timer.o + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DRV_SC) += sc.o + +include $(TOPDIR)/drivers/isdn/Rules.make + +# Link rules for multi-part drivers. + +sc.o: $(sc-objs) + $(LD) -r -o $@ $(sc-objs) diff --git a/drivers/isdn/sc/includes.h b/drivers/isdn/sc/includes.h index 951f06f258f8..840dfc0976fd 100644 --- a/drivers/isdn/sc/includes.h +++ b/drivers/isdn/sc/includes.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index e379ae44255d..fbe7891793b7 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -1,3 +1,5 @@ +#include +#include #include "includes.h" #include "hardware.h" #include "card.h" @@ -37,23 +39,12 @@ int irq_supported(int irq_x) return 0; } -#ifdef MODULE MODULE_PARM(io, "1-4i"); MODULE_PARM(irq, "1-4i"); MODULE_PARM(ram, "1-4i"); MODULE_PARM(do_reset, "i"); -#define init_sc init_module -#else -/* -Initialization code for non-module version to be included -void sc_setup(char *str, int *ints) -{ -} -*/ -#endif - -int init_sc(void) +static int __init sc_init(void) { int b = -1; int i, j; @@ -410,8 +401,7 @@ int init_sc(void) return status; } -#ifdef MODULE -void cleanup_module(void) +static void sc_exit(void) { int i, j; @@ -463,7 +453,6 @@ void cleanup_module(void) } pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n"); } -#endif int identify_board(unsigned long rambase, unsigned int iobase) { @@ -579,3 +568,6 @@ int identify_board(unsigned long rambase, unsigned int iobase) return -1; } + +module_init(sc_init); +module_exit(sc_exit); diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 5faa19d58fab..85449e338307 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -127,6 +127,7 @@ extern int lance_probe(struct device *dev); extern int rcpci_probe(struct device *); extern int dmfe_probe(struct device *); extern int sktr_probe(struct device *dev); +extern int starfire_probe(struct device *dev); /* Gigabit Ethernet adapters */ extern int yellowfin_probe(struct device *dev); @@ -278,9 +279,12 @@ struct devprobe pci_probes[] __initdata = { #ifdef CONFIG_VIA_RHINE {via_rhine_probe, 0}, #endif -#ifdef CONFI_NET_DM9102 +#ifdef CONFIG_NET_DM9102 {dmfe_probe, 0}, -#endif +#endif +#ifdef CONFIG_ADAPTEC_STARFIRE + {starfire_probe, 0}, +#endif {NULL, 0}, }; diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index b0b0a0e3c702..a776433e2c45 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -20,7 +20,7 @@ ----------------------------------------------------------- Linux kernel-specific changes: - + LK1.1.1 (jgarzik): - Use PCI driver interface - Fix MOD_xxx races @@ -31,7 +31,7 @@ LK1.1.3 (Andrew Morton) - Timer cleanups - + LK1.1.4 (jgarzik): - Merge Becker version 1.03 @@ -41,6 +41,17 @@ LK1.2.2 (Ion Badulescu) - Backported to 2.2.x + + LK1.2.3 (Ion Badulescu) + - Fix the flaky mdio interface + - More compat clean-ups + + LK1.2.4 (Ion Badulescu) + - More 2.2.x initialization fixes + +TODO: + - implement tx_timeout() properly + - support ethtool */ /* These identify the driver base version and may not be removed. */ @@ -50,7 +61,7 @@ static const char version2[] = " Updates and info at http://www.scyld.com/network/starfire.html\n"; static const char version3[] = -" (unofficial 2.2.x kernel port, version 1.2.2, February 07, 2001)\n"; +" (unofficial 2.2.x kernel port, version 1.2.4, February 11, 2001)\n"; /* The user-configurable values. These may be modified when a driver module is loaded.*/ @@ -66,8 +77,8 @@ static const char version3[] = * for this driver to really use the firmware. Note that Rx/Tx * hardware TCP checksumming is not possible without the firmware. * - * I'm currently talking to Adaptec about this redistribution issue. - * Stay tuned... + * I'm currently [Feb 2001] talking to Adaptec about this redistribution + * issue. Stay tuned... */ #undef HAS_FIRMWARE /* @@ -75,10 +86,6 @@ static const char version3[] = * of length 1. If and when this is fixed, the #define below can be removed. */ #define HAS_BROKEN_FIRMWARE -/* - * Define this if using the driver with the zero-copy patch - */ -#undef ZEROCOPY /* Used for tuning interrupt latency vs. overhead. */ static int interrupt_mitigation = 0x0; @@ -87,12 +94,27 @@ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ static int max_interrupt_work = 20; static int mtu = 0; /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). - The Starfire has a 512 element hash table based on the Ethernet CRC. */ + The Starfire has a 512 element hash table based on the Ethernet CRC. */ static int multicast_filter_limit = 32; -/* Set the copy breakpoint for the copy-only-tiny-frames scheme. - Setting to > 1518 effectively disables this feature. */ +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ +/* + * Set the copy breakpoint for the copy-only-tiny-frames scheme. + * Setting to > 1518 effectively disables this feature. + * + * NOTE: + * The ia64 doesn't allow for unaligned loads even of integers being + * misaligned on a 2 byte boundary. Thus always force copying of + * packets as the starfire doesn't allow for misaligned DMAs ;-( + * 23/10/2000 - Jes + * + * Neither does the Alpha. -Ion + */ +#if defined(__ia64__) || defined(__alpha__) +static int rx_copybreak = PKT_BUF_SZ; +#else static int rx_copybreak = 0; +#endif /* Used to pass the media type, etc. Both 'options[]' and 'full_duplex[]' exist for driver interoperability. @@ -116,29 +138,9 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; /* Operational parameters that usually are not changed. */ /* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (2*HZ) +#define TX_TIMEOUT (2*HZ) -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ - -/* - * The ia64 doesn't allow for unaligned loads even of integers being - * misaligned on a 2 byte boundary. Thus always force copying of - * packets as the starfire doesn't allow for misaligned DMAs ;-( - * 23/10/2000 - Jes - * - * Neither does the Alpha. -Ion - */ -#if defined(__ia64__) || defined(__alpha__) -#define PKT_SHOULD_COPY(pkt_len) 1 -#else -#define PKT_SHOULD_COPY(pkt_len) (pkt_len < rx_copybreak) -#endif - -#ifdef ZEROCOPY -#define skb_first_frag_len(skb) skb_headlen(skb) -#else /* not ZEROCOPY */ #define skb_first_frag_len(skb) (skb->len) -#endif /* not ZEROCOPY */ #if !defined(__OPTIMIZE__) #warning You must compile this file with the correct options! @@ -146,6 +148,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #error You must compile this driver with "-O". #endif +#include #include #include #include @@ -159,58 +162,159 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include -#include +#ifdef HAS_FIRMWARE +#include "starfire_firmware.h" +#endif /* HAS_FIRMWARE */ + +MODULE_AUTHOR("Donald Becker "); +MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); +MODULE_PARM(max_interrupt_work, "i"); +MODULE_PARM(mtu, "i"); +MODULE_PARM(debug, "i"); +MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(interrupt_mitigation, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); + +/* + Theory of Operation + +I. Board Compatibility + +This driver is for the Adaptec 6915 "Starfire" 64 bit PCI Ethernet adapter. + +II. Board-specific settings + +III. Driver operation + +IIIa. Ring buffers + +The Starfire hardware uses multiple fixed-size descriptor queues/rings. The +ring sizes are set fixed by the hardware, but may optionally be wrapped +earlier by the END bit in the descriptor. +This driver uses that hardware queue size for the Rx ring, where a large +number of entries has no ill effect beyond increases the potential backlog. +The Tx ring is wrapped with the END bit, since a large hardware Tx queue +disables the queue layer priority ordering and we have no mechanism to +utilize the hardware two-level priority queue. When modifying the +RX/TX_RING_SIZE pay close attention to page sizes and the ring-empty warning +levels. + +IIIb/c. Transmit/Receive Structure + +See the Adaptec manual for the many possible structures, and options for +each structure. There are far too many to document here. + +For transmit this driver uses type 0/1 transmit descriptors (depending +on the presence of the zerocopy patches), and relies on automatic +minimum-length padding. It does not use the completion queue +consumer index, but instead checks for non-zero status entries. + +For receive this driver uses type 0 receive descriptors. The driver +allocates full frame size skbuffs for the Rx ring buffers, so all frames +should fit in a single descriptor. The driver does not use the completion +queue consumer index, but instead checks for non-zero status entries. + +When an incoming frame is less than RX_COPYBREAK bytes long, a fresh skbuff +is allocated and the frame is copied to the new skbuff. When the incoming +frame is larger, the skbuff is passed directly up the protocol stack. +Buffers consumed this way are replaced by newly allocated skbuffs in a later +phase of receive. + +A notable aspect of operation is that unaligned buffers are not permitted by +the Starfire hardware. The IP header at offset 14 in an ethernet frame thus +isn't longword aligned, which may cause problems on some machine +e.g. Alphas and IA64. For these architectures, the driver is forced to copy +the frame into a new skbuff unconditionally. Copied frames are put into the +skbuff at an offset of "+2", thus 16-byte aligning the IP header. + +IIId. Synchronization + +The driver runs as two independent, single-threaded flows of control. One +is the send-packet routine, which enforces single-threaded use by the +dev->tbusy flag. The other thread is the interrupt handler, which is single +threaded by the hardware and interrupt handling software. + +The send packet thread has partial control over the Tx ring and 'dev->tbusy' +flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next +queue slot is empty, it clears the tbusy flag when finished otherwise it sets +the 'lp->tx_full' flag. + +The interrupt handler has exclusive control over the Rx ring and records stats +from the Tx ring. After reaping the stats, it marks the Tx queue entry as +empty by incrementing the dirty_tx mark. Iff the 'lp->tx_full' flag is set, it +clears both the tx_full and tbusy flags. + +IV. Notes + +IVb. References + +The Adaptec Starfire manuals, available only from Adaptec. +http://www.scyld.com/expert/100mbps.html +http://www.scyld.com/expert/NWay.html + +IVc. Errata + +*/ + + + +/* 2.2.x compatibility code */ #if LINUX_VERSION_CODE < 0x20300 #include static LIST_HEAD(pci_drivers); struct pci_driver_mapping { - struct pci_dev *dev; - struct pci_driver *drv; - void *driver_data; + struct pci_dev *dev; + struct pci_driver *drv; + void *driver_data; }; struct pci_device_id { - unsigned int vendor, device; - unsigned int subvendor, subdevice; - unsigned int class, class_mask; - unsigned long driver_data; + unsigned int vendor, device; + unsigned int subvendor, subdevice; + unsigned int class, class_mask; + unsigned long driver_data; }; struct pci_driver { - struct list_head node; - struct pci_dev *dev; - char *name; - const struct pci_device_id *id_table; /* NULL if wants all devices */ - int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ - void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ - void (*suspend)(struct pci_dev *dev); /* Device suspended */ - void (*resume)(struct pci_dev *dev); /* Device woken up */ + struct list_head node; + struct pci_dev *dev; + char *name; + const struct pci_device_id *id_table; /* NULL if wants all devices */ + int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ + void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ + void (*suspend)(struct pci_dev *dev); /* Device suspended */ + void (*resume)(struct pci_dev *dev); /* Device woken up */ }; #define PCI_MAX_MAPPINGS 16 static struct pci_driver_mapping drvmap [PCI_MAX_MAPPINGS] = { { NULL, } , }; -#define __devinit -#define __devinitdata +#define __devinit __init +#define __devinitdata __initdata #define __devexit #define MODULE_DEVICE_TABLE(foo,bar) +#define SET_MODULE_OWNER(dev) +#define COMPAT_MOD_INC_USE_COUNT MOD_INC_USE_COUNT +#define COMPAT_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT #define PCI_ANY_ID (~0) -#define IORESOURCE_MEM 2 -#define PCI_DMA_FROMDEVICE 0 -#define PCI_DMA_TODEVICE 0 +#define IORESOURCE_MEM 2 +#define PCI_DMA_FROMDEVICE 0 +#define PCI_DMA_TODEVICE 0 #define request_mem_region(addr, size, name) ((void *)1) #define release_mem_region(addr, size) #define del_timer_sync(timer) del_timer(timer) static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) + dma_addr_t *dma_handle) { void *virt_ptr; @@ -222,7 +326,7 @@ static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, #define pci_map_single(cookie, address, size, dir) virt_to_bus(address) #define pci_unmap_single(cookie, address, size, dir) #define pci_dma_sync_single(cookie, address, size, dir) -#undef pci_resource_flags +#undef pci_resource_flags #define pci_resource_flags(dev, i) \ ((dev->base_address[i] & IORESOURCE_IO) ? IORESOURCE_IO : IORESOURCE_MEM) @@ -282,19 +386,22 @@ pci_announce_device(struct pci_driver *drv, struct pci_dev *dev) id = NULL; found = 0; - for (i = 0; i < PCI_MAX_MAPPINGS && !found; i++) + for (i = 0; i < PCI_MAX_MAPPINGS; i++) if (!drvmap[i].dev) { drvmap[i].dev = dev; drvmap[i].drv = drv; found = 1; + break; } - if (drv->probe(dev, id) >= 0) { - if(found) - return 1; - } else { - drvmap[i - 1].dev = NULL; - } + if (!found) + return 0; + + if (drv->probe(dev, id) >= 0) + return 1; + + /* clean up */ + drvmap[i].dev = NULL; return 0; } @@ -326,13 +433,15 @@ pci_unregister_driver(struct pci_driver *drv) list_del(&drv->node); for (dev = pci_devices; dev; dev = dev->next) { found = 0; - for (i = 0; i < PCI_MAX_MAPPINGS && !found; i++) - if (drvmap[i].dev == dev) + for (i = 0; i < PCI_MAX_MAPPINGS; i++) + if (drvmap[i].dev == dev) { found = 1; + break; + } if (found) { if (drv->remove) drv->remove(dev); - drvmap[i - 1].dev = NULL; + drvmap[i].dev = NULL; } } #endif @@ -348,116 +457,46 @@ void *compat_request_region (unsigned long start, unsigned long n, const char *n static inline int pci_module_init(struct pci_driver *drv) { - int rc = pci_register_driver (drv); - - if (rc > 0) + if (pci_register_driver(drv)) return 0; - - /* if we get here, we need to clean up pci driver instance - * and return some sort of error */ - pci_unregister_driver (drv); - return -ENODEV; } -#endif /* LINUX_VERSION_CODE < 0x20300 */ - -#ifdef HAS_FIRMWARE -#include "starfire_firmware.h" -#endif /* HAS_FIRMWARE */ - -MODULE_AUTHOR("Donald Becker "); -MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); -MODULE_PARM(max_interrupt_work, "i"); -MODULE_PARM(mtu, "i"); -MODULE_PARM(debug, "i"); -MODULE_PARM(rx_copybreak, "i"); -MODULE_PARM(interrupt_mitigation, "i"); -MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); - -/* - Theory of Operation - -I. Board Compatibility - -This driver is for the Adaptec 6915 "Starfire" 64 bit PCI Ethernet adapter. - -II. Board-specific settings - -III. Driver operation - -IIIa. Ring buffers - -The Starfire hardware uses multiple fixed-size descriptor queues/rings. The -ring sizes are set fixed by the hardware, but may optionally be wrapped -earlier by the END bit in the descriptor. -This driver uses that hardware queue size for the Rx ring, where a large -number of entries has no ill effect beyond increases the potential backlog. -The Tx ring is wrapped with the END bit, since a large hardware Tx queue -disables the queue layer priority ordering and we have no mechanism to -utilize the hardware two-level priority queue. When modifying the -RX/TX_RING_SIZE pay close attention to page sizes and the ring-empty warning -levels. - -IIIb/c. Transmit/Receive Structure - -See the Adaptec manual for the many possible structures, and options for -each structure. There are far too many to document here. - -For transmit this driver uses type 0/1 transmit descriptors (depending -on the presence of the zerocopy patches), and relies on automatic -minimum-length padding. It does not use the completion queue -consumer index, but instead checks for non-zero status entries. - -For receive this driver uses type 0 receive descriptors. The driver -allocates full frame size skbuffs for the Rx ring buffers, so all frames -should fit in a single descriptor. The driver does not use the completion -queue consumer index, but instead checks for non-zero status entries. - -When an incoming frame is less than RX_COPYBREAK bytes long, a fresh skbuff -is allocated and the frame is copied to the new skbuff. When the incoming -frame is larger, the skbuff is passed directly up the protocol stack. -Buffers consumed this way are replaced by newly allocated skbuffs in a -later phase of receive. - -A notable aspect of operation is that unaligned buffers are not permitted by -the Starfire hardware. The IP header at offset 14 in an ethernet frame thus -isn't longword aligned, which may cause problems on some machine -e.g. Alphas and IA64. For these architectures, the driver is forced to copy -the frame into a new skbuff unconditionally. Copied frames are put into the -skbuff at an offset of "+2", thus 16-byte aligning the IP header. +static struct pci_driver starfire_driver; -IIId. Synchronization +int __init starfire_probe(struct net_device *dev) +{ + static int __initdata probed = 0; -The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single -threaded by the hardware and interrupt handling software. + if (probed) + return -ENODEV; + probed++; -The send packet thread has partial control over the Tx ring and 'dev->tbusy' -flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next -queue slot is empty, it clears the tbusy flag when finished otherwise it sets -the 'lp->tx_full' flag. + return pci_module_init(&starfire_driver); +} -The interrupt handler has exclusive control over the Rx ring and records stats -from the Tx ring. After reaping the stats, it marks the Tx queue entry as -empty by incrementing the dirty_tx mark. Iff the 'lp->tx_full' flag is set, it -clears both the tx_full and tbusy flags. +#define init_tx_timer(dev, func, timeout) +#define kick_tx_timer(dev, func, timeout) \ + if (netif_queue_stopped(dev)) { \ + /* If this happens network layer tells us we're broken. */ \ + if (jiffies - dev->trans_start > timeout) \ + func(dev); \ + } -IV. Notes +#else /* LINUX_VERSION_CODE > 0x20300 */ -IVb. References +#define COMPAT_MOD_INC_USE_COUNT +#define COMPAT_MOD_DEC_USE_COUNT -The Adaptec Starfire manuals, available only from Adaptec. -http://www.scyld.com/expert/100mbps.html -http://www.scyld.com/expert/NWay.html +#define init_tx_timer(dev, func, timeout) \ + dev->tx_timeout = func; \ + dev->watchdog_timeo = timeout; +#define kick_tx_timer(dev, func, timeout) -IVc. Errata -*/ +#endif /* LINUX_VERSION_CODE > 0x20300 */ +/* end of compatibility code */ - enum chip_capability_flags {CanHaveMII=1, }; #define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR0) @@ -574,7 +613,7 @@ enum rx_compl_bits { /* The Rx and Tx buffer descriptors. */ struct starfire_rx_desc { - u32 rxaddr; /* Optionally 64 bits. */ + u32 rxaddr; /* Optionally 64 bits. */ }; enum rx_desc_bits { RxDescValid=1, RxDescEndRing=2, @@ -587,14 +626,14 @@ enum rx_desc_bits { #define csum_rx_status #endif /* HAS_FIRMWARE */ struct rx_done_desc { - u32 status; /* Low 16 bits is length. */ + u32 status; /* Low 16 bits is length. */ #ifdef csum_rx_status - u32 status2; /* Low 16 bits is csum */ + u32 status2; /* Low 16 bits is csum */ #endif /* csum_rx_status */ #ifdef full_rx_status u32 status2; u16 vlanid; - u16 csum; /* partial checksum */ + u16 csum; /* partial checksum */ u32 timestamp; #endif /* full_rx_status */ }; @@ -602,41 +641,24 @@ enum rx_done_bits { RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000, }; -#ifdef ZEROCOPY -/* Type 0 Tx descriptor. */ -/* If more fragments are needed, don't forget to change the - descriptor spacing as well! */ -struct starfire_tx_desc { - u32 status; - u32 nbufs; - u32 first_addr; - u16 first_len; - u16 total_len; - struct { - u32 addr; - u32 len; - } frag[6]; -}; -#else /* not ZEROCOPY */ /* Type 1 Tx descriptor. */ struct starfire_tx_desc { - u32 status; /* Upper bits are status, lower 16 length. */ + u32 status; /* Upper bits are status, lower 16 length. */ u32 first_addr; }; -#endif /* not ZEROCOPY */ enum tx_desc_bits { TxDescID=0xB0000000, TxCRCEn=0x01000000, TxDescIntr=0x08000000, TxRingWrap=0x04000000, TxCalTCP=0x02000000, }; struct tx_done_report { - u32 status; /* timestamp, index. */ + u32 status; /* timestamp, index. */ #if 0 - u32 intrstatus; /* interrupt status */ + u32 intrstatus; /* interrupt status */ #endif }; -#define PRIV_ALIGN 15 /* Required alignment mask */ +#define PRIV_ALIGN 15 /* Required alignment mask */ struct rx_ring_info { struct sk_buff *skb; dma_addr_t mapping; @@ -644,9 +666,6 @@ struct rx_ring_info { struct tx_ring_info { struct sk_buff *skb; dma_addr_t first_mapping; -#ifdef ZEROCOPY - dma_addr_t frag_mapping[6]; -#endif /* ZEROCOPY */ }; struct netdev_private { @@ -670,45 +689,45 @@ struct netdev_private { struct timer_list timer; /* Media monitoring timer. */ struct pci_dev *pci_dev; /* Frequently used values: keep some adjacent for cache effect. */ - unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ + unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned int cur_tx, dirty_tx; - unsigned int rx_buf_sz; /* Based on MTU+slack. */ - unsigned int tx_full:1; /* The Tx queue is full. */ + unsigned int rx_buf_sz; /* Based on MTU+slack. */ + unsigned int tx_full:1; /* The Tx queue is full. */ /* These values are keep track of the transceiver/media in use. */ - unsigned int full_duplex:1, /* Full-duplex operation requested. */ - medialock:1, /* Xcvr set to fixed speed/duplex. */ + unsigned int full_duplex:1, /* Full-duplex operation requested. */ + medialock:1, /* Xcvr set to fixed speed/duplex. */ rx_flowctrl:1, - tx_flowctrl:1; /* Use 802.3x flow control. */ - unsigned int default_port:4; /* Last dev->if_port value. */ + tx_flowctrl:1; /* Use 802.3x flow control. */ + unsigned int default_port:4; /* Last dev->if_port value. */ u32 tx_mode; u8 tx_threshold; /* MII transceiver section. */ - int mii_cnt; /* MII device addresses. */ - u16 advertising; /* NWay media advertisement */ - unsigned char phys[2]; /* MII device addresses. */ + int mii_cnt; /* MII device addresses. */ + u16 advertising; /* NWay media advertisement */ + unsigned char phys[2]; /* MII device addresses. */ }; -static int mdio_read(struct net_device *dev, int phy_id, int location); -static void mdio_write(struct net_device *dev, int phy_id, int location, int value); -static int netdev_open(struct net_device *dev); -static void check_duplex(struct net_device *dev, int startup); -static void netdev_timer(unsigned long data); -static void tx_timeout(struct net_device *dev); -static void init_ring(struct net_device *dev); -static int start_tx(struct sk_buff *skb, struct net_device *dev); -static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs); -static void netdev_error(struct net_device *dev, int intr_status); -static int netdev_rx(struct net_device *dev); -static void netdev_error(struct net_device *dev, int intr_status); -static void set_rx_mode(struct net_device *dev); +static int mdio_read(struct net_device *dev, int phy_id, int location); +static void mdio_write(struct net_device *dev, int phy_id, int location, int value); +static int netdev_open(struct net_device *dev); +static void check_duplex(struct net_device *dev, int startup); +static void netdev_timer(unsigned long data); +static void tx_timeout(struct net_device *dev); +static void init_ring(struct net_device *dev); +static int start_tx(struct sk_buff *skb, struct net_device *dev); +static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs); +static void netdev_error(struct net_device *dev, int intr_status); +static int netdev_rx(struct net_device *dev); +static void netdev_error(struct net_device *dev, int intr_status); +static void set_rx_mode(struct net_device *dev); static struct net_device_stats *get_stats(struct net_device *dev); -static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static int netdev_close(struct net_device *dev); +static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int netdev_close(struct net_device *dev); -static int __devinit starfire_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit starfire_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct netdev_private *np; int i, irq, option, chip_idx = ent->driver_data; @@ -717,13 +736,14 @@ static int __devinit starfire_init_one (struct pci_dev *pdev, static int printed_version = 0; long ioaddr; int drv_flags, io_size; + int boguscnt; card_idx++; option = card_idx < MAX_UNITS ? options[card_idx] : 0; if (!printed_version++) printk(KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s", - version1, version2, version3); + version1, version2, version3); if (pci_enable_device (pdev)) return -EIO; @@ -734,21 +754,22 @@ static int __devinit starfire_init_one (struct pci_dev *pdev, printk (KERN_ERR "starfire %d: no PCI MEM resources, aborting\n", card_idx); return -ENODEV; } - + dev = init_etherdev(NULL, sizeof(*np)); if (!dev) { printk (KERN_ERR "starfire %d: cannot alloc etherdev, aborting\n", card_idx); return -ENOMEM; } - - irq = pdev->irq; + SET_MODULE_OWNER(dev); + + irq = pdev->irq; if (request_mem_region (ioaddr, io_size, dev->name) == NULL) { printk (KERN_ERR "starfire %d: resource 0x%x @ 0x%lx busy, aborting\n", card_idx, io_size, ioaddr); goto err_out_free_netdev; } - + ioaddr = (long) ioremap (ioaddr, io_size); if (!ioaddr) { printk (KERN_ERR "starfire %d: cannot remap 0x%x @ 0x%lx, aborting\n", @@ -757,34 +778,42 @@ static int __devinit starfire_init_one (struct pci_dev *pdev, } pci_set_master (pdev); - + printk(KERN_INFO "%s: %s at 0x%lx, ", dev->name, netdrv_tbl[chip_idx].name, ioaddr); -#ifdef ZEROCOPY - /* Starfire can do SG and TCP/UDP checksumming */ - dev->features |= NETIF_F_SG; -#ifdef HAS_FIRMWARE - dev->features |= NETIF_F_IP_CSUM; -#endif /* HAS_FIRMWARE */ -#endif /* ZEROCOPY */ - /* Serial EEPROM reads are hidden by the hardware. */ for (i = 0; i < 6; i++) dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20-i); for (i = 0; i < 5; i++) - printk("%2.2x:", dev->dev_addr[i]); + printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq); #if ! defined(final_version) /* Dump the EEPROM contents during development. */ if (debug > 4) for (i = 0; i < 0x20; i++) - printk("%2.2x%s", (unsigned int)readb(ioaddr + EEPROMCtrl + i), - i % 16 != 15 ? " " : "\n"); + printk("%2.2x%s", + (unsigned int)readb(ioaddr + EEPROMCtrl + i), + i % 16 != 15 ? " " : "\n"); #endif + /* Issue soft reset */ + writel(0x8000, ioaddr + TxMode); + udelay(1000); + writel(0, ioaddr + TxMode); + /* Reset the chip to erase previous misconfiguration. */ writel(1, ioaddr + PCIDeviceConfig); + boguscnt = 1000; + while (--boguscnt > 0) { + udelay(10); + if ((readl(ioaddr + PCIDeviceConfig) & 1) == 0) + break; + } + if (boguscnt == 0) + printk("%s: chipset reset never completed!\n", dev->name); + /* wait a little longer */ + udelay(1000); dev->base_addr = ioaddr; dev->irq = irq; @@ -806,7 +835,7 @@ static int __devinit starfire_init_one (struct pci_dev *pdev, if (np->default_port) np->medialock = 1; } - if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) + if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) np->full_duplex = 1; if (np->full_duplex) @@ -815,6 +844,7 @@ static int __devinit starfire_init_one (struct pci_dev *pdev, /* The chip-specific entries in the device structure. */ dev->open = &netdev_open; dev->hard_start_xmit = &start_tx; + init_tx_timer(dev, tx_timeout, TX_TIMEOUT); dev->stop = &netdev_close; dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; @@ -825,14 +855,27 @@ static int __devinit starfire_init_one (struct pci_dev *pdev, if (drv_flags & CanHaveMII) { int phy, phy_idx = 0; + int mii_status; for (phy = 0; phy < 32 && phy_idx < 4; phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { + mdio_write(dev, phy, 0, 0x8000); + udelay(500); + boguscnt = 1000; + while (--boguscnt > 0) + if ((mdio_read(dev, phy, 0) & 0x8000) == 0) + break; + if (boguscnt == 0) { + printk("%s: PHY reset never completed!\n", dev->name); + continue; + } + mii_status = mdio_read(dev, phy, 1); + if (mii_status != 0x0000) { np->phys[phy_idx++] = phy; np->advertising = mdio_read(dev, phy, 4); printk(KERN_INFO "%s: MII PHY found at address %d, status " "0x%4.4x advertising %4.4x.\n", dev->name, phy, mii_status, np->advertising); + /* there can be only one PHY on-board */ + break; } } np->mii_cnt = phy_idx; @@ -858,7 +901,11 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) /* ??? Should we add a busy-wait here? */ do result = readl(mdio_addr); - while ((result & 0xC0000000) != 0x80000000 && --boguscnt >= 0); + while ((result & 0xC0000000) != 0x80000000 && --boguscnt > 0); + if (boguscnt == 0) + return 0; + if ((result & 0xffff) == 0xffff) + return 0; return result & 0xffff; } @@ -879,11 +926,11 @@ static int netdev_open(struct net_device *dev) /* Do we ever need to reset the chip??? */ - MOD_INC_USE_COUNT; + COMPAT_MOD_INC_USE_COUNT; retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); if (retval) { - MOD_DEC_USE_COUNT; + COMPAT_MOD_DEC_USE_COUNT; return retval; } @@ -892,7 +939,7 @@ static int netdev_open(struct net_device *dev) writel(1, ioaddr + PCIDeviceConfig); if (debug > 1) printk(KERN_DEBUG "%s: netdev_open() irq %d.\n", - dev->name, dev->irq); + dev->name, dev->irq); /* Allocate the various queues, failing gracefully. */ if (np->tx_done_q == 0) np->tx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_done_q_dma); @@ -902,47 +949,38 @@ static int netdev_open(struct net_device *dev) np->tx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_ring_dma); if (np->rx_ring == 0) np->rx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->rx_ring_dma); - if (np->tx_done_q == 0 || np->rx_done_q == 0 - || np->rx_ring == 0 || np->tx_ring == 0) { + if (np->tx_done_q == 0 || np->rx_done_q == 0 + || np->rx_ring == 0 || np->tx_ring == 0) { if (np->tx_done_q) pci_free_consistent(np->pci_dev, PAGE_SIZE, - np->tx_done_q, np->tx_done_q_dma); + np->tx_done_q, np->tx_done_q_dma); if (np->rx_done_q) pci_free_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE, - np->rx_done_q, np->rx_done_q_dma); + np->rx_done_q, np->rx_done_q_dma); if (np->tx_ring) pci_free_consistent(np->pci_dev, PAGE_SIZE, - np->tx_ring, np->tx_ring_dma); + np->tx_ring, np->tx_ring_dma); if (np->rx_ring) pci_free_consistent(np->pci_dev, PAGE_SIZE, - np->rx_ring, np->rx_ring_dma); - MOD_DEC_USE_COUNT; + np->rx_ring, np->rx_ring_dma); + COMPAT_MOD_DEC_USE_COUNT; return -ENOMEM; } init_ring(dev); /* Set the size of the Rx buffers. */ writel((np->rx_buf_sz << RxBufferLenShift) | - (0 << RxMinDescrThreshShift) | - RxPrefetchMode | RxVariableQ | - RxDescSpace4, - ioaddr + RxDescQCtrl); + (0 << RxMinDescrThreshShift) | + RxPrefetchMode | RxVariableQ | + RxDescSpace4, + ioaddr + RxDescQCtrl); -#ifdef ZEROCOPY - /* Set Tx descriptor to type 0 and spacing to 64 bytes. */ - writel((2 << TxHiPriFIFOThreshShift) | - (0 << TxPadLenShift) | - (4 << TxDMABurstSizeShift) | - TxDescSpace64 | TxDescType0, - ioaddr + TxDescCtrl); -#else /* not ZEROCOPY */ /* Set Tx descriptor to type 1 and padding to 0 bytes. */ writel((2 << TxHiPriFIFOThreshShift) | (0 << TxPadLenShift) | (4 << TxDMABurstSizeShift) | TxDescSpaceUnlim | TxDescType1, ioaddr + TxDescCtrl); -#endif /* not ZEROCOPY */ #if defined(ADDR_64BITS) && defined(__alpha__) /* XXX We really need a 64-bit PCI dma interfaces too... -DaveM */ @@ -959,25 +997,25 @@ static int netdev_open(struct net_device *dev) writel(np->tx_done_q_dma, ioaddr + TxCompletionAddr); #ifdef full_rx_status writel(np->rx_done_q_dma | - RxComplType3 | - (0 << RxComplThreshShift), - ioaddr + RxCompletionAddr); + RxComplType3 | + (0 << RxComplThreshShift), + ioaddr + RxCompletionAddr); #else /* not full_rx_status */ #ifdef csum_rx_status writel(np->rx_done_q_dma | - RxComplType2 | - (0 << RxComplThreshShift), - ioaddr + RxCompletionAddr); + RxComplType2 | + (0 << RxComplThreshShift), + ioaddr + RxCompletionAddr); #else /* not csum_rx_status */ writel(np->rx_done_q_dma | - RxComplType0 | - (0 << RxComplThreshShift), - ioaddr + RxCompletionAddr); + RxComplType0 | + (0 << RxComplThreshShift), + ioaddr + RxCompletionAddr); #endif /* not csum_rx_status */ #endif /* not full_rx_status */ if (debug > 1) - printk(KERN_DEBUG "%s: Filling in the station address.\n", dev->name); + printk(KERN_DEBUG "%s: Filling in the station address.\n", dev->name); /* Fill both the unused Tx SA register and the Rx perfect filter. */ for (i = 0; i < 6; i++) @@ -1003,7 +1041,7 @@ static int netdev_open(struct net_device *dev) netif_start_queue(dev); if (debug > 1) - printk(KERN_DEBUG "%s: Setting the Rx and Tx modes.\n", dev->name); + printk(KERN_DEBUG "%s: Setting the Rx and Tx modes.\n", dev->name); set_rx_mode(dev); np->advertising = mdio_read(dev, np->phys[0], 4); @@ -1016,7 +1054,7 @@ static int netdev_open(struct net_device *dev) IntrRxGFPDead | IntrNoTxCsum | IntrTxBadID, ioaddr + IntrEnable); writel(0x00800000 | readl(ioaddr + PCIDeviceConfig), - ioaddr + PCIDeviceConfig); + ioaddr + PCIDeviceConfig); #ifdef HAS_FIRMWARE /* Load Rx/Tx firmware into the frame processors */ @@ -1033,7 +1071,7 @@ static int netdev_open(struct net_device *dev) if (debug > 2) printk(KERN_DEBUG "%s: Done netdev_open().\n", - dev->name); + dev->name); /* Set the timer to check for link beat. */ init_timer(&np->timer); @@ -1066,8 +1104,8 @@ static void check_duplex(struct net_device *dev, int startup) np->full_duplex = duplex; if (debug > 1) printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d" - " negotiated capability %4.4x.\n", dev->name, - duplex ? "full" : "half", np->phys[0], negotiated); + " negotiated capability %4.4x.\n", dev->name, + duplex ? "full" : "half", np->phys[0], negotiated); } } if (new_tx_mode != np->tx_mode) { @@ -1086,7 +1124,7 @@ static void netdev_timer(unsigned long data) if (debug > 3) { printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x.\n", - dev->name, (int)readl(ioaddr + IntrStatus)); + dev->name, (int)readl(ioaddr + IntrStatus)); } check_duplex(dev, 0); #if ! defined(final_version) @@ -1096,7 +1134,7 @@ static void netdev_timer(unsigned long data) /* Bogus hardware IRQ: Fake an interrupt handler call. */ if (new_status & 1) { printk(KERN_ERR "%s: Interrupt blocked, status %8.8x/%8.8x.\n", - dev->name, new_status, (int)readl(ioaddr + IntrStatus)); + dev->name, new_status, (int)readl(ioaddr + IntrStatus)); intr_handler(dev->irq, dev, 0); } } @@ -1112,7 +1150,7 @@ static void tx_timeout(struct net_device *dev) long ioaddr = dev->base_addr; printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," - " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus)); + " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus)); #ifndef __alpha__ { @@ -1183,13 +1221,6 @@ static void init_ring(struct net_device *dev) for (i = 0; i < TX_RING_SIZE; i++) { np->tx_info[i].skb = NULL; np->tx_info[i].first_mapping = 0; -#ifdef ZEROCOPY - { - int j; - for (j = 0; j < 6; j++) - np->tx_info[i].frag_mapping[j] = 0; - } -#endif /* ZEROCOPY */ np->tx_ring[i].status = 0; } return; @@ -1199,15 +1230,8 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) { struct netdev_private *np = dev->priv; unsigned int entry; -#ifdef ZEROCOPY - int i; -#endif - if (netif_queue_stopped(dev)) { - /* If this happens network layer tells us we're broken. */ - if (jiffies - dev->trans_start > TX_TIMEOUT) - tx_timeout(dev); - } + kick_tx_timer(dev, tx_timeout, TX_TIMEOUT); /* Caution: the write order is important here, set the field with the "ownership" bits last. */ @@ -1215,80 +1239,22 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) /* Calculate the next Tx descriptor entry. */ entry = np->cur_tx % TX_RING_SIZE; -#if defined(ZEROCOPY) && defined(HAS_FIRMWARE) && defined(HAS_BROKEN_FIRMWARE) - { - int has_bad_length = 0; - - if (skb_first_frag_len(skb) == 1) - has_bad_length = 1; - else { - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) - if (skb_shinfo(skb)->frags[i].size == 1) { - has_bad_length = 1; - break; - } - } - - if (has_bad_length) - skb_checksum_help(skb); - } -#endif /* ZEROCOPY && HAS_FIRMWARE && HAS_BROKEN_FIRMWARE */ - np->tx_info[entry].skb = skb; np->tx_info[entry].first_mapping = pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE); np->tx_ring[entry].first_addr = cpu_to_le32(np->tx_info[entry].first_mapping); -#ifdef ZEROCOPY - np->tx_ring[entry].first_len = cpu_to_le32(skb_first_frag_len(skb)); - np->tx_ring[entry].total_len = cpu_to_le32(skb->len); - /* Add "| TxDescIntr" to generate Tx-done interrupts. */ - np->tx_ring[entry].status = cpu_to_le32(TxDescID | TxCRCEn); - np->tx_ring[entry].nbufs = cpu_to_le32(skb_shinfo(skb)->nr_frags + 1); -#else /* not ZEROCOPY */ - /* Add "| TxDescIntr" to generate Tx-done interrupts. */ + /* Add "| TxDescIntr" to generate Tx-done interrupts. */ np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID | TxCRCEn | 1 << 16); -#endif /* not ZEROCOPY */ if (entry >= TX_RING_SIZE-1) /* Wrap ring */ np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr); - /* not ifdef'ed, but shouldn't happen without ZEROCOPY */ - if (skb->ip_summed == CHECKSUM_HW) - np->tx_ring[entry].status |= cpu_to_le32(TxCalTCP); - if (debug > 5) { -#ifdef ZEROCOPY - printk(KERN_DEBUG "%s: Tx #%d slot %d status %8.8x nbufs %d len %4.4x/%4.4x.\n", - dev->name, np->cur_tx, entry, - le32_to_cpu(np->tx_ring[entry].status), - le32_to_cpu(np->tx_ring[entry].nbufs), - le32_to_cpu(np->tx_ring[entry].first_len), - le32_to_cpu(np->tx_ring[entry].total_len)); -#else /* not ZEROCOPY */ printk(KERN_DEBUG "%s: Tx #%d slot %d status %8.8x.\n", - dev->name, np->cur_tx, entry, - le32_to_cpu(np->tx_ring[entry].status)); -#endif /* not ZEROCOPY */ - } - -#ifdef ZEROCOPY - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i]; - - /* we already have the proper value in entry */ - np->tx_info[entry].frag_mapping[i] = - pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE); - - np->tx_ring[entry].frag[i].addr = cpu_to_le32(np->tx_info[entry].frag_mapping[i]); - np->tx_ring[entry].frag[i].len = cpu_to_le32(this_frag->size); - if (debug > 5) { - printk(KERN_DEBUG "%s: Tx #%d frag %d len %4.4x.\n", - dev->name, np->cur_tx, i, - le32_to_cpu(np->tx_ring[entry].frag[i].len)); - } + dev->name, np->cur_tx, entry, + le32_to_cpu(np->tx_ring[entry].status)); } -#endif /* ZEROCOPY */ np->cur_tx++; @@ -1322,11 +1288,12 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) struct netdev_private *np; long ioaddr; int boguscnt = max_interrupt_work; + int consumer; + int tx_status; #ifndef final_version /* Can never occur. */ if (dev == NULL) { - printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown " - "device.\n", irq); + printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown device.\n", irq); return; } #endif @@ -1339,7 +1306,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) if (debug > 4) printk(KERN_DEBUG "%s: Interrupt status %4.4x.\n", - dev->name, intr_status); + dev->name, intr_status); if (intr_status == 0) break; @@ -1350,63 +1317,48 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) /* Scavenge the skbuff list based on the Tx-done queue. There are redundant checks here that may be cleaned up after the driver has proven to be reliable. */ - { - int consumer = readl(ioaddr + TxConsumerIdx); - int tx_status; - if (debug > 4) - printk(KERN_DEBUG "%s: Tx Consumer index is %d.\n", - dev->name, consumer); + consumer = readl(ioaddr + TxConsumerIdx); + if (debug > 4) + printk(KERN_DEBUG "%s: Tx Consumer index is %d.\n", + dev->name, consumer); #if 0 - if (np->tx_done >= 250 || np->tx_done == 0) - printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x, " - "%d is %8.8x.\n", dev->name, - np->tx_done, le32_to_cpu(np->tx_done_q[np->tx_done].status), - (np->tx_done+1) & (DONE_Q_SIZE-1), - le32_to_cpu(np->tx_done_q[(np->tx_done+1)&(DONE_Q_SIZE-1)].status)); + if (np->tx_done >= 250 || np->tx_done == 0) + printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x, %d is %8.8x.\n", + dev->name, np->tx_done, + le32_to_cpu(np->tx_done_q[np->tx_done].status), + (np->tx_done+1) & (DONE_Q_SIZE-1), + le32_to_cpu(np->tx_done_q[(np->tx_done+1)&(DONE_Q_SIZE-1)].status)); #endif - while ((tx_status = le32_to_cpu(np->tx_done_q[np->tx_done].status)) - != 0) { - if (debug > 4) - printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x.\n", - dev->name, np->tx_done, tx_status); - if ((tx_status & 0xe0000000) == 0xa0000000) { - np->stats.tx_packets++; - } else if ((tx_status & 0xe0000000) == 0x80000000) { - struct sk_buff *skb; -#ifdef ZEROCOPY - int i; -#endif /* ZEROCOPY */ - u16 entry = tx_status; /* Implicit truncate */ - entry /= sizeof(struct starfire_tx_desc); - - skb = np->tx_info[entry].skb; - np->tx_info[entry].skb = NULL; - pci_unmap_single(np->pci_dev, - np->tx_info[entry].first_mapping, - skb_first_frag_len(skb), - PCI_DMA_TODEVICE); - np->tx_info[entry].first_mapping = 0; - -#ifdef ZEROCOPY - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - pci_unmap_single(np->pci_dev, - np->tx_info[entry].frag_mapping[i], - skb_shinfo(skb)->frags[i].size, - PCI_DMA_TODEVICE); - np->tx_info[entry].frag_mapping[i] = 0; - } -#endif /* ZEROCOPY */ - - /* Scavenge the descriptor. */ - dev_kfree_skb_irq(skb); - - np->dirty_tx++; - } - np->tx_done_q[np->tx_done].status = 0; - np->tx_done = (np->tx_done+1) & (DONE_Q_SIZE-1); + + while ((tx_status = le32_to_cpu(np->tx_done_q[np->tx_done].status)) != 0) { + if (debug > 4) + printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x.\n", + dev->name, np->tx_done, tx_status); + if ((tx_status & 0xe0000000) == 0xa0000000) { + np->stats.tx_packets++; + } else if ((tx_status & 0xe0000000) == 0x80000000) { + struct sk_buff *skb; + u16 entry = tx_status; /* Implicit truncate */ + entry /= sizeof(struct starfire_tx_desc); + + skb = np->tx_info[entry].skb; + np->tx_info[entry].skb = NULL; + pci_unmap_single(np->pci_dev, + np->tx_info[entry].first_mapping, + skb_first_frag_len(skb), + PCI_DMA_TODEVICE); + np->tx_info[entry].first_mapping = 0; + + /* Scavenge the descriptor. */ + dev_kfree_skb_irq(skb); + + np->dirty_tx++; } - writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2); + np->tx_done_q[np->tx_done].status = 0; + np->tx_done = (np->tx_done+1) & (DONE_Q_SIZE-1); } + writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2); + if (np->tx_full && np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) { /* The ring is no longer full, wake the queue. */ np->tx_full = 0; @@ -1419,23 +1371,23 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) if (--boguscnt < 0) { printk(KERN_WARNING "%s: Too much work at interrupt, " - "status=0x%4.4x.\n", - dev->name, intr_status); + "status=0x%4.4x.\n", + dev->name, intr_status); break; } } while (1); if (debug > 4) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, (int)readl(ioaddr + IntrStatus)); + dev->name, (int)readl(ioaddr + IntrStatus)); #ifndef final_version /* Code that should never be run! Remove after testing.. */ { static int stopit = 10; - if (!netif_running(dev) && --stopit < 0) { + if (!netif_running(dev) && --stopit < 0) { printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n", - dev->name); + dev->name); free_irq(irq, dev); } } @@ -1452,98 +1404,99 @@ static int netdev_rx(struct net_device *dev) if (np->rx_done_q == 0) { printk(KERN_ERR "%s: rx_done_q is NULL! rx_done is %d. %p.\n", - dev->name, np->rx_done, np->tx_done_q); + dev->name, np->rx_done, np->tx_done_q); return 0; } /* If EOP is set on the next entry, it's a new packet. Send it up. */ while ((desc_status = le32_to_cpu(np->rx_done_q[np->rx_done].status)) != 0) { + struct sk_buff *skb; + u16 pkt_len; + int entry; + if (debug > 4) - printk(KERN_DEBUG " netdev_rx() status of %d was %8.8x.\n", - np->rx_done, desc_status); + printk(KERN_DEBUG " netdev_rx() status of %d was %8.8x.\n", np->rx_done, desc_status); if (--boguscnt < 0) break; if ( ! (desc_status & RxOK)) { /* There was a error. */ if (debug > 2) - printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n", - desc_status); + printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n", desc_status); np->stats.rx_errors++; if (desc_status & RxFIFOErr) np->stats.rx_fifo_errors++; - } else { - struct sk_buff *skb; - u16 pkt_len = desc_status; /* Implicitly Truncate */ - int entry = (desc_status >> 16) & 0x7ff; + goto next_rx; + } + + pkt_len = desc_status; /* Implicitly Truncate */ + entry = (desc_status >> 16) & 0x7ff; #ifndef final_version - if (debug > 4) - printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d" - ", bogus_cnt %d.\n", - pkt_len, boguscnt); + if (debug > 4) + printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d, bogus_cnt %d.\n", pkt_len, boguscnt); #endif - /* Check if the packet is long enough to accept without copying - to a minimally-sized skbuff. */ - if (PKT_SHOULD_COPY(pkt_len) - && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { - skb->dev = dev; - skb_reserve(skb, 2); /* 16 byte align the IP header */ - pci_dma_sync_single(np->pci_dev, - np->rx_info[entry].mapping, - pkt_len, PCI_DMA_FROMDEVICE); + /* Check if the packet is long enough to accept without copying + to a minimally-sized skbuff. */ + if (pkt_len < rx_copybreak + && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + skb->dev = dev; + skb_reserve(skb, 2); /* 16 byte align the IP header */ + pci_dma_sync_single(np->pci_dev, + np->rx_info[entry].mapping, + pkt_len, PCI_DMA_FROMDEVICE); #if HAS_IP_COPYSUM /* Call copy + cksum if available. */ - eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0); - skb_put(skb, pkt_len); + eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0); + skb_put(skb, pkt_len); #else - memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail, - pkt_len); + memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail, pkt_len); #endif - } else { - char *temp; - - pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE); - skb = np->rx_info[entry].skb; - temp = skb_put(skb, pkt_len); - np->rx_info[entry].skb = NULL; - np->rx_info[entry].mapping = 0; - } -#ifndef final_version /* Remove after testing. */ - /* You will want this info for the initial debug. */ - if (debug > 5) - printk(KERN_DEBUG " Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:" - "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x " - "%d.%d.%d.%d.\n", - skb->data[0], skb->data[1], skb->data[2], skb->data[3], - skb->data[4], skb->data[5], skb->data[6], skb->data[7], - skb->data[8], skb->data[9], skb->data[10], - skb->data[11], skb->data[12], skb->data[13], - skb->data[14], skb->data[15], skb->data[16], - skb->data[17]); + } else { + char *temp; + + pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE); + skb = np->rx_info[entry].skb; + temp = skb_put(skb, pkt_len); + np->rx_info[entry].skb = NULL; + np->rx_info[entry].mapping = 0; + } +#ifndef final_version /* Remove after testing. */ + /* You will want this info for the initial debug. */ + if (debug > 5) + printk(KERN_DEBUG " Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:" + "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x " + "%d.%d.%d.%d.\n", + skb->data[0], skb->data[1], skb->data[2], skb->data[3], + skb->data[4], skb->data[5], skb->data[6], skb->data[7], + skb->data[8], skb->data[9], skb->data[10], + skb->data[11], skb->data[12], skb->data[13], + skb->data[14], skb->data[15], skb->data[16], + skb->data[17]); #endif - skb->protocol = eth_type_trans(skb, dev); + skb->protocol = eth_type_trans(skb, dev); #if defined(full_rx_status) || defined(csum_rx_status) - if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - } - /* - * This feature doesn't seem to be working, at least - * with the two firmware versions I have. If the GFP sees - * a fragment, it either ignores it completely, or reports - * "bad checksum" on it. - * - * Maybe I missed something -- corrections are welcome. - * Until then, the printk stays. :-) -Ion - */ - else if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x00400000) { - skb->ip_summed = CHECKSUM_HW; - skb->csum = le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0xffff; - printk(KERN_DEBUG "%s: checksum_hw, status2 = %x\n", dev->name, np->rx_done_q[np->rx_done].status2); - } -#endif - netif_rx(skb); - dev->last_rx = jiffies; - np->stats.rx_packets++; + if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) { + skb->ip_summed = CHECKSUM_UNNECESSARY; } + /* + * This feature doesn't seem to be working, at least + * with the two firmware versions I have. If the GFP sees + * a fragment, it either ignores it completely, or reports + * "bad checksum" on it. + * + * Maybe I missed something -- corrections are welcome. + * Until then, the printk stays. :-) -Ion + */ + else if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x00400000) { + skb->ip_summed = CHECKSUM_HW; + skb->csum = le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0xffff; + printk(KERN_DEBUG "%s: checksum_hw, status2 = %x\n", dev->name, np->rx_done_q[np->rx_done].status2); + } +#endif + netif_rx(skb); + dev->last_rx = jiffies; + np->stats.rx_packets++; + +next_rx: np->cur_rx++; np->rx_done_q[np->rx_done].status = 0; np->rx_done = (np->rx_done + 1) & (DONE_Q_SIZE-1); @@ -1558,10 +1511,10 @@ static int netdev_rx(struct net_device *dev) skb = dev_alloc_skb(np->rx_buf_sz); np->rx_info[entry].skb = skb; if (skb == NULL) - break; /* Better luck next round. */ + break; /* Better luck next round. */ np->rx_info[entry].mapping = pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE); - skb->dev = dev; /* Mark as being used by this device. */ + skb->dev = dev; /* Mark as being used by this device. */ np->rx_ring[entry].rxaddr = cpu_to_le32(np->rx_info[entry].mapping | RxDescValid); } @@ -1572,10 +1525,10 @@ static int netdev_rx(struct net_device *dev) } if (debug > 5 - || memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1)) + || memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1)) printk(KERN_DEBUG " exiting netdev_rx() status of %d was %8.8x %d.\n", - np->rx_done, desc_status, - memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1)); + np->rx_done, desc_status, + memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1)); /* Restart Rx engine if stopped. */ return 0; @@ -1587,9 +1540,9 @@ static void netdev_error(struct net_device *dev, int intr_status) if (intr_status & IntrLinkChange) { printk(KERN_NOTICE "%s: Link changed: Autonegotiation advertising" - " %4.4x partner %4.4x.\n", dev->name, - mdio_read(dev, np->phys[0], 4), - mdio_read(dev, np->phys[0], 5)); + " %4.4x, partner %4.4x.\n", dev->name, + mdio_read(dev, np->phys[0], 4), + mdio_read(dev, np->phys[0], 5)); check_duplex(dev, 0); } if (intr_status & IntrStatsMax) { @@ -1598,10 +1551,9 @@ static void netdev_error(struct net_device *dev, int intr_status) /* Came close to underrunning the Tx FIFO, increase threshold. */ if (intr_status & IntrTxDataLow) writel(++np->tx_threshold, dev->base_addr + TxThreshold); - if ((intr_status & - ~(IntrAbnormalSummary|IntrLinkChange|IntrStatsMax|IntrTxDataLow|1)) && debug) + if ((intr_status & ~(IntrAbnormalSummary|IntrLinkChange|IntrStatsMax|IntrTxDataLow|1)) && debug) printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", - dev->name, intr_status); + dev->name, intr_status); /* Hmmmmm, it's not clear how to recover from DMA faults. */ if (intr_status & IntrDMAErr) np->stats.tx_fifo_errors++; @@ -1619,12 +1571,13 @@ static struct net_device_stats *get_stats(struct net_device *dev) np->stats.tx_aborted_errors = readl(ioaddr + 0x57024) + readl(ioaddr + 0x57028); np->stats.tx_window_errors = readl(ioaddr + 0x57018); - np->stats.collisions = readl(ioaddr + 0x57004) + readl(ioaddr + 0x57008); + np->stats.collisions = + readl(ioaddr + 0x57004) + readl(ioaddr + 0x57008); /* The chip only need report frame silently dropped. */ - np->stats.rx_dropped += readw(ioaddr + RxDMAStatus); + np->stats.rx_dropped += readw(ioaddr + RxDMAStatus); writew(0, ioaddr + RxDMAStatus); - np->stats.rx_crc_errors = readl(ioaddr + 0x5703C); + np->stats.rx_crc_errors = readl(ioaddr + 0x5703C); np->stats.rx_frame_errors = readl(ioaddr + 0x57040); np->stats.rx_length_errors = readl(ioaddr + 0x57058); np->stats.rx_missed_errors = readl(ioaddr + 0x5707C); @@ -1665,19 +1618,19 @@ static void set_rx_mode(struct net_device *dev) struct dev_mc_list *mclist; int i; - if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ /* Unconditionally log net taps. */ printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptAll|AcceptMyPhys; } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { + || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys; } else if (dev->mc_count <= 15) { /* Use the 16 element perfect filter. */ long filter_addr = ioaddr + 0x56000 + 1*16; - for (i = 1, mclist = dev->mc_list; mclist && i <= dev->mc_count; - i++, mclist = mclist->next) { + for (i = 1, mclist = dev->mc_list; mclist && i <= dev->mc_count; + i++, mclist = mclist->next) { u16 *eaddrs = (u16 *)mclist->dmi_addr; writew(cpu_to_be16(eaddrs[2]), filter_addr); filter_addr += 4; writew(cpu_to_be16(eaddrs[1]), filter_addr); filter_addr += 4; @@ -1696,7 +1649,7 @@ static void set_rx_mode(struct net_device *dev) memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { + i++, mclist = mclist->next) { set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23, mc_filter); } /* Clear the perfect filter list. */ @@ -1778,15 +1731,15 @@ static int netdev_close(struct net_device *dev) np->tx_ring_dma); for (i = 0; i < 8 /* TX_RING_SIZE is huge! */; i++) printk(KERN_DEBUG " #%d desc. %8.8x %8.8x -> %8.8x.\n", - i, le32_to_cpu(np->tx_ring[i].status), - le32_to_cpu(np->tx_ring[i].first_addr), - le32_to_cpu(np->tx_done_q[i].status)); + i, le32_to_cpu(np->tx_ring[i].status), + le32_to_cpu(np->tx_ring[i].first_addr), + le32_to_cpu(np->tx_done_q[i].status)); printk(KERN_DEBUG " Rx ring at %8.8x -> %p:\n", - np->rx_ring_dma, np->rx_done_q); + np->rx_ring_dma, np->rx_done_q); if (np->rx_done_q) for (i = 0; i < 8 /* RX_RING_SIZE */; i++) { printk(KERN_DEBUG " #%d desc. %8.8x -> %8.8x\n", - i, le32_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status)); + i, le32_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status)); } } #endif /* __i386__ debugging only */ @@ -1805,31 +1758,17 @@ static int netdev_close(struct net_device *dev) } for (i = 0; i < TX_RING_SIZE; i++) { struct sk_buff *skb = np->tx_info[i].skb; -#ifdef ZEROCOPY - int j; -#endif /* ZEROCOPY */ - if (skb != NULL) { - pci_unmap_single(np->pci_dev, - np->tx_info[i].first_mapping, - skb_first_frag_len(skb), PCI_DMA_TODEVICE); - np->tx_info[i].first_mapping = 0; - dev_kfree_skb(skb); - np->tx_info[i].skb = NULL; -#ifdef ZEROCOPY - for (j = 0; j < 6; j++) - if (np->tx_info[i].frag_mapping[j]) { - pci_unmap_single(np->pci_dev, - np->tx_info[i].frag_mapping[j], - skb_shinfo(skb)->frags[j].size, - PCI_DMA_TODEVICE); - np->tx_info[i].frag_mapping[j] = 0; - } else - break; -#endif /* ZEROCOPY */ - } + if (skb == NULL) + continue; + pci_unmap_single(np->pci_dev, + np->tx_info[i].first_mapping, + skb_first_frag_len(skb), PCI_DMA_TODEVICE); + np->tx_info[i].first_mapping = 0; + dev_kfree_skb(skb); + np->tx_info[i].skb = NULL; } - MOD_DEC_USE_COUNT; + COMPAT_MOD_DEC_USE_COUNT; return 0; } @@ -1839,7 +1778,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct netdev_private *np; - + if (!dev) BUG(); @@ -1849,7 +1788,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev) iounmap((char *)dev->base_addr); release_mem_region(pci_resource_start (pdev, 0), - pci_resource_len (pdev, 0)); + pci_resource_len (pdev, 0)); if (np->tx_done_q) pci_free_consistent(np->pci_dev, PAGE_SIZE, @@ -1896,8 +1835,7 @@ module_exit(starfire_cleanup); * Local variables: * compile-command: "gcc -DMODULE -Wall -Wstrict-prototypes -O6 -c starfire.c" * simple-compile-command: "gcc -DMODULE -O6 -c starfire.c" - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 4 + * c-basic-offset: 8 + * tab-width: 8 * End: */ diff --git a/include/linux/hysdn_if.h b/include/linux/hysdn_if.h new file mode 100644 index 000000000000..68cc72078e10 --- /dev/null +++ b/include/linux/hysdn_if.h @@ -0,0 +1,49 @@ +/* $Id: hysdn_if.h,v 1.1 2000/02/10 19:47:50 werner Exp $ + + * Linux driver for HYSDN cards, ioctl definitions shared by hynetmgr and driver. + * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH + * + * Copyright 1999 by Werner Cornelius (werner@titro.de) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Log: hysdn_if.h,v $ + * Revision 1.1 2000/02/10 19:47:50 werner + * + * Initial release + * + * + */ + +/****************/ +/* error values */ +/****************/ +#define ERR_NONE 0 /* no error occured */ +#define ERR_ALREADY_BOOT 1000 /* we are already booting */ +#define EPOF_BAD_MAGIC 1001 /* bad magic in POF header */ +#define ERR_BOARD_DPRAM 1002 /* board DPRAM failed */ +#define EPOF_INTERNAL 1003 /* internal POF handler error */ +#define EPOF_BAD_IMG_SIZE 1004 /* POF boot image size invalid */ +#define ERR_BOOTIMG_FAIL 1005 /* 1. stage boot image did not start */ +#define ERR_BOOTSEQ_FAIL 1006 /* 2. stage boot seq handshake timeout */ +#define ERR_POF_TIMEOUT 1007 /* timeout waiting for card pof ready */ +#define ERR_NOT_BOOTED 1008 /* operation only allowed when booted */ +#define ERR_CONF_LONG 1009 /* conf line is to long */ +#define ERR_INV_CHAN 1010 /* invalid channel number */ +#define ERR_ASYNC_TIME 1011 /* timeout sending async data */ + + + + diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 41190a2a2e00..b9bf7dd3d2eb 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -1,4 +1,4 @@ -/* $Id: isdn.h,v 1.111 2000/11/25 17:01:02 kai Exp $ +/* $Id: isdn.h,v 1.111.6.3 2001/02/10 14:44:10 kai Exp $ * Main header for the Linux ISDN subsystem (linklevel). * @@ -538,8 +538,7 @@ typedef struct modem_info { atemu emu; /* AT-emulator data */ struct termios normal_termios; /* For saving termios structs */ struct termios callout_termios; - struct wait_queue *open_wait; - struct wait_queue *close_wait; + wait_queue_head_t open_wait, close_wait; struct semaphore write_sem; } modem_info; diff --git a/include/linux/isdn_compat.h b/include/linux/isdn_compat.h new file mode 100644 index 000000000000..90917b423d3c --- /dev/null +++ b/include/linux/isdn_compat.h @@ -0,0 +1,48 @@ +/* Compatibility for various Linux kernel versions */ + +#ifndef _LINUX_ISDN_COMPAT_H +#define _LINUX_ISDN_COMPAT_H + +#ifdef __KERNEL__ + + +#include +#ifdef __powerpc__ +static inline int pci_enable_device(struct pci_dev *dev) +{ + u16 cmd; + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_SERR; + cmd &= ~PCI_COMMAND_FAST_BACK; + pci_write_config_word(dev, PCI_COMMAND, cmd); + return(0); +} +#else +static inline int pci_enable_device(struct pci_dev *dev) +{ + return 0; +} +#endif /* __powerpc__ */ + +#define PCI_ANY_ID (~0) + +/* as this is included multiple times, we make it inline */ + +static inline struct pci_dev * pci_find_subsys(unsigned int vendor, unsigned int device, + unsigned int ss_vendor, unsigned int ss_device, + struct pci_dev *from) +{ + unsigned short subsystem_vendor, subsystem_device; + + while ((from = pci_find_device(vendor, device, from))) { + pci_read_config_word(from, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); + pci_read_config_word(from, PCI_SUBSYSTEM_ID, &subsystem_device); + if ((ss_vendor == PCI_ANY_ID || subsystem_vendor == ss_vendor) && + (ss_device == PCI_ANY_ID || subsystem_device == ss_device)) + return from; + } + return NULL; +} + +#endif /* __KERNEL__ */ +#endif /* _LINUX_ISDN_COMPAT_H */ diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h index 988c9402d7a2..e2d9b1de101f 100644 --- a/include/linux/isdn_ppp.h +++ b/include/linux/isdn_ppp.h @@ -201,7 +201,7 @@ struct ippp_struct { struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */ struct ippp_buf_queue *first; /* pointer to (current) first packet */ struct ippp_buf_queue *last; /* pointer to (current) last used packet in queue */ - struct wait_queue *wq; + wait_queue_head_t wq; struct task_struct *tk; unsigned int mpppcfg; unsigned int pppcfg; diff --git a/include/linux/isdnif.h b/include/linux/isdnif.h index 7ce2fb214aa9..1d5d4f85b7dd 100644 --- a/include/linux/isdnif.h +++ b/include/linux/isdnif.h @@ -53,6 +53,7 @@ #define ISDN_PROTO_L2_V11038 9 /* V.110 bitrate adaption 38400 Baud */ #define ISDN_PROTO_L2_MODEM 10 /* Analog Modem on Board */ #define ISDN_PROTO_L2_FAX 11 /* Fax Group 2/3 */ +#define ISDN_PROTO_L2_HDLC_56K 12 /* HDLC 56k */ #define ISDN_PROTO_L2_MAX 15 /* Max. 16 Protocols */ /* @@ -253,6 +254,7 @@ typedef struct #define ISDN_FEATURE_L2_V11038 (0x0001 << ISDN_PROTO_L2_V11038) #define ISDN_FEATURE_L2_MODEM (0x0001 << ISDN_PROTO_L2_MODEM) #define ISDN_FEATURE_L2_FAX (0x0001 << ISDN_PROTO_L2_FAX) +#define ISDN_FEATURE_L2_HDLC_56K (0x0001 << ISDN_PROTO_L2_HDLC_56K) #define ISDN_FEATURE_L2_MASK (0x0FFFF) /* Max. 16 protocols */ #define ISDN_FEATURE_L2_SHIFT (0) diff --git a/ipc/shm.c b/ipc/shm.c index 4a33fa8fe850..ca25f68e223e 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -337,6 +337,8 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) if (current->euid == shp->u.shm_perm.uid || current->euid == shp->u.shm_perm.cuid || capable(CAP_SYS_ADMIN)) { + /* Do not find it any more */ + shp->u.shm_perm.key = IPC_PRIVATE; shp->u.shm_perm.mode |= SHM_DEST; if (shp->u.shm_nattch <= 0) killseg (id); diff --git a/net/core/sock.c b/net/core/sock.c index 0fe23ed6f6e6..703244921154 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -79,6 +79,7 @@ * Jay Schulist : Added SO_ATTACH_FILTER and SO_DETACH_FILTER. * Andi Kleen : Add sock_kmalloc()/sock_kfree_s() * Andi Kleen : Fix write_space callback + * Chris Evans : Security fixes - signedness again * * To Fix: * @@ -376,7 +377,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, struct timeval tm; } v; - int lv=sizeof(int),len; + unsigned int lv=sizeof(int),len; if(get_user(len,optlen)) return -EFAULT; -- 2.39.5