diff --git a/Documentation/Changes b/Documentation/Changes index 8db20b179f2ecfce4d4a2ca786e37a8ba13f4151..a883b8d5d3a523fb45d48ef47b03b358b3243e77 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -63,6 +63,7 @@ running, the suggested command should tell you. - Pcmcia-cs 3.1.2 ; cardmgr -V - PPP 2.3.9 ; pppd --version - Util-linux 2.9i ; chsh -v +- isdn4k-utils v3.1beta7 ; isdnctrl 2>&1|grep version Upgrade notes ************* @@ -245,9 +246,6 @@ modules) are currently distributed separately: see DHCP clients for 2.0 do not work with the new networking code in the 2.2 kernel. You will need to upgrade your dhcpcd / dhcpclient. - The ISDN code in the stock 2.2 kernel may not work for you. If it -doesn't, look in ftp://ftp.suse.com/pub/isdn4linux for updated versions. - In 2.0.x the kernel could be configured to drop source routed IP packets via a compile time configuration option. In 2.2.x, this has been replaced by a sysctl. See Documentation/networking/ip-sysctl.txt @@ -494,6 +492,15 @@ config.h file needs to so be sure to check that when you recompile. +ISDN4Linux +========== +Since 2.3.27 here is a new length of the phonenumber field, old utils +have to recompile, a upgrade to isdn4k-utils.v3.1beta7 or later is +recomented. +Older isdn4k-utils versions don't support EXTRAVERSION into kernel version +string. + + Where to get the files ********************** @@ -775,6 +782,11 @@ Patch The 2.5 release: ftp://ftp.gnu.org/gnu/patch/patch-2.5.tar.gz +ISDN4Linux +========== +The v3.1beta7 release: +ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/testing/isdn4k-utils.v3.1beta7.tar.gz + Other Info ========== diff --git a/Documentation/isdn/00-INDEX b/Documentation/isdn/00-INDEX index 919af90576546aa79caea0142a13258f0a369d3f..b7161af1a78f298cf4a01acc890438718ecb198e 100644 --- a/Documentation/isdn/00-INDEX +++ b/Documentation/isdn/00-INDEX @@ -6,12 +6,18 @@ INTERFACE - description of Linklevel and Hardwarelevel ISDN interface. README - general info on what you need and what to do for Linux ISDN. +README.FAQ + - general info for FAQ. README.audio - info for running audio over ISDN. +README.fax + - info for using Fax over ISDN. README.icn - info on the ICN-ISDN-card and its driver. README.HiSax - info on the HiSax driver which replaces the old teles. +README.hfc-pci + - info on hfc-pci based cards. README.pcbit - info on the PCBIT-D ISDN adapter and driver. README.syncppp @@ -22,8 +28,12 @@ README.avmb1 - info on driver for AVM-B1 ISDN card. README.act2000 - info on driver for IBM ACT-2000 card. +README.eicon + - info on driver for Eicon active cards. README.concap - info on "CONCAP" ecapsulation protocol interface used for X.25. +README.diversion + - info on module for isdn diversion services. README.sc - info on driver for Spellcaster cards. README.x25 diff --git a/Documentation/isdn/CREDITS b/Documentation/isdn/CREDITS index 31da77e3b1e46ad3d0957f335c4071d31cf07e4c..beef990bab6baa61828ca88b15aea0d69b3d500e 100644 --- a/Documentation/isdn/CREDITS +++ b/Documentation/isdn/CREDITS @@ -15,8 +15,11 @@ Volker G For contribution of man-pages, the imontty-tool and a perfect maintaining of the mailing-list at hub-wue. +Matthias Hessler (hessler@isdn4linux.de) + For creating and maintaining the FAQ. + Bernhard Hailer (Bernhard.Hailer@lrz.uni-muenchen.de) - For maintaining the FAQ. + For creating the FAQ, and the leafsite HOWTO. Michael 'Ghandi' Herold (michael@abadonna.franken.de) For contribution of the vbox answering machine. diff --git a/Documentation/isdn/README b/Documentation/isdn/README index dcd14151eb9bcb49bce3040b9545bd968fb65589..3cf623d48eec5dfb0e69f372e34996ccb6b5a92e 100644 --- a/Documentation/isdn/README +++ b/Documentation/isdn/README @@ -11,7 +11,7 @@ README for the ISDN-subsystem necessary. Those programs and some contributed utilities are available at - ftp.franken.de + ftp.isdn4linux.de /pub/isdn4linux/isdn4k-utils-<VersionNumber>.tar.gz @@ -22,19 +22,23 @@ README for the ISDN-subsystem reasons, the mailing-list's primary language is german. However mails written in english have been welcome all the time. - to subscribe: write a email to majordomo@hub-wue.franken.de, + to subscribe: write a email to majordomo@listserv.isdn4linux.de, Subject irrelevant, in the message body: subscribe isdn4linux <your_email_address> - To write to the mailing-list, write to isdn4linux@hub-wue.franken.de + To write to the mailing-list, write to isdn4linux@listserv.isdn4linux.de This mailinglist is bidirectionally gated to the newsgroup de.alt.comm.isdn4linux - There is also a well maintained FAQ (both english and german) available - at ftp.franken.de in /pub/isdn4linux/FAQ/ - This FAQ is also available at http://www.lrz-muenchen.de/~ui161ab/www/isdn/ + There is also a well maintained FAQ in English available at + http://www.mhessler.de/i4lfaq/ + It can be viewed online, or downloaded in sgml/text/html format. + The FAQ can also be viewed online at + http://www.isdn4inux.de/faq/ + or downloaded from + ftp://ftp.isdn4linux.de/pub/isdn4linux/FAQ/ 1.1 Technical details @@ -266,6 +270,8 @@ README for the ISDN-subsystem 23 0 Bit coded register: Bit 0: 0 = Add CPN to RING message off 1 = Add CPN to RING message on + Bit 1: 0 = Add CPN to FCON message off + 1 = Add CPN to FCON message on Last but not least a (at the moment fairly primitive) device to request the line-status (/dev/isdninfo) is made available. @@ -581,7 +587,7 @@ README for the ISDN-subsystem If other drivers will not be affected, I will include the changes in the next release. For developers only, there is a second mailing-list. Write to me - (fritz@wuemaus.franken.de), if you want to join that list. + (fritz@isdn4linux.de), if you want to join that list. Have fun! diff --git a/Documentation/isdn/README.FAQ b/Documentation/isdn/README.FAQ new file mode 100644 index 0000000000000000000000000000000000000000..356f7944641d50d71fd0d737a725a6a3d715a0dc --- /dev/null +++ b/Documentation/isdn/README.FAQ @@ -0,0 +1,26 @@ + +The FAQ for isdn4linux +====================== + +Please note that there is a big FAQ available in the isdn4k-utils. +You find it in: + isdn4k-utils/FAQ/i4lfaq.sgml + +In case you just want to see the FAQ online, or download the newest version, +you can have a look at my website: +http://www.mhessler.de/i4lfaq/ (view + download) +or: +http://www.isdn4linux.de/faq/ (view) + +As the extension tells, the FAQ is in SGML format, and you can convert it +into text/html/... format by using the sgml2txt/sgml2html/... tools. +Alternatively, you can also do a 'configure; make all' in the FAQ directory. + + +Please have a look at the FAQ before posting anything in the Mailinglist, +or the newsgroup! + + +Matthias Hessler +hessler@isdn4linux.de + diff --git a/Documentation/isdn/README.HiSax b/Documentation/isdn/README.HiSax index 7faff4a349221622007ec219cdbea6a533ada9e5..ee95d85f41479b76df5373ad43ab82766d5b75ac 100644 --- a/Documentation/isdn/README.HiSax +++ b/Documentation/isdn/README.HiSax @@ -63,6 +63,7 @@ Berkom Telekom A4T Scitel Quadro Gazel ISDN cards HFC-PCI based cards +Winbond W6692 based cards Note: PCF, PCF-Pro: up to now, only the ISDN part is supported PCC-8: not tested yet @@ -182,6 +183,7 @@ Card types: 34 Gazel ISDN cards (ISA) irq,io 34 Gazel ISDN cards (PCI) none 35 HFC 2BDS0 PCI none + 36 W6692 based PCI cards none At the moment IRQ sharing is only possible with PCI cards. Please make sure @@ -285,6 +287,7 @@ type 34 Gazel ISDN cards (ISA) pa=irq, pb=io 34 Gazel ISDN cards (PCI) no parameter 35 HFC 2BDS0 PCI no parameter + 36 W6692 based PCI cards none Running the driver ------------------ @@ -425,6 +428,7 @@ Special thanks to: Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE), for ELSA PCMCIA support Enrik Berkhan (enrik@starfleet.inka.de) for S0BOX specific stuff Ton van Rosmalen for Teles PCI + Petr Novak <petr.novak@i.cz> for Winbond W6692 support and more people who are hunting bugs. (If I forgot somebody, please send me a mail). diff --git a/Documentation/isdn/README.avmb1 b/Documentation/isdn/README.avmb1 index 34eee2125b2f47d62b8ac6dcc6669e1c587ebba7..6fa9406dfece99ef3bf1b79809e94932797ae524 100644 --- a/Documentation/isdn/README.avmb1 +++ b/Documentation/isdn/README.avmb1 @@ -169,7 +169,7 @@ capi20 Questions --------- -Check out the FAQ (ftp.franken.de) or subscribe to the +Check out the FAQ (ftp.isdn4linux.de) or subscribe to the linux-avmb1@calle.in-berlin.de mailing list by sending a mail to majordomo@calle.in-berlin.de with subscribe linux-avmb1 diff --git a/Documentation/isdn/README.eicon b/Documentation/isdn/README.eicon index d55cc14ad0052be07415daab1ef612ebb6dca3cb..b40e1ecd23c529a7d0072d47008fe982bb708740 100644 --- a/Documentation/isdn/README.eicon +++ b/Documentation/isdn/README.eicon @@ -1,6 +1,6 @@ -$Id: README.eicon,v 1.4 1999/07/11 17:17:30 armin Exp $ +$Id: README.eicon,v 1.5 1999/10/11 18:13:25 armin Exp $ -(c) 1999 Cytronics & Melware +(c) 1999 Cytronics & Melware (info@melware.de) This document describes the eicon driver for the Eicon.Diehl active ISDN cards. @@ -24,17 +24,26 @@ It is meant to be used with isdn4linux, an ISDN link-level module for Linux. Supported Cards ---------------- +=============== +Old ISA type +------------ - S-Card ISA - SX-Card ISA - SXn-Card ISA - SCOM-Card ISA - Quadro-Card ISA - S2M-Card ISA + +DIVA Server family +------------------ - DIVA Server BRI/PCI 2M - DIVA Server PRI/PCI 2M (9M 23M 30M) - (Only analog modem functions of the DSPs are currently implemented) + supported functions of onboard DSPs: + - analog modem + - fax group 2/3 (Fax Class 2 commands) + - DTMF detection + ISDN D-Channel Protocols ------------------------ @@ -76,6 +85,10 @@ Example for loading and starting a PRI card with E-DSS1 Protocol. Details about using the eiconctrl utility are in 'man eiconctrl' or will be printed by starting eiconctrl without any parameters. +Thanks to + Deutsche Mailbox Saar-Lor-Lux GmbH + for sponsoring and testing fax + capabilities with Diva Server cards. Any reports about bugs, errors and even wishes are welcome. diff --git a/Documentation/isdn/README.fax b/Documentation/isdn/README.fax index 897abd0ef53843521988a6cc92ef7bfc159d33df..eeff9ce9f2c0d983a6a91a94900480760867aaee 100644 --- a/Documentation/isdn/README.fax +++ b/Documentation/isdn/README.fax @@ -9,7 +9,7 @@ This only makes sense under the following conditions : - You need the commands as dummy, because you are using hylafax (with patch) for AVM capi. -- You want to use the fax capabillities of your isdn-card. +- You want to use the fax capabilities of your isdn-card. (supported cards are listed below) @@ -21,8 +21,12 @@ NOTE: This implementation does *not* support fax with passive Supported ISDN-Cards -------------------- -Eicon DIVA Server BRI/PCI (will be ready soon) -Eicon DIVA Server PRI/PCI (will be ready soon) +Eicon DIVA Server BRI/PCI + - full support with both B-channels. + +Eicon DIVA Server PRI/PCI + - full support on amount of B-channels + depending on DSPs on board. diff --git a/Documentation/isdn/README.hfc-pci b/Documentation/isdn/README.hfc-pci index 94e0d4352543ec2d45f4e7715db6316e01a38928..6cc311e359240627ac3518d1dcbf9888c614e212 100644 --- a/Documentation/isdn/README.hfc-pci +++ b/Documentation/isdn/README.hfc-pci @@ -20,6 +20,21 @@ This enables the echo mode. If Hex logging is activated the isdnctrlx devices show a output with a line beginning of HEX: for the providers exchange and ECHO: for isdn devices sending to the provider. +If more than one HFC-PCI cards are installed, a specific card may be selected +at the hisax module load command line. Supply the load command with the desired +IO-address of the desired card. +Example: +There tree cards installed in your machine at IO-base addresses 0xd000, 0xd400 +and 0xdc00 +If you want to use the card at 0xd400 standalone you should supply the insmod +or depmod with type=35 io=0xd400. +If you want to use all three cards, but the order needs to be at 0xdc00,0xd400, +0xd000 you may give the parameters type=35,35,35 io=0xdc00,0xd400,0xd00 +Then the desired card will be the initialised in the desired order. +If the io parameter is used the io addresses of all used cards should be +supplied else the parameter is assumed 0 and a auto search for a free card is +invoked which may not give the wanted result. + Comments and reports to werner@isdn4linux.de or werner@titro.de . diff --git a/Documentation/isdn/README.pcbit b/Documentation/isdn/README.pcbit index fb696422f911193583ae945a39c2334373f165d7..5125002282e5e4129da192477f692c19a6b09b12 100644 --- a/Documentation/isdn/README.pcbit +++ b/Documentation/isdn/README.pcbit @@ -32,7 +32,7 @@ allow normal operation. Plans for the future include cooperation with the manufacturer in order to solve this problem. Information/hints/help can be obtained in the linux isdn -mailing list (isdn4linux@hub-wue.franken.de) or directly from me. +mailing list (isdn4linux@listserv.isdn4linux.de) or directly from me. regards, Pedro. diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt index 9673a46e78fa3b76d29e233255fb8d4b120f2d30..4263c68d5e7088706ca33edf108d3a987b888ad1 100644 --- a/Documentation/oops-tracing.txt +++ b/Documentation/oops-tracing.txt @@ -16,6 +16,37 @@ If you are totally stumped as to whom to send the report, send it to linux-kernel@vger.rutgers.edu. Thanks for your help in making Linux as stable as humanly possible. +Where is the_oops.txt? +---------------------- + +Normally the Oops text is read from the kernel buffers by klogd and +handed to syslogd which writes it to a syslog file, typically +/var/log/messages (depends on /etc/syslog.conf). Sometimes klogd dies, +in which case you can run dmesg > file to read the data from the kernel +buffers and save it. Or you can cat /proc/kmsg > file, however you +have to break in to stop the transfer, kmsg is a "never ending file". +If the machine has crashed so badly that you cannot enter commands or +the disk is not available then you have three options :- + +(1) Hand copy the text from the screen and type it in after the machine + has restarted. Messy but it is the only option if you have not + planned for a crash. + +(2) Boot with a serial console (see Documentation/serial-console.txt), + run a null modem to a second machine and capture the output there + using your favourite communication program. Minicom works well. + +(3) Patch the kernel with one of the crash dump patches. These save + data to a floppy disk or video rom or a swap partition. None of + these are standard kernel patches so you have to find and apply + them yourself. Search kernel archives for kmsgdump, lkcd and + oops+smram. + +No matter how you capture the log output, feed the resulting file to +ksymoops along with /proc/ksyms and /proc/modules that applied at the +time of the crash. /var/log/ksymoops can be useful to capture the +latter, man ksymoops for details. + Full Information ---------------- diff --git a/MAINTAINERS b/MAINTAINERS index 14efbdd5dfb4a9c9abaf4feb3a94c8a9a5c959dd..118d5e64dafe5a1d3d0ddf5836ff0e65f9313095 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -482,10 +482,18 @@ P: Jaroslav Kysela M: perex@suse.cz S: Maintained -ISDN SUBSYSTEM +ISDN SUBSYSTEM (general) P: Fritz Elfert -M: fritz@wuemaus.franken.de -L: isdn4linux@hub-wue.franken.de +M: fritz@isdn4linux.de +L: isdn4linux@listserv.isdn4linux.de +W: http://www.isdn4linux.de +S: Maintained + +ISDN SUBSYSTEM (card drivers) +P: Karsten Keil +M: kkeil@suse.de +L: isdn4linux@listserv.isdn4linux.de +W: http://www.isdn4linux.de S: Maintained JOYSTICK DRIVER diff --git a/Makefile b/Makefile index f40b5f6f571f07e28b3b0cc924ade1ad52a61d86..45a55b331ae7fa50cd7fd31b9b5ea155e3938939 100644 --- a/Makefile +++ b/Makefile @@ -390,6 +390,7 @@ clean: archclean rm -f .tmp* rm -f drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c rm -f drivers/char/conmakehash + rm -f drivers/pci/devlist.h drivers/pci/gen-devlist rm -f drivers/sound/bin2hex drivers/sound/hex2hex rm -f net/khttpd/make_times_h rm -f net/khttpd/times.h diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 9a75fb233bf37043795f699176d5ddbc8262b8f0..cdeaf9a35f822143a7bfa7b7df2e8140c7d79c11 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -1367,8 +1367,10 @@ static int apm(void *unused) /* Install our power off handler.. */ if (power_off_enabled) acpi_power_off = apm_power_off; - sysrq_power_off = apm_power_off; +#ifdef CONFIG_MAGIC_SYSRQ + sysrq_power_off = apm_power_off; +#endif apm_mainloop(); return 0; } diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 7a275f9181f476223135680ed5cc00017af31df9..b21a915aa33e9f6017c753de183c2a18eb629335 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -129,3 +129,4 @@ EXPORT_SYMBOL(mca_is_adapter_used); EXPORT_SYMBOL(screen_info); #endif +EXPORT_SYMBOL(get_wchan); diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index 75659aac40dcd178af7b69152c18122a9342847d..1bccad67bf4aa89a0dcb6891dd8c13dce94157a3 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -650,6 +650,19 @@ int request_irq(unsigned int irq, int retval; struct irqaction * action; +#if 1 + /* + * Sanity-check: shared interrupts should REALLY pass in + * a real dev-ID, otherwise we'll have trouble later trying + * to figure out which interrupt is which (messes up the + * interrupt freeing logic etc). + */ + if (irqflags & SA_SHIRQ) { + if (!dev_id) + printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); + } +#endif + if (irq >= NR_IRQS) return -EINVAL; if (!handler) diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 934fb082eae04ede721dd2d3a34e91c099e65a60..429c4eacd9b12420cc35f4245d8011623810334a 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -685,3 +685,37 @@ asmlinkage int sys_execve(struct pt_regs regs) unlock_kernel(); return error; } + +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long ebp, esp, eip; + unsigned long stack_page; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + stack_page = (unsigned long)p; + esp = p->thread.esp; + if (!stack_page || esp < stack_page || esp > 8188+stack_page) + return 0; + /* include/asm-i386/system.h:switch_to() pushes ebp last. */ + ebp = *(unsigned long *) esp; + do { + if (ebp < stack_page || ebp > 8184+stack_page) + return 0; + eip = *(unsigned long *) (ebp+4); + if (eip < first_sched || eip >= last_sched) + return eip; + ebp = *(unsigned long *) ebp; + } while (count++ < 16); + return 0; +} +#undef last_sched +#undef first_sched diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index b27d120958a75e4c341638d2dad9888299e8952a..a3ee727bde292d2fabea1d60b22145eda867b4a8 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1821,13 +1821,13 @@ int __init amiga_floppy_init(void) return -ENOMEM; } - if (!request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) { + if (request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) { printk("fd: cannot get irq for dma\n"); amiga_chip_free(raw_buf); unregister_blkdev(MAJOR_NR,"fd"); return -EBUSY; } - if (!request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) { + if (request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) { printk("fd: cannot get irq for timer\n"); free_irq(IRQ_AMIGA_DSKBLK, NULL); amiga_chip_free(raw_buf); diff --git a/drivers/char/dn_keyb.c b/drivers/char/dn_keyb.c index 38010e29b63e9846b027b845a9bae0a4336a5853..f663790db122e1789b097d66671bdcf014a7a2e6 100644 --- a/drivers/char/dn_keyb.c +++ b/drivers/char/dn_keyb.c @@ -1,4 +1,3 @@ -#include <linux/types.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/errno.h> @@ -18,8 +17,9 @@ #include <asm/apollohw.h> #include <asm/uaccess.h> +#include "busmouse.h" -extern void handle_scancode(unsigned char); +/* extern void handle_scancode(unsigned char,int ); */ #define DNKEY_CAPS 0x7e #define BREAK_FLAG 0x80 @@ -37,18 +37,12 @@ extern void handle_scancode(unsigned char); #define APOLLO_KBD_MODE_MOUSE 0x02 #define APOLLO_KBD_MODE_CHANGE 0xff -#define MSE_UPDATE_ON() mouse_update_allowed=1 -#define MSE_UPDATE_OFF() mouse_update_allowed=0 - static u_char keyb_cmds[APOLLO_KEYB_CMD_ENTRIES]; static short keyb_cmd_read=0, keyb_cmd_write=0; static int keyb_cmd_transmit=0; +static int msedev; static unsigned int kbd_mode=APOLLO_KBD_MODE_KEYB; -static short mouse_dx,mouse_dy,mouse_buttons; -static int mouse_ready=0,mouse_update_allowed=0,mouse_active=0; -static DECLARE_WAIT_QUEUE_HEAD(mouse_wait); -static struct fasync_struct *mouse_fasyncptr=NULL; #if 0 static void debug_keyb_timer_handler(unsigned long ignored); @@ -302,103 +296,6 @@ static void debug_keyb_timer_handler(unsigned long ignored) { } #endif -static unsigned int mouse_poll(struct file *file, poll_table * wait) -{ - poll_wait(&mouse_wait, wait); - if (mouse_ready) - return POLLIN | POLLRDNORM; - return 0; -} - -static ssize_t write_mouse(struct file * file, const char * buffer, - size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -static ssize_t read_mouse(struct file * file, char * buffer, - size_t count, loff_t *ppos) -{ - int dx,dy,r; - unsigned char buttons; - - if (count < 3) - return -EINVAL; - if ((r = verify_area(VERIFY_WRITE, buffer, count))) - return r; - if (!mouse_ready) - return -EAGAIN; - - MSE_UPDATE_OFF(); - dx=mouse_dx; - dy=mouse_dy; - if (dx < -127) - dx = -127; - else - if (dx > 127) - dx = 127; - if (dy < -127) - dy = -127; - else - if (dy > 127) - dy = 127; - buttons=(mouse_buttons & 1 ? 4 : 0) | - (mouse_buttons & 2 ? 1 : 0) | - (mouse_buttons & 4 ? 2 : 0); - - mouse_dx-=dx; - mouse_dy-=dy; - MSE_UPDATE_ON(); - - if (put_user(buttons | 0x80, buffer++) || - put_user((char)dx, buffer++) || - put_user((char)dy, buffer++)) - return -EINVAL; - - if (count > 3) - if (clear_user(buffer, count - 3)) - return -EFAULT; - return count; -} - -static int fasync_mouse(int fd, struct file *filp, int on) -{ - int retval; - - retval = fasync_helper(fd, filp, on, &mouse_fasyncptr); - if (retval < 0) - return retval; - return 0; -} - - -static int release_mouse(struct inode * inode, struct file * file) -{ - fasync_mouse(-1, file, 0); - if (--mouse_active) - return 0; - MSE_UPDATE_OFF(); - MOD_DEC_USE_COUNT; - return 0; -} - -static int open_mouse(struct inode * inode, struct file * file) -{ - if (mouse_active++) - return 0; - /* - * use VBL to poll mouse deltas - */ - - mouse_dx = 0; - mouse_dy = 0; - mouse_buttons = 0; - mouse_active = 1; - MOD_INC_USE_COUNT; - MSE_UPDATE_ON(); - return 0; -} - static void dn_keyb_process_key_event(unsigned char scancode) { static unsigned char lastscancode; @@ -411,7 +308,7 @@ static void dn_keyb_process_key_event(unsigned char scancode) { if(prev_scancode==APOLLO_KBD_MODE_CHANGE) { kbd_mode=scancode; -/* printk("modechange: %d\n",scancode);*/ +/* printk("modechange: %d\n",scancode); */ } else if((scancode & (~BREAK_FLAG)) == DNKEY_CAPS) { /* printk("handle_scancode: %02x\n",DNKEY_CAPS); */ @@ -440,7 +337,8 @@ static void dn_keyb_process_mouse_event(unsigned char mouse_data) { static short mouse_byte_count=0; static u_char mouse_packet[3]; - + short mouse_buttons; + mouse_packet[mouse_byte_count++]=mouse_data; if(mouse_byte_count==3) { @@ -552,23 +450,20 @@ void write_keyb_cmd(u_short length, u_char *cmd) { } -struct file_operations apollo_mouse_fops = { - NULL, /* mouse_seek */ - read_mouse, - write_mouse, - NULL, /* mouse_readdir */ - mouse_poll, /* mouse_poll */ - NULL, /* mouse_ioctl */ - NULL, /* mouse_mmap */ - open_mouse, - NULL, /* flush */ - release_mouse, - NULL, - fasync_mouse, -}; +static int release_mouse(struct inode * inode, struct file * file) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static int open_mouse(struct inode * inode, struct file * file) +{ + MOD_INC_USE_COUNT; + return 0; +} -static struct miscdevice apollo_mouse = { - APOLLO_MOUSE_MINOR, "apollomouse", &apollo_mouse_fops +static struct busmouse apollo_mouse = { + APOLLO_MOUSE_MINOR, "apollomouse", open_mouse, release_mouse,7 }; int __init dn_keyb_init(void){ @@ -583,12 +478,12 @@ int __init dn_keyb_init(void){ memcpy(key_maps[8], dnalt_map, sizeof(plain_map)); memcpy(key_maps[12], dnctrl_alt_map, sizeof(plain_map)); - mouse_dx=0; - mouse_dy=0; - mouse_buttons=0; - mouse_wait=NULL; - misc_register(&apollo_mouse); + msedev=register_busmouse(&apollo_mouse); + if (msedev < 0) + printk(KERN_WARNING "Unable to install Apollo mouse driver.\n"); + else + printk(KERN_INFO "Apollo mouse installed.\n"); /* program UpDownMode */ diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 30a76a04ea6c2674dcf21ce88590f66ed194b2b1..bce9c6e02f806ccc6adbe603882d115084e1b4eb 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -73,13 +73,13 @@ m = min(count, maxio); \ for (i = 0; i < m; i++) { \ for (t = 0; t < timeout && !ENABLE; t++) \ - wait_some(2); \ + wait_some(HZ/50); \ if(!ENABLE) \ return -EIO; \ f; \ } \ count -= m; \ - if (m == maxio) wait_some(2); \ + if (m == maxio) wait_some(HZ/50); \ } \ } @@ -87,7 +87,7 @@ { \ int t; \ for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \ - wait_some(1); \ + wait_some(HZ/100); \ if(!DSP56K_TRANSMIT) { \ return -EIO; \ } \ @@ -97,7 +97,7 @@ { \ int t; \ for(t = 0; t < n && !DSP56K_RECEIVE; t++) \ - wait_some(1); \ + wait_some(HZ/100); \ if(!DSP56K_RECEIVE) { \ return -EIO; \ } \ diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 5935ea1227137a842700986204eb9c892cd2fbc5..5f19cfe55d6418773306bf823703d182fb9c2b7c 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -509,10 +509,10 @@ static int pp_open (struct inode * inode, struct file * file) if (!pp) return -ENOMEM; - memset (pp, 0, sizeof (struct pp_struct)); pp->state.mode = IEEE1284_MODE_COMPAT; pp->state.phase = init_phase (pp->state.mode); pp->flags = 0; + pp->irqresponse = 0; atomic_set (&pp->irqc, 0); init_waitqueue_head (&pp->irq_wait); @@ -539,8 +539,9 @@ static int pp_release (struct inode * inode, struct file * file) } if (pp->pdev) { + const char *name = pp->pdev->name; parport_unregister_device (pp->pdev); - kfree (pp->pdev->name); + kfree (name); pp->pdev = NULL; printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n", minor); diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in index 52b80809b39032e48389d5b521febc17257ce747..e88f5da946f9923bb12a477ce05360671c567952 100644 --- a/drivers/isdn/Config.in +++ b/drivers/isdn/Config.in @@ -2,76 +2,78 @@ # ISDN device configuration # 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 - fi + 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 + fi fi -bool ' Support audio via ISDN' CONFIG_ISDN_AUDIO +bool 'Support audio via ISDN' CONFIG_ISDN_AUDIO if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then - bool ' Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX + bool 'Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX fi -bool ' Support isdn diversion services' CONFIG_ISDN_DIVERSION -if [ "$CONFIG_X25" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25 +bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION +if [ "$CONFIG_X25" != "n" ]; then + bool 'X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25 fi -dep_tristate ' ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN -dep_tristate ' isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN -dep_tristate ' PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN -dep_tristate ' HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN +dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN +dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN +dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN +dep_tristate 'HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then - bool ' HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO - if [ "$CONFIG_HISAX_EURO" != "n" ]; then - bool ' Support for german chargeinfo' CONFIG_DE_AOC - bool ' Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE - bool ' Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC - fi - bool ' HiSax Support for german 1TR6' CONFIG_HISAX_1TR6 - bool ' HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0 - bool ' HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3 - bool ' HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI - bool ' HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX - bool ' HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1 - bool ' HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI - bool ' HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA - bool ' HiSax Support for Elsa cards' CONFIG_HISAX_ELSA - bool ' HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2 - bool ' HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA - bool ' HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM - bool ' HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT - bool ' HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS - bool ' HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER - bool ' HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER - bool ' HiSax Support for MIC card' CONFIG_HISAX_MIC - bool ' HiSax Support for NETjet card' CONFIG_HISAX_NETJET - bool ' HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY - bool ' HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF - bool ' HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR - bool ' HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T - bool ' HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO - bool ' HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL - bool ' HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI - if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then -# bool ' HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU - if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then - bool ' HiSax Support for Am7930' CONFIG_HISAX_AMD7930 - fi - fi + bool 'HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO + if [ "$CONFIG_HISAX_EURO" != "n" ]; then + bool 'Support for german chargeinfo' CONFIG_DE_AOC + bool 'Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE + bool 'Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC + fi + bool 'HiSax Support for german 1TR6' CONFIG_HISAX_1TR6 + bool 'HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0 + bool 'HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3 + bool 'HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI + bool 'HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX + bool 'HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1 + bool 'HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI + bool 'HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA + bool 'HiSax Support for Elsa cards' CONFIG_HISAX_ELSA + bool 'HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2 + bool 'HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA + bool 'HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM + bool 'HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT + bool 'HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS + bool 'HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER + bool 'HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER + bool 'HiSax Support for MIC card' CONFIG_HISAX_MIC + bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET + bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY + bool 'HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF + bool 'HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR + bool 'HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T + bool 'HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO + bool 'HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL + bool 'HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI + if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then + bool 'HiSax Support for Winbond W6692 based cards (EXPERIMENTAL)' CONFIG_HISAX_W6692 +# bool 'HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU + if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then + bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930 + fi + fi fi 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 + 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 ' Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN +dep_tristate 'Eicon.Diehl 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 + bool 'Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA fi -dep_tristate ' AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN +dep_tristate 'AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then - bool ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA - bool ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI - bool ' AVM T1/T1B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA - bool ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON + bool 'AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA + bool 'AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI + 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 + bool 'Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON fi diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c index 80f06b0808132b29ae6409ad8f938a26f10dd57c..99c93dbed6ec808bbeda19b0c7d4e9e771d095c8 100644 --- a/drivers/isdn/act2000/act2000_isa.c +++ b/drivers/isdn/act2000/act2000_isa.c @@ -1,4 +1,4 @@ -/* $Id: act2000_isa.c,v 1.8 1999/01/05 18:29:25 he Exp $ +/* $Id: act2000_isa.c,v 1.10 1999/10/24 18:46:05 fritz Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). * @@ -20,6 +20,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: act2000_isa.c,v $ + * Revision 1.10 1999/10/24 18:46:05 fritz + * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest + * kernels. + * + * Revision 1.9 1999/09/04 06:20:04 keil + * Changes from kernel set_current_state() + * * Revision 1.8 1999/01/05 18:29:25 he * merged remaining schedule_timeout() changes from 2.1.127 * @@ -61,17 +68,17 @@ static act2000_card *irq2card_map[16] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static int isa_irqs[] = +static int act2000_isa_irqs[] = { 3, 5, 7, 10, 11, 12, 15 }; -#define ISA_NRIRQS (sizeof(isa_irqs)/sizeof(int)) +#define ISA_NRIRQS (sizeof(act2000_isa_irqs)/sizeof(int)) static void -isa_delay(long t) +act2000_isa_delay(long t) { sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(t); sti(); } @@ -83,7 +90,7 @@ isa_delay(long t) * 0 = Signature not found. */ static int -isa_reset(unsigned short portbase) +act2000_isa_reset(unsigned short portbase) { unsigned char reg; int i; @@ -109,7 +116,7 @@ isa_reset(unsigned short portbase) } int -isa_detect(unsigned short portbase) +act2000_isa_detect(unsigned short portbase) { int ret = 0; unsigned long flags; @@ -117,13 +124,13 @@ isa_detect(unsigned short portbase) save_flags(flags); cli(); if (!check_region(portbase, ISA_REGION)) - ret = isa_reset(portbase); + ret = act2000_isa_reset(portbase); restore_flags(flags); return ret; } static void -isa_interrupt(int irq, void *dev_id, struct pt_regs *regs) +act2000_isa_interrupt(int irq, void *dev_id, struct pt_regs *regs) { act2000_card *card = irq2card_map[irq]; u_char istatus; @@ -138,7 +145,7 @@ isa_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* RX fifo has data */ istatus &= ISA_ISR_OUT_MASK; outb(0, ISA_PORT_SIS); - isa_receive(card); + act2000_isa_receive(card); outb(ISA_SIS_INT, ISA_PORT_SIS); } if (istatus & ISA_ISR_ERR) { @@ -151,7 +158,7 @@ isa_interrupt(int irq, void *dev_id, struct pt_regs *regs) } static void -isa_select_irq(act2000_card * card) +act2000_isa_select_irq(act2000_card * card) { unsigned char reg; @@ -183,9 +190,9 @@ isa_select_irq(act2000_card * card) } static void -isa_enable_irq(act2000_card * card) +act2000_isa_enable_irq(act2000_card * card) { - isa_select_irq(card); + act2000_isa_select_irq(card); /* Enable READ irq */ outb(ISA_SIS_INT, ISA_PORT_SIS); } @@ -195,7 +202,7 @@ isa_enable_irq(act2000_card * card) * If irq is -1, choose next free irq, else irq is given explicitely. */ int -isa_config_irq(act2000_card * card, short irq) +act2000_isa_config_irq(act2000_card * card, short irq) { int i; unsigned long flags; @@ -213,8 +220,8 @@ isa_config_irq(act2000_card * card, short irq) if (irq == -1) { /* Auto select */ for (i = 0; i < ISA_NRIRQS; i++) { - if (!request_irq(isa_irqs[i], &isa_interrupt, 0, card->regname, NULL)) { - card->irq = isa_irqs[i]; + if (!request_irq(act2000_isa_irqs[i], &act2000_isa_interrupt, 0, card->regname, NULL)) { + card->irq = act2000_isa_irqs[i]; irq2card_map[card->irq] = card; card->flags |= ACT2000_FLAGS_IVALID; break; @@ -222,7 +229,7 @@ isa_config_irq(act2000_card * card, short irq) } } else { /* Fixed irq */ - if (!request_irq(irq, &isa_interrupt, 0, card->regname, NULL)) { + if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) { card->irq = irq; irq2card_map[card->irq] = card; card->flags |= ACT2000_FLAGS_IVALID; @@ -234,7 +241,7 @@ isa_config_irq(act2000_card * card, short irq) "act2000: Could not request irq\n"); return -EBUSY; } else { - isa_select_irq(card); + act2000_isa_select_irq(card); /* Disable READ and WRITE irq */ outb(0, ISA_PORT_SIS); outb(0, ISA_PORT_SOS); @@ -243,7 +250,7 @@ isa_config_irq(act2000_card * card, short irq) } int -isa_config_port(act2000_card * card, unsigned short portbase) +act2000_isa_config_port(act2000_card * card, unsigned short portbase) { if (card->flags & ACT2000_FLAGS_PVALID) { release_region(card->port, ISA_REGION); @@ -262,7 +269,7 @@ isa_config_port(act2000_card * card, unsigned short portbase) * Release ressources, used by an adaptor. */ void -isa_release(act2000_card * card) +act2000_isa_release(act2000_card * card) { unsigned long flags; @@ -280,7 +287,7 @@ isa_release(act2000_card * card) } static int -isa_writeb(act2000_card * card, u_char data) +act2000_isa_writeb(act2000_card * card, u_char data) { u_char timeout = 40; @@ -297,7 +304,7 @@ isa_writeb(act2000_card * card, u_char data) } static int -isa_readb(act2000_card * card, u_char * data) +act2000_isa_readb(act2000_card * card, u_char * data) { u_char timeout = 40; @@ -314,13 +321,13 @@ isa_readb(act2000_card * card, u_char * data) } void -isa_receive(act2000_card *card) +act2000_isa_receive(act2000_card *card) { u_char c; if (test_and_set_bit(ACT2000_LOCK_RX, (void *) &card->ilock) != 0) return; - while (!isa_readb(card, &c)) { + while (!act2000_isa_readb(card, &c)) { if (card->idat.isa.rcvidx < 8) { card->idat.isa.rcvhdr[card->idat.isa.rcvidx++] = c; if (card->idat.isa.rcvidx == 8) { @@ -332,7 +339,7 @@ isa_receive(act2000_card *card) if (card->idat.isa.rcvskb == NULL) { card->idat.isa.rcvignore = 1; printk(KERN_WARNING - "isa_receive: no memory\n"); + "act2000_isa_receive: no memory\n"); test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock); return; } @@ -341,12 +348,12 @@ isa_receive(act2000_card *card) } else { card->idat.isa.rcvidx = 0; printk(KERN_WARNING - "isa_receive: Invalid CAPI msg\n"); + "act2000_isa_receive: Invalid CAPI msg\n"); { int i; __u8 *p; __u8 *c; __u8 tmp[30]; for (i = 0, p = (__u8 *)&card->idat.isa.rcvhdr, c = tmp; i < 8; i++) c += sprintf(c, "%02x ", *(p++)); - printk(KERN_WARNING "isa_receive: %s\n", tmp); + printk(KERN_WARNING "act2000_isa_receive: %s\n", tmp); } } } @@ -377,7 +384,7 @@ isa_receive(act2000_card *card) } void -isa_send(act2000_card * card) +act2000_isa_send(act2000_card * card) { unsigned long flags; struct sk_buff *skb; @@ -410,11 +417,8 @@ isa_send(act2000_card * card) skb = card->sbuf; l = 0; while (skb->len) { - if (isa_writeb(card, *(skb->data))) { + if (act2000_isa_writeb(card, *(skb->data))) { /* Fifo is full, but more data to send */ -#if 0 - printk(KERN_DEBUG "isa_send: %d bytes\n", l); -#endif test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock); /* Schedule myself */ act2000_schedule_tx(card); @@ -437,9 +441,6 @@ isa_send(act2000_card * card) } else dev_kfree_skb(skb); card->sbuf = NULL; -#if 0 - printk(KERN_DEBUG "isa_send: %d bytes\n", l); -#endif } } @@ -447,7 +448,7 @@ isa_send(act2000_card * card) * Get firmware ID, check for 'ISDN' signature. */ static int -isa_getid(act2000_card * card) +act2000_isa_getid(act2000_card * card) { act2000_fwid fid; @@ -457,7 +458,7 @@ isa_getid(act2000_card * card) while (1) { if (count > 510) return -EPROTO; - if (isa_readb(card, p++)) + if (act2000_isa_readb(card, p++)) break; count++; } @@ -476,7 +477,7 @@ isa_getid(act2000_card * card) printk(KERN_INFO "act2000: Firmware-ID: %s\n", fid.revision); if (card->flags & ACT2000_FLAGS_IVALID) { printk(KERN_DEBUG "Enabling Interrupts ...\n"); - isa_enable_irq(card); + act2000_isa_enable_irq(card); } return 0; } @@ -485,7 +486,7 @@ isa_getid(act2000_card * card) * Download microcode into card, check Firmware signature. */ int -isa_download(act2000_card * card, act2000_ddef * cb) +act2000_isa_download(act2000_card * card, act2000_ddef * cb) { int length; int ret; @@ -497,9 +498,9 @@ isa_download(act2000_card * card, act2000_ddef * cb) u_char *buf; act2000_ddef cblock; - if (!isa_reset(card->port)) + if (!act2000_isa_reset(card->port)) return -ENXIO; - isa_delay(HZ / 2); + act2000_isa_delay(HZ / 2); if ((ret = verify_area(VERIFY_READ, (void *) cb, sizeof(cblock)))) return ret; copy_from_user(&cblock, (char *) cb, sizeof(cblock)); @@ -517,7 +518,7 @@ isa_download(act2000_card * card, act2000_ddef * cb) b = buf; copy_from_user(buf, p, l); while (c < l) { - if (isa_writeb(card, *b++)) { + if (act2000_isa_writeb(card, *b++)) { printk(KERN_WARNING "act2000: loader timed out" " len=%d c=%d\n", length, c); @@ -530,6 +531,6 @@ isa_download(act2000_card * card, act2000_ddef * cb) p += l; } kfree(buf); - isa_delay(HZ / 2); - return (isa_getid(card)); + act2000_isa_delay(HZ / 2); + return (act2000_isa_getid(card)); } diff --git a/drivers/isdn/act2000/act2000_isa.h b/drivers/isdn/act2000/act2000_isa.h index 35a68e7d2ca04092f1edb49c51c077feca9bc10d..ff3e5419aeb7f3f3fb4ac0c2c84ab8c4a4ef926d 100644 --- a/drivers/isdn/act2000/act2000_isa.h +++ b/drivers/isdn/act2000/act2000_isa.h @@ -1,4 +1,4 @@ -/* $Id: act2000_isa.h,v 1.2 1998/11/05 22:12:43 fritz Exp $ +/* $Id: act2000_isa.h,v 1.3 1999/10/24 18:46:05 fritz Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). * @@ -20,6 +20,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: act2000_isa.h,v $ + * Revision 1.3 1999/10/24 18:46:05 fritz + * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest + * kernels. + * * Revision 1.2 1998/11/05 22:12:43 fritz * Changed mail-address. * @@ -141,12 +145,12 @@ typedef enum { /* Prototypes */ -extern int isa_detect(unsigned short portbase); -extern int isa_config_irq(act2000_card * card, short irq); -extern int isa_config_port(act2000_card * card, unsigned short portbase); -extern int isa_download(act2000_card * card, act2000_ddef * cb); -extern void isa_release(act2000_card * card); -extern void isa_receive(act2000_card *card); -extern void isa_send(act2000_card *card); +extern int act2000_isa_detect(unsigned short portbase); +extern int act2000_isa_config_irq(act2000_card * card, short irq); +extern int act2000_isa_config_port(act2000_card * card, unsigned short portbase); +extern int act2000_isa_download(act2000_card * card, act2000_ddef * cb); +extern void act2000_isa_release(act2000_card * card); +extern void act2000_isa_receive(act2000_card *card); +extern void act2000_isa_send(act2000_card *card); #endif /* act2000_isa_h */ diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c index df2fd68d33a29cf32bfa90ee74c735f9391fef24..9502b314e1c370962992195e0bb0e9810352cb2c 100644 --- a/drivers/isdn/act2000/capi.c +++ b/drivers/isdn/act2000/capi.c @@ -113,10 +113,6 @@ static actcapi_msgdsc valid_msg[] = { {{ 0x84, 0x03}, "DISCONNECT_B3_RESP"}, {{ 0x86, 0x03}, "DATA_B3_RESP"}, {{ 0xff, 0x03}, "MANUFACTURER_RESP"}, -#if 0 -/* CAPI 2.0 */ - {{ 0x05, 0x80}, "LISTEN_REQ (CAPI 2.0)"}, -#endif #endif {{ 0x00, 0x00}, NULL}, }; diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h index 69a1041005ffc1cb6394a92bdacbc8eeb7109e33..0500550db90f7b0a328d0e03fd6a9e185449173a 100644 --- a/drivers/isdn/act2000/capi.h +++ b/drivers/isdn/act2000/capi.h @@ -322,19 +322,6 @@ typedef struct actcapi_msg { __u16 plci; __u16 info; } select_b3_protocol_conf; -#if 0 - struct listen_req { - __u32 controller; - __u32 infomask; - __u32 cipmask; - __u32 cipmask2; - __u16 dummy; /* 2 Length-bytes of 2 Structs MUST always be 0!!! */ - } listen_req; - struct listen_conf { - __u32 controller; - __u16 info; - } listen_conf; -#else struct listen_req { __u8 controller; __u32 infomask __attribute__ ((packed)); @@ -345,7 +332,6 @@ typedef struct actcapi_msg { __u8 controller; __u16 info __attribute__ ((packed)); } listen_conf; -#endif struct data_b3_req { __u16 fakencci; __u16 datalen; diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index 2ec5e2fd4132a73ab0d6fe899338b5afddeef87e..f152792532ad88a274da22bc8ca3d514dc794c64 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c @@ -1,4 +1,4 @@ -/* $Id: module.c,v 1.9 1999/04/12 13:13:56 fritz Exp $ +/* $Id: module.c,v 1.11 1999/10/30 09:48:04 keil Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * @@ -20,6 +20,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: module.c,v $ + * Revision 1.11 1999/10/30 09:48:04 keil + * miss one prefix act2000 + * + * Revision 1.10 1999/10/24 18:46:05 fritz + * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest + * kernels. + * * Revision 1.9 1999/04/12 13:13:56 fritz * Made cards pointer static to avoid name-clash. * @@ -56,12 +63,12 @@ #include "act2000_isa.h" #include "capi.h" -static unsigned short isa_ports[] = +static unsigned short act2000_isa_ports[] = { 0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380, 0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60, }; -#define ISA_NRPORTS (sizeof(isa_ports)/sizeof(unsigned short)) +#define ISA_NRPORTS (sizeof(act2000_isa_ports)/sizeof(unsigned short)) static act2000_card *cards = (act2000_card *) NULL; @@ -238,7 +245,7 @@ act2000_transmit(struct act2000_card *card) { switch (card->bus) { case ACT2000_BUS_ISA: - isa_send(card); + act2000_isa_send(card); break; case ACT2000_BUS_PCMCIA: case ACT2000_BUS_MCA: @@ -253,7 +260,7 @@ act2000_receive(struct act2000_card *card) { switch (card->bus) { case ACT2000_BUS_ISA: - isa_receive(card); + act2000_isa_receive(card); break; case ACT2000_BUS_PCMCIA: case ACT2000_BUS_MCA: @@ -296,7 +303,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) case ACT2000_IOCTL_LOADBOOT: switch (card->bus) { case ACT2000_BUS_ISA: - ret = isa_download(card, + ret = act2000_isa_download(card, (act2000_ddef *)a); if (!ret) { card->flags |= ACT2000_FLAGS_LOADED; @@ -701,10 +708,6 @@ act2000_alloccard(int bus, int port, int irq, char *id) card->interface.features = ISDN_FEATURE_L2_X75I | ISDN_FEATURE_L2_HDLC | -#if 0 -/* Not yet! New Firmware is on the way ... */ - ISDN_FEATURE_L2_TRANS | -#endif ISDN_FEATURE_L3_TRANS | ISDN_FEATURE_P_UNKNOWN; card->interface.hl_hdrlen = 20; @@ -762,7 +765,7 @@ unregister_card(act2000_card * card) card->interface.statcallb(&cmd); switch (card->bus) { case ACT2000_BUS_ISA: - isa_release(card); + act2000_isa_release(card); break; case ACT2000_BUS_MCA: case ACT2000_BUS_PCMCIA: @@ -796,11 +799,11 @@ act2000_addcard(int bus, int port, int irq, char *id) switch (bus) { case ACT2000_BUS_ISA: for (i = 0; i < ISA_NRPORTS; i++) - if (isa_detect(isa_ports[i])) { + if (act2000_isa_detect(act2000_isa_ports[i])) { printk(KERN_INFO "act2000: Detected ISA card at port 0x%x\n", - isa_ports[i]); - act2000_alloccard(bus, isa_ports[i], irq, id); + act2000_isa_ports[i]); + act2000_alloccard(bus, act2000_isa_ports[i], irq, id); } break; case ACT2000_BUS_MCA: @@ -823,10 +826,10 @@ act2000_addcard(int bus, int port, int irq, char *id) added++; switch (p->bus) { case ACT2000_BUS_ISA: - if (isa_detect(p->port)) { + if (act2000_isa_detect(p->port)) { if (act2000_registercard(p)) break; - if (isa_config_port(p, p->port)) { + if (act2000_isa_config_port(p, p->port)) { printk(KERN_WARNING "act2000: Could not request port 0x%04x\n", p->port); @@ -834,7 +837,7 @@ act2000_addcard(int bus, int port, int irq, char *id) p->interface.statcallb = NULL; break; } - if (isa_config_irq(p, p->irq)) { + if (act2000_isa_config_irq(p, p->irq)) { printk(KERN_INFO "act2000: No IRQ available, fallback to polling\n"); /* Fall back to polled operation */ diff --git a/drivers/isdn/avmb1/Makefile b/drivers/isdn/avmb1/Makefile index 9f73ea2e3699e358b0bdfa68ea82d7e0ccbf9661..111c39466fb9409eeb0721dbd33fa1d8e6e9db90 100644 --- a/drivers/isdn/avmb1/Makefile +++ b/drivers/isdn/avmb1/Makefile @@ -1,5 +1,5 @@ # -# $Id: Makefile,v 1.6 1999/07/20 06:41:44 calle Exp $ +# $Id: Makefile,v 1.7 1999/09/15 08:16:03 calle Exp $ # # Makefile for the CAPI and AVM-B1 device drivers. # @@ -11,6 +11,9 @@ # parent makes.. # # $Log: Makefile,v $ +# 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. @@ -90,6 +93,12 @@ ifeq ($(CONFIG_ISDN_DRV_AVMB1),y) ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA OX_OBJS += b1pcmcia.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 else ifeq ($(CONFIG_ISDN_DRV_AVMB1),m) @@ -105,10 +114,16 @@ else ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA M_OBJS += t1isa.o endif - MX_OBJS += capiutil.o capidrv.o b1.o ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA MX_OBJS += b1pcmcia.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 endif endif diff --git a/drivers/isdn/avmb1/avmcard.h b/drivers/isdn/avmb1/avmcard.h index e94c5637cdec2f24e0decc4527cb8beeea92a88d..f4b5df6891194afdf72df6402317001633862e1b 100644 --- a/drivers/isdn/avmb1/avmcard.h +++ b/drivers/isdn/avmb1/avmcard.h @@ -1,9 +1,21 @@ /* - * $Id: avmcard.h,v 1.4 1999/08/04 10:10:08 calle Exp $ + * $Id: avmcard.h,v 1.6 1999/11/05 16:38:01 calle Exp $ * * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: avmcard.h,v $ + * Revision 1.6 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.5 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.4 1999/08/04 10:10:08 calle * Bugfix: corrected /proc functions, added structure for new AVM cards. * @@ -73,6 +85,7 @@ typedef struct avmcard_dmainfo { __u8 sendbuf[128+2048]; } avmcard_dmainfo; + typedef struct avmcard { char name[32]; unsigned int port; @@ -81,25 +94,34 @@ typedef struct avmcard { enum avmcardtype cardtype; int cardnr; /* for t1isa */ - int versionlen; - char versionbuf[1024]; - char *version[AVM_MAXVERSION]; - - char cardname[32]; - - char infobuf[128]; /* for function procinfo */ char msgbuf[128]; /* capimsg msg part */ char databuf[2048]; /* capimsg data part */ int interrupt; void *mbase; - __u32 csr; + volatile __u32 csr; avmcard_dmainfo *dma; - struct capi_ctr *ctrl; + struct avmctrl_info { + char cardname[32]; + + int versionlen; + char versionbuf[1024]; + char *version[AVM_MAXVERSION]; + + char infobuf[128]; /* for function procinfo */ + + struct avmcard *card; + struct capi_ctr *capi_ctrl; + + } *ctrlinfo; + + int nlogcontr; } avmcard; +typedef struct avmctrl_info avmctrl_info; + extern int b1_irq_table[16]; /* @@ -540,16 +562,16 @@ static inline void b1_setinterrupt(unsigned int base, unsigned irq, } int b1_detect(unsigned int base, enum avmcardtype cardtype); -int b1_load_t4file(unsigned int base, capiloaddatapart * t4file); -int b1_load_config(unsigned int base, capiloaddatapart * config); -int b1_loaded(unsigned int base); +int b1_load_t4file(avmcard *card, capiloaddatapart * t4file); +int b1_load_config(avmcard *card, capiloaddatapart * config); +int b1_loaded(avmcard *card); int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); void b1_reset_ctr(struct capi_ctr *ctrl); void b1_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp); void b1_release_appl(struct capi_ctr *ctrl, __u16 appl); void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -void b1_parse_version(avmcard *card); +void b1_parse_version(avmctrl_info *card); void b1_handle_interrupt(avmcard * card); int b1ctl_read_proc(char *page, char **start, off_t off, diff --git a/drivers/isdn/avmb1/b1.c b/drivers/isdn/avmb1/b1.c index c4dffdacbc7484c6da9c446b936663e3d45c7f54..900b31c8c1632a0475ae0199482dcaab2f5b4020 100644 --- a/drivers/isdn/avmb1/b1.c +++ b/drivers/isdn/avmb1/b1.c @@ -1,11 +1,29 @@ /* - * $Id: b1.c,v 1.8 1999/08/22 20:26:22 calle Exp $ + * $Id: b1.c,v 1.12 1999/11/05 16:38:01 calle Exp $ * * Common module for AVM B1 cards. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1.c,v $ + * Revision 1.12 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.11 1999/10/11 22:04:12 keil + * COMPAT_NEED_UACCESS (no include in isdn_compat.h) + * + * Revision 1.10 1999/09/15 08:16:03 calle + * Implementation of 64Bit extention complete. + * + * Revision 1.9 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.8 1999/08/22 20:26:22 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -62,13 +80,13 @@ #include <linux/ioport.h> #include <linux/capi.h> #include <asm/io.h> -#include <linux/isdn_compat.h> +#include <asm/uaccess.h> #include "capilli.h" #include "avmcard.h" #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.8 $"; +static char *revision = "$Revision: 1.12 $"; /* ------------------------------------------------------------- */ @@ -140,11 +158,12 @@ int b1_detect(unsigned int base, enum avmcardtype cardtype) return 0; } -int b1_load_t4file(unsigned int base, capiloaddatapart * t4file) +int b1_load_t4file(avmcard *card, capiloaddatapart * t4file) { unsigned char buf[256]; unsigned char *dp; int i, left, retval; + unsigned int base = card->port; dp = t4file->data; left = t4file->len; @@ -158,7 +177,8 @@ int b1_load_t4file(unsigned int base, capiloaddatapart * t4file) } for (i = 0; i < sizeof(buf); i++) if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n"); + printk(KERN_ERR "%s: corrupted firmware file ?\n", + card->name); return -EIO; } left -= sizeof(buf); @@ -174,17 +194,19 @@ int b1_load_t4file(unsigned int base, capiloaddatapart * t4file) } for (i = 0; i < left; i++) if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n"); + printk(KERN_ERR "%s: corrupted firmware file ?\n", + card->name); return -EIO; } } return 0; } -int b1_load_config(unsigned int base, capiloaddatapart * config) +int b1_load_config(avmcard *card, capiloaddatapart * config) { unsigned char buf[256]; unsigned char *dp; + unsigned int base = card->port; int i, j, left, retval; dp = config->data; @@ -233,8 +255,9 @@ int b1_load_config(unsigned int base, capiloaddatapart * config) return 0; } -int b1_loaded(unsigned int base) +int b1_loaded(avmcard *card) { + unsigned int base = card->port; unsigned long stop; unsigned char ans; unsigned long tout = 2; @@ -244,7 +267,8 @@ int b1_loaded(unsigned int base) break; } if (!b1_tx_empty(base)) { - printk(KERN_ERR "b1_loaded: tx err, corrupted t4 file ?\n"); + printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n", + card->name); return 0; } b1_put_byte(base, SEND_POLL); @@ -253,11 +277,12 @@ int b1_loaded(unsigned int base) if ((ans = b1_get_byte(base)) == RECEIVE_POLL) { return 1; } - printk(KERN_ERR "b1_loaded: got 0x%x, firmware not running\n", ans); + printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n", + card->name, ans); return 0; } } - printk(KERN_ERR "b1_loaded: firmware not running\n"); + printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name); return 0; } @@ -265,14 +290,15 @@ int b1_loaded(unsigned int base) int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; int retval; b1_reset(port); - if ((retval = b1_load_t4file(port, &data->firmware))) { + if ((retval = b1_load_t4file(card, &data->firmware))) { b1_reset(port); printk(KERN_ERR "%s: failed to load t4file!!\n", card->name); @@ -282,7 +308,7 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) b1_disable_irq(port); if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(port, &data->configuration))) { + if ((retval = b1_load_config(card, &data->configuration))) { b1_reset(port); printk(KERN_ERR "%s: failed to load config!!\n", card->name); @@ -290,7 +316,7 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) } } - if (!b1_loaded(port)) { + if (!b1_loaded(card)) { printk(KERN_ERR "%s: failed to load t4file.\n", card->name); return -EIO; } @@ -309,13 +335,14 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) void b1_reset_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; b1_reset(port); b1_reset(port); - memset(card->version, 0, sizeof(card->version)); + memset(cinfo->version, 0, sizeof(cinfo->version)); ctrl->reseted(ctrl); } @@ -323,7 +350,8 @@ void b1_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; int nconn, want = rp->level3cnt; @@ -347,7 +375,8 @@ void b1_register_appl(struct capi_ctr *ctrl, void b1_release_appl(struct capi_ctr *ctrl, __u16 appl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; @@ -360,7 +389,8 @@ void b1_release_appl(struct capi_ctr *ctrl, __u16 appl) void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; __u16 len = CAPIMSG_LEN(skb->data); @@ -384,25 +414,26 @@ void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) /* ------------------------------------------------------------- */ -void b1_parse_version(avmcard *card) +void b1_parse_version(avmctrl_info *cinfo) { - struct capi_ctr *ctrl = card->ctrl; + struct capi_ctr *ctrl = cinfo->capi_ctrl; + avmcard *card = cinfo->card; capi_profile *profp; __u8 *dversion; __u8 flag; int i, j; for (j = 0; j < AVM_MAXVERSION; j++) - card->version[j] = "\0\0" + 1; + cinfo->version[j] = "\0\0" + 1; for (i = 0, j = 0; - j < AVM_MAXVERSION && i < card->versionlen; - j++, i += card->versionbuf[i] + 1) - card->version[j] = &card->versionbuf[i + 1]; + j < AVM_MAXVERSION && i < cinfo->versionlen; + j++, i += cinfo->versionbuf[i] + 1) + cinfo->version[j] = &cinfo->versionbuf[i + 1]; - strncpy(ctrl->serial, card->version[VER_SERIAL], CAPI_SERIAL_LEN); - memcpy(&ctrl->profile, card->version[VER_PROFILE],sizeof(capi_profile)); + strncpy(ctrl->serial, cinfo->version[VER_SERIAL], CAPI_SERIAL_LEN); + memcpy(&ctrl->profile, cinfo->version[VER_PROFILE],sizeof(capi_profile)); strncpy(ctrl->manu, "AVM GmbH", CAPI_MANUFACTURER_LEN); - dversion = card->version[VER_DRIVER]; + dversion = cinfo->version[VER_DRIVER]; ctrl->version.majorversion = 2; ctrl->version.minorversion = 0; ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4); @@ -415,23 +446,24 @@ void b1_parse_version(avmcard *card) flag = ((__u8 *)(profp->manu))[1]; switch (flag) { - case 0: if (card->version[VER_CARDTYPE]) - strcpy(card->cardname, card->version[VER_CARDTYPE]); - else strcpy(card->cardname, "B1"); + case 0: if (cinfo->version[VER_CARDTYPE]) + strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]); + else strcpy(cinfo->cardname, "B1"); break; - case 3: strcpy(card->cardname,"PCMCIA B"); break; - case 4: strcpy(card->cardname,"PCMCIA M1"); break; - case 5: strcpy(card->cardname,"PCMCIA M2"); break; - case 6: strcpy(card->cardname,"B1 V3.0"); break; - case 7: strcpy(card->cardname,"B1 PCI"); break; - default: sprintf(card->cardname, "AVM?%u", (unsigned int)flag); break; + case 3: strcpy(cinfo->cardname,"PCMCIA B"); break; + case 4: strcpy(cinfo->cardname,"PCMCIA M1"); break; + case 5: strcpy(cinfo->cardname,"PCMCIA M2"); break; + case 6: strcpy(cinfo->cardname,"B1 V3.0"); break; + case 7: strcpy(cinfo->cardname,"B1 PCI"); break; + default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break; } printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n", - card->name, ctrl->cnr, card->cardname); + card->name, ctrl->cnr, cinfo->cardname); flag = ((__u8 *)(profp->manu))[3]; if (flag) - printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n", + printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n", + card->name, ctrl->cnr, (flag & 0x01) ? " DSS1" : "", (flag & 0x02) ? " CT1" : "", @@ -458,7 +490,8 @@ void b1_parse_version(avmcard *card) void b1_handle_interrupt(avmcard * card) { - struct capi_ctr *ctrl = card->ctrl; + avmctrl_info *cinfo = &card->ctrlinfo[0]; + struct capi_ctr *ctrl = cinfo->capi_ctrl; unsigned char b1cmd; struct sk_buff *skb; @@ -481,13 +514,17 @@ void b1_handle_interrupt(avmcard * card) MsgLen = b1_get_slice(card->port, card->msgbuf); DataB3Len = b1_get_slice(card->port, card->databuf); + if (MsgLen < 30) { /* not CAPI 64Bit */ + memset(card->msgbuf+MsgLen, 0, 30-MsgLen); + MsgLen = 30; + CAPIMSG_SETLEN(card->msgbuf, 30); + } if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); - CAPIMSG_SETDATA(skb->data, skb->data + MsgLen); ctrl->handle_capimsg(ctrl, ApplId, skb); } break; @@ -536,12 +573,12 @@ void b1_handle_interrupt(avmcard * card) case RECEIVE_INIT: - card->versionlen = b1_get_slice(card->port, card->versionbuf); - b1_parse_version(card); + cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf); + b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, - card->version[VER_CARDTYPE], - card->version[VER_DRIVER]); + cinfo->version[VER_CARDTYPE], + cinfo->version[VER_DRIVER]); ctrl->ready(ctrl); break; @@ -581,7 +618,8 @@ void b1_handle_interrupt(avmcard * card) int b1ctl_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; __u8 flag; int len = 0; char *s; @@ -603,11 +641,11 @@ int b1ctl_read_proc(char *page, char **start, off_t off, len += sprintf(page+len, "%-16s %s\n", "type", s); if (card->cardtype == avm_t1isa) len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr); - if ((s = card->version[VER_DRIVER]) != 0) + if ((s = cinfo->version[VER_DRIVER]) != 0) len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); - if ((s = card->version[VER_CARDTYPE]) != 0) + if ((s = cinfo->version[VER_CARDTYPE]) != 0) len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); - if ((s = card->version[VER_SERIAL]) != 0) + if ((s = cinfo->version[VER_SERIAL]) != 0) len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); if (card->cardtype != avm_m1) { @@ -635,7 +673,7 @@ int b1ctl_read_proc(char *page, char **start, off_t off, (flag & 0x04) ? " leased line with D-channel" : "" ); } - len += sprintf(page+len, "%-16s %s\n", "cardname", card->cardname); + len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); if (off+count >= len) *eof = 1; diff --git a/drivers/isdn/avmb1/b1isa.c b/drivers/isdn/avmb1/b1isa.c index 9ab1984323eea0b885aa24e5c60f5dcec94d12e7..01972b2d21df5a8dbaf3541cc7bec48428463b17 100644 --- a/drivers/isdn/avmb1/b1isa.c +++ b/drivers/isdn/avmb1/b1isa.c @@ -1,11 +1,18 @@ /* - * $Id: b1isa.c,v 1.4 1999/08/22 20:26:24 calle Exp $ + * $Id: b1isa.c,v 1.5 1999/11/05 16:38:01 calle Exp $ * * Module for AVM B1 ISA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1isa.c,v $ + * Revision 1.5 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * * Revision 1.4 1999/08/22 20:26:24 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -49,13 +56,12 @@ #include <linux/ioport.h> #include <linux/capi.h> #include <asm/io.h> -#include <linux/isdn_compat.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.4 $"; +static char *revision = "$Revision: 1.5 $"; /* ------------------------------------------------------------- */ @@ -92,7 +98,8 @@ static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) static void b1isa_remove_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; b1_reset(port); @@ -101,6 +108,7 @@ static void b1isa_remove_ctr(struct capi_ctr *ctrl) di->detach_ctr(ctrl); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); MOD_DEC_USE_COUNT; @@ -110,6 +118,7 @@ static void b1isa_remove_ctr(struct capi_ctr *ctrl) static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) { + avmctrl_info *cinfo; avmcard *card; int retval; @@ -120,6 +129,15 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) return -ENOMEM; } memset(card, 0, sizeof(avmcard)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "b1isa: no memory.\n"); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; sprintf(card->name, "b1isa-%x", p->port); card->port = p->port; card->irq = p->irq; @@ -129,17 +147,20 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) printk(KERN_WARNING "b1isa: ports 0x%03x-0x%03x in use.\n", card->port, card->port + AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } if (b1_irq_table[card->irq & 0xf] == 0) { printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq); + kfree(card->ctrlinfo); kfree(card); return -EINVAL; } if ( card->port != 0x150 && card->port != 0x250 && card->port != 0x300 && card->port != 0x340) { printk(KERN_WARNING "b1isa: illegal port 0x%x.\n", card->port); + kfree(card->ctrlinfo); kfree(card); return -EINVAL; } @@ -147,6 +168,7 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) if ((retval = b1_detect(card->port, card->cardtype)) != 0) { printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n", card->port, retval); + kfree(card->ctrlinfo); kfree(card); return -EIO; } @@ -158,15 +180,17 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) if (retval) { printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } - card->ctrl = di->attach_ctr(driver, card->name, card); - if (!card->ctrl) { + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { printk(KERN_ERR "b1isa: attach controller failed.\n"); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } @@ -177,15 +201,17 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) static char *b1isa_procinfo(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); - if (!card) + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) return ""; - sprintf(card->infobuf, "%s %s 0x%x %d", - card->cardname[0] ? card->cardname : "-", - card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", - card->port, card->irq + sprintf(cinfo->infobuf, "%s %s 0x%x %d", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0 ); - return card->infobuf; + return cinfo->infobuf; } /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/avmb1/b1pci.c b/drivers/isdn/avmb1/b1pci.c index 8c0006a78bf59f7eb23750cc9db657f2871487d9..f4e87b12fd029459e7a1d0ac1a71145a133516ed 100644 --- a/drivers/isdn/avmb1/b1pci.c +++ b/drivers/isdn/avmb1/b1pci.c @@ -1,11 +1,21 @@ /* - * $Id: b1pci.c,v 1.16 1999/08/11 21:01:07 keil Exp $ + * $Id: b1pci.c,v 1.18 1999/11/05 16:38:01 calle Exp $ * * Module for AVM B1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pci.c,v $ + * Revision 1.18 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.17 1999/10/05 06:50:07 calle + * Forgot SA_SHIRQ as argument to request_irq. + * * Revision 1.16 1999/08/11 21:01:07 keil * new PCI codefix * @@ -51,13 +61,12 @@ #include <linux/pci.h> #include <linux/capi.h> #include <asm/io.h> -#include <linux/isdn_compat.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.16 $"; +static char *revision = "$Revision: 1.18 $"; /* ------------------------------------------------------------- */ @@ -86,11 +95,11 @@ static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs) card = (avmcard *) devptr; if (!card) { - printk(KERN_WARNING "b1_interrupt: wrong device\n"); + printk(KERN_WARNING "b1pci: interrupt: wrong device\n"); return; } if (card->interrupt) { - printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name); + printk(KERN_ERR "%s: reentering interrupt hander.\n", card->name); return; } @@ -104,7 +113,8 @@ static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs) static void b1pci_remove_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; b1_reset(port); @@ -114,6 +124,7 @@ static void b1pci_remove_ctr(struct capi_ctr *ctrl) free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); ctrl->driverdata = 0; + kfree(card->ctrlinfo); kfree(card); MOD_DEC_USE_COUNT; @@ -123,15 +134,17 @@ static void b1pci_remove_ctr(struct capi_ctr *ctrl) static char *b1pci_procinfo(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); - if (!card) + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) return ""; - sprintf(card->infobuf, "%s %s 0x%x %d", - card->cardname[0] ? card->cardname : "-", - card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", - card->port, card->irq + sprintf(cinfo->infobuf, "%s %s 0x%x %d", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0 ); - return card->infobuf; + return cinfo->infobuf; } /* ------------------------------------------------------------- */ @@ -139,15 +152,25 @@ static char *b1pci_procinfo(struct capi_ctr *ctrl) static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p) { avmcard *card; + avmctrl_info *cinfo; int retval; card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); if (!card) { - printk(KERN_WARNING "b1pci: no memory.\n"); + printk(KERN_WARNING "%s: no memory.\n", driver->name); return -ENOMEM; } memset(card, 0, sizeof(avmcard)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; sprintf(card->name, "b1pci-%x", p->port); card->port = p->port; card->irq = p->irq; @@ -155,15 +178,17 @@ static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p) if (check_region(card->port, AVMB1_PORTLEN)) { printk(KERN_WARNING - "b1pci: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); + "%s: ports 0x%03x-0x%03x in use.\n", + driver->name, card->port, card->port + AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } b1_reset(card->port); if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n", - card->port, retval); + printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", + driver->name, card->port, retval); + kfree(card->ctrlinfo); kfree(card); return -EIO; } @@ -171,19 +196,23 @@ static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p) request_region(p->port, AVMB1_PORTLEN, card->name); - retval = request_irq(card->irq, b1pci_interrupt, 0, card->name, card); + retval = request_irq(card->irq, b1pci_interrupt, SA_SHIRQ, card->name, card); if (retval) { - printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", + driver->name, card->irq); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } - card->ctrl = di->attach_ctr(driver, card->name, card); - if (!card->ctrl) { - printk(KERN_ERR "b1pci: attach controller failed.\n"); + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { + printk(KERN_ERR "%s: attach controller failed.\n", + driver->name); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } @@ -252,7 +281,7 @@ int b1pci_init(void) while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) { struct capicardparams param; - param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK; + param.port = dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; param.irq = dev->irq; printk(KERN_INFO "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", @@ -277,7 +306,7 @@ int b1pci_init(void) printk(KERN_ERR "%s: NO B1-PCI card detected\n", driver->name); return -ESRCH; #else - printk(KERN_ERR "b1pci: kernel not compiled with PCI.\n"); + printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name); return -EIO; #endif } diff --git a/drivers/isdn/avmb1/b1pcmcia.c b/drivers/isdn/avmb1/b1pcmcia.c index d6acda9d9e08e1b546c714b6036de2a98cd4621d..79e34316481adec4deb2182a0bb8fbdced68f3c3 100644 --- a/drivers/isdn/avmb1/b1pcmcia.c +++ b/drivers/isdn/avmb1/b1pcmcia.c @@ -1,11 +1,18 @@ /* - * $Id: b1pcmcia.c,v 1.4 1999/08/22 20:26:26 calle Exp $ + * $Id: b1pcmcia.c,v 1.5 1999/11/05 16:38:01 calle 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.5 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * * Revision 1.4 1999/08/22 20:26:26 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -50,13 +57,12 @@ #include <asm/io.h> #include <linux/capi.h> #include <linux/b1pcmcia.h> -#include <linux/isdn_compat.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.4 $"; +static char *revision = "$Revision: 1.5 $"; /* ------------------------------------------------------------- */ @@ -75,11 +81,12 @@ static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs card = (avmcard *) devptr; if (!card) { - printk(KERN_WARNING "b1_interrupt: wrong device\n"); + printk(KERN_WARNING "b1pcmcia: interrupt: wrong device\n"); return; } if (card->interrupt) { - printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name); + printk(KERN_ERR "%s: reentering interrupt hander.\n", + card->name); return; } @@ -93,7 +100,8 @@ static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; b1_reset(port); @@ -116,16 +124,26 @@ static int b1pcmcia_add_card(struct capi_driver *driver, unsigned irq, enum avmcardtype cardtype) { + avmctrl_info *cinfo; avmcard *card; int retval; card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); if (!card) { - printk(KERN_WARNING "b1pcmcia: no memory.\n"); + printk(KERN_WARNING "%s: no memory.\n", driver->name); return -ENOMEM; } memset(card, 0, sizeof(avmcard)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; switch (cardtype) { case avm_m1: sprintf(card->name, "m1-%x", port); break; case avm_m2: sprintf(card->name, "m2-%x", port); break; @@ -137,8 +155,9 @@ static int b1pcmcia_add_card(struct capi_driver *driver, b1_reset(card->port); if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "b1pcmcia: NO card at 0x%x (%d)\n", - card->port, retval); + printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", + driver->name, card->port, retval); + kfree(card->ctrlinfo); kfree(card); return -EIO; } @@ -146,36 +165,42 @@ static int b1pcmcia_add_card(struct capi_driver *driver, retval = request_irq(card->irq, b1pcmcia_interrupt, 0, card->name, card); if (retval) { - printk(KERN_ERR "b1pcmcia: unable to get IRQ %d.\n", card->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", + driver->name, card->irq); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } - card->ctrl = di->attach_ctr(driver, card->name, card); - if (!card->ctrl) { - printk(KERN_ERR "b1pcmcia: attach controller failed.\n"); + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { + printk(KERN_ERR "%s: attach controller failed.\n", + driver->name); free_irq(card->irq, card); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } MOD_INC_USE_COUNT; - return card->ctrl->cnr; + return cinfo->capi_ctrl->cnr; } /* ------------------------------------------------------------- */ static char *b1pcmcia_procinfo(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); - if (!card) + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) return ""; - sprintf(card->infobuf, "%s %s 0x%x %d", - card->cardname[0] ? card->cardname : "-", - card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", - card->port, card->irq + sprintf(cinfo->infobuf, "%s %s 0x%x %d", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0 ); - return card->infobuf; + return cinfo->infobuf; } /* ------------------------------------------------------------- */ @@ -220,7 +245,7 @@ int b1pcmcia_delcard(unsigned int port, unsigned irq) avmcard *card; for (ctrl = b1pcmcia_driver.controller; ctrl; ctrl = ctrl->next) { - card = (avmcard *)(ctrl->driverdata); + card = ((avmctrl_info *)(ctrl->driverdata))->card; if (card->port == port && card->irq == irq) { b1pcmcia_remove_ctr(ctrl); return 0; diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c index c8cab69193e0f4bfa8dc589a8b6b76c5b650be09..6d1159d5617a260f4b139ddad080034ce0842aec 100644 --- a/drivers/isdn/avmb1/capi.c +++ b/drivers/isdn/avmb1/capi.c @@ -1,11 +1,20 @@ /* - * $Id: capi.c,v 1.19 1999/07/09 15:05:42 keil Exp $ + * $Id: capi.c,v 1.21 1999/09/10 17:24:18 calle Exp $ * * CAPI 2.0 Interface for Linux * * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capi.c,v $ + * Revision 1.21 1999/09/10 17:24:18 calle + * Changes for proposed standard for CAPI2.0: + * - AK148 "Linux Exention" + * + * Revision 1.20 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.19 1999/07/09 15:05:42 keil * compat.h is now isdn_compat.h * @@ -117,7 +126,6 @@ #include <linux/capi.h> #include <linux/kernelcapi.h> -#include <linux/isdn_compat.h> #include "capiutil.h" #include "capicmd.h" #include "capidev.h" @@ -201,9 +209,6 @@ static ssize_t capi_read(struct file *file, char *buf, skb_queue_head(&cdev->recv_queue, skb); return -EMSGSIZE; } - if (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 - && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) - CAPIMSG_SETDATA(skb->data, buf + CAPIMSG_LEN(skb->data)); retval = copy_to_user(buf, skb->data, skb->len); if (retval) { skb_queue_head(&cdev->recv_queue, skb); @@ -429,7 +434,7 @@ static int capi_ioctl(struct inode *inode, struct file *file, return data.errcode; case CAPI_INSTALLED: - if ((*capifuncs->capi_installed) ()) + if ((*capifuncs->capi_isinstalled)() == CAPI_NOERROR) return 0; return -ENXIO; @@ -615,16 +620,12 @@ static struct capi_interface_user cuser = { int capi_init(void) { -#ifdef COMPAT_HAS_NEW_WAITQ int j; -#endif memset(capidevs, 0, sizeof(capidevs)); -#ifdef COMPAT_HAS_NEW_WAITQ for ( j = 0; j < CAPI_MAXMINOR+1; j++ ) { init_waitqueue_head(&capidevs[j].recv_wait); } -#endif if (register_chrdev(capi_major, "capi20", &capi_fops)) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); diff --git a/drivers/isdn/avmb1/capidev.h b/drivers/isdn/avmb1/capidev.h index c66554a2979ed101f3a5666d8d09ef22bec552f2..96e37c1f47ecb4a0c4a30a70daaca0e28fcc2ce6 100644 --- a/drivers/isdn/avmb1/capidev.h +++ b/drivers/isdn/avmb1/capidev.h @@ -44,11 +44,7 @@ struct capidev { int is_registered; __u16 applid; struct sk_buff_head recv_queue; -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t recv_wait; -#else - struct wait_queue *recv_wait; -#endif __u16 errcode; /* Statistic */ unsigned long nopen; diff --git a/drivers/isdn/avmb1/capidrv.c b/drivers/isdn/avmb1/capidrv.c index fb83e52a6e066e3a1c37152053b5f0eb675b5f93..6db170e42486117f4814c7c4ab8015348b31c4bf 100644 --- a/drivers/isdn/avmb1/capidrv.c +++ b/drivers/isdn/avmb1/capidrv.c @@ -1,11 +1,17 @@ /* - * $Id: capidrv.c,v 1.26 1999/08/06 07:41:16 calle Exp $ + * $Id: capidrv.c,v 1.28 1999/11/05 16:22:37 calle Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidrv.c,v $ + * Revision 1.28 1999/11/05 16:22:37 calle + * Bugfix: Missing break in switch on ISDN_CMD_HANGUP. + * + * Revision 1.27 1999/09/16 15:13:04 calle + * forgot to change paramter type of contr for lower_callback ... + * * Revision 1.26 1999/08/06 07:41:16 calle * Added the "vbox patch". if (si1 == 1) si2 = 0; * @@ -158,12 +164,11 @@ #include <linux/ctype.h> #include <asm/segment.h> -#include <linux/isdn_compat.h> #include "capiutil.h" #include "capicmd.h" #include "capidrv.h" -static char *revision = "$Revision: 1.26 $"; +static char *revision = "$Revision: 1.28 $"; int debugmode = 0; MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>"); @@ -714,8 +719,6 @@ static struct plcistatechange plcitable[] = /* P-0.1 */ {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0}, {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0}, - {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, /* P-1 */ {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, @@ -1855,14 +1858,19 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card) ); ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ); send_message(card, &cmdcmsg); + return 0; } else if (bchan->plcip) { - bchan->disconnecting = 1; if (bchan->plcip->state == ST_PLCI_INCOMING) { - /* just ignore, we a called from isdn_status_callback(), - * which will return 0 or 2, this is handled by the - * CONNECT_IND handler + /* + * just ignore, we a called from + * isdn_status_callback(), + * which will return 0 or 2, this is handled + * by the CONNECT_IND handler */ - } else { + bchan->disconnecting = 1; + return 0; + } else if (bchan->plcip->plci) { + bchan->disconnecting = 1; capi_fill_DISCONNECT_REQ(&cmdcmsg, global.appid, card->msgid++, @@ -1874,8 +1882,18 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card) ); plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ); send_message(card, &cmdcmsg); + return 0; + } else { + printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n", + card->contrnr, + c->arg); + return -EINVAL; } } + printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n", + card->contrnr, + c->arg); + return -EINVAL; /* ready */ case ISDN_CMD_SETL2: @@ -2022,10 +2040,8 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb) (void)capidrv_del_ack(nccip, datahandle); return 0; } -#if 1 printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n", card->contrnr, skb_headroom(skb), msglen); -#endif memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen); errcode = (*capifuncs->capi_put_message) (global.appid, nskb); if (errcode == CAPI_NOERROR) { @@ -2211,10 +2227,6 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp) ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038 | -#if 0 - ISDN_FEATURE_L2_FAX | - ISDN_FEATURE_L3_FAX | -#endif ISDN_FEATURE_P_UNKNOWN; card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */ strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); @@ -2309,7 +2321,7 @@ static int capidrv_delcontr(__u16 contr) } -static void lower_callback(unsigned int cmd, __u16 contr, void *data) +static void lower_callback(unsigned int cmd, __u32 contr, void *data) { switch (cmd) { diff --git a/drivers/isdn/avmb1/capiutil.c b/drivers/isdn/avmb1/capiutil.c index 7f1a9f1adfa50fcfeede6fe8a8ce95176c9675fd..3482f2a97cbdbc62694379c026fb32e37646b971 100644 --- a/drivers/isdn/avmb1/capiutil.c +++ b/drivers/isdn/avmb1/capiutil.c @@ -1,5 +1,5 @@ /* - * $Id: capiutil.c,v 1.9 1999/07/09 15:05:46 keil Exp $ + * $Id: capiutil.c,v 1.10 1999/08/31 11:19:54 paul Exp $ * * CAPI 2.0 convert capi message to capi message struct * @@ -7,6 +7,9 @@ * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capiutil.c,v $ + * Revision 1.10 1999/08/31 11:19:54 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.9 1999/07/09 15:05:46 keil * compat.h is now isdn_compat.h * @@ -70,7 +73,6 @@ #include <asm/segment.h> #include <linux/config.h> -#include <linux/isdn_compat.h> #include "capiutil.h" /* from CAPI2.0 DDK AVM Berlin GmbH */ @@ -97,7 +99,7 @@ char *capi_info2str(__u16 reason) case 0x1001: return "Too many applications"; case 0x1002: - return "Logical block size to small, must be at least 128 Bytes"; + return "Logical block size too small, must be at least 128 Bytes"; case 0x1003: return "Buffer exceeds 64 kByte"; case 0x1004: diff --git a/drivers/isdn/avmb1/capiutil.h b/drivers/isdn/avmb1/capiutil.h index 38209212dbd91512cb3744ab5afce6eef0d678e1..3825ac3083786d175396cec5cca2db6df76e0ac6 100644 --- a/drivers/isdn/avmb1/capiutil.h +++ b/drivers/isdn/avmb1/capiutil.h @@ -1,5 +1,5 @@ /* - * $Id: capiutil.h,v 1.2 1997/05/18 09:24:19 calle Exp $ + * $Id: capiutil.h,v 1.4 1999/09/15 08:16:03 calle Exp $ * * CAPI 2.0 defines & types * @@ -7,6 +7,14 @@ * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capiutil.h,v $ + * Revision 1.4 1999/09/15 08:16:03 calle + * Implementation of 64Bit extention complete. + * + * Revision 1.3 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.2 1997/05/18 09:24:19 calle * added verbose disconnect reason reporting to avmb1. * some fixes in capi20 interface. @@ -45,12 +53,10 @@ ((__u8 *)m)[3] = ((__u16)(applid) >> 8) & 0xff; \ } while (0) -#define CAPIMSG_SETDATA(m, data) \ +#define CAPIMSG_SETLEN(m, len) \ do { \ - ((__u8 *)m)[12] = (__u32)(data) & 0xff; \ - ((__u8 *)m)[13] = ((__u32)(data) >> 8) & 0xff; \ - ((__u8 *)m)[14] = ((__u32)(data) >> 16) & 0xff; \ - ((__u8 *)m)[15] = ((__u32)(data) >> 24) & 0xff; \ + ((__u8 *)m)[0] = (__u16)(len) & 0xff; \ + ((__u8 *)m)[1] = ((__u16)(len) >> 8) & 0xff; \ } while (0) /*----- basic-type definitions -----*/ diff --git a/drivers/isdn/avmb1/kcapi.c b/drivers/isdn/avmb1/kcapi.c index fc58f12415cb0e3e3915c02f55c78fec3ddf43da..75d3f01c23e076174c4c342eced1b0c9d13a17c5 100644 --- a/drivers/isdn/avmb1/kcapi.c +++ b/drivers/isdn/avmb1/kcapi.c @@ -1,11 +1,25 @@ /* - * $Id: kcapi.c,v 1.6 1999/07/20 06:41:49 calle Exp $ + * $Id: kcapi.c,v 1.10 1999/10/26 15:30:32 calle Exp $ * * Kernel CAPI 2.0 Module * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: kcapi.c,v $ + * Revision 1.10 1999/10/26 15:30:32 calle + * Generate error message if user want to add card, but driver module is + * not loaded. + * + * Revision 1.9 1999/10/11 22:04:12 keil + * COMPAT_NEED_UACCESS (no include in isdn_compat.h) + * + * Revision 1.8 1999/09/10 17:24:18 calle + * Changes for proposed standard for CAPI2.0: + * - AK148 "Linux Exention" + * + * Revision 1.7 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.6 1999/07/20 06:41:49 calle * Bugfix: After the redesign of the AVM B1 driver, the driver didn't even * compile, if not selected as modules. @@ -57,7 +71,7 @@ #include <linux/tqueue.h> #include <linux/capi.h> #include <linux/kernelcapi.h> -#include <linux/isdn_compat.h> +#include <asm/uaccess.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" @@ -65,7 +79,7 @@ #include <linux/b1lli.h> #endif -static char *revision = "$Revision: 1.6 $"; +static char *revision = "$Revision: 1.10 $"; /* ------------------------------------------------------------- */ @@ -119,7 +133,7 @@ struct capi_appl { /* ------------------------------------------------------------- */ static struct capi_version driver_version = {2, 0, 1, 1<<4}; -static char driver_serial[CAPI_SERIAL_LEN] = "4711"; +static char driver_serial[CAPI_SERIAL_LEN] = "0004711"; static char capi_manufakturer[64] = "AVM Berlin"; #define APPL(a) (&applications[(a)-1]) @@ -719,7 +733,7 @@ static void controllercb_handle_capimsg(struct capi_ctr * card, /* -------- Notifier ------------------------------------------ */ -static void notify_up(__u16 contr) +static void notify_up(__u32 contr) { struct capi_interface_user *p; @@ -730,7 +744,7 @@ static void notify_up(__u16 contr) } } -static void notify_down(__u16 contr) +static void notify_down(__u32 contr) { struct capi_interface_user *p; printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr); @@ -742,7 +756,7 @@ static void notify_down(__u16 contr) static void notify_handler(void *dummy) { - __u16 contr; + __u32 contr; for (contr=1; VALID_CARD(contr); contr++) if (test_and_clear_bit(contr, ¬ify_up_set)) @@ -984,14 +998,14 @@ void detach_capi_driver(struct capi_driver *driver) /* -------- CAPI2.0 Interface ---------------------------------- */ /* ------------------------------------------------------------- */ -static int capi_installed(void) +static __u16 capi_isinstalled(void) { int i; for (i = 0; i < CAPI_MAXCONTR; i++) { if (cards[i].cardstate == CARD_RUNNING) - return 1; + return CAPI_NOERROR; } - return 0; + return CAPI_REGNOTINSTALLED; } static __u16 capi_register(capi_register_params * rparam, __u16 * applidp) @@ -1053,7 +1067,7 @@ static __u16 capi_release(__u16 applid) static __u16 capi_put_message(__u16 applid, struct sk_buff *skb) { struct capi_ncci *np; - int contr; + __u32 contr; int showctl = 0; __u8 cmd, subcmd; @@ -1131,53 +1145,53 @@ static __u16 capi_set_signal(__u16 applid, return CAPI_NOERROR; } -static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN]) +static __u16 capi_get_manufacturer(__u32 contr, __u8 buf[CAPI_MANUFACTURER_LEN]) { if (contr == 0) { strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; + return CAPI_REGNOTINSTALLED; strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } -static __u16 capi_get_version(__u16 contr, struct capi_version *verp) +static __u16 capi_get_version(__u32 contr, struct capi_version *verp) { if (contr == 0) { *verp = driver_version; return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; + return CAPI_REGNOTINSTALLED; memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version)); return CAPI_NOERROR; } -static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN]) +static __u16 capi_get_serial(__u32 contr, __u8 serial[CAPI_SERIAL_LEN]) { if (contr == 0) { strncpy(serial, driver_serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; + return CAPI_REGNOTINSTALLED; strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } -static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp) +static __u16 capi_get_profile(__u32 contr, struct capi_profile *profp) { if (contr == 0) { profp->ncontroller = ncards; return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; + return CAPI_REGNOTINSTALLED; memcpy((void *) profp, &CARD(contr)->profile, sizeof(struct capi_profile)); @@ -1219,7 +1233,12 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) case AVM_CARDTYPE_T1: driver = t1isa_driver; break; default: driver = 0; } - if (!driver || !driver->add_card) { + if (!driver) { + printk(KERN_ERR "kcapi: driver not loaded.\n"); + return -EIO; + } + if (!driver->add_card) { + printk(KERN_ERR "kcapi: driver has no add card function.\n"); return -EIO; } @@ -1277,7 +1296,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)) @@ -1302,7 +1321,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)) @@ -1355,7 +1374,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)) @@ -1404,7 +1423,7 @@ static int capi_manufacturer(unsigned int cmd, void *data) struct capi_interface avmb1_interface = { - capi_installed, + capi_isinstalled, capi_register, capi_release, capi_put_message, @@ -1479,6 +1498,12 @@ extern int t1isa_init(void); #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 /* @@ -1528,6 +1553,12 @@ int kcapi_init(void) #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 return 0; } diff --git a/drivers/isdn/avmb1/t1isa.c b/drivers/isdn/avmb1/t1isa.c index 3546e10610f3744b81e1644b7035140a3dd95a5b..22a07f2ade758a0eebb8e2a5cbf0cc4d7d06ce2b 100644 --- a/drivers/isdn/avmb1/t1isa.c +++ b/drivers/isdn/avmb1/t1isa.c @@ -1,11 +1,26 @@ /* - * $Id: t1isa.c,v 1.5 1999/08/22 20:26:28 calle Exp $ + * $Id: t1isa.c,v 1.8 1999/11/05 16:38:01 calle Exp $ * * Module for AVM T1 HEMA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: t1isa.c,v $ + * Revision 1.8 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.7 1999/09/15 08:16:03 calle + * Implementation of 64Bit extention complete. + * + * Revision 1.6 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.5 1999/08/22 20:26:28 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -53,13 +68,12 @@ #include <linux/ioport.h> #include <linux/capi.h> #include <asm/io.h> -#include <linux/isdn_compat.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.5 $"; +static char *revision = "$Revision: 1.8 $"; /* ------------------------------------------------------------- */ @@ -162,7 +176,8 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr) static void t1_handle_interrupt(avmcard * card) { - struct capi_ctr *ctrl = card->ctrl; + avmctrl_info *cinfo = &card->ctrlinfo[0]; + struct capi_ctr *ctrl = cinfo->capi_ctrl; unsigned char b1cmd; struct sk_buff *skb; @@ -184,12 +199,17 @@ static void t1_handle_interrupt(avmcard * card) MsgLen = t1_get_slice(card->port, card->msgbuf); DataB3Len = t1_get_slice(card->port, card->databuf); + if (MsgLen < 30) { /* not CAPI 64Bit */ + memset(card->msgbuf+MsgLen, 0, 30-MsgLen); + MsgLen = 30; + CAPIMSG_SETLEN(card->msgbuf, 30); + } if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "t1isa: incoming packet dropped\n"); + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); - CAPIMSG_SETDATA(skb->data, skb->data + MsgLen); ctrl->handle_capimsg(ctrl, ApplId, skb); } break; @@ -199,7 +219,8 @@ static void t1_handle_interrupt(avmcard * card) ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "t1isa: incoming packet dropped\n"); + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); ctrl->handle_capimsg(ctrl, ApplId, skb); @@ -237,12 +258,12 @@ static void t1_handle_interrupt(avmcard * card) case RECEIVE_INIT: - card->versionlen = t1_get_slice(card->port, card->versionbuf); - b1_parse_version(card); + cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf); + b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, - card->version[VER_CARDTYPE], - card->version[VER_DRIVER]); + cinfo->version[VER_CARDTYPE], + cinfo->version[VER_DRIVER]); ctrl->ready(ctrl); break; @@ -288,11 +309,12 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) card = (avmcard *) devptr; if (!card) { - printk(KERN_WARNING "t1_interrupt: wrong device\n"); + printk(KERN_WARNING "t1isa: interrupt: wrong device\n"); return; } if (card->interrupt) { - printk(KERN_ERR "t1_interrupt: reentering interrupt hander (%s)\n", card->name); + printk(KERN_ERR "%s: reentering interrupt hander.\n", + card->name); return; } @@ -306,7 +328,8 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; int retval; @@ -314,7 +337,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) t1_disable_irq(port); b1_reset(port); - if ((retval = b1_load_t4file(port, &data->firmware))) { + if ((retval = b1_load_t4file(card, &data->firmware))) { b1_reset(port); printk(KERN_ERR "%s: failed to load t4file!!\n", card->name); @@ -322,7 +345,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) } if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(port, &data->configuration))) { + if ((retval = b1_load_config(card, &data->configuration))) { b1_reset(port); printk(KERN_ERR "%s: failed to load config!!\n", card->name); @@ -330,7 +353,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) } } - if (!b1_loaded(port)) { + if (!b1_loaded(card)) { printk(KERN_ERR "%s: failed to load t4file.\n", card->name); return -EIO; } @@ -349,20 +372,22 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) void t1isa_reset_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; t1_disable_irq(port); b1_reset(port); b1_reset(port); - memset(card->version, 0, sizeof(card->version)); + memset(cinfo->version, 0, sizeof(cinfo->version)); ctrl->reseted(ctrl); } static void t1isa_remove_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; t1_disable_irq(port); @@ -373,6 +398,7 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl) di->detach_ctr(ctrl); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); MOD_DEC_USE_COUNT; @@ -383,16 +409,26 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl) static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) { struct capi_ctr *ctrl; + avmctrl_info *cinfo; avmcard *card; int retval; card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); if (!card) { - printk(KERN_WARNING "t1isa: no memory.\n"); + printk(KERN_WARNING "%s: no memory.\n", driver->name); return -ENOMEM; } memset(card, 0, sizeof(avmcard)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; sprintf(card->name, "t1isa-%x", p->port); card->port = p->port; card->irq = p->irq; @@ -400,33 +436,42 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) card->cardnr = p->cardnr; if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) { - printk(KERN_WARNING "t1isa: illegal port 0x%x.\n", card->port); + printk(KERN_WARNING "%s: illegal port 0x%x.\n", + driver->name, card->port); + kfree(card->ctrlinfo); kfree(card); return -EINVAL; } if (check_region(card->port, AVMB1_PORTLEN)) { printk(KERN_WARNING - "t1isa: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); + "%s: ports 0x%03x-0x%03x in use.\n", + driver->name, card->port, card->port + AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } if (hema_irq_table[card->irq & 0xf] == 0) { - printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq); + printk(KERN_WARNING "%s: irq %d not valid.\n", + driver->name, card->irq); + kfree(card->ctrlinfo); kfree(card); return -EINVAL; } for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) { - if (((avmcard *)(ctrl->driverdata))->cardnr == card->cardnr) { - printk(KERN_WARNING "t1isa: card with number %d already installed.\n", card->cardnr); + avmcard *cardp = ((avmctrl_info *)(ctrl->driverdata))->card; + if (cardp->cardnr == card->cardnr) { + printk(KERN_WARNING "%s: card with number %d already installed at 0x%x.\n", + driver->name, card->cardnr, cardp->port); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } } if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) { - printk(KERN_NOTICE "t1isa: NO card at 0x%x (%d)\n", - card->port, retval); + printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", + driver->name, card->port, retval); + kfree(card->ctrlinfo); kfree(card); return -EIO; } @@ -437,17 +482,21 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card); if (retval) { - printk(KERN_ERR "t1isa: unable to get IRQ %d.\n", card->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", + driver->name, card->irq); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } - card->ctrl = di->attach_ctr(driver, card->name, card); - if (!card->ctrl) { - printk(KERN_ERR "t1isa: attach controller failed.\n"); + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { + printk(KERN_ERR "%s: attach controller failed.\n", + driver->name); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } @@ -458,7 +507,8 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; __u16 len = CAPIMSG_LEN(skb->data); @@ -483,15 +533,18 @@ static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) static char *t1isa_procinfo(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); - if (!card) + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) return ""; - sprintf(card->infobuf, "%s %s 0x%x %d %d", - card->cardname[0] ? card->cardname : "-", - card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", - card->port, card->irq, card->cardnr + sprintf(cinfo->infobuf, "%s %s 0x%x %d %d", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0, + cinfo->card ? cinfo->card->cardnr : 0 ); - return card->infobuf; + return cinfo->infobuf; } diff --git a/drivers/isdn/avmb1/t1pci.c b/drivers/isdn/avmb1/t1pci.c new file mode 100644 index 0000000000000000000000000000000000000000..ad73e71cde045b51be156be71c10b190b96c8b22 --- /dev/null +++ b/drivers/isdn/avmb1/t1pci.c @@ -0,0 +1,1164 @@ +/* + * $Id: t1pci.c,v 1.2 1999/11/05 16:38:02 calle Exp $ + * + * Module for AVM T1 PCI-card. + * + * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) + * + * $Log: t1pci.c,v $ + * Revision 1.2 1999/11/05 16:38:02 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.1 1999/10/26 15:31:42 calle + * Added driver for T1-PCI card. + * + * + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/skbuff.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/pci.h> +#include <linux/capi.h> +#include <asm/io.h> +#include "compat.h" +#include "capicmd.h" +#include "capiutil.h" +#include "capilli.h" +#include "avmcard.h" + +static char *revision = "$Revision: 1.2 $"; + +#undef CONFIG_T1PCI_DEBUG +#undef CONFIG_T1PCI_POLLDEBUG + +/* ------------------------------------------------------------- */ + +#ifndef PCI_VENDOR_ID_AVM +#define PCI_VENDOR_ID_AVM 0x1244 +#endif + +#ifndef PCI_DEVICE_ID_AVM_T1 +#define PCI_DEVICE_ID_AVM_T1 0x1200 +#endif + +/* ------------------------------------------------------------- */ + +int suppress_pollack = 0; + +MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>"); + +MODULE_PARM(suppress_pollack, "0-1i"); + + +/* ------------------------------------------------------------- */ + +static struct capi_driver_interface *di; + +/* ------------------------------------------------------------- */ + +static void t1pci_dispatch_tx(avmcard *card); + +/* ------------------------------------------------------------- */ + +/* S5933 */ + +#define AMCC_RXPTR 0x24 +#define AMCC_RXLEN 0x28 +#define AMCC_TXPTR 0x2c +#define AMCC_TXLEN 0x30 + +#define AMCC_INTCSR 0x38 +# define EN_READ_TC_INT 0x00008000L +# define EN_WRITE_TC_INT 0x00004000L +# define EN_TX_TC_INT EN_READ_TC_INT +# define EN_RX_TC_INT EN_WRITE_TC_INT +# define AVM_FLAG 0x30000000L + +# define ANY_S5933_INT 0x00800000L +# define READ_TC_INT 0x00080000L +# define WRITE_TC_INT 0x00040000L +# define TX_TC_INT READ_TC_INT +# define RX_TC_INT WRITE_TC_INT +# define MASTER_ABORT_INT 0x00100000L +# define TARGET_ABORT_INT 0x00200000L +# define BUS_MASTER_INT 0x00200000L +# define ALL_INT 0x000C0000L + +#define AMCC_MCSR 0x3c +# define A2P_HI_PRIORITY 0x00000100L +# define EN_A2P_TRANSFERS 0x00000400L +# define P2A_HI_PRIORITY 0x00001000L +# define EN_P2A_TRANSFERS 0x00004000L +# define RESET_A2P_FLAGS 0x04000000L +# define RESET_P2A_FLAGS 0x02000000L + +/* ------------------------------------------------------------- */ + +#define t1outmeml(addr, value) writel(value, addr) +#define t1inmeml(addr) readl(addr) +#define t1outmemw(addr, value) writew(value, addr) +#define t1inmemw(addr) readw(addr) +#define t1outmemb(addr, value) writeb(value, addr) +#define t1inmemb(addr) readb(addr) + +/* ------------------------------------------------------------- */ + +static inline int t1pci_tx_empty(unsigned int port) +{ + return inb(port + 0x03) & 0x1; +} + +static inline int t1pci_rx_full(unsigned int port) +{ + return inb(port + 0x02) & 0x1; +} + +static int t1pci_tolink(avmcard *card, void *buf, unsigned int len) +{ + unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ + unsigned char *s = (unsigned char *)buf; + while (len--) { + while ( !t1pci_tx_empty(card->port) + && time_before(jiffies, stop)); + if (!t1pci_tx_empty(card->port)) + return -1; + t1outp(card->port, 0x01, *s++); + } + return 0; +} + +static int t1pci_fromlink(avmcard *card, void *buf, unsigned int len) +{ + unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ + unsigned char *s = (unsigned char *)buf; + while (len--) { + while ( !t1pci_rx_full(card->port) + && time_before(jiffies, stop)); + if (!t1pci_rx_full(card->port)) + return -1; + *s++ = t1inp(card->port, 0x00); + } + return 0; +} + +static int WriteReg(avmcard *card, __u32 reg, __u8 val) +{ + __u8 cmd = 0x00; + if ( t1pci_tolink(card, &cmd, 1) == 0 + && t1pci_tolink(card, ®, 4) == 0) { + __u32 tmp = val; + return t1pci_tolink(card, &tmp, 4); + } + return -1; +} + +static __u8 ReadReg(avmcard *card, __u32 reg) +{ + __u8 cmd = 0x01; + if ( t1pci_tolink(card, &cmd, 1) == 0 + && t1pci_tolink(card, ®, 4) == 0) { + __u32 tmp; + if (t1pci_fromlink(card, &tmp, 4) == 0) + return (__u8)tmp; + } + return 0xff; +} + +/* ------------------------------------------------------------- */ + +static inline void _put_byte(void **pp, __u8 val) +{ + __u8 *s = *pp; + *s++ = val; + *pp = s; +} + +static inline void _put_word(void **pp, __u32 val) +{ + __u8 *s = *pp; + *s++ = val & 0xff; + *s++ = (val >> 8) & 0xff; + *s++ = (val >> 16) & 0xff; + *s++ = (val >> 24) & 0xff; + *pp = s; +} + +static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len) +{ + unsigned i = len; + _put_word(pp, i); + while (i-- > 0) + _put_byte(pp, *dp++); +} + +static inline __u8 _get_byte(void **pp) +{ + __u8 *s = *pp; + __u8 val; + val = *s++; + *pp = s; + return val; +} + +static inline __u32 _get_word(void **pp) +{ + __u8 *s = *pp; + __u32 val; + val = *s++; + val |= (*s++ << 8); + val |= (*s++ << 16); + val |= (*s++ << 24); + *pp = s; + return val; +} + +static inline __u32 _get_slice(void **pp, unsigned char *dp) +{ + unsigned int len, i; + + len = i = _get_word(pp); + while (i-- > 0) *dp++ = _get_byte(pp); + return len; +} + +/* ------------------------------------------------------------- */ + +static void t1pci_reset(avmcard *card) +{ + unsigned long flags; + + save_flags(flags); + cli(); + card->csr = 0x0; + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + t1outmeml(card->mbase+AMCC_MCSR, 0); + t1outmeml(card->mbase+AMCC_RXLEN, 0); + t1outmeml(card->mbase+AMCC_TXLEN, 0); + + t1outp(card->port, T1_RESETLINK, 0x00); + t1outp(card->port, 0x07, 0x00); + + restore_flags(flags); + + t1outmeml(card->mbase+AMCC_MCSR, 0); + udelay(10 * 1000); + t1outmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */ + udelay(10 * 1000); + t1outmeml(card->mbase+AMCC_MCSR, 0); + udelay(42 * 1000); + +} + +/* ------------------------------------------------------------- */ + +static int t1pci_detect(avmcard *card) +{ + t1outmeml(card->mbase+AMCC_MCSR, 0); + udelay(10 * 1000); + t1outmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */ + udelay(10 * 1000); + t1outmeml(card->mbase+AMCC_MCSR, 0); + udelay(42 * 1000); + + t1outmeml(card->mbase+AMCC_RXLEN, 0); + t1outmeml(card->mbase+AMCC_TXLEN, 0); + card->csr = 0x0; + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + + if (t1inmeml(card->mbase+AMCC_MCSR) != 0x000000E6) + return 1; + + t1outmeml(card->mbase+AMCC_RXPTR, 0xffffffff); + t1outmeml(card->mbase+AMCC_TXPTR, 0xffffffff); + if ( t1inmeml(card->mbase+AMCC_RXPTR) != 0xfffffffc + || t1inmeml(card->mbase+AMCC_TXPTR) != 0xfffffffc) + return 2; + + t1outmeml(card->mbase+AMCC_RXPTR, 0x0); + t1outmeml(card->mbase+AMCC_TXPTR, 0x0); + if ( t1inmeml(card->mbase+AMCC_RXPTR) != 0x0 + || t1inmeml(card->mbase+AMCC_TXPTR) != 0x0) + return 3; + + t1outp(card->port, T1_RESETLINK, 0x00); + t1outp(card->port, 0x07, 0x00); + + t1outp(card->port, 0x02, 0x02); + t1outp(card->port, 0x03, 0x02); + + if ( (t1inp(card->port, 0x02) & 0xFE) != 0x02 + || t1inp(card->port, 0x3) != 0x03) + return 4; + + t1outp(card->port, 0x02, 0x00); + t1outp(card->port, 0x03, 0x00); + + if ( (t1inp(card->port, 0x02) & 0xFE) != 0x00 + || t1inp(card->port, 0x3) != 0x01) + return 5; + + /* Transputer test */ + + if ( WriteReg(card, 0x80001000, 0x11) != 0 + || WriteReg(card, 0x80101000, 0x22) != 0 + || WriteReg(card, 0x80201000, 0x33) != 0 + || WriteReg(card, 0x80301000, 0x44) != 0) + return 6; + + if ( ReadReg(card, 0x80001000) != 0x11 + || ReadReg(card, 0x80101000) != 0x22 + || ReadReg(card, 0x80201000) != 0x33 + || ReadReg(card, 0x80301000) != 0x44) + return 7; + + if ( WriteReg(card, 0x80001000, 0x55) != 0 + || WriteReg(card, 0x80101000, 0x66) != 0 + || WriteReg(card, 0x80201000, 0x77) != 0 + || WriteReg(card, 0x80301000, 0x88) != 0) + return 8; + + if ( ReadReg(card, 0x80001000) != 0x55 + || ReadReg(card, 0x80101000) != 0x66 + || ReadReg(card, 0x80201000) != 0x77 + || ReadReg(card, 0x80301000) != 0x88) + return 9; + + return 0; +} + +/* ------------------------------------------------------------- */ + +static void t1pci_dispatch_tx(avmcard *card) +{ + avmcard_dmainfo *dma = card->dma; + unsigned long flags; + struct sk_buff *skb; + __u8 cmd, subcmd; + __u16 len; + __u32 txlen; + int inint; + void *p; + + save_flags(flags); + cli(); + + inint = card->interrupt; + + if (card->csr & EN_TX_TC_INT) { /* tx busy */ + restore_flags(flags); + return; + } + + skb = skb_dequeue(&dma->send_queue); + if (!skb) { +#ifdef CONFIG_T1PCI_DEBUG + printk(KERN_DEBUG "tx(%d): underrun\n", inint); +#endif + restore_flags(flags); + return; + } + + len = CAPIMSG_LEN(skb->data); + + if (len) { + cmd = CAPIMSG_COMMAND(skb->data); + subcmd = CAPIMSG_SUBCOMMAND(skb->data); + + p = dma->sendbuf; + + if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { + __u16 dlen = CAPIMSG_DATALEN(skb->data); + _put_byte(&p, SEND_DATA_B3_REQ); + _put_slice(&p, skb->data, len); + _put_slice(&p, skb->data + len, dlen); + } else { + _put_byte(&p, SEND_MESSAGE); + _put_slice(&p, skb->data, len); + } + txlen = (__u8 *)p - (__u8 *)dma->sendbuf; +#ifdef CONFIG_T1PCI_DEBUG + printk(KERN_DEBUG "tx(%d): put msg len=%d\n", + inint, txlen); +#endif + } else { + txlen = skb->len-2; +#ifdef CONFIG_T1PCI_POLLDEBUG + if (skb->data[2] == SEND_POLLACK) + printk(KERN_INFO "%s: ack to t1\n", card->name); +#endif +#ifdef CONFIG_T1PCI_DEBUG + printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n", + inint, skb->data[2], txlen); +#endif + memcpy(dma->sendbuf, skb->data+2, skb->len-2); + } + txlen = (txlen + 3) & ~3; + + t1outmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf)); + t1outmeml(card->mbase+AMCC_TXLEN, txlen); + + card->csr |= EN_TX_TC_INT; + + if (!inint) + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + + restore_flags(flags); + dev_kfree_skb(skb); +} + +/* ------------------------------------------------------------- */ + +static void queue_pollack(avmcard *card) +{ + struct sk_buff *skb; + void *p; + + skb = alloc_skb(3, GFP_ATOMIC); + if (!skb) { + printk(KERN_CRIT "%s: no memory, lost poll ack\n", + card->name); + return; + } + p = skb->data; + _put_byte(&p, 0); + _put_byte(&p, 0); + _put_byte(&p, SEND_POLLACK); + skb_put(skb, (__u8 *)p - (__u8 *)skb->data); + + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); +} + +/* ------------------------------------------------------------- */ + +static void t1pci_handle_rx(avmcard *card) +{ + avmctrl_info *cinfo = &card->ctrlinfo[0]; + avmcard_dmainfo *dma = card->dma; + struct capi_ctr *ctrl = cinfo->capi_ctrl; + struct sk_buff *skb; + void *p = dma->recvbuf+4; + __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; + __u8 b1cmd = _get_byte(&p); + +#ifdef CONFIG_T1PCI_DEBUG + printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen); +#endif + + switch (b1cmd) { + case RECEIVE_DATA_B3_IND: + + ApplId = (unsigned) _get_word(&p); + MsgLen = _get_slice(&p, card->msgbuf); + DataB3Len = _get_slice(&p, card->databuf); + + if (MsgLen < 30) { /* not CAPI 64Bit */ + memset(card->msgbuf+MsgLen, 0, 30-MsgLen); + MsgLen = 30; + CAPIMSG_SETLEN(card->msgbuf, 30); + } + if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); + } else { + memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); + memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); + ctrl->handle_capimsg(ctrl, ApplId, skb); + } + break; + + case RECEIVE_MESSAGE: + + ApplId = (unsigned) _get_word(&p); + MsgLen = _get_slice(&p, card->msgbuf); + if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); + } else { + memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); + ctrl->handle_capimsg(ctrl, ApplId, skb); + } + break; + + case RECEIVE_NEW_NCCI: + + ApplId = _get_word(&p); + NCCI = _get_word(&p); + WindowSize = _get_word(&p); + + ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); + + break; + + case RECEIVE_FREE_NCCI: + + ApplId = _get_word(&p); + NCCI = _get_word(&p); + + if (NCCI != 0xffffffff) + ctrl->free_ncci(ctrl, ApplId, NCCI); + else ctrl->appl_released(ctrl, ApplId); + break; + + case RECEIVE_START: +#ifdef CONFIG_T1PCI_POLLDEBUG + printk(KERN_INFO "%s: poll from t1\n", card->name); +#endif + if (!suppress_pollack) + queue_pollack(card); + ctrl->resume_output(ctrl); + break; + + case RECEIVE_STOP: + ctrl->suspend_output(ctrl); + break; + + case RECEIVE_INIT: + + cinfo->versionlen = _get_slice(&p, cinfo->versionbuf); + b1_parse_version(cinfo); + printk(KERN_INFO "%s: %s-card (%s) now active\n", + card->name, + cinfo->version[VER_CARDTYPE], + cinfo->version[VER_DRIVER]); + ctrl->ready(ctrl); + break; + + case RECEIVE_TASK_READY: + ApplId = (unsigned) _get_word(&p); + MsgLen = _get_slice(&p, card->msgbuf); + card->msgbuf[MsgLen--] = 0; + while ( MsgLen >= 0 + && ( card->msgbuf[MsgLen] == '\n' + || card->msgbuf[MsgLen] == '\r')) + card->msgbuf[MsgLen--] = 0; + printk(KERN_INFO "%s: task %d \"%s\" ready.\n", + card->name, ApplId, card->msgbuf); + break; + + case RECEIVE_DEBUGMSG: + MsgLen = _get_slice(&p, card->msgbuf); + card->msgbuf[MsgLen--] = 0; + while ( MsgLen >= 0 + && ( card->msgbuf[MsgLen] == '\n' + || card->msgbuf[MsgLen] == '\r')) + card->msgbuf[MsgLen--] = 0; + printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); + break; + + default: + printk(KERN_ERR "%s: t1pci_interrupt: 0x%x ???\n", + card->name, b1cmd); + return; + } +} + +/* ------------------------------------------------------------- */ + +static void t1pci_handle_interrupt(avmcard *card) +{ + __u32 status = t1inmeml(card->mbase+AMCC_INTCSR); + __u32 newcsr; + + if ((status & ANY_S5933_INT) == 0) + return; + + newcsr = card->csr | (status & ALL_INT); + if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT; + if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT; + t1outmeml(card->mbase+AMCC_INTCSR, newcsr); + + if ((status & RX_TC_INT) != 0) { + __u8 *recvbuf = card->dma->recvbuf; + __u32 rxlen; + if (card->dma->recvlen == 0) { + card->dma->recvlen = *((__u32 *)recvbuf); + rxlen = (card->dma->recvlen + 3) & ~3; + t1outmeml(card->mbase+AMCC_RXPTR, + virt_to_phys(recvbuf+4)); + t1outmeml(card->mbase+AMCC_RXLEN, rxlen); + } else { + t1pci_handle_rx(card); + card->dma->recvlen = 0; + t1outmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf)); + t1outmeml(card->mbase+AMCC_RXLEN, 4); + } + } + + if ((status & TX_TC_INT) != 0) { + card->csr &= ~EN_TX_TC_INT; + t1pci_dispatch_tx(card); + } else if (card->csr & EN_TX_TC_INT) { + if (t1inmeml(card->mbase+AMCC_TXLEN) == 0) { + card->csr &= ~EN_TX_TC_INT; + t1pci_dispatch_tx(card); + } + } + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); +} + +static void t1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs) +{ + avmcard *card; + + card = (avmcard *) devptr; + + if (!card) { + printk(KERN_WARNING "t1pci: interrupt: wrong device\n"); + return; + } + if (card->interrupt) { + printk(KERN_ERR "%s: reentering interrupt hander\n", card->name); + return; + } + + card->interrupt = 1; + + t1pci_handle_interrupt(card); + + card->interrupt = 0; +} + +/* ------------------------------------------------------------- */ + +static int t1pci_loaded(avmcard *card) +{ + unsigned long stop; + unsigned char ans; + unsigned long tout = 2; + unsigned int base = card->port; + + for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { + if (b1_tx_empty(base)) + break; + } + if (!b1_tx_empty(base)) { + printk(KERN_ERR "%s: t1pci_loaded: tx err, corrupted t4 file ?\n", + card->name); + return 0; + } + b1_put_byte(base, SEND_POLLACK); + for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { + if (b1_rx_full(base)) { + if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) { + return 1; + } + printk(KERN_ERR "%s: t1pci_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans); + return 0; + } + } + printk(KERN_ERR "%s: t1pci_loaded: firmware not running\n", card->name); + return 0; +} + +/* ------------------------------------------------------------- */ + +static void t1pci_send_init(avmcard *card) +{ + struct sk_buff *skb; + void *p; + + skb = alloc_skb(15, GFP_ATOMIC); + if (!skb) { + printk(KERN_CRIT "%s: no memory, lost register appl.\n", + card->name); + return; + } + p = skb->data; + _put_byte(&p, 0); + _put_byte(&p, 0); + _put_byte(&p, SEND_INIT); + _put_word(&p, AVM_NAPPS); + _put_word(&p, AVM_NCCI_PER_CHANNEL*30); + _put_word(&p, card->cardnr - 1); + skb_put(skb, (__u8 *)p - (__u8 *)skb->data); + + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); +} + +static int t1pci_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + unsigned long flags; + int retval; + + t1pci_reset(card); + + if ((retval = b1_load_t4file(card, &data->firmware))) { + t1pci_reset(card); + printk(KERN_ERR "%s: failed to load t4file!!\n", + card->name); + return retval; + } + + if (data->configuration.len > 0 && data->configuration.data) { + if ((retval = b1_load_config(card, &data->configuration))) { + t1pci_reset(card); + printk(KERN_ERR "%s: failed to load config!!\n", + card->name); + return retval; + } + } + + if (!t1pci_loaded(card)) { + t1pci_reset(card); + printk(KERN_ERR "%s: failed to load t4file.\n", card->name); + return -EIO; + } + + save_flags(flags); + cli(); + + card->csr = AVM_FLAG; + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + t1outmeml(card->mbase+AMCC_MCSR, + EN_A2P_TRANSFERS|EN_P2A_TRANSFERS + |A2P_HI_PRIORITY|P2A_HI_PRIORITY + |RESET_A2P_FLAGS|RESET_P2A_FLAGS); + t1outp(card->port, 0x07, 0x30); + t1outp(card->port, 0x10, 0xF0); + + card->dma->recvlen = 0; + t1outmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf)); + t1outmeml(card->mbase+AMCC_RXLEN, 4); + card->csr |= EN_RX_TC_INT; + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + restore_flags(flags); + + t1pci_send_init(card); + + return 0; +} + +void t1pci_reset_ctr(struct capi_ctr *ctrl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + + t1pci_reset(card); + + memset(cinfo->version, 0, sizeof(cinfo->version)); + ctrl->reseted(ctrl); +} + +static void t1pci_remove_ctr(struct capi_ctr *ctrl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + + t1pci_reset(card); + + di->detach_ctr(ctrl); + free_irq(card->irq, card); + iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); + release_region(card->port, AVMB1_PORTLEN); + ctrl->driverdata = 0; + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + + MOD_DEC_USE_COUNT; +} + +/* ------------------------------------------------------------- */ + + +void t1pci_register_appl(struct capi_ctr *ctrl, + __u16 appl, + capi_register_params *rp) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + struct sk_buff *skb; + int want = rp->level3cnt; + int nconn; + void *p; + + if (want > 0) nconn = want; + else nconn = ctrl->profile.nbchannel * -want; + if (nconn == 0) nconn = ctrl->profile.nbchannel; + + skb = alloc_skb(23, GFP_ATOMIC); + if (!skb) { + printk(KERN_CRIT "%s: no memory, lost register appl.\n", + card->name); + return; + } + p = skb->data; + _put_byte(&p, 0); + _put_byte(&p, 0); + _put_byte(&p, SEND_REGISTER); + _put_word(&p, appl); + _put_word(&p, 1024 * (nconn+1)); + _put_word(&p, nconn); + _put_word(&p, rp->datablkcnt); + _put_word(&p, rp->datablklen); + skb_put(skb, (__u8 *)p - (__u8 *)skb->data); + + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); + + ctrl->appl_registered(ctrl, appl); +} + +/* ------------------------------------------------------------- */ + +void t1pci_release_appl(struct capi_ctr *ctrl, __u16 appl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + struct sk_buff *skb; + void *p; + + skb = alloc_skb(7, GFP_ATOMIC); + if (!skb) { + printk(KERN_CRIT "%s: no memory, lost release appl.\n", + card->name); + return; + } + p = skb->data; + _put_byte(&p, 0); + _put_byte(&p, 0); + _put_byte(&p, SEND_RELEASE); + _put_word(&p, appl); + + skb_put(skb, (__u8 *)p - (__u8 *)skb->data); + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); +} + +/* ------------------------------------------------------------- */ + + +static void t1pci_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); +} + +/* ------------------------------------------------------------- */ + +static char *t1pci_procinfo(struct capi_ctr *ctrl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) + return ""; + sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0, + cinfo->card ? cinfo->card->membase : 0 + ); + return cinfo->infobuf; +} + +static int t1pci_read_proc(char *page, char **start, off_t off, + int count, int *eof, struct capi_ctr *ctrl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + unsigned long flags; + __u8 flag; + int len = 0; + char *s; + __u32 txaddr, txlen, rxaddr, rxlen, csr; + + len += sprintf(page+len, "%-16s %s\n", "name", card->name); + len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); + len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); + len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); + switch (card->cardtype) { + case avm_b1isa: s = "B1 ISA"; break; + case avm_b1pci: s = "B1 PCI"; break; + case avm_b1pcmcia: s = "B1 PCMCIA"; break; + case avm_m1: s = "M1"; break; + case avm_m2: s = "M2"; break; + case avm_t1isa: s = "T1 ISA (HEMA)"; break; + case avm_t1pci: s = "T1 PCI"; break; + case avm_c4: s = "C4"; 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); + + if (card->cardtype != avm_m1) { + flag = ((__u8 *)(ctrl->profile.manu))[3]; + if (flag) + len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", + "protocol", + (flag & 0x01) ? " DSS1" : "", + (flag & 0x02) ? " CT1" : "", + (flag & 0x04) ? " VN3" : "", + (flag & 0x08) ? " NI1" : "", + (flag & 0x10) ? " AUSTEL" : "", + (flag & 0x20) ? " ESS" : "", + (flag & 0x40) ? " 1TR6" : "" + ); + } + if (card->cardtype != avm_m1) { + flag = ((__u8 *)(ctrl->profile.manu))[5]; + if (flag) + len += sprintf(page+len, "%-16s%s%s%s%s\n", + "linetype", + (flag & 0x01) ? " point to point" : "", + (flag & 0x02) ? " point to multipoint" : "", + (flag & 0x08) ? " leased line without D-channel" : "", + (flag & 0x04) ? " leased line with D-channel" : "" + ); + } + len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); + + save_flags(flags); + cli(); + + txaddr = (__u32)phys_to_virt(t1inmeml(card->mbase+0x2c)); + txaddr -= (__u32)card->dma->sendbuf; + txlen = t1inmeml(card->mbase+0x30); + + rxaddr = (__u32)phys_to_virt(t1inmeml(card->mbase+0x24)); + rxaddr -= (__u32)card->dma->recvbuf; + rxlen = t1inmeml(card->mbase+0x28); + + csr = t1inmeml(card->mbase+AMCC_INTCSR); + + restore_flags(flags); + + len += sprintf(page+len, "%-16s 0x%lx\n", + "csr (cached)", (unsigned long)card->csr); + len += sprintf(page+len, "%-16s 0x%lx\n", + "csr", (unsigned long)csr); + len += sprintf(page+len, "%-16s %lu\n", + "txoff", (unsigned long)txaddr); + len += sprintf(page+len, "%-16s %lu\n", + "txlen", (unsigned long)txlen); + len += sprintf(page+len, "%-16s %lu\n", + "rxoff", (unsigned long)rxaddr); + len += sprintf(page+len, "%-16s %lu\n", + "rxlen", (unsigned long)rxlen); + + if (off+count >= len) + *eof = 1; + if (len < off) + return 0; + *start = page + off; + return ((count < len-off) ? count : len-off); +} + +/* ------------------------------------------------------------- */ + +static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p) +{ + unsigned long page_offset, base; + avmcard *card; + avmctrl_info *cinfo; + int retval; + + card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); + + if (!card) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + return -ENOMEM; + } + memset(card, 0, sizeof(avmcard)); + card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC); + if (!card->dma) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card); + return -ENOMEM; + } + memset(card->dma, 0, sizeof(avmcard_dmainfo)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card->dma); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; + sprintf(card->name, "t1pci-%x", p->port); + card->port = p->port; + card->irq = p->irq; + card->membase = p->membase; + card->cardtype = avm_t1pci; + + if (check_region(card->port, AVMB1_PORTLEN)) { + printk(KERN_WARNING + "%s: ports 0x%03x-0x%03x in use.\n", + driver->name, card->port, card->port + AVMB1_PORTLEN); + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + return -EBUSY; + } + + base = card->membase & PAGE_MASK; + page_offset = card->membase - base; + card->mbase = ioremap_nocache(base, page_offset + 64); + + t1pci_reset(card); + + if ((retval = t1pci_detect(card)) != 0) { + printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", + driver->name, card->port, retval); + iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + return -EIO; + } + t1pci_reset(card); + + request_region(p->port, AVMB1_PORTLEN, card->name); + + retval = request_irq(card->irq, t1pci_interrupt, SA_SHIRQ, card->name, card); + if (retval) { + printk(KERN_ERR "%s: unable to get IRQ %d.\n", + driver->name, card->irq); + iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); + release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + return -EBUSY; + } + + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { + printk(KERN_ERR "%s: attach controller failed.\n", driver->name); + iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); + free_irq(card->irq, card); + release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + return -EBUSY; + } + card->cardnr = cinfo->capi_ctrl->cnr; + + skb_queue_head_init(&card->dma->send_queue); + + MOD_INC_USE_COUNT; + + return 0; +} + +/* ------------------------------------------------------------- */ + +static struct capi_driver t1pci_driver = { + "t1pci", + "0.0", + t1pci_load_firmware, + t1pci_reset_ctr, + t1pci_remove_ctr, + t1pci_register_appl, + t1pci_release_appl, + t1pci_send_message, + + t1pci_procinfo, + t1pci_read_proc, + 0, /* use standard driver_read_proc */ + + 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) +{ + struct capi_driver *driver = &t1pci_driver; + struct pci_dev *dev = NULL; + char *p; + int retval; + + if ((p = strchr(revision, ':'))) { + strncpy(driver->revision, p + 1, sizeof(driver->revision)); + p = strchr(driver->revision, '$'); + *p = 0; + } + + printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); + + di = attach_capi_driver(driver); + + if (!di) { + printk(KERN_ERR "%s: failed to attach capi_driver\n", + driver->name); + return -EIO; + } + +#ifdef CONFIG_PCI + if (!pci_present()) { + printk(KERN_ERR "%s: no PCI bus present\n", driver->name); + detach_capi_driver(driver); + return -EIO; + } + + while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, dev))) { + struct capicardparams param; + + param.port = dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; + param.irq = dev->irq; + param.membase = dev->resource[ 0].start & PCI_BASE_ADDRESS_MEM_MASK; + + printk(KERN_INFO + "%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n", + driver->name, param.port, param.irq, param.membase); + retval = t1pci_add_card(driver, ¶m); + if (retval != 0) { + 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 + return retval; + } + ncards++; + } + if (ncards) { + printk(KERN_INFO "%s: %d T1-PCI card(s) detected\n", + driver->name, ncards); + return 0; + } + printk(KERN_ERR "%s: NO T1-PCI card detected\n", driver->name); + return -ESRCH; +#else + printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name); + return -EIO; +#endif +} + +#ifdef MODULE +void cleanup_module(void) +{ + detach_capi_driver(&t1pci_driver); +} +#endif diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 035aa363613a808e1d9868703edb32e785f4f1c3..58a47bcd8e1f320e2337775da8432fc41a13ff71 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -1,5 +1,5 @@ /* - * $Id: divert_procfs.c,v 1.4 1999/08/06 07:42:48 calle Exp $ + * $Id: divert_procfs.c,v 1.5 1999/09/14 20:31:01 werner Exp $ * * Filesystem handling for the diversion supplementary services. * @@ -20,6 +20,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: divert_procfs.c,v $ + * Revision 1.5 1999/09/14 20:31:01 werner + * + * Removed obsoleted functions for proc fs and synced with new ones. + * * Revision 1.4 1999/08/06 07:42:48 calle * Added COMPAT_HAS_NEW_WAITQ for rd_queue for newer kernels. * @@ -38,16 +42,13 @@ #define __NO_VERSION__ #include <linux/module.h> #include <linux/version.h> -#if (LINUX_VERSION_CODE >= 0x020117) #include <linux/poll.h> -#endif #ifdef CONFIG_PROC_FS #include <linux/proc_fs.h> #else #include <linux/fs.h> #endif #include <linux/isdnif.h> -#include <linux/isdn_compat.h> #include "isdn_divert.h" /*********************************/ @@ -56,11 +57,7 @@ ulong if_used = 0; /* number of interface users */ static struct divert_info *divert_info_head = NULL; /* head of queue */ static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */ -#ifdef COMPAT_HAS_NEW_WAITQ static wait_queue_head_t rd_queue; -#else -static struct wait_queue *rd_queue = 0; /* Queue IO */ -#endif /*********************************/ /* put an info buffer into queue */ @@ -101,11 +98,7 @@ void put_info_buffer(char *cp) /**********************************/ /* deflection device read routine */ /**********************************/ -#if (LINUX_VERSION_CODE < 0x020117) -static int isdn_divert_read(struct inode *inode, struct file *file, char *buf, RWARG count) -#else static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff_t *off) -#endif { struct divert_info *inf; int len; @@ -130,11 +123,7 @@ static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff /**********************************/ /* deflection device write routine */ /**********************************/ -#if (LINUX_VERSION_CODE < 0x020117) -static int isdn_divert_write(struct inode *inode, struct file *file, const char *buf, RWARG count) -#else static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t *off) -#endif { return(-ENODEV); } /* isdn_divert_write */ @@ -143,17 +132,6 @@ static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t coun /***************************************/ /* select routines for various kernels */ /***************************************/ -#if (LINUX_VERSION_CODE < 0x020117) -static int isdn_divert_select(struct inode *inode, struct file *file, int type, select_table * st) -{ - if (*((struct divert_info **)file->private_data)) - return 1; - else - { if (st) select_wait(&(rd_queue), st); - return 0; - } -} /* isdn_divert_select */ -#else static unsigned int isdn_divert_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; @@ -164,7 +142,6 @@ static unsigned int isdn_divert_poll(struct file *file, poll_table * wait) } return mask; } /* isdn_divert_poll */ -#endif /****************/ /* Open routine */ @@ -188,11 +165,7 @@ static int isdn_divert_open(struct inode *ino, struct file *filep) /*******************/ /* close routine */ /*******************/ -#if (LINUX_VERSION_CODE < 0x020117) -static void isdn_divert_close(struct inode *ino, struct file *filep) -#else static int isdn_divert_close(struct inode *ino, struct file *filep) -#endif { struct divert_info *inf; int flags; @@ -212,10 +185,7 @@ static int isdn_divert_close(struct inode *ino, struct file *filep) kfree(inf); } MOD_DEC_USE_COUNT; -#if (LINUX_VERSION_CODE < 0x020117) -#else return(0); -#endif } /* isdn_divert_close */ /*********/ @@ -301,34 +271,12 @@ static int isdn_divert_ioctl(struct inode *inode, struct file *file, #ifdef CONFIG_PROC_FS -#if (LINUX_VERSION_CODE < 0x020117) -static LSTYPE -isdn_divert_lseek(struct inode *inode, struct file *file, LSARG offset, int orig) -#else static loff_t isdn_divert_lseek(struct file *file, loff_t offset, int orig) -#endif { return -ESPIPE; } -#if (LINUX_VERSION_CODE < 0x020117) -static struct file_operations isdn_fops = -{ - isdn_divert_lseek, - isdn_divert_read, - isdn_divert_write, - NULL, /* isdn_readdir */ - isdn_divert_select, /* isdn_select */ - isdn_divert_ioctl, /* isdn_ioctl */ - NULL, /* isdn_mmap */ - isdn_divert_open, - isdn_divert_close, - NULL /* fsync */ -}; - -#else - static struct file_operations isdn_fops = { isdn_divert_lseek, @@ -343,51 +291,33 @@ static struct file_operations isdn_fops = isdn_divert_close, NULL /* fsync */ }; -#endif /* kernel >= 2.1 */ - -/* - * proc directories can do almost nothing.. - */ -struct inode_operations proc_isdn_inode_ops = { - &isdn_fops, /* isdn divert special file-ops */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* bmap */ - NULL, /* truncate */ - NULL /* permission */ +struct inode_operations divert_file_inode_operations = { + &isdn_fops, /* default proc file-ops */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL /* permission */ }; + /****************************/ /* isdn subdir in /proc/net */ /****************************/ -static struct proc_dir_entry isdn_proc_entry = - { 0, 4, "isdn", S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, 0, - &proc_dir_inode_operations,NULL,NULL,NULL,NULL,NULL - }; - -static struct proc_dir_entry isdn_divert_entry = -{ 0, 6, "divert",S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_isdn_inode_ops, - NULL - }; - -/*****************************************************************/ -/* variables used for automatic determining existence of proc fs */ -/*****************************************************************/ -static int (*proc_reg_dynamic)(struct proc_dir_entry *, struct proc_dir_entry *) = NULL; -static int (*proc_unreg)(struct proc_dir_entry *, int) = NULL; - +static struct proc_dir_entry *isdn_proc_entry = NULL; +static struct proc_dir_entry *isdn_divert_entry = NULL; #endif CONFIG_PROC_FS /***************************************************************************/ @@ -396,36 +326,19 @@ static int (*proc_unreg)(struct proc_dir_entry *, int) = NULL; int divert_dev_init(void) { int i; -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&rd_queue); -#endif #ifdef CONFIG_PROC_FS -#if (LINUX_VERSION_CODE < 0x020117) - (void *) proc_reg_dynamic = get_module_symbol("","proc_register_dynamic"); - (void *) proc_unreg = get_module_symbol("","proc_unregister"); - if (proc_unreg) - { i = proc_reg_dynamic(&proc_net,&isdn_proc_entry); - if (i) return(i); - i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry); - if (i) - { proc_unreg(&proc_net,isdn_proc_entry.low_ino); - return(i); - } - } /* proc exists */ -#else - (void *) proc_reg_dynamic = get_module_symbol("","proc_register"); - (void *) proc_unreg = get_module_symbol("","proc_unregister"); - if (proc_unreg) - { i = proc_reg_dynamic(proc_net,&isdn_proc_entry); - if (i) return(i); - i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry); - if (i) - { proc_unreg(proc_net,isdn_proc_entry.low_ino); - return(i); - } - } /* proc exists */ -#endif + isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO ,proc_net); + if (!isdn_proc_entry) + return(-1); + isdn_divert_entry = create_proc_entry("divert",S_IFREG | S_IRUGO,isdn_proc_entry); + if (!isdn_divert_entry) + { + remove_proc_entry("isdn",proc_net); + return(-1); + } + isdn_divert_entry->ops = &divert_file_inode_operations; #endif CONFIG_PROC_FS return(0); @@ -439,16 +352,8 @@ int divert_dev_deinit(void) { int i; #ifdef CONFIG_PROC_FS - if (proc_unreg) - { i = proc_unreg(&isdn_proc_entry,isdn_divert_entry.low_ino); - if (i) return(i); -#if (LINUX_VERSION_CODE < 0x020117) - i = proc_unreg(&proc_net,isdn_proc_entry.low_ino); -#else - i = proc_unreg(proc_net,isdn_proc_entry.low_ino); -#endif - if (i) return(i); - } /* proc exists */ + remove_proc_entry("divert",isdn_proc_entry); + remove_proc_entry("isdn",proc_net); #endif CONFIG_PROC_FS return(0); diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index f10ea18b26f83ded6174c61ae71f41da5cf94c1f..7079232e7dcfd73adb288a7fdec7b6f73fc81dd2 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -1,5 +1,5 @@ /* - * $Id: isdn_divert.c,v 1.4 1999/08/25 20:02:21 werner Exp $ + * $Id: isdn_divert.c,v 1.5 1999/08/31 11:20:04 paul Exp $ * * DSS1 main diversion supplementary handling for i4l. * @@ -20,6 +20,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_divert.c,v $ + * Revision 1.5 1999/08/31 11:20:04 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.4 1999/08/25 20:02:21 werner * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts * with existing software definitions. (PtP incomplete called party number) @@ -513,7 +516,7 @@ int isdn_divert_icall(isdn_ctrl *ic) if (cs->akt_state == DEFLECT_ALERT) { strcpy(cs->deflect_dest,dv->rule.to_nr); if (!cs->timer.expires) - { strcpy(ic->parm.setup.eazmsn,"Testtext direkt"); + { strcpy(ic->parm.setup.eazmsn,"Testtext direct"); ic->parm.setup.screen = dv->rule.screen; strcpy(ic->parm.setup.phone,dv->rule.to_nr); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ @@ -769,18 +772,6 @@ int prot_stat_callback(isdn_ctrl *ic) } -#if 0 - sprintf(st, "0x%lx 0x%lx",ic->arg, ic->parm.dss1_io.ll_id); - p = st + strlen(st); - p1 = ic->parm.dss1_io.data; - i = ic->parm.dss1_io.datalen; - while ((i > 0) && (p - st < 530)) - { p += sprintf(p," %02x",(*p1++) & 0xFF); - i--; - } - sprintf(p, "\n"); - put_info_buffer(st); -#endif break; default: diff --git a/drivers/isdn/divert/isdn_divert.h b/drivers/isdn/divert/isdn_divert.h index 1d329c0fb7491108e823c770553f2444905a7310..6ab119ed9527f05e3bd19f337a6217dd037393f1 100644 --- a/drivers/isdn/divert/isdn_divert.h +++ b/drivers/isdn/divert/isdn_divert.h @@ -1,5 +1,5 @@ /* - * $Id: isdn_divert.h,v 1.3 1999/08/22 20:26:37 calle Exp $ + * $Id: isdn_divert.h,v 1.4 1999/09/02 13:24:12 paul Exp $ * * Header for the diversion supplementary ioctl interface. * @@ -20,6 +20,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_divert.h,v $ + * Revision 1.4 1999/09/02 13:24:12 paul + * cosmetics; text following #endif is not ANSI C + * * Revision 1.3 1999/08/22 20:26:37 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -29,12 +32,9 @@ * Revision 1.2 1999/07/04 21:37:33 werner * Ported from kernel version 2.0 * - * - * */ - #include <linux/ioctl.h> #include <linux/types.h> @@ -94,12 +94,12 @@ typedef struct typedef union { int drv_version; /* return of driver version */ struct - { int drvid; /* id of driver */ - char drvnam[30]; /* name of driver */ + { int drvid; /* id of driver */ + char drvnam[30]; /* name of driver */ } getid; struct - { int ruleidx; /* index of rule */ - divert_rule rule; /* rule parms */ + { int ruleidx; /* index of rule */ + divert_rule rule; /* rule parms */ } getsetrule; struct { u_char subcmd; /* 0 = hangup/reject, @@ -125,7 +125,7 @@ typedef union #include <linux/isdnif.h> #include <linux/isdn_divertif.h> -#define AUTODEL_TIME 30 /* timeout in s to delete internal entrys */ +#define AUTODEL_TIME 30 /* timeout in s to delete internal entries */ /**************************************************/ /* structure keeping ascii info for device output */ @@ -153,12 +153,4 @@ extern void deleteprocs(void); extern int deflect_extern_action(u_char, ulong, char *); extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *); -#endif __KERNEL__ - - - - - - - - +#endif /* __KERNEL__ */ diff --git a/drivers/isdn/eicon/eicon.h b/drivers/isdn/eicon/eicon.h index beee023dccd123d004d872cf2bb72367d2c9c770..88af10416c4855678c900cd14b9b97da21771815 100644 --- a/drivers/isdn/eicon/eicon.h +++ b/drivers/isdn/eicon/eicon.h @@ -1,8 +1,8 @@ -/* $Id: eicon.h,v 1.11 1999/08/29 17:23:44 armin Exp $ +/* $Id: eicon.h,v 1.17 1999/10/26 21:15:33 armin Exp $ * * ISDN low-level module for Eicon.Diehl active ISDN-Cards. * - * Copyright 1998 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * @@ -21,6 +21,26 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon.h,v $ + * Revision 1.17 1999/10/26 21:15:33 armin + * using define for checking phone number len to avoid buffer overflow. + * + * Revision 1.16 1999/10/08 22:09:33 armin + * Some fixes of cards interface handling. + * Bugfix of NULL pointer occurence. + * Changed a few log outputs. + * + * Revision 1.15 1999/09/26 14:17:53 armin + * Improved debug and log via readstat() + * + * Revision 1.14 1999/09/08 20:17:31 armin + * Added microchannel patch from Erik Weber. + * + * Revision 1.13 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * + * Revision 1.12 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.11 1999/08/29 17:23:44 armin * New setup compat. * Bugfix if compile as not module. @@ -117,6 +137,7 @@ #define MAX_HEADER_LEN 10 +#define MAX_STATUS_BUFFER 150 /* Struct for adding new cards */ typedef struct eicon_cdef { @@ -224,9 +245,9 @@ typedef struct { #include <linux/delay.h> #include <linux/ctype.h> +#include <linux/isdn.h> #include <linux/isdnif.h> -#include <linux/isdn_compat.h> typedef struct { __u16 length __attribute__ ((packed)); /* length of data/parameter field */ @@ -237,7 +258,7 @@ typedef struct { /* Macro for delay via schedule() */ #define SLEEP(j) { \ - current->state = TASK_INTERRUPTIBLE; \ + set_current_state(TASK_INTERRUPTIBLE); \ schedule_timeout(j); \ } @@ -472,7 +493,6 @@ typedef struct { typedef struct { int No; /* Channel Number */ - unsigned short callref; /* Call Reference */ unsigned short fsm_state; /* Current D-Channel state */ unsigned short eazmask; /* EAZ-Mask for this Channel */ int queued; /* User-Data Bytes in TX queue */ @@ -489,9 +509,13 @@ typedef struct { entity e; /* Entity */ char cpn[32]; /* remember cpn */ char oad[32]; /* remember oad */ + char dsa[32]; /* remember dsa */ + char osa[32]; /* remember osa */ unsigned char cause[2]; /* Last Cause */ unsigned char si1; unsigned char si2; + unsigned char plan; + unsigned char screen; } eicon_chan; typedef struct { @@ -527,7 +551,7 @@ typedef struct { #define EICON_STATE_LISTEN 15 #define EICON_STATE_WMCONN 16 -#define EICON_MAX_QUEUED 8000 /* 2 * maxbuff */ +#define EICON_MAX_QUEUE 2138 #define EICON_LOCK_TX 0 #define EICON_LOCK_RX 1 @@ -581,6 +605,8 @@ typedef struct eicon_card { struct sk_buff_head sndq; /* Send-Message queue */ struct sk_buff_head rackq; /* Req-Ack-Message queue */ struct sk_buff_head sackq; /* Data-Ack-Message queue */ + struct sk_buff_head statq; /* Status-Message queue */ + int statq_entries; u_char *ack_msg; /* Ptr to User Data in User skb */ __u16 need_b3ack; /* Flag: Need ACK for current skb */ struct sk_buff *sbuf; /* skb which is currently sent */ @@ -602,8 +628,9 @@ typedef struct eicon_card { isdn_if interface; /* Interface to upper layer */ char regname[35]; /* Name used for request_region */ #ifdef CONFIG_MCA - int mca_slot; /* # of cards MCA slot */ -#endif + int mca_slot; /* # of cards MCA slot */ + int mca_io; /* MCA cards IO port */ +#endif /* CONFIG_MCA */ } eicon_card; /* -----------------------------------------------------------** @@ -668,6 +695,7 @@ extern int eicon_info(char *, int , void *); #endif /* CONFIG_MCA */ extern ulong DebugVar; +extern void eicon_log(eicon_card * card, int level, const char *fmt, ...); #endif /* __KERNEL__ */ diff --git a/drivers/isdn/eicon/eicon_idi.c b/drivers/isdn/eicon/eicon_idi.c index af9c3048398e307b04b56d200c1e4418f43a325f..d8634bdbe587649c4b01a3da7b9fa4a87b7108c4 100644 --- a/drivers/isdn/eicon/eicon_idi.c +++ b/drivers/isdn/eicon/eicon_idi.c @@ -1,4 +1,4 @@ -/* $Id: eicon_idi.c,v 1.15 1999/08/28 21:32:50 armin Exp $ +/* $Id: eicon_idi.c,v 1.24 1999/10/26 21:15:33 armin Exp $ * * ISDN lowlevel-module for Eicon.Diehl active cards. * IDI interface @@ -6,6 +6,11 @@ * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * + * Thanks to Deutsche Mailbox Saar-Lor-Lux GmbH + * for sponsoring and testing fax + * capabilities with Diva Server cards. + * (dor@deutschemailbox.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) @@ -21,6 +26,35 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_idi.c,v $ + * Revision 1.24 1999/10/26 21:15:33 armin + * using define for checking phone number len to avoid buffer overflow. + * + * Revision 1.23 1999/10/11 18:13:25 armin + * Added fax capabilities for Eicon Diva Server cards. + * + * Revision 1.22 1999/10/08 22:09:33 armin + * Some fixes of cards interface handling. + * Bugfix of NULL pointer occurence. + * Changed a few log outputs. + * + * Revision 1.21 1999/09/26 14:17:53 armin + * Improved debug and log via readstat() + * + * Revision 1.20 1999/09/21 20:35:43 armin + * added more error checking. + * + * Revision 1.19 1999/09/21 20:06:40 armin + * Added pointer checks. + * + * Revision 1.18 1999/09/07 12:48:05 armin + * Prepared for sub-address usage. + * + * Revision 1.17 1999/09/07 12:35:39 armin + * Better checking and channel Id handling. + * + * Revision 1.16 1999/09/04 13:44:19 armin + * Fix of V.42 analog Modem negotiation handling. + * * Revision 1.15 1999/08/28 21:32:50 armin * Prepared for fax related functions. * Now compilable without errors/warnings. @@ -96,7 +130,7 @@ #undef EICON_FULL_SERVICE_OKTETT -char *eicon_idi_revision = "$Revision: 1.15 $"; +char *eicon_idi_revision = "$Revision: 1.24 $"; eicon_manifbuf *manbuf; @@ -162,9 +196,14 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan) reqbuf->XBuffer.P[l++] = 5; break; case ISDN_PROTO_L2_TRANS: - case ISDN_PROTO_L2_MODEM: reqbuf->XBuffer.P[l++] = 2; break; + case ISDN_PROTO_L2_MODEM: + if (chan->fsm_state == EICON_STATE_IWAIT) + reqbuf->XBuffer.P[l++] = 9; /* V.42 incoming */ + else + reqbuf->XBuffer.P[l++] = 10; /* V.42 */ + break; case ISDN_PROTO_L2_FAX: if (chan->fsm_state == EICON_STATE_IWAIT) reqbuf->XBuffer.P[l++] = 3; /* autoconnect on incoming */ @@ -275,8 +314,7 @@ idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan) reqbuf->XBuffer.P[8] = 0; reqbuf->XBuffer.length = l; reqbuf->Reference = 0; /* Sig Entity */ - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Call_Res\n", chan->No); + eicon_log(NULL, 8, "idi_req: Ch%d: Call_Res\n", chan->No); return(0); } @@ -292,8 +330,7 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No); + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No); if (skb) dev_kfree_skb(skb); if (skb2) @@ -305,8 +342,7 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) chan2->ptr = chan; reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - if (DebugVar & 8) - printk(KERN_DEBUG "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig"); + eicon_log(card, 8, "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig"); if (layer) cmd |= 0x700; switch(cmd) { case ASSIGN: @@ -345,8 +381,7 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) idi_put_req(reqbuf, IDI_N_DISC_ACK, 1); break; default: - if (DebugVar & 1) - printk(KERN_ERR "idi_req: Ch%d: Unknown request\n", chan->No); + eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No); dev_kfree_skb(skb); dev_kfree_skb(skb2); return(-1); @@ -361,8 +396,10 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) int eicon_idi_listen_req(eicon_card *card, eicon_chan *chan) { - if (DebugVar & 16) - printk(KERN_DEBUG"idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask); + if ((!card) || (!chan)) + return 1; + + eicon_log(card, 16, "idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask); if (!chan->e.D3Id) { idi_do_req(card, chan, ASSIGN, 0); } @@ -416,15 +453,19 @@ idi_si2bc(int si1, int si2, char *bc, char *hlc) int idi_hangup(eicon_card *card, eicon_chan *chan) { + if ((!card) || (!chan)) + return 1; + if ((chan->fsm_state == EICON_STATE_ACTIVE) || (chan->fsm_state == EICON_STATE_WMCONN)) { if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1); } if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1); - idi_do_req(card, chan, HANGUP, 0); - chan->fsm_state = EICON_STATE_NULL; - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Hangup\n", chan->No); + if (chan->fsm_state != EICON_STATE_NULL) { + idi_do_req(card, chan, HANGUP, 0); + chan->fsm_state = EICON_STATE_NULL; + } + eicon_log(card, 8, "idi_req: Ch%d: Hangup\n", chan->No); #ifdef CONFIG_ISDN_TTY_FAX chan->fax = 0; #endif @@ -434,10 +475,21 @@ idi_hangup(eicon_card *card, eicon_chan *chan) int idi_connect_res(eicon_card *card, eicon_chan *chan) { - chan->fsm_state = EICON_STATE_IWAIT; - idi_do_req(card, chan, CALL_RES, 0); - idi_do_req(card, chan, ASSIGN, 1); - return(0); + if ((!card) || (!chan)) + return 1; + + chan->fsm_state = EICON_STATE_IWAIT; + idi_do_req(card, chan, CALL_RES, 0); + + /* check if old NetID has been removed */ + if (chan->e.B2Id) { + eicon_log(card, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n", + chan->No, chan->e.B2Id); + idi_do_req(card, chan, REMOVE, 1); + } + + idi_do_req(card, chan, ASSIGN, 1); + return(0); } int @@ -447,6 +499,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, int l = 0; int i; unsigned char tmp; + unsigned char *sub, *sp; unsigned char bc[5]; unsigned char hlc[5]; struct sk_buff *skb; @@ -454,12 +507,14 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, eicon_REQ *reqbuf; eicon_chan_ptr *chan2; + if ((!card) || (!chan)) + return 1; + skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No); + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No); if (skb) dev_kfree_skb(skb); if (skb2) @@ -475,18 +530,52 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, reqbuf->ReqCh = 0; reqbuf->ReqId = 1; + sub = NULL; + sp = phone; + while (*sp) { + if (*sp == '.') { + sub = sp + 1; + *sp = 0; + } else + sp++; + } reqbuf->XBuffer.P[l++] = CPN; reqbuf->XBuffer.P[l++] = strlen(phone) + 1; reqbuf->XBuffer.P[l++] = 0x81; for(i=0; i<strlen(phone);i++) - reqbuf->XBuffer.P[l++] = phone[i]; + reqbuf->XBuffer.P[l++] = phone[i] & 0x7f; + if (sub) { + reqbuf->XBuffer.P[l++] = DSA; + reqbuf->XBuffer.P[l++] = strlen(sub) + 2; + reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */ + reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */ + while (*sub) + reqbuf->XBuffer.P[l++] = *sub++ & 0x7f; + } + sub = NULL; + sp = eazmsn; + while (*sp) { + if (*sp == '.') { + sub = sp + 1; + *sp = 0; + } else + sp++; + } reqbuf->XBuffer.P[l++] = OAD; reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2; reqbuf->XBuffer.P[l++] = 0x01; reqbuf->XBuffer.P[l++] = 0x80; for(i=0; i<strlen(eazmsn);i++) - reqbuf->XBuffer.P[l++] = eazmsn[i]; + reqbuf->XBuffer.P[l++] = eazmsn[i] & 0x7f; + if (sub) { + reqbuf->XBuffer.P[l++] = OSA; + reqbuf->XBuffer.P[l++] = strlen(sub) + 2; + reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */ + reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */ + while (*sub) + reqbuf->XBuffer.P[l++] = *sub++ & 0x7f; + } if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) { reqbuf->XBuffer.P[l++] = BC; @@ -500,6 +589,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, reqbuf->XBuffer.P[l++] = hlc[i]; } } + reqbuf->XBuffer.P[l++] = CAI; reqbuf->XBuffer.P[l++] = 6; reqbuf->XBuffer.P[l++] = 0x09; @@ -570,8 +660,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, skb_queue_tail(&card->sndq, skb2); eicon_schedule_tx(card); - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone); + eicon_log(card, 8, "idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone); return(0); } @@ -588,9 +677,10 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi __u16 code; isdn_ctrl cmd; - memset(message, 0, sizeof(idi_ind_message)); + memset(message, 0, sizeof(idi_ind_message)); + + if ((!len) || (!buffer[pos])) return; - if ((!len) || (!buffer[pos])) return; while(pos <= len) { w = buffer[pos++]; if (!w) return; @@ -620,8 +710,18 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi else code = w; code |= (codeset<<8); + if (pos + wlen > len) { + eicon_log(ccard, 1, "idi_err: Ch%d: IElen %d of %x exceeds Ind_Length (+%d)\n", chan->No, + wlen, code, (pos + wlen) - len); + return; + } + switch(code) { case OAD: + if (wlen > sizeof(message->oad)) { + pos += wlen; + break; + } j = 1; if (wlen) { message->plan = buffer[pos++]; @@ -634,11 +734,14 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi } for(i=0; i < wlen-j; i++) message->oad[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, - message->plan, message->screen, message->oad); + eicon_log(ccard, 2, "idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, + message->plan, message->screen, message->oad); break; case RDN: + if (wlen > sizeof(message->rdn)) { + pos += wlen; + break; + } j = 1; if (wlen) { if (!(buffer[pos++] & 0x80)) { @@ -648,92 +751,116 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi } for(i=0; i < wlen-j; i++) message->rdn[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: RDN= %s\n", chan->No, + eicon_log(ccard, 2, "idi_inf: Ch%d: RDN= %s\n", chan->No, message->rdn); break; case CPN: + if (wlen > sizeof(message->cpn)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->cpn[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No, - (__u8)message->cpn[0], message->cpn + 1); + eicon_log(ccard, 2, "idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No, + (__u8)message->cpn[0], message->cpn + 1); break; case DSA: - pos++; - for(i=0; i < wlen-1; i++) + if (wlen > sizeof(message->dsa)) { + pos += wlen; + break; + } + pos += 2; + for(i=0; i < wlen-2; i++) message->dsa[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa); + eicon_log(ccard, 2, "idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa); break; case OSA: - pos++; - for(i=0; i < wlen-1; i++) + if (wlen > sizeof(message->osa)) { + pos += wlen; + break; + } + pos += 2; + for(i=0; i < wlen-2; i++) message->osa[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa); + eicon_log(ccard, 2, "idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa); break; case BC: + if (wlen > sizeof(message->bc)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->bc[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No, - message->bc[0],message->bc[1],message->bc[2]); + eicon_log(ccard, 4, "idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No, + message->bc[0],message->bc[1],message->bc[2]); break; case 0x800|BC: + if (wlen > sizeof(message->e_bc)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->e_bc[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]); + eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]); break; case LLC: + if (wlen > sizeof(message->llc)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->llc[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0], - message->llc[1],message->llc[2],message->llc[3]); + eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0], + message->llc[1],message->llc[2],message->llc[3]); break; case HLC: + if (wlen > sizeof(message->hlc)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->hlc[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No, - message->hlc[0], message->hlc[1], - message->hlc[2], message->hlc[3], message->hlc[4]); + eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No, + message->hlc[0], message->hlc[1], + message->hlc[2], message->hlc[3], message->hlc[4]); break; case DSP: case 0x600|DSP: + if (wlen > sizeof(message->display)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->display[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: Display: %s\n", chan->No, - message->display); + eicon_log(ccard, 4, "idi_inf: Ch%d: Display: %s\n", chan->No, + message->display); break; case 0x600|KEY: + if (wlen > sizeof(message->keypad)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->keypad[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: Keypad: %s\n", chan->No, - message->keypad); + eicon_log(ccard, 4, "idi_inf: Ch%d: Keypad: %s\n", chan->No, + message->keypad); break; case NI: case 0x600|NI: if (wlen) { - if (DebugVar & 4) { - switch(buffer[pos] & 127) { - case 0: - printk(KERN_DEBUG"idi_inf: Ch%d: User suspended.\n", chan->No); - break; - case 1: - printk(KERN_DEBUG"idi_inf: Ch%d: User resumed.\n", chan->No); - break; - case 2: - printk(KERN_DEBUG"idi_inf: Ch%d: Bearer service change.\n", chan->No); - break; - default: - printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Notification %x.\n", - chan->No, buffer[pos] & 127); - } + switch(buffer[pos] & 127) { + case 0: + eicon_log(ccard, 4, "idi_inf: Ch%d: User suspended.\n", chan->No); + break; + case 1: + eicon_log(ccard, 4, "idi_inf: Ch%d: User resumed.\n", chan->No); + break; + case 2: + eicon_log(ccard, 4, "idi_inf: Ch%d: Bearer service change.\n", chan->No); + break; + default: + eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Notification %x.\n", + chan->No, buffer[pos] & 127); } pos += wlen; } @@ -741,80 +868,91 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi case PI: case 0x600|PI: if (wlen > 1) { - if (DebugVar & 4) { - switch(buffer[pos+1] & 127) { - case 1: - printk(KERN_DEBUG"idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No); - break; - case 2: - printk(KERN_DEBUG"idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No); - break; - case 3: - printk(KERN_DEBUG"idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No); - break; - case 4: - printk(KERN_DEBUG"idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No); - break; - case 5: - printk(KERN_DEBUG"idi_inf: Ch%d: Interworking has occurred.\n", chan->No); - break; - case 8: - printk(KERN_DEBUG"idi_inf: Ch%d: In-band information available.\n", chan->No); - break; - default: - printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Progress %x.\n", - chan->No, buffer[pos+1] & 127); - } + switch(buffer[pos+1] & 127) { + case 1: + eicon_log(ccard, 4, "idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No); + break; + case 2: + eicon_log(ccard, 4, "idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No); + break; + case 3: + eicon_log(ccard, 4, "idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No); + break; + case 4: + eicon_log(ccard, 4, "idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No); + break; + case 5: + eicon_log(ccard, 4, "idi_inf: Ch%d: Interworking has occurred.\n", chan->No); + break; + case 8: + eicon_log(ccard, 4, "idi_inf: Ch%d: In-band information available.\n", chan->No); + break; + default: + eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Progress %x.\n", + chan->No, buffer[pos+1] & 127); } } pos += wlen; break; case CAU: + if (wlen > sizeof(message->cau)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->cau[i] = buffer[pos++]; memcpy(&chan->cause, &message->cau, 2); - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: CAU=%d %d\n", chan->No, - message->cau[0],message->cau[1]); + eicon_log(ccard, 4, "idi_inf: Ch%d: CAU=%d %d\n", chan->No, + message->cau[0],message->cau[1]); break; case 0x800|CAU: + if (wlen > sizeof(message->e_cau)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->e_cau[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: ECAU=%d %d\n", chan->No, - message->e_cau[0],message->e_cau[1]); + eicon_log(ccard, 4, "idi_inf: Ch%d: ECAU=%d %d\n", chan->No, + message->e_cau[0],message->e_cau[1]); break; case 0x800|CHI: + if (wlen > sizeof(message->e_chi)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->e_chi[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: ESC/CHI=%d\n", chan->No, - message->e_cau[0]); + eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/CHI=%d\n", chan->No, + message->e_cau[0]); break; case 0x800|0x7a: pos ++; message->e_mt=buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt); + eicon_log(ccard, 4, "idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt); break; case DT: + if (wlen > sizeof(message->dt)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->dt[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No, - message->dt[2], message->dt[1], message->dt[0], - message->dt[3], message->dt[4], message->dt[5]); + eicon_log(ccard, 4, "idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No, + message->dt[2], message->dt[1], message->dt[0], + message->dt[3], message->dt[4], message->dt[5]); break; case 0x600|SIN: + if (wlen > sizeof(message->sin)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->sin[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: SIN=%d %d\n", chan->No, - message->sin[0],message->sin[1]); + eicon_log(ccard, 2, "idi_inf: Ch%d: SIN=%d %d\n", chan->No, + message->sin[0],message->sin[1]); break; case 0x600|CPS: - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: Called Party Status in ind\n", chan->No); + eicon_log(ccard, 2, "idi_inf: Ch%d: Called Party Status in ind\n", chan->No); pos += wlen; break; case 0x600|CIF: @@ -822,8 +960,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi if (buffer[pos + i] != '0') break; memcpy(&cmd.parm.num, &buffer[pos + i], wlen - i); cmd.parm.num[wlen - i] = 0; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num); + eicon_log(ccard, 2, "idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num); pos += wlen; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_CINF; @@ -831,8 +968,11 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi ccard->interface.statcallb(&cmd); break; case 0x600|DATE: - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: Date in ind\n", chan->No); + eicon_log(ccard, 2, "idi_inf: Ch%d: Date in ind\n", chan->No); + pos += wlen; + break; + case 0xa1: + eicon_log(ccard, 2, "idi_inf: Ch%d: Sending Complete in ind.\n", chan->No); pos += wlen; break; case 0xe08: @@ -852,8 +992,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi case 0x880: /* Managment Information Element */ if (!manbuf) { - if (DebugVar & 1) - printk(KERN_WARNING"idi_err: manbuf not allocated\n"); + eicon_log(ccard, 1, "idi_err: manbuf not allocated\n"); } else { memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen); @@ -865,9 +1004,8 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi break; default: pos += wlen; - if (DebugVar & 6) - printk(KERN_WARNING"idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", - chan->No, code, wlen); + eicon_log(ccard, 6, "idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", + chan->No, code, wlen); } } } @@ -908,110 +1046,1095 @@ idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned ch int idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer) { + eicon_t30_s *t30 = (eicon_t30_s *) buffer; - /* TODO , code follows */ + if (!chan->fax) { + eicon_log(NULL, 1,"idi_T30: fill_in with NULL fax struct, ERROR\n"); + return 0; + } + memset(t30, 0, sizeof(eicon_t30_s)); + t30->station_id_len = EICON_FAXID_LEN; + memcpy(&t30->station_id[0], &chan->fax->id[0], EICON_FAXID_LEN); + t30->resolution = chan->fax->resolution; + t30->rate = chan->fax->rate + 1; /* eicon rate starts with 1 */ + t30->format = T30_FORMAT_SFF; + t30->pages_low = 0; + t30->pages_high = 0; + t30->atf = 1; /* optimised for AT+F command set */ + t30->code = 0; + t30->feature_bits_low = 0; + t30->feature_bits_high = 0; + t30->control_bits_low = 0; + t30->control_bits_high = 0; + + if (chan->fax->nbc) { + /* set compression by DCC value */ + switch(chan->fax->compression) { + case (0): /* 1-D modified */ + break; + case (1): /* 2-D modified Read */ + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; + t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; + break; + case (2): /* 2-D uncompressed */ + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; + t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; + t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; + break; + case (3): /* 2-D modified Read */ + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; + t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; + t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING; + t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM; + break; + } + } else { + /* set compression to best */ + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; + t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; + t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING; + t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM; + } + switch(chan->fax->ecm) { + case (0): /* disable ECM */ + break; + case (1): + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; + t30->control_bits_low |= T30_CONTROL_BIT_ECM_64_BYTES; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM_64_BYTES; + break; + case (2): + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM; + break; + } - return(0); + if (DebugVar & 128) { + char st[40]; + eicon_log(NULL, 128, "sT30:code = %x\n", t30->code); + eicon_log(NULL, 128, "sT30:rate = %x\n", t30->rate); + eicon_log(NULL, 128, "sT30:res = %x\n", t30->resolution); + eicon_log(NULL, 128, "sT30:format = %x\n", t30->format); + eicon_log(NULL, 128, "sT30:pages_low = %x\n", t30->pages_low); + eicon_log(NULL, 128, "sT30:pages_high = %x\n", t30->pages_high); + eicon_log(NULL, 128, "sT30:atf = %x\n", t30->atf); + eicon_log(NULL, 128, "sT30:control_bits_low = %x\n", t30->control_bits_low); + eicon_log(NULL, 128, "sT30:control_bits_high = %x\n", t30->control_bits_high); + eicon_log(NULL, 128, "sT30:feature_bits_low = %x\n", t30->feature_bits_low); + eicon_log(NULL, 128, "sT30:feature_bits_high = %x\n", t30->feature_bits_high); + //eicon_log(NULL, 128, "sT30:universal_5 = %x\n", t30->universal_5); + //eicon_log(NULL, 128, "sT30:universal_6 = %x\n", t30->universal_6); + //eicon_log(NULL, 128, "sT30:universal_7 = %x\n", t30->universal_7); + eicon_log(NULL, 128, "sT30:station_id_len = %x\n", t30->station_id_len); + eicon_log(NULL, 128, "sT30:head_line_len = %x\n", t30->head_line_len); + strncpy(st, t30->station_id, t30->station_id_len); + st[t30->station_id_len] = 0; + eicon_log(NULL, 128, "sT30:station_id = <%s>\n", st); + } + return(sizeof(eicon_t30_s)); } /* send fax struct */ int idi_send_edata(eicon_card *card, eicon_chan *chan) { + struct sk_buff *skb; + struct sk_buff *skb2; + eicon_REQ *reqbuf; + eicon_chan_ptr *chan2; + + if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { + eicon_log(card, 1, "idi_snd: Ch%d: send edata on state %d !\n", chan->No, chan->fsm_state); + return -ENODEV; + } + eicon_log(card, 128, "idi_snd: Ch%d: edata (fax)\n", chan->No); + + skb = alloc_skb(sizeof(eicon_REQ) + sizeof(eicon_t30_s), GFP_ATOMIC); + skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); + + if ((!skb) || (!skb2)) { + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_edata()\n", chan->No); + if (skb) + dev_kfree_skb(skb); + if (skb2) + dev_kfree_skb(skb2); + return -ENOMEM; + } + + chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); + chan2->ptr = chan; - /* TODO , code follows */ + reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ)); + + reqbuf->Req = IDI_N_EDATA; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 1; + + reqbuf->XBuffer.length = idi_fill_in_T30(chan, reqbuf->XBuffer.P); + reqbuf->Reference = 1; /* Net Entity */ + skb_queue_tail(&chan->e.X, skb); + skb_queue_tail(&card->sndq, skb2); + eicon_schedule_tx(card); return (0); } void idi_parse_edata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len) { + eicon_t30_s *p = (eicon_t30_s *)buffer; + int i; - /* TODO , code follows */ + if (DebugVar & 128) { + char st[40]; + eicon_log(ccard, 128, "rT30:len %d , size %d\n", len, sizeof(eicon_t30_s)); + eicon_log(ccard, 128, "rT30:code = %x\n", p->code); + eicon_log(ccard, 128, "rT30:rate = %x\n", p->rate); + eicon_log(ccard, 128, "rT30:res = %x\n", p->resolution); + eicon_log(ccard, 128, "rT30:format = %x\n", p->format); + eicon_log(ccard, 128, "rT30:pages_low = %x\n", p->pages_low); + eicon_log(ccard, 128, "rT30:pages_high = %x\n", p->pages_high); + eicon_log(ccard, 128, "rT30:atf = %x\n", p->atf); + eicon_log(ccard, 128, "rT30:control_bits_low = %x\n", p->control_bits_low); + eicon_log(ccard, 128, "rT30:control_bits_high = %x\n", p->control_bits_high); + eicon_log(ccard, 128, "rT30:feature_bits_low = %x\n", p->feature_bits_low); + eicon_log(ccard, 128, "rT30:feature_bits_high = %x\n", p->feature_bits_high); + //eicon_log(ccard, 128, "rT30:universal_5 = %x\n", p->universal_5); + //eicon_log(ccard, 128, "rT30:universal_6 = %x\n", p->universal_6); + //eicon_log(ccard, 128, "rT30:universal_7 = %x\n", p->universal_7); + eicon_log(ccard, 128, "rT30:station_id_len = %x\n", p->station_id_len); + eicon_log(ccard, 128, "rT30:head_line_len = %x\n", p->head_line_len); + strncpy(st, p->station_id, p->station_id_len); + st[p->station_id_len] = 0; + eicon_log(ccard, 128, "rT30:station_id = <%s>\n", st); + } + if (!chan->fax) { + eicon_log(ccard, 1, "idi_edata: parse to NULL fax struct, ERROR\n"); + return; + } + chan->fax->code = p->code; + i = (p->station_id_len < FAXIDLEN) ? p->station_id_len : (FAXIDLEN - 1); + memcpy(chan->fax->r_id, p->station_id, i); + chan->fax->r_id[i] = 0; + chan->fax->r_resolution = p->resolution; + chan->fax->r_rate = p->rate - 1; + chan->fax->r_binary = 0; /* no binary support */ + chan->fax->r_width = 0; + chan->fax->r_length = 2; + chan->fax->r_scantime = 0; + chan->fax->r_compression = 0; + chan->fax->r_ecm = 0; + if (p->feature_bits_low & T30_FEATURE_BIT_2D_CODING) { + chan->fax->r_compression = 1; + if (p->feature_bits_low & T30_FEATURE_BIT_UNCOMPR_ENABLED) { + chan->fax->r_compression = 2; + } + } + if (p->feature_bits_low & T30_FEATURE_BIT_T6_CODING) { + chan->fax->r_compression = 3; + } + if (p->feature_bits_low & T30_FEATURE_BIT_ECM) { + chan->fax->r_ecm = 2; + if (p->feature_bits_low & T30_FEATURE_BIT_ECM_64_BYTES) + chan->fax->r_ecm = 1; + } } void idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header) { + static __u16 wd2sff[] = { + 1728, 2048, 2432, 1216, 864 + }; + static __u16 ln2sff[2][3] = { + { 1143, 1401, 0 } , { 2287, 2802, 0 } + }; + struct sk_buff *skb; + eicon_sff_dochead *doc; + eicon_sff_pagehead *page; + u_char *docp; - /* TODO , code follows */ + if (!chan->fax) { + eicon_log(card, 1, "idi_fax: send head with NULL fax struct, ERROR\n"); + return; + } + if (header == 2) { /* DocHeader + PageHeader */ + skb = alloc_skb(sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead), GFP_ATOMIC); + } else { + skb = alloc_skb(sizeof(eicon_sff_pagehead), GFP_ATOMIC); + } + if (!skb) { + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_header()\n", chan->No); + return; + } + + if (header == 2) { /* DocHeader + PageHeader */ + docp = skb_put(skb, sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead)); + doc = (eicon_sff_dochead *) docp; + page = (eicon_sff_pagehead *) (docp + sizeof(eicon_sff_dochead)); + memset(docp, 0,sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead)); + doc->id = 0x66666653; + doc->version = 0x01; + doc->off1pagehead = sizeof(eicon_sff_dochead); + } else { + page = (eicon_sff_pagehead *)skb_put(skb, sizeof(eicon_sff_pagehead)); + memset(page, 0, sizeof(eicon_sff_pagehead)); + } + switch(header) { + case 1: /* PageHeaderEnd */ + page->pageheadid = 254; + page->pageheadlen = 0; + break; + case 0: /* PageHeader */ + case 2: /* DocHeader + PageHeader */ + page->pageheadid = 254; + page->pageheadlen = sizeof(eicon_sff_pagehead) - 2; + page->resvert = chan->fax->resolution; + page->reshoriz = 0; /* always 203 dpi */ + page->coding = 0; /* always 1D */ + page->linelength = wd2sff[chan->fax->width]; + page->pagelength = ln2sff[chan->fax->resolution][chan->fax->length]; + eicon_log(card, 128, "sSFF-Head: linelength = %d\n", page->linelength); + eicon_log(card, 128, "sSFF-Head: pagelength = %d\n", page->pagelength); + break; + } + idi_send_data(card, chan, 0, skb, 0); } void idi_fax_cmd(eicon_card *card, eicon_chan *chan) { + isdn_ctrl cmd; - /* TODO , code follows */ + if ((!card) || (!chan)) + return; + if (!chan->fax) { + eicon_log(card, 1, "idi_fax: cmd with NULL fax struct, ERROR\n"); + return; + } + switch (chan->fax->code) { + case ISDN_TTY_FAX_DT: + if (chan->fax->phase == ISDN_FAX_PHASE_B) { + idi_send_edata(card, chan); + break; + } + if (chan->fax->phase == ISDN_FAX_PHASE_D) { + idi_send_edata(card, chan); + break; + } + break; + + case ISDN_TTY_FAX_DR: + if (chan->fax->phase == ISDN_FAX_PHASE_B) { + idi_send_edata(card, chan); + + cmd.driver = card->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_CFR; + card->interface.statcallb(&cmd); + + cmd.driver = card->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_RID; + card->interface.statcallb(&cmd); + + /* telling 1-D compression */ + chan->fax->r_compression = 0; + cmd.driver = card->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_DCS; + card->interface.statcallb(&cmd); + + chan->fax2.NextObject = FAX_OBJECT_DOCU; + chan->fax2.PrevObject = FAX_OBJECT_DOCU; + + break; + } + if (chan->fax->phase == ISDN_FAX_PHASE_D) { + idi_send_edata(card, chan); + break; + } + break; + + case ISDN_TTY_FAX_ET: + switch(chan->fax->fet) { + case 0: + case 1: + idi_fax_send_header(card, chan, 0); + break; + case 2: + idi_fax_send_header(card, chan, 1); + break; + } + break; + } } void idi_edata_rcveop(eicon_card *card, eicon_chan *chan) { + isdn_ctrl cmd; - /* TODO , code follows */ - + if (!chan->fax) { + eicon_log(card, 1, "idi_edata: rcveop with NULL fax struct, ERROR\n"); + return; + } + cmd.driver = card->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_ET; + card->interface.statcallb(&cmd); } void idi_reset_fax_stat(eicon_chan *chan) { - - /* TODO , code follows */ - + chan->fax2.LineLen = 0; + chan->fax2.LineData = 0; + chan->fax2.LineDataLen = 0; + chan->fax2.NullByteExist = 0; + chan->fax2.Dle = 0; + chan->fax2.PageCount = 0; + chan->fax2.Eop = 0; } void idi_edata_action(eicon_card *ccard, eicon_chan *chan, char *buffer, int len) { + isdn_ctrl cmd; + + if (!chan->fax) { + eicon_log(ccard, 1, "idi_edata: action with NULL fax struct, ERROR\n"); + return; + } + if (chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) { + idi_parse_edata(ccard, chan, buffer, len); + + if (chan->fax->phase == ISDN_FAX_PHASE_A) { + idi_reset_fax_stat(chan); + + chan->fsm_state = EICON_STATE_ACTIVE; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_BCONN; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_FCON; + ccard->interface.statcallb(&cmd); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_RID; + ccard->interface.statcallb(&cmd); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_DIS; + ccard->interface.statcallb(&cmd); + + if (chan->fax->r_compression != 0) { + /* telling fake compression in second DIS message */ + chan->fax->r_compression = 0; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_DIS; + ccard->interface.statcallb(&cmd); + } + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_SENT; /* OK message */ + ccard->interface.statcallb(&cmd); + } else + if (chan->fax->phase == ISDN_FAX_PHASE_D) { + + if ((chan->fax->code == EDATA_T30_MCF) && + (chan->fax->fet != 2)) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_PTS; + ccard->interface.statcallb(&cmd); + } + + switch(chan->fax->fet) { + case 0: /* new page */ + /* stay in phase D , wait on cmd +FDT */ + break; + case 1: /* new document */ + /* link-level switch to phase B */ + break; + case 2: /* session end */ + default: + /* idi_send_edata(ccard, chan); */ + break; + } + } + } + + if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { + idi_parse_edata(ccard, chan, buffer, len); - /* TODO , code follows */ + if ((chan->fax->code == EDATA_T30_DCS) && + (chan->fax->phase == ISDN_FAX_PHASE_A)) { + idi_reset_fax_stat(chan); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_BCONN; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_FCON_I; + ccard->interface.statcallb(&cmd); + } else + if ((chan->fax->code == EDATA_T30_TRAIN_OK) && + (chan->fax->phase == ISDN_FAX_PHASE_A)) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_RID; + ccard->interface.statcallb(&cmd); + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; + ccard->interface.statcallb(&cmd); + } else + if ((chan->fax->code == EDATA_T30_TRAIN_OK) && + (chan->fax->phase == ISDN_FAX_PHASE_B)) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; + ccard->interface.statcallb(&cmd); + } else + if (chan->fax->phase == ISDN_FAX_PHASE_C) { + switch(chan->fax->code) { + case EDATA_T30_TRAIN_OK: + idi_send_edata(ccard, chan); + break; + case EDATA_T30_MPS: + chan->fax->fet = 0; + idi_edata_rcveop(ccard, chan); + break; + case EDATA_T30_EOM: + chan->fax->fet = 1; + idi_edata_rcveop(ccard, chan); + break; + case EDATA_T30_EOP: + chan->fax->fet = 2; + idi_edata_rcveop(ccard, chan); + break; + } + } + } } void fax_put_rcv(eicon_card *ccard, eicon_chan *chan, u_char *Data, int len) { - - /* TODO , code follows */ - + struct sk_buff *skb; + + skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC); + if (!skb) { + eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_put_rcv()\n", chan->No); + return; + } + skb_reserve(skb, MAX_HEADER_LEN); + memcpy(skb_put(skb, len), Data, len); + ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb); } void idi_faxdata_rcv(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb) { + eicon_OBJBUFFER InBuf; + eicon_OBJBUFFER LineBuf; + unsigned int Length = 0; + unsigned int aLength = 0; + unsigned int ObjectSize = 0; + unsigned int ObjHeadLen = 0; + unsigned int ObjDataLen = 0; + __u8 Recordtype; + __u8 PageHeaderLen; + __u8 Event; + eicon_sff_pagehead *ob_page; + + __u16 Cl2Eol = 0x8000; + +# define EVENT_NONE 0 +# define EVENT_NEEDDATA 1 + + if (!chan->fax) { + eicon_log(ccard, 1, "idi_fax: rcvdata with NULL fax struct, ERROR\n"); + return; + } + + + + if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { + InBuf.Data = skb->data; + InBuf.Size = skb->len; + InBuf.Len = 0; + InBuf.Next = InBuf.Data; + LineBuf.Data = chan->fax2.abLine; + LineBuf.Size = sizeof(chan->fax2.abLine); + LineBuf.Len = chan->fax2.LineLen; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + + Event = EVENT_NONE; + while (Event == EVENT_NONE) { + switch(chan->fax2.NextObject) { + case FAX_OBJECT_DOCU: + Length = LineBuf.Len + (InBuf.Size - InBuf.Len); + if (Length < sizeof(eicon_sff_dochead)) { + Event = EVENT_NEEDDATA; + break; + } + ObjectSize = sizeof(eicon_sff_dochead); + Length = ObjectSize; + if (LineBuf.Len < Length) { + Length -= LineBuf.Len; + LineBuf.Len = 0; + LineBuf.Next = LineBuf.Data; + InBuf.Len += Length; + InBuf.Next += Length; + } else { + LineBuf.Len -= Length; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); + } + chan->fax2.PrevObject = FAX_OBJECT_DOCU; + chan->fax2.NextObject = FAX_OBJECT_PAGE; + break; + + case FAX_OBJECT_PAGE: + Length = LineBuf.Len + (InBuf.Size - InBuf.Len); + if (Length < 2) { + Event = EVENT_NEEDDATA; + break; + } + if (LineBuf.Len == 0) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + if (LineBuf.Len == 1) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + PageHeaderLen = *(LineBuf.Data + 1); + ObjectSize = (PageHeaderLen == 0) ? 2 : sizeof(eicon_sff_pagehead); + if (Length < ObjectSize) { + Event = EVENT_NEEDDATA; + break; + } + Length = ObjectSize; + /* extract page dimensions */ + if (LineBuf.Len < Length) { + aLength = Length - LineBuf.Len; + memcpy(LineBuf.Next, InBuf.Next, aLength); + LineBuf.Next += aLength; + InBuf.Next += aLength; + LineBuf.Len += aLength; + InBuf.Len += aLength; + } + if (Length > 2) { + ob_page = (eicon_sff_pagehead *)LineBuf.Data; + switch(ob_page->linelength) { + case 2048: + chan->fax->r_width = 1; + break; + case 2432: + chan->fax->r_width = 2; + break; + case 1216: + chan->fax->r_width = 3; + break; + case 864: + chan->fax->r_width = 4; + break; + case 1728: + default: + chan->fax->r_width = 0; + } + switch(ob_page->pagelength) { + case 1143: + case 2287: + chan->fax->r_length = 0; + break; + case 1401: + case 2802: + chan->fax->r_length = 1; + break; + default: + chan->fax->r_length = 2; + } + eicon_log(ccard, 128, "rSFF-Head: linelength = %d\n", ob_page->linelength); + eicon_log(ccard, 128, "rSFF-Head: pagelength = %d\n", ob_page->pagelength); + } + LineBuf.Len -= Length; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); + + chan->fax2.PrevObject = FAX_OBJECT_PAGE; + chan->fax2.NextObject = FAX_OBJECT_LINE; + break; + + case FAX_OBJECT_LINE: + Length = LineBuf.Len + (InBuf.Size - InBuf.Len); + if (Length < 1) { + Event = EVENT_NEEDDATA; + break; + } + if (LineBuf.Len == 0) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + Recordtype = *LineBuf.Data; + if (Recordtype == 0) { + /* recordtype pixel row (2 byte length) */ + ObjHeadLen = 3; + if (Length < ObjHeadLen) { + Event = EVENT_NEEDDATA; + break; + } + while (LineBuf.Len < ObjHeadLen) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + ObjDataLen = *((__u16*) (LineBuf.Data + 1)); + ObjectSize = ObjHeadLen + ObjDataLen; + if (Length < ObjectSize) { + Event = EVENT_NEEDDATA; + break; + } + } else + if ((Recordtype >= 1) && (Recordtype <= 216)) { + /* recordtype pixel row (1 byte length) */ + ObjHeadLen = 1; + ObjDataLen = Recordtype; + ObjectSize = ObjHeadLen + ObjDataLen; + if (Length < ObjectSize) { + Event = EVENT_NEEDDATA; + break; + } + } else + if ((Recordtype >= 217) && (Recordtype <= 253)) { + /* recordtype empty lines */ + ObjHeadLen = 1; + ObjDataLen = 0; + ObjectSize = ObjHeadLen + ObjDataLen; + LineBuf.Len--; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + 1, LineBuf.Len); + break; + } else + if (Recordtype == 254) { + /* recordtype page header */ + chan->fax2.PrevObject = FAX_OBJECT_LINE; + chan->fax2.NextObject = FAX_OBJECT_PAGE; + break; + } else { + /* recordtype user information */ + ObjHeadLen = 2; + if (Length < ObjHeadLen) { + Event = EVENT_NEEDDATA; + break; + } + while (LineBuf.Len < ObjHeadLen) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + ObjDataLen = *(LineBuf.Data + 1); + ObjectSize = ObjHeadLen + ObjDataLen; + if (ObjDataLen == 0) { + /* illegal line coding */ + LineBuf.Len -= ObjHeadLen; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + ObjHeadLen, LineBuf.Len); + break; + } else { + /* user information */ + if (Length < ObjectSize) { + Event = EVENT_NEEDDATA; + break; + } + Length = ObjectSize; + if (LineBuf.Len < Length) { + Length -= LineBuf.Len; + LineBuf.Len = 0; + LineBuf.Next = LineBuf.Data; + InBuf.Len += Length; + InBuf.Next += Length; + } else { + LineBuf.Len -= Length; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); + } + } + break; + } + Length = ObjectSize; + if (LineBuf.Len > ObjHeadLen) { + fax_put_rcv(ccard, chan, LineBuf.Data + ObjHeadLen, + (LineBuf.Len - ObjHeadLen)); + } + Length -= LineBuf.Len; + LineBuf.Len = 0; + LineBuf.Next = LineBuf.Data; + if (Length > 0) { + fax_put_rcv(ccard, chan, InBuf.Next, Length); + InBuf.Len += Length; + InBuf.Next += Length; + } + fax_put_rcv(ccard, chan, (__u8 *)&Cl2Eol, sizeof(Cl2Eol)); + break; + } /* end of switch (chan->fax2.NextObject) */ + } /* end of while (Event==EVENT_NONE) */ + if (InBuf.Len < InBuf.Size) { + Length = InBuf.Size - InBuf.Len; + if ((LineBuf.Len + Length) > LineBuf.Size) { + eicon_log(ccard, 1, "idi_fax: Ch%d: %d bytes dropping, small buffer\n", chan->No, + Length); + } else { + memcpy(LineBuf.Next, InBuf.Next, Length); + LineBuf.Len += Length; + } + } + chan->fax2.LineLen = LineBuf.Len; + } else { /* CONN_OUT */ + /* On CONN_OUT we do not need incoming data, drop it */ + /* maybe later for polling */ + } - /* TODO , code follows */ +# undef EVENT_NONE +# undef EVENT_NEEDDATA + return; } int idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf) { + struct sk_buff *skb; - /* TODO , code follows */ + skb = alloc_skb(OutBuf->Len, GFP_ATOMIC); + if (!skb) { + eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_outbuf()\n", chan->No); + return(-1); + } + memcpy(skb_put(skb, OutBuf->Len), OutBuf->Data, OutBuf->Len); - return(0); + OutBuf->Len = 0; + OutBuf->Next = OutBuf->Data; + + return(idi_send_data(ccard, chan, 0, skb, 1)); } int idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb) { + isdn_ctrl cmd; + eicon_OBJBUFFER InBuf; + __u8 InData; + __u8 InMask; + eicon_OBJBUFFER OutBuf; + eicon_OBJBUFFER LineBuf; + __u32 LineData; + unsigned int LineDataLen; + __u8 Byte; + __u8 Event; + int ret = 1; + +# define EVENT_NONE 0 +# define EVENT_EOD 1 +# define EVENT_EOL 2 +# define EVENT_EOP 3 + + if ((!ccard) || (!chan)) + return -1; - /* TODO , code follows */ + if (!chan->fax) { + eicon_log(ccard, 1, "idi_fax: senddata with NULL fax struct, ERROR\n"); + return -1; + } - return(0); + if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { + /* Simply ignore any data written in data mode when receiving a fax. */ + /* This is not completely correct because only XON's should come here. */ + dev_kfree_skb(skb); + return 1; + } + + if (chan->fax->phase != ISDN_FAX_PHASE_C) { + dev_kfree_skb(skb); + return 1; + } + + if (chan->queued + skb->len > 1200) + return 0; + + InBuf.Data = skb->data; + InBuf.Size = skb->len; + InBuf.Len = 0; + InBuf.Next = InBuf.Data; + InData = 0; + InMask = 0; + + LineBuf.Data = chan->fax2.abLine; + LineBuf.Size = sizeof(chan->fax2.abLine); + LineBuf.Len = chan->fax2.LineLen; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + LineData = chan->fax2.LineData; + LineDataLen = chan->fax2.LineDataLen; + + OutBuf.Data = chan->fax2.abFrame; + OutBuf.Size = sizeof(chan->fax2.abFrame); + OutBuf.Len = 0; + OutBuf.Next = OutBuf.Data; + + Event = EVENT_NONE; + + chan->fax2.Eop = 0; + + for (;;) { + for (;;) { + if (InMask == 0) { + if (InBuf.Len >= InBuf.Size) { + Event = EVENT_EOD; + break; + } + if ((chan->fax2.Dle != _DLE_) && *InBuf.Next == _DLE_) { + chan->fax2.Dle = _DLE_; + InBuf.Next++; + InBuf.Len++; + if (InBuf.Len >= InBuf.Size) { + Event = EVENT_EOD; + break; + } + } + if (chan->fax2.Dle == _DLE_) { + chan->fax2.Dle = 0; + if (*InBuf.Next == _ETX_) { + Event = EVENT_EOP; + break; + } else + if (*InBuf.Next == _DLE_) { + /* do nothing */ + } else { + eicon_log(ccard, 1, + "idi_err: Ch%d: unknown DLE escape %02x found\n", + chan->No, *InBuf.Next); + InBuf.Next++; + InBuf.Len++; + if (InBuf.Len >= InBuf.Size) { + Event = EVENT_EOD; + break; + } + } + } + InBuf.Len++; + InData = *InBuf.Next++; + InMask = (chan->fax->bor) ? 0x80 : 0x01; + } + while (InMask) { + LineData >>= 1; + LineDataLen++; + if (InData & InMask) + LineData |= 0x80000000; + if (chan->fax->bor) + InMask >>= 1; + else + InMask <<= 1; + + if ((LineDataLen >= T4_EOL_BITSIZE) && + ((LineData & T4_EOL_MASK_DWORD) == T4_EOL_DWORD)) { + Event = EVENT_EOL; + if (LineDataLen > T4_EOL_BITSIZE) { + Byte = (__u8) + ((LineData & ~T4_EOL_MASK_DWORD) >> + (32 - LineDataLen)); + if (Byte == 0) { + if (! chan->fax2.NullByteExist) { + chan->fax2.NullBytesPos = LineBuf.Len; + chan->fax2.NullByteExist = 1; + } + } else { + chan->fax2.NullByteExist = 0; + } + if (LineBuf.Len < LineBuf.Size) { + *LineBuf.Next++ = Byte; + LineBuf.Len++; + } + } + LineDataLen = 0; + break; + } + if (LineDataLen >= T4_EOL_BITSIZE + 8) { + Byte = (__u8) + ((LineData & ~T4_EOL_MASK_DWORD) >> + (32 - T4_EOL_BITSIZE - 8)); + LineData &= T4_EOL_MASK_DWORD; + LineDataLen = T4_EOL_BITSIZE; + if (Byte == 0) { + if (! chan->fax2.NullByteExist) { + chan->fax2.NullBytesPos = LineBuf.Len; + chan->fax2.NullByteExist = 1; + } + } else { + chan->fax2.NullByteExist = 0; + } + if (LineBuf.Len < LineBuf.Size) { + *LineBuf.Next++ = Byte; + LineBuf.Len++; + } + } + } + if (Event != EVENT_NONE) + break; + } + + if ((Event != EVENT_EOL) && (Event != EVENT_EOP)) + break; + + if ((Event == EVENT_EOP) && (LineDataLen > 0)) { + LineData >>= 32 - LineDataLen; + LineDataLen = 0; + while (LineData != 0) { + Byte = (__u8) LineData; + LineData >>= 8; + if (Byte == 0) { + if (! chan->fax2.NullByteExist) { + chan->fax2.NullBytesPos = LineBuf.Len; + chan->fax2.NullByteExist = 1; + } + } else { + chan->fax2.NullByteExist = 0; + } + if (LineBuf.Len < LineBuf.Size) { + *LineBuf.Next++ = Byte; + LineBuf.Len++; + } + + } + } + if (chan->fax2.NullByteExist) { + if (chan->fax2.NullBytesPos == 0) { + LineBuf.Len = 0; + } else { + LineBuf.Len = chan->fax2.NullBytesPos + 1; + } + } + if (LineBuf.Len > 0) { + if (OutBuf.Len + LineBuf.Len + SFF_LEN_FLD_SIZE > OutBuf.Size) { + ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); + } + if (LineBuf.Len <= 216) { + *OutBuf.Next++ = (__u8) LineBuf.Len; + OutBuf.Len++; + } else { + *OutBuf.Next++ = 0; + *((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len; + OutBuf.Len += 3; + } + memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len); + OutBuf.Next += LineBuf.Len; + OutBuf.Len += LineBuf.Len; + } + LineBuf.Len = 0; + LineBuf.Next = LineBuf.Data; + chan->fax2.NullByteExist = 0; + if (Event == EVENT_EOP) + break; + + Event = EVENT_NONE; + } + + if (Event == EVENT_EOP) { + chan->fax2.Eop = 1; + chan->fax2.PageCount++; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_EOP; + ccard->interface.statcallb(&cmd); + } + if (OutBuf.Len > 0) { + ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); + } + + chan->fax2.LineLen = LineBuf.Len; + chan->fax2.LineData = LineData; + chan->fax2.LineDataLen = LineDataLen; + +# undef EVENT_NONE +# undef EVENT_EOD +# undef EVENT_EOL +# undef EVENT_EOP + + if (ret >= 0) + dev_kfree_skb(skb); + if (ret == 0) + ret = 1; + return(ret); } void idi_fax_hangup(eicon_card *ccard, eicon_chan *chan) { + isdn_ctrl cmd; - /* TODO , code follows */ - + if (!chan->fax) { + eicon_log(ccard, 1, "idi_fax: hangup with NULL fax struct, ERROR\n"); + return; + } + if ((chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) && + (chan->fax->code == 0)) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_PTS; + ccard->interface.statcallb(&cmd); + } + if ((chan->fax->code > 1) && (chan->fax->code < 120)) + chan->fax->code += 120; + chan->fax->r_code = ISDN_TTY_FAX_HNG; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); } #endif /******** FAX ********/ @@ -1025,20 +2148,17 @@ idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int eicon_chan_ptr *chan2; if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { - if (DebugVar & 1) - printk(KERN_DEBUG"idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state); + eicon_log(card, 1, "idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state); return -ENODEV; } - if (DebugVar & 8) - printk(KERN_DEBUG"idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No, - UReq, buffer[0], buffer[1], buffer[2], buffer[3]); + eicon_log(card, 8, "idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No, + UReq, buffer[0], buffer[1], buffer[2], buffer[3]); skb = alloc_skb(sizeof(eicon_REQ) + len + 1, GFP_ATOMIC); skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No); + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No); if (skb) dev_kfree_skb(skb); if (skb2) @@ -1072,6 +2192,9 @@ idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value) u_char buf[6]; struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf; + if ((!ccard) || (!chan)) + return; + memset(buf, 0, 6); switch(cmd) { case ISDN_AUDIO_SETDD: @@ -1103,14 +2226,15 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int '1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D' }; + if ((!ccard) || (!chan)) + return; + switch (buffer[0]) { case DSP_UDATA_INDICATION_SYNC: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time); + eicon_log(ccard, 16, "idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time); break; case DSP_UDATA_INDICATION_DCD_OFF: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time); + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time); break; case DSP_UDATA_INDICATION_DCD_ON: if ((chan->l2prot == ISDN_PROTO_L2_MODEM) && @@ -1122,31 +2246,24 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]); ccard->interface.statcallb(&cmd); } - if (DebugVar & 8) { - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time); - printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No, - p->norm, p->options, p->speed, p->delay); - } + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time); + eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, + p->norm, p->options, p->speed, p->delay); break; case DSP_UDATA_INDICATION_CTS_OFF: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time); + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time); break; case DSP_UDATA_INDICATION_CTS_ON: - if (DebugVar & 8) { - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time); - printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No, - p->norm, p->options, p->speed, p->delay); - } + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time); + eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, + p->norm, p->options, p->speed, p->delay); break; case DSP_UDATA_INDICATION_DISCONNECT: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]); + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]); break; case DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No, - dtmf_code[buffer[1]]); + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No, + dtmf_code[buffer[1]]); cmd.driver = ccard->myid; cmd.command = ISDN_STAT_AUDIO; cmd.parm.num[0] = ISDN_AUDIO_DTMF; @@ -1155,8 +2272,7 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int ccard->interface.statcallb(&cmd); break; default: - if (DebugVar & 8) - printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]); + eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]); } } @@ -1164,23 +2280,35 @@ void idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) { int tmp; + char tnum[64]; + int dlev; int free_buff; + ulong flags; struct sk_buff *skb2; eicon_IND *ind = (eicon_IND *)skb->data; eicon_chan *chan; idi_ind_message message; isdn_ctrl cmd; + if (!ccard) { + eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ind\n"); + dev_kfree_skb(skb); + return; + } + if ((chan = ccard->IdTable[ind->IndId]) == NULL) { + eicon_log(ccard, 1, "idi_err: Ch??: null chan in handle_ind\n"); dev_kfree_skb(skb); return; } - if ((DebugVar & 128) || - ((DebugVar & 16) && (ind->Ind != 8))) { - printk(KERN_DEBUG "idi_hdl: Ch%d: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No, - ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); - } + if (ind->Ind != 8) + dlev = 144; + else + dlev = 128; + + eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No, + ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); free_buff = 1; /* Signal Layer */ @@ -1188,16 +2316,16 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length); switch(ind->Ind) { case HANGUP: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Hangup\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Hangup\n", chan->No); while((skb2 = skb_dequeue(&chan->e.X))) { dev_kfree_skb(skb2); } - chan->e.busy = 0; + save_flags(flags); + cli(); chan->queued = 0; chan->waitq = 0; chan->waitpq = 0; - chan->fsm_state = EICON_STATE_NULL; + restore_flags(flags); if (message.e_cau[0] & 0x7f) { cmd.driver = ccard->myid; cmd.arg = chan->No; @@ -1207,58 +2335,83 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) ccard->interface.statcallb(&cmd); } chan->cause[0] = 0; - cmd.driver = ccard->myid; - cmd.arg = chan->No; - cmd.command = ISDN_STAT_DHUP; - ccard->interface.statcallb(&cmd); - eicon_idi_listen_req(ccard, chan); #ifdef CONFIG_ISDN_TTY_FAX if (!chan->e.B2Id) chan->fax = 0; #endif + if (((chan->fsm_state == EICON_STATE_ACTIVE) || + (chan->fsm_state == EICON_STATE_WMCONN)) || + ((chan->l2prot == ISDN_PROTO_L2_FAX) && + (chan->fsm_state == EICON_STATE_OBWAIT))) { + chan->fsm_state = EICON_STATE_NULL; + } else { + if (chan->e.B2Id) + idi_do_req(ccard, chan, REMOVE, 1); + chan->fsm_state = EICON_STATE_NULL; + cmd.driver = ccard->myid; + cmd.arg = chan->No; + cmd.command = ISDN_STAT_DHUP; + ccard->interface.statcallb(&cmd); + eicon_idi_listen_req(ccard, chan); + } break; case INDICATE_IND: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Indicate_Ind\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Indicate_Ind\n", chan->No); + if (chan->fsm_state != EICON_STATE_LISTEN) { + eicon_log(ccard, 1, "idi_err: Ch%d: Incoming call on wrong state (%d).\n", + chan->No, chan->fsm_state); + idi_do_req(ccard, chan, HANGUP, 0); + break; + } chan->fsm_state = EICON_STATE_ICALL; idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2); strcpy(chan->cpn, message.cpn + 1); - if (strlen(message.dsa)) { - strcat(chan->cpn, "."); - strcat(chan->cpn, message.dsa); - } strcpy(chan->oad, message.oad); + strcpy(chan->dsa, message.dsa); + strcpy(chan->osa, message.osa); + chan->plan = message.plan; + chan->screen = message.screen; try_stat_icall_again: cmd.driver = ccard->myid; cmd.command = ISDN_STAT_ICALL; cmd.arg = chan->No; cmd.parm.setup.si1 = chan->si1; cmd.parm.setup.si2 = chan->si2; - strcpy(cmd.parm.setup.eazmsn, chan->cpn); - strcpy(cmd.parm.setup.phone, chan->oad); - cmd.parm.setup.plan = message.plan; - cmd.parm.setup.screen = message.screen; + strcpy(tnum, chan->cpn); + if (strlen(chan->dsa)) { + strcat(tnum, "."); + strcat(tnum, chan->dsa); + } + tnum[ISDN_MSNLEN - 1] = 0; + strcpy(cmd.parm.setup.eazmsn, tnum); + strcpy(tnum, chan->oad); + if (strlen(chan->osa)) { + strcat(tnum, "."); + strcat(tnum, chan->osa); + } + tnum[ISDN_MSNLEN - 1] = 0; + strcpy(cmd.parm.setup.phone, tnum); + cmd.parm.setup.plan = chan->plan; + cmd.parm.setup.screen = chan->screen; tmp = ccard->interface.statcallb(&cmd); switch(tmp) { case 0: /* no user responding */ idi_do_req(ccard, chan, HANGUP, 0); + chan->fsm_state = EICON_STATE_NULL; break; case 1: /* alert */ - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Call Alert\n", chan->No); + eicon_log(ccard, 8, "idi_req: Ch%d: Call Alert\n", chan->No); if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_ICALLW)) { chan->fsm_state = EICON_STATE_ICALL; idi_do_req(ccard, chan, CALL_ALERT, 0); } break; case 2: /* reject */ - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Call Reject\n", chan->No); + eicon_log(ccard, 8, "idi_req: Ch%d: Call Reject\n", chan->No); idi_do_req(ccard, chan, REJECT, 0); break; case 3: /* incomplete number */ - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Incomplete Number\n", chan->No); + eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No); switch(ccard->type) { case EICON_CTYPE_MAESTRAP: case EICON_CTYPE_S2M: @@ -1272,8 +2425,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) } break; case INFO_IND: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Info_Ind\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Info_Ind\n", chan->No); if ((chan->fsm_state == EICON_STATE_ICALLW) && (message.cpn[0])) { strcat(chan->cpn, message.cpn + 1); @@ -1281,35 +2433,45 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) } break; case CALL_IND: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Call_Ind\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Ind\n", chan->No); if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_IWAIT)) { chan->fsm_state = EICON_STATE_IBWAIT; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_DCONN; cmd.arg = chan->No; ccard->interface.statcallb(&cmd); - if (chan->l2prot != ISDN_PROTO_L2_FAX) { - idi_do_req(ccard, chan, IDI_N_CONNECT, 1); - } + switch(chan->l2prot) { + case ISDN_PROTO_L2_FAX: #ifdef CONFIG_ISDN_TTY_FAX - else { - if (chan->fax) - chan->fax->phase = ISDN_FAX_PHASE_A; - } + if (chan->fax) + chan->fax->phase = ISDN_FAX_PHASE_A; #endif + break; + case ISDN_PROTO_L2_MODEM: + /* do nothing, wait for connect */ + break; + default: + idi_do_req(ccard, chan, IDI_N_CONNECT, 1); + } } else idi_hangup(ccard, chan); break; case CALL_CON: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Call_Con\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No); if (chan->fsm_state == EICON_STATE_OCALL) { chan->fsm_state = EICON_STATE_OBWAIT; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_DCONN; cmd.arg = chan->No; ccard->interface.statcallb(&cmd); + + /* check if old NetID has been removed */ + if (chan->e.B2Id) { + eicon_log(ccard, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n", + chan->No, chan->e.B2Id); + idi_do_req(ccard, chan, REMOVE, 1); + } + idi_do_req(ccard, chan, ASSIGN, 1); idi_do_req(ccard, chan, IDI_N_CONNECT, 1); #ifdef CONFIG_ISDN_TTY_FAX @@ -1322,12 +2484,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) idi_hangup(ccard, chan); break; case AOC_IND: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Advice of Charge\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Advice of Charge\n", chan->No); break; default: - if (DebugVar & 8) - printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind); + eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind); } } /* Network Layer */ @@ -1341,8 +2501,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) else switch(ind->Ind) { case IDI_N_CONNECT_ACK: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect_Ack\n", chan->No); + eicon_log(ccard, 16, "idi_ind: Ch%d: N_Connect_Ack\n", chan->No); if (chan->l2prot == ISDN_PROTO_L2_MODEM) { chan->fsm_state = EICON_STATE_WMCONN; break; @@ -1362,8 +2521,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) } } else { - if (DebugVar & 1) - printk(KERN_DEBUG "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n"); + eicon_log(ccard, 1, "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n"); } #endif break; @@ -1375,8 +2533,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) ccard->interface.statcallb(&cmd); break; case IDI_N_CONNECT: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect\n", chan->No); + eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No); if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1); if (chan->l2prot == ISDN_PROTO_L2_FAX) { break; @@ -1392,9 +2549,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) ccard->interface.statcallb(&cmd); break; case IDI_N_DISC: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC\n", chan->No); + eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC\n", chan->No); if (chan->e.B2Id) { + while((skb2 = skb_dequeue(&chan->e.X))) { + dev_kfree_skb(skb2); + } idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1); idi_do_req(ccard, chan, REMOVE, 1); } @@ -1404,23 +2563,26 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) idi_fax_hangup(ccard, chan); } #endif + save_flags(flags); + cli(); chan->queued = 0; chan->waitq = 0; chan->waitpq = 0; + restore_flags(flags); idi_do_req(ccard, chan, HANGUP, 0); if (chan->fsm_state == EICON_STATE_ACTIVE) { cmd.driver = ccard->myid; cmd.command = ISDN_STAT_BHUP; cmd.arg = chan->No; ccard->interface.statcallb(&cmd); + chan->fsm_state = EICON_STATE_NULL; } #ifdef CONFIG_ISDN_TTY_FAX chan->fax = 0; #endif break; case IDI_N_DISC_ACK: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC_ACK\n", chan->No); + eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC_ACK\n", chan->No); #ifdef CONFIG_ISDN_TTY_FAX if (chan->l2prot == ISDN_PROTO_L2_FAX) { idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); @@ -1429,13 +2591,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) #endif break; case IDI_N_DATA_ACK: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_DATA_ACK\n", chan->No); + eicon_log(ccard, 16, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No); break; case IDI_N_DATA: skb_pull(skb, sizeof(eicon_IND) - 1); - if (DebugVar & 128) - printk(KERN_DEBUG"idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len); + eicon_log(ccard, 128, "idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len); if (chan->l2prot == ISDN_PROTO_L2_FAX) { #ifdef CONFIG_ISDN_TTY_FAX idi_faxdata_rcv(ccard, chan, skb); @@ -1454,27 +2614,26 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) break; #endif default: - if (DebugVar & 8) - printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind); + eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind); } } else { - if (DebugVar & 1) - printk(KERN_ERR "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No); + eicon_log(ccard, 1, "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No); } - if (free_buff) dev_kfree_skb(skb); + if (free_buff) + dev_kfree_skb(skb); } int idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) { + ulong flags; isdn_ctrl cmd; if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) { /* I dont know why this happens, just ignoring this RC */ - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, - ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id); + eicon_log(ccard, 16, "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, + ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id); return 1; } @@ -1488,27 +2647,27 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) /* Remove an Id */ if (chan->e.Req == REMOVE) { if (ack->Reference != chan->e.ref) { - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No, - ack->Reference, chan->e.ref); + eicon_log(ccard, 16, "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No, + ack->Reference, chan->e.ref); return 0; } + save_flags(flags); + cli(); ccard->IdTable[ack->RcId] = NULL; - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No, - ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig"); + eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No, + ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig"); if (!chan->e.ReqCh) chan->e.D3Id = 0; else chan->e.B2Id = 0; + restore_flags(flags); return 1; } /* Signal layer */ if (!chan->e.ReqCh) { - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, - ack->RcId, ack->RcCh, ack->Reference); + eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, + ack->RcId, ack->RcCh, ack->Reference); } else { /* Network layer */ switch(chan->e.Req & 0x0f) { @@ -1522,7 +2681,10 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) cmd.parm.length = chan->waitpq; ccard->interface.statcallb(&cmd); } + save_flags(flags); + cli(); chan->waitpq = 0; + restore_flags(flags); #ifdef CONFIG_ISDN_TTY_FAX if (chan->l2prot == ISDN_PROTO_L2_FAX) { if (((chan->queued - chan->waitq) < 1) && @@ -1536,20 +2698,21 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) ccard->interface.statcallb(&cmd); } else { - if (DebugVar & 1) - printk(KERN_DEBUG "idi_ack: Sent with NULL fax struct, ERROR\n"); + eicon_log(ccard, 1, "idi_ack: Sent with NULL fax struct, ERROR\n"); } } } #endif } + save_flags(flags); + cli(); chan->queued -= chan->waitq; if (chan->queued < 0) chan->queued = 0; + restore_flags(flags); break; default: - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, - ack->RcId, ack->RcCh, ack->Reference); + eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, + ack->RcId, ack->RcCh, ack->Reference); } } return 1; @@ -1559,22 +2722,30 @@ void idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) { int j; + ulong flags; eicon_RC *ack = (eicon_RC *)skb->data; eicon_chan *chan; isdn_ctrl cmd; int dCh = -1; + if (!ccard) { + eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ack\n"); + dev_kfree_skb(skb); + return; + } + + save_flags(flags); + cli(); if ((chan = ccard->IdTable[ack->RcId]) != NULL) dCh = chan->No; - + restore_flags(flags); switch (ack->Rc) { case OK_FC: case N_FLOW_CONTROL: case ASSIGN_RC: - if (DebugVar & 1) - printk(KERN_ERR "idi_ack: Ch%d: unhandled RC 0x%x\n", - dCh, ack->Rc); + eicon_log(ccard, 1, "idi_ack: Ch%d: unhandled RC 0x%x\n", + dCh, ack->Rc); break; case READY_INT: case TIMER_INT: @@ -1583,8 +2754,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) case OK: if (!chan) { - if (DebugVar & 1) - printk(KERN_ERR "idi_ack: Ch%d: OK on chan without Id\n", dCh); + eicon_log(ccard, 1, "idi_ack: Ch%d: OK on chan without Id\n", dCh); break; } if (!idi_handle_ack_ok(ccard, chan, ack)) @@ -1593,29 +2763,29 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) case ASSIGN_OK: if (chan) { - if (DebugVar & 1) - printk(KERN_ERR "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n", - chan->No, chan->e.D3Id, chan->e.B2Id); + eicon_log(ccard, 1, "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n", + chan->No, chan->e.D3Id, chan->e.B2Id); } + save_flags(flags); + cli(); for(j = 0; j < ccard->nchannels + 1; j++) { - if (ccard->bch[j].e.ref == ack->Reference) { + if ((ccard->bch[j].e.ref == ack->Reference) && + (ccard->bch[j].e.Req == ASSIGN)) { if (!ccard->bch[j].e.ReqCh) ccard->bch[j].e.D3Id = ack->RcId; else ccard->bch[j].e.B2Id = ack->RcId; ccard->IdTable[ack->RcId] = &ccard->bch[j]; - ccard->bch[j].e.busy = 0; - ccard->bch[j].e.ref = 0; - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ack: Ch%d: Id %x assigned (%s)\n", j, - ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig"); + chan = &ccard->bch[j]; + eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j, + ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig"); break; } } + restore_flags(flags); if (j > ccard->nchannels) { - if (DebugVar & 24) - printk(KERN_DEBUG"idi_ack: Ch??: ref %d not found for Id %d\n", - ack->Reference, ack->RcId); + eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n", + ack->Reference, ack->RcId); } break; @@ -1627,9 +2797,19 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) case UNKNOWN_IE: case WRONG_IE: default: - if (DebugVar & 1) - printk(KERN_ERR "eicon_ack: Ch%d: Not OK !!: Rc=%d Id=%x Ch=%d\n", dCh, - ack->Rc, ack->RcId, ack->RcCh); + if (!chan) { + eicon_log(ccard, 1, "idi_ack: Ch%d: Not OK !! on chan without Id\n", dCh); + break; + } else + switch (chan->e.Req) { + case 12: /* Alert */ + eicon_log(ccard, 2, "eicon_err: Ch%d: Alert Not OK : Rc=%d Id=%x Ch=%d\n", + dCh, ack->Rc, ack->RcId, ack->RcCh); + break; + default: + eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n", + dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req); + } if (dCh == ccard->nchannels) { /* Management */ chan->fsm_state = 2; } else if (dCh >= 0) { @@ -1642,8 +2822,13 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) ccard->interface.statcallb(&cmd); } } - if (chan) + save_flags(flags); + cli(); + if (chan) { + chan->e.ref = 0; chan->e.busy = 0; + } + restore_flags(flags); dev_kfree_skb(skb); eicon_schedule_tx(ccard); } @@ -1658,21 +2843,25 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int len, plen = 0, offset = 0; unsigned long flags; + if ((!card) || (!chan)) { + eicon_log(card, 1, "idi_err: Ch??: null card/chan in send_data\n"); + return -1; + } + if (chan->fsm_state != EICON_STATE_ACTIVE) { - if (DebugVar & 1) - printk(KERN_DEBUG"idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state); + eicon_log(card, 1, "idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state); return -ENODEV; } len = skb->len; - if (len > 2138) /* too much for the shared memory */ + if (len > EICON_MAX_QUEUE) /* too much for the shared memory */ return -1; if (!len) return 0; - if (chan->queued + len > ((chan->l2prot == ISDN_PROTO_L2_TRANS) ? 4000 : EICON_MAX_QUEUED)) + if (chan->queued + len > EICON_MAX_QUEUE) return 0; - if (DebugVar & 128) - printk(KERN_DEBUG"idi_snd: Ch%d: %d bytes\n", chan->No, len); + + eicon_log(card, 128, "idi_snd: Ch%d: %d bytes\n", chan->No, len); save_flags(flags); cli(); @@ -1685,8 +2874,7 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, if ((!xmit_skb) || (!skb2)) { restore_flags(flags); - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No); + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No); if (xmit_skb) dev_kfree_skb(skb); if (skb2) @@ -1740,8 +2928,7 @@ eicon_idi_manage_assign(eicon_card *card) skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: alloc_skb failed in manage_assign()\n"); + eicon_log(card, 1, "idi_err: alloc_skb failed in manage_assign()\n"); if (skb) dev_kfree_skb(skb); if (skb2) @@ -1783,8 +2970,7 @@ eicon_idi_manage_remove(eicon_card *card) skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: alloc_skb failed in manage_remove()\n"); + eicon_log(card, 1, "idi_err: alloc_skb failed in manage_remove()\n"); if (skb) dev_kfree_skb(skb); if (skb2) @@ -1850,8 +3036,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb) chan->fsm_state = 0; if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: alloc_manifbuf failed\n"); + eicon_log(card, 1, "idi_err: alloc_manifbuf failed\n"); chan->e.D3Id = 0; return -ENOMEM; } @@ -1865,8 +3050,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb) skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err_manif: alloc_skb failed in manage()\n"); + eicon_log(card, 1, "idi_err_manif: alloc_skb failed in manage()\n"); if (skb) dev_kfree_skb(skb); if (skb2) diff --git a/drivers/isdn/eicon/eicon_io.c b/drivers/isdn/eicon/eicon_io.c index 60b5b4818495e75fefc2651f0bde6feb4a5883f9..779f241e0a9c550eb70b345b339c55e6e94ef5cf 100644 --- a/drivers/isdn/eicon/eicon_io.c +++ b/drivers/isdn/eicon/eicon_io.c @@ -1,4 +1,4 @@ -/* $Id: eicon_io.c,v 1.4 1999/08/22 20:26:47 calle Exp $ +/* $Id: eicon_io.c,v 1.8 1999/10/08 22:09:34 armin Exp $ * * ISDN low-level module for Eicon.Diehl active ISDN-Cards. * Code for communicating with hardware. @@ -24,6 +24,20 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_io.c,v $ + * Revision 1.8 1999/10/08 22:09:34 armin + * Some fixes of cards interface handling. + * Bugfix of NULL pointer occurence. + * Changed a few log outputs. + * + * Revision 1.7 1999/09/26 14:17:53 armin + * Improved debug and log via readstat() + * + * Revision 1.6 1999/09/21 20:35:43 armin + * added more error checking. + * + * Revision 1.5 1999/08/31 11:20:11 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.4 1999/08/22 20:26:47 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -51,19 +65,21 @@ void eicon_io_rcv_dispatch(eicon_card *ccard) { + ulong flags; struct sk_buff *skb, *skb2, *skb_new; eicon_IND *ind, *ind2, *ind_new; eicon_chan *chan; if (!ccard) { - if (DebugVar & 1) - printk(KERN_WARNING "eicon_io_rcv_dispatch: NULL card!\n"); + eicon_log(ccard, 1, "eicon_err: NULL card in rcv_dispatch !\n"); return; } while((skb = skb_dequeue(&ccard->rcvq))) { ind = (eicon_IND *)skb->data; + save_flags(flags); + cli(); if ((chan = ccard->IdTable[ind->IndId]) == NULL) { if (DebugVar & 1) { switch(ind->Ind) { @@ -71,14 +87,16 @@ eicon_io_rcv_dispatch(eicon_card *ccard) { /* doesn't matter if this happens */ break; default: - printk(KERN_ERR "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId); - printk(KERN_DEBUG "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", + eicon_log(ccard, 1, "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId); + eicon_log(ccard, 1, "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); } } + restore_flags(flags); dev_kfree_skb(skb); continue; } + restore_flags(flags); if (chan->e.complete) { /* check for rec-buffer chaining */ if (ind->MLength == ind->RBuffer.length) { @@ -94,10 +112,12 @@ eicon_io_rcv_dispatch(eicon_card *ccard) { } } else { + save_flags(flags); + cli(); if (!(skb2 = skb_dequeue(&chan->e.R))) { chan->e.complete = 1; - if (DebugVar & 1) - printk(KERN_ERR "eicon: buffer incomplete, but 0 in queue\n"); + eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n"); + restore_flags(flags); dev_kfree_skb(skb); continue; } @@ -105,8 +125,8 @@ eicon_io_rcv_dispatch(eicon_card *ccard) { skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length), GFP_ATOMIC); if (!skb_new) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in rcv_dispatch()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n"); + restore_flags(flags); dev_kfree_skb(skb); dev_kfree_skb(skb2); continue; @@ -125,12 +145,14 @@ eicon_io_rcv_dispatch(eicon_card *ccard) { dev_kfree_skb(skb2); if (ind->MLength == ind->RBuffer.length) { chan->e.complete = 2; + restore_flags(flags); idi_handle_ind(ccard, skb_new); continue; } else { chan->e.complete = 0; skb_queue_tail(&chan->e.R, skb_new); + restore_flags(flags); continue; } } @@ -142,8 +164,7 @@ eicon_io_ack_dispatch(eicon_card *ccard) { struct sk_buff *skb; if (!ccard) { - if (DebugVar & 1) - printk(KERN_WARNING "eicon_io_ack_dispatch: NULL card!\n"); + eicon_log(ccard, 1, "eicon_err: NULL card in ack_dispatch!\n"); return; } while((skb = skb_dequeue(&ccard->rackq))) { @@ -399,13 +420,13 @@ eicon_io_transmit(eicon_card *ccard) { int scom = 0; int tmp = 0; int quloop = 1; + int dlev = 0; pci_card = &ccard->hwif.pci; isa_card = &ccard->hwif.isa; if (!ccard) { - if (DebugVar & 1) - printk(KERN_WARNING "eicon_transmit: NULL card!\n"); + eicon_log(ccard, 1, "eicon_transmit: NULL card!\n"); return; } @@ -438,7 +459,7 @@ eicon_io_transmit(eicon_card *ccard) { prram = 0; break; default: - printk(KERN_WARNING "eicon_transmit: unsupported card-type!\n"); + eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n"); return; } @@ -457,16 +478,14 @@ eicon_io_transmit(eicon_card *ccard) { } restore_flags(flags); skb_queue_head(&ccard->sndq, skb2); - if (DebugVar & 32) - printk(KERN_INFO "eicon: transmit: Card not ready\n"); + eicon_log(ccard, 32, "eicon: transmit: Card not ready\n"); return; } } else { if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) { restore_flags(flags); skb_queue_head(&ccard->sndq, skb2); - if (DebugVar & 32) - printk(KERN_INFO "eicon: transmit: Card not ready\n"); + eicon_log(ccard, 32, "eicon: transmit: Card not ready\n"); return; } } @@ -479,8 +498,7 @@ eicon_io_transmit(eicon_card *ccard) { cli(); reqbuf = (eicon_REQ *)skb->data; if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) { - if (DebugVar & 16) - printk(KERN_WARNING "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); + eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); } else { if (scom) { ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length); @@ -495,7 +513,7 @@ eicon_io_transmit(eicon_card *ccard) { ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh); ram_outb(ccard, &ReqOut->Req, reqbuf->Req); } - + dlev = 160; if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */ if (!reqbuf->Reference) { /* Signal Layer */ @@ -517,6 +535,7 @@ eicon_io_transmit(eicon_card *ccard) { ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */ chan->waitq = reqbuf->XBuffer.length; chan->waitpq += reqbuf->XBuffer.length; + dlev = 128; } } @@ -544,13 +563,12 @@ eicon_io_transmit(eicon_card *ccard) { else ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next)); - chan->e.busy = 1; - if (DebugVar & 32) - printk(KERN_DEBUG "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", - reqbuf->Req, - ram_inb(ccard, &ReqOut->ReqId), - reqbuf->ReqCh, reqbuf->XBuffer.length, - chan->e.ref); + chan->e.busy = 1; + eicon_log(ccard, dlev, "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", + reqbuf->Req, + ram_inb(ccard, &ReqOut->ReqId), + reqbuf->ReqCh, reqbuf->XBuffer.length, + chan->e.ref); } restore_flags(flags); dev_kfree_skb(skb); @@ -559,8 +577,7 @@ eicon_io_transmit(eicon_card *ccard) { } else { skb_queue_tail(&ccard->sackq, skb2); - if (DebugVar & 32) - printk(KERN_INFO "eicon: transmit: busy chan %d\n", chan->No); + eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No); } if (scom) @@ -601,10 +618,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { unsigned char *irqprobe = 0; int scom = 0; int tmp = 0; + int dlev = 0; if (!ccard) { - printk(KERN_WARNING "eicon_irq: spurious interrupt %d\n", irq); + eicon_log(ccard, 1, "eicon_irq: spurious interrupt %d\n", irq); return; } @@ -656,7 +674,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { prram = 0; break; default: - printk(KERN_WARNING "eicon_irq: unsupported card-type!\n"); + eicon_log(ccard, 1, "eicon_irq: unsupported card-type!\n"); return; } @@ -706,24 +724,21 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { case EICON_CTYPE_QUADRO: case EICON_CTYPE_S2M: if (!(readb(isa_card->intack))) { /* card did not interrupt */ - if (DebugVar & 1) - printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n"); + eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n"); return; } break; #endif case EICON_CTYPE_MAESTRAP: if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */ - if (DebugVar & 1) - printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n"); + eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n"); return; } break; case EICON_CTYPE_MAESTRA: outw(0x3fe, pci_card->PCIreg + M_ADDR); if (!(inb(pci_card->PCIreg + M_DATA))) { /* card did not interrupt */ - if (DebugVar & 1) - printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n"); + eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n"); return; } break; @@ -735,8 +750,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { if ((tmp = ram_inb(ccard, &com->Rc))) { eicon_RC *ack; if (tmp == READY_INT) { - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Rc=READY_INT\n"); + eicon_log(ccard, 64, "eicon: IRQ Rc=READY_INT\n"); if (ccard->ReadyInt) { ccard->ReadyInt--; ram_outb(ccard, &com->Rc, 0); @@ -744,17 +758,15 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { } else { skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC); if (!skb) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); } else { ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC)); ack->Rc = tmp; ack->RcId = ram_inb(ccard, &com->RcId); ack->RcCh = ram_inb(ccard, &com->RcCh); ack->Reference = ccard->ref_in++; - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", - tmp,ack->RcId,ack->RcCh,ack->Reference); + eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", + tmp,ack->RcId,ack->RcCh,ack->Reference); skb_queue_tail(&ccard->rackq, skb); eicon_schedule_ack(ccard); } @@ -770,8 +782,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { int len = ram_inw(ccard, &com->RBuffer.length); skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC); if (!skb) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); } else { ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1)); ind->Ind = tmp; @@ -779,9 +790,12 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { ind->IndCh = ram_inb(ccard, &com->IndCh); ind->MInd = ram_inb(ccard, &com->MInd); ind->MLength = ram_inw(ccard, &com->MLength); - ind->RBuffer.length = len; - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", + ind->RBuffer.length = len; + if ((tmp == 1) || (tmp == 8)) + dlev = 128; + else + dlev = 192; + eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len); ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len); skb_queue_tail(&ccard->rcvq, skb); @@ -804,17 +818,15 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { if((Rc=ram_inb(ccard, &RcIn->Rc))) { skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC); if (!skb) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); } else { ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC)); ack->Rc = Rc; ack->RcId = ram_inb(ccard, &RcIn->RcId); ack->RcCh = ram_inb(ccard, &RcIn->RcCh); ack->Reference = ram_inw(ccard, &RcIn->Reference); - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", - Rc,ack->RcId,ack->RcCh,ack->Reference); + eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", + Rc,ack->RcId,ack->RcCh,ack->Reference); skb_queue_tail(&ccard->rackq, skb); eicon_schedule_ack(ccard); } @@ -839,8 +851,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { int len = ram_inw(ccard, &IndIn->RBuffer.length); skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC); if (!skb) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); } else { ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1)); ind->Ind = Ind; @@ -849,8 +860,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { ind->MInd = ram_inb(ccard, &IndIn->MInd); ind->MLength = ram_inw(ccard, &IndIn->MLength); ind->RBuffer.length = len; - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", + if ((Ind == 1) || (Ind == 8)) + dlev = 128; + else + dlev = 192; + eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len); ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len); skb_queue_tail(&ccard->rcvq, skb); diff --git a/drivers/isdn/eicon/eicon_isa.c b/drivers/isdn/eicon/eicon_isa.c index 75122559ce9eabe4725dff76df5ec51d5ab143d5..a89d18b1212814592458640072ecd946ccd2c75e 100644 --- a/drivers/isdn/eicon/eicon_isa.c +++ b/drivers/isdn/eicon/eicon_isa.c @@ -1,9 +1,9 @@ -/* $Id: eicon_isa.c,v 1.7 1999/08/22 20:26:48 calle Exp $ +/* $Id: eicon_isa.c,v 1.9 1999/09/08 20:17:31 armin Exp $ * * ISDN low-level module for Eicon.Diehl active ISDN-Cards. * Hardware-specific code for old ISA cards. * - * Copyright 1998 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * @@ -22,6 +22,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_isa.c,v $ + * Revision 1.9 1999/09/08 20:17:31 armin + * Added microchannel patch from Erik Weber. + * + * Revision 1.8 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * * Revision 1.7 1999/08/22 20:26:48 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -64,7 +70,9 @@ #define release_shmem release_region #define request_shmem request_region -char *eicon_isa_revision = "$Revision: 1.7 $"; +char *eicon_isa_revision = "$Revision: 1.9 $"; + +#undef EICON_MCA_DEBUG #ifdef CONFIG_ISDN_DRV_EICON_ISA @@ -107,7 +115,7 @@ eicon_isa_printpar(eicon_isa_card *card) { case EICON_CTYPE_SCOM: case EICON_CTYPE_QUADRO: case EICON_CTYPE_S2M: - printk(KERN_INFO "Eicon %s at 0x%lx, irq %d\n", + printk(KERN_INFO "Eicon %s at 0x%lx, irq %d.\n", eicon_ctype_name[card->type], (unsigned long)card->shmem, card->irq); @@ -210,12 +218,30 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { return -EBUSY; } request_shmem((unsigned long)card->shmem, card->ramsize, "Eicon ISA ISDN"); +#ifdef EICON_MCA_DEBUG + printk(KERN_INFO "eicon_isa_boot: card->ramsize = %d.\n", card->ramsize); +#endif card->mvalid = 1; /* clear any pending irq's */ readb(card->intack); +#ifdef CONFIG_MCA + if (card->type == EICON_CTYPE_SCOM) { + outb_p(0,card->io+1); + } + else { + printk(KERN_WARNING "eicon_isa_boot: Card type yet not supported.\n"); + return -EINVAL; + }; + +#ifdef EICON_MCA_DEBUG + printk(KERN_INFO "eicon_isa_boot: card->io = %x.\n", card->io); + printk(KERN_INFO "eicon_isa_boot: card->irq = %d.\n", (int)card->irq); +#endif +#else /* set reset-line active */ writeb(0, card->stopcpu); +#endif /* CONFIG_MCA */ /* clear irq-requests */ writeb(0, card->intack); readb(card->intack); @@ -242,7 +268,11 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { /* Start CPU */ writeb(cbuf.boot_opt, &boot->ctrl); +#ifdef CONFIG_MCA + outb_p(0, card->io); +#else writeb(0, card->startcpu); +#endif /* CONFIG_MCA */ /* Delay 0.2 sec. */ SLEEP(20); @@ -254,7 +284,11 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { SLEEP(10); } if (readb(&boot->ctrl) != 0) { - printk(KERN_WARNING "eicon_isa_boot: CPU test failed\n"); + printk(KERN_WARNING "eicon_isa_boot: CPU test failed.\n"); +#ifdef EICON_MCA_DEBUG + printk(KERN_INFO "eicon_isa_boot: &boot->ctrl = %d.\n", + readb(&boot->ctrl)); +#endif eicon_isa_release_shmem(card); return -EIO; } @@ -307,7 +341,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { return -EFAULT; if (!(code = kmalloc(cbuf.firmware_len, GFP_KERNEL))) { - printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n"); + printk(KERN_WARNING "eicon_isa_load: Couldn't allocate code buffer\n"); return -ENOMEM; } @@ -323,7 +357,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { /* Check for valid IRQ */ if ((card->irq < 0) || (card->irq > 15) || (!((1 << card->irq) & eicon_isa_valid_irq[card->type & 0x0f]))) { - printk(KERN_WARNING "eicon_isa_boot: illegal irq: %d\n", card->irq); + printk(KERN_WARNING "eicon_isa_load: illegal irq: %d\n", card->irq); eicon_isa_release_shmem(card); kfree(code); return -EINVAL; @@ -332,7 +366,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { if (!request_irq(card->irq, &eicon_irq, 0, "Eicon ISA ISDN", card)) card->ivalid = 1; else { - printk(KERN_WARNING "eicon_isa_boot: irq %d already in use.\n", + printk(KERN_WARNING "eicon_isa_load: irq %d already in use.\n", card->irq); eicon_isa_release_shmem(card); kfree(code); @@ -343,7 +377,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { tmp = readb(&boot->msize); if (tmp != 8 && tmp != 16 && tmp != 24 && tmp != 32 && tmp != 48 && tmp != 60) { - printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n"); + printk(KERN_WARNING "eicon_isa_load: invalid memsize\n"); eicon_isa_release_shmem(card); return -EIO; } @@ -366,7 +400,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { SLEEP(2); } if (readb(&boot->ctrl)) { - printk(KERN_WARNING "eicon_isa_boot: download timeout at 0x%x\n", p-code); + printk(KERN_WARNING "eicon_isa_load: download timeout at 0x%x\n", p-code); eicon_isa_release(card); kfree(code); return -EIO; @@ -389,7 +423,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { SLEEP(2); } if (readw(&boot->signature) != 0x4447) { - printk(KERN_WARNING "eicon_isa_boot: firmware selftest failed %04x\n", + printk(KERN_WARNING "eicon_isa_load: firmware selftest failed %04x\n", readw(&boot->signature)); eicon_isa_release(card); return -EIO; @@ -414,11 +448,15 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { SLEEP(2); } if (card->irqprobe == 1) { - printk(KERN_WARNING "eicon_isa_boot: IRQ test failed\n"); + printk(KERN_WARNING "eicon_isa_load: IRQ # %d test failed\n", card->irq); eicon_isa_release(card); return -EIO; } } +#ifdef EICON_MCA_DEBUG + printk(KERN_INFO "eicon_isa_load: IRQ # %d test succeeded.\n", card->irq); +#endif + writeb(card->irq, &card->shmem->com.Int); /* initializing some variables */ diff --git a/drivers/isdn/eicon/eicon_isa.h b/drivers/isdn/eicon/eicon_isa.h index 5b0dc1a6a60fd7d5c06553ef6dd656c9bdc5d074..7f86bd9ff4efcc1755d12bc63ea463e984af64b8 100644 --- a/drivers/isdn/eicon/eicon_isa.h +++ b/drivers/isdn/eicon/eicon_isa.h @@ -1,8 +1,8 @@ -/* $Id: eicon_isa.h,v 1.3 1999/03/29 11:19:47 armin Exp $ +/* $Id: eicon_isa.h,v 1.5 1999/09/08 20:17:31 armin Exp $ * * ISDN low-level module for Eicon.Diehl active ISDN-Cards. * - * Copyright 1998 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * @@ -21,6 +21,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_isa.h,v $ + * Revision 1.5 1999/09/08 20:17:31 armin + * Added microchannel patch from Erik Weber. + * + * Revision 1.4 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * * Revision 1.3 1999/03/29 11:19:47 armin * I/O stuff now in seperate file (eicon_io.c) * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. @@ -106,6 +112,9 @@ typedef union { typedef struct { int ramsize; int irq; /* IRQ */ +#ifdef CONFIG_MCA + int io; /* IO-port for MCA brand */ +#endif /* CONFIG_MCA */ void* card; eicon_isa_shmem* shmem; /* Shared-memory area */ unsigned char* intack; /* Int-Acknowledge */ diff --git a/drivers/isdn/eicon/eicon_mod.c b/drivers/isdn/eicon/eicon_mod.c index 1ac22aa80e0f70e247f3ea424107665c74362561..2cad8a504a5f3d36914987299f928e70ba1b9189 100644 --- a/drivers/isdn/eicon/eicon_mod.c +++ b/drivers/isdn/eicon/eicon_mod.c @@ -1,8 +1,8 @@ -/* $Id: eicon_mod.c,v 1.11 1999/08/29 17:23:45 armin Exp $ +/* $Id: eicon_mod.c,v 1.18 1999/10/11 18:13:25 armin Exp $ * * ISDN lowlevel-module for Eicon.Diehl active cards. * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * @@ -11,6 +11,11 @@ * * Deutsche Telekom AG for S2M support. * + * Deutsche Mailbox Saar-Lor-Lux GmbH + * for sponsoring and testing fax + * capabilities with Diva Server cards. + * (dor@deutschemailbox.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) @@ -26,6 +31,30 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_mod.c,v $ + * Revision 1.18 1999/10/11 18:13:25 armin + * Added fax capabilities for Eicon Diva Server cards. + * + * Revision 1.17 1999/10/08 22:09:34 armin + * Some fixes of cards interface handling. + * Bugfix of NULL pointer occurence. + * Changed a few log outputs. + * + * Revision 1.16 1999/09/26 14:17:53 armin + * Improved debug and log via readstat() + * + * Revision 1.15 1999/09/08 20:17:31 armin + * Added microchannel patch from Erik Weber. + * + * Revision 1.14 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * + * Revision 1.13 1999/09/04 17:37:59 armin + * Removed not used define, did not work and caused error + * in 2.3.16 + * + * Revision 1.12 1999/08/31 11:20:14 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.11 1999/08/29 17:23:45 armin * New setup compat. * Bugfix if compile as not module. @@ -82,7 +111,7 @@ #include <linux/init.h> #ifdef CONFIG_MCA #include <linux/mca.h> -#endif +#endif /* CONFIG_MCA */ #include "eicon.h" @@ -91,7 +120,7 @@ static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains start of card-list */ -static char *eicon_revision = "$Revision: 1.11 $"; +static char *eicon_revision = "$Revision: 1.18 $"; extern char *eicon_pci_revision; extern char *eicon_isa_revision; @@ -172,8 +201,7 @@ find_channel(eicon_card *card, int channel) { if ((channel >= 0) && (channel < card->nchannels)) return &(card->bch[channel]); - if (DebugVar & 1) - printk(KERN_WARNING "eicon: Invalid channel %d\n", channel); + eicon_log(card, 1, "eicon: Invalid channel %d\n", channel); return NULL; } @@ -239,87 +267,6 @@ eicon_find_eaz(eicon_card *card, char eaz) return("\0"); } -#if 0 -/* - * Add or delete an MSN to the MSN list - * - * First character of msneaz is EAZ, rest is MSN. - * If length of eazmsn is 1, delete that entry. - */ -static int -eicon_set_msn(eicon_card *card, char *eazmsn) -{ - struct msn_entry *p = card->msn_list; - struct msn_entry *q = NULL; - unsigned long flags; - int i; - - if (!strlen(eazmsn)) - return 0; - if (strlen(eazmsn) > 16) - return -EINVAL; - for (i = 0; i < strlen(eazmsn); i++) - if (!isdigit(eazmsn[i])) - return -EINVAL; - if (strlen(eazmsn) == 1) { - /* Delete a single MSN */ - while (p) { - if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); - if (q) - q->next = p->next; - else - card->msn_list = p->next; - restore_flags(flags); - kfree(p); - if (DebugVar & 8) - printk(KERN_DEBUG - "Mapping for EAZ %c deleted\n", - eazmsn[0]); - return 0; - } - q = p; - p = p->next; - } - return 0; - } - /* Add a single MSN */ - while (p) { - /* Found in list, replace MSN */ - if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); - strcpy(p->msn, &eazmsn[1]); - restore_flags(flags); - if (DebugVar & 8) - printk(KERN_DEBUG - "Mapping for EAZ %c changed to %s\n", - eazmsn[0], - &eazmsn[1]); - return 0; - } - p = p->next; - } - /* Not found in list, add new entry */ - p = kmalloc(sizeof(msn_entry), GFP_KERNEL); - if (!p) - return -ENOMEM; - p->eaz = eazmsn[0]; - strcpy(p->msn, &eazmsn[1]); - p->next = card->msn_list; - save_flags(flags); - cli(); - card->msn_list = p; - restore_flags(flags); - if (DebugVar & 8) - printk(KERN_DEBUG - "Mapping %c -> %s added\n", - eazmsn[0], - &eazmsn[1]); - return 0; -} -#endif static void eicon_rcv_dispatch(struct eicon_card *card) @@ -331,9 +278,8 @@ eicon_rcv_dispatch(struct eicon_card *card) eicon_io_rcv_dispatch(card); break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); + eicon_log(card, 1, + "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); } } @@ -347,9 +293,8 @@ eicon_ack_dispatch(struct eicon_card *card) eicon_io_ack_dispatch(card); break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); + eicon_log(card, 1, + "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); } } @@ -363,9 +308,8 @@ eicon_transmit(struct eicon_card *card) eicon_io_transmit(card); break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon_transmit: Illegal bustype %d\n", card->bus); + eicon_log(card, 1, + "eicon_transmit: Illegal bustype %d\n", card->bus); } } @@ -375,8 +319,7 @@ static int eicon_xlog(eicon_card *card, xlogreq_t *xlogreq) int ret_val; if (!(xlr = kmalloc(sizeof(xlogreq_t), GFP_KERNEL))) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: alloc_xlogreq_t failed\n"); + eicon_log(card, 1, "idi_err: alloc_xlogreq_t failed\n"); return -ENOMEM; } if (copy_from_user(xlr, xlogreq, sizeof(xlogreq_t))) { @@ -406,9 +349,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) int ret = 0; unsigned long flags; - if (DebugVar & 16) - printk(KERN_WARNING "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n", - c->command, c->arg, (ulong) *c->parm.num); + eicon_log(card, 16, "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n", + c->command, c->arg, (ulong) *c->parm.num); switch (c->command) { case ISDN_CMD_IOCTL: @@ -428,9 +370,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) return card->hwif.pci.PCIram; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -440,17 +381,25 @@ eicon_command(eicon_card * card, isdn_ctrl * c) return -EBUSY; switch (card->bus) { case EICON_BUS_ISA: - case EICON_BUS_MCA: if (eicon_isa_find_card(a, card->hwif.isa.irq, card->regname) < 0) return -EFAULT; card->hwif.isa.shmem = (eicon_isa_shmem *)a; return 0; + case EICON_BUS_MCA: +#if CONFIG_MCA + if (eicon_mca_find_card( + 0, a, + card->hwif.isa.irq, + card->regname) < 0) + return -EFAULT; + card->hwif.isa.shmem = (eicon_isa_shmem *)a; + return 0; +#endif /* CONFIG_MCA */ default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -465,9 +414,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) return card->hwif.pci.irq; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -482,9 +430,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) card->hwif.isa.irq = a; return 0; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -500,9 +447,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) &(((eicon_codebuf *)a)->isa)); break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -534,9 +480,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) } break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -591,18 +536,6 @@ eicon_command(eicon_card * card, isdn_ctrl * c) } return ret; } else return -ENODEV; -#endif -#if 0 - case EICON_IOCTL_SETMSN: - if ((ret = copy_from_user(tmp, (char *)a, sizeof(tmp)))) - return -EFAULT; - if ((ret = eicon_set_msn(card, tmp))) - return ret; -#if 0 - if (card->flags & EICON_FLAGS_RUNNING) - return(eicon_capi_manufacturer_req_msn(card)); -#endif - return 0; #endif case EICON_IOCTL_ADDCARD: if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef)))) @@ -612,7 +545,7 @@ eicon_command(eicon_card * card, isdn_ctrl * c) return 0; case EICON_IOCTL_DEBUGVAR: DebugVar = a; - printk(KERN_DEBUG"Eicon: Debug Value set to %ld\n", DebugVar); + eicon_log(card, 1, "Eicon: Debug Value set to %ld\n", DebugVar); return 0; #ifdef MODULE case EICON_IOCTL_FREEIT: @@ -633,8 +566,7 @@ eicon_command(eicon_card * card, isdn_ctrl * c) cli(); if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) { restore_flags(flags); - if (DebugVar & 1) - printk(KERN_WARNING "Dial on channel %d with state %d\n", + eicon_log(card, 1, "Dial on channel %d with state %d\n", chan->No, chan->fsm_state); return -EBUSY; } @@ -643,7 +575,6 @@ eicon_command(eicon_card * card, isdn_ctrl * c) else tmp[0] = c->parm.setup.eazmsn[0]; chan->fsm_state = EICON_STATE_OCALL; - chan->callref = 0xffff; restore_flags(flags); ret = idi_connect_req(card, chan, c->parm.setup.phone, @@ -738,20 +669,17 @@ eicon_command(eicon_card * card, isdn_ctrl * c) case ISDN_CMD_GETEAZ: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - if (DebugVar & 1) - printk(KERN_DEBUG "eicon CMD_GETEAZ not implemented\n"); + eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n"); return 0; case ISDN_CMD_SETSIL: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - if (DebugVar & 1) - printk(KERN_DEBUG "eicon CMD_SETSIL not implemented\n"); + eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n"); return 0; case ISDN_CMD_GETSIL: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - if (DebugVar & 1) - printk(KERN_DEBUG "eicon CMD_GETSIL not implemented\n"); + eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n"); return 0; case ISDN_CMD_LOCK: MOD_INC_USE_COUNT; @@ -817,36 +745,58 @@ if_command(isdn_ctrl * c) static int if_writecmd(const u_char * buf, int len, int user, int id, int channel) { -#if 0 - /* Not yet used */ - eicon_card *card = eicon_findcard(id); - - if (card) { - if (!card->flags & EICON_FLAGS_RUNNING) - return (len); - return (len); - } - printk(KERN_ERR - "eicon: if_writecmd called with invalid driverId!\n"); -#endif return (len); } static int if_readstatus(u_char * buf, int len, int user, int id, int channel) { -#if 0 - /* Not yet used */ + int count = 0; + int cnt = 0; + ulong flags = 0; + u_char *p = buf; + struct sk_buff *skb; + eicon_card *card = eicon_findcard(id); if (card) { if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - return (eicon_readstatus(buf, len, user, card)); + + save_flags(flags); + cli(); + while((skb = skb_dequeue(&card->statq))) { + + if ((skb->len + count) > len) + cnt = len - count; + else + cnt = skb->len; + + if (user) + copy_to_user(p, skb->data, cnt); + else + memcpy(p, skb->data, cnt); + + count += cnt; + p += cnt; + + if (cnt == skb->len) { + dev_kfree_skb(skb); + if (card->statq_entries > 0) + card->statq_entries--; + } else { + skb_pull(skb, cnt); + skb_queue_head(&card->statq, skb); + restore_flags(flags); + return count; + } + } + card->statq_entries = 0; + restore_flags(flags); + return count; } printk(KERN_ERR "eicon: if_readstatus called with invalid driverId!\n"); -#endif return 0; } @@ -861,14 +811,11 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) len = skb->len; if (card) { - if (!card->flags & EICON_FLAGS_RUNNING) { - dev_kfree_skb(skb); + if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - } - if (!(chan = find_channel(card, channel))) { - dev_kfree_skb(skb); + if (!(chan = find_channel(card, channel))) return -ENODEV; - } + if (chan->fsm_state == EICON_STATE_ACTIVE) { #ifdef CONFIG_ISDN_TTY_FAX if (chan->l2prot == ISDN_PROTO_L2_FAX) { @@ -880,16 +827,115 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) ret = idi_send_data(card, chan, ack, skb, 1); return (ret); } else { - dev_kfree_skb(skb); return -ENODEV; } } printk(KERN_ERR "eicon: if_sendbuf called with invalid driverId!\n"); - dev_kfree_skb(skb); return -ENODEV; } +/* jiftime() copied from HiSax */ +inline int +jiftime(char *s, long mark) +{ + s += 8; + + *s-- = '\0'; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = '.'; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = mark % 6 + '0'; + mark /= 6; + *s-- = ':'; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = mark % 10 + '0'; + return(8); +} + +void +eicon_putstatus(eicon_card * card, char * buf) +{ + ulong flags; + int count; + isdn_ctrl cmd; + u_char *p; + struct sk_buff *skb; + + if (!card) + return; + + save_flags(flags); + cli(); + count = strlen(buf); + skb = alloc_skb(count, GFP_ATOMIC); + if (!skb) { + restore_flags(flags); + printk(KERN_ERR "eicon: could not alloc skb in putstatus\n"); + return; + } + p = skb_put(skb, count); + memcpy(p, buf, count); + + skb_queue_tail(&card->statq, skb); + + if (card->statq_entries >= MAX_STATUS_BUFFER) { + if ((skb = skb_dequeue(&card->statq))) { + count -= skb->len; + dev_kfree_skb(skb); + } else + count = 0; + } else + card->statq_entries++; + + restore_flags(flags); + if (count) { + cmd.command = ISDN_STAT_STAVAIL; + cmd.driver = card->myid; + cmd.arg = count; + card->interface.statcallb(&cmd); + } +} + +/* + * Debug and Log + */ +void +eicon_log(eicon_card * card, int level, const char *fmt, ...) +{ + va_list args; + char Line[160]; + u_char *p; + + + if ((DebugVar & level) || (DebugVar & 256)) { + va_start(args, fmt); + + if (DebugVar & level) { + if (DebugVar & 256) { + /* log-buffer */ + p = Line; + p += jiftime(p, jiffies); + *p++ = 32; + p += vsprintf(p, fmt, args); + *p = 0; + eicon_putstatus(card, Line); + } else { + /* printk, syslogd */ + vsprintf(Line, fmt, args); + printk(KERN_DEBUG "%s", Line); + } + } + + va_end(args); + } +} + /* * Allocate a new card-struct, initialize it @@ -912,7 +958,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id) qloop = (Type == EICON_CTYPE_QUADRO)?2:0; for (i = 0; i <= qloop; i++) { if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) { - printk(KERN_WARNING + eicon_log(card, 1, "eicon: (%s) Could not allocate card-struct.\n", id); return; } @@ -921,6 +967,8 @@ eicon_alloccard(int Type, int membase, int irq, char *id) skb_queue_head_init(&card->rcvq); skb_queue_head_init(&card->rackq); skb_queue_head_init(&card->sackq); + skb_queue_head_init(&card->statq); + card->statq_entries = 0; card->snd_tq.routine = (void *) (void *) eicon_transmit; card->snd_tq.data = card; card->rcv_tq.routine = (void *) (void *) eicon_rcv_dispatch; @@ -992,7 +1040,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id) p = p->next; } if (!p) { - printk(KERN_WARNING "eicon_alloccard: Quadro Master not found.\n"); + eicon_log(card, 1, "eicon_alloccard: Quadro Master not found.\n"); kfree(card); return; } @@ -1014,7 +1062,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id) ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038 | ISDN_FEATURE_L2_MODEM | - /* ISDN_FEATURE_L2_FAX | */ + ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_TRANSDSP | ISDN_FEATURE_L3_FAX; card->hwif.pci.card = (void *)card; @@ -1038,7 +1086,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id) ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038 | ISDN_FEATURE_L2_MODEM | - /* ISDN_FEATURE_L2_FAX | */ + ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_TRANSDSP | ISDN_FEATURE_L3_FAX; card->hwif.pci.card = (void *)card; @@ -1087,13 +1135,13 @@ eicon_alloccard(int Type, int membase, int irq, char *id) break; #endif default: - printk(KERN_WARNING "eicon_alloccard: Invalid type %d\n", Type); + eicon_log(card, 1, "eicon_alloccard: Invalid type %d\n", Type); kfree(card); return; } if (!(card->bch = (eicon_chan *) kmalloc(sizeof(eicon_chan) * (card->nchannels + 1) , GFP_KERNEL))) { - printk(KERN_WARNING + eicon_log(card, 1, "eicon: (%s) Could not allocate bch-struct.\n", id); kfree(card); return; @@ -1131,7 +1179,7 @@ eicon_registercard(eicon_card * card) case EICON_BUS_MCA: eicon_isa_printpar(&card->hwif.isa); break; -#endif +#endif /* CONFIG_MCA */ #endif case EICON_BUS_PCI: #if CONFIG_PCI @@ -1139,9 +1187,8 @@ eicon_registercard(eicon_card * card) break; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon_registercard: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon_registercard: Illegal BUS type %d\n", card->bus); return -1; } @@ -1170,7 +1217,7 @@ unregister_card(eicon_card * card) case EICON_BUS_ISA: #ifdef CONFIG_MCA case EICON_BUS_MCA: -#endif +#endif /* CONFIG_MCA */ eicon_isa_release(&card->hwif.isa); break; #endif @@ -1180,9 +1227,8 @@ unregister_card(eicon_card * card) break; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Invalid BUS type %d\n", + eicon_log(card, 1, + "eicon: Invalid BUS type %d\n", card->bus); break; } @@ -1191,6 +1237,26 @@ unregister_card(eicon_card * card) static void eicon_freecard(eicon_card *card) { + int i; + struct sk_buff *skb; + + for(i = 0; i < (card->nchannels + 1); i++) { + while((skb = skb_dequeue(&card->bch[i].e.X))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->bch[i].e.R))) + dev_kfree_skb(skb); + } + while((skb = skb_dequeue(&card->sndq))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->rcvq))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->rackq))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->sackq))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->statq))) + dev_kfree_skb(skb); + eicon_clear_msn(card); kfree(card->bch); kfree(card); @@ -1236,9 +1302,8 @@ eicon_addcard(int Type, int membase, int irq, char *id) break; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: addcard: Invalid BUS type %d\n", + printk(KERN_ERR + "eicon: addcard: Invalid BUS type %d\n", p->bus); } } else @@ -1250,7 +1315,7 @@ eicon_addcard(int Type, int membase, int irq, char *id) p = p->next; } else { /* registering failed, remove card from list, free memory */ - printk(KERN_WARNING + printk(KERN_ERR "eicon: Initialization of %s failed\n", p->interface.id); if (q) { @@ -1275,7 +1340,7 @@ eicon_addcard(int Type, int membase, int irq, char *id) #define eicon_init init_module #endif -int __init +int eicon_init(void) { int card_count = 0; @@ -1317,10 +1382,9 @@ eicon_init(void) printk(KERN_INFO "eicon: No MCA bus, ISDN-interfaces not probed.\n"); } else { - if (DebugVar & 8) - printk(KERN_DEBUG - "eicon_mca_find_card, irq=%d.\n", - irq); + eicon_log(card, 8, + "eicon_mca_find_card, irq=%d.\n", + irq); if (!eicon_mca_find_card(0, membase, irq, id)) card_count++; }; @@ -1361,12 +1425,14 @@ cleanup_module(void) eicon_card *card = cards; eicon_card *last; while (card) { +#ifdef CONFIG_ISDN_DRV_EICON_ISA #ifdef CONFIG_MCA if (MCA_bus) { mca_mark_as_unused (card->mca_slot); mca_set_adapter_procfn(card->mca_slot, NULL, NULL); }; +#endif /* CONFIG_MCA */ #endif unregister_card(card); card = card->next; @@ -1382,7 +1448,6 @@ cleanup_module(void) #else /* no module */ -#ifdef COMPAT_HAS_NEW_SETUP static int __init eicon_setup(char *line) { @@ -1391,12 +1456,6 @@ eicon_setup(char *line) char *str; str = get_options(line, 4, ints); -#else -void __init -eicon_setup(char *str, int *ints) -{ - int i, argc; -#endif argc = ints[0]; i = 1; @@ -1424,13 +1483,9 @@ eicon_setup(char *str, int *ints) #else printk(KERN_INFO "Eicon ISDN active driver setup\n"); #endif -#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("eicon=", eicon_setup); -#else -} -#endif #endif /* MODULE */ @@ -1456,10 +1511,9 @@ int eicon_mca_find_card(int type, /* type-idx of eicon-card */ { int j, curr_slot = 0; - if (DebugVar & 8) - printk(KERN_DEBUG - "eicon_mca_find_card type: %d, membase: %#x, irq %d \n", - type, membase, irq); + eicon_log(card, 8, + "eicon_mca_find_card type: %d, membase: %#x, irq %d \n", + type, membase, irq); /* find a no-driver-assigned eicon card */ for (j=0; eicon_mca_adapters[j].adf_id != 0; j++) { @@ -1524,11 +1578,10 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ int irq_array1[]={3,4,0,0,2,10,11,12}; adf_pos0 = mca_read_stored_pos(slot,2); - if (DebugVar & 8) - printk(KERN_DEBUG - "eicon_mca_probe irq=%d, membase=%d\n", - irq, - membase); + eicon_log(card, 8, + "eicon_mca_probe irq=%d, membase=%d\n", + irq, + membase); switch (a_idx) { case 0: /* P/2-Adapter (== PRI/S2M ? ) */ cards_membase= 0xC0000+((adf_pos0>>4)*0x4000); @@ -1542,7 +1595,7 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ if (irq == -1) { irq = cards_irq; } else { - if (irq != irq) + if (irq != cards_irq) return ENODEV; }; cards_io= 0xC00 + ((adf_pos0>>4)*0x10); @@ -1575,7 +1628,7 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ if (irq == -1) { irq = cards_irq; } else { - if (irq != irq) + if (irq != cards_irq) return ENODEV; }; type = 0; @@ -1591,8 +1644,12 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ mca_mark_as_used(slot); cards->mca_slot = slot; /* card->io noch setzen oder ?? */ - if (DebugVar & 8) - printk("eicon_addcard: erfolgreich fuer slot: %d.\n", + cards->mca_io = cards_io; + cards->hwif.isa.io = cards_io; + /* reset card */ + outb_p(0,cards_io+1); + + eicon_log(card, 8, "eicon_addcard: successful for slot # %d.\n", cards->mca_slot+1); return 0 ; /* eicon_addcard hat eine Karte zugefuegt */ } else { diff --git a/drivers/isdn/eicon/eicon_pci.c b/drivers/isdn/eicon/eicon_pci.c index c1919e9f810c4f432259c3da3a1f81de14148905..5c96302cb80e2795bc2c114b6aa813d534a386ad 100644 --- a/drivers/isdn/eicon/eicon_pci.c +++ b/drivers/isdn/eicon/eicon_pci.c @@ -152,8 +152,8 @@ int eicon_pci_find_card(char *ID) aparms->type = EICON_CTYPE_MAESTRA; aparms->irq = pdev->irq; - preg = get_pcibase(pdev, 2) & 0xfffffffc; - pcfg = get_pcibase(pdev, 1) & 0xffffff80; + preg = pdev->resource[ 2].start & 0xfffffffc; + pcfg = pdev->resource[ 1].start & 0xffffff80; #ifdef EICON_PCI_DEBUG printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); @@ -174,9 +174,9 @@ int eicon_pci_find_card(char *ID) printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n"); aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/ aparms->irq = pdev->irq; - pram = get_pcibase(pdev, 0) & 0xfffff000; - preg = get_pcibase(pdev, 2) & 0xfffff000; - pcfg = get_pcibase(pdev, 4) & 0xfffff000; + pram = pdev->resource[ 0].start & 0xfffff000; + preg = pdev->resource[ 2].start & 0xfffff000; + pcfg = pdev->resource[ 4].start & 0xfffff000; #ifdef EICON_PCI_DEBUG printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile index 051df618271607af5843551450818571a2982c69..e37d9c404d2d53ac92c52396d060c8da6601047e 100644 --- a/drivers/isdn/hisax/Makefile +++ b/drivers/isdn/hisax/Makefile @@ -30,6 +30,8 @@ ISAR_OBJ := HFC_OBJ := HFC_2BDS0 := JADE_OBJ := +W6692_OBJ := + ifeq ($(CONFIG_HISAX_16_0),y) O_OBJS += teles0.o ISAC_OBJ := isac.o @@ -170,6 +172,10 @@ ifeq ($(CONFIG_HISAX_GAZEL),y) 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 @@ -179,7 +185,7 @@ ifeq ($(ISAC_OBJ), isac.o) endif O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(JADE_OBJ) -O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) +O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) $(W6692_OBJ) OX_OBJS += config.o O_TARGET := diff --git a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c index 7bcc8827c08265c7038bd9afb2134bac20081271..2770aa65e1f045fc356cc3206583f6dc2bd2b1d7 100644 --- a/drivers/isdn/hisax/amd7930.c +++ b/drivers/isdn/hisax/amd7930.c @@ -749,8 +749,8 @@ amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_amd7930(struct IsdnCard *card) +__initfunc(int +setup_amd7930(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c index 9e582641d30e8f5938133675754521e7c5597c98..e8abc9de2d0add37f959974e6729794f8e352b99 100644 --- a/drivers/isdn/hisax/arcofi.c +++ b/drivers/isdn/hisax/arcofi.c @@ -154,8 +154,6 @@ init_arcofi(struct IsdnCardState *cs) { cs->dc.isac.arcofitimer.function = (void *) arcofi_timer; cs->dc.isac.arcofitimer.data = (long) cs; init_timer(&cs->dc.isac.arcofitimer); -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&cs->dc.isac.arcofi_wait); -#endif test_and_set_bit(HW_ARCOFI, &cs->HW_Flags); } diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c index 06d8b59d059ab5ac50da5112174c7506a3f47dbc..10657ad63afe23d467b5ff7c26e6876608d9d9b0 100644 --- a/drivers/isdn/hisax/asuscom.c +++ b/drivers/isdn/hisax/asuscom.c @@ -1,4 +1,4 @@ -/* $Id: asuscom.c,v 1.7 1999/07/12 21:04:53 keil Exp $ +/* $Id: asuscom.c,v 1.8 1999/09/04 06:20:05 keil Exp $ * asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards * @@ -8,6 +8,9 @@ * * * $Log: asuscom.c,v $ + * Revision 1.8 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.7 1999/07/12 21:04:53 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -39,7 +42,7 @@ extern const char *CardType[]; -const char *Asuscom_revision = "$Revision: 1.7 $"; +const char *Asuscom_revision = "$Revision: 1.8 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -288,13 +291,13 @@ reset_asuscom(struct IsdnCardState *cs) byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); if (cs->subtyp == ASUS_IPAC) writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0); else byteout(cs->hw.asus.adr, 0); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); if (cs->subtyp == ASUS_IPAC) { writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0); @@ -326,8 +329,8 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_asuscom(struct IsdnCard *card) +__initfunc(int +setup_asuscom(struct IsdnCard *card)) { int bytecnt; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c index f96db367510374b26738a42d8519d3308cd23df3..55df36f0f73827aa06adb76a5463f78c3871ccfd 100644 --- a/drivers/isdn/hisax/avm_a1.c +++ b/drivers/isdn/hisax/avm_a1.c @@ -227,8 +227,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_avm_a1(struct IsdnCard *card) +__initfunc(int +setup_avm_a1(struct IsdnCard *card)) { u_char val; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c index 862829ab3bdf83f287ea398a4dd279e4982c2003..76382c3722b755341940133d865edba191c7b016 100644 --- a/drivers/isdn/hisax/avm_a1p.c +++ b/drivers/isdn/hisax/avm_a1p.c @@ -1,4 +1,4 @@ -/* $Id: avm_a1p.c,v 2.4 1999/07/12 21:04:55 keil Exp $ +/* $Id: avm_a1p.c,v 2.5 1999/09/01 08:26:34 calle Exp $ * * avm_a1p.c low level stuff for the following AVM cards: * A1 PCMCIA @@ -8,6 +8,9 @@ * Author Carsten Paeth (calle@calle.in-berlin.de) * * $Log: avm_a1p.c,v $ + * Revision 2.5 1999/09/01 08:26:34 calle + * Patch from Daniel Beichl <dani@ecomag.net> to make A1 PCMCIA work again. + * * Revision 2.4 1999/07/12 21:04:55 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -71,7 +74,7 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static const char *avm_revision = "$Revision: 2.4 $"; +static const char *avm_revision = "$Revision: 2.5 $"; static inline u_char ReadISAC(struct IsdnCardState *cs, u_char offset) @@ -245,6 +248,7 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return 0; case CARD_INIT: + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE); clear_pending_isac_ints(cs); clear_pending_hscx_ints(cs); inithscxisac(cs, 1); @@ -262,8 +266,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return 0; } -int __init -setup_avm_a1_pcmcia(struct IsdnCard *card) +__initfunc(int +setup_avm_a1_pcmcia(struct IsdnCard *card)) { u_char model, vers; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index cd293f1473050f91cca643c279494c4718afa4f7..f343bfb5ae24146cc3ad96611b7427ca06fb3010 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.11 1999/08/11 21:01:18 keil Exp $ +/* $Id: avm_pci.c,v 1.12 1999/09/04 06:20:05 keil Exp $ * avm_pci.c low level stuff for AVM Fritz!PCI and ISA PnP isdn cards * Thanks to AVM, Berlin for informations @@ -7,6 +7,9 @@ * * * $Log: avm_pci.c,v $ + * Revision 1.12 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.11 1999/08/11 21:01:18 keil * new PCI codefix * @@ -50,13 +53,10 @@ #include "isac.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #include <linux/interrupt.h> extern const char *CardType[]; -static const char *avm_pci_rev = "$Revision: 1.11 $"; +static const char *avm_pci_rev = "$Revision: 1.12 $"; #define AVM_FRITZ_PCI 1 #define AVM_FRITZ_PNP 2 @@ -482,7 +482,7 @@ HDLC_irq(struct BCState *bcs, u_int stat) { if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hdlc.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.hdlc.count = 0; bcs->tx_skb = NULL; } @@ -609,7 +609,7 @@ close_hdlcstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -734,11 +734,11 @@ reset_avmpcipnp(struct IsdnCardState *cs) save_flags(flags); sti(); outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3)); } @@ -773,14 +773,10 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_avm __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_avm_pcipnp(struct IsdnCard *card) +__initfunc(int +setup_avm_pcipnp(struct IsdnCard *card)) { u_int val, ver; struct IsdnCardState *cs = card->cs; @@ -796,7 +792,6 @@ setup_avm_pcipnp(struct IsdnCard *card) cs->subtyp = AVM_FRITZ_PNP; } else { #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "FritzPCI: no PCI bus present\n"); return(0); @@ -808,7 +803,7 @@ setup_avm_pcipnp(struct IsdnCard *card) printk(KERN_WARNING "FritzPCI: No IRQ for PCI card found\n"); return(0); } - cs->hw.avm.cfg_reg = get_pcibase(dev_avm, 1) & + cs->hw.avm.cfg_reg = dev_avm->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; if (!cs->hw.avm.cfg_reg) { printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n"); @@ -819,36 +814,6 @@ setup_avm_pcipnp(struct IsdnCard *card) printk(KERN_WARNING "FritzPCI: No PCI card found\n"); return(0); } -#else - for (; pci_index < 255; pci_index++) { - unsigned char pci_bus, pci_device_fn; - unsigned int ioaddr; - unsigned char irq; - - if (pcibios_find_device (PCI_VENDOR_AVM, - PCI_FRITZPCI_ID, pci_index, - &pci_bus, &pci_device_fn) != 0) { - continue; - } - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &irq); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &ioaddr); - cs->irq = irq; - cs->hw.avm.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK; - if (!cs->hw.avm.cfg_reg) { - printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n"); - return(0); - } - cs->subtyp = AVM_FRITZ_PCI; - break; - } - if (pci_index == 255) { - printk(KERN_WARNING "FritzPCI: No PCI card found\n"); - return(0); - } - pci_index++; -#endif /* COMPAT_HAS_NEW_PCI */ cs->irq_flags |= SA_SHIRQ; #else printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c index 57d99b43669c33e527f5bde421201552c9810e5d..cb999972cc2a56583f10f1dab0b82404fc559561 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.7 1999/08/22 20:26:55 calle Exp $ +/* $Id: bkm_a4t.c,v 1.8 1999/09/04 06:20:05 keil 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 @@ -7,6 +7,9 @@ * Author Roland Klabunde (R.Klabunde@Berkom.de) * * $Log: bkm_a4t.c,v $ + * Revision 1.8 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.7 1999/08/22 20:26:55 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -42,13 +45,10 @@ #include "isdnl1.h" #include "bkm_ax.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; -const char *bkm_a4t_revision = "$Revision: 1.7 $"; +const char *bkm_a4t_revision = "$Revision: 1.8 $"; static inline u_char @@ -231,11 +231,11 @@ reset_bkm(struct IsdnCardState *cs) sti(); /* Issue the I20 soft reset */ pI20_Regs->i20SysControl = 0xFF; /* all in */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); /* Remove the soft reset */ pI20_Regs->i20SysControl = sysRESET | 0xFF; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); /* Set our configuration */ pI20_Regs->i20SysControl = sysRESET | sysCFG; @@ -246,14 +246,14 @@ reset_bkm(struct IsdnCardState *cs) g_A4T_ISAC_RES | g_A4T_JADE_BOOTR | g_A4T_ISAR_BOOTR; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); /* Remove RESET state from ISDN */ pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | g_A4T_JADE_RES | g_A4T_ISAR_RES); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); restore_flags(flags); } @@ -288,23 +288,16 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return (0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_a4t __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init - setup_bkm_a4t(struct IsdnCard *card) +__initfunc(int + setup_bkm_a4t(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; u_int pci_memaddr = 0, found = 0; I20_REGISTER_FILE *pI20_Regs; #if CONFIG_PCI -#ifndef COMPAT_HAS_NEW_PCI - u_char pci_bus, pci_device_fn, pci_irq = 0; -#endif #endif strcpy(tmp, bkm_a4t_revision); @@ -315,7 +308,6 @@ int __init return (0); #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "bkm_a4t: no PCI bus present\n"); return (0); @@ -327,40 +319,14 @@ int __init &sub_sys_id); if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) { found = 1; - pci_memaddr = get_pcibase(dev_a4t, 0); + pci_memaddr = dev_a4t->resource[ 0].start; cs->irq = dev_a4t->irq; } } -#else - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(I20_VENDOR_ID, - I20_DEVICE_ID, - pci_index, - &pci_bus, - &pci_device_fn) == PCIBIOS_SUCCESSFUL) { - u_int sub_sys_id = 0; - - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id); - if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) { - found = 1; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - cs->irq = pci_irq; - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_memaddr); - break; - } - } - } -#endif /* COMPAT_HAS_NEW_PCI */ if (!found) { printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); return (0); } -#ifndef COMPAT_HAS_NEW_PCI - pci_index++; -#endif if (!cs->irq) { /* IRQ range check ?? */ printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]); return (0); diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c index e32c4544a65f3583a227acf550e4b058aa524bc3..fda6c213c0fb602c2cb8bcc0d829c4077631cd4d 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.7 1999/08/22 20:26:58 calle Exp $ +/* $Id: bkm_a8.c,v 1.8 1999/09/04 06:20:05 keil 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 @@ -7,6 +7,9 @@ * Author Roland Klabunde (R.Klabunde@Berkom.de) * * $Log: bkm_a8.c,v $ + * Revision 1.8 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.7 1999/08/22 20:26:58 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -41,15 +44,12 @@ #include "isdnl1.h" #include "bkm_ax.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */ extern const char *CardType[]; -const char sct_quadro_revision[] = "$Revision: 1.7 $"; +const char sct_quadro_revision[] = "$Revision: 1.8 $"; /* To survive the startup phase */ typedef struct { @@ -298,13 +298,13 @@ reset_bkm(struct IsdnCardState *cs) save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); /* Remove the soft reset */ wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4)); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); restore_flags(flags); } @@ -341,14 +341,10 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return (0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_a8 __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init - setup_sct_quadro(struct IsdnCard *card) +__initfunc(int + setup_sct_quadro(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; @@ -372,7 +368,6 @@ int __init printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n", CardType[card->typ]); #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "bkm_a4t: no PCI bus present\n"); return (0); @@ -384,46 +379,18 @@ int __init &sub_sys_id); if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) { found = 1; - pci_ioaddr1 = get_pcibase(dev_a8, 1); + pci_ioaddr1 = dev_a8->resource[ 1].start; pci_irq = dev_a8->irq; pci_bus = dev_a8->bus->number; pci_device_fn = dev_a8->devfn; } } -#else - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device( - PLX_VENDOR_ID, - PLX_DEVICE_ID, - pci_index, - &pci_bus, - &pci_device_fn) == PCIBIOS_SUCCESSFUL) { - - u_int sub_sys_id = 0; - - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id); - if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) { - found = 1; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr1); - cs->irq = pci_irq; - break; - } - } - } -#endif /* COMPAT_HAS_NEW_PCI */ if (!found) { printk(KERN_WARNING "HiSax: %s (%s): Card not found\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp]); return (0); } -#ifndef COMPAT_HAS_NEW_PCI - pci_index++; /* need for more as one card */ -#endif if (!pci_irq) { /* IRQ range check ?? */ printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n", CardType[card->typ], @@ -445,9 +412,7 @@ int __init pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; pcibios_write_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, pci_ioaddr1); -#ifdef COMPAT_HAS_NEW_PCI - get_pcibase(dev_a8, 1) = pci_ioaddr1; -#endif /* COMPAT_HAS_NEW_PCI */ + dev_a8->resource[ 1].start = pci_ioaddr1; } /* End HACK */ #endif diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index ce0428a46eaa295a4f0a31a2e19797f9a66b5b77..e4c26d9debd2c3a08aaf68b52d0f5c8c81333997 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 2.34 1999/08/25 20:02:34 werner Exp $ +/* $Id: callc.c,v 2.39 1999/10/14 20:25:28 keil Exp $ * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -11,6 +11,21 @@ * Fritz Elfert * * $Log: callc.c,v $ + * Revision 2.39 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * + * Revision 2.38 1999/10/11 22:16:27 keil + * Suspend/Resume is possible without explicit ID too + * + * Revision 2.37 1999/09/20 19:49:47 keil + * Fix wrong init of PStack + * + * Revision 2.36 1999/09/20 12:13:13 keil + * Fix hang if no protocol was selected + * + * Revision 2.35 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 2.34 1999/08/25 20:02:34 werner * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts * with existing software definitions. (PtP incomplete called party number) @@ -145,15 +160,10 @@ #include "../avmb1/capicmd.h" /* this should be moved in a common place */ #ifdef MODULE -#ifdef COMPAT_HAS_NEW_SYMTAB #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module)) -#else -extern long mod_use_count_; -#define MOD_USE_COUNT mod_use_count_ -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* MODULE */ -const char *lli_revision = "$Revision: 2.34 $"; +const char *lli_revision = "$Revision: 2.39 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -209,7 +219,7 @@ discard_queue(struct sk_buff_head *q) int ret=0; while ((skb = skb_dequeue(q))) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); ret++; } return(ret); @@ -1121,13 +1131,38 @@ dchan_l3l4(struct PStack *st, int pr, void *arg) } } +static void +dummy_pstack(struct PStack *st, int pr, void *arg) { + printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg); +} + +static void +init_PStack(struct PStack **stp) { + *stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC); + (*stp)->next = NULL; + (*stp)->l1.l1l2 = dummy_pstack; + (*stp)->l1.l1hw = dummy_pstack; + (*stp)->l1.l1tei = dummy_pstack; + (*stp)->l2.l2tei = dummy_pstack; + (*stp)->l2.l2l1 = dummy_pstack; + (*stp)->l2.l2l3 = dummy_pstack; + (*stp)->l3.l3l2 = dummy_pstack; + (*stp)->l3.l3ml3 = dummy_pstack; + (*stp)->l3.l3l4 = dummy_pstack; + (*stp)->lli.l4l3 = dummy_pstack; + (*stp)->ma.layer = dummy_pstack; +} + static void init_d_st(struct Channel *chanp) { - struct PStack *st = chanp->d_st; + struct PStack *st; struct IsdnCardState *cs = chanp->cs; char tmp[16]; + init_PStack(&chanp->d_st); + st = chanp->d_st; + st->next = NULL; HiSax_addlist(cs, st); setstack_HiSax(st, cs); st->l2.sap = 0; @@ -1165,28 +1200,6 @@ callc_debug(struct FsmInst *fi, char *fmt, ...) va_end(args); } -static void -dummy_pstack(struct PStack *st, int pr, void *arg) { - printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg); -} - -static void -init_PStack(struct PStack **stp) { - *stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC); - (*stp)->next = NULL; - (*stp)->l1.l1l2 = dummy_pstack; - (*stp)->l1.l1hw = dummy_pstack; - (*stp)->l1.l1tei = dummy_pstack; - (*stp)->l2.l2tei = dummy_pstack; - (*stp)->l2.l2l1 = dummy_pstack; - (*stp)->l2.l2l3 = dummy_pstack; - (*stp)->l3.l3l2 = dummy_pstack; - (*stp)->l3.l3ml3 = dummy_pstack; - (*stp)->l3.l3l4 = dummy_pstack; - (*stp)->lli.l4l3 = dummy_pstack; - (*stp)->ma.layer = dummy_pstack; -} - static void init_chan(int chan, struct IsdnCardState *csta) { @@ -1209,10 +1222,6 @@ init_chan(int chan, struct IsdnCardState *csta) FsmInitTimer(&chanp->fi, &chanp->dial_timer); FsmInitTimer(&chanp->fi, &chanp->drel_timer); if (!chan || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { - init_PStack(&chanp->d_st); - if (chan) - csta->channel->d_st->next = chanp->d_st; - chanp->d_st->next = NULL; init_d_st(chanp); } else { chanp->d_st = csta->channel->d_st; @@ -1289,7 +1298,7 @@ lldata_handler(struct PStack *st, int pr, void *arg) if (chanp->data_open) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } break; case (DL_ESTABLISH | INDICATION): @@ -1319,7 +1328,7 @@ lltrans_handler(struct PStack *st, int pr, void *arg) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { link_debug(chanp, 0, "channel not open"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } break; case (PH_ACTIVATE | INDICATION): @@ -1426,7 +1435,7 @@ leased_l4l3(struct PStack *st, int pr, void *arg) switch (pr) { case (DL_DATA | REQUEST): link_debug(chanp, 0, "leased line d-channel DATA"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); break; case (DL_ESTABLISH | REQUEST): st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); @@ -1450,7 +1459,7 @@ leased_l1l2(struct PStack *st, int pr, void *arg) switch (pr) { case (PH_DATA | INDICATION): link_debug(chanp, 0, "leased line d-channel DATA"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); break; case (PH_ACTIVATE | INDICATION): case (PH_ACTIVATE | CONFIRM): @@ -1474,11 +1483,6 @@ leased_l1l2(struct PStack *st, int pr, void *arg) } } -static void -channel_report(struct Channel *chanp) -{ -} - static void distr_debug(struct IsdnCardState *csta, int debugflags) { @@ -1512,7 +1516,6 @@ capi_debug(struct Channel *chanp, capi_msg *cm) { char *t = tmpbuf; - t += sprintf(tmpbuf, "%d CAPIMSG", chanp->chan); t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length); t--; *t= 0; @@ -1529,20 +1532,16 @@ lli_got_fac_req(struct Channel *chanp, capi_msg *cm) { return; switch(cm->para[3]) { case 4: /* Suspend */ - if (cm->para[5]) { - strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); - FsmEvent(&chanp->fi, EV_SUSPEND, cm); - } + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + FsmEvent(&chanp->fi, EV_SUSPEND, cm); break; case 5: /* Resume */ - if (cm->para[5]) { - strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); - if (chanp->fi.state == ST_NULL) { - FsmEvent(&chanp->fi, EV_RESUME, cm); - } else { - FsmDelTimer(&chanp->dial_timer, 72); - FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73); - } + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + if (chanp->fi.state == ST_NULL) { + FsmEvent(&chanp->fi, EV_RESUME, cm); + } else { + FsmDelTimer(&chanp->dial_timer, 72); + FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73); } break; } @@ -1694,9 +1693,8 @@ HiSax_command(isdn_ctrl * ic) case (ISDN_CMD_IOCTL): switch (ic->arg) { case (0): - HiSax_reportcard(csta->cardnr); - for (i = 0; i < 2; i++) - channel_report(&csta->channel[i]); + num = *(unsigned int *) ic->parm.num; + HiSax_reportcard(csta->cardnr, num); break; case (1): num = *(unsigned int *) ic->parm.num; @@ -1904,7 +1902,7 @@ HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb) chanp->bcs->tx_cnt += len; st->l2.l2l1(st, PH_DATA | REQUEST, nskb); } - idev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb(skb); } else len = 0; restore_flags(flags); diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index dc0fa46a00a593ccb5268bdccce0799243d240d6..a75810f026ace717519b873de53b8ec4f7f3919d 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1,10 +1,32 @@ -/* $Id: config.c,v 2.33 1999/08/30 11:57:52 keil Exp $ +/* $Id: config.c,v 2.40 1999/10/30 13:09:45 keil Exp $ * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * * * $Log: config.c,v $ + * Revision 2.40 1999/10/30 13:09:45 keil + * Version 3.3c + * + * Revision 2.39 1999/10/16 14:44:45 keil + * Fix module parm if only NICCY was selected + * + * Revision 2.38 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * + * Revision 2.37 1999/09/20 12:11:08 keil + * Fix hang if no protocol was selected + * + * Revision 2.36 1999/09/07 05:43:58 werner + * + * Added io as parameter 0 for HFC-PCI cards, if manual selection needed. + * + * Revision 2.35 1999/09/04 06:35:09 keil + * Winbond W6692 support + * + * Revision 2.34 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 2.33 1999/08/30 11:57:52 keil * Fix broken avm pcmcia * @@ -126,10 +148,7 @@ #include <linux/stddef.h> #include <linux/timer.h> #include <linux/config.h> -#include <linux/isdn_compat.h> -#ifdef COMPAT_HAS_NEW_SETUP #include <linux/init.h> -#endif #include "hisax.h" #include <linux/module.h> #include <linux/kernel_stat.h> @@ -182,6 +201,8 @@ * 33 Scitel Quadro p0=subcontroller (4*S0, subctrl 1...4) * 34 Gazel ISDN cards * 35 HFC 2BDS0 PCI none + * 36 Winbond 6692 PCI none + * * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1 * * @@ -195,7 +216,7 @@ const char *CardType[] = "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)", "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI", "Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir", - "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", + "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692", }; void HiSax_closecard(int cardnr); @@ -204,15 +225,7 @@ void HiSax_closecard(int cardnr); #define DEFAULT_CARD ISDN_CTYPE_ELSA #define DEFAULT_CFG {0,0,0,0} int elsa_init_pcmcia(void*, int, int*, int); -#ifdef COMPAT_HAS_NEW_SYMTAB EXPORT_SYMBOL(elsa_init_pcmcia); -#else -static struct symbol_table hisax_syms_elsa = { -#include <linux/symtab_begin.h> - X(elsa_init_pcmcia), -#include <linux/symtab_end.h> -}; -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* CONFIG_HISAX_ELSA */ #ifdef CONFIG_HISAX_AVM_A1 @@ -228,17 +241,8 @@ static struct symbol_table hisax_syms_elsa = { #define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA #define DEFAULT_CFG {11,0x170,0,0} int avm_a1_init_pcmcia(void*, int, int*, int); -#ifdef COMPAT_HAS_NEW_SYMTAB EXPORT_SYMBOL(avm_a1_init_pcmcia); EXPORT_SYMBOL(HiSax_closecard); -#else -static struct symbol_table hisax_syms_avm_a1= { -#include <linux/symtab_begin.h> - X(avm_a1_init_pcmcia), - X(HiSax_closecard), -#include <linux/symtab_end.h> -}; -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* CONFIG_HISAX_AVM_A1_PCMCIA */ #ifdef CONFIG_HISAX_FRITZPCI @@ -310,15 +314,7 @@ static struct symbol_table hisax_syms_avm_a1= { #define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER #define DEFAULT_CFG {11,0x270,0,0} int sedl_init_pcmcia(void*, int, int*, int); -#ifdef COMPAT_HAS_NEW_SYMTAB EXPORT_SYMBOL(sedl_init_pcmcia); -#else -static struct symbol_table hisax_syms_sedl= { -#include <linux/symtab_begin.h> - X(sedl_init_pcmcia), -#include <linux/symtab_end.h> -}; -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* CONFIG_HISAX_SEDLBAUER */ #ifdef CONFIG_HISAX_SPORTSTER @@ -406,6 +402,13 @@ static struct symbol_table hisax_syms_sedl= { #define DEFAULT_CFG {15,0x180,0,0} #endif +#ifdef CONFIG_HISAX_W6692 +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_W6692 +#define DEFAULT_CFG {0,0,0,0} +#endif + #ifdef CONFIG_HISAX_1TR6 #define DEFAULT_PROTO ISDN_PTYPE_1TR6 #define DEFAULT_PROTO_NAME "1TR6" @@ -483,7 +486,6 @@ static int mem[] HISAX_INITDATA = {0, 0, 0, 0, 0, 0, 0, 0}; static char *id HISAX_INITDATA = HiSaxID; -#ifdef COMPAT_HAS_NEW_SYMTAB MODULE_AUTHOR("Karsten Keil"); MODULE_PARM(type, "1-8i"); MODULE_PARM(protocol, "1-8i"); @@ -491,11 +493,10 @@ MODULE_PARM(io, "1-8i"); MODULE_PARM(irq, "1-8i"); MODULE_PARM(mem, "1-8i"); MODULE_PARM(id, "s"); -#ifdef CONFIG_HISAX_16_3 /* For Creatix/Teles PnP */ +#ifdef IO0_IO1 MODULE_PARM(io0, "1-8i"); MODULE_PARM(io1, "1-8i"); -#endif /* CONFIG_HISAX_16_3 */ -#endif /* COMPAT_HAS_NEW_SYMTAB */ +#endif /* IO0_IO1 */ #endif /* MODULE */ int nrcards; @@ -528,9 +529,9 @@ HiSaxVersion(void)) printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n"); #ifdef MODULE - printk(KERN_INFO "HiSax: Version 3.3a (module)\n"); + printk(KERN_INFO "HiSax: Version 3.3c (module)\n"); #else - printk(KERN_INFO "HiSax: Version 3.3a (kernel)\n"); + printk(KERN_INFO "HiSax: Version 3.3c (kernel)\n"); #endif strcpy(tmp, l1_revision); printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp)); @@ -560,7 +561,6 @@ HiSax_mod_inc_use_count(void) #ifdef MODULE #define HiSax_init init_module #else -#ifdef COMPAT_HAS_NEW_SETUP #define MAX_ARG (HISAX_MAX_CARDS*5) static int __init HiSax_setup(char *line) @@ -570,12 +570,6 @@ HiSax_setup(char *line) char *str; str = get_options(line, MAX_ARG, ints); -#else -void __init -HiSax_setup(char *str, int *ints) -{ - int i, j, argc; -#endif argc = ints[0]; printk(KERN_DEBUG"HiSax_setup: argc(%d) str(%s)\n", argc, str); i = 0; @@ -615,14 +609,10 @@ HiSax_setup(char *str, int *ints) strcpy(HiSaxID, "HiSax"); HiSax_id = HiSaxID; } -#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("hisax=", HiSax_setup); -#else -} -#endif /* COMPAT_HAS_NEW_SETUP */ #endif /* MODULES */ #if CARD_TELES0 @@ -717,11 +707,11 @@ extern int setup_saphir(struct IsdnCard *card); extern int setup_testemu(struct IsdnCard *card); #endif -#if CARD_BKM_A4T +#if CARD_BKM_A4T extern int setup_bkm_a4t(struct IsdnCard *card); #endif -#if CARD_SCT_QUADRO +#if CARD_SCT_QUADRO extern int setup_sct_quadro(struct IsdnCard *card); #endif @@ -729,6 +719,10 @@ extern int setup_sct_quadro(struct IsdnCard *card); extern int setup_gazel(struct IsdnCard *card); #endif +#if CARD_W6692 +extern int setup_w6692(struct IsdnCard *card); +#endif + /* * Find card with given driverId */ @@ -967,7 +961,7 @@ closecard(int cardnr) csta->rcvbuf = NULL; } if (csta->tx_skb) { - idev_kfree_skb(csta->tx_skb, FREE_WRITE); + dev_kfree_skb(csta->tx_skb); csta->tx_skb = NULL; } if (csta->DC_Close != NULL) { @@ -1000,7 +994,7 @@ HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs)) while (cnt) { cs->cardmsg(cs, CARD_INIT, NULL); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); /* Timeout 10ms */ schedule_timeout((10*HZ)/1000); restore_flags(flags); @@ -1253,6 +1247,11 @@ checkcard(int cardnr, char *id, int *busy_flag)) case ISDN_CTYPE_GAZEL: ret = setup_gazel(card); break; +#endif +#if CARD_W6692 + case ISDN_CTYPE_W6692: + ret = setup_w6692(card); + break; #endif default: printk(KERN_WARNING @@ -1357,6 +1356,7 @@ HiSax_inithardware(int *busy_flag)) kfree((void *) cards[i].cs); cards[i].cs = NULL; HiSax_shiftcards(i); + nrcards--; } } return foundcards; @@ -1387,12 +1387,9 @@ HiSax_closecard(int cardnr) } void -HiSax_reportcard(int cardnr) +HiSax_reportcard(int cardnr, int sel) { struct IsdnCardState *cs = cards[cardnr].cs; - struct PStack *stptr; - struct l3_process *pc; - int j, i = 1; printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1); printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]); @@ -1400,50 +1397,38 @@ HiSax_reportcard(int cardnr) printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n", (ulong) & HiSax_reportcard); printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs); - printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc0 flg %x\n", + printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc1 flg %x\n", cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag); printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n", cs->bcs[0].mode, cs->bcs[0].channel); printk(KERN_DEBUG "HiSax: bcs 1 mode %d ch%d\n", cs->bcs[1].mode, cs->bcs[1].channel); - printk(KERN_DEBUG "HiSax: cs setstack_d 0x%lX\n", (ulong) cs->setstack_d); - printk(KERN_DEBUG "HiSax: cs stl 0x%lX\n", (ulong) & (cs->stlist)); - stptr = cs->stlist; - while (stptr != NULL) { - printk(KERN_DEBUG "HiSax: dst%d 0x%lX\n", i, (ulong) stptr); - printk(KERN_DEBUG "HiSax: dst%d stp 0x%lX\n", i, (ulong) stptr->l1.stlistp); - printk(KERN_DEBUG "HiSax: dst%d l1.l1hw 0x%lX\n", i, (ulong) stptr->l1.l1hw); - printk(KERN_DEBUG "HiSax: tei %d sapi %d\n", - stptr->l2.tei, stptr->l2.sap); - printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer); - pc = stptr->l3.proc; - while (pc) { - printk(KERN_DEBUG "HiSax: l3proc %x 0x%lX\n", pc->callref, - (ulong) pc); - printk(KERN_DEBUG "HiSax: state %d st 0x%lX chan 0x%lX\n", - pc->state, (ulong) pc->st, (ulong) pc->chan); - pc = pc->next; - } - stptr = stptr->next; - i++; - } - for (j = 0; j < 2; j++) { - printk(KERN_DEBUG "HiSax: ch%d 0x%lX\n", j, - (ulong) & cs->channel[j]); - stptr = cs->channel[j].b_st; - i = 1; - while (stptr != NULL) { - printk(KERN_DEBUG "HiSax: b_st%d 0x%lX\n", i, (ulong) stptr); - printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer); - stptr = stptr->next; - i++; - } +#ifdef ERROR_STATISTIC + printk(KERN_DEBUG "HiSax: dc errors(rx,crc,tx) %d,%d,%d\n", + cs->err_rx, cs->err_crc, cs->err_tx); + printk(KERN_DEBUG "HiSax: bc0 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n", + cs->bcs[0].err_inv, cs->bcs[0].err_rdo, cs->bcs[0].err_crc, cs->bcs[0].err_tx); + printk(KERN_DEBUG "HiSax: bc1 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n", + cs->bcs[1].err_inv, cs->bcs[1].err_rdo, cs->bcs[1].err_crc, cs->bcs[1].err_tx); + if (sel == 99) { + cs->err_rx = 0; + cs->err_crc = 0; + cs->err_tx = 0; + cs->bcs[0].err_inv = 0; + cs->bcs[0].err_rdo = 0; + cs->bcs[0].err_crc = 0; + cs->bcs[0].err_tx = 0; + cs->bcs[1].err_inv = 0; + cs->bcs[1].err_rdo = 0; + cs->bcs[1].err_crc = 0; + cs->bcs[1].err_tx = 0; } +#endif } -int __init -HiSax_init(void) +__initfunc(int +HiSax_init(void)) { int i; @@ -1452,27 +1437,18 @@ HiSax_init(void) #ifdef CONFIG_HISAX_ELSA if (type[0] == ISDN_CTYPE_ELSA_PCMCIA) { /* we have exported and return in this case */ -#ifndef COMPAT_HAS_NEW_SYMTAB - register_symtab(&hisax_syms_elsa); -#endif return 0; } #endif #ifdef CONFIG_HISAX_SEDLBAUER if (type[0] == ISDN_CTYPE_SEDLBAUER_PCMCIA) { /* we have to export and return in this case */ -#ifndef COMPAT_HAS_NEW_SYMTAB - register_symtab(&hisax_syms_sedl); -#endif return 0; } #endif #ifdef CONFIG_HISAX_AVM_A1_PCMCIA if (type[0] == ISDN_CTYPE_A1_PCMCIA) { /* we have to export and return in this case */ -#ifndef COMPAT_HAS_NEW_SYMTAB - register_symtab(&hisax_syms_avm_a1); -#endif return 0; } #endif @@ -1515,6 +1491,7 @@ HiSax_init(void) break; #endif case ISDN_CTYPE_ELSA: + case ISDN_CTYPE_HFC_PCI: cards[i].para[0] = io[i]; break; case ISDN_CTYPE_16_3: @@ -1550,6 +1527,7 @@ HiSax_init(void) case ISDN_CTYPE_NETJET: case ISDN_CTYPE_AMD7930: case ISDN_CTYPE_TELESPCI: + case ISDN_CTYPE_W6692: break; case ISDN_CTYPE_BKM_A4T: break; @@ -1582,11 +1560,6 @@ HiSax_init(void) if (HiSax_inithardware(NULL)) { /* Install only, if at least one card found */ #ifdef MODULE -#ifndef COMPAT_HAS_NEW_SYMTAB - /* No symbols to export, hide all symbols */ - register_symtab(NULL); - printk(KERN_INFO "HiSax: module installed\n"); -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* MODULE */ return (0); } else { @@ -1629,9 +1602,7 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) nrcards = 0; HiSaxVersion(); - if (id) /* If id= string used */ - HiSax_id = id; - /* Initialize all 8 structs, even though we only accept + /* Initialize all structs, even though we only accept two pcmcia cards */ for (i = 0; i < HISAX_MAX_CARDS; i++) { @@ -1680,9 +1651,7 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) nrcards = 0; HiSaxVersion(); - if (id) /* If id= string used */ - HiSax_id = id; - /* Initialize all 8 structs, even though we only accept + /* Initialize all structs, even though we only accept two pcmcia cards */ for (i = 0; i < HISAX_MAX_CARDS; i++) { @@ -1731,12 +1700,10 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) nrcards = 0; HiSaxVersion(); - if (id) /* If id= string used */ - HiSax_id = id; - /* Initialize all 16 structs, even though we only accept + /* Initialize all structs, even though we only accept two pcmcia cards */ - for (i = 0; i < 16; i++) { + for (i = 0; i < HISAX_MAX_CARDS; i++) { cards[i].para[0] = irq[i]; cards[i].para[1] = io[i]; cards[i].typ = type[i]; diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 8ec1a536c8ed0de3c1533932df4fa780a15e125b..f1161e63de6a3d20a30e54f1ae56f27f2b5165ed 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -1,4 +1,4 @@ -/* $Id: diva.c,v 1.16 1999/08/11 21:01:25 keil Exp $ +/* $Id: diva.c,v 1.17 1999/09/04 06:20:06 keil Exp $ * diva.c low level stuff for Eicon.Diehl Diva Family ISDN cards * @@ -12,6 +12,9 @@ * * * $Log: diva.c,v $ + * Revision 1.17 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.16 1999/08/11 21:01:25 keil * new PCI codefix * @@ -74,13 +77,10 @@ #include "ipac.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; -const char *Diva_revision = "$Revision: 1.16 $"; +const char *Diva_revision = "$Revision: 1.17 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -550,7 +550,6 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "HSCX: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -566,7 +565,6 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (!(skb = dev_alloc_skb(fifo_size))) printk(KERN_WARNING "HiSax: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); skb_queue_tail(&bcs->rqueue, skb); } @@ -583,7 +581,7 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.hscx.count = 0; bcs->tx_skb = NULL; } @@ -752,30 +750,30 @@ reset_diva(struct IsdnCardState *cs) sti(); if (cs->subtyp == DIVA_IPAC_ISA) { writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); } else if (cs->subtyp == DIVA_IPAC_PCI) { unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + PITA_MISC_REG); *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); *ireg = PITA_PARA_MPX_MODE; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); } else { /* DIVA 2.0 */ cs->hw.diva.ctrl_reg = 0; /* Reset On */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); if (cs->subtyp == DIVA_ISA) cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; @@ -880,16 +878,12 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_diva __initdata = NULL; static struct pci_dev *dev_diva_u __initdata = NULL; static struct pci_dev *dev_diva201 __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_diva(struct IsdnCard *card) +__initfunc(int +setup_diva(struct IsdnCard *card)) { int bytecnt; u_char val; @@ -927,7 +921,6 @@ setup_diva(struct IsdnCard *card) bytecnt = 8; } else { #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Diva: no PCI bus present\n"); return(0); @@ -938,23 +931,23 @@ setup_diva(struct IsdnCard *card) PCI_DIVA20_ID, dev_diva))) { cs->subtyp = DIVA_PCI; cs->irq = dev_diva->irq; - cs->hw.diva.cfg_reg = get_pcibase(dev_diva, 2) + cs->hw.diva.cfg_reg = dev_diva->resource[ 2].start & PCI_BASE_ADDRESS_IO_MASK; } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA20_U_ID, dev_diva_u))) { cs->subtyp = DIVA_PCI; cs->irq = dev_diva_u->irq; - cs->hw.diva.cfg_reg = get_pcibase(dev_diva_u, 2) + cs->hw.diva.cfg_reg = dev_diva_u->resource[ 2].start & PCI_BASE_ADDRESS_IO_MASK; } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA_201, dev_diva201))) { cs->subtyp = DIVA_IPAC_PCI; cs->irq = dev_diva201->irq; cs->hw.diva.pci_cfg = - (ulong) ioremap((get_pcibase(dev_diva201, 0) + (ulong) ioremap((dev_diva201->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK), 4096); cs->hw.diva.cfg_reg = - (ulong) ioremap((get_pcibase(dev_diva201, 1) + (ulong) ioremap((dev_diva201->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK), 4096); } else { printk(KERN_WARNING "Diva: No PCI card found\n"); @@ -970,66 +963,6 @@ setup_diva(struct IsdnCard *card) printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); return(0); } -#else - u_char pci_bus, pci_device_fn, pci_irq; - u_int pci_ioaddr; - - cs->subtyp = 0; - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, - PCI_DIVA20_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = DIVA_PCI; - else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, - PCI_DIVA20_U_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = DIVA_PCI; - else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, - PCI_DIVA_201, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = DIVA_IPAC_PCI; - else - break; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - /* get IO address */ - if (cs->subtyp == DIVA_IPAC_PCI) { - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - cs->hw.diva.pci_cfg = (ulong) ioremap(pci_ioaddr, - 4096); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr); - cs->hw.diva.cfg_reg = (ulong) ioremap(pci_ioaddr, - 4096); - } else { - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr); - cs->hw.diva.pci_cfg = pci_ioaddr & ~3; - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_2, &pci_ioaddr); - cs->hw.diva.cfg_reg = pci_ioaddr & ~3; - } - if (cs->subtyp) - break; - } - if (!cs->subtyp) { - printk(KERN_WARNING "Diva: No PCI card found\n"); - return(0); - } - pci_index++; - if (!pci_irq) { - printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); - return(0); - } - if (!pci_ioaddr) { - printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); - return(0); - } - cs->irq = pci_irq; -#endif /* COMPAT_HAS_NEW_PCI */ cs->irq_flags |= SA_SHIRQ; #else printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n"); diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index c2d6cf2d385272d18518e7d67f9a90fd822444e3..4dbe40c38462044cdd0555207ccea55bd2938be0 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -1,4 +1,4 @@ -/* $Id: elsa.c,v 2.18 1999/08/25 16:50:54 keil Exp $ +/* $Id: elsa.c,v 2.19 1999/09/04 06:20:06 keil Exp $ * elsa.c low level stuff for Elsa isdn cards * @@ -14,6 +14,9 @@ * for ELSA PCMCIA support * * $Log: elsa.c,v $ + * Revision 2.19 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 2.18 1999/08/25 16:50:54 keil * Fix bugs which cause 2.3.14 hangs (waitqueue init) * @@ -91,15 +94,12 @@ #include "hscx.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #include <linux/serial.h> #include <linux/serial_reg.h> extern const char *CardType[]; -const char *Elsa_revision = "$Revision: 2.18 $"; +const char *Elsa_revision = "$Revision: 2.19 $"; const char *Elsa_Types[] = {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI", @@ -578,10 +578,10 @@ reset_elsa(struct IsdnCardState *cs) save_flags(flags); sti(); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ restore_flags(flags); @@ -785,7 +785,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) cs->hw.elsa.status |= ELSA_TIMER_AKTIV; byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); byteout(cs->hw.elsa.timer, 0); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((110*HZ)/1000); restore_flags(flags); cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; @@ -928,12 +928,8 @@ probe_elsa(struct IsdnCardState *cs) return (CARD_portlist[i]); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_qs1000 __initdata = NULL; static struct pci_dev *dev_qs3000 __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif int setup_elsa(struct IsdnCard *card) @@ -1051,7 +1047,6 @@ setup_elsa(struct IsdnCard *card) cs->irq); } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Elsa: no PCI bus present\n"); return(0); @@ -1061,17 +1056,17 @@ setup_elsa(struct IsdnCard *card) dev_qs1000))) { cs->subtyp = ELSA_QS1000PCI; cs->irq = dev_qs1000->irq; - cs->hw.elsa.cfg = get_pcibase(dev_qs1000, 1) & + cs->hw.elsa.cfg = dev_qs1000->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; - cs->hw.elsa.base = get_pcibase(dev_qs1000, 3) & + cs->hw.elsa.base = dev_qs1000->resource[ 3].start & PCI_BASE_ADDRESS_IO_MASK; } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ELSA, PCI_QS3000_ID, dev_qs3000))) { cs->subtyp = ELSA_QS3000PCI; cs->irq = dev_qs3000->irq; - cs->hw.elsa.cfg = get_pcibase(dev_qs3000, 1) & + cs->hw.elsa.cfg = dev_qs3000->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; - cs->hw.elsa.base = get_pcibase(dev_qs3000, 3) & + cs->hw.elsa.base = dev_qs3000->resource[ 3].start & PCI_BASE_ADDRESS_IO_MASK; } else { printk(KERN_WARNING "Elsa: No PCI card found\n"); @@ -1096,54 +1091,6 @@ setup_elsa(struct IsdnCard *card) HZDELAY(500); /* wait 500*10 ms */ restore_flags(flags); } -#else - u_char pci_bus, pci_device_fn, pci_irq; - u_int pci_ioaddr; - - cs->subtyp = 0; - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(PCI_VENDOR_ELSA, - PCI_QS1000_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = ELSA_QS1000PCI; - else if (pcibios_find_device(PCI_VENDOR_ELSA, - PCI_QS3000_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = ELSA_QS3000PCI; - else - break; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - /* get IO address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr); - pci_ioaddr &= ~3; /* remove io/mem flag */ - cs->hw.elsa.cfg = pci_ioaddr; - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_3, &pci_ioaddr); - if (cs->subtyp) - break; - } - if (!cs->subtyp) { - printk(KERN_WARNING "Elsa: No PCI card found\n"); - return(0); - } - pci_index++; - if (!pci_irq) { - printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); - return(0); - } - - if (!pci_ioaddr) { - printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); - return(0); - } - pci_ioaddr &= ~3; /* remove io/mem flag */ - cs->hw.elsa.base = pci_ioaddr; - cs->irq = pci_irq; -#endif /* COMPAT_HAS_NEW_PCI */ cs->hw.elsa.ale = cs->hw.elsa.base; cs->hw.elsa.isac = cs->hw.elsa.base +1; cs->hw.elsa.hscx = cs->hw.elsa.base +1; diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c index e4b35e50290098e98a01132d150c070225861e75..529a748151698d9b20da88a8c5108c0b87a0c85f 100644 --- a/drivers/isdn/hisax/elsa_ser.c +++ b/drivers/isdn/hisax/elsa_ser.c @@ -298,7 +298,7 @@ modem_fill(struct BCState *bcs) { (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; } } @@ -389,74 +389,6 @@ static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done) } } -#if 0 -static inline void check_modem_status(struct IsdnCardState *cs) -{ - int status; - struct async_struct *info = cs->hw.elsa.info; - struct async_icount *icount; - - status = serial_inp(info, UART_MSR); - - if (status & UART_MSR_ANY_DELTA) { - icount = &info->state->icount; - /* update input line counters */ - if (status & UART_MSR_TERI) - icount->rng++; - if (status & UART_MSR_DDSR) - icount->dsr++; - if (status & UART_MSR_DDCD) { - icount->dcd++; - } - if (status & UART_MSR_DCTS) - icount->cts++; -// wake_up_interruptible(&info->delta_msr_wait); - } - - if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { -#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) - printk("ttys%d CD now %s...", info->line, - (status & UART_MSR_DCD) ? "on" : "off"); -#endif - if (status & UART_MSR_DCD) -// wake_up_interruptible(&info->open_wait); -; - else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_CALLOUT_NOHUP))) { -#ifdef SERIAL_DEBUG_OPEN - printk("doing serial hangup..."); -#endif - if (info->tty) - tty_hangup(info->tty); - } - } -#if 0 - if (info->flags & ASYNC_CTS_FLOW) { - if (info->tty->hw_stopped) { - if (status & UART_MSR_CTS) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx start..."); -#endif - info->tty->hw_stopped = 0; - info->IER |= UART_IER_THRI; - serial_outp(info, UART_IER, info->IER); -// rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - return; - } - } else { - if (!(status & UART_MSR_CTS)) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx stop..."); -#endif - info->tty->hw_stopped = 1; - info->IER &= ~UART_IER_THRI; - serial_outp(info, UART_IER, info->IER); - } - } - } -#endif 0 -} -#endif static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs) { @@ -510,13 +442,13 @@ close_elsastate(struct BCState *bcs) bcs->hw.hscx.rcvbuf = NULL; } while ((skb = skb_dequeue(&bcs->rqueue))) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } while ((skb = skb_dequeue(&bcs->squeue))) { - idev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb(skb); } if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c index ef64a4702dff4a4ceb27a2ef52c991314e2479cb..c104253c7ca08fc90c30fe11ad9b9a144fcec255 100644 --- a/drivers/isdn/hisax/gazel.c +++ b/drivers/isdn/hisax/gazel.c @@ -37,9 +37,6 @@ #include "isdnl1.h" #include "ipac.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; const char *gazel_revision = "$Revision: 2.6 $"; @@ -573,11 +570,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) return (0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_tel __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif static int setup_gazelpci(struct IsdnCardState *cs) @@ -589,42 +582,19 @@ setup_gazelpci(struct IsdnCardState *cs) printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); found = 0; -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_WARNING "Gazel: No PCI bus present\n"); return 1; } -#endif seekcard = GAZEL_R685; for (nbseek = 0; nbseek < 3; nbseek++) { -#ifdef COMPAT_HAS_NEW_PCI if ((dev_tel = pci_find_device(GAZEL_MANUFACTURER, seekcard, dev_tel))) { pci_irq = dev_tel->irq; - pci_ioaddr0 = get_pcibase(dev_tel, 1); - pci_ioaddr1 = get_pcibase(dev_tel, 2); + pci_ioaddr0 = dev_tel->resource[ 1].start; + pci_ioaddr1 = dev_tel->resource[ 2].start; found = 1; } -#else - for (; pci_index < 0xff; pci_index++) { - u_char pci_bus, pci_device_fn; - - if (pcibios_find_device(GAZEL_MANUFACTURER, seekcard, - pci_index, &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) - break; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - /* get IO address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr0); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_2, &pci_ioaddr1); - found = 1; - break; - } -#endif /* COMPAT_HAS_NEW_PCI */ if (found) break; else { @@ -636,9 +606,6 @@ setup_gazelpci(struct IsdnCardState *cs) seekcard = GAZEL_DJINN_ITOO; break; } -#ifndef COMPAT_HAS_NEW_PCI - pci_index = 0; -#endif } } if (!found) { @@ -690,8 +657,8 @@ setup_gazelpci(struct IsdnCardState *cs) return (0); } -int __init - setup_gazel(struct IsdnCard *card) +__initfunc(int + setup_gazel(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index 266916c39af4d4bab5db7a72c39841a043d63ab0..bb388c5c28c742795d6c1b6d4eda5df3efdcb054 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.c,v 1.9 1999/07/01 08:11:35 keil Exp $ +/* $Id: hfc_2bds0.c,v 1.10 1999/10/14 20:25:28 keil Exp $ * * specific routines for CCD's HFC 2BDS0 * @@ -6,6 +6,9 @@ * * * $Log: hfc_2bds0.c,v $ + * Revision 1.10 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * * Revision 1.9 1999/07/01 08:11:35 keil * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel * @@ -260,6 +263,9 @@ static struct sk_buff if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfc_empty_fifo: incoming packet too small"); cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif cli(); while ((idx++ < count) && WaitNoBusy(cs)) ReadReg(cs, HFCD_DATA_NODEB, cip); @@ -267,7 +273,6 @@ static struct sk_buff } else if (!(skb = dev_alloc_skb(count - 3))) printk(KERN_WARNING "HFC: receive out of memory\n"); else { - SET_SKB_FREE(skb); ptr = skb_put(skb, count - 3); idx = 0; cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); @@ -285,7 +290,7 @@ static struct sk_buff sti(); debugl1(cs, "RFIFO BUSY error"); printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; } else { cli(); @@ -301,8 +306,11 @@ static struct sk_buff bcs->channel, chksum, stat); if (stat) { debugl1(cs, "FIFO CRC error"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; +#ifdef ERROR_STATISTIC + bcs->err_crc++; +#endif } } } @@ -390,7 +398,7 @@ hfc_fill_fifo(struct BCState *bcs) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; } WaitForBusy(cs); @@ -592,7 +600,7 @@ close_2bs0(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -634,17 +642,6 @@ hfcd_bh(struct IsdnCardState *cs) */ if (!cs) return; -#if 0 - if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { - if (cs->debug) - debugl1(cs, "D-Channel Busy cleared"); - stptr = cs->stlist; - while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); - stptr = stptr->next; - } - } -#endif if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { switch (cs->dc.hfcd.ph_state) { case (0): @@ -737,7 +734,6 @@ int receive_dmsg(struct IsdnCardState *cs) while ((idx++ < rcnt) && WaitNoBusy(cs)) ReadReg(cs, HFCD_DATA_NODEB, cip); } else if ((skb = dev_alloc_skb(rcnt - 3))) { - SET_SKB_FREE(skb); ptr = skb_put(skb, rcnt - 3); while (idx < (rcnt - 3)) { cli(); @@ -752,8 +748,11 @@ int receive_dmsg(struct IsdnCardState *cs) sti(); debugl1(cs, "RFIFO D BUSY error"); printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; +#ifdef ERROR_STATISTIC + cs->err_rx++; +#endif } else { cli(); WaitNoBusy(cs); @@ -768,8 +767,11 @@ int receive_dmsg(struct IsdnCardState *cs) chksum, stat); if (stat) { debugl1(cs, "FIFO CRC error"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; +#ifdef ERROR_STATISTIC + cs->err_crc++; +#endif } else { skb_queue_tail(&cs->rq, skb); sched_event_D(cs, D_RCVBUFREADY); @@ -865,7 +867,7 @@ hfc_fill_dfifo(struct IsdnCardState *cs) cli(); WaitNoBusy(cs); ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND); - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_skb = NULL; sti(); WaitForBusy(cs); @@ -999,7 +1001,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val) } goto afterXPR; } else { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } @@ -1114,32 +1116,6 @@ HFCD_l1hw(struct PStack *st, int pr, void *arg) cs->hw.hfcD.mst_m |= HFCD_MASTER; cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); break; -#if 0 - case (HW_TESTLOOP | REQUEST): - u_char val = 0; - if (1 & (int) arg) - val |= 0x0c; - if (2 & (int) arg) - val |= 0x3; - if (test_bit(HW_IOM1, &cs->HW_Flags)) { - /* IOM 1 Mode */ - if (!val) { - cs->writeisac(cs, ISAC_SPCR, 0xa); - cs->writeisac(cs, ISAC_ADF1, 0x2); - } else { - cs->writeisac(cs, ISAC_SPCR, val); - cs->writeisac(cs, ISAC_ADF1, 0xa); - } - } else { - /* IOM 2 Mode */ - cs->writeisac(cs, ISAC_SPCR, val); - if (val) - cs->writeisac(cs, ISAC_ADF1, 0x8); - else - cs->writeisac(cs, ISAC_ADF1, 0x0); - } - break; -#endif default: if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcd_l1hw unknown pr %4x", pr); @@ -1156,24 +1132,10 @@ setstack_hfcd(struct PStack *st, struct IsdnCardState *cs) static void hfc_dbusy_timer(struct IsdnCardState *cs) { -#if 0 - struct PStack *stptr; - if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - if (cs->debug) - debugl1(cs, "D-Channel Busy"); - test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); - stptr = cs->stlist; - - while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); - stptr = stptr->next; - } - } -#endif } -unsigned int * __init -init_send_hfcd(int cnt) +__initfunc(unsigned int +*init_send_hfcd(int cnt)) { int i, *send; @@ -1187,8 +1149,8 @@ init_send_hfcd(int cnt) return(send); } -void __init -init2bds0(struct IsdnCardState *cs) +__initfunc(void +init2bds0(struct IsdnCardState *cs)) { cs->setstack_d = setstack_hfcd; cs->dbusytimer.function = (void *) hfc_dbusy_timer; diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c index 71767c888d58c1deb3ca184731cf2ef98223f27a..6620b90ecee3db4bb9bc19d903358fa475242fbb 100644 --- a/drivers/isdn/hisax/hfc_2bs0.c +++ b/drivers/isdn/hisax/hfc_2bs0.c @@ -1,4 +1,4 @@ -/* $Id: hfc_2bs0.c,v 1.9 1999/07/01 08:11:36 keil Exp $ +/* $Id: hfc_2bs0.c,v 1.10 1999/10/14 20:25:28 keil Exp $ * specific routines for CCD's HFC 2BS0 * @@ -6,6 +6,9 @@ * * * $Log: hfc_2bs0.c,v $ + * Revision 1.10 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * * Revision 1.9 1999/07/01 08:11:36 keil * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel * @@ -217,12 +220,14 @@ hfc_empty_fifo(struct BCState *bcs, int count) stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif return (NULL); } if (!(skb = dev_alloc_skb(count - 3))) printk(KERN_WARNING "HFC: receive out of memory\n"); else { - SET_SKB_FREE(skb); ptr = skb_put(skb, count - 3); idx = 0; cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); @@ -233,7 +238,7 @@ hfc_empty_fifo(struct BCState *bcs, int count) if (idx != count - 3) { debugl1(cs, "RFIFO BUSY error"); printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); WaitNoBusy(cs); stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); @@ -251,8 +256,11 @@ hfc_empty_fifo(struct BCState *bcs, int count) bcs->channel, chksum, stat); if (stat) { debugl1(cs, "FIFO CRC error"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; +#ifdef ERROR_STATISTIC + bcs->err_crc++; +#endif } WaitNoBusy(cs); stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | @@ -325,7 +333,7 @@ hfc_fill_fifo(struct BCState *bcs) bcs->tx_cnt -= count; if (PACKET_NOACK == bcs->tx_skb->pkt_type) count = -1; - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; WaitForBusy(cs); WaitNoBusy(cs); @@ -523,7 +531,7 @@ close_hfcstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -559,8 +567,8 @@ setstack_hfc(struct PStack *st, struct BCState *bcs) return (0); } -void __init -init_send(struct BCState *bcs) +__initfunc(void +init_send(struct BCState *bcs)) { int i; @@ -573,8 +581,8 @@ init_send(struct BCState *bcs) bcs->hw.hfc.send[i] = 0x1fff; } -void __init -inithfc(struct IsdnCardState *cs) +__initfunc(void +inithfc(struct IsdnCardState *cs)) { init_send(&cs->bcs[0]); init_send(&cs->bcs[1]); diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 9d8968e988dc6a95ff22effcbd943e95cc846270..518c1670aec750b74178fec28ca7ce4d5d1a9c06 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.18 1999/08/29 17:05:44 werner Exp $ +/* $Id: hfc_pci.c,v 1.23 1999/11/07 17:01:55 keil Exp $ * hfc_pci.c low level driver for CCD´s hfc-pci based cards * @@ -23,6 +23,25 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: hfc_pci.c,v $ + * Revision 1.23 1999/11/07 17:01:55 keil + * fix for 2.3 pci structs + * + * Revision 1.22 1999/10/10 20:14:27 werner + * + * Correct B2-chan usage in conjuntion with echo mode. First implementation of NT-leased line mode. + * + * Revision 1.21 1999/10/02 17:47:49 werner + * + * Changed init order, added correction for page alignment with shared mem + * + * Revision 1.20 1999/09/07 06:18:55 werner + * + * Added io parameter for HFC-PCI based cards. Needed only with multiple cards + * when initialisation/selection order needs to be set. + * + * Revision 1.19 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.18 1999/08/29 17:05:44 werner * corrected tx_lo line setup. Datasheet is not correct. * @@ -91,40 +110,40 @@ #include "hfc_pci.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #include <linux/interrupt.h> extern const char *CardType[]; -static const char *hfcpci_revision = "$Revision: 1.18 $"; +static const char *hfcpci_revision = "$Revision: 1.23 $"; /* table entry in the PCI devices list */ typedef struct { - int vendor_id; - int device_id; - char *vendor_name; - char *card_name; - } PCI_ENTRY; - -static const PCI_ENTRY id_list[] = { - {0x1397,0x2BD0,"CCD/Billion/Asuscom","2BD0"}, - {0x1397,0xB000,"Billion","B000"}, - {0x1397,0xB006,"Billion","B006"}, - {0x1397,0xB007,"Billion","B007"}, - {0x1397,0xB008,"Billion","B008"}, - {0x1397,0xB009,"Billion","B009"}, - {0x1397,0xB00A,"Billion","B00A"}, - {0x1397,0xB00B,"Billion","B00B"}, - {0x1397,0xB00C,"Billion","B00C"}, - {0x1043,0x0675,"Asuscom/Askey","675"}, - {0x0871,0xFFA2,"German telekom","T-Concept"}, - {0x0871,0xFFA1,"German telekom","A1T"}, - {0x1051,0x0100,"Motorola MC145575","MC145575"}, - {0x1397,0xB100,"Seyeon","B100"}, - {0x15B0,0x2BD0,"Zoltrix","2BD0"}, - {0,0,NULL,NULL}, + int vendor_id; + int device_id; + char *vendor_name; + char *card_name; +} PCI_ENTRY; + +#define NT_T1_COUNT 20 /* number of 3.125ms interrupts for G2 timeout */ + +static const PCI_ENTRY id_list[] = +{ + {0x1397, 0x2BD0, "CCD/Billion/Asuscom", "2BD0"}, + {0x1397, 0xB000, "Billion", "B000"}, + {0x1397, 0xB006, "Billion", "B006"}, + {0x1397, 0xB007, "Billion", "B007"}, + {0x1397, 0xB008, "Billion", "B008"}, + {0x1397, 0xB009, "Billion", "B009"}, + {0x1397, 0xB00A, "Billion", "B00A"}, + {0x1397, 0xB00B, "Billion", "B00B"}, + {0x1397, 0xB00C, "Billion", "B00C"}, + {0x1043, 0x0675, "Asuscom/Askey", "675"}, + {0x0871, 0xFFA2, "German telekom", "T-Concept"}, + {0x0871, 0xFFA1, "German telekom", "A1T"}, + {0x1051, 0x0100, "Motorola MC145575", "MC145575"}, + {0x1397, 0xB100, "Seyeon", "B100"}, + {0x15B0, 0x2BD0, "Zoltrix", "2BD0"}, + {0, 0, NULL, NULL}, }; @@ -151,9 +170,21 @@ releasehfcpci(struct IsdnCardState *cs) void release_io_hfcpci(struct IsdnCardState *cs) { + int flags; + + save_flags(flags); + cli(); + cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + restore_flags(flags); + Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ + sti(); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ #if CONFIG_PCI - pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disabe memory mapped ports + busmaster */ -#endif /* CONFIG_PCI */ + pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */ +#endif /* CONFIG_PCI */ releasehfcpci(cs); del_timer(&cs->hw.hfcpci.timer); kfree(cs->hw.hfcpci.share_start); @@ -170,16 +201,20 @@ reset_hfcpci(struct IsdnCardState *cs) { long flags; + save_flags(flags); + cli(); pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ + cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + printk(KERN_INFO "HFC_PCI: resetting card\n"); pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER); /* enable memory ports + busmaster */ Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ - save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ if (Read_hfc(cs, HFCPCI_STATUS) & 2) printk(KERN_WARNING "HFC-PCI init bit busy\n"); @@ -187,25 +222,23 @@ reset_hfcpci(struct IsdnCardState *cs) cs->hw.hfcpci.fifo_en = 0x30; /* only D fifos enabled */ Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); - cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */ + cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */ Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); Write_hfc(cs, HFCPCI_CLKDEL, 0x0e); /* ST-Bit delay for TE-Mode */ cs->hw.hfcpci.sctrl_e = HFCPCI_AUTO_AWAKE; Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e); /* S/T Auto awake */ - cs->hw.hfcpci.bswapped = 0; /* no exchange */ + cs->hw.hfcpci.bswapped = 0; /* no exchange */ + cs->hw.hfcpci.nt_mode = 0; /* we are in TE mode */ cs->hw.hfcpci.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER; Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); - cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE; - cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC | - HFCPCI_INTS_L1STATE | HFCPCI_CLTIMER; + cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC | + HFCPCI_INTS_L1STATE | HFCPCI_INTS_TIMER; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); /* Clear already pending ints */ if (Read_hfc(cs, HFCPCI_INT_S1)); - if (Read_hfc(cs, HFCPCI_INT_S2)); Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 2); /* HFC ST 2 */ udelay(10); @@ -213,24 +246,29 @@ reset_hfcpci(struct IsdnCardState *cs) cs->hw.hfcpci.mst_m = HFCPCI_MASTER; /* HFC Master Mode */ Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); - cs->hw.hfcpci.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */ + cs->hw.hfcpci.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */ Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); cs->hw.hfcpci.sctrl_r = 0; Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); - /* Init GCI/IOM2 in master mode */ + /* Init GCI/IOM2 in master mode */ /* Slots 0 and 1 are set for B-chan 1 and 2 */ /* D- and monitor/CI channel are not enabled */ /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */ - /* STIO2 is used as data input, B1+B2 from IOM->ST */ + /* STIO2 is used as data input, B1+B2 from IOM->ST */ /* ST B-channel send disabled -> continous 1s */ /* The IOM slots are always enabled */ - cs->hw.hfcpci.conn = 0x36; /* set data flow directions */ + cs->hw.hfcpci.conn = 0x36; /* set data flow directions */ Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); - Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */ - Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */ - Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */ - Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */ + Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */ + Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */ + Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */ + Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */ + + /* Finally enable IRQ output */ + cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE; + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + if (Read_hfc(cs, HFCPCI_INT_S2)); restore_flags(flags); } @@ -317,12 +355,11 @@ hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int cou } else if (!(skb = dev_alloc_skb(count - 3))) printk(KERN_WARNING "HFCPCI: receive out of memory\n"); else { - SET_SKB_FREE(skb); total = count; count -= 3; ptr = skb_put(skb, count); - if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL) + if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL) maxlen = count; /* complete transfer */ else maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ @@ -381,7 +418,6 @@ receive_dmsg(struct IsdnCardState *cs) df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1); } else if ((skb = dev_alloc_skb(rcnt - 3))) { - SET_SKB_FREE(skb); total = rcnt; rcnt -= 3; ptr = skb_put(skb, rcnt); @@ -415,55 +451,56 @@ receive_dmsg(struct IsdnCardState *cs) /*******************************************************************************/ /* check for transparent receive data and read max one threshold size if avail */ /*******************************************************************************/ -int hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type *bz, u_char *bdata) -{ unsigned short *z1r, *z2r; - int new_z2, fcnt, maxlen; - struct sk_buff *skb; - u_char *ptr, *ptr1; +int +hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata) +{ + unsigned short *z1r, *z2r; + int new_z2, fcnt, maxlen; + struct sk_buff *skb; + u_char *ptr, *ptr1; - z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ - z2r = z1r + 1; + z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ + z2r = z1r + 1; - if (!(fcnt = *z1r - *z2r)) - return(0); /* no data avail */ + if (!(fcnt = *z1r - *z2r)) + return (0); /* no data avail */ - if (fcnt <= 0) - fcnt += B_FIFO_SIZE; /* bytes actually buffered */ - if (fcnt > HFCPCI_BTRANS_THRESHOLD) - fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */ + if (fcnt <= 0) + fcnt += B_FIFO_SIZE; /* bytes actually buffered */ + if (fcnt > HFCPCI_BTRANS_THRESHOLD) + fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */ - new_z2 = *z2r + fcnt; /* new position in fifo */ - if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) - new_z2 -= B_FIFO_SIZE; /* buffer wrap */ + new_z2 = *z2r + fcnt; /* new position in fifo */ + if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) + new_z2 -= B_FIFO_SIZE; /* buffer wrap */ - if (!(skb = dev_alloc_skb(fcnt))) + if (!(skb = dev_alloc_skb(fcnt))) printk(KERN_WARNING "HFCPCI: receive out of memory\n"); - else { - SET_SKB_FREE(skb); - ptr = skb_put(skb, fcnt); - if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL) - maxlen = fcnt; /* complete transfer */ - else - maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */ - - ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */ - memcpy(ptr, ptr1, maxlen); /* copy data */ - fcnt -= maxlen; - - if (fcnt) { /* rest remaining */ - ptr += maxlen; - ptr1 = bdata; /* start of buffer */ - memcpy(ptr, ptr1, fcnt); /* rest */ - } - cli(); - skb_queue_tail(&bcs->rqueue, skb); - sti(); - hfcpci_sched_event(bcs, B_RCVBUFREADY); - } - - *z2r = new_z2; /* new position */ - return(1); -} /* hfcpci_empty_fifo_trans */ + else { + ptr = skb_put(skb, fcnt); + if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL) + maxlen = fcnt; /* complete transfer */ + else + maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */ + + ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */ + memcpy(ptr, ptr1, maxlen); /* copy data */ + fcnt -= maxlen; + + if (fcnt) { /* rest remaining */ + ptr += maxlen; + ptr1 = bdata; /* start of buffer */ + memcpy(ptr, ptr1, fcnt); /* rest */ + } + cli(); + skb_queue_tail(&bcs->rqueue, skb); + sti(); + hfcpci_sched_event(bcs, B_RCVBUFREADY); + } + + *z2r = new_z2; /* new position */ + return (1); +} /* hfcpci_empty_fifo_trans */ /**********************************/ /* B-channel main receive routine */ @@ -524,11 +561,10 @@ main_rec_hfcpci(struct BCState *bcs) receive = 1; else receive = 0; - } else - if (bcs->mode == L1_MODE_TRANS) - receive = hfcpci_empty_fifo_trans(bcs, bz, bdata); - else - receive = 0; + } else if (bcs->mode == L1_MODE_TRANS) + receive = hfcpci_empty_fifo_trans(bcs, bz, bdata); + else + receive = 0; test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; @@ -603,7 +639,7 @@ hfcpci_fill_dfifo(struct IsdnCardState *cs) df->f1 = new_f1; /* next frame */ restore_flags(flags); - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_skb = NULL; return; } @@ -620,7 +656,7 @@ hfcpci_fill_fifo(struct BCState *bcs) bzfifo_type *bz; u_char *bdata; u_char new_f1, *src, *dst; - unsigned short *z1t, *z2t; + unsigned short *z1t, *z2t; if (!bcs->tx_skb) return; @@ -639,57 +675,53 @@ hfcpci_fill_fifo(struct BCState *bcs) } if (bcs->mode == L1_MODE_TRANS) { - z1t = &bz->za[MAX_B_FRAMES].z1; - z2t = z1t + 1; - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)", - bcs->channel, *z1t, *z2t); - fcnt = *z2t - *z1t; - if (fcnt <= 0) - fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */ - fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */ - - while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) { - if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { - /* data is suitable for fifo */ - count = bcs->tx_skb->len; - - new_z1 = *z1t + count; /* new buffer Position */ - if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) - new_z1 -= B_FIFO_SIZE; /* buffer wrap */ - src = bcs->tx_skb->data; /* source pointer */ - dst = bdata + (*z1t - B_SUB_VAL); - maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */ - if (maxlen > count) - maxlen = count; /* limit size */ - memcpy(dst, src, maxlen); /* first copy */ - - count -= maxlen; /* remaining bytes */ - if (count) { - dst = bdata; /* start of buffer */ - src += maxlen; /* new position */ - memcpy(dst, src, count); - } - bcs->tx_cnt -= bcs->tx_skb->len; - fcnt += bcs->tx_skb->len; - *z1t = new_z1; /* now send data */ - } - else - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded", - bcs->channel, bcs->tx_skb->len); - - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); - cli(); - bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */ - sti(); - } - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - restore_flags(flags); - return; + z1t = &bz->za[MAX_B_FRAMES].z1; + z2t = z1t + 1; + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)", + bcs->channel, *z1t, *z2t); + fcnt = *z2t - *z1t; + if (fcnt <= 0) + fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */ + fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */ + + while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) { + if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { + /* data is suitable for fifo */ + count = bcs->tx_skb->len; + + new_z1 = *z1t + count; /* new buffer Position */ + if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) + new_z1 -= B_FIFO_SIZE; /* buffer wrap */ + src = bcs->tx_skb->data; /* source pointer */ + dst = bdata + (*z1t - B_SUB_VAL); + maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */ + if (maxlen > count) + maxlen = count; /* limit size */ + memcpy(dst, src, maxlen); /* first copy */ + + count -= maxlen; /* remaining bytes */ + if (count) { + dst = bdata; /* start of buffer */ + src += maxlen; /* new position */ + memcpy(dst, src, count); + } + bcs->tx_cnt -= bcs->tx_skb->len; + fcnt += bcs->tx_skb->len; + *z1t = new_z1; /* now send data */ + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded", + bcs->channel, bcs->tx_skb->len); + + dev_kfree_skb(bcs->tx_skb); + cli(); + bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */ + sti(); + } + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + restore_flags(flags); + return; } - - if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)", bcs->channel, bz->f1, bz->f2, @@ -749,57 +781,113 @@ hfcpci_fill_fifo(struct BCState *bcs) bz->f1 = new_f1; /* next frame */ restore_flags(flags); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); return; } +/**********************************************/ +/* D-channel l1 state call for leased NT-mode */ +/**********************************************/ +static void +dch_nt_l2l1(struct PStack *st, int pr, void *arg) +{ + struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; + + switch (pr) { + case (PH_DATA | REQUEST): + case (PH_PULL | REQUEST): + case (PH_PULL | INDICATION): + st->l1.l1hw(st, pr, arg); + break; + case (PH_ACTIVATE | REQUEST): + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); + break; + case (PH_TESTLOOP | REQUEST): + if (1 & (long) arg) + debugl1(cs, "PH_TEST_LOOP B1"); + if (2 & (long) arg) + debugl1(cs, "PH_TEST_LOOP B2"); + if (!(3 & (long) arg)) + debugl1(cs, "PH_TEST_LOOP DISABLED"); + st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg); + break; + default: + if (cs->debug) + debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr); + break; + } +} + + + /***********************/ /* set/reset echo mode */ -/***********************/ +/***********************/ static int -hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) +hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { - int flags; - int i = *(unsigned int *) ic->parm.num; - - if (cs->chanlimit > 1) - return(-EINVAL); - - save_flags(flags); - cli(); - if (i) { - cs->logecho = 1; - cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */ - cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC; - cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX; - } - else { - cs->logecho = 0; - cs->hw.hfcpci.trm &= ~0x20; /* enable echo chan */ - cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC; - cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX; - } - cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA; - cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA; - cs->hw.hfcpci.conn |= 0x10; /* B2-IOM -> B2-ST */ - cs->hw.hfcpci.ctmt &= ~2; - Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); - Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); - Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); - Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); - Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); - Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); - Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - restore_flags(flags); - return(0); -} /* hfcpci_auxcmd */ + int flags; + int i = *(unsigned int *) ic->parm.num; + + if ((ic->arg == 98) && + (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) { + save_flags(flags); + cli(); + Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* HFC ST G0 */ + udelay(10); + cs->hw.hfcpci.sctrl |= SCTRL_MODE_NT; + Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); /* set NT-mode */ + udelay(10); + Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1); /* HFC ST G1 */ + udelay(10); + Write_hfc(cs, HFCPCI_STATES, 1 | HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); + cs->dc.hfcpci.ph_state = 1; + cs->hw.hfcpci.nt_mode = 1; + cs->hw.hfcpci.nt_timer = 0; + cs->stlist->l2.l2l1 = dch_nt_l2l1; + restore_flags(flags); + debugl1(cs, "NT mode activated"); + return (0); + } + if ((cs->chanlimit > 1) || (cs->hw.hfcpci.bswapped) || + (cs->hw.hfcpci.nt_mode) || (ic->arg != 12)) + return (-EINVAL); + + save_flags(flags); + cli(); + if (i) { + cs->logecho = 1; + cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */ + cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC; + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX; + } else { + cs->logecho = 0; + cs->hw.hfcpci.trm &= ~0x20; /* disable echo chan */ + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC; + cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX; + } + cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA; + cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA; + cs->hw.hfcpci.conn |= 0x10; /* B2-IOM -> B2-ST */ + cs->hw.hfcpci.ctmt &= ~2; + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); + Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); + Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); + Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); + Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); + Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + restore_flags(flags); + return (0); +} /* hfcpci_auxcmd */ /*****************************/ /* E-channel receive routine */ /*****************************/ -static void receive_emsg(struct IsdnCardState *cs) +static void +receive_emsg(struct IsdnCardState *cs) { long flags; int rcnt; @@ -836,55 +924,54 @@ static void receive_emsg(struct IsdnCardState *cs) if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)", zp->z1, zp->z2, rcnt); - new_z2 = zp->z2 + rcnt; /* new position in fifo */ + new_z2 = zp->z2 + rcnt; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) - new_z2 -= B_FIFO_SIZE; /* buffer wrap */ + new_z2 -= B_FIFO_SIZE; /* buffer wrap */ new_f2 = (bz->f2 + 1) & MAX_B_FRAMES; - if ((rcnt > 256 + 3) || (count < 4) || + if ((rcnt > 256 + 3) || (count < 4) || (*(bdata + (zp->z1 - B_SUB_VAL)))) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt); - bz->za[new_f2].z2 = new_z2; - bz->f2 = new_f2; /* next buffer */ + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt); + bz->za[new_f2].z2 = new_z2; + bz->f2 = new_f2; /* next buffer */ } else { - total = rcnt; - rcnt -= 3; - ptr = e_buffer; - - if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL) - maxlen = rcnt; /* complete transfer */ - else - maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ + total = rcnt; + rcnt -= 3; + ptr = e_buffer; - ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ - memcpy(ptr, ptr1, maxlen); /* copy data */ - rcnt -= maxlen; + if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL) + maxlen = rcnt; /* complete transfer */ + else + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ - if (rcnt) { /* rest remaining */ - ptr += maxlen; - ptr1 = bdata; /* start of buffer */ - memcpy(ptr, ptr1, rcnt); /* rest */ - } - bz->za[new_f2].z2 = new_z2; - bz->f2 = new_f2; /* next buffer */ - if (cs->debug & DEB_DLOG_HEX) { - ptr = cs->dlog; - if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) { - *ptr++ = 'E'; - *ptr++ = 'C'; - *ptr++ = 'H'; - *ptr++ = 'O'; - *ptr++ = ':'; - ptr += QuickHex(ptr, e_buffer, total - 3); - ptr--; - *ptr++ = '\n'; - *ptr = 0; - HiSax_putstatus(cs, NULL, cs->dlog); - } else - HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3); - } + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ + memcpy(ptr, ptr1, maxlen); /* copy data */ + rcnt -= maxlen; - } + if (rcnt) { /* rest remaining */ + ptr += maxlen; + ptr1 = bdata; /* start of buffer */ + memcpy(ptr, ptr1, rcnt); /* rest */ + } + bz->za[new_f2].z2 = new_z2; + bz->f2 = new_f2; /* next buffer */ + if (cs->debug & DEB_DLOG_HEX) { + ptr = cs->dlog; + if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) { + *ptr++ = 'E'; + *ptr++ = 'C'; + *ptr++ = 'H'; + *ptr++ = 'O'; + *ptr++ = ':'; + ptr += QuickHex(ptr, e_buffer, total - 3); + ptr--; + *ptr++ = '\n'; + *ptr = 0; + HiSax_putstatus(cs, NULL, cs->dlog); + } else + HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3); + } + } rcnt = bz->f1 - bz->f2; if (rcnt < 0) @@ -900,7 +987,7 @@ static void receive_emsg(struct IsdnCardState *cs) goto Begin; restore_flags(flags); return; -} /* receive_emsg */ +} /* receive_emsg */ /*********************/ /* Interrupt handler */ @@ -919,6 +1006,9 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n"); return; } + if (!(cs->hw.hfcpci.int_m2 & 0x08)) + return; /* not initialised */ + if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) { val = Read_hfc(cs, HFCPCI_INT_S1); if (cs->debug & L1_DEB_ISAC) @@ -931,7 +1021,7 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? "locked" : "unlocked"); val &= cs->hw.hfcpci.int_m1; - if (val & 0x40) { /* TE state machine irq */ + if (val & 0x40) { /* state machine irq */ exval = Read_hfc(cs, HFCPCI_STATES) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state, @@ -940,6 +1030,14 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) sched_event_D_pci(cs, D_L1STATECHANGE); val &= ~0x40; } + if (val & 0x80) { /* timer irq */ + if (cs->hw.hfcpci.nt_mode) { + if ((--cs->hw.hfcpci.nt_timer) < 0) + sched_event_D_pci(cs, D_L1STATECHANGE); + } + val &= ~0x80; + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); + } while (val) { save_flags(flags); cli(); @@ -954,24 +1052,23 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) cs->hw.hfcpci.int_s1 = exval; } if (val & 0x08) { - if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) { + if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x08 IRQ"); } else main_rec_hfcpci(bcs); } - if (val & 0x10) { - if (cs->logecho) - receive_emsg(cs); - else - if (!(bcs = Sel_BCS(cs, 1))) { + if (val & 0x10) { + if (cs->logecho) + receive_emsg(cs); + else if (!(bcs = Sel_BCS(cs, 1))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x10 IRQ"); } else main_rec_hfcpci(bcs); } if (val & 0x01) { - if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) { + if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x01 IRQ"); } else { @@ -1036,7 +1133,7 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) } goto afterXPR; } else { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } @@ -1070,20 +1167,6 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) static void hfcpci_dbusy_timer(struct IsdnCardState *cs) { -#if 0 - struct PStack *stptr; - if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - if (cs->debug) - debugl1(cs, "D-Channel Busy"); - test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); - stptr = cs->stlist; - - while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); - stptr = stptr->next; - } - } -#endif } /*************************************/ @@ -1094,6 +1177,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg) { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + int flags; switch (pr) { case (PH_DATA | REQUEST): @@ -1169,39 +1253,46 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg) Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); break; case (HW_DEACTIVATE | REQUEST): - cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER; + cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); break; case (HW_INFO3 | REQUEST): cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); break; -#if 0 case (HW_TESTLOOP | REQUEST): - u_char val = 0; - if (1 & (int) arg) - val |= 0x0c; - if (2 & (int) arg) - val |= 0x3; - if (test_bit(HW_IOM1, &cs->HW_Flags)) { - /* IOM 1 Mode */ - if (!val) { - cs->writeisac(cs, ISAC_SPCR, 0xa); - cs->writeisac(cs, ISAC_ADF1, 0x2); - } else { - cs->writeisac(cs, ISAC_SPCR, val); - cs->writeisac(cs, ISAC_ADF1, 0xa); - } - } else { - /* IOM 2 Mode */ - cs->writeisac(cs, ISAC_SPCR, val); - if (val) - cs->writeisac(cs, ISAC_ADF1, 0x8); - else - cs->writeisac(cs, ISAC_ADF1, 0x0); + switch ((int) arg) { + case (1): + Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */ + Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* rx slot */ + save_flags(flags); + cli(); + cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~7) | 1; + Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); + restore_flags(flags); + break; + + case (2): + Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* tx slot */ + Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* rx slot */ + save_flags(flags); + cli(); + cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~0x38) | 0x08; + Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); + restore_flags(flags); + break; + + default: + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg); + return; } + save_flags(flags); + cli(); + cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */ + Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); + restore_flags(flags); break; -#endif default: if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr); @@ -1241,113 +1332,127 @@ mode_hfcpci(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; bzfifo_type *bzr, *bzt; - int flags; + int flags, fifo2; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d", mode, bc, bcs->channel); bcs->mode = mode; bcs->channel = bc; - if (cs->chanlimit > 1) { - cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ - cs->hw.hfcpci.sctrl_e &= ~0x80; - } - else { - if (bc) { - cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */ - cs->hw.hfcpci.sctrl_e |= 0x80; - bc = 0; /* B1 controller used */ - } - else { - cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ - cs->hw.hfcpci.sctrl_e &= ~0x80; - } - } + fifo2 = bc; save_flags(flags); cli(); + if (cs->chanlimit > 1) { + cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ + cs->hw.hfcpci.sctrl_e &= ~0x80; + } else { + if (bc) { + if (mode != L1_MODE_NULL) { + cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */ + cs->hw.hfcpci.sctrl_e |= 0x80; + } else { + cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ + cs->hw.hfcpci.sctrl_e &= ~0x80; + } + fifo2 = 0; + } else { + cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ + cs->hw.hfcpci.sctrl_e &= ~0x80; + } + } switch (mode) { case (L1_MODE_NULL): if (bc) { cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA; - cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2; - cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); } else { cs->hw.hfcpci.sctrl &= ~SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r &= ~SCTRL_B1_ENA; + } + if (fifo2) { + cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2; + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); + } else { cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1; - cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); } break; case (L1_MODE_TRANS): if (bc) { - cs->hw.hfcpci.ctmt |= 2; - cs->hw.hfcpci.conn &= ~0x18; cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; - cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; - cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); - bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; - bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2; } else { - cs->hw.hfcpci.ctmt |= 1; - cs->hw.hfcpci.conn &= ~0x03; cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; + } + if (fifo2) { + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); + cs->hw.hfcpci.ctmt |= 2; + cs->hw.hfcpci.conn &= ~0x18; + bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; + bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2; + } else { cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1; - cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); - bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1; - bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); + cs->hw.hfcpci.ctmt |= 1; + cs->hw.hfcpci.conn &= ~0x03; + bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1; + bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1; } bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1; - bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1; + bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1; bzr->f1 = MAX_B_FRAMES; - bzr->f2 = bzr->f1; /* init F pointers to remain constant */ + bzr->f2 = bzr->f1; /* init F pointers to remain constant */ bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1; - bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1; + bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1; bzt->f1 = MAX_B_FRAMES; - bzt->f2 = bzt->f1; /* init F pointers to remain constant */ + bzt->f2 = bzt->f1; /* init F pointers to remain constant */ break; case (L1_MODE_HDLC): if (bc) { - cs->hw.hfcpci.ctmt &= ~2; - cs->hw.hfcpci.conn &= ~0x18; cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; - cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; - cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); } else { - cs->hw.hfcpci.ctmt &= ~1; - cs->hw.hfcpci.conn &= ~0x3; cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; + } + if (fifo2) { + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); + cs->hw.hfcpci.ctmt &= ~2; + cs->hw.hfcpci.conn &= ~0x18; + } else { cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1; - cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); + cs->hw.hfcpci.ctmt &= ~1; + cs->hw.hfcpci.conn &= ~0x03; } break; case (L1_MODE_EXTRN): if (bc) { - cs->hw.hfcpci.conn |= 0x10; + cs->hw.hfcpci.conn |= 0x10; cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2; - cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); } else { - cs->hw.hfcpci.conn |= 0x02; + cs->hw.hfcpci.conn |= 0x02; cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1; - cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); } break; } + Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e); Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - restore_flags(flags); Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); + restore_flags(flags); } /******************************/ @@ -1420,7 +1525,7 @@ close_hfcpci(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -1467,40 +1572,72 @@ setstack_2b(struct PStack *st, struct BCState *bcs) static void hfcpci_bh(struct IsdnCardState *cs) { + int flags; /* struct PStack *stptr; */ if (!cs) return; -#if 0 - if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { - if (cs->debug) - debugl1(cs, "D-Channel Busy cleared"); - stptr = cs->stlist; - while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); - stptr = stptr->next; - } - } -#endif if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { - switch (cs->dc.hfcpci.ph_state) { - case (0): - l1_msg(cs, HW_RESET | INDICATION, NULL); - break; - case (3): - l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); - break; - case (8): - l1_msg(cs, HW_RSYNC | INDICATION, NULL); - break; - case (6): - l1_msg(cs, HW_INFO2 | INDICATION, NULL); - break; - case (7): - l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); - break; - default: - break; + if (!cs->hw.hfcpci.nt_mode) + switch (cs->dc.hfcpci.ph_state) { + case (0): + l1_msg(cs, HW_RESET | INDICATION, NULL); + break; + case (3): + l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); + break; + case (8): + l1_msg(cs, HW_RSYNC | INDICATION, NULL); + break; + case (6): + l1_msg(cs, HW_INFO2 | INDICATION, NULL); + break; + case (7): + l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); + break; + default: + break; + } else { + switch (cs->dc.hfcpci.ph_state) { + case (2): + save_flags(flags); + cli(); + if (cs->hw.hfcpci.nt_timer < 0) { + cs->hw.hfcpci.nt_timer = 0; + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + /* Clear already pending ints */ + if (Read_hfc(cs, HFCPCI_INT_S1)); + + Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE); + udelay(10); + Write_hfc(cs, HFCPCI_STATES, 4); + cs->dc.hfcpci.ph_state = 4; + } else { + cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + cs->hw.hfcpci.ctmt &= ~HFCPCI_AUTO_TIMER; + cs->hw.hfcpci.ctmt |= HFCPCI_TIM3_125; + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); + cs->hw.hfcpci.nt_timer = NT_T1_COUNT; + Write_hfc(cs, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3); /* allow G2 -> G3 transition */ + } + restore_flags(flags); + break; + case (1): + case (3): + case (4): + save_flags(flags); + cli(); + cs->hw.hfcpci.nt_timer = 0; + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + restore_flags(flags); + break; + default: + break; + } } } if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) @@ -1513,8 +1650,8 @@ hfcpci_bh(struct IsdnCardState *cs) /*************************************/ /* Alloc memory send data for queues */ /*************************************/ -unsigned int * __init - init_send_hfcpci(int cnt) +__initfunc(unsigned int + *init_send_hfcpci(int cnt)) { int i, *send; @@ -1531,18 +1668,14 @@ unsigned int * __init /********************************/ /* called for card init message */ /********************************/ -void __init - inithfcpci(struct IsdnCardState *cs) +__initfunc(void + inithfcpci(struct IsdnCardState *cs)) { cs->setstack_d = setstack_hfcpci; cs->dbusytimer.function = (void *) hfcpci_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); cs->tqueue.routine = (void *) (void *) hfcpci_bh; -#if 0 - if (!cs->hw.hfcpci.send) - cs->hw.hfcpci.send = init_send_hfcpci(16); -#endif if (!cs->bcs[0].hw.hfc.send) cs->bcs[0].hw.hfc.send = init_send_hfcpci(32); if (!cs->bcs[1].hw.hfc.send) @@ -1579,7 +1712,7 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) inithfcpci(cs); save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ /* now switch timer interrupt off */ cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; @@ -1596,52 +1729,49 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) /* this variable is used as card index when more than one cards are present */ -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_hfcpci __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif #endif /* CONFIG_PCI */ -int __init - setup_hfcpci(struct IsdnCard *card) +__initfunc(int + setup_hfcpci(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; + unsigned short cmd; char tmp[64]; int i; -#ifdef COMPAT_HAS_NEW_PCI - struct pci_dev *tmp_hfcpci = NULL; -#endif + struct pci_dev *tmp_hfcpci = NULL; strcpy(tmp, hfcpci_revision); printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); #if CONFIG_PCI cs->hw.hfcpci.int_s1 = 0; -#if 0 - cs->hw.hfcpci.send = NULL; -#endif cs->bcs[0].hw.hfc.send = NULL; cs->bcs[1].hw.hfc.send = NULL; cs->dc.hfcpci.ph_state = 0; cs->hw.hfcpci.fifo = 255; if (cs->typ == ISDN_CTYPE_HFC_PCI) { -#ifdef COMPAT_HAS_NEW_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, - id_list[i].device_id, - dev_hfcpci); - if (tmp_hfcpci) break; - i++; - } - + while (id_list[i].vendor_id) { + tmp_hfcpci = pci_find_device(id_list[i].vendor_id, + id_list[i].device_id, + dev_hfcpci); + i++; + if (tmp_hfcpci) { + if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) + continue; + else + break; + } + } + if (tmp_hfcpci) { - dev_hfcpci = tmp_hfcpci; /* old device */ + i--; + dev_hfcpci = tmp_hfcpci; /* old device */ cs->hw.hfcpci.pci_bus = dev_hfcpci->bus->number; cs->hw.hfcpci.pci_device_fn = dev_hfcpci->devfn; cs->irq = dev_hfcpci->irq; @@ -1649,43 +1779,45 @@ int __init printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); return (0); } - cs->hw.hfcpci.pci_io = (char *) get_pcibase(dev_hfcpci, 1); - printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name); + cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start; + printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name); } else { printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); return (0); } -#else - for (; pci_index < 255; pci_index++) { - unsigned char irq; - - i = 0; - while (id_list[i].vendor_id) { - if (pcibios_find_device(id_list[i].vendor_id, - id_list[i].device_id, pci_index, - &cs->hw.hfcpci.pci_bus, &cs->hw.hfcpci.pci_device_fn) == 0) - break; - i++; - } - if (!id_list[i].vendor_id) - continue; - - pcibios_read_config_byte(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, - PCI_INTERRUPT_LINE, &irq); - cs->irq = irq; - + 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); - printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name); - break; - } - if (pci_index == 255) { - printk(KERN_WARNING "HFC-PCI: No card found\n"); - return (0); + 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->resource[1].start = (int) cs->hw.hfcpci.pci_io; } - pci_index++; -#endif /* COMPAT_HAS_NEW_PCI */ if (!cs->hw.hfcpci.pci_io) { printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); return (0); @@ -1701,16 +1833,16 @@ int __init (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000; pcibios_write_config_dword(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, 0x80, - (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); + (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); printk(KERN_INFO - "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", + "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos, (u_int) virt_to_bus(cs->hw.hfcpci.fifos), cs->irq, HZ); pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ - cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ cs->hw.hfcpci.int_m1 = 0; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); @@ -1735,7 +1867,7 @@ int __init reset_hfcpci(cs); cs->cardmsg = &hfcpci_card_msg; - cs->auxcmd = &hfcpci_auxcmd; + cs->auxcmd = &hfcpci_auxcmd; return (1); #else printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n"); diff --git a/drivers/isdn/hisax/hfc_pci.h b/drivers/isdn/hisax/hfc_pci.h index ae04d3d16af9734bf8f7f243b56595c5b9c575ba..e8597d73049ed1aeaa41733e25f9faf0d0cb487c 100644 --- a/drivers/isdn/hisax/hfc_pci.h +++ b/drivers/isdn/hisax/hfc_pci.h @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.h,v 1.6 1999/08/28 21:04:29 werner Exp $ +/* $Id: hfc_pci.h,v 1.7 1999/10/10 20:13:06 werner Exp $ * specific defines for CCD's HFC 2BDS0 PCI chips * @@ -21,6 +21,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: hfc_pci.h,v $ + * Revision 1.7 1999/10/10 20:13:06 werner + * + * Corrected timer constant + * * Revision 1.6 1999/08/28 21:04:29 werner * Implemented full audio support (transparent mode) * @@ -129,7 +133,7 @@ /* bits in CTMT (Write) */ #define HFCPCI_CLTIMER 0x80 -#define HFCPCI_TIM3_125 0x00 +#define HFCPCI_TIM3_125 0x04 #define HFCPCI_TIM25 0x10 #define HFCPCI_TIM50 0x14 #define HFCPCI_TIM400 0x18 diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c index 05735e150e5f4123df5eabe5e956c89ec15f7af0..8654857fdef612beadc41bf6aa3e2dcdc66b407b 100644 --- a/drivers/isdn/hisax/hfcscard.c +++ b/drivers/isdn/hisax/hfcscard.c @@ -1,4 +1,4 @@ -/* $Id: hfcscard.c,v 1.4 1999/08/09 18:59:59 keil Exp $ +/* $Id: hfcscard.c,v 1.5 1999/09/04 06:20:06 keil Exp $ * hfcscard.c low level stuff for hfcs based cards (Teles3c, ACER P10) * @@ -6,6 +6,9 @@ * * * $Log: hfcscard.c,v $ + * Revision 1.5 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.4 1999/08/09 18:59:59 keil * Fix S0 init - Thanks to Stefan Gybas * @@ -27,7 +30,7 @@ extern const char *CardType[]; -static const char *hfcs_revision = "$Revision: 1.4 $"; +static const char *hfcs_revision = "$Revision: 1.5 $"; static void hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs) @@ -82,13 +85,13 @@ reset_hfcs(struct IsdnCardState *cs) cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30*HZ)/1000); cs->hw.hfcD.cirm = 0; if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_MEM8K; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_INTB; @@ -135,7 +138,7 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) init2bds0(cs); save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((80*HZ)/1000); cs->hw.hfcD.ctmt |= HFCD_TIM800; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); @@ -148,8 +151,8 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_hfcs(struct IsdnCard *card) +__initfunc(int +setup_hfcs(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 0fdf65a409ea6294846b741b477f93001b9755aa..230628486bbc088759c57654280822125ddc5a5a 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -1,8 +1,18 @@ -/* $Id: hisax.h,v 2.34 1999/08/25 17:00:04 keil Exp $ +/* $Id: hisax.h,v 2.37 1999/10/14 20:25:28 keil Exp $ * Basic declarations, defines and prototypes * * $Log: hisax.h,v $ + * Revision 2.37 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * + * Revision 2.36 1999/10/10 20:16:15 werner + * + * Added variable to hfcpci union. + * + * Revision 2.35 1999/09/04 06:35:09 keil + * Winbond W6692 support + * * Revision 2.34 1999/08/25 17:00:04 keil * Make ISAR V32bis modem running * Make LL->HL interface open for additional commands @@ -137,6 +147,8 @@ #include <linux/tty.h> #include <linux/serial_reg.h> +#undef ERROR_STATISTIC + #define REQUEST 0 #define CONFIRM 1 #define INDICATION 2 @@ -447,6 +459,13 @@ struct hscx_hw { u_char tsaxr1; }; +struct w6692B_hw { + int bchan; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ +}; + struct isar_reg { unsigned int Flags; volatile u_char bstat; @@ -571,6 +590,12 @@ struct BCState { int event; int (*BC_SetStack) (struct PStack *, struct BCState *); void (*BC_Close) (struct BCState *); +#ifdef ERROR_STATISTIC + int err_crc; + int err_tx; + int err_rdo; + int err_inv; +#endif union { struct hscx_hw hscx; struct hdlc_hw hdlc; @@ -578,6 +603,7 @@ struct BCState { struct hfcB_hw hfc; struct tiger_hw tiger; struct amd7930_hw amd7930; + struct w6692B_hw w6692; } hw; }; @@ -744,7 +770,8 @@ struct hfcPCI_hw { unsigned char fifo; unsigned char fifo_en; unsigned char bswapped; - /* unsigned int *send; */ + unsigned char nt_mode; + int nt_timer; unsigned char pci_bus; unsigned char pci_device_fn; unsigned char *pci_io; /* start of PCI IO memory */ @@ -813,6 +840,11 @@ struct gazel_hw { unsigned char iom2; }; +struct w6692_hw { + unsigned int iobase; + struct timer_list timer; +}; + #ifdef CONFIG_HISAX_TESTEMU struct te_hw { unsigned char *sfifo; @@ -821,13 +853,8 @@ struct te_hw { unsigned char *sfifo_e; int sfifo_cnt; unsigned int stat; -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t rwaitq; wait_queue_head_t swaitq; -#else - struct wait_queue *rwaitq; - struct wait_queue *swaitq; -#endif }; #endif @@ -847,11 +874,7 @@ struct isac_chip { int mon_rxp; struct arcofi_msg *arcofi_list; struct timer_list arcofitimer; -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t arcofi_wait; -#else - struct wait_queue *arcofi_wait; -#endif u_char arcofi_bc; u_char arcofi_state; u_char mocr; @@ -866,6 +889,10 @@ struct hfcpci_chip { int ph_state; }; +struct w6692_chip { + int ph_state; +}; + #define HW_IOM1 0 #define HW_IPAC 1 #define HW_ISAR 2 @@ -910,6 +937,7 @@ struct IsdnCardState { #endif struct bkm_hw ax; struct gazel_hw gazel; + struct w6692_hw w6692; } hw; int myid; isdn_if iif; @@ -940,6 +968,7 @@ struct IsdnCardState { struct isac_chip isac; struct hfcd_chip hfcd; struct hfcpci_chip hfcpci; + struct w6692_chip w6692; } dc; u_char *rcvbuf; int rcvidx; @@ -948,6 +977,11 @@ struct IsdnCardState { int event; struct tq_struct tqueue; struct timer_list dbusytimer; +#ifdef ERROR_STATISTIC + int err_crc; + int err_tx; + int err_rx; +#endif }; #define MON0_RX 1 @@ -992,7 +1026,8 @@ struct IsdnCardState { #define ISDN_CTYPE_SCT_QUADRO 33 #define ISDN_CTYPE_GAZEL 34 #define ISDN_CTYPE_HFC_PCI 35 -#define ISDN_CTYPE_COUNT 35 +#define ISDN_CTYPE_W6692 36 +#define ISDN_CTYPE_COUNT 36 #ifdef ISDN_CHIP_ISAC @@ -1007,10 +1042,6 @@ struct IsdnCardState { #define __initdata #endif -#ifndef __init -#define __init -#endif - #define HISAX_INITFUNC(__arginit) __initfunc(__arginit) #define HISAX_INITDATA __initdata @@ -1243,6 +1274,15 @@ struct IsdnCardState { #define CARD_GAZEL 0 #endif +#ifdef CONFIG_HISAX_W6692 +#define CARD_W6692 1 +#ifndef ISDN_CHIP_W6692 +#define ISDN_CHIP_W6692 1 +#endif +#else +#define CARD_W6692 0 +#endif + #define TEI_PER_CARD 0 #ifdef CONFIG_HISAX_1TR6 @@ -1336,7 +1376,7 @@ int HiSax_command(isdn_ctrl * ic); int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb); void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...); void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args); -void HiSax_reportcard(int cardnr); +void HiSax_reportcard(int cardnr, int sel); int QuickHex(char *txt, u_char * p, int cnt); void LogFrame(struct IsdnCardState *cs, u_char * p, int size); void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir); diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c index 290c89f5059b63217ba861fd55a8ee89db1c5a44..1c57cd3f1c432f5e837373a845e6301da1accd06 100644 --- a/drivers/isdn/hisax/hscx.c +++ b/drivers/isdn/hisax/hscx.c @@ -219,7 +219,7 @@ close_hscxstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c index ecc1e825e52a0ded8b0626ea6f8f33f118a192b6..655508f704e99e0e23b22a67e4ece78dcce35b4f 100644 --- a/drivers/isdn/hisax/hscx_irq.c +++ b/drivers/isdn/hisax/hscx_irq.c @@ -1,4 +1,4 @@ -/* $Id: hscx_irq.c,v 1.12 1999/07/01 08:11:42 keil Exp $ +/* $Id: hscx_irq.c,v 1.13 1999/10/14 20:25:28 keil Exp $ * hscx_irq.c low level b-channel stuff for Siemens HSCX * @@ -7,6 +7,9 @@ * This is an include file for fast inline IRQ stuff * * $Log: hscx_irq.c,v $ + * Revision 1.13 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * * Revision 1.12 1999/07/01 08:11:42 keil * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel * @@ -181,16 +184,28 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (val & 0x80) { /* RME */ r = READHSCX(cs, hscx, HSCX_RSTA); if ((r & 0xf0) != 0xa0) { - if (!(r & 0x80)) + if (!(r & 0x80)) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "HSCX invalid frame"); - if ((r & 0x40) && bcs->mode) +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif + } + if ((r & 0x40) && bcs->mode) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "HSCX RDO mode=%d", bcs->mode); - if (!(r & 0x20)) +#ifdef ERROR_STATISTIC + bcs->err_rdo++; +#endif + } + if (!(r & 0x20)) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "HSCX CRC error"); +#ifdef ERROR_STATISTIC + bcs->err_crc++; +#endif + } WriteHSCXCMDR(cs, hscx, 0x80); } else { count = READHSCX(cs, hscx, HSCX_RBCL) & ( @@ -204,7 +219,6 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "HSCX: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -220,7 +234,6 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (!(skb = dev_alloc_skb(fifo_size))) printk(KERN_WARNING "HiSax: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); skb_queue_tail(&bcs->rqueue, skb); } @@ -237,7 +250,7 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.hscx.count = 0; bcs->tx_skb = NULL; } @@ -267,6 +280,9 @@ hscx_int_main(struct IsdnCardState *cs, u_char val) if (bcs->mode == 1) hscx_fill_fifo(bcs); else { +#ifdef ERROR_STATISTIC + bcs->err_tx++; +#endif /* Here we lost an TX interrupt, so * restart transmitting the whole frame. */ @@ -297,6 +313,9 @@ hscx_int_main(struct IsdnCardState *cs, u_char val) /* Here we lost an TX interrupt, so * restart transmitting the whole frame. */ +#ifdef ERROR_STATISTIC + bcs->err_tx++; +#endif if (bcs->tx_skb) { skb_push(bcs->tx_skb, bcs->hw.hscx.count); bcs->tx_cnt += bcs->hw.hscx.count; diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index 46d5daef0071e9e78108656702a63289ccbb6c87..a992f76c48ee092347666e182912789edb2e743c 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -1,4 +1,4 @@ -/* $Id: isac.c,v 1.23 1999/08/25 16:50:52 keil Exp $ +/* $Id: isac.c,v 1.24 1999/10/14 20:25:28 keil Exp $ * isac.c ISAC specific routines * @@ -9,6 +9,9 @@ * ../../../Documentation/isdn/HiSax.cert * * $Log: isac.c,v $ + * Revision 1.24 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * * Revision 1.23 1999/08/25 16:50:52 keil * Fix bugs which cause 2.3.14 hangs (waitqueue init) * @@ -281,12 +284,20 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) if (val & 0x80) { /* RME */ exval = cs->readisac(cs, ISAC_RSTA); if ((exval & 0x70) != 0x20) { - if (exval & 0x40) + if (exval & 0x40) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC RDO"); - if (!(exval & 0x20)) +#ifdef ERROR_STATISTIC + cs->err_rx++; +#endif + } + if (!(exval & 0x20)) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC CRC error"); +#ifdef ERROR_STATISTIC + cs->err_crc++; +#endif + } cs->writeisac(cs, ISAC_CMDR, 0x80); } else { count = cs->readisac(cs, ISAC_RBCL) & 0x1f; @@ -300,7 +311,6 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) if (!(skb = alloc_skb(count, GFP_ATOMIC))) printk(KERN_WARNING "HiSax: D receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), cs->rcvbuf, count); skb_queue_tail(&cs->rq, skb); } @@ -328,7 +338,7 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) isac_fill_fifo(cs); goto afterXPR; } else { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } @@ -372,6 +382,9 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) if (exval & 0x40) { /* XDU */ debugl1(cs, "ISAC XDU"); printk(KERN_WARNING "HiSax: ISAC XDU\n"); +#ifdef ERROR_STATISTIC + cs->err_tx++; +#endif if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) @@ -614,7 +627,7 @@ ISAC_l1hw(struct PStack *st, int pr, void *arg) discard_queue(&cs->rq); discard_queue(&cs->sq); if (cs->tx_skb) { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_skb = NULL; } if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) @@ -670,7 +683,7 @@ dbusy_timer_handler(struct IsdnCardState *cs) /* discard frame; reset transceiver */ test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); if (cs->tx_skb) { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } else { diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index 96442ff7d4ddc302d1d5f365dbc328691ea5a2e7..417f2157dbdeb0f5a67e326eb32927aa40cb6445 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -1,4 +1,4 @@ -/* $Id: isar.c,v 1.5 1999/08/25 16:59:55 keil Exp $ +/* $Id: isar.c,v 1.7 1999/10/14 20:25:29 keil Exp $ * isar.c ISAR (Siemens PSB 7110) specific routines * @@ -6,6 +6,12 @@ * * * $Log: isar.c,v $ + * Revision 1.7 1999/10/14 20:25:29 keil + * add a statistic for error monitoring + * + * Revision 1.6 1999/08/31 11:20:20 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.5 1999/08/25 16:59:55 keil * Make ISAR V32bis modem running * Make LL->HL interface open for additional commands @@ -459,7 +465,6 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) case L1_MODE_TRANS: case L1_MODE_V32: if ((skb = dev_alloc_skb(ireg->clsb))) { - SET_SKB_FREE(skb); rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb)); skb_queue_tail(&bcs->rqueue, skb); isar_sched_event(bcs, B_RCVBUFREADY); @@ -478,6 +483,12 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar frame error %x len %d", ireg->cmsb, ireg->clsb); +#ifdef ERROR_STATISTIC + if (ireg->cmsb & HDLC_ERR_RER) + bcs->err_inv++; + if (ireg->cmsb & HDLC_ERR_CER) + bcs->err_crc++; +#endif bcs->hw.isar.rcvidx = 0; cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } else { @@ -493,7 +504,6 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2))) { printk(KERN_WARNING "ISAR: receive out of memory\n"); } else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2), bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2); skb_queue_tail(&bcs->rqueue, skb); @@ -593,7 +603,7 @@ send_frames(struct BCState *bcs) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.isar.txcnt = 0; bcs->tx_skb = NULL; } @@ -789,10 +799,19 @@ isar_int_main(struct IsdnCardState *cs) check_send(cs, ireg->cmsb); break; case ISAR_IIS_BSTEV: - cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); +#ifdef ERROR_STATISTIC + if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { + if (ireg->cmsb == BSTEV_TBO) + bcs->err_tx++; + if (ireg->cmsb == BSTEV_RBO) + bcs->err_rdo++; + } +#endif if (cs->debug & L1_DEB_WARN) debugl1(cs, "Buffer STEV dpath%d msb(%x)", ireg->iis>>6, ireg->cmsb); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + break; case ISAR_IIS_PSTEV: if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { rcv_mbox(cs, ireg, (u_char *)ireg->par); @@ -1022,8 +1041,8 @@ modeisar(struct BCState *bcs, int mode, int bc) &bcs->hw.isar.reg->Flags)) bcs->hw.isar.dpath = 1; else { - printk(KERN_WARNING"isar modeisar analog funktions only with DP1\n"); - debugl1(cs, "isar modeisar analog funktions only with DP1"); + printk(KERN_WARNING"isar modeisar analog works only with DP1\n"); + debugl1(cs, "isar modeisar analog works only with DP1"); return(1); } break; @@ -1159,7 +1178,7 @@ close_isarstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); if (bcs->cs->debug & L1_DEB_HSCX) @@ -1223,7 +1242,7 @@ isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { ll_run(cs, features); break; default: - printk(KERN_DEBUG "HiSax: invalid ioclt %d\n", + printk(KERN_DEBUG "HiSax: invalid ioctl %d\n", (int) ic->arg); return(-EINVAL); } diff --git a/drivers/isdn/hisax/isar.h b/drivers/isdn/hisax/isar.h index c6ac6532b231e17ff6ec4f1f10332f152888f656..f2bc4820a92d1ca9bd87173aea94ff1069ed3545 100644 --- a/drivers/isdn/hisax/isar.h +++ b/drivers/isdn/hisax/isar.h @@ -1,10 +1,13 @@ -/* $Id: isar.h,v 1.5 1999/08/25 16:59:59 keil Exp $ +/* $Id: isar.h,v 1.6 1999/10/14 20:25:29 keil Exp $ * isar.h ISAR (Siemens PSB 7110) specific defines * * Author Karsten Keil (keil@isdn4linux.de) * * * $Log: isar.h,v $ + * Revision 1.6 1999/10/14 20:25:29 keil + * add a statistic for error monitoring + * * Revision 1.5 1999/08/25 16:59:59 keil * Make ISAR V32bis modem running * Make LL->HL interface open for additional commands @@ -178,12 +181,17 @@ #define HDLC_FSD 0x20 #define HDLC_FST 0x20 #define HDLC_ERROR 0x1c +#define HDLC_ERR_FAD 0x10 +#define HDLC_ERR_RER 0x08 +#define HDLC_ERR_CER 0x01 #define SART_NMD 0x01 #define BSTAT_RDM0 0x1 #define BSTAT_RDM1 0x2 #define BSTAT_RDM2 0x4 #define BSTAT_RDM3 0x8 +#define BSTEV_TBO 0x1f +#define BSTEV_RBO 0x2f extern int ISARVersion(struct IsdnCardState *cs, char *s); extern void isar_int_main(struct IsdnCardState *cs); diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c index c819c4811b5822255c4c6e74cc6e94be73bddcb8..7682170253e7637a661b52167ca8ce064c3ae1f1 100644 --- a/drivers/isdn/hisax/isdnl1.c +++ b/drivers/isdn/hisax/isdnl1.c @@ -318,12 +318,12 @@ DChannel_proc_rcv(struct IsdnCardState *cs) stptr = cs->stlist; if (skb->len<3) { debugl1(cs, "D-channel frame too short(%d)",skb->len); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if ((skb->data[0] & 1) || !(skb->data[1] &1)) { debugl1(cs, "D-channel frame wrong EA0/EA1"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } sapi = skb->data[0] >> 2; @@ -350,7 +350,7 @@ DChannel_proc_rcv(struct IsdnCardState *cs) stptr = stptr->next; } } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } else if (sapi == CTRL_SAPI) { /* sapi 0 */ found = 0; while (stptr != NULL) @@ -361,7 +361,7 @@ DChannel_proc_rcv(struct IsdnCardState *cs) } else stptr = stptr->next; if (!found) - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } } } diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c index ca721ea864b5810d87e5c0f79ca59546310b2f10..69e320262ccd0eec6e534f90b2580c3de4fb8e1f 100644 --- a/drivers/isdn/hisax/isdnl2.c +++ b/drivers/isdn/hisax/isdnl2.c @@ -201,7 +201,7 @@ freewin1(struct Layer2 *l2) for (i = 0; i < MAX_WINDOW; i++) { if (l2->windowar[i]) { cnt++; - idev_kfree_skb(l2->windowar[i], FREE_WRITE); + dev_kfree_skb(l2->windowar[i]); l2->windowar[i] = NULL; } } @@ -480,7 +480,7 @@ setva(struct PStack *st, unsigned int nr) len = l2->windowar[l2->sow]->len; if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type) len = -1; - idev_kfree_skb(l2->windowar[l2->sow], FREE_WRITE); + dev_kfree_skb(l2->windowar[l2->sow]); l2->windowar[l2->sow] = NULL; l2->sow = (l2->sow + 1) % l2->window; if (st->lli.l2writewakeup && (len >=0)) @@ -501,7 +501,6 @@ send_uframe(struct PStack *st, u_char cmd, u_char cr) printk(KERN_WARNING "isdl2 can't alloc sbbuff for send_uframe\n"); return; } - SET_SKB_FREE(skb); memcpy(skb_put(skb, i), tmp, i); enqueue_super(st, skb); } @@ -515,7 +514,7 @@ get_PollFlag(struct PStack * st, struct sk_buff * skb) inline void FreeSkb(struct sk_buff *skb) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } @@ -970,7 +969,6 @@ enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf) printk(KERN_WARNING "isdl2 can't alloc sbbuff for enquiry_cr\n"); return; } - SET_SKB_FREE(skb); memcpy(skb_put(skb, i), tmp, i); enqueue_super(st, skb); } @@ -1343,7 +1341,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) if (l2->windowar[p1]) { printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n", p1); - idev_kfree_skb(l2->windowar[p1], FREE_WRITE); + dev_kfree_skb(l2->windowar[p1]); } l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC); @@ -1367,7 +1365,6 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) "isdl2 pull_iqueue skb header(%d/%d) too short\n", i, p1); oskb = skb; skb = alloc_skb(oskb->len + i, GFP_ATOMIC); - SET_SKB_FREE(skb); memcpy(skb_put(skb, i), header, i); memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len); FreeSkb(oskb); @@ -1788,12 +1785,12 @@ isdnl2_l3l2(struct PStack *st, int pr, void *arg) switch (pr) { case (DL_DATA | REQUEST): if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) { - idev_kfree_skb((struct sk_buff *) arg, FREE_READ); + dev_kfree_skb((struct sk_buff *) arg); } break; case (DL_UNIT_DATA | REQUEST): if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) { - idev_kfree_skb((struct sk_buff *) arg, FREE_READ); + dev_kfree_skb((struct sk_buff *) arg); } break; case (DL_ESTABLISH | REQUEST): diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c index 458afe920984e0b9dd123941e08cd36492558ebc..6dc8bd9d06c8417ab97d9bed4b0d662b4096b22e 100644 --- a/drivers/isdn/hisax/isdnl3.c +++ b/drivers/isdn/hisax/isdnl3.c @@ -260,7 +260,6 @@ l3_alloc_skb(int len) printk(KERN_WARNING "HiSax: No skb for D-channel\n"); return (NULL); } - SET_SKB_FREE(skb); skb_reserve(skb, MAX_HEADER_LEN); return (skb); } @@ -272,7 +271,7 @@ no_l3_proto(struct PStack *st, int pr, void *arg) HiSax_putstatus(st->l1.hardware, "L3", "no D protocol"); if (skb) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } } diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c index dd713921a6c04af6b3465cd1b1532cbbb2684cda..245b40bc083a3ab60286471161cd568ca1e168d7 100644 --- a/drivers/isdn/hisax/isurf.c +++ b/drivers/isdn/hisax/isurf.c @@ -1,10 +1,13 @@ -/* $Id: isurf.c,v 1.5 1999/08/25 17:00:02 keil Exp $ +/* $Id: isurf.c,v 1.6 1999/09/04 06:20:06 keil Exp $ * isurf.c low level stuff for Siemens I-Surf/I-Talk cards * * Author Karsten Keil (keil@isdn4linux.de) * * $Log: isurf.c,v $ + * Revision 1.6 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.5 1999/08/25 17:00:02 keil * Make ISAR V32bis modem running * Make LL->HL interface open for additional commands @@ -34,7 +37,7 @@ extern const char *CardType[]; -static const char *ISurf_revision = "$Revision: 1.5 $"; +static const char *ISurf_revision = "$Revision: 1.6 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -154,10 +157,10 @@ reset_isurf(struct IsdnCardState *cs, u_char chips) byteout(cs->hw.isurf.reset, chips); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -206,8 +209,8 @@ isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { return(isar_auxcmd(cs, ic)); } -int __init -setup_isurf(struct IsdnCard *card) +__initfunc(int +setup_isurf(struct IsdnCard *card)) { int ver; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c index 389d043a342be409bae118179c71c3fbfcce584e..cb94d5bb392c3373434634886960c1a33df2ec26 100644 --- a/drivers/isdn/hisax/ix1_micro.c +++ b/drivers/isdn/hisax/ix1_micro.c @@ -282,8 +282,8 @@ ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg) } -int __init -setup_ix1micro(struct IsdnCard *card) +__initfunc(int +setup_ix1micro(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c index 5699f28a76dd51abb2c0aa47ced3b03568d7ef63..4f07eed875a921bea83024c5816f0105ddfd68d0 100644 --- a/drivers/isdn/hisax/jade.c +++ b/drivers/isdn/hisax/jade.c @@ -214,7 +214,7 @@ close_jadestate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c index 9cfcc7d6db91fb7eff8a38f90df1195829080581..e54c80c1a082d7978961c9a7e48df70a0e95da86 100644 --- a/drivers/isdn/hisax/jade_irq.c +++ b/drivers/isdn/hisax/jade_irq.c @@ -161,7 +161,6 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A")); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -177,7 +176,6 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) if (!(skb = dev_alloc_skb(fifo_size))) printk(KERN_WARNING "HiSax: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); skb_queue_tail(&bcs->rqueue, skb); } @@ -194,7 +192,7 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.hscx.count = 0; bcs->tx_skb = NULL; } diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c index ba8d95dbdb77ff20c18fe79196ad42226bc3ee97..31b25acdfc28b41244367be2ccf5f4ac8566b9bd 100644 --- a/drivers/isdn/hisax/l3_1tr6.c +++ b/drivers/isdn/hisax/l3_1tr6.c @@ -94,14 +94,14 @@ l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); l3_1tr6_release_req(pc, 0, NULL); } static void l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); if (pc->st->l3.debug & L3_DEB_WARN) l3_debug(pc->st, msg); l3_1tr6_release_req(pc, 0, NULL); @@ -251,7 +251,7 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg) if ((FAC_SPV == p[3]) || (FAC_Activate == p[3])) pc->para.spv = 1; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); /* Signal all services, linklevel takes care of Service-Indicator */ if (bcfound) { @@ -290,7 +290,7 @@ l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); L3AddTimer(&pc->timer, T304, CC_T304); pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } @@ -321,7 +321,7 @@ l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing call sent WE0_chanID", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); L3AddTimer(&pc->timer, T310, CC_T310); newl3state(pc, 3); pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); @@ -332,7 +332,7 @@ l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); L3DelTimer(&pc->timer); /* T304 */ newl3state(pc, 4); pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); @@ -363,7 +363,7 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg) } } else if (pc->st->l3.debug & L3_DEB_CHARGE) l3_debug(pc->st, "charging info not found"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } @@ -372,7 +372,7 @@ l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } static void @@ -386,7 +386,7 @@ l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg) return; } newl3state(pc, 10); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); pc->para.chargeinfo = 0; pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } @@ -414,7 +414,7 @@ l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing REL cause", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); StopAllL3Timer(pc); newl3state(pc, 0); l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1); @@ -427,7 +427,7 @@ l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); StopAllL3Timer(pc); newl3state(pc, 0); pc->para.cause = NO_CAUSE; @@ -484,7 +484,7 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing connack date", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); newl3state(pc, 12); pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); } @@ -499,7 +499,7 @@ l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing connack date", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); newl3state(pc, 10); pc->para.chargeinfo = 0; L3DelTimer(&pc->timer); @@ -814,7 +814,7 @@ up1tr6(struct PStack *st, int pr, void *arg) sprintf(tmp, "up1tr6 len only %d", skb->len); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) { @@ -824,7 +824,7 @@ up1tr6(struct PStack *st, int pr, void *arg) skb->data[0], skb->len); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if (skb->data[1] != 1) { @@ -832,13 +832,13 @@ up1tr6(struct PStack *st, int pr, void *arg) sprintf(tmp, "up1tr6 CR len not 1"); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } cr = skb->data[2]; mt = skb->data[3]; if (skb->data[0] == PROTO_DIS_N0) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "up1tr6%s N0 mt %x unhandled", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt); @@ -853,11 +853,11 @@ up1tr6(struct PStack *st, int pr, void *arg) sprintf(tmp, "up1tr6 no roc mem"); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } } else { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } } else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) || @@ -865,7 +865,7 @@ up1tr6(struct PStack *st, int pr, void *arg) (mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) || (mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) || (mt == MT_N1_INFO)) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else { if (!(proc = new_l3_process(st, cr))) { @@ -873,7 +873,7 @@ up1tr6(struct PStack *st, int pr, void *arg) sprintf(tmp, "up1tr6 no roc mem"); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } mt = MT_N1_INVALID; @@ -884,7 +884,7 @@ up1tr6(struct PStack *st, int pr, void *arg) ((1 << proc->state) & datastln1[i].state)) break; if (i == DATASTLN1_LEN) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "up1tr6%sstate %d mt %x unhandled", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c index 22a5de9fa7ba783200d626a35663ee52658a0208..035ee54ca32d5798794271caedaf633ec93cbfa8 100644 --- a/drivers/isdn/hisax/l3dss1.c +++ b/drivers/isdn/hisax/l3dss1.c @@ -1,4 +1,4 @@ -/* $Id: l3dss1.c,v 2.19 1999/08/25 16:55:23 keil Exp $ +/* $Id: l3dss1.c,v 2.20 1999/10/11 22:16:27 keil Exp $ * EURO/DSS1 D-channel protocol * @@ -13,6 +13,9 @@ * Fritz Elfert * * $Log: l3dss1.c,v $ + * Revision 2.20 1999/10/11 22:16:27 keil + * Suspend/Resume is possible without explicit ID too + * * Revision 2.19 1999/08/25 16:55:23 keil * Fix for test case TC10011 * @@ -90,7 +93,7 @@ #include <linux/ctype.h> extern char *HiSax_getrev(const char *revision); -const char *dss1_revision = "$Revision: 2.19 $"; +const char *dss1_revision = "$Revision: 2.20 $"; #define EXT_BEARER_CAPS 1 @@ -2520,14 +2523,13 @@ l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg) u_char *msg = pc->chan->setup.phone; MsgHead(p, pc->callref, MT_SUSPEND); - - *p++ = IE_CALL_ID; l = *msg++; if (l && (l <= 10)) { /* Max length 10 octets */ + *p++ = IE_CALL_ID; *p++ = l; for (i = 0; i < l; i++) *p++ = *msg++; - } else { + } else if (l) { l3_debug(pc->st, "SUS wrong CALL_ID len %d", l); return; } @@ -2596,13 +2598,13 @@ l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg) MsgHead(p, pc->callref, MT_RESUME); - *p++ = IE_CALL_ID; l = *msg++; if (l && (l <= 10)) { /* Max length 10 octets */ + *p++ = IE_CALL_ID; *p++ = l; for (i = 0; i < l; i++) *p++ = *msg++; - } else { + } else if (l) { l3_debug(pc->st, "RES wrong CALL_ID len %d", l); return; } @@ -2976,7 +2978,7 @@ dss1up(struct PStack *st, int pr, void *arg) } if (skb->len < 3) { l3_debug(st, "dss1up frame too short(%d)", skb->len); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } @@ -2986,13 +2988,13 @@ dss1up(struct PStack *st, int pr, void *arg) (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", skb->data[0], skb->len); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } cr = getcallref(skb->data); if (skb->len < ((skb->data[1] & 0x0f) + 3)) { l3_debug(st, "dss1up frame too short(%d)", skb->len); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } mt = skb->data[skb->data[1] + 2]; @@ -3001,26 +3003,26 @@ dss1up(struct PStack *st, int pr, void *arg) if (cr == -2) { /* wrong Callref */ if (st->l3.debug & L3_DEB_WARN) l3_debug(st, "dss1up wrong Callref"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else if (cr == -1) { /* Dummy Callref */ if (mt == MT_FACILITY) if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) { l3dss1_parse_facility(st, NULL, (pr == (DL_DATA | INDICATION)) ? -1 : -2, p); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if (st->l3.debug & L3_DEB_WARN) l3_debug(st, "dss1up dummy Callref (no facility msg or ie)"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) || (((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) { /* Global CallRef */ if (st->l3.debug & L3_DEB_STATE) l3_debug(st, "dss1up Global CallRef"); global_handler(st, mt, skb); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else if (!(proc = getl3proc(st, cr))) { /* No transaction process exist, that means no call with @@ -3032,7 +3034,7 @@ dss1up(struct PStack *st, int pr, void *arg) /* Setup with wrong CREF flag */ if (st->l3.debug & L3_DEB_STATE) l3_debug(st, "dss1up wrong CRef flag"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if (!(proc = dss1_new_l3_process(st, cr))) { @@ -3040,7 +3042,7 @@ dss1up(struct PStack *st, int pr, void *arg) * CAUSE 0x2f "Resource unavailable", but this * need a new_l3_process too ... arghh */ - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } } else if (mt == MT_STATUS) { @@ -3074,17 +3076,17 @@ dss1up(struct PStack *st, int pr, void *arg) l3dss1_msg_without_setup(proc, 0, NULL); } } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else if (mt == MT_RELEASE_COMPLETE) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else { /* ETS 300-104 part 2 * if setup has not been made and a message type * (except MT_SETUP and RELEASE_COMPLETE) is received, * we must send MT_RELEASE_COMPLETE cause 81 */ - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); if ((proc = dss1_new_l3_process(st, cr))) { proc->para.cause = 81; l3dss1_msg_without_setup(proc, 0, NULL); @@ -3093,7 +3095,7 @@ dss1up(struct PStack *st, int pr, void *arg) } } if (l3dss1_check_messagetype_validity(proc, mt, skb)) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL) @@ -3120,7 +3122,7 @@ dss1up(struct PStack *st, int pr, void *arg) } datastatelist[i].rout(proc, pr, skb); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } diff --git a/drivers/isdn/hisax/md5sums.asc b/drivers/isdn/hisax/md5sums.asc index 481a7dc720ea628853dafacfd267654bea1a1dbe..985bd4cb416c336ff40087b28ce0a2bad18b629c 100644 --- a/drivers/isdn/hisax/md5sums.asc +++ b/drivers/isdn/hisax/md5sums.asc @@ -6,26 +6,26 @@ # Eicon Technology Diva 2.01 PCI cards in the moment. # Read ../../../Documentation/isdn/HiSax.cert for more informations. # -0cc164fadd4ec0e2983ec9735e209cbd isac.c -5fe8cb5526c78c91f61b0a94a423ea5d isdnl1.c -3b9522e8bf9e1c3e7848d729fc3dc05d isdnl2.c -f4184a50e35e5b568608e6cb7a693319 isdnl3.c -ef70f4269fdc2ca15100f9b776afaa0d tei.c -65be616dd9d0e06c788d4fdd0fe5fe0a callc.c +3c2b1c96274cba97a8261d1cecc662b8 isac.c +a9a15d069dbacb383cc24c238cb5ebbe isdnl1.c +bb51bd223040b511c18f091da5ab6456 isdnl2.c +b7aa7f97b2374967a4aca7c52991142c isdnl3.c +a23fbf8879c1432b04640b8b04bdf419 tei.c +d7072dbbeeb7c4c45f3810ed13cf5545 callc.c bf9605b36429898f7be6630034e83230 cert.c -97c5e31c2739665b9c2976a30ce0b357 l3dss1.c -b674eee9314a7cc413971c84003cf1d2 l3_1tr6.c -51b2ef1efb221bb09fd08ab28bd2c565 elsa.c -24cda374da44b57f6a1bb215424267b5 diva.c +0e500813968adacaea2ef22c9cdd89eb l3dss1.c +2d748ced0eea375b21fe7ea91ca7917c l3_1tr6.c +d45fde1c90dda636ab134f2a51db435e elsa.c +0b5fb429f5bfe188fd42a5be01abbb14 diva.c # end of md5sums -----BEGIN PGP SIGNATURE----- Version: 2.6.3i Charset: noconv -iQCVAwUBN8RgFjpxHvX/mS9tAQFzFQP/dOgnppDIm5ug1hnlWjQ/0BVurKEEJ64r -DYDHwkcog+0gVE/EB1A7WUDqpFEnj52OZeoVinCfdVuVjP8IkrAJ8dCONsnXjBXz -pzM+FunP1LFxuv2TVM0f642j98JxS8rObGWH8ZwY36P2QfNp47zorO2F9WvdCkuz -sxJUtMUOlQ8= -=8uEP +iQCVAwUBOCYF6jpxHvX/mS9tAQFnxQP/dpHyNjbo5BhFEZ8qIgpPJzoCgV+b2pB+ +h9Z/Q1jg8l23L/lP9dW00ogrKnKziVUUJqg+wWVEAA7BnNVr3aeyQKFTVuOnK5MC +Oy0Z98p530vgOBiZ47elNfpefjhfD3duSSYNA4R9fEHVZB/atKFYvB5GDGmrwjIZ +2f3g3kBP5Os= +=zNnO -----END PGP SIGNATURE----- diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c index fa85bbd27a7846a469f265ce457d4391e1f7151b..be65f1101ca09adda2addcc7cd08fdd0a76136b1 100644 --- a/drivers/isdn/hisax/mic.c +++ b/drivers/isdn/hisax/mic.c @@ -224,8 +224,8 @@ mic_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_mic(struct IsdnCard *card) +__initfunc(int +setup_mic(struct IsdnCard *card)) { int bytecnt; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index d88442e377d3e17ec44b5fc0b21f59c98c2c4527..3b502f7dbe4eefe943e97027f41fb29898705054 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -1,4 +1,4 @@ -/* $Id: netjet.c,v 1.13 1999/08/11 21:01:31 keil Exp $ +/* $Id: netjet.c,v 1.16 1999/10/14 20:25:29 keil Exp $ * netjet.c low level stuff for Traverse Technologie NETJet ISDN cards * @@ -7,6 +7,15 @@ * Thanks to Traverse Technologie Australia for documents and informations * * $Log: netjet.c,v $ + * Revision 1.16 1999/10/14 20:25:29 keil + * add a statistic for error monitoring + * + * Revision 1.15 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * + * Revision 1.14 1999/08/31 11:20:25 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.13 1999/08/11 21:01:31 keil * new PCI codefix * @@ -59,9 +68,6 @@ #include "hscx.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #include <linux/interrupt.h> #include <linux/ppp_defs.h> @@ -75,7 +81,7 @@ extern const char *CardType[]; -const char *NETjet_revision = "$Revision: 1.13 $"; +const char *NETjet_revision = "$Revision: 1.16 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -406,7 +412,6 @@ static void got_frame(struct BCState *bcs, int count) { if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "TIGER: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -526,19 +531,26 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){ debugl1(bcs->cs, "tiger: frame not byte aligned"); state=HDLC_FLAG_SEARCH; bcs->hw.tiger.r_err++; +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif } else { if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs,"tiger frame end(%d,%d): fcs(%x) i %x", i,j,bcs->hw.tiger.r_fcs, bcs->cs->hw.njet.irqstat0); if (bcs->hw.tiger.r_fcs == PPP_GOODFCS) { got_frame(bcs, (bitcnt>>3)-3); - } else + } else { if (bcs->cs->debug) { debugl1(bcs->cs, "tiger FCS error"); printframe(bcs->cs, bcs->hw.tiger.rcvbuf, (bitcnt>>3)-1, "rec"); bcs->hw.tiger.r_err++; } +#ifdef ERROR_STATISTIC + bcs->err_crc++; +#endif + } state=HDLC_FLAG_FOUND; } bitcnt=0; @@ -556,10 +568,13 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){ if ((state == HDLC_FRAME_FOUND) && !(bitcnt & 7)) { if ((bitcnt>>3)>=HSCX_BUFMAX) { - debugl1(bcs->cs, "tiger: frame to big"); + debugl1(bcs->cs, "tiger: frame too big"); r_val=0; state=HDLC_FLAG_SEARCH; bcs->hw.tiger.r_err++; +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif } else { bcs->hw.tiger.rcvbuf[(bitcnt>>3)-1] = r_val; bcs->hw.tiger.r_fcs = @@ -584,6 +599,12 @@ static void read_tiger(struct IsdnCardState *cs) { if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) { debugl1(cs,"tiger warn read double dma %x/%x", cs->hw.njet.irqstat0, cs->hw.njet.last_is0); +#ifdef ERROR_STATISTIC + if (cs->bcs[0].mode) + cs->bcs[0].err_rdo++; + if (cs->bcs[1].mode) + cs->bcs[1].err_rdo++; +#endif return; } else { cs->hw.njet.last_is0 &= ~NETJET_IRQM0_READ; @@ -705,7 +726,7 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) { if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); @@ -755,6 +776,12 @@ static void write_tiger(struct IsdnCardState *cs) { if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) { debugl1(cs,"tiger warn write double dma %x/%x", cs->hw.njet.irqstat0, cs->hw.njet.last_is0); +#ifdef ERROR_STATISTIC + if (cs->bcs[0].mode) + cs->bcs[0].err_tx++; + if (cs->bcs[1].mode) + cs->bcs[1].err_tx++; +#endif return; } else { cs->hw.njet.last_is0 &= ~NETJET_IRQM0_WRITE; @@ -842,7 +869,7 @@ close_tigerstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -889,8 +916,8 @@ setstack_tiger(struct PStack *st, struct BCState *bcs) } -void __init -inittiger(struct IsdnCardState *cs) +__initfunc(void +inittiger(struct IsdnCardState *cs)) { if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int), GFP_KERNEL | GFP_DMA))) { @@ -1027,11 +1054,11 @@ reset_netjet(struct IsdnCardState *cs) sti(); cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ restore_flags(flags); cs->hw.njet.auxd = 0; @@ -1074,23 +1101,15 @@ NETjet_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_netjet __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_netjet(struct IsdnCard *card) +__initfunc(int +setup_netjet(struct IsdnCard *card)) { int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; #if CONFIG_PCI -#ifndef COMPAT_HAS_NEW_PCI - u_char pci_bus, pci_device_fn, pci_irq; - u_int pci_ioaddr, found; -#endif #endif strcpy(tmp, NETjet_revision); printk(KERN_INFO "HiSax: Traverse Tech. NETjet driver Rev. %s\n", HiSax_getrev(tmp)); @@ -1098,7 +1117,6 @@ setup_netjet(struct IsdnCard *card) return(0); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Netjet: no PCI bus present\n"); return(0); @@ -1110,7 +1128,7 @@ setup_netjet(struct IsdnCard *card) printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n"); return(0); } - cs->hw.njet.base = get_pcibase(dev_netjet, 0) + cs->hw.njet.base = dev_netjet->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK; if (!cs->hw.njet.base) { printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n"); @@ -1120,41 +1138,6 @@ setup_netjet(struct IsdnCard *card) printk(KERN_WARNING "NETjet: No PCI card found\n"); return(0); } -#else - found = 0; - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(PCI_VENDOR_TRAVERSE_TECH, - PCI_NETJET_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - found = 1; - else - continue; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - /* get IO address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - if (found) - break; - } - if (!found) { - printk(KERN_WARNING "NETjet: No PCI card found\n"); - return(0); - } - pci_index++; - if (!pci_irq) { - printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n"); - return(0); - } - if (!pci_ioaddr) { - printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n"); - return(0); - } - cs->hw.njet.base = pci_ioaddr & PCI_BASE_ADDRESS_IO_MASK; - cs->irq = pci_irq; -#endif /* COMPAT_HAS_NEW_PCI */ cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; bytecnt = 256; diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c index 7574a8e8fb64a5cfc24dc57e5a1120ad27b85263..4198bb5e0fa3f9822380f0098bcb84b0b0438f7e 100644 --- a/drivers/isdn/hisax/niccy.c +++ b/drivers/isdn/hisax/niccy.c @@ -40,9 +40,6 @@ #include "hscx.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; const char *niccy_revision = "$Revision: 1.8 $"; @@ -259,14 +256,10 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *niccy_dev __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_niccy(struct IsdnCard *card) +__initfunc(int +setup_niccy(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; @@ -306,7 +299,6 @@ setup_niccy(struct IsdnCard *card) } else { #if CONFIG_PCI u_int pci_ioaddr; -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Niccy: no PCI bus present\n"); return(0); @@ -320,66 +312,21 @@ setup_niccy(struct IsdnCard *card) return(0); } cs->irq = niccy_dev->irq; - if (!get_pcibase(niccy_dev, 0)) { + if (!niccy_dev->resource[ 0].start) { printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); return(0); } - cs->hw.niccy.cfg_reg = get_pcibase(niccy_dev, 0) & PCI_BASE_ADDRESS_IO_MASK; - if (!get_pcibase(niccy_dev, 1)) { + cs->hw.niccy.cfg_reg = niccy_dev->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK; + if (!niccy_dev->resource[ 1].start) { printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); return(0); } - pci_ioaddr = get_pcibase(niccy_dev, 1) & PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr = niccy_dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; cs->subtyp = NICCY_PCI; } else { printk(KERN_WARNING "Niccy: No PCI card found\n"); return(0); } -#else - u_char pci_bus, pci_device_fn, pci_irq; - - cs->subtyp = 0; - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(PCI_VENDOR_DR_NEUHAUS, - PCI_NICCY_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = NICCY_PCI; - else - continue; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - /* get IO pci AMCC address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - if (!pci_ioaddr) { - printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); - return(0); - } - cs->hw.niccy.cfg_reg = pci_ioaddr & ~3 ; - /* get IO address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr); - if (cs->subtyp) - break; - } - if (!cs->subtyp) { - printk(KERN_WARNING "Niccy: No PCI card found\n"); - return(0); - } - pci_index++; - if (!pci_irq) { - printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n"); - return(0); - } - if (!pci_ioaddr) { - printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); - return(0); - } - pci_ioaddr &= ~3; /* remove io/mem flag */ - cs->irq = pci_irq; -#endif /* COMPAT_HAS_NEW_PCI */ cs->irq_flags |= SA_SHIRQ; cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c index d8dfb2ee3f0606fa60ca47d37dab6b97942c3de8..51bc116584160cc5563b262f7be7249bc2aee536 100644 --- a/drivers/isdn/hisax/s0box.c +++ b/drivers/isdn/hisax/s0box.c @@ -212,8 +212,8 @@ S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_s0box(struct IsdnCard *card) +__initfunc(int +setup_s0box(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c index 0d524faa869bc35d388d887dac9a139f765807c8..955a9a4de400ee136a4b1ee3be657ec4f093b16d 100644 --- a/drivers/isdn/hisax/saphir.c +++ b/drivers/isdn/hisax/saphir.c @@ -1,4 +1,4 @@ -/* $Id: saphir.c,v 1.3 1999/07/12 21:05:26 keil Exp $ +/* $Id: saphir.c,v 1.4 1999/09/04 06:20:06 keil Exp $ * saphir.c low level stuff for HST Saphir 1 * @@ -8,6 +8,9 @@ * * * $Log: saphir.c,v $ + * Revision 1.4 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.3 1999/07/12 21:05:26 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -26,7 +29,7 @@ #include "isdnl1.h" extern const char *CardType[]; -static char *saphir_rev = "$Revision: 1.3 $"; +static char *saphir_rev = "$Revision: 1.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -234,10 +237,10 @@ saphir_reset(struct IsdnCardState *cs) save_flags(flags); sti(); byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ restore_flags(flags); byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val); @@ -265,8 +268,8 @@ saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg) } -int __init -setup_saphir(struct IsdnCard *card) +__initfunc(int +setup_saphir(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 2640555b2d374f49e0ee91cc10b819320f0ae74f..daa7953d9033c3b8b095cd7bae49fe2e47f5252e 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -1,4 +1,4 @@ -/* $Id: sedlbauer.c,v 1.16 1999/08/29 18:23:01 niemann Exp $ +/* $Id: sedlbauer.c,v 1.17 1999/09/04 06:20:06 keil Exp $ * sedlbauer.c low level stuff for Sedlbauer cards * includes support for the Sedlbauer speed star (speed star II), @@ -17,6 +17,9 @@ * Edgar Toernig * * $Log: sedlbauer.c,v $ + * Revision 1.17 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.16 1999/08/29 18:23:01 niemann * Fixed typo in errormsg * @@ -100,13 +103,10 @@ #include "isar.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; -const char *Sedlbauer_revision = "$Revision: 1.16 $"; +const char *Sedlbauer_revision = "$Revision: 1.17 $"; const char *Sedlbauer_Types[] = {"None", "speed card/win", "speed star", "speed fax+", @@ -474,10 +474,10 @@ reset_sedlbauer(struct IsdnCardState *cs) writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20); save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff); @@ -489,10 +489,10 @@ reset_sedlbauer(struct IsdnCardState *cs) byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -542,15 +542,11 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) } #ifdef SEDLBAUER_PCI -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_sedl __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif #endif -int __init -setup_sedlbauer(struct IsdnCard *card) +__initfunc(int +setup_sedlbauer(struct IsdnCard *card)) { int bytecnt, ver, val; struct IsdnCardState *cs = card->cs; @@ -585,7 +581,6 @@ setup_sedlbauer(struct IsdnCard *card) /* Probe for Sedlbauer speed pci */ #if SEDLBAUER_PCI #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Sedlbauer: no PCI bus present\n"); return(0); @@ -597,41 +592,12 @@ setup_sedlbauer(struct IsdnCard *card) printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); return(0); } - cs->hw.sedl.cfg_reg = get_pcibase(dev_sedl, 0) & + cs->hw.sedl.cfg_reg = dev_sedl->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK; } else { printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); return(0); } -#else - for (; pci_index < 255; pci_index++) { - unsigned char pci_bus, pci_device_fn; - unsigned int ioaddr; - unsigned char irq; - - if (pcibios_find_device (PCI_VENDOR_SEDLBAUER, - PCI_SPEEDPCI_ID, pci_index, - &pci_bus, &pci_device_fn) != 0) { - continue; - } - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &irq); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &ioaddr); - cs->irq = irq; - cs->hw.sedl.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK; - if (!cs->hw.sedl.cfg_reg) { - printk(KERN_WARNING "Sedlbauer: No IO-Adr for PCI card found\n"); - return(0); - } - break; - } - if (pci_index == 255) { - printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); - return(0); - } - pci_index++; -#endif /* COMPAT_HAS_NEW_PCI */ cs->irq_flags |= SA_SHIRQ; cs->hw.sedl.bus = SEDL_BUS_PCI; cs->hw.sedl.chip = SEDL_CHIP_IPAC; diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c index 29fae02f7c39d5afca279aee25f32df405d1aa0b..91a6a6ae18da5c4f2375342d26d5e0573c198c8c 100644 --- a/drivers/isdn/hisax/sportster.c +++ b/drivers/isdn/hisax/sportster.c @@ -1,4 +1,4 @@ -/* $Id: sportster.c,v 1.9 1999/07/12 21:05:29 keil Exp $ +/* $Id: sportster.c,v 1.10 1999/09/04 06:20:06 keil Exp $ * sportster.c low level stuff for USR Sportster internal TA * @@ -7,6 +7,9 @@ * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation * * $Log: sportster.c,v $ + * Revision 1.10 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.9 1999/07/12 21:05:29 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -43,7 +46,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *sportster_revision = "$Revision: 1.9 $"; +const char *sportster_revision = "$Revision: 1.10 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -177,11 +180,11 @@ reset_sportster(struct IsdnCardState *cs) byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -208,8 +211,8 @@ Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -get_io_range(struct IsdnCardState *cs) +__initfunc(int +get_io_range(struct IsdnCardState *cs)) { int i, j, adr; @@ -234,8 +237,8 @@ get_io_range(struct IsdnCardState *cs) } } -int __init -setup_sportster(struct IsdnCard *card) +__initfunc(int +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 f21284bece2c2a9a99a0f69af2e2467d38bc2ca2..8454f1554ac5e0bb2daf7f3fe6a480115aafcf3b 100644 --- a/drivers/isdn/hisax/tei.c +++ b/drivers/isdn/hisax/tei.c @@ -169,7 +169,6 @@ put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei) printk(KERN_WARNING "HiSax: No skb for TEI manager\n"); return; } - SET_SKB_FREE(skb); bp = skb_put(skb, 3); bp[0] = (TEI_SAPI << 2); bp[1] = (GROUP_TEI << 1) | 0x1; @@ -371,7 +370,7 @@ tei_l1l2(struct PStack *st, int pr, void *arg) int mt; if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } @@ -417,7 +416,7 @@ tei_l1l2(struct PStack *st, int pr, void *arg) st->ma.tei_m.printdebug(&st->ma.tei_m, "tei handler wrong pr %x\n", pr); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } static void diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c index 430ea2768f99eb757dd8d7c54ea062b302e9f370..c34dc5613b2ba58eb037c7be6dff5e83f5715d82 100644 --- a/drivers/isdn/hisax/teleint.c +++ b/drivers/isdn/hisax/teleint.c @@ -1,4 +1,4 @@ -/* $Id: teleint.c,v 1.9 1999/07/12 21:05:30 keil Exp $ +/* $Id: teleint.c,v 1.11 1999/09/04 06:20:06 keil Exp $ * teleint.c low level stuff for TeleInt isdn cards * @@ -6,6 +6,12 @@ * * * $Log: teleint.c,v $ + * Revision 1.11 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * + * Revision 1.10 1999/08/31 11:20:27 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.9 1999/07/12 21:05:30 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -45,7 +51,7 @@ extern const char *CardType[]; -const char *TeleInt_revision = "$Revision: 1.9 $"; +const char *TeleInt_revision = "$Revision: 1.11 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -64,7 +70,7 @@ readreg(unsigned int ale, unsigned int adr, u_char off) while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { - printk(KERN_WARNING "TeleInt Busy not inaktive\n"); + printk(KERN_WARNING "TeleInt Busy not inactive\n"); restore_flags(flags); return (0); } @@ -86,7 +92,7 @@ readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { - printk(KERN_WARNING "TeleInt Busy not inaktive\n"); + printk(KERN_WARNING "TeleInt Busy not inactive\n"); return; } data[i] = bytein(adr); @@ -108,7 +114,7 @@ writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { - printk(KERN_WARNING "TeleInt Busy not inaktive\n"); + printk(KERN_WARNING "TeleInt Busy not inactive\n"); restore_flags(flags); return; } @@ -130,7 +136,7 @@ writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int siz while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { - printk(KERN_WARNING "TeleInt Busy not inaktive\n"); + printk(KERN_WARNING "TeleInt Busy not inactive\n"); return; } byteout(adr, data[i]); @@ -254,11 +260,11 @@ reset_TeleInt(struct IsdnCardState *cs) byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30*HZ)/1000); cs->hw.hfc.cirm &= ~HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -289,8 +295,8 @@ TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_TeleInt(struct IsdnCard *card) +__initfunc(int +setup_TeleInt(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c index 4046c4357d25ee8a75c670eaff958a729b6d0a89..866e8dac5effc29f1b5f4d2f02aaa885b0d5f290 100644 --- a/drivers/isdn/hisax/teles0.c +++ b/drivers/isdn/hisax/teles0.c @@ -295,8 +295,8 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_teles0(struct IsdnCard *card) +__initfunc(int +setup_teles0(struct IsdnCard *card)) { u_char val; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c index 3210a6af68a1adea9b291c84be9d369e1e0ab5d4..0db245abcfc860b28ef83761d8eade039cfd1e8b 100644 --- a/drivers/isdn/hisax/teles3.c +++ b/drivers/isdn/hisax/teles3.c @@ -321,8 +321,8 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_teles3(struct IsdnCard *card) +__initfunc(int +setup_teles3(struct IsdnCard *card)) { u_char val; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c index 9ffe99918bb8cd9b7b42bdac10c63f8eae971c5d..eee4ba322b56b5a7476e8c7c53c1de1ad4bdcad4 100644 --- a/drivers/isdn/hisax/telespci.c +++ b/drivers/isdn/hisax/telespci.c @@ -42,9 +42,6 @@ #include "hscx.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; const char *telespci_revision = "$Revision: 2.9 $"; @@ -304,29 +301,19 @@ TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_tel __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_telespci(struct IsdnCard *card) +__initfunc(int +setup_telespci(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; -#ifndef COMPAT_HAS_NEW_PCI - u_char pci_bus, pci_device_fn, pci_irq; - u_int pci_memaddr; - u_char found = 0; -#endif strcpy(tmp, telespci_revision); printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_TELESPCI) return (0); #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "TelesPCI: no PCI bus present\n"); return(0); @@ -337,40 +324,14 @@ setup_telespci(struct IsdnCard *card) printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); return(0); } - cs->hw.teles0.membase = (u_int) ioremap(get_pcibase(dev_tel, 0), + cs->hw.teles0.membase = (u_int) ioremap(dev_tel->resource[ 0].start, PAGE_SIZE); printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n", - get_pcibase(dev_tel, 0), dev_tel->irq); + dev_tel->resource[ 0].start, dev_tel->irq); } else { printk(KERN_WARNING "TelesPCI: No PCI card found\n"); return(0); } -#else - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device (0x11DE, 0x6120, - pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) { - found = 1; - } else { - break; - } - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_memaddr); - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - printk(KERN_INFO "Found: Zoran, base-address: 0x%x," - " irq: 0x%x\n", pci_memaddr, pci_irq); - break; - } - if (!found) { - printk(KERN_WARNING "TelesPCI: No PCI card found\n"); - return(0); - } - pci_index++; - cs->irq = pci_irq; - cs->hw.teles0.membase = (u_int) vremap(pci_memaddr, PAGE_SIZE); -#endif /* COMPAT_HAS_NEW_PCI */ #else printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n"); printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n"); diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c new file mode 100644 index 0000000000000000000000000000000000000000..724ce52c9913d7f0e9ffbf6cd4f538c10561f48e --- /dev/null +++ b/drivers/isdn/hisax/w6692.c @@ -0,0 +1,1063 @@ +/* $Id: w6692.c,v 1.1 1999/09/04 06:28:58 keil Exp $ + + * w6692.c Winbond W6692 specific routines + * + * Author Petr Novak <petr.novak@i.cz> + * (based on HiSax driver by Karsten Keil) + * + * This file is (c) under GNU PUBLIC LICENSE + * + * $Log: w6692.c,v $ + * Revision 1.1 1999/09/04 06:28:58 keil + * first revision + * + * + * + */ + +#include <linux/config.h> +#define __NO_VERSION__ +#include "hisax.h" +#include "w6692.h" +#include "isdnl1.h" +#include <linux/interrupt.h> +#include <linux/pci.h> + +#define PCI_VEND_ASUSCOM 0x675 +#define PCI_DEV_ASUSCOMPCI1 0x1702 +#ifndef PCI_VENDOR_ID_WINBOND2 +#define PCI_VENDOR_ID_WINBOND2 0x1050 +#endif +#define PCI_DEVICE_W6692 0x6692 + +/* table entry in the PCI devices list */ +typedef struct { + int vendor_id; + int device_id; + char *vendor_name; + char *card_name; +} PCI_ENTRY; + +static const PCI_ENTRY id_list[] = +{ + {PCI_VEND_ASUSCOM, PCI_DEV_ASUSCOMPCI1, "AsusCom", "TA XXX"}, + {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_W6692, "Winbond", "W6692"}, + {0, 0, NULL, NULL} +}; + +extern const char *CardType[]; + +const char *w6692_revision = "$Revision: 1.1 $"; + +#define DBUSY_TIMER_VALUE 80 + +static char *W6692Ver[] HISAX_INITDATA = +{"W6692 V00", "W6692 V01", "W6692 V10", + "W6692 V11"}; + +static void +W6692Version(struct IsdnCardState *cs, char *s) +{ + int val; + + val = cs->readW6692(cs, W_D_RBCH); + printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]); +} + +static void +ph_command(struct IsdnCardState *cs, unsigned int command) +{ + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ph_command %x", command); + cs->writeisac(cs, W_CIX, command); +} + + +static void +W6692_new_ph(struct IsdnCardState *cs) +{ + switch (cs->dc.w6692.ph_state) { + case (W_L1CMD_RST): + ph_command(cs, W_L1CMD_DRC); + l1_msg(cs, HW_RESET | INDICATION, NULL); + /* fallthru */ + case (W_L1IND_CD): + l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL); + break; + case (W_L1IND_DRD): + l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); + break; + case (W_L1IND_CE): + l1_msg(cs, HW_POWERUP | CONFIRM, NULL); + break; + case (W_L1IND_LD): + l1_msg(cs, HW_RSYNC | INDICATION, NULL); + break; + case (W_L1IND_ARD): + l1_msg(cs, HW_INFO2 | INDICATION, NULL); + break; + case (W_L1IND_AI8): + l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); + break; + case (W_L1IND_AI10): + l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL); + break; + default: + break; + } +} + +static void +W6692_bh(struct IsdnCardState *cs) +{ + struct PStack *stptr; + + if (!cs) + return; + if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { + if (cs->debug) + debugl1(cs, "D-Channel Busy cleared"); + stptr = cs->stlist; + while (stptr != NULL) { + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr = stptr->next; + } + } + if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) + W6692_new_ph(cs); + if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) + DChannel_proc_rcv(cs); + if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) + DChannel_proc_xmt(cs); +/* + if (test_and_clear_bit(D_RX_MON1, &cs->event)) + arcofi_fsm(cs, ARCOFI_RX_END, NULL); + if (test_and_clear_bit(D_TX_MON1, &cs->event)) + arcofi_fsm(cs, ARCOFI_TX_END, NULL); + */ +} + +void +W6692_sched_event(struct IsdnCardState *cs, int event) +{ + test_and_set_bit(event, &cs->event); + queue_task(&cs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +static void +W6692B_sched_event(struct BCState *bcs, int event) +{ + bcs->event |= 1 << event; + queue_task(&bcs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +static void +W6692_empty_fifo(struct IsdnCardState *cs, int count) +{ + u_char *ptr; + long flags; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "W6692_empty_fifo"); + + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692_empty_fifo overrun %d", + cs->rcvidx + count); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); + cs->rcvidx = 0; + return; + } + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + save_flags(flags); + cli(); + cs->readW6692fifo(cs, ptr, count); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); + restore_flags(flags); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "W6692_empty_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } +} + +static void +W6692_fill_fifo(struct IsdnCardState *cs) +{ + int count, more; + u_char *ptr; + long flags; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "W6692_fill_fifo"); + + if (!cs->tx_skb) + return; + + count = cs->tx_skb->len; + if (count <= 0) + return; + + more = 0; + if (count > W_D_FIFO_THRESH) { + more = !0; + count = W_D_FIFO_THRESH; + } + save_flags(flags); + cli(); + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeW6692fifo(cs, ptr, count); + cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME)); + restore_flags(flags); + if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { + debugl1(cs, "W6692_fill_fifo dbusytimer running"); + del_timer(&cs->dbusytimer); + } + init_timer(&cs->dbusytimer); + cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); + add_timer(&cs->dbusytimer); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "W6692_fill_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } +} + +static void +W6692B_empty_fifo(struct BCState *bcs, int count) +{ + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + long flags; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "W6692B_empty_fifo"); + + if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692B_empty_fifo: incoming packet too large"); + cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + bcs->hw.w6692.rcvidx = 0; + return; + } + ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx; + bcs->hw.w6692.rcvidx += count; + save_flags(flags); + cli(); + READW6692BFIFO(cs, bcs->hw.w6692.bchan, ptr, count); + cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + restore_flags(flags); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "W6692B_empty_fifo %c cnt %d", + bcs->hw.w6692.bchan ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } +} + +static void +W6692B_fill_fifo(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + int more, count; + u_char *ptr; + long flags; + + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "W6692B_fill_fifo"); + + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) + return; + + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > W_B_FIFO_THRESH) { + more = !0; + count = W_B_FIFO_THRESH; + } else + count = bcs->tx_skb->len; + + save_flags(flags); + cli(); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.w6692.count += count; + WRITEW6692BFIFO(cs, bcs->hw.w6692.bchan, ptr, count); + cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME)); + restore_flags(flags); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "W6692B_fill_fifo %c cnt %d", + bcs->hw.w6692.bchan ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } +} + +static void +W6692B_interrupt(struct IsdnCardState *cs, u_char bchan) +{ + u_char val; + u_char r; + struct BCState *bcs = cs->bcs + bchan; + struct sk_buff *skb; + int count; + + val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR); + debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val); + + if (!test_bit(BC_FLG_INIT, &bcs->Flag)) { + debugl1(cs, "W6692B not INIT yet"); + return; + } + if (val & W_B_EXI_RME) { /* RME */ + r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); + if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB | W_B_STAR_XDOW)) { + if ((r & W_B_STAR_RDOV) && bcs->mode) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B RDOV mode=%d", + bcs->mode); + if (r & W_B_STAR_CRCE) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B CRC error"); + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); + } else { + count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1); + if (count == 0) + count = W_B_FIFO_THRESH; + W6692B_empty_fifo(bcs, count); + if ((count = bcs->hw.w6692.rcvidx) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "W6692 Bchan Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "W6692: Bchan receive out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } + } + bcs->hw.w6692.rcvidx = 0; + W6692B_sched_event(bcs, B_RCVBUFREADY); + } + if (val & W_B_EXI_RMR) { /* RMR */ + W6692B_empty_fifo(bcs, W_B_FIFO_THRESH); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.w6692.rcvidx = 0; + W6692B_sched_event(bcs, B_RCVBUFREADY); + } + } + if (val & W_B_EXI_XFR) { /* XFR */ + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + W6692B_fill_fifo(bcs); + return; + } else { + if (bcs->st->lli.l1writewakeup && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.w6692.count); + dev_kfree_skb(bcs->tx_skb); + bcs->hw.w6692.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.w6692.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + W6692B_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + W6692B_sched_event(bcs, B_XMTBUFREADY); + } + } + if (val & W_B_EXI_XDUN) { /* XDUN */ + if (bcs->mode == 1) + W6692B_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.w6692.count); + bcs->tx_cnt += bcs->hw.w6692.count; + bcs->hw.w6692.count = 0; + } + cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B EXIR %x Lost TX", val); + } + } +} + +static void +W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val, exval, v1; + struct sk_buff *skb; + unsigned int count; + long flags; + int icnt = 5; + + if (!cs) { + printk(KERN_WARNING "W6692: Spurious interrupt!\n"); + return; + } + val = cs->readW6692(cs, W_ISTA); + + StartW6692: + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "W6692 ISTA %x", val); + + if (val & W_INT_D_RME) { /* RME */ + exval = cs->readW6692(cs, W_D_RSTA); + if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) { + if (exval & W_D_RSTA_RDOV) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 RDOV"); + if (exval & W_D_RSTA_CRCE) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 D-channel CRC error"); + if (exval & W_D_RSTA_RMB) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 D-channel ABORT"); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); + } else { + count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1); + if (count == 0) + count = W_D_FIFO_THRESH; + W6692_empty_fifo(cs, count); + save_flags(flags); + cli(); + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = alloc_skb(count, GFP_ATOMIC))) + printk(KERN_WARNING "HiSax: D receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } + restore_flags(flags); + } + cs->rcvidx = 0; + W6692_sched_event(cs, D_RCVBUFREADY); + } + if (val & W_INT_D_RMR) { /* RMR */ + W6692_empty_fifo(cs, W_D_FIFO_THRESH); + } + if (val & W_INT_D_XFR) { /* XFR */ + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + W6692_sched_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + W6692_fill_fifo(cs); + goto afterXFR; + } else { + dev_kfree_skb(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + W6692_fill_fifo(cs); + } else + W6692_sched_event(cs, D_XMTBUFREADY); + } + afterXFR: + if (val & (W_INT_XINT0 | W_INT_XINT1)) { /* XINT0/1 - never */ + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "W6692 spurious XINT!"); + } + if (val & W_INT_D_EXI) { /* EXI */ + exval = cs->readW6692(cs, W_D_EXIR); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 D_EXIR %02x", exval); + if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) { /* Transmit underrun/collision */ + debugl1(cs, "W6692 D-chan underrun/collision"); + printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n"); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + W6692_sched_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { /* Restart frame */ + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; + W6692_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n"); + debugl1(cs, "W6692 XDUN/XCOL no skb"); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); + } + } + if (exval & W_D_EXI_RDOV) { /* RDOV */ + debugl1(cs, "W6692 D-channel RDOV"); + printk(KERN_WARNING "HiSax: W6692 D-RDOV\n"); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST); + } + if (exval & W_D_EXI_TIN2) { /* TIN2 - never */ + debugl1(cs, "W6692 spurious TIN2 interrupt"); + } + if (exval & W_D_EXI_MOC) { /* MOC - not supported */ + debugl1(cs, "W6692 spurious MOC interrupt"); + v1 = cs->readW6692(cs, W_MOSR); + debugl1(cs, "W6692 MOSR %02x", v1); + } + if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */ + v1 = cs->readW6692(cs, W_CIR); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "W6692 ISC CIR=0x%02X", v1); + if (v1 & W_CIR_ICC) { + cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state); + W6692_sched_event(cs, D_L1STATECHANGE); + } + if (v1 & W_CIR_SCC) { + v1 = cs->readW6692(cs, W_SQR); + debugl1(cs, "W6692 SCC SQR=0x%02X", v1); + } + } + if (exval & W_D_EXI_WEXP) { + debugl1(cs, "W6692 spurious WEXP interrupt!"); + } + if (exval & W_D_EXI_TEXP) { + debugl1(cs, "W6692 spurious TEXP interrupt!"); + } + } + if (val & W_INT_B1_EXI) { + debugl1(cs, "W6692 B channel 1 interrupt"); + W6692B_interrupt(cs, 0); + } + if (val & W_INT_B2_EXI) { + debugl1(cs, "W6692 B channel 2 interrupt"); + W6692B_interrupt(cs, 1); + } + val = cs->readW6692(cs, W_ISTA); + if (val && icnt) { + icnt--; + goto StartW6692; + } + if (!icnt) { + printk(KERN_WARNING "W6692 IRQ LOOP\n"); + cs->writeW6692(cs, W_IMASK, 0xff); + } +} + +static void +W6692_l1hw(struct PStack *st, int pr, void *arg) +{ + struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; + struct sk_buff *skb = arg; + int val; + + switch (pr) { + case (PH_DATA | REQUEST): + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + W6692_fill_fifo(cs); + } + break; + case (PH_PULL | INDICATION): + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + W6692_fill_fifo(cs); + break; + case (PH_PULL | REQUEST): +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (HW_RESET | REQUEST): + if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) + ph_command(cs, W_L1CMD_ECK); + else { + ph_command(cs, W_L1CMD_RST); + cs->dc.w6692.ph_state = W_L1CMD_RST; + W6692_new_ph(cs); + } + break; + case (HW_ENABLE | REQUEST): + ph_command(cs, W_L1CMD_ECK); + break; + case (HW_INFO3 | REQUEST): + ph_command(cs, W_L1CMD_AR8); + break; + case (HW_TESTLOOP | REQUEST): + val = 0; + if (1 & (long) arg) + val |= 0x0c; + if (2 & (long) arg) + val |= 0x3; + /* !!! not implemented yet */ + break; + case (HW_DEACTIVATE | RESPONSE): + discard_queue(&cs->rq); + discard_queue(&cs->sq); + if (cs->tx_skb) { + dev_kfree_skb(cs->tx_skb); + cs->tx_skb = NULL; + } + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + W6692_sched_event(cs, D_CLEARBUSY); + break; + default: + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692_l1hw unknown %04x", pr); + break; + } +} + +static void +setstack_W6692(struct PStack *st, struct IsdnCardState *cs) +{ + st->l1.l1hw = W6692_l1hw; +} + +static void +DC_Close_W6692(struct IsdnCardState *cs) +{ +} + +static void +dbusy_timer_handler(struct IsdnCardState *cs) +{ + struct PStack *stptr; + int rbch, star; + + if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { + rbch = cs->readW6692(cs, W_D_RBCH); + star = cs->readW6692(cs, W_D_STAR); + if (cs->debug) + debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x", + rbch, star); + if (star & W_D_STAR_XBZ) { /* D-Channel Busy */ + test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); + stptr = cs->stlist; + while (stptr != NULL) { + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); + stptr = stptr->next; + } + } else { + /* discard frame; reset transceiver */ + test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); + if (cs->tx_skb) { + dev_kfree_skb(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } else { + printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n"); + debugl1(cs, "D-Channel Busy no skb"); + } + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */ + cs->irq_func(cs->irq, cs, NULL); + } + } +} + +static void +W6692Bmode(struct BCState *bcs, int mode, int bc) +{ + struct IsdnCardState *cs = bcs->cs; + int bchan = bcs->hw.w6692.bchan; + + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "w6692 %c mode %d ichan %d", + '1' + bchan, mode, bc); + bcs->mode = mode; + bcs->channel = bc; + + switch (mode) { + case (L1_MODE_NULL): + cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0); + break; + case (L1_MODE_TRANS): + cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS); + break; + case (L1_MODE_HDLC): + cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF); + cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff); + cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff); + break; + } + if (mode) + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST | + W_B_CMDR_RACT | W_B_CMDR_XRST); + cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00); +} + +static void +W6692_l2l1(struct PStack *st, int pr, void *arg) +{ + struct sk_buff *skb = arg; + long flags; + + switch (pr) { + case (PH_DATA | REQUEST): + save_flags(flags); + cli(); + if (st->l1.bcs->tx_skb) { + skb_queue_tail(&st->l1.bcs->squeue, skb); + restore_flags(flags); + } else { + st->l1.bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->hw.w6692.count = 0; + restore_flags(flags); + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + } + break; + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { + printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n"); + break; + } + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->tx_skb = skb; + st->l1.bcs->hw.w6692.count = 0; + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + break; + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + W6692Bmode(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + W6692Bmode(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; + } +} + +static void +close_w6692state(struct BCState *bcs) +{ + W6692Bmode(bcs, 0, bcs->channel); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.w6692.rcvbuf) { + kfree(bcs->hw.w6692.rcvbuf); + bcs->hw.w6692.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } +} + +static int +open_w6692state(struct IsdnCardState *cs, struct BCState *bcs) +{ + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for w6692.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.w6692.rcvbuf); + bcs->hw.w6692.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.w6692.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); +} + +static int +setstack_w6692(struct PStack *st, struct BCState *bcs) +{ + bcs->channel = st->l1.bc; + if (open_w6692state(st->l1.hardware, bcs)) + return (-1); + st->l1.bcs = bcs; + st->l2.l2l1 = W6692_l2l1; + setstack_manager(st); + bcs->st = st; + setstack_l1_B(st); + return (0); +} + +HISAX_INITFUNC(void initW6692(struct IsdnCardState *cs, int part)) +{ + if (part & 1) { + cs->tqueue.routine = (void *) (void *) W6692_bh; + cs->setstack_d = setstack_W6692; + cs->DC_Close = DC_Close_W6692; + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + + cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST); + cs->writeW6692(cs, W_D_CTL, 0x00); + cs->writeW6692(cs, W_IMASK, 0xff); + cs->writeW6692(cs, W_D_SAM, 0xff); + cs->writeW6692(cs, W_D_TAM, 0xff); + cs->writeW6692(cs, W_D_EXIM, 0x00); + cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT); + cs->writeW6692(cs, W_IMASK, 0x18); + ph_command(cs, W_L1CMD_RST); + cs->dc.w6692.ph_state = W_L1CMD_RST; + W6692_new_ph(cs); + ph_command(cs, W_L1CMD_ECK); + + cs->bcs[0].BC_SetStack = setstack_w6692; + cs->bcs[1].BC_SetStack = setstack_w6692; + cs->bcs[0].BC_Close = close_w6692state; + cs->bcs[1].BC_Close = close_w6692state; + cs->bcs[0].hw.w6692.bchan = 0; + cs->bcs[1].hw.w6692.bchan = 1; + W6692Bmode(cs->bcs, 0, 0); + W6692Bmode(cs->bcs + 1, 0, 0); + } + if (part & 2) { + /* Reenable all IRQ */ + cs->writeW6692(cs, W_IMASK, 0x18); + cs->writeW6692(cs, W_D_EXIM, 0x00); + cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00); + cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00); + /* Reset D-chan receiver and transmitter */ + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); + } +} + +/* Interface functions */ + +static u_char +ReadW6692(struct IsdnCardState *cs, u_char offset) +{ + return (inb(cs->hw.w6692.iobase + offset)); +} + +static void +WriteW6692(struct IsdnCardState *cs, u_char offset, u_char value) +{ + outb(value, cs->hw.w6692.iobase + offset); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size); +} + +static u_char +ReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset) +{ + return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset)); +} + +static void +WriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value) +{ + outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset); +} + +static int +w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + return (0); + case CARD_RELEASE: + release_region(cs->hw.w6692.iobase, 256); + return (0); + case CARD_INIT: + initW6692(cs, 3); + return (0); + case CARD_TEST: + return (0); + } + return (0); +} + +static int id_idx = 0; + +static struct pci_dev *dev_w6692 __initdata = NULL; + +__initfunc(int setup_w6692(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + u_char found = 0; + u_char pci_irq = 0; + u_int pci_ioaddr = 0; + + strcpy(tmp, w6692_revision); + printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_W6692) + return (0); +#if CONFIG_PCI + if (!pci_present()) { + printk(KERN_ERR "W6692: no PCI bus present\n"); + return (0); + } + while (id_list[id_idx].vendor_id) { + dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, + id_list[id_idx].device_id, + dev_w6692); + if (dev_w6692) + break; + id_idx++; + } + if (dev_w6692) { + found = 1; + pci_irq = dev_w6692->irq; + /* I think address 0 is allways the configuration area */ + /* and address 1 is the real IO space KKe 03.09.99 */ + pci_ioaddr = dev_w6692->resource[ 1].start; + } + if (!found) { + printk(KERN_WARNING "W6692: No PCI card found\n"); + return (0); + } + cs->irq = pci_irq; + if (!cs->irq) { + printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); + return (0); + } + pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK; + if (!pci_ioaddr) { + printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); + return (0); + } + cs->hw.w6692.iobase = pci_ioaddr; + printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", + id_list[id_idx].vendor_name, id_list[id_idx].card_name, + pci_ioaddr, dev_w6692->irq); + if (check_region((cs->hw.w6692.iobase), 256)) { + printk(KERN_WARNING + "HiSax: %s I/O ports %x-%x already in use\n", + id_list[id_idx].card_name, + cs->hw.w6692.iobase, + cs->hw.w6692.iobase + 255); + return (0); + } else { + request_region(cs->hw.w6692.iobase, 256, + id_list[id_idx].card_name); + } +#else + printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n"); + printk(KERN_WARNING "HiSax: W6692 unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ + + printk(KERN_INFO + "HiSax: %s config irq:%d I/O:%x\n", + id_list[id_idx].card_name, cs->irq, + cs->hw.w6692.iobase); + + cs->readW6692 = &ReadW6692; + cs->writeW6692 = &WriteW6692; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadW6692B; + cs->BC_Write_Reg = &WriteW6692B; + cs->BC_Send_Data = &W6692B_fill_fifo; + cs->cardmsg = &w6692_card_msg; + cs->irq_func = &W6692_interrupt; + W6692Version(cs, "W6692:"); + printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA)); + printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK)); + printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR)); + printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM)); + printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA)); + return (1); +} diff --git a/drivers/isdn/hisax/w6692.h b/drivers/isdn/hisax/w6692.h new file mode 100644 index 0000000000000000000000000000000000000000..4990b008263a34a13f8e696baf84f104a5eca1d0 --- /dev/null +++ b/drivers/isdn/hisax/w6692.h @@ -0,0 +1,190 @@ +/* $Id: w6692.h,v 1.1 1999/09/04 06:28:58 keil Exp $ + + * w6692.h Winbond W6692 specific defines + * + * Author Petr Novak <petr.novak@i.cz> + * + * + * $Log: w6692.h,v $ + * Revision 1.1 1999/09/04 06:28:58 keil + * first revision + * + * + * Revision 1.0 1999/08/28 21:58:00 pnovak + * first version + * + * + */ + +/* map W6692 functions to ISAC functions */ +#define readW6692 readisac +#define writeW6692 writeisac +#define readW6692fifo readisacfifo +#define writeW6692fifo writeisacfifo + +/* B-channel FIFO read/write routines */ + +#define READW6692BFIFO(cs,bchan,ptr,count) \ + insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count) + +#define WRITEW6692BFIFO(cs,bchan,ptr,count) \ + outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count) + +/* Specifications of W6692 registers */ + +#define W_D_RFIFO 0x00 /* R */ +#define W_D_XFIFO 0x04 /* W */ +#define W_D_CMDR 0x08 /* W */ +#define W_D_MODE 0x0c /* R/W */ +#define W_D_TIMR 0x10 /* R/W */ +#define W_ISTA 0x14 /* R_clr */ +#define W_IMASK 0x18 /* R/W */ +#define W_D_EXIR 0x1c /* R_clr */ +#define W_D_EXIM 0x20 /* R/W */ +#define W_D_STAR 0x24 /* R */ +#define W_D_RSTA 0x28 /* R */ +#define W_D_SAM 0x2c /* R/W */ +#define W_D_SAP1 0x30 /* R/W */ +#define W_D_SAP2 0x34 /* R/W */ +#define W_D_TAM 0x38 /* R/W */ +#define W_D_TEI1 0x3c /* R/W */ +#define W_D_TEI2 0x40 /* R/W */ +#define W_D_RBCH 0x44 /* R */ +#define W_D_RBCL 0x48 /* R */ +#define W_TIMR2 0x4c /* W */ +#define W_L1_RC 0x50 /* R/W */ +#define W_D_CTL 0x54 /* R/W */ +#define W_CIR 0x58 /* R */ +#define W_CIX 0x5c /* W */ +#define W_SQR 0x60 /* R */ +#define W_SQX 0x64 /* W */ +#define W_PCTL 0x68 /* R/W */ +#define W_MOR 0x6c /* R */ +#define W_MOX 0x70 /* R/W */ +#define W_MOSR 0x74 /* R_clr */ +#define W_MOCR 0x78 /* R/W */ +#define W_GCR 0x7c /* R/W */ + +#define W_B_RFIFO 0x80 /* R */ +#define W_B_XFIFO 0x84 /* W */ +#define W_B_CMDR 0x88 /* W */ +#define W_B_MODE 0x8c /* R/W */ +#define W_B_EXIR 0x90 /* R_clr */ +#define W_B_EXIM 0x94 /* R/W */ +#define W_B_STAR 0x98 /* R */ +#define W_B_ADM1 0x9c /* R/W */ +#define W_B_ADM2 0xa0 /* R/W */ +#define W_B_ADR1 0xa4 /* R/W */ +#define W_B_ADR2 0xa8 /* R/W */ +#define W_B_RBCL 0xac /* R */ +#define W_B_RBCH 0xb0 /* R */ + +#define W_XADDR 0xf4 /* R/W */ +#define W_XDATA 0xf8 /* R/W */ +#define W_EPCTL 0xfc /* W */ + +/* W6692 register bits */ + +#define W_D_CMDR_XRST 0x01 +#define W_D_CMDR_XME 0x02 +#define W_D_CMDR_XMS 0x08 +#define W_D_CMDR_STT 0x10 +#define W_D_CMDR_RRST 0x40 +#define W_D_CMDR_RACK 0x80 + +#define W_D_MODE_RLP 0x01 +#define W_D_MODE_DLP 0x02 +#define W_D_MODE_MFD 0x04 +#define W_D_MODE_TEE 0x08 +#define W_D_MODE_TMS 0x10 +#define W_D_MODE_RACT 0x40 +#define W_D_MODE_MMS 0x80 + +#define W_INT_B2_EXI 0x01 +#define W_INT_B1_EXI 0x02 +#define W_INT_D_EXI 0x04 +#define W_INT_XINT0 0x08 +#define W_INT_XINT1 0x10 +#define W_INT_D_XFR 0x20 +#define W_INT_D_RME 0x40 +#define W_INT_D_RMR 0x80 + +#define W_D_EXI_WEXP 0x01 +#define W_D_EXI_TEXP 0x02 +#define W_D_EXI_ISC 0x04 +#define W_D_EXI_MOC 0x08 +#define W_D_EXI_TIN2 0x10 +#define W_D_EXI_XCOL 0x20 +#define W_D_EXI_XDUN 0x40 +#define W_D_EXI_RDOV 0x80 + +#define W_D_STAR_DRDY 0x10 +#define W_D_STAR_XBZ 0x20 +#define W_D_STAR_XDOW 0x80 + +#define W_D_RSTA_RMB 0x10 +#define W_D_RSTA_CRCE 0x20 +#define W_D_RSTA_RDOV 0x40 + +#define W_D_CTL_SRST 0x20 + +#define W_CIR_SCC 0x80 +#define W_CIR_ICC 0x40 +#define W_CIR_COD_MASK 0x0f + +#define W_B_CMDR_XRST 0x01 +#define W_B_CMDR_XME 0x02 +#define W_B_CMDR_XMS 0x04 +#define W_B_CMDR_RACT 0x20 +#define W_B_CMDR_RRST 0x40 +#define W_B_CMDR_RACK 0x80 + +#define W_B_MODE_FTS0 0x01 +#define W_B_MODE_FTS1 0x02 +#define W_B_MODE_SW56 0x04 +#define W_B_MODE_BSW0 0x08 +#define W_B_MODE_BSW1 0x10 +#define W_B_MODE_EPCM 0x20 +#define W_B_MODE_ITF 0x40 +#define W_B_MODE_MMS 0x80 + +#define W_B_EXI_XDUN 0x01 +#define W_B_EXI_XFR 0x02 +#define W_B_EXI_RDOV 0x10 +#define W_B_EXI_RME 0x20 +#define W_B_EXI_RMR 0x40 + +#define W_B_STAR_XBZ 0x01 +#define W_B_STAR_XDOW 0x04 +#define W_B_STAR_RMB 0x10 +#define W_B_STAR_CRCE 0x20 +#define W_B_STAR_RDOV 0x40 + +#define W_B_RBCH_LOV 0x20 + +/* W6692 Layer1 commands */ + +#define W_L1CMD_ECK 0x00 +#define W_L1CMD_RST 0x01 +#define W_L1CMD_SCP 0x04 +#define W_L1CMD_SSP 0x02 +#define W_L1CMD_AR8 0x08 +#define W_L1CMD_AR10 0x09 +#define W_L1CMD_EAL 0x0a +#define W_L1CMD_DRC 0x0f + +/* W6692 Layer1 indications */ + +#define W_L1IND_CE 0x07 +#define W_L1IND_DRD 0x00 +#define W_L1IND_LD 0x04 +#define W_L1IND_ARD 0x08 +#define W_L1IND_TI 0x0a +#define W_L1IND_ATI 0x0b +#define W_L1IND_AI8 0x0c +#define W_L1IND_AI10 0x0d +#define W_L1IND_CD 0x0f + +/* FIFO thresholds */ +#define W_D_FIFO_THRESH 64 +#define W_B_FIFO_THRESH 64 diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 26ac3502df0500de2fc4ad67e0652911a75b0d84..92ee95a2e47931b6cd248b9c8da980b28e121b0e 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1,8 +1,8 @@ -/* $Id: icn.c,v 1.59 1999/08/28 22:10:55 keil Exp $ +/* $Id: icn.c,v 1.62 1999/09/06 07:29:35 fritz Exp $ * ISDN low-level module for the ICN active ISDN-Card. * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * 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 @@ -19,6 +19,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: icn.c,v $ + * Revision 1.62 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * + * Revision 1.61 1999/09/03 14:06:58 fritz + * Fixed a memory leak. + * + * Revision 1.60 1999/08/31 11:20:32 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.59 1999/08/28 22:10:55 keil * __setup function should be static * @@ -238,7 +247,7 @@ #undef MAP_DEBUG static char -*revision = "$Revision: 1.59 $"; +*revision = "$Revision: 1.62 $"; static int icn_addcard(int, char *, char *); @@ -467,7 +476,7 @@ icn_pollbchan_receive(int channel, icn_card * card) if (!eflag) { if ((cnt = card->rcvidx[channel])) { if (!(skb = dev_alloc_skb(cnt))) { - printk(KERN_WARNING "ïcn: receive out of memory\n"); + printk(KERN_WARNING "icn: receive out of memory\n"); break; } memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt); @@ -545,12 +554,10 @@ icn_pollbchan_send(int channel, icn_card * card) if (!skb->len) { save_flags(flags); cli(); - if (card->xskb[channel]) { + if (card->xskb[channel]) card->xskb[channel] = NULL; - restore_flags(flags); - dev_kfree_skb(skb); - } else - restore_flags(flags); + restore_flags(flags); + dev_kfree_skb(skb); if (card->xlen[channel]) { cmd.command = ISDN_STAT_BSENT; cmd.driver = card->myid; @@ -1852,7 +1859,6 @@ icn_addcard(int port, char *id1, char *id2) #ifdef MODULE #define icn_init init_module #else -#ifdef COMPAT_HAS_NEW_SETUP #include <linux/init.h> static int __init icn_setup(char *line) @@ -1863,14 +1869,6 @@ icn_setup(char *line) static char sid2[20]; str = get_options(line, 2, ints); -#else -void -icn_setup(char *str, int *ints) -{ - char *p; - static char sid[20]; - static char sid2[20]; -#endif if (ints[0]) portbase = ints[1]; if (ints[0] > 1) @@ -1884,13 +1882,9 @@ icn_setup(char *str, int *ints) icn_id2 = sid2; } } -#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("icn=", icn_setup); -#else -} -#endif #endif /* MODULES */ int diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h index 3bd2819cedb85b3d97c9f6acf81e795027a33aa5..6d40a695c434ce472b176321ffd55c67219dacfb 100644 --- a/drivers/isdn/icn/icn.h +++ b/drivers/isdn/icn/icn.h @@ -1,8 +1,8 @@ -/* $Id: icn.h,v 1.28 1997/10/10 15:56:18 fritz Exp $ +/* $Id: icn.h,v 1.29 1999/09/06 07:29:35 fritz Exp $ * ISDN lowlevel-module for the ICN active ISDN-Card. * - * Copyright 1994 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994 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 @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: icn.h,v $ + * Revision 1.29 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * * Revision 1.28 1997/10/10 15:56:18 fritz * New HL<->LL interface: * New BSENT callback with nr. of bytes included. diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c index 10414ee945cdab70c05b7a147282624d29f1a47b..ba890846d1b081f9210fc9ea7b92c4111121c2ad 100644 --- a/drivers/isdn/isdn_common.c +++ b/drivers/isdn/isdn_common.c @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.86 1999/07/31 12:59:42 armin Exp $ +/* $Id: isdn_common.c,v 1.93 1999/11/04 13:11:36 keil Exp $ * Linux ISDN subsystem, common used functions (linklevel). * @@ -21,6 +21,40 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_common.c,v $ + * Revision 1.93 1999/11/04 13:11:36 keil + * Reinit of v110 structs + * + * Revision 1.92 1999/10/31 15:59:50 he + * more skb headroom checks + * + * Revision 1.91 1999/10/28 22:48:45 armin + * Bugfix: isdn_free_channel() now frees the channel, + * even when the usage of the ttyI has changed. + * + * Revision 1.90 1999/10/27 21:21:17 detabc + * Added support for building logically-bind-group's per interface. + * usefull for outgoing call's with more then one isdn-card. + * + * Switchable support to dont reset the hangup-timeout for + * receive frames. Most part's of the timru-rules for receiving frames + * are now obsolete. If the input- or forwarding-firewall deny + * the frame, the line will be not hold open. + * + * Revision 1.89 1999/10/16 14:46:47 keil + * replace kmalloc with vmalloc for the big dev struct + * + * Revision 1.88 1999/10/02 00:39:26 he + * Fixed a 2.3.x wait queue initialization (was causing panics) + * + * Revision 1.87 1999/09/12 16:19:39 detabc + * added abc features + * low cost routing for net-interfaces (only the HL side). + * need more implementation in the isdnlog-utility + * udp info support (first part). + * different EAZ on outgoing call's. + * more checks on D-Channel callbacks (double use of channels). + * tested and running with kernel 2.3.17 + * * Revision 1.86 1999/07/31 12:59:42 armin * Added tty fax capabilities. * @@ -362,6 +396,7 @@ #include <linux/module.h> #include <linux/version.h> #include <linux/poll.h> +#include <linux/vmalloc.h> #include <linux/isdn.h> #include "isdn_common.h" #include "isdn_tty.h" @@ -381,7 +416,7 @@ isdn_dev *dev = (isdn_dev *) 0; -static char *isdn_revision = "$Revision: 1.86 $"; +static char *isdn_revision = "$Revision: 1.93 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; @@ -1039,9 +1074,6 @@ isdn_status_callback(isdn_ctrl * c) isdn_free_queue(&dev->drv[di]->rpqueue[i]); kfree(dev->drv[di]->rpqueue); kfree(dev->drv[di]->rcv_waitq); -#ifndef COMPAT_HAS_NEW_WAITQ - kfree(dev->drv[di]->snd_waitq); -#endif kfree(dev->drv[di]); dev->drv[di] = NULL; dev->drvid[di][0] = '\0'; @@ -1103,11 +1135,7 @@ isdn_getnum(char **p) * of the mapping (di,ch)<->minor, happen during the sleep? --he */ int -#ifdef COMPAT_HAS_NEW_WAITQ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep) -#else -isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep) -#endif { int left; int count; @@ -1535,6 +1563,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) * are serialized by means of a semaphore. */ switch (cmd) { + case IIOCNETLCR: + printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n"); + return -ENODEV; #ifdef CONFIG_NETDEVICES case IIOCNETAIF: /* Add a network-interface */ @@ -2092,13 +2123,19 @@ isdn_free_channel(int di, int ch, int usage) save_flags(flags); cli(); for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (((dev->usage[i] & ISDN_USAGE_MASK) == usage) && + if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) && (dev->drvmap[i] == di) && (dev->chanmap[i] == ch)) { dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE); strcpy(dev->num[i], "???"); dev->ibytes[i] = 0; dev->obytes[i] = 0; +// 20.10.99 JIM, try to reinitialize v110 ! + dev->v110emu[i] = 0; + atomic_set(&(dev->v110use[i]), 0); + isdn_v110_close(dev->v110[i]); + dev->v110[i] = NULL; +// 20.10.99 JIM, try to reinitialize v110 ! isdn_info_update(); isdn_free_queue(&dev->drv[di]->rpqueue[ch]); } @@ -2180,8 +2217,33 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) /* V.110 must always be acknowledged */ ack = 1; ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb); - } else - ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb); + } else { + int hl = dev->drv[drvidx]->interface->hl_hdrlen; + + if( skb_headroom(skb) < hl ){ + /* + * This should only occur when new HL driver with + * increased hl_hdrlen was loaded after netdevice + * was created and connected to the new driver. + * + * The V.110 branch (re-allocates on its own) does + * not need this + */ + struct sk_buff * skb_tmp; + + skb_tmp = skb_realloc_headroom(skb, hl); + printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed"); + if (!skb_tmp) return -ENOMEM; /* 0 better? */ + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp); + if( ret > 0 ){ + dev_kfree_skb(skb); + } else { + dev_kfree_skb(skb_tmp); + } + } else { + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb); + } + } if (ret > 0) { dev->obytes[idx] += ret; if (dev->v110[idx]) { @@ -2202,43 +2264,11 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) int register_isdn_module(isdn_module *m) { -#if 0 - isdn_module_list **pp = &dev->modules; - isdn_module *new = kmalloc(sizeof(isdn_module_list), GFP_KERNEL); - - if (!new) { - printk(KERN_WARNING "isdn: Out of memory in register_isdn_module\n"); - return -1; - } - while (*pp && (*pp)->orig != m) - pp = &(*pp)->next; - if (*pp != NULL) { - printk(KERN_WARNING "isdn: Module %s already registered\n", m->name); - return -1; - } - while (*pp && ((*pp)->module.priority < m->priority)) - pp = &(*pp)->next; - new->next = *pp; - new->orig = m; - new->module = *m; - - *pp = new; -#endif return 0; } int unregister_isdn_module(isdn_module *m) { -#if 0 - isdn_module_list **pp = &dev->modules; - - while (*pp && *pp != m) - pp = &(*pp)->next; - if (*pp == NULL) { - printk(KERN_WARNING "isdn: Module %s not found\n", m->name); - return -1; - } -#endif return 0; } @@ -2248,9 +2278,7 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding) int j, k, m; ulong flags; -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&d->st_waitq); -#endif if (d->flags & DRV_FLAG_RUNNING) return -1; if (n < 1) return 0; @@ -2300,14 +2328,9 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding) if ((adding) && (d->rcv_waitq)) kfree(d->rcv_waitq); -#ifdef COMPAT_HAS_NEW_WAITQ d->rcv_waitq = (wait_queue_head_t *) kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL); if (!d->rcv_waitq) { -#else - if (!(d->rcv_waitq = (struct wait_queue **) - kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) { -#endif printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n"); if (!adding) { kfree(d->rpqueue); @@ -2316,30 +2339,11 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding) } return -1; } -#ifdef COMPAT_HAS_NEW_WAITQ d->snd_waitq = d->rcv_waitq + m; for (j = 0; j < m; j++) { init_waitqueue_head(&d->rcv_waitq[j]); init_waitqueue_head(&d->snd_waitq[j]); } -#else - memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m); - - if ((adding) && (d->snd_waitq)) - kfree(d->snd_waitq); - if (!(d->snd_waitq = (struct wait_queue **) - kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n"); - if (!adding) { - kfree(d->rcv_waitq); - kfree(d->rpqueue); - kfree(d->rcvcount); - kfree(d->rcverr); - } - return -1; - } - memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m); -#endif dev->channels += n; save_flags(flags); @@ -2513,33 +2517,26 @@ isdn_init(void) int i; char tmprev[50]; - sti(); - if (!(dev = (isdn_dev *) kmalloc(sizeof(isdn_dev), GFP_KERNEL))) { + if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) { printk(KERN_WARNING "isdn: Could not allocate device-struct.\n"); return -EIO; } memset((char *) dev, 0, sizeof(isdn_dev)); init_timer(&dev->timer); dev->timer.function = isdn_timer_funct; -#ifdef COMPAT_HAS_NEW_WAITQ init_MUTEX(&dev->sem); init_waitqueue_head(&dev->info_waitq); -#else - dev->sem = MUTEX; -#endif for (i = 0; i < ISDN_MAX_CHANNELS; i++) { dev->drvmap[i] = -1; dev->chanmap[i] = -1; dev->m_idx[i] = -1; strcpy(dev->num[i], "???"); -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&dev->mdm.info[i].open_wait); init_waitqueue_head(&dev->mdm.info[i].close_wait); -#endif } if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { printk(KERN_WARNING "isdn: Could not register control devices\n"); - kfree(dev); + vfree(dev); return -EIO; } if ((i = isdn_tty_modem_init()) < 0) { @@ -2548,7 +2545,7 @@ isdn_init(void) tty_unregister_driver(&dev->mdm.cua_modem); if (i <= -2) tty_unregister_driver(&dev->mdm.tty_modem); - kfree(dev); + vfree(dev); unregister_chrdev(ISDN_MAJOR, "isdn"); return -EIO; } @@ -2560,7 +2557,7 @@ isdn_init(void) for (i = 0; i < ISDN_MAX_CHANNELS; i++) kfree(dev->mdm.info[i].xmit_buf - 4); unregister_chrdev(ISDN_MAJOR, "isdn"); - kfree(dev); + vfree(dev); return -EIO; } #endif /* CONFIG_ISDN_PPP */ @@ -2629,7 +2626,7 @@ cleanup_module(void) printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n"); } else { del_timer(&dev->timer); - kfree(dev); + vfree(dev); printk(KERN_NOTICE "ISDN-subsystem unloaded\n"); } restore_flags(flags); diff --git a/drivers/isdn/isdn_common.h b/drivers/isdn/isdn_common.h index e6fb122f6669accf4d3a952371cf3043338666ec..3c60d7c8076ac4866dc26574de7110faf9a30329 100644 --- a/drivers/isdn/isdn_common.h +++ b/drivers/isdn/isdn_common.h @@ -1,4 +1,4 @@ -/* $Id: isdn_common.h,v 1.16 1999/07/01 08:29:54 keil Exp $ +/* $Id: isdn_common.h,v 1.17 1999/10/27 21:21:17 detabc Exp $ * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel). * @@ -21,6 +21,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_common.h,v $ + * Revision 1.17 1999/10/27 21:21:17 detabc + * Added support for building logically-bind-group's per interface. + * usefull for outgoing call's with more then one isdn-card. + * + * Switchable support to dont reset the hangup-timeout for + * receive frames. Most part's of the timru-rules for receiving frames + * are now obsolete. If the input- or forwarding-firewall deny + * the frame, the line will be not hold open. + * * Revision 1.16 1999/07/01 08:29:54 keil * compatibility to 2.3 kernel * @@ -118,11 +127,7 @@ extern char *isdn_map_eaz2msn(char *msn, int di); extern void isdn_timer_ctrl(int tf, int onoff); extern void isdn_unexclusive_channel(int di, int ch); extern int isdn_getnum(char **); -#ifdef COMPAT_HAS_NEW_WAITQ extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *); -#else -extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**); -#endif extern int isdn_get_free_channel(int, int, int, int, int); extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *); extern int register_isdn(isdn_if * i); diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c index 9d54f01274e82df77965a8cdd0a5135b892f7ee5..e1c7cb75d4834959326f1c8b2f8a2d1caac24a43 100644 --- a/drivers/isdn/isdn_net.c +++ b/drivers/isdn/isdn_net.c @@ -1,4 +1,4 @@ -/* $Id: isdn_net.c,v 1.89 1999/08/22 20:26:03 calle Exp $ +/* $Id: isdn_net.c,v 1.95 1999/10/27 21:21:17 detabc Exp $ * Linux ISDN subsystem, network interfaces and related functions (linklevel). * @@ -21,6 +21,38 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_net.c,v $ + * Revision 1.95 1999/10/27 21:21:17 detabc + * Added support for building logically-bind-group's per interface. + * usefull for outgoing call's with more then one isdn-card. + * + * Switchable support to dont reset the hangup-timeout for + * receive frames. Most part's of the timru-rules for receiving frames + * are now obsolete. If the input- or forwarding-firewall deny + * the frame, the line will be not hold open. + * + * Revision 1.94 1999/10/02 11:07:02 he + * Changed tbusy logic in indn_net.c + * + * Revision 1.93 1999/09/23 22:22:41 detabc + * added tcp-keepalive-detect with local response (ipv4 only) + * added host-only-interface support + * (source ipaddr == interface ipaddr) (ipv4 only) + * ok with kernel 2.3.18 and 2.2.12 + * + * Revision 1.92 1999/09/13 23:25:17 he + * serialized xmitting frames from isdn_ppp and BSENT statcallb + * + * Revision 1.91 1999/09/12 16:19:39 detabc + * added abc features + * low cost routing for net-interfaces (only the HL side). + * need more implementation in the isdnlog-utility + * udp info support (first part). + * different EAZ on outgoing call's. + * more checks on D-Channel callbacks (double use of channels). + * tested and running with kernel 2.3.17 + * + * Revision 1.90 1999/09/04 22:21:39 detabc + * * Revision 1.89 1999/08/22 20:26:03 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -360,13 +392,58 @@ #include "isdn_concap.h" #endif + +#ifndef ISDN_NEW_TBUSY +#define ISDN_NEW_TBUSY +#endif +#ifdef ISDN_NEW_TBUSY +/* + * Outline of new tbusy handling: + * + * Old method, roughly spoken, consisted of setting tbusy when entering + * isdn_net_start_xmit() and at several other locations and clearing + * it from isdn_net_start_xmit() thread when sending was successful. + * + * With 2.3.x multithreaded network core, to prevent problems, tbusy should + * only be set by the isdn_net_start_xmit() thread and only when a tx-busy + * condition is detected. Other threads (in particular isdn_net_stat_callb()) + * are only allowed to clear tbusy. + * + * -HE + */ + +/* + * Tell upper layers that the network device is ready to xmit more frames. + */ +static void __inline__ isdn_net_dev_xon(struct net_device * dev) +{ + dev->tbusy = 0; + mark_bh(NET_BH); +} + +static void __inline__ isdn_net_lp_xon(isdn_net_local * lp) +{ + lp->netdev->dev.tbusy = 0; + if(lp->master) lp->master->tbusy = 0; + mark_bh(NET_BH); +} + +/* + * Ask upper layers to temporarily cease passing us more xmit frames. + */ +static void __inline__ isdn_net_dev_xoff(struct net_device * dev) +{ + dev->tbusy = 1; +} +#endif + /* Prototypes */ int isdn_net_force_dial_lp(isdn_net_local *); static int isdn_net_start_xmit(struct sk_buff *, struct net_device *); static int isdn_net_xmit(struct net_device *, isdn_net_local *, struct sk_buff *); -char *isdn_net_revision = "$Revision: 1.89 $"; +char *isdn_net_revision = "$Revision: 1.95 $"; /* * Code for raw-networking over ISDN @@ -408,7 +485,11 @@ isdn_net_reset(struct net_device *dev) save_flags(flags); cli(); /* Avoid glitch on writes to CMD regs */ dev->interrupt = 0; +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xon(dev); +#else dev->tbusy = 0; +#endif #ifdef CONFIG_ISDN_X25 if( cprot && cprot -> pops && dops ) cprot -> pops -> restart ( cprot, dev, dops ); @@ -607,6 +688,13 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) (!lp->dialstate)) { lp->stats.tx_packets++; lp->stats.tx_bytes += c->parm.length; + /* some HL drivers deliver + ISDN_STAT_BSENT from hw interrupt. + Output routines in isdn_ppp are now + called with irq disabled such that + dequeueing the sav_skb while another + frame is sent will not occur. + */ if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->sav_skb) { struct net_device *mdev; if (lp->master) @@ -615,13 +703,19 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) mdev = &lp->netdev->dev; if (!isdn_net_send_skb(mdev, lp, lp->sav_skb)) { lp->sav_skb = NULL; +#ifndef ISDN_NEW_TBUSY mark_bh(NET_BH); +#endif } else { return 1; } } +#ifdef ISDN_NEW_TBUSY + isdn_net_lp_xon(lp); +#else if (test_and_clear_bit(0, (void *) &(p->dev.tbusy))) mark_bh(NET_BH); +#endif } return 1; case ISDN_STAT_DCONN: @@ -704,7 +798,6 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) lp->dialstarted = 0; lp->dialwait_timer = 0; - /* Immediately send first skb to speed up arp */ #ifdef CONFIG_ISDN_PPP if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) isdn_ppp_wakeup_daemon(lp); @@ -715,11 +808,15 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) if( pops->connect_ind) pops->connect_ind(cprot); #endif /* CONFIG_ISDN_X25 */ + /* Immediately send first skb to speed up arp */ if (lp->first_skb) { if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb))) lp->first_skb = NULL; } +#ifdef ISDN_NEW_TBUSY + if(! lp->first_skb) isdn_net_lp_xon(lp); +#else else { /* * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb). @@ -728,6 +825,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) lp->netdev->dev.tbusy = 0; mark_bh(NET_BH); } +#endif /* ISDN_NEW_TBUSY */ return 1; } break; @@ -1162,6 +1260,7 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp) break; } printk(KERN_INFO "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n", + p[12], p[13], p[14], p[15], p[16], p[17], p[18], p[19], addinfo); @@ -1180,8 +1279,12 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp) * standard send-routine, else send directly. * * Return: 0 on success, !0 on failure. + */ +#ifndef ISDN_NEW_TBUSY +/* * Side-effects: ndev->tbusy is cleared on success. */ +#endif int isdn_net_send_skb(struct net_device *ndev, isdn_net_local * lp, struct sk_buff *skb) @@ -1192,13 +1295,17 @@ isdn_net_send_skb(struct net_device *ndev, isdn_net_local * lp, ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb); if (ret == len) { lp->transcount += len; +#ifndef ISDN_NEW_TBUSY clear_bit(0, (void *) &(ndev->tbusy)); +#endif return 0; } if (ret < 0) { dev_kfree_skb(skb); lp->stats.tx_errors++; +#ifndef ISDN_NEW_TBUSY clear_bit(0, (void *) &(ndev->tbusy)); +#endif return 0; } return 1; @@ -1244,7 +1351,11 @@ isdn_net_xmit(struct net_device *ndev, isdn_net_local * lp, struct sk_buff *skb) if (lp->srobin == ndev) ret = isdn_net_send_skb(ndev, lp, skb); else +#ifdef ISDN_NEW_TBUSY + ret = isdn_net_start_xmit(skb, lp->srobin); +#else ret = ndev->tbusy = isdn_net_start_xmit(skb, lp->srobin); +#endif lp->srobin = (slp->slave) ? slp->slave : ndev; slp = (isdn_net_local *) (lp->srobin->priv); if (!((slp->flags & ISDN_NET_CONNECTED) && (slp->dialstate == 0))) @@ -1298,15 +1409,19 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) #ifdef CONFIG_ISDN_X25 struct concap_proto * cprot = lp -> netdev -> cprot; #endif - if (ndev->tbusy) { if (jiffies - ndev->trans_start < (2 * HZ)) return 1; if (!lp->dialstate) lp->stats.tx_errors++; ndev->trans_start = jiffies; +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xon(ndev); +#endif } +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */ +#endif #ifdef CONFIG_ISDN_X25 /* At this point hard_start_xmit() passes control to the encapsulation protocol (if present). @@ -1320,7 +1435,11 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) when a dl_establish request is received from the upper layer. */ if( cprot ) { - return cprot -> pops -> encap_and_xmit ( cprot , skb); + int ret = cprot -> pops -> encap_and_xmit ( cprot , skb); +#ifdef ISDN_NEW_TBUSY + if(ret) isdn_net_dev_xoff(ndev); +#endif + return ret; } else #endif /* auto-dialing xmit function */ @@ -1339,7 +1458,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) { isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'"); dev_kfree_skb(skb); +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif return 0; } if (lp->phone[1]) { @@ -1355,7 +1476,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) if(jiffies < lp->dialwait_timer) { isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached"); dev_kfree_skb(skb); +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif restore_flags(flags); return 0; } else @@ -1364,22 +1487,28 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) /* Grab a free ISDN-Channel */ if (((chi = - isdn_get_free_channel(ISDN_USAGE_NET, - lp->l2_proto, - lp->l3_proto, - lp->pre_device, - lp->pre_channel)) < 0) && + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel) + ) < 0) && ((chi = - isdn_get_free_channel(ISDN_USAGE_NET, - lp->l2_proto, - lp->l3_proto, - lp->pre_device, - lp->pre_channel^1)) < 0)) { + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel^1) + ) < 0)) { restore_flags(flags); isdn_net_unreachable(ndev, skb, "No channel"); dev_kfree_skb(skb); +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif return 0; } /* Log packet, which triggered dialing */ @@ -1399,6 +1528,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) } restore_flags(flags); isdn_net_dial(); /* Initiate dialing */ +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xoff(ndev); +#endif return 1; /* let upper layer requeue skb packet */ } #endif @@ -1412,7 +1544,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) } lp->first_skb = skb; /* Initiate dialing */ +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif restore_flags(flags); isdn_net_dial(); return 0; @@ -1420,21 +1554,37 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) isdn_net_unreachable(ndev, skb, "No phone number"); dev_kfree_skb(skb); +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif return 0; } } else { - /* Connection is established, try sending */ + /* Device is connected to an ISDN channel */ ndev->trans_start = jiffies; if (!lp->dialstate) { + /* ISDN connection is established, try sending */ + int ret; if (lp->first_skb) { - if (isdn_net_xmit(ndev, lp, lp->first_skb)) + if (isdn_net_xmit(ndev, lp, lp->first_skb)){ +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xoff(ndev); +#endif return 1; +} lp->first_skb = NULL; } - return (isdn_net_xmit(ndev, lp, skb)); + ret = (isdn_net_xmit(ndev, lp, skb)); +#ifdef ISDN_NEW_TBUSY + if(ret) isdn_net_dev_xoff(ndev); +#endif + return ret; } else +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xoff(ndev); +#else ndev->tbusy = 1; +#endif } } return 1; @@ -1915,7 +2065,7 @@ isdn_net_rebuild_header(struct sk_buff *skb) } /* - * Interface-setup. (called just after registering a new interface) + * Interface-setup. (just after registering a new interface) */ static int isdn_net_init(struct net_device *ndev) @@ -2046,7 +2196,6 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup) isdn_net_phone *n; ulong flags; char nr[32]; - /* Search name in netdev-chain */ save_flags(flags); cli(); @@ -2258,10 +2407,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup) lp->name, nr, eaz); if (lp->phone[1]) { /* Grab a free ISDN-Channel */ - if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto, + if ((chi = + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, lp->l3_proto, - lp->pre_device, - lp->pre_channel)) < 0) { + lp->pre_device, + lp->pre_channel) + ) < 0) { + printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name); restore_flags(flags); return 0; @@ -2368,10 +2522,14 @@ isdn_net_force_dial_lp(isdn_net_local * lp) cli(); /* Grab a free ISDN-Channel */ - if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto, - lp->l3_proto, - lp->pre_device, - lp->pre_channel)) < 0) { + if ((chi = + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel) + ) < 0) { printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name); restore_flags(flags); return -EAGAIN; @@ -3076,7 +3234,6 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) if (dev->netdev == NULL) isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0); restore_flags(flags); - kfree(p->local); kfree(p); diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c index 78c71c7fe48814036bb954c7f823ce857304318d..06c2d83addd7f5e01525cb4861c48c132252f9c6 100644 --- a/drivers/isdn/isdn_ppp.c +++ b/drivers/isdn/isdn_ppp.c @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.c,v 1.52 1999/08/22 20:26:07 calle Exp $ +/* $Id: isdn_ppp.c,v 1.60 1999/11/04 20:29:55 he Exp $ * * Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -19,6 +19,34 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_ppp.c,v $ + * Revision 1.60 1999/11/04 20:29:55 he + * applied Andre Beck's reset_free fix + * + * Revision 1.59 1999/10/31 15:59:50 he + * more skb headroom checks + * + * Revision 1.58 1999/10/30 13:13:01 keil + * Henners isdn_ppp_skb_push:under fix + * + * Revision 1.57 1999/10/05 22:47:17 he + * Removed dead ISDN_SYNCPPP_READDRESS code (obsoleted by sysctl_ip_dynaddr + * and network address translation) + * + * Revision 1.56 1999/09/29 16:01:06 he + * replaced dev_alloc_skb() for downstream skbs by equivalent alloc_skb() + * + * Revision 1.55 1999/09/23 22:07:51 detabc + * + * make ipc_head common usable (for use compressor with raw-ip) + * add function before netif_rx(). needed for ipv4-tcp-keepalive-detect. + * ~ + * + * Revision 1.54 1999/09/13 23:25:17 he + * serialized xmitting frames from isdn_ppp and BSENT statcallb + * + * Revision 1.53 1999/08/31 11:18:14 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.52 1999/08/22 20:26:07 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -212,10 +240,6 @@ /* TODO: right tbusy handling when using MP */ -/* - * experimental for dynamic addressing: readdress IP frames - */ -#undef ISDN_SYNCPPP_READDRESS #define CONFIG_ISDN_CCP 1 #include <linux/config.h> @@ -258,6 +282,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, unsigned char code, unsigned char id, unsigned char *data, int len); static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is); +static void isdn_ppp_ccp_reset_free(struct ippp_struct *is); static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, unsigned char id); static void isdn_ppp_ccp_timer_callback(unsigned long closure); @@ -281,9 +306,10 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb, static void isdn_ppp_free_mpqueue(isdn_net_dev *); #endif -char *isdn_ppp_revision = "$Revision: 1.52 $"; +char *isdn_ppp_revision = "$Revision: 1.60 $"; static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; + static struct isdn_ppp_compressor *ipc_head = NULL; /* @@ -354,10 +380,6 @@ isdn_ppp_free(isdn_net_local * lp) printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp); is->lp = NULL; /* link is down .. set lp to NULL */ -#ifdef ISDN_SYNCPPP_READDRESS - is->old_pa_addr = 0x0; - is->old_pa_dstaddr = 0x0; -#endif lp->ppp_slot = -1; /* is this OK ?? */ restore_flags(flags); @@ -450,9 +472,6 @@ isdn_ppp_wakeup_daemon(isdn_net_local * lp) ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK; -#ifndef COMPAT_HAS_NEW_WAITQ - if (ippp_table[lp->ppp_slot]->wq) -#endif wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq); } @@ -470,11 +489,7 @@ isdn_ppp_closewait(int slot) return 0; is = ippp_table[slot]; -#ifdef COMPAT_HAS_NEW_WAITQ if (is->state) -#else - if (is->state && is->wq) -#endif wake_up_interruptible(&is->wq); is->state = IPPP_CLOSEWAIT; @@ -515,9 +530,6 @@ isdn_ppp_open(int min, struct file *file) } is = file->private_data = ippp_table[slot]; -#if 0 - if (is->debug & 0x1) -#endif printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state); /* compression stuff */ @@ -539,11 +551,7 @@ isdn_ppp_open(int min, struct file *file) is->mru = 1524; /* MRU, default 1524 */ is->maxcid = 16; /* VJ: maxcid */ is->tk = current; -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&is->wq); -#else - is->wq = NULL; /* read() wait queue */ -#endif is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */ is->last = is->rq; is->minor = min; @@ -615,9 +623,9 @@ isdn_ppp_release(int min, struct file *file) is->comp_stat = is->link_comp_stat = NULL; is->decomp_stat = is->link_decomp_stat = NULL; + /* Clean up if necessary */ if(is->reset) - kfree(is->reset); - is->reset = NULL; + isdn_ppp_ccp_reset_free(is); /* this slot is ready for new connections */ is->state = 0; @@ -719,10 +727,6 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) } is->pppcfg = val; break; -#if 0 - case PPPIOCGSTAT: /* read PPP statistic information */ - break; -#endif case PPPIOCGIDLE: /* get idle time information */ if (lp) { struct ppp_idle pidle; @@ -911,9 +915,6 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot) is->last = bl->next; restore_flags(flags); -#ifndef COMPAT_HAS_NEW_WAITQ - if (is->wq) -#endif wake_up_interruptible(&is->wq); return len; @@ -1004,6 +1005,7 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count) lp->dialstate == 0 && (lp->flags & ISDN_NET_CONNECTED)) { unsigned short hl; + unsigned long flags; int cnt; struct sk_buff *skb; /* @@ -1027,6 +1029,8 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count) isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */ + save_flags(flags); + cli(); if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) { if (lp->sav_skb) { dev_kfree_skb(lp->sav_skb); @@ -1035,6 +1039,7 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count) printk(KERN_INFO "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n", cnt, count); lp->sav_skb = skb; } + restore_flags(flags); } } return count; @@ -1115,7 +1120,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot); } if (net_dev->local->master) { - printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n"); + printk(KERN_WARNING "isdn_ppp_receive: net_dev != master\n"); net_dev = ((isdn_net_local *) net_dev->local->master->priv)->netdev; } if (skb->data[0] == 0xff && skb->data[1] == 0x03) @@ -1459,6 +1464,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) isdn_net_dev *nd; unsigned int proto = PPP_IP; /* 0x21 */ struct ippp_struct *ipt,*ipts; + unsigned long flags; if (mdev) mlp = (isdn_net_local *) (mdev->priv); @@ -1470,12 +1476,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) ipts = ippp_table[mlp->ppp_slot]; if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */ -#ifdef ISDN_SYNCPPP_READDRESS - if (!ipts->old_pa_addr) - ipts->old_pa_addr = mdev->pa_addr; - if (!ipts->old_pa_dstaddr) - ipts->old_pa_dstaddr = mdev->pa_dstaddr; -#endif if (ipts->debug & 0x1) printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name); return 1; @@ -1484,21 +1484,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) switch (ntohs(skb->protocol)) { case ETH_P_IP: proto = PPP_IP; -#ifdef ISDN_SYNCPPP_READDRESS - if (ipts->old_pa_addr != mdev->pa_addr) { - struct iphdr *ipfr; - ipfr = (struct iphdr *) skb->data; - if(ipts->debug & 0x4) - printk(KERN_DEBUG "IF-address changed from %lx to %lx\n", ipts->old_pa_addr, mdev->pa_addr); - if (ipfr->version == 4) { - if (ipfr->saddr == ipts->old_pa_addr) { - printk(KERN_DEBUG "readdressing %lx to %lx\n", ipfr->saddr, mdev->pa_addr); - ipfr->saddr = mdev->pa_addr; - } - } - } - /* dstaddr change not so important */ -#endif break; case ETH_P_IPX: proto = PPP_IPX; /* untested */ @@ -1529,8 +1514,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) /* Pull off the fake header we stuck on earlier to keep * the fragemntation code happy. - * this will break the ISDN_SYNCPPP_READDRESS hack a few lines - * above. So, enabling this is no longer allowed */ skb_pull(skb,IPPP_MAX_HEADER); @@ -1548,7 +1531,13 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) * sk_buff. old call to dev_alloc_skb only reserved * 16 bytes, now we are looking what the driver want. */ - hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER; + /* + * Note: hl might still be insufficient because the method + * above does not account for a possibible MPPP slave channel + * which had larger HL header space requirements than the + * master. + */ new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC); if (new_skb) { u_char *buf; @@ -1654,13 +1643,16 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len); isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot); } + save_flags(flags); + cli(); if (isdn_net_send_skb(netdev, lp, skb)) { - if (lp->sav_skb) { /* whole sav_skb processing with disabled IRQs ?? */ + if (lp->sav_skb) { /* should never happen as sav_skb are sent with disabled IRQs) */ printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", netdev->name); dev_kfree_skb(skb); } else lp->sav_skb = skb; } + restore_flags(flags); return 0; } @@ -1744,12 +1736,6 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit) ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg & (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ); -#if 0 - if (ippp_table[nlp->ppp_slot]->mpppcfg != ippp_table[lp->ppp_slot]->mpppcfg) { - printk(KERN_WARNING "isdn_ppp_bundle: different MP options %04x and %04x\n", - ippp_table[nlp->ppp_slot]->mpppcfg, ippp_table[lp->ppp_slot]->mpppcfg); - } -#endif restore_flags(flags); return 0; @@ -2075,9 +2061,6 @@ isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) int len; isdn_net_local *lp = (isdn_net_local *) dev->priv; -#if 0 - printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n", cmd, lp->ppp_slot); -#endif if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) return -EINVAL; @@ -2241,17 +2224,20 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, { struct sk_buff *skb; unsigned char *p; - int count; + int count, hl; + unsigned long flags; int cnt = 0; isdn_net_local *lp = is->lp; /* Alloc large enough skb */ - skb = dev_alloc_skb(len + 16); + hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + skb = alloc_skb(len + hl + 16,GFP_ATOMIC); if(!skb) { printk(KERN_WARNING "ippp: CCP cannot send reset - out of memory\n"); return; } + skb_reserve(skb, hl); /* We may need to stuff an address and control field first */ if(!(is->pppcfg & SC_COMP_AC)) { @@ -2284,6 +2270,8 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, especially dunno what the sav_skb stuff is good for. */ count = skb->len; + save_flags(flags); + cli(); if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) { if (lp->sav_skb) { @@ -2297,21 +2285,41 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, cnt, count); lp->sav_skb = skb; } + restore_flags(flags); } /* Allocate the reset state vector */ static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is) { struct ippp_ccp_reset *r; - printk(KERN_DEBUG "ippp_ccp: allocating reset data structure\n"); r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL); - if(!r) + if(!r) { + printk(KERN_ERR "ippp_ccp: failed to allocate reset data" + " structure - no mem\n"); return NULL; + } memset(r, 0, sizeof(struct ippp_ccp_reset)); + printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r); is->reset = r; return r; } +/* Destroy the reset state vector. Kill all pending timers first. */ +static void isdn_ppp_ccp_reset_free(struct ippp_struct *is) +{ + unsigned int id; + + printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n", + is->reset); + for(id = 0; id < 256; id++) { + if(is->reset->rs[id]) { + isdn_ppp_ccp_reset_free_state(is, (unsigned char)id); + } + } + kfree(is->reset); + is->reset = NULL; +} + /* Free a given state and clear everything up for later reallocation */ static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, unsigned char id) @@ -2653,13 +2661,7 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, } if(type) { /* type=1 => Link compression */ -#if 0 - compressor = is->link_compressor; - stat = is->link_comp_stat; - new_proto = PPP_LINK_COMP; -#else return skb_in; -#endif } else { if(!master) { @@ -2683,9 +2685,11 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, } /* Allow for at least 150 % expansion (for now) */ - skb_out = dev_alloc_skb(skb_in->len + skb_in->len/2 + 32); + skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 + + skb_headroom(skb_in), GFP_ATOMIC); if(!skb_out) return skb_in; + skb_reserve(skb_out, skb_headroom(skb_in)); ret = (compressor->compress)(stat,skb_in,skb_out,*proto); if(!ret) { @@ -2914,7 +2918,6 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct } } - int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc) { ipc->next = ipc_head; @@ -2949,6 +2952,16 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_ printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit, (data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num); + /* If is has no valid reset state vector, we cannot allocate a + decompressor. The decompressor would cause reset transactions + sooner or later, and they need that vector. */ + + if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) { + printk(KERN_ERR "ippp_ccp: no reset data structure - can't" + " allow decompression.\n"); + return -ENOMEM; + } + while(ipc) { if(ipc->num == num) { stat = ipc->alloc(data); @@ -3000,5 +3013,3 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_ } return -EINVAL; } - - diff --git a/drivers/isdn/isdn_tty.c b/drivers/isdn/isdn_tty.c index e502f90dadb3c90cdc70133239eb4eafd5d461c8..5b301adb9db8ec773764e8ccf35f053c92edaecc 100644 --- a/drivers/isdn/isdn_tty.c +++ b/drivers/isdn/isdn_tty.c @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.c,v 1.73 1999/08/28 21:56:27 keil Exp $ +/* $Id: isdn_tty.c,v 1.80 1999/11/07 13:34:30 armin Exp $ * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * @@ -20,6 +20,30 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_tty.c,v $ + * Revision 1.80 1999/11/07 13:34:30 armin + * Fixed AT command line editor + * + * Revision 1.79 1999/10/29 18:35:08 armin + * Check number len in isdn_get_msnstr() to avoid buffer overflow. + * + * Revision 1.78 1999/10/28 23:03:51 armin + * Bugfix: now freeing channel on modem_hup() even when + * usage on ttyI has changed and error-report for + * AT-commands on wrong channel-state. + * + * Revision 1.77 1999/10/26 21:13:14 armin + * using define for checking phone number len in isdn_tty_getdial() + * + * Revision 1.76 1999/10/11 22:16:26 keil + * Suspend/Resume is possible without explicit ID too + * + * Revision 1.75 1999/10/08 18:59:32 armin + * Bugfix of too small MSN buffer and checking phone number + * in isdn_tty_getdial() + * + * Revision 1.74 1999/09/04 06:20:04 keil + * Changes from kernel set_current_state() + * * Revision 1.73 1999/08/28 21:56:27 keil * misplaced #endif caused ttyI crash in 2.3.X * @@ -348,7 +372,7 @@ static int bit2si[8] = static int si2bit[8] = {4, 1, 4, 4, 4, 4, 4, 4}; -char *isdn_tty_revision = "$Revision: 1.73 $"; +char *isdn_tty_revision = "$Revision: 1.80 $"; /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() @@ -1014,7 +1038,6 @@ void isdn_tty_modem_hup(modem_info * info, int local) { isdn_ctrl cmd; - int usage; if (!info) return; @@ -1068,10 +1091,7 @@ isdn_tty_modem_hup(modem_info * info, int local) } isdn_all_eaz(info->isdn_driver, info->isdn_channel); info->emu.mdmreg[REG_RINGCNT] = 0; - usage = isdn_calc_usage(info->emu.mdmreg[REG_SI1I], - info->emu.mdmreg[REG_L2PROT]); - isdn_free_channel(info->isdn_driver, info->isdn_channel, - usage); + isdn_free_channel(info->isdn_driver, info->isdn_channel, 0); } info->isdn_driver = -1; info->isdn_channel = -1; @@ -1108,8 +1128,8 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m) printk(KERN_DEBUG "Msusp ttyI%d\n", info->line); #endif l = strlen(id); - if ((info->isdn_driver >= 0) && l) { - cmd.parm.cmsg.Length = l+17; + if ((info->isdn_driver >= 0)) { + cmd.parm.cmsg.Length = l+18; cmd.parm.cmsg.Command = CAPI_FACILITY; cmd.parm.cmsg.Subcommand = CAPI_REQ; cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; @@ -1147,10 +1167,6 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m) int l; l = strlen(id); - if (!l) { - isdn_tty_modem_result(4, info); - return; - } for (j = 7; j >= 0; j--) if (m->mdmreg[REG_SI1] & (1 << j)) { si = bit2si[j]; @@ -1204,7 +1220,7 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m) isdn_command(&cmd); cmd.driver = info->isdn_driver; cmd.arg = info->isdn_channel; - cmd.parm.cmsg.Length = l+17; + cmd.parm.cmsg.Length = l+18; cmd.parm.cmsg.Command = CAPI_FACILITY; cmd.parm.cmsg.Subcommand = CAPI_REQ; cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; @@ -1901,12 +1917,7 @@ isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios) static int isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info) { -#ifdef COMPAT_HAS_NEW_WAITQ DECLARE_WAITQUEUE(wait, NULL); -#else - struct wait_queue wait = - {current, NULL}; -#endif int do_clocal = 0; unsigned long flags; int retval; @@ -2157,7 +2168,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) */ timeout = jiffies + HZ; while (!(info->lsr & UART_LSR_TEMT)) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(20); if (time_after(jiffies,timeout)) break; @@ -2173,7 +2184,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) info->ncarrier = 0; tty->closing = 0; if (info->blocked_open) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(50); wake_up_interruptible(&info->open_wait); } @@ -2375,11 +2386,7 @@ isdn_tty_modem_init(void) return -3; } #endif -#ifdef COMPAT_HAS_NEW_WAITQ init_MUTEX(&info->write_sem); -#else - info->write_sem = MUTEX; -#endif sprintf(info->last_cause, "0000"); sprintf(info->last_num, "none"); info->last_dir = 0; @@ -2396,13 +2403,8 @@ isdn_tty_modem_init(void) info->blocked_open = 0; info->callout_termios = m->cua_modem.init_termios; info->normal_termios = m->tty_modem.init_termios; -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); -#else - info->open_wait = 0; - info->close_wait = 0; -#endif info->isdn_driver = -1; info->isdn_channel = -1; info->drv_index = -1; @@ -3101,9 +3103,12 @@ isdn_tty_show_profile(int ridx, modem_info * info) static void isdn_tty_get_msnstr(char *n, char **p) { - while ((*p[0] >= '0' && *p[0] <= '9') || + int limit = ISDN_MSNLEN - 1; + + while (((*p[0] >= '0' && *p[0] <= '9') || /* Why a comma ??? */ - (*p[0] == ',')) + (*p[0] == ',')) && + (limit--)) *n++ = *p[0]++; *n = '\0'; } @@ -3115,16 +3120,18 @@ static void isdn_tty_getdial(char *p, char *q,int cnt) { int first = 1; - int limit=39; /* MUST match the size in isdn_tty_parse to avoid - buffer overflow */ + int limit = ISDN_MSNLEN - 1; /* MUST match the size of interface var to avoid + buffer overflow */ while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) { if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) || - (*p == '*') || (*p == '#')) + (*p == '*') || (*p == '#')) { *q++ = *p; - p++; - if(!--limit) + limit--; + } + if(!limit) break; + p++; first = 0; } *q = 0; @@ -3268,6 +3275,8 @@ isdn_tty_cmd_ATand(char **p, modem_info * info) case 'F': /* &F -Set Factory-Defaults */ p[0]++; + if (info->msr & UART_MSR_DCD) + PARSE_ERROR1; isdn_tty_reset_profile(m); isdn_tty_modem_reset_regs(info, 1); break; @@ -3919,6 +3928,12 @@ isdn_tty_parse_at(modem_info * info) break; case 'D': /* D - Dial */ + if (info->msr & UART_MSR_DCD) + PARSE_ERROR; + if (info->msr & UART_MSR_RI) { + isdn_tty_modem_result(3, info); + return; + } isdn_tty_getdial(++p, ds, sizeof ds); p += strlen(p); if (!strlen(m->msn)) @@ -4113,7 +4128,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) c = *p; total++; if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) { - /* Separator (CR oder LF) */ + /* Separator (CR or LF) */ m->mdmcmd[m->mdmcmdl] = 0; if (m->mdmreg[REG_ECHO] & BIT_ECHO) { eb[0] = c; @@ -4126,7 +4141,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) continue; } if (c == m->mdmreg[REG_BS] && m->mdmreg[REG_BS] < 128) { - /* Backspace-Funktion */ + /* Backspace-Function */ if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) { if (m->mdmcmdl) m->mdmcmdl--; @@ -4144,18 +4159,24 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) if (m->mdmcmdl < 255) { c = my_toupper(c); switch (m->mdmcmdl) { - case 0: - if (c == 'A') - m->mdmcmd[m->mdmcmdl] = c; - break; case 1: - if (c == 'T') + if (c == 'T') { m->mdmcmd[m->mdmcmdl] = c; + m->mdmcmd[++m->mdmcmdl] = 0; + break; + } else + m->mdmcmdl = 0; + /* Fall through, check for 'A' */ + case 0: + if (c == 'A') { + m->mdmcmd[m->mdmcmdl] = c; + m->mdmcmd[++m->mdmcmdl] = 0; + } break; default: m->mdmcmd[m->mdmcmdl] = c; + m->mdmcmd[++m->mdmcmdl] = 0; } - m->mdmcmd[++m->mdmcmdl] = 0; } } } diff --git a/drivers/isdn/isdn_tty.h b/drivers/isdn/isdn_tty.h index 87acd7be2fd384864f81c84a257a5889391d7e26..1c27b83009c986129596e035aa961ac071f9476e 100644 --- a/drivers/isdn/isdn_tty.h +++ b/drivers/isdn/isdn_tty.h @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.h,v 1.16 1999/08/22 20:26:10 calle Exp $ +/* $Id: isdn_tty.h,v 1.17 1999/09/21 19:00:35 armin Exp $ * header for Linux ISDN subsystem, tty related functions (linklevel). * @@ -20,6 +20,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_tty.h,v $ + * Revision 1.17 1999/09/21 19:00:35 armin + * Extended FCON message with added CPN + * can now be activated with Bit 1 of Reg 23. + * * Revision 1.16 1999/08/22 20:26:10 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -154,6 +158,7 @@ #define REG_CPN 23 #define BIT_CPN 1 +#define BIT_CPNFCON 2 extern void isdn_tty_modem_escape(void); extern void isdn_tty_modem_ring(void); diff --git a/drivers/isdn/isdn_ttyfax.c b/drivers/isdn/isdn_ttyfax.c index 7665aa812c266cd6da310a1a40e0fbcd6446b648..9b7268b32c5ccd8a6a36936e61e7e3da9fbacb3c 100644 --- a/drivers/isdn/isdn_ttyfax.c +++ b/drivers/isdn/isdn_ttyfax.c @@ -1,4 +1,4 @@ -/* $Id: isdn_ttyfax.c,v 1.3 1999/08/22 20:26:12 calle Exp $ +/* $Id: isdn_ttyfax.c,v 1.4 1999/09/21 19:00:35 armin Exp $ * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel). * * Copyright 1999 by Armin Schindler (mac@melware.de) @@ -20,6 +20,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_ttyfax.c,v $ + * Revision 1.4 1999/09/21 19:00:35 armin + * Extended FCON message with added CPN + * can now be activated with Bit 1 of Reg 23. + * * Revision 1.3 1999/08/22 20:26:12 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -46,7 +50,7 @@ #include "isdn_ttyfax.h" -static char *isdn_tty_fax_revision = "$Revision: 1.3 $"; +static char *isdn_tty_fax_revision = "$Revision: 1.4 $"; #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; } @@ -98,7 +102,7 @@ static void isdn_tty_fax_modem_result(int code, modem_info * info) break; case 2: /* +FCON */ /* Append CPN, if enabled */ - if ((m->mdmreg[REG_CPN] & BIT_CPN) && + if ((m->mdmreg[REG_CPN] & BIT_CPNFCON) && (!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) { sprintf(rs, "/%s", m->cpn); isdn_tty_at_cout(rs, info); @@ -907,76 +911,6 @@ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info) return 0; } -#if 0 - /* LO=n - Flow control opts */ - if (!strncmp(p[0], "LO", 2)) { /* TODO */ - p[0] += 2; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d",f->lo); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') - { - p[0]++; - sprintf(rs, "\r\n0,1,2"); - isdn_tty_at_cout(rs, info); - } - else - { - par = isdn_getnum(p); - if ((par < 0) || (par > 2)) - PARSE_ERROR1; - f->lo = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FLO=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } -#endif -#if 0 - /* LPL=n - Doc for polling cmd */ - if (!strncmp(p[0], "LPL", 3)) { /* TODO */ - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d",f->lpl); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') - { - p[0]++; - sprintf(rs, "\r\n0,1"); - isdn_tty_at_cout(rs, info); - } - else - { - par = isdn_getnum(p); - if ((par < 0) || (par > 1)) - PARSE_ERROR1; - f->lpl = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FLPL=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } -#endif /* MDL? - DCE Model */ if (!strncmp(p[0], "MDL?", 4)) { @@ -1066,41 +1000,6 @@ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info) return 0; } -#if 0 - /* PTS=n - Page transfer status */ - if (!strncmp(p[0], "PTS", 3)) { /* TODO */ - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d",f->pts); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') - { - p[0]++; - sprintf(rs, "\r\n0-5"); - isdn_tty_at_cout(rs, info); - } - else - { - par = isdn_getnum(p); - if ((par < 0) || (par > 5)) - PARSE_ERROR1; - f->pts = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FPTS=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } -#endif /* REL=n - Phase C received EOL alignment */ if (!strncmp(p[0], "REL", 3)) { @@ -1148,41 +1047,6 @@ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info) return 0; } -#if 0 - /* SPL=n - Enable polling */ - if (!strncmp(p[0], "SPL", 3)) { /* TODO */ - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->spl); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') - { - p[0]++; - sprintf(rs, "\r\n0,1"); - isdn_tty_at_cout(rs, info); - } - else - { - par = isdn_getnum(p); - if ((par < 0) || (par > 1)) - PARSE_ERROR1; - f->spl = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FSPL=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } -#endif /* Phase C Transmit Data Block Size */ if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */ diff --git a/drivers/isdn/isdn_v110.c b/drivers/isdn/isdn_v110.c index ae62378b875751b4b742a031730562db27ed0723..a3ac19caf09bd2918e09465a2d96186db2bd1396 100644 --- a/drivers/isdn/isdn_v110.c +++ b/drivers/isdn/isdn_v110.c @@ -1,4 +1,4 @@ -/* $Id: isdn_v110.c,v 1.2 1998/02/22 19:44:25 fritz Exp $ +/* $Id: isdn_v110.c,v 1.3 1999/10/30 09:49:28 keil Exp $ * Linux ISDN subsystem, V.110 related functions (linklevel). * @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_v110.c,v $ + * Revision 1.3 1999/10/30 09:49:28 keil + * Reinit of v110 structs + * * Revision 1.2 1998/02/22 19:44:25 fritz * Bugfixes and improvements regarding V.110, V.110 now running. * @@ -36,7 +39,7 @@ #undef ISDN_V110_DEBUG -char *isdn_v110_revision = "$Revision: 1.2 $"; +char *isdn_v110_revision = "$Revision: 1.3 $"; #define V110_38400 255 #define V110_19200 15 @@ -148,21 +151,13 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize) } /* isdn_v110_close frees private V.110 data structures */ -static void +void isdn_v110_close(isdn_v110_stream * v) { if (v == NULL) return; #ifdef ISDN_V110_DEBUG printk(KERN_DEBUG "v110 close\n"); -#if 0 - printk(KERN_DEBUG "isdn_v110_close: nbytes=%d\n", v->nbytes); - printk(KERN_DEBUG "isdn_v110_close: nbits=%d\n", v->nbits); - printk(KERN_DEBUG "isdn_v110_close: key=%d\n", v->key); - printk(KERN_DEBUG "isdn_v110_close: SyncInit=%d\n", v->SyncInit); - printk(KERN_DEBUG "isdn_v110:close: decodelen=%d\n", v->decodelen); - printk(KERN_DEBUG "isdn_v110_close: framelen=%d\n", v->framelen); -#endif #endif kfree(v->encodebuf); kfree(v); diff --git a/drivers/isdn/isdn_v110.h b/drivers/isdn/isdn_v110.h index 9ab5a93f36181518866927c9f9cf85ee19fd59ac..4bb6948498430d2f151fbac55c5d34af196770fa 100644 --- a/drivers/isdn/isdn_v110.h +++ b/drivers/isdn/isdn_v110.h @@ -1,4 +1,4 @@ -/* $Id: isdn_v110.h,v 1.1 1998/02/20 17:32:11 fritz Exp $ +/* $Id: isdn_v110.h,v 1.2 1999/10/30 09:49:28 keil Exp $ * Linux ISDN subsystem, V.110 related functions (linklevel). * @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_v110.h,v $ + * Revision 1.2 1999/10/30 09:49:28 keil + * Reinit of v110 structs + * * Revision 1.1 1998/02/20 17:32:11 fritz * First checkin (not yet completely functionable). * @@ -41,5 +44,6 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *); extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *); extern int isdn_v110_stat_callback(int, isdn_ctrl *); +extern void isdn_v110_close(isdn_v110_stream * v); #endif diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 2e580e1c7a611784cf5e3cbd8d3204612b99de79..9168aca8cbba3c10d9387f5d8f2a18965b96b228 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -1,8 +1,8 @@ -/* $Id: isdnloop.c,v 1.8 1998/11/18 18:59:43 armin Exp $ +/* $Id: isdnloop.c,v 1.9 1999/09/06 07:29:36 fritz Exp $ * ISDN low-level module implementing a dummy loop driver. * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1997 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 @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdnloop.c,v $ + * Revision 1.9 1999/09/06 07:29:36 fritz + * Changed my mail-address. + * * Revision 1.8 1998/11/18 18:59:43 armin * changes for 2.1.127 * @@ -56,7 +59,7 @@ #include "isdnloop.h" static char -*revision = "$Revision: 1.8 $"; +*revision = "$Revision: 1.9 $"; static int isdnloop_addcard(char *); diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h index 42906c143ee3e833b46b4b9d94810336c0799362..82266edbe3938b8d33cdae4a005c2a1808fefa23 100644 --- a/drivers/isdn/isdnloop/isdnloop.h +++ b/drivers/isdn/isdnloop/isdnloop.h @@ -1,8 +1,8 @@ -/* $Id: isdnloop.h,v 1.3 1998/04/14 20:59:35 he Exp $ +/* $Id: isdnloop.h,v 1.4 1999/09/06 07:29:36 fritz Exp $ * Loopback lowlevel module for testing of linklevel. * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1997 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 @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdnloop.h,v $ + * Revision 1.4 1999/09/06 07:29:36 fritz + * Changed my mail-address. + * * Revision 1.3 1998/04/14 20:59:35 he * merged 2.1.94 changes * diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 77f0ed45f7d9afa028cfde2d4322077a23ade85c..679aaddeb46ecc36b6e6704718f4fd809abaa1c4 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -86,9 +86,7 @@ int pcbit_init_dev(int board, int mem_base, int irq) dev_pcbit[board] = dev; memset(dev, 0, sizeof(struct pcbit_dev)); -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&dev->set_running_wq); -#endif if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) dev->sh_mem = (unsigned char*) mem_base; @@ -593,20 +591,6 @@ void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, dev->b1->s_refnum, dev->b2->s_refnum); #endif -#if 0 - if (dev->b1->s_refnum == refnum) - chan = dev->b1; - else { - - if (dev->b2->s_refnum == refnum) - chan = dev->b2; - else { - chan = NULL; - printk(KERN_WARNING "Connection Confirm - refnum doesn't match chan\n"); - break; - } - } -#else /* We just try to find a channel in the right state */ if (dev->b1->fsm_state == ST_CALL_INIT) @@ -620,7 +604,6 @@ void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, break; } } -#endif if (capi_decode_conn_conf(chan, skb, &complete)) { printk(KERN_DEBUG "conn_conf indicates error\n"); pcbit_fsm_event(dev, chan, EV_ERROR, NULL); diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c index bc1b079a2d123b73ad0cf23065ecf8bbf6ff8a40..36bd6f8aad9ecb7337ec49bb1d2df150881b55a5 100644 --- a/drivers/isdn/pcbit/layer2.c +++ b/drivers/isdn/pcbit/layer2.c @@ -375,16 +375,11 @@ pcbit_receive(struct pcbit_dev *dev) if (dev->read_frame) { printk(KERN_DEBUG "pcbit_receive: Type 0 frame and read_frame != NULL\n"); -#if 0 - pcbit_l2_error(dev); - return; -#else /* discard previous queued frame */ if (dev->read_frame->skb) kfree_skb(dev->read_frame->skb); kfree(dev->read_frame); dev->read_frame = NULL; -#endif } frame = kmalloc(sizeof(struct frame_buf), GFP_ATOMIC); @@ -460,14 +455,10 @@ pcbit_receive(struct pcbit_dev *dev) if (!(frame = dev->read_frame)) { printk("Type 1 frame and no frame queued\n"); -#if 1 /* usually after an error: toss frame */ dev->readptr += tt; if (dev->readptr > dev->sh_mem + BANK2 + BANKLEN) dev->readptr -= BANKLEN; -#else - pcbit_l2_error(dev); -#endif return; } diff --git a/drivers/isdn/pcbit/module.c b/drivers/isdn/pcbit/module.c index 7995520194ad2b90be6accf5242c25ac588581fe..9d3aa8007ddb82daf174191e4044aac91c887ac3 100644 --- a/drivers/isdn/pcbit/module.c +++ b/drivers/isdn/pcbit/module.c @@ -102,7 +102,6 @@ void cleanup_module(void) } #else -#ifdef COMPAT_HAS_NEW_SETUP #define MAX_PARA (MAX_PCBIT_CARDS * 2) #include <linux/init.h> static int __init pcbit_setup(char *line) @@ -112,11 +111,6 @@ static int __init pcbit_setup(char *line) int ints[MAX_PARA+1]; str = get_options(line, MAX_PARA, ints); -#else -void pcbit_setup(char *str, int *ints) -{ - int i, j, argc; -#endif argc = ints[0]; i = 0; j = 1; @@ -135,13 +129,9 @@ void pcbit_setup(char *str, int *ints) i++; } -#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("pcbit=", pcbit_setup); -#else -} -#endif #endif diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h index 45c68871dd5b55fb8f47b95c464abeae37ce0321..d284cc70f0d540b1cb8e3a140dec8950fef64705 100644 --- a/drivers/isdn/pcbit/pcbit.h +++ b/drivers/isdn/pcbit/pcbit.h @@ -68,11 +68,7 @@ struct pcbit_dev { struct frame_buf *write_queue; /* Protocol start */ -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t set_running_wq; -#else - struct wait_queue *set_running_wq; -#endif struct timer_list set_running_timer; struct timer_list error_recover_timer; diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index 788950eebf5aa2e01747079f631840681ab0233a..e455c074e6f64dc590b4eb5e596078ad2c7bf2c5 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -164,7 +164,7 @@ int init_sc(void) if(do_reset) { pr_debug("Doing a SAFE probe reset\n"); outb(0xFF, io[b] + RESET_OFFSET); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(milliseconds(10000)); } pr_debug("RAM Base for board %d is 0x%x, %s probe\n", b, ram[b], @@ -512,19 +512,10 @@ int identify_board(unsigned long rambase, unsigned int iobase) * Try to identify a PRI card */ outb(PRI_BASEPG_VAL, pgport); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); sig = readl(rambase + SIG_OFFSET); pr_debug("Looking for a signature, got 0x%x\n", sig); -#if 0 -/* - * For Gary: - * If it's a timing problem, it should be gone with the above schedule() - * Another possible reason may be the missing volatile in the original - * code. readl() does this for us. - */ - printk(""); /* Hack! Doesn't work without this !!!??? */ -#endif if(sig == SIGNATURE) return PRI_BOARD; @@ -532,13 +523,10 @@ int identify_board(unsigned long rambase, unsigned int iobase) * Try to identify a PRI card */ outb(BRI_BASEPG_VAL, pgport); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); sig = readl(rambase + SIG_OFFSET); pr_debug("Looking for a signature, got 0x%x\n", sig); -#if 0 - printk(""); /* Hack! Doesn't work without this !!!??? */ -#endif if(sig == SIGNATURE) return BRI_BOARD; @@ -567,7 +555,7 @@ int identify_board(unsigned long rambase, unsigned int iobase) */ x = 0; while((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); x++; } diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 9915cb0d8cacc07ae974159596312f9d37f195d4..141d5254dbeae762a66777cd785a9b9d2eafad5e 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -15,9 +15,6 @@ extern int send_and_receive(int, unsigned int, unsigned char,unsigned char, extern board *adapter[]; -#if 0 -static char *ChannelStates[] = { "Idle", "Ready", "Connecting", "Connected", "Disconnecting" }; -#endif int GetStatus(int card, boardInfo *); @@ -42,7 +39,7 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOLOAD: ioctl received\n", adapter[card]->devicename); if(adapter[card]->EngineUp) { - pr_debug("%s: SCIOCLOAD: Command Failed, LoadProc while engine running.\n", + pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n", adapter[card]->devicename); return -1; } @@ -56,12 +53,12 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc, 0, sizeof(srec), srec, &rcvmsg, SAR_TIMEOUT); if(status) { - pr_debug("%s: SCIOCLOAD: Command Failed, status = %d\n", + pr_debug("%s: SCIOCLOAD: command failed, status = %d\n", adapter[card]->devicename, status); return -1; } else { - pr_debug("%s: SCIOCLOAD: Command Sucessful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCLOAD: command successful\n", adapter[card]->devicename); return 0; } } @@ -70,7 +67,7 @@ int sc_ioctl(int card, scs_ioctl *data) { pr_debug("%s: SCIOSTART: ioctl received\n", adapter[card]->devicename); if(adapter[card]->EngineUp) { - pr_debug("%s: SCIOCSTART: Command Failed, Engine already running.\n", + pr_debug("%s: SCIOCSTART: command failed, engine already running.\n", adapter[card]->devicename); return -1; } @@ -94,16 +91,16 @@ int sc_ioctl(int card, scs_ioctl *data) if ((err = copy_from_user(&switchtype, (char *) data->dataptr, sizeof(char)))) return err; - pr_debug("%s: SCIOCSETSWITCH: Setting switch type to %d\n", adapter[card]->devicename, + pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n", adapter[card]->devicename, switchtype); status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType, 0, sizeof(char),&switchtype,&rcvmsg, SAR_TIMEOUT); if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETSWITCH: Command Successful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCSETSWITCH: command successful\n", adapter[card]->devicename); return 0; } else { - pr_debug("%s: SCIOCSETSWITCH: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -123,10 +120,10 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSwitchType, 0, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCGETSWITCH: Command Sucessful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCGETSWITCH: command successful\n", adapter[card]->devicename); } else { - pr_debug("%s: SCIOCGETSWITCH: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -156,10 +153,10 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status) { - pr_debug("%s: SCIOCGETSPID: Command Sucessful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCGETSPID: command successful\n", adapter[card]->devicename); } else { - pr_debug("%s: SCIOCGETSPID: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -188,18 +185,18 @@ int sc_ioctl(int card, scs_ioctl *data) if ((err = copy_from_user(spid, (char *) data->dataptr, sizeof(spid)))) return err; - pr_debug("%s: SCIOCSETSPID: Setting channel %d spid to %s\n", + pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n", adapter[card]->devicename, data->channel, spid); status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSPID, data->channel, strlen(spid), spid, &rcvmsg, SAR_TIMEOUT); if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETSPID: Command Successful\n", + pr_debug("%s: SCIOCSETSPID: command successful\n", adapter[card]->devicename); return 0; } else { - pr_debug("%s: SCIOCSETSPID: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -219,10 +216,10 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status) { - pr_debug("%s: SCIOCGETDN: Command Sucessful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCGETDN: command successful\n", adapter[card]->devicename); } else { - pr_debug("%s: SCIOCGETDN: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -252,18 +249,18 @@ int sc_ioctl(int card, scs_ioctl *data) if ((err = copy_from_user(dn, (char *) data->dataptr, sizeof(dn)))) return err; - pr_debug("%s: SCIOCSETDN: Setting channel %d dn to %s\n", + pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n", adapter[card]->devicename, data->channel, dn); status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetMyNumber, data->channel, strlen(dn),dn,&rcvmsg, SAR_TIMEOUT); if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETDN: Command Successful\n", + pr_debug("%s: SCIOCSETDN: command successful\n", adapter[card]->devicename); return 0; } else { - pr_debug("%s: SCIOCSETDN: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -273,7 +270,7 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOTRACE: ioctl received\n", adapter[card]->devicename); /* adapter[card]->trace = !adapter[card]->trace; - pr_debug("%s: SCIOCTRACE: Tracing turned %s\n", adapter[card]->devicename, + pr_debug("%s: SCIOCTRACE: tracing turned %s\n", adapter[card]->devicename, adapter[card]->trace ? "ON" : "OFF"); */ break; @@ -305,11 +302,11 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetCallType, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCGETSPEED: Command Sucessful\n", + pr_debug("%s: SCIOCGETSPEED: command successful\n", adapter[card]->devicename); } else { - pr_debug("%s: SCIOCGETSPEED: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c index 4d4765f792470ad1e817c78095f586d9441df2c3..871a696434799daf6da206ed4af8f8a9fa6706ff 100644 --- a/drivers/isdn/sc/message.c +++ b/drivers/isdn/sc/message.c @@ -1,5 +1,5 @@ /* - * $Id: message.c,v 1.4 1999/01/05 18:29:47 he Exp $ + * $Id: message.c,v 1.5 1999/09/04 06:20:07 keil Exp $ * Copyright (C) 1996 SpellCaster Telecommunications Inc. * * message.c - functions for sending and receiving control messages @@ -266,7 +266,7 @@ int send_and_receive(int card, tries = 0; /* wait for the response */ while (tries < timeout) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); pr_debug("SAR waiting..\n"); diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c index d75cb04d7f7b4fb43d11a57a68b1e50470d4ce7e..31e562c57b046e5470eed56d8bfeff74bef6584e 100644 --- a/drivers/isdn/sc/packet.c +++ b/drivers/isdn/sc/packet.c @@ -1,5 +1,5 @@ /* - * $Id: packet.c,v 1.4 1998/02/12 23:08:50 keil Exp $ + * $Id: packet.c,v 1.5 1999/08/31 11:20:41 paul Exp $ * Copyright (C) 1996 SpellCaster Telecommunications Inc. * * This program is free software; you can redistribute it and/or modify @@ -52,11 +52,11 @@ int sndpkt(int devId, int channel, struct sk_buff *data) card = get_card_from_id(devId); if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); + pr_debug("invalid param: %d is not a valid card id\n", card); return -ENODEV; } - pr_debug("%s: Send Packet: frst = 0x%x nxt = %d f = %d n = %d\n", + pr_debug("%s: sndpkt: frst = 0x%x nxt = %d f = %d n = %d\n", adapter[card]->devicename, adapter[card]->channel[channel].first_sendbuf, adapter[card]->channel[channel].next_sendbuf, @@ -64,26 +64,26 @@ int sndpkt(int devId, int channel, struct sk_buff *data) adapter[card]->channel[channel].num_sendbufs); if(!adapter[card]->channel[channel].free_sendbufs) { - pr_debug("%s: Out out TX buffers\n", adapter[card]->devicename); + pr_debug("%s: out of TX buffers\n", adapter[card]->devicename); return -EINVAL; } if(data->len > BUFFER_SIZE) { - pr_debug("%s: Data overflows buffer size (data > buffer)\n", adapter[card]->devicename); + pr_debug("%s: data overflows buffer size (data > buffer)\n", adapter[card]->devicename); return -EINVAL; } ReqLnkWrite.buff_offset = adapter[card]->channel[channel].next_sendbuf * BUFFER_SIZE + adapter[card]->channel[channel].first_sendbuf; ReqLnkWrite.msg_len = data->len; /* sk_buff size */ - pr_debug("%s: Writing %d bytes to buffer offset 0x%x\n", adapter[card]->devicename, + pr_debug("%s: writing %d bytes to buffer offset 0x%x\n", adapter[card]->devicename, ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset); memcpy_toshmem(card, (char *)ReqLnkWrite.buff_offset, data->data, ReqLnkWrite.msg_len); /* * sendmessage */ - pr_debug("%s: Send Packet size=%d, buf_offset=0x%x buf_indx=%d\n", + pr_debug("%s: sndpkt size=%d, buf_offset=0x%x buf_indx=%d\n", adapter[card]->devicename, ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset, adapter[card]->channel[channel].next_sendbuf); @@ -92,7 +92,7 @@ int sndpkt(int devId, int channel, struct sk_buff *data) channel+1, sizeof(LLData), (unsigned int*)&ReqLnkWrite); len = data->len; if(status) { - pr_debug("%s: Failed to send packet, status = %d\n", adapter[card]->devicename, status); + pr_debug("%s: failed to send packet, status = %d\n", adapter[card]->devicename, status); return -1; } else { @@ -101,7 +101,7 @@ int sndpkt(int devId, int channel, struct sk_buff *data) ++adapter[card]->channel[channel].next_sendbuf == adapter[card]->channel[channel].num_sendbufs ? 0 : adapter[card]->channel[channel].next_sendbuf; - pr_debug("%s: Packet sent successfully\n", adapter[card]->devicename); + pr_debug("%s: packet sent successfully\n", adapter[card]->devicename); dev_kfree_skb(data); indicate_status(card,ISDN_STAT_BSENT,channel, (char *)&len); } @@ -114,7 +114,7 @@ void rcvpkt(int card, RspMessage *rcvmsg) struct sk_buff *skb; if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); + pr_debug("invalid param: %d is not a valid card id\n", card); return; } @@ -122,7 +122,7 @@ void rcvpkt(int card, RspMessage *rcvmsg) case 0x01: case 0x02: case 0x70: - pr_debug("%s: Error status code: 0x%x\n", adapter[card]->devicename, rcvmsg->rsp_status); + pr_debug("%s: error status code: 0x%x\n", adapter[card]->devicename, rcvmsg->rsp_status); return; case 0x00: if (!(skb = dev_alloc_skb(rcvmsg->msg_data.response.msg_len))) { @@ -144,7 +144,7 @@ void rcvpkt(int card, RspMessage *rcvmsg) /* * Recycle the buffer */ - pr_debug("%s: Buffer size : %d\n", adapter[card]->devicename, BUFFER_SIZE); + pr_debug("%s: buffer size : %d\n", adapter[card]->devicename, BUFFER_SIZE); /* memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */ newll.buff_offset = rcvmsg->msg_data.response.buff_offset; newll.msg_len = BUFFER_SIZE; @@ -163,30 +163,30 @@ int setup_buffers(int card, int c) LLData RcvBuffOffset; if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); + pr_debug("invalid param: %d is not a valid card id\n", card); return -ENODEV; } /* * Calculate the buffer offsets (send/recv/send/recv) */ - pr_debug("%s: Seting up channel buffer space in shared RAM\n", adapter[card]->devicename); + pr_debug("%s: setting up channel buffer space in shared RAM\n", adapter[card]->devicename); buffer_size = BUFFER_SIZE; nBuffers = ((adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2; nBuffers = nBuffers > BUFFERS_MAX ? BUFFERS_MAX : nBuffers; - pr_debug("%s: Calculating buffer space: %d buffers, %d big\n", adapter[card]->devicename, + pr_debug("%s: calculating buffer space: %d buffers, %d big\n", adapter[card]->devicename, nBuffers, buffer_size); if(nBuffers < 2) { - pr_debug("%s: Not enough buffer space\n", adapter[card]->devicename); + pr_debug("%s: not enough buffer space\n", adapter[card]->devicename); return -1; } cBase = (nBuffers * buffer_size) * (c - 1); - pr_debug("%s: Channel buffer offset from Shared RAM: 0x%x\n", adapter[card]->devicename, cBase); + pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n", adapter[card]->devicename, cBase); adapter[card]->channel[c-1].first_sendbuf = BUFFER_BASE + cBase; adapter[card]->channel[c-1].num_sendbufs = nBuffers / 2; adapter[card]->channel[c-1].free_sendbufs = nBuffers / 2; adapter[card]->channel[c-1].next_sendbuf = 0; - pr_debug("%s: Send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n", + pr_debug("%s: send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n", adapter[card]->devicename, adapter[card]->channel[c-1].first_sendbuf, adapter[card]->channel[c-1].num_sendbufs, @@ -196,13 +196,13 @@ int setup_buffers(int card, int c) /* * Prep the receive buffers */ - pr_debug("%s: Adding %d RecvBuffers:\n", adapter[card]->devicename, nBuffers /2); + pr_debug("%s: adding %d RecvBuffers:\n", adapter[card]->devicename, nBuffers /2); for (i = 0 ; i < nBuffers / 2; i++) { RcvBuffOffset.buff_offset = ((adapter[card]->channel[c-1].first_sendbuf + (nBuffers / 2) * buffer_size) + (buffer_size * i)); RcvBuffOffset.msg_len = buffer_size; - pr_debug("%s: Adding RcvBuffer #%d offset=0x%x sz=%d buffsz:%d\n", + pr_debug("%s: adding RcvBuffer #%d offset=0x%x sz=%d bufsz:%d\n", adapter[card]->devicename, i + 1, RcvBuffOffset.buff_offset, RcvBuffOffset.msg_len,buffer_size); diff --git a/drivers/misc/acpi.c b/drivers/misc/acpi.c index 3538155a581582c2b295f40cf106ef6db26ca64d..3fd6bcc3c8ae4b67209627c63f3f8145a0e10998 100644 --- a/drivers/misc/acpi.c +++ b/drivers/misc/acpi.c @@ -917,7 +917,7 @@ static int __init acpi_init(void) acpi_irq, SA_INTERRUPT | SA_SHIRQ, "acpi", - NULL)) { + acpi_facp)) { printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", acpi_facp->sci_int); acpi_destroy_tables(); @@ -956,7 +956,7 @@ static void __exit acpi_exit(void) acpi_release_ioports(acpi_facp); if (acpi_facp->sci_int) - free_irq(acpi_facp->sci_int, NULL); + free_irq(acpi_facp->sci_int, acpi_facp); acpi_destroy_tables(); } diff --git a/drivers/net/82596.c b/drivers/net/82596.c index f3e1839041ebbf2471f49acc5f096f06a8873a42..0b8a9723b73cd3bacd176252e70e09dce6031e69 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -11,10 +11,15 @@ by Richard Hirst <richard@sleepie.demon.co.uk> Renamed to be 82596.c - *** Untested on Apricot hardware, and may require some hacking - *** to make it work. The old 82596.c reported hasn't worked - *** since 1.3.xx anyway. I have been unable to find any users - *** of Apricot hardware to test this on. + 980825: Changed to receive directly in to sk_buffs which are + allocated at open() time. Eliminates copy on incoming frames + (small ones are still copied). Shared data now held in a + non-cached page, so we can run on 68060 in copyback mode. + + TBD: + * look at deferring rx frames rather than discarding (as per tulip) + * handle tx ring full as per tulip + * performace test to tune rx_copybreak Most of my modifications relate to the braindead big-endian implementation by Intel. When the i596 is operating in @@ -57,12 +62,22 @@ static const char *version = "82596.c:v1.0 15/07/98\n"; #include <asm/bitops.h> #include <asm/io.h> #include <asm/dma.h> -#include <asm/pgtable.h> /*?? */ +#include <asm/pgtable.h> + +#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_MVME16x_NET_MODULE) +#define ENABLE_MVME16x_NET +#endif +#if defined(CONFIG_BVME6000_NET) || defined(CONFIG_BVME6000_NET_MODULE) +#define ENABLE_BVME6000_NET +#endif +#if defined(CONFIG_APRICOT) || defined(CONFIG_APRICOT_MODULE) +#define ENABLE_APRICOT +#endif -#ifdef CONFIG_MVME16x_NET +#ifdef ENABLE_MVME16x_NET #include <asm/mvme16xhw.h> #endif -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET #include <asm/bvme6000hw.h> #endif @@ -83,11 +98,12 @@ static const char *version = "82596.c:v1.0 15/07/98\n"; #define MACH_IS_APRICOT 0 #else #define WSWAPrfd(x) x +#define WSWAPrbd(x) ((struct i596_rbd *)(x)) #define WSWAPiscp(x) ((struct i596_iscp *)(x)) #define WSWAPscb(x) ((struct i596_scb *)(x)) #define WSWAPcmd(x) x #define WSWAPtbd(x) x -#define WSWAPchar(x) x +#define WSWAPchar(x) ((char *)(x)) #define ISCP_BUSY 0x0001 #define MACH_IS_APRICOT 1 #endif @@ -103,19 +119,22 @@ static const char *version = "82596.c:v1.0 15/07/98\n"; #define PORT_ALTSCP 0x02 /* alternate SCB address */ #define PORT_ALTDUMP 0x03 /* Alternate DUMP address */ -#ifndef HAVE_ALLOC_SKB -#define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority) -#define kfree_skbmem(buff, size) kfree_s(buff,size) -#endif +#define I82596_DEBUG 1 -#define APRICOT_DEBUG 2 - -#ifdef APRICOT_DEBUG -int i596_debug = APRICOT_DEBUG; +#ifdef I82596_DEBUG +int i596_debug = I82596_DEBUG; #else int i596_debug = 1; #endif +/* Copy frames shorter than rx_copybreak, otherwise pass on up in + * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha). + */ +static int rx_copybreak = 100; + +#define PKT_BUF_SZ 1536 +#define MAX_MC_CNT 64 + #define I596_TOTAL_SIZE 17 #define I596_NULL -1 @@ -179,12 +198,22 @@ struct i596_rfd { unsigned short stat; unsigned short cmd; struct i596_rfd *next; - long rbd; + struct i596_rbd *rbd; unsigned short count; unsigned short size; - char data[1532]; }; +struct i596_rbd { + unsigned short count; + unsigned short zero1; + struct i596_rbd *next; + char *data; + unsigned short size; + unsigned short zero2; + struct sk_buff *skb; +}; + +#define TX_RING_SIZE 16 #define RX_RING_SIZE 16 struct i596_scb { @@ -222,6 +251,9 @@ struct i596_private { struct i596_cmd set_conf; char i596_config[16]; struct i596_cmd tdr; + struct i596_cmd mc_cmd; /* Keep these three together!!! */ + short mc_cnt; /* Keep these three together!!! */ + char mc_addrs[MAX_MC_CNT*6]; /* Keep these three together!!! */ unsigned long stat; int last_restart __attribute__((aligned(4))); struct i596_rfd *rx_tail; @@ -230,6 +262,11 @@ struct i596_private { int cmd_backlog; unsigned long last_cmd; struct net_device_stats stats; + struct i596_rfd rfds[RX_RING_SIZE]; + struct i596_rbd rbds[RX_RING_SIZE]; + struct tx_cmd tx_cmds[TX_RING_SIZE]; + struct i596_tbd tbds[TX_RING_SIZE]; + int next_tx_cmd; }; char init_setup[] = @@ -262,23 +299,24 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd); static void print_eth(char *); static void set_multicast_list(struct net_device *dev); +static int rx_ring_size = RX_RING_SIZE; static int ticks_limit = 25; static int max_cmd_backlog = 16; static inline void CA(struct net_device *dev) { -#ifdef CONFIG_MVME16x_NET +#ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) { ((struct i596_reg *) dev->base_addr)->ca = 1; } #endif -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) { volatile u32 i = *(volatile u32 *) (dev->base_addr); } #endif -#ifdef CONFIG_APRICOT_i596 +#ifdef ENABLE_APRICOT if (MACH_IS_APRICOT) { outw(0, (short) (dev->base_addr) + 4); } @@ -288,14 +326,14 @@ static inline void CA(struct net_device *dev) static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x) { -#ifdef CONFIG_MVME16x_NET +#ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) { struct i596_reg *p = (struct i596_reg *) (dev->base_addr); p->porthi = ((c) | (u32) (x)) & 0xffff; p->portlo = ((c) | (u32) (x)) >> 16; } #endif -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) { u32 v = (u32) (c) | (u32) (x); v = ((u32) (v) << 16) | ((u32) (v) >> 16); @@ -307,7 +345,7 @@ static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x) } -#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET) +#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET) static void i596_error(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; @@ -333,77 +371,88 @@ static void i596_error(int irq, void *dev_id, struct pt_regs *regs) } #endif -static inline int init_rx_bufs(struct net_device *dev, int num) +static inline void init_rx_bufs(struct net_device *dev) { - struct i596_private *lp = (struct i596_private *) dev->priv; + struct i596_private *lp = (struct i596_private *)dev->priv; int i; struct i596_rfd *rfd; - - lp->scb.rfd = (struct i596_rfd *) I596_NULL; + struct i596_rbd *rbd; if (i596_debug > 1) - printk("%s: init_rx_bufs %d.\n", dev->name, num); + printk ("%s: init_rx_bufs %d.\n", dev->name, rx_ring_size); - for (i = 0; i < num; i++) { - if (!(rfd = (struct i596_rfd *) kmalloc(sizeof(struct i596_rfd), GFP_KERNEL))) - break; + /* First build the Receive Buffer Descriptor List */ - rfd->stat = 0x0000; - rfd->rbd = I596_NULL; - rfd->count = 0; - rfd->size = 1532; - if (i == 0) { - rfd->cmd = CMD_EOL; - lp->rx_tail = rfd; - } else - rfd->cmd = 0x0000; - - rfd->next = lp->scb.rfd; - lp->scb.rfd = WSWAPrfd(rfd); + for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { + struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ); + + if (skb == NULL) + panic("82596: alloc_skb() failed"); + skb->dev = dev; + rbd->next = WSWAPrbd(rbd+1); + rbd->skb = skb; + rbd->data = WSWAPchar(skb->tail); + rbd->size = PKT_BUF_SZ; +#ifdef __mc68000__ + cache_clear(virt_to_phys(skb->tail), PKT_BUF_SZ); +#endif } + lp->rbds[rx_ring_size-1].next = WSWAPrbd(lp->rbds); - if (i != 0) - lp->rx_tail->next = lp->scb.rfd; + /* Now build the Receive Frame Descriptor List */ - return (i); + for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) { + rfd->rbd = (struct i596_rbd *)I596_NULL; + rfd->next = WSWAPrfd(rfd+1); + rfd->cmd = CMD_FLEX; + } + lp->scb.rfd = WSWAPrfd(lp->rfds); + lp->rfds[0].rbd = WSWAPrbd(lp->rbds); + rfd = lp->rfds + rx_ring_size - 1; + lp->rx_tail = rfd; + rfd->next = WSWAPrfd(lp->rfds); + rfd->cmd = CMD_EOL|CMD_FLEX; } static inline void remove_rx_bufs(struct net_device *dev) { - struct i596_private *lp = (struct i596_private *) dev->priv; - struct i596_rfd *rfd = WSWAPrfd(lp->scb.rfd); - - lp->rx_tail->next = (struct i596_rfd *) I596_NULL; + struct i596_private *lp = (struct i596_private *)dev->priv; + struct i596_rbd *rbd; + int i; - do { - lp->scb.rfd = rfd->next; - kfree(rfd); - rfd = WSWAPrfd(lp->scb.rfd); + for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { + if (rbd->skb == NULL) + break; + dev_kfree_skb(rbd->skb); } - while (rfd != lp->rx_tail); } static inline void init_i596_mem(struct net_device *dev) { struct i596_private *lp = (struct i596_private *) dev->priv; -#if !defined(CONFIG_MVME16x_NET) && !defined(CONFIG_BVME6000_NET) +#if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET) short ioaddr = dev->base_addr; #endif int boguscnt = 100000; unsigned long flags; + int i; -#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET) -#ifdef CONFIG_MVME16x_NET +#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET) +#ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) { volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000; /* Disable all ints for now */ pcc2[0x28] = 1; pcc2[0x2a] = 0x40; - pcc2[0x2b] = 0x40; /* Set snooping bits now! */ + /* Following disables snooping. Snooping is not required + * as we make appropriate use of non-cached pages for + * shared data, and cache_push/cache_clear. + */ + pcc2[0x2b] = 0x00; } #endif -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) { volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG; @@ -419,7 +468,7 @@ static inline void init_i596_mem(struct net_device *dev) MPU_PORT(dev, PORT_ALTSCP, &lp->scp); -#else +#elif defined(ENABLE_APRICOT) /* change the scp address */ outw(0, ioaddr); @@ -431,15 +480,15 @@ static inline void init_i596_mem(struct net_device *dev) lp->last_cmd = jiffies; -#ifdef CONFIG_MVME16x_NET +#ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) lp->scp.sysbus = 0x00000054; #endif -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) lp->scp.sysbus = 0x0000004c; #endif -#ifdef CONFIG_APRICOT_i596 +#ifdef ENABLE_APRICOT if (MACH_IS_APRICOT) lp->scp.sysbus = 0x00440000; #endif @@ -454,7 +503,7 @@ static inline void init_i596_mem(struct net_device *dev) if (i596_debug > 1) printk("%s: starting i82596.\n", dev->name); -#if !defined(CONFIG_MVME16x_NET) && !defined(CONFIG_BVME6000_NET) +#if defined(ENABLE_APRICOT) (void) inb(ioaddr + 0x10); outb(4, ioaddr + 0xf); #endif @@ -466,9 +515,22 @@ static inline void init_i596_mem(struct net_device *dev) dev->name, lp->scb.status, lp->scb.command); break; } + + /* Ensure rx frame/buffer descriptors are tidy */ + /* Bit naff doing this here as well as in init_rx_bufs() */ + + for (i = 0; i < rx_ring_size; i++) { + lp->rfds[i].rbd = (struct i596_rbd *)I596_NULL; + lp->rfds[i].cmd = CMD_FLEX; + } + lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX; + lp->scb.rfd = WSWAPrfd(lp->rfds); + lp->rfds[0].rbd = WSWAPrbd(lp->rbds); + lp->rx_tail = lp->rfds + rx_ring_size - 1; + lp->scb.command = 0; -#ifdef CONFIG_MVME16x_NET +#ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) { volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000; @@ -478,7 +540,7 @@ static inline void init_i596_mem(struct net_device *dev) pcc2[0x2b] = 0x55; } #endif -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) { volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG; @@ -525,38 +587,88 @@ static inline void init_i596_mem(struct net_device *dev) static inline int i596_rx(struct net_device *dev) { - struct i596_private *lp = (struct i596_private *) dev->priv; + struct i596_private *lp = (struct i596_private *)dev->priv; struct i596_rfd *rfd; + struct i596_rbd *rbd; int frames = 0; if (i596_debug > 3) - printk("i596_rx()\n"); + printk ("i596_rx()\n"); - rfd = WSWAPrfd(lp->scb.rfd); /* Reference next frame descriptor to check */ + rfd = WSWAPrfd(lp->scb.rfd); /* Ref next frame to check */ - while ((rfd->stat) & STAT_C) { /* Loop while we have complete frames */ - if (i596_debug > 2) - print_eth(rfd->data); + while ((rfd->stat) & STAT_C) { /* Loop while complete frames */ + rbd = WSWAPrbd(rfd->rbd); /* Ref associated buffer desc */ + + if (i596_debug >2) + print_eth(WSWAPchar(rbd->data)); if ((rfd->stat) & STAT_OK) { /* a good frame */ - int pkt_len = rfd->count & 0x3fff; - struct sk_buff *skb = dev_alloc_skb(pkt_len); + int pkt_len = rbd->count & 0x3fff; + struct sk_buff *skb = rbd->skb; + int rx_in_place = 0; frames++; + /* Check if the packet is long enough to just accept + * without copying to a properly sized skbuff. + */ + + if (pkt_len > rx_copybreak) { + struct sk_buff *newskb; + char *temp; + + /* Get fresh skbuff to replace filled one. */ + newskb = dev_alloc_skb(PKT_BUF_SZ); + if (newskb == NULL) { + skb = NULL; /* drop pkt */ + goto memory_squeeze; + } + /* Pass up the skb already on the Rx ring. */ + temp = skb_put(skb, pkt_len); + if (WSWAPchar(rbd->data) != temp) + printk(KERN_ERR "%s: Internal consistency error " + "-- the skbuff addresses do not match" + " in i596_rx: %p vs. %p / %p.\n", dev->name, + WSWAPchar(rbd->data), + skb->head, temp); + rx_in_place = 1; + rbd->skb = newskb; + newskb->dev = dev; + rbd->data = WSWAPchar(newskb->tail); +#ifdef __mc68000__ + cache_clear(virt_to_phys(newskb->tail), PKT_BUF_SZ); +#endif + } + else + skb = dev_alloc_skb(pkt_len + 2); +memory_squeeze: if (skb == NULL) { - printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name); + /* XXX tulip.c can defer packets here!! */ + printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; - } else { + } + else { skb->dev = dev; - memcpy(skb_put(skb, pkt_len), rfd->data, pkt_len); - skb->protocol = eth_type_trans(skb, dev); + if (!rx_in_place) { + /* 16 byte align the data fields */ + skb_reserve(skb, 2); + memcpy(skb_put(skb,pkt_len), + WSWAPchar(rbd->data), pkt_len); + } + skb->protocol=eth_type_trans(skb,dev); + skb->len = pkt_len; +#ifdef __mc68000__ + cache_clear(virt_to_phys(rbd->skb->tail), + pkt_len); +#endif netif_rx(skb); lp->stats.rx_packets++; - lp->stats.rx_bytes += pkt_len; + lp->stats.rx_bytes+=pkt_len; } - } else { + } + else { lp->stats.rx_errors++; if ((rfd->stat) & 0x0001) lp->stats.collisions++; @@ -576,21 +688,40 @@ static inline int i596_rx(struct net_device *dev) /* Clear the buffer descriptor count and EOF + F flags */ + if (rbd != (struct i596_rbd *)I596_NULL) + rbd->count=0; + else + printk("%s: Null rbd - oops!\n", dev->name); + + /* Tidy the frame descriptor, marking it as end of list */ + + rfd->rbd = (struct i596_rbd *)I596_NULL; rfd->stat = 0; + rfd->cmd = CMD_EOL|CMD_FLEX; rfd->count = 0; - rfd->cmd = CMD_EOL; - lp->rx_tail->cmd = 0; + + /* Remove end-of-list from old end descriptor */ + + lp->rx_tail->cmd = CMD_FLEX; + + /* Update last frame descriptor to reference the one just + * processed */ + lp->rx_tail = rfd; + + /* Update record of next frame descriptor to process */ + lp->scb.rfd = rfd->next; - rfd = WSWAPrfd(lp->scb.rfd); /* Next frame descriptor to check */ + rfd = WSWAPrfd(lp->scb.rfd); /* Next frame desc. to check */ } if (i596_debug > 3) - printk("frames %d\n", frames); + printk ("frames %d\n", frames); return 0; } + static inline void i596_cleanup_cmd(struct i596_private *lp) { struct i596_cmd *ptr; @@ -617,13 +748,12 @@ static inline void i596_cleanup_cmd(struct i596_private *lp) lp->stats.tx_aborted_errors++; ptr->next = (struct i596_cmd *) I596_NULL; - kfree(tx_cmd); + tx_cmd->cmd.command = 0; /* Mark as free */ break; } case CmdMulticastList: { ptr->next = (struct i596_cmd *) I596_NULL; - kfree(ptr); break; } default: @@ -743,26 +873,19 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) static int i596_open(struct net_device *dev) { - int i; - if (i596_debug > 1) printk("%s: i596_open() irq %d.\n", dev->name, dev->irq); - if (request_irq(dev->irq, &i596_interrupt, 0, "apricot", dev)) + if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) return -EAGAIN; -#ifdef CONFIG_MVME16x_NET +#ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) { - if (request_irq(0x56, &i596_error, 0, "apricot_error", dev)) + if (request_irq(0x56, &i596_error, 0, "i82596_error", dev)) return -EAGAIN; } #endif - if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE) - printk("%s: only able to allocate %d receive buffers\n", dev->name, i); + init_rx_bufs(dev); - if (i < 4) { - free_irq(dev->irq, dev); - return -EAGAIN; - } dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; @@ -779,6 +902,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) struct i596_private *lp = (struct i596_private *) dev->priv; int ioaddr = dev->base_addr; struct tx_cmd *tx_cmd; + struct i596_tbd *tbd; if (i596_debug > 2) printk("%s: 82596 start xmit\n", dev->name); @@ -810,7 +934,8 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; } if (i596_debug > 3) - printk("%s: i596_start_xmit() called\n", dev->name); + printk("%s: i596_start_xmit(%x,%x) called\n", dev->name, + skb->len, (unsigned int)skb->data); /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ @@ -820,14 +945,18 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; dev->trans_start = jiffies; - tx_cmd = (struct tx_cmd *) kmalloc((sizeof(struct tx_cmd) + sizeof(struct i596_tbd)), GFP_ATOMIC); - if (tx_cmd == NULL) { - printk("%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name); + tx_cmd = lp->tx_cmds + lp->next_tx_cmd; + tbd = lp->tbds + lp->next_tx_cmd; + + if (tx_cmd->cmd.command) { + printk ("%s: xmit ring full, dropping packet.\n", + dev->name); lp->stats.tx_dropped++; dev_kfree_skb(skb); } else { - struct i596_tbd *tbd = (struct i596_tbd *) (tx_cmd + 1); + if (++lp->next_tx_cmd == TX_RING_SIZE) + lp->next_tx_cmd = 0; tx_cmd->tbd = WSWAPtbd(tbd); tbd->next = (struct i596_tbd *) I596_NULL; @@ -841,6 +970,9 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) tbd->data = WSWAPchar(skb->data); +#ifdef __mc68000__ + cache_push(virt_to_phys(skb->data), length); +#endif if (i596_debug > 3) print_eth(skb->data); i596_add_cmd(dev, (struct i596_cmd *) tx_cmd); @@ -854,7 +986,6 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - static void print_eth(char *add) { @@ -879,14 +1010,15 @@ int __init i82596_probe(struct net_device *dev) struct i596_private *lp; char eth_addr[6]; -#ifdef CONFIG_MVME16x_NET +#ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) { static int probed = 0; - +#ifdef XXX_FIXME if (mvme16x_config & MVME16x_CONFIG_NO_ETHERNET) { printk("Ethernet probe disabled - chip not present\n"); return ENODEV; } +#endif if (probed) return ENODEV; probed++; @@ -895,7 +1027,7 @@ int __init i82596_probe(struct net_device *dev) dev->irq = (unsigned) MVME16x_IRQ_I596; } #endif -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) { volatile unsigned char *rtc = (unsigned char *) BVME_RTC_BASE; unsigned char msr = rtc[3]; @@ -909,7 +1041,7 @@ int __init i82596_probe(struct net_device *dev) dev->irq = (unsigned) BVME_IRQ_I596; } #endif -#ifdef CONFIG_APRICOT_INTEL +#ifdef ENABLE_APRICOT int checksum = 0; int ioaddr = 0x300; @@ -953,22 +1085,28 @@ int __init i82596_probe(struct net_device *dev) if (i596_debug > 0) printk(version); - /* The APRICOT-specific entries in the device structure. */ + /* The 82596-specific entries in the device structure. */ dev->open = &i596_open; dev->stop = &i596_close; dev->hard_start_xmit = &i596_start_xmit; dev->get_stats = &i596_get_stats; dev->set_multicast_list = &set_multicast_list; - dev->mem_start = (int) kmalloc(sizeof(struct i596_private) + 0x0f, GFP_KERNEL); - /* align for scp */ - dev->priv = (void *) ((dev->mem_start + 0xf) & 0xfffffff0); + dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0); + dev->priv = (void *)(dev->mem_start); lp = (struct i596_private *) dev->priv; if (i596_debug) - printk("%s: lp at 0x%08lx, lp->scb at 0x%08lx\n" - ,dev->name, (unsigned long) lp, (unsigned long) &lp->scb); + printk ("%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n", + dev->name, (unsigned long)lp, + sizeof(struct i596_private), (unsigned long)&lp->scb); memset((void *) lp, 0, sizeof(struct i596_private)); + +#ifdef __mc68000__ + cache_push(virt_to_phys((void *)(dev->mem_start)), 4096); + cache_clear(virt_to_phys((void *)(dev->mem_start)), 4096); + kernel_set_cachemode((void *)(dev->mem_start), 4096, IOMAP_NOCACHE_SER); +#endif lp->scb.command = 0; lp->scb.cmd = (struct i596_cmd *) I596_NULL; lp->scb.rfd = (struct i596_rfd *) I596_NULL; @@ -984,7 +1122,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs) int boguscnt = 2000; unsigned short status, ack_cmd = 0; -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) { if (*(char *) BVME_LOCAL_IRQ_STAT & BVME_ETHERR) { i596_error(BVME_IRQ_I596, NULL, NULL); @@ -1063,13 +1201,12 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs) dev_kfree_skb(skb); ptr->next = (struct i596_cmd *) I596_NULL; - kfree(tx_cmd); + tx_cmd->cmd.command = 0; /* Mark free */ break; } case CmdMulticastList: { ptr->next = (struct i596_cmd *) I596_NULL; - kfree(ptr); break; } case CmdTDR: @@ -1141,7 +1278,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs) } lp->scb.command = ack_cmd; -#ifdef CONFIG_MVME16x_NET +#ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) { /* Ack the interrupt */ @@ -1150,7 +1287,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs) pcc2[0x2a] |= 0x08; } #endif -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) { volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG; @@ -1158,7 +1295,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs) *ethirq = 3; } #endif -#ifdef CONFIG_APRICOT_INTEL +#ifdef ENABLE_APRICOT (void) inb(ioaddr + 0x10); outb(4, ioaddr + 0xf); #endif @@ -1208,7 +1345,7 @@ static int i596_close(struct net_device *dev) i596_cleanup_cmd(lp); -#ifdef CONFIG_MVME16x_NET +#ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) { volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000; @@ -1218,7 +1355,7 @@ static int i596_close(struct net_device *dev) pcc2[0x2b] = 0x40; /* Set snooping bits now! */ } #endif -#ifdef CONFIG_BVME6000_NET +#ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) { volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG; @@ -1249,7 +1386,7 @@ static void set_multicast_list(struct net_device *dev) { struct i596_private *lp = (struct i596_private *) dev->priv; struct i596_cmd *cmd; - int config = 0; + int config = 0, cnt; if (i596_debug > 1) printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF"); @@ -1279,18 +1416,24 @@ static void set_multicast_list(struct net_device *dev) i596_add_cmd(dev, &lp->set_conf); } } + + cnt = dev->mc_count; + if (cnt > MAX_MC_CNT) + { + cnt = MAX_MC_CNT; + printk("%s: Only %d multicast addresses supported", + dev->name, cnt); + } + if (dev->mc_count > 0) { struct dev_mc_list *dmi; unsigned char *cp; - cmd = (struct i596_cmd *) kmalloc(sizeof(struct i596_cmd) + 2 + dev->mc_count * 6, GFP_ATOMIC); - if (cmd == NULL) { - printk("%s: set_multicast Memory squeeze.\n", dev->name); - return; - } + + cmd = &lp->mc_cmd; cmd->command = CmdMulticastList; *((unsigned short *) (cmd + 1)) = dev->mc_count * 6; cp = ((unsigned char *) (cmd + 1)) + 2; - for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { + for(dmi=dev->mc_list;cnt && dmi!=NULL;dmi=dmi->next,cnt--) { memcpy(cp, dmi->dmi_addr, 6); if (i596_debug > 1) printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, *(cp + 0), *(cp + 1), *(cp + 2), *(cp + 3), *(cp + 4), *(cp + 5)); @@ -1306,40 +1449,58 @@ static void set_multicast_list(struct net_device *dev) static unsigned int i596_portlist[] __initdata = {0x300, 0}; struct netdev_entry i596_drv = -{"apricot", i82596_probe, I596_TOTAL_SIZE, apricot_portlist}; +{"i82596", i82596_probe, I596_TOTAL_SIZE, i596_portlist}; #endif #ifdef MODULE static char devicename[9] = {0,}; -static struct net_device dev_apricot = +static struct net_device dev_82596 = { - devicename, /* device name inserted by /linux/drivers/net/net_init.c */ + devicename, /* device name inserted by drivers/net/net_init.c */ 0, 0, 0, 0, - 0x300, 10, + 0, 0, /* base, irq */ 0, 0, 0, NULL, i82596_probe}; +#ifdef ENABLE_APRICOT static int io = 0x300; static int irq = 10; MODULE_PARM(irq, "i"); +#endif + +MODULE_PARM(debug, "i"); +static int debug = -1; int init_module(void) { - dev_apricot.base_addr = io; - dev_apricot.irq = irq; - if (register_netdev(&dev_apricot) != 0) +#ifdef ENABLE_APRICOT + dev_82596.base_addr = io; + dev_82596.irq = irq; +#endif + if (debug >= 0) + i596_debug = debug; + if (register_netdev(&dev_82596) != 0) return -EIO; return 0; } void cleanup_module(void) { - unregister_netdev(&dev_apricot); - kfree((void *) dev_apricot.mem_start); - dev_apricot.priv = NULL; + unregister_netdev(&dev_82596); +#ifdef __mc68000__ + /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, + * XXX which may be invalid (CONFIG_060_WRITETHROUGH) + */ + kernel_set_cachemode((u32)(dev_82596.mem_start), 4096, + IOMAP_FULL_CACHING); +#endif + free_page ((u32)(dev_82596.mem_start)); + dev_82596.priv = NULL; +#ifdef ENABLE_APRICOT /* If we don't do this, we can't re-insmod it later. */ - release_region(dev_apricot.base_addr, I596_TOTAL_SIZE); + release_region(dev_82596.base_addr, I596_TOTAL_SIZE); +#endif } #endif /* MODULE */ diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index ba7fc1610fced5bf5565ccf19fa4a5d79bf189e3..8db17e5c90d5413d5f70c977f1cc8b24aa1a95b2 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c @@ -80,19 +80,42 @@ int parport_wait_event (struct parport *port, signed long timeout) * are able to eat the time up to 40ms. */ +int parport_poll_peripheral(struct parport *port, + unsigned char mask, + unsigned char result, + int usec) +{ + /* Zero return code is success, >0 is timeout. */ + int counter = usec / 5; + unsigned char status; + for (; counter > 0; counter--) { + status = parport_read_status (port); + if ((status & mask) == result) + return 0; + if (signal_pending (current)) + return -EINTR; + if (current->need_resched) + break; + udelay (5); + } + + return 1; +} + int parport_wait_peripheral(struct parport *port, unsigned char mask, unsigned char result) { - int counter; + int ret; + int usec; long deadline; unsigned char status; - counter = port->physport->spintime; /* usecs of fast polling */ + usec = port->physport->spintime; /* usecs of fast polling */ if (!port->physport->cad->timeout) /* A zero timeout is "special": busy wait for the entire 35ms. */ - counter = 35000; + usec = 35000; /* Fast polling. * @@ -100,16 +123,9 @@ int parport_wait_peripheral(struct parport *port, * How about making a note (in the device structure) of how long * it takes, so we know for next time? */ - for (counter /= 5; counter > 0; counter--) { - status = parport_read_status (port); - if ((status & mask) == result) - return 0; - if (signal_pending (current)) - return -EINTR; - if (current->need_resched) - break; - udelay(5); - } + ret = parport_poll_peripheral (port, mask, result, usec); + if (ret != 1) + return ret; if (!port->physport->cad->timeout) /* We may be in an interrupt handler, so we can't poll @@ -137,7 +153,7 @@ int parport_wait_peripheral(struct parport *port, /* parport_wait_event didn't time out, but the * peripheral wasn't actually ready either. * Wait for another 10ms. */ - current->state = TASK_INTERRUPTIBLE; + __set_current_state (TASK_INTERRUPTIBLE); schedule_timeout ((HZ+ 99) / 100); } } @@ -369,8 +385,17 @@ int parport_negotiate (struct parport *port, int mode) PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); + /* Event 52: nAck goes low */ + if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) { + /* This peripheral is _very_ slow. */ + DPRINTK (KERN_DEBUG + "%s: Event 52 didn't happen\n", + port->name); + parport_ieee1284_terminate (port); + return 1; + } + /* Event 53: Set nStrobe high */ - udelay (5); parport_frob_control (port, PARPORT_CONTROL_STROBE, 0); diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c index 4d460a58d6f95fb9c8c35142e491f5f6289da4c5..3d77776b515d53cbd2f61c06f021f98dfea9d5f6 100644 --- a/drivers/parport/ieee1284_ops.c +++ b/drivers/parport/ieee1284_ops.c @@ -95,7 +95,7 @@ size_t parport_ieee1284_write_compat (struct parport *port, our interrupt handler called. */ if (count && no_irq) { parport_release (dev); - current->state = TASK_INTERRUPTIBLE; + set_current_state (TASK_INTERRUPTIBLE); schedule_timeout (wait); parport_claim_or_block (dev); } @@ -525,7 +525,7 @@ size_t parport_ieee1284_ecp_read_data (struct parport *port, /* Yield the port for a while. */ if (count && dev->port->irq != PARPORT_IRQ_NONE) { parport_release (dev); - current->state = TASK_INTERRUPTIBLE; + set_current_state (TASK_INTERRUPTIBLE); schedule_timeout ((HZ + 24) / 25); parport_claim_or_block (dev); } diff --git a/drivers/parport/init.c b/drivers/parport/init.c index 432fede95faf8c1297de45571309494e51b882ce..b2f4d4b06c16dc7d553999c4011c697fd77af380 100644 --- a/drivers/parport/init.c +++ b/drivers/parport/init.c @@ -181,6 +181,7 @@ EXPORT_SYMBOL(parport_write); EXPORT_SYMBOL(parport_read); EXPORT_SYMBOL(parport_ieee1284_wakeup); EXPORT_SYMBOL(parport_wait_peripheral); +EXPORT_SYMBOL(parport_poll_peripheral); EXPORT_SYMBOL(parport_wait_event); EXPORT_SYMBOL(parport_set_timeout); EXPORT_SYMBOL(parport_ieee1284_interrupt); diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 587a6a2b0bc74aa5e8867af5e040a9db4e0eddc1..72d8dc15203e819d247239c2e78921429f04b9b8 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -122,7 +122,7 @@ static int change_mode(struct parport *p, int m) if (time_after_eq (jiffies, expire)) /* The FIFO is stuck. */ return -EBUSY; - current->state = TASK_INTERRUPTIBLE; + __set_current_state (TASK_INTERRUPTIBLE); schedule_timeout ((HZ + 99) / 100); if (signal_pending (current)) break; diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 0503f4af1caeb6875809a41b5c6af6b3959d6477..2913461938ad919650a28aaf75a46df48c877cfa 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -32,3 +32,11 @@ L_OBJS += syscall.o setup.o endif include $(TOPDIR)/Rules.make + +names.o: names.c devlist.h + +devlist.h: pci.ids gen-devlist + ./gen-devlist <pci.ids >devlist.h + +gen-devlist: gen-devlist.c + $(HOSTCC) $(HOSTCFLAGS) -o gen-devlist gen-devlist.c diff --git a/drivers/pci/devlist.h b/drivers/pci/devlist.h deleted file mode 100644 index f0482b7d3c3171a676912a4017f880ce76f633d1..0000000000000000000000000000000000000000 --- a/drivers/pci/devlist.h +++ /dev/null @@ -1,1016 +0,0 @@ -VENDOR( COMPAQ, "Compaq" ) - DEVICE( COMPAQ, COMPAQ_TOKENRING, "Token Ring 4/16") - DEVICE( COMPAQ, COMPAQ_1280, "QVision 1280/p") - DEVICE( COMPAQ, COMPAQ_SMART2P, "Smart-2/P RAID Controller") - DEVICE( COMPAQ, COMPAQ_NETEL100,"Netelligent 10/100") - DEVICE( COMPAQ, COMPAQ_NETEL10, "Netelligent 10") - DEVICE( COMPAQ, COMPAQ_NETFLEX3I,"NetFlex 3") - DEVICE( COMPAQ, COMPAQ_NETEL100D,"Netelligent 10/100 Dual") - DEVICE( COMPAQ, COMPAQ_NETEL100PI,"Netelligent 10/100 ProLiant") - DEVICE( COMPAQ, COMPAQ_NETEL100I,"Netelligent 10/100 Integrated") - DEVICE( COMPAQ, COMPAQ_THUNDER, "ThunderLAN") - DEVICE( COMPAQ, COMPAQ_NETFLEX3B,"NetFlex 3 BNC") -ENDVENDOR() - -VENDOR( NCR, "NCR" ) - DEVICE( NCR, NCR_53C810, "53c810") - DEVICE( NCR, NCR_53C820, "53c820") - DEVICE( NCR, NCR_53C825, "53c825") - DEVICE( NCR, NCR_53C815, "53c815") - DEVICE( NCR, NCR_53C860, "53c860") - DEVICE( NCR, NCR_53C896, "53c896") - DEVICE( NCR, NCR_53C895, "53c895") - DEVICE( NCR, NCR_53C885, "53c885") - DEVICE( NCR, NCR_53C875, "53c875") - DEVICE( NCR, NCR_53C875J, "53c875J") -ENDVENDOR() - -VENDOR( ATI, "ATI" ) - DEVICE( ATI, ATI_68800, "68800AX") - DEVICE( ATI, ATI_215CT222, "215CT222") - DEVICE( ATI, ATI_210888CX, "210888CX") - DEVICE( ATI, ATI_215GB, "Mach64 GB") - DEVICE( ATI, ATI_215GD, "Mach64 GD (Rage Pro)") - DEVICE( ATI, ATI_215GI, "Mach64 GI (Rage Pro)") - DEVICE( ATI, ATI_215GP, "Mach64 GP (Rage Pro)") - DEVICE( ATI, ATI_215GQ, "Mach64 GQ (Rage Pro)") - DEVICE( ATI, ATI_215GT, "Mach64 GT (Rage II)") - DEVICE( ATI, ATI_215GTB, "Mach64 GTB (Rage II)") - DEVICE( ATI, ATI_210888GX, "210888GX") - DEVICE( ATI, ATI_215LG, "Mach64 LG (Rage Pro)") - DEVICE( ATI, ATI_264LT, "Mach64 LT") - DEVICE( ATI, ATI_264VT, "Mach64 VT") -ENDVENDOR() - -VENDOR( VLSI, "VLSI" ) - DEVICE( VLSI, VLSI_82C592, "82C592-FC1") - DEVICE( VLSI, VLSI_82C593, "82C593-FC1") - DEVICE( VLSI, VLSI_82C594, "82C594-AFC2") - DEVICE( VLSI, VLSI_82C597, "82C597-AFC2") - DEVICE( VLSI, VLSI_82C541, "82C541 Lynx") - DEVICE( VLSI, VLSI_82C543, "82C543 Lynx ISA") - DEVICE( VLSI, VLSI_82C532, "82C532") - DEVICE( VLSI, VLSI_82C534, "82C534") - DEVICE( VLSI, VLSI_82C535, "82C535") - DEVICE( VLSI, VLSI_82C147, "82C147") - DEVICE( VLSI, VLSI_VAS96011, "VAS96011 (Golden Gate II)") -ENDVENDOR() - -VENDOR( ADL, "Avance Logic" ) - DEVICE( ADL, ADL_2301, "2301") -ENDVENDOR() - -VENDOR( NS, "NS" ) - DEVICE( NS, NS_87415, "87415") - DEVICE( NS, NS_87410, "87410") -ENDVENDOR() - -VENDOR( TSENG, "Tseng'Lab" ) - DEVICE( TSENG, TSENG_W32P_2, "ET4000W32P") - DEVICE( TSENG, TSENG_W32P_b, "ET4000W32P rev B") - DEVICE( TSENG, TSENG_W32P_c, "ET4000W32P rev C") - DEVICE( TSENG, TSENG_W32P_d, "ET4000W32P rev D") - DEVICE( TSENG, TSENG_ET6000, "ET6000") -ENDVENDOR() - -VENDOR( WEITEK, "Weitek" ) - DEVICE( WEITEK, WEITEK_P9000, "P9000") - DEVICE( WEITEK, WEITEK_P9100, "P9100") -ENDVENDOR() - -VENDOR( DEC, "DEC" ) - DEVICE( DEC, DEC_BRD, "DC21050") - DEVICE( DEC, DEC_TULIP, "DC21040") - DEVICE( DEC, DEC_TGA, "TGA") - DEVICE( DEC, DEC_TULIP_FAST, "DC21140") - DEVICE( DEC, DEC_TGA2, "TGA2") - DEVICE( DEC, DEC_FDDI, "DEFPA") - DEVICE( DEC, DEC_TULIP_PLUS, "DC21041") - DEVICE( DEC, DEC_21142, "DC21142") - DEVICE( DEC, DEC_21052, "DC21052") - DEVICE( DEC, DEC_21150, "DC21150") - DEVICE( DEC, DEC_21152, "DC21152") - DEVICE( DEC, DEC_21153, "DC21153") - DEVICE( DEC, DEC_21154, "DC21154") -ENDVENDOR() - -VENDOR( CIRRUS, "Cirrus Logic" ) - DEVICE( CIRRUS, CIRRUS_7548, "GD 7548") - DEVICE( CIRRUS, CIRRUS_5430, "GD 5430") - DEVICE( CIRRUS, CIRRUS_5434_4, "GD 5434") - DEVICE( CIRRUS, CIRRUS_5434_8, "GD 5434") - DEVICE( CIRRUS, CIRRUS_5436, "GD 5436") - DEVICE( CIRRUS, CIRRUS_5446, "GD 5446") - DEVICE( CIRRUS, CIRRUS_5480, "GD 5480") - DEVICE( CIRRUS, CIRRUS_5462, "Laguna") - DEVICE( CIRRUS, CIRRUS_5464, "Laguna 3D") - DEVICE( CIRRUS, CIRRUS_5465, "Laguna 3DA") - DEVICE( CIRRUS, CIRRUS_6729, "CL 6729") - DEVICE( CIRRUS, CIRRUS_6832, "PD 6832") - DEVICE( CIRRUS, CIRRUS_7542, "CL 7542") - DEVICE( CIRRUS, CIRRUS_7543, "CL 7543") - DEVICE( CIRRUS, CIRRUS_7541, "CL 7541") -ENDVENDOR() - -VENDOR( IBM, "IBM" ) - DEVICE( IBM, IBM_FIRE_CORAL, "Fire Coral") - DEVICE( IBM, IBM_TR, "Token Ring") - DEVICE( IBM, IBM_82G2675, "82G2675") - DEVICE( IBM, IBM_MCA, "MicroChannel") - DEVICE( IBM, IBM_82351, "82351") - DEVICE( IBM, IBM_PYTHON, "Python") - DEVICE( IBM, IBM_SERVERAID, "ServeRAID") - DEVICE( IBM, IBM_TR_WAKE, "Wake On LAN Token Ring") - DEVICE( IBM, IBM_MPIC, "MPIC-2 Interrupt Controller") - DEVICE( IBM, IBM_3780IDSP, "MWave DSP") - DEVICE( IBM, IBM_MPIC_2, "MPIC-2 ASIC Interrupt Controller") -ENDVENDOR() - -VENDOR( WD, "Western Digital" ) - DEVICE( WD, WD_7197, "WD 7197") -ENDVENDOR() - -VENDOR( AMD, "AMD" ) - DEVICE( AMD, AMD_LANCE, "79C970") - DEVICE( AMD, AMD_SCSI, "53C974") -ENDVENDOR() - -VENDOR( TRIDENT, "Trident" ) - DEVICE( TRIDENT, TRIDENT_9320, "Cyber9320") - DEVICE( TRIDENT, TRIDENT_9388, "Cyber9388") - DEVICE( TRIDENT, TRIDENT_9397, "Cyber9397") - DEVICE( TRIDENT, TRIDENT_939A, "Cyber939a") - DEVICE( TRIDENT, TRIDENT_9520, "Cyber9520") - DEVICE( TRIDENT, TRIDENT_9525, "Cyber9525") - DEVICE( TRIDENT, TRIDENT_9420, "TGUI 9420") - DEVICE( TRIDENT, TRIDENT_9440, "TGUI 9440") - DEVICE( TRIDENT, TRIDENT_9660, "TGUI 9660 / Cyber9385") - DEVICE( TRIDENT, TRIDENT_9750, "3DImage 975") - DEVICE( TRIDENT, TRIDENT_9850, "3DImage 985") - DEVICE( TRIDENT, TRIDENT_9880, "Blade 3D") - DEVICE( TRIDENT, TRIDENT_8400, "CyberBlade/i7") - DEVICE( TRIDENT, TRIDENT_8420, "CyberBlade/i7d") - DEVICE( TRIDENT, TRIDENT_8500, "CyberBlade/i1") -ENDVENDOR() - -VENDOR( AI, "Acer Incorporated" ) - DEVICE( AI, AI_M1435, "M1435") -ENDVENDOR() - -VENDOR( MATROX, "Matrox" ) - DEVICE( MATROX, MATROX_MGA_2, "Atlas PX2085") - DEVICE( MATROX, MATROX_MIL, "Millennium") - DEVICE( MATROX, MATROX_MYS, "Mystique") - DEVICE( MATROX, MATROX_MIL_2, "Millennium II") - DEVICE( MATROX, MATROX_MIL_2_AGP,"Millennium II AGP") - DEVICE( MATROX, MATROX_MGA_IMP, "MGA Impression") - DEVICE( MATROX, MATROX_G100_MM, "G100 multi monitor") - DEVICE( MATROX, MATROX_G100_AGP,"G100 AGP") - DEVICE( MATROX, MATROX_G200_PCI,"G200 PCI") - DEVICE( MATROX, MATROX_G200_AGP,"G200 AGP") - DEVICE( MATROX, MATROX_G400, "G400") - DEVICE( MATROX, MATROX_VIA, "Corona / Meteor-II") -ENDVENDOR() - -VENDOR( CT, "Chips & Technologies" ) - DEVICE( CT, CT_65545, "65545") - DEVICE( CT, CT_65548, "65548") - DEVICE( CT, CT_65550, "65550") - DEVICE( CT, CT_65554, "65554") - DEVICE( CT, CT_65555, "65555") -ENDVENDOR() - -VENDOR( MIRO, "Miro" ) - DEVICE( MIRO, MIRO_36050, "ZR36050") -ENDVENDOR() - -VENDOR( NEC, "NEC" ) - DEVICE( NEC, NEC_PCX2, "PowerVR PCX2") -ENDVENDOR() - -VENDOR( FD, "Future Domain" ) - DEVICE( FD, FD_36C70, "TMC-18C30") -ENDVENDOR() - -VENDOR( SI, "Silicon Integrated Systems" ) - DEVICE( SI, SI_5591_AGP, "5591/5592 AGP") - DEVICE( SI, SI_6202, "6202") - DEVICE( SI, SI_503, "85C503") - DEVICE( SI, SI_ACPI, "ACPI") - DEVICE( SI, SI_5597_VGA, "5597/5598 VGA") - DEVICE( SI, SI_6205, "6205") - DEVICE( SI, SI_496, "85C496") - DEVICE( SI, SI_501, "85C501") - DEVICE( SI, SI_530, "530 Host") - DEVICE( SI, SI_601, "85C601") - DEVICE( SI, SI_620, "620 Host") - DEVICE( SI, SI_5107, "5107") - DEVICE( SI, SI_5511, "85C5511") - DEVICE( SI, SI_5513, "85C5513 IDE") - DEVICE( SI, SI_5571, "5571") - DEVICE( SI, SI_5591, "5591/5592 Host") - DEVICE( SI, SI_5597, "5597/5598 Host") - DEVICE( SI, SI_5600, "5600 Host") - DEVICE( SI, SI_6306, "3D-AGP 6306 VGA") - DEVICE( SI, SI_6326, "3D-AGP 6326 VGA") - DEVICE( SI, SI_7001, "7001 USB") -ENDVENDOR() - -VENDOR( HP, "Hewlett Packard" ) - DEVICE( HP, HP_J2585A, "J2585A") - DEVICE( HP, HP_J2585B, "J2585B (Lassen)") -ENDVENDOR() - -VENDOR( PCTECH, "PCTECH" ) - DEVICE( PCTECH, PCTECH_RZ1000, "RZ1000 (buggy)") - DEVICE( PCTECH, PCTECH_RZ1001, "RZ1001 (buggy?)") - DEVICE( PCTECH, PCTECH_SAMURAI_0,"Samurai 0") - DEVICE( PCTECH, PCTECH_SAMURAI_1,"Samurai 1") - DEVICE( PCTECH, PCTECH_SAMURAI_IDE,"Samurai IDE") -ENDVENDOR() - -VENDOR( DPT, "DPT" ) - DEVICE( DPT, DPT, "SmartCache/Raid") -ENDVENDOR() - -VENDOR( OPTI, "OPTi" ) - DEVICE( OPTI, OPTI_92C178, "92C178") - DEVICE( OPTI, OPTI_82C557, "82C557 Viper-M") - DEVICE( OPTI, OPTI_82C558, "82C558 Viper-M ISA+IDE") - DEVICE( OPTI, OPTI_82C621, "82C621") - DEVICE( OPTI, OPTI_82C700, "82C700") - DEVICE( OPTI, OPTI_82C701, "82C701 FireStar Plus") - DEVICE( OPTI, OPTI_82C814, "82C814 Firebridge 1") - DEVICE( OPTI, OPTI_82C822, "82C822") - DEVICE( OPTI, OPTI_82C825, "82C825 Firebridge 2") -ENDVENDOR() - -VENDOR( SGS, "SGS Thomson" ) - DEVICE( SGS, SGS_2000, "STG 2000X") - DEVICE( SGS, SGS_1764, "STG 1764X") -ENDVENDOR() - -VENDOR( BUSLOGIC, "BusLogic" ) - DEVICE( BUSLOGIC, BUSLOGIC_MULTIMASTER_NC, "MultiMaster NC") - DEVICE( BUSLOGIC, BUSLOGIC_MULTIMASTER, "MultiMaster") - DEVICE( BUSLOGIC, BUSLOGIC_FLASHPOINT, "FlashPoint") -ENDVENDOR() - -VENDOR( TI, "Texas Instruments" ) - DEVICE( TI, TI_TVP4010, "TVP4010 Permedia") - DEVICE( TI, TI_TVP4020, "TVP4020 Permedia 2") - DEVICE( TI, TI_PCI1130, "PCI1130") - DEVICE( TI, TI_PCI1131, "PCI1131") - DEVICE( TI, TI_PCI1250, "PCI1250") -ENDVENDOR() - -VENDOR( OAK, "OAK" ) - DEVICE( OAK, OAK_OTI107, "OTI107") -ENDVENDOR() - -VENDOR( WINBOND2, "Winbond" ) - DEVICE( WINBOND2, WINBOND2_89C940,"NE2000-PCI") - DEVICE( WINBOND2, WINBOND2_89C940F, "W89C940F") -ENDVENDOR() - -VENDOR( MOTOROLA, "Motorola" ) - DEVICE( MOTOROLA, MOTOROLA_MPC105,"MPC105 Eagle") - DEVICE( MOTOROLA, MOTOROLA_MPC106,"MPC106 Grackle") - DEVICE( MOTOROLA, MOTOROLA_RAVEN, "Raven") - DEVICE( MOTOROLA, MOTOROLA_FALCON,"Falcon") - DEVICE( MOTOROLA, MOTOROLA_CPX8216,"CPX8216") -ENDVENDOR() - -VENDOR( PROMISE, "Promise Technology" ) - DEVICE( PROMISE, PROMISE_20246, "IDE UltraDMA/33") - DEVICE( PROMISE, PROMISE_20262, "IDE UltraDMA/66") - DEVICE( PROMISE, PROMISE_5300, "DC5030") -ENDVENDOR() - -VENDOR( N9, "Number Nine" ) - DEVICE( N9, N9_I128, "Imagine 128") - DEVICE( N9, N9_I128_2, "Imagine 128v2") - DEVICE( N9, N9_I128_T2R, "Revolution 3D") -ENDVENDOR() - -VENDOR( UMC, "UMC" ) - DEVICE( UMC, UMC_UM8673F, "UM8673F") - DEVICE( UMC, UMC_UM8891A, "UM8891A") - DEVICE( UMC, UMC_UM8886BF, "UM8886BF") - DEVICE( UMC, UMC_UM8886A, "UM8886A") - DEVICE( UMC, UMC_UM8881F, "UM8881F") - DEVICE( UMC, UMC_UM8886F, "UM8886F") - DEVICE( UMC, UMC_UM9017F, "UM9017F") - DEVICE( UMC, UMC_UM8886N, "UM8886N") - DEVICE( UMC, UMC_UM8891N, "UM8891N") -ENDVENDOR() - -VENDOR( X, "X Technology" ) - DEVICE( X, X_AGX016, "ITT AGX016") -ENDVENDOR() - -VENDOR( PICOP, "PicoPower" ) - DEVICE( PICOP, PICOP_PT86C52X, "PT86C52x Vesuvius") - DEVICE( PICOP, PICOP_PT80C524, "PT80C524 Nile") -ENDVENDOR() - -VENDOR( APPLE, "Apple" ) - DEVICE( APPLE, APPLE_BANDIT, "Bandit") - DEVICE( APPLE, APPLE_GC, "Grand Central") - DEVICE( APPLE, APPLE_HYDRA, "Hydra") -ENDVENDOR() - -VENDOR( NEXGEN, "Nexgen" ) - DEVICE( NEXGEN, NEXGEN_82C501, "82C501") -ENDVENDOR() - -VENDOR( QLOGIC, "Q Logic" ) - DEVICE( QLOGIC, QLOGIC_ISP1020, "ISP1020") - DEVICE( QLOGIC, QLOGIC_ISP1022, "ISP1022") -ENDVENDOR() - -VENDOR( CYRIX, "Cyrix" ) - DEVICE( CYRIX, CYRIX_5510, "5510") - DEVICE( CYRIX, CYRIX_PCI_MASTER,"PCI Master") - DEVICE( CYRIX, CYRIX_5520, "5520") - DEVICE( CYRIX, CYRIX_5530_LEGACY,"5530 Kahlua Legacy") - DEVICE( CYRIX, CYRIX_5530_SMI, "5530 Kahlua SMI") - DEVICE( CYRIX, CYRIX_5530_IDE, "5530 Kahlua IDE") - DEVICE( CYRIX, CYRIX_5530_AUDIO,"5530 Kahlua Audio") - DEVICE( CYRIX, CYRIX_5530_VIDEO,"5530 Kahlua Video") -ENDVENDOR() - -VENDOR( LEADTEK, "Leadtek Research" ) - DEVICE( LEADTEK, LEADTEK_805, "S3 805") -ENDVENDOR() - -VENDOR( CONTAQ, "Contaq" ) - DEVICE( CONTAQ, CONTAQ_82C599, "82C599") - DEVICE( CONTAQ, CONTAQ_82C693, "82C693") -ENDVENDOR() - -VENDOR( FOREX, "Forex" ) -ENDVENDOR() - -VENDOR( OLICOM, "Olicom" ) - DEVICE( OLICOM, OLICOM_OC3136, "OC-3136/3137") - DEVICE( OLICOM, OLICOM_OC2315, "OC-2315") - DEVICE( OLICOM, OLICOM_OC2325, "OC-2325") - DEVICE( OLICOM, OLICOM_OC2183, "OC-2183/2185") - DEVICE( OLICOM, OLICOM_OC2326, "OC-2326") - DEVICE( OLICOM, OLICOM_OC6151, "OC-6151/6152") -ENDVENDOR() - -VENDOR( SUN, "Sun Microsystems" ) - DEVICE( SUN, SUN_EBUS, "PCI-EBus Bridge") - DEVICE( SUN, SUN_HAPPYMEAL, "Happy Meal Ethernet") - DEVICE( SUN, SUN_SIMBA, "Advanced PCI Bridge") - DEVICE( SUN, SUN_PBM, "PCI Bus Module") - DEVICE( SUN, SUN_SABRE, "Ultra IIi PCI") -ENDVENDOR() - -VENDOR( CMD, "CMD" ) - DEVICE( CMD, CMD_640, "640 (buggy)") - DEVICE( CMD, CMD_643, "643") - DEVICE( CMD, CMD_646, "646") - DEVICE( CMD, CMD_670, "670") -ENDVENDOR() - -VENDOR( VISION, "Vision" ) - DEVICE( VISION, VISION_QD8500, "QD-8500") - DEVICE( VISION, VISION_QD8580, "QD-8580") -ENDVENDOR() - -VENDOR( BROOKTREE, "Brooktree" ) - DEVICE( BROOKTREE, BROOKTREE_848, "Bt848") - DEVICE( BROOKTREE, BROOKTREE_849A, "Bt849") - DEVICE( BROOKTREE, BROOKTREE_878_1,"Bt878 2nd Contr. (?)") - DEVICE( BROOKTREE, BROOKTREE_878, "Bt878") - DEVICE( BROOKTREE, BROOKTREE_8474, "Bt8474") -ENDVENDOR() - -VENDOR( SIERRA, "Sierra" ) - DEVICE( SIERRA, SIERRA_STB, "STB Horizon 64") -ENDVENDOR() - -VENDOR( SGI, "Silicon Graphics Inc" ) - DEVICE( SGI, SGI_IOC3, "IOC3") -ENDVENDOR() - -VENDOR( ACC, "ACC MICROELECTRONICS" ) - DEVICE( ACC, ACC_2056, "2056") -ENDVENDOR() - -VENDOR( WINBOND, "Winbond" ) - DEVICE( WINBOND, WINBOND_83769, "W83769F") - DEVICE( WINBOND, WINBOND_82C105, "SL82C105") - DEVICE( WINBOND, WINBOND_83C553, "W83C553") -ENDVENDOR() - -VENDOR( DATABOOK, "Databook" ) - DEVICE( DATABOOK, DATABOOK_87144, "DB87144") -ENDVENDOR() - -VENDOR( PLX, "PLX" ) - DEVICE( PLX, PLX_9050, "PCI9050 I2O") - DEVICE( PLX, PLX_9080, "PCI9080 I2O") -ENDVENDOR() - -VENDOR( MADGE, "Madge Networks" ) - DEVICE( MADGE, MADGE_MK2, "Smart 16/4 BM Mk2 Ringnode") - DEVICE( MADGE, MADGE_C155S, "Collage 155 Server") -ENDVENDOR() - -VENDOR( 3COM, "3Com" ) - DEVICE( 3COM, 3COM_3C339, "3C339 TokenRing") - DEVICE( 3COM, 3COM_3C590, "3C590 10bT") - DEVICE( 3COM, 3COM_3C595TX, "3C595 100bTX") - DEVICE( 3COM, 3COM_3C595T4, "3C595 100bT4") - DEVICE( 3COM, 3COM_3C595MII, "3C595 100b-MII") - DEVICE( 3COM, 3COM_3C900TPO, "3C900 10bTPO") - DEVICE( 3COM, 3COM_3C900COMBO,"3C900 10b Combo") - DEVICE( 3COM, 3COM_3C905TX, "3C905 100bTX") - DEVICE( 3COM, 3COM_3C905T4, "3C905 100bT4") - DEVICE( 3COM, 3COM_3C905B_TX, "3C905B 100bTX") -ENDVENDOR() - -VENDOR( SMC, "SMC" ) - DEVICE( SMC, SMC_EPIC100, "9432 TX") -ENDVENDOR() - -VENDOR( AL, "Acer Labs" ) - DEVICE( AL, AL_M1445, "M1445") - DEVICE( AL, AL_M1449, "M1449") - DEVICE( AL, AL_M1451, "M1451") - DEVICE( AL, AL_M1461, "M1461") - DEVICE( AL, AL_M1489, "M1489") - DEVICE( AL, AL_M1511, "M1511") - DEVICE( AL, AL_M1513, "M1513") - DEVICE( AL, AL_M1521, "M1521") - DEVICE( AL, AL_M1523, "M1523") - DEVICE( AL, AL_M1531, "M1531 Aladdin IV") - DEVICE( AL, AL_M1533, "M1533 Aladdin IV") - DEVICE( AL, AL_M1541, "M1541 Aladdin V") - DEVICE( AL, AL_M1543, "M1543 Aladdin V") - DEVICE( AL, AL_M3307, "M3307 MPEG-1 decoder") - DEVICE( AL, AL_M4803, "M4803") - DEVICE( AL, AL_M5219, "M5219") - DEVICE( AL, AL_M5229, "M5229 TXpro") - DEVICE( AL, AL_M5237, "M5237 USB") - DEVICE( AL, AL_M5243, "M5243 AGP") - DEVICE( AL, AL_M7101, "M7101 PMU") -ENDVENDOR() - -VENDOR( MITSUBISHI, "Mitsubishi" ) -ENDVENDOR() - -VENDOR( SURECOM, "Surecom" ) - DEVICE( SURECOM, SURECOM_NE34, "NE-34PCI LAN") -ENDVENDOR() - -VENDOR( NEOMAGIC, "Neomagic" ) - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2070, "Magicgraph NM2070") - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V") - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV") - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160") - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128ZVPLUS, "MagicGraph 128ZV+") -ENDVENDOR() - -VENDOR( ASP, "Advanced System Products" ) - DEVICE( ASP, ASP_ABP940, "ABP940") - DEVICE( ASP, ASP_ABP940U, "ABP940U") - DEVICE( ASP, ASP_ABP940UW, "ABP940UW") -ENDVENDOR() - -VENDOR( MACRONIX, "Macronix" ) - DEVICE( MACRONIX, MACRONIX_MX98713,"MX98713") - DEVICE( MACRONIX, MACRONIX_MX987x5,"MX98715 / MX98725") -ENDVENDOR() - -VENDOR( TCONRAD, "Thomas-Conrad" ) - DEVICE( TCONRAD, TCONRAD_TOKENRING, "Token Ring 4/16") -ENDVENDOR() - -VENDOR( CERN, "CERN" ) - DEVICE( CERN, CERN_SPSB_PMC, "STAR/RD24 SCI-PCI (PMC)") - DEVICE( CERN, CERN_SPSB_PCI, "STAR/RD24 SCI-PCI (PMC)") - DEVICE( CERN, CERN_HIPPI_DST, "HIPPI destination") - DEVICE( CERN, CERN_HIPPI_SRC, "HIPPI source") -ENDVENDOR() - -VENDOR( NVIDIA, "NVidia" ) - DEVICE( NVIDIA, NVIDIA_TNT, "Riva TNT") - DEVICE( NVIDIA, NVIDIA_TNT2, "Riva TNT2") - DEVICE( NVIDIA, NVIDIA_UTNT2, "Riva TNT2 (Ultra)") - DEVICE( NVIDIA, NVIDIA_VTNT2, "Riva TNT2 (Vanta)") - DEVICE( NVIDIA, NVIDIA_UVTNT2, "Riva TNT2 (Ultra Vanta)") - DEVICE( NVIDIA, NVIDIA_ITNT2, "Riva TNT2 (Integrated)") -ENDVENDOR() - -VENDOR( IMS, "IMS" ) - DEVICE( IMS, IMS_8849, "8849") -ENDVENDOR() - -VENDOR( TEKRAM2, "Tekram" ) - DEVICE( TEKRAM2, TEKRAM2_690c, "DC690c") -ENDVENDOR() - -VENDOR( TUNDRA, "Tundra" ) - DEVICE( TUNDRA, TUNDRA_CA91C042,"CA91C042 Universe") -ENDVENDOR() - -VENDOR( AMCC, "AMCC" ) - DEVICE( AMCC, AMCC_MYRINET, "Myrinet PCI (M2-PCI-32)") - DEVICE( AMCC, AMCC_PARASTATION,"ParaStation Interface") - DEVICE( AMCC, AMCC_S5933, "S5933 PCI44") - DEVICE( AMCC, AMCC_S5933_HEPC3,"S5933 Traquair HEPC3") -ENDVENDOR() - -VENDOR( INTERG, "Intergraphics" ) - DEVICE( INTERG, INTERG_1680, "IGA-1680") - DEVICE( INTERG, INTERG_1682, "IGA-1682") - DEVICE( INTERG, INTERG_2000, "CyberPro 2000") -ENDVENDOR() - -VENDOR( REALTEK, "Realtek" ) - DEVICE( REALTEK, REALTEK_8029, "8029") - DEVICE( REALTEK, REALTEK_8129, "8129") - DEVICE( REALTEK, REALTEK_8139, "8139") -ENDVENDOR() - -VENDOR( TRUEVISION, "Truevision" ) - DEVICE( TRUEVISION, TRUEVISION_T1000,"TARGA 1000") -ENDVENDOR() - -VENDOR( INIT, "Initio Corp" ) - DEVICE( INIT, INIT_320P, "320 P") - DEVICE( INIT, INIT_360P, "360 P") -ENDVENDOR() - -VENDOR( TTI, "Triones Technologies, Inc." ) - DEVICE( TTI, TTI_HPT343, "HPT343 IDE UltraDMA/33") - DEVICE( TTI, TTI_HPT366, "HPT366 IDE UltraDMA/66") -ENDVENDOR() - -VENDOR( VIA, "VIA Technologies" ) - DEVICE( VIA, VIA_8501_0, "VT 8501") - DEVICE( VIA, VIA_82C505, "VT 82C505") - DEVICE( VIA, VIA_82C561, "VT 82C561") - DEVICE( VIA, VIA_82C586_1, "VT 82C586 Apollo IDE") - DEVICE( VIA, VIA_82C576, "VT 82C576 3V") - DEVICE( VIA, VIA_82C585, "VT 82C585 Apollo VP1/VPX") - DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo ISA") - DEVICE( VIA, VIA_82C595, "VT 82C595 Apollo VP2") - DEVICE( VIA, VIA_82C596, "VT 82C596 Apollo Mobile") - DEVICE( VIA, VIA_82C597_0, "VT 82C597 Apollo VP3") - DEVICE( VIA, VIA_82C598_0, "VT 82C598 Apollo MVP3") - DEVICE( VIA, VIA_82C680, "VT 82C680 Apollo P6") - DEVICE( VIA, VIA_82C686, "VT 82C686 Apollo Super") - DEVICE( VIA, VIA_82C691, "VT 82C691 Apollo Pro") - DEVICE( VIA, VIA_82C693, "VT 82C693 Apollo Pro Plus") - DEVICE( VIA, VIA_82C926, "VT 82C926 Amazon") - DEVICE( VIA, VIA_82C416, "VT 82C416MV") - DEVICE( VIA, VIA_82C595_97, "VT 82C595 Apollo VP2/97") - DEVICE( VIA, VIA_82C586_2, "VT 82C586 Apollo USB") - DEVICE( VIA, VIA_82C586_3, "VT 82C586B Apollo ACPI") - DEVICE( VIA, VIA_82C686_4, "VT 82C686 Apollo Super ACPI") - DEVICE( VIA, VIA_82C686_5, "VT 82C686 Apollo Super AC97/Audio") - DEVICE( VIA, VIA_82C686_6, "VT 82C686 Apollo Super AC97/Modem") - DEVICE( VIA, VIA_86C100A, "VT 86C100A") - DEVICE( VIA, VIA_8501_1, "VT 8501 PCI Bridge") - DEVICE( VIA, VIA_82C597_1, "VT 82C597 Apollo VP3 AGP") - DEVICE( VIA, VIA_82C598_1, "VT 82C598 Apollo MVP3 AGP") -ENDVENDOR() - -VENDOR( SMC2, "SMC" ) - DEVICE( SMC2, SMC2_1211TX, "1211 TX") -ENDVENDOR() - -VENDOR( VORTEX, "VORTEX" ) - DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0") - DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b") - DEVICE( VORTEX, VORTEX_GDT6x10, "GDT 6110/6510") - DEVICE( VORTEX, VORTEX_GDT6x20, "GDT 6120/6520") - DEVICE( VORTEX, VORTEX_GDT6530, "GDT 6530") - DEVICE( VORTEX, VORTEX_GDT6550, "GDT 6550") - DEVICE( VORTEX, VORTEX_GDT6x17, "GDT 6117/6517") - DEVICE( VORTEX, VORTEX_GDT6x27, "GDT 6127/6527") - DEVICE( VORTEX, VORTEX_GDT6537, "GDT 6537") - DEVICE( VORTEX, VORTEX_GDT6557, "GDT 6557") - DEVICE( VORTEX, VORTEX_GDT6x15, "GDT 6115/6515") - DEVICE( VORTEX, VORTEX_GDT6x25, "GDT 6125/6525") - DEVICE( VORTEX, VORTEX_GDT6535, "GDT 6535") - DEVICE( VORTEX, VORTEX_GDT6555, "GDT 6555") - DEVICE( VORTEX, VORTEX_GDT6x17RP,"GDT 6117RP/6517RP") - DEVICE( VORTEX, VORTEX_GDT6x27RP,"GDT 6127RP/6527RP") - DEVICE( VORTEX, VORTEX_GDT6537RP,"GDT 6537RP") - DEVICE( VORTEX, VORTEX_GDT6557RP,"GDT 6557RP") - DEVICE( VORTEX, VORTEX_GDT6x11RP,"GDT 6111RP/6511RP") - DEVICE( VORTEX, VORTEX_GDT6x21RP,"GDT 6121RP/6521RP") - DEVICE( VORTEX, VORTEX_GDT6x17RP1,"GDT 6117RP1/6517RP1") - DEVICE( VORTEX, VORTEX_GDT6x27RP1,"GDT 6127RP1/6527RP1") - DEVICE( VORTEX, VORTEX_GDT6537RP1,"GDT 6537RP1") - DEVICE( VORTEX, VORTEX_GDT6557RP1,"GDT 6557RP1") - DEVICE( VORTEX, VORTEX_GDT6x11RP1,"GDT 6111RP1/6511RP1") - DEVICE( VORTEX, VORTEX_GDT6x21RP1,"GDT 6121RP1/6521RP1") - DEVICE( VORTEX, VORTEX_GDT6x17RP2,"GDT 6117RP2/6517RP2") - DEVICE( VORTEX, VORTEX_GDT6x27RP2,"GDT 6127RP2/6527RP2") - DEVICE( VORTEX, VORTEX_GDT6537RP2,"GDT 6537RP2") - DEVICE( VORTEX, VORTEX_GDT6557RP2,"GDT 6557RP2") - DEVICE( VORTEX, VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2") - DEVICE( VORTEX, VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2") -ENDVENDOR() - -VENDOR( EF, "Efficient Networks" ) - DEVICE( EF, EF_ATM_FPGA, "155P-MF1 (FPGA)") - DEVICE( EF, EF_ATM_ASIC, "155P-MF1 (ASIC)") -ENDVENDOR() - -VENDOR( FORE, "Fore Systems" ) - DEVICE( FORE, FORE_PCA200PC, "PCA-200PC") - DEVICE( FORE, FORE_PCA200E, "PCA-200E") -ENDVENDOR() - -VENDOR( IMAGINGTECH, "Imaging Technology" ) - DEVICE( IMAGINGTECH, IMAGINGTECH_ICPCI, "MVC IC-PCI") -ENDVENDOR() - -VENDOR( PHILIPS, "Philips" ) - DEVICE( PHILIPS, PHILIPS_SAA7145,"SAA7145") - DEVICE( PHILIPS, PHILIPS_SAA7146,"SAA7146") -ENDVENDOR() - -VENDOR( CYCLONE, "Cyclone" ) - DEVICE( CYCLONE, CYCLONE_SDK, "SDK") -ENDVENDOR() - -VENDOR( ALLIANCE, "Alliance" ) - DEVICE( ALLIANCE, ALLIANCE_PROMOTIO, "Promotion-6410") - DEVICE( ALLIANCE, ALLIANCE_PROVIDEO, "Provideo") - DEVICE( ALLIANCE, ALLIANCE_AT24, "AT24") - DEVICE( ALLIANCE, ALLIANCE_AT3D, "AT3D") -ENDVENDOR() - -VENDOR( VMIC, "VMIC" ) - DEVICE( VMIC, VMIC_VME, "VMIVME-7587") -ENDVENDOR() - -VENDOR( DIGI, "Digi Intl." ) - DEVICE( DIGI, DIGI_EPC, "AccelPort EPC") - DEVICE( DIGI, DIGI_RIGHTSWITCH, "RightSwitch SE-6") - DEVICE( DIGI, DIGI_XEM, "AccelPort Xem") - DEVICE( DIGI, DIGI_XR, "AccelPort Xr") - DEVICE( DIGI, DIGI_CX, "AccelPort C/X") - DEVICE( DIGI, DIGI_XRJ, "AccelPort Xr/J") - DEVICE( DIGI, DIGI_EPCJ, "AccelPort EPC/J") - DEVICE( DIGI, DIGI_XR_920, "AccelPort Xr 920") -ENDVENDOR() - -VENDOR( MUTECH, "Mutech" ) - DEVICE( MUTECH, MUTECH_MV1000, "MV-1000") -ENDVENDOR() - -VENDOR( RENDITION, "Rendition" ) - DEVICE( RENDITION, RENDITION_VERITE,"Verite 1000") - DEVICE( RENDITION, RENDITION_VERITE2100,"Verite 2100") -ENDVENDOR() - -VENDOR( TOSHIBA, "Toshiba" ) - DEVICE( TOSHIBA, TOSHIBA_601, "Laptop") - DEVICE( TOSHIBA, TOSHIBA_TOPIC95,"ToPIC95") - DEVICE( TOSHIBA, TOSHIBA_TOPIC97,"ToPIC97") -ENDVENDOR() - -VENDOR( RICOH, "Ricoh" ) - DEVICE( RICOH, RICOH_RL5C466, "RL5C466") -ENDVENDOR() - -VENDOR( ARTOP, "Artop Electronics" ) - DEVICE( ARTOP, ARTOP_ATP8400, "ATP8400") - DEVICE( ARTOP, ARTOP_ATP850UF, "ATP850UF") -ENDVENDOR() - -VENDOR( ZEITNET, "ZeitNet" ) - DEVICE( ZEITNET, ZEITNET_1221, "1221") - DEVICE( ZEITNET, ZEITNET_1225, "1225") -ENDVENDOR() - -VENDOR( OMEGA, "Omega Micro" ) - DEVICE( OMEGA, OMEGA_82C092G, "82C092G") -ENDVENDOR() - -VENDOR( LITEON, "LiteOn" ) - DEVICE( LITEON, LITEON_LNE100TX,"LNE100TX") -ENDVENDOR() - -VENDOR( NP, "Network Peripherals" ) - DEVICE( NP, NP_PCI_FDDI, "NP-PCI") -ENDVENDOR() - -VENDOR( ATT, "Lucent Microelectronics" ) - DEVICE( ATT, ATT_L56XMF, "L56xMF") -ENDVENDOR() - -VENDOR( SPECIALIX, "Specialix" ) - DEVICE( SPECIALIX, SPECIALIX_IO8, "IO8+/PCI") - DEVICE( SPECIALIX, SPECIALIX_XIO, "XIO/SIO host") - DEVICE( SPECIALIX, SPECIALIX_RIO, "RIO host") -ENDVENDOR() - -VENDOR( AURAVISION, "Auravision" ) - DEVICE( AURAVISION, AURAVISION_VXP524,"VXP524") -ENDVENDOR() - -VENDOR( IKON, "Ikon" ) - DEVICE( IKON, IKON_10115, "10115 Greensheet") - DEVICE( IKON, IKON_10117, "10117 Greensheet") -ENDVENDOR() - -VENDOR( ZORAN, "Zoran" ) - DEVICE( ZORAN, ZORAN_36057, "ZR36057") - DEVICE( ZORAN, ZORAN_36120, "ZR36120") -ENDVENDOR() - -VENDOR( KINETIC, "Kinetic" ) - DEVICE( KINETIC, KINETIC_2915, "2915 CAMAC") -ENDVENDOR() - -VENDOR( COMPEX, "Compex" ) - DEVICE( COMPEX, COMPEX_ENET100VG4, "Readylink ENET100-VG4") - DEVICE( COMPEX, COMPEX_RL2000, "ReadyLink 2000") -ENDVENDOR() - -VENDOR( RP, "Comtrol" ) - DEVICE( RP, RP32INTF, "RocketPort 32 Intf") - DEVICE( RP, RP8INTF, "RocketPort 8 Intf") - DEVICE( RP, RP16INTF, "RocketPort 16 Intf") - DEVICE( RP, RP4QUAD, "Rocketport 4 Quad") - DEVICE( RP, RP8OCTA, "RocketPort 8 Oct") - DEVICE( RP, RP8J, "RocketPort 8 J") - DEVICE( RP, RPP4, "RocketPort Plus 4 Quad") - DEVICE( RP, RPP8, "RocketPort Plus 8 Oct") - DEVICE( RP, RP8M, "RocketModem 8 J") -ENDVENDOR() - -VENDOR( CYCLADES, "Cyclades" ) - DEVICE( CYCLADES, CYCLOM_Y_Lo, "Cyclom-Y below 1Mbyte") - DEVICE( CYCLADES, CYCLOM_Y_Hi, "Cyclom-Y above 1Mbyte") - DEVICE( CYCLADES, CYCLOM_4Y_Lo, "Cyclom-4Y below 1Mbyte") - DEVICE( CYCLADES, CYCLOM_4Y_Hi, "Cyclom-4Y above 1Mbyte") - DEVICE( CYCLADES, CYCLOM_8Y_Lo, "Cyclom-8Y below 1Mbyte") - DEVICE( CYCLADES, CYCLOM_8Y_Hi, "Cyclom-8Y above 1Mbyte") - DEVICE( CYCLADES, CYCLOM_Z_Lo, "Cyclades-Z below 1Mbyte") - DEVICE( CYCLADES, CYCLOM_Z_Hi, "Cyclades-Z above 1Mbyte") -ENDVENDOR() - -VENDOR( ESSENTIAL, "Essential Communications" ) - DEVICE( ESSENTIAL, ESSENTIAL_ROADRUNNER,"Roadrunner serial HIPPI") -ENDVENDOR() - -VENDOR( O2, "O2 Micro" ) - DEVICE( O2, O2_6832, "6832") -ENDVENDOR() - -VENDOR( 3DFX, "3Dfx" ) - DEVICE( 3DFX, 3DFX_VOODOO, "Voodoo") - DEVICE( 3DFX, 3DFX_VOODOO2, "Voodoo2") - DEVICE( 3DFX, 3DFX_BANSHEE, "Banshee") - DEVICE( 3DFX, 3DFX_VOODOO3, "Voodoo3") -ENDVENDOR() - -VENDOR( SIGMADES, "Sigma Designs" ) - DEVICE( SIGMADES, SIGMADES_6425, "REALmagic64/GX") -ENDVENDOR() - -VENDOR( AVM, "AVM" ) - DEVICE( AVM, AVM_A1, "A1 (Fritz)") -ENDVENDOR() - -VENDOR( CCUBE, "C-Cube" ) -ENDVENDOR() - -VENDOR( DIPIX, "Dipix" ) -ENDVENDOR() - -VENDOR( STALLION, "Stallion" ) - DEVICE( STALLION, STALLION_ECHPCI832,"EasyConnection 8/32") - DEVICE( STALLION, STALLION_ECHPCI864,"EasyConnection 8/64") - DEVICE( STALLION, STALLION_EIOPCI,"EasyIO") -ENDVENDOR() - -VENDOR( OPTIBASE, "Optibase" ) - DEVICE( OPTIBASE, OPTIBASE_FORGE, "MPEG Forge") - DEVICE( OPTIBASE, OPTIBASE_FUSION,"MPEG Fusion") - DEVICE( OPTIBASE, OPTIBASE_VPLEX, "VideoPlex") - DEVICE( OPTIBASE, OPTIBASE_VPLEXCC,"VideoPlex CC") - DEVICE( OPTIBASE, OPTIBASE_VQUEST,"VideoQuest") -ENDVENDOR() - -VENDOR( ESS, "ESS Technologies" ) - DEVICE( ESS, ESS_AUDIOPCI, "3D Audio 1969") -ENDVENDOR() - -VENDOR( SATSAGEM, "SatSagem" ) - DEVICE( SATSAGEM, SATSAGEM_PCR2101,"PCR2101 DVB receiver") - DEVICE( SATSAGEM, SATSAGEM_TELSATTURBO,"Telsat Turbo DVB") -ENDVENDOR() - -VENDOR( HUGHES, "Hughes" ) - DEVICE( HUGHES, HUGHES_DIRECPC, "DirecPC") -ENDVENDOR() - -VENDOR( ENSONIQ, "Ensoniq" ) - DEVICE( ENSONIQ, ENSONIQ_ES1371, "ES1371") - DEVICE( ENSONIQ, ENSONIQ_AUDIOPCI,"AudioPCI") -ENDVENDOR() - -VENDOR( ALTEON, "Alteon" ) - DEVICE( ALTEON, ALTEON_ACENIC, "AceNIC") -ENDVENDOR() - -VENDOR( PICTUREL, "Picture Elements" ) - DEVICE( PICTUREL, PICTUREL_PCIVST,"PCIVST") -ENDVENDOR() - -VENDOR( NVIDIA_SGS, "NVidia/SGS Thomson" ) - DEVICE( NVIDIA_SGS, NVIDIA_SGS_RIVA128, "Riva 128") -ENDVENDOR() - -VENDOR( CBOARDS, "ComputerBoards" ) - DEVICE( CBOARDS, CBOARDS_DAS1602_16,"DAS1602/16") -ENDVENDOR() - -VENDOR( MOTOROLA_OOPS, "Motorola" ) - DEVICE( MOTOROLA_OOPS, MOTOROLA_FALCON,"Falcon") -ENDVENDOR() - -VENDOR( LAVA, "Lava Computer MFG" ) - DEVICE( LAVA, LAVA_PARALLEL, "Lava Parallel") - DEVICE( LAVA, LAVA_DUAL_PAR_A,"Lava Dual Parallel (A)") - DEVICE( LAVA, LAVA_DUAL_PAR_B,"Lava Dual Parallel (B)") - DEVICE( LAVA, LAVA_BOCA_IOPPAR,"BOCA Research IOPPAR") -ENDVENDOR() - -VENDOR( SYMPHONY, "Symphony" ) - DEVICE( SYMPHONY, SYMPHONY_101, "82C101") -ENDVENDOR() - -VENDOR( TEKRAM, "Tekram" ) - DEVICE( TEKRAM, TEKRAM_DC290, "DC-290") -ENDVENDOR() - -VENDOR( 3DLABS, "3Dlabs" ) - DEVICE( 3DLABS, 3DLABS_300SX, "GLINT 300SX") - DEVICE( 3DLABS, 3DLABS_500TX, "GLINT 500TX") - DEVICE( 3DLABS, 3DLABS_DELTA, "GLINT Delta") - DEVICE( 3DLABS, 3DLABS_PERMEDIA,"PERMEDIA") - DEVICE( 3DLABS, 3DLABS_MX, "GLINT MX") -ENDVENDOR() - -VENDOR( AVANCE, "Avance" ) - DEVICE( AVANCE, AVANCE_ALG2064, "ALG2064i") - DEVICE( AVANCE, AVANCE_2302, "ALG-2302") -ENDVENDOR() - -VENDOR( NETVIN, "NetVin" ) - DEVICE( NETVIN, NETVIN_NV5000SC,"NV5000") -ENDVENDOR() - -VENDOR( S3, "S3 Inc." ) - DEVICE( S3, S3_PLATO_PXS, "PLATO/PX (system)") - DEVICE( S3, S3_ViRGE, "ViRGE") - DEVICE( S3, S3_TRIO, "Trio32/Trio64") - DEVICE( S3, S3_AURORA64VP, "Aurora64V+") - DEVICE( S3, S3_TRIO64UVP, "Trio64UV+") - DEVICE( S3, S3_ViRGE_VX, "ViRGE/VX") - DEVICE( S3, S3_868, "Vision 868") - DEVICE( S3, S3_928, "Vision 928-P") - DEVICE( S3, S3_864_1, "Vision 864-P") - DEVICE( S3, S3_864_2, "Vision 864-P") - DEVICE( S3, S3_964_1, "Vision 964-P") - DEVICE( S3, S3_964_2, "Vision 964-P") - DEVICE( S3, S3_968, "Vision 968") - DEVICE( S3, S3_TRIO64V2, "Trio64V2/DX or /GX") - DEVICE( S3, S3_PLATO_PXG, "PLATO/PX (graphics)") - DEVICE( S3, S3_ViRGE_DXGX, "ViRGE/DX or /GX") - DEVICE( S3, S3_ViRGE_GX2, "ViRGE/GX2") - DEVICE( S3, S3_ViRGE_MX, "ViRGE/MX") - DEVICE( S3, S3_ViRGE_MXP, "ViRGE/MX+") - DEVICE( S3, S3_ViRGE_MXPMV, "ViRGE/MX+MV") - DEVICE( S3, S3_SONICVIBES, "SonicVibes") -ENDVENDOR() - -VENDOR( DCI, "Decision Computer Int." ) - DEVICE( DCI, DCI_PCCOM4, "PC COM PCI Bus 4 port serial Adapter") -ENDVENDOR() - -VENDOR( GENROCO, "Genroco" ) - DEVICE( GENROCO, GENROCO_HFP832, "TURBOstor HFP832") -ENDVENDOR() - -VENDOR( INTEL, "Intel" ) - DEVICE( INTEL, INTEL_82375, "82375EB") - DEVICE( INTEL, INTEL_82424, "82424ZX Saturn") - DEVICE( INTEL, INTEL_82378, "82378IB") - DEVICE( INTEL, INTEL_82430, "82430ZX Aries") - DEVICE( INTEL, INTEL_82434, "82434LX Mercury/Neptune") - DEVICE( INTEL, INTEL_82092AA_0,"82092AA PCMCIA bridge") - DEVICE( INTEL, INTEL_82092AA_1,"82092AA EIDE") - DEVICE( INTEL, INTEL_7116, "SAA7116") - DEVICE( INTEL, INTEL_82596, "82596") - DEVICE( INTEL, INTEL_82865, "82865") - DEVICE( INTEL, INTEL_82557, "EtherExpress Pro100") - DEVICE( INTEL, INTEL_82559ER, "82559ER") - DEVICE( INTEL, INTEL_82437, "82437") - DEVICE( INTEL, INTEL_82371FB_0,"82371FB PIIX ISA") - DEVICE( INTEL, INTEL_82371FB_1,"82371FB PIIX IDE") - DEVICE( INTEL, INTEL_82371MX, "430MX - 82371MX MPIIX") - DEVICE( INTEL, INTEL_82437MX, "430MX - 82437MX MTSC") - DEVICE( INTEL, INTEL_82441, "82441FX Natoma") - DEVICE( INTEL, INTEL_82380FB, "82380FB Mobile") - DEVICE( INTEL, INTEL_82439, "82439HX Triton II") - DEVICE( INTEL, INTEL_82371SB_0,"82371SB PIIX3 ISA") - DEVICE( INTEL, INTEL_82371SB_1,"82371SB PIIX3 IDE") - DEVICE( INTEL, INTEL_82371SB_2,"82371SB PIIX3 USB") - DEVICE( INTEL, INTEL_82437VX, "82437VX Triton II") - DEVICE( INTEL, INTEL_82439TX, "82439TX") - DEVICE( INTEL, INTEL_82371AB_0,"82371AB PIIX4 ISA") - DEVICE( INTEL, INTEL_82371AB, "82371AB PIIX4 IDE") - DEVICE( INTEL, INTEL_82371AB_2,"82371AB PIIX4 USB") - DEVICE( INTEL, INTEL_82371AB_3,"82371AB PIIX4 ACPI") - DEVICE( INTEL, INTEL_82443LX_0,"440LX - 82443LX PAC Host") - DEVICE( INTEL, INTEL_82443LX_1,"440LX - 82443LX PAC AGP") - DEVICE( INTEL, INTEL_82443BX_0,"440BX - 82443BX Host") - DEVICE( INTEL, INTEL_82443BX_1,"440BX - 82443BX AGP") - DEVICE( INTEL, INTEL_82443BX_2,"440BX - 82443BX Host (no AGP)") - DEVICE( INTEL, INTEL_P6, "Orion P6") - DEVICE( INTEL, INTEL_82450GX, "82450GX Orion P6") -ENDVENDOR() - -VENDOR( KTI, "KTI" ) - DEVICE( KTI, KTI_ET32P2, "ET32P2") -ENDVENDOR() - -VENDOR( ADAPTEC, "Adaptec" ) - DEVICE( ADAPTEC, ADAPTEC_7810, "AIC-7810 RAID") - DEVICE( ADAPTEC, ADAPTEC_7821, "AIC-7860") - DEVICE( ADAPTEC, ADAPTEC_38602, "AIC-7860") - DEVICE( ADAPTEC, ADAPTEC_7850, "AIC-7850") - DEVICE( ADAPTEC, ADAPTEC_7855, "AIC-7855") - DEVICE( ADAPTEC, ADAPTEC_5800, "AIC-5800") - DEVICE( ADAPTEC, ADAPTEC_3860, "AIC-7860") - DEVICE( ADAPTEC, ADAPTEC_7860, "AIC-7860") - DEVICE( ADAPTEC, ADAPTEC_7861, "AIC-7861") - DEVICE( ADAPTEC, ADAPTEC_7870, "AIC-7870") - DEVICE( ADAPTEC, ADAPTEC_7871, "AIC-7871") - DEVICE( ADAPTEC, ADAPTEC_7872, "AIC-7872") - DEVICE( ADAPTEC, ADAPTEC_7873, "AIC-7873") - DEVICE( ADAPTEC, ADAPTEC_7874, "AIC-7874") - DEVICE( ADAPTEC, ADAPTEC_7895, "AIC-7895U") - DEVICE( ADAPTEC, ADAPTEC_7880, "AIC-7880U") - DEVICE( ADAPTEC, ADAPTEC_7881, "AIC-7881U") - DEVICE( ADAPTEC, ADAPTEC_7882, "AIC-7882U") - DEVICE( ADAPTEC, ADAPTEC_7883, "AIC-7883U") - DEVICE( ADAPTEC, ADAPTEC_7884, "AIC-7884U") - DEVICE( ADAPTEC, ADAPTEC_7885, "AIC-7885U") - DEVICE( ADAPTEC, ADAPTEC_7886, "AIC-7886U") - DEVICE( ADAPTEC, ADAPTEC_7887, "AIC-7887U") - DEVICE( ADAPTEC, ADAPTEC_7888, "AIC-7888U") - DEVICE( ADAPTEC, ADAPTEC_1030, "ABA-1030 DVB receiver") -ENDVENDOR() - -VENDOR( ADAPTEC2, "Adaptec" ) - DEVICE( ADAPTEC2, ADAPTEC2_2940U2,"AHA-2940U2") - DEVICE( ADAPTEC2, ADAPTEC2_2930U2,"AHA-2930U2") - DEVICE( ADAPTEC2, ADAPTEC2_7890B, "AIC-7890/1") - DEVICE( ADAPTEC2, ADAPTEC2_7890, "AIC-7890/1") - DEVICE( ADAPTEC2, ADAPTEC2_3940U2,"AHA-3940U2") - DEVICE( ADAPTEC2, ADAPTEC2_3950U2D,"AHA-3950U2D") - DEVICE( ADAPTEC2, ADAPTEC2_7896, "AIC-7896/7") - DEVICE( ADAPTEC2, ADAPTEC2_7892A, "AIC-7892") - DEVICE( ADAPTEC2, ADAPTEC2_7892B, "AIC-7892") - DEVICE( ADAPTEC2, ADAPTEC2_7892D, "AIC-7892") - DEVICE( ADAPTEC2, ADAPTEC2_7892P, "AIC-7892") - DEVICE( ADAPTEC2, ADAPTEC2_7899A, "AIC-7899") - DEVICE( ADAPTEC2, ADAPTEC2_7899B, "AIC-7899") - DEVICE( ADAPTEC2, ADAPTEC2_7899D, "AIC-7899") - DEVICE( ADAPTEC2, ADAPTEC2_7899P, "AIC-7899") -ENDVENDOR() - -VENDOR( ATRONICS, "Atronics" ) - DEVICE( ATRONICS, ATRONICS_2015, "IDE-2015PL") -ENDVENDOR() - -VENDOR( TIGERJET, "TigerJet" ) - DEVICE( TIGERJET, TIGERJET_300, "Tiger300 ISDN") -ENDVENDOR() - -VENDOR( ARK, "ARK" ) - DEVICE( ARK, ARK_STING, "Stingray") - DEVICE( ARK, ARK_STINGARK, "Stingray ARK 2000PV") - DEVICE( ARK, ARK_2000MT, "2000MT") -ENDVENDOR() - -#undef VENDOR -#undef ENDVENDOR -#undef DEVICE diff --git a/drivers/pci/gen-devlist.c b/drivers/pci/gen-devlist.c new file mode 100644 index 0000000000000000000000000000000000000000..b9809f744d55f05c968a91d09052454a6c28d136 --- /dev/null +++ b/drivers/pci/gen-devlist.c @@ -0,0 +1,66 @@ +/* + * Generate devlist.h from the PCI ID file. + * + * (c) 1999 Martin Mares <mj@ucw.cz> + */ + +#include <stdio.h> +#include <string.h> + +static void +pq(char *c) +{ + while (*c) { + if (*c == '"') + printf("\\\""); + else + putchar(*c); + c++; + } +} + +int +main(void) +{ + char line[1024], *c, vend[8]; + int vendors = 0; + + while (fgets(line, sizeof(line)-1, stdin)) { + if ((c = strchr(line, '\n'))) + *c = 0; + if (!line[0] || line[0] == '#') + continue; + if (line[1] == ' ') { + vend[0] = 0; + continue; + } + if (line[0] == '\t') { + if (vend[0] && strlen(line) > 5 && line[5] == ' ') { + c = line + 5; + while (*c == ' ') + *c++ = 0; + printf("\tDEVICE(%s,%s,\"", vend, line+1); + pq(c); + puts("\")"); + } + } else if (strlen(line) > 4 && line[4] == ' ') { + c = line + 4; + while (*c == ' ') + *c++ = 0; + if (vendors) + puts("ENDVENDOR()\n"); + vendors++; + strcpy(vend, line); + printf("VENDOR(%s,\"", vend); + pq(c); + puts("\")"); + } + } + puts("ENDVENDOR()\n\ +\n\ +#undef VENDOR\n\ +#undef DEVICE\n\ +#undef ENDVENDOR"); + + return 0; +} diff --git a/drivers/pci/names.c b/drivers/pci/names.c index 52d0492368fb4c226679af1ed583dc5e8f6879f5..81dafad61c96585de257eccd4ec5550dc47459ea 100644 --- a/drivers/pci/names.c +++ b/drivers/pci/names.c @@ -39,11 +39,11 @@ struct pci_vendor_info { #define VENDOR( vendor, name ) static struct pci_device_info __devices_##vendor[] __initdata = { #define ENDVENDOR() }; -#define DEVICE( vendor, device, name ) { PCI_DEVICE_ID_##device, 0, __devicestr_##vendor##device }, +#define DEVICE( vendor, device, name ) { 0x##device, 0, __devicestr_##vendor##device }, #include "devlist.h" static const struct pci_vendor_info __initdata pci_vendor_list[] = { -#define VENDOR( vendor, name ) { PCI_VENDOR_ID_##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor }, +#define VENDOR( vendor, name ) { 0x##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor }, #define ENDVENDOR() #define DEVICE( vendor, device, name ) #include "devlist.h" diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids new file mode 100644 index 0000000000000000000000000000000000000000..d9b44d1e009c4859c5367b998081b669cc2c312c --- /dev/null +++ b/drivers/pci/pci.ids @@ -0,0 +1,3640 @@ +# +# List of PCI ID's +# +# Maintained by Martin Mares <pci-ids@ucw.cz> +# If you have any new entries, send them to the maintainer. +# +# $Id: pci.ids,v 1.41 1999/10/30 09:25:10 mj Exp $ +# + +# Vendors, devices and subsystems. Please keep sorted. + +# Syntax: +# vendor vendor_name +# device device_name <-- single tab +# subvendor subdevice subsystem_name <-- two tabs + +0000 Gammagraphx, Inc. +001a Ascend Communications, Inc. +0033 Paradyne corp. +003d Lockheed Martin-Marietta Corp +0070 Hauppage computer works Inc. +0675 Dynalink + 1700 IS64PH ISDN Adapter + 1702 IS64PH ISDN Adapter +0a89 BREA Technologies Inc +0e11 Compaq Computer Corporation + 0001 PCI to EISA Bridge + 0002 PCI to ISA Bridge + 0508 Netelligent 4/16 Token Ring + 1000 Triflex/Pentium Bridge, Model 1000 + 2000 Triflex/Pentium Bridge, Model 2000 + 3032 QVision 1280/p + 3033 QVision 1280/p + 3034 QVision 1280/p + 4000 4000 [Triflex] + 6010 HotPlug PCI Bridge 6010 + a0f3 Triflex PCI to ISA Bridge + ae10 Smart-2/P RAID Controller + 0e11 4030 Smart-2/P Array Controller + 0e11 4031 Smart-2SL Array Controller + 0e11 4032 Smart Array Controller + 0e11 4033 Smart 3100ES Array Controller + ae29 MIS-L + ae2a MPC + ae2b MIS-E + ae32 Netelligent 10/100 + ae34 Netelligent 10 + ae35 Integrated NetFlex-3/P + ae40 Netelligent 10/100 Dual + ae43 ProLiant Integrated Netelligent 10/100 + ae69 CETUS-L + ae6c Northstar + b011 Integrated Netelligent 10/100 + b012 Netelligent 10 T/2 + b030 Netelligent WS 5100 + b04a 10/100TX WOL UTP Controller + b0c6 10/100TX Embedded WOL UTP Controller + b0d7 NC3121 (Rev A & B) + f130 NetFlex-3/P ThunderLAN 1.0 + f150 NetFlex-3/P ThunderLAN 2.3 +1000 Symbios Logic Inc. (formerly NCR) + 0001 53c810 + 1000 1000 8100S + 0002 53c820 + 0003 53c825 + 0004 53c815 + 0005 53c810AP + 0006 53c860 + 000b 53c896 + 000c 53c895 + 000d 53c885 + 000f 53c875 + 0e11 7004 Embedded Ultra Wide SCSI Controller + 1092 8760 FirePort 40 Dual SCSI Controller + 1de1 3904 DC390F Ultra Wide SCSI Controller + 0012 53c895a + 008f 53c875J + 1092 8000 FirePort 40 SCSI Controller + 1092 8760 FirePort 40 Dual SCSI Host Adapter + 0701 83C885 + 0702 Yellowfin G-NIC gigabit ethernet + 1318 0000 PEI100X + 0901 61C102 + 1000 63C815 +1001 Initio + 9100 INI-9100/9100W SCSI Host +1002 ATI Technologies Inc + 4158 68800AX [Mach32] + 4354 215CT [Mach64 CT] + 4358 210888CX [Mach64 CX] + 4554 210888ET [Mach64 ET] + 4742 3D Rage Pro AGP 1X/2X + 4744 3D Rage Pro AGP 1X + 4747 3D Rage Pro + 4749 3D Rage Pro + 474c Rage XC + 474d Rage XL AGP + 474e Rage XC AGP + 474f Rage XL + 4750 3D Rage Pro 215GP + 4751 3D Rage Pro 215GQ + 4753 Rage XC + 4754 3D Rage I/II 215GT [Mach64 GT] + 4755 3D Rage II+ 215GTB [Mach64 GTB] + 4756 3D Rage IIC 215IIC [Mach64 GT IIC] + 4757 3D Rage IIC AGP + 4758 210888GX [Mach64 GX] + 4759 3D Rage IIC + 475a 3D Rage IIC AGP + 4c42 3D Rage LT Pro AGP-133 + 0e11 b10e 3D Rage LT Pro (Compaq Armada 1750) + 4c44 3D Rage LT Pro AGP-66 + 4c47 3D Rage LT-G 215LG + 4c49 3D Rage LT Pro + 4c4d 3D Rage P/M Mobility AGP 2x + 4c4e 3D Rage L Mobility AGP 2x + 4c50 3D Rage LT Pro + 4c51 3D Rage LT Pro + 4c52 3D Rage P/M Mobility + 4c53 3D Rage L Mobility + 4c54 264LT [Mach64 LT] + 5041 Rage 128 PA + 5042 Rage 128 PB + 5043 Rage 128 PC + 5044 Rage 128 PD + 5045 Rage 128 PE + 5046 Rage 128 PF + 5047 Rage 128 PG + 5048 Rage 128 PH + 5049 Rage 128 PI + 504A Rage 128 PJ + 504B Rage 128 PK + 504C Rage 128 PL + 504D Rage 128 PM + 504E Rage 128 PN + 504F Rage 128 PO + 5050 Rage 128 PP + 5051 Rage 128 PQ + 5052 Rage 128 PR + 5053 Rage 128 PS + 5054 Rage 128 PT + 5055 Rage 128 PU + 5056 Rage 128 PV + 5057 Rage 128 PW + 5058 Rage 128 PX + 5245 Rage 128 RE + 5246 Rage 128 RF + 524b Rage 128 RK + 524c Rage 128 RL + 5345 Rage 128 SE + 5346 Rage 128 SF + 5347 Rage 128 SG + 534B Rage 128 SK + 534C Rage 128 SL + 534D Rage 128 SM + 5354 Mach 64 VT + 1002 5654 Mach 64 reference + 5654 264VT [Mach64 VT] + 5655 264VT3 [Mach64 VT3] + 5656 264VT4 [Mach64 VT4] +1003 ULSI Systems + 0201 US201 +1004 VLSI Technology Inc + 0005 82C592-FC1 + 0006 82C593-FC1 + 0007 82C594-AFC2 + 0008 82C596/7 [Wildcat] + 0009 82C597-AFC2 + 000c 82C541 [Lynx] + 000d 82C543 [Lynx] + 0101 82C532 + 0102 82C534 + 0103 82C538 + 0104 82C535 + 0105 82C147 + 0200 82C975 + 0280 82C925 + 0702 VAS96011 [Golden Gate II] +1005 Avance Logic Inc. [ALI] + 2064 ALG2032/2064 + 2128 ALG2364A + 2301 ALG2301 + 2302 ALG2302 + 2364 ALG2364 + 2464 ALG2364A + 2501 ALG2564A/25128A +1006 Reply Group +1007 NetFrame Systems Inc +1008 Epson +100a Phoenix Technologies +100b National Semiconductor Corporation + 0001 DP83810 + 0002 87415 + d001 87410 +100c Tseng Labs Inc + 3202 ET4000/W32p rev A + 3205 ET4000/W32p rev B + 3206 ET4000/W32p rev C + 3207 ET4000/W32p rev D + 3208 ET6000 + 4702 ET6300 +100d AST Research Inc +100e Weitek + 9000 P9000 + 9001 P9000 + 9100 P9100 +1010 Video Logic, Ltd. +1011 Digital Equipment Corporation + 0001 DECchip 21050 + 0002 DECchip 21040 [Tulip] + 0004 DECchip 21030 [TGA] + 0007 NVRAM [Zephyr NVRAM] + 0008 KZPSA [KZPSA] + 0009 DECchip 21140 [FasterNet] + 10b8 2001 SMC9332BDT EtherPower 10/100 + 10b8 2002 SMC9332BVT EtherPower T4 10/100 + 10b8 2003 SMC9334BDT EtherPower 10/100 (1-port) + 1112 2300 RNS2300 Fast Ethernet + 1112 2320 RNS2320 Fast Ethernet + 1112 2340 RNS2340 Fast Ethernet + 1113 1207 EN-1207-TX Fast Ethernet + 1109 2400 ANA-6944A/TX Fast Ethernet + 1186 1100 DFE-500TX Fast Ethernet + 1282 9100 AEF-380TXD Fast Ethernet + 2646 0001 KNE100TX Fast Ethernet + 000a 21230 Video Codec + 000d PBXGB [TGA2] + 000f DEFPA + 0014 DECchip 21041 [Tulip Pass 3] + 1186 0100 DE-530+ + 0016 DGLPB [OPPO] + 0019 DECchip 21142/43 + 1011 500b DE500 Fast Ethernet + 1014 0001 10/100 EtherJet Cardbus + 1025 0315 ALN315 Fast Ethernet + 108d 0016 Rapidfire 2327 10/100 Ethernet + 10b8 2005 SMC8032DT Extreme Ethernet 10/100 + 10ef 8169 Cardbus Fast Ethernet + 1109 2a00 ANA-6911A/TX Fast Ethernet + 1109 2b00 ANA-6911A/TXC Fast Ethernet + 1109 3000 ANA-6922/TX Fast Ethernet + 1113 1207 Cheetah Fast Ethernet + 1113 2220 Cardbus Fast Ethernet + 115d 0002 Cardbus Ethernet 10/100 + 1179 0203 Fast Ethernet + 1179 0204 Cardbus Fast Ethernet + 1186 1101 DFE-500TX Fast Ethernet + 1186 1102 DFE-500TX Fast Ethernet + 1266 0004 Eagle Fast EtherMAX + 12af 0019 NetFlyer Cardbus Fast Ethernet + 1395 0001 10/100 Ethernet CardBus PC Card + 8086 0001 EtherExpress PRO/100 Mobile CardBus 32 + 0021 DECchip 21052 + 0022 DECchip 21150 + 0024 DECchip 21152 + 0025 DECchip 21153 + 0026 DECchip 21154 + 0045 DECchip 21553 + 0046 DECchip 21554 +1012 Micronics Computers Inc +1013 Cirrus Logic + 0038 GD 7548 + 0040 GD 7555 Flat Panel GUI Accelerator + 004c GD 7556 Video/Graphics LCD/CRT Ctrlr + 00a0 GD 5430/40 [Alpine] + 00a2 GD 5432 [Alpine] + 00a4 GD 5434-4 [Alpine] + 00a8 GD 5434-8 [Alpine] + 00ac GD 5436 [Alpine] + 00b0 GD 5440 + 00b8 GD 5446 + 00bc GD 5480 + 00d0 GD 5462 + 00d2 GD 5462 [Laguna I] + 00d4 GD 5464 [Laguna] + 00d6 GD 5465 [Laguna] + 00e8 GD 5436U + 1100 CL 6729 + 1110 PD 6832 + 1112 PD 6834 PCMCIA/CardBus Ctrlr + 1113 PD 6833 PCMCIA/CardBus Ctrlr + 1200 GD 7542 [Nordic] + 1202 GD 7543 [Viking] + 1204 GD 7541 [Nordic Light] + 4400 CD 4400 + 6001 CS 4610/11 [CrystalClear SoundFusion Audio Accelerator] + 6003 CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator] +1014 IBM + 0002 PCI to MCA Bridge + 0005 Alta Lite + 0007 Alta MP + 000a Fire Coral + 0018 TR Auto LANstreamer + 001b GXT-150P + 001d 82G2675 + 0020 MCA + 0022 IBM27-82351 + 002d Python + 002e ServeRAID controller + 0036 Miami + 003e 16/4 Token ring UTP/STP controller + 1014 003E Token-Ring Adapter + 1014 00CD Token-Ring Adapter + Wake-On-LAN + 1014 00CE 16/4 Token-Ring Adapter 2 + 1014 00CF 16/4 Token-Ring Adapter Special + 1014 00E4 High-Speed 100/16/4 Token-Ring Adapter + 1014 00E5 16/4 Token-Ring Adapter 2 + Wake-On-LAN + 0046 MPIC interrupt controller + 0053 25 MBit ATM Controller + 0057 MPEG PCI Bridge + 005C i82557B 10/100 + 007d 3780IDSP [MWave] + 0095 20H2999 PCI Docking Bridge + 00b7 256-bit Graphics Rasterizer [Fire GL1] + ffff MPIC-2 interrupt controller +1015 LSI Logic Corp of Canada +1016 ICL Personal Systems +1017 SPEA Software AG + 5343 SPEA 3D Accelerator +1018 Unisys Systems +1019 Elitegroup Computer Systems +101a AT&T GIS (NCR) + 0005 100VG ethernet +101b Vitesse Semiconductor +101c Western Digital + 0193 33C193A + 0196 33C196A + 0197 33C197A + 0296 33C296A + 3193 7193 + 3197 7197 + 3296 33C296A + 4296 34C296 + 9710 Pipeline 9710 + 9712 Pipeline 9712 + c24a 90C +101e American Megatrends Inc. + 9010 MegaRAID + 9060 MegaRAID +101f PictureTel +1020 Hitachi Computer Products +1021 OKI Electric Industry Co. Ltd. +1022 Advanced Micro Devices [AMD] + 2000 79c970 [PCnet LANCE] + 103c 104c Ethernet with LAN remote power Adapter + 103c 1064 Ethernet with LAN remote power Adapter + 103c 1065 Ethernet with LAN remote power Adapter + 103c 106c Ethernet with LAN remote power Adapter + 103c 106e Ethernet with LAN remote power Adapter + 103c 10ea Ethernet with LAN remote power Adapter + 1113 1220 EN1220 10/100 Fast Ethernet + 1259 2450 AT-2450 10/100 Fast Ethernet + 1259 2700 AT-2700TX 10/100 Fast Ethernet + 1259 2701 AT-2700FX 100Mb Ethernet + 2001 79c978 [HomePNA] + 2020 53c974 [PCscsi] + 2040 79c974 +1023 Trident Microsystems + 0194 82C194 + 2000 4DWave DX + 2001 4DWave NX + 8400 CyberBlade/i7 + 8420 CyberBlade/i7d + 8500 CyberBlade/i1 + 9320 TGUI 9320 + 9382 Cyber 9382 [Reference design] + 9383 Cyber 9383 [Reference design] + 9385 Cyber 9385 [Reference design] + 9386 Cyber 9386 + 9388 Cyber 9388 + 9397 Cyber 9397 + 939a Cyber 9397DVD + 9420 TGUI 9420 + 9430 TGUI 9430 + 9440 TGUI 9440 + 9460 TGUI 9460 + 9470 TGUI 9470 + 9520 Cyber 9520 + 9525 Cyber 9525 + 9660 TGUI 9660/968x/968x + 9680 TGUI 9680 + 9682 TGUI 9682 + 9683 TGUI 9683 + 9685 ProVIDIA 9685 + 9750 3DIm`age 975 + 9753 TGUI 9753 + 9754 TGUI 9754 + 9759 TGUI 975 + 9783 TGUI 9783 + 9785 TGUI 9785 + 9850 3DImage 9850 + 9880 Blade 3D PCI/AGP +1024 Zenith Data Systems +1025 Acer Incorporated [ALI] + 1435 M1435 + 1445 M1445 + 1449 M1449 + 1451 M1451 + 1461 M1461 + 1489 M1489 + 1511 M1511 + 1513 M1513 + 1531 M1531 + 1533 M1533 + 3141 M3141 + 3143 M3143 + 3145 M3145 + 3147 M3147 + 3149 M3149 + 3151 M3151 + 5217 M5217H + 5219 M5219 + 5225 M5225 + 5229 M5229 + 5235 M5235 +1028 Dell Computer Corporation +1029 Siemens Nixdorf IS +102a LSI Logic + 0000 HYDRA + 0010 ASPEN +102b Matrox Graphics, Inc. +#DJ: I've a suspicion that 0010 is a duplicate of 0d10. + 0010 MGA-I [Impression?] + 0518 MGA-II [Athena] + 0519 MGA 2064W [Millennium] + 051a MGA 1064SG [Mystique] + 1100 102b MGA-1084SG Mystique + 051b MGA 2164W [Millennium II] + 051e MGA 1064SG [Mystique] AGP + 051f MGA 2164W [Millennium II] AGP + 0520 MGA G200 + 102b dbc2 G200 Multi-Monitor + 102b dbc8 G200 Multi-Monitor + 102b dbe2 G200 Multi-Monitor + 102b dbe8 G200 Multi-Monitor + 102b ff03 Millennium G200 SD + 102b ff04 Marvel G200 + 0521 MGA G200 AGP + 1014 ff03 Millennium G200 AGP + 102b 48e9 Mystique G200 AGP + 102b 48f8 Millennium G200 SD AGP + 102b 4a60 Millennium G200 LE AGP + 102b 4a64 Millennium G200 AGP + 102b c93c Millennium G200 AGP + 102b c9b0 Millennium G200 AGP + 102b c9bc Millennium G200 AGP + 102b ca60 Millennium G250 LE AGP + 102b ca6c Millennium G250 AGP + 102b dbbc Millennium G200 AGP + 102b f806 Mystique G200 Video AGP + 102b ff02 Mystique G200 AGP + 102b ff03 Millennium G200 AGP + 102b ff04 Marvel G200 AGP + 0525 MGA G400 AGP + 0e11 b16f Matrox MGA-G400 AGP + 102b 0328 Millennium G400 16Mb SDRAM + 102b 0338 Millennium G400 16Mb SDRAM + 102b 19d8 Millennium G400 16Mb SGRAM + 102b 19f8 Millennium G400 32Mb SGRAM + 102b 2159 Millennium G400 Dual Head 16Mb + 102b 2179 Millennium G400 MAX/Dual Head 32Mb + 102b 217d Millennium G400 Dual Head Max + 102b 2f58 Millennium G400 + 102b 2f78 Millennium G400 + 102b 3693 Marvel G400 AGP + b16f 0e11 Matrox MGA-G400 AGP + 0d10 MGA Ultima/Impression + 1000 MGA G100 [Productiva] + 102b ff01 Productiva G100 + 102b ff05 Productiva G100 Multi-Monitor + 1001 MGA G100 [Productiva] AGP + 102b ff05 MGA-G100 Productiva AGP Multi-Monitor + 2007 MGA Mistral + 4536 VIA Framegrabber +102c Chips and Technologies + 00b8 F64310 + 00c0 F69000 HiQVideo + 00d0 F65545 + 00d8 F65545 + 00dc F65548 + 00e0 F65550 + 00e4 F65554 + 00e5 F65555 HiQVPro + 0e11 b049 Armada 1700 Laptop Display Controller + 00f0 F68554 + 00f4 F68554 HiQVision + 00f5 F68555 +102d Wyse Technology Inc. + 50dc 3328 Audio +102e Olivetti Advanced Technology +102f Toshiba America + 0009 r4x00 + 0020 ATM Meteor 155 +1030 TMC Research +1031 Miro Computer Products AG + 5601 DC20 ASIC + 5607 Video I/O & motion JPEG compressor + 5631 Media 3D + 6057 MiroVideo DC10/DC30+ +1032 Compaq +1033 NEC Corporation + 0001 PCI to 486-like bus Bridge + 0002 PCI to VL98 Bridge + 0003 ATM Controller + 0004 R4000 PCI Bridge + 0005 PCI to 486-like bus Bridge + 0007 PCI to UX-Bus Bridge + 001a [Nile II] + 0021 Vrc4373 [Nile I] + 0029 PowerVR PCX1 + 002a PowerVR 3D + 0035 USB + 0046 PowerVR PCX2 [midas] + 005a Vrc5074 [Nile 4] + 0063 Firewarden + 0067 PowerVR Neon 250 Chipset + 1010 0020 PowerVR Neon 250 AGP 32Mb + 1010 0080 PowerVR Neon 250 AGP 16Mb + 1010 0088 PowerVR Neon 250 16Mb + 1010 0090 PowerVR Neon 250 AGP 16Mb + 1010 0098 PowerVR Neon 250 16Mb + 1010 00a0 PowerVR Neon 250 AGP 32Mb + 1010 00a8 PowerVR Neon 250 32Mb + 1010 0120 PowerVR Neon 250 AGP 32Mb + 0074 56k Voice Modem + 1033 8014 RCV56ACF 56k Voice Modem + 009b Vrc5476 +1034 Framatome Connectors USA Inc. +1035 Comp. & Comm. Research Lab +1036 Future Domain Corp. + 0000 TMC-18C30 [36C70] +1037 Hitachi Micro Systems +1038 AMP, Inc +1039 Silicon Integrated Systems [SiS] + 0001 5591/5592 AGP + 0002 SG86C202 + 0006 85C501/2/3 + 0008 85C503/5513 + 0009 ACPI + 0200 5597/5598 VGA + 0204 82C204 + 0205 SG86C205 + 0406 85C501/2 + 0496 85C496 + 0530 530 Host + 0597 5513C + 0601 85C601 + 0620 620 Host + 0900 SiS900 10/100 Ethernet + 3602 83C602 + 5107 5107 + 5511 5511/5512 + 5513 5513 + 5517 5517 + 5571 5571 + 5591 5591/5592 Host + 5597 5597 [SiS5582] + 5600 5600 Host + 6204 Video decoder & MPEG interface + 6236 6236 3D-AGP + 6306 6306 3D-AGP + 6326 86C326 + 1092 0a50 SpeedStar A50 + 1092 0a70 SpeedStar A70 + 1092 4910 SpeedStar A70 + 1092 4920 SpeedStar A70 + 7001 7001 + 7007 OHCI Compliant FireWire Controller +103a Seiko Epson Corporation +103b Tatung Co. of America +103c Hewlett-Packard Company + 1030 J2585A + 1031 J2585B + 1040 J2973A DeskDirect 10BaseT NIC + 1041 J2585B DeskDirect 10/100 NIC + 1042 J2970A DeskDirect 10BaseT/2 NIC + 1064 79C970 PCnet Ethernet Controller + 2910 E2910A + 2925 E2925A +103e Solliday Engineering +103f Synopsys/Logic Modeling Group +1040 Accelgraphics Inc. +1041 Computrend +1042 Micron + 1000 FDC 37C665 + 1001 37C922 + 3000 Samurai_0 + 3010 Samurai_1 + 3020 Samurai_IDE +1043 Asustek Computer, Inc. +1044 Distributed Processing Technology + 1012 Domino RAID Engine + a400 SmartCache/Raid I-IV Controller + a500 PCI Bridge + a501 SmartRAID V Controller +1045 OPTi Inc. + a0f8 82C750 [Vendetta] USB Controller + c101 92C264 + c178 92C178 + c556 82X556 [Viper] + c557 82C557 [Viper-M] + c558 82C558 [Viper-M ISA+IDE] + c567 82C750 [Vendetta], device 0 + c568 82C750 [Vendetta], device 1 + c569 82C579 [Viper XPress+ Chipset] + c621 82C621 + c700 82C700 + c701 82C701 [FireStar Plus] + c814 82C814 [Firebridge 1] + c822 82C822 + c824 82C824 + c825 82C825 [Firebridge 2] + c861 82C861 + c895 82C895 + d568 82C825 [Firebridge 2] +1046 IPC Corporation, Ltd. +1047 Genoa Systems Corp +1048 Elsa AG + 1000 QuickStep 1000 + 3000 QuickStep 3000 +1049 Fountain Technologies, Inc. +104a SGS Thomson Microelectronics + 0008 STG 2000X + 0009 STG 1764X + 1746 STG 1764X + 3520 MPEG-II decoder card +104b BusLogic + 0140 BT-946C (old) [multimaster 01] + 1040 BT-946C (BA80C30) [MultiMaster 10] + 8130 Flashpoint LT +104c Texas Instruments + 0500 100 MBit LAN Controller + 0508 TMS380C2X Compressor Interface + 1000 Eagle i/f AS + 3d04 TVP4010 [Permedia] + 3d07 TVP4020 [Permedia 2] + 1092 0127 FIRE GL 1000 PRO + 1092 0136 FIRE GL 1000 PRO + 1092 0141 FIRE GL 1000 PRO + 1092 0146 FIRE GL 1000 PRO + 1092 0148 FIRE GL 1000 PRO + 1092 0149 FIRE GL 1000 PRO + 1092 0152 FIRE GL 1000 PRO + 1092 0154 FIRE GL 1000 PRO + 1092 0155 FIRE GL 1000 PRO + 1092 0156 FIRE GL 1000 PRO + 1092 0157 FIRE GL 1000 PRO + 1097 3d01 Jeronimo Pro + 3d3d 0100 Reference Permedia 2 3D + 8000 LYNX FireWire Host Controller + 8009 OHCI Compliant FireWire Controller + 8019 TSB12LV23 OHCI Compliant IEEE-1394 Controller + a001 TDC1570 + a100 TDC1561 + ac10 PCI1050 + ac11 PCI1053 + ac12 PCI1130 + ac13 PCI1031 + ac15 PCI1131 + ac16 PCI1250 + ac17 PCI1220 + ac18 PCI1260 + ac19 PCI1221 + ac1a PCI1210 + ac1b PCI1221 + ac1c PCI1225 + ac1d PCI1251 + ac20 TI 2030 + fe00 FireWire Host Controller + fe03 12C01A FireWire Host Controller +104d Sony Corporation +104e Oak Technology, Inc + 0017 OTI-64017 + 0107 OTI-107 [Spitfire] + 0111 OTI-64111 [Spitfire] + 0217 OTI-64217 + 0317 OTI-64317 +104f Co-time Computer Ltd +1050 Winbond Electronics Corp + 0000 NE2000 + 0001 W83769F + 0105 W82C105 + 0840 W89C840 + 0940 W89C940 + 5a5a W89C940F + 9970 W9970CF +1051 Anigma, Inc. +1053 Young Micro Systems +1054 Hitachi, Ltd +1055 EFAR Microsystems +1056 ICL +# Motorola made a mistake and used this value, please duplicate Moto +# entries here -- Cort +1507 Motorola Computer Group + 0001 MPC105 [Eagle] + 0002 MPC106 [Grackle] + 0100 MC145575 [HFC-PCI] + 0431 KTI829c 100VG + 4801 Raven + 4802 Falcon + 4803 Hawk + 4806 CPX8216 +1057 Motorola Computer Group + 0001 MPC105 [Eagle] + 0002 MPC106 [Grackle] + 0100 MC145575 [HFC-PCI] + 0431 KTI829c 100VG + 4801 Raven + 4802 Falcon + 4803 Hawk + 4806 CPX8216 +1058 Electronics & Telecommunications RSH +1059 Teknor Industrial Computers Inc +105a Promise Technology, Inc. + 4d33 20246 + 4d38 20262 + 5300 DC5300 +105b Foxconn International, Inc. +105c Wipro Infotech Limited +105d Number 9 Computer Company + 2309 Imagine 128 + 2339 Imagine 128-II + 105d 0000 Imagine 128 series 2 4Mb VRAM + 105d 0001 Imagine 128 series 2 4Mb VRAM + 105d 0002 Imagine 128 series 2 4Mb VRAM + 105d 0003 Imagine 128 series 2 4Mb VRAM + 105d 0004 Imagine 128 series 2 4Mb VRAM + 105d 0005 Imagine 128 series 2 4Mb VRAM + 105d 0006 Imagine 128 series 2 4Mb VRAM + 105d 0007 Imagine 128 series 2 4Mb VRAM + 105d 0008 Imagine 128 series 2e 4Mb DRAM + 105d 0009 Imagine 128 series 2e 4Mb DRAM + 105d 000a Imagine 128 series 2 8Mb VRAM + 105d 000b Imagine 128 series 2 8Mb H-VRAM + 493d Imagine 128 T2R [Ticket to Ride] + 5348 Revolution 4 +105e Vtech Computers Ltd +105f Infotronic America Inc +1060 United Microelectronics [UMC] + 0001 UM82C881 + 0002 UM82C886 + 0101 UM8673F + 0881 UM8881 + 0886 UM8886F + 0891 UM8891A + 1001 UM886A + 673a UM8886BF + 8710 UM8710 + 886a UM8886A + 8881 UM8881F + 8886 UM8886F + 888a UM8886A + 8891 UM8891A + 9017 UM9017F + 9018 UM9018 + 9026 UM9026 + e881 UM8881N + e886 UM8886N + e891 UM8891N +1061 I.I.T. + 0001 AGX016 + 0002 IIT3204/3501 +1062 Maspar Computer Corp +1063 Ocean Office Automation +1064 Alcatel +1065 Texas Microsystems +1066 PicoPower Technology + 0000 PT80C826 + 0001 PT86C52x [Vesuvius] + 0002 PT80C524 [Nile] + 0005 National PC87550 System Controller + 8002 PT80C524 [Nile] +1067 Mitsubishi Electronics +1068 Diversified Technology +1069 Mylex Corporation + 0001 DAC960P + 0002 DAC960PD + 0010 DAC960PX + ba55 eXtremeRAID support Device +106a Aten Research Inc +106b Apple Computer Inc. + 0001 Bandit PowerPC host bridge + 0002 Grand Central I/O + 0003 Control Video + 0004 PlanB Video-In + 0007 O'Hare I/O + 000e Hydra Mac I/O + 0010 Heathrow Mac I/O + 0017 Paddington Mac I/O +106c Hyundai Electronics America + 8803 Dual Window Graphics Accelerator + 8804 LAN Controller + 8805 100-BaseT LAN +106d Sequent Computer Systems +106e DFI, Inc +106f City Gate Development Ltd +1070 Daewoo Telecom Ltd +1071 Mitac +1072 GIT Co Ltd +1073 Yamaha Corporation + 0002 YGV615 [RPA3 3D-Graphics Controller] + 0003 YMF-740 + 0004 YMF-724 + 000C YMF-740C [DS-1L Audio Controller] + 000D YMF-724F [DS-1 Audio Controller] + 0010 YMF-744B [DS-1S Audio Controller] + 0012 YMF-754 [DS-1E Audio Controller] +1074 NexGen Microsystems + 4e78 82c500/1 +1075 Advanced Integrations Research +1076 Chaintech Computer Co. Ltd +1077 Q Logic + 1020 ISP1020 + 1022 ISP1022 + 1080 ISP1080 + 1240 ISP1240 + 2020 ISP2020A + 2100 ISP2100 +1078 Cyrix Corporation + 0000 5510 [Grappa] + 0001 PCI Master + 0002 5520 [Cognac] + 0100 5530 Legacy [Kahlua] + 0101 5530 SMI [Kahlua] + 0102 5530 IDE [Kahlua] + 0103 5530 Audio [Kahlua] + 0104 5530 Video [Kahlua] +1079 I-Bus +107a NetWorth +107b Gateway 2000 +107c LG Electronics [Lucky Goldstar Co. Ltd] +107d LeadTek Research Inc. + 0000 P86C850 +107e Interphase Corporation + 0001 ATM Interface Card + 0002 100 VG AnyLan Controller + 0008 155 Mbit ATM Controller +107f Data Technology Corporation + 0802 SL82C105 +1080 Contaq Microsystems + 0600 82C599 + c691 Cypress CY82C691 + c693 82c693 +1081 Supermac Technology + 0d47 Radius PCI to NuBUS Bridge +1082 EFA Corporation of America +1083 Forex Computer Corporation + 0001 FR710 +1084 Parador +1085 Tulip Computers Int.B.V. +1086 J. Bond Computer Systems +1087 Cache Computer +1088 Microcomputer Systems (M) Son +1089 Data General Corporation +108a Bit3 Computer Corp. + 0001 VME Bridge Model 617 + 0010 VME Bridge Model 618 + 3000 VME Bridge Model 2706 +108c Oakleigh Systems Inc. +108d Olicom + 0001 OC-3136/3137 + 0002 16/4 Token Ring + 0004 OC-3139/3140 RapidFire Token-Ring 16/4 + 0005 OC-3250 GoCard Token-Ring 16/4 + 0006 OC-3530 RapidFire Token-Ring 100 + 0007 OC-3141 RapidFire Token-Ring 16/4 + 0011 OC-2315 + 0012 OC-2325 + 0013 OC-2183/2185 + 0014 OC-2326 + 0021 OC-6151/6152 [RapidFire ATM 155] + 0022 ATM Adapter +108e Sun Microsystems Computer Corp. + 0001 EBUS + 1000 EBUS + 1001 Happy Meal + 5000 Simba Advanced PCI Bridge + 8000 PCI Bus Module + a000 Ultra IIi +108f Systemsoft +1090 Encore Computer Corporation +1091 Intergraph Corporation + 0020 3D graphics processor + 0021 3D graphics processor w/Texturing + 0040 3D graphics frame buffer + 0041 3D graphics frame buffer + 0060 Proprietary bus bridge + 00E4 Powerstorm 4D50T + 0720 Motion JPEG codec +1092 Diamond Multimedia Systems + 00a0 Speedstar Pro SE + 00a8 Speedstar 64 + 08d4 Supra 2260 Modem + 1092 Viper V330 + 6120 Maximum DVD + 8810 Stealth SE + 8811 Stealth 64/SE + 8880 Stealth + 8881 Stealth + 88b0 Stealth 64 + 88b1 Stealth 64 + 88c0 Stealth 64 + 88c1 Stealth 64 + 88d0 Stealth 64 + 88d1 Stealth 64 + 88f0 Stealth 64 + 88f1 Stealth 64 + 9999 DMD-I0928-1 "Monster sound" sound chip +1093 National Instruments + 0160 PCI-DIO-96 + 0162 PCI-MIO-16XE-50 + 1170 PCI-MIO-16XE-10 + 1180 PCI-MIO-16E-1 + 1190 PCI-MIO-16E-4 + 1330 PCI-6031E + 1350 PCI-6071E + 2a60 PCI-6023E + c801 PCI-GPIB +1094 First International Computers [FIC] +1095 CMD Technology Inc + 0640 PCI0640 + 0643 PCI0643 + 0646 PCI0646 + 0650 PBC0650A + 0647 PCI0647 + 0670 USB0670 + 0673 USB0673 +1096 Alacron +1097 Appian Technology +1098 Quantum Designs (H.K.) Ltd + 0001 QD-8500 + 0002 QD-8580 +1099 Samsung Electronics Co., Ltd +109a Packard Bell +109b Gemlight Computer Ltd. +109c Megachips Corporation +109d Zida Technologies Ltd. +109e Brooktree Corporation + 0350 Bt848 TV with DMA push + 0351 Bt849A Video capture + 036e Bt878 + 1851 1850 FlyVideo'98 - Video + 1851 1851 FlyVideo II + 1852 1852 FlyVideo'98 - Video (with FM Tuner) + 036f Bt879 + 1851 1850 FlyVideo'98 - Video + 1851 1851 FlyVideo II + 1852 1852 FlyVideo'98 - Video (with FM Tuner) + 0878 Bt878 + 2115 BtV 2115 Mediastream controller + 2125 BtV 2125 Mediastream controller + 2164 BtV 2164 + 2165 BtV 2165 + 8230 Bt8230 ATM Segment/Reassembly Ctrlr (SRC) + 8472 Bt8472 + 8474 Bt8474 +109f Trigem Computer Inc. +10a0 Meidensha Corporation +10a1 Juko Electronics Ind. Co. Ltd +10a2 Quantum Corporation +10a3 Everex Systems Inc +10a4 Globe Manufacturing Sales +10a5 Racal Interlan +10a6 Informtech Industrial Ltd. +10a7 Benchmarq Microelectronics +10a8 Sierra Semiconductor + 0000 STB Horizon 64 +10a9 Silicon Graphics + 0003 IOC3 + 0005 RAD Audio + 0009 Alteon Gigabit Ethernet +10aa ACC Microelectronics + 0000 ACCM 2188 +10ab Digicom +10ac Honeywell IAC +10ad Symphony Labs + 0001 W83769F + 0003 SL82C103 + 0005 SL82C105 + 0103 SL82c103 + 0105 SL82c105 + 0565 W83C553 +10ae Cornerstone Technology +10af Micro Computer Systems Inc +10b0 CardExpert Technology +10b1 Cabletron Systems Inc +10b2 Raytheon Company +10b3 Databook Inc + 3106 DB87144 + b106 DB87144 +10b4 STB Systems Inc + 1b1d Velocity 128 3D + 10b4 237e Velocity 4400 +10b5 PLX Technology, Inc. + 0001 i960 PCI bus interface + 1076 VScom 800 8 port serial adaptor + 1077 VScom 400 4 port serial adaptor + 9036 9036 + 9050 PCI <-> IOBus Bridge + 9060 9060 + 906d 9060SD + 125c 0640 Aries 16000P + 906e 9060ES + 9080 9080 + 10b5 9080 9080 [real subsystem ID not set] +10b6 Madge Networks + 0001 Smart 16/4 Ringnode + 0002 Smart 16/4 BM Mk2 Ringnode + 0003 Smart 16/4 Ringnode + 0e11 b0fd NC4621 4/16 Token-Ring Adapter + WOL + 10b6 0003 Smart 16/4 Ringnode Mk3 + 10b6 0007 Presto Mk2 + 0004 Smart 16/4 Ringnode (BM) + 0006 16/4 Cardbus Adapter + 0007 Presto + 1000 Collage 25 ATM adaptor + 1001 Collage 155 Server +10b7 3Com Corporation + 0001 3c985 1000BaseSX + 3390 Token Link Velocity + 3590 3c359 TokenLink Velocity XL + 5057 3c575 [Megahertz] 10/100 LAN CardBus + 5157 3c575 [Megahertz] 10/100 LAN CardBus + 5900 3c590 10BaseT [Vortex] + 5950 3c595 100BaseTX [Vortex] + 5951 3c595 100BaseT4 [Vortex] + 5952 3c595 100Base-MII [Vortex] + 8811 Token ring + 9000 3c900 10BaseT [Boomerang] + 9001 3c900 Combo [Boomerang] + 9004 3c900B-TPO [Etherlink XL TPO] + 9005 3c900B-Combo [Etherlink XL Combo] + 9006 3c900B-TPC [Etherlink XL TPC] + 900A 3c900B-FL [Etherlink XL FL] + 9050 3c905 100BaseTX [Boomerang] + 9051 3c905 100BaseT4 + 9055 3c905B 100BaseTX [Cyclone] + 9058 3c905B-Combo [Deluxe Etherlink XL 10/100] + 905A 3c905B-FX [Fast Etherlink XL FX 10/100] + 9200 3c905C-TX [Fast Etherlink] + 9800 3c980-TX [Fast Etherlink XL Server Adapter] +10b8 Standard Microsystems Corp [SMC] + 0005 83C170QF + 1055 e000 LANEPIC + 1055 e002 LANEPIC + 10b8 a011 EtherPower II 10/100 + 10b8 a014 EtherPower II 10/100 + 10b8 a015 EtherPower II 10/100 + 10b8 a016 EtherPower II 10/100 + 10b8 a017 EtherPower II 10/100 + 0006 LANEPIC + 1000 FDC 37c665 + 1001 FDC 37C922 + a011 83C170QF + b106 SMC34C90 +10b9 Acer Laboratories Inc. [ALi] + 1435 M1435 + 1445 M1445 + 1449 M1449 + 1451 M1451 + 1461 M1461 + 1489 M1489 + 1511 M1511 [Aladdin] + 1512 M1512 [Aladdin] + 1513 M1513 [Aladdin] + 1521 M1521 [Aladdin III] + 1523 M1523 + 1531 M1531 [Aladdin IV] + 1533 M1533 PCI to ISA Bridge [Aladdin IV] + 1541 M1541 + 1543 M1543 + 1621 M1621 + 3141 M3141 + 3143 M3143 + 3145 M3145 + 3147 M3147 + 3149 M3149 + 3151 M3151 + 3307 M3307 + 3309 M3309 + 5212 M4803 + 5215 MS4803 + 5217 M5217H + 5219 M5219 + 5225 M5225 + 5229 M5229 IDE + 5235 M5225 + 5237 M5237 USB + 5243 M5243 + 5247 M5247 + 7101 M7101 PMU +10ba Mitsubishi Electric Corp. + 0301 AccelGraphics AccelECLIPSE +10bb Dapha Electronics Corporation +10bc Advanced Logic Research +10bd Surecom Technology + 0e34 NE-34 +10be Tseng Labs International Co. +10bf Most Inc +10c0 Boca Research Inc. +10c1 ICM Co., Ltd. +10c2 Auspex Systems Inc. +10c3 Samsung Semiconductors, Inc. + 1100 Smartether100 SC1100 LAN Adapter (i82557B) +10c4 Award Software International Inc. +10c5 Xerox Corporation +10c6 Rambus Inc. +10c7 Media Vision +10c8 Neomagic Corporation + 0001 NM2070 [MagicGraph NM2070] + 0002 NM2090 [MagicGraph 128V] + 0003 NM2093 [MagicGraph 128ZV] + 0004 NM2160 [MagicGraph 128XD] + 0005 [MagicGraph 256AV] + 0006 [MagicGraph 256ZX] + 0083 [MagicGraph 128ZV Plus] + 8005 [MagicMedia 256AV] +10c9 Dataexpert Corporation +10ca Fujitsu Microelectr., Inc. +10cb Omron Corporation +10cc Mentor ARC Inc +10cd Advanced System Products, Inc + 1100 ASC1100 + 1200 ASC1200 [(abp940) Fast SCSI-II] + 1300 ABP940-U / ABP960-U + 2300 ABP940-UW +10ce Radius +10cf Citicorp TTI + 2001 mb86605 +10d0 Fujitsu Limited +10d1 FuturePlus Systems Corp. +10d2 Molex Incorporated +10d3 Jabil Circuit Inc +10d4 Hualon Microelectronics +10d5 Autologic Inc. +10d6 Cetia +10d7 BCM Advanced Research +10d8 Advanced Peripherals Labs +10d9 Macronix, Inc. [MXIC] + 0512 MX98713 + 0531 MX987x5 + 8625 MX86250 + 8888 MX86200 +10da Compaq IPG-Austin + 0508 TC4048 Token Ring 4/16 + 3390 Tl3c3x9 +10db Rohm LSI Systems, Inc. +10dc CERN/ECP/EDU + 0001 STAR/RD24 SCI-PCI (PMC) + 0002 TAR/RD24 SCI-PCI (PMC) [ATT 2C15-3 (FPGA) SCI bridge on PCI 5 Volt card] + 0021 HIPPI destination + 0022 HIPPI source + 10dc ATT2C15-3 FPGA +10dd Evans & Sutherland +10de nVidia Corporation + 0008 NV1 EDGE 3D + 0009 NV1 EDGE 3D + 0020 Riva TNT 128 + 1043 0200 V3400 TNT + 1092 0550 Viper V550 + 1092 0552 Viper V550 + 1102 1015 Graphics Blaster CT6710 + 1092 4804 Viper V550 + 1092 4808 Viper V550 + 1092 4810 Viper V550 + 1092 4812 Viper V550 + 1092 4815 Viper V550 + 1092 4820 Viper V550 with TV out + 1092 4822 Viper V550 + 1092 4904 Viper V550 + 1092 4914 Viper V550 + 1092 8225 Viper V550 + 0028 Riva TNT2 + 1043 0200 AGP-V3800 SGRAM + 1092 4804 Viper V770 + 1092 4a00 Viper V770 + 1092 4a02 Viper V770 Ultra + 1092 6a02 Viper V770 Ultra + 1092 7a02 Viper V770 Ultra + 1102 1020 3D Blaster RIVA TNT2 + 14af 5810 Maxi Gamer Xentor + 0029 Riva TNT2 Ultra + 1043 0200 AGP-V3800 Deluxe + 1102 1021 3D Blaster RIVA TNT2 Ultra + 14af 5820 Maxi Gamer Xentor 32 + 002c Vanta + 1043 0200 AGP-V3800 Combat SDRAM + 1092 6820 Viper V730 + 14af 5008 Maxi Gamer Phoenix 2 + 002d Riva TNT2 Model 64 + 1043 0200 AGP-V3800M + 00a0 Riva TNT2 + 14af 5810 Maxi Gamer Xentor +10df Emulex Corporation + 10df Light Pulse Fibre Channel Adapter + 1ae5 LP6000 Fibre Channel Host Adapter + f700 LP7000 Fibre Channel Host Adapter +10e0 Integrated Micro Solutions Inc. + 5026 IMS5026/27/28 + 5027 IMS5027 + 5028 IMS5028 + 8849 IMS8849 + 8853 IMS8853 + 9128 IMS9129 [Twin turbo 128] +10e1 Tekram Technology Co.,Ltd. + 0391 TRM-S1040 + 690c DC-690c + dc29 DC-290 +10e2 Aptix Corporation +10e3 Tundra Semiconductor Corp. + 0000 CA91C042 [Universe] + 0860 CA91C860 [QSpan] +10e4 Tandem Computers +10e5 Micro Industries Corporation +10e6 Gainbery Computer Products Inc. +10e7 Vadem +10e8 Applied Micro Circuits Corporation + 2011 Q-Motion Video Capture/Edit board + 4750 S5930 [Matchmaker] + 5920 S5920 + 8043 LANai4.x [Myrinet LANai interface chip] + 8062 S5933_PARASTATION + 807d S5933 [Matchmaker] + 8088 Kingsberg Spacetec Format Synchronizer + 8089 Kingsberg Spacetec Serial Output Board + 809c S5933_HEPC3 + 811a PCI-IEEE1355-DS-DE Interface + 8170 S5933 "Matchmaker" PCI Chipset Development Tool +10e9 Alps Electric Co., Ltd. +10ea Intergraphics Systems + 1680 IGA-1680 + 1682 IGA-1682 + 1683 IGA-1683 + 2000 CyberPro 2000 + 2010 CyberPro 2000A +10eb Artists Graphics + 0101 3GA + 8111 Twist3 Frame Grabber +10ec Realtek Semiconductor Co., Ltd. + 8029 RT8029(AS) + 10b8 2011 EZ-Card + 10ec 8029 RT8029(AS) + 1113 1208 EN1208 + 1186 0300 DE-528 + 1259 2400 AT-2400 + 8129 RT8129 + 8139 RT8139 + 1025 8920 ALN-325 + 1025 8921 ALN-325 + 10bd 0320 EP-320X-R + 10ec 8139 RT8139 + 1186 1320 SN5200 + 1259 2500 AT-2500TX + 1429 d010 ND010 + 1432 9130 EN-9130TX + 1436 8139 RT8139 + 146c 1439 FE-1439TX + 1489 6001 GF100TXRII + 1489 6002 GF100TXRA + 149c 139a LFE-8139ATX + 149c 8139 LFE-8139TX + 2646 0001 EtheRx + 8e2e 7000 KF-230TX + 8e2e 7100 KF-230TX/2 +10ed Ascii Corporation + 7310 V7310 +10ee Xilinx, Inc. +10ef Racore Computer Products, Inc. + 8154 M815x Token Ring Adapter +10f0 Peritek Corporation +10f1 Tyan Computer +10f2 Achme Computer, Inc. +10f3 Alaris, Inc. +10f4 S-MOS Systems, Inc. +10f5 NKK Corporation + a001 NDR4000 [NR4600 Bridge] +10f6 Creative Electronic Systems SA +10f7 Matsushita Electric Industrial Co., Ltd. +10f8 Altos India Ltd +10f9 PC Direct +10fa Truevision + 000c TARGA 1000 +10fb Thesys Gesellschaft für Mikroelektronik mbH +10fc I-O Data Device, Inc. +10fd Soyo Computer, Inc +10fe Fast Multimedia AG +10ff NCube +1100 Jazz Multimedia +1101 Initio Corporation + 9100 INI-9100/9100W + 9400 INI-940 + 9401 INI-950 + 9500 360P +1102 Creative Labs + 0002 SB Live! EMU10000 + 1102 0020 CT4850 SBLive! Value + 1102 0021 CT4620 SBLive! + 1102 002f SBLive! mainboard implementation + 1102 8022 CT4780 SBLive! Value + 1102 8024 CT4760 SBLive! + 1102 8026 CT4830 SBLive! Value + 1102 8027 CT4832 SBLive! Value + 1102 8031 CT4831 SBLive! Value + 1102 8040 CT4760 SBLive! + 7002 SB Live! + 1102 0020 Gameport Joystick +1103 Triones Technologies, Inc. + 0003 HPT343 + 0004 HPT366 +1104 RasterOps Corp. +1105 Sigma Designs, Inc. + 8300 REALmagic Hollywood Plus DVD Decoder +1106 VIA Technologies, Inc. + 0501 VT8501 + 0505 VT82C505 + 0561 VT82C561 + 0571 VT82C586 IDE [Apollo] + 0576 VT82C576 3V [Apollo Master] + 0585 VT82C585VP [Apollo VP1/VPX] + 0586 VT82C586/A/B PCI-to-ISA [Apollo VP] + 1106 0000 MVP3 ISA Bridge + 0595 VT82C595 [Apollo VP2] + 0596 VT82C596 ISA [Apollo PRO] + 0597 VT82C597 [Apollo VP3] + 0598 VT82C598 [Apollo MVP3] + 0680 VT82C680 [Apollo P6] + 0686 VT82C686 [Apollo Super] + 0691 VT82C691 [Apollo PRO] + 0693 VT82C693 [Apollo Pro Plus] + 0926 VT82C926 [Amazon] + 1000 VT82C570MV + 1106 VT82C570MV + 1571 VT82C416MV + 1595 VT82C595/97 [Apollo VP2/97] + 3038 VT82C586B USB + 1234 0925 MVP3 USB Controller + 3040 VT82C586B ACPI + 3043 VT86C100A [Rhine 10/100] + 1106 0100 VT86C100A + 1186 1400 DFE-530TX + 3057 VT82C686 [Apollo Super ACPI] + 3058 VT82C686 [Apollo Super AC97/Audio] + 3068 VT82C686 [Apollo Super AC97/Modem] + 5030 VT82C596 ACPI [Apollo PRO] + 6100 VT85C100A [Rhine II] + 8501 VT8501 + 8596 VT82C596 [Apollo PRO AGP] + 8597 VT82C597 [Apollo VP3 AGP] + 8598 VT82C598 [Apollo MVP3 AGP] + 8691 VT82C691 [Apollo Pro] +1107 Stratus Computers + 0576 VIA VT82C570MV [Apollo] (Wrong vendor ID!) +1108 Proteon, Inc. + 0100 p1690plus_AA + 0101 p1690plus_AB + 0105 P1690Plus + 0108 P1690Plus + 0138 P1690Plus + 0139 P1690Plus + 013C P1690Plus + 013D P1690Plus +1109 Cogent Data Technologies, Inc. + 1400 EM110TX [EX110TX] +110a Siemens Nixdorf AG + 0002 Pirahna 2-port + 0005 Tulip controller, power management, switch extender + 4942 FPGA I-Bus Tracer for MBD + 6120 SZB6120 +110b Chromatic Research Inc. + 0001 Mpact Media Processor +110c Mini-Max Technology, Inc. +110d Znyx Advanced Systems +110e CPU Technology +110f Ross Technology +1110 Powerhouse Systems + 6037 Firepower Powerized SMP I/O ASIC + 6073 Firepower Powerized SMP I/O ASIC +1111 Santa Cruz Operation +# DJ- Some people say that 0x1112 is Rockwell International ? +1112 RNS - Div. of Meret Communications Inc + 2200 FDDI Adapter + 2340 4 Port Fast Ethernet Adapter + 2400 ATM Adapter +1113 Accton Technology Corporation + 1211 SMC2-1211TX + 1217 EN-1217 Ethernet Adapter + 5105 10Mbps Network card + 9211 EN-1207D Fast Ethernet Adapter +1114 Atmel Corporation +1115 3D Labs +1116 Data Translation + 0022 DT3001 + 0023 DT3002 + 0024 DT3003 + 0028 DT3003-PGL + 0025 DT3004 + 0026 DT3005 + 0027 DT3001-PGL +1117 Datacube, Inc + 9500 Max-1C SVGA card + 9501 Max-1C image processing +1118 Berg Electronics +1119 ICP Vortex Computersysteme GmbH + 0000 GDT 6000/6020/6050 + 0001 GDT 6000b/6010 + 0002 GDT 6110/6510 + 0003 GDT 6120/6520 + 0004 GDT 6530 + 0005 GDT 6550 + 0006 GDT 6x17 + 0007 GDT 6x27 + 0008 GDT 6537 + 0009 GDT 5557 + 000a GDT 6x15 + 000b GDT 6x25 + 000c GDT 6535 + 000d GDT 6555 + 0100 GDT 6117RP/6517RP + 0101 GDT 6127RP/6527RP + 0102 GDT 6537RP + 0103 GDT 6557RP + 0104 GDT 6111RP/6511RP + 0105 GDT 6121RP/6521RP + 0110 GDT 6117RP1/6517RP1 + 0111 GDT 6127RP1/6527RP1 + 0112 GDT 6537RP1 + 0113 GDT 6557RP1 + 0114 GDT 6111RP1/6511RP1 + 0115 GDT 6121RP1/6521RP1 + 0118 GDT 6x18RD + 0119 GDT 6x28RD + 011A GDT 6x38RD + 011B GDT 6x58RD + 0120 GDT 6117RP2/6517RP2 + 0121 GDT 6127RP2/6527RP2 + 0122 GDT 6537RP2 + 0123 GDT 6557RP2 + 0124 GDT 6111RP2/6511RP2 + 0125 GDT 6121RP2/6521RP2 + 0168 GDT 7x18RN + 0169 GDT 7x28RN + 016A GDT 7x38RN + 016B GDT 7x58RN + 0210 GDT 6x19RD + 0211 GDT 6x29RD + 0260 GDT 7x19RN + 0261 GDT 7x29RN +111a Efficient Networks, Inc + 0000 155P-MF1 (FPGA) + 0002 155P-MF1 (ASIC) + 0003 ENI-25P ATM Adapter + 0005 ENI-25P ATM Adapter +111b Teledyne Electronic Systems +111c Tricord Systems Inc. + 0001 Powerbis Bridge +111d Integrated Device Tech + 0001 IDT77211 ATM Adapter +111e Eldec +111f Precision Digital Images + 4a47 Precision MX Video engine interface + 5243 Frame capture bus interface +1120 EMC Corporation +1121 Zilog +1122 Multi-tech Systems, Inc. +1123 Excellent Design, Inc. +1124 Leutron Vision AG +1125 Eurocore +1127 FORE Systems Inc + 0200 ForeRunner PCA-200 ATM + 0210 PCA-200PC + 0250 ATM + 0300 PCA-200E + 0310 ATM + 0400 ForeRunnerHE ATM Adapter +1129 Firmworks +112a Hermes Electronics Company, Ltd. +112b Linotype - Hell AG +112c Zenith Data Systems +112d Ravicad +112e Infomedia Microelectronics Inc. +112f Imaging Technology Inc + 0000 MVC IC-PCI + 0001 Video frame grabber/processor +1130 Computervision +1131 Philips Semiconductors + 7145 SAA7145 + 7146 SAA7146 +1132 Mitel Corp. +1133 Eicon Technology Corporation + 7901 EiconCard S90 + 7902 EiconCard S90 + 7911 EiconCard S91 + 7912 EiconCard S91 + 7941 EiconCard S94 + 7942 EiconCard S94 + b921 EiconCard P92 + b922 EiconCard P92 + e001 DIVA 20PRO + e002 DIVA 20 + e003 DIVA 20PRO_U + e004 DIVA 20_U + e010 DIVA Server BRI-2M + e014 DIVA Server PRO-30M +1134 Mercury Computer Systems + 0001 Raceway Bridge +1135 Fuji Xerox Co Ltd + 0001 Printer controller +1136 Momentum Data Systems +1137 Cisco Systems Inc +1138 Ziatech Corporation + 8905 8905 [STD 32 Bridge] +1139 Dynamic Pictures, Inc +113a FWB Inc +113b Network Computing Devices +113c Cyclone Microsystems, Inc. + 0000 PCI-9060 i960 Bridge + 0001 PCI-SDK [PCI i960 Evaluation Platform] + 0911 PCI-911 [PCI-based i960Jx Intelligent I/O Controller] + 0912 PCI-912 [i960CF-based Intelligent I/O Controller] + 0913 PCI-913 + 0914 PCI-914 [I/O Controller w/ secondary PCI bus] +113d Leading Edge Products Inc +113e Sanyo Electric Co - Computer Engineering Dept +113f Equinox Systems, Inc. + 0808 SST-64P Adapter + 1010 SST-128P Adapter + 80C0 SST-16P Adapter + 80C4 SST-16P Adapter + 80C8 SST-16P Adapter + 8888 SST-4P Adapter + 9090 SST-8P Adapter +1140 Intervoice Inc +1141 Crest Microsystem Inc +1142 Alliance Semiconductor Corporation + 3210 AP6410 + 6422 ProVideo 6422 + 6424 ProVideo 6424 + 6425 ProMotion AT25 + 643d ProMotion AT3D +1143 NetPower, Inc +1144 Cincinnati Milacron + 0001 Noservo controller +1145 Workbit Corporation +1146 Force Computers +1147 Interface Corp +1148 Syskonnect (Schneider & Koch) + 4000 FDDI Adapter + 0e11 b03b Netelligent 100 FDDI DAS Fibre SC + 0e11 b03c Netelligent 100 FDDI SAS Fibre SC + 0e11 b03d Netelligent 100 FDDI DAS UTP + 0e11 b03e Netelligent 100 FDDI SAS UTP + 0e11 b03f Netelligent 100 FDDI SAS Fibre MIC + 1148 5521 FDDI SK-5521 (SK-NET FDDI-UP) + 1148 5522 FDDI SK-5522 (SK-NET FDDI-UP DAS) + 1148 5541 FDDI SK-5541 (SK-NET FDDI-FP) + 1148 5543 FDDI SK-5543 (SK-NET FDDI-LP) + 1148 5544 FDDI SK-5544 (SK-NET FDDI-LP DAS) + 1148 5821 FDDI SK-5821 (SK-NET FDDI-UP64) + 1148 5822 FDDI SK-5822 (SK-NET FDDI-UP64 DAS) + 1148 5841 FDDI SK-5841 (SK-NET FDDI-FP64) + 1148 5843 FDDI SK-5843 (SK-NET FDDI-LP64) + 1148 5844 FDDI SK-5844 (SK-NET FDDI-LP64 DAS) + 4200 Token ring adaptor + 4300 GE +1149 Win System Corporation +114a VMIC + 7587 VMIVME-7587 +114b Canopus Co., Ltd +114c Annabooks +114d IC Corporation +114e Nikon Systems Inc +114f Digi International + 0002 AccelePort EPC + 0003 RightSwitch SE-6 + 0004 AccelePort Xem + 0005 AccelePort Xr + 0006 AccelePort Xr,C/X + 0009 AccelePort Xr/J + 000a AccelePort EPC/J + 000C DataFirePRIme T1 (1-port) + 000D SyncPort 2-Port (x.25/FR) + 0011 AccelePort 8r EIA-232 (IBM) + 0012 AccelePort 8r EIA-422 + 0013 AccelePort Xr + 0014 AccelePort 8r EIA-422 + 0015 AccelePort Xem + 0016 AccelePort EPC/X + 0017 AccelePort C/X + 001A DataFirePRIme E1 (1-port) + 001B AccelePort C/X (IBM) + 001D DataFire RAS T1/E1/PRI + 0023 AccelePort RAS + 0024 DataFire RAS B4 ST/U + 0026 AccelePort 4r 920 + 0027 AccelePort Xr 920 + 0034 AccelePort 2r 920 + 0035 DataFire DSP T1/E1/PRI cPCI + 6001 Avanstar +1150 Thinking Machines Corp +1151 JAE Electronics Inc. +1152 Megatek +1153 Land Win Electronic Corp +1154 Melco Inc +1155 Pine Technology Ltd +1156 Periscope Engineering +1157 Avsys Corporation +1158 Voarx R & D Inc + 3011 Tokenet/vg 1001/10m anylan + 9050 Lanfleet/Truevalue + 9051 Lanfleet/Truevalue +1159 Mutech Corp + 0001 MV-1000 +115a Harlequin Ltd +115b Parallax Graphics +115c Photron Ltd. +115d Xircom + 0003 Cardbus Ethernet 10/100 + 1014 0181 10/100 EtherJet Cardbus Adapter + 1014 1181 10/100 EtherJet Cardbus Adapter + 115d 0181 Cardbus Ethernet 10/100 + 115d 1181 Cardbus Ethernet 10/100 + 8086 8181 EtherExpress PRO/100 Mobile CardBus 32 Adapter + 8086 9181 EtherExpress PRO/100 Mobile CardBus 32 Adapter + 0005 Cardbus Ethernet 10/100 + 1014 0182 10/100 EtherJet Cardbus Adapter + 1014 1182 10/100 EtherJet Cardbus Adapter + 115d 0182 Cardbus Ethernet 10/100 + 115d 1182 Cardbus Ethernet 10/100 + 0007 Cardbus Ethernet 10/100 + 1014 0182 10/100 EtherJet Cardbus Adapter + 1014 1182 10/100 EtherJet Cardbus Adapter + 115d 0182 Cardbus Ethernet 10/100 + 115d 1182 Cardbus Ethernet 10/100 + 000b Cardbus Ethernet 10/100 + 1014 0183 10/100 EtherJet Cardbus Adapter + 115d 0183 Cardbus Ethernet 10/100 + 000f Cardbus Ethernet 10/100 + 1014 0183 10/100 EtherJet Cardbus Adapter + 115d 0183 Cardbus Ethernet 10/100 + 0101 Cardbus 56k modem + 0103 Cardbus Ethernet + 56k Modem + 115d 1181 CBEM56G-100 Ethernet + 56k Modem + 8086 9181 PRO/100 LAN + Modem56 CardBus +115e Peer Protocols Inc +115f Maxtor Corporation +1160 Megasoft Inc +1161 PFU Limited +1162 OA Laboratory Co Ltd +1163 Rendition + 0001 Verite 1000 + 2000 Verite V2000/V2100/V2200 +1164 Advanced Peripherals Technologies +1165 Imagraph Corporation + 0001 Motion TPEG Recorder/Player with audio +1166 Relience Computer + 0008 CNB20HE + 0009 CNB20HE +1167 Mutoh Industries Inc +1168 Thine Electronics Inc +1169 Centre for Development of Advanced Computing +116a Polaris Communications + 6100 Bus/Tag Channel + 6800 Escon Channel + 7100 Bus/Tag Channel + 7800 Escon Channel +116b Connectware Inc +116c Intelligent Resources Integrated Systems +116d Martin-Marietta +116e Electronics for Imaging +116f Workstation Technology +1170 Inventec Corporation +1171 Loughborough Sound Images Plc +1172 Altera Corporation +1173 Adobe Systems, Inc +1174 Bridgeport Machines +1175 Mitron Computer Inc. +1176 SBE Incorporated +1177 Silicon Engineering +1178 Alfa, Inc. +1179 Toshiba America Info Systems + 0404 DVD Decoder card + 0406 Tecra Video Capture device + 0407 DVD Decoder card (Version 2) + 0601 601 + 0603 ToPIC95 PCI to CardBus Bridge for Notebooks + 060a ToPIC95 + 060f ToPIC97 + 0701 FIR Port +# This is apparently incorrect. Does anyone know the correct ID? +# 0701 Lucent DSP1645 [Mars] +117b L G Electronics, Inc. +117c Atto Technology +117d Becton & Dickinson +117e T/R Systems +117f Integrated Circuit Systems +1180 Ricoh Co Ltd + 0465 RL5c465 + 0466 RL5c466 + 0475 RL5c475 + 0476 RL5c476 II + 0477 RL5c477 + 0478 RL5c478 +1181 Telmatics International +1183 Fujikura Ltd +1184 Forks Inc +1185 Dataworld International Ltd +1186 D-Link System Inc + 0100 DC21041 +1187 Advanced Technology Laboratories, Inc. +1188 Shima Seiki Manufacturing Ltd. +1189 Matsushita Electronics Co Ltd +118a Hilevel Technology +118b Hypertec Pty Limited +118c Corollary, Inc + 0014 PCIB [C-bus II to PCI bus host bridge chip] +118d BitFlow Inc + 0001 Raptor-PCI framegrabber + 0012 Model 12 Road Runner Frame Grabber + 0014 Model 14 Road Runner Frame Grabber + 0024 Model 24 Road Runner Frame Grabber + 0044 Model 44 Road Runner Frame Grabber + 0112 Model 12 Road Runner Frame Grabber + 0114 Model 14 Road Runner Frame Grabber + 0124 Model 24 Road Runner Frame Grabber + 0144 Model 44 Road Runner Frame Grabber + 0212 Model 12 Road Runner Frame Grabber + 0214 Model 14 Road Runner Frame Grabber + 0224 Model 24 Road Runner Frame Grabber + 0244 Model 44 Road Runner Frame Grabber + 0312 Model 12 Road Runner Frame Grabber + 0314 Model 14 Road Runner Frame Grabber + 0324 Model 24 Road Runner Frame Grabber + 0344 Model 44 Road Runner Frame Grabber +118e Hermstedt GmbH +118f Green Logic +1190 Tripace +1191 Artop Electronic Corp + 0004 ATP8400 + 0005 ATP850UF + 8002 AEC6710 SCSI-2 Host Adapter + 8010 AEC6712UW SCSI + 8020 AEC6712U SCSI + 8030 AEC6712S SCSI + 8040 AEC6712D SCSI + 8050 AEC6712SUW SCSI +1192 Densan Company Ltd +1193 Zeitnet Inc. + 0001 1221 + 0002 1225 +1194 Toucan Technology +1195 Ratoc System Inc +1196 Hytec Electronics Ltd +1197 Gage Applied Sciences, Inc. +1198 Lambda Systems Inc +1199 Attachmate Corporation +119a Mind Share, Inc. +119b Omega Micro Inc. + 1221 82C092G +119c Information Technology Inst. +119d Bug, Inc. Sapporo Japan +119e Fujitsu Microelectronics Ltd. +119f Bull HN Information Systems +11a0 Convex Computer Corporation +11a1 Hamamatsu Photonics K.K. +11a2 Sierra Research and Technology +11a3 Deuretzbacher GmbH & Co. Eng. KG +11a4 Barco Graphics NV +11a5 Microunity Systems Eng. Inc +11a6 Pure Data Ltd. +11a7 Power Computing Corp. +11a8 Systech Corp. +11a9 InnoSys Inc. + 4240 AMCC S933Q Intelligent Serial Card +11aa Actel +11ab Galileo Technology Ltd. + 0146 GT-64010 + 4801 GT-48001 + f003 GT-64010 Primary Image Piranha Image Generator +11ac Canon Information Systems Research Aust. +11ad Lite-On Communications Inc + 0002 LNE100TX + 11ad 0002 LNE100TX + 11ad 0003 LNE100TX + 11ad f003 LNE100TX + 11ad ffff LNE100TX + 1385 f004 FA310TX +11ae Aztech System Ltd +11af Avid Technology Inc. +11b0 V3 Semiconductor Inc. + 0292 V292PBC [Am29030/40 Bridge] + 0960 V96xPBC + c960 V96DPC +11b1 Apricot Computers +11b2 Eastman Kodak +11b3 Barr Systems Inc. +11b4 Leitch Technology International +11b5 Radstone Technology Plc +11b6 United Video Corp +11b8 XPoint Technologies, Inc + 0001 Quad PeerMaster +11b9 Pathlight Technology Inc. + c0ed SSA Controller +11ba Videotron Corp +11bb Pyramid Technology +11bc Network Peripherals Inc + 0001 NP-PCI +11bd Pinnacle Systems Inc. +11be International Microcircuits Inc +11bf Astrodesign, Inc. +11c0 Hewlett Packard +11c1 Lucent Microelectronics + 0440 56k WinModem + 0001 0440 LT WinModem 56k Data+Fax+Voice+Dsvd + 1033 8015 LT WinModem 56k Data+Fax+Voice+Dsvd + 1033 804f LT WinModem 56k Data+Fax+Voice+Dsvd + 10cf 102c LB LT Modem V.90 56k + 10cf 104a BIBLO LT Modem 56k + 10cf 105f LB2 LT Modem V.90 56k + 1179 0001 Internal V.90 Modem + 11c1 0440 LT WinModem 56k Data+Fax+Voice+Dsvd + 122d 4101 MDP7800-U Modem + 13e0 0040 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 0440 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 0441 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 f100 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 f101 LT WinModem 56k Data+Fax+Voice+Dsvd + 144d 2101 LT56PV Modem + 149f 0440 LT WinModem 56k Data+Fax+Voice+Dsvd + 0441 56k WinModem + 1033 804d LT WinModem 56k Data+Fax + 1092 0440 Supra 56i + 1179 0001 Internal V.90 Modem + 11c1 0440 LT WinModem 56k Data+Fax + 11c1 0441 LT WinModem 56k Data+Fax + 122d 4100 MDP7800-U Modem + 13e0 0040 LT WinModem 56k Data+Fax + 13e0 0100 LT WinModem 56k Data+Fax + 13e0 0410 LT WinModem 56k Data+Fax + 13e0 0420 TelePath Internet 56k WinModem + 13e0 0443 LT WinModem 56k Data+Fax + 1416 9804 CommWave 56k Modem + 141d 0440 LT WinModem 56k Data+Fax + 144f 0441 Lucent 56k V.90 DF Modem + 1468 0441 Presario 56k V.90 DF Modem + 0442 56k WinModem + 0001 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 11c1 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 11c1 0442 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 13e0 0412 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 13e0 0442 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 13fc 2471 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 144d 2104 LT56PT Modem + 149f 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 1668 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 0448 WinModem 56k + 13e0 0040 LT WinModem 56k Data+Fax+Voice+Dsvd + 0449 WinModem 56k + 0e11 b14d 56k V.90 Modem + 13e0 0020 LT WinModem 56k Data+Fax + 13e0 0041 TelePath Internet 56k WinModem + 144f 0449 Lucent 56k V.90 DFi Modem + 1468 0449 Presario 56k V.90 DFi Modem + 044A F-1156IV WinModem (V90, 56KFlex) + 13e0 0012 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 13e0 0042 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 144f 1005 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 0480 Venus WinModem (V90, 56KFlex) +11c2 Sand Microelectronics +11c4 Document Technologies, Inc +11c5 Shiva Corporation +11c6 Dainippon Screen Mfg. Co. Ltd +11c7 D.C.M. Data Systems +11c8 Dolphin Interconnect Solutions AS + 0658 PSB32 SCI-Adapter D31x + d665 PSB64 SCI-Adapter D32x + d667 PSB66 SCI-Adapter D33x +11c9 Magma + 0010 16-line serial port w/- DMA + 0011 4-line serial port w/- DMA +11ca LSI Systems, Inc +11cb Specialix Research Ltd. + 2000 PCI_9050 + 11cb 0200 SX + 11cb b008 I/O8+ + 4000 SUPI_1 + 8000 T225 +11cc Michels & Kleberhoff Computer GmbH +11cd HAL Computer Systems, Inc. +11ce Netaccess +11cf Pioneer Electronic Corporation +11d0 Lockheed Martin Federal Systems-Manassas +11d1 Auravision + 01f7 VxP524 +11d2 Intercom Inc. +11d3 Trancell Systems Inc +11d4 Analog Devices +11d5 Ikon Corporation + 0115 10115 + 0117 10117 +11d6 Tekelec Telecom +11d7 Trenton Technology, Inc. +11d8 Image Technologies Development +11d9 TEC Corporation +11da Novell +11db Sega Enterprises Ltd +11dc Questra Corporation +11dd Crosfield Electronics Limited +11de Zoran Corporation + 6057 ZR36057PQC Video cutting chipset + 1031 7efe DC10 Plus + 1031 fc00 MiroVIDEO DC50, Motion JPEG Capture/CODEC Board + 13ca 4231 JPEG/TV Card + 6120 ZR36120 + 1328 f001 Cinemaster C DVD Decoder +11df New Wave PDG +11e0 Cray Communications A/S +11e1 GEC Plessey Semi Inc. +11e2 Samsung Information Systems America +11e3 Quicklogic Corporation +11e4 Second Wave Inc +11e5 IIX Consulting +11e6 Mitsui-Zosen System Research +11e7 Toshiba America, Elec. Company +11e8 Digital Processing Systems Inc. +11e9 Highwater Designs Ltd. +11ea Elsag Bailey +11eb Formation Inc. +11ec Coreco Inc +11ed Mediamatics +11ee Dome Imaging Systems Inc +11ef Nicolet Technologies B.V. +11f0 Compu-Shack + 4231 FDDI + 4232 FASTline UTP Quattro + 4233 FASTline FO + 4234 FASTline UTP + 4235 FASTline-II UTP + 4236 FASTline-II FO + 4731 GIGAline +11f1 Symbios Logic Inc +11f2 Picture Tel Japan K.K. +11f3 Keithley Metrabyte +11f4 Kinetic Systems Corporation + 2915 CAMAC controller +11f5 Computing Devices International +11f6 Compex + 0112 ENet100VG4 + 1401 ReadyLink 2000 + 2011 RL100-ATX 10/100 + 2201 ReadyLink 100TX (Winbond W89C840) + 9881 RL100TX +11f7 Scientific Atlanta +11f8 PMC-Sierra Inc. + 7375 PM7375 [LASAR-155 ATM SAR] +11f9 I-Cube Inc +11fa Kasan Electronics Company, Ltd. +11fb Datel Inc +11fc Silicon Magic +11fd High Street Consultants +11fe Comtrol Corporation + 0001 RocketPort 8 Oct + 0002 RocketPort 8 Intf + 0003 RocketPort 16 Intf + 0004 RocketPort 32 Intf + 0005 RocketPort Octacable + 0006 RocketPort 8J + 0008 RocketPort 8-port + 0009 RocketPort 16-port + 000A RocketPort Plus Quadcable + 000B RocketPort Plus Octacable + 000C RocketPort 8-port Modem +11ff Scion Corporation +1200 CSS Corporation +1201 Vista Controls Corp +1202 Network General Corp. +1203 Bayer Corporation, Agfa Division +1204 Lattice Semiconductor Corporation +1205 Array Corporation +1206 Amdahl Corporation +1208 Parsytec GmbH + 4853 HS-Link Device +1209 SCI Systems Inc +120a Synaptel +120b Adaptive Solutions +120c Technical Corp. +120d Compression Labs, Inc. +120e Cyclades Corporation + 0100 Cyclom_Y below first megabyte + 0101 Cyclom_Y above first megabyte + 0102 Cyclom_4Y below first megabyte + 0103 Cyclom_4Y above first megabyte + 0104 Cyclom_8Y below first megabyte + 0105 Cyclom_8Y above first megabyte + 0200 Cyclom_Z below first megabyte + 0201 Cyclom_Z above first megabyte +120f Essential Communications + 0001 Roadrunner serial HIPPI +1210 Hyperparallel Technologies +1211 Braintech Inc +1212 Kingston Technology Corp. +1213 Applied Intelligent Systems, Inc. +1214 Performance Technologies, Inc. +1215 Interware Co., Ltd +1216 Purup Prepress A/S +1217 O2 Micro, Inc. + 6729 6729 + 673a 6730 + 6832 6832 + 6836 6836 +1218 Hybricon Corp. +1219 First Virtual Corporation +121a 3Dfx Interactive, Inc. + 0001 Voodoo + 0002 Voodoo 2 + 0003 Voodoo Banshee + 1092 0003 Monster Fusion + 1092 4000 Monster Fusion + 1092 4002 Monster Fusion + 1092 4801 Monster Fusion AGP + 1092 4803 Monster Fusion AGP + 1092 8030 Monster Fusion + 1092 8035 Monster Fusion AGP + 121a 0001 Voodoo Banshee AGP + 121a 0003 Voodoo Banshee AGP SGRAM + 121a 0004 Voodoo Banshee + 3030 3030 Skywell Magic TwinPower + 0005 Voodoo 3 + 121a 0004 Voodoo3 AGP + 121a 0030 Voodoo3 AGP + 121a 0031 Voodoo3 AGP + 121a 0034 Voodoo3 AGP + 121a 0036 Voodoo3 + 121a 0037 Voodoo3 AGP + 121a 0038 Voodoo3 AGP + 121a 003a Voodoo3 AGP + 121a 0044 Voodoo3 + 121a 004b Velocity 100 + 121a 004c Velocity 200 + 121a 004d Voodoo3 AGP + 121a 004e Voodoo3 AGP + 121a 0051 Voodoo3 AGP + 121a 0052 Voodoo3 AGP + 121a 0060 Voodoo3 3500 TV (NTSC) + 121a 0061 Voodoo3 3500 TV (PAL) + 121a 0062 Voodoo3 3500 TV (SECAM) +121b Advanced Telecommunications Modules +121c Nippon Texaco., Ltd +121d Lippert Automationstechnik GmbH +121e CSPI +121f Arcus Technology, Inc. +1220 Ariel Corporation + 1220 AMCC 5933 TMS320C80 DSP/Imaging board +1221 Contec Co., Ltd +1222 Ancor Communications, Inc. +1223 Heurikon/Computer Products +1224 Interactive Images +1225 Power I/O, Inc. +1227 Tech-Source +1228 Norsk Elektro Optikk A/S +1229 Data Kinesis Inc. +122a Integrated Telecom +122b LG Industrial Systems Co., Ltd +122c Sican GmbH +122d Aztech System Ltd + 1206 368DSP + 50dc 3328 Audio + 80da 3328 Audio +122e Xyratex +122f Andrew Corporation +1230 Fishcamp Engineering +1231 Woodward McCoach, Inc. +1232 GPT Limited +1233 Bus-Tech, Inc. +1234 Technical Corp. +1235 Risq Modular Systems, Inc. +1236 Sigma Designs Corporation + 0000 RealMagic64/GX + 6401 REALmagic 64/GX (SD 6425) +1237 Alta Technology Corporation +1238 Adtran +1239 3DO Company +123a Visicom Laboratories, Inc. +123b Seeq Technology, Inc. +123c Century Systems, Inc. +123d Engineering Design Team, Inc. + 0000 EasyConnect 8/32 + 0002 EasyConnect 8/64 + 0003 EasyIO +123e Simutech, Inc. +123f C-Cube Microsystems + 00e4 MPEG + 8888 Cinemaster C 3.0 DVD Decoder +1240 Marathon Technologies Corp. +1241 DSC Communications +1243 Delphax +1244 AVM Audiovisuelles MKTG & Computer System GmbH + 0700 B1 ISDN + 0a00 A1 ISDN [Fritz] +1245 A.P.D., S.A. +1246 Dipix Technologies, Inc. +1247 Xylon Research, Inc. +1248 Central Data Corporation +1249 Samsung Electronics Co., Ltd. +124a AEG Electrocom GmbH +124b SBS/Greenspring Modular I/O +124c Solitron Technologies, Inc. +124d Stallion Technologies, Inc. + 0000 EasyConnection 8/32 + 0002 EasyConnection 8/64 + 0003 EasyIO +124e Cylink +124f Infotrend Technology, Inc. + 0041 IFT-2000 Series RAID Controller +1250 Hitachi Microcomputer System Ltd +1251 VLSI Solutions Oy +1253 Guzik Technical Enterprises +1254 Linear Systems Ltd. +1255 Optibase Ltd + 1110 MPEG Forge + 1210 MPEG Fusion + 2110 VideoPlex + 2120 VideoPlex CC + 2130 VideoQuest +1256 Perceptive Solutions, Inc. +1257 Vertex Networks, Inc. +1258 Gilbarco, Inc. +1259 Allied Telesyn International + 2560 AT-2560 Fast Ethernet Adapter (i82557B) +125a ABB Power Systems +125b Asix Electronics Corporation +125c Aurora Technologies, Inc. +125d ESS Technology + 0000 ES336H Fax Modem (Early Model) + 1948 Solo? + 1968 ES1968 Maestro 2 + 1969 ES1969 Solo-1 Audiodrive + 1978 ES1978 Maestro Audiodrive + 2808 ES336H Fax Modem (Later Model) + 2898 ES2898 Modem +125e Specialvideo Engineering SRL +125f Concurrent Technologies, Inc. +1260 Harris Semiconductor + 8130 HMP8130 NTSC/PAL Video Decoder + 8131 HMP8131 NTSC/PAL Video Decoder +1261 Matsushita-Kotobuki Electronics Industries, Ltd. +1262 ES Computer Company, Ltd. +1263 Sonic Solutions +1264 Aval Nagasaki Corporation +1265 Casio Computer Co., Ltd. +1266 Microdyne Corporation + 0001 NE10/100 Adapter (i82557B) + 1910 NE2000Plus (RT8029) Ethernet Adapter +1267 S. A. Telecommunications + 5352 PCR2101 + 5a4b Telsat Turbo +1268 Tektronix +1269 Thomson-CSF/TTM +126a Lexmark International, Inc. +126b Adax, Inc. +126c Northern Telecom +126d Splash Technology, Inc. +126e Sumitomo Metal Industries, Ltd. +126f Silicon Motion, Inc. + 0910 SM910 +1270 Olympus Optical Co., Ltd. +1271 GW Instruments +1272 Telematics International +1273 Hughes Network Systems + 0002 DirecPC +1274 Ensoniq + 1371 ES1371 [AudioPCI-97] + 5000 ES1370 [AudioPCI] +1275 Network Appliance Corporation +1276 Switched Network Technologies, Inc. +1277 Comstream +1278 Transtech Parallel Systems Ltd. +1279 Transmeta Corporation +127a Rockwell International + 1002 HCF 56k V90 FaxModem + 1003 HCF 56k V90 FaxModem + 1004 HCF 56k V90 FaxModem + 1005 HCF 56k V90 FaxModem + 122d 4008 MDP3858SP-A SVD Modem + 127a 1005 PCI56RVP Modem + 13df 1005 PCI56RVP Modem + 1436 1005 WS-5614PS3G + 8234 RapidFire 616X ATM155 Adapter +127b Pixera Corporation +127c Crosspoint Solutions, Inc. +127d Vela Research +127e Winnov, L.P. +127f Fujifilm +1280 Photoscript Group Ltd. +1281 Yokogawa Electric Corporation +1282 Davicom Semiconductor, Inc. +1283 Integrated Technology Express, Inc. + 673a IT8330G + 8330 IT8330G + e886 IT8330G +1284 Sahara Networks, Inc. +1285 Platform Technologies, Inc. + 0100 PT-201C-O-P AGOGO-XP sound chip +1286 Mazet GmbH +1287 M-Pact, Inc. + 001e LS220D DVD Decoder + 001f LS220C DVD Decoder +1288 Timestep Corporation +1289 AVC Technology, Inc. +128a Asante Technologies, Inc. +128b Transwitch Corporation +128c Retix Corporation +128d G2 Networks, Inc. + 0021 ATM155 Adapter +128e Hoontech Corporation/Samho Multi Tech Ltd. + 0008 ST128 WSS/SB + 0009 ST128 SAM9407 + 000a ST128 Game Port + 000b ST128 MPU Port + 000c ST128 Ctrl Port +128f Tateno Dennou, Inc. +1290 Sord Computer Corporation +1291 NCS Computer Italia +1292 Tritech Microelectronics Inc +1293 Media Reality Technology +1294 Rhetorex, Inc. +1295 Imagenation Corporation +1296 Kofax Image Products +1297 Holco Enterprise Co, Ltd/Shuttle Computer +1298 Spellcaster Telecommunications Inc. +1299 Knowledge Technology Lab. +129a VMetro, inc. +129b Image Access +129c Jaycor +129d Compcore Multimedia, Inc. +129e Victor Company of Japan, Ltd. +129f OEC Medical Systems, Inc. +12a0 Allen-Bradley Company +12a1 Simpact Associates, Inc. +12a2 Newgen Systems Corporation +12a3 Lucent Technologies +12a4 NTT Electronics Technology Company +12a5 Vision Dynamics Ltd. +12a6 Scalable Networks, Inc. +12a7 AMO GmbH +12a8 News Datacom +12a9 Xiotech Corporation +12aa SDL Communications, Inc. +12ab Yuan Yuan Enterprise Co., Ltd. +12ac Measurex Corporation +12ad Multidata GmbH +12ae Alteon Networks Inc. + 0001 AceNIC Gigabit Ethernet +12af TDK USA Corp +12b0 Jorge Scientific Corp +12b1 GammaLink +12b2 General Signal Networks +12b3 Inter-Face Co Ltd +12b4 FutureTel Inc +12b5 Granite Systems Inc. +12b6 Natural Microsystems +12b7 Cognex Modular Vision Systems Div. - Acumen Inc. +12b8 Korg +12b9 US Robotics/3Com + 1006 WinModem +12ba PMC Sierra +12bb Nippon Unisoft Corporation +12bc Array Microsystems +12bd Computerm Corp. +12be Anchor Chips Inc. + 3041 AN3041Q CO-MEM + 3042 AN3042Q CO-MEM Lite +12bf Fujifilm Microdevices +12c0 Infimed +12c1 GMM Research Corp +12c2 Mentec Limited +12c3 Holtek Microelectronics Inc +12c4 Connect Tech Inc +12c5 Picture Elements Incorporated + 0081 PCIVST [Grayscale Thresholding Engine] +12c6 Mitani Corporation +12c7 Dialogic Corp +12c8 G Force Co, Ltd +12c9 Gigi Operations +12ca Integrated Computing Engines +12cb Antex Electronics Corporation +12cc Pluto Technologies International +12cd Aims Lab +12ce Netspeed Inc. +12cf Prophet Systems, Inc. +12d0 GDE Systems, Inc. +12d1 PSITech +12d2 NVidia / SGS Thomson (Joint Venture) + 0008 NV1 + 0009 DAC64 + 0018 Riva128 + 107b 8030 STB Velocity 128 + 1092 0350 Viper V330 + 1092 1092 Viper V330 + 10b4 1b1b STB Velocity 128 + 10b4 1b20 STB Velocity 128 + 10b4 1b21 STB Velocity 128 + 10b4 1b22 STB Velocity 128 AGP, NTSC TV-Out + 10b4 1b23 STB Velocity 128 AGP, PAL TV-Out + 10b4 1b27 STB Velocity 128 DVD + 10b4 222a STB Velocity 128 AGP + 10b4 2230 STB Velocity 128 + 10b4 2235 STB Velocity 128 AGP + 0019 Riva128ZX + 0020 TNT + 0028 TNT2 + 0029 UTNT2 + 002C VTNT2 + 00A0 ITNT2 +12d3 Vingmed Sound A/S +12d4 DGM&S +12d5 Equator Technologies +12d6 Analogic Corp +12d7 Biotronic SRL +12d8 Pericom Semiconductor +12d9 Aculab PLC +12da True Time Inc. +12db Annapolis Micro Systems, Inc +12dc Symicron Computer Communication Ltd. +12dd Management Graphics +12de Rainbow Technologies +12df SBS Technologies Inc +12e0 Chase Research + 0010 ST16C654 Quad UART + 0020 ST16C654 Quad UART + 0030 ST16C654 Quad UART +12e1 Nintendo Co, Ltd +12e2 Datum Inc. Bancomm-Timing Division +12e3 Imation Corp - Medical Imaging Systems +12e4 Brooktrout Technology Inc +12e5 Apex Semiconductor Inc +12e6 Cirel Systems +12e7 Sunsgroup Corporation +12e8 Crisc Corp +12e9 GE Spacenet +12ea Zuken +12eb Aureal Semiconductor + 0001 Vortex 1 + 0002 Vortex 2 +12ec 3A International, Inc. +12ed Optivision Inc. +12ee Orange Micro +12ef Vienna Systems +12f0 Pentek +12f1 Sorenson Vision Inc +12f2 Gammagraphx, Inc. +12f3 Radstone Technology +12f4 Megatel +12f5 Forks +12f6 Dawson France +12f7 Cognex +12f8 Electronic Design GmbH + 0002 VideoMaker +12f9 Four Fold Ltd +12fb Spectrum Signal Processing +12fc Capital Equipment Corp +12fd I2S +12fe ESD Electronic System Design GmbH +12ff Lexicon +1300 Harman International Industries Inc +1302 Computer Sciences Corp +1303 Innovative Integration +1304 Juniper Networks +1305 Netphone, Inc +1306 Duet Technologies +1307 Computer Boards + 0001 PCI-DAS1602/16 + 000C PCI-PDISO8 + 000D PCI-PDISO16 + 000B PCI-DIO48H + 000F PCI-DAS1200 + 0010 PCI-DAS1602/12 + 0014 PCI-DIO24H + 0015 PCI-DIO24H/CTR3 + 0016 PCI-DIO48H/CTR15 + 0017 PCI-DIO96H + 0018 PCI-CTR05 + 0019 PCI-DAS1200/JR + 001A PCI-DAS1001 + 001B PCI-DAS1002 + 001C PCI-DAS1602JR/16 + 001D PCI-DAS6402/16 + 001E PCI-DAS6402/12 + 001F PCI-DAS16/M1 + 0020 PCI-DDA02/12 + 0021 PCI-DDA04/12 + 0022 PCI-DDA08/12 + 0023 PCI-DDA02/16 + 0024 PCI-DDA04/16 + 0025 PCI-DDA08/16 + 0026 PCI-DAC04/12-HS + 0027 PCI-DAC04/16-HS + 0028 PCI-DIO24 + 0029 PCI-DAS08 + 002C PCI-INT32 + 0033 PCI-DUAL-AC5 + 0034 PCI-DAS-TC + 0035 PCI-DAS64/M1/16 + 0036 PCI-DAS64/M2/16 + 0037 PCI-DAS64/M3/16 + 004C PCI-DAS1000 +1308 Jato Technologies Inc. + 0001 NetCelerator Adapter +1309 AB Semiconductor Ltd +130a Mitsubishi Electric Microcomputer +130b Colorgraphic Communications Corp +130c Ambex Technologies, Inc +130d Accelerix Inc +130e Yamatake-Honeywell Co. Ltd +130f Advanet Inc +1310 Gespac +1311 Videoserver, Inc +1312 Acuity Imaging, Inc +1313 Yaskawa Electric Co. +1316 Teradyne Inc +1317 Bridgecom, Inc +1318 Packet Engines Inc. +1319 Fortemedia, Inc + 0801 Xwave QS3000A [FM801] + 0802 Xwave QS3000A [FM801 game port] +131a Finisar Corp. +131c Nippon Electro-Sensory Devices Corp +131d Sysmic, Inc. +131e Xinex Networks Inc +131f Siig Inc + 1010 Duet 1S(16550)+1P + 1011 Duet 1S(16650)+1P + 1012 Duet 1S(16850)+1P + 1020 CyberParallel (1-port) + 1021 CyberParallel (2-port) + 1034 Trio 2S(16550)+1P + 1035 Trio 2S(16650)+1P + 1036 Trio 2S(16850)+1P + 2010 Duet 1S(16550)+1P + 2011 Duet 1S(16650)+1P + 2012 Duet 1S(16850)+1P + 2020 CyberParallel (1-port) + 2021 CyberParallel (2-port) + 2040 Trio 1S(16550)+2P + 2041 Trio 1S(16650)+2P + 2042 Trio 1S(16850)+2P + 2060 Trio 2S(16550)+1P + 2061 Trio 2S(16650)+1P + 2062 Trio 2S(16850)+1P +1320 Crypto AG +1321 Arcobel Graphics BV +1322 MTT Co., Ltd +1323 Dome Inc +1324 Sphere Communications +1325 Salix Technologies, Inc +1326 Seachange international +1327 Voss scientific +1328 quadrant international +1329 Productivity Enhancement +132a Microcom Inc. +132b Broadband Technologies +132c Micrel Inc +132d Integrated Silicon Solution, Inc. +1330 MMC Networks +1331 Radisys Corp. +1332 Micro Memory +1334 Redcreek Communications, Inc +1335 Videomail, Inc +1337 Third Planet Publishing +1338 BT Electronics +133a Vtel Corp +133b Softcom Microsystems +133c Holontech Corp +133d SS Technologies +133e Virtual Computer Corp +133f SCM Microsystems +1340 Atalla Corp +1341 Kyoto Microcomputer Co +1342 Promax Systems Inc +1343 Phylon Communications Inc +1344 Crucial Technology +1345 Arescom Inc +1347 Odetics +1349 Sumitomo Electric Industries, Ltd. +134a DTC Technology Corp. + 0001 Domex 536 +134b ARK Research Corp. +134c Chori Joho System Co. Ltd +134d PCTel Inc +134e CSTI +134f Algo System Co Ltd +1350 Systec Co. Ltd +1351 Sonix Inc +1353 Dassault A.T. +1354 Dwave System Inc +1355 Kratos Analytical Ltd +1356 The Logical Co +1359 Prisa Networks +135a Brain Boxes +135b Giganet Inc +135c Quatech Inc +135d ABB Network Partner AB +135e Sealevel Systems Inc + 7101 Single Port RS-232/422/485/530 + 7201 Dual Port RS-232/422/485 Interface + 7202 Dual Port RS-232 Interface + 7401 Four Port RS-232 Interface + 7402 Four Port RS-422/485 Interface + 7801 Eight Port RS-232 Interface + 8001 8001 Digital I/O Adapter +1360 Meinberg Funkuhren +1361 Soliton Systems K.K. +1362 Fujifacom Corporation +1363 Phoenix Technology Ltd +1364 ATM Communications Inc +1365 Hypercope GmbH +1366 Teijin Seiki Co. Ltd +1367 Hitachi Zosen Corporation +1368 Skyware Corporation +1369 Digigram +136a High Soft Tech +136b Kawasaki Steel Corporation +136c Adtek System Science Co Ltd +136d Gigalabs Inc +136f Applied Magic Inc +1370 ATL Products +1371 CNet Technology Inc +1373 Silicon Vision Inc +1374 Silicom Ltd +1375 Argosystems Inc +1376 LMC +1377 Electronic Equipment Production & Distribution GmbH +1378 Telemann Co. Ltd +1379 Asahi Kasei Microsystems Co Ltd +137a Mark of the Unicorn Inc +137b PPT Vision +137c Iwatsu Electric Co Ltd +137d Dynachip Corporation +137e Patriot Scientific Corporation +137f Japan Satellite Systems Inc +1380 Sanritz Automation Co Ltd +1381 Brains Co. Ltd +1382 Marian - Electronic & Software +1383 Controlnet Inc +1384 Reality Simulation Systems Inc +1385 Netgear + 620a GA620 +1386 Video Domain Technologies +1387 Systran Corp +1388 Hitachi Information Technology Co Ltd +1389 Applicom International + 0001 PCI1500PFB [Intelligent fieldbus adaptor] +138a Fusion Micromedia Corp +138b Tokimec Inc +138c Silicon Reality +138d Future Techno Designs pte Ltd +138e Basler GmbH +138f Patapsco Designs Inc +1390 Concept Development Inc +1391 Development Concepts Inc +1392 Medialight Inc +1393 Moxa Technologies Co Ltd +1394 Level One Communications +1395 Ambicom Inc +1396 Cipher Systems Inc +1397 Cologne Chip Designs GmbH + 2bd0 ISDN network controller +1398 Clarion co. Ltd +1399 Rios systems Co Ltd +139a Alacritech Inc +139b Mediasonic Multimedia Systems Ltd +139c Quantum 3d Inc +139d EPL limited +139e Media4 +139f Aethra s.r.l. +13a0 Crystal Group Inc +13a1 Kawasaki Heavy Industries Ltd +13a2 Ositech Communications Inc +13a3 Hi-Fn +13a4 Rascom Inc +13a5 Audio Digital Imaging Inc +13a6 Videonics Inc +13a7 Teles AG +13a8 Exar Corp. +13a9 Siemens Medical Systems, Ultrasound Group +13aa Broadband Networks Inc +13ab Arcom Control Systems Ltd +13ac Motion Media Technology Ltd +13ad Nexus Inc +13ae ALD Technology Ltd +13af T.Sqware +13b0 Maxspeed Corp +13b1 Tamura corporation +13b2 Techno Chips Co. Ltd +13b3 Lanart Corporation +13b4 Wellbean Co Inc +13b5 ARM +13b6 Dlog GmbH +13b7 Logic Devices Inc +13b8 Nokia Telecommunications oy +13b9 Elecom Co Ltd +13ba Oxford Instruments +13bb Sanyo Technosound Co Ltd +13bc Bitran Corporation +13bd Sharp corporation +13be Miroku Jyoho Service Co. Ltd +13bf Sharewave Inc +13c0 Microgate Corporation + 0010 SyncLink WAN Adapter +13c1 3ware Inc +13c2 Technotrend Systemtechnik GmbH +13c3 Janz Computer AG +13c4 Phase Metrics +13c5 Alphi Technology Corp +13c6 Condor Engineering Inc +13c7 Blue Chip Technology Ltd +13c8 Apptech Inc +13c9 Eaton Corporation +13ca Iomega Corporation +13cb Yano Electric Co Ltd +13cc Metheus Corporation +13cd Compatible Systems Corporation +13ce Cocom A/S +13cf Studio Audio & Video Ltd +13d0 Techsan Electronics Co Ltd +13d1 Abocom Systems Inc +13d2 Shark Multimedia Inc +13d3 IMC Networks +13d4 Graphics Microsystems Inc +13d5 Media 100 Inc +13d6 K.I. Technology Co Ltd +13d7 Toshiba Engineering Corporation +13d8 Phobos corporation +13d9 Apex PC Solutions Inc +13da Intresource Systems pte Ltd +13db Janich & Klass Computertechnik GmbH +13dc Netboost Corporation +13dd Multimedia Bundle Inc +13de ABB Robotics Products AB +13df E-Tech Inc + 0001 PCI56RVP Modem +13e0 GVC Corporation +13e1 Silicom Multimedia Systems Inc +13e2 Dynamics Research Corporation +13e3 Nest Inc +13e4 Calculex Inc +13e5 Telesoft Design Ltd +13e6 Argosy research Inc +13e7 NAC Incorporated +13e8 Chip Express Corporation +13e9 Chip Express Corporation +13ea Dallas Semiconductor +13eb Hauppauge Computer Works Inc +13ec Zydacron Inc +13ed Raytheion E-Systems +13ee Hayes Microcomputer Products Inc +13ef Coppercom Inc +13f0 Sundance technology Inc +13f1 Oce' - Technologies B.V. +13f2 Ford Microelectronics Inc +13f3 Mcdata Corporation +13f4 Troika Design Inc +13f5 Kansai Electric Co. Ltd +13f6 C-Media Electronics Inc + 0100 CM8338A + 0101 CM8338B + 0111 CM8738 +13f7 Wildfire Communications +13f8 Ad Lib Multimedia Inc +13f9 NTT Advanced Technology Corp. +13fa Pentland Systems Ltd +13fb Aydin Corp +13fc Computer Peripherals International +13fd Micro Science Inc +13fe Advantech Co. Ltd +13ff Silicon Spice Inc +1400 Artx Inc +1401 CR-Systems A/S +1402 Meilhaus Electronic GmbH +1403 Ascor Inc +1404 Fundamental Software Inc +1405 Excalibur Systems Inc +1406 Oce' Printing Systems GmbH +1407 Lava Computer mfg Inc + 8000 Lava Parallel + 8002 Lava Dual Parallel port A + 8003 Lava Dual Parallel port B + 8800 BOCA Research IOPPAR +1408 Aloka Co. Ltd +1409 Timedia Technology Co Ltd +140a DSP Research Inc +140b Ramix Inc +140c Elmic Systems Inc +140d Matsushita Electric Works Ltd +140e Goepel Electronic GmbH +140f Salient Systems Corp +1410 Midas lab Inc +1411 Ikos Systems Inc +1412 IC Ensemble Inc +1413 Addonics +1414 Microsoft Corporation +1415 Oxford Semiconductor Ltd +1416 Multiwave Innovation pte Ltd +1417 Convergenet Technologies Inc +1418 Kyushu electronics systems Inc +1419 Excel Switching Corp +141a Apache Micro Peripherals Inc +141b Zoom Telephonics Inc +141d Digitan Systems Inc +141e Fanuc Ltd +141f Visiontech Ltd +1420 Psion Dacom plc +1421 Ads Technologies Inc +1422 Ygrec Systems Co Ltd +1423 Custom Technology Corp. +1424 Videoserver Connections +1425 ASIC Designers Inc +1426 Storage Technology Corp. +1427 Better On-Line Solutions +1428 Edec Co Ltd +1429 Unex Technology Corp. +142a Kingmax Technology Inc +142b Radiolan +142c Minton Optic Industry Co Ltd +142d Pix stream Inc +142e Vitec Multimedia +142f Radicom Research Inc +1430 ITT Aerospace/Communications Division +1431 Gilat Satellite Networks +1432 Edimax Computer Co. +1433 Eltec Elektronik GmbH +1435 Real Time Devices US Inc. +1436 CIS Technology Inc +1437 Nissin Inc Co +1438 Atmel-dream +1439 Outsource Engineering & Mfg. Inc +143a Stargate Solutions Inc +143b Canon Research Center, America +143c Amlogic Inc +143d Tamarack Microelectronics Inc +143e Jones Futurex Inc +143f Lightwell Co Ltd - Zax Division +1440 ALGOL Corp. +1441 AGIE Ltd +1442 Phoenix Contact GmbH & Co. +1443 Unibrain S.A. +1444 TRW +1445 Logical DO Ltd +1446 Graphin Co Ltd +1447 AIM GmBH +1448 Alesis Studio Electronics +1449 TUT Systems Inc +144a Adlink Technology +144b Loronix Information Systems Inc +144c Catalina Research Inc +144d Samsung Electronics Co Ltd +144e OLITEC +144f Askey Computer Corp. +1450 Octave Communications Ind. +1451 SP3D Chip Design GmBH +1453 MYCOM Inc +1454 Altiga Networks +1455 Logic Plus Plus Inc +1456 Advanced Hardware Architectures +1457 Nuera Communications Inc +1458 Giga-byte Technology +1459 DOOIN Electronics +145a Escalate Networks Inc +145b PRAIM SRL +145c Cryptek +145d Gallant Computer Inc +145e Aashima Technology B.V. +145f Baldor Electric Company +1460 DYNARC INC +1461 Avermedia Technologies Inc +1462 Micro-star International Co Ltd +1463 Fast Corporation +1464 Interactive Circuits & Systems Ltd +1465 GN NETTEST Telecom DIV. +1466 Designpro Inc. +1467 DIGICOM SPA +1468 AMBIT Microsystem Corp. +1469 Cleveland Motion Controls +146a IFR +146b Parascan Technologies Ltd +146c Ruby Tech Corp. +146d Tachyon, INC. +146e Williams Electronics Games, Inc. +146f Multi Dimensional Consulting Inc +1470 Bay Networks +1471 Integrated Telecom Express Inc +1472 DAIKIN Industries, Ltd +1473 ZAPEX Technologies Inc +1474 Doug Carson & Associates +1475 PICAZO Communications +1476 MORTARA Instrument Inc +1477 Net Insight +1478 DIATREND Corporation +1479 TORAY Industries Inc +147a FORMOSA Industrial Computing +147b ABIT Computer Corp. +147c AWARE, Inc. +147d Interworks Computer Products +147e Matsushita Graphic Communication Systems, Inc. +147f NIHON UNISYS, Ltd. +1480 SCII Telecom +1481 BIOPAC Systems Inc +1482 ISYTEC - Integrierte Systemtechnik GmBH +1483 LABWAY Corporation +1484 Logic Corporation +1485 ERMA - Electronic GmBH +1486 L3 Communications Telemetry & Instrumentation +1487 MARQUETTE Medical Systems +1488 KONTRON Electronik GmBH +1489 KYE Systems Corporation +148a OPTO +148b INNOMEDIALOGIC Inc. +148c C.P. Technology Co. Ltd +148d DIGICOM Systems, Inc. +148e OSI Plus Corporation +148f Plant Equipment, Inc. +1490 Stone Microsystems PTY Ltd. +1491 ZEAL Corporation +1492 Time Logic Corporation +1493 MAKER Communications +1494 WINTOP Technology, Inc. +1495 TOKAI Communications Industry Co. Ltd +1496 JOYTECH Computer Co., Ltd. +1497 SMA Regelsysteme GmBH +1498 TEWS Datentechnik GmBH +1499 EMTEC CO., Ltd +149a ANDOR Technology Ltd +149b SEIKO Instruments Inc +149c OVISLINK Corp. +149D NEWTEK Inc +149e Mapletree Networks Inc. +149f LECTRON Co Ltd +14a0 SOFTING GmBH +14a1 Systembase Co Ltd +14a2 Millennium Engineering Inc +14a3 Maverick Networks +14a4 GVC/BCM Advanced Research +14a5 XIONICS Document Technologies Inc +14a6 INOVA Computers GmBH & Co KG +14a7 MYTHOS Systems Inc +14a8 FEATRON Technologies Corporation +14a9 HIVERTEC Inc +14aa Advanced MOS Technology Inc +14ab Mentor Graphics Corp. +14ac Novaweb Technologies Inc +14ad Time Space Radio AB +14ae CTI, Inc +14af Guillemot Corporation +14b0 BST Communication Technology Ltd +14b1 Nextcom K.K. +14b2 ENNOVATE Networks Inc +14b3 XPEED Inc +14b4 PHILIPS Business Electronics B.V. +14b5 Creamware GmBH +14b6 Quantum Data Corp. +14b7 PROXIM Inc + 0001 Symphony 4110 +14b8 Techsoft Technology Co Ltd +14b9 AIRONET Wireless Communications + 0001 PC4800 +14ba INTERNIX Inc. +14bb SEMTECH Corporation +14bc Globespan Semiconductor Inc. +14bd CARDIO Control N.V. +14be L3 Communications +14bf SPIDER Communications Inc. +14c0 COMPAL Electronics Inc +14c1 MYRICOM Inc. +14c2 DTK Computer +14c3 MEDIATEK Corp. +14c4 IWASAKI Information Systems Co Ltd +14c5 Automation Products AB +14c6 Data Race Inc +14c7 Modular Technology Holdings Ltd +14c8 Turbocomm Tech. Inc. +14c9 ODIN Telesystems Inc +14ca PE Logic Corp. +14cb Billionton Systems Inc +14cc NAKAYO Telecommunications Inc +14cd Universal Scientific Ind. +14ce Whistle Communications +14cf TEK Microsystems Inc. +14d0 Ericsson Axe R & D +14d1 Computer Hi-Tech Co Ltd +14d2 Titan Electronics Inc +14d3 CIRTECH (UK) Ltd +14d4 Panacom Technology Corp +14d5 Nitsuko Corporation +14d6 Accusys Inc +14d7 Hirakawa Hewtech Corp +14d8 HOPF Elektronik GmBH +14d9 Alpha Processor Inc +14da National Aerospace Laboratories +14db AFAVLAB Technology Inc +14dc Amplicon Liveline Ltd +14dd Boulder Design Labs Inc +14de Applied Integration Corporation +14df ASIC Communications Corp +14e1 INVERTEX +14e2 INFOLIBRIA +14e3 AMTELCO +14e4 BROADCOM Corporation +14e5 Pixelfusion Ltd +14e6 SHINING Technology Inc +14e7 3CX +14e8 RAYCER Inc +14e9 GARNETS System CO Ltd +14ea PLANEX COMMUNICATIONS Inc +14eb SEIKO EPSON Corp +14ec ACQIRIS +14ed DATAKINETICS Ltd +14ee MASPRO KENKOH Corp +14ef CARRY Computer ENG. CO Ltd +14f0 CANON RESEACH CENTRE FRANCE +14f1 CONEXANT + 2013 HSP MicroModem 56K +14f2 MOBILITY Electronics +14f3 BROADLOGIC +14f4 TOKYO Electronic Industry CO Ltd +14f5 SOPAC Ltd +14f6 COYOTE Technologies LLC +14f7 WOLF Technology Inc +14f8 AUDIOCODES Inc +14f9 AG COMMUNICATIONS +14fa WANDEL & GOCHERMANN +14fb TRANSAS MARINE (UK) Ltd +14fc QUADRICS Supercomputers World +14fd JAPAN Computer Industry Inc +14fe ARCHTEK TELECOM Corp +14ff TWINHEAD INTERNATIONAL Corp +1500 DELTA Electronics, Inc +1501 BANKSOFT CANADA Ltd +1502 MITSUBISHI ELECTRIC LOGISTICS SUPPORT Co Ltd +1503 KAWASAKI LSI USA Inc +1504 KAISER Electronics +1505 ITA INGENIEURBURO FUR TESTAUFGABEN GmbH +1506 CHAMELEON Systems Inc +# 1507 HTEC Ltd +# Commented out because there are no known HTEC chips and 1507 is already +# used by mistake by Motorola (see vendor ID 1057) +1508 HONDA CONNECTORS/MHOTRONICS Inc +1509 FIRST INTERNATIONAL Computer Inc +150a FORVUS RESEARCH Inc +150b YAMASHITA Systems Corp +150c KYOPAL CO Ltd +150d WARPSPPED Inc +150e C-PORT Corp +150f INTEC GmbH +1510 BEHAVIOR TECH Computer Corp +1511 CENTILLIUM Technology Corp +1512 ROSUN Technologies Inc +1513 Raychem +1514 TFL LAN Inc +1515 Advent design +1516 MYSON Technology Inc +1517 ECHOTEK Corp +1518 PEP MODULAR Computers GmbH +1519 TELEFON AKTIEBOLAGET LM Ericsson +151a GLOBETEK Inc +151b COMBOX Ltd +151c DIGITAL AUDIO LABS Inc +151d Fujitsu Computer Products Of America +151e MATRIX Corp +151f TOPIC SEMICONDUCTOR Corp +1520 CHAPLET System Inc +1521 BELL Corp +1522 MainPine Ltd +1523 MUSIC Semiconductors +1524 ENE Technology Inc +1525 IMPACT Technologies +1526 ISS, Inc +1527 SOLECTRON +1528 ACKSYS +1529 AMERICAN MICROSystems Inc +152a QUICKTURN DESIGN Systems +152b FLYTECH Technology CO Ltd +152c MACRAIGOR Systems LLC +152d QUANTA Computer Inc +152e MELEC Inc +152f PHILIPS - CRYPTO +1530 ACQIS Technology Inc +1531 CHRYON Corp +1532 ECHELON Corp +1533 BALTIMORE +1534 ROAD Corp +1535 EVERGREEN Technologies Inc +1537 DATALEX COMMUNCATIONS +1538 ARALION Inc +1539 ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A. +153a ONO SOKKI +153b TERRATEC Electronic GmbH +153c ANTAL Electronic +153d FILANET Corp +153e TECHWELL Inc +153f MIPS DENMARK +1540 PROVIDEO MULTIMEDIA Co Ltd +1541 MACHONE Communications +1542 VIVID Technology Inc +1543 SILICON Laboratories +1544 DCM DATA Systems +1545 VISIONTEK +1546 IOI Technology Corp +1547 MITUTOYO Corp +1548 JET PROPULSION Laboratory +1549 INTERCONNECT Systems Solutions +154a MAX Technologies Inc +154b COMPUTEX Co Ltd +154c VISUAL Technology Inc +154d PAN INTERNATIONAL Industrial Corp +154e SERVOTEST Ltd +154f STRATABEAM Technology +1550 OPEN NETWORK Co Ltd +1551 SMART Electronic DEVELOPMENT GmBH +1552 RACAL AIRTECH Ltd +1553 CHICONY Electronics Co Ltd +1554 PROLINK Microsystems Corp +1555 GESYTEC GmBH +1556 PLD APPLICATIONS +1557 MEDIASTAR Co Ltd +1558 CLEVO/KAPOK Computer +1559 SI LOGIC Ltd +155a INNOMEDIA Inc +155b PROTAC INTERNATIONAL Corp +1668 Action Tec Electronics Inc +1a08 Sierra semiconductor + 0000 SC15064 +1b13 Jaton Corp +1c1c Symphony + 0001 82C101 +1d44 DPT + a400 PM2x24/PM3224 +1de1 Tekram Technology Co.,Ltd. + 2020 DC-390 + 690c 690c + dc29 DC290 +2001 Temporal Research Ltd +21c3 21st Century Computer Corp. +2348 Racore + 2010 8142 100VG/AnyLAN +2646 Kingston Technologies +270b Xantel Corporation +270f Chaintech Computer Co. Ltd +2711 AVID Technology Inc. +3000 Hansol Electronics Inc. +3142 Post Impression Systems. +3388 Hint Corp + 8011 VXPro II Chipset + 8012 VXPro II Chipset + 8013 VXPro II Chipset +3513 ARCOM Control Systems Ltd +3d3d 3DLabs + 0001 GLINT 300SX + 0002 GLINT 500TX + 0003 GLINT Delta + 0004 Permedia + 0005 Permedia + 0006 GLINT MX + 0007 3D Extreme + 0009 Permedia II 2D+3D + 3d3d 0100 AccelStar II 3D Accelerator + 3d3d 0111 Permedia 3:16 + 3d3d 0114 Santa Ana + 3d3d 0116 Oxygen GVX1 + 3d3d 0119 Scirocco + 3d3d 0120 Santa Ana PCL + 3d3d 0125 Oxygen VX1 + 3d3d 0127 Permedia3 Create! + 0100 Permedia II 2D+3D + 1004 Permedia + 3d04 Permedia + ffff Glint VGA +4005 Avance Logic Inc. + 1064 ALG-2064 + 2064 ALG-2064i + 2128 ALG-2364A GUI Accelerator + 2301 ALG-2301 + 2302 ALG-2302 + 2303 AVG-2302 GUI Accelerator + 2364 ALG-2364A + 2464 ALG-2464 + 2501 ALG-2564A/25128A +4033 Addtron Technology Co, Inc. +4444 Internext Compression Inc +4468 Bridgeport machines +4594 Cogetec Informatique Inc +45fb Baldor Electric Company +4680 Umax Computer Corp +4843 Hercules Computer Technology Inc +4943 Growth Networks +4978 Axil Computer Inc +4a14 NetVin + 5000 NV5000SC +4b10 Buslogic Inc. +4c48 LUNG HWA Electronics +4d51 MEDIAQ Inc. + 0200 MQ-200 +4ddc ILC Data Device Corp +5053 Voyetra Technologies + 2010 Daytona Audio Adapter +5136 S S Technologies +5143 Qualcomm Inc +5145 Ensoniq (Old) + 3031 Concert AudioPCI +5301 Alliance Semiconductor Corp. + 0001 ProMotion aT3D +5333 S3 Inc. + 0551 Plato/PX (system) + 5631 86c325 [ViRGE] + 8800 86c866 [Vision 866] + 8801 86c964 [Vision 964] + 8810 86c764_0 [Trio 32 vers 0] + 8811 86c764/765 [Trio32/64/64V+] + 8812 86cM65 [Aurora64V+] + 8813 86c764_3 [Trio 32/64 vers 3] + 8814 86c767 [Trio 64UV+] + 8815 86cM65 [Aurora 128] + 883d 86c988 [ViRGE/VX] + 8870 FireGL + 8880 86c868 [Vision 868 VRAM] vers 0 + 8881 86c868 [Vision 868 VRAM] vers 1 + 8882 86c868 [Vision 868 VRAM] vers 2 + 8883 86c868 [Vision 868 VRAM] vers 3 + 88b0 86c928 [Vision 928 VRAM] vers 0 + 88b1 86c928 [Vision 928 VRAM] vers 1 + 88b2 86c928 [Vision 928 VRAM] vers 2 + 88b3 86c928 [Vision 928 VRAM] vers 3 + 88c0 86c864 [Vision 864 DRAM] vers 0 + 88c1 86c864 [Vision 864 DRAM] vers 1 + 88c2 86c864 [Vision 864-P DRAM] vers 2 + 88c3 86c864 [Vision 864-P DRAM] vers 3 + 88d0 86c964 [Vision 964 VRAM] vers 0 + 88d1 86c964 [Vision 964 VRAM] vers 1 + 88d2 86c964 [Vision 964-P VRAM] vers 2 + 88d3 86c964 [Vision 964-P VRAM] vers 3 + 88f0 86c968 [Vision 968 VRAM] rev 0 + 88f1 86c968 [Vision 968 VRAM] rev 1 + 88f2 86c968 [Vision 968 VRAM] rev 2 + 88f3 86c968 [Vision 968 VRAM] rev 3 + 8900 86c755 [Trio 64V2/DX] + 8901 Trio 64V2/DX or /GX + 8902 Plato/PX + 8903 Trio 3D business multimedia + 8904 Trio 64 3D + 1014 00db Integrated Trio3D + 5333 8904 86C365 Trio3D AGP + 8905 Trio 64V+ family + 8906 Trio 64V+ family + 8907 Trio 64V+ family + 8908 Trio 64V+ family + 8909 Trio 64V+ family + 890a Trio 64V+ family + 890b Trio 64V+ family + 890c Trio 64V+ family + 890d Trio 64V+ family + 890e Trio 64V+ family + 890f Trio 64V+ family + 8a01 ViRGE/DX or /GX + 0e11 b032 ViRGE/GX + 10b4 1617 Nitro 3D + 10b4 1717 Nitro 3D + 5333 8a01 ViRGE/DX + 8a10 ViRGE/GX2 + 1092 8a10 Stealth 3D 4000 + 8a13 86c368 [Trio 3D/2X] + 5333 8a13 Trio3D/2X + 8a20 86c794 [Savage 3D] + 8a21 86c795 [Savage 3D/MV] + 8a22 Savage 4 + 105d 0018 SR9 8Mb SDRAM + 105d 002a SR9 Pro 16Mb SDRAM + 105d 003a SR9 Pro 32Mb SDRAM + 105d 092f SR9 Pro+ 16Mb SGRAM + 1092 4207 Stealth III S540 + 1092 4800 Stealth III S540 + 1092 4808 Stealth III S540 + 1092 480e Stealth III S540 + 1092 4904 Stealth III S520 + 1092 4a09 Stealth III S540 + 1092 4a0b Stealth III S540 Xtreme + 1092 4a0f Stealth III S540 + 1092 4e01 Stealth III S540 + 1102 101d 3d Blaster Savage 4 + 1102 101e 3d Blaster Savage 4 + 8a23 Savage 4 + 8c00 ViRGE/M3 + 8c01 ViRGE/MX + 8c02 ViRGE/MX+ + 8c03 ViRGE/MX+MV + ca00 SonicVibes +544c Teralogic Inc +5455 Technische University Berlin + 4458 S5933 +5519 Cnet Technologies, Inc. +5555 Genroco, Inc + 0003 TURBOstor HFP-832 [HiPPI NIC] +5700 Netpower +6356 UltraStor +6374 c't Magazin für Computertechnik + 6773 GPPCI +6409 Logitec Corp. +6666 Decision Computer International Co. + 0001 PCCOM4 + 0002 PCCOM8 +7604 O.N. Electronic Co Ltd. +7bde MIDAC Corporation +7fed PowerTV +8008 Quancom Electronic GmbH + 0010 WDOG1 [PCI-Watchdog 1] + 0011 PWDOG2 [PCI-Watchdog 2] +8086 Intel Corporation + 0007 82379AB + 0039 21145 + 0122 82437FX + 0482 82375EB + 0483 82424ZX [Saturn] + 0484 82378IB [SIO ISA Bridge] + 0486 82430ZX [Aries] + 04a3 82434LX [Mercury/Neptune] + 04d0 82437FX [Triton FX] + 0960 80960RP [i960 RP Microprocessor/Bridge] + 1000 82542 Gigabit Ethernet Adapter + 0e11 b0df NC1632 Gigabit Ethernet Adapter + 0e11 b0e0 NC1633 Gigabit Ethernet Adapter + 0e11 b123 NC1634 Gigabit Ethernet Adapter + 1014 0119 Netfinity Gigabit Ethernet SX Adapter + 8086 1000 EtherExpress PRO/1000 Gigabit Server Adapter + 1209 82559ER + 1221 82092AA_0 + 1222 82092AA_1 + 1223 SAA7116 + 1225 82452KX/GX [Orion] + 1226 82596 + 1227 82865 [Ether Express Pro 100] + 1228 82556 [Ether Express Pro 100 Smart] + 1229 82557 [Ethernet Pro 100] + 0e11 b01e NC3120 + 0e11 b01f NC3122 + 0e11 b02f NC1120 + 0e11 b04a Netelligent 10/100TX NIC with Wake on LAN + 0e11 b0c6 Embedded NC3120 with Wake on LAN + 0e11 b0c7 Embedded NC3121 + 0e11 b0d7 NC3121 with Wake on LAN + 0e11 b0dd NC3131 + 0e11 b0de NC3132 + 0e11 b0e1 NC3133 + 1014 005c Ethernet Pro 10/100 + 1014 105c Netfinity 10/100 + 1033 8000 PC-9821X-B06 + 1033 8016 PK-UG-X006 + 1033 801f PK-UG-X006 + 103c 10C0 Ethernet Pro 10/100TX + 103c 10C3 Ethernet Pro 10/100TX + 103c 1200 Ethernet Pro 10/100TX + 10c3 1100 SmartEther100 SC1100 + 1259 2560 AT-2560 100 + 1259 2561 AT-2560 100 FX Ethernet Adapter + 1266 0001 NE10/100 Adapter + 8086 0001 EtherExpress PRO/100B (TX) + 8086 0002 EtherExpress PRO/100B (T4) + 8086 0003 EtherExpress PRO/10+ + 8086 0004 EtherExpress PRO/100 WfM + 8086 0005 82557 10/100 + 8086 0006 82557 10/100 with Wake on LAN + 8086 0007 82558 10/100 Adapter + 8086 0008 82558 10/100 with Wake on LAN + 8086 0009 EtherExpress PRO/100+ + 8086 000a EtherExpress PRO/100+ Management Adapter + 8086 000b EtherExpress PRO/100+ + 8086 000c EtherExpress PRO/100+ Management Adapter + 8086 000d EtherExpress PRO/100+ Alert On LAN II* Adapter + 8086 000e EtherExpress PRO/100+ Management Adapter with Alert On LAN* + 8086 1009 EtherExpress PRO/100+ Server Adapter + 8086 100C EtherExpress PRO/100+ Server Adapter (PILA8470B) + 8086 10f0 EtherExpress PRO/100+ Dual Port Adapter + 8086 200d EtherExpress PRO/100 Cardbus + 8086 200e EtherExpress PRO/100 LAN+V90 Cardbus Modem + 8086 3000 82559 Fast Ethernet LAN on Motherboard + 8086 3001 82559 Fast Ethernet LOM with Basic Alert on LAN* + 8086 3002 82559 Fast Ethernet LOM with Alert on LAN II* + 122d 430FX - 82437FX TSC [Triton I] + 122e 82371FB PIIX ISA [Triton I] + 1230 82371FB PIIX IDE [Triton I] + 1231 DSVD Modem + 1234 430MX - 82371MX MPIIX [430MX PCIset - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX)] + 1235 430MX - 82437MX MTSC [430MX PCIset - 82437MX Mobile System Controller (MTSC) and 82438MX Mobile Data Path (MTDP)] + 1237 440FX - 82441FX PMC [Natoma] + 1239 82371FB + 123b 82380PB + 123c 82380AB + 1240 752 AGP + 124b 82380FB + 1250 430HX - 82439HX TXC [Triton II] + 1960 80960RP [i960RP Microprocessor] + 101e 0438 MegaRaid 438 + 101e 0466 MegaRaid 466 + 103c 10C6 MegaRaid 438 + 103c 10C7 MegaRaid T5 + 1111 1111 MegaRaid 466 + 113c 03A2 MegaRaid + 5200 EtherExpress PRO/100 + 5201 EtherExpress PRO/100 + 7000 82371SB PIIX3 ISA [Natoma/Triton II] + 7010 82371SB PIIX3 IDE [Natoma/Triton II] + 7020 82371SB PIIX3 USB [Natoma/Triton II] + 7030 430VX - 82437VX TVX [Triton VX] + 7100 430TX - 82439TX MTXC + 7110 82371AB PIIX4 ISA + 7111 82371AB PIIX4 IDE + 7112 82371AB PIIX4 USB + 7113 82371AB PIIX4 ACPI + 7120 82810 GMCH [Graphics Memory Controller Hub] + 7121 82810 CGC [Chipset Graphics Controller] + 7122 82810-DC100 GMCH [Graphics Memory Controller Hub] + 7123 82810-DC100 CGC [Chipset Graphics Controller] + 7180 440LX/EX - 82443LX/EX Host bridge + 7181 440LX/EX - 82443LX/EX AGP bridge + 7190 440BX/ZX - 82443BX/ZX Host bridge + 0e11 0500 Armada 1750 Laptop System Chipset + 7191 440BX/ZX - 82443BX/ZX AGP bridge + 7192 440BX/ZX - 82443BX/ZX Host bridge (AGP disabled) + 0e11 0460 Armada 1700 Laptop System Chipset + 71a0 440GX - 82443GX Host bridge + 71a1 440GX - 82443GX AGP bridge + 71a2 440GX - 82443GX Host bridge (AGP disabled) + 7602 82372FB [PCI-to-USB UHCI] + 7800 i740 + 1092 0100 Stealth II G460 + 8086 0100 Intel740 Graphics Accelerator + 84c4 450KX/GX [Orion] - 82454KX/GX PCI bridge + 84c5 450KX/GX [Orion] - 82453KX/GX Memory controller + 84ca 450NX - 82451NX Memory & I/O Controller + 84cb 450NX - 82454NX PCI Expander Bridge + ffff 450NX/GX [Orion] - 82453KX/GX Memory controller [BUG] +8800 Trigem Computer Inc. + 2008 Video assistent component +8866 T-Square Design Inc. +8888 Silicon Magic +8e0e Computone Corporation +8e2e KTI + 3000 ET32P2 +9004 Adaptec +# FIXME: [dj] In one document I have, lot of these AIC's are actually AHA's + 1078 AIC-7810 + 1160 AIC-1160 [Family Fiber Channel Adapter] + 2178 AIC-7821 + 3860 AHA-2930CU + 3b78 AHA-4844W/4844UW + 5075 AIC-755x + 5078 AHA-7850 + 5175 AIC-755x + 5178 AIC-7851 + 5275 AIC-755x + 5278 AIC-7852 + 5375 AIC-755x + 5378 AIC-7850 + 5475 AIC-2930 + 5478 AIC-7850 + 5575 AVA-2930 + 5578 AIC-7855 + 5675 AIC-755x + 5678 AIC-7850 + 5775 AIC-755x + 5778 AIC-7850 + 5800 AIC-5800 + 5900 ANA-5910/5930/5940 ATM155 & 25 LAN Adapter + 5905 ANA-5910A/5930A/5940A ATM Adapter + 6038 AIC-3860 +# FIXME: This is a cardbus card. The declaration may be duplicative. + 6075 AIC-1480 / APA-1480 + 6078 AIC-7860 + 6178 AIC-7861 + 6278 AIC-7860 + 6378 AIC-7860 + 6478 AIC-786 + 6578 AIC-786x + 6678 AIC-786 + 6778 AIC-786x + 6915 ANA620xx/ANA69011A + 9004 0008 ANA69011A/TX 10/100 + 9004 0009 ANA69011A/TX 10/100 + 9004 0010 ANA62022 2-port 10/100 + 9004 0018 ANA62044 4-port 10/100 + 9004 0020 ANA62022 2-port 10/100 + 9004 0028 ANA69011A/TX 10/100 + 9004 8008 ANA69011A/TX 64 bit 10/100 + 9004 8009 ANA69011A/TX 64 bit 10/100 + 9004 8010 ANA62022 2-port 64 bit 10/100 + 9004 8018 ANA62044 4-port 64 bit 10/100 + 9004 8020 ANA62022 2-port 64 bit 10/100 + 9004 8028 ANA69011A/TX 64 bit 10/100 + 7078 AHA-294x / AIC-7870 + 7178 AHA-294x / AIC-7871 + 7278 AHA-3940 / AIC-7872 + 7378 AHA-3985 / AIC-7873 + 7478 AHA-2944 / AIC-7874 +# FIXME: [dj] Where did the 3rd number come from in 0x7578 & 0x7678 ? + 7578 AHA-3944 / AHA-3944W / 7875 + 7678 AHA-4944W/UW / 7876 + 7778 AIC-787x + 7810 AIC-7810 + 7850 AIC-7850 + 7855 AHA-2930 + 7860 AIC-7860 + 7870 AIC-7870 + 7871 AHA-2940 + 7872 AHA-3940 + 7873 AHA-3980 + 7874 AHA-2944 + 7880 AIC-7880P + 7890 AIC-7890 + 7891 AIC-789x + 7892 AIC-789x + 7893 AIC-789x + 7894 AIC-789x + 7895 AHA-2940U/UW / AHA-39xx / AIC-7895 + 7896 AIC-789x + 7897 AIC-789x + 8078 AIC-7880U + 8178 AIC-7881U + 8278 AHA-3940U/UW / AIC-7882U + 8378 AHA-3940U/UW / AIC-7883U + 8478 AHA-294x / AIC-7884U + 8578 AHA-3944U / AHA-3944UWD / 7885 + 8678 AHA-4944UW / 7886 + 8778 AIC-788x + 8878 7888 + 8b78 ABA-1030 + ec78 AHA-4944W/UW +9005 Adaptec + 0010 AHA-2940U2/W + 0011 2930U2 + 0013 78902 + 001f AHA-2940U2/W / 7890 + 0020 AIC-7890 + 002f AIC-7890 + 0030 AIC-7890 + 003f AIC-7890 + 0050 3940U2 + 0051 3950U2D + 005f 7896 + 0080 7892A + 0081 7892B + 0083 7892D + 008f 7892P + 00c0 7899A + 00c1 7899B + 00c3 7899D + 00cf 7899P +907f Atronics + 2015 IDE-2015PL +9412 Holtek + 6565 6565 +a0a0 AOPEN Inc. +a0f1 UNISYS Corporation +a200 NEC Corporation +a259 Hewlett Packard +a25b Hewlett Packard GmbH PL24-MKT +a304 Sony +a727 3Com Corporation +aa42 Scitex Digital Video +b1b3 Shiva Europe Limited +c001 TSI Telsys +c0a9 Micron/Crucial Technology +c0de Motorola +c0fe Motion Engineering, Inc. +cafe Chrysalis-ITS +cccc Catapult Communications +d4d4 Dy4 Systems Inc +e000 Winbond + e000 W89C940 +e159 Tiger Jet Network Inc. + 0001 Model 300 128k + 0059 0001 128k ISDN-S/T Adapter + 0059 0003 128k ISDN-U Adapter +eabb Aashima Technology B.V. +ecc0 Echo Corporation +edd8 ARK Logic Inc + a091 1000PV [Stingray] + a099 2000PV [Stingray] + a0a1 2000MT + a0a9 2000MI +feda Epigram Inc +fffe VMWare Inc + 0710 Virtual SVGA +ffff Illegal Vendor ID + + +# List of known device classes, subclasses and programming interfaces + +# Syntax: +# C class class_name +# subclass subclass_name <-- single tab +# prog-if prog-if_name <-- two tabs + +C 00 Unclassified device + 00 Non-VGA unclassified device + 01 VGA compatible unclassified device +C 01 Mass storage controller + 00 SCSI storage controller + 01 IDE interface + 02 Floppy disk controller + 03 IPI bus controller + 04 RAID bus controller + 80 Unknown mass storage controller +C 02 Network controller + 00 Ethernet controller + 01 Token ring network controller + 02 FDDI network controller + 03 ATM network controller + 80 Network controller +C 03 Display controller + 00 VGA compatible controller + 00 VGA + 01 8514 + 01 XGA compatible controller + 02 3D controller + 80 Display controller +C 04 Multimedia controller + 00 Multimedia video controller + 01 Multimedia audio controller + 02 Computer telephony device + 80 Multimedia controller +C 05 Memory controller + 00 RAM memory + 01 FLASH memory + 80 Memory controller +C 06 Bridge + 00 Host bridge + 01 ISA bridge + 02 EISA bridge + 03 MicroChannel bridge + 04 PCI bridge + 00 Normal decode + 01 Subtractive decode + 05 PCMCIA bridge + 06 NuBus bridge + 07 CardBus bridge + 08 RACEway bridge + 00 Transparent mode + 01 Endpoint mode + 80 Bridge +C 07 Communication controller + 00 Serial controller + 00 8250 + 01 16450 + 02 16550 + 03 16650 + 04 16750 + 05 16850 + 06 16950 + 01 Parallel controller + 00 SPP + 01 BiDir + 02 ECP + 03 IEEE1284 + FE IEEE1284 Target + 02 Multiport serial controller + 03 Modem + 00 Generic + 01 Hayes/16450 + 02 Hayes/16550 + 03 Hayes/16650 + 04 Hayes/16750 + 80 Communication controller +C 08 Generic system peripheral + 00 PIC + 00 8259 + 01 ISA PIC + 02 EISA PIC + 10 IO-APIC + 20 IO(X)-APIC + 01 DMA controller + 00 8237 + 01 ISA DMA + 02 EISA DMA + 02 Timer + 00 8254 + 01 ISA Timer + 02 EISA Timers + 03 RTC + 00 Generic + 01 ISA RTC + 04 PCI Hot-plug controller + 80 System peripheral +C 09 Input device controller + 00 Keyboard controller + 01 Digitizer Pen + 02 Mouse controller + 03 Scanner controller + 04 Gameport controller + 00 Generic + 10 Extended + 80 Input device controller +C 0A Docking station + 00 Generic Docking Station + 80 Docking Station +C 0B Processor + 00 386 + 01 486 + 02 Pentium + 10 Alpha + 20 Power PC + 30 MIPS + 40 Co-processor +C 0C Serial bus controller + 00 FireWire (IEEE 1394) + 00 Generic + 10 OHCI + 01 ACCESS Bus + 02 SSA + 03 USB Controller + 00 UHCI + 10 OHCI + 80 Unspecified + FE USB Device + 04 Fiber Channel + 05 SMBus +C 0D Wireless controller + 00 IRDA controller + 01 Consumer IR controller + 10 RF controller + 80 Wireless controller +C 0E Intelligent controller + 00 I2O +C 0F Satellite communications controller + 00 Satellite TV controller + 01 Satellite audio communication controller + 03 Satellite voice communication controller + 04 Satellite data communication controller +C 10 Encryption controller + 00 Network and computing encryption device + 01 Entertainment encryption device + 80 Encryption controller +C 11 Signal processing controller + 00 DPIO module + 80 Signal processing controller diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 323e077caeb0af49d9033ea103d616edb1fc1d44..2056501c2b20bdd2c007d6f93d5627da596d7715 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -265,14 +265,22 @@ else endif endif -ifeq ($(CONFIG_MAC_SCSI_OLD),y) +ifeq ($(CONFIG_MAC_SCSI),y) L_OBJS += mac_scsi.o else - ifeq ($(CONFIG_MAC_SCSI_OLD),m) + ifeq ($(CONFIG_MAC_SCSI),m) M_OBJS += mac_scsi.o endif endif +ifeq ($(CONFIG_SUN3_SCSI),y) +L_OBJS += sun3_scsi.o +else + ifeq ($(CONFIG_SUN3_SCSI),m) + M_OBJS += sun3_scsi.o + endif +endif + ifeq ($(CONFIG_SCSI_MAC_ESP),y) L_OBJS += mac_esp.o NCR53C9x.o else diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 46b8045331f96821834fdfc60babdf527c5b12dc..93d084cbfe9324c2999bc22b1ec7c1cd107228d1 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -111,8 +111,12 @@ #include "mac_scsi.h" #endif +#ifdef CONFIG_SUN3_SCSI +#include "sun3_scsi.h" +#endif + #ifdef CONFIG_MAC_SCSI -#include "mac_scsinew.h" +#include "mac_scsi.h" #endif #ifdef CONFIG_SCSI_MAC_ESP @@ -445,6 +449,10 @@ static Scsi_Host_Template builtin_scsi_hosts[] = #endif #endif +#ifdef CONFIG_SUN3_SCSI + SUN3_NCR5380, +#endif + #ifdef CONFIG_MVME16x_SCSI MVME16x_SCSI, #endif diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index 726bf4107db64d708896182229355cb3e14f32b8..036ffdf2c49dd67c854bc524cea08add73aeec20 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -22,25 +22,28 @@ #include <linux/blk.h> #include <linux/proc_fs.h> #include <linux/stat.h> +#include <linux/init.h> #include "scsi.h" #include "hosts.h" #include "NCR53C9x.h" #include "mac_esp.h" -#include "../../arch/m68k/mac/via6522.h" /* huh? */ - #include <asm/io.h> #include <asm/setup.h> #include <asm/irq.h> #include <asm/macints.h> #include <asm/machw.h> +#include <asm/mac_via.h> #include <asm/pgtable.h> #include <asm/macintosh.h> +#define mac_turnon_irq(x) mac_enable_irq(x) +#define mac_turnoff_irq(x) mac_disable_irq(x) + extern inline void esp_handle(struct NCR_ESP *esp); extern void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs); @@ -236,6 +239,8 @@ void mac_esp_setup(char *str, int *ints) { #endif } +__setup("mac53c9x=", mac_esp_setup); + /* * ESP address 'detection' */ diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 79009810706d83b3075b80f3a263c0c804441c96..3832fa2665411eccea1688e153dfa4776e4c31a5 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -1,95 +1,104 @@ /* - * mac_scsi.c -- Device dependent functions for the Macintosh NCR5380 SCSI - * port (MacII style machines, no DMA). + * Generic Macintosh NCR5380 driver * - * based on: + * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov> + * + * derived in part from: */ - /* - * atari_scsi.c -- Device dependent functions for the Atari generic SCSI port + * Generic Generic NCR5380 driver + * + * Copyright 1995, Russell King * - * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> + * ALPHA RELEASE 1. * - * Loosely based on the work of Robert De Vries' team and added: - * - working real DMA - * - Falcon support (untested yet!) ++bjoern fixed and now it works - * - lots of extensions and bug fixes. + * For more information, please consult * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. + * NCR 5380 Family + * SCSI Protocol Controller + * Databook * + * NCR Microelectronics + * 1635 Aeroplaza Drive + * Colorado Springs, CO 80916 + * 1+ (719) 578-3400 + * 1+ (800) 334-5454 */ -#include <linux/config.h> -#include <linux/module.h> - -#define NDEBUG_ABORT 0x800000 -#define NDEBUG_TAGS 0x1000000 -#define NDEBUG_MERGING 0x2000000 - -#define NDEBUG (0) - -#define AUTOSENSE -/* MSch: Tested the pseudo-DMA code on Atari for the Mac68k port ... */ -/* Defining neither PSEUDO_DMA nor REAL_DMA -> PIO transfer, sloooow ! */ -/*#define REAL_DMA*/ /* never supported on NCR5380 Macs */ /* - * Usage: define PSEUDO_DMA to use hardware-handshaked PIO mode (TBI) - * undef PSEUDO_DMA to use pure PIO mode + * Options : + * + * PARITY - enable parity checking. Not supported. + * + * SCSI2 - enable support for SCSI-II tagged queueing. Untested. + * + * USLEEP - enable support for devices that don't disconnect. Untested. */ -/*#define PSEUDO_DMA*/ /* currently gives trouble on some Macs */ +/* + * $Log: mac_NCR5380.c,v $ + */ -#ifdef PSEUDO_DMA -#define EMULATE_PSEUDO_DMA -#define DMA_WORKS_RIGHT -#define UNSAFE +#define AUTOSENSE +#if 0 +#define PSEUDO_DMA #endif -/* Support tagged queuing? (on devices that are able to... :-) */ -#define SUPPORT_TAGS -#define MAX_TAGS 32 - #include <linux/types.h> #include <linux/stddef.h> #include <linux/ctype.h> #include <linux/delay.h> -#include <linux/mm.h> -#include <linux/blk.h> + +#include <linux/module.h> +#include <linux/signal.h> #include <linux/sched.h> -#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/blk.h> -#include <asm/setup.h> -#include <asm/machw.h> -#include <asm/macints.h> -#include <asm/macintosh.h> -#include <asm/page.h> -#include <asm/pgtable.h> +#include <asm/io.h> #include <asm/irq.h> -#include <asm/traps.h> -#include <asm/bitops.h> +#include <asm/system.h> + +#include <asm/macintosh.h> +#include <asm/macints.h> +#include <asm/machw.h> +#include <asm/mac_via.h> #include "scsi.h" #include "hosts.h" #include "mac_scsi.h" #include "NCR5380.h" #include "constants.h" -#include <asm/io.h> -#include <linux/stat.h> +#if 0 +#define NDEBUG (NDEBUG_INTR | NDEBUG_PSEUDO_DMA | NDEBUG_ARBITRATION | NDEBUG_SELECTION | NDEBUG_RESELECTION) +#else +#define NDEBUG (NDEBUG_ABORT) +#endif -struct proc_dir_entry proc_scsi_mac = { - PROC_SCSI_MAC, 8, "mac_5380", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; +#define USE_WRAPPER +#define RESET_BOOT +#define DRIVER_SETUP /* - * Define RBV_HACK to run the SCSI driver on RBV Macs; undefine to - * try getting better interrupt latency + * BUG can be used to trigger a strange code-size related hang on 2.1 kernels + */ +#ifdef BUG +#undef RESET_BOOT +#undef DRIVER_SETUP +#endif + +/* + * Need to define this to make SCSI work on RBV machines; leave undefined + * to enable interrupts a bit more on other machines + * Changes method of SCSI interrupt disable from software mask to VIA IER! + * (don't know if that's essential) + * + * 990502 (jmt) - not needed (and won't work) on new irq architecture */ -#define RBV_HACK +/* #define RBV_HACK */ #ifdef RBV_HACK #define ENABLE_IRQ() mac_turnon_irq( IRQ_MAC_SCSI ); @@ -99,83 +108,18 @@ struct proc_dir_entry proc_scsi_mac = { #define DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI ); #endif -#define HOSTDATA_DMALEN (((struct NCR5380_hostdata *) \ - (mac_scsi_host->hostdata))->dma_len) - -/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms, - * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more - * need ten times the standard value... */ -#ifndef CONFIG_MAC_SCSI_TOSHIBA_DELAY -#define AFTER_RESET_DELAY (HZ/2) -#else -#define AFTER_RESET_DELAY (5*HZ/2) -#endif - -/***************************** Prototypes *****************************/ - -#ifdef REAL_DMA -static int scsi_dma_is_ignored_buserr( unsigned char dma_stat ); -static void mac_scsi_fetch_restbytes( void ); -static long mac_scsi_dma_residual( struct Scsi_Host *instance ); -static int mac_classify_cmd( Scsi_Cmnd *cmd ); -static unsigned long mac_dma_xfer_len( unsigned long wanted_len, - Scsi_Cmnd *cmd, int write_flag ); -#endif -#ifdef PSEUDO_DMA -static int mac_pdma_read(struct Scsi_Host *instance, unsigned char *dst, - int len); -static int mac_pdma_write(struct Scsi_Host *instance, unsigned char *src, - int len); -static unsigned long mac_dma_xfer_len( unsigned long wanted_len, - Scsi_Cmnd *cmd, int write_flag ); -#endif -static void scsi_mac_intr( int irq, void *dummy, struct pt_regs *fp); -static void mac_scsi_reset_boot( void ); -static unsigned char mac_scsi_reg_read( unsigned char reg ); -static void mac_scsi_reg_write( unsigned char reg, unsigned char value); - -/************************* End of Prototypes **************************/ +#define mac_turnon_irq(x) mac_enable_irq(x) +#define mac_turnoff_irq(x) mac_disable_irq(x) +extern void via_scsi_clear(void); -static struct Scsi_Host *mac_scsi_host = NULL; -#if 0 -static unsigned char (*mac_scsi_reg_read)( unsigned char reg ); -static void (*mac_scsi_reg_write)( unsigned char reg, unsigned char value ); +static void scsi_mac_intr(int irq, void *dummy, struct pt_regs *fp); +#ifdef RESET_BOOT +static void mac_scsi_reset_boot(struct Scsi_Host *instance); #endif +static char macscsi_read(struct Scsi_Host *instance, int reg); +static void macscsi_write(struct Scsi_Host *instance, int reg, int value); -#ifdef REAL_DMA -static unsigned long mac_dma_residual, mac_dma_startaddr; -static short mac_dma_active; -/* pointer to the dribble buffer */ -static char *mac_dma_buffer = NULL; -/* precalculated physical address of the dribble buffer */ -static unsigned long mac_dma_phys_buffer; -/* != 0 tells the int handler to copy data from the dribble buffer */ -static char *mac_dma_orig_addr; -/* size of the dribble buffer; 4k seems enough, since the Falcon cannot use - * scatter-gather anyway, so most transfers are 1024 byte only. In the rare - * cases where requests to physical contiguous buffers have been merged, this - * request is <= 4k (one page). So I don't think we have to split transfers - * just due to this buffer size... - */ -#define MAC_BUFFER_SIZE (4096) -#if 1 /* FIXME: is that an issue for Macs?? */ -/* mask for address bits that can't be used with the ST-DMA */ -static unsigned long mac_dma_stram_mask; -#define STRAM_ADDR(a) (((a) & mac_dma_stram_mask) == 0) -#endif -/* number of bytes to cut from a transfer to handle NCR overruns */ -static int mac_read_overruns = 0; -#endif -#ifdef PSEUDO_DMA -static unsigned long mac_pdma_residual, mac_pdma_startaddr, mac_pdma_current; -static short mac_pdma_active; -/* FIXME: is that an issue for Macs?? */ -/* mask for address bits that can't be used with the ST-DMA */ -static unsigned long mac_dma_stram_mask; -#define STRAM_ADDR(a) (((a) & mac_dma_stram_mask) == 0) -static int mac_read_overruns = 0; -#endif static int setup_can_queue = -1; static int setup_cmd_per_lun = -1; static int setup_sg_tablesize = -1; @@ -184,371 +128,39 @@ static int setup_use_tagged_queuing = -1; #endif static int setup_hostid = -1; - -#if defined(REAL_DMA) - -#if 0 /* FIXME */ -static int scsi_dma_is_ignored_buserr( unsigned char dma_stat ) -{ - int i; - unsigned long addr = SCSI_DMA_READ_P( dma_addr ), end_addr; - - if (dma_stat & 0x01) { - - /* A bus error happens when DMA-ing from the last page of a - * physical memory chunk (DMA prefetch!), but that doesn't hurt. - * Check for this case: - */ - - for( i = 0; i < boot_info.num_memory; ++i ) { - end_addr = boot_info.memory[i].addr + - boot_info.memory[i].size; - if (end_addr <= addr && addr <= end_addr + 4) - return( 1 ); - } - } - return( 0 ); -} - - -/* Dead code... wasn't called anyway :-) and causes some trouble, because at - * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has - * to clear the DMA int pending bit before it allows other level 6 interrupts. - */ -static void scsi_dma_buserr (int irq, void *dummy, struct pt_regs *fp) -{ - unsigned char dma_stat = tt_scsi_dma.dma_ctrl; - - /* Don't do anything if a NCR interrupt is pending. Probably it's just - * masked... */ - if (mac_irq_pending( IRQ_MAC_SCSI )) - return; - - printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n", - SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt)); - if (dma_stat & 0x80) { - if (!scsi_dma_is_ignored_buserr( dma_stat )) - printk( "SCSI DMA bus error -- bad DMA programming!\n" ); - } - else { - /* Under normal circumstances we never should get to this point, - * since both interrupts are triggered simultaneously and the 5380 - * int has higher priority. When this irq is handled, that DMA - * interrupt is cleared. So a warning message is printed here. - */ - printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" ); - } -} -#endif - -#endif - -void restore_irq(struct pt_regs *regs) -{ - unsigned long flags; - - save_flags(flags); - flags = (flags & ~0x0700) | (regs->sr & 0x0700); - restore_flags(flags); -} - static int polled_scsi_on = 0; -static unsigned char *mac_scsi_regp = NULL; - -void scsi_mac_polled (void) -{ - if (polled_scsi_on) - { - if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ) - { - printk("SCSI poll\n"); - scsi_mac_intr(IRQ_MAC_SCSI, NULL, NULL); - } - } -} - -static void scsi_mac_intr (int irq, void *dummy, struct pt_regs *fp) -{ - unsigned long flags; -#ifdef REAL_DMA - int dma_stat; - - dma_stat = mac_scsi_dma.dma_ctrl; - - INT_PRINTK("scsi%d: NCR5380 interrupt, DMA status = %02x\n", - mac_scsi_host->host_no, dma_stat & 0xff); - - /* Look if it was the DMA that has interrupted: First possibility - * is that a bus error occurred... - */ - if (dma_stat & 0x80) { - if (!scsi_dma_is_ignored_buserr( dma_stat )) { - printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n", - SCSI_DMA_READ_P(dma_addr)); - printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!"); - } - } - - /* If the DMA is active but not finished, we have the the case - * that some other 5380 interrupt occurred within the DMA transfer. - * This means we have residual bytes, if the desired end address - * is not yet reached. Maybe we have to fetch some bytes from the - * rest data register, too. The residual must be calculated from - * the address pointer, not the counter register, because only the - * addr reg counts bytes not yet written and pending in the rest - * data reg! - */ - if ((dma_stat & 0x02) && !(dma_stat & 0x40)) { - mac_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P( dma_addr ) - - mac_dma_startaddr); - - DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n", - mac_dma_residual); - - if ((signed int)mac_dma_residual < 0) - mac_dma_residual = 0; - if ((dma_stat & 1) == 0) { - /* After read operations, we maybe have to - transport some rest bytes */ - mac_scsi_fetch_restbytes(); - } - else { - /* There seems to be a nasty bug in some SCSI-DMA/NCR - combinations: If a target disconnects while a write - operation is going on, the address register of the - DMA may be a few bytes farer than it actually read. - This is probably due to DMA prefetching and a delay - between DMA and NCR. Experiments showed that the - dma_addr is 9 bytes to high, but this could vary. - The problem is, that the residual is thus calculated - wrong and the next transfer will start behind where - it should. So we round up the residual to the next - multiple of a sector size, if it isn't already a - multiple and the originally expected transfer size - was. The latter condition is there to ensure that - the correction is taken only for "real" data - transfers and not for, e.g., the parameters of some - other command. These shouldn't disconnect anyway. - */ - if (mac_dma_residual & 0x1ff) { - DMA_PRINTK("SCSI DMA: DMA bug corrected, " - "difference %ld bytes\n", - 512 - (mac_dma_residual & 0x1ff)); - mac_dma_residual = (mac_dma_residual + 511) & ~0x1ff; - } - } - mac_scsi_dma.dma_ctrl = 0; - } - - /* If the DMA is finished, fetch the rest bytes and turn it off */ - if (dma_stat & 0x40) { - atari_dma_residual = 0; - if ((dma_stat & 1) == 0) - atari_scsi_fetch_restbytes(); - tt_scsi_dma.dma_ctrl = 0; - } - -#endif /* REAL_DMA */ - -#ifdef PSEUDO_DMA - /* determine if there is any residual for the current transfer */ - if (mac_pdma_active) { - /* probably EOP interrupt, signaling i.e. target disconnect. - * We must figure out the residual from the source/destination - * pointers here ... */ - /* Should check bus status here to make sure it wasn't reselect or reset */ - mac_pdma_residual = HOSTDATA_DMALEN - (mac_pdma_current - mac_pdma_startaddr); - mac_pdma_active = 0; - } -#endif - -#ifdef RBV_HACK - mac_turnoff_irq( IRQ_MAC_SCSI ); -#else - mac_disable_irq( IRQ_MAC_SCSI ); -#endif - - save_flags(flags); -#ifndef RBV_HACK /* interferes with level triggered RBV IRQs ?? */ - restore_irq(fp); -#endif - - if ( irq == IRQ_IDX(IRQ_MAC_SCSI) ) - NCR5380_intr (irq, dummy, fp); - - restore_flags(flags); - - /* To be sure the int is not masked */ -#ifdef RBV_HACK - mac_turnon_irq( IRQ_MAC_SCSI ); -#else - mac_enable_irq( IRQ_MAC_SCSI ); -#endif - - /* Clear the IRQ */ - via_scsi_clear(); -} - - -#ifdef REAL_DMA -static void mac_scsi_fetch_restbytes( void ) -{ - int nr; - char *src, *dst; - - /* fetch rest bytes in the DMA register */ - dst = (char *)SCSI_DMA_READ_P( dma_addr ); - if ((nr = ((long)dst & 3))) { - /* there are 'nr' bytes left for the last long address before the - DMA pointer */ - dst = (char *)( (unsigned long)dst & ~3 ); - DMA_PRINTK("SCSI DMA: there are %d rest bytes for phys addr 0x%08lx", - nr, (long)dst); - dst = (char *)PTOV(dst); /* The content of the DMA pointer - * is a physical address! */ - DMA_PRINTK(" = virt addr 0x%08lx\n", (long)dst); - for( src = (char *)&mac_scsi_dma.dma_restdata; nr > 0; --nr ) - *dst++ = *src++; - } -} -#endif /* REAL_DMA */ - -#if 0 /* FIXME : how is the host ID determined on a Mac? */ -#define RTC_READ(reg) \ - ({ unsigned char __val; \ - outb(reg,&tt_rtc.regsel); \ - __val = tt_rtc.data; \ - __val; \ - }) - -#define RTC_WRITE(reg,val) \ - do { \ - outb(reg,&tt_rtc.regsel); \ - tt_rtc.data = (val); \ - } while(0) -#endif - -int mac_scsi_detect (Scsi_Host_Template *host) -{ - static int called = 0; - struct Scsi_Host *instance; - - if (!MACH_IS_MAC || called) - return( 0 ); - - if (macintosh_config->scsi_type != MAC_SCSI_OLD) - return( 0 ); - - host->proc_dir = &proc_scsi_mac; - - /* testing: IIfx SCSI without IOP ?? */ - if (macintosh_config->ident == MAC_MODEL_IIFX) - mac_scsi_regp = via1_regp+0x8000; - else - mac_scsi_regp = via1_regp+0x10000; - -#if 0 /* maybe if different SCSI versions show up ? */ - mac_scsi_reg_read = IS_A_TT() ? atari_scsi_tt_reg_read : - atari_scsi_falcon_reg_read; - mac_scsi_reg_write = IS_A_TT() ? atari_scsi_tt_reg_write : -#endif atari_scsi_falcon_reg_write; - - /* setup variables */ - host->can_queue = - (setup_can_queue > 0) ? setup_can_queue : - MAC_SCSI_CAN_QUEUE; - host->cmd_per_lun = - (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : - MAC_SCSI_CMD_PER_LUN; - host->sg_tablesize = - (setup_sg_tablesize >= 0) ? setup_sg_tablesize : MAC_SCSI_SG_TABLESIZE; - - if (setup_hostid >= 0) - host->this_id = setup_hostid; - else { - /* use 7 as default */ - host->this_id = 7; - } - -#ifdef SUPPORT_TAGS - if (setup_use_tagged_queuing < 0) - setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING; -#endif - instance = scsi_register (host, sizeof (struct NCR5380_hostdata)); - mac_scsi_host = instance; +/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms, + * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more + * need ten times the standard value... */ +#define TOSHIBA_DELAY - /* truncation of machspec bit not critical as instance->irq never used */ -#if 0 /* Might work; problem was only with Falcon lock */ - instance->irq = IRQ_MAC_SCSI; +#ifdef TOSHIBA_DELAY +#define AFTER_RESET_DELAY (5*HZ/2) #else - instance->irq = 0; -#endif - mac_scsi_reset_boot(); - NCR5380_init (instance, 0); - - /* This int is actually "pseudo-slow", i.e. it acts like a slow - * interrupt after having cleared the pending flag for the DMA - * interrupt. */ - request_irq(IRQ_MAC_SCSI, scsi_mac_intr, IRQ_TYPE_SLOW, - "SCSI NCR5380", scsi_mac_intr); -#ifdef REAL_DMA - tt_scsi_dma.dma_ctrl = 0; - atari_dma_residual = 0; - - if (is_brokenscsi) { - /* While the read overruns (described by Drew Eckhardt in - * NCR5380.c) never happened on TTs, they do in fact on the Medusa - * (This was the cause why SCSI didn't work right for so long - * there.) Since handling the overruns slows down a bit, I turned - * the #ifdef's into a runtime condition. - * - * In principle it should be sufficient to do max. 1 byte with - * PIO, but there is another problem on the Medusa with the DMA - * rest data register. So 'atari_read_overruns' is currently set - * to 4 to avoid having transfers that aren't a multiple of 4. If - * the rest data bug is fixed, this can be lowered to 1. - */ - mac_read_overruns = 4; - } -#endif /* REAL_DMA */ - -#ifdef PSEUDO_DMA - mac_pdma_residual = 0; - mac_pdma_active = 0; +#define AFTER_RESET_DELAY (HZ/2) #endif - printk(KERN_INFO "scsi%d: options CAN_QUEUE=%d CMD_PER_LUN=%d SCAT-GAT=%d " -#ifdef SUPPORT_TAGS - "TAGGED-QUEUING=%s " -#endif - "HOSTID=%d", - instance->host_no, instance->hostt->can_queue, - instance->hostt->cmd_per_lun, - instance->hostt->sg_tablesize, -#ifdef SUPPORT_TAGS - setup_use_tagged_queuing ? "yes" : "no", -#endif - instance->hostt->this_id ); - NCR5380_print_options (instance); - printk ("\n"); +static struct proc_dir_entry proc_scsi_mac5380 = { + PROC_SCSI_MAC, 13, "Mac 5380 SCSI", S_IFDIR | S_IRUGO, S_IXUGO, 2 +}; - called = 1; - return( 1 ); -} +static volatile unsigned char *mac_scsi_regp = NULL; +static volatile unsigned char *mac_scsi_drq = NULL; +static volatile unsigned char *mac_scsi_nodrq = NULL; -#ifdef MODULE -int mac_scsi_release (struct Scsi_Host *sh) -{ - free_irq(IRQ_MAC_SCSI, scsi_mac_intr); - if (mac_dma_buffer) - scsi_init_free (mac_dma_buffer, MAC_BUFFER_SIZE); - return 1; -} -#endif +/* + * Function : mac_scsi_setup(char *str, int *ints) + * + * Purpose : booter command line initialization of the overrides array, + * + * Inputs : str - unused, ints - array of integer parameters with ints[0] + * equal to the number of ints. + * + */ -void mac_scsi_setup( char *str, int *ints ) -{ +void mac_scsi_setup(char *str, int *ints) { +#ifdef DRIVER_SETUP /* Format of mac5380 parameter is: * mac5380=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags> * Negative values mean don't change. @@ -606,39 +218,145 @@ void mac_scsi_setup( char *str, int *ints ) setup_use_tagged_queuing = !!ints[5]; } #endif +#endif } -int mac_scsi_reset( Scsi_Cmnd *cmd, unsigned int reset_flags) +__setup("mac5380=", mac_scsi_setup); + +#if 0 +#define MAC_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800) +#define MAC_IRQ(card) ((card)->irq) +#endif + +/* + * XXX: status debug + */ +static struct Scsi_Host *default_instance; + +/* + * Function : int macscsi_detect(Scsi_Host_Template * tpnt) + * + * Purpose : initializes mac NCR5380 driver based on the + * command line / compile time port and irq definitions. + * + * Inputs : tpnt - template for this SCSI adapter. + * + * Returns : 1 if a host adapter was found, 0 if not. + * + */ + +int macscsi_detect(Scsi_Host_Template * tpnt) { - int rv; - struct NCR5380_hostdata *hostdata = - (struct NCR5380_hostdata *)cmd->host->hostdata; + int count = 0; + static int called = 0; + struct Scsi_Host *instance; - /* For doing the reset, SCSI interrupts must be disabled first, - * since the 5380 raises its IRQ line while _RST is active and we - * can't disable interrupts completely, since we need the timer. - */ - /* And abort a maybe active DMA transfer */ - mac_turnoff_irq( IRQ_MAC_SCSI ); -#ifdef REAL_DMA - mac_scsi_dma.dma_ctrl = 0; -#endif /* REAL_DMA */ -#ifdef PSEUDO_DMA - mac_pdma_active = 0; + if (!MACH_IS_MAC || called) + return( 0 ); + + if (macintosh_config->scsi_type != MAC_SCSI_OLD) + return( 0 ); + + tpnt->proc_dir = &proc_scsi_mac5380; + + /* setup variables */ + tpnt->can_queue = + (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE; + tpnt->cmd_per_lun = + (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN; + tpnt->sg_tablesize = + (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE; + + if (setup_hostid >= 0) + tpnt->this_id = setup_hostid; + else { + /* use 7 as default */ + tpnt->this_id = 7; + } + +#ifdef SUPPORT_TAGS + if (setup_use_tagged_queuing < 0) + setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING; #endif - rv = NCR5380_reset(cmd, reset_flags); +#if 0 /* loop over multiple adapters (Powerbooks ??) */ + for (count = 0; count < mac_num_scsi; count++) { +#endif + instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + default_instance = instance; - /* Re-enable ints */ - mac_turnon_irq( IRQ_MAC_SCSI ); + if (macintosh_config->ident == MAC_MODEL_IIFX) { + mac_scsi_regp = via1+0x8000; + mac_scsi_drq = via1+0xE000; + mac_scsi_nodrq = via1+0xC000; + } else { + mac_scsi_regp = via1+0x10000; + mac_scsi_drq = via1+0x6000; + mac_scsi_nodrq = via1+0x12000; + } + + + instance->io_port = (unsigned long) mac_scsi_regp; + instance->irq = IRQ_MAC_SCSI; + +#ifdef RESET_BOOT + mac_scsi_reset_boot(instance); +#endif + + NCR5380_init(instance, 0); + + instance->n_io_port = 255; + + ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; + + if (instance->irq != IRQ_NONE) +#ifdef USE_WRAPPER + if (request_irq(instance->irq, scsi_mac_intr, IRQ_FLG_SLOW, "MacSCSI-5380", NULL)) { +#else + if (request_irq(instance->irq, macscsi_intr, IRQ_FLG_SLOW, "MacSCSI-5380", NULL)) { +#endif + printk("scsi%d: IRQ%d not free, interrupts disabled\n", + instance->host_no, instance->irq); + instance->irq = IRQ_NONE; + } + + printk("scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port); + if (instance->irq == IRQ_NONE) + printk ("s disabled"); + else + printk (" %d", instance->irq); + printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", + instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE); + printk("\nscsi%d:", instance->host_no); + NCR5380_print_options(instance); + printk("\n"); +#if 0 /* multiple adapters */ + } +#endif + called = 1; + return 1; - return( rv ); } - -static void mac_scsi_reset_boot( void ) +int macscsi_release (struct Scsi_Host *shpnt) +{ + if (shpnt->irq != IRQ_NONE) + free_irq (shpnt->irq, NULL); + + return 0; +} + +#ifdef RESET_BOOT +/* + * Our 'bus reset on boot' function + */ + +static void mac_scsi_reset_boot(struct Scsi_Host *instance) { unsigned long end; + + NCR5380_local_declare(); + NCR5380_setup(instance); /* * Do a SCSI reset to clean up the bus during initialization. No messing @@ -662,7 +380,7 @@ static void mac_scsi_reset_boot( void ) NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); NCR5380_read( RESET_PARITY_INTERRUPT_REG ); - for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); ) + for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; ) barrier(); /* switch on SCSI IRQ again */ @@ -670,438 +388,359 @@ static void mac_scsi_reset_boot( void ) printk( " done\n" ); } +#endif +const char * macscsi_info (struct Scsi_Host *spnt) { + return ""; +} -const char * mac_scsi_info (struct Scsi_Host *host) +void restore_irq(struct pt_regs *regs) { - /* mac_scsi_detect() is verbose enough... */ - static const char string[] = "Macintosh NCR5380 SCSI"; - return string; -} + unsigned long flags; + save_flags(flags); + flags = (flags & ~0x0700) | (regs->sr & 0x0700); + restore_flags(flags); +} -#if defined(REAL_DMA) +#ifdef USE_WRAPPER +/* + * SCSI interrupt wrapper - just to make sure it's the proper irq, and + * that we leave the handler in a clean state + */ -unsigned long mac_scsi_dma_setup( struct Scsi_Host *instance, void *data, - unsigned long count, int dir ) +static void scsi_mac_intr (int irq, void *dev_id, struct pt_regs *fp) { - unsigned long addr = virt_to_phys( data ); - - DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, " - "dir = %d\n", instance->host_no, data, addr, count, dir); - - if (!STRAM_ADDR(addr)) { - /* If we have a non-DMAable address on a Falcon, use the dribble - * buffer; 'orig_addr' != 0 in the read case tells the interrupt - * handler to copy data from the dribble buffer to the originally - * wanted address. - */ - if (dir) - memcpy( mac_dma_buffer, data, count ); - else - mac_dma_orig_addr = data; - addr = mac_dma_phys_buffer; - } - - mac_dma_startaddr = addr; /* Needed for calculating residual later. */ - - /* Cache cleanup stuff: On writes, push any dirty cache out before sending - * it to the peripheral. (Must be done before DMA setup, since at least - * the ST-DMA begins to fill internal buffers right after setup. For - * reads, invalidate any cache, may be altered after DMA without CPU - * knowledge. - * - * ++roman: For the Medusa, there's no need at all for that cache stuff, - * because the hardware does bus snooping (fine!). - */ - dma_cache_maintenance( addr, count, dir ); +#ifndef RBV_HACK + unsigned long flags; +#endif + +#ifdef RBV_HACK + mac_turnoff_irq( IRQ_MAC_SCSI ); +#else + mac_disable_irq( IRQ_MAC_SCSI ); +#endif - if (count == 0) - printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n"); + if ( irq == IRQ_MAC_SCSI ) { +#ifndef RBV_HACK + save_flags(flags); + restore_irq(fp); +#endif + NCR5380_intr (irq, dev_id, fp); +#ifndef RBV_HACK + restore_flags(flags); +#endif + } - mac_scsi_dma.dma_ctrl = dir; - SCSI_DMA_WRITE_P( dma_addr, addr ); - SCSI_DMA_WRITE_P( dma_cnt, count ); - mac_scsi_dma.dma_ctrl = dir | 2; + /* To be sure the int is not masked */ +#ifdef RBV_HACK + mac_turnon_irq( IRQ_MAC_SCSI ); +#else + mac_enable_irq( IRQ_MAC_SCSI ); +#endif - return( count ); +#if 1 /* ??? 0 worked */ + /* Clear the IRQ */ + via_scsi_clear(); +#endif } +#endif +/* + * pseudo-DMA transfer functions, copied and modified from Russel King's + * ARM 5380 driver (cumana_1) + * + * Work in progress (sort of), didn't work last time I checked, don't use! + */ -static long mac_scsi_dma_residual( struct Scsi_Host *instance ) -{ - return( mac_dma_residual ); -} +#ifdef NOT_EFFICIENT +#define CTRL(p,v) outb(*ctrl = (v), (p) - 577) +#define STAT(p) inb((p)+1) +#define IN(p) inb((p)) +#define OUT(v,p) outb((v), (p)) +#else +#if 0 +#define CTRL(p,v) (p[-2308] = (*ctrl = (v))) +#else +#define CTRL(p,v) (*ctrl = (v)) +#endif +#define STAT(p) (p[1<<4]) +#define IN(p) (*(p)) +#define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p))) +#define OUT(v,p) (*(p) = (v)) +#define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v)) +#endif +#define L(v) (((v)<<16)|((v) & 0x0000ffff)) +#define H(v) (((v)>>16)|((v) & 0xffff0000)) +#define ioaddr(v) (v) +static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, + int len) +{ + int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; + int oldctrl = *ctrl; + unsigned long *laddr; +#ifdef NOT_EFFICIENT + int iobase = instance->io_port; + int dma_io = mac_scsi_nodrq; +#else + volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); + volatile unsigned char *dma_io = (unsigned char *)(mac_scsi_nodrq); +#endif + + if(!len) return 0; + + CTRL(iobase, 0x02); + laddr = (unsigned long *)addr; + while(len >= 32) + { + int status; + unsigned long v; + status = STAT(iobase); + if(status & 0x80) + goto end; + if(!(status & 0x40)) + continue; + v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); + v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); + v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); + v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); + v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); + v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); + v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); + v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); + len -= 32; + if(len == 0) + break; + } + + addr = (unsigned char *)laddr; + CTRL(iobase, 0x12); + while(len > 0) + { + int status; + status = STAT(iobase); + if(status & 0x80) + goto end; + if(status & 0x40) + { + OUT(*addr++, dma_io); + if(--len == 0) + break; + } -#define CMD_SURELY_BLOCK_MODE 0 -#define CMD_SURELY_BYTE_MODE 1 -#define CMD_MODE_UNKNOWN 2 + status = STAT(iobase); + if(status & 0x80) + goto end; + if(status & 0x40) + { + OUT(*addr++, dma_io); + if(--len == 0) + break; + } + } +end: + CTRL(iobase, oldctrl|0x40); + return len; +} -static int mac_classify_cmd( Scsi_Cmnd *cmd ) +static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, + int len) { - unsigned char opcode = cmd->cmnd[0]; - - if (opcode == READ_DEFECT_DATA || opcode == READ_LONG || - opcode == READ_BUFFER) - return( CMD_SURELY_BYTE_MODE ); - else if (opcode == READ_6 || opcode == READ_10 || - opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE || - opcode == RECOVER_BUFFERED_DATA) { - /* In case of a sequential-access target (tape), special care is - * needed here: The transfer is block-mode only if the 'fixed' bit is - * set! */ - if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1)) - return( CMD_SURELY_BYTE_MODE ); - else - return( CMD_SURELY_BLOCK_MODE ); - } - else - return( CMD_MODE_UNKNOWN ); + int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; + int oldctrl = *ctrl; + unsigned long *laddr; +#ifdef NOT_EFFICIENT + int iobase = instance->io_port; + int dma_io = mac_scsi_nodrq; +#else + volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); + volatile unsigned char *dma_io = (unsigned char *)((int)mac_scsi_nodrq); +#endif + + if(!len) return 0; + + CTRL(iobase, 0x00); + laddr = (unsigned long *)addr; + while(len >= 32) + { + int status; + status = STAT(iobase); + if(status & 0x80) + goto end; + if(!(status & 0x40)) + continue; + *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); + *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); + *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); + *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); + *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); + *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); + *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); + *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); + len -= 32; + if(len == 0) + break; + } + + addr = (unsigned char *)laddr; + CTRL(iobase, 0x10); + while(len > 0) + { + int status; + status = STAT(iobase); + if(status & 0x80) + goto end; + if(status & 0x40) + { + *addr++ = IN(dma_io); + if(--len == 0) + break; + } + + status = STAT(iobase); + if(status & 0x80) + goto end; + if(status & 0x40) + { + *addr++ = IN(dma_io); + if(--len == 0) + break; + } + } +end: + CTRL(iobase, oldctrl|0x40); + return len; } -#endif /* REAL_DMA */ +#undef STAT +#undef CTRL +#undef IN +#undef OUT -#if defined(REAL_DMA) || defined(PSEUDO_DMA) -/* This function calculates the number of bytes that can be transferred via - * DMA. On the TT, this is arbitrary, but on the Falcon we have to use the - * ST-DMA chip. There are only multiples of 512 bytes possible and max. - * 255*512 bytes :-( This means also, that defining READ_OVERRUNS is not - * possible on the Falcon, since that would require to program the DMA for - * n*512 - atari_read_overrun bytes. But it seems that the Falcon doesn't have - * the overrun problem, so this question is academic :-) +/* + * NCR 5380 register access functions */ -static unsigned long mac_dma_xfer_len( unsigned long wanted_len, - Scsi_Cmnd *cmd, - int write_flag ) +#ifdef ORIG +#if 0 +#define CTRL(p,v) outb(*ctrl = (v), (p) - 577) +#else +#define CTRL(p,v) (*ctrl = (v)) +#endif + +static char macscsi_read(struct Scsi_Host *instance, int reg) { - unsigned long possible_len, limit; - -#if defined(REAL_DMA) - if (IS_A_TT()) - /* TT SCSI DMA can transfer arbitrary #bytes */ - return( wanted_len ); - - /* ST DMA chip is stupid -- only multiples of 512 bytes! (and max. - * 255*512 bytes, but this should be enough) - * - * ++roman: Aaargl! Another Falcon-SCSI problem... There are some commands - * that return a number of bytes which cannot be known beforehand. In this - * case, the given transfer length is an "allocation length". Now it - * can happen that this allocation length is a multiple of 512 bytes and - * the DMA is used. But if not n*512 bytes really arrive, some input data - * will be lost in the ST-DMA's FIFO :-( Thus, we have to distinguish - * between commands that do block transfers and those that do byte - * transfers. But this isn't easy... there are lots of vendor specific - * commands, and the user can issue any command via the - * SCSI_IOCTL_SEND_COMMAND. - * - * The solution: We classify SCSI commands in 1) surely block-mode cmd.s, - * 2) surely byte-mode cmd.s and 3) cmd.s with unknown mode. In case 1) - * and 3), the thing to do is obvious: allow any number of blocks via DMA - * or none. In case 2), we apply some heuristic: Byte mode is assumed if - * the transfer (allocation) length is < 1024, hoping that no cmd. not - * explicitly known as byte mode have such big allocation lengths... - * BTW, all the discussion above applies only to reads. DMA writes are - * unproblematic anyways, since the targets aborts the transfer after - * receiving a sufficient number of bytes. - * - * Another point: If the transfer is from/to an non-ST-RAM address, we - * use the dribble buffer and thus can do only STRAM_BUFFER_SIZE bytes. - */ + int iobase = instance->io_port; + int i; + int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; - if (write_flag) { - /* Write operation can always use the DMA, but the transfer size must - * be rounded up to the next multiple of 512 (atari_dma_setup() does - * this). - */ - possible_len = wanted_len; - } - else { - /* Read operations: if the wanted transfer length is not a multiple of - * 512, we cannot use DMA, since the ST-DMA cannot split transfers - * (no interrupt on DMA finished!) - */ - if (wanted_len & 0x1ff) - possible_len = 0; - else { - /* Now classify the command (see above) and decide whether it is - * allowed to do DMA at all */ - switch( falcon_classify_cmd( cmd )) { - case CMD_SURELY_BLOCK_MODE: - possible_len = wanted_len; - break; - case CMD_SURELY_BYTE_MODE: - possible_len = 0; /* DMA prohibited */ - break; - case CMD_MODE_UNKNOWN: - default: - /* For unknown commands assume block transfers if the transfer - * size/allocation length is >= 1024 */ - possible_len = (wanted_len < 1024) ? 0 : wanted_len; - break; - } - } - } + CTRL(iobase, 0); +#if 0 + i = inb(iobase + 64 + reg); +#else + i = inb(iobase + reg<<4); +#endif + CTRL(iobase, 0x40); - /* Last step: apply the hard limit on DMA transfers */ - limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ? - STRAM_BUFFER_SIZE : 255*512; - if (possible_len > limit) - possible_len = limit; + return i; +} - if (possible_len != wanted_len) - DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes " - "instead of %ld\n", possible_len, wanted_len); +static void macscsi_write(struct Scsi_Host *instance, int reg, int value) +{ + int iobase = instance->io_port; + int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; -#else /* REAL_DMA */ - possible_len = wanted_len; + CTRL(iobase, 0); +#if 0 + outb(value, iobase + 64 + reg); +#else + outb(value, iobase + reg<<4); #endif - - return( possible_len ); + CTRL(iobase, 0x40); } -#endif /* REAL_DMA || PSEUDO_DMA */ - - -/* - * FIXME !!! - */ -/* NCR5380 register access functions - */ +#undef CTRL -static unsigned char mac_scsi_reg_read( unsigned char reg ) +#else +static char macscsi_read(struct Scsi_Host *instance, int reg) { return( mac_scsi_regp[reg << 4] ); } -static void mac_scsi_reg_write( unsigned char reg, unsigned char value ) +static void macscsi_write(struct Scsi_Host *instance, int reg, int value) { mac_scsi_regp[reg << 4] = value; } -#include "mac_NCR5380.c" +#endif -#ifdef PSEUDO_DMA +#include "NCR5380.c" /* - * slightly optimized PIO transfer routines, experimental! - * command may time out if interrupts are left enabled + * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; + * reentering NCR5380_print_status seems to have ugly side effects */ -static inline int mac_pdma_read (struct Scsi_Host *instance, unsigned char *dst, int len) +void scsi_mac_debug (void) { - register unsigned char *d = dst; - register i = len; - register unsigned char p, tmp; - -#if (NDEBUG & NDEBUG_PSEUDO_DMA) - printk("pdma_read: reading %d bytes to %p\n", len, dst); -#endif - - mac_pdma_residual = len; - if (mac_pdma_active) { - printk("pseudo-DMA already active in pread!\n"); - return -1; - } - mac_pdma_active = 1; - mac_pdma_startaddr = (unsigned long) dst; - mac_pdma_current = (unsigned long) dst; - - /* - * Get the phase from the bus (sanity check) - * Hopefully, the phase bits are valid here ... - */ - p = NCR5380_read(STATUS_REG) & PHASE_MASK; - if (!(p & SR_IO)) { - PDMA_PRINTK("NCR5380_pread: initial phase mismatch!\n"); - NCR_PRINT_PHASE(NDEBUG_ANY); - return -1; - } - - /* - * The NCR5380 chip will only drive the SCSI bus when the - * phase specified in the appropriate bits of the TARGET COMMAND - * REGISTER match the STATUS REGISTER - */ + unsigned long flags; + NCR5380_local_declare(); -#if 0 /* done in transfer_dma */ - p = PHASE_DATAIN; - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); + if (default_instance) { +#if 0 + NCR5380_setup(default_instance); + if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ) #endif - - for (; i; --i) { - HSH_PRINTK(" read %d ..", i); - /* check if we were interrupted ... */ - if (!mac_pdma_active) { - printk("pwrite: interrupt detected!\n"); - break; - } - - /* - * Wait for assertion of REQ, after which the phase bits will be - * valid - */ - while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ)) - barrier(); - - HSH_PRINTK(" REQ .."); - - /* Check for phase mismatch */ - if ((tmp & PHASE_MASK) != p) { - if (!mac_pdma_active) - printk("scsi%d : phase mismatch after interrupt\n", instance->host_no); - else - printk("scsi%d : phase mismatch w/o interrupt\n", instance->host_no); - NCR_PRINT_PHASE(NDEBUG_ANY); - break; + save_flags(flags); + cli(); + NCR5380_print_status(default_instance); + restore_flags(flags); } - - /* Do actual transfer from SCSI bus to memory */ - *d = NCR5380_read(CURRENT_SCSI_DATA_REG); - - d++; - - /* Handshake ... */ - - /* Assert ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); - HSH_PRINTK(" ACK .."); - - /* Wait for REQ to be dropped */ - while (NCR5380_read(STATUS_REG) & SR_REQ) - barrier(); - HSH_PRINTK(" /REQ .."); - - /* Drop ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - HSH_PRINTK(" /ACK !\n"); - - mac_pdma_current = (unsigned long) d; - mac_pdma_residual--; - } - -#if (NDEBUG & NDEBUG_PSEUDO_DMA) - printk("pdma_read: read at %d bytes to %p\n", i, dst); -#endif - - if (mac_pdma_residual) - printk("pread: leaving with residual %ld of %ld\n", - mac_pdma_residual, len); - mac_pdma_active = 0; - - /* ?? */ #if 0 - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); + polled_scsi_on = 1; #endif - return 0; } - -static inline int mac_pdma_write (struct Scsi_Host *instance, unsigned char *src, int len) -{ - register unsigned char *s = src; - register i = len; - register unsigned char p, tmp; +/* + * Helper function for interrupt trouble. More ugly side effects here. + */ -#if (NDEBUG & NDEBUG_PSEUDO_DMA) - printk("pdma_write: writing %d bytes from %p\n", len, src); +void scsi_mac_polled (void) +{ + unsigned long flags; + NCR5380_local_declare(); + struct Scsi_Host *instance; + +#if 0 + for (instance = first_instance; instance && (instance->hostt == + the_template); instance = instance->next) + if (instance->irq == IRQ_MAC_SCSI && polled_scsi_on) { +#else + instance = default_instance; #endif - - mac_pdma_residual = len; - if (mac_pdma_active) { - printk("pseudo-DMA already active in pwrite!\n"); - return -1; - } - mac_pdma_active = 1; - mac_pdma_startaddr = (unsigned long) src; - mac_pdma_current = (unsigned long) src; - - /* - * Get the phase from the bus (sanity check) - */ - p = NCR5380_read(STATUS_REG) & PHASE_MASK; - if (p & SR_IO) { - printk("NCR5380_pwrite: initial phase mismatch!\n"); - NCR_PRINT_PHASE(NDEBUG_ANY); - return -1; - } - - /* - * The NCR5380 chip will only drive the SCSI bus when the - * phase specified in the appropriate bits of the TARGET COMMAND - * REGISTER match the STATUS REGISTER - */ - -#if 0 /* already done in transfer_dma */ - p = PHASE_DATAOUT; - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); + NCR5380_setup(instance); + if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ) + { + printk("SCSI poll\n"); + save_flags(flags); + cli(); +#ifdef USE_WRAPPER + scsi_mac_intr(IRQ_MAC_SCSI, instance, NULL); +#else + macscsi_intr(IRQ_MAC_SCSI, instance, NULL); #endif - - for (; i; --i) { - /* check if we were interrupted ... */ - if (!mac_pdma_active) { - printk("pwrite: interrupt detected!\n"); - break; - } - - /* - * Wait for assertion of REQ, after which the phase bits will be - * valid - */ - while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ)); - - /* Check for phase mismatch */ - if ((tmp & PHASE_MASK) != p) { - if (!mac_pdma_active) - printk("scsi%d : phase mismatch after interrupt\n", instance->host_no); - else - printk("scsi%d : phase mismatch w/o interrupt\n", instance->host_no); - NCR_PRINT_PHASE(NDEBUG_ANY); - /* should we signal an error here?? */ - break; - } - - /* Do actual transfer to SCSI bus from memory */ - - NCR5380_write(OUTPUT_DATA_REG, *s); - - s++; - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA); - - /* Handshake ... assert ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ACK); - - /* ... wait for REQ to be dropped */ - while (NCR5380_read(STATUS_REG) & SR_REQ); - - /* and drop ACK (and DATA) ! */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - mac_pdma_current = (unsigned long) s; - mac_pdma_residual--; - } - -#if (NDEBUG & NDEBUG_PSEUDO_DMA) - printk("pdma_write: write at %d bytes from %p\n", i, src); + restore_flags(flags); + } +#if 0 + } #endif +} - if (mac_pdma_residual) - printk("pwrite: leaving with residual %ld of len %ld \n", - mac_pdma_residual, len); - mac_pdma_active = 0; - return 0; - -} -#endif /* PSEUDO_DMA */ #ifdef MODULE -Scsi_Host_Template driver_template = MAC_SCSI; + +Scsi_Host_Template driver_template = MAC_NCR5380; #include "scsi_module.c" #endif diff --git a/drivers/scsi/mac_scsi.h b/drivers/scsi/mac_scsi.h index da186f9d406b3b7af60c1d3656a8d92292d66da4..49a90965c34b3eeb28d4faa5b2029309adf02484 100644 --- a/drivers/scsi/mac_scsi.h +++ b/drivers/scsi/mac_scsi.h @@ -1,286 +1,110 @@ /* - * mac_scsi.h -- Header file for the Macintosh native SCSI driver + * Cumana Generic NCR5380 driver defines * - * based on Roman Hodeks atari_scsi.h - */ - -/* - * atari_scsi.h -- Header file for the Atari native SCSI driver + * Copyright 1993, Drew Eckhardt + * Visionary Computing + * (Unix and Linux consulting and custom programming) + * drew@colorado.edu + * +1 (303) 440-4894 * - * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> + * ALPHA RELEASE 1. * - * (Loosely based on the work of Robert De Vries' team) + * For more information, please consult * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. + * NCR 5380 Family + * SCSI Protocol Controller + * Databook * + * NCR Microelectronics + * 1635 Aeroplaza Drive + * Colorado Springs, CO 80916 + * 1+ (719) 578-3400 + * 1+ (800) 334-5454 */ +/* + * $Log: cumana_NCR5380.h,v $ + */ -#ifndef MAC_SCSI_H -#define MAC_SCSI_H - -/* (I_HAVE_OVERRUNS stuff removed) */ - -#ifndef ASM -int mac_scsi_abort (Scsi_Cmnd *); -int mac_scsi_detect (Scsi_Host_Template *); -const char * mac_scsi_info (struct Scsi_Host *host); -int mac_scsi_queue_command (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -int mac_scsi_reset (Scsi_Cmnd *, unsigned int); -int mac_scsi_proc_info (char *, char **, off_t, int, int, int); -#ifdef MODULE -int mac_scsi_release (struct Scsi_Host *); -#else -#define mac_scsi_release NULL -#endif - -/* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher - * values should work, too; try it! (but cmd_per_lun costs memory!) */ - -/* But there seems to be a bug somewhere that requires CAN_QUEUE to be - * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since - * changed CMD_PER_LUN... */ - -/* Note: The Falcon currently uses 8/1 setting due to unsolved problems with - * cmd_per_lun != 1 */ - -#define MAC_SCSI_CAN_QUEUE 16 -#define MAC_SCSI_CMD_PER_LUN 8 -#define MAC_SCSI_SG_TABLESIZE SG_ALL - -#define DEFAULT_USE_TAGGED_QUEUING 0 +#ifndef MAC_NCR5380_H +#define MAC_NCR5380_H +#define MACSCSI_PUBLIC_RELEASE 1 -#if defined (HOSTS_C) || defined (MODULE) -#define MAC_SCSI { NULL, NULL, NULL, \ - mac_scsi_proc_info, \ - "Macintosh NCR5380 SCSI", \ - mac_scsi_detect, \ - mac_scsi_release, \ - mac_scsi_info, \ - /* command */ NULL, \ - mac_scsi_queue_command, \ - mac_scsi_abort, \ - mac_scsi_reset, \ - /* slave_attach */ NULL, \ - /* bios_param */ NULL, \ - /* can queue */ 0, /* initialized at run-time */ \ - /* host_id */ 0, /* initialized at run-time */ \ - /* scatter gather */ 0, /* initialized at run-time */ \ - /* cmd per lun */ 0, /* initialized at run-time */ \ - /* present */ 0, \ - /* unchecked ISA DMA */ 0, \ - /* use_clustering */ DISABLE_CLUSTERING } +#ifndef ASM +int macscsi_abort (Scsi_Cmnd *); +int macscsi_detect (Scsi_Host_Template *); +int macscsi_release (struct Scsi_Host *); +const char *macscsi_info (struct Scsi_Host *); +int macscsi_reset(Scsi_Cmnd *, unsigned int); +int macscsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int macscsi_proc_info (char *buffer, char **start, off_t offset, + int length, int hostno, int inout); +#ifndef NULL +#define NULL 0 #endif -#ifndef HOSTS_C +#ifndef CMD_PER_LUN +#define CMD_PER_LUN 2 +#endif -#define NCR5380_implementation_fields /* none */ +#ifndef CAN_QUEUE +#define CAN_QUEUE 16 +#endif -#define NCR5380_read(reg) mac_scsi_reg_read( reg ) -#define NCR5380_write(reg, value) mac_scsi_reg_write( reg, value ) +#ifndef SG_TABLESIZE +#define SG_TABLESIZE SG_NONE +#endif -#define NCR5380_intr mac_scsi_intr -#define NCR5380_queue_command mac_scsi_queue_command -#define NCR5380_abort mac_scsi_abort -#define NCR5380_proc_info mac_scsi_proc_info -#define NCR5380_dma_read_setup(inst,d,c) mac_scsi_dma_setup (inst, d, c, 0) -#define NCR5380_dma_write_setup(inst,d,c) mac_scsi_dma_setup (inst, d, c, 1) -#define NCR5380_dma_residual(inst) mac_scsi_dma_residual( inst ) -#define NCR5380_dma_xfer_len(i,cmd,phase) \ - mac_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1) -#ifdef PSEUDO_DMA -#define NCR5380_pread(inst,d,l) mac_pdma_read (inst, d, l) -#define NCR5380_pwrite(inst,d,l) mac_pdma_write (inst, d, l) +#ifndef USE_TAGGED_QUEUING +#define USE_TAGGED_QUEUING 0 #endif -/* Debugging printk definitions: - * - * ARB -> arbitration - * ASEN -> auto-sense - * DMA -> DMA - * HSH -> PIO handshake - * INF -> information transfer - * INI -> initialization - * INT -> interrupt - * LNK -> linked commands - * MAIN -> NCR5380_main() control flow - * NDAT -> no data-out phase - * NWR -> no write commands - * PIO -> PIO transfers - * PDMA -> pseudo DMA (unused on MAC) - * QU -> queues - * RSL -> reselections - * SEL -> selections - * USL -> usleep cpde (unused on MAC) - * LBS -> last byte sent (unused on MAC) - * RSS -> restarting of selections - * EXT -> extended messages - * ABRT -> aborting and resetting - * TAG -> queue tag handling - * MER -> merging of consec. buffers - * - */ +#include <scsi/scsicam.h> -#if NDEBUG & NDEBUG_ARBITRATION -#define ARB_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define ARB_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_AUTOSENSE -#define ASEN_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define ASEN_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_DMA -#define DMA_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define DMA_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_HANDSHAKE -#define HSH_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define HSH_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_INFORMATION -#define INF_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define INF_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_INIT -#define INI_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define INI_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_INTR -#define INT_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define INT_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_LINKED -#define LNK_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define LNK_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_MAIN -#define MAIN_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define MAIN_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_NO_DATAOUT -#define NDAT_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define NDAT_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_NO_WRITE -#define NWR_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define NWR_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_PIO -#define PIO_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define PIO_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_PSEUDO_DMA -#define PDMA_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define PDMA_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_QUEUES -#define QU_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define QU_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_RESELECTION -#define RSL_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define RSL_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_SELECTION -#define SEL_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define SEL_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_USLEEP -#define USL_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define USL_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_LAST_BYTE_SENT -#define LBS_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define LBS_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_RESTART_SELECT -#define RSS_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define RSS_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_EXTENDED -#define EXT_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define EXT_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_ABORT -#define ABRT_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define ABRT_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_TAGS -#define TAG_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define TAG_PRINTK(format, args...) -#endif -#if NDEBUG & NDEBUG_MERGING -#define MER_PRINTK(format, args...) \ - printk(KERN_DEBUG format , ## args) -#else -#define MER_PRINTK(format, args...) -#endif +#define MAC_NCR5380 { \ +name: "Macintosh NCR5380 SCSI", \ +detect: macscsi_detect, \ +release: macscsi_release, /* Release */ \ +info: macscsi_info, \ +queuecommand: macscsi_queue_command, \ +abort: macscsi_abort, \ +reset: macscsi_reset, \ +bios_param: scsicam_bios_param, /* biosparam */ \ +can_queue: CAN_QUEUE, /* can queue */ \ +this_id: 7, /* id */ \ +sg_tablesize: SG_ALL, /* sg_tablesize */ \ +cmd_per_lun: CMD_PER_LUN, /* cmd per lun */ \ +unchecked_isa_dma: 0, /* unchecked_isa_dma */ \ +use_clustering: DISABLE_CLUSTERING \ + } -/* conditional macros for NCR5380_print_{,phase,status} */ +#ifndef HOSTS_C -#define NCR_PRINT(mask) \ - ((NDEBUG & (mask)) ? NCR5380_print(instance) : (void)0) +#define NCR5380_implementation_fields \ + int port, ctrl -#define NCR_PRINT_PHASE(mask) \ - ((NDEBUG & (mask)) ? NCR5380_print_phase(instance) : (void)0) +#define NCR5380_local_declare() \ + struct Scsi_Host *_instance -#define NCR_PRINT_STATUS(mask) \ - ((NDEBUG & (mask)) ? NCR5380_print_status(instance) : (void)0) +#define NCR5380_setup(instance) \ + _instance = instance -#define NDEBUG_ANY 0xffffffff +#define NCR5380_read(reg) macscsi_read(_instance, reg) +#define NCR5380_write(reg, value) macscsi_write(_instance, reg, value) +#define NCR5380_intr macscsi_intr +#define NCR5380_queue_command macscsi_queue_command +#define NCR5380_abort macscsi_abort +#define NCR5380_reset macscsi_reset +#define NCR5380_proc_info macscsi_proc_info -#endif /* else def HOSTS_C */ -#endif /* ndef ASM */ -#endif /* MAC_SCSI_H */ +#define BOARD_NORMAL 0 +#define BOARD_NCR53C400 1 +#endif /* ndef HOSTS_C */ +#endif /* ndef ASM */ +#endif /* MAC_NCR5380_H */ diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c new file mode 100644 index 0000000000000000000000000000000000000000..76930a9e055dd7f49e586a005ef89c44f868b0d7 --- /dev/null +++ b/drivers/scsi/sun3_scsi.c @@ -0,0 +1,420 @@ +/* + * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl) + * + * Adapted from mac_scsinew.c: + */ +/* + * Generic Macintosh NCR5380 driver + * + * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov> + * + * derived in part from: + */ +/* + * Generic Generic NCR5380 driver + * + * Copyright 1995, Russell King + * + * ALPHA RELEASE 1. + * + * For more information, please consult + * + * NCR 5380 Family + * SCSI Protocol Controller + * Databook + * + * NCR Microelectronics + * 1635 Aeroplaza Drive + * Colorado Springs, CO 80916 + * 1+ (719) 578-3400 + * 1+ (800) 334-5454 + */ + + +/* + * This is from mac_scsi.h, but hey, maybe this is usefull for Sun3 too! :) + * + * Options : + * + * PARITY - enable parity checking. Not supported. + * + * SCSI2 - enable support for SCSI-II tagged queueing. Untested. + * + * USLEEP - enable support for devices that don't disconnect. Untested. + */ + +/* + * $Log: mac_NCR5380.c,v $ + */ + +#define AUTOSENSE +#if 0 +#define PSEUDO_DMA +#endif + +#include <linux/types.h> +#include <linux/stddef.h> +#include <linux/ctype.h> +#include <linux/delay.h> + +#include <linux/module.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/blk.h> + +#include <asm/io.h> +#include <asm/system.h> + +#include <asm/sun3ints.h> + +#include "scsi.h" +#include "hosts.h" +#include "sun3_scsi.h" +#include "NCR5380.h" +#include "constants.h" + +#if 0 +#define NDEBUG (NDEBUG_INTR | NDEBUG_PSEUDO_DMA | NDEBUG_ARBITRATION | NDEBUG_SELECTION | NDEBUG_RESELECTION) +#define NCR_TIMEOUT 100 +#else +#define NDEBUG (NDEBUG_ABORT) +#endif + +#define USE_WRAPPER +#define RESET_BOOT +#define DRIVER_SETUP + +/* + * BUG can be used to trigger a strange code-size related hang on 2.1 kernels + */ +#ifdef BUG +#undef RESET_BOOT +#undef DRIVER_SETUP +#endif + +#define ENABLE_IRQ() sun3_enable_irq( IRQ_SUN3_SCSI ); +#define DISABLE_IRQ() sun3_enable_irq( IRQ_SUN3_SCSI ); + +/* extern void via_scsi_clear(void); */ + +static void scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp); +static char sun3scsi_read(struct Scsi_Host *instance, int reg); +static void sun3scsi_write(struct Scsi_Host *instance, int reg, int value); + +static int setup_can_queue = -1; +static int setup_cmd_per_lun = -1; +static int setup_sg_tablesize = -1; +#ifdef SUPPORT_TAGS +static int setup_use_tagged_queuing = -1; +#endif +static int setup_hostid = -1; + +static int polled_scsi_on = 0; + +#define AFTER_RESET_DELAY (HZ/2) + +static struct proc_dir_entry proc_scsi_sun3_5380 = { + PROC_SCSI_MAC, 13, "Sun3 5380 SCSI", S_IFDIR | S_IRUGO, S_IXUGO, 2 +}; + +static volatile unsigned char *sun3_scsi_regp = IOBASE_SUN3_SCSI; +/* +static volatile unsigned char *sun3_scsi_drq = NULL; +static volatile unsigned char *sun3_scsi_nodrq = NULL; +*/ + +/* + * Function : sun3_scsi_setup(char *str, int *ints) + * + * Purpose : booter command line initialization of the overrides array, + * + * Inputs : str - unused, ints - array of integer parameters with ints[0] + * equal to the number of ints. + * + * TODO: make it actually work! + * + */ + +void sun3_scsi_setup(char *str, int *ints) { + printk("sun3_scsi_setup() called\n"); + setup_can_queue = -1; + setup_cmd_per_lun = -1; + setup_sg_tablesize = -1; + setup_hostid = -1; +#ifdef SUPPORT_TAGS + setup_use_tagged_queuing = -1; +#endif + printk("sun3_scsi_setup() done\n"); +} + +/* + * XXX: status debug + */ +static struct Scsi_Host *default_instance; + +/* + * Function : int sun3scsi_detect(Scsi_Host_Template * tpnt) + * + * Purpose : initializes mac NCR5380 driver based on the + * command line / compile time port and irq definitions. + * + * Inputs : tpnt - template for this SCSI adapter. + * + * Returns : 1 if a host adapter was found, 0 if not. + * + */ + +int sun3scsi_detect(Scsi_Host_Template * tpnt) +{ + unsigned long ioaddr, iopte; + unsigned short *ioptr; + int count = 0; + static int called = 0; + struct Scsi_Host *instance; + + if(called) + return 0; + +printk("sun3scsi_detect(0x%p)\n",tpnt); + + tpnt->proc_dir = &proc_scsi_sun3_5380; + + /* setup variables */ + tpnt->can_queue = + (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE; + tpnt->cmd_per_lun = + (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN; + tpnt->sg_tablesize = + (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE; + + if (setup_hostid >= 0) + tpnt->this_id = setup_hostid; + else { + /* use 7 as default */ + tpnt->this_id = 7; + } + + /* Taken from Sammy's lance driver: */ + /* IOBASE_SUN3_SCSI can be found within the IO pmeg with some effort */ + for(ioaddr = 0xfe00000; ioaddr < (0xfe00000 + SUN3_PMEG_SIZE); + ioaddr += SUN3_PTE_SIZE) { + + iopte = sun3_get_pte(ioaddr); + if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */ + continue; + + if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) == + IOBASE_SUN3_SCSI) { + count = 1; +printk("Found ioaddr in pmeg\n"); + break; + } + } + + if(!count) { + printk("No Sun3 NCR5380 found!\n"); + return 0; + } + + sun3_scsi_regp = ioaddr; + + /* doing some stuff like resetting DVMA: */ + ioptr = ioaddr; + *(ioptr+8) = 0; + udelay(10); + *(ioptr+9) = 0; + udelay(10); + *(ioptr+12) = 0; + udelay(10); + *(ioptr+12) = 0x7; + udelay(10); + printk("SCSI status reg = %x\n", *(ioptr+12)); + udelay(10); + *(ioptr+13) = 0; + udelay(10); + +#ifdef SUPPORT_TAGS + if (setup_use_tagged_queuing < 0) + setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING; +#endif + + instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + default_instance = instance; + +/* + if (macintosh_config->ident == MAC_MODEL_IIFX) { + mac_scsi_regp = via1_regp+0x8000; + mac_scsi_drq = via1_regp+0x6000; + mac_scsi_nodrq = via1_regp+0x12000; + } else { + mac_scsi_regp = via1_regp+0x10000; + mac_scsi_drq = via1_regp+0x6000; + mac_scsi_nodrq = via1_regp+0x12000; + } +*/ + + instance->io_port = (unsigned long) ioaddr; + instance->irq = IRQ_SUN3_SCSI; + + NCR5380_init(instance, 0); + + instance->n_io_port = 32; + + ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; + + if (instance->irq != IRQ_NONE) + if (sun3_request_irq(instance->irq, sun3scsi_intr, + 0, "Sun3SCSI-5380", NULL)) { + printk("scsi%d: IRQ%d not free, interrupts disabled\n", + instance->host_no, instance->irq); + instance->irq = IRQ_NONE; + } + + printk("scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port); + if (instance->irq == IRQ_NONE) + printk ("s disabled"); + else + printk (" %d", instance->irq); + printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", + instance->can_queue, instance->cmd_per_lun, + SUN3SCSI_PUBLIC_RELEASE); + printk("\nscsi%d:", instance->host_no); + NCR5380_print_options(instance); + printk("\n"); + + called = 1; + return 1; +} + +int sun3scsi_release (struct Scsi_Host *shpnt) +{ + if (shpnt->irq != IRQ_NONE) + free_irq (shpnt->irq, NULL); + + return 0; +} + +#ifdef RESET_BOOT +/* + * Our 'bus reset on boot' function + */ + +static void sun3_scsi_reset_boot(struct Scsi_Host *instance) +{ + unsigned long end; + + NCR5380_local_declare(); + NCR5380_setup(instance); + + /* + * Do a SCSI reset to clean up the bus during initialization. No + * messing with the queues, interrupts, or locks necessary here. + */ + + printk( "Sun3 SCSI: resetting the SCSI bus..." ); + + /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */ + sun3_disable_irq( IRQ_SUN3_SCSI ); + + /* get in phase */ + NCR5380_write( TARGET_COMMAND_REG, + PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) )); + + /* assert RST */ + NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST ); + + /* The min. reset hold time is 25us, so 40us should be enough */ + udelay( 50 ); + + /* reset RST and interrupt */ + NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); + NCR5380_read( RESET_PARITY_INTERRUPT_REG ); + + for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; ) + barrier(); + + /* switch on SCSI IRQ again */ + sun3_enable_irq( IRQ_SUN3_SCSI ); + + printk( " done\n" ); +} +#endif + +const char * sun3scsi_info (struct Scsi_Host *spnt) { + return ""; +} + + +/* + * NCR 5380 register access functions + */ + +static char sun3scsi_read(struct Scsi_Host *instance, int reg) +{ +/* +printk("sun3scsi_read(instance=0x%p, reg=0x%x): @0x%p= %d\n",instance,reg,sun3_scsi_regp,sun3_scsi_regp[reg]); +*/ + return( sun3_scsi_regp[reg] ); +} + +static void sun3scsi_write(struct Scsi_Host *instance, int reg, int value) +{ +/* + printk("sun3scsi_write(instance=0x%p, reg=0x%x, value=0x%x)\n", instance, reg, value); +*/ + sun3_scsi_regp[reg] = value; +} + +#include "NCR5380.c" + +/* + * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; + * reentering NCR5380_print_status seems to have ugly side effects + */ + +void sun3_sun3_debug (void) +{ + unsigned long flags; + NCR5380_local_declare(); + + if (default_instance) { + save_flags(flags); + cli(); + NCR5380_print_status(default_instance); + restore_flags(flags); + } +#if 0 + polled_scsi_on = 1; +#endif +} +/* + * Helper function for interrupt trouble. More ugly side effects here. + */ + +void scsi_sun3_polled (void) +{ + unsigned long flags; + NCR5380_local_declare(); + struct Scsi_Host *instance; + + instance = default_instance; + NCR5380_setup(instance); + if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ) + { + printk("SCSI poll\n"); + save_flags(flags); + cli(); + sun3scsi_intr(IRQ_SUN3_SCSI, instance, NULL); + restore_flags(flags); + } +} + + +#ifdef MODULE + +Scsi_Host_Template driver_template = SUN3_NCR5380; + +#include "scsi_module.c" +#endif diff --git a/drivers/scsi/sun3_scsi.h b/drivers/scsi/sun3_scsi.h new file mode 100644 index 0000000000000000000000000000000000000000..c677bfbf614bd84b18b81d52be5b037f931b2c44 --- /dev/null +++ b/drivers/scsi/sun3_scsi.h @@ -0,0 +1,119 @@ +/* + * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl) + * + * Adapted from mac_scsinew.h: + */ +/* + * Cumana Generic NCR5380 driver defines + * + * Copyright 1993, Drew Eckhardt + * Visionary Computing + * (Unix and Linux consulting and custom programming) + * drew@colorado.edu + * +1 (303) 440-4894 + * + * ALPHA RELEASE 1. + * + * For more information, please consult + * + * NCR 5380 Family + * SCSI Protocol Controller + * Databook + * + * NCR Microelectronics + * 1635 Aeroplaza Drive + * Colorado Springs, CO 80916 + * 1+ (719) 578-3400 + * 1+ (800) 334-5454 + */ + +/* + * $Log: cumana_NCR5380.h,v $ + */ + +#ifndef SUN3_NCR5380_H +#define SUN3_NCR5380_H + +#define SUN3SCSI_PUBLIC_RELEASE 1 + +/* + * Int: level 2 autovector + * IO: type 1, base 0x00140000, 5 bits phys space: A<4..0> + */ +#define IRQ_SUN3_SCSI 2 +#define IOBASE_SUN3_SCSI 0x00140000 + +int sun3scsi_abort (Scsi_Cmnd *); +int sun3scsi_detect (Scsi_Host_Template *); +int sun3scsi_release (struct Scsi_Host *); +const char *sun3scsi_info (struct Scsi_Host *); +int sun3scsi_reset(Scsi_Cmnd *, unsigned int); +int sun3scsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int sun3scsi_proc_info (char *buffer, char **start, off_t offset, + int length, int hostno, int inout); + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef CMD_PER_LUN +#define CMD_PER_LUN 2 +#endif + +#ifndef CAN_QUEUE +#define CAN_QUEUE 16 +#endif + +#ifndef SG_TABLESIZE +#define SG_TABLESIZE SG_NONE +#endif + +#ifndef USE_TAGGED_QUEUING +#define USE_TAGGED_QUEUING 0 +#endif + +#include <scsi/scsicam.h> + +#define SUN3_NCR5380 { \ +name: "Sun3 NCR5380 SCSI", \ +detect: sun3scsi_detect, \ +release: sun3scsi_release, /* Release */ \ +info: sun3scsi_info, \ +queuecommand: sun3scsi_queue_command, \ +abort: sun3scsi_abort, \ +reset: sun3scsi_reset, \ +bios_param: scsicam_bios_param, /* biosparam */ \ +can_queue: CAN_QUEUE, /* can queue */ \ +this_id: 7, /* id */ \ +sg_tablesize: SG_ALL, /* sg_tablesize */ \ +cmd_per_lun: CMD_PER_LUN, /* cmd per lun */ \ +unchecked_isa_dma: 0, /* unchecked_isa_dma */ \ +use_clustering: DISABLE_CLUSTERING \ + } + +#ifndef HOSTS_C + +#define NCR5380_implementation_fields \ + int port, ctrl + +#define NCR5380_local_declare() \ + struct Scsi_Host *_instance + +#define NCR5380_setup(instance) \ + _instance = instance + +#define NCR5380_read(reg) sun3scsi_read(_instance, reg) +#define NCR5380_write(reg, value) sun3scsi_write(_instance, reg, value) + +#define NCR5380_intr sun3scsi_intr +#define NCR5380_queue_command sun3scsi_queue_command +#define NCR5380_abort sun3scsi_abort +#define NCR5380_reset sun3scsi_reset +#define NCR5380_proc_info sun3scsi_proc_info + +#define BOARD_NORMAL 0 +#define BOARD_NCR53C400 1 + +#endif /* ndef HOSTS_C */ +#endif /* SUN3_NCR5380_H */ + diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 8f163cd8ca75c2cc2d05bbe8480d309673e8b941..51d1cb05ed797aac7de61970a5cc1acfd2cc52e5 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -464,7 +464,7 @@ static int tt_encode_fix( struct fb_fix_screeninfo *fix, int mode; strcpy(fix->id,"Atari Builtin"); - fix->smem_start = real_screen_base; + fix->smem_start = (unsigned long)real_screen_base; fix->smem_len = screen_len; fix->type=FB_TYPE_INTERLEAVED_PLANES; fix->type_aux=2; @@ -797,7 +797,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, struct atafb_par *par ) { strcpy(fix->id, "Atari Builtin"); - fix->smem_start = real_screen_base; + fix->smem_start = (unsigned long)real_screen_base; fix->smem_len = screen_len; fix->type = FB_TYPE_INTERLEAVED_PLANES; fix->type_aux = 2; @@ -1760,7 +1760,7 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix, int mode; strcpy(fix->id,"Atari Builtin"); - fix->smem_start = real_screen_base; + fix->smem_start = (unsigned long)real_screen_base; fix->smem_len = screen_len; fix->type = FB_TYPE_INTERLEAVED_PLANES; fix->type_aux = 2; @@ -2104,7 +2104,7 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix, { strcpy(fix->id,"Unknown Extern"); - fix->smem_start=external_addr; + fix->smem_start = (unsigned long)external_addr; fix->smem_len = PAGE_ALIGN(external_len); if (external_depth == 1) { fix->type = FB_TYPE_PACKED_PIXELS; @@ -2488,7 +2488,7 @@ atafb_set_disp(int con, struct fb_info *info) atafb_get_var(&var, con, info); if (con == -1) con=0; - display->screen_base = fix.smem_start; + display->screen_base = (void *)fix.smem_start; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; diff --git a/fs/exec.c b/fs/exec.c index 44a43b356f90179917ce6430f0726edd39cdaedc..d94f55e5f4b986d896bb308d03f3d85a4c323c83 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -462,6 +462,7 @@ int flush_old_exec(struct linux_binprm * bprm) /* * Make sure we have a private signal table */ + task_lock(current); oldsig = current->sig; retval = make_private_signals(); if (retval) goto flush_failed; @@ -500,6 +501,7 @@ int flush_old_exec(struct linux_binprm * bprm) flush_signal_handlers(current); flush_old_files(current->files); + task_unlock(current); return 0; @@ -508,6 +510,7 @@ int flush_old_exec(struct linux_binprm * bprm) kfree(current->sig); flush_failed: current->sig = oldsig; + task_unlock(current); return retval; } diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index 356286fb2f277db8eb0b98fa4573a2de021f3594..a582fd5459ae3fd08dc07f00de54063f97b7de8e 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -23,7 +23,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, switch (cmd) { case EXT2_IOC_GETFLAGS: flags = inode->u.ext2_i.i_flags & EXT2_FL_USER_VISIBLE; - return put_user(inode->u.ext2_i.i_flags, (int *) arg); + return put_user(flags, (int *) arg); case EXT2_IOC_SETFLAGS: { unsigned int oldflags; diff --git a/fs/proc/Makefile b/fs/proc/Makefile index 38b59aed767f2bf30b9736e29f45525acafe4dba..28ff91997c612fe933831eb3d94c0bba70dfdd83 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile. O_TARGET := proc.o -O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \ +O_OBJS := inode.o root.o base.o generic.o array.o \ kmsg.o scsi.o proc_tty.o sysvipc.o proc_misc.o kcore.o ifdef CONFIG_OMIRR O_OBJS := $(O_OBJS) omirr.o diff --git a/fs/proc/array.c b/fs/proc/array.c index e72203cfae956c1feaf2cd63bd98efe1056819b2..03802b89230edde40cc5155a895d8a6973c9500b 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -70,401 +70,7 @@ #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/io.h> - - -static int open_kcore(struct inode * inode, struct file * filp) -{ - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -} - -extern ssize_t read_kcore(struct file *, char *, size_t, loff_t *); - -static struct file_operations proc_kcore_operations = { - NULL, /* lseek */ - read_kcore, - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - NULL, /* ioctl */ - NULL, /* mmap */ - open_kcore -}; - -struct inode_operations proc_kcore_inode_operations = { - &proc_kcore_operations, -}; - -/* - * This function accesses profiling information. The returned data is - * binary: the sampling step and the actual contents of the profile - * buffer. Use of the program readprofile is recommended in order to - * get meaningful info out of these data. - */ -static ssize_t read_profile(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - unsigned long p = *ppos; - ssize_t read; - char * pnt; - unsigned int sample_step = 1 << prof_shift; - - if (p >= (prof_len+1)*sizeof(unsigned int)) - return 0; - if (count > (prof_len+1)*sizeof(unsigned int) - p) - count = (prof_len+1)*sizeof(unsigned int) - p; - read = 0; - - while (p < sizeof(unsigned int) && count > 0) { - put_user(*((char *)(&sample_step)+p),buf); - buf++; p++; count--; read++; - } - pnt = (char *)prof_buffer + p - sizeof(unsigned int); - copy_to_user(buf,(void *)pnt,count); - read += count; - *ppos += read; - return read; -} - -/* - * Writing to /proc/profile resets the counters - * - * Writing a 'profiling multiplier' value into it also re-sets the profiling - * interrupt frequency, on architectures that support this. - */ -static ssize_t write_profile(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ -#ifdef __SMP__ - extern int setup_profiling_timer (unsigned int multiplier); - - if (count==sizeof(int)) { - unsigned int multiplier; - - if (copy_from_user(&multiplier, buf, sizeof(int))) - return -EFAULT; - - if (setup_profiling_timer(multiplier)) - return -EINVAL; - } -#endif - - memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer)); - return count; -} - -static struct file_operations proc_profile_operations = { - NULL, /* lseek */ - read_profile, - write_profile, -}; - -struct inode_operations proc_profile_inode_operations = { - &proc_profile_operations, -}; - -static struct page * get_phys_addr(struct mm_struct * mm, unsigned long ptr) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t pte; - - if (ptr >= TASK_SIZE) - return 0; - pgd = pgd_offset(mm,ptr); - if (pgd_none(*pgd)) - return 0; - if (pgd_bad(*pgd)) { - pgd_ERROR(*pgd); - pgd_clear(pgd); - return 0; - } - pmd = pmd_offset(pgd,ptr); - if (pmd_none(*pmd)) - return 0; - if (pmd_bad(*pmd)) { - pmd_ERROR(*pmd); - pmd_clear(pmd); - return 0; - } - pte = *pte_offset(pmd,ptr); - if (!pte_present(pte)) - return 0; - return pte_page(pte); -} - -static int get_array(struct mm_struct *mm, unsigned long start, unsigned long end, char * buffer) -{ - struct page *page; - unsigned long kaddr; - int size = 0, result = 0; - char c; - - if (start >= end) - return result; - for (;;) { - page = get_phys_addr(mm, start); - if (!page) - return result; - kaddr = kmap(page, KM_READ) + (start & ~PAGE_MASK); - do { - c = *(char *) kaddr; - if (!c) - result = size; - if (size < PAGE_SIZE) - buffer[size++] = c; - else { - kunmap(kaddr, KM_READ); - return result; - } - kaddr++; - start++; - if (!c && start >= end) { - kunmap(kaddr, KM_READ); - return result; - } - } while (kaddr & ~PAGE_MASK); - kunmap(kaddr, KM_READ); - } - return result; -} - -static struct mm_struct *get_mm(int pid) -{ - struct task_struct *p; - struct mm_struct *mm = NULL; - - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - if (p) - mm = p->mm; - if (mm) - atomic_inc(&mm->mm_users); - read_unlock(&tasklist_lock); - return mm; -} - - -static int get_env(int pid, char * buffer) -{ - struct mm_struct *mm = get_mm(pid); - int res = 0; - if (mm) { - res = get_array(mm, mm->env_start, mm->env_end, buffer); - mmput(mm); - } - return res; -} - -static int get_arg(int pid, char * buffer) -{ - struct mm_struct *mm = get_mm(pid); - int res = 0; - if (mm) { - res = get_array(mm, mm->arg_start, mm->arg_end, buffer); - mmput(mm); - } - return res; -} - -/* - * These bracket the sleeping functions.. - */ -extern void scheduling_functions_start_here(void); -extern void scheduling_functions_end_here(void); -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - -static unsigned long get_wchan(struct task_struct *p) -{ - if (!p || p == current || p->state == TASK_RUNNING) - return 0; -#if defined(__i386__) - { - unsigned long ebp, esp, eip; - unsigned long stack_page; - int count = 0; - - stack_page = (unsigned long)p; - esp = p->thread.esp; - if (!stack_page || esp < stack_page || esp > 8188+stack_page) - return 0; - /* include/asm-i386/system.h:switch_to() pushes ebp last. */ - ebp = *(unsigned long *) esp; - do { - if (ebp < stack_page || ebp > 8184+stack_page) - return 0; - eip = *(unsigned long *) (ebp+4); - if (eip < first_sched || eip >= last_sched) - return eip; - ebp = *(unsigned long *) ebp; - } while (count++ < 16); - } -#elif defined(__alpha__) - /* - * This one depends on the frame size of schedule(). Do a - * "disass schedule" in gdb to find the frame size. Also, the - * code assumes that sleep_on() follows immediately after - * interruptible_sleep_on() and that add_timer() follows - * immediately after interruptible_sleep(). Ugly, isn't it? - * Maybe adding a wchan field to task_struct would be better, - * after all... - */ - { - unsigned long schedule_frame; - unsigned long pc; - - pc = thread_saved_pc(&p->thread); - if (pc >= first_sched && pc < last_sched) { - schedule_frame = ((unsigned long *)p->thread.ksp)[6]; - return ((unsigned long *)schedule_frame)[12]; - } - return pc; - } -#elif defined(__mips__) - /* - * The same comment as on the Alpha applies here, too ... - */ - { - unsigned long schedule_frame; - unsigned long pc; - - pc = thread_saved_pc(&p->tss); - if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) { - schedule_frame = ((unsigned long *)(long)p->tss.reg30)[16]; - return (unsigned long)((unsigned long *)schedule_frame)[11]; - } - return pc; - } -#elif defined(__mc68000__) - { - unsigned long fp, pc; - unsigned long stack_page; - int count = 0; - - stack_page = (unsigned long)p; - fp = ((struct switch_stack *)p->thread.ksp)->a6; - do { - if (fp < stack_page+sizeof(struct task_struct) || - fp >= 8184+stack_page) - return 0; - pc = ((unsigned long *)fp)[1]; - /* FIXME: This depends on the order of these functions. */ - if (pc < first_sched || pc >= last_sched) - return pc; - fp = *(unsigned long *) fp; - } while (count++ < 16); - } -#elif defined(__powerpc__) - { - unsigned long ip, sp; - unsigned long stack_page = (unsigned long) p; - int count = 0; - - sp = p->thread.ksp; - do { - sp = *(unsigned long *)sp; - if (sp < stack_page || sp >= stack_page + 8188) - return 0; - if (count > 0) { - ip = *(unsigned long *)(sp + 4); - if (ip < first_sched || ip >= last_sched) - return ip; - } - } while (count++ < 16); - } -#elif defined(__arm__) - { - unsigned long fp, lr; - unsigned long stack_page; - int count = 0; - - stack_page = 4096 + (unsigned long)p; - fp = get_css_fp(&p->thread); - do { - if (fp < stack_page || fp > 4092+stack_page) - return 0; - lr = pc_pointer (((unsigned long *)fp)[-1]); - if (lr < first_sched || lr > last_sched) - return lr; - fp = *(unsigned long *) (fp - 12); - } while (count ++ < 16); - } -#elif defined (__sparc__) - { - unsigned long pc, fp, bias = 0; - unsigned long task_base = (unsigned long) p; - struct reg_window *rw; - int count = 0; - -#ifdef __sparc_v9__ - bias = STACK_BIAS; -#endif - fp = p->thread.ksp + bias; - do { - /* Bogus frame pointer? */ - if (fp < (task_base + sizeof(struct task_struct)) || - fp >= (task_base + (2 * PAGE_SIZE))) - break; - rw = (struct reg_window *) fp; - pc = rw->ins[7]; - if (pc < first_sched || pc >= last_sched) - return pc; - fp = rw->ins[6] + bias; - } while (++count < 16); - } -#endif - - return 0; -} - -#if defined(__i386__) -# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) -# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) -#elif defined(__alpha__) - /* - * See arch/alpha/kernel/ptrace.c for details. - */ -# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ - + (long)&((struct pt_regs *)0)->reg) -# define KSTK_EIP(tsk) \ - (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk))) -# define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) -#elif defined(__arm__) -# ifdef CONFIG_CPU_26 -# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) -# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020]) -# else -# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1021]) -# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) -# endif -#elif defined(__mc68000__) -#define KSTK_EIP(tsk) \ - ({ \ - unsigned long eip = 0; \ - if ((tsk)->thread.esp0 > PAGE_SIZE && \ - MAP_NR((tsk)->thread.esp0) < max_mapnr) \ - eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \ - eip; }) -#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) -#elif defined(__powerpc__) -#define KSTK_EIP(tsk) ((tsk)->thread.regs->nip) -#define KSTK_ESP(tsk) ((tsk)->thread.regs->gpr[1]) -#elif defined (__sparc_v9__) -# define KSTK_EIP(tsk) ((tsk)->thread.kregs->tpc) -# define KSTK_ESP(tsk) ((tsk)->thread.kregs->u_regs[UREG_FP]) -#elif defined(__sparc__) -# define KSTK_EIP(tsk) ((tsk)->thread.kregs->pc) -# define KSTK_ESP(tsk) ((tsk)->thread.kregs->u_regs[UREG_FP]) -#elif defined(__mips__) -# define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg \ - - sizeof(struct pt_regs)) -#define KSTK_TOS(tsk) ((unsigned long)(tsk) + KERNEL_STACK_SIZE - 32) -# define KSTK_EIP(tsk) (*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(cp0_epc))) -# define KSTK_ESP(tsk) (*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(regs[29]))) -#elif defined(__sh__) -# define KSTK_EIP(tsk) ((tsk)->thread.pc) -# define KSTK_ESP(tsk) ((tsk)->thread.sp) -#endif +#include <asm/processor.h> /* Gcc optimizes away "strlen(x)" for constant x */ #define ADDBUF(buffer, string) \ @@ -654,36 +260,27 @@ extern inline char *task_cap(struct task_struct *p, char *buffer) } -static int get_status(int pid, char * buffer) +/* task is locked, so we are safe here */ + +int proc_pid_status(struct task_struct *task, char * buffer) { char * orig = buffer; - struct task_struct *tsk; - struct mm_struct *mm = NULL; + struct mm_struct *mm = task->mm; - read_lock(&tasklist_lock); - tsk = find_task_by_pid(pid); - if (tsk) - mm = tsk->mm; - if (mm) - atomic_inc(&mm->mm_users); - read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */ - if (!tsk) - return 0; - buffer = task_name(tsk, buffer); - buffer = task_state(tsk, buffer); + buffer = task_name(task, buffer); + buffer = task_state(task, buffer); if (mm) buffer = task_mem(mm, buffer); - buffer = task_sig(tsk, buffer); - buffer = task_cap(tsk, buffer); - if (mm) - mmput(mm); + buffer = task_sig(task, buffer); + buffer = task_cap(task, buffer); return buffer - orig; } -static int get_stat(int pid, char * buffer) +/* task is locked, so we are safe here */ + +int proc_pid_stat(struct task_struct *task, char * buffer) { - struct task_struct *tsk; - struct mm_struct *mm = NULL; + struct mm_struct *mm = task->mm; unsigned long vsize, eip, esp, wchan; long priority, nice; int tty_pgrp; @@ -691,16 +288,7 @@ static int get_stat(int pid, char * buffer) char state; int res; - read_lock(&tasklist_lock); - tsk = find_task_by_pid(pid); - if (tsk) - mm = tsk->mm; - if (mm) - atomic_inc(&mm->mm_users); - read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */ - if (!tsk) - return 0; - state = *get_task_state(tsk); + state = *get_task_state(task); vsize = eip = esp = 0; if (mm) { struct vm_area_struct *vma; @@ -710,55 +298,55 @@ static int get_stat(int pid, char * buffer) vsize += vma->vm_end - vma->vm_start; vma = vma->vm_next; } - eip = KSTK_EIP(tsk); - esp = KSTK_ESP(tsk); + eip = KSTK_EIP(task); + esp = KSTK_ESP(task); up(&mm->mmap_sem); } - wchan = get_wchan(tsk); + wchan = get_wchan(task); - collect_sigign_sigcatch(tsk, &sigign, &sigcatch); + collect_sigign_sigcatch(task, &sigign, &sigcatch); - if (tsk->tty) - tty_pgrp = tsk->tty->pgrp; + if (task->tty) + tty_pgrp = task->tty->pgrp; else tty_pgrp = -1; /* scale priority and nice values from timeslices to -20..20 */ /* to make it look like a "normal" Unix priority/nice value */ - priority = tsk->counter; + priority = task->counter; priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY; - nice = tsk->priority; + nice = task->priority; nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY; res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \ %lu %lu %lu %lu %lu %lu %lu %lu %d %d\n", - pid, - tsk->comm, + task->pid, + task->comm, state, - tsk->p_pptr->pid, - tsk->pgrp, - tsk->session, - tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0, + task->p_pptr->pid, + task->pgrp, + task->session, + task->tty ? kdev_t_to_nr(task->tty->device) : 0, tty_pgrp, - tsk->flags, - tsk->min_flt, - tsk->cmin_flt, - tsk->maj_flt, - tsk->cmaj_flt, - tsk->times.tms_utime, - tsk->times.tms_stime, - tsk->times.tms_cutime, - tsk->times.tms_cstime, + task->flags, + task->min_flt, + task->cmin_flt, + task->maj_flt, + task->cmaj_flt, + task->times.tms_utime, + task->times.tms_stime, + task->times.tms_cutime, + task->times.tms_cstime, priority, nice, 0UL /* removed */, - tsk->it_real_value, - tsk->start_time, + task->it_real_value, + task->start_time, vsize, mm ? mm->rss : 0, /* you might want to shift this left 3 */ - tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0, + task->rlim ? task->rlim[RLIMIT_RSS].rlim_cur : 0, mm ? mm->start_code : 0, mm ? mm->end_code : 0, mm ? mm->start_stack : 0, @@ -768,17 +356,15 @@ static int get_stat(int pid, char * buffer) * It must be decimal for Linux 2.0 compatibility. * Use /proc/#/status for real-time signals. */ - tsk->signal .sig[0] & 0x7fffffffUL, - tsk->blocked.sig[0] & 0x7fffffffUL, + task->signal .sig[0] & 0x7fffffffUL, + task->blocked.sig[0] & 0x7fffffffUL, sigign .sig[0] & 0x7fffffffUL, sigcatch .sig[0] & 0x7fffffffUL, wchan, - tsk->nswap, - tsk->cnswap, - tsk->exit_signal, - tsk->processor); - if (mm) - mmput(mm); + task->nswap, + task->cnswap, + task->exit_signal, + task->processor); return res; } @@ -855,9 +441,9 @@ static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long en } } -static int get_statm(int pid, char * buffer) +int proc_pid_statm(struct task_struct *task, char * buffer) { - struct mm_struct *mm = get_mm(pid); + struct mm_struct *mm = task->mm; int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0; if (mm) { @@ -884,7 +470,6 @@ static int get_statm(int pid, char * buffer) vma = vma->vm_next; } up(&mm->mmap_sem); - mmput(mm); } return sprintf(buffer,"%d %d %d %d %d %d %d\n", size, resident, share, trs, lrs, drs, dt); @@ -923,10 +508,10 @@ static int get_statm(int pid, char * buffer) #define MAPS_LINE_MAX MAPS_LINE_MAX8 -static ssize_t read_maps (int pid, struct file * file, char * buf, +ssize_t proc_pid_read_maps (struct task_struct *task, struct file * file, char * buf, size_t count, loff_t *ppos) { - struct task_struct *p; + struct mm_struct *mm = task->mm; struct vm_area_struct * map, * next; char * destptr = buf, * buffer; loff_t lineno; @@ -942,25 +527,19 @@ static ssize_t read_maps (int pid, struct file * file, char * buf, if (!buffer) goto out; - retval = -EINVAL; - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */ - if (!p) - goto freepage_out; - - if (!p->mm || count == 0) + if (!mm || count == 0) goto getlen_out; /* Check whether the mmaps could change if we sleep */ - volatile_task = (p != current || atomic_read(&p->mm->mm_users) > 1); + volatile_task = (task != current || atomic_read(&mm->mm_users) > 1); /* decode f_pos */ lineno = *ppos >> MAPS_LINE_SHIFT; column = *ppos & (MAPS_LINE_LENGTH-1); /* quickly go to line lineno */ - for (map = p->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++) + down(&mm->mmap_sem); + for (map = mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++) continue; for ( ; map ; map = next ) { @@ -1019,7 +598,9 @@ static ssize_t read_maps (int pid, struct file * file, char * buf, i = len-column; if (i > count) i = count; + up(&mm->mmap_sem); copy_to_user(destptr, line+column, i); /* may have slept */ + down(&mm->mmap_sem); destptr += i; count -= i; column += i; @@ -1038,246 +619,34 @@ static ssize_t read_maps (int pid, struct file * file, char * buf, if (volatile_task) break; } + up(&mm->mmap_sem); /* encode f_pos */ *ppos = (lineno << MAPS_LINE_SHIFT) + column; getlen_out: retval = destptr - buf; - -freepage_out: free_page((unsigned long)buffer); out: return retval; } #ifdef __SMP__ -static int get_pidcpu(int pid, char * buffer) +int proc_pid_cpu(struct task_struct *task, char * buffer) { - struct task_struct * tsk = current ; int i, len; - read_lock(&tasklist_lock); - if (pid != tsk->pid) - tsk = find_task_by_pid(pid); - read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */ - - if (tsk == NULL) - return 0; - len = sprintf(buffer, "cpu %lu %lu\n", - tsk->times.tms_utime, - tsk->times.tms_stime); + task->times.tms_utime, + task->times.tms_stime); for (i = 0 ; i < smp_num_cpus; i++) len += sprintf(buffer + len, "cpu%d %lu %lu\n", i, - tsk->per_cpu_utime[cpu_logical_map(i)], - tsk->per_cpu_stime[cpu_logical_map(i)]); + task->per_cpu_utime[cpu_logical_map(i)], + task->per_cpu_stime[cpu_logical_map(i)]); return len; } #endif - -static int process_unauthorized(int type, int pid) -{ - struct task_struct *p; - uid_t euid=0; /* Save the euid keep the lock short */ - int ok = 0; - - read_lock(&tasklist_lock); - - /* - * Grab the lock, find the task, save the uid and - * check it has an mm still (ie its not dead) - */ - - p = find_task_by_pid(pid); - if (p) { - euid=p->euid; - ok = p->dumpable; - if(!cap_issubset(p->cap_permitted, current->cap_permitted)) - ok=0; - } - - read_unlock(&tasklist_lock); - - if (!p) - return 1; - - switch(type) { - case PROC_PID_STATUS: - case PROC_PID_STATM: - case PROC_PID_STAT: - case PROC_PID_MAPS: - case PROC_PID_CMDLINE: - case PROC_PID_CPU: - return 0; - } - if(capable(CAP_DAC_OVERRIDE) || (current->fsuid == euid && ok)) - return 0; - return 1; -} - - -static inline int get_process_array(char * page, int pid, int type) -{ - switch (type) { - case PROC_PID_STATUS: - return get_status(pid, page); - case PROC_PID_ENVIRON: - return get_env(pid, page); - case PROC_PID_CMDLINE: - return get_arg(pid, page); - case PROC_PID_STAT: - return get_stat(pid, page); - case PROC_PID_STATM: - return get_statm(pid, page); -#ifdef __SMP__ - case PROC_PID_CPU: - return get_pidcpu(pid, page); -#endif - } - return -EBADF; -} - -#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ - -static ssize_t array_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - struct inode * inode = file->f_dentry->d_inode; - unsigned long page; - char *start; - ssize_t length; - ssize_t end; - unsigned int type, pid; - struct proc_dir_entry *dp; - - if (count > PROC_BLOCK_SIZE) - count = PROC_BLOCK_SIZE; - if (!(page = __get_free_page(GFP_KERNEL))) - return -ENOMEM; - type = inode->i_ino; - pid = type >> 16; - type &= 0x0000ffff; - start = NULL; - dp = (struct proc_dir_entry *) inode->u.generic_ip; - - if (!pid) { /* can't happen */ - free_page(page); - return -EBADF; - } - - if (process_unauthorized(type, pid)) { - free_page(page); - return -EIO; - } - - length = get_process_array((char *) page, pid, type); - if (length < 0) { - free_page(page); - return length; - } - /* Static 4kB (or whatever) block capacity */ - if (*ppos >= length) { - free_page(page); - return 0; - } - if (count + *ppos > length) - count = length - *ppos; - end = count + *ppos; - copy_to_user(buf, (char *) page + *ppos, count); - *ppos = end; - free_page(page); - return count; -} - -static struct file_operations proc_array_operations = { - NULL, /* array_lseek */ - array_read, - NULL, /* array_write */ - NULL, /* array_readdir */ - NULL, /* array_poll */ - NULL, /* array_ioctl */ - NULL, /* mmap */ - NULL, /* no special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL /* can't fsync */ -}; - -struct inode_operations proc_array_inode_operations = { - &proc_array_operations, /* default base directory file-ops */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL /* revalidate */ -}; - -static ssize_t arraylong_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - struct inode * inode = file->f_dentry->d_inode; - unsigned int pid = inode->i_ino >> 16; - unsigned int type = inode->i_ino & 0x0000ffff; - - switch (type) { - case PROC_PID_MAPS: - return read_maps(pid, file, buf, count, ppos); - } - return -EINVAL; -} - -static struct file_operations proc_arraylong_operations = { - NULL, /* array_lseek */ - arraylong_read, - NULL, /* array_write */ - NULL, /* array_readdir */ - NULL, /* array_poll */ - NULL, /* array_ioctl */ - NULL, /* mmap */ - NULL, /* no special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL /* can't fsync */ -}; - -struct inode_operations proc_arraylong_inode_operations = { - &proc_arraylong_operations, /* default base directory file-ops */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL /* revalidate */ -}; diff --git a/fs/proc/base.c b/fs/proc/base.c index f0a0febf8860eb170128251ea2a1250e57817ad4..658da356237b1b23502c8dcae2098c31587a16d1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -14,28 +14,328 @@ #include <linux/proc_fs.h> #include <linux/stat.h> #include <linux/init.h> +#include <linux/file.h> -static struct file_operations proc_base_operations = { - NULL, /* lseek - default */ - NULL, /* read - bad */ - NULL, /* write - bad */ - proc_readdir, /* readdir */ - NULL, /* poll - default */ - NULL, /* ioctl - default */ - NULL, /* mmap */ - NULL, /* no special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL /* can't fsync */ +#define fake_ino(pid,ino) (((pid)<<16)|(ino)) + +ssize_t proc_pid_read_maps(struct task_struct*,struct file*,char*,size_t,loff_t*); +int proc_pid_stat(struct task_struct*,char*); +int proc_pid_status(struct task_struct*,char*); +int proc_pid_statm(struct task_struct*,char*); +int proc_pid_cpu(struct task_struct*,char*); + +static struct dentry *proc_fd_link(struct inode *inode) +{ + if (inode->u.proc_i.file) + return dget(inode->u.proc_i.file->f_dentry); + return NULL; +} + +static struct dentry *proc_exe_link(struct inode *inode) +{ + struct mm_struct * mm; + struct vm_area_struct * vma; + struct dentry *result = NULL; + struct task_struct *task = inode->u.proc_i.task; + + if (!task_lock(task)) + return NULL; + mm = task->mm; + if (!mm) + goto out; + down(&mm->mmap_sem); + vma = mm->mmap; + while (vma) { + if ((vma->vm_flags & VM_EXECUTABLE) && + vma->vm_file) { + result = dget(vma->vm_file->f_dentry); + break; + } + vma = vma->vm_next; + } + up(&mm->mmap_sem); +out: + task_unlock(task); + return result; +} + +static struct dentry *proc_cwd_link(struct inode *inode) +{ + struct dentry *result = NULL; + if (task_lock(inode->u.proc_i.task)) { + struct fs_struct *fs = inode->u.proc_i.task->fs; + if (fs) + result = dget(fs->pwd); + task_unlock(inode->u.proc_i.task); + } + return result; +} + +static struct dentry *proc_root_link(struct inode *inode) +{ + struct dentry *result = NULL; + if (task_lock(inode->u.proc_i.task)) { + struct fs_struct *fs = inode->u.proc_i.task->fs; + if (fs) + result = dget(fs->root); + task_unlock(inode->u.proc_i.task); + } + return result; +} + +/* task is locked and can't drop mm, so we are safe */ + +static int proc_pid_environ(struct task_struct *task, char * buffer) +{ + struct mm_struct *mm = task->mm; + int res = 0; + if (mm) + res = access_process_vm(task, mm->env_start, buffer, + mm->env_end - mm->env_start, 0); + return res; +} + +/* task is locked and can't drop mm, so we are safe */ + +static int proc_pid_cmdline(struct task_struct *task, char * buffer) +{ + struct mm_struct *mm = task->mm; + int res = 0; + if (mm) + res = access_process_vm(task, mm->arg_start, buffer, + mm->arg_end - mm->arg_start, 0); + return res; +} + +/************************************************************************/ +/* Here the fs part begins */ +/************************************************************************/ + +/* permission checks */ + +static int standard_permission(struct inode *inode, int mask) +{ + int mode = inode->i_mode; + + if ((mask & S_IWOTH) && IS_RDONLY(inode) && + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) + return -EROFS; /* Nobody gets write access to a read-only fs */ + else if ((mask & S_IWOTH) && IS_IMMUTABLE(inode)) + return -EACCES; /* Nobody gets write access to an immutable file */ + else if (current->fsuid == inode->i_uid) + mode >>= 6; + else if (in_group_p(inode->i_gid)) + mode >>= 3; + if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE)) + return 0; + /* read and search access */ + if ((mask == S_IROTH) || + (S_ISDIR(mode) && !(mask & ~(S_IROTH | S_IXOTH)))) + if (capable(CAP_DAC_READ_SEARCH)) + return 0; + return -EACCES; +} + +static int proc_permission(struct inode *inode, int mask) +{ + struct dentry *de, *base, *root; + struct super_block *our_sb, *sb, *below; + + if (standard_permission(inode, mask) != 0) + return -EACCES; + + base = current->fs->root; + de = root = proc_root_link(inode); /* Ewww... */ + + if (!de) + return -ENOENT; + + our_sb = base->d_inode->i_sb; + sb = de->d_inode->i_sb; + while (sb != our_sb) { + de = sb->s_root->d_covers; + below = de->d_inode->i_sb; + if (sb == below) + goto out; + sb = below; + } + + if (!is_subdir(de, base)) + goto out; + + dput(root); + return 0; +out: + dput(root); + return -EACCES; +} + +static ssize_t pid_maps_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + struct inode * inode = file->f_dentry->d_inode; + struct task_struct *task = inode->u.proc_i.task; + ssize_t res; + + if (!task_lock(task)) + return -EIO; + res = proc_pid_read_maps(task, file, buf, count, ppos); + task_unlock(task); + return res; +} + +static struct file_operations proc_maps_operations = { + NULL, /* array_lseek */ + pid_maps_read, }; -/* - * proc directories can do almost nothing.. - */ -static struct inode_operations proc_base_inode_operations = { - &proc_base_operations, /* default base directory file-ops */ +struct inode_operations proc_maps_inode_operations = { + &proc_maps_operations, /* default base directory file-ops */ +}; + +#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ + +static ssize_t proc_info_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + struct inode * inode = file->f_dentry->d_inode; + unsigned long page; + ssize_t length; + ssize_t end; + struct task_struct *task = inode->u.proc_i.task; + + if (count > PROC_BLOCK_SIZE) + count = PROC_BLOCK_SIZE; + if (!(page = __get_free_page(GFP_KERNEL))) + return -ENOMEM; + + if (!task_lock(task)) { + free_page(page); + return -EIO; + } + + length = inode->u.proc_i.op.proc_read(task, (char*)page); + + task_unlock(task); + + if (length < 0) { + free_page(page); + return length; + } + /* Static 4kB (or whatever) block capacity */ + if (*ppos >= length) { + free_page(page); + return 0; + } + if (count + *ppos > length) + count = length - *ppos; + end = count + *ppos; + copy_to_user(buf, (char *) page + *ppos, count); + *ppos = end; + free_page(page); + return count; +} + +static struct file_operations proc_info_file_operations = { + NULL, /* lseek */ + proc_info_read, /* read */ +}; + +struct inode_operations proc_info_inode_operations = { + &proc_info_file_operations, /* default proc file-ops */ +}; + +#define MAY_PTRACE(p) \ +(p==current||(p->p_pptr==current&&(p->flags&PF_PTRACED)&&p->state==TASK_STOPPED)) + +static ssize_t mem_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task; + char *page; + unsigned long src = *ppos; + int copied = 0; + + if (!MAY_PTRACE(task)) + return -ESRCH; + + page = (char *)__get_free_page(GFP_USER); + if (!page) + return -ENOMEM; + + while (count > 0) { + int this_len, retval; + + this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; + retval = access_process_vm(task, src, page, this_len, 0); + if (!retval) { + if (!copied) + copied = -EIO; + break; + } + if (copy_to_user(buf, page, retval)) { + copied = -EFAULT; + break; + } + copied += retval; + src += retval; + buf += retval; + count -= retval; + } + *ppos = src; + free_page((unsigned long) page); + return copied; +} + +static ssize_t mem_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + int copied = 0; + char *page; + struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task; + unsigned long dst = *ppos; + + if (!MAY_PTRACE(task)) + return -ESRCH; + + page = (char *)__get_free_page(GFP_USER); + if (!page) + return -ENOMEM; + + while (count > 0) { + int this_len, retval; + + this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; + if (copy_from_user(page, buf, this_len)) { + copied = -EFAULT; + break; + } + retval = access_process_vm(task, dst, page, this_len, 1); + if (!retval) { + if (!copied) + copied = -EIO; + break; + } + copied += retval; + buf += retval; + dst += retval; + count -= retval; + } + *ppos = dst; + free_page((unsigned long) page); + return copied; +} + +static struct file_operations proc_mem_operations = { + NULL, /* lseek - default */ + mem_read, + mem_write, +}; + +static struct inode_operations proc_mem_inode_operations = { + &proc_mem_operations, /* default base directory file-ops */ NULL, /* create */ - proc_lookup, /* lookup */ + NULL, /* lookup */ NULL, /* link */ NULL, /* unlink */ NULL, /* symlink */ @@ -50,161 +350,576 @@ static struct inode_operations proc_base_inode_operations = { NULL, /* writepage */ NULL, /* flushpage */ NULL, /* truncate */ - NULL, /* permission */ + proc_permission, /* permission */ NULL, /* smap */ NULL /* revalidate */ }; -/* - * The fill argument is non-zero when the inode is being filled ... - * we don't need to do anything when it's being deleted. - */ -static void proc_pid_fill_inode(struct inode * inode, int fill) +static struct dentry * proc_pid_follow_link(struct dentry *dentry, + struct dentry *base, + unsigned int follow) { - struct task_struct *p; - int pid = inode->i_ino >> 16; - int ino = inode->i_ino & 0xffff; + struct inode *inode = dentry->d_inode; + struct dentry * result; + int error; - read_lock(&tasklist_lock); - if (fill && (p = find_task_by_pid(pid)) != NULL) { - uid_t uid = 0; - gid_t gid = 0; - if (p->dumpable || ino == PROC_PID_INO) { - uid = p->euid; - gid = p->egid; - } - inode->i_uid = uid; - inode->i_gid = gid; + /* We don't need a base pointer in the /proc filesystem */ + dput(base); + + error = proc_permission(inode, MAY_EXEC); + result = ERR_PTR(error); + if (error) + goto out; + + result = inode->u.proc_i.op.proc_get_link(inode); +out: + if (!result) + result = ERR_PTR(-ENOENT); + return result; +} + +static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen) +{ + struct inode * inode; + char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern; + int len; + + if (!tmp) + return -ENOMEM; + + /* Check for special dentries.. */ + pattern = NULL; + inode = dentry->d_inode; + if (inode && IS_ROOT(dentry)) { + if (S_ISSOCK(inode->i_mode)) + pattern = "socket:[%lu]"; + if (S_ISFIFO(inode->i_mode)) + pattern = "pipe:[%lu]"; } - read_unlock(&tasklist_lock); + + if (pattern) { + len = sprintf(tmp, pattern, inode->i_ino); + path = tmp; + } else { + path = d_path(dentry, tmp, PAGE_SIZE); + len = tmp + PAGE_SIZE - 1 - path; + } + + if (len < buflen) + buflen = len; + copy_to_user(buffer, path, buflen); + free_page((unsigned long)tmp); + return buflen; } -/* - * This is really a pseudo-entry, and only links - * backwards to the parent with no link from the - * root directory to this. This way we can have just - * one entry for every /proc/<pid>/ directory. - */ -struct proc_dir_entry proc_pid = { - PROC_PID_INO, 5, "<pid>", - S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, - 0, &proc_base_inode_operations, - NULL, proc_pid_fill_inode, - NULL, &proc_root, NULL -}; - -static struct proc_dir_entry proc_pid_status = { - PROC_PID_STATUS, 6, "status", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_mem = { - PROC_PID_MEM, 3, "mem", - S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0, - 0, &proc_mem_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_cwd = { - PROC_PID_CWD, 3, "cwd", - S_IFLNK | S_IRWXU, 1, 0, 0, - 0, &proc_link_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_root = { - PROC_PID_ROOT, 4, "root", - S_IFLNK | S_IRWXU, 1, 0, 0, - 0, &proc_link_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_exe = { - PROC_PID_EXE, 3, "exe", - S_IFLNK | S_IRWXU, 1, 0, 0, - 0, &proc_link_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_fd = { - PROC_PID_FD, 2, "fd", - S_IFDIR | S_IRUSR | S_IXUSR, 2, 0, 0, - 0, &proc_fd_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_environ = { - PROC_PID_ENVIRON, 7, "environ", - S_IFREG | S_IRUSR, 1, 0, 0, - 0, &proc_array_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_cmdline = { - PROC_PID_CMDLINE, 7, "cmdline", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_stat = { - PROC_PID_STAT, 4, "stat", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_statm = { - PROC_PID_STATM, 5, "statm", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations, - NULL, proc_pid_fill_inode, -}; -static struct proc_dir_entry proc_pid_maps = { - PROC_PID_MAPS, 4, "maps", - S_IFIFO | S_IRUGO, 1, 0, 0, - 0, &proc_arraylong_inode_operations, - NULL, proc_pid_fill_inode, +static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen) +{ + int error; + struct inode *inode = dentry->d_inode; + + error = proc_permission(inode, MAY_EXEC); + if (error) + goto out; + + dentry = inode->u.proc_i.op.proc_get_link(inode); + error = -ENOENT; + if (!dentry) + goto out; + + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) + goto out; + + error = do_proc_readlink(dentry, buffer, buflen); + dput(dentry); +out: + return error; +} + +static struct inode_operations proc_pid_link_inode_operations = { + NULL, /* file-operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + proc_pid_readlink, /* readlink */ + proc_pid_follow_link, /* follow_link */ }; -#if CONFIG_AP1000 -static struct proc_dir_entry proc_pid_ringbuf = { - PROC_PID_RINGBUF, 7, "ringbuf", - S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0, - 0, &proc_ringbuf_inode_operations, - NULL, proc_pid_fill_inode, +/* reading from directory - bad */ + +static ssize_t proc_dir_read (struct file * filp, char * buf, + size_t count, loff_t *ppos) +{ + return -EISDIR; +} + +struct pid_entry { + int type; + int len; + char *name; + mode_t mode; }; + +#define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)} +static struct pid_entry base_stuff[] = { + E(PROC_PID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR), + E(PROC_PID_ENVIRON, "environ", S_IFREG|S_IRUSR), + E(PROC_PID_STATUS, "status", S_IFREG|S_IRUGO), + E(PROC_PID_CMDLINE, "cmdline", S_IFREG|S_IRUGO), + E(PROC_PID_STAT, "stat", S_IFREG|S_IRUGO), + E(PROC_PID_STATM, "statm", S_IFREG|S_IRUGO), +#ifdef SMP + E(PROC_PID_CPU, "cpu", S_IFREG|S_IRUGO), #endif +#if CONFIG_AP1000 + E(PROC_PID_RINGBUF, "ringbuf", S_IFREG|S_IRUGO|S_IWUSR), +#endif + E(PROC_PID_MAPS, "maps", S_IFREG|S_IRUGO), + E(PROC_PID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR), + E(PROC_PID_CWD, "cwd", S_IFLNK|S_IRWXUGO), + E(PROC_PID_ROOT, "root", S_IFLNK|S_IRWXUGO), + E(PROC_PID_EXE, "exe", S_IFLNK|S_IRWXUGO), + {0,0,NULL,0} +}; +#undef E -#ifdef __SMP__ -static struct proc_dir_entry proc_pid_cpu = { - PROC_PID_CPU, 3, "cpu", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations, - NULL, proc_pid_fill_inode, +#define NUMBUF 10 + +static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) +{ + struct inode *inode = filp->f_dentry->d_inode; + struct task_struct *p = inode->u.proc_i.task; + unsigned int fd, pid, ino; + int retval; + char buf[NUMBUF]; + + retval = 0; + pid = p->pid; + + fd = filp->f_pos; + switch (fd) { + case 0: + if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0) + goto out; + filp->f_pos++; + case 1: + ino = fake_ino(pid, PROC_PID_INO); + if (filldir(dirent, "..", 2, 1, ino) < 0) + goto out; + filp->f_pos++; + default: + for (fd = filp->f_pos-2; + p->p_pptr && p->files && fd < p->files->max_fds; + fd++, filp->f_pos++) { + unsigned int i,j; + + if (!fcheck_task(p, fd)) + continue; + + j = NUMBUF; + i = fd; + do { + j--; + buf[j] = '0' + (i % 10); + i /= 10; + } while (i); + + ino = fake_ino(pid, PROC_PID_FD_DIR + fd); + if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0) + break; + + } + } +out: + return retval; +} + +static int proc_base_readdir(struct file * filp, + void * dirent, filldir_t filldir) +{ + int i; + int pid; + struct inode *inode = filp->f_dentry->d_inode; + struct pid_entry *p; + + pid = inode->u.proc_i.task->pid; + if (!inode->u.proc_i.task->p_pptr) + return -ENOENT; + i = filp->f_pos; + switch (i) { + case 0: + if (filldir(dirent, ".", 1, i, inode->i_ino) < 0) + return 0; + i++; + filp->f_pos++; + /* fall through */ + case 1: + if (filldir(dirent, "..", 2, i, PROC_ROOT_INO) < 0) + return 0; + i++; + filp->f_pos++; + /* fall through */ + default: + i -= 2; + if (i>=sizeof(base_stuff)/sizeof(base_stuff[0])) + return 1; + p = base_stuff + i; + while (p->name) { + if (filldir(dirent, p->name, p->len, filp->f_pos, fake_ino(pid, p->type)) < 0) + return 0; + filp->f_pos++; + p++; + } + } + return 1; +} + +/* building an inode */ + +static struct inode *proc_pid_get_inode(struct super_block * sb, struct task_struct *task, int ino) +{ + struct inode * inode; + + /* We need a new inode */ + + inode = get_empty_inode(); + if (!inode) + goto out; + + /* Common stuff */ + + inode->i_sb = sb; + inode->i_dev = sb->s_dev; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + inode->i_ino = fake_ino(task->pid, ino); + + inode->u.proc_i.file = NULL; + /* + * grab the reference to task. + */ + inode->u.proc_i.task = task; + atomic_inc(&mem_map[MAP_NR(task)].count); + if (!task->p_pptr) + goto out_unlock; + + inode->i_uid = 0; + inode->i_gid = 0; + if (ino == PROC_PID_INO || task->dumpable) { + inode->i_uid = task->euid; + inode->i_gid = task->egid; + } + +out: + return inode; + +out_unlock: + iput(inode); + return NULL; +} + +/* dentry stuff */ + +static int pid_fd_revalidate(struct dentry * dentry, int flags) +{ + return 0; +} + +static int pid_base_revalidate(struct dentry * dentry, int flags) +{ + if (dentry->d_inode->u.proc_i.task->p_pptr) + return 1; + d_drop(dentry); + return 0; +} + +static void pid_delete_dentry(struct dentry * dentry) +{ + d_drop(dentry); +} + +static struct dentry_operations pid_fd_dentry_operations = +{ + pid_fd_revalidate, /* revalidate */ + NULL, /* d_hash */ + NULL, /* d_compare */ + pid_delete_dentry /* d_delete(struct dentry *) */ +}; + +static struct dentry_operations pid_dentry_operations = +{ + NULL, /* revalidate */ + NULL, /* d_hash */ + NULL, /* d_compare */ + pid_delete_dentry /* d_delete(struct dentry *) */ +}; + +static struct dentry_operations pid_base_dentry_operations = +{ + pid_base_revalidate, /* revalidate */ + NULL, /* d_hash */ + NULL, /* d_compare */ + pid_delete_dentry /* d_delete(struct dentry *) */ }; -#endif -void __init proc_base_init(void) +/* Lookups */ + +static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) { + unsigned int fd, c; + struct task_struct *task = dir->u.proc_i.task; + struct file * file; + struct files_struct * files; + struct inode *inode; + const char *name; + int len; + + fd = 0; + len = dentry->d_name.len; + name = dentry->d_name.name; + if (len > 1 && *name == '0') goto out; + while (len-- > 0) { + c = *name - '0'; + name++; + if (c > 9) + goto out; + fd *= 10; + fd += c; + if (fd & 0xffff8000) + goto out; + } + + inode = proc_pid_get_inode(dir->i_sb, task, PROC_PID_FD_DIR+fd); + if (!inode) + goto out; + /* FIXME */ + files = task->files; + if (!files) /* can we ever get here if that's the case? */ + goto out_unlock; + read_lock(&files->file_lock); + file = inode->u.proc_i.file = fcheck_task(task, fd); + if (!file) + goto out_unlock2; + get_file(file); + read_unlock(&files->file_lock); + inode->i_op = &proc_pid_link_inode_operations; + inode->i_size = 64; + inode->i_mode = S_IFLNK; + inode->u.proc_i.op.proc_get_link = proc_fd_link; + if (file->f_mode & 1) + inode->i_mode |= S_IRUSR | S_IXUSR; + if (file->f_mode & 2) + inode->i_mode |= S_IWUSR | S_IXUSR; + dentry->d_op = &pid_fd_dentry_operations; + d_add(dentry, inode); + return NULL; + +out_unlock2: + read_unlock(&files->file_lock); +out_unlock: + iput(inode); +out: + return ERR_PTR(-ENOENT); +} + +static struct file_operations proc_fd_operations = { + NULL, /* lseek - default */ + proc_dir_read, /* read - bad */ + NULL, /* write - bad */ + proc_readfd, /* readdir */ +}; + +/* + * proc directories can do almost nothing.. + */ +static struct inode_operations proc_fd_inode_operations = { + &proc_fd_operations, /* default base directory file-ops */ + NULL, /* create */ + proc_lookupfd, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* get_block */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* flushpage */ + NULL, /* truncate */ + proc_permission, /* permission */ +}; + +static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode; + int error; + struct task_struct *task = dir->u.proc_i.task; + struct pid_entry *p; + + error = -ENOENT; + inode = NULL; + + for (p = base_stuff; p->name; p++) { + if (p->len != dentry->d_name.len) + continue; + if (!memcmp(dentry->d_name.name, p->name, p->len)) + break; + } + if (!p->name) + goto out; + + error = -EINVAL; + inode = proc_pid_get_inode(dir->i_sb, task, p->type); + if (!inode) + goto out; + + inode->i_mode = p->mode; + /* + * Yes, it does not scale. And it should not. Don't add + * new entries into /proc/<pid>/ without very good reasons. + */ + switch(p->type) { + case PROC_PID_FD: + inode->i_nlink = 2; + inode->i_op = &proc_fd_inode_operations; + break; + case PROC_PID_EXE: + inode->i_op = &proc_pid_link_inode_operations; + inode->u.proc_i.op.proc_get_link = proc_exe_link; + break; + case PROC_PID_CWD: + inode->i_op = &proc_pid_link_inode_operations; + inode->u.proc_i.op.proc_get_link = proc_cwd_link; + break; + case PROC_PID_ROOT: + inode->i_op = &proc_pid_link_inode_operations; + inode->u.proc_i.op.proc_get_link = proc_root_link; + break; + case PROC_PID_ENVIRON: + inode->i_op = &proc_info_inode_operations; + inode->u.proc_i.op.proc_read = proc_pid_environ; + break; + case PROC_PID_STATUS: + inode->i_op = &proc_info_inode_operations; + inode->u.proc_i.op.proc_read = proc_pid_status; + break; + case PROC_PID_STAT: + inode->i_op = &proc_info_inode_operations; + inode->u.proc_i.op.proc_read = proc_pid_stat; + break; + case PROC_PID_CMDLINE: + inode->i_op = &proc_info_inode_operations; + inode->u.proc_i.op.proc_read = proc_pid_cmdline; + break; + case PROC_PID_STATM: + inode->i_op = &proc_info_inode_operations; + inode->u.proc_i.op.proc_read = proc_pid_statm; + break; + case PROC_PID_MAPS: + inode->i_op = &proc_maps_inode_operations; + break; +#ifdef SMP + case PROC_PID_CPU: + inode->i_op = &proc_info_inode_operations; + inode->u.proc_i.op.proc_read = proc_pid_cpu; + break; +#endif #if CONFIG_AP1000 - proc_register(&proc_pid, &proc_pid_ringbuf); + case PROC_PID_RINGBUF: + inode->i_op = &proc_ringbuf_inode_operations; + break; #endif - proc_register(&proc_pid, &proc_pid_status); - proc_register(&proc_pid, &proc_pid_mem); - proc_register(&proc_pid, &proc_pid_cwd); - proc_register(&proc_pid, &proc_pid_root); - proc_register(&proc_pid, &proc_pid_exe); - proc_register(&proc_pid, &proc_pid_fd); - proc_register(&proc_pid, &proc_pid_environ); - proc_register(&proc_pid, &proc_pid_cmdline); - proc_register(&proc_pid, &proc_pid_stat); - proc_register(&proc_pid, &proc_pid_statm); - proc_register(&proc_pid, &proc_pid_maps); -#ifdef __SMP__ - proc_register(&proc_pid, &proc_pid_cpu); -#endif -}; + case PROC_PID_MEM: + inode->i_op = &proc_mem_inode_operations; + break; + default: + printk("procfs: impossible type (%d)",p->type); + iput(inode); + return ERR_PTR(-EINVAL); + } + dentry->d_op = &pid_dentry_operations; + d_add(dentry, inode); + return NULL; +out: + return ERR_PTR(error); +} +static struct file_operations proc_base_operations = { + NULL, /* lseek - default */ + proc_dir_read, /* read - bad */ + NULL, /* write - bad */ + proc_base_readdir, /* readdir */ +}; + +static struct inode_operations proc_base_inode_operations = { + &proc_base_operations, /* default base directory file-ops */ + NULL, /* create */ + proc_base_lookup, /* lookup */ +}; +struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry) +{ + unsigned int pid, c; + struct task_struct *task; + const char *name; + struct inode *inode; + int len; + pid = 0; + name = dentry->d_name.name; + len = dentry->d_name.len; + while (len-- > 0) { + c = *name - '0'; + name++; + if (c > 9) + goto out; + pid *= 10; + pid += c; + if (!pid) + goto out; + if (pid & 0xffff0000) + goto out; + } + read_lock(&tasklist_lock); + task = find_task_by_pid(pid); + if (task) + atomic_inc(&mem_map[MAP_NR(task)].count); + read_unlock(&tasklist_lock); + if (!task) + goto out; + inode = proc_pid_get_inode(dir->i_sb, task, PROC_PID_INO); + free_task_struct(task); + if (!inode) + goto out; + inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; + inode->i_op = &proc_base_inode_operations; + inode->i_nlink = 3; + inode->i_flags|=S_IMMUTABLE; + dentry->d_op = &pid_base_dentry_operations; + d_add(dentry, inode); + return NULL; +out: + return ERR_PTR(-ENOENT); +} +void proc_pid_delete_inode(struct inode *inode) +{ + if (inode->u.proc_i.file) + fput(inode->u.proc_i.file); + free_task_struct(inode->u.proc_i.task); +} diff --git a/fs/proc/fd.c b/fs/proc/fd.c deleted file mode 100644 index 1862f6f5fd1f6c512d5536d30a2f0bf13907f35b..0000000000000000000000000000000000000000 --- a/fs/proc/fd.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * linux/fs/proc/fd.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * proc fd directory handling functions - * - * 01-May-98 Edgar Toernig <froese@gmx.de> - * Added support for more than 256 fds. - * Limit raised to 32768. - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/file.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> - -#include <asm/uaccess.h> - -static int proc_readfd(struct file *, void *, filldir_t); -static struct dentry *proc_lookupfd(struct inode *, struct dentry *); - -static struct file_operations proc_fd_operations = { - NULL, /* lseek - default */ - NULL, /* read - bad */ - NULL, /* write - bad */ - proc_readfd, /* readdir */ - NULL, /* poll - default */ - NULL, /* ioctl - default */ - NULL, /* mmap */ - NULL, /* no special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL /* can't fsync */ -}; - -/* - * proc directories can do almost nothing.. - */ -struct inode_operations proc_fd_inode_operations = { - &proc_fd_operations, /* default base directory file-ops */ - NULL, /* create */ - proc_lookupfd, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - NULL, /* truncate */ - proc_permission, /* permission */ - NULL, /* smap */ - NULL /* revalidate */ -}; - -/* - * NOTE! Normally we'd indicate that a file does not - * exist by creating a negative dentry and returning - * a successful return code. However, for this case - * we do not want to create negative dentries, because - * the state of the world can change behind our backs. - * - * Thus just return -ENOENT instead. - */ -static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) -{ - unsigned int ino, pid, fd, c; - struct task_struct * p; - struct file * file; - struct inode *inode; - const char *name; - int len, err; - - err = -ENOENT; - ino = dir->i_ino; - pid = ino >> 16; - ino &= 0x0000ffff; - - if (!pid || ino != PROC_PID_FD) - goto out; - - fd = 0; - len = dentry->d_name.len; - name = dentry->d_name.name; - if (len > 1 && *name == '0') goto out; - while (len-- > 0) { - c = *name - '0'; - name++; - if (c > 9) - goto out; - fd *= 10; - fd += c; - if (fd & 0xffff8000) - goto out; - } - - read_lock(&tasklist_lock); - file = NULL; - p = find_task_by_pid(pid); - if (p && p->files) - file = fcheck_task(p, fd); - read_unlock(&tasklist_lock); - - /* - * File handle is invalid if it is out of range, if the process - * has no files (Zombie) if the file is closed, or if its inode - * is NULL - */ - - if (!file) - goto out; - - ino = (pid << 16) + PROC_PID_FD_DIR + fd; - inode = proc_get_inode(dir->i_sb, ino, NULL); - if (inode) { - dentry->d_op = &proc_dentry_operations; - d_add(dentry, inode); - return NULL; - } -out: - return ERR_PTR(err); -} - -#define NUMBUF 10 - -static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) -{ - struct inode *inode = filp->f_dentry->d_inode; - struct task_struct *p, *tmp; - unsigned int fd, pid, ino; - int retval; - char buf[NUMBUF]; - - retval = 0; - ino = inode->i_ino; - pid = ino >> 16; - ino &= 0x0000ffff; - if (ino != PROC_PID_FD) - goto out; - - for (fd = filp->f_pos; fd < 2; fd++, filp->f_pos++) { - ino = inode->i_ino; - if (fd) - ino = (ino & 0xffff0000) | PROC_PID_INO; - if (filldir(dirent, "..", fd+1, fd, ino) < 0) - goto out; - } - - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - if (!p) - goto out_unlock; - - for (fd -= 2 ; p->files && fd < p->files->max_fds; fd++, filp->f_pos++) - { - unsigned int i,j; - - if (!fcheck_task(p, fd)) - continue; - - j = NUMBUF; - i = fd; - do { - j--; - buf[j] = '0' + (i % 10); - i /= 10; - } while (i); - - /* Drop the task lock, as the filldir function may block */ - read_unlock(&tasklist_lock); - - ino = (pid << 16) + PROC_PID_FD_DIR + fd; - if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0) - goto out; - - read_lock(&tasklist_lock); - /* - * filldir() might have slept, so we must - * re-validate "p". This is fast enough due - * to the pidhash - */ - tmp = find_task_by_pid(pid); - if (p != tmp) - break; - } -out_unlock: - read_unlock(&tasklist_lock); - -out: - return retval; -} diff --git a/fs/proc/inode.c b/fs/proc/inode.c index a5596e4ee404ed9e8b17afb7edeff8e66458e147..205f83fc45cbbd24e9174ad62392042ec2ef55c0 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -51,9 +51,7 @@ void de_put(struct proc_dir_entry *de) static void proc_put_inode(struct inode *inode) { #ifdef CONFIG_SUN_OPENPROMFS_MODULE - if ((inode->i_ino >= PROC_OPENPROM_FIRST) && - (inode->i_ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM) && - proc_openprom_use) + if (PROC_INODE_OPENPROM(inode) && proc_openprom_use) (*proc_openprom_use)(inode, 0); #endif /* @@ -71,11 +69,12 @@ static void proc_delete_inode(struct inode *inode) { struct proc_dir_entry *de = inode->u.generic_ip; -#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE) - if ((inode->i_ino >= PROC_OPENPROM_FIRST) && - (inode->i_ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM)) + if (PROC_INODE_PROPER(inode)) { + proc_pid_delete_inode(inode); + return; + } + if (PROC_INODE_OPENPROM(inode)) return; -#endif if (de) { /* @@ -142,113 +141,6 @@ static int parse_options(char *options,uid_t *uid,gid_t *gid) return 1; } -/* - * The standard rules, copied from fs/namei.c:permission(). - */ -static int standard_permission(struct inode *inode, int mask) -{ - int mode = inode->i_mode; - - if ((mask & S_IWOTH) && IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; /* Nobody gets write access to a read-only fs */ - else if ((mask & S_IWOTH) && IS_IMMUTABLE(inode)) - return -EACCES; /* Nobody gets write access to an immutable file */ - else if (current->fsuid == inode->i_uid) - mode >>= 6; - else if (in_group_p(inode->i_gid)) - mode >>= 3; - if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE)) - return 0; - /* read and search access */ - if ((mask == S_IROTH) || - (S_ISDIR(mode) && !(mask & ~(S_IROTH | S_IXOTH)))) - if (capable(CAP_DAC_READ_SEARCH)) - return 0; - return -EACCES; -} - -/* - * Set up permission rules for processes looking at other processes. - * You're not allowed to see a process unless it has the same or more - * restricted root than your own. This prevents a chrooted processes - * from escaping through the /proc entries of less restricted - * processes, and thus allows /proc to be safely mounted in a chrooted - * area. - * - * Note that root (uid 0) doesn't get permission for this either, - * since chroot is stronger than root. - * - * XXX TODO: use the dentry mechanism to make off-limits procs simply - * invisible rather than denied? Does each namespace root get its own - * dentry tree? - * - * This also applies the default permissions checks, as it only adds - * restrictions. - * - * Jeremy Fitzhardinge <jeremy@zip.com.au> - */ -int proc_permission(struct inode *inode, int mask) -{ - struct task_struct *p; - unsigned long ino = inode->i_ino; - unsigned long pid; - struct dentry *de, *base; - - if (standard_permission(inode, mask) != 0) - return -EACCES; - - /* - * Find the root of the processes being examined (if any). - * XXX Surely there's a better way of doing this? - */ - if (ino >= PROC_OPENPROM_FIRST && - ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM) - return 0; /* already allowed */ - - pid = ino >> 16; - if (pid == 0) - return 0; /* already allowed */ - - de = NULL; - base = current->fs->root; - - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - - if (p && p->fs) - de = p->fs->root; - read_unlock(&tasklist_lock); /* FIXME! */ - - if (p == NULL) - return -EACCES; /* ENOENT? */ - - if (de == NULL) - { - /* kswapd and bdflush don't have proper root or cwd... */ - return -EACCES; - } - - /* XXX locking? */ - for(;;) - { - struct dentry *parent; - - if (de == base) - return 0; /* already allowed */ - - de = de->d_covers; - parent = de->d_parent; - - if (de == parent) - break; - - de = parent; - } - - return -EACCES; /* incompatible roots */ -} - struct inode * proc_get_inode(struct super_block * sb, int ino, struct proc_dir_entry * de) { @@ -269,14 +161,9 @@ printk("proc_iget: using deleted entry %s, count=%d\n", de->name, de->count); goto out_fail; #ifdef CONFIG_SUN_OPENPROMFS_MODULE - if ((inode->i_ino >= PROC_OPENPROM_FIRST) - && (inode->i_ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM) - && proc_openprom_use) + if (PROC_INODE_OPENPROM(inode) && proc_openprom_use) (*proc_openprom_use)(inode, 1); #endif - /* N.B. How can this test ever fail?? */ - if (inode->i_sb != sb) - printk("proc_get_inode: inode fubar\n"); inode->u.generic_ip = (void *) de; if (de) { @@ -366,63 +253,7 @@ int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) void proc_read_inode(struct inode * inode) { - unsigned long ino, pid; - struct task_struct * p; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_blocks = 0; - inode->i_blksize = 1024; - ino = inode->i_ino; - if (ino >= PROC_OPENPROM_FIRST && - ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM) - goto out; - inode->i_op = NULL; - inode->i_mode = 0; - inode->i_uid = 0; - inode->i_gid = 0; - inode->i_nlink = 1; - inode->i_size = 0; - - pid = ino >> 16; - if (!pid) - goto out; - - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - if (!p) - goto out_unlock; - - ino &= 0x0000ffff; - if (ino == PROC_PID_INO || p->dumpable) { - inode->i_uid = p->euid; - inode->i_gid = p->egid; - } - if (ino & PROC_PID_FD_DIR) { - struct file * file; - ino &= 0x7fff; - if (!p->files) /* can we ever get here if that's the case? */ - goto out_unlock; - read_lock(&p->files->file_lock); - file = fcheck_task(p, ino); - if (!file) - goto out_unlock2; - - inode->i_op = &proc_link_inode_operations; - inode->i_size = 64; - inode->i_mode = S_IFLNK; - if (file->f_mode & 1) - inode->i_mode |= S_IRUSR | S_IXUSR; - if (file->f_mode & 2) - inode->i_mode |= S_IWUSR | S_IXUSR; -out_unlock2: - read_unlock(&p->files->file_lock); - } -out_unlock: - /* Defer unlocking until we're done with the task */ - read_unlock(&tasklist_lock); - -out: - return; } void proc_write_inode(struct inode * inode) diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index d58914e7d6185395c1b576e7daae06d1245a12ba..107f86e16333af04dee1969f79ee653547b27cd4 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c @@ -5,6 +5,7 @@ * Jeremy Fitzhardinge <jeremy@sw.oz.au> * Implemented by David Howells <David.Howells@nexor.co.uk> * Modified and incorporated into 2.3.x by Tigran Aivazian <tigran@sco.com> + * Support to dump module's data structures (ELF only), Tigran Aivazian <tigran@sco.com> */ #include <linux/config.h> @@ -14,6 +15,8 @@ #include <linux/a.out.h> #include <linux/elf.h> #include <linux/elfcore.h> +#include <linux/module.h> +#include <linux/proc_fs.h> #include <asm/uaccess.h> #ifdef CONFIG_KCORE_AOUT @@ -262,7 +265,7 @@ ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, char *page; /* work out how much file we allow to be read */ - size = ((size_t)high_memory - PAGE_OFFSET) + PAGE_SIZE; + proc_root_kcore.size = size = get_kcore_size(); acc = 0; /* see if file pointer already beyond EOF */ diff --git a/fs/proc/link.c b/fs/proc/link.c deleted file mode 100644 index 69d435600505983a3fb91f5083796476803f98a3..0000000000000000000000000000000000000000 --- a/fs/proc/link.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * linux/fs/proc/link.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * /proc link-file handling code - */ - -#include <asm/uaccess.h> - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> - -static int proc_readlink(struct dentry *, char *, int); -static struct dentry * proc_follow_link(struct dentry *, struct dentry *, unsigned int); - -/* - * links can't do much... - */ -static struct file_operations proc_fd_link_operations = { - NULL, /* lseek - default */ - NULL, /* read - bad */ - NULL, /* write - bad */ - NULL, /* readdir - bad */ - NULL, /* poll - default */ - NULL, /* ioctl - default */ - NULL, /* mmap */ - NULL, /* very special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL /* can't fsync */ -}; - -struct inode_operations proc_link_inode_operations = { - &proc_fd_link_operations,/* file-operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - proc_readlink, /* readlink */ - proc_follow_link, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - NULL, /* truncate */ - proc_permission, /* permission */ - NULL, /* smap */ - NULL /* revalidate */ -}; - -static struct dentry * proc_follow_link(struct dentry *dentry, - struct dentry *base, - unsigned int follow) -{ - struct inode *inode = dentry->d_inode; - struct task_struct *p; - struct dentry * result; - int ino, pid; - int error; - - /* We don't need a base pointer in the /proc filesystem */ - dput(base); - - error = permission(inode, MAY_EXEC); - result = ERR_PTR(error); - if (error) - goto out; - - ino = inode->i_ino; - pid = ino >> 16; - ino &= 0x0000ffff; - - result = ERR_PTR(-ENOENT); - - switch (ino) { - case PROC_PID_CWD: - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - if (p && p->fs && p->fs->pwd) - result = dget(p->fs->pwd); - read_unlock(&tasklist_lock); - break; - - case PROC_PID_ROOT: - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - if (p && p->fs && p->fs->root) - result = dget(p->fs->root); - read_unlock(&tasklist_lock); - break; - - case PROC_PID_EXE: { - struct mm_struct *mm = NULL; - struct vm_area_struct * vma; - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - if (p) - mm = p->mm; - if (mm) - atomic_inc(&mm->mm_users); - read_unlock(&tasklist_lock); - if (!mm) - break; - down(&mm->mmap_sem); - vma = mm->mmap; - while (vma) { - if ((vma->vm_flags & VM_EXECUTABLE) && - vma->vm_file) { - result = dget(vma->vm_file->f_dentry); - break; - } - vma = vma->vm_next; - } - up(&mm->mmap_sem); - mmput(mm); - break; - } - default: - if (ino & PROC_PID_FD_DIR) { - struct file * file; - struct files_struct *files = NULL; - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - if (p) - files = p->files; - read_unlock(&tasklist_lock); - if (!files) - break; - ino &= 0x7fff; - read_lock(&files->file_lock); - /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ - if (ino < files->max_fds && - (file = files->fd[ino]) && file->f_dentry) - result = dget(file->f_dentry); - read_unlock(&p->files->file_lock); - } - } -out: - return result; -} - -/* - * This pretty-prints the pathname of a dentry, - * clarifying sockets etc. - */ -static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen) -{ - struct inode * inode; - char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern; - int len; - - if(tmp==NULL) - return -ENOMEM; - - /* Check for special dentries.. */ - pattern = NULL; - inode = dentry->d_inode; - if (inode && IS_ROOT(dentry)) { - if (S_ISSOCK(inode->i_mode)) - pattern = "socket:[%lu]"; - if (S_ISFIFO(inode->i_mode)) - pattern = "pipe:[%lu]"; - } - - if (pattern) { - len = sprintf(tmp, pattern, inode->i_ino); - path = tmp; - } else { - path = d_path(dentry, tmp, PAGE_SIZE); - len = tmp + PAGE_SIZE - 1 - path; - } - - if (len < buflen) - buflen = len; - dput(dentry); - copy_to_user(buffer, path, buflen); - free_page((unsigned long)tmp); - return buflen; -} - -static int proc_readlink(struct dentry * dentry, char * buffer, int buflen) -{ - int error; - - dentry = proc_follow_link(dentry, NULL, 1); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = -ENOENT; - if (dentry) { - error = do_proc_readlink(dentry, buffer, buflen); - } - } - return error; -} diff --git a/fs/proc/mem.c b/fs/proc/mem.c deleted file mode 100644 index 410ea32f02537e290a5694c79f4d505f6352a2a8..0000000000000000000000000000000000000000 --- a/fs/proc/mem.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * linux/fs/proc/mem.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/proc_fs.h> -#include <linux/highmem.h> - -#include <asm/page.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/pgtable.h> - -/* - * mem_write isn't really a good idea right now. It needs - * to check a lot more: if the process we try to write to - * dies in the middle right now, mem_write will overwrite - * kernel memory.. This disables it altogether. - */ -#define mem_write NULL - -static int check_range(struct mm_struct * mm, unsigned long addr, int count) -{ - struct vm_area_struct *vma; - int retval; - - vma = find_vma(mm, addr); - if (!vma) - return -EACCES; - if (vma->vm_start > addr) - return -EACCES; - if (!(vma->vm_flags & VM_READ)) - return -EACCES; - while ((retval = vma->vm_end - addr) < count) { - struct vm_area_struct *next = vma->vm_next; - if (!next) - break; - if (vma->vm_end != next->vm_start) - break; - if (!(next->vm_flags & VM_READ)) - break; - vma = next; - } - if (retval > count) - retval = count; - return retval; -} - -static struct task_struct * get_task(int pid) -{ - struct task_struct * tsk = current; - - if (pid != tsk->pid) { - tsk = find_task_by_pid(pid); - - /* Allow accesses only under the same circumstances - * that we would allow ptrace to work. - */ - if (tsk) { - if (!(tsk->flags & PF_PTRACED) - || tsk->state != TASK_STOPPED - || tsk->p_pptr != current) - tsk = NULL; - } - } - return tsk; -} - -static ssize_t mem_read(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - struct inode * inode = file->f_dentry->d_inode; - pgd_t *page_dir; - pmd_t *page_middle; - pte_t pte; - struct page * page; - struct task_struct * tsk; - unsigned long addr; - unsigned long maddr; /* temporary mapped address */ - char *tmp; - ssize_t scount, i; - - read_lock(&tasklist_lock); - tsk = get_task(inode->i_ino >> 16); - read_unlock(&tasklist_lock); /* FIXME: This should really be done only afetr not using tsk any more!!! */ - if (!tsk) - return -ESRCH; - addr = *ppos; - scount = check_range(tsk->mm, addr, count); - if (scount < 0) - return scount; - tmp = buf; - while (scount > 0) { - if (signal_pending(current)) - break; - page_dir = pgd_offset(tsk->mm,addr); - if (pgd_none(*page_dir)) - break; - if (pgd_bad(*page_dir)) { - pgd_ERROR(*page_dir); - pgd_clear(page_dir); - break; - } - page_middle = pmd_offset(page_dir,addr); - if (pmd_none(*page_middle)) - break; - if (pmd_bad(*page_middle)) { - pmd_ERROR(*page_middle); - pmd_clear(page_middle); - break; - } - pte = *pte_offset(page_middle,addr); - if (!pte_present(pte)) - break; - page = pte_page(pte); - i = PAGE_SIZE-(addr & ~PAGE_MASK); - if (i > scount) - i = scount; - maddr = kmap(page, KM_READ); - copy_to_user(tmp, (char *)maddr + (addr & ~PAGE_MASK), i); - kunmap(maddr, KM_READ); - addr += i; - tmp += i; - scount -= i; - } - *ppos = addr; - return tmp-buf; -} - -#ifndef mem_write - -static ssize_t mem_write(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - struct inode * inode = file->f_dentry->d_inode; - pgd_t *page_dir; - pmd_t *page_middle; - pte_t pte; - struct page * page; - struct task_struct * tsk; - unsigned long addr; - unsigned long maddr; /* temporary mapped address */ - char *tmp; - long i; - - addr = *ppos; - tsk = get_task(inode->i_ino >> 16); - if (!tsk) - return -ESRCH; - tmp = buf; - while (count > 0) { - if (signal_pending(current)) - break; - page_dir = pgd_offset(tsk,addr); - if (pgd_none(*page_dir)) - break; - if (pgd_bad(*page_dir)) { - pgd_ERROR(*page_dir); - pgd_clear(page_dir); - break; - } - page_middle = pmd_offset(page_dir,addr); - if (pmd_none(*page_middle)) - break; - if (pmd_bad(*page_middle)) { - pmd_ERROR(*page_middle); - pmd_clear(page_middle); - break; - } - pte = *pte_offset(page_middle,addr); - if (!pte_present(pte)) - break; - if (!pte_write(pte)) - break; - page = pte_page(pte); - i = PAGE_SIZE-(addr & ~PAGE_MASK); - if (i > count) - i = count; - maddr = kmap(page, KM_WRITE); - copy_from_user((char *)maddr + (addr & ~PAGE_MASK), tmp, i); - kunmap(maddr, KM_WRITE); - addr += i; - tmp += i; - count -= i; - } - *ppos = addr; - if (tmp != buf) - return tmp-buf; - if (signal_pending(current)) - return -ERESTARTSYS; - return 0; -} - -#endif - -static long long mem_lseek(struct file * file, long long offset, int orig) -{ - switch (orig) { - case 0: - file->f_pos = offset; - return file->f_pos; - case 1: - file->f_pos += offset; - return file->f_pos; - default: - return -EINVAL; - } -} - -/* - * This isn't really reliable by any means.. - */ -int mem_mmap(struct file * file, struct vm_area_struct * vma) -{ - struct task_struct *tsk; - pgd_t *src_dir, *dest_dir; - pmd_t *src_middle, *dest_middle; - pte_t *src_table, *dest_table; - unsigned long stmp, etmp, dtmp, mapnr; - struct vm_area_struct *src_vma = NULL; - struct inode *inode = file->f_dentry->d_inode; - - /* Get the source's task information */ - - tsk = get_task(inode->i_ino >> 16); - - if (!tsk) - return -ESRCH; - - /* Ensure that we have a valid source area. (Has to be mmap'ed and - have valid page information.) We can't map shared memory at the - moment because working out the vm_area_struct & nattach stuff isn't - worth it. */ - - src_vma = tsk->mm->mmap; - stmp = vma->vm_pgoff << PAGE_SHIFT; - etmp = stmp + vma->vm_end - vma->vm_start; - while (stmp < etmp) { - while (src_vma && stmp > src_vma->vm_end) - src_vma = src_vma->vm_next; - if (!src_vma || (src_vma->vm_flags & VM_SHM)) - return -EINVAL; - - src_dir = pgd_offset(tsk->mm, stmp); - if (pgd_none(*src_dir)) - return -EINVAL; - if (pgd_bad(*src_dir)) { - pgd_ERROR(*src_dir); - return -EINVAL; - } - src_middle = pmd_offset(src_dir, stmp); - if (pmd_none(*src_middle)) - return -EINVAL; - if (pmd_bad(*src_middle)) { - pmd_ERROR(*src_middle); - return -EINVAL; - } - src_table = pte_offset(src_middle, stmp); - if (pte_none(*src_table)) - return -EINVAL; - - if (stmp < src_vma->vm_start) { - if (!(src_vma->vm_flags & VM_GROWSDOWN)) - return -EINVAL; - if (src_vma->vm_end - stmp > current->rlim[RLIMIT_STACK].rlim_cur) - return -EINVAL; - } - stmp += PAGE_SIZE; - } - - src_vma = tsk->mm->mmap; - stmp = vma->vm_pgoff << PAGE_SHIFT; - dtmp = vma->vm_start; - - flush_cache_range(vma->vm_mm, vma->vm_start, vma->vm_end); - flush_cache_range(src_vma->vm_mm, src_vma->vm_start, src_vma->vm_end); - while (dtmp < vma->vm_end) { - while (src_vma && stmp > src_vma->vm_end) - src_vma = src_vma->vm_next; - - src_dir = pgd_offset(tsk->mm, stmp); - src_middle = pmd_offset(src_dir, stmp); - src_table = pte_offset(src_middle, stmp); - - dest_dir = pgd_offset(current->mm, dtmp); - dest_middle = pmd_alloc(dest_dir, dtmp); - if (!dest_middle) - return -ENOMEM; - dest_table = pte_alloc(dest_middle, dtmp); - if (!dest_table) - return -ENOMEM; - - if (!pte_present(*src_table)) - handle_mm_fault(tsk, src_vma, stmp, 1); - - if ((vma->vm_flags & VM_WRITE) && !pte_write(*src_table)) - handle_mm_fault(tsk, src_vma, stmp, 1); - - set_pte(src_table, pte_mkdirty(*src_table)); - set_pte(dest_table, *src_table); - mapnr = pte_pagenr(*src_table); - if (mapnr < max_mapnr) - get_page(mem_map + pte_pagenr(*src_table)); - - stmp += PAGE_SIZE; - dtmp += PAGE_SIZE; - } - - flush_tlb_range(vma->vm_mm, vma->vm_start, vma->vm_end); - flush_tlb_range(src_vma->vm_mm, src_vma->vm_start, src_vma->vm_end); - return 0; -} - -static struct file_operations proc_mem_operations = { - mem_lseek, - mem_read, - mem_write, - NULL, /* mem_readdir */ - NULL, /* mem_poll */ - NULL, /* mem_ioctl */ - mem_mmap, /* mmap */ - NULL, /* no special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL /* can't fsync */ -}; - -struct inode_operations proc_mem_inode_operations = { - &proc_mem_operations, /* default base directory file-ops */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - NULL, /* truncate */ - proc_permission, /* permission */ - NULL, /* smap */ - NULL /* revalidate */ -}; diff --git a/fs/proc/net.c b/fs/proc/net.c deleted file mode 100644 index b4e18bc499b5940c88bf8774f504a3d5c11f1f63..0000000000000000000000000000000000000000 --- a/fs/proc/net.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * linux/fs/proc/net.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * gjh 3/'93 heim@peanuts.informatik.uni-tuebingen.de (Gerald J. Heim) - * most of this file is stolen from base.c - * it works, but you shouldn't use it as a guideline - * for new proc-fs entries. once i'll make it better. - * fvk 3/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen) - * cleaned up the whole thing, moved "net" specific code to - * the NET kernel layer (where it belonged in the first place). - * Michael K. Johnson (johnsonm@stolaf.edu) 3/93 - * Added support from my previous inet.c. Cleaned things up - * quite a bit, modularized the code. - * fvk 4/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen) - * Renamed "route_get_info()" to "rt_get_info()" for consistency. - * Alan Cox (gw4pts@gw4pts.ampr.org) 4/94 - * Dusted off the code and added IPX. Fixed the 4K limit. - * Erik Schoenfelder (schoenfr@ibr.cs.tu-bs.de) - * /proc/net/snmp. - * Alan Cox (gw4pts@gw4pts.ampr.org) 1/95 - * Added AppleTalk slots - * - * proc net directory handling functions - */ -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> -#include <linux/fcntl.h> -#include <linux/mm.h> - -#include <asm/uaccess.h> - -#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ - -static long proc_readnet(struct inode * inode, struct file * file, - char * buf, unsigned long count) -{ - char * page; - int bytes=count; - int copied=0; - char *start; - struct proc_dir_entry * dp; - - if (count < 0) - return -EINVAL; - dp = (struct proc_dir_entry *) inode->u.generic_ip; - if (!(page = (char*) __get_free_page(GFP_KERNEL))) - return -ENOMEM; - - while (bytes>0) - { - int length, thistime=bytes; - if (bytes > PROC_BLOCK_SIZE) - thistime=PROC_BLOCK_SIZE; - - length = dp->get_info(page, &start, - file->f_pos, - thistime, - (file->f_flags & O_ACCMODE) == O_RDWR); - - /* - * We have been given a non page aligned block of - * the data we asked for + a bit. We have been given - * the start pointer and we know the length.. - */ - - if (length <= 0) - break; - /* - * Copy the bytes - */ - copy_to_user(buf+copied, start, length); - file->f_pos += length; /* Move down the file */ - bytes -= length; - copied += length; - if (length<thistime) - break; /* End of file */ - } - free_page((unsigned long) page); - return copied; -} - -static struct file_operations proc_net_operations = { - NULL, /* lseek - default */ - proc_readnet, /* read - bad */ - NULL, /* write - bad */ - NULL, /* readdir */ - NULL, /* poll - default */ - NULL, /* ioctl - default */ - NULL, /* mmap */ - NULL, /* no special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL /* can't fsync */ -}; - -/* - * proc directories can do almost nothing.. - */ -struct inode_operations proc_net_inode_operations = { - &proc_net_operations, /* default net file-ops */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL /* revalidate */ -}; diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 7826d9fa913de4750c6614dbb38e3ff2ec54b5c6..bd3a0842fbe2f76f5add39d9a25f63bf287eab26 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -30,6 +30,7 @@ #include <linux/slab.h> #include <linux/smp.h> #include <linux/signal.h> +#include <linux/module.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -545,12 +546,102 @@ static int memory_read_proc(char *page, char **start, off_t off, return len; } +static int open_kcore(struct inode * inode, struct file * filp) +{ + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +extern ssize_t read_kcore(struct file *, char *, size_t, loff_t *); + +static struct file_operations proc_kcore_operations = { + NULL, /* lseek */ + read_kcore, + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + open_kcore +}; + +static struct inode_operations proc_kcore_inode_operations = { + &proc_kcore_operations, +}; + +/* + * This function accesses profiling information. The returned data is + * binary: the sampling step and the actual contents of the profile + * buffer. Use of the program readprofile is recommended in order to + * get meaningful info out of these data. + */ +static ssize_t read_profile(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + ssize_t read; + char * pnt; + unsigned int sample_step = 1 << prof_shift; + + if (p >= (prof_len+1)*sizeof(unsigned int)) + return 0; + if (count > (prof_len+1)*sizeof(unsigned int) - p) + count = (prof_len+1)*sizeof(unsigned int) - p; + read = 0; + + while (p < sizeof(unsigned int) && count > 0) { + put_user(*((char *)(&sample_step)+p),buf); + buf++; p++; count--; read++; + } + pnt = (char *)prof_buffer + p - sizeof(unsigned int); + copy_to_user(buf,(void *)pnt,count); + read += count; + *ppos += read; + return read; +} + +/* + * Writing to /proc/profile resets the counters + * + * Writing a 'profiling multiplier' value into it also re-sets the profiling + * interrupt frequency, on architectures that support this. + */ +static ssize_t write_profile(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ +#ifdef __SMP__ + extern int setup_profiling_timer (unsigned int multiplier); + + if (count==sizeof(int)) { + unsigned int multiplier; + + if (copy_from_user(&multiplier, buf, sizeof(int))) + return -EFAULT; + + if (setup_profiling_timer(multiplier)) + return -EINVAL; + } +#endif + + memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer)); + return count; +} + +static struct file_operations proc_profile_operations = { + NULL, /* lseek */ + read_profile, + write_profile, +}; + +static struct inode_operations proc_profile_inode_operations = { + &proc_profile_operations, +}; + static struct proc_dir_entry proc_root_kmsg = { 0, 4, "kmsg", S_IFREG | S_IRUSR, 1, 0, 0, 0, &proc_kmsg_inode_operations }; -static struct proc_dir_entry proc_root_kcore = { +struct proc_dir_entry proc_root_kcore = { 0, 5, "kcore", S_IFREG | S_IRUSR, 1, 0, 0, 0, &proc_kcore_inode_operations @@ -613,7 +704,7 @@ void proc_misc_init(void) /* And now for trickier ones */ proc_register(&proc_root, &proc_root_kmsg); proc_register(&proc_root, &proc_root_kcore); - proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE; + proc_root_kcore.size = get_kcore_size(); if (prof_shift) { proc_register(&proc_root, &proc_root_profile); proc_root_profile.size = (1+prof_len) * sizeof(unsigned int); diff --git a/fs/proc/root.c b/fs/proc/root.c index 082b419fdc392d625c9924d195a8fc0a97643bb1..545e7cfada3d5bd9739634acd87a898f652ffd4f 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -541,7 +541,6 @@ static struct proc_dir_entry proc_root_ppc_htab = { void __init proc_root_init(void) { - proc_base_init(); proc_misc_init(); proc_register(&proc_root, &proc_root_self); proc_net = create_proc_entry("net", S_IFDIR, 0); @@ -631,11 +630,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry) static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry) { - unsigned int pid, c; struct task_struct *p; - const char *name; - struct inode *inode; - int len; if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */ extern unsigned long total_forks; @@ -666,40 +661,7 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr if (!proc_lookup(dir, dentry)) return NULL; - pid = 0; - name = dentry->d_name.name; - len = dentry->d_name.len; - while (len-- > 0) { - c = *name - '0'; - name++; - if (c > 9) { - pid = 0; - break; - } - pid *= 10; - pid += c; - if (!pid) - break; - if (pid & 0xffff0000) { - pid = 0; - break; - } - } - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - read_unlock(&tasklist_lock); - inode = NULL; - if (pid && p) { - unsigned long ino = (pid << 16) + PROC_PID_INO; - inode = proc_get_inode(dir->i_sb, ino, &proc_pid); - if (!inode) - return ERR_PTR(-EINVAL); - inode->i_flags|=S_IMMUTABLE; - } - - dentry->d_op = &proc_dentry_operations; - d_add(dentry, inode); - return NULL; + return proc_pid_lookup(dir, dentry); } /* diff --git a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h index 92654cd8328947cd3d341f56cb94c7e13e1056ee..f986d1c14b43c4ab3f94857def3761e2c9cfddeb 100644 --- a/include/asm-alpha/processor.h +++ b/include/asm-alpha/processor.h @@ -126,6 +126,49 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); #define release_segments(mm) do { } while (0) #define forget_segments() do { } while (0) +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +static inline unsigned long get_wchan(struct task_struct *p) +{ + unsigned long schedule_frame; + unsigned long pc; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + /* + * This one depends on the frame size of schedule(). Do a + * "disass schedule" in gdb to find the frame size. Also, the + * code assumes that sleep_on() follows immediately after + * interruptible_sleep_on() and that add_timer() follows + * immediately after interruptible_sleep(). Ugly, isn't it? + * Maybe adding a wchan field to task_struct would be better, + * after all... + */ + + pc = thread_saved_pc(&p->thread); + if (pc >= first_sched && pc < last_sched) { + schedule_frame = ((unsigned long *)p->thread.ksp)[6]; + return ((unsigned long *)schedule_frame)[12]; + } + return pc; +} +#undef last_sched +#undef first_sched + +/* +* See arch/alpha/kernel/ptrace.c for details. +*/ +#define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + + (long)&((struct pt_regs *)0)->reg) +#define KSTK_EIP(tsk) \ + (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk))) +#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) + /* NOTE: The task struct and the stack go together! */ #define alloc_task_struct() \ ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h index 33b98efa16d8f17d226d5805c21722643aa957d4..02cd7202906d613d022b6222cbed123b8f25cd9f 100644 --- a/include/asm-arm/processor.h +++ b/include/asm-arm/processor.h @@ -107,6 +107,45 @@ extern void release_thread(struct task_struct *); #define release_segments(mm) do { } while (0) #define forget_segments() do { } while (0) +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +static inline unsigned long get_wchan(struct task_struct *p) +{ + unsigned long fp, lr; + unsigned long stack_page; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + stack_page = 4096 + (unsigned long)p; + fp = get_css_fp(&p->thread); + do { + if (fp < stack_page || fp > 4092+stack_page) + return 0; + lr = pc_pointer (((unsigned long *)fp)[-1]); + if (lr < first_sched || lr > last_sched) + return lr; + fp = *(unsigned long *) (fp - 12); + } while (count ++ < 16); + return 0; +} +#undef last_sched +#undef first_sched + +#ifdef CONFIG_CPU_26 +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020]) +#else +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1021]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) +#endif + extern struct task_struct *alloc_task_struct(void); extern void free_task_struct(struct task_struct *); diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index ddd5e165e224f517c947aac522b9a57cf1f788ab..878c637f7cea012afaf58309add49a65086efbbe 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -406,6 +406,10 @@ extern inline unsigned long thread_saved_pc(struct thread_struct *t) return ((unsigned long *)t->esp)[3]; } +unsigned long get_wchan(struct task_struct *p); +#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) +#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) + #define THREAD_SIZE (2*PAGE_SIZE) #define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) #define free_task_struct(p) free_pages((unsigned long) (p), 1) diff --git a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h index 7b6564813d3cc0ab45f86fc4a590c8641a57ed0c..545673d7c041052fc9db15f3c771efda6d0d535e 100644 --- a/include/asm-m68k/processor.h +++ b/include/asm-m68k/processor.h @@ -134,6 +134,48 @@ extern inline unsigned long thread_saved_pc(struct thread_struct *t) return sw->retpc; } +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +static inline unsigned long get_wchan(struct task_struct *p) +{ + unsigned long fp, pc; + unsigned long stack_page; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + stack_page = (unsigned long)p; + fp = ((struct switch_stack *)p->thread.ksp)->a6; + do { + if (fp < stack_page+sizeof(struct task_struct) || + fp >= 8184+stack_page) + return 0; + pc = ((unsigned long *)fp)[1]; + /* FIXME: This depends on the order of these functions. */ + if (pc < first_sched || pc >= last_sched) + return pc; + fp = *(unsigned long *) fp; + } while (count++ < 16); + return 0; +} +#undef last_sched +#undef first_sched + +#define KSTK_EIP(tsk) \ + ({ \ + unsigned long eip = 0; \ + if ((tsk)->thread.esp0 > PAGE_SIZE && \ + MAP_NR((tsk)->thread.esp0) < max_mapnr) \ + eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \ + eip; }) +#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) + #define THREAD_SIZE (2*PAGE_SIZE) /* Allocation and freeing of basic task resources. */ diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h index a264617a3f0fafdeb801fa53b9071e53f449e93f..4f277148ae7a53512e7fe7f6b810b5806dea7054 100644 --- a/include/asm-mips/processor.h +++ b/include/asm-mips/processor.h @@ -206,6 +206,39 @@ extern inline unsigned long thread_saved_pc(struct thread_struct *t) */ extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp); +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +static inline unsigned long get_wchan(struct task_struct *p) +{ + unsigned long schedule_frame; + unsigned long pc; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + /* + * The same comment as on the Alpha applies here, too ... + */ + pc = thread_saved_pc(&p->tss); + if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) { + schedule_frame = ((unsigned long *)(long)p->tss.reg30)[16]; + return (unsigned long)((unsigned long *)schedule_frame)[11]; + } + return pc; +} +#undef last_sched +#undef first_sched + +#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg \ + - sizeof(struct pt_regs)) +#define KSTK_TOS(tsk) ((unsigned long)(tsk) + KERNEL_STACK_SIZE - 32) +#define KSTK_EIP(tsk) (*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(cp0_epc))) +#define KSTK_ESP(tsk) (*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(regs[29]))) + /* Allocation and freeing of basic task resources. */ /* * NOTE! The task struct and the stack go together diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index 6e425b60b58bbf308aea5df760e158491aeade5d..167debde713b4bff2557d59e0d273afc980ae1ac 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -316,6 +316,40 @@ static inline unsigned long thread_saved_pc(struct thread_struct *t) #define release_segments(mm) do { } while (0) #define forget_segments() do { } while (0) +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +static inline unsigned long get_wchan(struct task_struct *p) +{ + unsigned long ip, sp; + unsigned long stack_page = (unsigned long) p; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + sp = p->thread.ksp; + do { + sp = *(unsigned long *)sp; + if (sp < stack_page || sp >= stack_page + 8188) + return 0; + if (count > 0) { + ip = *(unsigned long *)(sp + 4); + if (ip < first_sched || ip >= last_sched) + return ip; + } + } while (count++ < 16); + return 0; +} +#undef last_sched +#undef first_sched + +#define KSTK_EIP(tsk) ((tsk)->thread.regs->nip) +#define KSTK_ESP(tsk) ((tsk)->thread.regs->gpr[1]) + /* * NOTE! The task struct and the stack go together */ diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index 07175eff5c5e85c4373ed8d623720a5198176e08..ae8b036c227d1541b6913b19c541b78d97a57642 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -189,6 +189,17 @@ extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t) return t->pc; } +static inline unsigned long get_wchan(struct task_struct *p) +{ + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + /* FIXME: here the actual wchan calculation should sit */ + return 0; +} + +#define KSTK_EIP(tsk) ((tsk)->thread.pc) +#define KSTK_ESP(tsk) ((tsk)->thread.sp) + #define THREAD_SIZE (2*PAGE_SIZE) extern struct task_struct * alloc_task_struct(void); extern void free_task_struct(struct task_struct *); diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h index 81739b0a528bde1e20d38b390c3caa4c2888983a..662a8119f42ddc406f4042bb2d9586632afdfbd4 100644 --- a/include/asm-sparc/processor.h +++ b/include/asm-sparc/processor.h @@ -161,6 +161,43 @@ extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); #define release_segments(mm) do { } while (0) #define forget_segments() do { } while (0) +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +static inline unsigned long get_wchan(struct task_struct *p) +{ + unsigned long pc, fp, bias = 0; + unsigned long task_base = (unsigned long) p; + struct reg_window *rw; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + fp = p->thread.ksp + bias; + do { + /* Bogus frame pointer? */ + if (fp < (task_base + sizeof(struct task_struct)) || + fp >= (task_base + (2 * PAGE_SIZE))) + break; + rw = (struct reg_window *) fp; + pc = rw->ins[7]; + if (pc < first_sched || pc >= last_sched) + return pc; + fp = rw->ins[6] + bias; + } while (++count < 16); + return 0; +} +#undef last_sched +#undef first_sched + +#define KSTK_EIP(tsk) ((tsk)->thread.kregs->pc) +#define KSTK_ESP(tsk) ((tsk)->thread.kregs->u_regs[UREG_FP]) + #ifdef __KERNEL__ #define THREAD_SIZE (2*PAGE_SIZE) diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h index d5074144dd0c84367565bd569f1a9bc760c8c987..56a116279dd9f7c32ed30da2939112608f096b95 100644 --- a/include/asm-sparc64/processor.h +++ b/include/asm-sparc64/processor.h @@ -209,6 +209,43 @@ extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); #define release_segments(mm) do { } while (0) #define forget_segments() do { } while (0) +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +static inline unsigned long get_wchan(struct task_struct *p) +{ + unsigned long pc, fp, bias = 0; + unsigned long task_base = (unsigned long) p; + struct reg_window *rw; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + bias = STACK_BIAS; + fp = p->thread.ksp + bias; + do { + /* Bogus frame pointer? */ + if (fp < (task_base + sizeof(struct task_struct)) || + fp >= (task_base + (2 * PAGE_SIZE))) + break; + rw = (struct reg_window *) fp; + pc = rw->ins[7]; + if (pc < first_sched || pc >= last_sched) + return pc; + fp = rw->ins[6] + bias; + } while (++count < 16); + return 0; +} +#undef last_sched +#undef first_sched + +#define KSTK_EIP(tsk) ((tsk)->thread.kregs->tpc) +#define KSTK_ESP(tsk) ((tsk)->thread.kregs->u_regs[UREG_FP]) + #ifdef __KERNEL__ #define THREAD_SIZE (2*PAGE_SIZE) /* Allocation and freeing of task_struct and kernel stack. */ diff --git a/include/linux/concap.h b/include/linux/concap.h index a0743ec146b8e98b5b257115277dbfd80c4f01db..79d642288891259b767dddc0e93fa6804fcc6d7f 100644 --- a/include/linux/concap.h +++ b/include/linux/concap.h @@ -5,7 +5,6 @@ #ifdef __KERNEL__ #include <linux/skbuff.h> #include <linux/netdevice.h> -#include <linux/isdn_compat.h> /* Stuff to support encapsulation protocols genericly. The encapsulation protocol is processed at the uppermost layer of the network interface. diff --git a/include/linux/fs.h b/include/linux/fs.h index 4b1fadbf996ae21080cc0f1e7a27cf6efde39e8b..a7efa4ea0b79161925c42a75c53664959915cabb 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -271,6 +271,7 @@ void init_buffer(struct buffer_head *, bh_end_io_t *, void *); #include <linux/bfs_fs_i.h> #include <linux/udf_fs_i.h> #include <linux/ncp_fs_i.h> +#include <linux/proc_fs_i.h> /* * Attribute flags. These should be or-ed together to figure out what @@ -395,6 +396,7 @@ struct inode { struct bfs_inode_info bfs_i; struct udf_inode_info udf_i; struct ncp_inode_info ncpfs_i; + struct proc_inode_info proc_i; struct socket socket_i; void *generic_ip; } u; diff --git a/include/linux/isdn.h b/include/linux/isdn.h index d1d7350b1cc6481ffb404f939110521c32b2b555..b73358b68240a9c88b06b441572d012c25b168e1 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -1,8 +1,8 @@ -/* $Id: isdn.h,v 1.71 1999/08/23 15:54:22 keil Exp $ +/* $Id: isdn.h,v 1.81 1999/10/27 21:21:18 detabc Exp $ * * Main header for the Linux ISDN subsystem (linklevel). * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) * @@ -21,6 +21,51 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn.h,v $ + * Revision 1.81 1999/10/27 21:21:18 detabc + * Added support for building logically-bind-group's per interface. + * usefull for outgoing call's with more then one isdn-card. + * + * Switchable support to dont reset the hangup-timeout for + * receive frames. Most part's of the timru-rules for receiving frames + * are now obsolete. If the input- or forwarding-firewall deny + * the frame, the line will be not hold open. + * + * Revision 1.80 1999/10/26 21:09:29 armin + * New bufferlen for phonenumber only with kernel 2.3.x + * + * Revision 1.79 1999/10/16 17:52:38 keil + * Changing the MSN length need new data versions + * + * Revision 1.78 1999/10/08 18:59:33 armin + * Bugfix of too small MSN buffer and checking phone number + * in isdn_tty_getdial() + * + * Revision 1.77 1999/09/23 22:22:42 detabc + * added tcp-keepalive-detect with local response (ipv4 only) + * added host-only-interface support + * (source ipaddr == interface ipaddr) (ipv4 only) + * ok with kernel 2.3.18 and 2.2.12 + * + * Revision 1.76 1999/09/14 10:16:21 keil + * change ABC include + * + * Revision 1.75 1999/09/13 23:25:17 he + * serialized xmitting frames from isdn_ppp and BSENT statcallb + * + * Revision 1.74 1999/09/12 16:19:39 detabc + * added abc features + * low cost routing for net-interfaces (only the HL side). + * need more implementation in the isdnlog-utility + * udp info support (first part). + * different EAZ on outgoing call's. + * more checks on D-Channel callbacks (double use of channels). + * tested and running with kernel 2.3.17 + * + * Revision 1.73 1999/09/06 07:29:36 fritz + * Changed my mail-address. + * + * Revision 1.72 1999/09/04 22:20:19 detabc + * * Revision 1.71 1999/08/23 15:54:22 keil * more backported changes from kernel 2.3.14 * @@ -250,7 +295,6 @@ #ifndef isdn_h #define isdn_h -#include <linux/isdn_compat.h> #include <linux/config.h> #include <linux/ioctl.h> @@ -279,6 +323,18 @@ #define ISDN_MINOR_PPPMAX (128 + (ISDN_MAX_CHANNELS-1)) #define ISDN_MINOR_STATUS 255 +#undef CONFIG_ISDN_WITH_ABC_CALLB +#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK +#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP +#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL +#undef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ +#undef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT +#undef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE +#undef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR +#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER +#undef CONFIG_ISDN_WITH_ABC_ICALL_BIND + + /* New ioctl-codes */ #define IIOCNETAIF _IO('I',1) #define IIOCNETDIF _IO('I',2) @@ -302,6 +358,7 @@ #define IIOCNETDIL _IO('I',20) #define IIOCGETCPS _IO('I',21) #define IIOCGETDVR _IO('I',22) +#define IIOCNETLCR _IO('I',23) /* dwabc ioctl for LCR from isdnlog */ #define IIOCNETALN _IO('I',32) #define IIOCNETDLN _IO('I',33) @@ -335,10 +392,15 @@ #define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing */ #define ISDN_MODEM_ANZREG 24 /* Number of Modem-Registers */ -#define ISDN_MSNLEN 20 #define ISDN_LMSNLEN 255 /* Length of tty's Listen-MSN string */ #define ISDN_CMSGLEN 50 /* Length of CONNECT-Message to add for Modem */ +#define ISDN_MSNLEN 32 +#define NET_DV 0x06 /* Data version for isdn_net_ioctl_cfg */ +#define TTY_DV 0x06 /* Data version for iprofd etc. */ + +#define INF_DV 0x01 /* Data version for /dev/isdninfo */ + typedef struct { char drvid[25]; unsigned long arg; @@ -356,10 +418,6 @@ typedef struct { int outgoing; } isdn_net_ioctl_phone; -#define NET_DV 0x05 /* Data version for isdn_net_ioctl_cfg */ -#define TTY_DV 0x05 /* Data version for iprofd etc. */ -#define INF_DV 0x01 /* Data version for /dev/isdninfo */ - typedef struct { char name[10]; /* Name of interface */ char master[10]; /* Name of Master for Bundling */ @@ -438,7 +496,6 @@ typedef struct { #include <linux/isdnif.h> - #define ISDN_DRVIOCTL_MASK 0x7f /* Mask for Device-ioctl */ /* Until now unused */ @@ -504,12 +561,6 @@ typedef struct { #define ISDN_NET_CALLBACK 0x04 /* activate callback */ #define ISDN_NET_CBHUP 0x08 /* hangup before callback */ #define ISDN_NET_CBOUT 0x10 /* remote machine does callback */ -#if 0 -/* Unused??? */ -#define ISDN_NET_CLONE 0x08 /* clone a tmp interface when called */ -#define ISDN_NET_TMP 0x10 /* tmp interface until getting an IP */ -#define ISDN_NET_DYNAMIC 0x20 /* this link is dynamically allocated */ -#endif #define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */ @@ -591,7 +642,7 @@ typedef struct isdn_net_local_s { struct isdn_net_local_s *last; /* Ptr to last link in bundle */ struct isdn_net_dev_s *netdev; /* Ptr to netdev */ struct sk_buff *first_skb; /* Ptr to skb that triggers dialing */ - struct sk_buff *sav_skb; /* Ptr to skb, rejected by LL-driver*/ + struct sk_buff *volatile sav_skb; /* Ptr to skb, rejected by LL-driver*/ /* Ptr to orig. hard_header_cache */ int (*org_hhc)( struct neighbour *neigh, @@ -743,12 +794,7 @@ typedef struct modem_info { atemu emu; /* AT-emulator data */ struct termios normal_termios; /* For saving termios structs */ struct termios callout_termios; -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t open_wait, close_wait; -#else - struct wait_queue *open_wait; - struct wait_queue *close_wait; -#endif struct semaphore write_sem; } modem_info; @@ -826,11 +872,7 @@ typedef struct { ulong flags; /* Misc driver Flags */ int locks; /* Number of locks for this driver */ int channels; /* Number of channels */ -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t st_waitq; /* Wait-Queue for status-read's */ -#else - struct wait_queue *st_waitq; /* Wait-Queue for status-read's */ -#endif int maxbufsize; /* Maximum Buffersize supported */ unsigned long pktcount; /* Until now: unused */ int stavail; /* Chars avail on Status-device */ @@ -841,13 +883,8 @@ typedef struct { unsigned long DLEflag; /* Flags: Insert DLE at next read */ #endif struct sk_buff_head *rpqueue; /* Pointers to start of Rcv-Queue */ -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t *rcv_waitq; /* Wait-Queues for B-Channel-Reads */ wait_queue_head_t *snd_waitq; /* Wait-Queue for B-Channel-Send's */ -#else - struct wait_queue **rcv_waitq; /* Wait-Queues for B-Channel-Reads */ - struct wait_queue **snd_waitq; /* Wait-Queue for B-Channel-Send's */ -#endif char msn2eaz[10][ISDN_MSNLEN]; /* Mapping-Table MSN->EAZ */ } driver; @@ -863,11 +900,7 @@ typedef struct isdn_devt { /* see ISDN_TIMER_..defines */ int global_flags; infostruct *infochain; /* List of open info-devs. */ -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */ -#else - struct wait_queue *info_waitq; /* Wait-Queue for isdninfo */ -#endif struct timer_list timer; /* Misc.-function Timer */ int chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel */ int drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index */ @@ -894,6 +927,7 @@ typedef struct isdn_devt { extern isdn_dev *dev; + /* Utility-Macros */ #define MIN(a,b) ((a<b)?a:b) #define MAX(a,b) ((a>b)?a:b) diff --git a/include/linux/isdn_compat.h b/include/linux/isdn_compat.h deleted file mode 100644 index 7750f63037eadb557880110bbc742ca6bc6cfbd2..0000000000000000000000000000000000000000 --- a/include/linux/isdn_compat.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifdef __KERNEL__ -/* Compatibility for various Linux kernel versions */ - -#ifndef _LINUX_ISDN_COMPAT_H -#define _LINUX_ISDN_COMPAT_H - -#ifndef LINUX_VERSION_CODE -#include <linux/version.h> -#endif - -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -#include <linux/mm.h> - -#define ioremap vremap -#define ioremap_nocache vremap -#define iounmap vfree - -static inline unsigned long copy_from_user(void *to, const void *from, unsigned long n) -{ - int i; - if ((i = verify_area(VERIFY_READ, from, n)) != 0) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -static inline unsigned long copy_to_user(void *to, const void *from, unsigned long n) -{ - int i; - if ((i = verify_area(VERIFY_WRITE, to, n)) != 0) - return i; - memcpy_tofs(to, from, n); - return 0; -} - -#define GET_USER(x, addr) ( x = get_user(addr) ) -#ifdef __alpha__ /* needed for 2.0.x with alpha-patches */ -#define RWTYPE long -#define LSTYPE long -#define RWARG unsigned long -#else -#define RWTYPE int -#define LSTYPE int -#define RWARG int -#endif -#define LSARG off_t -#else -#include <asm/uaccess.h> -#define GET_USER get_user -#define PUT_USER put_user -#define RWTYPE long -#define LSTYPE long long -#define RWARG unsigned long -#define LSARG long long -#endif /* LINUX_VERSION_CODE */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,15) -#define SET_SKB_FREE(x) ( x->free = 1 ) -#define idev_kfree_skb(a,b) dev_kfree_skb(a,b) -#else -#define SET_SKB_FREE(x) -#define idev_kfree_skb(a,b) dev_kfree_skb(a) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,18) -#define COMPAT_HAS_NEW_SYMTAB -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,31) -#define CLOSETYPE void -#define CLOSEVAL -#else -#define CLOSETYPE int -#define CLOSEVAL (0) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,37) -#define test_and_clear_bit clear_bit -#define test_and_set_bit set_bit -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,81) -#define kstat_irqs( PAR ) kstat.interrupts[PAR] -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,91) -#define COMPAT_HAS_NEW_PCI -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) -#define get_pcibase(ps, nr) ps->base_address[nr] -#else -#define get_pcibase(ps, nr) ps->resource[nr].start -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127) -#define schedule_timeout(a) current->timeout = jiffies + (a); schedule (); -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) -#define COMPAT_HAS_NEW_WAITQ -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,12) -#define COMPAT_HAS_NEW_SETUP -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14) -#define net_device device -#endif - -#endif /* __KERNEL__ */ -#endif /* _LINUX_ISDN_COMPAT_H */ diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h index 9ca7dc7cde3210a0b8031e977bbaeb65aa523b8d..6ba3086abda995cbc69b2fe0959783e4b6f745e4 100644 --- a/include/linux/isdn_ppp.h +++ b/include/linux/isdn_ppp.h @@ -4,7 +4,6 @@ #define _LINUX_ISDN_PPP_H #include <linux/config.h> -#include <linux/isdn_compat.h> #define CALLTYPE_INCOMING 0x1 #define CALLTYPE_OUTGOING 0x2 @@ -207,11 +206,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 */ -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t wq; -#else - struct wait_queue *wq; -#endif struct task_struct *tk; unsigned int mpppcfg; unsigned int pppcfg; diff --git a/include/linux/isdnif.h b/include/linux/isdnif.h index 06206eb916d684e663dfaea812c99fce5146ca62..07e3b826df910b34e4345b51d8d97c3b20337099 100644 --- a/include/linux/isdnif.h +++ b/include/linux/isdnif.h @@ -1,10 +1,10 @@ -/* $Id: isdnif.h,v 1.30 1999/08/23 15:54:29 keil Exp $ +/* $Id: isdnif.h,v 1.32 1999/10/11 22:03:00 keil Exp $ * * Linux ISDN subsystem * * Definition of the interface between the subsystem and its low-level drivers. * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg * * This program is free software; you can redistribute it and/or modify @@ -22,6 +22,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdnif.h,v $ + * Revision 1.32 1999/10/11 22:03:00 keil + * COMPAT_NEED_UACCESS (no include in isdn_compat.h) + * + * Revision 1.31 1999/09/06 07:29:36 fritz + * Changed my mail-address. + * * Revision 1.30 1999/08/23 15:54:29 keil * more backported changes from kernel 2.3.14 * @@ -138,7 +144,6 @@ #define isdnif_h #include <linux/config.h> -#include <linux/isdn_compat.h> /* * Values for general protocol-selection diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h index 7b212be059557509dcdf5ee23f02d32edbe0acfe..5778d2ebb97f1b2438c12a470813de1fed62d152 100644 --- a/include/linux/kernelcapi.h +++ b/include/linux/kernelcapi.h @@ -1,11 +1,15 @@ /* - * $Id: kernelcapi.h,v 1.3 1999/07/01 15:26:56 calle Exp $ + * $Id: kernelcapi.h,v 1.4 1999/09/10 17:24:19 calle Exp $ * * Kernel CAPI 2.0 Interface for Linux * * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: kernelcapi.h,v $ + * Revision 1.4 1999/09/10 17:24:19 calle + * Changes for proposed standard for CAPI2.0: + * - AK148 "Linux Exention" + * * Revision 1.3 1999/07/01 15:26:56 calle * complete new version (I love it): * + new hardware independed "capi_driver" interface that will make it easy to: @@ -70,19 +74,19 @@ typedef struct kcapi_flagdef { #ifdef __KERNEL__ struct capi_interface { - int (*capi_installed) (void); + __u16 (*capi_isinstalled) (void); - __u16(*capi_register) (capi_register_params * rparam, __u16 * applidp); - __u16(*capi_release) (__u16 applid); - __u16(*capi_put_message) (__u16 applid, struct sk_buff * msg); - __u16(*capi_get_message) (__u16 applid, struct sk_buff ** msgp); - __u16(*capi_set_signal) (__u16 applid, + __u16 (*capi_register) (capi_register_params * rparam, __u16 * applidp); + __u16 (*capi_release) (__u16 applid); + __u16 (*capi_put_message) (__u16 applid, struct sk_buff * msg); + __u16 (*capi_get_message) (__u16 applid, struct sk_buff ** msgp); + __u16 (*capi_set_signal) (__u16 applid, void (*signal) (__u16 applid, __u32 param), __u32 param); - __u16(*capi_get_manufacturer) (__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN]); - __u16(*capi_get_version) (__u16 contr, struct capi_version * verp); - __u16(*capi_get_serial) (__u16 contr, __u8 serial[CAPI_SERIAL_LEN]); - __u16(*capi_get_profile) (__u16 contr, struct capi_profile * profp); + __u16 (*capi_get_manufacturer) (__u32 contr, __u8 buf[CAPI_MANUFACTURER_LEN]); + __u16 (*capi_get_version) (__u32 contr, struct capi_version * verp); + __u16(*capi_get_serial) (__u32 contr, __u8 serial[CAPI_SERIAL_LEN]); + __u16(*capi_get_profile) (__u32 contr, struct capi_profile * profp); /* * to init controllers, data is always in user memory @@ -96,7 +100,7 @@ struct capi_interface { struct capi_interface_user { char name[20]; - void (*callback) (unsigned int cmd, __u16 contr, void *data); + void (*callback) (unsigned int cmd, __u32 contr, void *data); /* internal */ struct capi_interface_user *next; }; diff --git a/include/linux/module.h b/include/linux/module.h index e0b655aab82cb91eac95321b7a8e739d07bbdc6c..88c260f658b01022318a007ff98a34ecdaac1869 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -286,4 +286,5 @@ __attribute__((section("__ksymtab"))) = \ #define EXPORT_NO_SYMBOLS #endif /* MODULE */ +extern unsigned long get_kcore_size(void); #endif /* _LINUX_MODULE_H */ diff --git a/include/linux/parport.h b/include/linux/parport.h index b663548f6972115ba0c9fc81ce8b51c8325d552c..8a1e97501633ed0803eafce21afc661d92774cf0 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -422,6 +422,10 @@ extern int parport_wait_event (struct parport *, long timeout); extern int parport_wait_peripheral (struct parport *port, unsigned char mask, unsigned char val); +extern int parport_poll_peripheral (struct parport *port, + unsigned char mask, + unsigned char val, + int usec); /* For architectural drivers */ extern void parport_ieee1284_wakeup (struct parport *port); diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 69f55ff2aca77aa62fd5dae112821feab9961a30..a76f96bb726057241e972eeeba0bfd8fcdb5bd50 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -179,6 +179,11 @@ struct proc_dir_entry { extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start, off_t offset, int length, int inout); +#define PROC_INODE_PROPER(inode) ((inode)->i_ino & ~0xffff) +#define PROC_INODE_OPENPROM(inode) \ + ((inode->i_ino >= PROC_OPENPROM_FIRST) \ + && (inode->i_ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM)) + #ifdef CONFIG_PROC_FS extern struct proc_dir_entry proc_root; @@ -193,6 +198,7 @@ extern struct proc_dir_entry *proc_mca; extern struct proc_dir_entry *proc_bus; extern struct proc_dir_entry *proc_sysvipc; extern struct proc_dir_entry *proc_root_driver; +extern struct proc_dir_entry proc_root_kcore; extern struct inode_operations proc_scsi_inode_operations; @@ -292,7 +298,6 @@ extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_ extern int proc_statfs(struct super_block *, struct statfs *, int); extern void proc_read_inode(struct inode *); extern void proc_write_inode(struct inode *); -extern int proc_permission(struct inode *, int); extern int proc_match(int, const char *,struct proc_dir_entry *); diff --git a/include/linux/proc_fs_i.h b/include/linux/proc_fs_i.h new file mode 100644 index 0000000000000000000000000000000000000000..5060d08fc4c9e057d910ae7b718e1fee6ee4d9d6 --- /dev/null +++ b/include/linux/proc_fs_i.h @@ -0,0 +1,9 @@ +struct proc_inode_info { + struct task_struct *task; + int type; + union { + struct dentry *(*proc_get_link)(struct inode *); + int (*proc_read)(struct task_struct *task, char *page); + } op; + struct file *file; +}; diff --git a/include/linux/sched.h b/include/linux/sched.h index 81ec83c273bbf87aca6a9738feb4d95ce74282bf..191de76af9af8cd71f53f4c6f69342c39b46546f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -361,6 +361,8 @@ struct task_struct { /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; +/* Protection of fields allocatio/deallocation */ + struct semaphore exit_sem; }; /* @@ -427,6 +429,7 @@ struct task_struct { /* mm */ NULL, &init_mm, \ /* signals */ SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \ /* exec cts */ 0,0, \ +/* exit_sem */ __MUTEX_INITIALIZER(name.exit_sem), \ } #ifndef INIT_TASK_SIZE @@ -837,6 +840,21 @@ extern inline void unhash_process(struct task_struct *p) write_unlock_irq(&tasklist_lock); } +static inline int task_lock(struct task_struct *p) +{ + down(&p->exit_sem); + if (p->p_pptr) + return 1; + /* He's dead, Jim. You take his wallet, I'll take tricoder... */ + up(&p->exit_sem); + return 0; +} + +static inline void task_unlock(struct task_struct *p) +{ + up(&p->exit_sem); +} + #endif /* __KERNEL__ */ #endif diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index c5ba9895f445fcdfb356371bdebfeeb1e9b3273a..0e1e65a70aedb4065e4c3ddadd93cd71866d7715 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -103,7 +103,8 @@ enum KERN_MSGPOOL=37, /* int: Maximum system message pool size */ KERN_SYSRQ=38, /* int: Sysreq enable */ KERN_MAX_THREADS=39, /* int: Maximum nr of threads in the system */ - KERN_RANDOM=40 /* Random driver */ + KERN_RANDOM=40, /* Random driver */ + KERN_SHMALL=41 /* int: Maximum size of shared memory */ }; diff --git a/ipc/shm.c b/ipc/shm.c index 58b41189a9a83655fbeec1fb2519347111871cc4..34ec74877cc85add2e53a9bd821fee7f74d96690 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -50,7 +50,7 @@ static int shm_swapout(struct page *, struct file *); static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data); #endif -unsigned int shm_prm[3] = {SHMMAX, SHMALL, SHMMNI}; +size_t shm_prm[3] = {SHMMAX, SHMALL, SHMMNI}; static int shm_tot = 0; /* total number of shared memory pages */ static int shm_rss = 0; /* number of shared memory pages that are in memory */ diff --git a/kernel/exit.c b/kernel/exit.c index db0d1f1fa83f7e0906b42b0c8a0ed40ce2336916..399cb98998896da8dba92f1655438e5474446af9 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -402,6 +402,7 @@ NORET_TYPE void do_exit(long code) #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); #endif + task_lock(tsk); sem_exit(); __exit_mm(tsk); #if CONFIG_AP1000 @@ -414,6 +415,7 @@ NORET_TYPE void do_exit(long code) tsk->state = TASK_ZOMBIE; tsk->exit_code = code; exit_notify(); + task_unlock(tsk); #ifdef DEBUG_PROC_TREE audit_ptree(); #endif diff --git a/kernel/fork.c b/kernel/fork.c index 2cce575fc6891dbd8f347a44c929a85aa9427c9e..a90a6bc470ffbc07370c48e7d40f380e869b400a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -650,6 +650,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) p->p_cptr = NULL; init_waitqueue_head(&p->wait_chldexit); p->vfork_sem = NULL; + sema_init(&p->exit_sem, 1); p->sigpending = 0; sigemptyset(&p->signal); diff --git a/kernel/module.c b/kernel/module.c index 6f4ad977d846789645eedfed5160da3705085716..fd80b8c42b415a6afc96b203ebb029bfe8698506 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -53,6 +53,26 @@ static struct module *find_module(const char *name); static void free_module(struct module *, int tag_freed); +/* needed for /proc/kcore, here because kernel_module is static (TA) */ +unsigned long get_kcore_size(void) +{ + unsigned long try, size = 0; + struct module * m; + + if (module_list == &kernel_module) + return ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE); + + /* shouldn't we have a rw spinlock for module_list? */ + lock_kernel(); + for (m=module_list; m; m=m->next) { + try = (unsigned long)m + m->size; + if (try > size) + size = try; + } + unlock_kernel(); + return (size - PAGE_OFFSET + PAGE_SIZE); +} + /* * Called at boot time */ @@ -969,6 +989,13 @@ get_module_symbol(char *modname, char *symname) #else /* CONFIG_MODULES */ +/* no MODULES so high_memory is good enough for /proc/kcore (TA) */ +unsigned long get_kcore_size(void) +{ + return ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE); +} + + /* Dummy syscalls for people who don't want modules */ asmlinkage unsigned long