diff -Nru a/CREDITS b/CREDITS --- a/CREDITS Wed Nov 27 14:36:31 2002 +++ b/CREDITS Wed Nov 27 14:36:31 2002 @@ -156,6 +156,14 @@ S: Calgary, Alberta S: Canada +N: Miles Bader +E: miles@gnu.org +D: v850 port (uClinux) +S: NEC Corporation +S: 1753 Shimonumabe, Nakahara-ku +S: Kawasaki 211-8666 +S: Japan + N: Ralf Baechle E: ralf@gnu.org P: 1024/AF7B30C1 CF 97 C2 CC 6D AE A7 FE C8 BA 9C FC 88 DE 32 C3 @@ -1507,16 +1515,17 @@ S: USA N: Dave Jones +E: davej@codemonkey.org.uk E: davej@suse.de W: http://www.codemonkey.org.uk D: x86 errata/setup maintenance. D: Backport/Forwardport merge monkey. D: Various Janitor work. S: c/o SuSE Linux UK Ltd -S: The Kinetic Centre -S: Theobald Street -S: Borehamwood -S: Herts, WD6 4PJ +S: Appleton House +S: 139 King Street +S: Hammersmith +S: W6 9JG S: United Kingdom N: Ani Joshi diff -Nru a/Documentation/BK-usage/unbz64wrap b/Documentation/BK-usage/unbz64wrap --- a/Documentation/BK-usage/unbz64wrap Wed Nov 27 14:36:30 2002 +++ b/Documentation/BK-usage/unbz64wrap Wed Nov 27 14:36:30 2002 @@ -15,7 +15,7 @@ case $LINE in begin-base64*) SHOW=YES ;; ====) SHOW= ;; - *) [ "$SHOW" ] && echo $LINE ;; + *) [ "$SHOW" ] && echo "$LINE" ;; esac done | mimencode -u | bunzip2 exit $? diff -Nru a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl --- a/Documentation/DocBook/journal-api.tmpl Wed Nov 27 14:36:27 2002 +++ b/Documentation/DocBook/journal-api.tmpl Wed Nov 27 14:36:27 2002 @@ -196,6 +196,8 @@ Lock is also providing through journal_{un,}lock_updates(), ext3 uses this when it wants a window with a clean and stable fs for a moment. eg. + + journal_lock_updates() //stop new stuff happening.. @@ -216,9 +218,13 @@ Using the journal is a matter of wrapping the different context changes, being each mount, each modification (transaction) and each changed buffer to tell the journalling layer about them. + + Here is a some pseudo code to give you an idea of how it works, as an example. + + journal_t* my_jnrl = journal_create(); journal_init_{dev,inode}(jnrl,...) diff -Nru a/Documentation/DocBook/lsm.tmpl b/Documentation/DocBook/lsm.tmpl --- a/Documentation/DocBook/lsm.tmpl Wed Nov 27 14:36:31 2002 +++ b/Documentation/DocBook/lsm.tmpl Wed Nov 27 14:36:31 2002 @@ -203,29 +203,6 @@ permission when accessing an inode. - -LSM adds a general security system call that -simply invokes the sys_security hook. This -system call and hook permits security modules to implement new system -calls for security-aware applications. The interface is similar to -socketcall, but also has an id to help identify -the security module whose call is being invoked. -To eliminate the need for a central registry of ids, -the recommended convention for creating the hexadecimal id value is: - - - -C code will need to prefix this result with ``0x''. -For example, the id for ``SGI Trusted Linux'' could be used in C as: - - - - - LSM Capabilities Module diff -Nru a/Documentation/DocBook/mousedrivers.tmpl b/Documentation/DocBook/mousedrivers.tmpl --- a/Documentation/DocBook/mousedrivers.tmpl Wed Nov 27 14:36:31 2002 +++ b/Documentation/DocBook/mousedrivers.tmpl Wed Nov 27 14:36:31 2002 @@ -153,11 +153,17 @@ __init ourmouse_init(void) { - if(check_region(OURMOUSE_BASE, 3)) + if (request_region(OURMOUSE_BASE, 3, "ourmouse") < 0) { + printk(KERN_ERR "ourmouse: request_region failed.\n"); return -ENODEV; - request_region(OURMOUSE_BASE, 3, "ourmouse"); + } + + if (misc_register(&our_mouse) < 0) { + printk(KERN_ERR "ourmouse: cannot register misc device.\n"); + release_region(OURMOUSE_BASE, 3); + return -EBUSY; + } - misc_register(&our_mouse); return 0; } @@ -177,18 +183,20 @@ so it is a good idea to obtain a current copy of this file first. - Our code then is fairly simple. We check nobody else has taken our - address space. Having done so we reserve it to ensure nobody stamps - on our device while probing for other ISA bus devices. Such a probe - might confuse our device. + Our code then is fairly simple. We reserve our I/O address space with + request_region, checking to make sure that it succeeded (i.e. the + space wasn't reserved by anyone else). - Then we tell the misc driver that we wish to own a minor number. We also + Then we ask the misc driver to allocate our minor device number. We also hand it our name (which is used in /proc/misc) and a set of file operations that are to be used. The file operations work exactly like the file operations you would register for a normal character device. The misc device itself is simply acting as a redirector for requests. + Since misc_register can fail, it is important to check for failure + and act accordingly (which in the case of a mouse driver is to abort, + since you can't use the mouse without a working device node). Next, in order to be able to use and test our code we need to add some diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Wed Nov 27 14:36:32 2002 +++ b/Documentation/kernel-parameters.txt Wed Nov 27 14:36:32 2002 @@ -1,21 +1,22 @@ -July 2000 Kernel Parameters v2.4.0 - ~~~~~~~~~~~~~~~~~ +November 2002 Kernel Parameters v2.5.49 + ~~~~~~~~~~~~~~~~~ The following is a consolidated list of the kernel parameters as implemented -by the __setup() macro and sorted into English Dictionary order (defined -as ignoring all punctuation and sorting digits before letters in a case -insensitive manner), and with descriptions where known. +(mostly) by the __setup() macro and sorted into English Dictionary order +(defined as ignoring all punctuation and sorting digits before letters in a +case insensitive manner), and with descriptions where known. The text in square brackets at the beginning of the description state the restrictions on the kernel for the said kernel parameter to be valid. The restrictions referred to are that the relevant option is valid if: - ACPI ACPI support is enabled. + ACPI ACPI support is enabled. + ALSA ALSA sound support is enabled. APIC APIC support is enabled. - APM Advanced Power Management support is enabled. + APM Advanced Power Management support is enabled. AX25 Appropriate AX.25 support is enabled. CD Appropriate CD support is enabled. - DEVFS devfs support is enabled. + DEVFS devfs support is enabled. DRM Direct Rendering Management support is enabled. EFI EFI Partitioning (GPT) is enabled EIDE EIDE/ATAPI support is enabled. @@ -24,38 +25,47 @@ IA-32 IA-32 aka i386 architecture is enabled. IA-64 IA-64 architecture is enabled. IP_PNP IP DCHP, BOOTP, or RARP is enabled. - ISAPNP ISA PnP code is enabled. + ISAPNP ISA PnP code is enabled. ISDN Appropriate ISDN support is enabled. - JOY Appropriate joystick support is enabled. + JOY Appropriate joystick support is enabled. LP Printer support is enabled. LOOP Loopback device support is enabled. - M68k M68k architecture is enabled. - MCA MCA bus support is enabled. - MDA MDA console support is enabled. + M68k M68k architecture is enabled. + These options have more detailed description inside of + Documentation/m68k/kernel-options.txt. + MCA MCA bus support is enabled. + MDA MDA console support is enabled. MOUSE Appropriate mouse support is enabled. - NET Appropriate network support is enabled. - NFS Appropriate NFS support is enabled. + MTD MTD support is nebaled. + NET Appropriate network support is enabled. + NFS Appropriate NFS support is enabled. + OSS OSS sound support is enabled. PARIDE The ParIDE subsystem is enabled. - PCI PCI bus support is enabled. + PCI PCI bus support is enabled. PCMCIA The PCMCIA subsystem is enabled. - PNP Plug & Play support is enabled. + PNP Plug & Play support is enabled. + PPC PowerPC architecture is enabled. PPT Parallel port support is enabled. - PS2 Appropriate PS/2 support is enabled. - RAM RAM disk support is enabled. + PS2 Appropriate PS/2 support is enabled. + RAM RAM disk support is enabled. + S390 S390 architecture is enabled. SCSI Appropriate SCSI support is enabled. + A lot of drivers has their options described inside of + Documentation/scsi/. SERIAL Serial support is enabled. - SMP The kernel is an SMP kernel. - SOUND Appropriate sound system support is enabled. - SWSUSP Software suspension is enabled. + SMP The kernel is an SMP kernel. + SPARC Sparc architecture is enabled. + SWSUSP Software suspension is enabled. + USB USB support is enabled. V4L Video For Linux support is enabled. - VGA The VGA console has been enabled. + VGA The VGA console has been enabled. VT Virtual terminal support is enabled. XT IBM PC/XT MFM hard disk support is enabled. In addition, the following text indicates that the option: BUGS= Relates to possible processor bugs on the said processor. - KNL Is a kernel start-up parameter. + KNL Is a kernel start-up parameter. BOOT Is a boot loader parameter. Parameters denoted with BOOT are actually interpreted by the boot @@ -67,66 +77,113 @@ it will appear as a kernel argument readable via /proc/cmdline by programs running once the system is up. - 53c7xx= [HW,SCSI] Amiga SCSI controllers. + 53c7xx= [HW,SCSI] Amiga SCSI controllers + See header of drivers/scsi/53c7xx.c. + See also Documentation/scsi/ncr53c7xx.txt. acpi= [HW,ACPI] Advanced Configuration and Power Interface + Format: off[,<...>] + See also Documentation/pm.txt. - ad1816= [HW,SOUND] + ad1816= [HW,OSS] + Format: ,,, + See also Documentation/sound/oss/AD1816. - ad1848= [HW,SOUND] - - adb_buttons= [HW,MOUSE] + ad1848= [HW,OSS] + Format: ,,,, - adlib= [HW,SOUND] + adlib= [HW,OSS] + Format: advansys= [HW,SCSI] + See header of drivers/scsi/advansys.c. - aedsp16= [HW,SOUND] + aedsp16= [HW,OSS] Audio Excel DSP 16 + Format: ,,,,, + See also header of sound/oss/aedsp16.c. aha152x= [HW,SCSI] + See Documentation/scsi/aha152x.txt. aha1542= [HW,SCSI] + Format: [,,[,]] aic7xxx= [HW,SCSI] + See Documentation/scsi/aic7xxx.txt. + + allowdma0 [ISAPNP] AM53C974= [HW,SCSI] + Format: ,,, + See also header of drivers/scsi/AM53C974.c. amijoy= [HW,JOY] Amiga joystick support + + apc= [HW,SPARC] Power management functions (SPARCstation-4/5 + deriv.) + Format: noidle + Disable APC CPU standby support. SPARCstation-Fox does + not play well with APC CPU idle - disable it if you have + APC and your system crashes randomly. - apm= [APM] Advanced Power Management. + apm= [APM] Advanced Power Management + See header of arch/i386/kernel/apm.c. applicom= [HW] + Format: , - arcrimi= [HW,NET] + arcrimi= [HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards + Format: ,, ataflop= [HW,M68k] - atarimouse= [HW,MOUSE] Atari Mouse. + atarimouse= [HW,MOUSE] Atari Mouse - atascsi= [HW,SCSI] Atari SCSI. + atascsi= [HW,SCSI] Atari SCSI - awe= [HW,SOUND] - - aztcd= [HW,CD] Aztec CD driver. + atkbd_set= [HW] Select keyboard code set + Format: - baycom_epp= [HW,AX25] - - baycom_par= [HW,AX25] BayCom Parallel Port AX.25 Modem. - - baycom_ser_fdx= [HW,AX25] BayCom Serial Port AX.25 Modem in Full - Duplex Mode. + atkbd_reset [HW] Reset keyboard during initialization - baycom_ser_hdx= [HW,AX25] BayCom Serial Port AX.25 Modem in Half - Duplex Mode. + autotest [IA64] - bmouse= [HW,MOUSE,PS2] Bus mouse. + awe= [HW,OSS] AWE32/SB32/AWE64 wave table synth + Format: ,, + + aztcd= [HW,CD] Aztech CD268 CDROM driver + Format: ,0x79 (?) - bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards), most - bttv.radio= important insmod options are available as kernel args too. - bttv.pll= see Documentation/video4linux/bttv/Insmod-options + baycom_epp= [HW,AX25] + Format: , + + baycom_par= [HW,AX25] BayCom Parallel Port AX.25 Modem + Format: , + See header of drivers/net/hamradio/baycom_par.c. + + baycom_ser_fdx= [HW,AX25] BayCom Serial Port AX.25 Modem (Full Duplex Mode) + Format: ,,[,] + See header of drivers/net/hamradio/baycom_ser_fdx.c. + + baycom_ser_hdx= [HW,AX25] BayCom Serial Port AX.25 Modem (Half Duplex Mode) + Format: ,, + See header of drivers/net/hamradio/baycom_ser_hdx.c. + + blkmtd_device= [HW,MTD] + blkmtd_erasesz= + blkmtd_ro= + blkmtd_bs= + blkmtd_count= + + bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards) + bttv.radio= Most important insmod options are available as kernel args too. + bttv.pll= See Documentation/video4linux/bttv/Insmod-options bttv.tuner= and Documentation/video4linux/bttv/CARDLIST BusLogic= [HW,SCSI] + See drivers/scsi/BusLogic.c, comment before function + BusLogic_ParseDriverOptions(). + + c101= [NET] Moxa C101 synchronous serial card cachesize= [BUGS=IA-32] Override level 2 CPU cache size detection. Sometimes CPU hardware bugs make them report the cache @@ -136,54 +193,87 @@ This option provides an override for these situations. cdu31a= [HW,CD] + Format: ,[,PAS] + See header of drivers/cdrom/cdu31a.c. - chandev= [HW,NET] + chandev= [HW,NET] Generic channel device initialisation cm206= [HW,CD] + Format: { auto | [,][] } - com20020= [HW,NET] + com20020= [HW,NET] ARCnet - COM20020 chipset + Format: [,[,[,[,[,]]]]] - com90io= [HW,NET] + com90io= [HW,NET] ARCnet - COM90xx chipset (IO-mapped buffers) + Format: [,] - com90xx= [HW,NET] + com90xx= [HW,NET] ARCnet - COM90xx chipset (memory-mapped buffers) + Format: [,[,]] - condev= [HW] + condev= [HW,S390] console device + conmode= - console= [KNL] output console + comm spec (speed, control, - parity). + console= [KNL] Output console + Console device and comm spec (speed, control, parity). + + cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver + Format: ,,,[,] cpia_pp= [HW,PPT] + Format: { parport | auto | none } - cs4232= [HW,SOUND] + cs4232= [HW,OSS] + Format: ,,,,, cs89x0_dma= [HW,NET] + Format: + + cs89x0_media= [HW,NET] + Format: { rj45 | aui | bnc } ctc= [HW,NET] + See drivers/s390/net/ctcmain.c, comment before function + ctc_setup(). cyclades= [HW,SERIAL] Cyclades multi-serial port adapter. dasd= [HW,NET] + See header of drivers/s390/block/dasd_devmap.c. - db9= [HW,JOY] + dasd_discipline= + [HW,NET] + See header of drivers/s390/block/dasd.c. - db9_2= [HW,JOY] - - db9_3= [HW,JOY] + db9= [HW,JOY] + db9_2= + db9_3= debug [KNL] Enable kernel debugging (events log level). decnet= [HW,NET] + Format: [,] + See also Documentation/networking/decnet.txt. - devfs= [DEVFS] + decr_overclock= [PPC] + decr_overclock_proc0= + + devfs= [DEVFS] + See Documentation/filesystems/devfs/boot-options. - digi= [HW,SERIAL] io parameters + enable/disable command. + digi= [HW,SERIAL] + IO parameters + enable/disable command. digiepca= [HW,SERIAL] + See drivers/char/README.epca and + Documentation/digiepca.txt. dmascc= [HW,AX25,SERIAL] AX.25 Z80SCC driver with DMA support available. + Format: [,[,..]] + + dmasound= [HW,OSS] Sound subsystem buffers - dmasound= [HW,SOUND] (sound subsystem buffers). + dscc4.setup= [NET] dtc3181e= [HW,SCSI] @@ -194,101 +284,155 @@ edb= [HW,PS2] eicon= [HW,ISDN] + Format: ,, - es1370= [HW,SOUND] + eisa_irq_edge= [PARISC] + See header of drivers/parisc/eisa.c. - es1371= [HW,SOUND] - - ether= [HW,NET] Ethernet cards parameters (irq, - base_io_addr, mem_start, mem_end, name. - (mem_start is often overloaded to mean something - different and driver-specific). + elanfreq= [IA-32] + See comment before function elanfreq_setup() in + arch/i386/kernel/cpu/cpufreq/elanfreq.c. + + es1370= [HW,OSS] + Format: [,] + See also header of sound/oss/es1370.c. + + es1371= [HW,OSS] + Format: ,[,[]] + See also header of sound/oss/es1371.c. + + ether= [HW,NET] Ethernet cards parameters + This option is obsoleted by the "netdev=" option, which + has equivalent usage. See its documentation for details. fd_mcs= [HW,SCSI] + See header of drivers/scsi/fd_mcs.c. fdomain= [HW,SCSI] + See header of drivers/scsi/fdomain.c. floppy= [HW] + See Documentation/floppy.txt. ftape= [HW] Floppy Tape subsystem debugging options. + See Documentation/ftape.txt. gamma= [HW,DRM] gc= [HW,JOY] - - gc_2= [HW,JOY] - - gc_3= [HW,JOY] + gc_2= See Documentation/input/joystick-parport.txt. + gc_3= gdth= [HW,SCSI] + See header of drivers/scsi/gdth.c. - gpt [EFI] Forces disk with valid GPT signature but + gpt [EFI] Forces disk with valid GPT signature but invalid Protective MBR to be treated as GPT. gscd= [HW,CD] + Format: + + gt96100eth= [NET] MIPS GT96100 Advanced Communication Controller - gus= [HW,SOUND] + gus= [HW,OSS] + Format: ,,, gvp11= [HW,SCSI] - hd= [EIDE] (E)IDE hard drive subsystem geometry - (Cyl/heads/sectors) or tune parameters. + hcl= [IA-64] SGI's Hardware Graph compatibility layer - hfmodem= [HW,AX25] + hd= [EIDE] (E)IDE hard drive subsystem geometry + Format: ,, + + hd?= [HW] (E)IDE subsystem + hd?lun= See Documentation/ide.txt. hisax= [HW,ISDN] + See Documentation/isdn/README.HiSax. + + hugepages= [HW,IA-32] Maximal number of HugeTLB pages + + i8042_direct [HW] Non-translated mode + i8042_dumbkbd + i8042_noaux + i8042_nomux + i8042_reset [HW] Reset the controller during init and cleanup + i8042_unlock [HW] Unlock (ignore) the keylock i810= [HW,DRM] - ibmmcascsi= [HW,MCA,SCSI] IBM MicroChannel SCSI adapter. + ibmmcascsi= [HW,MCA,SCSI] IBM MicroChannel SCSI adapter + See Documentation/mca.txt. icn= [HW,ISDN] + Format: [,[,[,]]] - ide?= [HW] (E)IDE subsystem : config (iomem/irq), tuning or - debugging (serialize,reset,no{dma,tune,probe}) or - chipset specific parameters. + ide?= [HW] (E)IDE subsystem + Config (iomem/irq), tuning or debugging + (serialize,reset,no{dma,tune,probe}) or chipset + specific parameters. + See Documentation/ide.txt. - idebus= [HW] (E)IDE subsystem : VLB/PCI bus speed. + idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed + See Documentation/ide.txt. idle= [HW] + Format: poll in2000= [HW,SCSI] + See header of drivers/scsi/in2000.c. init= [KNL] + Format: + Run specified binary instead of /sbin/init as init + process. - initrd= [BOOT] Specify the location of the initial ramdisk. + initrd= [BOOT] Specify the location of the initial ramdisk - ip= [IP_PNP] + inport_irq= [HW] Inport (ATI XL and Microsoft) busmouse driver + Format: - isapnp= [ISAPNP] Specify RDP, reset, pci_scan and verbosity. + inttest= [IA64] - isapnp_reserve_irq= [ISAPNP] Exclude IRQs for the autoconfiguration. + ip= [IP_PNP] + See Documentation/nfsroot.txt. - isapnp_reserve_dma= [ISAPNP] Exclude DMAs for the autoconfiguration. + ip2= [HW] Set IO/IRQ pairs for up to 4 IntelliPort boards + See comment before ip2_setup() in drivers/char/ip2.c. - isapnp_reserve_io= [ISAPNP] Exclude I/O ports for the autoconfiguration. - Ranges are in pairs (I/O port base and size). + ips= [HW,SCSI] Adaptec / IBM ServeRAID controller + See header of drivers/scsi/ips.c. - isapnp_reserve_mem= [ISAPNP] Exclude memory regions for the autoconfiguration. - Ranges are in pairs (memory base and size). + isapnp= [ISAPNP] + Format: , , , isp16= [HW,CD] + Format: ,,, iucv= [HW,NET] js= [HW,JOY] Analog joystick - - kbd-reset [VT] + See Documentation/input/joystick.txt. - keepinitrd [HW, ARM] + keepinitrd [HW,ARM] - load_ramdisk= [RAM] List of ramdisks to load from floppy. + l2cr= [PPC] + + lasi= [HW,SCSI] PARISC LASI driver for the 53c700 chip + Format: addr:,irq: + + llsc*= [IA64] + See function print_params() in arch/ia64/sn/kernel/llsc4.c. + + load_ramdisk= [RAM] List of ramdisks to load from floppy + See Documentation/ramdisk.txt. lockd.udpport= [NFS] lockd.tcpport= [NFS] - logi_busmouse= [HW, MOUSE] + logibm_irq= [HW,MOUSE] Logitech Bus Mouse Driver + Format: lp=0 [LP] Specify parallel ports to use, e.g, lp=port[,port...] lp=none,parport0 (lp0 not configured, lp1 uses @@ -305,62 +449,93 @@ from each port should be examined, to see if an IEEE 1284-compliant printer is attached; if so, the driver will manage that printer. + See also header of drivers/char/lp.c. - ltpc= [HW] + ltpc= [NET] + Format: ,, mac5380= [HW,SCSI] + Format: ,,,, - mac53c9x= [HW,SCSI] + mac53c9x= [HW,SCSI] + Format: ,,,,,,, - mad16= [HW,SOUND] + mad16= [HW,OSS] + Format: ,,,,,, - maui= [HW,SOUND] + maui= [HW,OSS] + Format: , - max_loop=[0-255] [LOOP] Set the maximum number of loopback devices - that can be mounted. + max_loop= [LOOP] Maximum number of loopback devices that can + be mounted + Format: <1-256> - maxcpus= [SMP] States the maximum number of processors that - an SMP kernel should make use of. + maxcpus= [SMP] Maximum number of processors that an SMP kernel + should make use of max_scsi_luns= [SCSI] - mca [IA-32] On some pentium machines the mce support defaults - to off as the mainboard support is not always present. - You must activate it as a boot option + max_scsi_report_luns= + [SCSI] Maximum number of LUNs received + Should be between 1 and 16384. mca-pentium [BUGS=IA-32] + mcatest= [IA-64] + mcd= [HW,CD] + Format: ,, mcdx= [HW,CD] - md= [HW] RAID subsystems devices and level. + mce [IA-32] Machine Check Exception - mdisk= [HW] + md= [HW] RAID subsystems devices and level + See Documentation/md.txt. mdacon= [MDA] - - megaraid= [HW,SCSI] + Format: , - mem=exactmap [KNL,BOOT,IA-32] enable setting of an exact - e820 memory map, as specified by the user. - Such mem=exactmap lines can be constructed - based on BIOS output or other requirements. + mem=exactmap [KNL,BOOT,IA-32] Enable setting of an exact + E820 memory map, as specified by the user. + Such mem=exactmap lines can be constructed based on + BIOS output or other requirements. See the mem=nn@ss + option description. - mem=nn[KMG] [KNL,BOOT] force use of a specific amount of - memory; to be used when the kernel is not able + mem=nn[KMG] [KNL,BOOT] Force usage of a specific amount of memory + Amount of memory to be used when the kernel is not able to see the whole system memory or for test. - memfrac= [KNL] + mem=nn[KMG]@ss[KMG] + [KNL,BOOT] Force usage of a specific region of memory + Region of memory to be used, from ss to ss+nn. mem=nopentium [BUGS=IA-32] Disable usage of 4MB pages for kernel memory. + memfrac= [KNL] + + meye= [HW] Set MotionEye Camera parameters + See Documentation/video4linux/meye.txt. + mga= [HW,DRM] - mpu401= [HW,SOUND] - - msmouse= [HW,MOUSE] Microsoft Mouse. + mpu401= [HW,OSS] + Format: , + + MTD_Partition= [MTD] + Format: ,,, + + MTD_Region= [MTD] + Format: ,[,,,,] + + mtdparts= [MTD] + See drivers/mtd/cmdline.c. + + n2= [NET] SDL Inc. RISCom/N2 synchronous serial card + + NCR_D700= [HW,SCSI] + See header of drivers/scsi/NCR_D700.c. ncr5380= [HW,SCSI] @@ -372,17 +547,18 @@ ncr53c8xx= [HW,SCSI] - netdev= [NET] Ethernet cards parameters (irq, - base_io_addr, mem_start, mem_end, name. - (mem_start is often overloaded to mean something - different and driver-specific). - (cf: ether=) + netdev= [NET] Network devices parameters + Format: ,,,, + Note that mem_start is often overloaded to mean + something different and driver-specific. nfsaddrs= [NFS] + See Documentation/nfsroot.txt. nfsroot= [NFS] nfs root filesystem for disk-less boxes. + See Documentation/nfsroot.txt. - nmi_watchdog= [KNL,BUGS=IA-32] debugging features for SMP kernels. + nmi_watchdog= [KNL,BUGS=IA-32] Debugging features for SMP kernels no387 [BUGS=IA-32] Tells the kernel to use the 387 maths emulation library even if a 387 maths coprocessor @@ -393,12 +569,16 @@ noapic [SMP,APIC] Tells the kernel not to make use of any APIC that may be present on the system. - noasync [HW, M68K] Disables async and sync negotiation for + noasync [HW,M68K] Disables async and sync negotiation for all devices. nocache [ARM] - nodisconnect [HW,SCSI, M68K] Disables SCSI disconnects. + nodisconnect [HW,SCSI,M68K] Disables SCSI disconnects. + + nofxsr [BUGS=IA-32] + + nohighio [BUGS=IA-32] Disable highmem block I/O. nohlt [BUGS=ARM] @@ -415,27 +595,42 @@ nointroute [IA-64] + nomce [IA-32] Machine Check Exception + noresume [SWSUSP] Disables resume and restore original swap space. no-scroll [VGA] + nosbagart [IA-64] + nosmp [SMP] Tells an SMP kernel to act as a UP kernel. - nosync [HW, M68K] Disables sync negotiation for all devices. + nosync [HW,M68K] Disables sync negotiation for all devices. - notsc [BUGS=IA-32] Disable Time Stamp Counter + notsc [BUGS=IA-32] Disable Time Stamp Counter + + nousb [USB] Disable the USB subsystem nowb [ARM] - opl3= [HW,SOUND] + opl3= [HW,OSS] + Format: - opl3sa= [HW,SOUND] + opl3sa= [HW,OSS] + Format: ,,,,, - opl3sa2= [HW,SOUND] + opl3sa2= [HW,OSS] + Format: ,,,,,,,[,, + + osst= [HW,SCSI] SCSI Tape Driver + Format: , + See also Documentation/scsi/st.txt. - panic= [KNL] kernel behaviour on panic. + panic= [KNL] Kernel behaviour on panic + Format: parport=0 [HW,PPT] Specify parallel ports. 0 disables. parport=auto Use 'auto' to force the driver to use @@ -452,13 +647,17 @@ order they are specified on the command line, starting with parport0. - pas2= [HW,SOUND] + pas2= [HW,OSS] + Format: ,,,,,,, pas16= [HW,SCSI] + See header of drivers/scsi/pas16.c. pcbit= [HW,ISDN] pcd. [PARIDE] + See header of drivers/block/paride/pcd.c. + See also Documentation/paride.txt. pci=option[,option...] [PCI] various PCI subsystem options: off [IA-32] don't probe for the PCI bus @@ -503,153 +702,407 @@ have no effect if ACPI IRQ routing is enabled. + pcmv= [HW,PCMCIA] BadgePAD 4 + pd. [PARIDE] + See Documentation/paride.txt. pf. [PARIDE] + See Documentation/paride.txt. pg. [PARIDE] + See Documentation/paride.txt. + + pirq= [SMP,APIC] Manual mp-table setup + See Documentation/i386/IO-APIC.txt. + + plip= [PPT,NET] Parallel port network link + Format: { parport | timid | 0 } + See also Documentation/parport.txt. + + pnpbios= [ISAPNP] + { on | off | curr | res | no-curr | no-res } - pirq= [SMP,APIC] mp-table. + pnp_reserve_irq= + [ISAPNP] Exclude IRQs for the autoconfiguration - plip= [PPT,NET] Parallel port network link. + pnp_reserve_dma= + [ISAPNP] Exclude DMAs for the autoconfiguration - profile= [KNL] enable kernel profiling via /proc/profile - (param:log level). + pnp_reserve_io= [ISAPNP] Exclude I/O ports for the autoconfiguration + Ranges are in pairs (I/O port base and size). + + pnp_reserve_mem= + [ISAPNP] Exclude memory regions for the autoconfiguration + Ranges are in pairs (memory base and size). + + profile= [KNL] Enable kernel profiling via /proc/profile + Format: prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk before loading. + See Documentation/ramdisk.txt. + + psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions + + pss= [HW,OSS] Personal Sound System (ECHO ESC614) + Format: ,,,,, - pss= [HW,SOUND] - pt. [PARIDE] + See Documentation/paride.txt. - quiet= [KNL] Disable log messages. + quiet= [KNL] Disable log messages r128= [HW,DRM] raid= [HW,RAID] + See Documentation/md.txt. - ramdisk= [RAM] Sizes of RAM disks in kilobytes [deprecated]. + ramdisk= [RAM] Sizes of RAM disks in kilobytes [deprecated] + See Documentation/ramdisk.txt. ramdisk_blocksize= [RAM] + See Documentation/ramdisk.txt. - ramdisk_size= [RAM] New name for the ramdisk parameter. + ramdisk_size= [RAM] Sizes of RAM disks in kilobytes + New name for the ramdisk parameter. + See Documentation/ramdisk.txt. ramdisk_start= [RAM] Starting block of RAM disk image (so you can place it after the kernel image on a boot floppy). + See Documentation/ramdisk.txt. - reboot= [BUGS=IA-32] + reboot= [BUGS=IA-32,BUGS=ARM,BUGS=IA-64] Rebooting mode + Format: [,[,...]] + See arch/*/kernel/reboot.c. - reserve= [KNL,BUGS] force the kernel to ignore some iomem area. + reserve= [KNL,BUGS] Force the kernel to ignore some iomem area - resume= [SWSUSP] specify the partition device for software suspension. + resume= [SWSUSP] Specify the partition device for software suspension riscom8= [HW,SERIAL] + Format: [,[,...]] - ro [KNL] Mount root device read-only on boot. + ro [KNL] Mount root device read-only on boot - root= [KNL] root filesystem. + root= [KNL] Root filesystem - rootflags= [KNL] set root filesystem mount option string + rootflags= [KNL] Set root filesystem mount option string - rootfstype= [KNL] set root filesystem type + rootfstype= [KNL] Set root filesystem type - rw [KNL] Mount root device read-write on boot. + rw [KNL] Mount root device read-write on boot - S [KNL] run init in single mode. + S [KNL] Run init in single mode - sb= [HW,SOUND] + sa1100ir [NET] + See drivers/net/irda/sa1100_ir.c. + + sb= [HW,OSS] + Format: ,,, + + sbni= [NET] Granch SBNI12 leased line adapter - sbpcd= [HW,CD] Soundblaster CD adapter. + sbpcd= [HW,CD] Soundblaster CD adapter + Format: , + See a comment before function sbpcd_setup() in + drivers/cdrom/sbpcd.c. + + scsi_debug_*= [SCSI] + See drivers/scsi/scsi_debug.c. + + scsi_default_dev_flags= + [SCSI] SCSI default device flags + Format: + + scsi_dev_flags= [SCSI] Black/white list entry for vendor and model + Format: :: + (flags are integer value) scsi_logging= [SCSI] scsihosts= [SCSI] + serialnumber [BUGS=IA-32] + + sf16fm= [HW] SF16FMI radio driver for Linux + Format: + sg_def_reserved_size= [SCSI] - sgalaxy= [HW,SOUND] + sgalaxy= [HW,OSS] + Format: ,,,, + + shapers= [NET] + Maximal number of shapers. sim710= [SCSI,HW] + See header of drivers/scsi/sim710.c. + + simeth= [IA-64] + simscsi= sjcd= [HW,CD] + Format: ,, + See header of drivers/cdrom/sjcd.c. + + slram= [HW,MTD] smart2= [HW] + Format: [,[,...,]] + + snd-ad1816a= [HW,ALSA] + + snd-ad1848= [HW,ALSA] + + snd-ali5451= [HW,ALSA] + + snd-als100= [HW,ALSA] + + snd-als4000= [HW,ALSA] + + snd-azt2320= [HW,ALSA] + + snd-cmi8330= [HW,ALSA] + + snd-cmipci= [HW,ALSA] + + snd-cs4231= [HW,ALSA] + + snd-cs4232= [HW,ALSA] + + snd-cs4236= [HW,ALSA] + + snd-cs4281= [HW,ALSA] + + snd-cs46xx= [HW,ALSA] + + snd-dt019x= [HW,ALSA] + + snd-dummy= [HW,ALSA] + + snd-emu10k1= [HW,ALSA] + + snd-ens1370= [HW,ALSA] + + snd-ens1371= [HW,ALSA] + + snd-es968= [HW,ALSA] + + snd-es1688= [HW,ALSA] + + snd-es18xx= [HW,ALSA] + + snd-es1938= [HW,ALSA] + + snd-es1968= [HW,ALSA] + + snd-fm801= [HW,ALSA] + + snd-gusclassic= [HW,ALSA] + + snd-gusextreme= [HW,ALSA] + + snd-gusmax= [HW,ALSA] + + snd-hdsp= [HW,ALSA] + + snd-ice1712= [HW,ALSA] + + snd-intel8x0= [HW,ALSA] + + snd-interwave= [HW,ALSA] + + snd-interwave-stb= + [HW,ALSA] + + snd-korg1212= [HW,ALSA] + + snd-maestro3= [HW,ALSA] + + snd-mpu401= [HW,ALSA] + + snd-mtpav= [HW,ALSA] + + snd-nm256= [HW,ALSA] + + snd-opl3sa2= [HW,ALSA] + + snd-opti92x-ad1848= + [HW,ALSA] + + snd-opti92x-cs4231= + [HW,ALSA] + + snd-opti93x= [HW,ALSA] + + snd-pmac= [HW,ALSA] + + snd-rme32= [HW,ALSA] + + snd-rme96= [HW,ALSA] + + snd-rme9652= [HW,ALSA] + + snd-sb8= [HW,ALSA] + + snd-sb16= [HW,ALSA] + + snd-sbawe= [HW,ALSA] + + snd-serial= [HW,ALSA] + + snd-sgalaxy= [HW,ALSA] + + snd-sonicvibes= [HW,ALSA] + + snd-sun-amd7930= + [HW,ALSA] + + snd-sun-cs4231= [HW,ALSA] + + snd-trident= [HW,ALSA] + + snd-usb-audio= [HW,ALSA,USB] + + snd-via82xx= [HW,ALSA] + + snd-virmidi= [HW,ALSA] + + snd-wavefront= [HW,ALSA] + + snd-ymfpci= [HW,ALSA] - sonicvibes= [HW,SOUND] + sonicvibes= [HW,OSS] + Format: sonycd535= [HW,CD] + Format: [,] - sound= [SOUND] + sonypi= [HW] Sony Programmable I/O Control Device driver + Format: ,,,,, - soundmodem= [HW,AX25,SOUND] Use sound card as packet radio modem. + specialix= [HW,SERIAL] Specialix multi-serial port adapter + See Documentation/specialix.txt. - specialix= [HW,SERIAL] Specialix multi-serial port adapter. + speedstep_coppermine= + [HW,IA-32] Take CPU in your notebook as SpeedStep-capable + See comment before function speedstep_setup() in + arch/i386/kernel/cpu/cpufreq/speedstep.c. - sscape= [HW,SOUND] + spia_io_base= [HW,MTD] + spia_fio_base= + spia_pedr= + spia_peddr= + + spread_lpevents= + [PPC] + + sscape= [HW,OSS] + Format: ,,,, - st= [HW,SCSI] SCSI tape parameters (buffers, etc.). + st= [HW,SCSI] SCSI tape parameters (buffers, etc.) + See Documentation/scsi/st.txt. st0x= [HW,SCSI] + See header of drivers/scsi/seagate.c. - stram_swap= [HW] + stram_swap= [HW,M68k] - swiotlb= [IA-64] Number of I/O TLB slabs. + swiotlb= [IA-64] Number of I/O TLB slabs - switches= [HW, M68K] + switches= [HW,M68k] sym53c416= [HW,SCSI] + See header of drivers/scsi/sym53c416.c. sym53c8xx= [HW,SCSI] + See Documentation/scsi/ncr53c8xx.txt. t128= [HW,SCSI] + See header of drivers/scsi/t128.c. tdfx= [HW,DRM] - tgfx= [HW,JOY] + tgfx= [HW,JOY] TurboGraFX parallel port interface + tgfx_2= See Documentation/input/joystick-parport.txt. + tgfx_3= - tgfx_2= [HW,JOY] + tipar= [HW] + See header of drivers/char/tipar.c. - tgfx_3= [HW,JOY] + tiusb= [HW,USB] Texas Instruments' USB GraphLink (aka SilverLink) + Format: tmc8xx= [HW,SCSI] + See header of drivers/scsi/seagate.c. tmscsim= [HW,SCSI] + See comment before function dc390_setup() in + drivers/scsi/tmscsim.c. tp720= [HW,PS2] - trix= [HW,SOUND] + trix= [HW,OSS] MediaTrix AudioTrix Pro + Format: ,,,,,,,, - u14-34f= [HW,SCSI] + u14-34f= [HW,SCSI] UltraStor 14F/34F SCSI host adapter + See header of drivers/scsi/u14-34f.c. - uart401= [HW,SOUND] + uart401= [HW,OSS] + Format: , - uart6850= [HW,SOUND] - - usbfix [BUGS=IA-64] - - video= [FB] frame buffer configuration. - - vga= [BOOT] on IA-32, select a particular video mode - (use vga=ask for menu). This is actually a - boot loader parameter; the value is passed to - the kernel using a special protocol. See - linux/Documentation/i386/boot.txt for information. + uart6850= [HW,OSS] + Format: , + + video= [FB] Frame buffer configuration + See Documentation/fb/modedb.txt. + + vga= [BOOT,IA-32] Select a particular video mode + See Documentation/i386/boot.txt and Documentation/svga.txt. + Use vga=ask for menu. + This is actually a boot loader parameter; the value is + passed to the kernel using a special protocol. vmhalt= [KNL,S390] vmpoff= [KNL,S390] - waveartist= [HW,SOUND] + waveartist= [HW,OSS] + Format: ,,, wd33c93= [HW,SCSI] + See header of drivers/scsi/wd33c93.c. wd7000= [HW,SCSI] + See header of drivers/scsi/wd7000.c. - wdt= [HW] + wdt= [HW] Watchdog + See Documentation/watchdog.txt. xd= [HW,XT] Original XT pre-IDE (RLL encoded) disks. + xd_geo= See header of drivers/block/xd.c. + + xirc2ps_cs= [NET,PCMCIA] + Format: ,,,,,[,[,[,]]] + + + +Changelog: + + The last known update (for 2.4.0) - the changelog was not kept before. + 2000-06-?? Mr. Unknown + + Update for 2.5.49, description for most of the options introduced, + references to other documentation (C files, READMEs, ..), added S390, + PPC, SPARC, MTD, ALSA and OSS category. Minor corrections and + reformatting. + 2002-11-24 Petr Baudis + Randy Dunlap + +TODO: - xd_geo= [HW,XT] + Add documentation for ALSA options. + Add more DRM drivers. diff -Nru a/Documentation/magic-number.txt b/Documentation/magic-number.txt --- a/Documentation/magic-number.txt Wed Nov 27 14:36:30 2002 +++ b/Documentation/magic-number.txt Wed Nov 27 14:36:30 2002 @@ -43,57 +43,115 @@ 29 Jul 1998 +Updated the magic table to Linux 2.5.45. Right over the feature freeze, +but it is possible that some new magic numbers will sneak into the +kernel before 2.6.x yet. + + Petr Baudis + + 03 Nov 2002 + Magic Name Number Structure File =========================================================================== -PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h +PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h +CMAGIC 0x0111 user include/linux/a.out.h MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h +SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h +AURORA_MAGIC 0x0A18 Aurora_port drivers/sbus/char/aurora.h +HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c APM_BIOS_MAGIC 0x4101 apm_user arch/i386/kernel/apm.c CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h FASYNC_MAGIC 0x4601 fasync_struct include/linux/fs.h -PTY_MAGIC 0x5001 (none at the moment) - drivers/char/pty.c -PPP_MAGIC 0x5002 ppp include/linux/if_ppp.h +ISICOM_MAGIC 0x4d54 isi_port include/linux/isicom.h +PTY_MAGIC 0x5001 (none at the moment) + drivers/char/pty.c +PPP_MAGIC 0x5002 ppp include/linux/if_pppvar.h SERIAL_MAGIC 0x5301 async_struct include/linux/serial.h SSTATE_MAGIC 0x5302 serial_state include/linux/serial.h SLIP_MAGIC 0x5302 slip drivers/net/slip.h STRIP_MAGIC 0x5303 strip drivers/net/strip.c X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h -SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h +SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h ESP_MAGIC 0x53ee esp_struct drivers/char/esp.h TTY_MAGIC 0x5401 tty_struct include/linux/tty.h +MGSL_MAGIC 0x5401 mgsl_info drivers/char/synclink.c TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h +MGSLPC_MAGIC 0x5402 mgslpc_info drivers/char/pcmcia/synclink_cs.c TTY_LDISC_MAGIC 0x5403 tty_ldisc include/linux/tty_ldisc.h -SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h -CG_MAGIC 0x090255 ufs_cylinder_group include/linux/ufs_fs.h -RPORT_MAGIC 0x525001 r_port drivers/char/rocket_int.h -GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h +USB_SERIAL_MAGIC 0x6702 usb_serial drivers/usb/serial/usb-serial.h +USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth drivers/usb/class/bluetty.c +RFCOMM_TTY_MAGIC 0x6d02 (note at the moment) + net/bluetooth/rfcomm/tty.c +USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h +CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h +A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h +SOLARIS_SOCKET_MAGIC 0x000ADDED sol_socket_struct arch/sparc64/solaris/socksys.h +RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h +LSEMAGIC 0x05091998 lse drivers/fc4/fc.c +GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h +RIO_MAGIC 0x12345678 gs_port drivers/char/rio/rio_linux.c +SX_MAGIC 0x12345678 gs_port drivers/char/sx.h NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h -SLAB_RED_MAGIC2 0x170fc2a5 (any) mm/slab.c +RED_MAGIC2 0x170fc2a5 (any) mm/slab.c BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data drivers/isdn/isdn_x25iface.h ECP_MAGIC 0x21504345 cdkecpsig include/linux/cdk.h +LSOMAGIC 0x27091997 lso drivers/fc4/fc.c LSMAGIC 0x2a3b4d2a ls drivers/fc4/fc.c -LSOMAGIC 0x2a3c4e3c lso drivers/fc4/fc.c WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} include/linux/wanpipe.h -CODA_CNODE_MAGIC 0x47114711 coda_inode_info include/linux/coda_fs_i.h +CS_CARD_MAGIC 0x43525553 cs_card sound/oss/cs46xx.c +LABELCL_MAGIC 0x4857434c labelcl_info_s include/asm/ia64/sn/labelcl.h ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h -ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s include/linux/isdn.h +CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info drivers/s390/net/ctctty.c +ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_lib.h +SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h +CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c +COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c +I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c +TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c ROUTER_MAGIC 0x524d4157 wan_device include/linux/wanrouter.h -SLAB_RED_MAGIC1 0x5a2cf071 (any) mm/slab.c +SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h +SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c +GDA_MAGIC 0x58464552 gda include/asm-mips64/sn/gda.h +RED_MAGIC1 0x5a2cf071 (any) mm/slab.c STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h -EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h +EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h +KV_MAGIC 0x5f4b565f kernel_vars_s include/asm-mips64/sn/klkernvars.h +I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c +TRIDENT_STATE_MAGIC 0x63657373 trient_state sound/oss/trident.c +M3_CARD_MAGIC 0x646e6f50 m3_card sound/oss/maestro3.c +SLOT_MAGIC 0x67267321 slot drivers/hotplug/cpqphp.h +SLOT_MAGIC 0x67267322 slot drivers/hotplug/acpiphp.h LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h +M3_STATE_MAGIC 0x734d724d m3_state sound/oss/maestro3.c STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h +VMALLOC_MAGIC 0x87654320 snd_alloc_track sound/core/memory.c +KMALLOC_MAGIC 0x87654321 snd_alloc_track sound/core/memory.c +PWC_MAGIC 0x89DC10AB pwc_device drivers/usb/media/pwc.h NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h -SLAB_MAGIC_ALLOC 0xa5c32f2b kmem_slab_s mm/slab.c -SLAB_MAGIC_DESTROYED 0xb2f23c5a kmem_slab_s mm/slab.c +SCI_MAGIC 0xbabeface gs_port drivers/char/sh-sci.h +CODA_MAGIC 0xC0DAC0DA coda_file_info include/linux/coda_fs_i.h STLI_PORTMAGIC 0xe671c7a1 stliport include/linux/istallion.h +YAM_MAGIC 0xF10A7654 yam_port drivers/net/hamradio/yam.c CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c +HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c +NMI_MAGIC 0x48414d4d455201 nmi_s include/asm-mips64/sn/nmi.h + +Note that there are also defined special per-driver magic numbers in sound +memory managment. See include/sound/sndmagic.h for complete list of them. Many +OSS sound drivers have their magic numbers constructed from the soundcard PCI +ID - these are not listed here as well. + +IrDA subsystem also uses large number of own magic numbers, see +include/net/irda/irda.h for a complete list of them. + +HFS is another larger user of magic numbers - you can find them in +fs/hfs/hfs.h. diff -Nru a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX --- a/Documentation/networking/00-INDEX Wed Nov 27 14:36:31 2002 +++ b/Documentation/networking/00-INDEX Wed Nov 27 14:36:31 2002 @@ -104,8 +104,6 @@ - the driver for SMC's 9000 series of Ethernet cards smctr.txt - SMC TokenCard TokenRing Linux driver info. -soundmodem.txt - - Linux driver for sound cards as AX.25 modems tcp.txt - short blurb on how TCP output takes place. tlan.txt diff -Nru a/Documentation/networking/soundmodem.txt b/Documentation/networking/soundmodem.txt --- a/Documentation/networking/soundmodem.txt Wed Nov 27 14:36:27 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,90 +0,0 @@ - LINUX DRIVER FOR SOUNDCARDS AS AX.25 MODEMS - - Thomas M. Sailer, HB9JNX/AE4WA, - -This driver allows either SoundBlaster (sbc) or Windows Sound System (wss) -compatible soundcards to be used as either 1200 baud AFSK or 9600 baud FSK -AX.25 packet radio modems. Only half duplex operation is supported; an -attempt to include full duplex support failed because the hardware did -not support it (it appeared that the card only provides one DMA channel, -although the codec chip would support two channels). The driver needs -some processing power! A 66 MHz 486 DX2 is a minimum requirement. Otherwise -interactive performance of the computer may become sluggish. This driver -does *not* support telephone modem standards, it is intended for radio -use only. - - -The Interface of the driver - -The driver provides kernel network drivers named sm[0-3]. sethdlc -from the ax25 utilities may be used to set driver states etc. Users -of userland AX.25 stacks may use the net2kiss utility (also available -in the ax25 utilities package) to convert packets of a network interface -to a KISS stream on a pseudo tty. There's also a patch available from -me for WAMPES which allows attaching a kernel network interface directly. - - -Configuring the driver - -Some sound cards need to be initialized before they operate in either -SoundBlaster or WSS compatibility mode. The driver does _NOT_ do this; -you may use the standard linux sound driver to initialize the soundcard; -compile it as a module, and do - insmod sound - rmmod sound -The soundcard should then be initialized correctly. If this does not help, -you'll have to write your own initialization utility. - -Every time the driver is inserted into the kernel, it has to know which -modems it should access at which ports. This can be done with the setbaycom -utility. If you are only using one modem, you can also configure the -driver from the insmod command line (or by means of an option line in -/etc/modules.conf). - -Examples: - insmod soundmodem mode="sbc:afsk1200" iobase=0x220 irq=5 dma=1 - sethdlc -i sm0 -p mode "sbc:afsk1200" io 0x220 irq 5 dma 1 - -Both lines configure the first port to drive a soundblaster card -in 1200 baud AFSK mode. - -The channel access parameters can be set with sethdlc -a or kissparms. -Note that both utilities interpret the values slightly different. - - -Input and output levels - -It is important that the input and output levels are adjusted properly. -There are two utilities, available in the ax25 utilities distribution, -to facilitate this: smmixer and smdiag. smdiag allows you to display -the input signal in an oscilloscope like display or an eye diagram. -smmixer allows you to adjust input/output levels. See the respective -man pages. - - -Transmitter keying - -Since soundcards do not have a DC coupled output; PTT keying options include -the following: -* VOX circuitry -* Serial port pin -* Parallel port pin -* MPU401 MIDI output via a retriggerable monoflop. -Circuit schematics may be found at -http://www.ife.ee.ethz.ch/~sailer/pcf/ptt_circ/ptt.html. - - -Compatibility with the rest of the Linux kernel - -The sound driver and the soundcard modem driver compete for the same -hardware resources. Of course only one driver can access a given -interface at a time. Worse yet, the sound driver grabs the soundcard -at startup time. Therefore the soundcard modem driver subsequently won't -be able to access the soundcard. You might therefore find it necessary to -unload the sound driver before using the soundcard modem driver. - - - -vy 73s de -Tom Sailer, sailer@ife.ee.ethz.ch -hb9jnx @ hb9w.ampr.org diff -Nru a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt --- a/Documentation/sysctl/kernel.txt Wed Nov 27 14:36:30 2002 +++ b/Documentation/sysctl/kernel.txt Wed Nov 27 14:36:30 2002 @@ -17,29 +17,42 @@ Currently, these files might (depending on your configuration) show up in /proc/sys/kernel: - acct +- core_pattern +- core_uses_pid - ctrl-alt-del - dentry-state - domainname - hostname - htab-reclaim [ PPC only ] +- hotplug - java-appletviewer [ binfmt_java, obsolete ] - java-interpreter [ binfmt_java, obsolete ] - l2cr [ PPC only ] - modprobe ==> Documentation/kmod.txt +- msgmax +- msgmnb +- msgmni - osrelease - ostype - overflowgid - overflowuid - panic +- pid_max - powersave-nap [ PPC only ] - printk - real-root-dev ==> Documentation/initrd.txt - reboot-cmd [ SPARC only ] -- rtsig-nr - rtsig-max +- rtsig-nr +- sem - sg-big-buff [ generic SCSI device (sg) ] +- shmall - shmmax [ sysv ipc ] +- shmmni +- stop-a [ SPARC only ] +- sysrq ==> Documentation/sysrq.txt - tainted +- threads-max - version - zero-paged [ PPC only ] @@ -62,6 +75,41 @@ ============================================================== +core_pattern: + +core_pattern is used to specify a core dumpfile pattern name. +. max length 64 characters; default value is "core" +. core_pattern is used as a pattern template for the output filename; + certain string patterns (beginning with '%') are substituted with + their actual values. +. backward compatibility with core_uses_pid: + If core_pattern does not include "%p" (default does not) + and core_uses_pid is set, then .PID will be appended to + the filename. +. corename format specifiers: + % '%' is dropped + %% output one '%' + %p pid + %u uid + %g gid + %s signal number + %t UNIX time of dump + %h hostname + %e executable filename + % both are dropped + +============================================================== + +core_uses_pid: + +The default coredump filename is "core". By setting +core_uses_pid to 1, the coredump filename becomes core.PID. +If core_pattern does not include "%p" (default does not) +and core_uses_pid is set, then .PID will be appended to +the filename. + +============================================================== + ctrl-alt-del: When the value in this file is 0, ctrl-alt-del is trapped and @@ -105,6 +153,13 @@ ============================================================== +hotplug: + +Path for the hotplug policy agent. +Default value is "/sbin/hotplug". + +============================================================== + l2cr: (PPC only) This flag controls the L2 cache of G3 processor boards. If @@ -149,6 +204,14 @@ ============================================================== +pid_max: + +PID allocation wrap value. When the kenrel's next PID value +reaches this value, it wraps back to a minimum PID value. +PIDs of value pid_max or larger are not allocated. + +============================================================== + powersave-nap: (PPC only) If set, Linux-PPC will use the 'nap' mode of powersaving, @@ -195,7 +258,7 @@ of POSIX realtime (queued) signals that can be outstanding in the system. -Rtsig-nr shows the number of RT signals currently queued. +rtsig-nr shows the number of RT signals currently queued. ============================================================== @@ -231,6 +294,7 @@ Set by modutils >= 2.4.9. 2 - A module was force loaded by insmod -f. Set by modutils >= 2.4.9. + 4 - Unsafe SMP processors: SMP with CPUs not designed for SMP. ============================================================== diff -Nru a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt --- a/Documentation/usb/ov511.txt Wed Nov 27 14:36:27 2002 +++ b/Documentation/usb/ov511.txt Wed Nov 27 14:36:27 2002 @@ -255,6 +255,15 @@ might be necessary if your camera has a custom lens assembly. This has no effect with video capture devices. + NAME: ov518_color + TYPE: integer (Boolean) + DEFAULT: 0 (off) + DESC: Enable OV518 color support. This is off by default since it doesn't + work most of the time. If you want to try it, you must also load + ov518_decomp with the "nouv=0" parameter. If you get improper colors or + diagonal lines through the image, restart your video app and try again. + Repeat as necessary. + WORKING FEATURES: o Color streaming/capture at most widths and heights that are multiples of 8. o Monochrome (use force_palette=1 to enable) diff -Nru a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt --- a/Documentation/usb/usb-serial.txt Wed Nov 27 14:36:27 2002 +++ b/Documentation/usb/usb-serial.txt Wed Nov 27 14:36:27 2002 @@ -94,10 +94,11 @@ Compaq iPAQ, HP Jornada and Casio EM500 driver This driver can be used to connect to Compaq iPAQ, HP Jornada and Casio EM500 - PDAs running Windows CE 3.0 or PocketPC 2002 using a USB cable/cradle. It - has been tested only on the Compaq H3135, but is rumoured to work on - with the H3600 and later models as well as the Jornada 548 and 568. - With minor modifications, it may work for other CE based handhelds too. + PDAs running Windows CE 3.0 or PocketPC 2002 using a USB cable/cradle. + It's very likely that every device supported by ActiveSync USB works with this + driver. The driver supports the Compaq iPAQ, Jornada 548/568 and the Casio + EM500 out of the box. For others, please use module parameters to specify + the product and vendor id. e.g. modprobe ipaq vendor=0x3f0 product=0x1125 The driver presents a serial interface (usually on /dev/ttyUSB0) over which one may run ppp and establish a TCP/IP link to the iPAQ. Once this @@ -105,36 +106,12 @@ significant advantage of using USB is speed - you can get 73 to 113 kbytes/sec for download/upload to the iPAQ. - The driver works intermittently with the usb-uhci driver but quite - reliably with the uhci driver. However, performance is much better - with usb-uhci. It does not seem to work with ohci at all. + This driver is only one of a set of components required to utilize + the USB connection. Please visit http://synce.sourceforge.net which + contains the necessary packages and a simple step-by-step howto. - You must setup hotplug to invoke pppd as soon as the iPAQ is connected. - A ppp script like the one below should be kept in the file - /etc/hotplug/usb/ipaq Remember to chmod +x. Make sure there are no - options in /etc/ppp/options or ~/.ppprc which conflict with the ones - given below. - - #!/bin/bash - - MYIP=linux.box.ip - REMOTEIP=ipaq.ip - MYDNS=my.dns.server - killall -9 pppd - /usr/sbin/pppd /dev/ttyUSB0 \ - connect "/usr/sbin/chat -v TIMEOUT 60 CLIENT 'CLIENTSERVER\c'" \ - nocrtscts local debug passive $MYIP:$REMOTEIP ms-dns $MYDNS noauth \ - proxyarp - - You must also download and install asyncd from http://synce.sourceforge.net - This is required to emulate keep-alive packets which are exchanged by - ActiveSync and the iPAQ. - - On connecting the cable, you should see the usual "Device Connected", - "User Authenticated" messages flash by on your iPAQ. Once connected, - you can use Win CE programs like ftpView, Pocket Outlook from the iPAQ - and xcerdisp, synce utilities from the Linux side. Remember to enable IP - forwarding. + Once connected, you can use Win CE programs like ftpView, Pocket Outlook + from the iPAQ and xcerdisp, synce utilities from the Linux side. To use Pocket IE, follow the instructions given at http://www.tekguru.co.uk/EM500/usbtonet.htm to achieve the same thing diff -Nru a/Makefile b/Makefile --- a/Makefile Wed Nov 27 14:36:27 2002 +++ b/Makefile Wed Nov 27 14:36:27 2002 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 49 +SUBLEVEL = 50 EXTRAVERSION = # *DOCUMENTATION* @@ -168,7 +168,10 @@ CPPFLAGS := -D__KERNEL__ -Iinclude CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ - -fomit-frame-pointer -fno-strict-aliasing -fno-common + -fno-strict-aliasing -fno-common +ifndef CONFIG_FRAME_POINTER +CFLAGS += -fomit-frame-pointer +endif AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \ diff -Nru a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S --- a/arch/alpha/kernel/systbls.S Wed Nov 27 14:36:31 2002 +++ b/arch/alpha/kernel/systbls.S Wed Nov 27 14:36:31 2002 @@ -399,7 +399,7 @@ .quad sys_getdents64 .quad sys_gettid .quad sys_readahead - .quad sys_ni_syscall /* 380, sys_security */ + .quad sys_ni_syscall /* 380 */ .quad sys_tkill .quad sys_setxattr .quad sys_lsetxattr diff -Nru a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c --- a/arch/arm/boot/compressed/ofw-shark.c Wed Nov 27 14:36:30 2002 +++ b/arch/arm/boot/compressed/ofw-shark.c Wed Nov 27 14:36:30 2002 @@ -27,7 +27,7 @@ /* Head of the taglist */ tag->hdr.tag = ATAG_CORE; tag->hdr.size = tag_size(tag_core); - tag->u.core.flags = FLAG_READONLY; + tag->u.core.flags = 1; tag->u.core.pagesize = PAGE_SIZE; tag->u.core.rootdev = 0; diff -Nru a/arch/arm/def-configs/shark b/arch/arm/def-configs/shark --- a/arch/arm/def-configs/shark Wed Nov 27 14:36:27 2002 +++ b/arch/arm/def-configs/shark Wed Nov 27 14:36:27 2002 @@ -40,6 +40,7 @@ # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set @@ -110,6 +111,12 @@ # CONFIG_H3600_SLEEVE is not set # +# Intel PXA250/210 Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_ARCH_PXA_IDP is not set + +# # CLPS711X/EP721X Implementations # # CONFIG_ARCH_AUTCPU12 is not set @@ -120,6 +127,19 @@ # CONFIG_ARCH_FORTUNET is not set # CONFIG_ARCH_EP7211 is not set # CONFIG_ARCH_EP7212 is not set + +# +# IOP310 Implementation Options +# +# CONFIG_ARCH_IQ80310 is not set + +# +# IOP310 Chipset Features +# +# CONFIG_IOP310_AAU is not set +# CONFIG_IOP310_DMA is not set +# CONFIG_IOP310_MU is not set +# CONFIG_IOP310_PMON is not set # CONFIG_ARCH_ACORN is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set @@ -159,6 +179,9 @@ CONFIG_ISA=y CONFIG_ISA_DMA=y # CONFIG_FIQ is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 # CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set @@ -177,10 +200,11 @@ # CONFIG_PREEMPT is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set +CONFIG_CMDLINE="" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y # CONFIG_LEDS_CPU is not set -# CONFIG_ALIGNMENT_TRAP is not set +CONFIG_ALIGNMENT_TRAP=y # # Parallel port support @@ -201,6 +225,11 @@ # CONFIG_PARPORT_1284 is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Plug and Play configuration # # CONFIG_PNP is not set @@ -217,6 +246,7 @@ # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_CISS_SCSI_TAPE is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y @@ -254,7 +284,6 @@ # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set @@ -263,6 +292,11 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -378,7 +412,7 @@ # CONFIG_WAN is not set # -# "Tulip" family network device support +# Tulip family network device support # # CONFIG_NET_TULIP is not set @@ -393,38 +427,66 @@ # CONFIG_IRDA is not set # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y - -# -# ATA and ATAPI Block devices -# CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# # CONFIG_BLK_DEV_HD_IDE is not set # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set # CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECS is not set +CONFIG_ATAPI=y CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y # CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_IDECS is not set # -# IDE chipset support +# ATA host controller support # +# CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_CMD640_ENHANCED is not set # CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_BLK_DEV_RZ1000 is not set + +# +# PCI host controller support +# +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_IDEDMA_PCI is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_BLK_DEV_IDE_TCQ is not set +# CONFIG_BLK_DEV_IDE_TCQ_DEFAULT is not set +# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC6280_BURST is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_HPT34X_AUTODMA is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_PDC202XX is not set +# CONFIG_PDC202XX_BURST is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_SL82C105 is not set # CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_IVB is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_ATARAID is not set # CONFIG_BLK_DEV_ATARAID_PDC is not set @@ -451,6 +513,7 @@ # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set @@ -462,7 +525,6 @@ # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set # CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_DPT_I2O is not set @@ -522,42 +584,60 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set # # Input device support # # CONFIG_INPUT is not set + +# +# Userland interfaces +# # CONFIG_INPUT_KEYBDEV is not set # CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set # CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_TSLIBDEV is not set # CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_UINPUT is not set + +# +# Input I/O drivers +# # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_GAMEPORT_NS558 is not set # CONFIG_GAMEPORT_L4 is not set -# CONFIG_INPUT_EMU10K1 is not set -# CONFIG_GAMEPORT_PCIGAME is not set +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_VORTEX is not set # CONFIG_GAMEPORT_FM801 is not set # CONFIG_GAMEPORT_CS461x is not set # CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set + +# +# Input Device Drivers +# # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_CS is not set # CONFIG_SERIAL_8250_EXTENDED is not set # CONFIG_SERIAL_8250_MANY_PORTS is not set # CONFIG_SERIAL_8250_SHARE_IRQ is not set @@ -568,10 +648,6 @@ # # Non-8250 serial port support # - -# -# ARM Serial drivers -# # CONFIG_ATOMWIDE_SERIAL is not set # CONFIG_DUALSP_SERIAL is not set # CONFIG_SERIAL_ANAKIN is not set @@ -580,6 +656,7 @@ # CONFIG_SERIAL_AMBA_CONSOLE is not set # CONFIG_SERIAL_CLPS711X is not set # CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X_OLD_NAME is not set # CONFIG_SERIAL_21285 is not set # CONFIG_SERIAL_21285_OLD is not set # CONFIG_SERIAL_21285_CONSOLE is not set @@ -587,6 +664,8 @@ # CONFIG_SERIAL_UART00_CONSOLE is not set # CONFIG_SERIAL_SA1100 is not set # CONFIG_SERIAL_SA1100_CONSOLE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 CONFIG_PRINTER=m @@ -615,17 +694,13 @@ # Mice # # CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set # CONFIG_QIC02_TAPE is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set CONFIG_RTC=y # CONFIG_DTLK is not set @@ -638,6 +713,7 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set # # Multimedia devices @@ -648,6 +724,8 @@ # File systems # # CONFIG_QUOTA is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set @@ -711,6 +789,7 @@ # CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -741,6 +820,7 @@ # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set # CONFIG_SMB_NLS is not set CONFIG_NLS=y @@ -769,6 +849,7 @@ # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set @@ -788,8 +869,6 @@ # # Console drivers # -CONFIG_PC_KEYB=y -CONFIG_PC_KEYMAP=y # CONFIG_VGA_CONSOLE is not set # @@ -797,7 +876,6 @@ # CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set # CONFIG_FB_CLGEN is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_PM3 is not set @@ -806,6 +884,7 @@ # CONFIG_FB_CLPS711X is not set # CONFIG_FB_SA1100 is not set CONFIG_FB_CYBER2000=y +# CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set # CONFIG_FB_ATY is not set # CONFIG_FB_RADEON is not set @@ -814,6 +893,8 @@ # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_PM3 is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB8=y @@ -903,6 +984,8 @@ # Console Switches # # CONFIG_SWITCHES is not set +# CONFIG_SWITCHES_SA1100 is not set +# CONFIG_SWITCHES_UCB1X00 is not set # # USB support @@ -930,6 +1013,11 @@ # CONFIG_DEBUG_LL is not set # CONFIG_DEBUG_DC21285_PORT is not set # CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Security options +# +CONFIG_SECURITY_CAPABILITIES=y # # Library routines diff -Nru a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c --- a/arch/arm/kernel/arthur.c Wed Nov 27 14:36:28 2002 +++ b/arch/arm/kernel/arthur.c Wed Nov 27 14:36:28 2002 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -64,13 +63,13 @@ } static struct exec_domain arthur_exec_domain = { - "Arthur", /* name */ - arthur_lcall7, - PER_RISCOS, PER_RISCOS, - arthur_to_linux_signals, - linux_to_arthur_signals, - THIS_MODULE, - NULL /* Nothing after this in the list. */ + .name = "Arthur", + .handler = arthur_lcall7, + .pers_low = PER_RISCOS, + .pers_high = PER_RISCOS, + .signal_map = arthur_to_linux_signals, + .signal_invmap = linux_to_arthur_signals, + .module = THIS_MODULE, }; /* @@ -78,12 +77,12 @@ * processes are using it. */ -int __init arthur_init(void) +static int __init arthur_init(void) { return register_exec_domain(&arthur_exec_domain); } -void __exit arthur_exit(void) +static void __exit arthur_exit(void) { unregister_exec_domain(&arthur_exec_domain); } diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S --- a/arch/arm/kernel/calls.S Wed Nov 27 14:36:32 2002 +++ b/arch/arm/kernel/calls.S Wed Nov 27 14:36:32 2002 @@ -237,7 +237,7 @@ /* 220 */ .long sys_madvise .long sys_fcntl64 .long sys_ni_syscall /* TUX */ - .long sys_security + .long sys_ni_syscall .long sys_gettid /* 225 */ .long sys_readahead .long sys_setxattr diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c --- a/arch/arm/kernel/ptrace.c Wed Nov 27 14:36:27 2002 +++ b/arch/arm/kernel/ptrace.c Wed Nov 27 14:36:27 2002 @@ -711,8 +711,7 @@ /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if (ret) + if ((ret = security_ptrace(current->parent, current))) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/arch/arm/kernel/via82c505.c b/arch/arm/kernel/via82c505.c --- a/arch/arm/kernel/via82c505.c Wed Nov 27 14:36:27 2002 +++ b/arch/arm/kernel/via82c505.c Wed Nov 27 14:36:27 2002 @@ -20,7 +20,7 @@ via82c505_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { - outl(CONFIG_CMD(dev,where),0xCF8); + outl(CONFIG_CMD(bus,devfn,where),0xCF8); switch (size) { case 1: *value=inb(0xCFC + (where&3)); @@ -36,7 +36,7 @@ } static int -via82c505_write_config(struct pci_bus *bus, unsigned int devfn, int where +via82c505_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { outl(CONFIG_CMD(bus,devfn,where),0xCF8); @@ -61,8 +61,6 @@ void __init via82c505_preinit(void *sysdata) { - struct pci_bus *bus; - printk(KERN_DEBUG "PCI: VIA 82c505\n"); if (!request_region(0xA8,2,"via config")) { printk(KERN_WARNING"VIA 82c505: Unable to request region 0xA8\n"); diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c --- a/arch/arm/mach-sa1100/cpu-sa1110.c Wed Nov 27 14:36:27 2002 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c Wed Nov 27 14:36:27 2002 @@ -305,7 +305,7 @@ .verify = sa11x0_verify_speed, .setpolicy = sa1110_setspeed, .policy = &sa1110_policy, - .cpu_min_freq[0] = 59000, + .cpu_min_freq = { 59000, }, }; static int __init sa1110_clk_init(void) diff -Nru a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h --- a/arch/arm/mach-sa1100/generic.h Wed Nov 27 14:36:31 2002 +++ b/arch/arm/mach-sa1100/generic.h Wed Nov 27 14:36:31 2002 @@ -21,5 +21,5 @@ struct cpufreq_policy; extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); -extern void sa11x0_verify_speed(struct cpufreq_policy *policy); +extern int sa11x0_verify_speed(struct cpufreq_policy *policy); extern unsigned int sa11x0_getspeed(void); diff -Nru a/arch/arm/mach-sa1100/sa1111-pcibuf.c b/arch/arm/mach-sa1100/sa1111-pcibuf.c --- a/arch/arm/mach-sa1100/sa1111-pcibuf.c Wed Nov 27 14:36:27 2002 +++ b/arch/arm/mach-sa1100/sa1111-pcibuf.c Wed Nov 27 14:36:27 2002 @@ -31,6 +31,14 @@ #define DPRINTK(...) do { } while (0) #endif +//#define STATS +#ifdef STATS +#define DO_STATS(X) do { X ; } while (0) +#else +#define DO_STATS(X) do { } while (0) +#endif + +/* ************************************************** */ struct safe_buffer { struct list_head node; @@ -50,10 +58,24 @@ #define SIZE_SMALL 1024 -#define SIZE_LARGE (16*1024) +#define SIZE_LARGE (4*1024) static struct pci_pool *small_buffer_pool, *large_buffer_pool; +#ifdef STATS +static unsigned long sbp_allocs __initdata = 0; +static unsigned long lbp_allocs __initdata = 0; +static unsigned long total_allocs __initdata= 0; + +static void print_alloc_stats(void) +{ + printk(KERN_INFO + "sa1111_pcibuf: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n", + sbp_allocs, lbp_allocs, + total_allocs - sbp_allocs - lbp_allocs, total_allocs); +} +#endif + static int __init create_safe_buffer_pools(void) { @@ -81,6 +103,10 @@ return -1; } + printk(KERN_INFO + "sa1111_pcibuf: buffer sizes: small=%u, large=%u\n", + SIZE_SMALL, SIZE_LARGE); + return 0; } @@ -108,6 +134,8 @@ DPRINTK("%s(ptr=%p, size=%d, direction=%d)\n", __func__, ptr, size, direction); + DO_STATS ( total_allocs++ ); + buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC); if (buf == 0) { printk(KERN_WARNING "%s: kmalloc failed\n", __func__); @@ -117,12 +145,14 @@ if (size <= SIZE_SMALL) { pool = small_buffer_pool; safe = pci_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); + + DO_STATS ( sbp_allocs++ ); } else if (size <= SIZE_LARGE) { pool = large_buffer_pool; safe = pci_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); + + DO_STATS ( lbp_allocs++ ); } else { - printk(KERN_DEBUG - "sa111_pcibuf: resorting to pci_alloc_consistent\n"); pool = 0; safe = pci_alloc_consistent(SA1111_FAKE_PCIDEV, size, &safe_dma_addr); @@ -136,6 +166,11 @@ return 0; } +#ifdef STATS + if (total_allocs % 1000 == 0) + print_alloc_stats(); +#endif + BUG_ON(sa1111_check_dma_bug(safe_dma_addr)); // paranoia buf->ptr = ptr; @@ -204,37 +239,39 @@ return ((physaddr + size - 1) < (1<<20)); } -/* - * see if a buffer address is in an 'unsafe' range. if it is - * allocate a 'safe' buffer and copy the unsafe buffer into it. - * substitute the safe buffer for the unsafe one. - * (basically move the buffer from an unsafe area to a safe one) - */ -dma_addr_t -sa1111_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction) -{ - unsigned long flags; - dma_addr_t dma_addr; +/* ************************************************** */ - DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n", - __func__, hwdev, ptr, size, direction); +#ifdef STATS +static unsigned long map_op_count __initdata = 0; +static unsigned long bounce_count __initdata = 0; - BUG_ON(hwdev != SA1111_FAKE_PCIDEV); - BUG_ON(direction == PCI_DMA_NONE); +static void print_map_stats(void) +{ + printk(KERN_INFO + "sa1111_pcibuf: map_op_count=%lu, bounce_count=%lu\n", + map_op_count, bounce_count); +} +#endif - local_irq_save(flags); +static dma_addr_t +map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction) +{ + dma_addr_t dma_addr; + + DO_STATS ( map_op_count++ ); dma_addr = virt_to_bus(ptr); if (!dma_range_is_safe(dma_addr, size)) { struct safe_buffer *buf; + DO_STATS ( bounce_count++ ) ; + buf = alloc_safe_buffer(hwdev, ptr, size, direction); if (buf == 0) { printk(KERN_ERR "%s: unable to map unsafe buffer %p!\n", __func__, ptr); - local_irq_restore(flags); return 0; } @@ -256,33 +293,22 @@ consistent_sync(ptr, size, direction); } - local_irq_restore(flags); +#ifdef STATS + if (map_op_count % 1000 == 0) + print_map_stats(); +#endif + return dma_addr; } -/* - * see if a mapped address was really a "safe" buffer and if so, copy - * the data from the safe buffer back to the unsafe buffer and free up - * the safe buffer. (basically return things back to the way they - * should be) - */ - -void -sa1111_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, - size_t size, int direction) +static void +unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) { - unsigned long flags; struct safe_buffer *buf; - DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n", - __func__, hwdev, (void *) dma_addr, size, direction); - - BUG_ON(hwdev != SA1111_FAKE_PCIDEV); - BUG_ON(direction == PCI_DMA_NONE); - - local_irq_save(flags); - buf = find_safe_buffer(dma_addr); + if (buf) { BUG_ON(buf->size != size); BUG_ON(buf->direction != direction); @@ -292,6 +318,9 @@ buf->ptr, (void *) virt_to_bus(buf->ptr), buf->safe, (void *) buf->safe_dma_addr); + + DO_STATS ( bounce_count++ ); + if ((direction == PCI_DMA_FROMDEVICE) || (direction == PCI_DMA_BIDIRECTIONAL)) { DPRINTK("%s: copy back from safe %p, to unsafe %p size %d\n", @@ -300,39 +329,16 @@ } free_safe_buffer(buf); } - - local_irq_restore(flags); -} - -int -sa1111_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, - int nents, int direction) -{ - BUG(); /* Not implemented. */ } -void -sa1111_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, - int direction) -{ - BUG(); /* Not implemented. */ -} - -void -sa1111_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_addr, +static void +sync_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction) { - unsigned long flags; struct safe_buffer *buf; - DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n", - __func__, hwdev, (void *) dma_addr, size, direction); - - BUG_ON(hwdev != SA1111_FAKE_PCIDEV); - - local_irq_save(flags); - buf = find_safe_buffer(dma_addr); + if (buf) { BUG_ON(buf->size != size); BUG_ON(buf->direction != direction); @@ -342,6 +348,8 @@ buf->ptr, (void *) virt_to_bus(buf->ptr), buf->safe, (void *) buf->safe_dma_addr); + DO_STATS ( bounce_count++ ); + switch (direction) { case PCI_DMA_FROMDEVICE: DPRINTK("%s: copy back from safe %p, to unsafe %p size %d\n", @@ -362,15 +370,159 @@ } else { consistent_sync(bus_to_virt(dma_addr), size, direction); } +} + +/* ************************************************** */ + +/* + * see if a buffer address is in an 'unsafe' range. if it is + * allocate a 'safe' buffer and copy the unsafe buffer into it. + * substitute the safe buffer for the unsafe one. + * (basically move the buffer from an unsafe area to a safe one) + */ +dma_addr_t +sa1111_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction) +{ + unsigned long flags; + dma_addr_t dma_addr; + + DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n", + __func__, hwdev, ptr, size, direction); + + BUG_ON(hwdev != SA1111_FAKE_PCIDEV); + BUG_ON(direction == PCI_DMA_NONE); + + local_irq_save(flags); + + dma_addr = map_single(hwdev, ptr, size, direction); + + local_irq_restore(flags); + + return dma_addr; +} + +/* + * see if a mapped address was really a "safe" buffer and if so, copy + * the data from the safe buffer back to the unsafe buffer and free up + * the safe buffer. (basically return things back to the way they + * should be) + */ + +void +sa1111_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ + unsigned long flags; + + DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n", + __func__, hwdev, (void *) dma_addr, size, direction); + + BUG_ON(hwdev != SA1111_FAKE_PCIDEV); + BUG_ON(direction == PCI_DMA_NONE); + + local_irq_save(flags); + + unmap_single(hwdev, dma_addr, size, direction); + + local_irq_restore(flags); +} + +int +sa1111_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction) +{ + unsigned long flags; + int i; + + DPRINTK("%s(hwdev=%p,sg=%p,nents=%d,dir=%x)\n", + __func__, hwdev, sg, nents, direction); + + BUG_ON(hwdev != SA1111_FAKE_PCIDEV); + BUG_ON(direction == PCI_DMA_NONE); + + local_irq_save(flags); + + for (i = 0; i < nents; i++, sg++) { + struct page *page = sg->page; + unsigned int offset = sg->offset; + unsigned int length = sg->length; + void *ptr = page_address(page) + offset; + + sg->dma_address = + map_single(hwdev, ptr, length, direction); + } + + local_irq_restore(flags); + + return nents; +} + +void +sa1111_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, + int direction) +{ + unsigned long flags; + int i; + + DPRINTK("%s(hwdev=%p,sg=%p,nents=%d,dir=%x)\n", + __func__, hwdev, sg, nents, direction); + + BUG_ON(hwdev != SA1111_FAKE_PCIDEV); + BUG_ON(direction == PCI_DMA_NONE); + + local_irq_save(flags); + + for (i = 0; i < nents; i++, sg++) { + dma_addr_t dma_addr = sg->dma_address; + unsigned int length = sg->length; + + unmap_single(hwdev, dma_addr, length, direction); + } + + local_irq_restore(flags); +} + +void +sa1111_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ + unsigned long flags; + + DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n", + __func__, hwdev, (void *) dma_addr, size, direction); + + BUG_ON(hwdev != SA1111_FAKE_PCIDEV); + + local_irq_save(flags); + + sync_single(hwdev, dma_addr, size, direction); local_irq_restore(flags); } void sa1111_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, - int nelems, int direction) + int nents, int direction) { - BUG(); /* Not implemented. */ + unsigned long flags; + int i; + + DPRINTK("%s(hwdev=%p,sg=%p,nents=%d,dir=%x)\n", + __func__, hwdev, sg, nents, direction); + + BUG_ON(hwdev != SA1111_FAKE_PCIDEV); + BUG_ON(direction == PCI_DMA_NONE); + + local_irq_save(flags); + + for (i = 0; i < nents; i++, sg++) { + dma_addr_t dma_addr = sg->dma_address; + unsigned int length = sg->length; + + sync_single(hwdev, dma_addr, length, direction); + } + + local_irq_restore(flags); } EXPORT_SYMBOL(sa1111_map_single); @@ -398,6 +550,11 @@ static void __exit sa1111_pcibuf_exit(void) { BUG_ON(!list_empty(&safe_buffers)); + +#ifdef STATS + print_alloc_stats(); + print_map_stats(); +#endif destroy_safe_buffer_pools(); } diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Wed Nov 27 14:36:28 2002 +++ b/arch/i386/Kconfig Wed Nov 27 14:36:28 2002 @@ -1612,6 +1612,20 @@ symbolic stack backtraces. This increases the size of the kernel somewhat, as all symbols have to be loaded into the kernel image. +config DEBUG_SPINLOCK_SLEEP + bool "Sleep-inside-spinlock checking" + help + If you say Y here, various routines which may sleep will become very + noisy if they are called with a spinlock held. + +config FRAME_POINTER + bool "Compile the kernel with frame pointers" + help + If you say Y here the resulting kernel image will be slightly larger + and slower, but it will give very useful debugging information. + If you don't debug the kernel, you can say N, but we may not be able + to solve problems without frame pointers. + config X86_EXTRA_IRQS bool depends on X86_LOCAL_APIC diff -Nru a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c --- a/arch/i386/kernel/cpu/cyrix.c Wed Nov 27 14:36:28 2002 +++ b/arch/i386/kernel/cpu/cyrix.c Wed Nov 27 14:36:28 2002 @@ -106,6 +106,89 @@ } } + +static void __init set_cx86_reorder(void) +{ +#ifdef CONFIG_OOSTORE + u8 ccr3; + + printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n"); + ccr3 = getCx86(CX86_CCR3); + setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */ + + /* Load/Store Serialize to mem access disable (=reorder it)  */ + setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80); +#ifdef CONFIG_NOHIGHMEM + /* set load/store serialize from 1GB to 4GB */ + ccr3 |= 0xe0; +#endif + setCx86(CX86_CCR3, ccr3); +#endif +} + +static void __init set_cx86_memwb(void) +{ + u32 cr0; + + printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n"); + + /* CCR2 bit 2: unlock NW bit */ + setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04); + /* set 'Not Write-through' */ + cr0 = 0x20000000; + __asm__("movl %%cr0,%%eax\n\t" + "orl %0,%%eax\n\t" + "movl %%eax,%%cr0\n" + : : "r" (cr0) + :"ax"); + /* CCR2 bit 2: lock NW bit and set WT1 */ + setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 ); +} + +static void __init set_cx86_inc(void) +{ + unsigned char ccr3; + + printk(KERN_INFO "Enable Incrementor on Cyrix/NSC processor.\n"); + + ccr3 = getCx86(CX86_CCR3); + setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */ + /* PCR1 -- Performance Control */ + /* Incrementor on, whatever that is */ + setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02); + /* PCR0 -- Performance Control */ + /* Incrementor Margin 10 */ + setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04); + setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ +} + +/* + * Configure later MediaGX and/or Geode processor. + */ + +static void __init geode_configure(void) +{ + unsigned long flags; + u8 ccr3, ccr4; + unsigned long cr0; + local_irq_save(flags); + + ccr3 = getCx86(CX86_CCR3); + setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* Enable */ + + ccr4 = getCx86(CX86_CCR4); + ccr4 |= 0x38; /* FPU fast, DTE cache, Mem bypass */ + + setCx86(CX86_CCR3, ccr3); + + set_cx86_memwb(); + set_cx86_reorder(); + set_cx86_inc(); + + local_irq_restore(flags); +} + + static void __init init_cyrix(struct cpuinfo_x86 *c) { unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0; @@ -201,7 +284,10 @@ if (c->cpuid_level == 2) { /* Enable cxMMX extensions (GX1 Datasheet 54) */ setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1); - + + /* GXlv/GXm/GX1 */ + if((dir1 >= 0x50 && dir1 <= 0x54) || dir1 >= 0x63) + geode_configure(); get_model_name(c); /* get CPU marketing name */ return; } diff -Nru a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c --- a/arch/i386/kernel/cpu/mcheck/non-fatal.c Wed Nov 27 14:36:28 2002 +++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c Wed Nov 27 14:36:28 2002 @@ -49,7 +49,6 @@ static void do_mce_timer(void *data) { - mce_checkregs (NULL); smp_call_function (mce_checkregs, NULL, 1, 1); } @@ -57,11 +56,10 @@ static void mce_timerfunc (unsigned long data) { + mce_checkregs (NULL); #ifdef CONFIG_SMP if (num_online_cpus() > 1) schedule_work (&mce_work); -#else - mce_checkregs (NULL); #endif mce_timer.expires = jiffies + MCE_RATE; add_timer (&mce_timer); diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Wed Nov 27 14:36:28 2002 +++ b/arch/i386/kernel/entry.S Wed Nov 27 14:36:28 2002 @@ -707,7 +707,7 @@ .long sys_getdents64 /* 220 */ .long sys_fcntl64 .long sys_ni_syscall /* reserved for TUX */ - .long sys_security /* reserved for Security */ + .long sys_ni_syscall .long sys_gettid .long sys_readahead /* 225 */ .long sys_setxattr diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Wed Nov 27 14:36:28 2002 +++ b/arch/i386/kernel/io_apic.c Wed Nov 27 14:36:28 2002 @@ -44,6 +44,12 @@ static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; /* + * Is the SiS APIC rmw bug present ? + * -1 = dont know, 0 = no, 1 = yes + */ +int sis_apic_bug = -1; + +/* * # of IRQ routing registers */ int nr_ioapic_registers[MAX_IO_APICS]; @@ -122,7 +128,7 @@ break; \ reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \ reg ACTION; \ - io_apic_modify(entry->apic, reg); \ + io_apic_modify(entry->apic, 0x10 + R + pin*2, reg); \ if (!entry->next) \ break; \ entry = irq_2_pin + entry->next; \ @@ -1738,6 +1744,18 @@ print_IO_APIC(); } +/* + * Called after all the initialization is done. If we didnt find any + * APIC bugs then we can allow the modify fast path + */ + +static void __init io_apic_bug_finalize(void) +{ + if(sis_apic_bug == -1) + sis_apic_bug = 0; +} + +late_initcall(io_apic_bug_finalize); /* -------------------------------------------------------------------------- ACPI-based IOAPIC Configuration diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c --- a/arch/i386/kernel/ptrace.c Wed Nov 27 14:36:28 2002 +++ b/arch/i386/kernel/ptrace.c Wed Nov 27 14:36:28 2002 @@ -160,8 +160,7 @@ /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if (ret) + if ((ret = security_ptrace(current->parent, current))) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c --- a/arch/i386/kernel/semaphore.c Wed Nov 27 14:36:29 2002 +++ b/arch/i386/kernel/semaphore.c Wed Nov 27 14:36:29 2002 @@ -191,6 +191,10 @@ ".align 4\n" ".globl __down_failed\n" "__down_failed:\n\t" +#if defined(CONFIG_FRAME_POINTER) + "pushl %ebp\n\t" + "movl %esp,%ebp\n\t" +#endif "pushl %eax\n\t" "pushl %edx\n\t" "pushl %ecx\n\t" @@ -198,6 +202,10 @@ "popl %ecx\n\t" "popl %edx\n\t" "popl %eax\n\t" +#if defined(CONFIG_FRAME_POINTER) + "movl %ebp,%esp\n\t" + "popl %ebp\n\t" +#endif "ret" ); @@ -206,11 +214,19 @@ ".align 4\n" ".globl __down_failed_interruptible\n" "__down_failed_interruptible:\n\t" +#if defined(CONFIG_FRAME_POINTER) + "pushl %ebp\n\t" + "movl %esp,%ebp\n\t" +#endif "pushl %edx\n\t" "pushl %ecx\n\t" "call __down_interruptible\n\t" "popl %ecx\n\t" "popl %edx\n\t" +#if defined(CONFIG_FRAME_POINTER) + "movl %ebp,%esp\n\t" + "popl %ebp\n\t" +#endif "ret" ); @@ -219,11 +235,19 @@ ".align 4\n" ".globl __down_failed_trylock\n" "__down_failed_trylock:\n\t" +#if defined(CONFIG_FRAME_POINTER) + "pushl %ebp\n\t" + "movl %esp,%ebp\n\t" +#endif "pushl %edx\n\t" "pushl %ecx\n\t" "call __down_trylock\n\t" "popl %ecx\n\t" "popl %edx\n\t" +#if defined(CONFIG_FRAME_POINTER) + "movl %ebp,%esp\n\t" + "popl %ebp\n\t" +#endif "ret" ); diff -Nru a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c --- a/arch/i386/pci/direct.c Wed Nov 27 14:36:28 2002 +++ b/arch/i386/pci/direct.c Wed Nov 27 14:36:28 2002 @@ -261,7 +261,6 @@ } local_irq_restore(flags); - pci_root_ops = NULL; return 0; } diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S Wed Nov 27 14:36:28 2002 +++ b/arch/ia64/kernel/entry.S Wed Nov 27 14:36:28 2002 @@ -1241,7 +1241,7 @@ data8 sys_futex // 1230 data8 sys_sched_setaffinity data8 sys_sched_getaffinity - data8 sys_security + data8 sys_ni_syscall data8 sys_alloc_hugepages data8 sys_free_hugepages // 1235 data8 sys_exit_group diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c --- a/arch/ia64/kernel/ptrace.c Wed Nov 27 14:36:32 2002 +++ b/arch/ia64/kernel/ptrace.c Wed Nov 27 14:36:32 2002 @@ -1101,8 +1101,7 @@ /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if (ret) + if ((ret = security_ptrace(current->parent, current))) goto out; current->ptrace |= PT_PTRACED; ret = 0; diff -Nru a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c --- a/arch/m68k/lib/checksum.c Wed Nov 27 14:36:32 2002 +++ b/arch/m68k/lib/checksum.c Wed Nov 27 14:36:32 2002 @@ -243,7 +243,7 @@ "8:\n" ".section .fixup,\"ax\"\n" ".even\n" - /* If any execption occurs zero out the rest. + /* If any exception occurs zero out the rest. Similarities with the code above are intentional :-) */ "90:\t" "clrw %3@+\n\t" diff -Nru a/arch/mips64/Kconfig b/arch/mips64/Kconfig --- a/arch/mips64/Kconfig Wed Nov 27 14:36:28 2002 +++ b/arch/mips64/Kconfig Wed Nov 27 14:36:28 2002 @@ -693,7 +693,7 @@ architecture than the one it is intended to run on. config MIPS_FPE_MODULE - bool "Build fp execption handler module" + bool "Build fp exception handler module" depends on MODULES help Build the floating point exception handler module. This option is diff -Nru a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S --- a/arch/ppc/kernel/entry.S Wed Nov 27 14:36:31 2002 +++ b/arch/ppc/kernel/entry.S Wed Nov 27 14:36:31 2002 @@ -182,9 +182,7 @@ .globl ret_from_fork ret_from_fork: REST_NVGPRS(r1) -#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) bl schedule_tail -#endif li r3,0 b ret_from_syscall diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S Wed Nov 27 14:36:31 2002 +++ b/arch/ppc/kernel/misc.S Wed Nov 27 14:36:31 2002 @@ -1006,6 +1006,7 @@ mr r31,r4 /* argument */ ori r3,r5,CLONE_VM /* flags */ oris r3,r3,CLONE_UNTRACED>>16 + li r4,0 /* new sp (unused) */ li r0,__NR_clone sc cmpi 0,r3,0 /* parent or child? */ @@ -1279,7 +1280,7 @@ .long sys_futex .long sys_sched_setaffinity .long sys_sched_getaffinity - .long sys_security + .long sys_ni_syscall .long sys_ni_syscall /* 225 - reserved for Tux */ .long sys_sendfile64 .long sys_io_setup diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Wed Nov 27 14:36:30 2002 +++ b/arch/ppc/kernel/process.c Wed Nov 27 14:36:30 2002 @@ -332,7 +332,7 @@ unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; unsigned long childframe; - p->user_tid = NULL; + p->set_child_tid = p->clear_child_tid = NULL; CHECK_FULL_REGS(regs); /* Copy registers */ @@ -344,8 +344,10 @@ childregs->gpr[1] = sp + sizeof(struct pt_regs); childregs->gpr[2] = (unsigned long) p; p->thread.regs = NULL; /* no user register state */ - } else + } else { + childregs->gpr[1] = usp; p->thread.regs = childregs; + } childregs->gpr[3] = 0; /* Result from fork() */ sp -= STACK_FRAME_OVERHEAD; childframe = sp; @@ -449,9 +451,9 @@ struct task_struct *p; CHECK_FULL_REGS(regs); - if ((p1 & (CLONE_SETTID | CLONE_CLEARTID)) == 0) - p3 = 0; - p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3); + if (p2 == 0) + p2 = regs->gpr[1]; /* stack pointer for child */ + p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3, (int *)p4); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -460,7 +462,7 @@ { struct task_struct *p; CHECK_FULL_REGS(regs); - p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL); + p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -469,7 +471,8 @@ { struct task_struct *p; CHECK_FULL_REGS(regs); - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, NULL); + p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, + 0, NULL, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff -Nru a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c --- a/arch/ppc/kernel/ptrace.c Wed Nov 27 14:36:28 2002 +++ b/arch/ppc/kernel/ptrace.c Wed Nov 27 14:36:28 2002 @@ -166,8 +166,7 @@ /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if (ret) + if ((ret = security_ptrace(current->parent, current))) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Wed Nov 27 14:36:31 2002 +++ b/arch/ppc64/kernel/misc.S Wed Nov 27 14:36:31 2002 @@ -730,7 +730,7 @@ .llong .sys_futex .llong .sys32_sched_setaffinity .llong .sys32_sched_getaffinity - .llong .sys_security + .llong .sys_ni_syscall .llong .sys_ni_syscall /* 225 - reserved for tux */ .llong .sys32_sendfile64 .llong .sys_ni_syscall /* reserved for sys_io_setup */ @@ -973,7 +973,7 @@ .llong .sys_futex .llong .sys_sched_setaffinity .llong .sys_sched_getaffinity - .llong .sys_security + .llong .sys_ni_syscall .llong .sys_ni_syscall /* 225 - reserved for tux */ .llong .sys_ni_syscall /* 32bit only sendfile64 */ .llong .sys_io_setup diff -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c --- a/arch/ppc64/kernel/ptrace.c Wed Nov 27 14:36:28 2002 +++ b/arch/ppc64/kernel/ptrace.c Wed Nov 27 14:36:28 2002 @@ -59,8 +59,7 @@ /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if (ret) + if ((ret = security_ptrace(current->parent, current))) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c --- a/arch/ppc64/kernel/ptrace32.c Wed Nov 27 14:36:30 2002 +++ b/arch/ppc64/kernel/ptrace32.c Wed Nov 27 14:36:30 2002 @@ -48,8 +48,7 @@ /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if (ret) + if ((ret = security_ptrace(current->parent, current))) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Wed Nov 27 14:36:31 2002 +++ b/arch/ppc64/kernel/sys_ppc32.c Wed Nov 27 14:36:31 2002 @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -3520,8 +3521,7 @@ if ((retval = bprm.envc) < 0) goto out_mm; - retval = security_ops->bprm_alloc_security(&bprm); - if (retval) + if ((retval = security_bprm_alloc(&bprm))) goto out; retval = prepare_binprm(&bprm); @@ -3544,7 +3544,7 @@ retval = search_binary_handler(&bprm,regs); if (retval >= 0) { /* execve success */ - security_ops->bprm_free_security(&bprm); + security_bprm_free(&bprm); return retval; } @@ -3557,7 +3557,7 @@ } if (bprm.security) - security_ops->bprm_free_security(&bprm); + security_bprm_free(&bprm); out_mm: mmdrop(bprm.mm); diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S --- a/arch/s390/kernel/entry.S Wed Nov 27 14:36:28 2002 +++ b/arch/s390/kernel/entry.S Wed Nov 27 14:36:28 2002 @@ -588,7 +588,7 @@ .long sys_futex .long sys_sched_setaffinity .long sys_sched_getaffinity /* 240 */ - .long sys_security + .long sys_ni_syscall .long sys_ni_syscall /* reserved for TUX */ .long sys_io_setup .long sys_io_destroy diff -Nru a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c --- a/arch/s390/kernel/ptrace.c Wed Nov 27 14:36:31 2002 +++ b/arch/s390/kernel/ptrace.c Wed Nov 27 14:36:31 2002 @@ -323,8 +323,7 @@ ret = -EPERM; if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if (ret) + if ((ret = security_ptrace(current->parent, current))) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S --- a/arch/s390x/kernel/entry.S Wed Nov 27 14:36:28 2002 +++ b/arch/s390x/kernel/entry.S Wed Nov 27 14:36:28 2002 @@ -617,7 +617,7 @@ .long SYSCALL(sys_futex,sys32_futex_wrapper) .long SYSCALL(sys_sched_setaffinity,sys32_sched_setaffinity_wrapper) .long SYSCALL(sys_sched_getaffinity,sys32_sched_getaffinity_wrapper) /* 240 */ - .long SYSCALL(sys_security,sys_ni_syscall) + .long SYSCALL(sys_ni_syscall,sys_ni_syscall) .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* reserved for TUX */ .long SYSCALL(sys_io_setup,sys_ni_syscall) .long SYSCALL(sys_io_destroy,sys_ni_syscall) diff -Nru a/arch/s390x/kernel/ptrace.c b/arch/s390x/kernel/ptrace.c --- a/arch/s390x/kernel/ptrace.c Wed Nov 27 14:36:27 2002 +++ b/arch/s390x/kernel/ptrace.c Wed Nov 27 14:36:27 2002 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -562,8 +563,7 @@ ret = -EPERM; if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if (ret) + if ((ret = security_ptrace(current->parent, current))) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/arch/sh/kernel/hd64465_gpio.c b/arch/sh/kernel/hd64465_gpio.c --- a/arch/sh/kernel/hd64465_gpio.c Wed Nov 27 14:36:31 2002 +++ b/arch/sh/kernel/hd64465_gpio.c Wed Nov 27 14:36:31 2002 @@ -165,12 +165,19 @@ static int __init hd64465_gpio_init(void) { - /* TODO: check return values */ - request_region(HD64465_REG_GPACR, 0x1000, MODNAME); - request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt, - SA_INTERRUPT, MODNAME, 0); + int err; + + if (!request_region(HD64465_REG_GPACR, 0x1000, MODNAME)) + return -EIO; + err = request_irq (HD64465_IRQ_GPIO, hd64465_gpio_interrupt, + SA_INTERRUPT, MODNAME, 0); + if (err) { + printk(KERN_ERR"HD64465: Unable to get irq %d.\n", HD64465_IRQ_GPIO); + release_region(HD64465_REG_GPACR, 0x1000); + return err; + } - printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO); + printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO); return 0; } diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig --- a/arch/sparc/Kconfig Wed Nov 27 14:36:27 2002 +++ b/arch/sparc/Kconfig Wed Nov 27 14:36:27 2002 @@ -1424,6 +1424,12 @@ config DEBUG_SPINLOCK bool "Spinlock debugging" +config DEBUG_SPINLOCK_SLEEP + bool "Sleep-inside-spinlock checking" + help + If you say Y here, various routines which may sleep will become very + noisy if they are called with a spinlock held. + endmenu source "security/Kconfig" diff -Nru a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c --- a/arch/sparc/kernel/ptrace.c Wed Nov 27 14:36:32 2002 +++ b/arch/sparc/kernel/ptrace.c Wed Nov 27 14:36:32 2002 @@ -291,8 +291,7 @@ pt_error_return(regs, EPERM); goto out; } - ret = security_ops->ptrace(current->parent, current); - if (ret) { + if ((ret = security_ptrace(current->parent, current))) { pt_error_return(regs, -ret); goto out; } diff -Nru a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c --- a/arch/sparc/kernel/signal.c Wed Nov 27 14:36:31 2002 +++ b/arch/sparc/kernel/signal.c Wed Nov 27 14:36:31 2002 @@ -1135,7 +1135,7 @@ if (current->pid == 1) continue; switch (signr) { - case SIGCONT: case SIGCHLD: case SIGWINCH: + case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S --- a/arch/sparc/kernel/systbls.S Wed Nov 27 14:36:30 2002 +++ b/arch/sparc/kernel/systbls.S Wed Nov 27 14:36:30 2002 @@ -49,7 +49,7 @@ /*140*/ .long sys_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys_getrlimit /*145*/ .long sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 -/*155*/ .long sys_fcntl64, sys_security, sys_statfs, sys_fstatfs, sys_oldumount +/*155*/ .long sys_fcntl64, sys_ni_syscall, sys_statfs, sys_fstatfs, sys_oldumount /*160*/ .long sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall /*165*/ .long sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr /*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Wed Nov 27 14:36:31 2002 +++ b/arch/sparc64/Kconfig Wed Nov 27 14:36:31 2002 @@ -1681,6 +1681,12 @@ best used in conjunction with the NMI watchdog so that spinlock deadlocks are also debuggable. +config DEBUG_SPINLOCK_SLEEP + bool "Sleep-inside-spinlock checking" + help + If you say Y here, various routines which may sleep will become very + noisy if they are called with a spinlock held. + config DEBUG_BUGVERBOSE bool "Verbose BUG() reporting (adds 70K)" depends on DEBUG_KERNEL diff -Nru a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c --- a/arch/sparc64/kernel/binfmt_elf32.c Wed Nov 27 14:36:31 2002 +++ b/arch/sparc64/kernel/binfmt_elf32.c Wed Nov 27 14:36:31 2002 @@ -32,12 +32,10 @@ for(i = 0; i < 16; i++) \ dest[i] = (unsigned int) src->u_regs[i];\ /* Don't try this at home kids... */ \ - set_fs(USER_DS); \ sp = (unsigned int *) (src->u_regs[14] & \ 0x00000000fffffffc); \ for(i = 0; i < 16; i++) \ __get_user(dest[i+16], &sp[i]); \ - set_fs(KERNEL_DS); \ dest[32] = tstate_to_psr(src->tstate); \ dest[33] = (unsigned int) src->tpc; \ dest[34] = (unsigned int) src->tnpc; \ diff -Nru a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c --- a/arch/sparc64/kernel/ptrace.c Wed Nov 27 14:36:32 2002 +++ b/arch/sparc64/kernel/ptrace.c Wed Nov 27 14:36:32 2002 @@ -140,8 +140,7 @@ pt_error_return(regs, EPERM); goto out; } - ret = security_ops->ptrace(current->parent, current); - if (ret) { + if ((ret = security_ptrace(current->parent, current))) { pt_error_return(regs, -ret); goto out; } diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c --- a/arch/sparc64/kernel/signal.c Wed Nov 27 14:36:30 2002 +++ b/arch/sparc64/kernel/signal.c Wed Nov 27 14:36:30 2002 @@ -682,7 +682,7 @@ if (current->pid == 1) continue; switch (signr) { - case SIGCONT: case SIGCHLD: case SIGWINCH: + case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: diff -Nru a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c --- a/arch/sparc64/kernel/signal32.c Wed Nov 27 14:36:27 2002 +++ b/arch/sparc64/kernel/signal32.c Wed Nov 27 14:36:27 2002 @@ -1353,7 +1353,7 @@ if (current->pid == 1) continue; switch (signr) { - case SIGCONT: case SIGCHLD: case SIGWINCH: + case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c Wed Nov 27 14:36:31 2002 +++ b/arch/sparc64/kernel/sys_sparc32.c Wed Nov 27 14:36:31 2002 @@ -3026,8 +3026,7 @@ if ((retval = bprm.envc) < 0) goto out_mm; - retval = security_ops->bprm_alloc_security(&bprm); - if (retval) + if ((retval = security_bprm_alloc(&bprm))) goto out; retval = prepare_binprm(&bprm); @@ -3050,7 +3049,7 @@ retval = search_binary_handler(&bprm, regs); if (retval >= 0) { /* execve success */ - security_ops->bprm_free_security(&bprm); + security_bprm_free(&bprm); return retval; } @@ -3063,7 +3062,7 @@ } if (bprm.security) - security_ops->bprm_free_security(&bprm); + security_bprm_free(&bprm); out_mm: mmdrop(bprm.mm); diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S --- a/arch/sparc64/kernel/systbls.S Wed Nov 27 14:36:30 2002 +++ b/arch/sparc64/kernel/systbls.S Wed Nov 27 14:36:30 2002 @@ -50,7 +50,7 @@ /*140*/ .word sys32_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys32_getrlimit .word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 - .word sys32_fcntl64, sys_security, sys32_statfs, sys32_fstatfs, sys_oldumount + .word sys32_fcntl64, sys_ni_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount /*160*/ .word sys32_sched_setaffinity, sys32_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall .word sys_quotactl, sys_set_tid_address, sys32_mount, sys_ustat, sys_setxattr /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents @@ -109,7 +109,7 @@ /*140*/ .word sys_sendfile64, sys_getpeername, sys_futex, sys_gettid, sys_getrlimit .word sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 - .word sys_nis_syscall, sys_security, sys_statfs, sys_fstatfs, sys_oldumount + .word sys_nis_syscall, sys_ni_syscall, sys_statfs, sys_fstatfs, sys_oldumount /*160*/ .word sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_utrap_install .word sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents diff -Nru a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c --- a/arch/um/kernel/ptrace.c Wed Nov 27 14:36:28 2002 +++ b/arch/um/kernel/ptrace.c Wed Nov 27 14:36:28 2002 @@ -33,8 +33,7 @@ if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if(ret) + if ((ret = security_ptrace(current->parent, current))) goto out; /* set the ptrace bit in the process flags. */ diff -Nru a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c --- a/arch/um/kernel/sys_call_table.c Wed Nov 27 14:36:31 2002 +++ b/arch/um/kernel/sys_call_table.c Wed Nov 27 14:36:31 2002 @@ -217,7 +217,6 @@ extern syscall_handler_t sys_madvise; extern syscall_handler_t sys_fcntl64; extern syscall_handler_t sys_getdents64; -extern syscall_handler_t sys_security; extern syscall_handler_t sys_gettid; extern syscall_handler_t sys_readahead; extern syscall_handler_t sys_tkill; @@ -458,7 +457,6 @@ [ __NR_fstat64 ] = sys_fstat64, [ __NR_fcntl64 ] = sys_fcntl64, [ __NR_getdents64 ] = sys_getdents64, - [ __NR_security ] = sys_security, [ __NR_gettid ] = sys_gettid, [ __NR_readahead ] = sys_readahead, [ __NR_setxattr ] = sys_ni_syscall, diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig --- a/arch/v850/Kconfig Wed Nov 27 14:36:30 2002 +++ b/arch/v850/Kconfig Wed Nov 27 14:36:30 2002 @@ -63,6 +63,8 @@ bool "NA85E2C-FPGA" config V850E2_ANNA bool "Anna" + config V850E_AS85EP1 + bool "AS85EP1" endchoice diff -Nru a/arch/v850/Makefile b/arch/v850/Makefile --- a/arch/v850/Makefile Wed Nov 27 14:36:32 2002 +++ b/arch/v850/Makefile Wed Nov 27 14:36:32 2002 @@ -22,6 +22,9 @@ CFLAGS += -fno-builtin CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\" +LDFLAGS_BLOB := -b binary --oformat elf32-little +OBJCOPY_FLAGS_BLOB := -I binary -O elf32-little -B v850e + HEAD := $(arch_dir)/kernel/head.o $(arch_dir)/kernel/init_task.o core-y += $(arch_dir)/kernel/ @@ -40,10 +43,8 @@ # This results in it being built anew each time, but that's alright. root_fs_image.o: root_fs_image_force -# Note that we use the build-system's objcopy, as the v850 tools are fairly -# old, and don't have the --rename-section option. root_fs_image_force: $(ROOT_FS_IMAGE) - objcopy -I binary -O elf32-little -B i386 --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o + $(OBJCOPY) $(OBJCOPY_FLAGS_BLOB) --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o endif diff -Nru a/arch/v850/anna-rom.ld b/arch/v850/anna-rom.ld --- a/arch/v850/anna-rom.ld Wed Nov 27 14:36:28 2002 +++ b/arch/v850/anna-rom.ld Wed Nov 27 14:36:28 2002 @@ -80,6 +80,11 @@ __root_fs_image_start = . ; *(.root) __root_fs_image_end = . ; + + . = ALIGN (4) ; + ___initramfs_start = . ; + *(.init.ramfs) + ___initramfs_end = . ; } > ROM __rom_copy_src_start = . ; diff -Nru a/arch/v850/anna.ld b/arch/v850/anna.ld --- a/arch/v850/anna.ld Wed Nov 27 14:36:29 2002 +++ b/arch/v850/anna.ld Wed Nov 27 14:36:29 2002 @@ -103,6 +103,12 @@ *(.initcall7.init) . = ALIGN (4) ; ___initcall_end = . ; + + . = ALIGN (4) ; + ___initramfs_start = . ; + *(.init.ramfs) + ___initramfs_end = . ; + __init_end = . ; __kram_end = . ; diff -Nru a/arch/v850/as85ep1.ld b/arch/v850/as85ep1.ld --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/as85ep1.ld Wed Nov 27 14:36:32 2002 @@ -0,0 +1,147 @@ +/* Linker script for the NEC AS85EP1 V850E evaluation board + (CONFIG_V850E_AS85EP1). */ + +/* Note, all symbols are prefixed with an extra `_' for compatibility with + the existing linux sources. */ + +_jiffies = _jiffies_64 ; + +MEMORY { + /* 1MB of internal memory ($BFbB"L?Na(BRAM). */ + iMEM0 : ORIGIN = 0, LENGTH = 0x00100000 + + /* 1MB of static RAM. */ + SRAM : ORIGIN = 0x00400000, LENGTH = 0x00100000 + + /* About 58MB of DRAM. This can actually be at one of two positions, + determined by jump JP3; we have to use the first position because the + second is partially out of processor instruction addressing range + (though in the second position there's actually 64MB available). */ + SDRAM : ORIGIN = 0x00600000, LENGTH = 0x039F8000 +} + +SECTIONS { + .resetv : { + __intv_start = . ; + *(.intv.reset) /* Reset vector */ + } > iMEM0 + + .text : { + __kram_start = . ; + + __stext = . ; + *(.text) + *(.exit.text) /* 2.5 convention */ + *(.text.exit) /* 2.4 convention */ + *(.text.lock) + *(.exitcall.exit) + __real_etext = . ; /* There may be data after here. */ + *(.rodata) + + . = ALIGN (0x4) ; + *(.kstrtab) + + . = ALIGN (4) ; + *(.call_table_data) + *(.call_table_text) + + . = ALIGN (16) ; /* Exception table. */ + ___start___ex_table = . ; + *(__ex_table) + ___stop___ex_table = . ; + + ___start___ksymtab = . ;/* Kernel symbol table. */ + *(__ksymtab) + ___stop___ksymtab = . ; + . = ALIGN (4) ; + __etext = . ; + } > SRAM + + .data ALIGN (0x4) : { + __sdata = . ; + ___data_start = . ; + *(.data) + *(.exit.data) /* 2.5 convention */ + *(.data.exit) /* 2.4 convention */ + . = ALIGN (16) ; + *(.data.cacheline_aligned) + . = ALIGN (0x2000) ; + *(.data.init_task) + . = ALIGN (0x2000) ; + __edata = . ; + } > SRAM + + .bss ALIGN (0x4) : { + __sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN (4) ; + __init_stack_end = . ; + __ebss = . ; + } > SRAM + + .init ALIGN (4096) : { + __init_start = . ; + *(.init.text) /* 2.5 convention */ + *(.init.data) + *(.text.init) /* 2.4 convention */ + *(.data.init) + . = ALIGN (16) ; + ___setup_start = . ; + *(.init.setup) /* 2.5 convention */ + *(.setup.init) /* 2.4 convention */ + ___setup_end = . ; + ___initcall_start = . ; + *(.initcall.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + . = ALIGN (4) ; + ___initcall_end = . ; + + . = ALIGN (4) ; + ___initramfs_start = . ; + *(.init.ramfs) + ___initramfs_end = . ; + + /* We stick most of the interrupt vectors here; they'll be + copied into the proper location by the early init code (we + can't put them directly in the right place because of + hardware bugs). The vectors shouldn't need to be + relocated, so we don't have to use `> ... AT> ...' to + split the load/vm addresses (and we can't because of + problems with the loader). */ + . = ALIGN (0x10) ; + __intv_copy_src_start = . ; + *(.intv.common) /* Vectors common to all v850e proc. */ + *(.intv.mach) /* Machine-specific int. vectors. */ + . = ALIGN (0x10) ; + __intv_copy_src_end = . ; + + /* This is here so that when we free init memory, the initial + load-area of the interrupt vectors is freed too. */ + __init_end = . ; + __kram_end = . ; + + __bootmap = . ; + . = . + 4096 ; /* enough for 128MB. */ + } > SRAM + + /* Where we end up putting the vectors. */ + __intv_copy_dst_start = 0x10 ; + __intv_copy_dst_end = __intv_copy_dst_start + (__intv_copy_src_end - __intv_copy_src_start) ; + + __intv_end = __intv_copy_dst_end ; + + /* Device contents for the root filesystem. */ + .root : { + . = ALIGN (4096) ; + __root_fs_image_start = . ; + *(.root) + __root_fs_image_end = . ; + } > SDRAM +} diff -Nru a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile --- a/arch/v850/kernel/Makefile Wed Nov 27 14:36:32 2002 +++ b/arch/v850/kernel/Makefile Wed Nov 27 14:36:32 2002 @@ -15,11 +15,12 @@ signal.o irq.o mach.o ptrace.o bug.o export-objs += v850_ksyms.o rte_mb_a_pci.o -obj-$(CONFIG_MODULES) += v850_ksyms.o +obj-$(CONFIG_MODULES) += module.o v850_ksyms.o # chip-specific code obj-$(CONFIG_V850E_MA1) += ma.o nb85e_utils.o nb85e_timer_d.o obj-$(CONFIG_V850E_NB85E) += nb85e_intc.o obj-$(CONFIG_V850E2_ANNA) += anna.o nb85e_intc.o nb85e_utils.o nb85e_timer_d.o +obj-$(CONFIG_V850E_AS85EP1) += as85ep1.o nb85e_intc.o nb85e_utils.o nb85e_timer_d.o # platform-specific code obj-$(CONFIG_V850E_SIM) += sim.o simcons.o obj-$(CONFIG_V850E2_SIM85E2C) += sim85e2c.o nb85e_intc.o memcons.o diff -Nru a/arch/v850/kernel/anna.c b/arch/v850/kernel/anna.c --- a/arch/v850/kernel/anna.c Wed Nov 27 14:36:30 2002 +++ b/arch/v850/kernel/anna.c Wed Nov 27 14:36:30 2002 @@ -27,11 +27,14 @@ #include "mach.h" -/* SRAM and SDRAM are vaguely contiguous (with a hole in between; see - mach_reserve_bootmem for details), so just use both as one big area. */ +/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see + mach_reserve_bootmem for details); use both as one big area. */ #define RAM_START SRAM_ADDR #define RAM_END (SDRAM_ADDR + SDRAM_SIZE) +/* The bits of this port are connected to an 8-LED bar-graph. */ +#define LEDS_PORT 0 + static void anna_led_tick (void); @@ -44,7 +47,7 @@ ANNA_BPC = 0; ANNA_BSC = 0xAAAA; ANNA_BEC = 0; - ANNA_BHC = 0x00FF; /* icache all memory, dcache none */ + ANNA_BHC = 0xFFFF; /* icache all memory, dcache all */ ANNA_BCT(0) = 0xB088; ANNA_BCT(1) = 0x0008; ANNA_DWC(0) = 0x0027; @@ -60,17 +63,11 @@ void __init mach_setup (char **cmdline) { - printk (KERN_INFO - "CPU: %s\n" - "Platform: %s\n", - CPU_MODEL_LONG, - PLATFORM_LONG); - #ifdef CONFIG_V850E_NB85E_UART_CONSOLE nb85e_uart_cons_init (1); #endif - ANNA_PORT_PM (0) = 0; /* Make all LED pins output pins. */ + ANNA_PORT_PM (LEDS_PORT) = 0; /* Make all LED pins output pins. */ mach_tick = anna_led_tick; } @@ -138,7 +135,7 @@ disable_reset_guard (); #endif local_irq_disable (); /* Ignore all interrupts. */ - ANNA_PORT_IO(0) = 0xAA; /* Note that we halted. */ + ANNA_PORT_IO(LEDS_PORT) = 0xAA; /* Note that we halted. */ for (;;) asm ("halt; nop; nop; nop; nop; nop"); } @@ -191,9 +188,9 @@ if (pos + dir <= max_pos) { /* Each bit of port 0 has a LED. */ - clear_bit (pos, &ANNA_PORT_IO(0)); + clear_bit (pos, &ANNA_PORT_IO(LEDS_PORT)); pos += dir; - set_bit (pos, &ANNA_PORT_IO(0)); + set_bit (pos, &ANNA_PORT_IO(LEDS_PORT)); } } diff -Nru a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/as85ep1.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,241 @@ +/* + * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mach.h" + + +/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see + mach_reserve_bootmem for details); use both as one big area. */ +#define RAM_START SRAM_ADDR +#define RAM_END (SDRAM_ADDR + SDRAM_SIZE) + +/* The bits of this port are connected to an 8-LED bar-graph. */ +#define LEDS_PORT 4 + + +static void as85ep1_led_tick (void); + +extern char _intv_copy_src_start, _intv_copy_src_end; +extern char _intv_copy_dst_start; + + +void __init mach_early_init (void) +{ + const u32 *src; + register u32 *dst asm ("ep"); + + AS85EP1_CSC(0) = 0x0403; + AS85EP1_BCT(0) = 0xB8B8; + AS85EP1_DWC(0) = 0x0104; + AS85EP1_BCC = 0x0012; + AS85EP1_ASC = 0; + AS85EP1_LBS = 0x00A9; + AS85EP1_RFS(1) = 0x8205; + AS85EP1_RFS(3) = 0x8205; + AS85EP1_SCR(1) = 0x20A9; + AS85EP1_SCR(3) = 0x20A9; + + AS85EP1_PORT_PMC(6) = 0xFF; /* A20-25, A0,A1 $BM-8z(B */ + AS85EP1_PORT_PMC(7) = 0x0E; /* CS1,2,3 $BM-8z(B */ + AS85EP1_PORT_PMC(9) = 0xFF; /* D16-23 $BM-8z(B */ + AS85EP1_PORT_PMC(10) = 0xFF; /* D24-31 $BM-8z(B */ + + AS85EP1_IRAMM = 0x3; /* $BFbB"L?Na(BRAM$B$O!V(Bwrite-mode$B!W$K$J$j$^$9(B */ + + /* The early chip we have is buggy, so that writing the interrupt + vectors into low RAM may screw up, so for non-ROM kernels, we + only rely on the reset vector being downloaded, and copy the + rest of the interrupt vectors into place here. The specific bug + is that writing address N, where (N & 0x10) == 0x10, will _also_ + write to address (N - 0x10). We avoid this (effectively) by + writing in 16-byte chunks backwards from the end. */ + src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF); + dst = (u32 *)&_intv_copy_dst_start + + (src - (u32 *)&_intv_copy_src_start); + do { + u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3]; + dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3; + dst -= 4; + src -= 4; + } while (src > (u32 *)&_intv_copy_src_start); + + AS85EP1_IRAMM = 0x0; /* $BFbB"L?Na(BRAM$B$O!V(Bread-mode$B!W$K$J$j$^$9(B */ + + nb85e_intc_disable_irqs (); +} + +void __init mach_setup (char **cmdline) +{ +#ifdef CONFIG_V850E_NB85E_UART_CONSOLE + nb85e_uart_cons_init (1); +#endif + + AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */ + AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins. */ + mach_tick = as85ep1_led_tick; + + ROOT_DEV = MKDEV (BLKMEM_MAJOR, 0); +} + +void __init mach_get_physical_ram (unsigned long *ram_start, + unsigned long *ram_len) +{ + *ram_start = RAM_START; + *ram_len = RAM_END - RAM_START; +} + +void __init mach_reserve_bootmem () +{ + extern char _root_fs_image_start, _root_fs_image_end; + u32 root_fs_image_start = (u32)&_root_fs_image_start; + u32 root_fs_image_end = (u32)&_root_fs_image_end; + + /* We can't use the space between SRAM and SDRAM, so prevent the + kernel from trying. */ + reserve_bootmem (SRAM_ADDR + SRAM_SIZE, + SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE)); + + /* Reserve the memory used by the root filesystem image if it's + in RAM. */ + if (root_fs_image_end > root_fs_image_start + && root_fs_image_start >= RAM_START + && root_fs_image_start < RAM_END) + reserve_bootmem (root_fs_image_start, + root_fs_image_end - root_fs_image_start); +} + +void mach_gettimeofday (struct timeval *tv) +{ + tv->tv_sec = 0; + tv->tv_usec = 0; +} + +void __init mach_sched_init (struct irqaction *timer_action) +{ + /* Start hardware timer. */ + nb85e_timer_d_configure (0, HZ); + /* Install timer interrupt handler. */ + setup_irq (IRQ_INTCMD(0), timer_action); +} + +static struct nb85e_intc_irq_init irq_inits[] = { + { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, + { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 }, + { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, + { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 }, + { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 }, + { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 }, + { 0 } +}; +#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) + +static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; + +void __init mach_init_irqs (void) +{ + nb85e_intc_init_irq_types (irq_inits, hw_itypes); +} + +void machine_restart (char *__unused) +{ +#ifdef CONFIG_RESET_GUARD + disable_reset_guard (); +#endif + asm ("jmp r0"); /* Jump to the reset vector. */ +} + +void machine_halt (void) +{ +#ifdef CONFIG_RESET_GUARD + disable_reset_guard (); +#endif + local_irq_disable (); /* Ignore all interrupts. */ + AS85EP1_PORT_IO (LEDS_PORT) = 0xAA; /* Note that we halted. */ + for (;;) + asm ("halt; nop; nop; nop; nop; nop"); +} + +void machine_power_off (void) +{ + machine_halt (); +} + +/* Called before configuring an on-chip UART. */ +void as85ep1_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) +{ + /* Make the shared uart/port pins be uart pins. */ + AS85EP1_PORT_PMC(3) |= (0x5 << chan); + + /* The AS85EP1 connects some general-purpose I/O pins on the CPU to + the RTS/CTS lines of UART 1's serial connection. I/O pins P53 + and P54 are RTS and CTS respectively. */ + if (chan == 1) { + /* Put P53 & P54 in I/O port mode. */ + AS85EP1_PORT_PMC(5) &= ~0x18; + /* Make P53 an output, and P54 an input. */ + AS85EP1_PORT_PM(5) |= 0x10; + } +} + +/* Minimum and maximum bounds for the moving upper LED boundary in the + clock tick display. */ +#define MIN_MAX_POS 0 +#define MAX_MAX_POS 7 + +/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if + we pick 6 and 0 as above, we get 49 cycles, which is when divided into + the standard 100 value for HZ, gives us an almost 1s total time. */ +#define TICKS_PER_FRAME \ + (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS)) + +static void as85ep1_led_tick () +{ + static unsigned counter = 0; + + if (++counter == TICKS_PER_FRAME) { + static int pos = 0, max_pos = MAX_MAX_POS, dir = 1; + + if (dir > 0 && pos == max_pos) { + dir = -1; + if (max_pos == MIN_MAX_POS) + max_pos = MAX_MAX_POS; + else + max_pos--; + } else { + if (dir < 0 && pos == 0) + dir = 1; + + if (pos + dir <= max_pos) { + /* Each bit of port 0 has a LED. */ + set_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT)); + pos += dir; + clear_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT)); + } + } + + counter = 0; + } +} diff -Nru a/arch/v850/kernel/bug.c b/arch/v850/kernel/bug.c --- a/arch/v850/kernel/bug.c Wed Nov 27 14:36:31 2002 +++ b/arch/v850/kernel/bug.c Wed Nov 27 14:36:31 2002 @@ -60,3 +60,76 @@ machine_halt (); } #endif /* CONFIG_RESET_GUARD */ + + + +struct spec_reg_name { + const char *name; + int gpr; +}; + +struct spec_reg_name spec_reg_names[] = { + { "sp", GPR_SP }, + { "gp", GPR_GP }, + { "tp", GPR_TP }, + { "ep", GPR_EP }, + { "lp", GPR_LP }, + { 0, 0 } +}; + +void show_regs (struct pt_regs *regs) +{ + int gpr_base, gpr_offs; + + printk (" pc 0x%08lx psw 0x%08lx kernel_mode %d\n", + regs->pc, regs->psw, regs->kernel_mode); + printk (" ctpc 0x%08lx ctpsw 0x%08lx ctbp 0x%08lx\n", + regs->ctpc, regs->ctpsw, regs->ctbp); + + for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) { + for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) { + int gpr = gpr_base + gpr_offs; + long val = regs->gpr[gpr]; + struct spec_reg_name *srn; + + for (srn = spec_reg_names; srn->name; srn++) + if (srn->gpr == gpr) + break; + + if (srn->name) + printk ("%7s 0x%08lx", srn->name, val); + else + printk (" r%02d 0x%08lx", gpr, val); + } + + printk ("\n"); + } +} + +void show_stack (unsigned long *sp) +{ + unsigned long end; + unsigned long addr = (unsigned long)sp; + + if (! addr) + addr = stack_addr (); + + addr = addr & ~3; + end = (addr + THREAD_SIZE - 1) & THREAD_MASK; + + while (addr < end) { + printk ("%8lX: ", addr); + while (addr < end) { + printk (" %8lX", *(unsigned long *)addr); + addr += sizeof (unsigned long); + if (! (addr & 0xF)) + break; + } + printk ("\n"); + } +} + +void dump_stack () +{ + show_stack (0); +} diff -Nru a/arch/v850/kernel/entry.S b/arch/v850/kernel/entry.S --- a/arch/v850/kernel/entry.S Wed Nov 27 14:36:31 2002 +++ b/arch/v850/kernel/entry.S Wed Nov 27 14:36:31 2002 @@ -657,6 +657,12 @@ shl 16, r6 // clear upper 16 bits shr 20, r6 // shift back, and remove lower nibble add -8, r6 // remove bias for irqs + + // If the IRQ index is negative, it's actually one of the exception + // traps below 0x80 (currently, the illegal instruction trap, and + // the `debug trap'). Handle these separately. + bn exception + // Call the high-level interrupt handling code. jarl CSYM(handle_irq), lp // fall through @@ -665,6 +671,23 @@ handlers, below). */ ret_from_irq: RETURN(IRQ) + +exception: + mov hilo(ret_from_irq), lp // where the handler should return + + cmp -2, r6 + bne 1f + // illegal instruction exception + addi SIGILL, r0, r6 // Arg 0: signal number + mov CURRENT_TASK, r7 // Arg 1: task + jr CSYM(force_sig) // tail call + +1: cmp -1, r6 + bne bad_trap_wrapper + // `dbtrap' exception + movea PTO, sp, r6 // Arg 0: user regs + jr CSYM(debug_trap) // tail call + END(irq) @@ -692,44 +715,7 @@ jarl CSYM(handle_irq), lp RETURN(NMI) -END(nmi0) - - -/* - * Illegal instruction trap. - * - * The stack-pointer (r3) should have already been saved to the memory - * location ENTRY_SP (the reason for this is that the interrupt vectors may be - * beyond a 22-bit signed offset jump from the actual interrupt handler, and - * this allows them to save the stack-pointer and use that register to do an - * indirect jump). - */ -G_ENTRY(illegal_instruction): - SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers. - ei - addi SIGILL, r0, r6 // Arg 0: signal number - mov CURRENT_TASK, r7 // Arg 1: task - mov hilo(ret_from_irq), lp // where the handler should return - jr CSYM(force_sig) -END(illegal_instruction) - - -/* - * `Debug' trap - * - * The stack-pointer (r3) should have already been saved to the memory - * location ENTRY_SP (the reason for this is that the interrupt vectors may be - * beyond a 22-bit signed offset jump from the actual interrupt handler, and - * this allows them to save the stack-pointer and use that register to do an - * indirect jump). - */ -G_ENTRY(dbtrap): - SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers. - ei - movea PTO, sp, r6 // Arg 0: user regs - mov hilo(ret_from_irq), lp // where the handler should return - jr CSYM(debug_trap) -END(dbtrap) +END(nmi) /* @@ -771,8 +757,7 @@ .data .align 4 - .globl CSYM(trap_table) -CSYM(trap_table): +C_DATA(trap_table): .long bad_trap_wrapper // trap 0, doesn't use trap table. .long syscall_long // trap 1, `long' syscall. .long bad_trap_wrapper @@ -789,13 +774,13 @@ .long bad_trap_wrapper .long bad_trap_wrapper .long bad_trap_wrapper +C_END(trap_table) .section .rodata .align 4 - .globl CSYM(sys_call_table) -CSYM(sys_call_table): +C_DATA(sys_call_table): .long CSYM(sys_ni_syscall) // 0 - old "setup()" system call .long CSYM(sys_exit) .long sys_fork_wrapper @@ -923,10 +908,10 @@ .long CSYM(sys_adjtimex) .long CSYM(sys_ni_syscall) // 125 - sys_mprotect .long CSYM(sys_sigprocmask) - .long CSYM(sys_create_module) + .long CSYM(sys_ni_syscall) // sys_create_module .long CSYM(sys_init_module) .long CSYM(sys_delete_module) - .long CSYM(sys_get_kernel_syms) // 130 + .long CSYM(sys_ni_syscall) // 130 - sys_get_kernel_syms .long CSYM(sys_quotactl) .long CSYM(sys_getpgid) .long CSYM(sys_fchdir) @@ -963,7 +948,7 @@ .long CSYM(sys_setresuid) .long CSYM(sys_getresuid) // 165 .long CSYM(sys_ni_syscall) // for vm86 - .long CSYM(sys_query_module) + .long CSYM(sys_ni_syscall) // sys_query_module .long CSYM(sys_poll) .long CSYM(sys_nfsservctl) .long CSYM(sys_setresgid) // 170 @@ -1003,3 +988,4 @@ .long CSYM(sys_ni_syscall) // sys_madvise .space (NR_syscalls-205)*4 +C_END(sys_call_table) diff -Nru a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c --- a/arch/v850/kernel/fpga85e2c.c Wed Nov 27 14:36:31 2002 +++ b/arch/v850/kernel/fpga85e2c.c Wed Nov 27 14:36:31 2002 @@ -73,8 +73,6 @@ void __init mach_setup (char **cmdline) { - printk (KERN_INFO "CPU: NEC V850E2 (NA85E2C FPGA implementation)\n"); - memcons_setup (); /* Setup up NMI0 to copy the registers to a known memory location. diff -Nru a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c --- a/arch/v850/kernel/gbus_int.c Wed Nov 27 14:36:32 2002 +++ b/arch/v850/kernel/gbus_int.c Wed Nov 27 14:36:32 2002 @@ -14,11 +14,10 @@ #include #include #include -#include /* For some unfathomable reason, - request_irq/free_irq are declared here. */ +#include +#include #include -#include /* The number of shared GINT interrupts. */ @@ -72,7 +71,7 @@ } /* Disable all GBUS irqs. */ -int gbus_int_disable_irqs () +void gbus_int_disable_irqs () { unsigned w, n; for (w = 0; w < GBUS_INT_NUM_WORDS; w++) @@ -183,7 +182,7 @@ { struct gbus_int_irq_init *init; for (init = inits; init->name; init++) { - int i; + unsigned i; struct hw_interrupt_type *hwit = hw_irq_types++; hwit->typename = init->name; @@ -200,7 +199,7 @@ /* Set the interrupt priorities. */ for (i = 0; i < init->num; i++) { - int j; + unsigned j; for (j = 0; j < NUM_USED_GINTS; j++) if (used_gint[j].priority > init->priority) break; @@ -222,7 +221,7 @@ /* GBUS interrupts themselves. */ -__init struct gbus_int_irq_init gbus_irq_inits[] = { +struct gbus_int_irq_init gbus_irq_inits[] __initdata = { /* First set defaults. */ { "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6}, { 0 } @@ -236,7 +235,7 @@ /* Initialize GBUS interrupts. */ void __init gbus_int_init_irqs (void) { - int i; + unsigned i; /* First initialize the shared gint interrupts. */ for (i = 0; i < NUM_USED_GINTS; i++) { diff -Nru a/arch/v850/kernel/head.S b/arch/v850/kernel/head.S --- a/arch/v850/kernel/head.S Wed Nov 27 14:36:27 2002 +++ b/arch/v850/kernel/head.S Wed Nov 27 14:36:27 2002 @@ -118,4 +118,4 @@ // Start Linux kernel. mov hilo(CSYM(machine_halt)), lp jr CSYM(start_kernel) -END(start) +C_END(start) diff -Nru a/arch/v850/kernel/intv.S b/arch/v850/kernel/intv.S --- a/arch/v850/kernel/intv.S Wed Nov 27 14:36:30 2002 +++ b/arch/v850/kernel/intv.S Wed Nov 27 14:36:30 2002 @@ -52,10 +52,10 @@ JUMP_TO_HANDLER (trap, ENTRY_SP) // TRAP1n .balign 0x10 - JUMP_TO_HANDLER (illegal_instruction, ENTRY_SP) // illegal insn trap + JUMP_TO_HANDLER (irq, ENTRY_SP) // illegal insn trap .balign 0x10 - JUMP_TO_HANDLER (dbtrap, ENTRY_SP) // DBTRAP insn + JUMP_TO_HANDLER (irq, ENTRY_SP) // DBTRAP insn /* Hardware interrupt vectors. */ diff -Nru a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c --- a/arch/v850/kernel/irq.c Wed Nov 27 14:36:31 2002 +++ b/arch/v850/kernel/irq.c Wed Nov 27 14:36:31 2002 @@ -252,7 +252,7 @@ unsigned int status; irq_enter(); - kstat.irqs[cpu][irq]++; + kstat_cpu(cpu).irqs[irq]++; spin_lock(&desc->lock); desc->handler->ack(irq); /* diff -Nru a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/module.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,225 @@ +/* + * arch/v850/kernel/module.c -- Architecture-specific module functions + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * Copyright (C) 2001 Rusty Russell + * + * 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. + * + * Written by Miles Bader + * + * Derived in part from arch/ppc/kernel/module.c + */ + +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt , ...) +#endif + +void *module_alloc (unsigned long size) +{ + return size == 0 ? 0 : vmalloc (size); +} + +void module_free (struct module *mod, void *module_region) +{ + vfree (module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +int module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, + struct module *mod) +{ + return 0; +} + +/* Count how many different relocations (different symbol, different + addend) */ +static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) +{ + unsigned int i, j, ret = 0; + + /* Sure, this is order(n^2), but it's usually short, and not + time critical */ + for (i = 0; i < num; i++) { + for (j = 0; j < i; j++) { + /* If this addend appeared before, it's + already been counted */ + if (ELF32_R_SYM(rela[i].r_info) + == ELF32_R_SYM(rela[j].r_info) + && rela[i].r_addend == rela[j].r_addend) + break; + } + if (j == i) ret++; + } + return ret; +} + +/* Get the potential trampolines size required of the init and + non-init sections */ +static unsigned long get_plt_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + int is_init) +{ + unsigned long ret = 0; + unsigned i; + + /* Everything marked ALLOC (this includes the exported + symbols) */ + for (i = 1; i < hdr->e_shnum; i++) { + /* If it's called *.init*, and we're not init, we're + not interested */ + if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) + != is_init) + continue; + + if (sechdrs[i].sh_type == SHT_RELA) { + DEBUGP("Found relocations in section %u\n", i); + DEBUGP("Ptr: %p. Number: %u\n", + (void *)hdr + sechdrs[i].sh_offset, + sechdrs[i].sh_size / sizeof(Elf32_Rela)); + ret += count_relocs((void *)hdr + + sechdrs[i].sh_offset, + sechdrs[i].sh_size + / sizeof(Elf32_Rela)) + * sizeof(struct v850_plt_entry); + } + } + + return ret; +} + +long module_core_size (const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs, + const char *secstrings, struct module *mod) +{ + mod->arch.core_plt_offset = (mod->core_size + 3) & ~3; + return mod->core_size + get_plt_size (hdr, sechdrs, secstrings, 1); +} + +long module_init_size (const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs, + const char *secstrings, struct module *mod) +{ + mod->arch.init_plt_offset = (mod->init_size + 3) & ~3; + return mod->init_size + get_plt_size (hdr, sechdrs, secstrings, 1); +} + +int apply_relocate (Elf32_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, + struct module *mod) +{ + printk ("Barf\n"); + return -ENOEXEC; +} + +/* Set up a trampoline in the PLT to bounce us to the distant function */ +static uint32_t do_plt_call(void *location, Elf32_Addr val, struct module *mod) +{ + struct v850_plt_entry *entry; + /* Instructions used to do the indirect jump. */ + uint32_t tramp[2]; + + /* We have to trash a register, so we assume that any control + transfer more than 21-bits away must be a function call + (so we can use a call-clobbered register). */ + tramp[0] = 0x0621 + ((val & 0xffff) << 16); /* mov sym, r1 ... */ + tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */ + + /* Init, or core PLT? */ + if (location >= mod->module_core + && location < mod->module_core + mod->arch.core_plt_offset) + entry = mod->module_core + mod->arch.core_plt_offset; + else + entry = mod->module_init + mod->arch.init_plt_offset; + + /* Find this entry, or if that fails, the next avail. entry */ + while (entry->tramp[0]) + if (entry->tramp[0] == tramp[0] && entry->tramp[1] == tramp[1]) + return (uint32_t)entry; + else + entry++; + + entry->tramp[0] = tramp[0]; + entry->tramp[1] = tramp[1]; + + return (uint32_t)entry; +} + +int apply_relocate_add (Elf32_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, + struct module *mod) +{ + unsigned int i; + Elf32_Rela *rela = (void *)sechdrs[relsec].sh_offset; + + DEBUGP ("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + + for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) { + /* This is where to make the change */ + uint32_t *loc + = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_offset + + rela[i].r_offset); + /* This is the symbol it is referring to */ + Elf32_Sym *sym + = ((Elf32_Sym *)sechdrs[symindex].sh_offset + + ELF32_R_SYM (rela[i].r_info)); + uint32_t val = sym->st_value; + + if (! val) { + printk (KERN_WARNING "%s: Unknown symbol %s\n", + mod->name, strtab + sym->st_name); + return -ENOENT; + } + + val += rela[i].r_addend; + + switch (ELF32_R_TYPE (rela[i].r_info)) { + case R_V850_32: + /* We write two shorts instead of a long because even + 32-bit insns only need half-word alignment, but + 32-bit data writes need to be long-word aligned. */ + val += ((uint16_t *)loc)[0]; + val += ((uint16_t *)loc)[1] << 16; + ((uint16_t *)loc)[0] = val & 0xffff; + ((uint16_t *)loc)[1] = (val >> 16) & 0xffff; + break; + + case R_V850_22_PCREL: + /* Maybe jump indirectly via a PLT table entry. */ + if ((int32_t)(val - (uint32_t)loc) > 0x1fffff + || (int32_t)(val - (uint32_t)loc) < -0x200000) + val = do_plt_call (loc, val, mod); + + val -= (uint32_t)loc; + + /* We write two shorts instead of a long because + even 32-bit insns only need half-word alignment, + but 32-bit data writes need to be long-word + aligned. */ + ((uint16_t *)loc)[0] = + (*(uint16_t *)loc & 0xffc0) /* opcode + reg */ + | ((val >> 16) & 0xffc03f); /* offs high */ + ((uint16_t *)loc)[1] = + (val & 0xffff); /* offs low */ + break; + + default: + printk (KERN_ERR "module %s: Unknown reloc: %u\n", + mod->name, ELF32_R_TYPE (rela[i].r_info)); + return -ENOEXEC; + } + } + + return 0; +} diff -Nru a/arch/v850/kernel/nb85e_intc.c b/arch/v850/kernel/nb85e_intc.c --- a/arch/v850/kernel/nb85e_intc.c Wed Nov 27 14:36:28 2002 +++ b/arch/v850/kernel/nb85e_intc.c Wed Nov 27 14:36:28 2002 @@ -33,7 +33,7 @@ { struct nb85e_intc_irq_init *init; for (init = inits; init->name; init++) { - int i; + unsigned i; struct hw_interrupt_type *hwit = hw_irq_types++; hwit->typename = init->name; diff -Nru a/arch/v850/kernel/nb85e_utils.c b/arch/v850/kernel/nb85e_utils.c --- a/arch/v850/kernel/nb85e_utils.c Wed Nov 27 14:36:28 2002 +++ b/arch/v850/kernel/nb85e_utils.c Wed Nov 27 14:36:28 2002 @@ -2,8 +2,8 @@ * include/asm-v850/nb85e_utils.h -- Utility functions associated with * the NB85E cpu core * - * Copyright (C) 2001 NEC Corporation - * Copyright (C) 2001 Miles Bader + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader * * 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 @@ -40,7 +40,7 @@ /* Find the lowest clock divider setting that can represent RATE. */ for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) { /* Minimum interrupt rate possible using this divider. */ - int min_int_rate + unsigned min_int_rate = (base_freq >> _divlog2) >> counter_size; if (min_int_rate <= rate) { diff -Nru a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c --- a/arch/v850/kernel/process.c Wed Nov 27 14:36:28 2002 +++ b/arch/v850/kernel/process.c Wed Nov 27 14:36:28 2002 @@ -58,49 +58,6 @@ (*idle) (); } -struct spec_reg_name { - const char *name; - int gpr; -}; - -struct spec_reg_name spec_reg_names[] = { - { "sp", GPR_SP }, - { "gp", GPR_GP }, - { "tp", GPR_TP }, - { "ep", GPR_EP }, - { "lp", GPR_LP }, - { 0, 0 } -}; - -void show_regs (struct pt_regs *regs) -{ - int gpr_base, gpr_offs; - - printk (" pc 0x%08lx psw 0x%08lx kernel_mode %d\n", - regs->pc, regs->psw, regs->kernel_mode); - printk (" ctpc 0x%08lx ctpsw 0x%08lx ctbp 0x%08lx\n", - regs->ctpc, regs->ctpsw, regs->ctbp); - - for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) { - for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) { - int gpr = gpr_base + gpr_offs; - long val = regs->gpr[gpr]; - struct spec_reg_name *srn; - - for (srn = spec_reg_names; srn->name; srn++) - if (srn->gpr == gpr) - break; - - if (srn->name) - printk ("%7s 0x%08lx", srn->name, val); - else - printk (" r%02d 0x%08lx", gpr, val); - } - - printk ("\n"); - } -} - /* * This is the mechanism for creating a new kernel thread. * @@ -231,7 +188,7 @@ are in entry.S). */ int fork_common (int flags, unsigned long new_sp, struct pt_regs *regs) { - struct task_struct *p = do_fork (flags, new_sp, regs, 0, 0); + struct task_struct *p = do_fork (flags, new_sp, regs, 0, 0, 0); return IS_ERR (p) ? PTR_ERR (p) : p->pid; } diff -Nru a/arch/v850/kernel/procfs.c b/arch/v850/kernel/procfs.c --- a/arch/v850/kernel/procfs.c Wed Nov 27 14:36:30 2002 +++ b/arch/v850/kernel/procfs.c Wed Nov 27 14:36:30 2002 @@ -24,7 +24,7 @@ #else seq_printf (m, "CPU-Model: %s\n", CPU_MODEL); #endif - + #ifdef CPU_CLOCK_FREQ seq_printf (m, "CPU-Clock: %ld (%ld MHz)\n", (long)CPU_CLOCK_FREQ, diff -Nru a/arch/v850/kernel/rte_cb.c b/arch/v850/kernel/rte_cb.c --- a/arch/v850/kernel/rte_cb.c Wed Nov 27 14:36:27 2002 +++ b/arch/v850/kernel/rte_cb.c Wed Nov 27 14:36:27 2002 @@ -60,25 +60,11 @@ void __init mach_setup (char **cmdline) { - printk (KERN_INFO - "CPU: %s\n" - "Platform: %s%s\n", - CPU_MODEL_LONG, - PLATFORM_LONG, -#ifdef CONFIG_ROM_KERNEL - "" -#elif defined (CONFIG_RTE_CB_MULTI) - " (with Multi ROM monitor)" -#else - " (with ROM monitor)" -#endif - ); - /* Probe for Mother-A, and print a message if we find it. */ - *(volatile long *)MB_A_SRAM_ADDR = 0xDEADBEEF; - if (*(volatile long *)MB_A_SRAM_ADDR == 0xDEADBEEF) { - *(volatile long *)MB_A_SRAM_ADDR = 0x12345678; - if (*(volatile long *)MB_A_SRAM_ADDR == 0x12345678) + *(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF; + if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) { + *(volatile unsigned long *)MB_A_SRAM_ADDR = 0x12345678; + if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0x12345678) printk (KERN_INFO " NEC SolutionGear/Midas lab" " RTE-MOTHER-A motherboard\n"); diff -Nru a/arch/v850/kernel/rte_cb_leds.c b/arch/v850/kernel/rte_cb_leds.c --- a/arch/v850/kernel/rte_cb_leds.c Wed Nov 27 14:36:27 2002 +++ b/arch/v850/kernel/rte_cb_leds.c Wed Nov 27 14:36:27 2002 @@ -109,10 +109,12 @@ else if (whence == 2) offs += LED_NUM_DIGITS; /* end-relative */ - if (offs >= 0 && offs <= LED_NUM_DIGITS) - file->f_pos = offs; - else + if (offs < 0 || offs > LED_NUM_DIGITS) return -EINVAL; + + file->f_pos = offs; + + return 0; } static struct file_operations leds_fops = { diff -Nru a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c --- a/arch/v850/kernel/rte_mb_a_pci.c Wed Nov 27 14:36:28 2002 +++ b/arch/v850/kernel/rte_mb_a_pci.c Wed Nov 27 14:36:28 2002 @@ -239,7 +239,7 @@ struct resource *r; pci_for_each_dev (dev) { - int di_num; + unsigned di_num; unsigned class = dev->class >> 8; if (class && class != PCI_CLASS_BRIDGE_HOST) { diff -Nru a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c --- a/arch/v850/kernel/setup.c Wed Nov 27 14:36:30 2002 +++ b/arch/v850/kernel/setup.c Wed Nov 27 14:36:30 2002 @@ -78,6 +78,9 @@ /* ... and tell the kernel about it. */ init_mem_alloc (ram_start, ram_len); + printk (KERN_INFO "CPU: %s\nPlatform: %s\n", + CPU_MODEL_LONG, PLATFORM_LONG); + /* do machine-specific setups. */ mach_setup (cmdline); @@ -266,6 +269,16 @@ initial gap from PAGE_OFFSET to ram_start. */ zones_size[ZONE_DMA] = ADDR_TO_PAGE (ram_len + (ram_start - PAGE_OFFSET)); + + /* The allocator is very picky about the address of the first + allocatable page -- it must be at least as aligned as the + maximum allocation -- so try to detect cases where it will get + confused and signal them at compile time (this is a common + problem when porting to a new platform with ). There is a + similar runtime check in free_area_init_core. */ +#if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1)) +#error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it) +#endif free_area_init_node (0, NODE_DATA(0), 0, zones_size, ADDR_TO_PAGE (PAGE_OFFSET), 0); diff -Nru a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c --- a/arch/v850/kernel/signal.c Wed Nov 27 14:36:32 2002 +++ b/arch/v850/kernel/signal.c Wed Nov 27 14:36:32 2002 @@ -512,9 +512,10 @@ /* Did we come from a system call? */ if (PT_REGS_SYSCALL (regs)) { /* Restart the system call - no handlers present */ - if (regs->gpr[GPR_RVAL] == -ERESTARTNOHAND || - regs->gpr[GPR_RVAL] == -ERESTARTSYS || - regs->gpr[GPR_RVAL] == -ERESTARTNOINTR) { + if (regs->gpr[GPR_RVAL] == (v850_reg_t)-ERESTARTNOHAND || + regs->gpr[GPR_RVAL] == (v850_reg_t)-ERESTARTSYS || + regs->gpr[GPR_RVAL] == (v850_reg_t)-ERESTARTNOINTR) + { regs->gpr[12] = PT_REGS_SYSCALL (regs); regs->pc -= 4; /* Size of `trap 0' insn. */ } diff -Nru a/arch/v850/kernel/sim.c b/arch/v850/kernel/sim.c --- a/arch/v850/kernel/sim.c Wed Nov 27 14:36:31 2002 +++ b/arch/v850/kernel/sim.c Wed Nov 27 14:36:31 2002 @@ -42,8 +42,6 @@ const char *err; unsigned long root_dev_addr, root_dev_len; - printk (KERN_INFO "CPU: NEC V850E (GDB simulator)\n"); - simcons_setup (); printk (KERN_INFO "Reading root filesystem: %s", ROOT_FS); diff -Nru a/arch/v850/kernel/sim85e2c.c b/arch/v850/kernel/sim85e2c.c --- a/arch/v850/kernel/sim85e2c.c Wed Nov 27 14:36:30 2002 +++ b/arch/v850/kernel/sim85e2c.c Wed Nov 27 14:36:30 2002 @@ -79,8 +79,6 @@ void __init mach_setup (char **cmdline) { - printk (KERN_INFO "CPU: NEC V850E2 (sim85e2c simulator)\n"); - memcons_setup (); } diff -Nru a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c --- a/arch/v850/kernel/simcons.c Wed Nov 27 14:36:31 2002 +++ b/arch/v850/kernel/simcons.c Wed Nov 27 14:36:31 2002 @@ -154,5 +154,5 @@ { V850_SIM_SYSCALL (make_raw, 0); register_console (&simcons); - printk (KERN_INFO "Console: GDB/v850e simulator stdio\n"); + printk (KERN_INFO "Console: GDB V850E simulator stdio\n"); } diff -Nru a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c --- a/arch/v850/kernel/v850_ksyms.c Wed Nov 27 14:36:30 2002 +++ b/arch/v850/kernel/v850_ksyms.c Wed Nov 27 14:36:30 2002 @@ -27,6 +27,9 @@ extern void dump_thread (struct pt_regs *, struct user *); EXPORT_SYMBOL (dump_thread); EXPORT_SYMBOL (kernel_thread); +EXPORT_SYMBOL (enable_irq); +EXPORT_SYMBOL (disable_irq); +EXPORT_SYMBOL (disable_irq_nosync); EXPORT_SYMBOL (__bug); /* Networking helper routines. */ @@ -46,7 +49,6 @@ EXPORT_SYMBOL_NOVERS (strlen); EXPORT_SYMBOL_NOVERS (strnlen); EXPORT_SYMBOL_NOVERS (strpbrk); -EXPORT_SYMBOL_NOVERS (strtok); EXPORT_SYMBOL_NOVERS (strrchr); EXPORT_SYMBOL_NOVERS (strstr); EXPORT_SYMBOL_NOVERS (memset); diff -Nru a/arch/v850/rte_ma1_cb-ksram.ld b/arch/v850/rte_ma1_cb-ksram.ld --- a/arch/v850/rte_ma1_cb-ksram.ld Wed Nov 27 14:36:32 2002 +++ b/arch/v850/rte_ma1_cb-ksram.ld Wed Nov 27 14:36:32 2002 @@ -93,6 +93,11 @@ *(.initcall7.init) . = ALIGN (4) ; ___initcall_end = . ; + + . = ALIGN (4) ; + ___initramfs_start = . ; + *(.init.ramfs) + ___initramfs_end = . ; } > SRAM /* This provides address at which the interrupt vectors are diff -Nru a/arch/v850/rte_ma1_cb-rom.ld b/arch/v850/rte_ma1_cb-rom.ld --- a/arch/v850/rte_ma1_cb-rom.ld Wed Nov 27 14:36:31 2002 +++ b/arch/v850/rte_ma1_cb-rom.ld Wed Nov 27 14:36:31 2002 @@ -45,9 +45,14 @@ ___stop___ksymtab = . ; . = ALIGN (4) ; __etext = . ; + + . = ALIGN (4) ; + ___initramfs_start = . ; + *(.init.ramfs) + ___initramfs_end = . ; } > ROM - __data_load_start = . ; + __rom_copy_src_start = . ; .data : { __kram_start = . ; diff -Nru a/arch/v850/rte_ma1_cb.ld b/arch/v850/rte_ma1_cb.ld --- a/arch/v850/rte_ma1_cb.ld Wed Nov 27 14:36:27 2002 +++ b/arch/v850/rte_ma1_cb.ld Wed Nov 27 14:36:27 2002 @@ -98,10 +98,15 @@ *(.initcall7.init) . = ALIGN (4) ; ___initcall_end = . ; + + . = ALIGN (4) ; + ___initramfs_start = . ; + *(.init.ramfs) + ___initramfs_end = . ; } > SDRAM - /* This provides address at which the interrupt vectors are - initially loaded by the loader. */ + /* The address at which the interrupt vectors are initially + loaded by the loader. */ __intv_load_start = ALIGN (0x10) ; /* Interrupt vector space. Because we're using the monitor diff -Nru a/arch/v850/sim.ld b/arch/v850/sim.ld --- a/arch/v850/sim.ld Wed Nov 27 14:36:27 2002 +++ b/arch/v850/sim.ld Wed Nov 27 14:36:27 2002 @@ -96,6 +96,12 @@ *(.initcall7.init) . = ALIGN (4) ; ___initcall_end = . ; + + . = ALIGN (4) ; + ___initramfs_start = . ; + *(.init.ramfs) + ___initramfs_end = . ; + __init_end = . ; __kram_end = . ; diff -Nru a/arch/v850/sim85e2c.ld b/arch/v850/sim85e2c.ld --- a/arch/v850/sim85e2c.ld Wed Nov 27 14:36:32 2002 +++ b/arch/v850/sim85e2c.ld Wed Nov 27 14:36:32 2002 @@ -86,6 +86,12 @@ *(.initcall7.init) . = ALIGN (4) ; ___initcall_end = . ; + + . = ALIGN (4) ; + ___initramfs_start = . ; + *(.init.ramfs) + ___initramfs_end = . ; + __init_end = . ; } > IRAM diff -Nru a/arch/v850/vmlinux.lds.S b/arch/v850/vmlinux.lds.S --- a/arch/v850/vmlinux.lds.S Wed Nov 27 14:36:31 2002 +++ b/arch/v850/vmlinux.lds.S Wed Nov 27 14:36:31 2002 @@ -20,6 +20,10 @@ # endif #endif +#ifdef CONFIG_V850E_AS85EP1 +# include "as85ep1.ld" +#endif + #ifdef CONFIG_RTE_CB_MA1 # ifdef CONFIG_ROM_KERNEL # include "rte_ma1_cb-rom.ld" diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c --- a/arch/x86_64/kernel/ptrace.c Wed Nov 27 14:36:28 2002 +++ b/arch/x86_64/kernel/ptrace.c Wed Nov 27 14:36:28 2002 @@ -178,8 +178,7 @@ /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; - ret = security_ops->ptrace(current->parent, current); - if (ret) + if ((ret = security_ptrace(current->parent, current))) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Wed Nov 27 14:36:31 2002 +++ b/drivers/Makefile Wed Nov 27 14:36:31 2002 @@ -8,6 +8,9 @@ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_PARISC) += parisc/ obj-$(CONFIG_ACPI) += acpi/ +# PnP must come after ACPI since it will eventually need to check if acpi +# was used and do nothing if so +obj-$(CONFIG_PNP) += pnp/ obj-y += serial/ obj-$(CONFIG_PARPORT) += parport/ obj-y += base/ char/ block/ misc/ net/ media/ @@ -26,7 +29,6 @@ obj-$(CONFIG_ZORRO) += zorro/ obj-$(CONFIG_ALL_PPC) += macintosh/ obj-$(CONFIG_MAC) += macintosh/ -obj-$(CONFIG_PNP) += pnp/ obj-$(CONFIG_SGI) += sgi/ obj-$(CONFIG_VT) += video/ obj-$(CONFIG_PARIDE) += block/paride/ diff -Nru a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile --- a/drivers/acorn/char/Makefile Wed Nov 27 14:36:27 2002 +++ b/drivers/acorn/char/Makefile Wed Nov 27 14:36:27 2002 @@ -2,7 +2,6 @@ # Makefile for the acorn character device drivers. # -# All the objects that export symbols. obj-arc := keyb_arc.o defkeymap-acorn.o obj-$(CONFIG_ARCH_ACORN) += i2c.o pcf8583.o diff -Nru a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c --- a/drivers/acorn/scsi/acornscsi.c Wed Nov 27 14:36:30 2002 +++ b/drivers/acorn/scsi/acornscsi.c Wed Nov 27 14:36:30 2002 @@ -137,10 +137,10 @@ #include #include #include -#include #include #include #include +#include #include #include diff -Nru a/drivers/acorn/scsi/arxescsi.h b/drivers/acorn/scsi/arxescsi.h --- a/drivers/acorn/scsi/arxescsi.h Wed Nov 27 14:36:27 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,80 +0,0 @@ -/* - * ARXE SCSI card driver - * - * Copyright (C) 1997-2000 Russell King - * - * Changes to support ARXE 16-bit SCSI card by Stefan Hanske - */ -#ifndef ARXE_SCSI_H -#define ARXE_SCSI_H - -#define MANU_ARXE 0x0041 -#define PROD_ARXE_SCSI 0x00be - -extern int arxescsi_detect (Scsi_Host_Template *); -extern int arxescsi_release (struct Scsi_Host *); -extern const char *arxescsi_info (struct Scsi_Host *); -extern int arxescsi_proc_info (char *buffer, char **start, off_t offset, - int length, int hostno, int inout); - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#ifndef CAN_QUEUE -/* - * Default queue size - */ -#define CAN_QUEUE 1 -#endif - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 1 -#endif - -#ifndef SCSI_ID -/* - * Default SCSI host ID - */ -#define SCSI_ID 7 -#endif - -#include - -#include "fas216.h" - -#define ARXEScsi { \ -proc_info: arxescsi_proc_info, \ -name: "ARXE SCSI card", \ -detect: arxescsi_detect, \ -release: arxescsi_release, \ -info: arxescsi_info, \ -can_queue: CAN_QUEUE, \ -this_id: SCSI_ID, \ -sg_tablesize: SG_ALL, \ -cmd_per_lun: CMD_PER_LUN, \ -use_clustering: DISABLE_CLUSTERING, \ -command: fas216_command, \ -queuecommand: fas216_queue_command, \ -eh_host_reset_handler: fas216_eh_host_reset, \ -eh_bus_reset_handler: fas216_eh_bus_reset, \ -eh_device_reset_handler: fas216_eh_device_reset, \ -eh_abort_handler: fas216_eh_abort, \ - } - -#ifndef HOSTS_C - -typedef struct { - FAS216_Info info; - - /* other info... */ - unsigned int cstatus; /* card status register */ - unsigned int dmaarea; /* Pseudo DMA area */ -} ARXEScsi_Info; - -#define CSTATUS_IRQ (1 << 0) -#define CSTATUS_DRQ (1 << 0) - -#endif /* HOSTS_C */ - -#endif /* ARXE_SCSI_H */ diff -Nru a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c --- a/drivers/acorn/scsi/cumana_2.c Wed Nov 27 14:36:31 2002 +++ b/drivers/acorn/scsi/cumana_2.c Wed Nov 27 14:36:31 2002 @@ -23,10 +23,8 @@ #include #include #include -#include -#include #include -#include +#include #include #include diff -Nru a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c --- a/drivers/acorn/scsi/eesox.c Wed Nov 27 14:36:32 2002 +++ b/drivers/acorn/scsi/eesox.c Wed Nov 27 14:36:32 2002 @@ -29,10 +29,8 @@ #include #include #include -#include -#include #include -#include +#include #include #include diff -Nru a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c --- a/drivers/acorn/scsi/fas216.c Wed Nov 27 14:36:29 2002 +++ b/drivers/acorn/scsi/fas216.c Wed Nov 27 14:36:29 2002 @@ -44,8 +44,6 @@ #include #include #include -#include -#include #include #include diff -Nru a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c --- a/drivers/acorn/scsi/powertec.c Wed Nov 27 14:36:31 2002 +++ b/drivers/acorn/scsi/powertec.c Wed Nov 27 14:36:31 2002 @@ -14,10 +14,8 @@ #include #include #include -#include -#include #include -#include +#include #include #include diff -Nru a/drivers/acpi/ac.c b/drivers/acpi/ac.c --- a/drivers/acpi/ac.c Wed Nov 27 14:36:29 2002 +++ b/drivers/acpi/ac.c Wed Nov 27 14:36:29 2002 @@ -29,6 +29,7 @@ #include #include #include +#include #include "acpi_bus.h" #include "acpi_drivers.h" @@ -53,6 +54,7 @@ int acpi_ac_add (struct acpi_device *device); int acpi_ac_remove (struct acpi_device *device, int type); +static int acpi_ac_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_ac_driver = { .name = ACPI_AC_DRIVER_NAME, @@ -69,6 +71,12 @@ unsigned long state; }; +static struct file_operations acpi_ac_fops = { + .open = acpi_ac_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; /* -------------------------------------------------------------------------- AC Adapter Management @@ -103,53 +111,40 @@ struct proc_dir_entry *acpi_ac_dir = NULL; -static int -acpi_ac_read_state ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +int acpi_ac_seq_show(struct seq_file *seq, void *offset) { - struct acpi_ac *ac = (struct acpi_ac *) data; - char *p = page; - int len = 0; + struct acpi_ac *ac = (struct acpi_ac *) seq->private; - ACPI_FUNCTION_TRACE("acpi_ac_read_state"); + ACPI_FUNCTION_TRACE("acpi_ac_seq_show"); - if (!ac || (off != 0)) - goto end; + if (!ac) + return 0; if (acpi_ac_get_state(ac)) { - p += sprintf(p, "ERROR: Unable to read AC Adapter state\n"); - goto end; + seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); + return 0; } - p += sprintf(p, "state: "); + seq_puts(seq, "state: "); switch (ac->state) { case ACPI_AC_STATUS_OFFLINE: - p += sprintf(p, "off-line\n"); + seq_puts(seq, "off-line\n"); break; case ACPI_AC_STATUS_ONLINE: - p += sprintf(p, "on-line\n"); + seq_puts(seq, "on-line\n"); break; default: - p += sprintf(p, "unknown\n"); + seq_puts(seq, "unknown\n"); break; } -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return 0; +} + +static int acpi_ac_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_ac_seq_show, PDE(inode)->data); } - static int acpi_ac_add_fs ( @@ -174,7 +169,7 @@ "Unable to create '%s' fs entry\n", ACPI_AC_FILE_STATE)); else { - entry->read_proc = acpi_ac_read_state; + entry->proc_fops = &acpi_ac_fops; entry->data = acpi_driver_data(device); } diff -Nru a/drivers/acpi/button.c b/drivers/acpi/button.c --- a/drivers/acpi/button.c Wed Nov 27 14:36:27 2002 +++ b/drivers/acpi/button.c Wed Nov 27 14:36:27 2002 @@ -29,6 +29,7 @@ #include #include #include +#include #include "acpi_bus.h" #include "acpi_drivers.h" @@ -69,6 +70,7 @@ int acpi_button_add (struct acpi_device *device); int acpi_button_remove (struct acpi_device *device, int type); +static int acpi_button_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_button_driver = { .name = ACPI_BUTTON_DRIVER_NAME, @@ -87,6 +89,12 @@ unsigned long pushed; }; +static struct file_operations acpi_button_fops = { + .open = acpi_button_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; /* -------------------------------------------------------------------------- FS Interface (/proc) @@ -94,39 +102,26 @@ static struct proc_dir_entry *acpi_button_dir = NULL; -static int -acpi_button_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_button_seq_show(struct seq_file *seq, void *offset) { - struct acpi_button *button = (struct acpi_button *) data; - char *p = page; - int len = 0; + struct acpi_button *button = (struct acpi_button *) seq->private; - ACPI_FUNCTION_TRACE("acpi_button_read_info"); + ACPI_FUNCTION_TRACE("acpi_button_seq_show"); if (!button || !button->device) - goto end; + return 0; - p += sprintf(p, "type: %s\n", + seq_printf(seq, "type: %s\n", acpi_device_name(button->device)); -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return 0; } - +static int acpi_button_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_button_seq_show, PDE(inode)->data); +} + static int acpi_button_add_fs ( struct acpi_device *device) @@ -170,7 +165,7 @@ "Unable to create '%s' fs entry\n", ACPI_BUTTON_FILE_INFO)); else { - entry->read_proc = acpi_button_read_info; + entry->proc_fops = &acpi_button_fops; entry->data = acpi_driver_data(device); } diff -Nru a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c --- a/drivers/acpi/dispatcher/dsmthdat.c Wed Nov 27 14:36:29 2002 +++ b/drivers/acpi/dispatcher/dsmthdat.c Wed Nov 27 14:36:29 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dsmthdat - control method arguments and local variables - * $Revision: 64 $ + * $Revision: 66 $ * ******************************************************************************/ @@ -28,6 +28,7 @@ #include "acdispat.h" #include "amlcode.h" #include "acnamesp.h" +#include "acinterp.h" #define _COMPONENT ACPI_DISPATCHER @@ -274,6 +275,7 @@ * RETURN: Status * * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. + * Note: There is no "implicit conversion" for locals. * ******************************************************************************/ @@ -286,11 +288,17 @@ { acpi_status status; acpi_namespace_node *node; + acpi_operand_object *new_desc = object; ACPI_FUNCTION_TRACE ("Ds_method_data_set_value"); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "obj %p op %X, ref count = %d [%s]\n", object, + opcode, object->common.reference_count, + acpi_ut_get_type_name (object->common.type))); + /* Get the namespace node for the arg/local */ status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node); @@ -298,14 +306,30 @@ return_ACPI_STATUS (status); } - /* Increment ref count so object can't be deleted while installed */ + /* + * If the object has just been created and is not attached to anything, + * (the reference count is 1), then we can just store it directly into + * the arg/local. Otherwise, we must copy it. + */ + if (object->common.reference_count > 1) { + status = acpi_ut_copy_iobject_to_iobject (object, &new_desc, walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_ut_add_reference (object); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object Copied %p, new %p\n", + object, new_desc)); + } + else { + /* Increment ref count so object can't be deleted while installed */ - /* Install the object into the stack entry */ + acpi_ut_add_reference (new_desc); + } - node->object = object; - return_ACPI_STATUS (AE_OK); + /* Install the object */ + + node->object = new_desc; + return_ACPI_STATUS (status); } @@ -560,7 +584,8 @@ current_obj_desc = acpi_ns_get_attached_object (node); if (current_obj_desc == obj_desc) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n", obj_desc)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n", + obj_desc)); return_ACPI_STATUS (status); } @@ -609,16 +634,12 @@ "Arg (%p) is an Obj_ref(Node), storing in node %p\n", obj_desc, current_obj_desc)); - /* Detach an existing object from the referenced Node */ - - acpi_ns_detach_object (current_obj_desc->reference.object); - /* - * Store this object into the Node + * Store this object to the Node * (perform the indirect store) */ - status = acpi_ns_attach_object (current_obj_desc->reference.object, - obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc)); + status = acpi_ex_store_object_to_node (obj_desc, + current_obj_desc->reference.object, walk_state); return_ACPI_STATUS (status); } } diff -Nru a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c --- a/drivers/acpi/events/evevent.c Wed Nov 27 14:36:31 2002 +++ b/drivers/acpi/events/evevent.c Wed Nov 27 14:36:31 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evevent - Fixed and General Purpose Even handling and dispatch - * $Revision: 96 $ + * $Revision: 99 $ * *****************************************************************************/ @@ -331,11 +331,8 @@ * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need * to be the same size." */ - acpi_gbl_gpe_block_info[0].address_space_id = acpi_gbl_FADT->Xgpe0_blk.address_space_id; - acpi_gbl_gpe_block_info[1].address_space_id = acpi_gbl_FADT->Xgpe1_blk.address_space_id; - - acpi_gbl_gpe_block_info[0].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe0_blk.register_bit_width); - acpi_gbl_gpe_block_info[1].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe1_blk.register_bit_width); + acpi_gbl_gpe_block_info[0].register_count = 0; + acpi_gbl_gpe_block_info[1].register_count = 0; acpi_gbl_gpe_block_info[0].block_address = &acpi_gbl_FADT->Xgpe0_blk; acpi_gbl_gpe_block_info[1].block_address = &acpi_gbl_FADT->Xgpe1_blk; @@ -343,28 +340,25 @@ acpi_gbl_gpe_block_info[0].block_base_number = 0; acpi_gbl_gpe_block_info[1].block_base_number = acpi_gbl_FADT->gpe1_base; - /* Warn and exit if there are no GPE registers */ - - acpi_gbl_gpe_register_count = acpi_gbl_gpe_block_info[0].register_count + - acpi_gbl_gpe_block_info[1].register_count; - if (!acpi_gbl_gpe_register_count) { - ACPI_REPORT_WARNING (("There are no GPE blocks defined in the FADT\n")); - return_ACPI_STATUS (AE_OK); - } /* * Determine the maximum GPE number for this machine. * Note: both GPE0 and GPE1 are optional, and either can exist without - * the other + * the other. + * If EITHER the register length OR the block address are zero, then that + * particular block is not supported. */ - if (acpi_gbl_gpe_block_info[0].register_count) { - /* GPE block 0 exists */ + if (acpi_gbl_FADT->Xgpe0_blk.register_bit_width && ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0_blk.address)) { + /* GPE block 0 exists (has length and address > 0) */ - acpi_gbl_gpe_number_max = ACPI_MUL_8 (acpi_gbl_gpe_block_info[0].register_count) - 1; + acpi_gbl_gpe_block_info[0].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe0_blk.register_bit_width); + acpi_gbl_gpe_number_max = ACPI_MUL_8 (acpi_gbl_gpe_block_info[0].register_count) - 1; } - if (acpi_gbl_gpe_block_info[1].register_count) { - /* GPE block 1 exists */ + if (acpi_gbl_FADT->Xgpe1_blk.register_bit_width && ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address)) { + /* GPE block 1 exists (has length and address > 0) */ + + acpi_gbl_gpe_block_info[1].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe1_blk.register_bit_width); /* Check for GPE0/GPE1 overlap (if both banks exist) */ @@ -385,6 +379,15 @@ (ACPI_MUL_8 (acpi_gbl_gpe_block_info[1].register_count) - 1); } + /* Warn and exit if there are no GPE registers */ + + acpi_gbl_gpe_register_count = acpi_gbl_gpe_block_info[0].register_count + + acpi_gbl_gpe_block_info[1].register_count; + if (!acpi_gbl_gpe_register_count) { + ACPI_REPORT_WARNING (("There are no GPE blocks defined in the FADT\n")); + return_ACPI_STATUS (AE_OK); + } + /* Check for Max GPE number out-of-range */ if (acpi_gbl_gpe_number_max > ACPI_GPE_MAX) { @@ -460,8 +463,8 @@ + i + acpi_gbl_gpe_block_info[gpe_block].register_count)); - gpe_register_info->status_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id; - gpe_register_info->enable_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id; + gpe_register_info->status_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].block_address->address_space_id; + gpe_register_info->enable_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].block_address->address_space_id; gpe_register_info->status_address.register_bit_width = 8; gpe_register_info->enable_address.register_bit_width = 8; gpe_register_info->status_address.register_bit_offset = 8; @@ -565,7 +568,7 @@ /* Extract the name from the object and convert to a string */ ACPI_MOVE_UNALIGNED32_TO_32 (name, - &((acpi_namespace_node *) obj_handle)->name.integer); + &((acpi_namespace_node *) obj_handle)->name.integer); name[ACPI_NAME_SIZE] = 0; /* @@ -614,8 +617,8 @@ * Now we can add this information to the Gpe_info block * for use during dispatch of this GPE. */ - acpi_gbl_gpe_number_info [gpe_number_index].type = type; - acpi_gbl_gpe_number_info [gpe_number_index].method_handle = obj_handle; + acpi_gbl_gpe_number_info [gpe_number_index].type = type; + acpi_gbl_gpe_number_info [gpe_number_index].method_node = (acpi_namespace_node *) obj_handle; /* * Enable the GPE (SCIs should be disabled at this point) @@ -625,7 +628,7 @@ return (status); } - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %X\n", + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %2.2X\n", name, gpe_number)); return (AE_OK); } @@ -805,15 +808,16 @@ return_VOID; } - if (gpe_info.method_handle) { + if (gpe_info.method_node) { /* * Invoke the GPE Method (_Lxx, _Exx): * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.) */ - status = acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL); + status = acpi_ns_evaluate_by_handle (gpe_info.method_node, NULL, NULL); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("%s while evaluating GPE%X method\n", - acpi_format_exception (status), gpe_number)); + ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2.2X]\n", + acpi_format_exception (status), + gpe_info.method_node->name.ascii, gpe_number)); } } @@ -881,7 +885,7 @@ if (gpe_info->type & ACPI_EVENT_EDGE_TRIGGERED) { status = acpi_hw_clear_gpe (gpe_number); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%X]\n", gpe_number)); + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%2.2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } } @@ -898,14 +902,14 @@ gpe_info->handler (gpe_info->context); } - else if (gpe_info->method_handle) { + else if (gpe_info->method_node) { /* * Disable GPE, so it doesn't keep firing before the method has a * chance to run. */ status = acpi_hw_disable_gpe (gpe_number); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%X]\n", gpe_number)); + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%2.2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } @@ -915,13 +919,13 @@ if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE, acpi_ev_asynch_execute_gpe_method, ACPI_TO_POINTER (gpe_number)))) { - ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%X], event is disabled\n", gpe_number)); + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2.2X], event is disabled\n", gpe_number)); } } else { /* No handler or method to run! */ - ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: No handler or method for GPE[%X], disabling event\n", gpe_number)); + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: No handler or method for GPE[%2.2X], disabling event\n", gpe_number)); /* * Disable the GPE. The GPE will remain disabled until the ACPI @@ -929,7 +933,7 @@ */ status = acpi_hw_disable_gpe (gpe_number); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%X]\n", gpe_number)); + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%2.2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } } @@ -940,7 +944,7 @@ if (gpe_info->type & ACPI_EVENT_LEVEL_TRIGGERED) { status = acpi_hw_clear_gpe (gpe_number); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%X]\n", gpe_number)); + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%2.2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } } diff -Nru a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c --- a/drivers/acpi/events/evrgnini.c Wed Nov 27 14:36:27 2002 +++ b/drivers/acpi/events/evrgnini.c Wed Nov 27 14:36:27 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evrgnini- ACPI Address_space (Op_region) init - * $Revision: 63 $ + * $Revision: 64 $ * *****************************************************************************/ @@ -268,6 +268,11 @@ if (ACPI_SUCCESS (status)) { pci_id->bus = ACPI_LOWORD (temp); } + + /* + * Complete this device's Pci_id + */ + acpi_os_derive_pci_id (node, region_obj->region.node, &pci_id); *region_context = pci_id; return_ACPI_STATUS (AE_OK); diff -Nru a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h --- a/drivers/acpi/include/acconfig.h Wed Nov 27 14:36:31 2002 +++ b/drivers/acpi/include/acconfig.h Wed Nov 27 14:36:31 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acconfig.h - Global configuration constants - * $Revision: 118 $ + * $Revision: 119 $ * *****************************************************************************/ @@ -54,7 +54,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20021115 +#define ACPI_CA_VERSION 0x20021122 /* Version of ACPI supported */ diff -Nru a/drivers/acpi/include/aclocal.h b/drivers/acpi/include/aclocal.h --- a/drivers/acpi/include/aclocal.h Wed Nov 27 14:36:31 2002 +++ b/drivers/acpi/include/aclocal.h Wed Nov 27 14:36:31 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: aclocal.h - Internal data types used across the ACPI subsystem - * $Revision: 179 $ + * $Revision: 181 $ * *****************************************************************************/ @@ -301,7 +301,6 @@ typedef struct { - u8 address_space_id; acpi_generic_address *block_address; u16 register_count; u8 block_base_number; @@ -330,7 +329,7 @@ typedef struct { - acpi_handle method_handle; /* Method handle for direct (fast) execution */ + acpi_namespace_node *method_node; /* Method node for this GPE level */ acpi_gpe_handler handler; /* Address of handler, if any */ void *context; /* Context to be passed to handler */ u8 type; /* Level or Edge */ diff -Nru a/drivers/acpi/include/acpiosxf.h b/drivers/acpi/include/acpiosxf.h --- a/drivers/acpi/include/acpiosxf.h Wed Nov 27 14:36:27 2002 +++ b/drivers/acpi/include/acpiosxf.h Wed Nov 27 14:36:27 2002 @@ -246,6 +246,14 @@ acpi_integer value, u32 width); +/* + * Interim function needed for PCI IRQ routing + */ +void +acpi_os_derive_pci_id( + acpi_handle rhandle, + acpi_handle chandle, + acpi_pci_id **pci_id); /* * Miscellaneous diff -Nru a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c --- a/drivers/acpi/namespace/nsxfobj.c Wed Nov 27 14:36:27 2002 +++ b/drivers/acpi/namespace/nsxfobj.c Wed Nov 27 14:36:27 2002 @@ -141,7 +141,7 @@ *ret_handle = acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_node (node)); - /* Return exeption if parent is null */ + /* Return exception if parent is null */ if (!acpi_ns_get_parent_node (node)) { status = AE_NULL_ENTRY; diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c Wed Nov 27 14:36:31 2002 +++ b/drivers/acpi/osl.c Wed Nov 27 14:36:31 2002 @@ -36,6 +36,7 @@ #include #include #include +#include "acpi_bus.h" #include "acpi.h" #ifdef CONFIG_ACPI_EFI @@ -481,6 +482,44 @@ pci_id->function), reg, size, value); return (result ? AE_ERROR : AE_OK); +} + +/* TODO: Rewrite this code!!! */ +void +acpi_os_derive_pci_id ( + acpi_handle rhandle, /* upper bound */ + acpi_handle chandle, /* current node */ + acpi_pci_id **id) +{ + acpi_handle handle; + acpi_pci_id *pci_id = *id; + acpi_status status; + unsigned long temp; + acpi_object_type type; + u8 tu8; + + acpi_get_parent(chandle, &handle); + if (handle != rhandle) { + acpi_os_derive_pci_id(rhandle, handle, &pci_id); + + status = acpi_get_type(handle, &type); + if ( (ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE) ) + return; + + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp); + if (ACPI_SUCCESS(status)) { + pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp)); + pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp)); + + /* any nicer way to get bus number of bridge ? */ + status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8); + if (ACPI_SUCCESS(status) && (tu8 & 0x7f) == 1) { + status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8); + if (ACPI_SUCCESS(status)) + pci_id->bus = tu8; + } + } + } } #else /*!CONFIG_ACPI_PCI*/ diff -Nru a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c --- a/drivers/acpi/parser/psopcode.c Wed Nov 27 14:36:28 2002 +++ b/drivers/acpi/parser/psopcode.c Wed Nov 27 14:36:28 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psopcode - Parser/Interpreter opcode information table - * $Revision: 73 $ + * $Revision: 74 $ * *****************************************************************************/ @@ -734,7 +734,7 @@ acpi_ps_get_opcode_name ( u16 opcode) { -#ifdef ACPI_DISASSEMBLER +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) const acpi_opcode_info *op; diff -Nru a/drivers/acpi/power.c b/drivers/acpi/power.c --- a/drivers/acpi/power.c Wed Nov 27 14:36:30 2002 +++ b/drivers/acpi/power.c Wed Nov 27 14:36:30 2002 @@ -29,6 +29,7 @@ #include #include #include +#include #include "acpi_bus.h" #include "acpi_drivers.h" @@ -48,6 +49,7 @@ int acpi_power_add (struct acpi_device *device); int acpi_power_remove (struct acpi_device *device, int type); +static int acpi_power_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_power_driver = { .name = ACPI_POWER_DRIVER_NAME, @@ -71,6 +73,12 @@ static struct list_head acpi_power_resource_list; +static struct file_operations acpi_power_fops = { + .open = acpi_power_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; /* -------------------------------------------------------------------------- Power Resource Management @@ -379,58 +387,45 @@ struct proc_dir_entry *acpi_power_dir = NULL; - -static int -acpi_power_read_status ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_power_seq_show(struct seq_file *seq, void *offset) { struct acpi_power_resource *resource = NULL; - char *p = page; - int len; - ACPI_FUNCTION_TRACE("acpi_power_read_status"); + ACPI_FUNCTION_TRACE("acpi_power_seq_show"); - if (!data || (off != 0)) - goto end; + resource = (struct acpi_power_resource *)seq->private; - resource = (struct acpi_power_resource *) data; + if (!resource) + goto end; - p += sprintf(p, "state: "); + seq_puts(seq, "state: "); switch (resource->state) { case ACPI_POWER_RESOURCE_STATE_ON: - p += sprintf(p, "on\n"); + seq_puts(seq, "on\n"); break; case ACPI_POWER_RESOURCE_STATE_OFF: - p += sprintf(p, "off\n"); + seq_puts(seq, "off\n"); break; default: - p += sprintf(p, "unknown\n"); + seq_puts(seq, "unknown\n"); break; } - p += sprintf(p, "system level: S%d\n", - resource->system_level); - p += sprintf(p, "order: %d\n", - resource->order); - p += sprintf(p, "reference count: %d\n", - resource->references); + seq_printf(seq, "system level: S%d\n" + "order: %d\n" + "reference count: %d\n", + resource->system_level, + resource->order, + resource->references); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return 0; } +static int acpi_power_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_power_seq_show, PDE(inode)->data); +} static int acpi_power_add_fs ( @@ -458,7 +453,7 @@ "Unable to create '%s' fs entry\n", ACPI_POWER_FILE_STATUS)); else { - entry->read_proc = acpi_power_read_status; + entry->proc_fops = &acpi_power_fops; entry->data = acpi_driver_data(device); } diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c --- a/drivers/acpi/processor.c Wed Nov 27 14:36:31 2002 +++ b/drivers/acpi/processor.c Wed Nov 27 14:36:31 2002 @@ -40,6 +40,7 @@ #include #include #include +#include #include "acpi_bus.h" #include "acpi_drivers.h" @@ -90,6 +91,11 @@ static int acpi_processor_add (struct acpi_device *device); static int acpi_processor_remove (struct acpi_device *device, int type); +static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); +static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file); +static int acpi_processor_power_open_fs(struct inode *inode, struct file *file); +static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file); + static struct acpi_driver acpi_processor_driver = { .name = ACPI_PROCESSOR_DRIVER_NAME, @@ -224,6 +230,34 @@ } piix4; }; +static struct file_operations acpi_processor_info_fops = { + .open = acpi_processor_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_processor_power_fops = { + .open = acpi_processor_power_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_processor_throttling_fops = { + .open = acpi_processor_throttling_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_processor_limit_fops = { + .open = acpi_processor_limit_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static struct acpi_processor *processors[NR_CPUS]; static struct acpi_processor_errata errata; static void (*pm_idle_save)(void) = NULL; @@ -231,6 +265,13 @@ #ifdef CONFIG_ACPI_PROCESSOR_PERF static unsigned int cpufreq_usage_count = 0; static struct cpufreq_driver *acpi_cpufreq_driver; +static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file); +static struct file_operations acpi_processor_perf_fops = { + .open = acpi_processor_perf_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif @@ -1884,174 +1925,132 @@ struct proc_dir_entry *acpi_processor_dir = NULL; -static int -acpi_processor_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; + struct acpi_processor *pr = (struct acpi_processor *)seq->private; - ACPI_FUNCTION_TRACE("acpi_processor_read_info"); + ACPI_FUNCTION_TRACE("acpi_processor_info_seq_show"); - if (!pr || (off != 0)) + if (!pr) goto end; - p += sprintf(p, "processor id: %d\n", - pr->id); - - p += sprintf(p, "acpi id: %d\n", - pr->acpi_id); - - p += sprintf(p, "bus mastering control: %s\n", - pr->flags.bm_control ? "yes" : "no"); - - p += sprintf(p, "power management: %s\n", - pr->flags.power ? "yes" : "no"); - - p += sprintf(p, "throttling control: %s\n", - pr->flags.throttling ? "yes" : "no"); - - p += sprintf(p, "performance management: %s\n", - pr->flags.performance ? "yes" : "no"); - - p += sprintf(p, "limit interface: %s\n", - pr->flags.limit ? "yes" : "no"); + seq_printf(seq, "processor id: %d\n" + "acpi id: %d\n" + "bus mastering control: %s\n" + "power management: %s\n" + "throttling control: %s\n" + "performance management: %s\n" + "limit interface: %s\n", + pr->id, + pr->acpi_id, + pr->flags.bm_control ? "yes" : "no", + pr->flags.power ? "yes" : "no", + pr->flags.throttling ? "yes" : "no", + pr->flags.performance ? "yes" : "no", + pr->flags.limit ? "yes" : "no"); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return 0; } +static int acpi_processor_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_processor_info_seq_show, + PDE(inode)->data); +} -static int -acpi_processor_read_power ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; + struct acpi_processor *pr = (struct acpi_processor *)seq->private; int i = 0; - ACPI_FUNCTION_TRACE("acpi_processor_read_power"); + ACPI_FUNCTION_TRACE("acpi_processor_power_seq_show"); - if (!pr || (off != 0)) + if (!pr) goto end; - p += sprintf(p, "active state: C%d\n", - pr->power.state); - - p += sprintf(p, "default state: C%d\n", - pr->power.default_state); + seq_printf(seq, "active state: C%d\n" + "default state: C%d\n" + "bus master activity: %08x\n", + pr->power.state, + pr->power.default_state, + pr->power.bm_activity); - p += sprintf(p, "bus master activity: %08x\n", - pr->power.bm_activity); + seq_puts(seq, "states:\n"); - p += sprintf(p, "states:\n"); - - for (i=1; ipower.state?'*':' '), i); if (!pr->power.states[i].valid) { - p += sprintf(p, "\n"); + seq_puts(seq, "\n"); continue; } if (pr->power.states[i].promotion.state) - p += sprintf(p, "promotion[C%d] ", + seq_printf(seq, "promotion[C%d] ", pr->power.states[i].promotion.state); else - p += sprintf(p, "promotion[--] "); + seq_puts(seq, "promotion[--] "); if (pr->power.states[i].demotion.state) - p += sprintf(p, "demotion[C%d] ", + seq_printf(seq, "demotion[C%d] ", pr->power.states[i].demotion.state); else - p += sprintf(p, "demotion[--] "); + seq_puts(seq, "demotion[--] "); - p += sprintf(p, "latency[%03d] usage[%08d]\n", + seq_printf(seq, "latency[%03d] usage[%08d]\n", pr->power.states[i].latency, pr->power.states[i].usage); } end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; + return 0; +} - return_VALUE(len); +static int acpi_processor_power_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_processor_power_seq_show, + PDE(inode)->data); } #ifdef CONFIG_ACPI_PROCESSOR_PERF -static int -acpi_processor_read_performance ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; + struct acpi_processor *pr = (struct acpi_processor *)seq->private; int i = 0; - ACPI_FUNCTION_TRACE("acpi_processor_read_performance"); + ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show"); - if (!pr || (off != 0)) + if (!pr) goto end; if (!pr->flags.performance) { - p += sprintf(p, "\n"); + seq_puts(seq, "\n"); goto end; } - p += sprintf(p, "state count: %d\n", - pr->performance.state_count); - - p += sprintf(p, "active state: P%d\n", - pr->performance.state); - - p += sprintf(p, "states:\n"); - - for (i=0; iperformance.state_count; i++) - p += sprintf(p, " %cP%d: %d MHz, %d mW, %d uS\n", + seq_printf(seq, "state count: %d\n" + "active state: P%d\n", + pr->performance.state_count, + pr->performance.state); + + seq_puts(seq, "states:\n"); + for (i = 0; i < pr->performance.state_count; i++) + seq_printf(seq, " %cP%d: %d MHz, %d mW, %d uS\n", (i == pr->performance.state?'*':' '), i, (u32) pr->performance.states[i].core_frequency, (u32) pr->performance.states[i].power, (u32) pr->performance.states[i].transition_latency); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; + return 0; +} - return_VALUE(len); +static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_processor_perf_seq_show, + PDE(inode)->data); } static int @@ -2091,63 +2090,49 @@ } #endif - -static int -acpi_processor_read_throttling ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_processor_throttling_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; + struct acpi_processor *pr = (struct acpi_processor *)seq->private; int i = 0; int result = 0; - ACPI_FUNCTION_TRACE("acpi_processor_read_throttling"); + ACPI_FUNCTION_TRACE("acpi_processor_throttling_seq_show"); - if (!pr || (off != 0)) + if (!pr) goto end; if (!(pr->throttling.state_count > 0)) { - p += sprintf(p, "\n"); + seq_puts(seq, "\n"); goto end; } result = acpi_processor_get_throttling(pr); if (result) { - p += sprintf(p, "Could not determine current throttling state.\n"); + seq_puts(seq, "Could not determine current throttling state.\n"); goto end; } - p += sprintf(p, "state count: %d\n", - pr->throttling.state_count); - - p += sprintf(p, "active state: T%d\n", - pr->throttling.state); - - p += sprintf(p, "states:\n"); - - for (i=0; ithrottling.state_count; i++) - p += sprintf(p, " %cT%d: %02d%%\n", + seq_printf(seq, "state count: %d\n" + "active state: T%d\n", + pr->throttling.state_count, + pr->throttling.state); + + seq_puts(seq, "states:\n"); + for (i = 0; i < pr->throttling.state_count; i++) + seq_printf(seq, " %cT%d: %02d%%\n", (i == pr->throttling.state?'*':' '), i, (pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0)); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return 0; } +static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_processor_throttling_seq_show, + PDE(inode)->data); +} static int acpi_processor_write_throttling ( @@ -2178,53 +2163,38 @@ return_VALUE(count); } - -static int -acpi_processor_read_limit ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; + struct acpi_processor *pr = (struct acpi_processor *)seq->private; - ACPI_FUNCTION_TRACE("acpi_processor_read_limit"); + ACPI_FUNCTION_TRACE("acpi_processor_limit_seq_show"); - if (!pr || (off != 0)) + if (!pr) goto end; if (!pr->flags.limit) { - p += sprintf(p, "\n"); + seq_puts(seq, "\n"); goto end; } - p += sprintf(p, "active limit: P%d:T%d\n", - pr->limit.state.px, pr->limit.state.tx); - - p += sprintf(p, "platform limit: P%d:T0\n", - pr->flags.performance?pr->performance.platform_limit:0); - - p += sprintf(p, "user limit: P%d:T%d\n", - pr->limit.user.px, pr->limit.user.tx); - - p += sprintf(p, "thermal limit: P%d:T%d\n", - pr->limit.thermal.px, pr->limit.thermal.tx); + seq_printf(seq, "active limit: P%d:T%d\n" + "platform limit: P%d:T0\n" + "user limit: P%d:T%d\n" + "thermal limit: P%d:T%d\n", + pr->limit.state.px, pr->limit.state.tx, + pr->flags.performance?pr->performance.platform_limit:0, + pr->limit.user.px, pr->limit.user.tx, + pr->limit.thermal.px, pr->limit.thermal.tx); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return 0; } +static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_processor_limit_seq_show, + PDE(inode)->data); +} static int acpi_processor_write_limit ( @@ -2304,7 +2274,7 @@ "Unable to create '%s' fs entry\n", ACPI_PROCESSOR_FILE_INFO)); else { - entry->read_proc = acpi_processor_read_info; + entry->proc_fops = &acpi_processor_info_fops; entry->data = acpi_driver_data(device); } @@ -2316,7 +2286,7 @@ "Unable to create '%s' fs entry\n", ACPI_PROCESSOR_FILE_POWER)); else { - entry->read_proc = acpi_processor_read_power; + entry->proc_fops = &acpi_processor_power_fops; entry->data = acpi_driver_data(device); } @@ -2329,7 +2299,7 @@ "Unable to create '%s' fs entry\n", ACPI_PROCESSOR_FILE_PERFORMANCE)); else { - entry->read_proc = acpi_processor_read_performance; + entry->proc_fops = &acpi_processor_perf_fops; entry->write_proc = acpi_processor_write_performance; entry->data = acpi_driver_data(device); } @@ -2343,7 +2313,7 @@ "Unable to create '%s' fs entry\n", ACPI_PROCESSOR_FILE_THROTTLING)); else { - entry->read_proc = acpi_processor_read_throttling; + entry->proc_fops = &acpi_processor_throttling_fops; entry->write_proc = acpi_processor_write_throttling; entry->data = acpi_driver_data(device); } @@ -2356,7 +2326,7 @@ "Unable to create '%s' fs entry\n", ACPI_PROCESSOR_FILE_LIMIT)); else { - entry->read_proc = acpi_processor_read_limit; + entry->proc_fops = &acpi_processor_limit_fops; entry->write_proc = acpi_processor_write_limit; entry->data = acpi_driver_data(device); } diff -Nru a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c --- a/drivers/acpi/sleep.c Wed Nov 27 14:36:27 2002 +++ b/drivers/acpi/sleep.c Wed Nov 27 14:36:27 2002 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -32,8 +33,25 @@ #define ACPI_SYSTEM_FILE_SLEEP "sleep" #define ACPI_SYSTEM_FILE_ALARM "alarm" +static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file); +static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file); + static u8 sleep_states[ACPI_S_STATE_COUNT]; +static struct file_operations acpi_system_sleep_fops = { + .open = acpi_system_sleep_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_system_alarm_fops = { + .open = acpi_system_alarm_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static void acpi_power_off (void) { @@ -271,43 +289,26 @@ return status; } - -static int -acpi_system_read_sleep ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset) { - char *p = page; - int size; int i; - ACPI_FUNCTION_TRACE("acpi_system_read_sleep"); - - if (off != 0) - goto end; + ACPI_FUNCTION_TRACE("acpi_system_sleep_seq_show"); for (i = 0; i <= ACPI_STATE_S5; i++) { if (sleep_states[i]) - p += sprintf(p,"S%d ", i); + seq_printf(seq,"S%d ", i); } - p += sprintf(p, "\n"); - -end: - size = (p - page); - if (size <= off+count) *eof = 1; - *start = page + off; - size -= off; - if (size>count) size = count; - if (size<0) size = 0; + seq_puts(seq, "\n"); - return_VALUE(size); + return 0; } +static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_system_sleep_seq_show, PDE(inode)->data); +} static int acpi_system_write_sleep ( @@ -349,25 +350,12 @@ return_VALUE(count); } - -static int -acpi_system_read_alarm ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *context) +static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) { - char *p = page; - int size = 0; u32 sec, min, hr; u32 day, mo, yr; - ACPI_FUNCTION_TRACE("acpi_system_read_alarm"); - - if (off != 0) - goto end; + ACPI_FUNCTION_TRACE("acpi_system_alarm_seq_show"); spin_lock(&rtc_lock); @@ -427,21 +415,19 @@ yr += 2000; #endif - p += sprintf(p,"%4.4u-", yr); - p += (mo > 12) ? sprintf(p, "**-") : sprintf(p, "%2.2u-", mo); - p += (day > 31) ? sprintf(p, "** ") : sprintf(p, "%2.2u ", day); - p += (hr > 23) ? sprintf(p, "**:") : sprintf(p, "%2.2u:", hr); - p += (min > 59) ? sprintf(p, "**:") : sprintf(p, "%2.2u:", min); - p += (sec > 59) ? sprintf(p, "**\n") : sprintf(p, "%2.2u\n", sec); - - end: - size = p - page; - if (size < count) *eof = 1; - else if (size > count) size = count; - if (size < 0) size = 0; - *start = page; + seq_printf(seq,"%4.4u-", yr); + (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo); + (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day); + (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr); + (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min); + (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec); - return_VALUE(size); + return 0; +} + +static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data); } @@ -687,7 +673,7 @@ "Unable to create '%s' fs entry\n", ACPI_SYSTEM_FILE_SLEEP)); else { - entry->read_proc = acpi_system_read_sleep; + entry->proc_fops = &acpi_system_sleep_fops; entry->write_proc = acpi_system_write_sleep; } @@ -699,7 +685,7 @@ "Unable to create '%s' fs entry\n", ACPI_SYSTEM_FILE_ALARM)); else { - entry->read_proc = acpi_system_read_alarm; + entry->proc_fops = &acpi_system_alarm_fops; entry->write_proc = acpi_system_write_alarm; } diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c --- a/drivers/acpi/thermal.c Wed Nov 27 14:36:31 2002 +++ b/drivers/acpi/thermal.c Wed Nov 27 14:36:31 2002 @@ -39,6 +39,7 @@ #include #include #include +#include #include "acpi_bus.h" #include "acpi_drivers.h" @@ -79,6 +80,11 @@ static int acpi_thermal_add (struct acpi_device *device); static int acpi_thermal_remove (struct acpi_device *device, int type); +static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); +static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); +static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); +static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); +static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_thermal_driver = { .name = ACPI_THERMAL_DRIVER_NAME, @@ -157,6 +163,40 @@ struct timer_list timer; }; +static struct file_operations acpi_thermal_state_fops = { + .open = acpi_thermal_state_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_thermal_temp_fops = { + .open = acpi_thermal_temp_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_thermal_trip_fops = { + .open = acpi_thermal_trip_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_thermal_cooling_fops = { + .open = acpi_thermal_cooling_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_thermal_polling_fops = { + .open = acpi_thermal_polling_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; /* -------------------------------------------------------------------------- Thermal Zone Management @@ -720,154 +760,119 @@ struct proc_dir_entry *acpi_thermal_dir = NULL; - -static int -acpi_thermal_read_state ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) { - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; + struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; - ACPI_FUNCTION_TRACE("acpi_thermal_read_state"); + ACPI_FUNCTION_TRACE("acpi_thermal_state_seq_show"); - if (!tz || (off != 0)) + if (!tz) goto end; - p += sprintf(p, "state: "); + seq_puts(seq, "state: "); if (!tz->state.critical && !tz->state.hot && !tz->state.passive && !tz->state.active) - p += sprintf(p, "ok\n"); + seq_puts(seq, "ok\n"); else { if (tz->state.critical) - p += sprintf(p, "critical "); + seq_puts(seq, "critical "); if (tz->state.hot) - p += sprintf(p, "hot "); + seq_puts(seq, "hot "); if (tz->state.passive) - p += sprintf(p, "passive "); + seq_puts(seq, "passive "); if (tz->state.active) - p += sprintf(p, "active[%d]", tz->state.active_index); - p += sprintf(p, "\n"); + seq_printf(seq, "active[%d]", tz->state.active_index); + seq_puts(seq, "\n"); } end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; + return 0; +} - return_VALUE(len); +static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data); } -static int -acpi_thermal_read_temperature ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset) { int result = 0; - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; + struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; - ACPI_FUNCTION_TRACE("acpi_thermal_read_temperature"); + ACPI_FUNCTION_TRACE("acpi_thermal_temp_seq_show"); - if (!tz || (off != 0)) + if (!tz) goto end; result = acpi_thermal_get_temperature(tz); if (result) goto end; - p += sprintf(p, "temperature: %ld C\n", + seq_printf(seq, "temperature: %ld C\n", KELVIN_TO_CELSIUS(tz->temperature)); - + end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; + return 0; +} - return_VALUE(len); +static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data); } -static int -acpi_thermal_read_trip_points ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) { - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; + struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; int i = 0; int j = 0; - ACPI_FUNCTION_TRACE("acpi_thermal_read_trip_points"); + ACPI_FUNCTION_TRACE("acpi_thermal_trip_seq_show"); - if (!tz || (off != 0)) + if (!tz) goto end; if (tz->trips.critical.flags.valid) - p += sprintf(p, "critical (S5): %ld C\n", + seq_printf(seq, "critical (S5): %ld C\n", KELVIN_TO_CELSIUS(tz->trips.critical.temperature)); if (tz->trips.hot.flags.valid) - p += sprintf(p, "hot (S4): %ld C\n", + seq_printf(seq, "hot (S4): %ld C\n", KELVIN_TO_CELSIUS(tz->trips.hot.temperature)); if (tz->trips.passive.flags.valid) { - p += sprintf(p, "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=", + seq_printf(seq, "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=", KELVIN_TO_CELSIUS(tz->trips.passive.temperature), tz->trips.passive.tc1, tz->trips.passive.tc2, tz->trips.passive.tsp); for (j=0; jtrips.passive.devices.count; j++) { - p += sprintf(p, "0x%p ", tz->trips.passive.devices.handles[j]); + seq_printf(seq, "0x%p ", tz->trips.passive.devices.handles[j]); } - p += sprintf(p, "\n"); + seq_puts(seq, "\n"); } - for (i=0; itrips.active[i].flags.valid)) break; - p += sprintf(p, "active[%d]: %ld C: devices=", + seq_printf(seq, "active[%d]: %ld C: devices=", i, KELVIN_TO_CELSIUS(tz->trips.active[i].temperature)); - for (j=0; jtrips.active[i].devices.count; j++) - p += sprintf(p, "0x%p ", + for (j = 0; j < tz->trips.active[i].devices.count; j++) + seq_printf(seq, "0x%p ", tz->trips.active[i].devices.handles[j]); - p += sprintf(p, "\n"); + seq_puts(seq, "\n"); } end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return 0; } +static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data); +} static int acpi_thermal_write_trip_points ( @@ -909,43 +914,32 @@ } -static int -acpi_thermal_read_cooling_mode ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) { - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; + struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; - ACPI_FUNCTION_TRACE("acpi_thermal_read_cooling_mode"); + ACPI_FUNCTION_TRACE("acpi_thermal_cooling_seq_show"); - if (!tz || (off != 0)) + if (!tz) goto end; if (!tz->flags.cooling_mode) { - p += sprintf(p, "\n"); + seq_puts(seq, "\n"); goto end; } - p += sprintf(p, "cooling mode: %s\n", + seq_printf(seq, "cooling mode: %s\n", tz->cooling_mode?"passive":"active"); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return 0; } +static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_thermal_cooling_seq_show, + PDE(inode)->data); +} static int acpi_thermal_write_cooling_mode ( @@ -980,43 +974,32 @@ } -static int -acpi_thermal_read_polling ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset) { - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; + struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; - ACPI_FUNCTION_TRACE("acpi_thermal_read_polling"); + ACPI_FUNCTION_TRACE("acpi_thermal_polling_seq_show"); - if (!tz || (off != 0)) + if (!tz) goto end; if (!tz->polling_frequency) { - p += sprintf(p, "\n"); + seq_puts(seq, "\n"); goto end; } - p += sprintf(p, "polling frequency: %lu seconds\n", + seq_printf(seq, "polling frequency: %lu seconds\n", (tz->polling_frequency / 10)); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return 0; } +static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_thermal_polling_seq_show, + PDE(inode)->data); +} static int acpi_thermal_write_polling ( @@ -1075,7 +1058,7 @@ "Unable to create '%s' fs entry\n", ACPI_THERMAL_FILE_STATE)); else { - entry->read_proc = acpi_thermal_read_state; + entry->proc_fops = &acpi_thermal_state_fops; entry->data = acpi_driver_data(device); } @@ -1087,7 +1070,7 @@ "Unable to create '%s' fs entry\n", ACPI_THERMAL_FILE_TEMPERATURE)); else { - entry->read_proc = acpi_thermal_read_temperature; + entry->proc_fops = &acpi_thermal_temp_fops; entry->data = acpi_driver_data(device); } @@ -1099,7 +1082,7 @@ "Unable to create '%s' fs entry\n", ACPI_THERMAL_FILE_POLLING_FREQ)); else { - entry->read_proc = acpi_thermal_read_trip_points; + entry->proc_fops = &acpi_thermal_trip_fops; entry->write_proc = acpi_thermal_write_trip_points; entry->data = acpi_driver_data(device); } @@ -1112,7 +1095,7 @@ "Unable to create '%s' fs entry\n", ACPI_THERMAL_FILE_COOLING_MODE)); else { - entry->read_proc = acpi_thermal_read_cooling_mode; + entry->proc_fops = &acpi_thermal_cooling_fops; entry->write_proc = acpi_thermal_write_cooling_mode; entry->data = acpi_driver_data(device); } @@ -1125,7 +1108,7 @@ "Unable to create '%s' fs entry\n", ACPI_THERMAL_FILE_POLLING_FREQ)); else { - entry->read_proc = acpi_thermal_read_polling; + entry->proc_fops = &acpi_thermal_polling_fops; entry->write_proc = acpi_thermal_write_polling; entry->data = acpi_driver_data(device); } diff -Nru a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c --- a/drivers/acpi/toshiba_acpi.c Wed Nov 27 14:36:27 2002 +++ b/drivers/acpi/toshiba_acpi.c Wed Nov 27 14:36:27 2002 @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,47 @@ #define HCI_VIDEO_OUT_CRT 0x2 #define HCI_VIDEO_OUT_TV 0x4 +static int toshiba_lcd_open_fs(struct inode *inode, struct file *file); +static int toshiba_video_open_fs(struct inode *inode, struct file *file); +static int toshiba_fan_open_fs(struct inode *inode, struct file *file); +static int toshiba_keys_open_fs(struct inode *inode, struct file *file); +static int toshiba_version_open_fs(struct inode *inode, struct file *file); + +static struct file_operations toshiba_lcd_fops = { + .open = toshiba_lcd_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations toshiba_video_fops = { + .open = toshiba_video_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations toshiba_fan_fops = { + .open = toshiba_fan_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations toshiba_keys_fops = { + .open = toshiba_keys_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations toshiba_version_fops = { + .open = toshiba_version_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* utility */ @@ -126,22 +168,6 @@ return result; } -/* This is the common code at the end of every proc read handler. I don't - * understand it yet. - */ -static int -end_proc_read(const char* p, char* page, off_t off, int count, - char** start, int* eof) -{ - int len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; -} - /* acpi interface wrappers */ @@ -259,29 +285,27 @@ /* proc file handlers */ -static int -proc_read_lcd(char* page, char** start, off_t off, int count, int* eof, - void* context) +static int toshiba_lcd_seq_show(struct seq_file *seq, void *offset) { - char* p = page; u32 hci_result; u32 value; - if (off != 0) goto end; - hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result); if (hci_result == HCI_SUCCESS) { value = value >> HCI_LCD_BRIGHTNESS_SHIFT; - p += sprintf(p, "brightness: %d\n", value); - p += sprintf(p, "brightness_levels: %d\n", - HCI_LCD_BRIGHTNESS_LEVELS); - } else { - p += sprintf(p, "ERROR\n"); - goto end; - } + seq_printf(seq, "brightness: %d\n" + "brightness_levels: %d\n", + value, + HCI_LCD_BRIGHTNESS_LEVELS); + } else + seq_puts(seq, "ERROR\n"); -end: - return end_proc_read(p, page, off, count, start, eof); + return 0; +} + +static int toshiba_lcd_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, toshiba_lcd_seq_show, NULL); } static int @@ -306,31 +330,31 @@ return count; } -static int -proc_read_video(char* page, char** start, off_t off, int count, int* eof, - void* context) +static int toshiba_video_seq_show(struct seq_file *seq, void *offset) { - char* p = page; u32 hci_result; u32 value; - if (off != 0) goto end; - hci_read1(HCI_VIDEO_OUT, &value, &hci_result); if (hci_result == HCI_SUCCESS) { int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; int is_tv = (value & HCI_VIDEO_OUT_TV ) ? 1 : 0; - p += sprintf(p, "lcd_out: %d\n", is_lcd); - p += sprintf(p, "crt_out: %d\n", is_crt); - p += sprintf(p, "tv_out: %d\n", is_tv); - } else { - p += sprintf(p, "ERROR\n"); - goto end; - } + seq_printf(seq, "lcd_out: %d\n" + "crt_out: %d\n" + "tv_out: %d\n", + is_lcd, + is_crt, + is_tv); + } else + seq_puts(seq, "ERROR\n"); -end: - return end_proc_read(p, page, off, count, start, eof); + return 0; +} + +static int toshiba_video_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, toshiba_video_seq_show, NULL); } static int @@ -376,27 +400,26 @@ return count; } -static int -proc_read_fan(char* page, char** start, off_t off, int count, int* eof, - void* context) +static int toshiba_fan_seq_show(struct seq_file *seq, void *offset) { - char* p = page; u32 hci_result; u32 value; - if (off != 0) goto end; - hci_read1(HCI_FAN, &value, &hci_result); if (hci_result == HCI_SUCCESS) { - p += sprintf(p, "running: %d\n", (value > 0)); - p += sprintf(p, "force_on: %d\n", force_fan); - } else { - p += sprintf(p, "ERROR\n"); - goto end; - } + seq_printf(seq, "running: %d\n" + "force_on: %d\n", + (value > 0), + force_fan); + } else + seq_puts(seq, "ERROR\n"); -end: - return end_proc_read(p, page, off, count, start, eof); + return 0; +} + +static int toshiba_fan_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, toshiba_fan_seq_show, NULL); } static int @@ -420,16 +443,11 @@ return count; } -static int -proc_read_keys(char* page, char** start, off_t off, int count, int* eof, - void* context) +static int toshiba_keys_seq_show(struct seq_file *seq, void *offset) { - char* p = page; u32 hci_result; u32 value; - if (off != 0) goto end; - if (!key_event_valid) { hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result); if (hci_result == HCI_SUCCESS) { @@ -438,16 +456,23 @@ } else if (hci_result == HCI_EMPTY) { /* better luck next time */ } else { - p += sprintf(p, "ERROR\n"); + seq_puts(seq, "ERROR\n"); goto end; } } - p += sprintf(p, "hotkey_ready: %d\n", key_event_valid); - p += sprintf(p, "hotkey: 0x%04x\n", last_key_event); + seq_printf(seq, "hotkey_ready: %d\n" + "hotkey: 0x%04x\n", + key_event_valid, + last_key_event); end: - return end_proc_read(p, page, off, count, start, eof); + return 0; +} + +static int toshiba_keys_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, toshiba_keys_seq_show, NULL); } static int @@ -466,20 +491,19 @@ return count; } -static int -proc_read_version(char* page, char** start, off_t off, int count, int* eof, - void* context) +static int toshiba_version_seq_show(struct seq_file *seq, void *offset) { - char* p = page; + seq_printf(seq, "driver: %s\n" + "proc_interface: %d\n", + TOSHIBA_ACPI_VERSION, + PROC_INTERFACE_VERSION); - if (off != 0) goto end; - - p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION); - p += sprintf(p, "proc_interface: %d\n", - PROC_INTERFACE_VERSION); + return 0; +} -end: - return end_proc_read(p, page, off, count, start, eof); +static int toshiba_version_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, toshiba_version_seq_show, NULL); } /* proc and module init @@ -490,24 +514,38 @@ { struct proc_dir_entry* proc; - proc = create_proc_read_entry(PROC_LCD, S_IFREG | S_IRUGO | S_IWUSR, - toshiba_proc_dir, proc_read_lcd, 0); - if (proc) proc->write_proc = proc_write_lcd; - - proc = create_proc_read_entry(PROC_VIDEO, S_IFREG | S_IRUGO | S_IWUSR, - toshiba_proc_dir, proc_read_video, 0); - if (proc) proc->write_proc = proc_write_video; - - proc = create_proc_read_entry(PROC_FAN, S_IFREG | S_IRUGO | S_IWUSR, - toshiba_proc_dir, proc_read_fan, 0); - if (proc) proc->write_proc = proc_write_fan; - - proc = create_proc_read_entry(PROC_KEYS, S_IFREG | S_IRUGO | S_IWUSR, - toshiba_proc_dir, proc_read_keys, 0); - if (proc) proc->write_proc = proc_write_keys; + proc = create_proc_entry(PROC_LCD, S_IFREG | S_IRUGO | S_IWUSR, + toshiba_proc_dir); + if (proc) { + proc->proc_fops = &toshiba_lcd_fops; + proc->write_proc = proc_write_lcd; + } + + proc = create_proc_entry(PROC_VIDEO, S_IFREG | S_IRUGO | S_IWUSR, + toshiba_proc_dir); + if (proc) { + proc->proc_fops = &toshiba_video_fops; + proc->write_proc = proc_write_video; + } + + proc = create_proc_entry(PROC_FAN, S_IFREG | S_IRUGO | S_IWUSR, + toshiba_proc_dir); + if (proc) { + proc->proc_fops = &toshiba_fan_fops; + proc->write_proc = proc_write_fan; + } + + proc = create_proc_entry(PROC_KEYS, S_IFREG | S_IRUGO | S_IWUSR, + toshiba_proc_dir); + if (proc) { + proc->proc_fops = &toshiba_keys_fops; + proc->write_proc = proc_write_keys; + } - proc = create_proc_read_entry(PROC_VERSION, S_IFREG | S_IRUGO | S_IWUSR, - toshiba_proc_dir, proc_read_version, 0); + proc = create_proc_entry(PROC_VERSION, S_IFREG | S_IRUGO | S_IWUSR, + toshiba_proc_dir); + if (proc) + proc->proc_fops = &toshiba_version_fops; return(AE_OK); } diff -Nru a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c --- a/drivers/acpi/utilities/utcopy.c Wed Nov 27 14:36:30 2002 +++ b/drivers/acpi/utilities/utcopy.c Wed Nov 27 14:36:30 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utcopy - Internal to external object translation utilities - * $Revision: 105 $ + * $Revision: 106 $ * *****************************************************************************/ @@ -419,7 +419,8 @@ case ACPI_TYPE_STRING: - internal_object->string.pointer = ACPI_MEM_CALLOCATE ((ACPI_SIZE) external_object->string.length + 1); + internal_object->string.pointer = + ACPI_MEM_CALLOCATE ((ACPI_SIZE) external_object->string.length + 1); if (!internal_object->string.pointer) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -434,7 +435,8 @@ case ACPI_TYPE_BUFFER: - internal_object->buffer.pointer = ACPI_MEM_CALLOCATE (external_object->buffer.length); + internal_object->buffer.pointer = + ACPI_MEM_CALLOCATE (external_object->buffer.length); if (!internal_object->buffer.pointer) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -471,10 +473,10 @@ * FUNCTION: Acpi_ut_copy_epackage_to_ipackage * * PARAMETERS: *Internal_object - Pointer to the object we are returning - * *Buffer - Where the object is returned - * *Space_used - Where the length of the object is returned + * *Buffer - Where the object is returned + * *Space_used - Where the length of the object is returned * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to place a package object in a user * buffer. A package object by definition contains other objects. @@ -607,7 +609,8 @@ /* Copy the entire source object over the destination object*/ - ACPI_MEMCPY ((char *) dest_desc, (char *) source_desc, sizeof (acpi_operand_object)); + ACPI_MEMCPY ((char *) dest_desc, (char *) source_desc, + sizeof (acpi_operand_object)); /* Restore the saved fields */ @@ -687,26 +690,36 @@ &state->pkg.dest_object->package.elements[this_index]; switch (object_type) { - case 0: + case ACPI_COPY_TYPE_SIMPLE: - /* - * This is a simple object, just copy it - */ - target_object = acpi_ut_create_internal_object (ACPI_GET_OBJECT_TYPE (source_object)); - if (!target_object) { - return (AE_NO_MEMORY); - } + /* A null source object indicates a (legal) null package element */ - status = acpi_ut_copy_simple_object (source_object, target_object); - if (ACPI_FAILURE (status)) { - return (status); + if (source_object) { + /* + * This is a simple object, just copy it + */ + target_object = acpi_ut_create_internal_object ( + ACPI_GET_OBJECT_TYPE (source_object)); + if (!target_object) { + return (AE_NO_MEMORY); + } + + status = acpi_ut_copy_simple_object (source_object, target_object); + if (ACPI_FAILURE (status)) { + return (status); + } + + *this_target_ptr = target_object; } + else { + /* Pass through a null element */ - *this_target_ptr = target_object; + *this_target_ptr = NULL; + } break; - case 1: + case ACPI_COPY_TYPE_PACKAGE: /* * This object is a package - go down another nesting level @@ -719,6 +732,17 @@ target_object->package.count = source_object->package.count; target_object->common.flags = source_object->common.flags; + + /* + * Create the object array + */ + target_object->package.elements = + ACPI_MEM_CALLOCATE (((ACPI_SIZE) source_object->package.count + 1) * + sizeof (void *)); + if (!target_object->package.elements) { + ACPI_MEM_FREE (target_object); + return (AE_NO_MEMORY); + } /* * Pass the new package object back to the package walk routine diff -Nru a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c --- a/drivers/acpi/utilities/utmisc.c Wed Nov 27 14:36:27 2002 +++ b/drivers/acpi/utilities/utmisc.c Wed Nov 27 14:36:27 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: utmisc - common utility procedures - * $Revision: 86 $ + * $Revision: 87 $ * ******************************************************************************/ @@ -475,7 +475,6 @@ string++; } - return (src_string); } @@ -575,7 +574,6 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) { status = acpi_os_create_semaphore (1, 1, &acpi_gbl_acpi_mutex_info[mutex_id].mutex); @@ -613,7 +611,6 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex); acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL; @@ -651,7 +648,6 @@ return (AE_BAD_PARAMETER); } - this_thread_id = acpi_os_get_thread_id (); /* @@ -679,7 +675,6 @@ } } - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X attempting to acquire Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); @@ -693,7 +688,6 @@ acpi_gbl_acpi_mutex_info[mutex_id].use_count++; acpi_gbl_acpi_mutex_info[mutex_id].owner_id = this_thread_id; } - else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not acquire Mutex [%s] %s\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id), @@ -737,7 +731,6 @@ return (AE_BAD_PARAMETER); } - /* * Mutex must be acquired in order to release it! */ @@ -749,7 +742,6 @@ return (AE_NOT_ACQUIRED); } - /* * Deadlock prevention. Check if this thread owns any mutexes of value * greater than this one. If so, the thread has violated the mutex @@ -770,7 +762,6 @@ } } - /* Mark unlocked FIRST */ acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; @@ -828,7 +819,6 @@ return (AE_NO_MEMORY); } - acpi_ut_push_generic_state (state_list, state); return (AE_OK); } @@ -866,7 +856,6 @@ return (AE_NO_MEMORY); } - acpi_ut_push_generic_state (state_list, state); return (AE_OK); } @@ -1129,7 +1118,6 @@ return_PTR (NULL); } - /* Init fields specific to the control struct */ state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL; @@ -1224,6 +1212,8 @@ } while (state) { + /* Get one element of the package */ + this_index = state->pkg.index; this_source_obj = (acpi_operand_object *) state->pkg.source_object->package.elements[this_index]; @@ -1323,6 +1313,7 @@ { u32 i; signed char sum = 0; + for (i = 0; i < length; i++) { sum = (signed char) (sum + buffer[i]); diff -Nru a/drivers/base/base.h b/drivers/base/base.h --- a/drivers/base/base.h Wed Nov 27 14:36:29 2002 +++ b/drivers/base/base.h Wed Nov 27 14:36:29 2002 @@ -34,7 +34,7 @@ { return 0; } -static int class_hotplug(struct device *dev, const char *action) +static inline int class_hotplug(struct device *dev, const char *action) { return 0; } diff -Nru a/drivers/base/hotplug.c b/drivers/base/hotplug.c --- a/drivers/base/hotplug.c Wed Nov 27 14:36:27 2002 +++ b/drivers/base/hotplug.c Wed Nov 27 14:36:27 2002 @@ -35,6 +35,8 @@ #define BUFFER_SIZE 1024 /* should be enough memory for the env */ #define NUM_ENVP 32 /* number of env pointers */ +static char prefix [] = "devices"; /* /sys/devices/... */ + static int do_hotplug (struct device *dev, char *argv1, const char *action, int (* hotplug) (struct device *, char **, int, char *, int)) { @@ -72,7 +74,7 @@ } dev_length = get_devpath_length (dev); - dev_length += strlen("root"); + dev_length += strlen(prefix); dev_path = kmalloc (dev_length, GFP_KERNEL); if (!dev_path) { kfree (buffer); @@ -80,7 +82,7 @@ return -ENOMEM; } memset (dev_path, 0x00, dev_length); - strcpy (dev_path, "root"); + strcpy (dev_path, prefix); fill_devpath (dev, dev_path, dev_length); argv [0] = hotplug_path; diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Wed Nov 27 14:36:31 2002 +++ b/drivers/block/DAC960.c Wed Nov 27 14:36:31 2002 @@ -19,8 +19,8 @@ */ -#define DAC960_DriverVersion "2.4.11" -#define DAC960_DriverDate "11 October 2001" +#define DAC960_DriverVersion "2.5.47" +#define DAC960_DriverDate "14 November 2002" #include @@ -56,16 +56,6 @@ static int DAC960_ControllerCount = 0; - -/* - DAC960_ActiveControllerCount is the number of active DAC960 Controllers - detected. -*/ - -static int - DAC960_ActiveControllerCount = 0; - - /* DAC960_Controllers is an array of pointers to the DAC960 Controller structures. @@ -82,11 +72,11 @@ */ static struct block_device_operations DAC960_BlockDeviceOperations = { - .owner = THIS_MODULE, - .open = DAC960_Open, - .release = DAC960_Release, - .ioctl = DAC960_IOCTL, - .revalidate_disk= DAC960_revalidate, + .owner =THIS_MODULE, + .open =DAC960_Open, + .release =DAC960_Release, + .ioctl =DAC960_IOCTL, + .revalidate_disk=DAC960_revalidate, }; @@ -99,14 +89,6 @@ /* - DAC960_NotifierBlock is the Notifier Block structure for DAC960 Driver. -*/ - -static NotifierBlock_T - DAC960_NotifierBlock = { DAC960_Notifier, NULL, 0 }; - - -/* DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name, Copyright Notice, and Electronic Mail Address. */ @@ -144,6 +126,54 @@ return false; } +/* + init_dma_loaf() and slice_dma_loaf() are helper functions for + aggregating the dma-mapped memory for a well-known collection of + data structures that are of different lengths. + + These routines don't guarantee any alignment. The caller must + include any space needed for alignment in the sizes of the structures + that are passed in. + */ + +static boolean init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf, + size_t len) +{ + void *cpu_addr; + dma_addr_t dma_handle; + + cpu_addr = pci_alloc_consistent(dev, len, &dma_handle); + if (cpu_addr == NULL) + return false; + + loaf->cpu_free = loaf->cpu_base = cpu_addr; + loaf->dma_free =loaf->dma_base = dma_handle; + loaf->length = len; + memset(cpu_addr, 0, len); + return true; +} + +static void *slice_dma_loaf(struct dma_loaf *loaf, size_t len, + dma_addr_t *dma_handle) +{ + void *cpu_end = loaf->cpu_free + len; + void *cpu_addr = loaf->cpu_free; + + if (cpu_end > loaf->cpu_base + loaf->length) + BUG(); + *dma_handle = loaf->dma_free; + loaf->cpu_free = cpu_end; + loaf->dma_free += len; + return cpu_addr; +} + +static void free_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf_handle) +{ + if (loaf_handle->cpu_base != NULL) + pci_free_consistent(dev, loaf_handle->length, + loaf_handle->cpu_base, loaf_handle->dma_base); +} + /* DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary @@ -156,15 +186,42 @@ int CommandAllocationLength, CommandAllocationGroupSize; int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount; void *AllocationPointer = NULL; + void *ScatterGatherCPU = NULL; + dma_addr_t ScatterGatherDMA; + struct pci_pool *ScatterGatherPool; + void *RequestSenseCPU = NULL; + dma_addr_t RequestSenseDMA; + struct pci_pool *RequestSensePool = NULL; + if (Controller->FirmwareType == DAC960_V1_Controller) { CommandAllocationLength = offsetof(DAC960_Command_T, V1.EndMarker); CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize; + ScatterGatherPool = pci_pool_create("DAC960_V1_ScatterGather", + Controller->PCIDevice, + DAC960_V1_ScatterGatherLimit * sizeof(DAC960_V1_ScatterGatherSegment_T), + sizeof(DAC960_V1_ScatterGatherSegment_T), 0); + if (ScatterGatherPool == NULL) + return DAC960_Failure(Controller, + "AUXILIARY STRUCTURE CREATION (SG)"); + Controller->ScatterGatherPool = ScatterGatherPool; } else { CommandAllocationLength = offsetof(DAC960_Command_T, V2.EndMarker); CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize; + ScatterGatherPool = pci_pool_create("DAC960_V2_ScatterGather", + Controller->PCIDevice, + DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T), + sizeof(DAC960_V2_ScatterGatherSegment_T), 0); + RequestSensePool = pci_pool_create("DAC960_V2_RequestSense", + Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T), + sizeof(int), 0); + if (ScatterGatherPool == NULL || RequestSensePool == NULL) + return DAC960_Failure(Controller, + "AUXILIARY STRUCTURE CREATION (SG)"); + Controller->ScatterGatherPool = ScatterGatherPool; + Controller->V2.RequestSensePool = RequestSensePool; } Controller->CommandAllocationGroupSize = CommandAllocationGroupSize; Controller->FreeCommands = NULL; @@ -176,16 +233,17 @@ if (--CommandsRemaining <= 0) { CommandsRemaining = - Controller->DriverQueueDepth - CommandIdentifier + 1; + Controller->DriverQueueDepth - CommandIdentifier + 1; if (CommandsRemaining > CommandAllocationGroupSize) - CommandsRemaining = CommandAllocationGroupSize; + CommandsRemaining = CommandAllocationGroupSize; CommandGroupByteCount = - CommandsRemaining * CommandAllocationLength; + CommandsRemaining * CommandAllocationLength; AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC); if (AllocationPointer == NULL) - return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); + return DAC960_Failure(Controller, + "AUXILIARY STRUCTURE CREATION"); memset(AllocationPointer, 0, CommandGroupByteCount); - } + } Command = (DAC960_Command_T *) AllocationPointer; AllocationPointer += CommandAllocationLength; Command->CommandIdentifier = CommandIdentifier; @@ -193,6 +251,33 @@ Command->Next = Controller->FreeCommands; Controller->FreeCommands = Command; Controller->Commands[CommandIdentifier-1] = Command; + ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, SLAB_ATOMIC, + &ScatterGatherDMA); + if (ScatterGatherCPU == NULL) + return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); + + if (RequestSensePool != NULL) { + RequestSenseCPU = pci_pool_alloc(RequestSensePool, SLAB_ATOMIC, + &RequestSenseDMA); + if (RequestSenseCPU == NULL) { + pci_pool_free(ScatterGatherPool, ScatterGatherCPU, + ScatterGatherDMA); + return DAC960_Failure(Controller, + "AUXILIARY STRUCTURE CREATION"); + } + } + if (Controller->FirmwareType == DAC960_V1_Controller) { + Command->V1.ScatterGatherList = + (DAC960_V1_ScatterGatherSegment_T *)ScatterGatherCPU; + Command->V1.ScatterGatherListDMA = ScatterGatherDMA; + } else { + Command->V2.ScatterGatherList = + (DAC960_V2_ScatterGatherSegment_T *)ScatterGatherCPU; + Command->V2.ScatterGatherListDMA = ScatterGatherDMA; + Command->V2.RequestSense = + (DAC960_SCSI_RequestSense_T *)RequestSenseCPU; + Command->V2.RequestSenseDMA = RequestSenseDMA; + } } return true; } @@ -206,29 +291,80 @@ static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller) { int i; + struct pci_pool *ScatterGatherPool = Controller->ScatterGatherPool; + struct pci_pool *RequestSensePool = NULL; + void *ScatterGatherCPU; + dma_addr_t ScatterGatherDMA; + void *RequestSenseCPU; + dma_addr_t RequestSenseDMA; + DAC960_Command_T *CommandGroup = NULL; + + + if (Controller->FirmwareType == DAC960_V2_Controller) + RequestSensePool = Controller->V2.RequestSensePool; + Controller->FreeCommands = NULL; for (i = 0; i < Controller->DriverQueueDepth; i++) { DAC960_Command_T *Command = Controller->Commands[i]; - if (Command != NULL && - (Command->CommandIdentifier - % Controller->CommandAllocationGroupSize) == 1) - kfree(Command); + + if (Command == NULL) + continue; + + if (Controller->FirmwareType == DAC960_V1_Controller) { + ScatterGatherCPU = (void *)Command->V1.ScatterGatherList; + ScatterGatherDMA = Command->V1.ScatterGatherListDMA; + RequestSenseCPU = NULL; + RequestSenseDMA = (dma_addr_t)0; + } else { + ScatterGatherCPU = (void *)Command->V2.ScatterGatherList; + ScatterGatherDMA = Command->V2.ScatterGatherListDMA; + RequestSenseCPU = (void *)Command->V2.RequestSense; + RequestSenseDMA = Command->V2.RequestSenseDMA; + } + if (ScatterGatherCPU != NULL) + pci_pool_free(ScatterGatherPool, ScatterGatherCPU, ScatterGatherDMA); + if (RequestSenseCPU != NULL) + pci_pool_free(RequestSensePool, RequestSenseCPU, RequestSenseDMA); + + if ((Command->CommandIdentifier + % Controller->CommandAllocationGroupSize) == 1) { + /* + * We can't free the group of commands until all of the + * request sense and scatter gather dma structures are free. + * Remember the beginning of the group, but don't free it + * until we've reached the beginning of the next group. + */ + if (CommandGroup != NULL) + kfree(CommandGroup); + CommandGroup = Command; + } Controller->Commands[i] = NULL; } + if (CommandGroup != NULL) + kfree(CommandGroup); + if (Controller->CombinedStatusBuffer != NULL) { kfree(Controller->CombinedStatusBuffer); Controller->CombinedStatusBuffer = NULL; Controller->CurrentStatusBuffer = NULL; } + + if (ScatterGatherPool != NULL) + pci_pool_destroy(ScatterGatherPool); if (Controller->FirmwareType == DAC960_V1_Controller) return; + + if (RequestSensePool != NULL) + pci_pool_destroy(RequestSensePool); + for (i = 0; i < DAC960_MaxLogicalDrives; i++) if (Controller->V2.LogicalDeviceInformation[i] != NULL) { kfree(Controller->V2.LogicalDeviceInformation[i]); Controller->V2.LogicalDeviceInformation[i] = NULL; } + for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++) { if (Controller->V2.PhysicalDeviceInformation[i] != NULL) @@ -297,6 +433,8 @@ static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; + + Command->Request = NULL; Command->Next = Controller->FreeCommands; Controller->FreeCommands = Command; } @@ -308,9 +446,9 @@ static void DAC960_WaitForCommand(DAC960_Controller_T *Controller) { - spin_unlock_irq(Controller->RequestQueue.queue_lock); + spin_unlock_irq(&Controller->queue_lock); __wait_event(Controller->CommandWaitQueue, Controller->FreeCommands); - spin_lock_irq(Controller->RequestQueue.queue_lock); + spin_lock_irq(&Controller->queue_lock); } @@ -557,7 +695,7 @@ static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller, DAC960_V1_CommandOpcode_T CommandOpcode, - void *DataPointer) + dma_addr_t DataDMA) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; @@ -565,7 +703,7 @@ DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->Type3.CommandOpcode = CommandOpcode; - CommandMailbox->Type3.BusAddress = Virtual_to_Bus32(DataPointer); + CommandMailbox->Type3.BusAddress = DataDMA; DAC960_ExecuteCommand(Command); CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); @@ -582,7 +720,7 @@ static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller, DAC960_V1_CommandOpcode_T CommandOpcode, unsigned char CommandOpcode2, - void *DataPointer) + dma_addr_t DataDMA) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; @@ -591,7 +729,7 @@ Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->Type3B.CommandOpcode = CommandOpcode; CommandMailbox->Type3B.CommandOpcode2 = CommandOpcode2; - CommandMailbox->Type3B.BusAddress = Virtual_to_Bus32(DataPointer); + CommandMailbox->Type3B.BusAddress = DataDMA; DAC960_ExecuteCommand(Command); CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); @@ -609,7 +747,7 @@ DAC960_V1_CommandOpcode_T CommandOpcode, unsigned char Channel, unsigned char TargetID, - void *DataPointer) + dma_addr_t DataDMA) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; @@ -619,7 +757,7 @@ CommandMailbox->Type3D.CommandOpcode = CommandOpcode; CommandMailbox->Type3D.Channel = Channel; CommandMailbox->Type3D.TargetID = TargetID; - CommandMailbox->Type3D.BusAddress = Virtual_to_Bus32(DataPointer); + CommandMailbox->Type3D.BusAddress = DataDMA; DAC960_ExecuteCommand(Command); CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); @@ -631,12 +769,11 @@ DAC960_V2_GeneralInfo executes a DAC960 V2 Firmware General Information Reading IOCTL Command and waits for completion. It returns true on success and false on failure. + + Return data in The controller's HealthStatusBuffer, which is dma-able memory */ -static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller, - DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, - void *DataPointer, - unsigned int DataByteCount) +static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; @@ -648,12 +785,12 @@ .DataTransferControllerToHost = true; CommandMailbox->Common.CommandControlBits .NoAutoRequestSense = true; - CommandMailbox->Common.DataTransferSize = DataByteCount; - CommandMailbox->Common.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->Common.DataTransferSize = sizeof(DAC960_V2_HealthStatusBuffer_T); + CommandMailbox->Common.IOCTL_Opcode = DAC960_V2_GetHealthStatus; CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(DataPointer); + Controller->V2.HealthStatusBufferDMA; CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -669,12 +806,12 @@ DAC960_V2_ControllerInfo executes a DAC960 V2 Firmware Controller Information Reading IOCTL Command and waits for completion. It returns true on success and false on failure. + + Data is returned in the controller's V2.NewControllerInformation dma-able + memory buffer. */ -static boolean DAC960_V2_ControllerInfo(DAC960_Controller_T *Controller, - DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, - void *DataPointer, - unsigned int DataByteCount) +static boolean DAC960_V2_NewControllerInfo(DAC960_Controller_T *Controller) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; @@ -686,13 +823,13 @@ .DataTransferControllerToHost = true; CommandMailbox->ControllerInfo.CommandControlBits .NoAutoRequestSense = true; - CommandMailbox->ControllerInfo.DataTransferSize = DataByteCount; + CommandMailbox->ControllerInfo.DataTransferSize = sizeof(DAC960_V2_ControllerInfo_T); CommandMailbox->ControllerInfo.ControllerNumber = 0; - CommandMailbox->ControllerInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->ControllerInfo.IOCTL_Opcode = DAC960_V2_GetControllerInfo; CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(DataPointer); + Controller->V2.NewControllerInformationDMA; CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -708,34 +845,34 @@ DAC960_V2_LogicalDeviceInfo executes a DAC960 V2 Firmware Controller Logical Device Information Reading IOCTL Command and waits for completion. It returns true on success and false on failure. + + Data is returned in the controller's V2.NewLogicalDeviceInformation */ -static boolean DAC960_V2_LogicalDeviceInfo(DAC960_Controller_T *Controller, - DAC960_V2_IOCTL_Opcode_T - IOCTL_Opcode, - unsigned short - LogicalDeviceNumber, - void *DataPointer, - unsigned int DataByteCount) +static boolean DAC960_V2_NewLogicalDeviceInfo(DAC960_Controller_T *Controller, + unsigned short LogicalDeviceNumber) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->LogicalDeviceInfo.CommandOpcode = + DAC960_V2_IOCTL; CommandMailbox->LogicalDeviceInfo.CommandControlBits .DataTransferControllerToHost = true; CommandMailbox->LogicalDeviceInfo.CommandControlBits .NoAutoRequestSense = true; - CommandMailbox->LogicalDeviceInfo.DataTransferSize = DataByteCount; + CommandMailbox->LogicalDeviceInfo.DataTransferSize = + sizeof(DAC960_V2_LogicalDeviceInfo_T); CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = LogicalDeviceNumber; - CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = DAC960_V2_GetLogicalDeviceInfoValid; CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(DataPointer); + Controller->V2.NewLogicalDeviceInformationDMA; CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -748,23 +885,30 @@ /* - DAC960_V2_PhysicalDeviceInfo executes a DAC960 V2 Firmware Controller Physical - Device Information Reading IOCTL Command and waits for completion. It + DAC960_V2_PhysicalDeviceInfo executes a DAC960 V2 Firmware Controller "Read + Physical Device Information" IOCTL Command and waits for completion. It returns true on success and false on failure. + + The Channel, TargetID, LogicalUnit arguments should be 0 the first time + this function is called for a given controller. This will return data + for the "first" device on that controller. The returned data includes a + Channel, TargetID, LogicalUnit that can be passed in to this routine to + get data for the NEXT device on that controller. + + Data is stored in the controller's V2.NewPhysicalDeviceInfo dma-able + memory buffer. + */ -static boolean DAC960_V2_PhysicalDeviceInfo(DAC960_Controller_T *Controller, - DAC960_V2_IOCTL_Opcode_T - IOCTL_Opcode, +static boolean DAC960_V2_NewPhysicalDeviceInfo(DAC960_Controller_T *Controller, unsigned char Channel, unsigned char TargetID, - unsigned char LogicalUnit, - void *DataPointer, - unsigned int DataByteCount) + unsigned char LogicalUnit) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; @@ -772,15 +916,17 @@ .DataTransferControllerToHost = true; CommandMailbox->PhysicalDeviceInfo.CommandControlBits .NoAutoRequestSense = true; - CommandMailbox->PhysicalDeviceInfo.DataTransferSize = DataByteCount; + CommandMailbox->PhysicalDeviceInfo.DataTransferSize = + sizeof(DAC960_V2_PhysicalDeviceInfo_T); CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = LogicalUnit; CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = TargetID; CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = Channel; - CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_GetPhysicalDeviceInfoValid; CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(DataPointer); + Controller->V2.NewPhysicalDeviceInformationDMA; CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -792,6 +938,75 @@ } +static void DAC960_V2_ConstructNewUnitSerialNumber( + DAC960_Controller_T *Controller, + DAC960_V2_CommandMailbox_T *CommandMailbox, int Channel, int TargetID, + int LogicalUnit) +{ + CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru; + CommandMailbox->SCSI_10.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->SCSI_10.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->SCSI_10.DataTransferSize = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit; + CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID; + CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel; + CommandMailbox->SCSI_10.CDBLength = 6; + CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ + CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ + CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ + CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ + CommandMailbox->SCSI_10.SCSI_CDB[4] = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Controller->V2.NewInquiryUnitSerialNumberDMA; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; +} + + +/* + DAC960_V2_NewUnitSerialNumber executes an SCSI pass-through + Inquiry command to a SCSI device identified by Channel number, + Target id, Logical Unit Number. This function Waits for completion + of the command. + + The return data includes Unit Serial Number information for the + specified device. + + Data is stored in the controller's V2.NewPhysicalDeviceInfo dma-able + memory buffer. +*/ + +static boolean DAC960_V2_NewInquiryUnitSerialNumber(DAC960_Controller_T *Controller, + int Channel, int TargetID, int LogicalUnit) +{ + DAC960_Command_T *Command; + DAC960_V2_CommandMailbox_T *CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + + Command = DAC960_AllocateCommand(Controller); + CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + + DAC960_V2_ConstructNewUnitSerialNumber(Controller, CommandMailbox, + Channel, TargetID, LogicalUnit); + + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} + + /* DAC960_V2_DeviceOperation executes a DAC960 V2 Firmware Controller Device Operation IOCTL Command and waits for completion. It returns true on @@ -825,84 +1040,144 @@ /* DAC960_V1_EnableMemoryMailboxInterface enables the Memory Mailbox Interface for DAC960 V1 Firmware Controllers. + + PD and P controller types have no memory mailbox, but still need the + other dma mapped memory. */ static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_HardwareType_T hw_type = Controller->HardwareType; + PCI_Device_T *PCI_Device = Controller->PCIDevice; + struct dma_loaf *DmaPages = &Controller->DmaPages; + size_t DmaPagesSize; + size_t CommandMailboxesSize; + size_t StatusMailboxesSize; + DAC960_V1_CommandMailbox_T *CommandMailboxesMemory; + dma_addr_t CommandMailboxesMemoryDMA; + DAC960_V1_StatusMailbox_T *StatusMailboxesMemory; + dma_addr_t StatusMailboxesMemoryDMA; + DAC960_V1_CommandMailbox_T CommandMailbox; DAC960_V1_CommandStatus_T CommandStatus; - unsigned long MemoryMailboxPagesAddress; - unsigned long MemoryMailboxPagesOrder; - unsigned long MemoryMailboxPagesSize; - void *SavedMemoryMailboxesAddress = NULL; - short NextCommandMailboxIndex = 0; - short NextStatusMailboxIndex = 0; - int TimeoutCounter = 1000000, i; - MemoryMailboxPagesOrder = 0; - MemoryMailboxPagesSize = - DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T) + - DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T); - while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) - MemoryMailboxPagesOrder++; - if (Controller->HardwareType == DAC960_LA_Controller) - DAC960_LA_RestoreMemoryMailboxInfo(Controller, - &SavedMemoryMailboxesAddress, - &NextCommandMailboxIndex, - &NextStatusMailboxIndex); - else DAC960_PG_RestoreMemoryMailboxInfo(Controller, - &SavedMemoryMailboxesAddress, - &NextCommandMailboxIndex, - &NextStatusMailboxIndex); - if (SavedMemoryMailboxesAddress == NULL) - { - MemoryMailboxPagesAddress = - __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); - Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; - CommandMailboxesMemory = - (DAC960_V1_CommandMailbox_T *) MemoryMailboxPagesAddress; - } - else CommandMailboxesMemory = SavedMemoryMailboxesAddress; - if (CommandMailboxesMemory == NULL) return false; - Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; - memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + int TimeoutCounter; + int i; + + + if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V1_PciDmaMask)) + return DAC960_Failure(Controller, "DMA mask out of range"); + + if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) { + CommandMailboxesSize = 0; + StatusMailboxesSize = 0; + } else { + CommandMailboxesSize = DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T); + StatusMailboxesSize = DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T); + } + DmaPagesSize = CommandMailboxesSize + StatusMailboxesSize + + sizeof(DAC960_V1_DCDB_T) + sizeof(DAC960_V1_Enquiry_T) + + sizeof(DAC960_V1_ErrorTable_T) + sizeof(DAC960_V1_EventLogEntry_T) + + sizeof(DAC960_V1_RebuildProgress_T) + + sizeof(DAC960_V1_LogicalDriveInformationArray_T) + + sizeof(DAC960_V1_BackgroundInitializationStatus_T) + + sizeof(DAC960_V1_DeviceState_T) + sizeof(DAC960_SCSI_Inquiry_T) + + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + + if (!init_dma_loaf(PCI_Device, DmaPages, DmaPagesSize)) + return false; + + + if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) + goto skip_mailboxes; + + CommandMailboxesMemory = slice_dma_loaf(DmaPages, + CommandMailboxesSize, &CommandMailboxesMemoryDMA); + + /* These are the base addresses for the command memory mailbox array */ Controller->V1.FirstCommandMailbox = CommandMailboxesMemory; + Controller->V1.FirstCommandMailboxDMA = CommandMailboxesMemoryDMA; + CommandMailboxesMemory += DAC960_V1_CommandMailboxCount - 1; Controller->V1.LastCommandMailbox = CommandMailboxesMemory; - Controller->V1.NextCommandMailbox = - &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; - if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; - Controller->V1.PreviousCommandMailbox1 = - &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; - if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; + Controller->V1.NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.PreviousCommandMailbox1 = Controller->V1.LastCommandMailbox; Controller->V1.PreviousCommandMailbox2 = - &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; - StatusMailboxesMemory = - (DAC960_V1_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V1.LastCommandMailbox - 1; + + /* These are the base addresses for the status memory mailbox array */ + StatusMailboxesMemory = slice_dma_loaf(DmaPages, + StatusMailboxesSize, &StatusMailboxesMemoryDMA); + Controller->V1.FirstStatusMailbox = StatusMailboxesMemory; + Controller->V1.FirstStatusMailboxDMA = StatusMailboxesMemoryDMA; StatusMailboxesMemory += DAC960_V1_StatusMailboxCount - 1; Controller->V1.LastStatusMailbox = StatusMailboxesMemory; - Controller->V1.NextStatusMailbox = - &Controller->V1.FirstStatusMailbox[NextStatusMailboxIndex]; - if (SavedMemoryMailboxesAddress != NULL) return true; + Controller->V1.NextStatusMailbox = Controller->V1.FirstStatusMailbox; + +skip_mailboxes: + Controller->V1.MonitoringDCDB = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_DCDB_T), + &Controller->V1.MonitoringDCDB_DMA); + + Controller->V1.NewEnquiry = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_Enquiry_T), + &Controller->V1.NewEnquiryDMA); + + Controller->V1.NewErrorTable = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_ErrorTable_T), + &Controller->V1.NewErrorTableDMA); + + Controller->V1.EventLogEntry = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_EventLogEntry_T), + &Controller->V1.EventLogEntryDMA); + + Controller->V1.RebuildProgress = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_RebuildProgress_T), + &Controller->V1.RebuildProgressDMA); + + Controller->V1.NewLogicalDriveInformation = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_LogicalDriveInformationArray_T), + &Controller->V1.NewLogicalDriveInformationDMA); + + Controller->V1.BackgroundInitializationStatus = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_BackgroundInitializationStatus_T), + &Controller->V1.BackgroundInitializationStatusDMA); + + Controller->V1.NewDeviceState = slice_dma_loaf(DmaPages, + sizeof(DAC960_V1_DeviceState_T), + &Controller->V1.NewDeviceStateDMA); + + Controller->V1.NewInquiryStandardData = slice_dma_loaf(DmaPages, + sizeof(DAC960_SCSI_Inquiry_T), + &Controller->V1.NewInquiryStandardDataDMA); + + Controller->V1.NewInquiryUnitSerialNumber = slice_dma_loaf(DmaPages, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), + &Controller->V1.NewInquiryUnitSerialNumberDMA); + + if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) + return true; + /* Enable the Memory Mailbox Interface. */ Controller->V1.DualModeMemoryMailboxInterface = true; CommandMailbox.TypeX.CommandOpcode = 0x2B; CommandMailbox.TypeX.CommandIdentifier = 0; CommandMailbox.TypeX.CommandOpcode2 = 0x14; CommandMailbox.TypeX.CommandMailboxesBusAddress = - Virtual_to_Bus32(Controller->V1.FirstCommandMailbox); + Controller->V1.FirstCommandMailboxDMA; CommandMailbox.TypeX.StatusMailboxesBusAddress = - Virtual_to_Bus32(Controller->V1.FirstStatusMailbox); + Controller->V1.FirstStatusMailboxDMA; +#define TIMEOUT_COUNT 1000000 + for (i = 0; i < 2; i++) switch (Controller->HardwareType) { case DAC960_LA_Controller: + TimeoutCounter = TIMEOUT_COUNT; while (--TimeoutCounter >= 0) { if (!DAC960_LA_HardwareMailboxFullP(ControllerBaseAddress)) @@ -912,6 +1187,7 @@ if (TimeoutCounter < 0) return false; DAC960_LA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); DAC960_LA_HardwareMailboxNewCommand(ControllerBaseAddress); + TimeoutCounter = TIMEOUT_COUNT; while (--TimeoutCounter >= 0) { if (DAC960_LA_HardwareMailboxStatusAvailableP( @@ -928,6 +1204,7 @@ CommandMailbox.TypeX.CommandOpcode2 = 0x10; break; case DAC960_PG_Controller: + TimeoutCounter = TIMEOUT_COUNT; while (--TimeoutCounter >= 0) { if (!DAC960_PG_HardwareMailboxFullP(ControllerBaseAddress)) @@ -937,6 +1214,8 @@ if (TimeoutCounter < 0) return false; DAC960_PG_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); DAC960_PG_HardwareMailboxNewCommand(ControllerBaseAddress); + + TimeoutCounter = TIMEOUT_COUNT; while (--TimeoutCounter >= 0) { if (DAC960_PG_HardwareMailboxStatusAvailableP( @@ -953,6 +1232,7 @@ CommandMailbox.TypeX.CommandOpcode2 = 0x10; break; default: + DAC960_Failure(Controller, "Unknown Controller Type\n"); break; } return false; @@ -962,75 +1242,146 @@ /* DAC960_V2_EnableMemoryMailboxInterface enables the Memory Mailbox Interface for DAC960 V2 Firmware Controllers. + + Aggregate the space needed for the controller's memory mailbox and + the other data structures that will be targets of dma transfers with + the controller. Allocate a dma-mapped region of memory to hold these + structures. Then, save CPU pointers and dma_addr_t values to reference + the structures that are contained in that region. */ static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; + PCI_Device_T *PCI_Device = Controller->PCIDevice; + struct dma_loaf *DmaPages = &Controller->DmaPages; + size_t DmaPagesSize; + size_t CommandMailboxesSize; + size_t StatusMailboxesSize; + DAC960_V2_CommandMailbox_T *CommandMailboxesMemory; + dma_addr_t CommandMailboxesMemoryDMA; + DAC960_V2_StatusMailbox_T *StatusMailboxesMemory; - DAC960_V2_CommandMailbox_T CommandMailbox; - DAC960_V2_CommandStatus_T CommandStatus = 0; - unsigned long MemoryMailboxPagesAddress; - unsigned long MemoryMailboxPagesOrder; - unsigned long MemoryMailboxPagesSize; - MemoryMailboxPagesOrder = 0; - MemoryMailboxPagesSize = - DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T) + - DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T) + - sizeof(DAC960_V2_HealthStatusBuffer_T); - while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) - MemoryMailboxPagesOrder++; - MemoryMailboxPagesAddress = - __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); - Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; - CommandMailboxesMemory = - (DAC960_V2_CommandMailbox_T *) MemoryMailboxPagesAddress; - if (CommandMailboxesMemory == NULL) return false; - Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; - memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + dma_addr_t StatusMailboxesMemoryDMA; + + DAC960_V2_CommandMailbox_T *CommandMailbox; + dma_addr_t CommandMailboxDMA; + DAC960_V2_CommandStatus_T CommandStatus; + + if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V2_PciDmaMask)) + return DAC960_Failure(Controller, "DMA mask out of range"); + + /* This is a temporary dma mapping, used only in the scope of this function */ + CommandMailbox = + (DAC960_V2_CommandMailbox_T *)pci_alloc_consistent( PCI_Device, + sizeof(DAC960_V2_CommandMailbox_T), &CommandMailboxDMA); + if (CommandMailbox == NULL) + return false; + + CommandMailboxesSize = DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T); + StatusMailboxesSize = DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T); + DmaPagesSize = + CommandMailboxesSize + StatusMailboxesSize + + sizeof(DAC960_V2_HealthStatusBuffer_T) + + sizeof(DAC960_V2_ControllerInfo_T) + + sizeof(DAC960_V2_LogicalDeviceInfo_T) + + sizeof(DAC960_V2_PhysicalDeviceInfo_T) + + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T) + + sizeof(DAC960_V2_Event_T) + + sizeof(DAC960_V2_PhysicalToLogicalDevice_T); + + if (!init_dma_loaf(PCI_Device, DmaPages, DmaPagesSize)) { + pci_free_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T), + CommandMailbox, CommandMailboxDMA); + return false; + } + + CommandMailboxesMemory = slice_dma_loaf(DmaPages, + CommandMailboxesSize, &CommandMailboxesMemoryDMA); + + /* These are the base addresses for the command memory mailbox array */ Controller->V2.FirstCommandMailbox = CommandMailboxesMemory; + Controller->V2.FirstCommandMailboxDMA = CommandMailboxesMemoryDMA; + CommandMailboxesMemory += DAC960_V2_CommandMailboxCount - 1; Controller->V2.LastCommandMailbox = CommandMailboxesMemory; Controller->V2.NextCommandMailbox = Controller->V2.FirstCommandMailbox; Controller->V2.PreviousCommandMailbox1 = Controller->V2.LastCommandMailbox; Controller->V2.PreviousCommandMailbox2 = - Controller->V2.LastCommandMailbox - 1; - StatusMailboxesMemory = - (DAC960_V2_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V2.LastCommandMailbox - 1; + + /* These are the base addresses for the status memory mailbox array */ + StatusMailboxesMemory = slice_dma_loaf(DmaPages, + StatusMailboxesSize, &StatusMailboxesMemoryDMA); + Controller->V2.FirstStatusMailbox = StatusMailboxesMemory; + Controller->V2.FirstStatusMailboxDMA = StatusMailboxesMemoryDMA; StatusMailboxesMemory += DAC960_V2_StatusMailboxCount - 1; Controller->V2.LastStatusMailbox = StatusMailboxesMemory; Controller->V2.NextStatusMailbox = Controller->V2.FirstStatusMailbox; - Controller->V2.HealthStatusBuffer = - (DAC960_V2_HealthStatusBuffer_T *) (StatusMailboxesMemory + 1); - /* Enable the Memory Mailbox Interface. */ - memset(&CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T)); - CommandMailbox.SetMemoryMailbox.CommandIdentifier = 1; - CommandMailbox.SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL; - CommandMailbox.SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true; - CommandMailbox.SetMemoryMailbox.FirstCommandMailboxSizeKB = + + Controller->V2.HealthStatusBuffer = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_HealthStatusBuffer_T), + &Controller->V2.HealthStatusBufferDMA); + + Controller->V2.NewControllerInformation = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_ControllerInfo_T), + &Controller->V2.NewControllerInformationDMA); + + Controller->V2.NewLogicalDeviceInformation = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_LogicalDeviceInfo_T), + &Controller->V2.NewLogicalDeviceInformationDMA); + + Controller->V2.NewPhysicalDeviceInformation = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_PhysicalDeviceInfo_T), + &Controller->V2.NewPhysicalDeviceInformationDMA); + + Controller->V2.NewInquiryUnitSerialNumber = slice_dma_loaf(DmaPages, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), + &Controller->V2.NewInquiryUnitSerialNumberDMA); + + Controller->V2.Event = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_Event_T), + &Controller->V2.EventDMA); + + Controller->V2.PhysicalToLogicalDevice = slice_dma_loaf(DmaPages, + sizeof(DAC960_V2_PhysicalToLogicalDevice_T), + &Controller->V2.PhysicalToLogicalDeviceDMA); + + /* + Enable the Memory Mailbox Interface. + + I don't know why we can't just use one of the memory mailboxes + we just allocated to do this, instead of using this temporary one. + Try this change later. + */ + memset(CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox->SetMemoryMailbox.CommandIdentifier = 1; + CommandMailbox->SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true; + CommandMailbox->SetMemoryMailbox.FirstCommandMailboxSizeKB = (DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T)) >> 10; - CommandMailbox.SetMemoryMailbox.FirstStatusMailboxSizeKB = + CommandMailbox->SetMemoryMailbox.FirstStatusMailboxSizeKB = (DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T)) >> 10; - CommandMailbox.SetMemoryMailbox.SecondCommandMailboxSizeKB = 0; - CommandMailbox.SetMemoryMailbox.SecondStatusMailboxSizeKB = 0; - CommandMailbox.SetMemoryMailbox.RequestSenseSize = 0; - CommandMailbox.SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox; - CommandMailbox.SetMemoryMailbox.HealthStatusBufferSizeKB = 1; - CommandMailbox.SetMemoryMailbox.HealthStatusBufferBusAddress = - Virtual_to_Bus64(Controller->V2.HealthStatusBuffer); - CommandMailbox.SetMemoryMailbox.FirstCommandMailboxBusAddress = - Virtual_to_Bus64(Controller->V2.FirstCommandMailbox); - CommandMailbox.SetMemoryMailbox.FirstStatusMailboxBusAddress = - Virtual_to_Bus64(Controller->V2.FirstStatusMailbox); + CommandMailbox->SetMemoryMailbox.SecondCommandMailboxSizeKB = 0; + CommandMailbox->SetMemoryMailbox.SecondStatusMailboxSizeKB = 0; + CommandMailbox->SetMemoryMailbox.RequestSenseSize = 0; + CommandMailbox->SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox; + CommandMailbox->SetMemoryMailbox.HealthStatusBufferSizeKB = 1; + CommandMailbox->SetMemoryMailbox.HealthStatusBufferBusAddress = + Controller->V2.HealthStatusBufferDMA; + CommandMailbox->SetMemoryMailbox.FirstCommandMailboxBusAddress = + Controller->V2.FirstCommandMailboxDMA; + CommandMailbox->SetMemoryMailbox.FirstStatusMailboxBusAddress = + Controller->V2.FirstStatusMailboxDMA; switch (Controller->HardwareType) { case DAC960_BA_Controller: while (DAC960_BA_HardwareMailboxFullP(ControllerBaseAddress)) udelay(1); - DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA); DAC960_BA_HardwareMailboxNewCommand(ControllerBaseAddress); while (!DAC960_BA_HardwareMailboxStatusAvailableP(ControllerBaseAddress)) udelay(1); @@ -1041,7 +1392,7 @@ case DAC960_LP_Controller: while (DAC960_LP_HardwareMailboxFullP(ControllerBaseAddress)) udelay(1); - DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA); DAC960_LP_HardwareMailboxNewCommand(ControllerBaseAddress); while (!DAC960_LP_HardwareMailboxStatusAvailableP(ControllerBaseAddress)) udelay(1); @@ -1050,8 +1401,12 @@ DAC960_LP_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); break; default: + DAC960_Failure(Controller, "Unknown Controller Type\n"); + CommandStatus = DAC960_V2_AbormalCompletion; break; } + pci_free_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T), + CommandMailbox, CommandMailboxDMA); return (CommandStatus == DAC960_V2_NormalCompletion); } @@ -1064,33 +1419,65 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T *Controller) { - DAC960_V1_Enquiry2_T Enquiry2; - DAC960_V1_Config2_T Config2; + DAC960_V1_Enquiry2_T *Enquiry2; + dma_addr_t Enquiry2DMA; + DAC960_V1_Config2_T *Config2; + dma_addr_t Config2DMA; int LogicalDriveNumber, Channel, TargetID; + struct dma_loaf local_dma; + + if (!init_dma_loaf(Controller->PCIDevice, &local_dma, + sizeof(DAC960_V1_Enquiry2_T) + sizeof(DAC960_V1_Config2_T))) + return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION"); + + Enquiry2 = slice_dma_loaf(&local_dma, sizeof(DAC960_V1_Enquiry2_T), &Enquiry2DMA); + Config2 = slice_dma_loaf(&local_dma, sizeof(DAC960_V1_Config2_T), &Config2DMA); + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry, - &Controller->V1.Enquiry)) + Controller->V1.NewEnquiryDMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "ENQUIRY"); - if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, &Enquiry2)) + } + memcpy(&Controller->V1.Enquiry, Controller->V1.NewEnquiry, + sizeof(DAC960_V1_Enquiry_T)); + + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, Enquiry2DMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "ENQUIRY2"); - if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, &Config2)) + } + + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, Config2DMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "READ CONFIG2"); + } + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_GetLogicalDriveInformation, - &Controller->V1.LogicalDriveInformation)) + Controller->V1.NewLogicalDriveInformationDMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION"); - for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++) - for (TargetID = 0; TargetID < Enquiry2.MaxTargets; TargetID++) + } + memcpy(&Controller->V1.LogicalDriveInformation, + Controller->V1.NewLogicalDriveInformation, + sizeof(DAC960_V1_LogicalDriveInformationArray_T)); + + for (Channel = 0; Channel < Enquiry2->ActualChannels; Channel++) + for (TargetID = 0; TargetID < Enquiry2->MaxTargets; TargetID++) { if (!DAC960_V1_ExecuteType3D(Controller, DAC960_V1_GetDeviceState, Channel, TargetID, - &Controller->V1.DeviceState - [Channel][TargetID])) - return DAC960_Failure(Controller, "GET DEVICE STATE"); + Controller->V1.NewDeviceStateDMA)) { + free_dma_loaf(Controller->PCIDevice, &local_dma); + return DAC960_Failure(Controller, "GET DEVICE STATE"); + } + memcpy(&Controller->V1.DeviceState[Channel][TargetID], + Controller->V1.NewDeviceState, sizeof(DAC960_V1_DeviceState_T)); + } /* Initialize the Controller Model Name and Full Model Name fields. */ - switch (Enquiry2.HardwareID.SubModel) + switch (Enquiry2->HardwareID.SubModel) { case DAC960_V1_P_PD_PU: - if (Enquiry2.SCSICapability.BusSpeed == DAC960_V1_Ultra) + if (Enquiry2->SCSICapability.BusSpeed == DAC960_V1_Ultra) strcpy(Controller->ModelName, "DAC960PU"); else strcpy(Controller->ModelName, "DAC960PD"); break; @@ -1122,6 +1509,7 @@ strcpy(Controller->ModelName, "DAC1164P"); break; default: + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "MODEL VERIFICATION"); } strcpy(Controller->FullModelName, "Mylex "); @@ -1135,18 +1523,18 @@ DAC960PU/PD/PL 3.51 and above DAC960PU/PD/PL/P 2.73 and above */ - if (Enquiry2.FirmwareID.MajorVersion == 0) + if (Enquiry2->FirmwareID.MajorVersion == 0) { - Enquiry2.FirmwareID.MajorVersion = + Enquiry2->FirmwareID.MajorVersion = Controller->V1.Enquiry.MajorFirmwareVersion; - Enquiry2.FirmwareID.MinorVersion = + Enquiry2->FirmwareID.MinorVersion = Controller->V1.Enquiry.MinorFirmwareVersion; - Enquiry2.FirmwareID.FirmwareType = '0'; - Enquiry2.FirmwareID.TurnID = 0; + Enquiry2->FirmwareID.FirmwareType = '0'; + Enquiry2->FirmwareID.TurnID = 0; } sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d", - Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion, - Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID); + Enquiry2->FirmwareID.MajorVersion, Enquiry2->FirmwareID.MinorVersion, + Enquiry2->FirmwareID.FirmwareType, Enquiry2->FirmwareID.TurnID); if (!((Controller->FirmwareVersion[0] == '5' && strcmp(Controller->FirmwareVersion, "5.06") >= 0) || (Controller->FirmwareVersion[0] == '4' && @@ -1159,17 +1547,18 @@ DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION"); DAC960_Error("Firmware Version = '%s'\n", Controller, Controller->FirmwareVersion); + free_dma_loaf(Controller->PCIDevice, &local_dma); return false; } /* Initialize the Controller Channels, Targets, Memory Size, and SAF-TE Enclosure Management Enabled fields. */ - Controller->Channels = Enquiry2.ActualChannels; - Controller->Targets = Enquiry2.MaxTargets; - Controller->MemorySize = Enquiry2.MemorySize >> 20; + Controller->Channels = Enquiry2->ActualChannels; + Controller->Targets = Enquiry2->MaxTargets; + Controller->MemorySize = Enquiry2->MemorySize >> 20; Controller->V1.SAFTE_EnclosureManagementEnabled = - (Enquiry2.FaultManagementType == DAC960_V1_SAFTE); + (Enquiry2->FaultManagementType == DAC960_V1_SAFTE); /* Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive Count, Maximum Blocks per Command, Controller Scatter/Gather Limit, and @@ -1183,8 +1572,8 @@ Controller->DriverQueueDepth = DAC960_MaxDriverQueueDepth; Controller->LogicalDriveCount = Controller->V1.Enquiry.NumberOfLogicalDrives; - Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand; - Controller->ControllerScatterGatherLimit = Enquiry2.MaxScatterGatherEntries; + Controller->MaxBlocksPerCommand = Enquiry2->MaxBlocksPerCommand; + Controller->ControllerScatterGatherLimit = Enquiry2->MaxScatterGatherEntries; Controller->DriverScatterGatherLimit = Controller->ControllerScatterGatherLimit; if (Controller->DriverScatterGatherLimit > DAC960_V1_ScatterGatherLimit) @@ -1192,11 +1581,11 @@ /* Initialize the Stripe Size, Segment Size, and Geometry Translation. */ - Controller->V1.StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor + Controller->V1.StripeSize = Config2->BlocksPerStripe * Config2->BlockFactor >> (10 - DAC960_BlockSizeBits); - Controller->V1.SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor + Controller->V1.SegmentSize = Config2->BlocksPerCacheLine * Config2->BlockFactor >> (10 - DAC960_BlockSizeBits); - switch (Config2.DriveGeometry) + switch (Config2->DriveGeometry) { case DAC960_V1_Geometry_128_32: Controller->V1.GeometryTranslationHeads = 128; @@ -1207,6 +1596,7 @@ Controller->V1.GeometryTranslationSectors = 63; break; default: + free_dma_loaf(Controller->PCIDevice, &local_dma); return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY"); } /* @@ -1220,8 +1610,11 @@ Controller->V1.BackgroundInitializationStatusSupported = true; DAC960_V1_ExecuteType3B(Controller, DAC960_V1_BackgroundInitializationControl, 0x20, - &Controller-> - V1.LastBackgroundInitializationStatus); + Controller-> + V1.BackgroundInitializationStatusDMA); + memcpy(&Controller->V1.LastBackgroundInitializationStatus, + Controller->V1.BackgroundInitializationStatus, + sizeof(DAC960_V1_BackgroundInitializationStatus_T)); } /* Initialize the Logical Drive Initially Accessible flag. @@ -1234,6 +1627,7 @@ DAC960_V1_LogicalDrive_Offline) Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true; Controller->V1.LastRebuildStatus = DAC960_V1_NoRebuildOrCheckInProgress; + free_dma_loaf(Controller->PCIDevice, &local_dma); return true; } @@ -1247,17 +1641,20 @@ *Controller) { DAC960_V2_ControllerInfo_T *ControllerInfo = - &Controller->V2.ControllerInformation; + &Controller->V2.ControllerInformation; unsigned short LogicalDeviceNumber = 0; int ModelNameLength; - if (!DAC960_V2_ControllerInfo(Controller, DAC960_V2_GetControllerInfo, - ControllerInfo, - sizeof(DAC960_V2_ControllerInfo_T))) + + /* Get data into dma-able area, then copy into permanant location */ + if (!DAC960_V2_NewControllerInfo(Controller)) return DAC960_Failure(Controller, "GET CONTROLLER INFO"); - if (!DAC960_V2_GeneralInfo(Controller, DAC960_V2_GetHealthStatus, - Controller->V2.HealthStatusBuffer, - sizeof(DAC960_V2_HealthStatusBuffer_T))) + memcpy(ControllerInfo, Controller->V2.NewControllerInformation, + sizeof(DAC960_V2_ControllerInfo_T)); + + + if (!DAC960_V2_GeneralInfo(Controller)) return DAC960_Failure(Controller, "GET HEALTH STATUS"); + /* Initialize the Controller Model Name and Full Model Name fields. */ @@ -1325,14 +1722,11 @@ while (true) { DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo = - &Controller->V2.NewLogicalDeviceInformation; + Controller->V2.NewLogicalDeviceInformation; DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo; DAC960_V2_PhysicalDevice_T PhysicalDevice; - if (!DAC960_V2_LogicalDeviceInfo(Controller, - DAC960_V2_GetLogicalDeviceInfoValid, - LogicalDeviceNumber, - NewLogicalDeviceInfo, - sizeof(DAC960_V2_LogicalDeviceInfo_T))) + + if (!DAC960_V2_NewLogicalDeviceInfo(Controller, LogicalDeviceNumber)) break; LogicalDeviceNumber = NewLogicalDeviceInfo->LogicalDeviceNumber; if (LogicalDeviceNumber > DAC960_MaxLogicalDrives) @@ -1421,26 +1815,61 @@ static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T *Controller) { - DAC960_V1_DCDB_T DCDBs[DAC960_V1_MaxChannels], *DCDB; - Completion_T Completions[DAC960_V1_MaxChannels], *Completion; + struct dma_loaf local_dma; + + dma_addr_t DCDBs_dma[DAC960_V1_MaxChannels]; + DAC960_V1_DCDB_T *DCDBs_cpu[DAC960_V1_MaxChannels]; + + dma_addr_t SCSI_Inquiry_dma[DAC960_V1_MaxChannels]; + DAC960_SCSI_Inquiry_T *SCSI_Inquiry_cpu[DAC960_V1_MaxChannels]; + + dma_addr_t SCSI_NewInquiryUnitSerialNumberDMA[DAC960_V1_MaxChannels]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *SCSI_NewInquiryUnitSerialNumberCPU[DAC960_V1_MaxChannels]; + + Completion_T Completions[DAC960_V1_MaxChannels]; unsigned long ProcessorFlags; int Channel, TargetID; + + if (!init_dma_loaf(Controller->PCIDevice, &local_dma, + DAC960_V1_MaxChannels*(sizeof(DAC960_V1_DCDB_T) + + sizeof(DAC960_SCSI_Inquiry_T) + + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)))) + return DAC960_Failure(Controller, + "DMA ALLOCATION FAILED IN ReadDeviceConfiguration"); + + for (Channel = 0; Channel < Controller->Channels; Channel++) { + DCDBs_cpu[Channel] = slice_dma_loaf(&local_dma, + sizeof(DAC960_V1_DCDB_T), DCDBs_dma + Channel); + SCSI_Inquiry_cpu[Channel] = slice_dma_loaf(&local_dma, + sizeof(DAC960_SCSI_Inquiry_T), + SCSI_Inquiry_dma + Channel); + SCSI_NewInquiryUnitSerialNumberCPU[Channel] = slice_dma_loaf(&local_dma, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), + SCSI_NewInquiryUnitSerialNumberDMA + Channel); + } + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { + /* + * For each channel, submit a probe for a device on that channel. + * The timeout interval for a device that is present is 10 seconds. + * With this approach, the timeout periods can elapse in parallel + * on each channel. + */ for (Channel = 0; Channel < Controller->Channels; Channel++) { + dma_addr_t NewInquiryStandardDataDMA = SCSI_Inquiry_dma[Channel]; + DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel]; + dma_addr_t DCDB_dma = DCDBs_dma[Channel]; DAC960_Command_T *Command = Controller->Commands[Channel]; - DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->V1.InquiryStandardData[Channel][TargetID]; - InquiryStandardData->PeripheralDeviceType = 0x1F; - Completion = &Completions[Channel]; + Completion_T *Completion = &Completions[Channel]; + init_completion(Completion); - DCDB = &DCDBs[Channel]; DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; Command->Completion = Completion; Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; - Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus32(DCDB); + Command->V1.CommandMailbox.Type3.BusAddress = DCDB_dma; DCDB->Channel = Channel; DCDB->TargetID = TargetID; DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; @@ -1449,7 +1878,7 @@ DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); - DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData); + DCDB->BusAddress = NewInquiryStandardDataDMA; DCDB->CDBLength = 6; DCDB->TransferLengthHigh4 = 0; DCDB->SenseLength = sizeof(DCDB->SenseData); @@ -1463,20 +1892,39 @@ DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); } + /* + * Wait for the problems submitted in the previous loop + * to complete. On the probes that are successful, + * get the serial number of the device that was found. + */ for (Channel = 0; Channel < Controller->Channels; Channel++) { - DAC960_Command_T *Command = Controller->Commands[Channel]; + DAC960_SCSI_Inquiry_T *InquiryStandardData = + &Controller->V1.InquiryStandardData[Channel][TargetID]; + DAC960_SCSI_Inquiry_T *NewInquiryStandardData = SCSI_Inquiry_cpu[Channel]; + dma_addr_t NewInquiryUnitSerialNumberDMA = + SCSI_NewInquiryUnitSerialNumberDMA[Channel]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber = + SCSI_NewInquiryUnitSerialNumberCPU[Channel]; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID]; - InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; - Completion = &Completions[Channel]; + DAC960_Command_T *Command = Controller->Commands[Channel]; + DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel]; + Completion_T *Completion = &Completions[Channel]; + wait_for_completion(Completion); - if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) + + if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) { + memset(InquiryStandardData, 0, sizeof(DAC960_SCSI_Inquiry_T)); + InquiryStandardData->PeripheralDeviceType = 0x1F; continue; + } else + memcpy(InquiryStandardData, NewInquiryStandardData, sizeof(DAC960_SCSI_Inquiry_T)); + + /* Preserve Channel and TargetID values from the previous loop */ Command->Completion = Completion; - DCDB = &DCDBs[Channel]; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber); + DCDB->BusAddress = NewInquiryUnitSerialNumberDMA; DCDB->SenseLength = sizeof(DCDB->SenseData); DCDB->CDB[0] = 0x12; /* INQUIRY */ DCDB->CDB[1] = 1; /* EVPD = 1 */ @@ -1488,8 +1936,17 @@ DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); wait_for_completion(Completion); + + if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) { + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + } else + memcpy(InquiryUnitSerialNumber, NewInquiryUnitSerialNumber, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); } } + free_dma_loaf(Controller->PCIDevice, &local_dma); return true; } @@ -1506,74 +1963,55 @@ { unsigned char Channel = 0, TargetID = 0, LogicalUnit = 0; unsigned short PhysicalDeviceIndex = 0; + while (true) { DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo = - &Controller->V2.NewPhysicalDeviceInformation; + Controller->V2.NewPhysicalDeviceInformation; DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber = + Controller->V2.NewInquiryUnitSerialNumber; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber; - DAC960_Command_T *Command; - DAC960_V2_CommandMailbox_T *CommandMailbox; - if (!DAC960_V2_PhysicalDeviceInfo(Controller, - DAC960_V2_GetPhysicalDeviceInfoValid, - Channel, - TargetID, - LogicalUnit, - NewPhysicalDeviceInfo, - sizeof(DAC960_V2_PhysicalDeviceInfo_T))) + + if (!DAC960_V2_NewPhysicalDeviceInfo(Controller, Channel, TargetID, LogicalUnit)) break; - Channel = NewPhysicalDeviceInfo->Channel; - TargetID = NewPhysicalDeviceInfo->TargetID; - LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit; + PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) - kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); + kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); if (PhysicalDeviceInfo == NULL) - return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION"); + return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION"); Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] = - PhysicalDeviceInfo; + PhysicalDeviceInfo; memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo, - sizeof(DAC960_V2_PhysicalDeviceInfo_T)); + sizeof(DAC960_V2_PhysicalDeviceInfo_T)); + InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); - if (InquiryUnitSerialNumber == NULL) + if (InquiryUnitSerialNumber == NULL) { + kfree(PhysicalDeviceInfo); return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION"); + } Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex] = - InquiryUnitSerialNumber; - memset(InquiryUnitSerialNumber, 0, - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); - InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; - Command = DAC960_AllocateCommand(Controller); - CommandMailbox = &Command->V2.CommandMailbox; - DAC960_V2_ClearCommand(Command); - Command->CommandType = DAC960_ImmediateCommand; - CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru; - CommandMailbox->SCSI_10.CommandControlBits - .DataTransferControllerToHost = true; - CommandMailbox->SCSI_10.CommandControlBits - .NoAutoRequestSense = true; - CommandMailbox->SCSI_10.DataTransferSize = - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit; - CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID; - CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel; - CommandMailbox->SCSI_10.CDBLength = 6; - CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ - CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ - CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ - CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ - CommandMailbox->SCSI_10.SCSI_CDB[4] = - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(InquiryUnitSerialNumber); - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentByteCount = - CommandMailbox->SCSI_10.DataTransferSize; - DAC960_ExecuteCommand(Command); - DAC960_DeallocateCommand(Command); + InquiryUnitSerialNumber; + + Channel = NewPhysicalDeviceInfo->Channel; + TargetID = NewPhysicalDeviceInfo->TargetID; + LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit; + + /* + Some devices do NOT have Unit Serial Numbers. + This command fails for them. But, we still want to + remember those devices are there. Construct a + UnitSerialNumber structure for the failure case. + */ + if (!DAC960_V2_NewInquiryUnitSerialNumber(Controller, Channel, TargetID, LogicalUnit)) { + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + } else + memcpy(InquiryUnitSerialNumber, NewInquiryUnitSerialNumber, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + PhysicalDeviceIndex++; LogicalUnit++; } @@ -1947,12 +2385,12 @@ Initialize the I/O Request Queue. */ RequestQueue = &Controller->RequestQueue; - Controller->queue_lock = SPIN_LOCK_UNLOCKED; blk_init_queue(RequestQueue, DAC960_RequestFunction, &Controller->queue_lock); RequestQueue->queuedata = Controller; blk_queue_max_hw_segments(RequestQueue, Controller->DriverScatterGatherLimit); - blk_queue_max_phys_segments(RequestQueue, ~0); + blk_queue_max_phys_segments(RequestQueue, + Controller->DriverScatterGatherLimit); blk_queue_max_sectors(RequestQueue, Controller->MaxBlocksPerCommand); for (n = 0; n < DAC960_MaxLogicalDrives; n++) { @@ -1978,8 +2416,10 @@ { int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber; int disk; + for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) del_gendisk(Controller->disks[disk]); + /* Unregister the Block Device Major Number for this DAC960 Controller. */ @@ -2082,159 +2522,155 @@ /* - DAC960_DetectControllers detects Mylex DAC960/AcceleRAID/eXtremeRAID + * DAC960_DetectCleanup releases the resources that were allocated + * during DAC960_DetectController(). DAC960_DetectController can + * has several internal failure points, so not ALL resources may + * have been allocated. It's important to free only + * resources that HAVE been allocated. The code below always + * tests that the resource has been allocated before attempting to + * free it. + */ +static void DAC960_DetectCleanup(DAC960_Controller_T *Controller) +{ + int i; + + /* Free the memory mailbox, status, and related structures */ + free_dma_loaf(Controller->PCIDevice, &Controller->DmaPages); + if (Controller->MemoryMappedAddress) { + switch(Controller->HardwareType) + { + case DAC960_BA_Controller: + DAC960_BA_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_LP_Controller: + DAC960_LP_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_LA_Controller: + DAC960_LA_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_PG_Controller: + DAC960_PG_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_PD_Controller: + DAC960_PD_DisableInterrupts(Controller->BaseAddress); + break; + case DAC960_P_Controller: + DAC960_PD_DisableInterrupts(Controller->BaseAddress); + break; + } + iounmap(Controller->MemoryMappedAddress); + } + if (Controller->IRQ_Channel) + free_irq(Controller->IRQ_Channel, Controller); + if (Controller->IO_Address) + release_region(Controller->IO_Address, 0x80); + pci_disable_device(Controller->PCIDevice); + for (i = 0; (i < DAC960_MaxLogicalDrives) && Controller->disks[i]; i++) + put_disk(Controller->disks[i]); + DAC960_Controllers[Controller->ControllerNumber] = NULL; + kfree(Controller); +} + + +/* + DAC960_DetectController detects Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers by interrogating the PCI Configuration Space for Controller Type. */ -static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType) -{ - void (*InterruptHandler)(int, void *, Registers_T *) = NULL; +static DAC960_Controller_T * +DAC960_DetectController(PCI_Device_T *PCI_Device, + const struct pci_device_id *entry) +{ + struct DAC960_privdata *privdata = (struct DAC960_privdata *)entry->driver_data; + void (*InterruptHandler)(int, void *, Registers_T *) = privdata->InterruptHandler; + unsigned int MemoryWindowSize = privdata->MemoryWindowSize; DAC960_Controller_T *Controller = NULL; - DAC960_FirmwareType_T FirmwareType = 0; - unsigned short VendorID = 0, DeviceID = 0; - unsigned int MemoryWindowSize = 0; - PCI_Device_T *PCI_Device = NULL; + unsigned char DeviceFunction = PCI_Device->devfn; + unsigned char ErrorStatus, Parameter0, Parameter1; + unsigned int IRQ_Channel = PCI_Device->irq; + void *BaseAddress; int i; - switch (HardwareType) - { - case DAC960_BA_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_BA; - FirmwareType = DAC960_V2_Controller; - InterruptHandler = DAC960_BA_InterruptHandler; - MemoryWindowSize = DAC960_BA_RegisterWindowSize; - break; - case DAC960_LP_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_LP; - FirmwareType = DAC960_LP_Controller; - InterruptHandler = DAC960_LP_InterruptHandler; - MemoryWindowSize = DAC960_LP_RegisterWindowSize; - break; - case DAC960_LA_Controller: - VendorID = PCI_VENDOR_ID_DEC; - DeviceID = PCI_DEVICE_ID_DEC_21285; - FirmwareType = DAC960_V1_Controller; - InterruptHandler = DAC960_LA_InterruptHandler; - MemoryWindowSize = DAC960_LA_RegisterWindowSize; - break; - case DAC960_PG_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PG; - FirmwareType = DAC960_V1_Controller; - InterruptHandler = DAC960_PG_InterruptHandler; - MemoryWindowSize = DAC960_PG_RegisterWindowSize; - break; - case DAC960_PD_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PD; - FirmwareType = DAC960_V1_Controller; - InterruptHandler = DAC960_PD_InterruptHandler; - MemoryWindowSize = DAC960_PD_RegisterWindowSize; - break; - case DAC960_P_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_P; - FirmwareType = DAC960_V1_Controller; - InterruptHandler = DAC960_P_InterruptHandler; - MemoryWindowSize = DAC960_PD_RegisterWindowSize; - break; - } - while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL) - { - DAC960_IO_Address_T IO_Address = 0; - DAC960_PCI_Address_T PCI_Address = 0; - unsigned char Bus = PCI_Device->bus->number; - unsigned char DeviceFunction = PCI_Device->devfn; - unsigned char Device = DeviceFunction >> 3; - unsigned char Function = DeviceFunction & 0x7; - unsigned char ErrorStatus, Parameter0, Parameter1; - unsigned int IRQ_Channel = PCI_Device->irq; - void *BaseAddress; - Controller = NULL; - if (pci_enable_device(PCI_Device) != 0) continue; - switch (HardwareType) - { + + Controller = (DAC960_Controller_T *) + kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); + if (Controller == NULL) { + DAC960_Error("Unable to allocate Controller structure for " + "Controller at\n", NULL); + return NULL; + } + memset(Controller, 0, sizeof(DAC960_Controller_T)); + Controller->ControllerNumber = DAC960_ControllerCount; + DAC960_Controllers[DAC960_ControllerCount++] = Controller; + Controller->Bus = PCI_Device->bus->number; + Controller->FirmwareType = privdata->FirmwareType; + Controller->HardwareType = privdata->HardwareType; + Controller->Device = DeviceFunction >> 3; + Controller->Function = DeviceFunction & 0x7; + Controller->PCIDevice = PCI_Device; + strcpy(Controller->FullModelName, "DAC960"); + + if (pci_enable_device(PCI_Device)) { + kfree(Controller); + goto Failure; + } + + switch (Controller->HardwareType) + { case DAC960_BA_Controller: - PCI_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 0); break; case DAC960_LP_Controller: - PCI_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 0); break; case DAC960_LA_Controller: - if (!(PCI_Device->subsystem_vendor == PCI_VENDOR_ID_MYLEX && - PCI_Device->subsystem_device == PCI_DEVICE_ID_MYLEX_DAC960_LA)) - continue; - PCI_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 0); break; case DAC960_PG_Controller: - PCI_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 0); break; case DAC960_PD_Controller: - IO_Address = pci_resource_start(PCI_Device, 0); - PCI_Address = pci_resource_start(PCI_Device, 1); + Controller->IO_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 1); break; case DAC960_P_Controller: - IO_Address = pci_resource_start(PCI_Device, 0); - PCI_Address = pci_resource_start(PCI_Device, 1); + Controller->IO_Address = pci_resource_start(PCI_Device, 0); + Controller->PCI_Address = pci_resource_start(PCI_Device, 1); break; - } - if (DAC960_ControllerCount == DAC960_MaxControllers) - { - DAC960_Error("More than %d DAC960 Controllers detected - " - "ignoring from Controller at\n", - NULL, DAC960_MaxControllers); - goto Failure; - } - Controller = (DAC960_Controller_T *) - kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); - if (Controller == NULL) - { - DAC960_Error("Unable to allocate Controller structure for " - "Controller at\n", NULL); - goto Failure; - } - memset(Controller, 0, sizeof(DAC960_Controller_T)); - for (i = 0; i < DAC960_MaxLogicalDrives; i++) { - Controller->disks[i] = alloc_disk(1<disks[i]) - goto Enomem; - Controller->disks[i]->private_data = (void*)i; - Controller->disks[i]->queue = &Controller->RequestQueue; - } - Controller->ControllerNumber = DAC960_ControllerCount; - init_waitqueue_head(&Controller->CommandWaitQueue); - init_waitqueue_head(&Controller->HealthStatusWaitQueue); - DAC960_Controllers[DAC960_ControllerCount++] = Controller; - DAC960_AnnounceDriver(Controller); - Controller->FirmwareType = FirmwareType; - Controller->HardwareType = HardwareType; - Controller->IO_Address = IO_Address; - Controller->PCI_Address = PCI_Address; - Controller->Bus = Bus; - Controller->Device = Device; - Controller->Function = Function; - /* - Map the Controller Register Window. - */ - if (MemoryWindowSize < PAGE_SIZE) + } + + pci_set_drvdata(PCI_Device, (void *)((int)Controller->ControllerNumber)); + for (i = 0; i < DAC960_MaxLogicalDrives; i++) { + Controller->disks[i] = alloc_disk(1<disks[i]) + goto Failure; + Controller->disks[i]->private_data = (void *)i; + Controller->disks[i]->queue = &Controller->RequestQueue; + } + init_waitqueue_head(&Controller->CommandWaitQueue); + init_waitqueue_head(&Controller->HealthStatusWaitQueue); + Controller->queue_lock = SPIN_LOCK_UNLOCKED; + DAC960_AnnounceDriver(Controller); + /* + Map the Controller Register Window. + */ + if (MemoryWindowSize < PAGE_SIZE) MemoryWindowSize = PAGE_SIZE; - Controller->MemoryMappedAddress = - ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize); - Controller->BaseAddress = - Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK); - if (Controller->MemoryMappedAddress == NULL) - { + Controller->MemoryMappedAddress = + ioremap_nocache(Controller->PCI_Address & PAGE_MASK, MemoryWindowSize); + Controller->BaseAddress = + Controller->MemoryMappedAddress + (Controller->PCI_Address & ~PAGE_MASK); + if (Controller->MemoryMappedAddress == NULL) + { DAC960_Error("Unable to map Controller Register Window for " "Controller at\n", Controller); goto Failure; - } - BaseAddress = Controller->BaseAddress; - switch (HardwareType) - { + } + BaseAddress = Controller->BaseAddress; + switch (Controller->HardwareType) + { case DAC960_BA_Controller: - DAC960_BA_DisableInterrupts(Controller->BaseAddress); + DAC960_BA_DisableInterrupts(BaseAddress); DAC960_BA_AcknowledgeHardwareMailboxStatus(BaseAddress); udelay(1000); while (DAC960_BA_InitializationInProgressP(BaseAddress)) @@ -2252,7 +2688,7 @@ "for Controller at\n", Controller); goto Failure; } - DAC960_BA_EnableInterrupts(Controller->BaseAddress); + DAC960_BA_EnableInterrupts(BaseAddress); Controller->QueueCommand = DAC960_BA_QueueCommand; Controller->ReadControllerConfiguration = DAC960_V2_ReadControllerConfiguration; @@ -2264,7 +2700,7 @@ DAC960_V2_QueueReadWriteCommand; break; case DAC960_LP_Controller: - DAC960_LP_DisableInterrupts(Controller->BaseAddress); + DAC960_LP_DisableInterrupts(BaseAddress); DAC960_LP_AcknowledgeHardwareMailboxStatus(BaseAddress); udelay(1000); while (DAC960_LP_InitializationInProgressP(BaseAddress)) @@ -2282,7 +2718,7 @@ "for Controller at\n", Controller); goto Failure; } - DAC960_LP_EnableInterrupts(Controller->BaseAddress); + DAC960_LP_EnableInterrupts(BaseAddress); Controller->QueueCommand = DAC960_LP_QueueCommand; Controller->ReadControllerConfiguration = DAC960_V2_ReadControllerConfiguration; @@ -2294,7 +2730,7 @@ DAC960_V2_QueueReadWriteCommand; break; case DAC960_LA_Controller: - DAC960_LA_DisableInterrupts(Controller->BaseAddress); + DAC960_LA_DisableInterrupts(BaseAddress); DAC960_LA_AcknowledgeHardwareMailboxStatus(BaseAddress); udelay(1000); while (DAC960_LA_InitializationInProgressP(BaseAddress)) @@ -2312,7 +2748,7 @@ "for Controller at\n", Controller); goto Failure; } - DAC960_LA_EnableInterrupts(Controller->BaseAddress); + DAC960_LA_EnableInterrupts(BaseAddress); if (Controller->V1.DualModeMemoryMailboxInterface) Controller->QueueCommand = DAC960_LA_QueueCommandDualMode; else Controller->QueueCommand = DAC960_LA_QueueCommandSingleMode; @@ -2326,7 +2762,7 @@ DAC960_V1_QueueReadWriteCommand; break; case DAC960_PG_Controller: - DAC960_PG_DisableInterrupts(Controller->BaseAddress); + DAC960_PG_DisableInterrupts(BaseAddress); DAC960_PG_AcknowledgeHardwareMailboxStatus(BaseAddress); udelay(1000); while (DAC960_PG_InitializationInProgressP(BaseAddress)) @@ -2344,7 +2780,7 @@ "for Controller at\n", Controller); goto Failure; } - DAC960_PG_EnableInterrupts(Controller->BaseAddress); + DAC960_PG_EnableInterrupts(BaseAddress); if (Controller->V1.DualModeMemoryMailboxInterface) Controller->QueueCommand = DAC960_PG_QueueCommandDualMode; else Controller->QueueCommand = DAC960_PG_QueueCommandSingleMode; @@ -2373,10 +2809,16 @@ &Parameter0, &Parameter1) && DAC960_ReportErrorStatus(Controller, ErrorStatus, Parameter0, Parameter1)) - goto Failure1; + goto Failure; udelay(10); } - DAC960_PD_EnableInterrupts(Controller->BaseAddress); + if (!DAC960_V1_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to allocate DMA mapped memory " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_PD_EnableInterrupts(BaseAddress); Controller->QueueCommand = DAC960_PD_QueueCommand; Controller->ReadControllerConfiguration = DAC960_V1_ReadControllerConfiguration; @@ -2403,10 +2845,16 @@ &Parameter0, &Parameter1) && DAC960_ReportErrorStatus(Controller, ErrorStatus, Parameter0, Parameter1)) - goto Failure1; + goto Failure; udelay(10); } - DAC960_PD_EnableInterrupts(Controller->BaseAddress); + if (!DAC960_V1_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to allocate DMA mapped memory" + "for Controller at\n", Controller); + goto Failure; + } + DAC960_PD_EnableInterrupts(BaseAddress); Controller->QueueCommand = DAC960_P_QueueCommand; Controller->ReadControllerConfiguration = DAC960_V1_ReadControllerConfiguration; @@ -2417,107 +2865,47 @@ Controller->QueueReadWriteCommand = DAC960_V1_QueueReadWriteCommand; break; - } - /* - Acquire shared access to the IRQ Channel. - */ - if (IRQ_Channel == 0) - { - DAC960_Error("IRQ Channel %d illegal for Controller at\n", - Controller, IRQ_Channel); - goto Failure1; - } - strcpy(Controller->FullModelName, "DAC960"); - if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ, + } + /* + Acquire shared access to the IRQ Channel. + */ + if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ, Controller->FullModelName, Controller) < 0) - { - DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", - Controller, IRQ_Channel); - goto Failure1; - } - Controller->IRQ_Channel = IRQ_Channel; - DAC960_ActiveControllerCount++; - Controller->InitialCommand.CommandIdentifier = 1; - Controller->InitialCommand.Controller = Controller; - Controller->Commands[0] = &Controller->InitialCommand; - Controller->FreeCommands = &Controller->InitialCommand; - Controller->ControllerDetectionSuccessful = true; - continue; - Failure1: - if (Controller->IO_Address) release_region(Controller->IO_Address, 0x80); - Failure: - if (IO_Address == 0) + { + DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", + Controller, Controller->IRQ_Channel); + goto Failure; + } + Controller->IRQ_Channel = IRQ_Channel; + Controller->InitialCommand.CommandIdentifier = 1; + Controller->InitialCommand.Controller = Controller; + Controller->Commands[0] = &Controller->InitialCommand; + Controller->FreeCommands = &Controller->InitialCommand; + return Controller; + +Failure: + if (Controller->IO_Address == 0) DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " "PCI Address 0x%X\n", Controller, - Bus, Device, Function, PCI_Address); - else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " + Controller->Bus, Controller->Device, + Controller->Function, Controller->PCI_Address); + else + DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " "0x%X PCI Address 0x%X\n", Controller, - Bus, Device, Function, IO_Address, PCI_Address); - if (Controller == NULL) break; - if (Controller->MemoryMappedAddress != NULL) - iounmap(Controller->MemoryMappedAddress); - if (Controller->IRQ_Channel > 0) - free_irq(IRQ_Channel, Controller); - } - return; -Enomem: - while (i--) - put_disk(Controller->disks[i]); - kfree(Controller); - goto Failure; -} - - -/* - DAC960_SortControllers sorts the Controllers by PCI Bus and Device Number. -*/ - -static void DAC960_SortControllers(void) -{ - int ControllerNumber, LastInterchange, Bound, j; - LastInterchange = DAC960_ControllerCount-1; - while (LastInterchange > 0) - { - Bound = LastInterchange; - LastInterchange = 0; - for (j = 0; j < Bound; j++) - { - DAC960_Controller_T *Controller1 = DAC960_Controllers[j]; - DAC960_Controller_T *Controller2 = DAC960_Controllers[j+1]; - if (Controller1->Bus > Controller2->Bus || - (Controller1->Bus == Controller2->Bus && - (Controller1->Device > Controller2->Device))) - { - Controller2->ControllerNumber = j; - DAC960_Controllers[j] = Controller2; - Controller1->ControllerNumber = j+1; - DAC960_Controllers[j+1] = Controller1; - LastInterchange = j; - } - } - } - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - if (!Controller->ControllerDetectionSuccessful) - { - int i; - DAC960_Controllers[ControllerNumber] = NULL; - for (i = 0; i < DAC960_MaxLogicalDrives; i++) - put_disk(Controller->disks[i]); - kfree(Controller); - } - } + Controller->Bus, Controller->Device, + Controller->Function, Controller->IO_Address, + Controller->PCI_Address); + DAC960_DetectCleanup(Controller); + DAC960_ControllerCount--; + return NULL; } - /* DAC960_InitializeController initializes Controller. */ -static void DAC960_InitializeController(DAC960_Controller_T *Controller) +static boolean +DAC960_InitializeController(DAC960_Controller_T *Controller) { if (DAC960_ReadControllerConfiguration(Controller) && DAC960_ReportControllerConfiguration(Controller) && @@ -2536,8 +2924,9 @@ Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction; add_timer(&Controller->MonitoringTimer); Controller->ControllerInitialized = true; + return true; } - else DAC960_FinalizeController(Controller); + return false; } @@ -2547,35 +2936,38 @@ static void DAC960_FinalizeController(DAC960_Controller_T *Controller) { - int i; if (Controller->ControllerInitialized) { - del_timer(&Controller->MonitoringTimer); + unsigned long ProcessorFlags; + + /* + * Acquiring and releasing lock here eliminates + * a very low probability race. + * + * The code below allocates controller command structures + * from the free list without holding the controller lock. + * This is safe assuming there is no other activity on + * the controller at the time. + * + * But, there might be a monitoring command still + * in progress. Setting the Shutdown flag while holding + * the lock ensures that there is no monitoring command + * in the interrupt handler currently, and any monitoring + * commands that complete from this time on will NOT return + * their command structure to the free list. + */ + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + Controller->ShutdownMonitoringTimer = 1; + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + del_timer_sync(&Controller->MonitoringTimer); if (Controller->FirmwareType == DAC960_V1_Controller) { DAC960_Notice("Flushing Cache...", Controller); - DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, NULL); + DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, 0); DAC960_Notice("done\n", Controller); - switch (Controller->HardwareType) - { - case DAC960_LA_Controller: - if (Controller->V1.DualModeMemoryMailboxInterface) - free_pages(Controller->MemoryMailboxPagesAddress, - Controller->MemoryMailboxPagesOrder); - else DAC960_LA_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_PG_Controller: - if (Controller->V1.DualModeMemoryMailboxInterface) - free_pages(Controller->MemoryMailboxPagesAddress, - Controller->MemoryMailboxPagesOrder); - else DAC960_PG_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_PD_Controller: + + if (Controller->HardwareType == DAC960_PD_Controller) release_region(Controller->IO_Address, 0x80); - break; - default: - break; - } } else { @@ -2583,51 +2975,48 @@ DAC960_V2_DeviceOperation(Controller, DAC960_V2_PauseDevice, DAC960_V2_RAID_Controller); DAC960_Notice("done\n", Controller); - free_pages(Controller->MemoryMailboxPagesAddress, - Controller->MemoryMailboxPagesOrder); } } - free_irq(Controller->IRQ_Channel, Controller); - iounmap(Controller->MemoryMappedAddress); DAC960_UnregisterBlockDevice(Controller); DAC960_DestroyAuxiliaryStructures(Controller); - DAC960_Controllers[Controller->ControllerNumber] = NULL; - for (i = 0; i < DAC960_MaxLogicalDrives; i++) - put_disk(Controller->disks[i]); - kfree(Controller); + DAC960_DestroyProcEntries(Controller); + DAC960_DetectCleanup(Controller); } /* - DAC960_Initialize initializes the DAC960 Driver. + DAC960_Probe verifies controller's existence and + initializes the DAC960 Driver for that controller. */ -static int DAC960_Initialize(void) +static int +DAC960_Probe(struct pci_dev *dev, const struct pci_device_id *entry) { - int ControllerNumber; - DAC960_DetectControllers(DAC960_BA_Controller); - DAC960_DetectControllers(DAC960_LP_Controller); - DAC960_DetectControllers(DAC960_LA_Controller); - DAC960_DetectControllers(DAC960_PG_Controller); - DAC960_DetectControllers(DAC960_PD_Controller); - DAC960_DetectControllers(DAC960_P_Controller); - DAC960_SortControllers(); - if (DAC960_ActiveControllerCount == 0) return -ENODEV; - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - int disk; - if (Controller == NULL) continue; - DAC960_InitializeController(Controller); - for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) { - set_capacity(Controller->disks[disk], disk_size(Controller, disk)); - add_disk(Controller->disks[disk]); - } - } - DAC960_CreateProcEntries(); - register_reboot_notifier(&DAC960_NotifierBlock); + int disk; + DAC960_Controller_T *Controller; + + if (DAC960_ControllerCount == DAC960_MaxControllers) + { + DAC960_Error("More than %d DAC960 Controllers detected - " + "ignoring from Controller at\n", + NULL, DAC960_MaxControllers); + return -ENODEV; + } + + Controller = DAC960_DetectController(dev, entry); + if (!Controller) + return -ENODEV; + + if (!DAC960_InitializeController(Controller)) { + DAC960_FinalizeController(Controller); + return -ENODEV; + } + + for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) { + set_capacity(Controller->disks[disk], disk_size(Controller, disk)); + add_disk(Controller->disks[disk]); + } + DAC960_CreateProcEntries(Controller); return 0; } @@ -2636,32 +3025,12 @@ DAC960_Finalize finalizes the DAC960 Driver. */ -static void DAC960_Finalize(void) -{ - int ControllerNumber; - if (DAC960_ActiveControllerCount == 0) return; - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - if (DAC960_Controllers[ControllerNumber] != NULL) - DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]); - DAC960_DestroyProcEntries(); - unregister_reboot_notifier(&DAC960_NotifierBlock); -} - - -/* - DAC960_Notifier is the notifier for the DAC960 Driver. -*/ - -static int DAC960_Notifier(NotifierBlock_T *NotifierBlock, - unsigned long Event, - void *Buffer) +static void DAC960_Remove(PCI_Device_T *PCI_Device) { - if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF)) - return NOTIFY_DONE; - DAC960_Finalize(); - return NOTIFY_OK; + int Controller_Number = (int)pci_get_drvdata(PCI_Device); + DAC960_Controller_T *Controller = DAC960_Controllers[Controller_Number]; + if (Controller != NULL) + DAC960_FinalizeController(Controller); } @@ -2674,57 +3043,60 @@ { DAC960_Controller_T *Controller = Command->Controller; DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_ScatterGatherSegment_T *ScatterGatherList = + Command->V1.ScatterGatherList; + struct scatterlist *ScatterList = Command->V1.ScatterList; + int DmaDirection, SegCount; + DAC960_V1_ClearCommand(Command); - if (Command->SegmentCount == 1) + + if (Command->CommandType == DAC960_ReadCommand) + DmaDirection = PCI_DMA_FROMDEVICE; + else + DmaDirection = PCI_DMA_TODEVICE; + + SegCount = blk_rq_map_sg(&Controller->RequestQueue, Command->Request, + ScatterList); + /* pci_map_sg MAY change the value of SegCount */ + SegCount = pci_map_sg(Command->PciDevice, ScatterList, SegCount, + DmaDirection); + Command->SegmentCount = SegCount; + + if (SegCount == 1) { if (Command->CommandType == DAC960_ReadCommand) CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read; - else CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; + else + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; + CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; CommandMailbox->Type5.BusAddress = - Virtual_to_Bus32(Command->RequestBuffer); + (DAC960_BusAddress32_T)sg_dma_address(ScatterList); } else { - DAC960_V1_ScatterGatherSegment_T - *ScatterGatherList = Command->V1.ScatterGatherList; - BufferHeader_T *BufferHeader = Command->BufferHeader; - char *LastDataEndPointer = NULL; - int SegmentNumber = 0; + int i; + if (Command->CommandType == DAC960_ReadCommand) CommandMailbox->Type5.CommandOpcode = DAC960_V1_ReadWithScatterGather; else CommandMailbox->Type5.CommandOpcode = DAC960_V1_WriteWithScatterGather; + CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; - CommandMailbox->Type5.BusAddress = Virtual_to_Bus32(ScatterGatherList); - CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount; - while (BufferHeader != NULL) - { - if (bio_data(BufferHeader) == LastDataEndPointer) - { - ScatterGatherList[SegmentNumber-1].SegmentByteCount += - BufferHeader->bi_size; - LastDataEndPointer += BufferHeader->bi_size; - } - else - { - ScatterGatherList[SegmentNumber].SegmentDataPointer = - Virtual_to_Bus32(bio_data(BufferHeader)); - ScatterGatherList[SegmentNumber].SegmentByteCount = - BufferHeader->bi_size; - LastDataEndPointer = bio_data(BufferHeader) + - BufferHeader->bi_size; - if (SegmentNumber++ > Controller->DriverScatterGatherLimit) - panic("DAC960: Scatter/Gather Segment Overflow\n"); - } - BufferHeader = BufferHeader->bi_next; - } - if (SegmentNumber != Command->SegmentCount) - panic("DAC960: SegmentNumber != SegmentCount\n"); + CommandMailbox->Type5.BusAddress = Command->V1.ScatterGatherListDMA; + + CommandMailbox->Type5.ScatterGatherCount = SegCount; + + for (i = 0; i < SegCount; i++, ScatterList++, ScatterGatherList++) { + ScatterGatherList->SegmentDataPointer = + (DAC960_BusAddress32_T)sg_dma_address(ScatterList); + ScatterGatherList->SegmentByteCount = + (DAC960_ByteCount32_T)sg_dma_len(ScatterList); + } } DAC960_QueueCommand(Command); } @@ -2739,18 +3111,32 @@ { DAC960_Controller_T *Controller = Command->Controller; DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + struct scatterlist *ScatterList = Command->V2.ScatterList; + int DmaDirection, SegCount; + DAC960_V2_ClearCommand(Command); + + if (Command->CommandType == DAC960_ReadCommand) + DmaDirection = PCI_DMA_FROMDEVICE; + else + DmaDirection = PCI_DMA_TODEVICE; + + SegCount = blk_rq_map_sg(&Controller->RequestQueue, Command->Request, + ScatterList); + /* pci_map_sg MAY change the value of SegCount */ + SegCount = pci_map_sg(Command->PciDevice, ScatterList, SegCount, + DmaDirection); + Command->SegmentCount = SegCount; + CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10; CommandMailbox->SCSI_10.CommandControlBits.DataTransferControllerToHost = (Command->CommandType == DAC960_ReadCommand); CommandMailbox->SCSI_10.DataTransferSize = Command->BlockCount << DAC960_BlockSizeBits; - CommandMailbox->SCSI_10.RequestSenseBusAddress = - Virtual_to_Bus64(&Command->V2.RequestSense); + CommandMailbox->SCSI_10.RequestSenseBusAddress = Command->V2.RequestSenseDMA; CommandMailbox->SCSI_10.PhysicalDevice = Controller->V2.LogicalDriveToVirtualDevice[Command->LogicalDriveNumber]; - CommandMailbox->SCSI_10.RequestSenseSize = - sizeof(DAC960_SCSI_RequestSense_T); + CommandMailbox->SCSI_10.RequestSenseSize = sizeof(DAC960_SCSI_RequestSense_T); CommandMailbox->SCSI_10.CDBLength = 10; CommandMailbox->SCSI_10.SCSI_CDB[0] = (Command->CommandType == DAC960_ReadCommand ? 0x28 : 0x2A); @@ -2760,12 +3146,13 @@ CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber; CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; - if (Command->SegmentCount == 1) + + if (SegCount == 1) { CommandMailbox->SCSI_10.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(Command->RequestBuffer); + (DAC960_BusAddress64_T)sg_dma_address(ScatterList); CommandMailbox->SCSI_10.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -2773,49 +3160,30 @@ } else { - DAC960_V2_ScatterGatherSegment_T - *ScatterGatherList = Command->V2.ScatterGatherList; - BufferHeader_T *BufferHeader = Command->BufferHeader; - char *LastDataEndPointer = NULL; - int SegmentNumber = 0; - if (Command->SegmentCount > 2) + DAC960_V2_ScatterGatherSegment_T *ScatterGatherList; + int i; + + if (SegCount > 2) { + ScatterGatherList = Command->V2.ScatterGatherList; CommandMailbox->SCSI_10.CommandControlBits .AdditionalScatterGatherListMemory = true; CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ExtendedScatterGather.ScatterGatherList0Length = - Command->SegmentCount; + .ExtendedScatterGather.ScatterGatherList0Length = SegCount; CommandMailbox->SCSI_10.DataTransferMemoryAddress .ExtendedScatterGather.ScatterGatherList0Address = - Virtual_to_Bus64(ScatterGatherList); + Command->V2.ScatterGatherListDMA; } else - ScatterGatherList = - CommandMailbox->SCSI_10.DataTransferMemoryAddress + ScatterGatherList = CommandMailbox->SCSI_10.DataTransferMemoryAddress .ScatterGatherSegments; - while (BufferHeader != NULL) - { - if (bio_data(BufferHeader) == LastDataEndPointer) - { - ScatterGatherList[SegmentNumber-1].SegmentByteCount += - BufferHeader->bi_size; - LastDataEndPointer += BufferHeader->bi_size; - } - else - { - ScatterGatherList[SegmentNumber].SegmentDataPointer = - Virtual_to_Bus64(bio_data(BufferHeader)); - ScatterGatherList[SegmentNumber].SegmentByteCount = - BufferHeader->bi_size; - LastDataEndPointer = bio_data(BufferHeader) + - BufferHeader->bi_size; - if (SegmentNumber++ > Controller->DriverScatterGatherLimit) - panic("DAC960: Scatter/Gather Segment Overflow\n"); - } - BufferHeader = BufferHeader->bi_next; - } - if (SegmentNumber != Command->SegmentCount) - panic("DAC960: SegmentNumber != SegmentCount\n"); + + for (i = 0; i < SegCount; i++, ScatterList++, ScatterGatherList++) { + ScatterGatherList->SegmentDataPointer = + (DAC960_BusAddress64_T)sg_dma_address(ScatterList); + ScatterGatherList->SegmentByteCount = + (DAC960_ByteCount64_T)sg_dma_len(ScatterList); + } } DAC960_QueueCommand(Command); } @@ -2832,32 +3200,36 @@ boolean WaitForCommand) { RequestQueue_T *RequestQueue = &Controller->RequestQueue; - ListHead_T *RequestQueueHead; IO_Request_T *Request; DAC960_Command_T *Command; - if (RequestQueue == NULL) return false; - RequestQueueHead = &RequestQueue->queue_head; - while (true) - { - if (list_empty(RequestQueueHead)) return false; + + if (!Controller->ControllerInitialized) + return false; + + while (true) { + if (blk_queue_empty(RequestQueue)) + return false; + Request = elv_next_request(RequestQueue); Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) break; - if (!WaitForCommand) return false; + if (Command != NULL) + break; + + if (!WaitForCommand) + return false; + DAC960_WaitForCommand(Controller); - } - if (Request->cmd == READ) + } + if (rq_data_dir(Request) == READ) Command->CommandType = DAC960_ReadCommand; - else Command->CommandType = DAC960_WriteCommand; + else + Command->CommandType = DAC960_WriteCommand; Command->Completion = Request->waiting; Command->LogicalDriveNumber = (int)Request->rq_disk->private_data; Command->BlockNumber = Request->sector; Command->BlockCount = Request->nr_sectors; - Command->SegmentCount = Request->nr_phys_segments; - Command->BufferHeader = Request->bio; - Command->RequestBuffer = Request->buffer; + Command->Request = Request; blkdev_dequeue_request(Request); - blk_put_request(Request); DAC960_QueueReadWriteCommand(Command); return true; } @@ -2904,16 +3276,43 @@ individual Buffer. */ -static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader, +static inline void DAC960_ProcessCompletedRequest(DAC960_Command_T *Command, boolean SuccessfulIO) { - bio_endio(BufferHeader, BufferHeader->bi_size, SuccessfulIO ? 0 : -EIO); - blk_finished_io(bio_sectors(BufferHeader)); -} + DAC960_CommandType_T CommandType = Command->CommandType; + IO_Request_T *Request = Command->Request; + int DmaDirection, UpToDate; + + UpToDate = 0; + if (SuccessfulIO) + UpToDate = 1; + + /* + * We could save DmaDirection in the command structure + * and just reuse that information here. + */ + if (CommandType == DAC960_ReadCommand || + CommandType == DAC960_ReadRetryCommand) + DmaDirection = PCI_DMA_FROMDEVICE; + else + DmaDirection = PCI_DMA_TODEVICE; -static inline int DAC960_PartitionByCommand(DAC960_Command_T *Command) -{ - return (int)Command->BufferHeader->bi_bdev->bd_disk->private_data; + pci_unmap_sg(Command->PciDevice, Command->V1.ScatterList, + Command->SegmentCount, DmaDirection); + /* + * BlockCount is redundant with nr_sectors in the request + * structure. Consider eliminating BlockCount from the + * command structure now that Command includes a pointer to + * the request. + */ + while (end_that_request_first(Request, UpToDate, Command->BlockCount)) + ; + end_that_request_last(Request); + + if (Command->Completion) { + complete(Command->Completion); + Command->Completion = NULL; + } } /* @@ -2966,13 +3365,6 @@ Controller, Controller->ControllerNumber, Command->LogicalDriveNumber, Command->BlockNumber, Command->BlockNumber + Command->BlockCount - 1); - if (DAC960_PartitionByCommand(Command) > 0) - DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %u..%u\n", - Controller, Controller->ControllerNumber, - Command->LogicalDriveNumber, - DAC960_PartitionByCommand(Command), - Command->BufferHeader->bi_sector, - Command->BufferHeader->bi_sector + Command->BlockCount - 1); } @@ -2988,129 +3380,60 @@ DAC960_V1_CommandOpcode_T CommandOpcode = Command->V1.CommandMailbox.Common.CommandOpcode; DAC960_V1_CommandStatus_T CommandStatus = Command->V1.CommandStatus; - BufferHeader_T *BufferHeader = Command->BufferHeader; + if (CommandType == DAC960_ReadCommand || CommandType == DAC960_WriteCommand) { if (CommandStatus == DAC960_V1_NormalCompletion) + + DAC960_ProcessCompletedRequest(Command, true); + + else if (CommandStatus == DAC960_V1_IrrecoverableDataError || + CommandStatus == DAC960_V1_BadDataEncountered) { + /* - Perform completion processing for all buffers in this I/O Request. - */ - while (BufferHeader != NULL) - { - BufferHeader_T *NextBufferHeader = BufferHeader->bi_next; - BufferHeader->bi_next = NULL; - DAC960_ProcessCompletedBuffer(BufferHeader, true); - BufferHeader = NextBufferHeader; - } - if (Command->Completion != NULL) - { - complete(Command->Completion); - Command->Completion = NULL; - } - add_disk_randomness(Controller->disks[Command->LogicalDriveNumber]); - } - else if ((CommandStatus == DAC960_V1_IrrecoverableDataError || - CommandStatus == DAC960_V1_BadDataEncountered) && - BufferHeader != NULL && - BufferHeader->bi_next != NULL) - { - DAC960_V1_CommandMailbox_T *CommandMailbox = - &Command->V1.CommandMailbox; - if (CommandType == DAC960_ReadCommand) - { - Command->CommandType = DAC960_ReadRetryCommand; - CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read; - } - else - { - Command->CommandType = DAC960_WriteRetryCommand; - CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; - } - Command->BlockCount = BufferHeader->bi_size >> DAC960_BlockSizeBits; - CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; - CommandMailbox->Type5.BusAddress = - Virtual_to_Bus32(bio_data(BufferHeader)); - DAC960_QueueCommand(Command); - return; + * Finish this later. + * + * We should call "complete_that_request_first()" + * to remove the first part of the request. Then, if there + * is still more I/O to be done, resubmit the request. + * + * We want to recalculate scatter/gather list, + * and requeue the command. + * + * For now, print a message on the console, and clone + * the code for "normal" completion. + */ + printk("V1_ProcessCompletedCommand: I/O error on read/write\n"); + + DAC960_ProcessCompletedRequest(Command, false); } else { if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline) DAC960_V1_ReadWriteError(Command); - /* - Perform completion processing for all buffers in this I/O Request. - */ - while (BufferHeader != NULL) - { - BufferHeader_T *NextBufferHeader = BufferHeader->bi_next; - BufferHeader->bi_next = NULL; - DAC960_ProcessCompletedBuffer(BufferHeader, false); - BufferHeader = NextBufferHeader; - } - if (Command->Completion != NULL) - { - complete(Command->Completion); - Command->Completion = NULL; - } + + DAC960_ProcessCompletedRequest(Command, false); } } else if (CommandType == DAC960_ReadRetryCommand || CommandType == DAC960_WriteRetryCommand) { - BufferHeader_T *NextBufferHeader = BufferHeader->bi_next; - BufferHeader->bi_next = NULL; - /* - Perform completion processing for this single buffer. - */ - if (CommandStatus == DAC960_V1_NormalCompletion) - DAC960_ProcessCompletedBuffer(BufferHeader, true); - else - { - if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline) - DAC960_V1_ReadWriteError(Command); - DAC960_ProcessCompletedBuffer(BufferHeader, false); - } - if (NextBufferHeader != NULL) - { - DAC960_V1_CommandMailbox_T *CommandMailbox = - &Command->V1.CommandMailbox; - Command->BlockNumber += - BufferHeader->bi_size >> DAC960_BlockSizeBits; - Command->BlockCount = - NextBufferHeader->bi_size >> DAC960_BlockSizeBits; - Command->BufferHeader = NextBufferHeader; - CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; - CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; - CommandMailbox->Type5.BusAddress = - Virtual_to_Bus32(bio_data(NextBufferHeader)); - DAC960_QueueCommand(Command); - return; - } + /* + * We're not doing retry commands yet. + */ + printk("DAC960_ProcessCompletedCommand: RetryCommand not done yet\n"); } - else if (CommandType == DAC960_MonitoringCommand || - CommandOpcode == DAC960_V1_Enquiry || - CommandOpcode == DAC960_V1_GetRebuildProgress) - { - if (CommandType != DAC960_MonitoringCommand) - { - if (CommandOpcode == DAC960_V1_Enquiry) - memcpy(&Controller->V1.NewEnquiry, - Bus32_to_Virtual(Command->V1.CommandMailbox - .Type3.BusAddress), - sizeof(DAC960_V1_Enquiry_T)); - else if (CommandOpcode == DAC960_V1_GetRebuildProgress) - memcpy(&Controller->V1.RebuildProgress, - Bus32_to_Virtual(Command->V1.CommandMailbox - .Type3.BusAddress), - sizeof(DAC960_V1_RebuildProgress_T)); - } - if (CommandOpcode == DAC960_V1_Enquiry && - Controller->ControllerInitialized) + + else if (CommandType == DAC960_MonitoringCommand) + { + if (Controller->ShutdownMonitoringTimer) + return; + if (CommandOpcode == DAC960_V1_Enquiry) { DAC960_V1_Enquiry_T *OldEnquiry = &Controller->V1.Enquiry; - DAC960_V1_Enquiry_T *NewEnquiry = &Controller->V1.NewEnquiry; + DAC960_V1_Enquiry_T *NewEnquiry = Controller->V1.NewEnquiry; unsigned int OldCriticalLogicalDriveCount = OldEnquiry->CriticalLogicalDriveCount; unsigned int NewCriticalLogicalDriveCount = @@ -3220,17 +3543,7 @@ (NewEnquiry->CriticalLogicalDriveCount > 0 || NewEnquiry->OfflineLogicalDriveCount > 0 || NewEnquiry->DeadDriveCount > 0); - if (CommandType != DAC960_MonitoringCommand && - Controller->V1.RebuildFlagPending) - { - DAC960_V1_Enquiry_T *Enquiry = (DAC960_V1_Enquiry_T *) - Bus32_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress); - Enquiry->RebuildFlag = Controller->V1.PendingRebuildFlag; - Controller->V1.RebuildFlagPending = false; - } - else if (CommandType == DAC960_MonitoringCommand && - NewEnquiry->RebuildFlag > - DAC960_V1_BackgroundCheckInProgress) + if (NewEnquiry->RebuildFlag > DAC960_V1_BackgroundCheckInProgress) { Controller->V1.PendingRebuildFlag = NewEnquiry->RebuildFlag; Controller->V1.RebuildFlagPending = true; @@ -3256,7 +3569,7 @@ "killed due to SCSI phase sequence error", "killed due to unknown status" }; DAC960_V1_EventLogEntry_T *EventLogEntry = - &Controller->V1.EventLogEntry; + Controller->V1.EventLogEntry; if (EventLogEntry->SequenceNumber == Controller->V1.OldEventLogSequenceNumber) { @@ -3316,7 +3629,7 @@ else if (CommandOpcode == DAC960_V1_GetErrorTable) { DAC960_V1_ErrorTable_T *OldErrorTable = &Controller->V1.ErrorTable; - DAC960_V1_ErrorTable_T *NewErrorTable = &Controller->V1.NewErrorTable; + DAC960_V1_ErrorTable_T *NewErrorTable = Controller->V1.NewErrorTable; int Channel, TargetID; for (Channel = 0; Channel < Controller->Channels; Channel++) for (TargetID = 0; TargetID < Controller->Targets; TargetID++) @@ -3342,7 +3655,7 @@ NewErrorEntry->HardErrorCount, NewErrorEntry->MiscErrorCount); } - memcpy(&Controller->V1.ErrorTable, &Controller->V1.NewErrorTable, + memcpy(&Controller->V1.ErrorTable, Controller->V1.NewErrorTable, sizeof(DAC960_V1_ErrorTable_T)); } else if (CommandOpcode == DAC960_V1_GetDeviceState) @@ -3351,7 +3664,7 @@ &Controller->V1.DeviceState[Controller->V1.DeviceStateChannel] [Controller->V1.DeviceStateTargetID]; DAC960_V1_DeviceState_T *NewDeviceState = - &Controller->V1.NewDeviceState; + Controller->V1.NewDeviceState; if (NewDeviceState->DeviceState != OldDeviceState->DeviceState) DAC960_Critical("Physical Device %d:%d is now %s\n", Controller, Controller->V1.DeviceStateChannel, @@ -3387,7 +3700,7 @@ DAC960_V1_LogicalDriveInformation_T *OldLogicalDriveInformation = &Controller->V1.LogicalDriveInformation[LogicalDriveNumber]; DAC960_V1_LogicalDriveInformation_T *NewLogicalDriveInformation = - &Controller->V1.NewLogicalDriveInformation[LogicalDriveNumber]; + &(*Controller->V1.NewLogicalDriveInformation)[LogicalDriveNumber]; if (NewLogicalDriveInformation->LogicalDriveState != OldLogicalDriveInformation->LogicalDriveState) DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " @@ -3412,17 +3725,17 @@ ? "WRITE BACK" : "WRITE THRU")); } memcpy(&Controller->V1.LogicalDriveInformation, - &Controller->V1.NewLogicalDriveInformation, + Controller->V1.NewLogicalDriveInformation, sizeof(DAC960_V1_LogicalDriveInformationArray_T)); } else if (CommandOpcode == DAC960_V1_GetRebuildProgress) { unsigned int LogicalDriveNumber = - Controller->V1.RebuildProgress.LogicalDriveNumber; + Controller->V1.RebuildProgress->LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->V1.RebuildProgress.LogicalDriveSize; + Controller->V1.RebuildProgress->LogicalDriveSize; unsigned int BlocksCompleted = - LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks; if (CommandStatus == DAC960_V1_NoRebuildOrCheckInProgress && Controller->V1.LastRebuildStatus == DAC960_V1_NormalCompletion) CommandStatus = DAC960_V1_RebuildSuccessful; @@ -3479,11 +3792,11 @@ else if (CommandOpcode == DAC960_V1_RebuildStat) { unsigned int LogicalDriveNumber = - Controller->V1.RebuildProgress.LogicalDriveNumber; + Controller->V1.RebuildProgress->LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->V1.RebuildProgress.LogicalDriveSize; + Controller->V1.RebuildProgress->LogicalDriveSize; unsigned int BlocksCompleted = - LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks; if (CommandStatus == DAC960_V1_NormalCompletion) { Controller->EphemeralProgressMessage = true; @@ -3501,15 +3814,15 @@ else if (CommandOpcode == DAC960_V1_BackgroundInitializationControl) { unsigned int LogicalDriveNumber = - Controller->V1.BackgroundInitializationStatus.LogicalDriveNumber; + Controller->V1.BackgroundInitializationStatus->LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->V1.BackgroundInitializationStatus.LogicalDriveSize; + Controller->V1.BackgroundInitializationStatus->LogicalDriveSize; unsigned int BlocksCompleted = - Controller->V1.BackgroundInitializationStatus.BlocksCompleted; + Controller->V1.BackgroundInitializationStatus->BlocksCompleted; switch (CommandStatus) { case DAC960_V1_NormalCompletion: - switch (Controller->V1.BackgroundInitializationStatus.Status) + switch (Controller->V1.BackgroundInitializationStatus->Status) { case DAC960_V1_BackgroundInitializationInvalid: break; @@ -3519,11 +3832,11 @@ break; case DAC960_V1_BackgroundInitializationInProgress: if (BlocksCompleted == - Controller->V1.LastBackgroundInitializationStatus - .BlocksCompleted && + Controller->V1.LastBackgroundInitializationStatus. + BlocksCompleted && LogicalDriveNumber == - Controller->V1.LastBackgroundInitializationStatus - .LogicalDriveNumber) + Controller->V1.LastBackgroundInitializationStatus. + LogicalDriveNumber) break; Controller->EphemeralProgressMessage = true; DAC960_Progress("Background Initialization in Progress: " @@ -3546,32 +3859,84 @@ break; } memcpy(&Controller->V1.LastBackgroundInitializationStatus, - &Controller->V1.BackgroundInitializationStatus, + Controller->V1.BackgroundInitializationStatus, sizeof(DAC960_V1_BackgroundInitializationStatus_T)); break; case DAC960_V1_BackgroundInitSuccessful: - if (Controller->V1.BackgroundInitializationStatus.Status == + if (Controller->V1.BackgroundInitializationStatus->Status == DAC960_V1_BackgroundInitializationInProgress) DAC960_Progress("Background Initialization " "Completed Successfully\n", Controller); - Controller->V1.BackgroundInitializationStatus.Status = + Controller->V1.BackgroundInitializationStatus->Status = DAC960_V1_BackgroundInitializationInvalid; break; case DAC960_V1_BackgroundInitAborted: - if (Controller->V1.BackgroundInitializationStatus.Status == + if (Controller->V1.BackgroundInitializationStatus->Status == DAC960_V1_BackgroundInitializationInProgress) DAC960_Progress("Background Initialization Aborted\n", Controller); - Controller->V1.BackgroundInitializationStatus.Status = + Controller->V1.BackgroundInitializationStatus->Status = DAC960_V1_BackgroundInitializationInvalid; break; case DAC960_V1_NoBackgroundInitInProgress: break; } + } + else if (CommandOpcode == DAC960_V1_DCDB) + { + /* + This is a bit ugly. + + The InquiryStandardData and + the InquiryUntitSerialNumber information + retrieval operations BOTH use the DAC960_V1_DCDB + commands. the test above can't distinguish between + these two cases. + + Instead, we rely on the order of code later in this + function to ensure that DeviceInquiryInformation commands + are submitted before DeviceSerialNumber commands. + */ + if (Controller->V1.NeedDeviceInquiryInformation) + { + DAC960_SCSI_Inquiry_T *InquiryStandardData = + &Controller->V1.InquiryStandardData + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; + if (CommandStatus != DAC960_V1_NormalCompletion) + { + memset(InquiryStandardData, 0, + sizeof(DAC960_SCSI_Inquiry_T)); + InquiryStandardData->PeripheralDeviceType = 0x1F; + } + else + memcpy(InquiryStandardData, + Controller->V1.NewInquiryStandardData, + sizeof(DAC960_SCSI_Inquiry_T)); + Controller->V1.NeedDeviceInquiryInformation = false; + } + else if (Controller->V1.NeedDeviceSerialNumberInformation) + { + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = + &Controller->V1.InquiryUnitSerialNumber + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; + if (CommandStatus != DAC960_V1_NormalCompletion) + { + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + } + else + memcpy(InquiryUnitSerialNumber, + Controller->V1.NewInquiryUnitSerialNumber, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + Controller->V1.NeedDeviceSerialNumberInformation = false; + } } - } - if (CommandType == DAC960_MonitoringCommand) - { + /* + Begin submitting new monitoring commands. + */ if (Controller->V1.NewEventLogSequenceNumber - Controller->V1.OldEventLogSequenceNumber > 0) { @@ -3583,7 +3948,7 @@ Command->V1.CommandMailbox.Type3E.SequenceNumber = Controller->V1.OldEventLogSequenceNumber; Command->V1.CommandMailbox.Type3E.BusAddress = - Virtual_to_Bus32(&Controller->V1.EventLogEntry); + Controller->V1.EventLogEntryDMA; DAC960_QueueCommand(Command); return; } @@ -3593,7 +3958,7 @@ Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_GetErrorTable; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.NewErrorTable); + Controller->V1.NewErrorTableDMA; DAC960_QueueCommand(Command); return; } @@ -3604,7 +3969,7 @@ Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_GetRebuildProgress; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.RebuildProgress); + Controller->V1.RebuildProgressDMA; DAC960_QueueCommand(Command); return; } @@ -3612,15 +3977,14 @@ { if (Controller->V1.NeedDeviceInquiryInformation) { - DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; - DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->V1.InquiryStandardData - [Controller->V1.DeviceStateChannel] - [Controller->V1.DeviceStateTargetID]; - InquiryStandardData->PeripheralDeviceType = 0x1F; + DAC960_V1_DCDB_T *DCDB = Controller->V1.MonitoringDCDB; + dma_addr_t DCDB_DMA = Controller->V1.MonitoringDCDB_DMA; + + dma_addr_t NewInquiryStandardDataDMA = + Controller->V1.NewInquiryStandardDataDMA; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DCDB); + Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA; DCDB->Channel = Controller->V1.DeviceStateChannel; DCDB->TargetID = Controller->V1.DeviceStateTargetID; DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; @@ -3629,7 +3993,7 @@ DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); - DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData); + DCDB->BusAddress = NewInquiryStandardDataDMA; DCDB->CDBLength = 6; DCDB->TransferLengthHigh4 = 0; DCDB->SenseLength = sizeof(DCDB->SenseData); @@ -3640,20 +4004,17 @@ DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T); DCDB->CDB[5] = 0; /* Control */ DAC960_QueueCommand(Command); - Controller->V1.NeedDeviceInquiryInformation = false; return; } if (Controller->V1.NeedDeviceSerialNumberInformation) { - DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; - DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->V1.InquiryUnitSerialNumber - [Controller->V1.DeviceStateChannel] - [Controller->V1.DeviceStateTargetID]; - InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + DAC960_V1_DCDB_T *DCDB = Controller->V1.MonitoringDCDB; + dma_addr_t DCDB_DMA = Controller->V1.MonitoringDCDB_DMA; + dma_addr_t NewInquiryUnitSerialNumberDMA = + Controller->V1.NewInquiryUnitSerialNumberDMA; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DCDB); + Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA; DCDB->Channel = Controller->V1.DeviceStateChannel; DCDB->TargetID = Controller->V1.DeviceStateTargetID; DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; @@ -3663,7 +4024,7 @@ DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber); + DCDB->BusAddress = NewInquiryUnitSerialNumberDMA; DCDB->CDBLength = 6; DCDB->TransferLengthHigh4 = 0; DCDB->SenseLength = sizeof(DCDB->SenseData); @@ -3674,7 +4035,6 @@ DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); DCDB->CDB[5] = 0; /* Control */ DAC960_QueueCommand(Command); - Controller->V1.NeedDeviceSerialNumberInformation = false; return; } if (Controller->V1.StartDeviceStateScan) @@ -3690,7 +4050,7 @@ } if (Controller->V1.DeviceStateChannel < Controller->Channels) { - Controller->V1.NewDeviceState.DeviceState = + Controller->V1.NewDeviceState->DeviceState = DAC960_V1_Device_Dead; Command->V1.CommandMailbox.Type3D.CommandOpcode = DAC960_V1_GetDeviceState; @@ -3699,7 +4059,7 @@ Command->V1.CommandMailbox.Type3D.TargetID = Controller->V1.DeviceStateTargetID; Command->V1.CommandMailbox.Type3D.BusAddress = - Virtual_to_Bus32(&Controller->V1.NewDeviceState); + Controller->V1.NewDeviceStateDMA; DAC960_QueueCommand(Command); return; } @@ -3711,7 +4071,7 @@ Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_GetLogicalDriveInformation; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.NewLogicalDriveInformation); + Controller->V1.NewLogicalDriveInformationDMA; DAC960_QueueCommand(Command); return; } @@ -3721,7 +4081,7 @@ Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_GetRebuildProgress; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.RebuildProgress); + Controller->V1.RebuildProgressDMA; DAC960_QueueCommand(Command); return; } @@ -3731,7 +4091,7 @@ Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_RebuildStat; Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.RebuildProgress); + Controller->V1.RebuildProgressDMA; DAC960_QueueCommand(Command); return; } @@ -3742,14 +4102,14 @@ DAC960_V1_BackgroundInitializationControl; Command->V1.CommandMailbox.Type3B.CommandOpcode2 = 0x20; Command->V1.CommandMailbox.Type3B.BusAddress = - Virtual_to_Bus32(&Controller->V1.BackgroundInitializationStatus); + Controller->V1.BackgroundInitializationStatusDMA; DAC960_QueueCommand(Command); return; } Controller->MonitoringTimerCount++; Controller->MonitoringTimer.expires = jiffies + DAC960_MonitoringTimerInterval; - add_timer(&Controller->MonitoringTimer); + add_timer(&Controller->MonitoringTimer); } if (CommandType == DAC960_ImmediateCommand) { @@ -3825,18 +4185,11 @@ break; } DAC960_Error("Error Condition %s on %s:\n", Controller, - SenseErrors[Command->V2.RequestSense.SenseKey], CommandName); + SenseErrors[Command->V2.RequestSense->SenseKey], CommandName); DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %u..%u\n", Controller, Controller->ControllerNumber, Command->LogicalDriveNumber, Command->BlockNumber, Command->BlockNumber + Command->BlockCount - 1); - if (DAC960_PartitionByCommand(Command) > 0) - DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %u..%u\n", - Controller, Controller->ControllerNumber, - Command->LogicalDriveNumber, - DAC960_PartitionByCommand(Command), - Command->BufferHeader->bi_sector, - Command->BufferHeader->bi_sector + Command->BlockCount - 1); } @@ -4094,123 +4447,51 @@ DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; DAC960_V2_IOCTL_Opcode_T CommandOpcode = CommandMailbox->Common.IOCTL_Opcode; DAC960_V2_CommandStatus_T CommandStatus = Command->V2.CommandStatus; - BufferHeader_T *BufferHeader = Command->BufferHeader; + if (CommandType == DAC960_ReadCommand || CommandType == DAC960_WriteCommand) { if (CommandStatus == DAC960_V2_NormalCompletion) + + DAC960_ProcessCompletedRequest(Command, true); + + else if (Command->V2.RequestSense->SenseKey == DAC960_SenseKey_MediumError) { + /* - Perform completion processing for all buffers in this I/O Request. - */ - while (BufferHeader != NULL) - { - BufferHeader_T *NextBufferHeader = BufferHeader->bi_next; - BufferHeader->bi_next = NULL; - DAC960_ProcessCompletedBuffer(BufferHeader, true); - BufferHeader = NextBufferHeader; - } - if (Command->Completion != NULL) - { - complete(Command->Completion); - Command->Completion = NULL; - } - add_disk_randomness(Controller->disks[Command->LogicalDriveNumber]); - } - else if (Command->V2.RequestSense.SenseKey - == DAC960_SenseKey_MediumError && - BufferHeader != NULL && - BufferHeader->bi_next != NULL) - { - if (CommandType == DAC960_ReadCommand) - Command->CommandType = DAC960_ReadRetryCommand; - else Command->CommandType = DAC960_WriteRetryCommand; - Command->BlockCount = BufferHeader->bi_size >> DAC960_BlockSizeBits; - CommandMailbox->SCSI_10.CommandControlBits - .AdditionalScatterGatherListMemory = false; - CommandMailbox->SCSI_10.DataTransferSize = - Command->BlockCount << DAC960_BlockSizeBits; - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0].SegmentDataPointer = - Virtual_to_Bus64(bio_data(BufferHeader)); - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0].SegmentByteCount = - CommandMailbox->SCSI_10.DataTransferSize; - CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; - CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; - DAC960_QueueCommand(Command); - return; + * Don't know yet how to handle this case. + * See comments in DAC960_V1_ProcessCompletedCommand() + * + * For now, print a message on the console, and clone + * the code for "normal" completion. + */ + printk("V1_ProcessCompletedCommand: I/O error on read/write\n"); + + DAC960_ProcessCompletedRequest(Command, false); } else { - if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady) + if (Command->V2.RequestSense->SenseKey != DAC960_SenseKey_NotReady) DAC960_V2_ReadWriteError(Command); /* Perform completion processing for all buffers in this I/O Request. */ - while (BufferHeader != NULL) - { - BufferHeader_T *NextBufferHeader = BufferHeader->bi_next; - BufferHeader->bi_next = NULL; - DAC960_ProcessCompletedBuffer(BufferHeader, false); - BufferHeader = NextBufferHeader; - } - if (Command->Completion != NULL) - { - complete(Command->Completion); - Command->Completion = NULL; - } + DAC960_ProcessCompletedRequest(Command, false); } } else if (CommandType == DAC960_ReadRetryCommand || CommandType == DAC960_WriteRetryCommand) { - BufferHeader_T *NextBufferHeader = BufferHeader->bi_next; - BufferHeader->bi_next = NULL; - /* - Perform completion processing for this single buffer. - */ - if (CommandStatus == DAC960_V2_NormalCompletion) - DAC960_ProcessCompletedBuffer(BufferHeader, true); - else - { - if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady) - DAC960_V2_ReadWriteError(Command); - DAC960_ProcessCompletedBuffer(BufferHeader, false); - } - if (NextBufferHeader != NULL) - { - Command->BlockNumber += - BufferHeader->bi_size >> DAC960_BlockSizeBits; - Command->BlockCount = - NextBufferHeader->bi_size >> DAC960_BlockSizeBits; - Command->BufferHeader = NextBufferHeader; - CommandMailbox->SCSI_10.DataTransferSize = - Command->BlockCount << DAC960_BlockSizeBits; - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(bio_data(NextBufferHeader)); - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentByteCount = - CommandMailbox->SCSI_10.DataTransferSize; - CommandMailbox->SCSI_10.SCSI_CDB[2] = Command->BlockNumber >> 24; - CommandMailbox->SCSI_10.SCSI_CDB[3] = Command->BlockNumber >> 16; - CommandMailbox->SCSI_10.SCSI_CDB[4] = Command->BlockNumber >> 8; - CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber; - CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; - CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; - DAC960_QueueCommand(Command); - return; - } + printk("DAC960_V2_ProcessCompletedCommand: retries not coded yet\n"); } else if (CommandType == DAC960_MonitoringCommand) { + if (Controller->ShutdownMonitoringTimer) + return; if (CommandOpcode == DAC960_V2_GetControllerInfo) { DAC960_V2_ControllerInfo_T *NewControllerInfo = - &Controller->V2.NewControllerInformation; + Controller->V2.NewControllerInformation; DAC960_V2_ControllerInfo_T *ControllerInfo = &Controller->V2.ControllerInformation; Controller->LogicalDriveCount = @@ -4229,15 +4510,16 @@ } else if (CommandOpcode == DAC960_V2_GetEvent) { - if (CommandStatus == DAC960_V2_NormalCompletion) - DAC960_V2_ReportEvent(Controller, &Controller->V2.Event); + if (CommandStatus == DAC960_V2_NormalCompletion) { + DAC960_V2_ReportEvent(Controller, Controller->V2.Event); + } Controller->V2.NextEventSequenceNumber++; } else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid && CommandStatus == DAC960_V2_NormalCompletion) { DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo = - &Controller->V2.NewPhysicalDeviceInformation; + Controller->V2.NewPhysicalDeviceInformation; unsigned int PhysicalDeviceIndex = Controller->V2.PhysicalDeviceIndex; DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo = Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex]; @@ -4448,7 +4730,7 @@ CommandStatus == DAC960_V2_NormalCompletion) { DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo = - &Controller->V2.NewLogicalDeviceInformation; + Controller->V2.NewLogicalDeviceInformation; unsigned short LogicalDeviceNumber = NewLogicalDeviceInfo->LogicalDeviceNumber; DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = @@ -4598,6 +4880,23 @@ } Controller->V2.NeedLogicalDeviceInformation = false; } + else if (CommandOpcode == DAC960_V2_SCSI_10_Passthru) + { + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = + Controller->V2.InquiryUnitSerialNumber[Controller->V2.PhysicalDeviceIndex - 1]; + + if (CommandStatus != DAC960_V2_NormalCompletion) { + memset(InquiryUnitSerialNumber, + 0, sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + } else + memcpy(InquiryUnitSerialNumber, + Controller->V2.NewInquiryUnitSerialNumber, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + + Controller->V2.NeedDeviceSerialNumberInformation = false; + } + if (Controller->V2.HealthStatusBuffer->NextEventSequenceNumber - Controller->V2.NextEventSequenceNumber > 0) { @@ -4613,7 +4912,7 @@ CommandMailbox->GetEvent.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.Event); + Controller->V2.EventDMA; CommandMailbox->GetEvent.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -4626,62 +4925,41 @@ if (Controller->V2.NeedDeviceSerialNumberInformation) { DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - Controller->V2.InquiryUnitSerialNumber - [Controller->V2.PhysicalDeviceIndex - 1]; + Controller->V2.NewInquiryUnitSerialNumber; InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; - CommandMailbox->SCSI_10.CommandOpcode = - DAC960_V2_SCSI_10_Passthru; - CommandMailbox->SCSI_10.DataTransferSize = - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = - Controller->V2.NewPhysicalDeviceInformation.LogicalUnit - 1; - CommandMailbox->SCSI_10.PhysicalDevice.TargetID = - Controller->V2.NewPhysicalDeviceInformation.TargetID; - CommandMailbox->SCSI_10.PhysicalDevice.Channel = - Controller->V2.NewPhysicalDeviceInformation.Channel; - CommandMailbox->SCSI_10.CDBLength = 6; - CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ - CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ - CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ - CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ - CommandMailbox->SCSI_10.SCSI_CDB[4] = - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(InquiryUnitSerialNumber); - CommandMailbox->SCSI_10.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentByteCount = - CommandMailbox->SCSI_10.DataTransferSize; + + DAC960_V2_ConstructNewUnitSerialNumber(Controller, CommandMailbox, + Controller->V2.NewPhysicalDeviceInformation->Channel, + Controller->V2.NewPhysicalDeviceInformation->TargetID, + Controller->V2.NewPhysicalDeviceInformation->LogicalUnit - 1); + + DAC960_QueueCommand(Command); - Controller->V2.NeedDeviceSerialNumberInformation = false; return; } if (Controller->V2.StartPhysicalDeviceInformationScan) { Controller->V2.PhysicalDeviceIndex = 0; - Controller->V2.NewPhysicalDeviceInformation.Channel = 0; - Controller->V2.NewPhysicalDeviceInformation.TargetID = 0; - Controller->V2.NewPhysicalDeviceInformation.LogicalUnit = 0; + Controller->V2.NewPhysicalDeviceInformation->Channel = 0; + Controller->V2.NewPhysicalDeviceInformation->TargetID = 0; + Controller->V2.NewPhysicalDeviceInformation->LogicalUnit = 0; Controller->V2.StartPhysicalDeviceInformationScan = false; } CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; CommandMailbox->PhysicalDeviceInfo.DataTransferSize = sizeof(DAC960_V2_PhysicalDeviceInfo_T); CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = - Controller->V2.NewPhysicalDeviceInformation.LogicalUnit; + Controller->V2.NewPhysicalDeviceInformation->LogicalUnit; CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = - Controller->V2.NewPhysicalDeviceInformation.TargetID; + Controller->V2.NewPhysicalDeviceInformation->TargetID; CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = - Controller->V2.NewPhysicalDeviceInformation.Channel; + Controller->V2.NewPhysicalDeviceInformation->Channel; CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = DAC960_V2_GetPhysicalDeviceInfoValid; CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.NewPhysicalDeviceInformation); + Controller->V2.NewPhysicalDeviceInformationDMA; CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -4699,21 +4977,20 @@ LogicalDriveNumber++) Controller->V2.LogicalDriveFoundDuringScan [LogicalDriveNumber] = false; - Controller->V2.NewLogicalDeviceInformation - .LogicalDeviceNumber = 0; + Controller->V2.NewLogicalDeviceInformation->LogicalDeviceNumber = 0; Controller->V2.StartLogicalDeviceInformationScan = false; } CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; CommandMailbox->LogicalDeviceInfo.DataTransferSize = sizeof(DAC960_V2_LogicalDeviceInfo_T); CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = - Controller->V2.NewLogicalDeviceInformation.LogicalDeviceNumber; + Controller->V2.NewLogicalDeviceInformation->LogicalDeviceNumber; CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = DAC960_V2_GetLogicalDeviceInfoValid; CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.NewLogicalDeviceInformation); + Controller->V2.NewLogicalDeviceInformationDMA; CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -4724,7 +5001,7 @@ Controller->MonitoringTimerCount++; Controller->MonitoringTimer.expires = jiffies + DAC960_HealthStatusMonitoringInterval; - add_timer(&Controller->MonitoringTimer); + add_timer(&Controller->MonitoringTimer); } if (CommandType == DAC960_ImmediateCommand) { @@ -5002,6 +5279,10 @@ /* DAC960_P_InterruptHandler handles hardware interrupts from DAC960 P Series Controllers. + + Translations of DAC960_V1_Enquiry and DAC960_V1_GetDeviceState rely + on the data having been placed into DAC960_Controller_T, rather than + an arbitrary buffer. */ static void DAC960_P_InterruptHandler(int IRQ_Channel, @@ -5034,14 +5315,12 @@ { case DAC960_V1_Enquiry_Old: Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Enquiry; - DAC960_P_To_PD_TranslateEnquiry( - Bus32_to_Virtual(CommandMailbox->Type3.BusAddress)); + DAC960_P_To_PD_TranslateEnquiry(Controller->V1.NewEnquiry); break; case DAC960_V1_GetDeviceState_Old: Command->V1.CommandMailbox.Common.CommandOpcode = - DAC960_V1_GetDeviceState; - DAC960_P_To_PD_TranslateDeviceState( - Bus32_to_Virtual(CommandMailbox->Type3.BusAddress)); + DAC960_V1_GetDeviceState; + DAC960_P_To_PD_TranslateDeviceState(Controller->V1.NewDeviceState); break; case DAC960_V1_Read_Old: Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Read; @@ -5090,8 +5369,7 @@ DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_MonitoringCommand; CommandMailbox->Type3.CommandOpcode = DAC960_V1_Enquiry; - CommandMailbox->Type3.BusAddress = - Virtual_to_Bus32(&Controller->V1.NewEnquiry); + CommandMailbox->Type3.BusAddress = Controller->V1.NewEnquiryDMA; DAC960_QueueCommand(Command); } @@ -5119,7 +5397,7 @@ CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.NewControllerInformation); + Controller->V2.NewControllerInformationDMA; CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -5198,7 +5476,7 @@ { Controller->MonitoringTimer.expires = jiffies + DAC960_HealthStatusMonitoringInterval; - add_timer(&Controller->MonitoringTimer); + add_timer(&Controller->MonitoringTimer); return; } Controller->V2.StatusChangeCounter = StatusChangeCounter; @@ -5225,6 +5503,7 @@ } } + /* DAC960_Open is the Device Open Function for the DAC960 Driver. */ @@ -5423,14 +5702,17 @@ DAC960_V1_CommandOpcode_T CommandOpcode; DAC960_V1_CommandStatus_T CommandStatus; DAC960_V1_DCDB_T DCDB; + DAC960_V1_DCDB_T *DCDB_IOBUF = NULL; + dma_addr_t DCDB_IOBUFDMA; ProcessorFlags_T ProcessorFlags; int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; + dma_addr_t DataTransferBufferDMA; if (UserSpaceUserCommand == NULL) return -EINVAL; if (copy_from_user(&UserCommand, UserSpaceUserCommand, sizeof(DAC960_V1_UserCommand_T))) { ErrorCode = -EFAULT; - goto Failure1; + goto Failure1a; } ControllerNumber = UserCommand.ControllerNumber; if (ControllerNumber < 0 || @@ -5447,7 +5729,7 @@ if (copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_V1_DCDB_T))) { ErrorCode = -EFAULT; - goto Failure1; + goto Failure1a; } if (DCDB.Channel >= DAC960_V1_MaxChannels) return -EINVAL; if (!((DataTransferLength == 0 && @@ -5463,17 +5745,29 @@ if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength) != abs(DataTransferLength)) return -EINVAL; + DCDB_IOBUF = pci_alloc_consistent(Controller->PCIDevice, + sizeof(DAC960_V1_DCDB_T), &DCDB_IOBUFDMA); + if (DCDB_IOBUF == NULL) + return -ENOMEM; } if (DataTransferLength > 0) { - DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL); - if (DataTransferBuffer == NULL) return -ENOMEM; + DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, + DataTransferLength, &DataTransferBufferDMA); + if (DataTransferBuffer == NULL) { + ErrorCode = -ENOMEM; + goto Failure1; + } memset(DataTransferBuffer, 0, DataTransferLength); } else if (DataTransferLength < 0) { - DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); - if (DataTransferBuffer == NULL) return -ENOMEM; + DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, + -DataTransferLength, &DataTransferBufferDMA); + if (DataTransferBuffer == NULL) { + ErrorCode = -ENOMEM; + goto Failure1; + } if (copy_from_user(DataTransferBuffer, UserCommand.DataTransferBuffer, -DataTransferLength)) { @@ -5489,11 +5783,11 @@ while (Controller->V1.DirectCommandActive[DCDB.Channel] [DCDB.TargetID]) { - spin_unlock_irq(Controller->RequestQueue.queue_lock); + spin_unlock_irq(&Controller->queue_lock); __wait_event(Controller->CommandWaitQueue, !Controller->V1.DirectCommandActive [DCDB.Channel][DCDB.TargetID]); - spin_lock_irq(Controller->RequestQueue.queue_lock); + spin_lock_irq(&Controller->queue_lock); } Controller->V1.DirectCommandActive[DCDB.Channel] [DCDB.TargetID] = true; @@ -5502,9 +5796,9 @@ Command->CommandType = DAC960_ImmediateCommand; memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, sizeof(DAC960_V1_CommandMailbox_T)); - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(&DCDB); - DCDB.BusAddress = Virtual_to_Bus32(DataTransferBuffer); + Command->V1.CommandMailbox.Type3.BusAddress = DCDB_IOBUFDMA; + DCDB.BusAddress = DataTransferBufferDMA; + memcpy(DCDB_IOBUF, &DCDB, sizeof(DAC960_V1_DCDB_T)); } else { @@ -5518,7 +5812,7 @@ sizeof(DAC960_V1_CommandMailbox_T)); if (DataTransferBuffer != NULL) Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DataTransferBuffer); + DataTransferBufferDMA; } DAC960_ExecuteCommand(Command); CommandStatus = Command->V1.CommandStatus; @@ -5528,15 +5822,20 @@ if (DataTransferLength > 0) { if (copy_to_user(UserCommand.DataTransferBuffer, - DataTransferBuffer, DataTransferLength)) + DataTransferBuffer, DataTransferLength)) { ErrorCode = -EFAULT; goto Failure1; + } } if (CommandOpcode == DAC960_V1_DCDB) { + /* + I don't believe Target or Channel in the DCDB_IOBUF + should be any different from the contents of DCDB. + */ Controller->V1.DirectCommandActive[DCDB.Channel] [DCDB.TargetID] = false; - if (copy_to_user(UserCommand.DCDB, &DCDB, + if (copy_to_user(UserCommand.DCDB, DCDB_IOBUF, sizeof(DAC960_V1_DCDB_T))) { ErrorCode = -EFAULT; goto Failure1; @@ -5545,7 +5844,12 @@ ErrorCode = CommandStatus; Failure1: if (DataTransferBuffer != NULL) - kfree(DataTransferBuffer); + pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength), + DataTransferBuffer, DataTransferBufferDMA); + if (DCDB_IOBUF != NULL) + pci_free_consistent(Controller->PCIDevice, sizeof(DAC960_V1_DCDB_T), + DCDB_IOBUF, DCDB_IOBUFDMA); + Failure1a: return ErrorCode; } case DAC960_IOCTL_V2_EXECUTE_COMMAND: @@ -5561,12 +5865,14 @@ int ControllerNumber, DataTransferLength; int DataTransferResidue, RequestSenseLength; unsigned char *DataTransferBuffer = NULL; + dma_addr_t DataTransferBufferDMA; unsigned char *RequestSenseBuffer = NULL; + dma_addr_t RequestSenseBufferDMA; if (UserSpaceUserCommand == NULL) return -EINVAL; if (copy_from_user(&UserCommand, UserSpaceUserCommand, sizeof(DAC960_V2_UserCommand_T))) { ErrorCode = -EFAULT; - goto Failure2; + goto Failure2a; } ControllerNumber = UserCommand.ControllerNumber; if (ControllerNumber < 0 || @@ -5578,13 +5884,15 @@ DataTransferLength = UserCommand.DataTransferLength; if (DataTransferLength > 0) { - DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL); + DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, + DataTransferLength, &DataTransferBufferDMA); if (DataTransferBuffer == NULL) return -ENOMEM; memset(DataTransferBuffer, 0, DataTransferLength); } else if (DataTransferLength < 0) { - DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); + DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, + -DataTransferLength, &DataTransferBufferDMA); if (DataTransferBuffer == NULL) return -ENOMEM; if (copy_from_user(DataTransferBuffer, UserCommand.DataTransferBuffer, @@ -5596,7 +5904,8 @@ RequestSenseLength = UserCommand.RequestSenseLength; if (RequestSenseLength > 0) { - RequestSenseBuffer = kmalloc(RequestSenseLength, GFP_KERNEL); + RequestSenseBuffer = pci_alloc_consistent(Controller->PCIDevice, + RequestSenseLength, &RequestSenseBufferDMA); if (RequestSenseBuffer == NULL) { ErrorCode = -ENOMEM; @@ -5637,8 +5946,7 @@ } CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(DataTransferBuffer); + .SegmentDataPointer = DataTransferBufferDMA; CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = @@ -5650,7 +5958,7 @@ .NoAutoRequestSense = false; CommandMailbox->Common.RequestSenseSize = RequestSenseLength; CommandMailbox->Common.RequestSenseBusAddress = - Virtual_to_Bus64(RequestSenseBuffer); + RequestSenseBufferDMA; } DAC960_ExecuteCommand(Command); CommandStatus = Command->V2.CommandStatus; @@ -5690,10 +5998,12 @@ } ErrorCode = CommandStatus; Failure2: - if (DataTransferBuffer != NULL) - kfree(DataTransferBuffer); + pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength), + DataTransferBuffer, DataTransferBufferDMA); if (RequestSenseBuffer != NULL) - kfree(RequestSenseBuffer); + pci_free_consistent(Controller->PCIDevice, RequestSenseLength, + RequestSenseBuffer, RequestSenseBufferDMA); + Failure2a: return ErrorCode; } case DAC960_IOCTL_V2_GET_HEALTH_STATUS: @@ -5740,226 +6050,6 @@ /* - DAC960_KernelIOCTL is the Kernel IOCTL Function for the DAC960 Driver. -*/ - -int DAC960_KernelIOCTL(unsigned int Request, void *Argument) -{ - switch (Request) - { - case DAC960_IOCTL_GET_CONTROLLER_COUNT: - return DAC960_ControllerCount; - case DAC960_IOCTL_GET_CONTROLLER_INFO: - { - DAC960_ControllerInfo_T *ControllerInfo = - (DAC960_ControllerInfo_T *) Argument; - DAC960_Controller_T *Controller; - int ControllerNumber; - if (ControllerInfo == NULL) return -EINVAL; - ControllerNumber = ControllerInfo->ControllerNumber; - if (ControllerNumber < 0 || - ControllerNumber > DAC960_ControllerCount - 1) - return -ENXIO; - Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) return -ENXIO; - memset(ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); - ControllerInfo->ControllerNumber = ControllerNumber; - ControllerInfo->FirmwareType = Controller->FirmwareType; - ControllerInfo->Channels = Controller->Channels; - ControllerInfo->Targets = Controller->Targets; - ControllerInfo->PCI_Bus = Controller->Bus; - ControllerInfo->PCI_Device = Controller->Device; - ControllerInfo->PCI_Function = Controller->Function; - ControllerInfo->IRQ_Channel = Controller->IRQ_Channel; - ControllerInfo->PCI_Address = Controller->PCI_Address; - strcpy(ControllerInfo->ModelName, Controller->ModelName); - strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion); - return 0; - } - case DAC960_IOCTL_V1_EXECUTE_COMMAND: - { - DAC960_V1_KernelCommand_T *KernelCommand = - (DAC960_V1_KernelCommand_T *) Argument; - DAC960_Controller_T *Controller; - DAC960_Command_T *Command = NULL; - DAC960_V1_CommandOpcode_T CommandOpcode; - DAC960_V1_DCDB_T *DCDB = NULL; - ProcessorFlags_T ProcessorFlags; - int ControllerNumber, DataTransferLength; - unsigned char *DataTransferBuffer = NULL; - if (KernelCommand == NULL) return -EINVAL; - ControllerNumber = KernelCommand->ControllerNumber; - if (ControllerNumber < 0 || - ControllerNumber > DAC960_ControllerCount - 1) - return -ENXIO; - Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) return -ENXIO; - if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL; - CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode; - DataTransferLength = KernelCommand->DataTransferLength; - DataTransferBuffer = KernelCommand->DataTransferBuffer; - if (CommandOpcode & 0x80) return -EINVAL; - if (CommandOpcode == DAC960_V1_DCDB) - { - DCDB = KernelCommand->DCDB; - if (DCDB->Channel >= DAC960_V1_MaxChannels) return -EINVAL; - if (!((DataTransferLength == 0 && - DCDB->Direction == DAC960_V1_DCDB_NoDataTransfer) || - (DataTransferLength > 0 && - DCDB->Direction - == DAC960_V1_DCDB_DataTransferDeviceToSystem) || - (DataTransferLength < 0 && - DCDB->Direction - == DAC960_V1_DCDB_DataTransferSystemToDevice))) - return -EINVAL; - if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength) - != abs(DataTransferLength)) - return -EINVAL; - } - if (DataTransferLength != 0 && DataTransferBuffer == NULL) - return -EINVAL; - if (DataTransferLength > 0) - memset(DataTransferBuffer, 0, DataTransferLength); - if (CommandOpcode == DAC960_V1_DCDB) - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - if (!Controller->V1.DirectCommandActive[DCDB->Channel] - [DCDB->TargetID]) - Command = DAC960_AllocateCommand(Controller); - if (Command == NULL) - { - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - return -EBUSY; - } - else Controller->V1.DirectCommandActive[DCDB->Channel] - [DCDB->TargetID] = true; - DAC960_V1_ClearCommand(Command); - Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_V1_CommandMailbox_T)); - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DCDB); - Command->V1.KernelCommand = KernelCommand; - DCDB->BusAddress = Virtual_to_Bus32(DataTransferBuffer); - DAC960_QueueCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - } - else - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - Command = DAC960_AllocateCommand(Controller); - if (Command == NULL) - { - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - return -EBUSY; - } - DAC960_V1_ClearCommand(Command); - Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_V1_CommandMailbox_T)); - if (DataTransferBuffer != NULL) - Command->V1.CommandMailbox.Type3.BusAddress = - Virtual_to_Bus32(DataTransferBuffer); - Command->V1.KernelCommand = KernelCommand; - DAC960_QueueCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - } - return 0; - } - case DAC960_IOCTL_V2_EXECUTE_COMMAND: - { - DAC960_V2_KernelCommand_T *KernelCommand = - (DAC960_V2_KernelCommand_T *) Argument; - DAC960_Controller_T *Controller; - DAC960_Command_T *Command = NULL; - DAC960_V2_CommandMailbox_T *CommandMailbox; - ProcessorFlags_T ProcessorFlags; - int ControllerNumber, DataTransferLength, RequestSenseLength; - unsigned char *DataTransferBuffer = NULL; - unsigned char *RequestSenseBuffer = NULL; - if (KernelCommand == NULL) return -EINVAL; - ControllerNumber = KernelCommand->ControllerNumber; - if (ControllerNumber < 0 || - ControllerNumber > DAC960_ControllerCount - 1) - return -ENXIO; - Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) return -ENXIO; - if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; - DataTransferLength = KernelCommand->DataTransferLength; - RequestSenseLength = KernelCommand->RequestSenseLength; - DataTransferBuffer = KernelCommand->DataTransferBuffer; - RequestSenseBuffer = KernelCommand->RequestSenseBuffer; - if (DataTransferLength != 0 && DataTransferBuffer == NULL) - return -EINVAL; - if (RequestSenseLength < 0) - return -EINVAL; - if (RequestSenseLength > 0 && RequestSenseBuffer == NULL) - return -EINVAL; - if (DataTransferLength > 0) - memset(DataTransferBuffer, 0, DataTransferLength); - if (RequestSenseLength > 0) - memset(RequestSenseBuffer, 0, RequestSenseLength); - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - Command = DAC960_AllocateCommand(Controller); - if (Command == NULL) - { - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - return -EBUSY; - } - DAC960_V2_ClearCommand(Command); - Command->CommandType = DAC960_QueuedCommand; - CommandMailbox = &Command->V2.CommandMailbox; - memcpy(CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_V2_CommandMailbox_T)); - CommandMailbox->Common.CommandControlBits - .AdditionalScatterGatherListMemory = false; - CommandMailbox->Common.CommandControlBits - .NoAutoRequestSense = true; - CommandMailbox->Common.DataTransferSize = 0; - CommandMailbox->Common.DataTransferPageNumber = 0; - memset(&CommandMailbox->Common.DataTransferMemoryAddress, 0, - sizeof(DAC960_V2_DataTransferMemoryAddress_T)); - if (DataTransferLength != 0) - { - if (DataTransferLength > 0) - { - CommandMailbox->Common.CommandControlBits - .DataTransferControllerToHost = true; - CommandMailbox->Common.DataTransferSize = DataTransferLength; - } - else - { - CommandMailbox->Common.CommandControlBits - .DataTransferControllerToHost = false; - CommandMailbox->Common.DataTransferSize = -DataTransferLength; - } - CommandMailbox->Common.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentDataPointer = - Virtual_to_Bus64(DataTransferBuffer); - CommandMailbox->Common.DataTransferMemoryAddress - .ScatterGatherSegments[0] - .SegmentByteCount = - CommandMailbox->Common.DataTransferSize; - } - if (RequestSenseLength > 0) - { - CommandMailbox->Common.CommandControlBits - .NoAutoRequestSense = false; - CommandMailbox->Common.RequestSenseBusAddress = - Virtual_to_Bus64(RequestSenseBuffer); - } - Command->V2.KernelCommand = KernelCommand; - DAC960_QueueCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - return 0; - } - } - return -EINVAL; -} - - -/* DAC960_CheckStatusBuffer verifies that there is room to hold ByteCount additional bytes in the Combined Status Buffer and grows the buffer if necessary. It returns true if there is enough room and false otherwise. @@ -6381,11 +6471,25 @@ else if (strcmp(UserCommand, "cancel-rebuild") == 0 || strcmp(UserCommand, "cancel-consistency-check") == 0) { - unsigned char OldRebuildRateConstant; + /* + the OldRebuildRateConstant is never actually used + once its value is retrieved from the controller. + */ + unsigned char *OldRebuildRateConstant; + dma_addr_t OldRebuildRateConstantDMA; + + OldRebuildRateConstant = pci_alloc_consistent( Controller->PCIDevice, + sizeof(char), &OldRebuildRateConstantDMA); + if (OldRebuildRateConstant == NULL) { + DAC960_UserCritical("Cancellation of Rebuild or " + "Consistency Check Failed - " + "Out of Memory", + Controller); + goto failure; + } CommandMailbox->Type3R.CommandOpcode = DAC960_V1_RebuildControl; CommandMailbox->Type3R.RebuildRateConstant = 0xFF; - CommandMailbox->Type3R.BusAddress = - Virtual_to_Bus32(&OldRebuildRateConstant); + CommandMailbox->Type3R.BusAddress = OldRebuildRateConstantDMA; DAC960_ExecuteCommand(Command); switch (Command->V1.CommandStatus) { @@ -6400,6 +6504,9 @@ Controller, Command->V1.CommandStatus); break; } +failure: + pci_free_consistent(Controller->PCIDevice, sizeof(char), + OldRebuildRateConstant, OldRebuildRateConstantDMA); } else DAC960_UserCritical("Illegal User Command: '%s'\n", Controller, UserCommand); @@ -6423,10 +6530,12 @@ *LogicalDeviceNumber) { DAC960_V2_CommandMailbox_T SavedCommandMailbox, *CommandMailbox; - DAC960_V2_PhysicalToLogicalDevice_T PhysicalToLogicalDevice; + DAC960_Controller_T *Controller = Command->Controller; + CommandMailbox = &Command->V2.CommandMailbox; memcpy(&SavedCommandMailbox, CommandMailbox, sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; CommandMailbox->PhysicalDeviceInfo.CommandControlBits .DataTransferControllerToHost = true; @@ -6441,15 +6550,17 @@ CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&PhysicalToLogicalDevice); + Controller->V2.PhysicalToLogicalDeviceDMA; CommandMailbox->Common.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = - CommandMailbox->Common.DataTransferSize; + CommandMailbox->Common.DataTransferSize; + DAC960_ExecuteCommand(Command); + *LogicalDeviceNumber = Controller->V2.PhysicalToLogicalDevice->LogicalDeviceNumber; + memcpy(CommandMailbox, &SavedCommandMailbox, sizeof(DAC960_V2_CommandMailbox_T)); - *LogicalDeviceNumber = PhysicalToLogicalDevice.LogicalDeviceNumber; return (Command->V2.CommandStatus == DAC960_V2_NormalCompletion); } @@ -6635,16 +6746,20 @@ CommandMailbox->ControllerInfo.ControllerNumber = 0; CommandMailbox->ControllerInfo.IOCTL_Opcode = DAC960_V2_GetControllerInfo; + /* + * How does this NOT race with the queued Monitoring + * usage of this structure? + */ CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentDataPointer = - Virtual_to_Bus64(&Controller->V2.NewControllerInformation); + Controller->V2.NewControllerInformationDMA; CommandMailbox->ControllerInfo.DataTransferMemoryAddress .ScatterGatherSegments[0] .SegmentByteCount = CommandMailbox->ControllerInfo.DataTransferSize; DAC960_ExecuteCommand(Command); - while (Controller->V2.NewControllerInformation.PhysicalScanActive) + while (Controller->V2.NewControllerInformation->PhysicalScanActive) { DAC960_ExecuteCommand(Command); sleep_on_timeout(&Controller->CommandWaitQueue, HZ); @@ -6817,22 +6932,19 @@ DAC960 Driver. */ -static void DAC960_CreateProcEntries(void) +static void DAC960_CreateProcEntries(DAC960_Controller_T *Controller) { - PROC_DirectoryEntry_T *StatusProcEntry; - int ControllerNumber; - DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); - StatusProcEntry = create_proc_read_entry("status", 0, + PROC_DirectoryEntry_T *StatusProcEntry; + PROC_DirectoryEntry_T *ControllerProcEntry; + PROC_DirectoryEntry_T *UserCommandProcEntry; + + if (DAC960_ProcDirectoryEntry == NULL) { + DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); + StatusProcEntry = create_proc_read_entry("status", 0, DAC960_ProcDirectoryEntry, DAC960_ProcReadStatus, NULL); - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - PROC_DirectoryEntry_T *ControllerProcEntry; - PROC_DirectoryEntry_T *UserCommandProcEntry; - if (Controller == NULL) continue; + } + sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); ControllerProcEntry = proc_mkdir(Controller->ControllerName, DAC960_ProcDirectoryEntry); @@ -6846,7 +6958,6 @@ Controller); UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand; Controller->ControllerProcEntry = ControllerProcEntry; - } } @@ -6855,26 +6966,138 @@ DAC960 Driver. */ -static void DAC960_DestroyProcEntries(void) +static void DAC960_DestroyProcEntries(DAC960_Controller_T *Controller) { - int ControllerNumber; - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) continue; + if (Controller->ControllerProcEntry == NULL) + return; remove_proc_entry("initial_status", Controller->ControllerProcEntry); remove_proc_entry("current_status", Controller->ControllerProcEntry); remove_proc_entry("user_command", Controller->ControllerProcEntry); remove_proc_entry(Controller->ControllerName, DAC960_ProcDirectoryEntry); - } - remove_proc_entry("rd/status", NULL); - remove_proc_entry("rd", NULL); + Controller->ControllerProcEntry = NULL; } +static struct DAC960_privdata DAC960_BA_privdata = { + .HardwareType = DAC960_BA_Controller, + .FirmwareType = DAC960_V2_Controller, + .InterruptHandler = DAC960_BA_InterruptHandler, + .MemoryWindowSize = DAC960_BA_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_LP_privdata = { + .HardwareType = DAC960_LP_Controller, + .FirmwareType = DAC960_LP_Controller, + .InterruptHandler = DAC960_LP_InterruptHandler, + .MemoryWindowSize = DAC960_LP_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_LA_privdata = { + .HardwareType = DAC960_LA_Controller, + .FirmwareType = DAC960_V1_Controller, + .InterruptHandler = DAC960_LA_InterruptHandler, + .MemoryWindowSize = DAC960_LA_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_PG_privdata = { + .HardwareType = DAC960_PG_Controller, + .FirmwareType = DAC960_V1_Controller, + .InterruptHandler = DAC960_PG_InterruptHandler, + .MemoryWindowSize = DAC960_PG_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_PD_privdata = { + .HardwareType = DAC960_PD_Controller, + .FirmwareType = DAC960_V1_Controller, + .InterruptHandler = DAC960_PD_InterruptHandler, + .MemoryWindowSize = DAC960_PD_RegisterWindowSize, +}; + +static struct DAC960_privdata DAC960_P_privdata = { + .HardwareType = DAC960_P_Controller, + .FirmwareType = DAC960_V1_Controller, + .InterruptHandler = DAC960_P_InterruptHandler, + .MemoryWindowSize = DAC960_PD_RegisterWindowSize, +}; + +static struct pci_device_id DAC960_id_table[] = { + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_BA, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_BA_privdata, + }, + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_LP, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_LP_privdata, + }, + { + .vendor = PCI_VENDOR_ID_DEC, + .device = PCI_DEVICE_ID_DEC_21285, + .subvendor = PCI_VENDOR_ID_MYLEX, + .subdevice = PCI_DEVICE_ID_MYLEX_DAC960_LA, + .driver_data = (unsigned long) &DAC960_LA_privdata, + }, + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_PG, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_PG_privdata, + }, + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_PD, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_PD_privdata, + }, + { + .vendor = PCI_VENDOR_ID_MYLEX, + .device = PCI_DEVICE_ID_MYLEX_DAC960_P, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) &DAC960_P_privdata, + }, + {0, }, +}; + +MODULE_DEVICE_TABLE(pci, DAC960_id_table); + +static struct pci_driver DAC960_pci_driver = { + .name = "DAC960", + .id_table = DAC960_id_table, + .probe = DAC960_Probe, + .remove = DAC960_Remove, +}; + +static int DAC960_init_module(void) +{ + return pci_module_init(&DAC960_pci_driver); +} + +static void DAC960_cleanup_module(void) +{ + int i; + + for (i = 0; i < DAC960_ControllerCount; i++) { + DAC960_Controller_T *Controller = DAC960_Controllers[i]; + if (Controller == NULL) + continue; + DAC960_FinalizeController(Controller); + } + if (DAC960_ProcDirectoryEntry != NULL) { + remove_proc_entry("rd/status", NULL); + remove_proc_entry("rd", NULL); + } + DAC960_ControllerCount = 0; + pci_unregister_driver(&DAC960_pci_driver); +} -module_init(DAC960_Initialize); -module_exit(DAC960_Finalize); +module_init(DAC960_init_module); +module_exit(DAC960_cleanup_module); MODULE_LICENSE("GPL"); diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h --- a/drivers/block/DAC960.h Wed Nov 27 14:36:31 2002 +++ b/drivers/block/DAC960.h Wed Nov 27 14:36:31 2002 @@ -60,6 +60,17 @@ #define DAC960_V1_MaxPhysicalDevices 45 #define DAC960_V2_MaxPhysicalDevices 272 +/* + Define the pci dma mask supported by DAC960 V1 and V2 Firmware Controlers + + For now set the V2 mask to only 32 bits. The controller IS capable + of doing 64 bit dma. But I have yet to find out whether this needs to + be explicitely enabled in the controller, or of the controller adapts + automatically. + */ + +#define DAC690_V1_PciDmaMask 0xffffffff +#define DAC690_V2_PciDmaMask 0xffffffffffffffff /* Define a Boolean data type. @@ -111,6 +122,20 @@ /* + dma_loaf is used by helper routines to divide a region of + dma mapped memory into smaller pieces, where those pieces + are not of uniform size. + */ + +struct dma_loaf { + void *cpu_base; + dma_addr_t dma_base; + size_t length; + void *cpu_free; + dma_addr_t dma_free; +}; + +/* Define the SCSI INQUIRY Standard Data structure. */ @@ -2059,9 +2084,6 @@ #define DAC960_LogicalDriveNumber(Device) \ (minor(Device) >> DAC960_MaxPartitionsBits) -#define DAC960_PartitionNumber(Device) \ - (minor(Device) & (DAC960_MaxPartitions - 1)) - #define DAC960_MajorNumber(ControllerNumber) \ (DAC960_MAJOR + (ControllerNumber)) @@ -2191,7 +2213,6 @@ of the Linux Kernel and I/O Subsystem. */ -typedef struct bio BufferHeader_T; typedef struct file File_T; typedef struct block_device_operations BlockDeviceOperations_T; typedef struct completion Completion_T; @@ -2200,7 +2221,6 @@ typedef struct inode_operations InodeOperations_T; typedef kdev_t KernelDevice_T; typedef struct list_head ListHead_T; -typedef struct notifier_block NotifierBlock_T; typedef struct pci_dev PCI_Device_T; typedef struct proc_dir_entry PROC_DirectoryEntry_T; typedef unsigned long ProcessorFlags_T; @@ -2211,6 +2231,13 @@ typedef struct timer_list Timer_T; typedef wait_queue_head_t WaitQueue_T; +struct DAC960_privdata { + DAC960_HardwareType_T HardwareType; + DAC960_FirmwareType_T FirmwareType; + void (*InterruptHandler)(int, void *, Registers_T *); + unsigned int MemoryWindowSize; +}; + /* Define the DAC960 V1 Firmware Controller Status Mailbox structure. @@ -2278,16 +2305,16 @@ unsigned int BlockNumber; unsigned int BlockCount; unsigned int SegmentCount; - BufferHeader_T *BufferHeader; - void *RequestBuffer; + IO_Request_T *Request; + struct pci_dev *PciDevice; union { struct { DAC960_V1_CommandMailbox_T CommandMailbox; DAC960_V1_KernelCommand_T *KernelCommand; DAC960_V1_CommandStatus_T CommandStatus; - DAC960_V1_ScatterGatherSegment_T - ScatterGatherList[DAC960_V1_ScatterGatherLimit] - __attribute__ ((aligned (sizeof(DAC960_V1_ScatterGatherSegment_T)))); + DAC960_V1_ScatterGatherSegment_T *ScatterGatherList; + dma_addr_t ScatterGatherListDMA; + struct scatterlist ScatterList[DAC960_V1_ScatterGatherLimit]; unsigned int EndMarker[0]; } V1; struct { @@ -2296,11 +2323,11 @@ DAC960_V2_CommandStatus_T CommandStatus; unsigned char RequestSenseLength; int DataTransferResidue; - DAC960_V2_ScatterGatherSegment_T - ScatterGatherList[DAC960_V2_ScatterGatherLimit] - __attribute__ ((aligned (sizeof(DAC960_V2_ScatterGatherSegment_T)))); - DAC960_SCSI_RequestSense_T RequestSense - __attribute__ ((aligned (sizeof(int)))); + DAC960_V2_ScatterGatherSegment_T *ScatterGatherList; + dma_addr_t ScatterGatherListDMA; + DAC960_SCSI_RequestSense_T *RequestSense; + dma_addr_t RequestSenseDMA; + struct scatterlist ScatterList[DAC960_V2_ScatterGatherLimit]; unsigned int EndMarker[0]; } V2; } FW; @@ -2320,6 +2347,7 @@ DAC960_HardwareType_T HardwareType; DAC960_IO_Address_T IO_Address; DAC960_PCI_Address_T PCI_Address; + PCI_Device_T *PCIDevice; unsigned char ControllerNumber; unsigned char ControllerName[4]; unsigned char ModelName[20]; @@ -2345,14 +2373,13 @@ unsigned int CurrentStatusLength; unsigned int ProgressBufferLength; unsigned int UserStatusLength; - unsigned long MemoryMailboxPagesAddress; - unsigned long MemoryMailboxPagesOrder; + struct dma_loaf DmaPages; unsigned long MonitoringTimerCount; unsigned long PrimaryMonitoringTime; unsigned long SecondaryMonitoringTime; + unsigned long ShutdownMonitoringTimer; unsigned long LastProgressReportTime; unsigned long LastCurrentStatusTime; - boolean ControllerDetectionSuccessful; boolean ControllerInitialized; boolean MonitoringCommandDeferred; boolean EphemeralProgressMessage; @@ -2361,6 +2388,7 @@ boolean SuppressEnclosureMessages; Timer_T MonitoringTimer; struct gendisk *disks[DAC960_MaxLogicalDrives]; + struct pci_pool *ScatterGatherPool; DAC960_Command_T *FreeCommands; unsigned char *CombinedStatusBuffer; unsigned char *CurrentStatusBuffer; @@ -2404,36 +2432,63 @@ boolean RebuildProgressFirst; boolean RebuildFlagPending; boolean RebuildStatusPending; + + dma_addr_t FirstCommandMailboxDMA; DAC960_V1_CommandMailbox_T *FirstCommandMailbox; DAC960_V1_CommandMailbox_T *LastCommandMailbox; DAC960_V1_CommandMailbox_T *NextCommandMailbox; DAC960_V1_CommandMailbox_T *PreviousCommandMailbox1; DAC960_V1_CommandMailbox_T *PreviousCommandMailbox2; + + dma_addr_t FirstStatusMailboxDMA; DAC960_V1_StatusMailbox_T *FirstStatusMailbox; DAC960_V1_StatusMailbox_T *LastStatusMailbox; DAC960_V1_StatusMailbox_T *NextStatusMailbox; - DAC960_V1_DCDB_T MonitoringDCDB; + + DAC960_V1_DCDB_T *MonitoringDCDB; + dma_addr_t MonitoringDCDB_DMA; + DAC960_V1_Enquiry_T Enquiry; - DAC960_V1_Enquiry_T NewEnquiry; + DAC960_V1_Enquiry_T *NewEnquiry; + dma_addr_t NewEnquiryDMA; + DAC960_V1_ErrorTable_T ErrorTable; - DAC960_V1_ErrorTable_T NewErrorTable; - DAC960_V1_EventLogEntry_T EventLogEntry; - DAC960_V1_RebuildProgress_T RebuildProgress; + DAC960_V1_ErrorTable_T *NewErrorTable; + dma_addr_t NewErrorTableDMA; + + DAC960_V1_EventLogEntry_T *EventLogEntry; + dma_addr_t EventLogEntryDMA; + + DAC960_V1_RebuildProgress_T *RebuildProgress; + dma_addr_t RebuildProgressDMA; DAC960_V1_CommandStatus_T LastRebuildStatus; DAC960_V1_CommandStatus_T PendingRebuildStatus; + DAC960_V1_LogicalDriveInformationArray_T LogicalDriveInformation; - DAC960_V1_LogicalDriveInformationArray_T NewLogicalDriveInformation; + DAC960_V1_LogicalDriveInformationArray_T *NewLogicalDriveInformation; + dma_addr_t NewLogicalDriveInformationDMA; + DAC960_V1_BackgroundInitializationStatus_T - BackgroundInitializationStatus; + *BackgroundInitializationStatus; + dma_addr_t BackgroundInitializationStatusDMA; DAC960_V1_BackgroundInitializationStatus_T - LastBackgroundInitializationStatus; + LastBackgroundInitializationStatus; + DAC960_V1_DeviceState_T DeviceState[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; - DAC960_V1_DeviceState_T NewDeviceState; + DAC960_V1_DeviceState_T *NewDeviceState; + dma_addr_t NewDeviceStateDMA; + DAC960_SCSI_Inquiry_T InquiryStandardData[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + DAC960_SCSI_Inquiry_T *NewInquiryStandardData; + dma_addr_t NewInquiryStandardDataDMA; + DAC960_SCSI_Inquiry_UnitSerialNumber_T InquiryUnitSerialNumber[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber; + dma_addr_t NewInquiryUnitSerialNumberDMA; + int DeviceResetCount[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; boolean DirectCommandActive[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; } V1; @@ -2446,28 +2501,50 @@ boolean NeedDeviceSerialNumberInformation; boolean StartLogicalDeviceInformationScan; boolean StartPhysicalDeviceInformationScan; + struct pci_pool *RequestSensePool; + + dma_addr_t FirstCommandMailboxDMA; DAC960_V2_CommandMailbox_T *FirstCommandMailbox; DAC960_V2_CommandMailbox_T *LastCommandMailbox; DAC960_V2_CommandMailbox_T *NextCommandMailbox; DAC960_V2_CommandMailbox_T *PreviousCommandMailbox1; DAC960_V2_CommandMailbox_T *PreviousCommandMailbox2; + + dma_addr_t FirstStatusMailboxDMA; DAC960_V2_StatusMailbox_T *FirstStatusMailbox; DAC960_V2_StatusMailbox_T *LastStatusMailbox; DAC960_V2_StatusMailbox_T *NextStatusMailbox; + + dma_addr_t HealthStatusBufferDMA; DAC960_V2_HealthStatusBuffer_T *HealthStatusBuffer; + DAC960_V2_ControllerInfo_T ControllerInformation; - DAC960_V2_ControllerInfo_T NewControllerInformation; + DAC960_V2_ControllerInfo_T *NewControllerInformation; + dma_addr_t NewControllerInformationDMA; + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInformation[DAC960_MaxLogicalDrives]; - DAC960_V2_LogicalDeviceInfo_T NewLogicalDeviceInformation; + DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInformation; + dma_addr_t NewLogicalDeviceInformationDMA; + DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInformation[DAC960_V2_MaxPhysicalDevices]; - DAC960_V2_PhysicalDeviceInfo_T NewPhysicalDeviceInformation; + DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInformation; + dma_addr_t NewPhysicalDeviceInformationDMA; + + DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber; + dma_addr_t NewInquiryUnitSerialNumberDMA; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber[DAC960_V2_MaxPhysicalDevices]; + + DAC960_V2_Event_T *Event; + dma_addr_t EventDMA; + + DAC960_V2_PhysicalToLogicalDevice_T *PhysicalToLogicalDevice; + dma_addr_t PhysicalToLogicalDeviceDMA; + DAC960_V2_PhysicalDevice_T LogicalDriveToVirtualDevice[DAC960_MaxLogicalDrives]; - DAC960_V2_Event_T Event; boolean LogicalDriveFoundDuringScan[DAC960_MaxLogicalDrives]; } V2; } FW; @@ -2495,16 +2572,47 @@ #define DAC960_QueueReadWriteCommand(Command) \ (Controller->QueueReadWriteCommand)(Command) +/* + * dma_addr_writeql is provided to write dma_addr_t types + * to a 64-bit pci address space register. The controller + * will accept having the register written as two 32-bit + * values. + * + * In HIGHMEM kernels, dma_addr_t is a 64-bit value. + * without HIGHMEM, dma_addr_t is a 32-bit value. + * + * The compiler should always fix up the assignment + * to u.wq appropriately, depending upon the size of + * dma_addr_t. + */ +static inline +void dma_addr_writeql(dma_addr_t addr, void *write_address) +{ + union { + u64 wq; + uint wl[2]; + } u; + + u.wq = addr; + + writel(u.wl[0], write_address); + writel(u.wl[1], write_address + 4); +} /* DAC960_AcquireControllerLock acquires exclusive access to Controller. + Reference the queue_lock through the controller structure, + rather than through the request queue. These macros are + used to mutex on the controller structure during initialization, + BEFORE the request queue is allocated and initialized in + DAC960_RegisterBlockDevice(). */ static inline void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller, ProcessorFlags_T *ProcessorFlags) { - spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags); + spin_lock_irqsave(&Controller->queue_lock, *ProcessorFlags); } @@ -2516,7 +2624,7 @@ void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller, ProcessorFlags_T *ProcessorFlags) { - spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, *ProcessorFlags); } @@ -2553,7 +2661,7 @@ void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller, ProcessorFlags_T *ProcessorFlags) { - spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags); + spin_lock_irqsave(&Controller->queue_lock, *ProcessorFlags); } @@ -2566,10 +2674,9 @@ void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller, ProcessorFlags_T *ProcessorFlags) { - spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, *ProcessorFlags); } -#error I am a non-portable driver, please convert me to use the Documentation/DMA-mapping.txt interfaces /* Define the DAC960 BA Series Controller Interface Register Offsets. @@ -2834,17 +2941,14 @@ mb(); } + static inline void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress, - DAC960_V2_CommandMailbox_T *CommandMailbox) + dma_addr_t CommandMailboxDMA) { -#ifdef __ia64__ - writeq(Virtual_to_Bus64(CommandMailbox), - ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset); -#else - writel(Virtual_to_Bus32(CommandMailbox), - ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset); -#endif + dma_addr_writeql(CommandMailboxDMA, + ControllerBaseAddress + + DAC960_BA_CommandMailboxBusAddressOffset); } static inline DAC960_V2_CommandIdentifier_T @@ -3142,15 +3246,11 @@ static inline void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress, - DAC960_V2_CommandMailbox_T *CommandMailbox) + dma_addr_t CommandMailboxDMA) { -#ifdef __ia64__ - writeq(Virtual_to_Bus64(CommandMailbox), - ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset); -#else - writel(Virtual_to_Bus32(CommandMailbox), - ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset); -#endif + dma_addr_writeql(CommandMailboxDMA, + ControllerBaseAddress + + DAC960_LP_CommandMailboxBusAddressOffset); } static inline DAC960_V2_CommandIdentifier_T @@ -3506,43 +3606,6 @@ return true; } -static inline -void DAC960_LA_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) -{ -#ifdef __i386__ - void *ControllerBaseAddress = Controller->BaseAddress; - writel(0x743C485E, - ControllerBaseAddress + DAC960_LA_CommandOpcodeRegisterOffset); - writel((unsigned long) Controller->V1.FirstCommandMailbox, - ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset); - writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox, - ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset); - writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox, - ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset); -#endif -} - -static inline -void DAC960_LA_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, - void **MemoryMailboxAddress, - short *NextCommandMailboxIndex, - short *NextStatusMailboxIndex) -{ -#ifdef __i386__ - void *ControllerBaseAddress = Controller->BaseAddress; - if (readl(ControllerBaseAddress - + DAC960_LA_CommandOpcodeRegisterOffset) != 0x743C485E) - return; - *MemoryMailboxAddress = - (void *) readl(ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset); - *NextCommandMailboxIndex = - readw(ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset); - *NextStatusMailboxIndex = - readw(ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset); -#endif -} - - /* Define the DAC960 PG Series Controller Interface Register Offsets. */ @@ -3868,43 +3931,6 @@ return true; } -static inline -void DAC960_PG_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) -{ -#ifdef __i386__ - void *ControllerBaseAddress = Controller->BaseAddress; - writel(0x743C485E, - ControllerBaseAddress + DAC960_PG_CommandOpcodeRegisterOffset); - writel((unsigned long) Controller->V1.FirstCommandMailbox, - ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset); - writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox, - ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset); - writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox, - ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset); -#endif -} - -static inline -void DAC960_PG_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, - void **MemoryMailboxAddress, - short *NextCommandMailboxIndex, - short *NextStatusMailboxIndex) -{ -#ifdef __i386__ - void *ControllerBaseAddress = Controller->BaseAddress; - if (readl(ControllerBaseAddress - + DAC960_PG_CommandOpcodeRegisterOffset) != 0x743C485E) - return; - *MemoryMailboxAddress = - (void *) readl(ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset); - *NextCommandMailboxIndex = - readw(ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset); - *NextStatusMailboxIndex = - readw(ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset); -#endif -} - - /* Define the DAC960 PD Series Controller Interface Register Offsets. */ @@ -4206,9 +4232,8 @@ */ static void DAC960_FinalizeController(DAC960_Controller_T *); -static int DAC960_Notifier(NotifierBlock_T *, unsigned long, void *); static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *); -static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *); +static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *); static void DAC960_RequestFunction(RequestQueue_T *); static void DAC960_BA_InterruptHandler(int, void *, Registers_T *); static void DAC960_LP_InterruptHandler(int, void *, Registers_T *); @@ -4225,7 +4250,7 @@ static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long); static void DAC960_Message(DAC960_MessageLevel_T, unsigned char *, DAC960_Controller_T *, ...); -static void DAC960_CreateProcEntries(void); -static void DAC960_DestroyProcEntries(void); +static void DAC960_CreateProcEntries(DAC960_Controller_T *); +static void DAC960_DestroyProcEntries(DAC960_Controller_T *); #endif /* DAC960_DriverVersion */ diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Wed Nov 27 14:36:27 2002 +++ b/drivers/block/ll_rw_blk.c Wed Nov 27 14:36:27 2002 @@ -737,7 +737,7 @@ } -inline int blk_phys_contig_segment(request_queue_t *q, struct bio *bio, +int blk_phys_contig_segment(request_queue_t *q, struct bio *bio, struct bio *nxt) { if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER))) @@ -758,7 +758,7 @@ return 0; } -inline int blk_hw_contig_segment(request_queue_t *q, struct bio *bio, +int blk_hw_contig_segment(request_queue_t *q, struct bio *bio, struct bio *nxt) { if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER))) @@ -956,6 +956,7 @@ */ void blk_plug_device(request_queue_t *q) { + WARN_ON(!irqs_disabled()); if (!blk_queue_plugged(q)) { spin_lock(&blk_plug_lock); list_add_tail(&q->plug_list, &blk_plug_list); @@ -967,8 +968,9 @@ * remove the queue from the plugged list, if present. called with * queue lock held and interrupts disabled. */ -inline int blk_remove_plug(request_queue_t *q) +int blk_remove_plug(request_queue_t *q) { + WARN_ON(!irqs_disabled()); if (blk_queue_plugged(q)) { spin_lock(&blk_plug_lock); list_del_init(&q->plug_list); @@ -1096,28 +1098,27 @@ #define blk_plug_entry(entry) list_entry((entry), request_queue_t, plug_list) void blk_run_queues(void) { - struct list_head local_plug_list; - - INIT_LIST_HEAD(&local_plug_list); + LIST_HEAD(local_plug_list); spin_lock_irq(&blk_plug_lock); /* * this will happen fairly often */ - if (list_empty(&blk_plug_list)) { - spin_unlock_irq(&blk_plug_lock); - return; - } + if (list_empty(&blk_plug_list)) + goto out; list_splice_init(&blk_plug_list, &local_plug_list); - spin_unlock_irq(&blk_plug_lock); while (!list_empty(&local_plug_list)) { request_queue_t *q = blk_plug_entry(local_plug_list.next); + spin_unlock_irq(&blk_plug_lock); q->unplug_fn(q); + spin_lock_irq(&blk_plug_lock); } +out: + spin_unlock_irq(&blk_plug_lock); } static int __blk_cleanup_queue(struct request_list *list) @@ -1958,7 +1959,7 @@ return 1; } -inline void blk_recalc_rq_segments(struct request *rq) +void blk_recalc_rq_segments(struct request *rq) { struct bio *bio; int nr_phys_segs, nr_hw_segs; @@ -1981,7 +1982,7 @@ rq->nr_hw_segments = nr_hw_segs; } -inline void blk_recalc_rq_sectors(struct request *rq, int nsect) +void blk_recalc_rq_sectors(struct request *rq, int nsect) { if (blk_fs_request(rq)) { rq->hard_sector += nsect; diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c --- a/drivers/block/nbd.c Wed Nov 27 14:36:28 2002 +++ b/drivers/block/nbd.c Wed Nov 27 14:36:28 2002 @@ -26,6 +26,8 @@ * reduce number of partial TCP segments sent. * 01-12-6 Fix deadlock condition by making queue locks independant of * the transmit lock. + * 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes. + * * * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall * why not: would need verify_area and friends, would share yet another @@ -89,10 +91,12 @@ oldfs = get_fs(); set_fs(get_ds()); - + /* Allow interception of SIGKILL only + * Don't allow other signals to interrupt the transmission */ spin_lock_irqsave(¤t->sig->siglock, flags); oldset = current->blocked; sigfillset(¤t->blocked); + sigdelsetmask(¤t->blocked, sigmask(SIGKILL)); recalc_sigpending(); spin_unlock_irqrestore(¤t->sig->siglock, flags); @@ -115,6 +119,17 @@ else result = sock_recvmsg(sock, &msg, size, 0); + if (signal_pending(current)) { + siginfo_t info; + spin_lock_irqsave(¤t->sig->siglock, flags); + printk(KERN_WARNING "NBD (pid %d: %s) got signal %d\n", + current->pid, current->comm, + dequeue_signal(¤t->blocked, &info)); + spin_unlock_irqrestore(¤t->sig->siglock, flags); + result = -EINTR; + break; + } + if (result <= 0) { #ifdef PARANOIA printk(KERN_ERR "NBD: %s - sock=%ld at buf=%ld, size=%d returned %d.\n", @@ -154,6 +169,10 @@ down(&lo->tx_lock); + if (!sock || !lo->sock) { + FAIL("Attempted sendmsg to closed socket\n"); + } + result = nbd_xmit(1, sock, (char *) &request, sizeof(request), nbd_cmd(req) == NBD_CMD_WRITE ? MSG_MORE : 0); if (result <= 0) FAIL("Sendmsg failed for control."); @@ -324,11 +343,31 @@ spin_unlock_irq(q->queue_lock); spin_lock(&lo->queue_lock); + + if (!lo->file) { + spin_unlock(&lo->queue_lock); + printk(KERN_ERR "nbd: failed between accept and semaphore, file lost\n"); + req->errors++; + nbd_end_request(req); + spin_lock_irq(q->queue_lock); + continue; + } + list_add(&req->queuelist, &lo->queue_head); spin_unlock(&lo->queue_lock); nbd_send_req(lo, req); + if (req->errors) { + printk(KERN_ERR "nbd: nbd_send_req failed\n"); + spin_lock(&lo->queue_lock); + list_del(&req->queuelist); + spin_unlock(&lo->queue_lock); + nbd_end_request(req); + spin_lock_irq(q->queue_lock); + continue; + } + spin_lock_irq(q->queue_lock); continue; @@ -371,12 +410,14 @@ printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n"); return -EBUSY; } - spin_unlock(&lo->queue_lock); file = lo->file; - if (!file) + if (!file) { + spin_unlock(&lo->queue_lock); return -EINVAL; + } lo->file = NULL; lo->sock = NULL; + spin_unlock(&lo->queue_lock); fput(file); return 0; case NBD_SET_SOCK: @@ -420,6 +461,26 @@ if (!lo->file) return -EINVAL; nbd_do_it(lo); + /* on return tidy up in case we have a signal */ + /* Forcibly shutdown the socket causing all listeners + * to error + * + * FIXME: This code is duplicated from sys_shutdown, but + * there should be a more generic interface rather than + * calling socket ops directly here */ + down(&lo->tx_lock); + printk(KERN_WARNING "nbd: shutting down socket\n"); + lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN); + lo->sock = NULL; + up(&lo->tx_lock); + spin_lock(&lo->queue_lock); + file = lo->file; + lo->file = NULL; + spin_unlock(&lo->queue_lock); + nbd_clear_que(lo); + printk(KERN_WARNING "nbd: queue cleared\n"); + if (file) + fput(file); return lo->harderror; case NBD_CLEAR_QUE: nbd_clear_que(lo); @@ -498,7 +559,7 @@ init_MUTEX(&nbd_dev[i].tx_lock); nbd_dev[i].blksize = 1024; nbd_dev[i].blksize_bits = 10; - nbd_dev[i].bytesize = 0x7ffffc00; /* 2GB */ + nbd_dev[i].bytesize = ((u64)0x7ffffc00) << 10; /* 2TB */ disk->major = MAJOR_NR; disk->first_minor = i; disk->fops = &nbd_fops; diff -Nru a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c --- a/drivers/block/scsi_ioctl.c Wed Nov 27 14:36:32 2002 +++ b/drivers/block/scsi_ioctl.c Wed Nov 27 14:36:32 2002 @@ -7,7 +7,7 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * @@ -16,26 +16,20 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- * */ -#include #include #include #include -#include -#include -#include -#include #include -#include +#include #include #include #include #include +#include -#include "../scsi/scsi.h" #include #include -#include /* Command group 3 is reserved and should never be used. */ const unsigned char scsi_command_size[8] = diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile Wed Nov 27 14:36:32 2002 +++ b/drivers/char/Makefile Wed Nov 27 14:36:32 2002 @@ -77,7 +77,7 @@ obj-$(CONFIG_NWFLASH) += nwflash.o obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o -obj-$(CONFIG_WATCHDOGS) += watchdog/ +obj-$(CONFIG_WATCHDOG) += watchdog/ obj-$(CONFIG_MWAVE) += mwave/ obj-$(CONFIG_AGP) += agp/ obj-$(CONFIG_DRM) += drm/ diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h --- a/drivers/char/agp/agp.h Wed Nov 27 14:36:30 2002 +++ b/drivers/char/agp/agp.h Wed Nov 27 14:36:30 2002 @@ -294,7 +294,14 @@ #define I810_DRAM_ROW_0 0x00000001 #define I810_DRAM_ROW_0_SDRAM 0x00000001 - +/* Intel 7505 registers */ +#define INTEL_I7505_NAPBASELO 0x10 +#define INTEL_I7505_APSIZE 0x74 +#define INTEL_I7505_NCAPID 0x60 +#define INTEL_I7505_NISTAT 0x6c +#define INTEL_I7505_ATTBASE 0x78 +#define INTEL_I7505_ERRSTS 0x42 +#define INTEL_I7505_AGPCTRL 0x70 /* VIA register */ #define VIA_APBASE 0x10 diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c --- a/drivers/char/cyclades.c Wed Nov 27 14:36:28 2002 +++ b/drivers/char/cyclades.c Wed Nov 27 14:36:28 2002 @@ -3434,8 +3434,8 @@ } #ifdef CY_DEBUG_DTR printk("cyc:set_line_char dropping DTR\n"); - printk(" status: 0x%x, - 0x%x\n", cy_readb(base_addr+(CyMSVR1<, All Rights Reserved. - * http://www.kernelconcepts.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 of the License, or (at your option) any later version. - * - * Neither kernel concepts nor Nils Faerber admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 2000 kernel concepts - * developed for - * Jentro AG, Haar/Munich (Germany) - * - * TCO timer driver for i8xx chipsets - * based on softdog.c by Alan Cox - * - * For history and the complete list of supported I/O Controller Hub's - * see i810-tco.c - */ - - -/* - * Some address definitions for the i810 TCO - */ - -#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ -#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ -#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ -#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ -#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ -#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ -#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */ -#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */ -#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */ - -#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c --- a/drivers/char/ip2main.c Wed Nov 27 14:36:32 2002 +++ b/drivers/char/ip2main.c Wed Nov 27 14:36:32 2002 @@ -253,10 +253,6 @@ /***********************/ /* Global module entry functions */ -#ifdef MODULE -int init_module(void); -void cleanup_module(void); -#endif /* Private (static) functions */ static int ip2_open(PTTY, struct file *); diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c --- a/drivers/char/keyboard.c Wed Nov 27 14:36:29 2002 +++ b/drivers/char/keyboard.c Wed Nov 27 14:36:29 2002 @@ -681,8 +681,8 @@ static void k_pad(struct vc_data *vc, unsigned char value, char up_flag) { - static const char *pad_chars = "0123456789+-*/\015,.?()"; - static const char *app_map = "pqrstuvwxylSRQMnnmPQ"; + static const char *pad_chars = "0123456789+-*/\015,.?()#"; + static const char *app_map = "pqrstuvwxylSRQMnnmPQS"; if (up_flag) return; /* no action, if this is a key release */ diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Wed Nov 27 14:36:30 2002 +++ b/drivers/char/mem.c Wed Nov 27 14:36:30 2002 @@ -697,9 +697,6 @@ lp_m68k_init(); #endif misc_init(); -#if CONFIG_QIC02_TAPE - qic02_tape_init(); -#endif #ifdef CONFIG_FTAPE ftape_init(); #endif diff -Nru a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c --- a/drivers/char/rio/riocmd.c Wed Nov 27 14:36:28 2002 +++ b/drivers/char/rio/riocmd.c Wed Nov 27 14:36:28 2002 @@ -462,8 +462,8 @@ rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", PacketP->len,PacketP->len ); rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control); rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum ); - rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, - Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command ); + rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " + "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command ); return TRUE; } diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c --- a/drivers/char/rocket.c Wed Nov 27 14:36:31 2002 +++ b/drivers/char/rocket.c Wed Nov 27 14:36:31 2002 @@ -1330,7 +1330,7 @@ { if (tty) sprintf(buf, "%s%d", tty->driver.name, - MINOR(tty->device) - tty->driver.minor_start + + minor(tty->device) - tty->driver.minor_start + tty->driver.name_base); else strcpy(buf, "NULL tty"); @@ -1794,6 +1794,10 @@ str = "8-port Modem"; max_num_aiops = 1; break; + case 0x8: + str = "mysterious 8 port"; + max_num_aiops = 1; + break; default: str = "(unknown/unsupported)"; max_num_aiops = 0; @@ -1872,6 +1876,10 @@ PCI_DEVICE_ID_RP8M, i, &bus, &device_fn)) if(register_PCI(count+boards_found, bus, device_fn)) count++; + if(!pcibios_find_device(PCI_VENDOR_ID_RP, + 0x8, i, &bus, &device_fn)) + if(register_PCI(count+boards_found, bus, device_fn)) + count++; } return(count); } @@ -2072,6 +2080,7 @@ if (retval < 0) { printk("Couldn't install Rocketport callout driver " "(error %d)\n", -retval); + release_region(controller, 4); return -1; } @@ -2079,6 +2088,7 @@ if (retval < 0) { printk("Couldn't install tty Rocketport driver " "(error %d)\n", -retval); + release_region(controller, 4); return -1; } #ifdef ROCKET_DEBUG_OPEN diff -Nru a/drivers/char/sx.c b/drivers/char/sx.c --- a/drivers/char/sx.c Wed Nov 27 14:36:29 2002 +++ b/drivers/char/sx.c Wed Nov 27 14:36:29 2002 @@ -353,9 +353,11 @@ 0xc8000, 0xd8000, 0xe8000}; static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 0xc8000, 0xd8000, 0xe8000, 0xa0000}; +static int si1_probe_addrs[]= { 0xd0000}; #define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int)) #define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int)) +#define NR_SI1_ADDRS (sizeof(si1_probe_addrs)/sizeof (int)) /* Set the mask to all-ones. This alas, only supports 32 interrupts. @@ -582,6 +584,8 @@ } } else if (IS_EISA_BOARD(board)) { outb(board->irq<<4, board->eisa_base+0xc02); + } else if (IS_SI1_BOARD(board)) { + write_sx_byte (board, SI1_ISA_RESET, 0); // value does not matter } else { /* Gory details of the SI/ISA board */ write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_SET); @@ -656,6 +660,9 @@ } else if (IS_EISA_BOARD(board)) { write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL); outb((board->irq<<4)|4, board->eisa_base+0xc02); + } else if (IS_SI1_BOARD(board)) { + write_sx_byte (board, SI1_ISA_RESET_CLEAR, 0); + write_sx_byte (board, SI1_ISA_INTCL, 0); } else { /* Don't bug me about the clear_set. I haven't the foggiest idea what it's about -- REW */ @@ -681,6 +688,9 @@ SX_CONF_HOSTIRQ); } else if (IS_EISA_BOARD(board)) { inb(board->eisa_base+0xc03); + } else if (IS_SI1_BOARD(board)) { + write_sx_byte (board, SI1_ISA_INTCL,0); + write_sx_byte (board, SI1_ISA_INTCL_CLEAR,0); } else { switch (board->irq) { case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break; @@ -1690,6 +1700,7 @@ if (IS_SX_BOARD (board)) rc = SX_TYPE_SX; if (IS_CF_BOARD (board)) rc = SX_TYPE_CF; if (IS_SI_BOARD (board)) rc = SX_TYPE_SI; + if (IS_SI1_BOARD (board)) rc = SX_TYPE_SI; if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI; sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); break; @@ -2184,13 +2195,20 @@ int i; func_enter(); - sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature %lx.\n", + sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at %lx.\n", board->hw_base, board->base + SI2_ISA_ID_BASE); if (sx_debug & SX_DEBUG_PROBE) my_hd ((char *)(board->base + SI2_ISA_ID_BASE), 0x8); if (!IS_EISA_BOARD(board)) { + if( IS_SI1_BOARD(board) ) + { + for (i=0;i<8;i++) { + write_sx_byte (board, SI2_ISA_ID_BASE+7-i,i); + + } + } for (i=0;i<8;i++) { if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) { return 0; @@ -2198,6 +2216,23 @@ } } + /* Now we're pretty much convinced that there is an SI board here, + but to prevent trouble, we'd better double check that we don't + have an SI1 board when we're probing for an SI2 board.... */ + + write_sx_byte (board, SI2_ISA_ID_BASE,0x10); + if ( IS_SI1_BOARD(board)) { + /* This should be an SI1 board, which has this + location writable... */ + if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) + return 0; + } else { + /* This should be an SI2 board, which has the bottom + 3 bits non-writable... */ + if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) + return 0; + } + printheader (); printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); @@ -2554,6 +2589,21 @@ board->base = (ulong) ioremap(board->hw_base, SI2_ISA_WINDOW_LEN); board->flags &= ~SX_BOARD_TYPE; board->flags |= SI_ISA_BOARD; + board->irq = sx_irqmask ?-1:0; + + if (probe_si (board)) { + found++; + } else { + my_iounmap (board->hw_base, board->base); + } + } + for (i=0;ihw_base = si1_probe_addrs[i]; + board->base2 = + board->base = (ulong) ioremap(board->hw_base, SI1_ISA_WINDOW_LEN); + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SI1_ISA_BOARD; board->irq = sx_irqmask ?-1:0; if (probe_si (board)) { diff -Nru a/drivers/char/sx.h b/drivers/char/sx.h --- a/drivers/char/sx.h Wed Nov 27 14:36:28 2002 +++ b/drivers/char/sx.h Wed Nov 27 14:36:28 2002 @@ -69,6 +69,7 @@ #define SX_CFPCI_BOARD 0x00000008 #define SX_CFISA_BOARD 0x00000010 #define SI_EISA_BOARD 0x00000020 +#define SI1_ISA_BOARD 0x00000040 #define SX_BOARD_PRESENT 0x00001000 #define SX_BOARD_INITIALIZED 0x00002000 @@ -80,6 +81,7 @@ SX_ISA_BOARD | SX_CFISA_BOARD)) #define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD) +#define IS_SI1_BOARD(board) (board->flags & SI1_ISA_BOARD) #define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD) diff -Nru a/drivers/char/sxboards.h b/drivers/char/sxboards.h --- a/drivers/char/sxboards.h Wed Nov 27 14:36:27 2002 +++ b/drivers/char/sxboards.h Wed Nov 27 14:36:27 2002 @@ -46,12 +46,36 @@ #define CARD_BUS(type) ((type>>4)&0xF) #define CARD_PHASE(type) (type&0xF) +#define TYPE_SI1_ISA CARD_TYPE(BUS_ISA,SI1_Z280) #define TYPE_SI2_ISA CARD_TYPE(BUS_ISA,SI2_Z280) #define TYPE_SI2_EISA CARD_TYPE(BUS_EISA,SI2_Z280) #define TYPE_SI2_PCI CARD_TYPE(BUS_PCI,SI2_Z280) #define TYPE_SX_ISA CARD_TYPE(BUS_ISA,SI3_T225) #define TYPE_SX_PCI CARD_TYPE(BUS_PCI,SI3_T225) +/***************************************************************************** +****************************** ****************************** +****************************** Phase 1 Z280 ****************************** +****************************** ****************************** +*****************************************************************************/ + +/* ISA board details... */ +#define SI1_ISA_WINDOW_LEN 0x10000 /* 64 Kbyte shared memory window */ +//#define SI1_ISA_MEMORY_LEN 0x8000 /* Usable memory - unused define*/ +//#define SI1_ISA_ADDR_LOW 0x0A0000 /* Lowest address = 640 Kbyte */ +//#define SI1_ISA_ADDR_HIGH 0xFF8000 /* Highest address = 16Mbyte - 32Kbyte */ +//#define SI2_ISA_ADDR_STEP SI2_ISA_WINDOW_LEN/* ISA board address step */ +//#define SI2_ISA_IRQ_MASK 0x9800 /* IRQs 15,12,11 */ + +/* ISA board, register definitions... */ +//#define SI2_ISA_ID_BASE 0x7FF8 /* READ: Board ID string */ +#define SI1_ISA_RESET 0x8000 /* WRITE: Host Reset */ +#define SI1_ISA_RESET_CLEAR 0xc000 /* WRITE: Host Reset clear*/ +#define SI1_ISA_WAIT 0x9000 /* WRITE: Host wait */ +#define SI1_ISA_WAIT_CLEAR 0xd000 /* WRITE: Host wait clear */ +#define SI1_ISA_INTCL 0xa000 /* WRITE: Host Reset */ +#define SI1_ISA_INTCL_CLEAR 0xe000 /* WRITE: Host Reset */ + /***************************************************************************** ****************************** ****************************** diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c --- a/drivers/char/synclink.c Wed Nov 27 14:36:29 2002 +++ b/drivers/char/synclink.c Wed Nov 27 14:36:29 2002 @@ -875,22 +875,22 @@ * Global linked list of SyncLink devices */ struct mgsl_struct *mgsl_device_list; -int mgsl_device_count; +static int mgsl_device_count; /* * Set this param to non-zero to load eax with the * .text section address and breakpoint on module load. * This is useful for use with gdb and add-symbol-file command. */ -int break_on_load; +static int break_on_load; /* * Driver major number, defaults to zero to get auto * assigned major number. May be forced as module parameter. */ -int ttymajor; +static int ttymajor; -int cuamajor; +static int cuamajor; /* * Array of user specified options for ISA adapters. diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c --- a/drivers/char/tpqic02.c Wed Nov 27 14:36:30 2002 +++ b/drivers/char/tpqic02.c Wed Nov 27 14:36:30 2002 @@ -2759,9 +2759,7 @@ return 0; } /* qic02_tape_init */ -#ifdef MODULE - -void cleanup_module(void) +static void qic02_module_exit(void) { unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME); if (status_zombie == NO) @@ -2777,7 +2775,7 @@ devfs_remove("tpqic150"); } -int init_module(void) +static int qic02_module_init(void) { int retval; retval = qic02_tape_init(); @@ -2788,12 +2786,14 @@ if (!retval && qic02_tape_dynconf.ifc_type) { retval = update_ifc_masks(qic02_tape_dynconf.ifc_type); if (retval) { - cleanup_module(); + qic02_module_exit(); } } # endif return retval; } -#endif MODULE_LICENSE("GPL"); + +module_init(qic02_module_init); +module_exit(qic02_module_exit); diff -Nru a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile --- a/drivers/char/watchdog/Makefile Wed Nov 27 14:36:31 2002 +++ b/drivers/char/watchdog/Makefile Wed Nov 27 14:36:31 2002 @@ -7,21 +7,21 @@ # watchdog dies or is 'borrowed' for some reason the software watchdog # still gives you some cover. -watchdog-$(CONFIG_PCWATCHDOG) += pcwd.o -watchdog-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o -watchdog-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o -watchdog-$(CONFIG_IB700_WDT) += ib700wdt.o -watchdog-$(CONFIG_MIXCOMWD) += mixcomwd.o -watchdog-$(CONFIG_SCx200_WDT) += scx200_wdt.o -watchdog-$(CONFIG_60XX_WDT) += sbc60xxwdt.o -watchdog-$(CONFIG_WDT) += wdt.o -watchdog-$(CONFIG_WDTPCI) += wdt_pci.o -watchdog-$(CONFIG_21285_WATCHDOG) += wdt285.o -watchdog-$(CONFIG_977_WATCHDOG) += wdt977.o -watchdog-$(CONFIG_I810_TCO) += i810-tco.o -watchdog-$(CONFIG_MACHZ_WDT) += machzwd.o -watchdog-$(CONFIG_SH_WDT) += shwdt.o -watchdog-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o -watchdog-$(CONFIG_SOFT_WATCHDOG) += softdog.o +obj-$(CONFIG_PCWATCHDOG) += pcwd.o +obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o +obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o +obj-$(CONFIG_IB700_WDT) += ib700wdt.o +obj-$(CONFIG_MIXCOMWD) += mixcomwd.o +obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o +obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o +obj-$(CONFIG_WDT) += wdt.o +obj-$(CONFIG_WDTPCI) += wdt_pci.o +obj-$(CONFIG_21285_WATCHDOG) += wdt285.o +obj-$(CONFIG_977_WATCHDOG) += wdt977.o +obj-$(CONFIG_I810_TCO) += i810-tco.o +obj-$(CONFIG_MACHZ_WDT) += machzwd.o +obj-$(CONFIG_SH_WDT) += shwdt.o +obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o +obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o include $(TOPDIR)/Rules.make diff -Nru a/drivers/char/watchdog/i810-tco.h b/drivers/char/watchdog/i810-tco.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/i810-tco.h Wed Nov 27 14:36:31 2002 @@ -0,0 +1,42 @@ +/* + * i810-tco 0.05: TCO timer driver for i8xx chipsets + * + * (c) Copyright 2000 kernel concepts , All Rights Reserved. + * http://www.kernelconcepts.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 of the License, or (at your option) any later version. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i8xx chipsets + * based on softdog.c by Alan Cox + * + * For history and the complete list of supported I/O Controller Hub's + * see i810-tco.c + */ + + +/* + * Some address definitions for the i810 TCO + */ + +#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ +#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ +#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ +#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ +#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ +#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ +#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */ +#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */ +#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */ + +#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff -Nru a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c --- a/drivers/char/watchdog/sbc60xxwdt.c Wed Nov 27 14:36:31 2002 +++ b/drivers/char/watchdog/sbc60xxwdt.c Wed Nov 27 14:36:31 2002 @@ -310,15 +310,16 @@ unregister_reboot_notifier(&wdt_notifier); release_region(WDT_START,1); - release_region(WDT_STOP,1); +// release_region(WDT_STOP,1); } static int __init sbc60xxwdt_init(void) { int rc = -EBUSY; - if (!request_region(WDT_STOP, 1, "SBC 60XX WDT")) - goto err_out; +// We cannot reserve 0x45 - the kernel already has! +// if (!request_region(WDT_STOP, 1, "SBC 60XX WDT")) +// goto err_out; if (!request_region(WDT_START, 1, "SBC 60XX WDT")) goto err_out_region1; diff -Nru a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c --- a/drivers/char/watchdog/scx200_wdt.c Wed Nov 27 14:36:31 2002 +++ b/drivers/char/watchdog/scx200_wdt.c Wed Nov 27 14:36:31 2002 @@ -245,13 +245,18 @@ sema_init(&open_semaphore, 1); r = misc_register(&scx200_wdt_miscdev); - if (r) + if (r) { + release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET, + SCx200_WDT_SIZE); return r; + } r = register_reboot_notifier(&scx200_wdt_notifier); if (r) { printk(KERN_ERR NAME ": unable to register reboot notifier"); misc_deregister(&scx200_wdt_miscdev); + release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET, + SCx200_WDT_SIZE); return r; } diff -Nru a/drivers/char/watchdog/wd501p.h b/drivers/char/watchdog/wd501p.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/wd501p.h Wed Nov 27 14:36:27 2002 @@ -0,0 +1,91 @@ +/* + * Industrial Computer Source WDT500/501 driver for Linux 1.3.x + * + * (c) Copyright 1995 CymruNET Ltd + * Innovation Centre + * Singleton Park + * Swansea + * Wales + * UK + * SA2 8PP + * + * http://www.cymru.net + * + * This driver is provided under the GNU General Public License, incorporated + * herein by reference. The driver is provided without warranty or + * support. + * + * Release 0.04. + * + */ + +#include + +#define WDT_COUNT0 (io+0) +#define WDT_COUNT1 (io+1) +#define WDT_COUNT2 (io+2) +#define WDT_CR (io+3) +#define WDT_SR (io+4) /* Start buzzer on PCI write */ +#define WDT_RT (io+5) /* Stop buzzer on PCI write */ +#define WDT_BUZZER (io+6) /* PCI only: rd=disable, wr=enable */ +#define WDT_DC (io+7) + +/* The following are only on the PCI card, they're outside of I/O space on + * the ISA card: */ +#define WDT_CLOCK (io+12) /* COUNT2: rd=16.67MHz, wr=2.0833MHz */ +/* inverted opto isolated reset output: */ +#define WDT_OPTONOTRST (io+13) /* wr=enable, rd=disable */ +/* opto isolated reset output: */ +#define WDT_OPTORST (io+14) /* wr=enable, rd=disable */ +/* programmable outputs: */ +#define WDT_PROGOUT (io+15) /* wr=enable, rd=disable */ + +#define WDC_SR_WCCR 1 /* Active low */ +#define WDC_SR_TGOOD 2 +#define WDC_SR_ISOI0 4 +#define WDC_SR_ISII1 8 +#define WDC_SR_FANGOOD 16 +#define WDC_SR_PSUOVER 32 /* Active low */ +#define WDC_SR_PSUUNDR 64 /* Active low */ +#define WDC_SR_IRQ 128 /* Active low */ + +#ifndef WDT_IS_PCI + +/* + * Feature Map 1 is the active high inputs not supported on your card. + * Feature Map 2 is the active low inputs not supported on your card. + */ + +#ifdef CONFIG_WDT_501 /* Full board */ + +#ifdef CONFIG_WDT501_FAN /* Full board, Fan has no tachometer */ +#define FEATUREMAP1 0 +#define WDT_OPTION_MASK (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT) +#else +#define FEATUREMAP1 WDC_SR_FANGOOD +#define WDT_OPTION_MASK (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2) +#endif + +#define FEATUREMAP2 0 +#endif + +#ifndef CONFIG_WDT_501 +#define CONFIG_WDT_500 +#endif + +#ifdef CONFIG_WDT_500 /* Minimal board */ +#define FEATUREMAP1 (WDC_SR_TGOOD|WDC_SR_FANGOOD) +#define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR) +#define WDT_OPTION_MASK (WDIOF_OVERHEAT) +#endif + +#else + +#define FEATUREMAP1 (WDC_SR_TGOOD|WDC_SR_FANGOOD) +#define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR) +#define WDT_OPTION_MASK (WDIOF_OVERHEAT) +#endif + +#ifndef FEATUREMAP1 +#error "Config option not set" +#endif diff -Nru a/drivers/char/wd501p.h b/drivers/char/wd501p.h --- a/drivers/char/wd501p.h Wed Nov 27 14:36:27 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,91 +0,0 @@ -/* - * Industrial Computer Source WDT500/501 driver for Linux 1.3.x - * - * (c) Copyright 1995 CymruNET Ltd - * Innovation Centre - * Singleton Park - * Swansea - * Wales - * UK - * SA2 8PP - * - * http://www.cymru.net - * - * This driver is provided under the GNU General Public License, incorporated - * herein by reference. The driver is provided without warranty or - * support. - * - * Release 0.04. - * - */ - -#include - -#define WDT_COUNT0 (io+0) -#define WDT_COUNT1 (io+1) -#define WDT_COUNT2 (io+2) -#define WDT_CR (io+3) -#define WDT_SR (io+4) /* Start buzzer on PCI write */ -#define WDT_RT (io+5) /* Stop buzzer on PCI write */ -#define WDT_BUZZER (io+6) /* PCI only: rd=disable, wr=enable */ -#define WDT_DC (io+7) - -/* The following are only on the PCI card, they're outside of I/O space on - * the ISA card: */ -#define WDT_CLOCK (io+12) /* COUNT2: rd=16.67MHz, wr=2.0833MHz */ -/* inverted opto isolated reset output: */ -#define WDT_OPTONOTRST (io+13) /* wr=enable, rd=disable */ -/* opto isolated reset output: */ -#define WDT_OPTORST (io+14) /* wr=enable, rd=disable */ -/* programmable outputs: */ -#define WDT_PROGOUT (io+15) /* wr=enable, rd=disable */ - -#define WDC_SR_WCCR 1 /* Active low */ -#define WDC_SR_TGOOD 2 -#define WDC_SR_ISOI0 4 -#define WDC_SR_ISII1 8 -#define WDC_SR_FANGOOD 16 -#define WDC_SR_PSUOVER 32 /* Active low */ -#define WDC_SR_PSUUNDR 64 /* Active low */ -#define WDC_SR_IRQ 128 /* Active low */ - -#ifndef WDT_IS_PCI - -/* - * Feature Map 1 is the active high inputs not supported on your card. - * Feature Map 2 is the active low inputs not supported on your card. - */ - -#ifdef CONFIG_WDT_501 /* Full board */ - -#ifdef CONFIG_WDT501_FAN /* Full board, Fan has no tachometer */ -#define FEATUREMAP1 0 -#define WDT_OPTION_MASK (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT) -#else -#define FEATUREMAP1 WDC_SR_FANGOOD -#define WDT_OPTION_MASK (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2) -#endif - -#define FEATUREMAP2 0 -#endif - -#ifndef CONFIG_WDT_501 -#define CONFIG_WDT_500 -#endif - -#ifdef CONFIG_WDT_500 /* Minimal board */ -#define FEATUREMAP1 (WDC_SR_TGOOD|WDC_SR_FANGOOD) -#define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR) -#define WDT_OPTION_MASK (WDIOF_OVERHEAT) -#endif - -#else - -#define FEATUREMAP1 (WDC_SR_TGOOD|WDC_SR_FANGOOD) -#define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR) -#define WDT_OPTION_MASK (WDIOF_OVERHEAT) -#endif - -#ifndef FEATUREMAP1 -#error "Config option not set" -#endif diff -Nru a/drivers/hotplug/cpqphp_nvram.c b/drivers/hotplug/cpqphp_nvram.c --- a/drivers/hotplug/cpqphp_nvram.c Wed Nov 27 14:36:31 2002 +++ b/drivers/hotplug/cpqphp_nvram.c Wed Nov 27 14:36:31 2002 @@ -177,12 +177,12 @@ spin_lock_irqsave(&int15_lock, flags); __asm__ ( - "xorl %%ebx,%%ebx - xorl %%edx,%%edx - pushf - push %%cs - cli - call *%6" + "xorl %%ebx,%%ebx\n" \ + "xorl %%edx,%%edx\n" \ + "pushf\n" \ + "push %%cs\n" \ + "cli\n" \ + "call *%6\n" : "=c" (*buf_size), "=a" (ret_val) : "a" (op), "c" (*buf_size), "S" (ev_name), "D" (buffer), "m" (compaq_int15_entry_point) diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c --- a/drivers/i2c/i2c-dev.c Wed Nov 27 14:36:31 2002 +++ b/drivers/i2c/i2c-dev.c Wed Nov 27 14:36:31 2002 @@ -115,6 +115,9 @@ struct i2c_client *client = (struct i2c_client *)file->private_data; + if(count > 8192) + count = 8192; + /* copy user space data to kernel space. */ tmp = kmalloc(count,GFP_KERNEL); if (tmp==NULL) @@ -143,6 +146,9 @@ struct inode *inode = file->f_dentry->d_inode; #endif /* DEBUG */ + if(count > 8192) + count = 8192; + /* copy user space data to kernel space. */ tmp = kmalloc(count,GFP_KERNEL); if (tmp==NULL) diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig --- a/drivers/ide/Kconfig Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/Kconfig Wed Nov 27 14:36:30 2002 @@ -467,17 +467,25 @@ If you say Y here, you need to say Y to "Use DMA by default when available" as well. +config BLK_DEV_CS5520 + tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)" + depends on BLK_DEV_IDEDMA_PCI && EXPERIMENTAL + help + Include support for PIO tuning an virtual DMA on the Cyrix MediaGX + 5510/5520 chipset. This will automatically be detected and + configured if found. + + It is safe to say Y to this question. + config BLK_DEV_CS5530 - tristate "Cyrix CS5530 MediaGX chipset support" - depends on BLK_DEV_IDEDMA_PCI + tristate "Cyrix/National Semiconductor CS5530 MediaGX chipset support" + depends on BLK_DEV_IDEDMA_PCIOA help Include support for UDMA on the Cyrix MediaGX 5530 chipset. This will automatically be detected and configured if found. It is safe to say Y to this question. - People with SCSI-only systems should say N here. If unsure, say Y. - config BLK_DEV_HPT34X tristate "HPT34X chipset support" depends on BLK_DEV_IDEDMA_PCI @@ -524,6 +532,13 @@ ide-probe at boot. It is reported to support DVD II drives, by the manufacturer. +config BLK_DEV_SC1200 + tristate "National SCx200 chipset support" + depends on BLK_DEV_IDEDMA_PCI + help + This driver adds support for the built in IDE on the National + SCx200 series of embedded x86 "Geode" systems + config BLK_DEV_PIIX tristate "Intel PIIXn chipsets support" depends on BLK_DEV_IDEDMA_PCI @@ -616,6 +631,9 @@ config BLK_DEV_SIIMAGE tristate "Silicon Image chipset support" depends on BLK_DEV_IDEDMA_PCI + help + This driver adds PIO/(U)DMA support for the SI CMD680 and SII + 3112 (Serial ATA) chips. config BLK_DEV_SIS5513 tristate "SiS5513 chipset support" diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile --- a/drivers/ide/Makefile Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/Makefile Wed Nov 27 14:36:30 2002 @@ -7,14 +7,14 @@ # Note : at this point, these files are compiled on all systems. # In the future, some of these should be built conditionally. # -export-objs := ide-iops.o ide-taskfile.o ide-proc.o ide.o ide-probe.o ide-dma.o ide-lib.o setup-pci.o +export-objs := ide-iops.o ide-taskfile.o ide-proc.o ide.o ide-probe.o ide-dma.o ide-lib.o setup-pci.o ide-io.o # First come modules that register themselves with the core obj-$(CONFIG_BLK_DEV_IDEPCI) += pci/ # Core IDE code - must come before legacy -obj-$(CONFIG_BLK_DEV_IDE) += ide-probe.o ide-geometry.o ide-iops.o ide-taskfile.o ide.o ide-lib.o +obj-$(CONFIG_BLK_DEV_IDE) += ide-io.o ide-probe.o ide-geometry.o ide-iops.o ide-taskfile.o ide.o ide-lib.o obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/ide-cd.c Wed Nov 27 14:36:30 2002 @@ -2965,10 +2965,8 @@ printk(", %dkB Cache", be16_to_cpu(cap.buffer_size)); -#ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) (void) HWIF(drive)->ide_dma_verbose(drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ printk("\n"); return nslots; diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Wed Nov 27 14:36:29 2002 +++ b/drivers/ide/ide-disk.c Wed Nov 27 14:36:29 2002 @@ -1412,24 +1412,6 @@ return call_idedisk_standby(drive, 0); } -static int call_idedisk_suspend (ide_drive_t *drive, int arg) -{ - ide_task_t args; - u8 suspend = (arg) ? WIN_SLEEPNOW2 : WIN_SLEEPNOW1; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_COMMAND_OFFSET] = suspend; - args.command_type = ide_cmd_type_parser(&args); - return ide_raw_taskfile(drive, &args, NULL); -} - -static int do_idedisk_suspend (ide_drive_t *drive) -{ - if (drive->suspend_reset) - return 1; - - return call_idedisk_suspend(drive, 0); -} - #if 0 static int call_idedisk_checkpower (ide_drive_t *drive, int arg) { @@ -1456,13 +1438,6 @@ } #endif -static int do_idedisk_resume (ide_drive_t *drive) -{ - if (!drive->suspend_reset) - return 1; - return 0; -} - static int do_idedisk_flushcache (ide_drive_t *drive) { ide_task_t args; @@ -1561,6 +1536,39 @@ #endif } +static int idedisk_suspend(struct device *dev, u32 state, u32 level) +{ + ide_drive_t *drive = dev->driver_data; + + printk("Suspending device %p\n", dev->driver_data); + + /* I hope that every freeze operation from the upper levels have + * already been done... + */ + + if (level != SUSPEND_SAVE_STATE) + return 0; + + /* set the drive to standby */ + printk(KERN_INFO "suspending: %s ", drive->name); + do_idedisk_standby(drive); + drive->blocked = 1; + + BUG_ON (HWGROUP(drive)->handler); + return 0; +} + +static int idedisk_resume(struct device *dev, u32 level) +{ + ide_drive_t *drive = dev->driver_data; + + if (level != RESUME_RESTORE_STATE) + return 0; + BUG_ON(!drive->blocked); + drive->blocked = 0; + return 0; +} + static void idedisk_setup (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -1641,10 +1649,8 @@ printk(", CHS=%d/%d/%d", drive->bios_cyl, drive->bios_head, drive->bios_sect); -#ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) (void) HWIF(drive)->ide_dma_verbose(drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ printk("\n"); drive->mult_count = 0; @@ -1671,6 +1677,7 @@ { struct gendisk *g = drive->disk; + do_idedisk_standby(drive); if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if (do_idedisk_flushcache(drive)) printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", @@ -1696,9 +1703,6 @@ .supports_dma = 1, .supports_dsc_overlap = 0, .cleanup = idedisk_cleanup, - .standby = do_idedisk_standby, - .suspend = do_idedisk_suspend, - .resume = do_idedisk_resume, .flushcache = do_idedisk_flushcache, .do_request = do_rw_disk, .sense = idedisk_dump_status, @@ -1709,6 +1713,10 @@ .proc = idedisk_proc, .attach = idedisk_attach, .drives = LIST_HEAD_INIT(idedisk_driver.drives), + .gen_driver = { + .suspend = idedisk_suspend, + .resume = idedisk_resume, + } }; static int idedisk_open(struct inode *inode, struct file *filp) @@ -1835,8 +1843,7 @@ static int idedisk_init (void) { - ide_register_driver(&idedisk_driver); - return 0; + return ide_register_driver(&idedisk_driver); } module_init(idedisk_init); diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c --- a/drivers/ide/ide-dma.c Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/ide-dma.c Wed Nov 27 14:36:30 2002 @@ -90,6 +90,7 @@ #include #include +#define CONFIG_IDEDMA_NEW_DRIVE_LISTINGS #ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS struct drive_list_entry { @@ -145,11 +146,20 @@ }; -int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) +/** + * in_drive_list - look for drive in black/white list + * @id: drive identifier + * @drive_table: list to inspect + * + * Look for a drive in the blacklist and the whitelist tables + * Returns 1 if the drive is found in the table. + */ + +static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) { for ( ; drive_table->id_model ; drive_table++) if ((!strcmp(drive_table->id_model, id->model)) && - ((!strstr(drive_table->id_firmware, id->fw_rev)) || + ((strstr(drive_table->id_firmware, id->fw_rev)) || (!strcmp(drive_table->id_firmware, "ALL")))) return 1; return 0; @@ -189,9 +199,14 @@ #endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ -/* - * dma_intr() is the handler for disk read/write DMA interrupts +/** + * ide_dma_intr - IDE DMA interrupt handler + * @drive: the drive the interrupt is for + * + * Handle an interrupt completing a read/write DMA transfer on an + * IDE device */ + ide_startstop_t ide_dma_intr (ide_drive_t *drive) { u8 stat = 0, dma_stat = 0; @@ -205,7 +220,7 @@ DRIVER(drive)->end_request(drive, 1, rq->nr_sectors); return ide_stopped; } - printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", + printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); } return DRIVER(drive)->error(drive, "dma_intr", stat); @@ -213,6 +228,17 @@ EXPORT_SYMBOL_GPL(ide_dma_intr); +/** + * ide_build_sglist - map IDE scatter gather for DMA I/O + * @drive: the drive to build the DMA table for + * @rq: the request holding the sg list + * + * Perform the PCI mapping magic neccessary to access the source or + * target buffers of a request via PCI DMA. The lower layers of the + * kernel provide the neccessary cache management so that we can + * operate in a portable fashion + */ + static int ide_build_sglist (ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = HWIF(drive); @@ -232,6 +258,17 @@ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); } +/** + * ide_raw_build_sglist - map IDE scatter gather for DMA + * @drive: the drive to build the DMA table for + * @rq: the request holding the sg list + * + * Perform the PCI mapping magic neccessary to access the source or + * target buffers of a taskfile request via PCI DMA. The lower layers + * of the kernel provide the neccessary cache management so that we can + * operate in a portable fashion + */ + static int ide_raw_build_sglist (ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = HWIF(drive); @@ -246,6 +283,9 @@ else hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; #if 1 + if (sector_count > 256) + BUG(); + if (sector_count > 128) { memset(&sg[nents], 0, sizeof(*sg)); sg[nents].page = virt_to_page(virt_addr); @@ -279,11 +319,18 @@ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); } -/* - * ide_build_dmatable() prepares a dma request. - * Returns 0 if all went okay, returns 1 otherwise. - * May also be invoked from trm290.c +/** + * ide_build_dmatable - build IDE DMA table + * + * ide_build_dmatable() prepares a dma request. We map the command + * to get the pci bus addresses of the buffers and then build up + * the PRD table that the IDE layer wants to be fed. The code + * knows about the 64K wrap bug in the CS5530. + * + * Returns 0 if all went okay, returns 1 otherwise. + * May also be invoked from trm290.c */ + int ide_build_dmatable (ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = HWIF(drive); @@ -317,7 +364,7 @@ while (cur_len) { if (count++ >= PRD_ENTRIES) { - printk("%s: DMA table too small\n", drive->name); + printk(KERN_ERR "%s: DMA table too small\n", drive->name); goto use_pio_instead; } else { u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); @@ -335,7 +382,7 @@ * So here we break the 64KB entry into two 32KB entries instead. */ if (count++ >= PRD_ENTRIES) { - printk("%s: DMA table too small\n", drive->name); + printk(KERN_ERR "%s: DMA table too small\n", drive->name); goto use_pio_instead; } *table++ = cpu_to_le32(0x8000); @@ -357,7 +404,7 @@ *--table |= cpu_to_le32(0x80000000); return count; } - printk("%s: empty DMA table?\n", drive->name); + printk(KERN_ERR "%s: empty DMA table?\n", drive->name); use_pio_instead: pci_unmap_sg(hwif->pci_dev, hwif->sg_table, @@ -369,7 +416,17 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable); -/* Teardown mappings after DMA has completed. */ +/** + * ide_destroy_dmatable - clean up DMA mapping + * @drive: The drive to unmap + * + * Teardown mappings after DMA has completed. This must be called + * after the completion of each use of ide_build_dmatable and before + * the next use of ide_build_dmatable. Failure to do so will cause + * an oops as only one mapping can be live for each target at a given + * time. + */ + void ide_destroy_dmatable (ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; @@ -382,6 +439,17 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable); +/** + * config_drive_for_dma - attempt to activate IDE DMA + * @drive: the drive to place in DMA mode + * + * If the drive supports at least mode 2 DMA or UDMA of any kind + * then attempt to place it into DMA mode. Drives that are known to + * support DMA but predate the DMA properties or that are known + * to have DMA handling bugs are also set up appropriately based + * on the good/bad drive lists. + */ + static int config_drive_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -415,15 +483,25 @@ return hwif->ide_dma_off_quietly(drive); } -/* - * 1 dmaing, 2 error, 4 intr +/** + * dma_timer_expiry - handle a DMA timeout + * @drive: Drive that timed out + * + * An IDE DMA transfer timed out. In the event of an error we ask + * the driver to resolve the problem, if a DMA transfer is still + * in progress we continue to wait (arguably we need to add a + * secondary 'I dont care what the drive thinks' timeout here) + * Finally if we have an interrupt but for some reason got the + * timeout first we complete the I/O. This can occur if an + * interrupt is lost or due to bugs. */ + static int dma_timer_expiry (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = hwif->INB(hwif->dma_status); - printk("%s: dma_timer_expiry: dma status == 0x%02x\n", + printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat); if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */ @@ -431,6 +509,8 @@ HWGROUP(drive)->expiry = NULL; /* one free ride for now */ + /* 1 dmaing, 2 error, 4 intr */ + if (dma_stat & 2) { /* ERROR */ (void) hwif->ide_dma_end(drive); return DRIVER(drive)->error(drive, @@ -445,6 +525,14 @@ return 0; } +/** + * __ide_dma_host_off - Generic DMA kill + * @drive: drive to control + * + * Perform the generic IDE controller DMA off operation. This + * works for most IDE bus mastering controllers + */ + int __ide_dma_host_off (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -457,6 +545,13 @@ EXPORT_SYMBOL(__ide_dma_host_off); +/** + * __ide_dma_host_off_quietly - Generic DMA kill + * @drive: drive to control + * + * Turn off the current DMA on this IDE controller. + */ + int __ide_dma_off_quietly (ide_drive_t *drive) { drive->using_dma = 0; @@ -473,14 +568,30 @@ EXPORT_SYMBOL(__ide_dma_off_quietly); +/** + * __ide_dma_host_off - Generic DMA kill + * @drive: drive to control + * + * Turn off the current DMA on this IDE controller. Inform the + * user that DMA has been disabled. + */ + int __ide_dma_off (ide_drive_t *drive) { - printk("%s: DMA disabled\n", drive->name); + printk(KERN_INFO "%s: DMA disabled\n", drive->name); return HWIF(drive)->ide_dma_off_quietly(drive); } EXPORT_SYMBOL(__ide_dma_off); +/** + * __ide_dma_host_on - Enable DMA on a host + * @drive: drive to enable for DMA + * + * Enable DMA on an IDE controller following generic bus mastering + * IDE controller behaviour + */ + int __ide_dma_host_on (ide_drive_t *drive) { if (drive->using_dma) { @@ -496,6 +607,13 @@ EXPORT_SYMBOL(__ide_dma_host_on); +/** + * __ide_dma_on - Enable DMA on a device + * @drive: drive to enable DMA on + * + * Enable IDE DMA for a device on this IDE controller. + */ + int __ide_dma_on (ide_drive_t *drive) { drive->using_dma = 1; @@ -512,6 +630,13 @@ EXPORT_SYMBOL(__ide_dma_on); +/** + * __ide_dma_check - check DMA setup + * @drive: drive to check + * + * Don't use - due for extermination + */ + int __ide_dma_check (ide_drive_t *drive) { return config_drive_for_dma(drive); @@ -519,6 +644,21 @@ EXPORT_SYMBOL(__ide_dma_check); +/** + * ide_start_dma - begin a DMA phase + * @hwif: interface + * @drive: target device + * @reading: set if reading, clear if writing + * + * Build an IDE DMA PRD (IDE speak for scatter gather table) + * and then set up the DMA transfer registers for a device + * that follows generic IDE PCI DMA behaviour. Controllers can + * override this function if they need to + * + * Returns 0 on success. If a PIO fallback is required then 1 + * is returned. + */ + int ide_start_dma(ide_hwif_t *hwif, ide_drive_t *drive, int reading) { struct request *rq = HWGROUP(drive)->rq; @@ -566,6 +706,10 @@ ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; + + if (drive->vdma) + command = (lba48) ? WIN_READ_EXT: WIN_READ; + if (rq->flags & REQ_DRIVE_TASKFILE) { ide_task_t *args = rq->special; command = args->tfRegister[IDE_COMMAND_OFFSET]; @@ -600,6 +744,9 @@ ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; + if (drive->vdma) + command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE; + if (rq->flags & REQ_DRIVE_TASKFILE) { ide_task_t *args = rq->special; command = args->tfRegister[IDE_COMMAND_OFFSET]; @@ -791,9 +938,17 @@ EXPORT_SYMBOL(__ide_dma_verbose); +/** + * __ide_dma_retune - default retune handler + * @drive: drive to retune + * + * Default behaviour when we decide to return the IDE DMA setup. + * The default behaviour is "we don't" + */ + int __ide_dma_retune (ide_drive_t *drive) { - printk("%s: chipset supported call only\n", __FUNCTION__); + printk(KERN_WARNING "%s: chipset supported call only\n", __FUNCTION__); return 1; } @@ -809,7 +964,7 @@ int __ide_dma_timeout (ide_drive_t *drive) { - printk("%s: timeout waiting for DMA\n", drive->name); + printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); if (HWIF(drive)->ide_dma_test_irq(drive)) return 0; @@ -882,7 +1037,7 @@ if ((hwif->dmatable_cpu) && (hwif->sg_table)) return 0; - printk("%s: -- Error, unable to allocate%s%s table(s).\n", + printk(KERN_ERR "%s: -- Error, unable to allocate%s%s table(s).\n", (hwif->dmatable_cpu == NULL) ? " CPU" : "", (hwif->sg_table == NULL) ? " SG DMA" : " DMA", hwif->cds->name); @@ -893,7 +1048,7 @@ int ide_mmio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports) { - printk(" %s: MMIO-DMA at 0x%08lx-0x%08lx", + printk(KERN_INFO " %s: MMIO-DMA at 0x%08lx-0x%08lx", hwif->name, base, base + ports - 1); if (check_mem_region(base, ports)) { printk(" -- Error, MMIO ports already in use.\n"); @@ -905,7 +1060,11 @@ request_region(base+16, hwif->cds->extra, hwif->cds->name); hwif->dma_extra = hwif->cds->extra; } - hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base; + + if(hwif->mate) + hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base; + else + hwif->dma_master = base; if (hwif->dma_base2) { if (!check_mem_region(hwif->dma_base2, ports)) request_mem_region(hwif->dma_base2, ports, hwif->name); @@ -915,7 +1074,7 @@ int ide_iomio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports) { - printk(" %s: BM-DMA at 0x%04lx-0x%04lx", + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, base, base + ports - 1); if (!request_region(base, ports, hwif->name)) { printk(" -- Error, ports in use.\n"); @@ -926,7 +1085,11 @@ request_region(base+16, hwif->cds->extra, hwif->cds->name); hwif->dma_extra = hwif->cds->extra; } - hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base; + + if(hwif->mate) + hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base; + else + hwif->dma_master = base; if (hwif->dma_base2) { if (!request_region(hwif->dma_base2, ports, hwif->name)) { diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/ide-floppy.c Wed Nov 27 14:36:30 2002 @@ -115,6 +115,12 @@ /* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */ #define IDEFLOPPY_DEBUG( fmt, args... ) +#ifndef IDEFLOPPY_DEBUG_LOG +#define debug_log(fmt, args... ) do {} while(0) +#else +#define debug_log printk +#endif + /* * Some drives require a longer irq timeout. @@ -543,9 +549,7 @@ struct request *rq = HWGROUP(drive)->rq; int error; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "Reached idefloppy_end_request\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "Reached idefloppy_end_request\n"); switch (uptodate) { case 0: error = IDEFLOPPY_ERROR_GENERAL; break; @@ -627,7 +631,6 @@ } } -#ifdef CONFIG_BLK_DEV_IDEDMA static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc) { struct request *rq = pc->rq; @@ -636,7 +639,6 @@ while ((bio = rq->bio) != NULL) idefloppy_do_end_request(drive, 1, 0); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * idefloppy_queue_pc_head generates a new packet command request in front @@ -682,25 +684,22 @@ floppy->ascq = result->ascq; floppy->progress_indication = result->sksv[0] & 0x80 ? (u16)get_unaligned((u16 *)(result->sksv+1)):0x10000; -#if IDEFLOPPY_DEBUG_LOG if (floppy->failed_pc) - printk(KERN_INFO "ide-floppy: pc = %x, sense key = %x, " + debug_log(KERN_INFO "ide-floppy: pc = %x, sense key = %x, " "asc = %x, ascq = %x\n", floppy->failed_pc->c[0], result->sense_key, result->asc, result->ascq); else - printk(KERN_INFO "ide-floppy: sense key = %x, asc = %x, " + debug_log(KERN_INFO "ide-floppy: sense key = %x, asc = %x, " "ascq = %x\n", result->sense_key, result->asc, result->ascq); -#endif /* IDEFLOPPY_DEBUG_LOG */ } static void idefloppy_request_sense_callback (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); + if (!floppy->pc->error) { idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); idefloppy_do_end_request(drive, 1, 0); @@ -717,9 +716,7 @@ { idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0); } @@ -781,12 +778,9 @@ struct request *rq = pc->rq; unsigned int temp; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "ide-floppy: Reached %s interrupt handler\n", + debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n", __FUNCTION__); -#endif /* IDEFLOPPY_DEBUG_LOG */ -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { if (HWIF(drive)->ide_dma_end(drive)) { set_bit(PC_DMA_ERROR, &pc->flags); @@ -794,30 +788,23 @@ pc->actually_transferred = pc->request_transfer; idefloppy_update_buffers(drive, pc); } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: DMA finished\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "ide-floppy: DMA finished\n"); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* Clear the interrupt */ status.all = HWIF(drive)->INB(IDE_STATUS_REG); if (!status.b.drq) { /* No more interrupts */ -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "Packet command completed, %d bytes " + debug_log(KERN_INFO "Packet command completed, %d bytes " "transferred\n", pc->actually_transferred); -#endif /* IDEFLOPPY_DEBUG_LOG */ clear_bit(PC_DMA_IN_PROGRESS, &pc->flags); local_irq_enable(); if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { /* Error detected */ -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "ide-floppy: %s: I/O error\n", + debug_log(KERN_INFO "ide-floppy: %s: I/O error\n", drive->name); -#endif /* IDEFLOPPY_DEBUG_LOG */ rq->errors++; if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { printk(KERN_ERR "ide-floppy: I/O error in " @@ -836,14 +823,14 @@ pc->callback(drive); return ide_stopped; } -#ifdef CONFIG_BLK_DEV_IDEDMA + if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { printk(KERN_ERR "ide-floppy: The floppy wants to issue " "more interrupts in DMA mode\n"); (void) HWIF(drive)->ide_dma_off(drive); return ide_do_reset(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ + /* Get the number of bytes to transfer */ bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG); bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG); @@ -879,11 +866,9 @@ NULL); return ide_started; } -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_NOTICE "ide-floppy: The floppy wants to " + debug_log(KERN_NOTICE "ide-floppy: The floppy wants to " "send us more data than expected - " "allowing transfer\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ } } if (test_bit(PC_WRITING, &pc->flags)) { @@ -1047,9 +1032,8 @@ pc->callback(drive); return ide_stopped; } -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "Retry number - %d\n",pc->retries); -#endif /* IDEFLOPPY_DEBUG_LOG */ + + debug_log(KERN_INFO "Retry number - %d\n",pc->retries); pc->retries++; /* We haven't transferred any data yet */ @@ -1057,13 +1041,11 @@ pc->current_position = pc->buffer; bcount.all = min(pc->request_transfer, 63 * 1024); -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { (void) HWIF(drive)->ide_dma_off(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ feature.all = 0; -#ifdef CONFIG_BLK_DEV_IDEDMA + if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { if (test_bit(PC_WRITING, &pc->flags)) { feature.b.dma = !HWIF(drive)->ide_dma_write(drive); @@ -1071,7 +1053,6 @@ feature.b.dma = !HWIF(drive)->ide_dma_read(drive); } } -#endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); @@ -1081,12 +1062,10 @@ HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG); HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA if (feature.b.dma) { /* Begin DMA, if necessary */ set_bit(PC_DMA_IN_PROGRESS, &pc->flags); (void) (HWIF(drive)->ide_dma_begin(drive)); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* Can we transfer the packet when we get the interrupt or wait? */ if (test_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) { @@ -1116,9 +1095,7 @@ static void idefloppy_rw_callback (ide_drive_t *drive) { -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); idefloppy_do_end_request(drive, 1, 0); return; @@ -1126,10 +1103,8 @@ static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent) { -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "ide-floppy: creating prevent removal command, " + debug_log(KERN_INFO "ide-floppy: creating prevent removal command, " "prevent = %d\n", prevent); -#endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_init_pc(pc); pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD; @@ -1212,11 +1187,9 @@ int blocks = rq->nr_sectors / floppy->bs_factor; int cmd = rq_data_dir(rq); -#if IDEFLOPPY_DEBUG_LOG - printk("create_rw1%d_cmd: block == %d, blocks == %d\n", + debug_log("create_rw1%d_cmd: block == %d, blocks == %d\n", 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks); -#endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_init_pc(pc); if (test_bit(IDEFLOPPY_USE_READ12, &floppy->flags)) { @@ -1262,14 +1235,12 @@ idefloppy_pc_t *pc; unsigned long block = (unsigned long)block_s; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n", + debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n", rq->rq_status, rq->rq_disk->disk_name, rq->flags, rq->errors); - printk(KERN_INFO "sector: %ld, nr_sectors: %ld, " - "current_nr_sectors: %ld\n", (long)rq->sector, + debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, " + "current_nr_sectors: %d\n", (long)rq->sector, rq->nr_sectors, rq->current_nr_sectors); -#endif /* IDEFLOPPY_DEBUG_LOG */ if (rq->errors >= ERROR_MAX) { if (floppy->failed_pc != NULL) @@ -1473,10 +1444,10 @@ } } if (!i) { - IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", + debug_log( "Descriptor 0 Code: %d\n", descriptor->dc); } - IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d " + debug_log( "Descriptor %d: %dkB, %d blocks, %d " "sector size\n", i, blocks * length / 1024, blocks, length); } @@ -1909,9 +1880,7 @@ drive->usage++; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "Reached idefloppy_open\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "Reached idefloppy_open\n"); if (drive->usage == 1) { clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); @@ -1958,9 +1927,7 @@ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; idefloppy_pc_t pc; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_release\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "Reached idefloppy_release\n"); if (drive->usage == 1) { idefloppy_floppy_t *floppy = drive->driver_data; diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ide/ide-io.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,1320 @@ +/* + * IDE I/O functions + * + * Basic PIO and command management functionality. + * + * This code was split off from ide.c. See ide.c for history and original + * copyrights. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open non patent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ide_modes.h" + +#if (DISK_RECOVERY_TIME > 0) + +Error So the User Has To Fix the Compilation And Stop Hacking Port 0x43 +Does anyone ever use this anyway ?? + +/* + * For really screwy hardware (hey, at least it *can* be used with Linux) + * we can enforce a minimum delay time between successive operations. + */ +static unsigned long read_timer (ide_hwif_t *hwif) +{ + unsigned long t, flags; + int i; + + /* FIXME this is completely unsafe! */ + local_irq_save(flags); + t = jiffies * 11932; + outb_p(0, 0x43); + i = inb_p(0x40); + i |= inb_p(0x40) << 8; + local_irq_restore(flags); + return (t - i); +} +#endif /* DISK_RECOVERY_TIME */ + +static inline void set_recovery_timer (ide_hwif_t *hwif) +{ +#if (DISK_RECOVERY_TIME > 0) + hwif->last_time = read_timer(hwif); +#endif /* DISK_RECOVERY_TIME */ +} + +/** + * ide_end_request - complete an IDE I/O + * @drive: IDE device for the I/O + * @uptodate: + * @nr_sectors: number of sectors completed + * + * This is our end_request wrapper function. We complete the I/O + * update random number input and dequeue the request, which if + * it was tagged may be out of order. + */ + +int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&ide_lock, flags); + rq = HWGROUP(drive)->rq; + + BUG_ON(!(rq->flags & REQ_STARTED)); + + if (!nr_sectors) + nr_sectors = rq->hard_cur_sectors; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->ide_dma_on(drive); + } + + if (!end_that_request_first(rq, uptodate, nr_sectors)) { + add_disk_randomness(rq->rq_disk); + if (!blk_rq_tagged(rq)) + blkdev_dequeue_request(rq); + else + blk_queue_end_tag(&drive->queue, rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&ide_lock, flags); + return ret; +} + +EXPORT_SYMBOL(ide_end_request); + +/** + * ide_end_drive_cmd - end an explicit drive command + * @drive: command + * @stat: status bits + * @err: error bits + * + * Clean up after success/failure of an explicit drive command. + * These get thrown onto the queue so they are synchronized with + * real I/O operations on the drive. + * + * In LBA48 mode we have to read the register set twice to get + * all the extra information out. + */ + +void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long flags; + struct request *rq; + + spin_lock_irqsave(&ide_lock, flags); + rq = HWGROUP(drive)->rq; + spin_unlock_irqrestore(&ide_lock, flags); + + if (rq->flags & REQ_DRIVE_CMD) { + u8 *args = (u8 *) rq->buffer; + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + + if (args) { + args[0] = stat; + args[1] = err; + args[2] = hwif->INB(IDE_NSECTOR_REG); + } + } else if (rq->flags & REQ_DRIVE_TASK) { + u8 *args = (u8 *) rq->buffer; + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + + if (args) { + args[0] = stat; + args[1] = err; + args[2] = hwif->INB(IDE_NSECTOR_REG); + args[3] = hwif->INB(IDE_SECTOR_REG); + args[4] = hwif->INB(IDE_LCYL_REG); + args[5] = hwif->INB(IDE_HCYL_REG); + args[6] = hwif->INB(IDE_SELECT_REG); + } + } else if (rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *args = (ide_task_t *) rq->special; + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + + if (args) { + if (args->tf_in_flags.b.data) { + u16 data = hwif->INW(IDE_DATA_REG); + args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; + args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; + } + args->tfRegister[IDE_ERROR_OFFSET] = err; + args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); + args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); + args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); + args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); + args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); + args->tfRegister[IDE_STATUS_OFFSET] = stat; + + if (drive->addressing == 1) { + hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB); + args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG); + args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG); + args->hobRegister[IDE_SECTOR_OFFSET_HOB] = hwif->INB(IDE_SECTOR_REG); + args->hobRegister[IDE_LCYL_OFFSET_HOB] = hwif->INB(IDE_LCYL_REG); + args->hobRegister[IDE_HCYL_OFFSET_HOB] = hwif->INB(IDE_HCYL_REG); + } + } + } + + spin_lock_irqsave(&ide_lock, flags); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + spin_unlock_irqrestore(&ide_lock, flags); +} + +EXPORT_SYMBOL(ide_end_drive_cmd); + +/** + * try_to_flush_leftover_data - flush junk + * @drive: drive to flush + * + * try_to_flush_leftover_data() is invoked in response to a drive + * unexpectedly having its DRQ_STAT bit set. As an alternative to + * resetting the drive, this routine tries to clear the condition + * by read a sector's worth of data from the drive. Of course, + * this may not help if the drive is *waiting* for data from *us*. + */ +void try_to_flush_leftover_data (ide_drive_t *drive) +{ + int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; + + if (drive->media != ide_disk) + return; + while (i > 0) { + u32 buffer[16]; + u32 wcount = (i > 16) ? 16 : i; + + i -= wcount; + HWIF(drive)->ata_input_data(drive, buffer, wcount); + } +} + +EXPORT_SYMBOL(try_to_flush_leftover_data); + +/* + * FIXME Add an ATAPI error + */ + +/** + * ide_error - handle an error on the IDE + * @drive: drive the error occurred on + * @msg: message to report + * @stat: status bits + * + * ide_error() takes action based on the error returned by the drive. + * For normal I/O that may well include retries. We deal with + * both new-style (taskfile) and old style command handling here. + * In the case of taskfile command handling there is work left to + * do + */ + +ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) +{ + ide_hwif_t *hwif; + struct request *rq; + u8 err; + + err = ide_dump_status(drive, msg, stat); + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + + hwif = HWIF(drive); + /* retry only "normal" I/O: */ + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) { + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); + return ide_stopped; + } + if (rq->flags & REQ_DRIVE_TASKFILE) { + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); +// ide_end_taskfile(drive, stat, err); + return ide_stopped; + } + + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } else { + if (drive->media != ide_disk) + goto media_out; + + if (stat & ERR_STAT) { + /* err has different meaning on cdrom and tape */ + if (err == ABRT_ERR) { + if (drive->select.b.lba && + (hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)) + /* some newer drives don't + * support WIN_SPECIFY + */ + return ide_stopped; + } else if ((err & BAD_CRC) == BAD_CRC) { + drive->crc_count++; + /* UDMA crc error -- just retry the operation */ + } else if (err & (BBD_ERR | ECC_ERR)) { + /* retries won't help these */ + rq->errors = ERROR_MAX; + } else if (err & TRK0_ERR) { + /* help it find track zero */ + rq->errors |= ERROR_RECAL; + } + } +media_out: + if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE) + try_to_flush_leftover_data(drive); + } + if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) { + /* force an abort */ + hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); + } + if (rq->errors >= ERROR_MAX) { + if (drive->driver != NULL) + DRIVER(drive)->end_request(drive, 0, 0); + else + ide_end_request(drive, 0, 0); + } else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + drive->special.b.recalibrate = 1; + ++rq->errors; + } + return ide_stopped; +} + +EXPORT_SYMBOL(ide_error); + +/** + * ide_cmd - issue a simple drive command + * @drive: drive the command is for + * @cmd: command byte + * @nsect: sector byte + * @handler: handler for the command completion + * + * Issue a simple drive command with interrupts. + * The drive must be selected beforehand. + */ + +void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler) +{ + ide_hwif_t *hwif = HWIF(drive); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, handler, WAIT_CMD, NULL); + if (IDE_CONTROL_REG) + hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(drive,0); + hwif->OUTB(nsect,IDE_NSECTOR_REG); + hwif->OUTB(cmd,IDE_COMMAND_REG); +} + +EXPORT_SYMBOL(ide_cmd); + +/** + * drive_cmd_intr - drive command completion interrupt + * @drive: drive the completion interrupt occurred on + * + * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. + * We do any neccessary daya reading and then wait for the drive to + * go non busy. At that point we may read the error data and complete + * the request + */ + +ide_startstop_t drive_cmd_intr (ide_drive_t *drive) +{ + struct request *rq = HWGROUP(drive)->rq; + ide_hwif_t *hwif = HWIF(drive); + u8 *args = (u8 *) rq->buffer; + u8 stat = hwif->INB(IDE_STATUS_REG); + int retries = 10; + + local_irq_enable(); + if ((stat & DRQ_STAT) && args && args[3]) { + u8 io_32bit = drive->io_32bit; + drive->io_32bit = 0; + hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); + drive->io_32bit = io_32bit; + while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) + udelay(100); + } + + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) + return DRIVER(drive)->error(drive, "drive_cmd", stat); + /* calls ide_end_drive_cmd */ + ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); + return ide_stopped; +} + +EXPORT_SYMBOL(drive_cmd_intr); + +/** + * do_special - issue some special commands + * @drive: drive the command is for + * + * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT + * commands to a drive. It used to do much more, but has been scaled + * back. + */ + +ide_startstop_t do_special (ide_drive_t *drive) +{ + special_t *s = &drive->special; + +#ifdef DEBUG + printk("%s: do_special: 0x%02x\n", drive->name, s->all); +#endif + if (s->b.set_tune) { + s->b.set_tune = 0; + if (HWIF(drive)->tuneproc != NULL) + HWIF(drive)->tuneproc(drive, drive->tune_req); + } else if (drive->driver != NULL) { + return DRIVER(drive)->special(drive); + } else if (s->all) { + printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, s->all); + s->all = 0; + } + return ide_stopped; +} + +EXPORT_SYMBOL(do_special); + +/** + * execute_drive_command - issue special drive command + * @drive: the drive to issue th command on + * @rq: the request structure holding the command + * + * execute_drive_cmd() issues a special drive command, usually + * initiated by ioctl() from the external hdparm program. The + * command can be a drive command, drive task or taskfile + * operation. Weirdly you can call it with NULL to wait for + * all commands to finish. Don't do this as that is due to change + */ + +ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) +{ + ide_hwif_t *hwif = HWIF(drive); + if (rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + + if (!args) + goto done; + + if (args->tf_out_flags.all != 0) + return flagged_taskfile(drive, args); + return do_rw_taskfile(drive, args); + } else if (rq->flags & REQ_DRIVE_TASK) { + u8 *args = rq->buffer; + u8 sel; + + if (!args) + goto done; +#ifdef DEBUG + printk("%s: DRIVE_TASK_CMD ", drive->name); + printk("cmd=0x%02x ", args[0]); + printk("fr=0x%02x ", args[1]); + printk("ns=0x%02x ", args[2]); + printk("sc=0x%02x ", args[3]); + printk("lcyl=0x%02x ", args[4]); + printk("hcyl=0x%02x ", args[5]); + printk("sel=0x%02x\n", args[6]); +#endif + hwif->OUTB(args[1], IDE_FEATURE_REG); + hwif->OUTB(args[3], IDE_SECTOR_REG); + hwif->OUTB(args[4], IDE_LCYL_REG); + hwif->OUTB(args[5], IDE_HCYL_REG); + sel = (args[6] & ~0x10); + if (drive->select.b.unit) + sel |= 0x10; + hwif->OUTB(sel, IDE_SELECT_REG); + ide_cmd(drive, args[0], args[2], &drive_cmd_intr); + return ide_started; + } else if (rq->flags & REQ_DRIVE_CMD) { + u8 *args = rq->buffer; + + if (!args) + goto done; +#ifdef DEBUG + printk("%s: DRIVE_CMD ", drive->name); + printk("cmd=0x%02x ", args[0]); + printk("sc=0x%02x ", args[1]); + printk("fr=0x%02x ", args[2]); + printk("xx=0x%02x\n", args[3]); +#endif + if (args[0] == WIN_SMART) { + hwif->OUTB(0x4f, IDE_LCYL_REG); + hwif->OUTB(0xc2, IDE_HCYL_REG); + hwif->OUTB(args[2],IDE_FEATURE_REG); + hwif->OUTB(args[1],IDE_SECTOR_REG); + ide_cmd(drive, args[0], args[3], &drive_cmd_intr); + return ide_started; + } + hwif->OUTB(args[2],IDE_FEATURE_REG); + ide_cmd(drive, args[0], args[1], &drive_cmd_intr); + return ide_started; + } + +done: + /* + * NULL is actually a valid way of waiting for + * all current requests to be flushed from the queue. + */ +#ifdef DEBUG + printk("%s: DRIVE_CMD (null)\n", drive->name); +#endif + ide_end_drive_cmd(drive, + hwif->INB(IDE_STATUS_REG), + hwif->INB(IDE_ERROR_REG)); + return ide_stopped; +} + +EXPORT_SYMBOL(execute_drive_cmd); + +/** + * start_request - start of I/O and command issuing for IDE + * + * start_request() initiates handling of a new I/O request. It + * accepts commands and I/O (read/write) requests. It also does + * the final remapping for weird stuff like EZDrive. Once + * device mapper can work sector level the EZDrive stuff can go away + * + * FIXME: this function needs a rename + */ + +ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) +{ + ide_startstop_t startstop; + unsigned long block; + + BUG_ON(!(rq->flags & REQ_STARTED)); + +#ifdef DEBUG + printk("%s: start_request: current=0x%08lx\n", + HWIF(drive)->name, (unsigned long) rq); +#endif + + /* bail early if we've exceeded max_failures */ + if (drive->max_failures && (drive->failures > drive->max_failures)) { + goto kill_rq; + } + + /* + * bail early if we've sent a device to sleep, however how to wake + * this needs to be a masked flag. FIXME for proper operations. + */ + if (drive->suspend_reset) + goto kill_rq; + + block = rq->sector; + if (blk_fs_request(rq) && + (drive->media == ide_disk || drive->media == ide_floppy)) { + block += drive->sect0; + } + /* Yecch - this will shift the entire interval, + possibly killing some innocent following sector */ + if (block == 0 && drive->remap_0_to_1 == 1) + block = 1; /* redirect MBR access to EZ-Drive partn table */ + +#if (DISK_RECOVERY_TIME > 0) + while ((read_timer() - HWIF(drive)->last_time) < DISK_RECOVERY_TIME); +#endif + + SELECT_DRIVE(drive); + if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { + printk(KERN_ERR "%s: drive not ready for command\n", drive->name); + return startstop; + } + if (!drive->special.all) { + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) + return execute_drive_cmd(drive, rq); + else if (rq->flags & REQ_DRIVE_TASKFILE) + return execute_drive_cmd(drive, rq); + + if (drive->driver != NULL) { + return (DRIVER(drive)->do_request(drive, rq, block)); + } + printk(KERN_ERR "%s: media type %d not supported\n", drive->name, drive->media); + goto kill_rq; + } + return do_special(drive); +kill_rq: + if (drive->driver != NULL) + DRIVER(drive)->end_request(drive, 0, 0); + else + ide_end_request(drive, 0, 0); + return ide_stopped; +} + +EXPORT_SYMBOL(start_request); + +/** + * restart_request - reissue an IDE request + * @drive: drive for request + * @rq: request to reissue + * + * Reissue a request. See start_request for details and for + * FIXME + */ + +int restart_request (ide_drive_t *drive, struct request *rq) +{ + (void) start_request(drive, rq); + return 0; +} + +EXPORT_SYMBOL(restart_request); + +/** + * ide_stall_queue - pause an IDE device + * @drive: drive to stall + * @timeout: time to stall for (jiffies) + * + * ide_stall_queue() can be used by a drive to give excess bandwidth back + * to the hwgroup by sleeping for timeout jiffies. + */ + +void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) +{ + if (timeout > WAIT_WORSTCASE) + timeout = WAIT_WORSTCASE; + drive->sleep = timeout + jiffies; +} + +EXPORT_SYMBOL(ide_stall_queue); + +#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) + +/** + * choose_drive - select a drive to service + * @hwgroup: hardware group to select on + * + * choose_drive() selects the next drive which will be serviced. + * This is neccessary because the IDE layer can't issue commands + * to both drives on the same cable, unlike SCSI. + */ + +static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) +{ + ide_drive_t *drive, *best; + +repeat: + best = NULL; + drive = hwgroup->drive; + do { + if (!blk_queue_empty(&drive->queue) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) { + if (!best + || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) + || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) + { + if (!blk_queue_plugged(&drive->queue)) + best = drive; + } + } + } while ((drive = drive->next) != hwgroup->drive); + if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { + long t = (signed long)(WAKEUP(best) - jiffies); + if (t >= WAIT_MIN_SLEEP) { + /* + * We *may* have some time to spare, but first let's see if + * someone can potentially benefit from our nice mood today.. + */ + drive = best->next; + do { + if (!drive->sleep + /* FIXME: use time_before */ + && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time)) + && 0 < (signed long)((jiffies + t) - WAKEUP(drive))) + { + ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP)); + goto repeat; + } + } while ((drive = drive->next) != best); + } + } + return best; +} + +/* + * Issue a new request to a drive from hwgroup + * Caller must have already done spin_lock_irqsave(&ide_lock, ..); + * + * A hwgroup is a serialized group of IDE interfaces. Usually there is + * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) + * may have both interfaces in a single hwgroup to "serialize" access. + * Or possibly multiple ISA interfaces can share a common IRQ by being grouped + * together into one hwgroup for serialized access. + * + * Note also that several hwgroups can end up sharing a single IRQ, + * possibly along with many other devices. This is especially common in + * PCI-based systems with off-board IDE controller cards. + * + * The IDE driver uses the single global ide_lock spinlock to protect + * access to the request queues, and to protect the hwgroup->busy flag. + * + * The first thread into the driver for a particular hwgroup sets the + * hwgroup->busy flag to indicate that this hwgroup is now active, + * and then initiates processing of the top request from the request queue. + * + * Other threads attempting entry notice the busy setting, and will simply + * queue their new requests and exit immediately. Note that hwgroup->busy + * remains set even when the driver is merely awaiting the next interrupt. + * Thus, the meaning is "this hwgroup is busy processing a request". + * + * When processing of a request completes, the completing thread or IRQ-handler + * will start the next request from the queue. If no more work remains, + * the driver will clear the hwgroup->busy flag and exit. + * + * The ide_lock (spinlock) is used to protect all access to the + * hwgroup->busy flag, but is otherwise not needed for most processing in + * the driver. This makes the driver much more friendlier to shared IRQs + * than previous designs, while remaining 100% (?) SMP safe and capable. + */ +/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back + * into life on wakeup from machine sleep. + */ +void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) +{ + ide_drive_t *drive; + ide_hwif_t *hwif; + struct request *rq; + ide_startstop_t startstop; + + /* for atari only: POSSIBLY BROKEN HERE(?) */ + ide_get_lock(&ide_intr_lock, ide_intr, hwgroup); + + /* necessary paranoia: ensure IRQs are masked on local CPU */ + local_irq_disable(); + + while (!hwgroup->busy) { + hwgroup->busy = 1; + drive = choose_drive(hwgroup); + if (drive == NULL) { + unsigned long sleep = 0; + hwgroup->rq = NULL; + drive = hwgroup->drive; + do { + if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep))) + sleep = drive->sleep; + } while ((drive = drive->next) != hwgroup->drive); + if (sleep) { + /* + * Take a short snooze, and then wake up this hwgroup again. + * This gives other hwgroups on the same a chance to + * play fairly with us, just in case there are big differences + * in relative throughputs.. don't want to hog the cpu too much. + */ + if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) + sleep = jiffies + WAIT_MIN_SLEEP; +#if 1 + if (timer_pending(&hwgroup->timer)) + printk(KERN_CRIT "ide_set_handler: timer already active\n"); +#endif + /* so that ide_timer_expiry knows what to do */ + hwgroup->sleeping = 1; + mod_timer(&hwgroup->timer, sleep); + /* we purposely leave hwgroup->busy==1 + * while sleeping */ + } else { + /* Ugly, but how can we sleep for the lock + * otherwise? perhaps from tq_disk? + */ + + /* for atari only */ + ide_release_lock(&ide_intr_lock); + hwgroup->busy = 0; + } + + /* no more work for this hwgroup (for now) */ + return; + } + hwif = HWIF(drive); + if (hwgroup->hwif->sharing_irq && + hwif != hwgroup->hwif && + hwif->io_ports[IDE_CONTROL_OFFSET]) { + /* set nIEN for previous hwif */ + SELECT_INTERRUPT(drive); + } + hwgroup->hwif = hwif; + hwgroup->drive = drive; + drive->sleep = 0; + drive->service_start = jiffies; + +queue_next: + if (!ata_can_queue(drive)) { + if (!ata_pending_commands(drive)) + hwgroup->busy = 0; + + break; + } + + if (blk_queue_plugged(&drive->queue)) { + if (drive->using_tcq) + break; + + printk(KERN_ERR "ide: huh? queue was plugged!\n"); + break; + } + + /* + * we know that the queue isn't empty, but this can happen + * if the q->prep_rq_fn() decides to kill a request + */ + rq = elv_next_request(&drive->queue); + if (!rq) { + hwgroup->busy = !!ata_pending_commands(drive); + break; + } + + if (!rq->bio && ata_pending_commands(drive)) + break; + + hwgroup->rq = rq; + + /* + * Some systems have trouble with IDE IRQs arriving while + * the driver is still setting things up. So, here we disable + * the IRQ used by this interface while the request is being started. + * This may look bad at first, but pretty much the same thing + * happens anyway when any interrupt comes in, IDE or otherwise + * -- the kernel masks the IRQ while it is being handled. + */ + if (masked_irq && hwif->irq != masked_irq) + disable_irq_nosync(hwif->irq); + spin_unlock(&ide_lock); + local_irq_enable(); + /* allow other IRQs while we start this request */ + startstop = start_request(drive, rq); + spin_lock_irq(&ide_lock); + if (masked_irq && hwif->irq != masked_irq) + enable_irq(hwif->irq); + if (startstop == ide_released) + goto queue_next; + if (startstop == ide_stopped) + hwgroup->busy = 0; + } +} + +EXPORT_SYMBOL(ide_do_request); + +/* + * Passes the stuff to ide_do_request + */ +void do_ide_request(request_queue_t *q) +{ + ide_do_request(q->queuedata, 0); +} + +/* + * un-busy the hwgroup etc, and clear any pending DMA status. we want to + * retry the current request in pio mode instead of risking tossing it + * all away + */ +void ide_dma_timeout_retry(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct request *rq; + + /* + * end current dma transaction + */ + (void) hwif->ide_dma_end(drive); + + /* + * complain a little, later we might remove some of this verbosity + */ + printk(KERN_WARNING "%s: timeout waiting for DMA\n", drive->name); + (void) hwif->ide_dma_timeout(drive); + + /* + * disable dma for now, but remember that we did so because of + * a timeout -- we'll reenable after we finish this next request + * (or rather the first chunk of it) in pio. + */ + drive->retry_pio++; + drive->state = DMA_PIO_RETRY; + (void) hwif->ide_dma_off_quietly(drive); + + /* + * un-busy drive etc (hwgroup->busy is cleared on return) and + * make sure request is sane + */ + rq = HWGROUP(drive)->rq; + HWGROUP(drive)->rq = NULL; + + rq->errors = 0; + rq->sector = rq->bio->bi_sector; + rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; + if (rq->bio) + rq->buffer = NULL; +} + +EXPORT_SYMBOL(ide_dma_timeout_retry); + +/** + * ide_timer_expiry - handle lack of an IDE interrupt + * @data: timer callback magic (hwgroup) + * + * An IDE command has timed out before the expected drive return + * occurred. At this point we attempt to clean up the current + * mess. If the current handler includes an expiry handler then + * we invoke the expiry handler, and providing it is happy the + * work is done. If that fails we apply generic recovery rules + * invoking the handler and checking the drive DMA status. We + * have an excessively incestuous relationship with the DMA + * logic that wants cleaning up. + */ + +void ide_timer_expiry (unsigned long data) +{ + ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; + ide_handler_t *handler; + ide_expiry_t *expiry; + unsigned long flags; + unsigned long wait; + + spin_lock_irqsave(&ide_lock, flags); + del_timer(&hwgroup->timer); + + if ((handler = hwgroup->handler) == NULL) { + /* + * Either a marginal timeout occurred + * (got the interrupt just as timer expired), + * or we were "sleeping" to give other devices a chance. + * Either way, we don't really want to complain about anything. + */ + if (hwgroup->sleeping) { + hwgroup->sleeping = 0; + hwgroup->busy = 0; + } + } else { + ide_drive_t *drive = hwgroup->drive; + if (!drive) { + printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n"); + hwgroup->handler = NULL; + } else { + ide_hwif_t *hwif; + ide_startstop_t startstop = ide_stopped; + if (!hwgroup->busy) { + hwgroup->busy = 1; /* paranoia */ + printk(KERN_ERR "%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); + } + if ((expiry = hwgroup->expiry) != NULL) { + /* continue */ + if ((wait = expiry(drive)) != 0) { + /* reset timer */ + hwgroup->timer.expires = jiffies + wait; + add_timer(&hwgroup->timer); + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + } + hwgroup->handler = NULL; + /* + * We need to simulate a real interrupt when invoking + * the handler() function, which means we need to + * globally mask the specific IRQ: + */ + spin_unlock(&ide_lock); + hwif = HWIF(drive); +#if DISABLE_IRQ_NOSYNC + disable_irq_nosync(hwif->irq); +#else + /* disable_irq_nosync ?? */ + disable_irq(hwif->irq); +#endif /* DISABLE_IRQ_NOSYNC */ + /* local CPU only, + * as if we were handling an interrupt */ + local_irq_disable(); + if (hwgroup->poll_timeout != 0) { + startstop = handler(drive); + } else if (drive_is_ready(drive)) { + if (drive->waiting_for_dma) + (void) hwgroup->hwif->ide_dma_lostirq(drive); + (void)ide_ack_intr(hwif); + printk(KERN_WARNING "%s: lost interrupt\n", drive->name); + startstop = handler(drive); + } else { + if (drive->waiting_for_dma) { + startstop = ide_stopped; + ide_dma_timeout_retry(drive); + } else + startstop = DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG)); + } + set_recovery_timer(hwif); + drive->service_time = jiffies - drive->service_start; + enable_irq(hwif->irq); + spin_lock_irq(&ide_lock); + if (startstop == ide_stopped) + hwgroup->busy = 0; + } + } + ide_do_request(hwgroup, 0); + spin_unlock_irqrestore(&ide_lock, flags); +} + +EXPORT_SYMBOL(ide_timer_expiry); + +/** + * unexpected_intr - handle an unexpected IDE interrupt + * @irq: interrupt line + * @hwgroup: hwgroup being processed + * + * There's nothing really useful we can do with an unexpected interrupt, + * other than reading the status register (to clear it), and logging it. + * There should be no way that an irq can happen before we're ready for it, + * so we needn't worry much about losing an "important" interrupt here. + * + * On laptops (and "green" PCs), an unexpected interrupt occurs whenever + * the drive enters "idle", "standby", or "sleep" mode, so if the status + * looks "good", we just ignore the interrupt completely. + * + * This routine assumes __cli() is in effect when called. + * + * If an unexpected interrupt happens on irq15 while we are handling irq14 + * and if the two interfaces are "serialized" (CMD640), then it looks like + * we could screw up by interfering with a new request being set up for + * irq15. + * + * In reality, this is a non-issue. The new command is not sent unless + * the drive is ready to accept one, in which case we know the drive is + * not trying to interrupt us. And ide_set_handler() is always invoked + * before completing the issuance of any new drive command, so we will not + * be accidentally invoked as a result of any valid command completion + * interrupt. + * + * Note that we must walk the entire hwgroup here. We know which hwif + * is doing the current command, but we don't know which hwif burped + * mysteriously. + */ + +static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) +{ + u8 stat; + ide_hwif_t *hwif = hwgroup->hwif; + + /* + * handle the unexpected interrupt + */ + do { + if (hwif->irq == irq) { + stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + /* Try to not flood the console with msgs */ + static unsigned long last_msgtime, count; + ++count; + if (time_after(jiffies, last_msgtime + HZ)) { + last_msgtime = jiffies; + printk(KERN_ERR "%s%s: unexpected interrupt, " + "status=0x%02x, count=%ld\n", + hwif->name, + (hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count); + } + } + } + } while ((hwif = hwif->next) != hwgroup->hwif); +} + +/** + * ide_intr - default IDE interrupt handler + * @irq: interrupt number + * @dev_id: hwif group + * @regs: unused weirdness from the kernel irq layer + * + * This is the default IRQ handler for the IDE layer. You should + * not need to override it. If you do be aware it is subtle in + * places + * + * hwgroup->hwif is the interface in the group currently performing + * a command. hwgroup->drive is the drive and hwgroup->handler is + * the IRQ handler to call. As we issue a command the handlers + * step through multiple states, reassigning the handler to the + * next step in the process. Unlike a smart SCSI controller IDE + * expects the main processor to sequence the various transfer + * stages. We also manage a poll timer to catch up with most + * timeout situations. There are still a few where the handlers + * don't ever decide to give up. + * + * The handler eventually returns ide_stopped to indicate the + * request completed. At this point we issue the next request + * on the hwgroup and the process begins again. + */ + +void ide_intr (int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; + ide_hwif_t *hwif; + ide_drive_t *drive; + ide_handler_t *handler; + ide_startstop_t startstop; + + spin_lock_irqsave(&ide_lock, flags); + hwif = hwgroup->hwif; + + if (!ide_ack_intr(hwif)) { + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + + if ((handler = hwgroup->handler) == NULL || + hwgroup->poll_timeout != 0) { + /* + * Not expecting an interrupt from this drive. + * That means this could be: + * (1) an interrupt from another PCI device + * sharing the same PCI INT# as us. + * or (2) a drive just entered sleep or standby mode, + * and is interrupting to let us know. + * or (3) a spurious interrupt of unknown origin. + * + * For PCI, we cannot tell the difference, + * so in that case we just ignore it and hope it goes away. + * + * FIXME: unexpected_intr should be hwif-> then we can + * remove all the ifdef PCI crap + */ +#ifdef CONFIG_BLK_DEV_IDEPCI + if (hwif->pci_dev && !hwif->pci_dev->vendor) +#endif /* CONFIG_BLK_DEV_IDEPCI */ + { + /* + * Probably not a shared PCI interrupt, + * so we can safely try to do something about it: + */ + unexpected_intr(irq, hwgroup); +#ifdef CONFIG_BLK_DEV_IDEPCI + } else { + /* + * Whack the status register, just in case + * we have a leftover pending IRQ. + */ + (void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); +#endif /* CONFIG_BLK_DEV_IDEPCI */ + } + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + drive = hwgroup->drive; + if (!drive) { + /* + * This should NEVER happen, and there isn't much + * we could do about it here. + * + * [Note - this can occur if the drive is hot unplugged] + */ + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + if (!drive_is_ready(drive)) { + /* + * This happens regularly when we share a PCI IRQ with + * another device. Unfortunately, it can also happen + * with some buggy drives that trigger the IRQ before + * their status register is up to date. Hopefully we have + * enough advance overhead that the latter isn't a problem. + */ + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + if (!hwgroup->busy) { + hwgroup->busy = 1; /* paranoia */ + printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); + } + hwgroup->handler = NULL; + del_timer(&hwgroup->timer); + spin_unlock(&ide_lock); + + if (drive->unmask) + local_irq_enable(); + /* service this interrupt, may set handler for next interrupt */ + startstop = handler(drive); + spin_lock_irq(&ide_lock); + + /* + * Note that handler() may have set things up for another + * interrupt to occur soon, but it cannot happen until + * we exit from this routine, because it will be the + * same irq as is currently being serviced here, and Linux + * won't allow another of the same (on any CPU) until we return. + */ + set_recovery_timer(HWIF(drive)); + drive->service_time = jiffies - drive->service_start; + if (startstop == ide_stopped) { + if (hwgroup->handler == NULL) { /* paranoia */ + hwgroup->busy = 0; + ide_do_request(hwgroup, hwif->irq); + } else { + printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler " + "on exit\n", drive->name); + } + } + spin_unlock_irqrestore(&ide_lock, flags); +} + +EXPORT_SYMBOL(ide_intr); + +/** + * ide_init_drive_cmd - initialize a drive command request + * @rq: request object + * + * Initialize a request before we fill it in and send it down to + * ide_do_drive_cmd. Commands must be set up by this function. Right + * now it doesn't do a lot, but if that changes abusers will have a + * nasty suprise. + */ + +void ide_init_drive_cmd (struct request *rq) +{ + memset(rq, 0, sizeof(*rq)); + rq->flags = REQ_DRIVE_CMD; +} + +EXPORT_SYMBOL(ide_init_drive_cmd); + +/** + * ide_do_drive_cmd - issue IDE special command + * @drive: device to issue command + * @rq: request to issue + * @action: action for processing + * + * This function issues a special IDE device request + * onto the request queue. + * + * If action is ide_wait, then the rq is queued at the end of the + * request queue, and the function sleeps until it has been processed. + * This is for use when invoked from an ioctl handler. + * + * If action is ide_preempt, then the rq is queued at the head of + * the request queue, displacing the currently-being-processed + * request and this function returns immediately without waiting + * for the new rq to be completed. This is VERY DANGEROUS, and is + * intended for careful use by the ATAPI tape/cdrom driver code. + * + * If action is ide_next, then the rq is queued immediately after + * the currently-being-processed-request (if any), and the function + * returns without waiting for the new rq to be completed. As above, + * This is VERY DANGEROUS, and is intended for careful use by the + * ATAPI tape/cdrom driver code. + * + * If action is ide_end, then the rq is queued at the end of the + * request queue, and the function returns immediately without waiting + * for the new rq to be completed. This is again intended for careful + * use by the ATAPI tape/cdrom driver code. + */ + +int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action) +{ + unsigned long flags; + ide_hwgroup_t *hwgroup = HWGROUP(drive); + DECLARE_COMPLETION(wait); + int insert_end = 1, err; + +#ifdef CONFIG_BLK_DEV_PDC4030 + /* + * FIXME: there should be a drive or hwif->special + * handler that points here by default, not hacks + * in the ide-io.c code + */ + if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) + return -ENOSYS; /* special drive cmds not supported */ +#endif + rq->errors = 0; + rq->rq_status = RQ_ACTIVE; + + rq->rq_disk = drive->disk; + + /* + * we need to hold an extra reference to request for safe inspection + * after completion + */ + if (action == ide_wait) { + rq->ref_count++; + rq->waiting = &wait; + } + + spin_lock_irqsave(&ide_lock, flags); + if (action == ide_preempt) { + hwgroup->rq = NULL; + insert_end = 0; + } + __elv_add_request(&drive->queue, rq, insert_end, 0); + ide_do_request(hwgroup, 0); + spin_unlock_irqrestore(&ide_lock, flags); + + err = 0; + if (action == ide_wait) { + wait_for_completion(&wait); + if (rq->errors) + err = -EIO; + + blk_put_request(rq); + } + + return err; +} + +EXPORT_SYMBOL(ide_do_drive_cmd); diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c --- a/drivers/ide/ide-iops.c Wed Nov 27 14:36:28 2002 +++ b/drivers/ide/ide-iops.c Wed Nov 27 14:36:28 2002 @@ -57,14 +57,14 @@ insl(port, addr, count); } -static void ide_outb (u8 addr, ide_ioreg_t port) +static void ide_outb (u8 value, ide_ioreg_t port) { - outb(addr, port); + outb(value, port); } -static void ide_outw (u16 addr, ide_ioreg_t port) +static void ide_outw (u16 value, ide_ioreg_t port) { - outw(addr, port); + outw(value, port); } static void ide_outsw (ide_ioreg_t port, void *addr, u32 count) @@ -72,14 +72,14 @@ outsw(port, addr, count); } -static void ide_outl (u32 addr, ide_ioreg_t port) +static void ide_outl (u32 value, ide_ioreg_t port) { - outl(addr, port); + outl(value, port); } static void ide_outsl (ide_ioreg_t port, void *addr, u32 count) { - return outsl(port, addr, count); + outsl(port, addr, count); } void default_hwif_iops (ide_hwif_t *hwif) @@ -819,9 +819,9 @@ // while (HWGROUP(drive)->busy) // ide_delay_50ms(); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) hwif->ide_dma_host_off(drive); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ /* * Don't use ide_wait_cmd here - it will @@ -887,12 +887,12 @@ drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) if (speed >= XFER_SW_DMA_0) hwif->ide_dma_host_on(drive); else hwif->ide_dma_off(drive); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ switch(speed) { case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; @@ -1057,8 +1057,7 @@ { if (drive->crc_count) { (void) HWIF(drive)->ide_dma_off_quietly(drive); - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive)); + ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive)); if (drive->current_speed >= XFER_SW_DMA_0) (void) HWIF(drive)->ide_dma_on(drive); } else { diff -Nru a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c --- a/drivers/ide/ide-lib.c Wed Nov 27 14:36:32 2002 +++ b/drivers/ide/ide-lib.c Wed Nov 27 14:36:32 2002 @@ -300,7 +300,7 @@ } /** - * ide_get_best_pio_mode - get PIO mode fro drive + * ide_get_best_pio_mode - get PIO mode from drive * @driver: drive to consider * @mode_wanted: preferred mode * @max_mode: highest allowed @@ -387,6 +387,15 @@ EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); +/** + * ide_toggle_bounce - handle bounce buffering + * @drive: drive to update + * @on: on/off boolean + * + * Enable or disable bounce buffering for the device. Drives move + * between PIO and DMA and that changes the rules we need. + */ + void ide_toggle_bounce(ide_drive_t *drive, int on) { u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ @@ -402,3 +411,28 @@ } EXPORT_SYMBOL(ide_toggle_bounce); + +/** + * ide_set_xfer_rate - set transfer rate + * @drive: drive to set + * @speed: speed to attempt to set + * + * General helper for setting the speed of an IDE device. This + * function knows about user enforced limits from the configuration + * which speedproc() does not. High level drivers should never + * invoke speedproc() directly. + */ + +int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) +{ +#ifndef CONFIG_BLK_DEV_IDEDMA + rate = min(rate, (u8) XFER_PIO_4); +#endif + if(HWIF(drive)->speedproc) + return HWIF(drive)->speedproc(drive, rate); + else + return -1; +} + +EXPORT_SYMBOL_GPL(ide_set_xfer_rate); + diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/ide-probe.c Wed Nov 27 14:36:30 2002 @@ -144,6 +144,7 @@ id->model[sizeof(id->model)-1] = '\0'; printk("%s: %s, ", drive->name, id->model); drive->present = 1; + drive->dead = 0; /* * Check for an ATAPI device @@ -546,8 +547,24 @@ return 1; } -#define hwif_check_region(addr, num) \ - ((hwif->mmio) ? check_mem_region((addr),(num)) : check_region((addr),(num))) +static int hwif_check_region(ide_hwif_t *hwif, unsigned long addr, int num) +{ + int err; + + if(hwif->mmio) + err = check_mem_region(addr, num); + else + err = check_region(addr, num); + + if(err) + { + printk("%s: %s resource 0x%lX-0x%lX not free.\n", + hwif->name, hwif->mmio?"MMIO":"I/O", addr, addr+num-1); + mdelay(2000); + } + return err; +} + static int hwif_check_regions (ide_hwif_t *hwif) { @@ -556,14 +573,14 @@ if (hwif->mmio == 2) return 0; - addr_errs = hwif_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1); + addr_errs = hwif_check_region(hwif, hwif->io_ports[IDE_DATA_OFFSET], 1); for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; i++) - addr_errs += hwif_check_region(hwif->io_ports[i], 1); + addr_errs += hwif_check_region(hwif, hwif->io_ports[i], 1); if (hwif->io_ports[IDE_CONTROL_OFFSET]) - addr_errs += hwif_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); + addr_errs += hwif_check_region(hwif, hwif->io_ports[IDE_CONTROL_OFFSET], 1); #if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) if (hwif->io_ports[IDE_IRQ_OFFSET]) - addr_errs += hwif_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); + addr_errs += hwif_check_region(hwif, hwif->io_ports[IDE_IRQ_OFFSET], 1); #endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ /* If any errors are return, we drop the hwif interface. */ hwif->straight8 = 0; @@ -629,7 +646,7 @@ } #endif - if ((hwif->chipset != ide_4drives || !hwif->mate->present) && + if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) && #if CONFIG_BLK_DEV_PDC4030 (hwif->chipset != ide_pdc4030 || hwif->channel == 0) && #endif /* CONFIG_BLK_DEV_PDC4030 */ @@ -655,6 +672,13 @@ * we'll install our IRQ driver much later... */ irqd = hwif->irq; + + if (irqd >= NR_IRQS) + { + printk(KERN_ERR "***WARNING***: Bogus interrupt reported. Probably a bug in the Linux ACPI\n"); + printk(KERN_ERR "***WARNING***: Attempting to continue as best we can.\n"); + irqd = 0; + } if (irqd) disable_irq(hwif->irq); @@ -1058,6 +1082,7 @@ "%s","IDE Drive"); drive->gendev.parent = &hwif->gendev; drive->gendev.bus = &ide_bus_type; + drive->gendev.driver_data = drive; sprintf (name, "ide/host%d/bus%d/target%d/lun%d", (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c Wed Nov 27 14:36:28 2002 +++ b/drivers/ide/ide-tape.c Wed Nov 27 14:36:28 2002 @@ -1450,7 +1450,6 @@ } } -#ifdef CONFIG_BLK_DEV_IDEDMA static void idetape_update_buffers (idetape_pc_t *pc) { struct bio *bio = pc->bio; @@ -1475,7 +1474,6 @@ } pc->bio = bio; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * idetape_next_pc_storage returns a pointer to a place in which we can @@ -1580,7 +1578,6 @@ ide_stall_queue(drive, HZ / 2); return; } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * Correct pc->actually_transferred by asking the tape. @@ -1589,7 +1586,7 @@ pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl(get_unaligned(&result->information)); idetape_update_buffers(pc); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ + if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) { pc->error = IDETAPE_ERROR_FILEMARK; set_bit(PC_ABORT, &pc->flags); @@ -1982,7 +1979,6 @@ /* Clear the interrupt */ status.all = HWIF(drive)->INB(IDE_STATUS_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { if (HWIF(drive)->ide_dma_end(drive)) { /* @@ -2006,7 +2002,6 @@ printk(KERN_INFO "ide-tape: DMA finished\n"); #endif /* IDETAPE_DEBUG_LOG */ } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* No more interrupts */ if (!status.b.drq) { @@ -2061,7 +2056,6 @@ tape->failed_pc = NULL; return pc->callback(drive); /* Command finished - Call the callback function */ } -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { printk(KERN_ERR "ide-tape: The tape wants to issue more " "interrupts in DMA mode\n"); @@ -2069,7 +2063,6 @@ (void) HWIF(drive)->ide_dma_off(drive); return ide_do_reset(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ bcount.b.high = IN_BYTE(IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ bcount.b.low = IN_BYTE(IDE_BCOUNTL_REG); /* on this interrupt */ ireason.all = IN_BYTE(IDE_IREASON_REG); @@ -2264,7 +2257,6 @@ pc->current_position = pc->buffer; bcount.all = pc->request_transfer; /* Request to transfer the entire buffer at once */ -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { printk(KERN_WARNING "ide-tape: DMA disabled, " "reverting to PIO\n"); @@ -2276,7 +2268,6 @@ else dma_ok = !HWIF(drive)->ide_dma_read(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl, IDE_CONTROL_REG); @@ -2284,12 +2275,10 @@ OUT_BYTE(bcount.b.high, IDE_BCOUNTH_REG); OUT_BYTE(bcount.b.low, IDE_BCOUNTL_REG); OUT_BYTE(drive->select.all, IDE_SELECT_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA if (dma_ok) { /* Begin DMA, if necessary */ set_bit(PC_DMA_IN_PROGRESS, &pc->flags); (void) (HWIF(drive)->ide_dma_begin(drive)); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { if (HWGROUP(drive)->handler != NULL) /* paranoia check */ BUG(); diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Wed Nov 27 14:36:27 2002 +++ b/drivers/ide/ide-taskfile.c Wed Nov 27 14:36:27 2002 @@ -1068,7 +1068,6 @@ case DISABLE_SEAGATE: case EXABYTE_ENABLE_NEST: return &task_no_data_intr; -#ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: // case WIN_READDMA_ONCE: case WIN_IDENTIFY_DMA: @@ -1080,7 +1079,6 @@ case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: -#endif case WIN_FORMAT: case WIN_INIT: case WIN_DEVICE_RESET: @@ -1164,7 +1162,6 @@ default: return IDE_DRIVE_TASK_NO_DATA; } -#ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: // case WIN_READDMA_ONCE: case WIN_IDENTIFY_DMA: @@ -1178,7 +1175,6 @@ case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: return IDE_DRIVE_TASK_RAW_WRITE; -#endif case WIN_SETFEATURES: switch(args->tfRegister[IDE_FEATURE_OFFSET]) { case SETFEATURES_EN_8BIT: @@ -1669,8 +1665,7 @@ if (!err && xfer_rate) { /* active-retuning-calls future */ - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, xfer_rate); + ide_set_xfer_rate(drive, xfer_rate); ide_driveid_update(drive); } abort: @@ -1724,8 +1719,7 @@ if (!err && xfer_rate) { /* active-retuning-calls future */ - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, xfer_rate); + ide_set_xfer_rate(driver, xfer_rate); ide_driveid_update(drive); } abort: diff -Nru a/drivers/ide/ide-tcq.c b/drivers/ide/ide-tcq.c --- a/drivers/ide/ide-tcq.c Wed Nov 27 14:36:32 2002 +++ b/drivers/ide/ide-tcq.c Wed Nov 27 14:36:32 2002 @@ -148,14 +148,14 @@ ide_hwif_t *hwif = HWIF(drive); unsigned long flags; - printk("ide_tcq_intr_timeout: timeout waiting for %s interrupt\n", hwgroup->rq ? "completion" : "service"); + printk(KERN_ERR "ide_tcq_intr_timeout: timeout waiting for %s interrupt\n", hwgroup->rq ? "completion" : "service"); spin_lock_irqsave(&ide_lock, flags); if (!hwgroup->busy) - printk("ide_tcq_intr_timeout: hwgroup not busy\n"); + printk(KERN_ERR "ide_tcq_intr_timeout: hwgroup not busy\n"); if (hwgroup->handler == NULL) - printk("ide_tcq_intr_timeout: missing isr!\n"); + printk(KERN_ERR "ide_tcq_intr_timeout: missing isr!\n"); hwgroup->busy = 1; spin_unlock_irqrestore(&ide_lock, flags); @@ -261,7 +261,7 @@ hwif->OUTB(WIN_QUEUED_SERVICE, IDE_COMMAND_REG); if (ide_tcq_wait_altstat(drive, &stat, BUSY_STAT)) { - printk("ide_service: BUSY clear took too long\n"); + printk(KERN_ERR "ide_service: BUSY clear took too long\n"); ide_dump_status(drive, "ide_service", stat); ide_tcq_invalidate_queue(drive); return ide_stopped; @@ -284,7 +284,7 @@ feat = hwif->INB(IDE_NSECTOR_REG); if (feat & REL) { HWGROUP(drive)->rq = NULL; - printk("%s: release in service\n", drive->name); + printk(KERN_ERR "%s: release in service\n", drive->name); return ide_stopped; } @@ -307,7 +307,7 @@ return HWIF(drive)->ide_dma_queued_start(drive); } - printk("ide_service: missing request for tag %d\n", tag); + printk(KERN_ERR "ide_service: missing request for tag %d\n", tag); spin_unlock_irqrestore(&ide_lock, flags); return ide_stopped; } @@ -347,14 +347,14 @@ * must be end of I/O, check status and complete as necessary */ if (unlikely(!OK_STAT(stat, READY_STAT, drive->bad_wstat | DRQ_STAT))) { - printk("ide_dmaq_intr: %s: error status %x\n",drive->name,stat); + printk(KERN_ERR "ide_dmaq_intr: %s: error status %x\n",drive->name,stat); ide_dump_status(drive, "ide_dmaq_complete", stat); ide_tcq_invalidate_queue(drive); return ide_stopped; } if (dma_stat) - printk("%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); + printk(KERN_WARNING "%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); TCQ_PRINTK("ide_dmaq_complete: ending %p, tag %d\n", rq, rq->tag); ide_end_request(drive, 1, rq->nr_sectors); @@ -465,7 +465,7 @@ args->command_type = ide_cmd_type_parser(args); if (ide_raw_taskfile(drive, args, NULL)) { - printk("%s: failed to enable write cache\n", drive->name); + printk(KERN_WARNING "%s: failed to enable write cache\n", drive->name); goto err; } @@ -479,7 +479,7 @@ args->command_type = ide_cmd_type_parser(args); if (ide_raw_taskfile(drive, args, NULL)) { - printk("%s: disabling release interrupt fail\n", drive->name); + printk(KERN_ERR "%s: disabling release interrupt fail\n", drive->name); goto err; } @@ -493,7 +493,7 @@ args->command_type = ide_cmd_type_parser(args); if (ide_raw_taskfile(drive, args, NULL)) { - printk("%s: enabling service interrupt fail\n", drive->name); + printk(KERN_ERR "%s: enabling service interrupt fail\n", drive->name); goto err; } #endif @@ -518,7 +518,7 @@ */ if (!on) { if (drive->using_tcq) - printk("%s: TCQ disabled\n", drive->name); + printk(KERN_INFO "%s: TCQ disabled\n", drive->name); drive->using_tcq = 0; return 0; @@ -541,7 +541,7 @@ ide_tcq_check_autopoll(drive); if (depth != drive->queue_depth) - printk("%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth); + printk(KERN_INFO "%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth); drive->using_tcq = 1; return 0; @@ -588,7 +588,7 @@ return 1; if (ata_pending_commands(drive)) { - printk("ide-tcq; can't toggle tcq feature on busy drive\n"); + printk(KERN_WARNING "ide-tcq; can't toggle tcq feature on busy drive\n"); return 1; } @@ -692,10 +692,10 @@ TCQ_PRINTK("ide_dma: setting up queued tag=%d\n", rq->tag); if (!hwgroup->busy) - printk("queued_rw: hwgroup not busy\n"); + printk(KERN_ERR "queued_rw: hwgroup not busy\n"); if (ide_tcq_wait_dataphase(drive)) { - printk("timeout waiting for data phase\n"); + printk(KERN_WARNING "timeout waiting for data phase\n"); return ide_stopped; } diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Wed Nov 27 14:36:28 2002 +++ b/drivers/ide/ide.c Wed Nov 27 14:36:28 2002 @@ -222,37 +222,6 @@ EXPORT_SYMBOL(idetape); EXPORT_SYMBOL(idescsi); -#if (DISK_RECOVERY_TIME > 0) - -Error So the User Has To Fix the Compilation And Stop Hacking Port 0x43 -Does anyone ever use this anyway ?? - -/* - * For really screwy hardware (hey, at least it *can* be used with Linux) - * we can enforce a minimum delay time between successive operations. - */ -static unsigned long read_timer (ide_hwif_t *hwif) -{ - unsigned long t, flags; - int i; - - /* FIXME this is completely unsafe! */ - local_irq_save(flags); - t = jiffies * 11932; - outb_p(0, 0x43); - i = inb_p(0x40); - i |= inb_p(0x40) << 8; - local_irq_restore(flags); - return (t - i); -} -#endif /* DISK_RECOVERY_TIME */ - -static inline void set_recovery_timer (ide_hwif_t *hwif) -{ -#if (DISK_RECOVERY_TIME > 0) - hwif->last_time = read_timer(hwif); -#endif /* DISK_RECOVERY_TIME */ -} /* * Do not even *think* about calling this! @@ -310,6 +279,7 @@ drive->max_failures = IDE_DEFAULT_MAX_FAILURES; drive->using_dma = 0; drive->is_flash = 0; + drive->vdma = 0; INIT_LIST_HEAD(&drive->list); } } @@ -372,7 +342,7 @@ /* safe default value for VESA and PCI */ system_bus_speed = 50; } - printk("ide: Assuming %dMHz system bus speed " + printk(KERN_INFO "ide: Assuming %dMHz system bus speed " "for PIO modes%s\n", system_bus_speed, idebus_parameter ? "" : "; override with idebus=xx"); } @@ -380,48 +350,6 @@ } /* - * This is our end_request replacement function. - */ -int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) -{ - struct request *rq; - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; - - BUG_ON(!(rq->flags & REQ_STARTED)); - - if (!nr_sectors) - nr_sectors = rq->hard_cur_sectors; - - /* - * decide whether to reenable DMA -- 3 is a random magic for now, - * if we DMA timeout more than 3 times, just stay in PIO - */ - if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { - drive->state = 0; - HWGROUP(drive)->hwif->ide_dma_on(drive); - } - - if (!end_that_request_first(rq, uptodate, nr_sectors)) { - add_disk_randomness(rq->rq_disk); - if (!blk_rq_tagged(rq)) - blkdev_dequeue_request(rq); - else - blk_queue_end_tag(&drive->queue, rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - ret = 0; - } - spin_unlock_irqrestore(&ide_lock, flags); - return ret; -} - -EXPORT_SYMBOL(ide_end_request); - -/* * current_capacity() returns the capacity (in sectors) of a drive * according to its current geometry/LBA settings. */ @@ -444,82 +372,6 @@ } /* - * Clean up after success/failure of an explicit drive cmd - */ -void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long flags; - struct request *rq; - - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; - spin_unlock_irqrestore(&ide_lock, flags); - - if (rq->flags & REQ_DRIVE_CMD) { - u8 *args = (u8 *) rq->buffer; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - args[0] = stat; - args[1] = err; - args[2] = hwif->INB(IDE_NSECTOR_REG); - } - } else if (rq->flags & REQ_DRIVE_TASK) { - u8 *args = (u8 *) rq->buffer; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - args[0] = stat; - args[1] = err; - args[2] = hwif->INB(IDE_NSECTOR_REG); - args[3] = hwif->INB(IDE_SECTOR_REG); - args[4] = hwif->INB(IDE_LCYL_REG); - args[5] = hwif->INB(IDE_HCYL_REG); - args[6] = hwif->INB(IDE_SELECT_REG); - } - } else if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = (ide_task_t *) rq->special; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - if (args->tf_in_flags.b.data) { - u16 data = hwif->INW(IDE_DATA_REG); - args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; - args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; - } - args->tfRegister[IDE_ERROR_OFFSET] = err; - args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); - args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); - args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); - args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); - args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); - args->tfRegister[IDE_STATUS_OFFSET] = stat; - - if (drive->addressing == 1) { - hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB); - args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG); - args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG); - args->hobRegister[IDE_SECTOR_OFFSET_HOB] = hwif->INB(IDE_SECTOR_REG); - args->hobRegister[IDE_LCYL_OFFSET_HOB] = hwif->INB(IDE_LCYL_REG); - args->hobRegister[IDE_HCYL_OFFSET_HOB] = hwif->INB(IDE_HCYL_REG); - } - } - } - - spin_lock_irqsave(&ide_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - spin_unlock_irqrestore(&ide_lock, flags); -} - -EXPORT_SYMBOL(ide_end_drive_cmd); - -/* * Error reporting, in human readable form (luxurious, but a memory hog). */ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat) @@ -529,7 +381,7 @@ u8 err = 0; local_irq_set(flags); - printk("%s: %s: status=0x%02x", drive->name, msg, stat); + printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat); #if FANCY_STATUS_DUMPS printk(" { "); if (stat & BUSY_STAT) { @@ -602,967 +454,7 @@ EXPORT_SYMBOL(ide_dump_status); -/* - * try_to_flush_leftover_data() is invoked in response to a drive - * unexpectedly having its DRQ_STAT bit set. As an alternative to - * resetting the drive, this routine tries to clear the condition - * by read a sector's worth of data from the drive. Of course, - * this may not help if the drive is *waiting* for data from *us*. - */ -void try_to_flush_leftover_data (ide_drive_t *drive) -{ - int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; - - if (drive->media != ide_disk) - return; - while (i > 0) { - u32 buffer[16]; - u32 wcount = (i > 16) ? 16 : i; - - i -= wcount; - HWIF(drive)->ata_input_data(drive, buffer, wcount); - } -} - -EXPORT_SYMBOL(try_to_flush_leftover_data); - -/* - * FIXME Add an ATAPI error - */ - -/* - * ide_error() takes action based on the error returned by the drive. - */ -ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) -{ - ide_hwif_t *hwif; - struct request *rq; - u8 err; - - err = ide_dump_status(drive, msg, stat); - if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) - return ide_stopped; - - hwif = HWIF(drive); - /* retry only "normal" I/O: */ - if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); - return ide_stopped; - } - if (rq->flags & REQ_DRIVE_TASKFILE) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); -// ide_end_taskfile(drive, stat, err); - return ide_stopped; - } - - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { - /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - if (drive->media != ide_disk) - goto media_out; - if (stat & ERR_STAT) { - /* err has different meaning on cdrom and tape */ - if (err == ABRT_ERR) { - if (drive->select.b.lba && - (hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)) - /* some newer drives don't - * support WIN_SPECIFY - */ - return ide_stopped; - } else if ((err & BAD_CRC) == BAD_CRC) { - drive->crc_count++; - /* UDMA crc error -- just retry the operation */ - } else if (err & (BBD_ERR | ECC_ERR)) { - /* retries won't help these */ - rq->errors = ERROR_MAX; - } else if (err & TRK0_ERR) { - /* help it find track zero */ - rq->errors |= ERROR_RECAL; - } - } -media_out: - if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE) - try_to_flush_leftover_data(drive); - } - if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) { - /* force an abort */ - hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); - } - if (rq->errors >= ERROR_MAX) { - if (drive->driver != NULL) - DRIVER(drive)->end_request(drive, 0, 0); - else - ide_end_request(drive, 0, 0); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; - ++rq->errors; - } - return ide_stopped; -} - -EXPORT_SYMBOL(ide_error); - -/* - * Issue a simple drive command - * The drive must be selected beforehand. - */ -void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler) -{ - ide_hwif_t *hwif = HWIF(drive); - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, handler, WAIT_CMD, NULL); - if (IDE_CONTROL_REG) - hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(drive,0); - hwif->OUTB(nsect,IDE_NSECTOR_REG); - hwif->OUTB(cmd,IDE_COMMAND_REG); -} - -EXPORT_SYMBOL(ide_cmd); - -/* - * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. - */ -ide_startstop_t drive_cmd_intr (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - ide_hwif_t *hwif = HWIF(drive); - u8 *args = (u8 *) rq->buffer; - u8 stat = hwif->INB(IDE_STATUS_REG); - int retries = 10; - - local_irq_enable(); - if ((stat & DRQ_STAT) && args && args[3]) { - u8 io_32bit = drive->io_32bit; - drive->io_32bit = 0; - hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); - drive->io_32bit = io_32bit; - while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) - udelay(100); - } - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return DRIVER(drive)->error(drive, "drive_cmd", stat); - /* calls ide_end_drive_cmd */ - ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); - return ide_stopped; -} - -EXPORT_SYMBOL(drive_cmd_intr); - -/* - * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT - * commands to a drive. It used to do much more, but has been scaled back. - */ -ide_startstop_t do_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - -#ifdef DEBUG - printk("%s: do_special: 0x%02x\n", drive->name, s->all); -#endif - if (s->b.set_tune) { - s->b.set_tune = 0; - if (HWIF(drive)->tuneproc != NULL) - HWIF(drive)->tuneproc(drive, drive->tune_req); - } else if (drive->driver != NULL) { - return DRIVER(drive)->special(drive); - } else if (s->all) { - printk("%s: bad special flag: 0x%02x\n", drive->name, s->all); - s->all = 0; - } - return ide_stopped; -} - -EXPORT_SYMBOL(do_special); - -/* - * execute_drive_cmd() issues a special drive command, - * usually initiated by ioctl() from the external hdparm program. - */ -ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = HWIF(drive); - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - - if (!args) - goto done; - - if (args->tf_out_flags.all != 0) - return flagged_taskfile(drive, args); - return do_rw_taskfile(drive, args); - } else if (rq->flags & REQ_DRIVE_TASK) { - u8 *args = rq->buffer; - u8 sel; - - if (!args) - goto done; -#ifdef DEBUG - printk("%s: DRIVE_TASK_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("fr=0x%02x ", args[1]); - printk("ns=0x%02x ", args[2]); - printk("sc=0x%02x ", args[3]); - printk("lcyl=0x%02x ", args[4]); - printk("hcyl=0x%02x ", args[5]); - printk("sel=0x%02x\n", args[6]); -#endif - hwif->OUTB(args[1], IDE_FEATURE_REG); - hwif->OUTB(args[3], IDE_SECTOR_REG); - hwif->OUTB(args[4], IDE_LCYL_REG); - hwif->OUTB(args[5], IDE_HCYL_REG); - sel = (args[6] & ~0x10); - if (drive->select.b.unit) - sel |= 0x10; - hwif->OUTB(sel, IDE_SELECT_REG); - ide_cmd(drive, args[0], args[2], &drive_cmd_intr); - return ide_started; - } else if (rq->flags & REQ_DRIVE_CMD) { - u8 *args = rq->buffer; - - if (!args) - goto done; -#ifdef DEBUG - printk("%s: DRIVE_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("sc=0x%02x ", args[1]); - printk("fr=0x%02x ", args[2]); - printk("xx=0x%02x\n", args[3]); -#endif - if (args[0] == WIN_SMART) { - hwif->OUTB(0x4f, IDE_LCYL_REG); - hwif->OUTB(0xc2, IDE_HCYL_REG); - hwif->OUTB(args[2],IDE_FEATURE_REG); - hwif->OUTB(args[1],IDE_SECTOR_REG); - ide_cmd(drive, args[0], args[3], &drive_cmd_intr); - return ide_started; - } - hwif->OUTB(args[2],IDE_FEATURE_REG); - ide_cmd(drive, args[0], args[1], &drive_cmd_intr); - return ide_started; - } - -done: - /* - * NULL is actually a valid way of waiting for - * all current requests to be flushed from the queue. - */ -#ifdef DEBUG - printk("%s: DRIVE_CMD (null)\n", drive->name); -#endif - ide_end_drive_cmd(drive, - hwif->INB(IDE_STATUS_REG), - hwif->INB(IDE_ERROR_REG)); - return ide_stopped; -} - -EXPORT_SYMBOL(execute_drive_cmd); - -/* - * start_request() initiates handling of a new I/O request - * needed to reverse the perverted changes anonymously made back - * 2.3.99-pre6 - */ -ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) -{ - ide_startstop_t startstop; - unsigned long block; - - BUG_ON(!(rq->flags & REQ_STARTED)); - -#ifdef DEBUG - printk("%s: start_request: current=0x%08lx\n", - HWIF(drive)->name, (unsigned long) rq); -#endif - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - goto kill_rq; - } - - /* - * bail early if we've sent a device to sleep, however how to wake - * this needs to be a masked flag. FIXME for proper operations. - */ - if (drive->suspend_reset) - goto kill_rq; - - block = rq->sector; - if (blk_fs_request(rq) && - (drive->media == ide_disk || drive->media == ide_floppy)) { - block += drive->sect0; - } - /* Yecch - this will shift the entire interval, - possibly killing some innocent following sector */ - if (block == 0 && drive->remap_0_to_1 == 1) - block = 1; /* redirect MBR access to EZ-Drive partn table */ - -#if (DISK_RECOVERY_TIME > 0) - while ((read_timer() - HWIF(drive)->last_time) < DISK_RECOVERY_TIME); -#endif - - SELECT_DRIVE(drive); - if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { - printk("%s: drive not ready for command\n", drive->name); - return startstop; - } - if (!drive->special.all) { - if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) - return execute_drive_cmd(drive, rq); - else if (rq->flags & REQ_DRIVE_TASKFILE) - return execute_drive_cmd(drive, rq); - - if (drive->driver != NULL) { - return (DRIVER(drive)->do_request(drive, rq, block)); - } - printk("%s: media type %d not supported\n", drive->name, drive->media); - goto kill_rq; - } - return do_special(drive); -kill_rq: - if (drive->driver != NULL) - DRIVER(drive)->end_request(drive, 0, 0); - else - ide_end_request(drive, 0, 0); - return ide_stopped; -} - -EXPORT_SYMBOL(start_request); - -int restart_request (ide_drive_t *drive, struct request *rq) -{ - (void) start_request(drive, rq); - return 0; -} - -EXPORT_SYMBOL(restart_request); - -/* - * ide_stall_queue() can be used by a drive to give excess bandwidth back - * to the hwgroup by sleeping for timeout jiffies. - */ -void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) -{ - if (timeout > WAIT_WORSTCASE) - timeout = WAIT_WORSTCASE; - drive->sleep = timeout + jiffies; -} - -EXPORT_SYMBOL(ide_stall_queue); - -#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) - -/* - * choose_drive() selects the next drive which will be serviced. - */ -static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) -{ - ide_drive_t *drive, *best; - -repeat: - best = NULL; - drive = hwgroup->drive; - do { - if (!blk_queue_empty(&drive->queue) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) { - if (!best - || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) - || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) - { - if (!blk_queue_plugged(&drive->queue)) - best = drive; - } - } - } while ((drive = drive->next) != hwgroup->drive); - if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { - long t = (signed long)(WAKEUP(best) - jiffies); - if (t >= WAIT_MIN_SLEEP) { - /* - * We *may* have some time to spare, but first let's see if - * someone can potentially benefit from our nice mood today.. - */ - drive = best->next; - do { - if (!drive->sleep - && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time)) - && 0 < (signed long)((jiffies + t) - WAKEUP(drive))) - { - ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP)); - goto repeat; - } - } while ((drive = drive->next) != best); - } - } - return best; -} - -/* - * Issue a new request to a drive from hwgroup - * Caller must have already done spin_lock_irqsave(&ide_lock, ..); - * - * A hwgroup is a serialized group of IDE interfaces. Usually there is - * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) - * may have both interfaces in a single hwgroup to "serialize" access. - * Or possibly multiple ISA interfaces can share a common IRQ by being grouped - * together into one hwgroup for serialized access. - * - * Note also that several hwgroups can end up sharing a single IRQ, - * possibly along with many other devices. This is especially common in - * PCI-based systems with off-board IDE controller cards. - * - * The IDE driver uses the single global ide_lock spinlock to protect - * access to the request queues, and to protect the hwgroup->busy flag. - * - * The first thread into the driver for a particular hwgroup sets the - * hwgroup->busy flag to indicate that this hwgroup is now active, - * and then initiates processing of the top request from the request queue. - * - * Other threads attempting entry notice the busy setting, and will simply - * queue their new requests and exit immediately. Note that hwgroup->busy - * remains set even when the driver is merely awaiting the next interrupt. - * Thus, the meaning is "this hwgroup is busy processing a request". - * - * When processing of a request completes, the completing thread or IRQ-handler - * will start the next request from the queue. If no more work remains, - * the driver will clear the hwgroup->busy flag and exit. - * - * The ide_lock (spinlock) is used to protect all access to the - * hwgroup->busy flag, but is otherwise not needed for most processing in - * the driver. This makes the driver much more friendlier to shared IRQs - * than previous designs, while remaining 100% (?) SMP safe and capable. - */ -/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back - * into life on wakeup from machine sleep. - */ -void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) -{ - ide_drive_t *drive; - ide_hwif_t *hwif; - struct request *rq; - ide_startstop_t startstop; - - /* for atari only: POSSIBLY BROKEN HERE(?) */ - ide_get_lock(&ide_intr_lock, ide_intr, hwgroup); - - /* necessary paranoia: ensure IRQs are masked on local CPU */ - local_irq_disable(); - - while (!hwgroup->busy) { - hwgroup->busy = 1; - drive = choose_drive(hwgroup); - if (drive == NULL) { - unsigned long sleep = 0; - hwgroup->rq = NULL; - drive = hwgroup->drive; - do { - if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep))) - sleep = drive->sleep; - } while ((drive = drive->next) != hwgroup->drive); - if (sleep) { - /* - * Take a short snooze, and then wake up this hwgroup again. - * This gives other hwgroups on the same a chance to - * play fairly with us, just in case there are big differences - * in relative throughputs.. don't want to hog the cpu too much. - */ - if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) - sleep = jiffies + WAIT_MIN_SLEEP; -#if 1 - if (timer_pending(&hwgroup->timer)) - printk("ide_set_handler: timer already active\n"); -#endif - /* so that ide_timer_expiry knows what to do */ - hwgroup->sleeping = 1; - mod_timer(&hwgroup->timer, sleep); - /* we purposely leave hwgroup->busy==1 - * while sleeping */ - } else { - /* Ugly, but how can we sleep for the lock - * otherwise? perhaps from tq_disk? - */ - - /* for atari only */ - ide_release_lock(&ide_intr_lock); - hwgroup->busy = 0; - } - - /* no more work for this hwgroup (for now) */ - return; - } - hwif = HWIF(drive); - if (hwgroup->hwif->sharing_irq && - hwif != hwgroup->hwif && - hwif->io_ports[IDE_CONTROL_OFFSET]) { - /* set nIEN for previous hwif */ - SELECT_INTERRUPT(drive); - } - hwgroup->hwif = hwif; - hwgroup->drive = drive; - drive->sleep = 0; - drive->service_start = jiffies; - -queue_next: - if (!ata_can_queue(drive)) { - if (!ata_pending_commands(drive)) - hwgroup->busy = 0; - - break; - } - - if (blk_queue_plugged(&drive->queue)) { - if (drive->using_tcq) - break; - - printk("ide: huh? queue was plugged!\n"); - break; - } - - /* - * we know that the queue isn't empty, but this can happen - * if the q->prep_rq_fn() decides to kill a request - */ - rq = elv_next_request(&drive->queue); - if (!rq) { - hwgroup->busy = !!ata_pending_commands(drive); - break; - } - - if (!rq->bio && ata_pending_commands(drive)) - break; - - hwgroup->rq = rq; - - /* - * Some systems have trouble with IDE IRQs arriving while - * the driver is still setting things up. So, here we disable - * the IRQ used by this interface while the request is being started. - * This may look bad at first, but pretty much the same thing - * happens anyway when any interrupt comes in, IDE or otherwise - * -- the kernel masks the IRQ while it is being handled. - */ - if (masked_irq && hwif->irq != masked_irq) - disable_irq_nosync(hwif->irq); - spin_unlock(&ide_lock); - local_irq_enable(); - /* allow other IRQs while we start this request */ - startstop = start_request(drive, rq); - spin_lock_irq(&ide_lock); - if (masked_irq && hwif->irq != masked_irq) - enable_irq(hwif->irq); - if (startstop == ide_released) - goto queue_next; - if (startstop == ide_stopped) - hwgroup->busy = 0; - } -} - -EXPORT_SYMBOL(ide_do_request); - -/* - * Passes the stuff to ide_do_request - */ -void do_ide_request(request_queue_t *q) -{ - ide_do_request(q->queuedata, 0); -} - -/* - * un-busy the hwgroup etc, and clear any pending DMA status. we want to - * retry the current request in pio mode instead of risking tossing it - * all away - */ -void ide_dma_timeout_retry(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct request *rq; - - /* - * end current dma transaction - */ - (void) hwif->ide_dma_end(drive); - - /* - * complain a little, later we might remove some of this verbosity - */ - printk("%s: timeout waiting for DMA\n", drive->name); - (void) hwif->ide_dma_timeout(drive); - - /* - * disable dma for now, but remember that we did so because of - * a timeout -- we'll reenable after we finish this next request - * (or rather the first chunk of it) in pio. - */ - drive->retry_pio++; - drive->state = DMA_PIO_RETRY; - (void) hwif->ide_dma_off_quietly(drive); - - /* - * un-busy drive etc (hwgroup->busy is cleared on return) and - * make sure request is sane - */ - rq = HWGROUP(drive)->rq; - HWGROUP(drive)->rq = NULL; - - rq->errors = 0; - rq->sector = rq->bio->bi_sector; - rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; - rq->hard_cur_sectors = rq->current_nr_sectors; - if (rq->bio) - rq->buffer = NULL; -} - -EXPORT_SYMBOL(ide_dma_timeout_retry); - -/* - * ide_timer_expiry() is our timeout function for all drive operations. - * But note that it can also be invoked as a result of a "sleep" operation - * triggered by the mod_timer() call in ide_do_request. - */ -void ide_timer_expiry (unsigned long data) -{ - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; - ide_handler_t *handler; - ide_expiry_t *expiry; - unsigned long flags; - unsigned long wait; - - spin_lock_irqsave(&ide_lock, flags); - del_timer(&hwgroup->timer); - - if ((handler = hwgroup->handler) == NULL) { - /* - * Either a marginal timeout occurred - * (got the interrupt just as timer expired), - * or we were "sleeping" to give other devices a chance. - * Either way, we don't really want to complain about anything. - */ - if (hwgroup->sleeping) { - hwgroup->sleeping = 0; - hwgroup->busy = 0; - } - } else { - ide_drive_t *drive = hwgroup->drive; - if (!drive) { - printk("ide_timer_expiry: hwgroup->drive was NULL\n"); - hwgroup->handler = NULL; - } else { - ide_hwif_t *hwif; - ide_startstop_t startstop = ide_stopped; - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); - } - if ((expiry = hwgroup->expiry) != NULL) { - /* continue */ - if ((wait = expiry(drive)) != 0) { - /* reset timer */ - hwgroup->timer.expires = jiffies + wait; - add_timer(&hwgroup->timer); - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - } - hwgroup->handler = NULL; - /* - * We need to simulate a real interrupt when invoking - * the handler() function, which means we need to - * globally mask the specific IRQ: - */ - spin_unlock(&ide_lock); - hwif = HWIF(drive); -#if DISABLE_IRQ_NOSYNC - disable_irq_nosync(hwif->irq); -#else - /* disable_irq_nosync ?? */ - disable_irq(hwif->irq); -#endif /* DISABLE_IRQ_NOSYNC */ - /* local CPU only, - * as if we were handling an interrupt */ - local_irq_disable(); - if (hwgroup->poll_timeout != 0) { - startstop = handler(drive); - } else if (drive_is_ready(drive)) { - if (drive->waiting_for_dma) - (void) hwgroup->hwif->ide_dma_lostirq(drive); - (void)ide_ack_intr(hwif); - printk("%s: lost interrupt\n", drive->name); - startstop = handler(drive); - } else { - if (drive->waiting_for_dma) { - startstop = ide_stopped; - ide_dma_timeout_retry(drive); - } else - startstop = DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG)); - } - set_recovery_timer(hwif); - drive->service_time = jiffies - drive->service_start; - enable_irq(hwif->irq); - spin_lock_irq(&ide_lock); - if (startstop == ide_stopped) - hwgroup->busy = 0; - } - } - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&ide_lock, flags); -} - -EXPORT_SYMBOL(ide_timer_expiry); - -/* - * There's nothing really useful we can do with an unexpected interrupt, - * other than reading the status register (to clear it), and logging it. - * There should be no way that an irq can happen before we're ready for it, - * so we needn't worry much about losing an "important" interrupt here. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the - * drive enters "idle", "standby", or "sleep" mode, so if the status looks - * "good", we just ignore the interrupt completely. - * - * This routine assumes __cli() is in effect when called. - * - * If an unexpected interrupt happens on irq15 while we are handling irq14 - * and if the two interfaces are "serialized" (CMD640), then it looks like - * we could screw up by interfering with a new request being set up for irq15. - * - * In reality, this is a non-issue. The new command is not sent unless the - * drive is ready to accept one, in which case we know the drive is not - * trying to interrupt us. And ide_set_handler() is always invoked before - * completing the issuance of any new drive command, so we will not be - * accidentally invoked as a result of any valid command completion interrupt. - * - */ -static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) -{ - u8 stat; - ide_hwif_t *hwif = hwgroup->hwif; - - /* - * handle the unexpected interrupt - */ - do { - if (hwif->irq == irq) { - stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { - /* Try to not flood the console with msgs */ - static unsigned long last_msgtime, count; - ++count; - if (time_after(jiffies, last_msgtime + HZ)) { - last_msgtime = jiffies; - printk("%s%s: unexpected interrupt, " - "status=0x%02x, count=%ld\n", - hwif->name, - (hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count); - } - } - } - } while ((hwif = hwif->next) != hwgroup->hwif); -} - -/* - * entry point for all interrupts, caller does __cli() for us - */ -void ide_intr (int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; - ide_hwif_t *hwif; - ide_drive_t *drive; - ide_handler_t *handler; - ide_startstop_t startstop; - - spin_lock_irqsave(&ide_lock, flags); - hwif = hwgroup->hwif; - - if (!ide_ack_intr(hwif)) { - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - - if ((handler = hwgroup->handler) == NULL || - hwgroup->poll_timeout != 0) { - /* - * Not expecting an interrupt from this drive. - * That means this could be: - * (1) an interrupt from another PCI device - * sharing the same PCI INT# as us. - * or (2) a drive just entered sleep or standby mode, - * and is interrupting to let us know. - * or (3) a spurious interrupt of unknown origin. - * - * For PCI, we cannot tell the difference, - * so in that case we just ignore it and hope it goes away. - */ -#ifdef CONFIG_BLK_DEV_IDEPCI - if (hwif->pci_dev && !hwif->pci_dev->vendor) -#endif /* CONFIG_BLK_DEV_IDEPCI */ - { - /* - * Probably not a shared PCI interrupt, - * so we can safely try to do something about it: - */ - unexpected_intr(irq, hwgroup); -#ifdef CONFIG_BLK_DEV_IDEPCI - } else { - /* - * Whack the status register, just in case - * we have a leftover pending IRQ. - */ - (void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - drive = hwgroup->drive; - if (!drive) { - /* - * This should NEVER happen, and there isn't much - * we could do about it here. - */ - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - if (!drive_is_ready(drive)) { - /* - * This happens regularly when we share a PCI IRQ with - * another device. Unfortunately, it can also happen - * with some buggy drives that trigger the IRQ before - * their status register is up to date. Hopefully we have - * enough advance overhead that the latter isn't a problem. - */ - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); - } - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock(&ide_lock); - - if (drive->unmask) - local_irq_enable(); - /* service this interrupt, may set handler for next interrupt */ - startstop = handler(drive); - spin_lock_irq(&ide_lock); - - /* - * Note that handler() may have set things up for another - * interrupt to occur soon, but it cannot happen until - * we exit from this routine, because it will be the - * same irq as is currently being serviced here, and Linux - * won't allow another of the same (on any CPU) until we return. - */ - set_recovery_timer(HWIF(drive)); - drive->service_time = jiffies - drive->service_start; - if (startstop == ide_stopped) { - if (hwgroup->handler == NULL) { /* paranoia */ - hwgroup->busy = 0; - ide_do_request(hwgroup, hwif->irq); - } else { - printk("%s: ide_intr: huh? expected NULL handler " - "on exit\n", drive->name); - } - } - spin_unlock_irqrestore(&ide_lock, flags); -} - -EXPORT_SYMBOL(ide_intr); - -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -void ide_init_drive_cmd (struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->flags = REQ_DRIVE_CMD; -} - -EXPORT_SYMBOL(ide_init_drive_cmd); - -/* - * This function issues a special IDE device request - * onto the request queue. - * - * If action is ide_wait, then the rq is queued at the end of the - * request queue, and the function sleeps until it has been processed. - * This is for use when invoked from an ioctl handler. - * - * If action is ide_preempt, then the rq is queued at the head of - * the request queue, displacing the currently-being-processed - * request and this function returns immediately without waiting - * for the new rq to be completed. This is VERY DANGEROUS, and is - * intended for careful use by the ATAPI tape/cdrom driver code. - * - * If action is ide_next, then the rq is queued immediately after - * the currently-being-processed-request (if any), and the function - * returns without waiting for the new rq to be completed. As above, - * This is VERY DANGEROUS, and is intended for careful use by the - * ATAPI tape/cdrom driver code. - * - * If action is ide_end, then the rq is queued at the end of the - * request queue, and the function returns immediately without waiting - * for the new rq to be completed. This is again intended for careful - * use by the ATAPI tape/cdrom driver code. - */ -int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - DECLARE_COMPLETION(wait); - int insert_end = 1, err; - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) - return -ENOSYS; /* special drive cmds not supported */ -#endif - rq->errors = 0; - rq->rq_status = RQ_ACTIVE; - - rq->rq_disk = drive->disk; - - /* - * we need to hold an extra reference to request for safe inspection - * after completion - */ - if (action == ide_wait) { - rq->ref_count++; - rq->waiting = &wait; - } - - spin_lock_irqsave(&ide_lock, flags); - if (action == ide_preempt) { - hwgroup->rq = NULL; - insert_end = 0; - } - __elv_add_request(&drive->queue, rq, insert_end, 0); - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&ide_lock, flags); - - err = 0; - if (action == ide_wait) { - wait_for_completion(&wait); - if (rq->errors) - err = -EIO; - - blk_put_request(rq); - } - - return err; -} - -EXPORT_SYMBOL(ide_do_drive_cmd); void ide_probe_module (void) { @@ -1632,11 +524,18 @@ #define hwif_release_region(addr, num) \ ((hwif->mmio) ? release_mem_region((addr),(num)) : release_region((addr),(num))) -/* - * Note that we only release the standard ports, - * and do not even try to handle any extra ports - * allocated for weird IDE interface chipsets. +/** + * hwif_unregister - free IDE resources + * + * Note that we only release the standard ports, + * and do not even try to handle any extra ports + * allocated for weird IDE interface chipsets. + * + * Note also that we don't yet handle mmio resources here. More + * importantly our caller should be doing this so we need to + * restructure this as a helper function for drivers. */ + void hwif_unregister (ide_hwif_t *hwif) { u32 i = 0; @@ -1665,6 +564,28 @@ extern void init_hwif_data(unsigned int index); +/** + * ide_unregister - free an ide interface + * @index: index of interface (will change soon to a pointer) + * + * Perform the final unregister of an IDE interface. At the moment + * we don't refcount interfaces so this will also get split up. + * + * Locking: + * The caller must not hold the IDE locks + * The drive present/vanishing is not yet properly locked + * Take care with the callbacks. These have been split to avoid + * deadlocking the IDE layer. The shutdown callback is called + * before we take the lock and free resources. It is up to the + * caller to be sure there is no pending I/O here, and that + * the interfce will not be reopened (present/vanishing locking + * isnt yet done btw). After we commit to the final kill we + * call the cleanup callback with the ide locks held. + * + * Unregister restores the hwif structures to the default state. + * This is raving bonkers. + */ + void ide_unregister (unsigned int index) { ide_drive_t *drive, *d; @@ -1675,7 +596,8 @@ ide_hwif_t old_hwif; if (index >= MAX_HWIFS) - return; + BUG(); + spin_lock_irqsave(&ide_lock, flags); hwif = &ide_hwifs[index]; if (!hwif->present) @@ -1686,12 +608,21 @@ continue; if (drive->usage) goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) + if (drive->driver != NULL && DRIVER(drive)->shutdown(drive)) goto abort; } hwif->present = 0; spin_unlock_irqrestore(&ide_lock, flags); + + for (unit = 0; unit < MAX_DRIVES; ++unit) { + drive = &hwif->drives[unit]; + if (!drive->present) + continue; + if (drive->driver != NULL) + DRIVER(drive)->cleanup(drive); + } + #ifdef CONFIG_PROC_FS destroy_proc_ide_drives(hwif); #endif @@ -1752,7 +683,7 @@ else hwgroup->hwif = HWIF(hwgroup->drive); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) if (hwif->dma_base) { (void) ide_release_dma(hwif); @@ -1764,7 +695,7 @@ hwif->dma_vendor3 = 0; hwif->dma_prdtable = 0; } -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ /* * Remove us from the kernel's knowledge @@ -1894,11 +825,21 @@ EXPORT_SYMBOL(ide_unregister); -/* - * Setup hw_regs_t structure described by parameters. You - * may set up the hw structure yourself OR use this routine to - * do it for you. +/** + * ide_setup_ports - set up IDE interface ports + * @hw: register descriptions + * @base: base register + * @offsets: table of register offsets + * @ctrl: control register + * @ack_irq: IRQ ack + * @irq: interrupt lie + * + * Setup hw_regs_t structure described by parameters. You + * may set up the hw structure yourself OR use this routine to + * do it for you. This is basically a helper + * */ + void ide_setup_ports ( hw_regs_t *hw, ide_ioreg_t base, int *offsets, ide_ioreg_t ctrl, ide_ioreg_t intr, @@ -2004,6 +945,27 @@ EXPORT_SYMBOL(ide_register); +/** + * ide_add_setting - attach an IDE setting + * drive: drive the setting is for + * name: name of setting + * rw: set if writable + * read_ioctl: read function + * write_ioctl: write function + * data_type: form expected + * min: minimum + * max: maximum + * mul_factor: multiply by + * div_factor: divide by + * data: value + * set: handling for setting + * + * Add a setting to the IDE drive. Support automatic removal and allow + * all the work to be done by plugged in handlers. This code is also + * rather short on locking, but the current plan is to do the locking + * internally to the function. + */ + void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; @@ -2038,6 +1000,14 @@ EXPORT_SYMBOL(ide_add_setting); +/** + * ide_remove_setting - remove an ioctl setting + * @name: name of the property + * + * Remove a drive ioctl setting that was created by ide_add_setting. + * Again this needs the locking fixed + */ + void ide_remove_setting (ide_drive_t *drive, char *name) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting; @@ -2053,6 +1023,16 @@ EXPORT_SYMBOL(ide_remove_setting); +/** + * ide_find_setting_by_ioctl - find a setting handler by its command + * @drive: drive to act for + * @cmd: ioctl command code + * + * Scan the drive handlers for an ioctl handler for this function. + * The handlers vary by drive and sometimes by drive state. + * Needs locking fixes. + */ + static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) { ide_settings_t *setting = drive->settings; @@ -2065,6 +1045,16 @@ return setting; } +/** + * ide_find_setting_by_name - find a setting handler by its name + * @drive: drive to act for + * @cmd: ioctl command code + * + * Scan the drive handlers handler matching the name for this function. + * The handlers vary by drive and sometimes by drive state. + * Needs locking fixes. + */ + ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) { ide_settings_t *setting = drive->settings; @@ -2077,6 +1067,17 @@ return setting; } +/** + * auto_remove_settings - remove driver settings on a device + * @drive: drive to clean + * + * Called when we change the driver bindings for a device, for + * example if the device is hot plugged. We must scrub the driver + * bindings that are thus no longer relevant to the device in case + * it changes from say a CD-ROM to a disk + * Needs locking fixes + */ + static void auto_remove_settings (ide_drive_t *drive) { ide_settings_t *setting; @@ -2128,7 +1129,7 @@ local_irq_set(lflags); if (time_after(jiffies, timeout)) { local_irq_restore(lflags); - printk("%s: channel busy\n", drive->name); + printk(KERN_ERR "%s: channel busy\n", drive->name); return -EBUSY; } local_irq_restore(lflags); @@ -2229,8 +1230,7 @@ SETFEATURES_XFER, 0, NULL); if (!err && arg) { - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, (u8) arg); + ide_set_xfer_rate(drive, (u8) arg); ide_driveid_update(drive); } return err; @@ -2312,7 +1312,7 @@ */ int ide_replace_subdriver (ide_drive_t *drive, const char *driver) { - if (!drive->present || drive->usage) + if (!drive->present || drive->usage || drive->dead) goto abort; if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) goto abort; @@ -2487,7 +1487,7 @@ #if 1 spin_lock_irqsave(&ide_lock, flags); if ( HWGROUP(drive)->handler != NULL) { - printk("%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler); + printk(KERN_ERR "%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler); (void) HWGROUP(drive)->handler(drive); // HWGROUP(drive)->handler = NULL; HWGROUP(drive)->expiry = NULL; @@ -2702,7 +1702,7 @@ strncmp(s,"hd",2)) /* hdx= & hdxlun= */ return 0; - printk("ide_setup: %s", s); + printk(KERN_INFO "ide_setup: %s", s); init_ide_data (); #ifdef CONFIG_BLK_DEV_IDEDOUBLER @@ -3050,18 +2050,6 @@ swarm_ide_probe(); } #endif /* CONFIG_BLK_DEV_IDE_SWARM */ -#ifdef CONFIG_BLK_DEV_IDE_ICSIDE - { - extern void icside_init(void); - icside_init(); - } -#endif /* CONFIG_BLK_DEV_IDE_ICSIDE */ -#ifdef CONFIG_BLK_DEV_IDE_RAPIDE - { - extern void rapide_init(void); - rapide_init(); - } -#endif /* CONFIG_BLK_DEV_IDE_RAPIDE */ #ifdef CONFIG_BLK_DEV_GAYLE { extern void gayle_init(void); @@ -3122,21 +2110,39 @@ #endif } -static int default_standby (ide_drive_t *drive) -{ - return 0; -} - -static int default_suspend (ide_drive_t *drive) +/* + * Actually unregister the subdriver. Called with the + * request lock dropped. + */ + +static int default_cleanup (ide_drive_t *drive) { - return 0; + return ide_unregister_subdriver(drive); } -static int default_resume (ide_drive_t *drive) +/* + * Check if we can unregister the subdriver. Called with the + * request lock held. + */ + +static int default_shutdown(ide_drive_t *drive) { + if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) { + return 1; + } + drive->dead = 1; return 0; } +/* + * Default function to use for the cache flush operation. This + * must be replaced for disk devices (see ATA specification + * documents on cache flush and drive suspend rules) + * + * If we have no device attached or the device is not writable + * this handler is sufficient. + */ + static int default_flushcache (ide_drive_t *drive) { return 0; @@ -3193,9 +2199,8 @@ { ide_driver_t *d = drive->driver; - if (d->standby == NULL) d->standby = default_standby; - if (d->suspend == NULL) d->suspend = default_suspend; - if (d->resume == NULL) d->resume = default_resume; + if (d->cleanup == NULL) d->cleanup = default_cleanup; + if (d->shutdown == NULL) d->shutdown = default_shutdown; if (d->flushcache == NULL) d->flushcache = default_flushcache; if (d->do_request == NULL) d->do_request = default_do_request; if (d->end_request == NULL) d->end_request = default_end_request; @@ -3213,7 +2218,7 @@ spin_lock_irqsave(&ide_lock, flags); if (version != IDE_SUBDRIVER_VERSION || !drive->present || - drive->driver != NULL || drive->usage) { + drive->driver != NULL || drive->usage || drive->dead) { spin_unlock_irqrestore(&ide_lock, flags); return 1; } @@ -3274,13 +2279,8 @@ ide_drive_t * drive = container_of(dev,ide_drive_t,gendev); ide_driver_t * driver = drive->driver; - if (driver) { - if (driver->standby) - driver->standby(drive); - if (driver->cleanup) - driver->cleanup(drive); - } - + if (driver && driver->cleanup) + driver->cleanup(drive); return 0; } @@ -3321,7 +2321,7 @@ while(!list_empty(&driver->drives)) { drive = list_entry(driver->drives.next, ide_drive_t, list); if (driver->cleanup(drive)) { - printk("%s: cleanup_module() called while still busy\n", drive->name); + printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); BUG(); } /* We must remove proc entries defined in this module. @@ -3395,7 +2395,7 @@ if ((next = strchr(line,' ')) != NULL) *next++ = 0; if (!ide_setup(line)) - printk ("Unknown option '%s'\n", line); + printk (KERN_INFO "Unknown option '%s'\n", line); } } @@ -3411,10 +2411,10 @@ for (index = 0; index < MAX_HWIFS; ++index) { ide_unregister(index); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) if (ide_hwifs[index].dma_base) (void) ide_release_dma(&ide_hwifs[index]); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ } #ifdef CONFIG_PROC_FS diff -Nru a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c --- a/drivers/ide/legacy/ide-cs.c Wed Nov 27 14:36:31 2002 +++ b/drivers/ide/legacy/ide-cs.c Wed Nov 27 14:36:31 2002 @@ -411,6 +411,8 @@ DEBUG(0, "ide_release(0x%p)\n", link); if (info->ndev) { + /* FIXME: if this fails we need to queue the cleanup somehow + -- need to investigate the required PCMCIA magic */ ide_unregister(info->hd); /* deal with brain dead IDE resource management */ request_region(link->io.BasePort1, link->io.NumPorts1, diff -Nru a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile --- a/drivers/ide/pci/Makefile Wed Nov 27 14:36:28 2002 +++ b/drivers/ide/pci/Makefile Wed Nov 27 14:36:28 2002 @@ -5,7 +5,9 @@ obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o +obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o +obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o diff -Nru a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c --- a/drivers/ide/pci/aec62xx.c Wed Nov 27 14:36:31 2002 +++ b/drivers/ide/pci/aec62xx.c Wed Nov 27 14:36:31 2002 @@ -292,7 +292,6 @@ } } -#ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, aec62xx_ratemask(drive)); @@ -303,7 +302,6 @@ (void) aec62xx_tune_chipset(drive, speed); return ide_dma_enable(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) { @@ -321,7 +319,6 @@ (void) aec62xx_tune_chipset(drive, speed); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -405,7 +402,6 @@ #endif return 0; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_aec62xx (struct pci_dev *dev, const char *name) { @@ -457,7 +453,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate; hwif->ide_dma_lostirq = &aec62xx_irq_timeout; hwif->ide_dma_timeout = &aec62xx_irq_timeout; @@ -465,7 +460,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_aec62xx (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/aec62xx.h b/drivers/ide/pci/aec62xx.h --- a/drivers/ide/pci/aec62xx.h Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/pci/aec62xx.h Wed Nov 27 14:36:30 2002 @@ -14,7 +14,6 @@ }; struct chipset_bus_clock_list_entry aec6xxx_33_base [] = { -#ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_6, 0x31, 0x07 }, { XFER_UDMA_5, 0x31, 0x06 }, { XFER_UDMA_4, 0x31, 0x05 }, @@ -26,7 +25,6 @@ { XFER_MW_DMA_2, 0x31, 0x00 }, { XFER_MW_DMA_1, 0x31, 0x00 }, { XFER_MW_DMA_0, 0x0a, 0x00 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ { XFER_PIO_4, 0x31, 0x00 }, { XFER_PIO_3, 0x33, 0x00 }, { XFER_PIO_2, 0x08, 0x00 }, @@ -36,7 +34,6 @@ }; struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { -#ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_6, 0x41, 0x06 }, { XFER_UDMA_5, 0x41, 0x05 }, { XFER_UDMA_4, 0x41, 0x04 }, @@ -48,7 +45,6 @@ { XFER_MW_DMA_2, 0x41, 0x00 }, { XFER_MW_DMA_1, 0x42, 0x00 }, { XFER_MW_DMA_0, 0x7a, 0x00 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ { XFER_PIO_4, 0x41, 0x00 }, { XFER_PIO_3, 0x43, 0x00 }, { XFER_PIO_2, 0x78, 0x00 }, diff -Nru a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c --- a/drivers/ide/pci/alim15x3.c Wed Nov 27 14:36:29 2002 +++ b/drivers/ide/pci/alim15x3.c Wed Nov 27 14:36:29 2002 @@ -450,7 +450,6 @@ if (speed < XFER_SW_DMA_0) ali15x3_tune_drive(drive, speed); -#ifdef CONFIG_BLK_DEV_IDEDMA } else { pci_read_config_byte(dev, m5229_udma, &tmpbyte); tmpbyte &= (0x0f << ((1-unit) << 2)); @@ -464,12 +463,10 @@ tmpbyte |= 1; pci_write_config_byte(dev, 0x4b, tmpbyte); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ } return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /** * config_chipset_for_dma - set up DMA mode @@ -562,7 +559,6 @@ return 1; /* try PIO instead of DMA */ return __ide_dma_write(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /** * init_chipset_ali15x3 - Initialise an ALi IDE controller @@ -756,7 +752,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (m5229_revision >= 0x20) { /* * M1543C or newer for DMAing @@ -770,7 +765,6 @@ } hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } /** @@ -854,6 +848,12 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) { ide_pci_device_t *d = &ali15x3_chipsets[id->driver_data]; + + if(pci_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_IGP, NULL)) + { + printk(KERN_ERR "Warning: ATI Radeon IGP Northbridge is not supported by Linux\n"); + return 1; + } #if defined(CONFIG_SPARC64) d->init_hwif = init_hwif_common_ali15x3; #endif /* CONFIG_SPARC64 */ diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c --- a/drivers/ide/pci/amd74xx.c Wed Nov 27 14:36:32 2002 +++ b/drivers/ide/pci/amd74xx.c Wed Nov 27 14:36:32 2002 @@ -148,7 +148,6 @@ pio_timing &= ~(0x03 << drive->dn); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_7: case XFER_UDMA_6: speed = XFER_UDMA_5; @@ -194,7 +193,6 @@ case XFER_SW_DMA_0: dma_pio_timing |= 0xA8; break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: dma_pio_timing |= 0x20; break; @@ -215,9 +213,7 @@ pio_timing |= (0x03 << drive->dn); -#ifdef CONFIG_BLK_DEV_IDEDMA pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing); -#endif /* CONFIG_BLK_DEV_IDEDMA */ pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing); pci_write_config_byte(dev, 0x4c, pio_timing); @@ -230,7 +226,6 @@ (void) amd74xx_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities @@ -290,14 +285,11 @@ } return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_amd74xx (struct pci_dev *dev, const char *name) { -#ifdef CONFIG_BLK_DEV_IDEDMA if (!amd74xx_swdma_check(dev)) printk("%s: disabling single-word DMA support (revision < C4)\n", name); -#endif /* CONFIG_BLK_DEV_IDEDMA */ #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) if (!amd74xx_proc) { @@ -348,11 +340,7 @@ default: break; } -#ifdef CONFIG_AMD74XX_OVERRIDE - return(1); -#else return (unsigned int) ata66; -#endif /* CONFIG_AMD74XX_OVERRIDE */ } static void __init init_hwif_amd74xx (ide_hwif_t *hwif) @@ -373,7 +361,6 @@ if (amd74xx_swdma_check(hwif->pci_dev)) hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!(hwif->udma_four)) hwif->udma_four = ata66_amd74xx(hwif); hwif->ide_dma_check = &amd74xx_config_drive_xfer_rate; @@ -381,7 +368,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_amd74xx (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c --- a/drivers/ide/pci/cmd640.c Wed Nov 27 14:36:31 2002 +++ b/drivers/ide/pci/cmd640.c Wed Nov 27 14:36:31 2002 @@ -751,7 +751,7 @@ */ put_cmd640_reg(0x5b, 0xbd); if (get_cmd640_reg(0x5b) != 0xbd) { - printk("ide: cmd640 init failed: wrong value in reg 0x5b\n"); + printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n"); return 0; } put_cmd640_reg(0x5b, 0); @@ -836,7 +836,7 @@ cmd_hwif1->tuneproc = &cmd640_tune_drive; #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ } - printk("%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, + printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, cmd_hwif0->serialized ? "" : "not ", port2); /* diff -Nru a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c --- a/drivers/ide/pci/cmd64x.c Wed Nov 27 14:36:31 2002 +++ b/drivers/ide/pci/cmd64x.c Wed Nov 27 14:36:31 2002 @@ -383,18 +383,15 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) { -#ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 unit = (drive->select.b.unit & 0x01); u8 regU = 0, pciU = (hwif->channel) ? UDIDETCR1 : UDIDETCR0; u8 regD = 0, pciD = (hwif->channel) ? BMIDESR1 : BMIDESR0; -#endif /* CONFIG_BLK_DEV_IDEDMA */ u8 speed = ide_rate_filter(cmd64x_ratemask(drive), xferspeed); -#ifdef CONFIG_BLK_DEV_IDEDMA if (speed > XFER_PIO_4) { (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); @@ -405,10 +402,8 @@ (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_5: regU |= (unit ? 0x0A : 0x05); break; case XFER_UDMA_4: regU |= (unit ? 0x4A : 0x15); break; case XFER_UDMA_3: regU |= (unit ? 0x8A : 0x25); break; @@ -421,7 +416,6 @@ case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; case XFER_PIO_2: cmd64x_tuneproc(drive, 2); break; @@ -432,29 +426,26 @@ return 1; } -#ifdef CONFIG_BLK_DEV_IDEDMA if (speed > XFER_PIO_4) { (void) pci_write_config_byte(dev, pciU, regU); regD |= (unit ? 0x40 : 0x20); (void) pci_write_config_byte(dev, pciD, regD); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); - config_chipset_for_pio(drive, (!(speed))); + config_chipset_for_pio(drive, !speed); - if ((!(speed))) + if (!speed) return 0; - if (HWIF(drive)->speedproc(drive, speed)) - return 0; + if(ide_set_xfer_rate(drive, speed)) + return 0; if (!drive->init_speed) drive->init_speed = speed; @@ -593,7 +584,6 @@ /* verify good DMA status */ return (dma_stat & 7) != 4; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_cmd64x (struct pci_dev *dev, const char *name) { @@ -732,7 +722,6 @@ if (dev->device == PCI_DEVICE_ID_CMD_648) hwif->ultra_mask = 0x1f; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &cmd64x_config_drive_for_dma; if (!(hwif->udma_four)) hwif->udma_four = ata66_cmd64x(hwif); @@ -755,7 +744,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_cmd64x (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ide/pci/cs5520.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,323 @@ +/* + * IDE tuning and bus mastering support for the CS5510/CS5520 + * chipsets + * + * The CS5510/CS5520 are slightly unusual devices. Unlike the + * typical IDE controllers they do bus mastering with the drive in + * PIO mode and smarter silicon. + * + * The practical upshot of this is that we must always tune the + * drive for the right PIO mode. We must also ignore all the blacklists + * and the drive bus mastering DMA information. + * + * *** This driver is strictly experimental *** + * + * (c) Copyright Red Hat Inc 2002 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open non patent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" +#include "cs5520.h" + +#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 cs5520_proc = 0; +static struct pci_dev *bmide_dev; + +static int cs5520_get_info(char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + unsigned long bmiba = pci_resource_start(bmide_dev, 2); + u8 c0 = 0, c1 = 0; + u16 reg16; + u32 reg32; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb((unsigned short)bmiba + 0x02); + c1 = inb((unsigned short)bmiba + 0x0a); + + p += sprintf(p, "\nCyrix CS55x0 IDE\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + + p += sprintf(p, "\n\nTimings: \n"); + + pci_read_config_word(bmide_dev, 0x62, ®16); + p += sprintf(p, "8bit CAT/CRT : %04x\n", reg16); + pci_read_config_dword(bmide_dev, 0x64, ®32); + p += sprintf(p, "16bit Primary : %08x\n", reg32); + pci_read_config_dword(bmide_dev, 0x68, ®32); + p += sprintf(p, "16bit Secondary: %08x\n", reg32); + + return p-buffer; +} + +#endif + +struct pio_clocks +{ + int address; + int assert; + int recovery; +}; + +struct pio_clocks cs5520_pio_clocks[]={ + {3, 6, 11}, + {2, 5, 6}, + {1, 4, 3}, + {1, 3, 2}, + {1, 2, 1} +}; + +static int cs5520_tune_chipset(ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *pdev = hwif->pci_dev; + u8 speed = min((u8)XFER_PIO_4, xferspeed); + int pio = speed; + u8 reg; + int controller = drive->dn > 1 ? 1 : 0; + int error; + + switch(speed) + { + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + pio -= XFER_PIO_0; + break; + default: + pio = 0; + printk(KERN_ERR "cs55x0: bad ide timing.\n"); + } + + printk("PIO clocking = %d\n", pio); + + /* FIXME: if DMA = 1 do we need to set the DMA bit here ? */ + + /* 8bit command timing for channel */ + pci_write_config_byte(pdev, 0x62 + controller, + (cs5520_pio_clocks[pio].recovery << 4) | + (cs5520_pio_clocks[pio].assert)); + + /* FIXME: should these use address ? */ + /* Data read timing */ + pci_write_config_byte(pdev, 0x64 + 4*controller + (drive->dn&1), + (cs5520_pio_clocks[pio].recovery << 4) | + (cs5520_pio_clocks[pio].assert)); + /* Write command timing */ + pci_write_config_byte(pdev, 0x66 + 4*controller + (drive->dn&1), + (cs5520_pio_clocks[pio].recovery << 4) | + (cs5520_pio_clocks[pio].assert)); + + /* Set the DMA enable/disable flag */ + reg = inb(hwif->dma_base + 0x02 + 8*controller); + reg |= 1<<((drive->dn&1)+5); + outb(reg, hwif->dma_base + 0x02 + 8*controller); + + error = ide_config_drive_speed(drive, speed); + /* ATAPI is harder so leave it for now */ + if(!error && drive->media == ide_disk) + error = hwif->ide_dma_on(drive); +} + +static void cs5520_tune_drive(ide_drive_t *drive, u8 pio) +{ + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + cs5520_tune_chipset(drive, (XFER_PIO_0 + pio)); +} + +static int cs5520_config_drive_xfer_rate(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + + /* Tune the drive for PIO modes up to PIO 4 */ + cs5520_tune_drive(drive, 4); + /* Then tell the core to use DMA operations */ + return hwif->ide_dma_on(drive); +} + + +static unsigned int __devinit init_chipset_cs5520(struct pci_dev *dev, const char *name) +{ +#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) + if (!cs5520_proc) { + cs5520_proc = 1; + bmide_dev = dev; + ide_pci_register_host_proc(&cs5520_procs[0]); + } +#endif /* DISPLAY_CS5520_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + +/* + * We provide a callback for our nonstandard DMA location + */ + +static void __devinit cs5520_init_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif) +{ + u32 bmide = pci_resource_start(dev, 2); /* Not the usual 4 */ + if(hwif->mate && hwif->mate->dma_base) /* Second channel at primary + 8 */ + bmide += 8; + ide_setup_dma(hwif, bmide, 8); +} + +/* + * We wrap the DMA activate to set the vdma flag. This is needed + * so that the IDE DMA layer issues PIO not DMA commands over the + * DMA channel + */ + +static int cs5520_dma_on(ide_drive_t *drive) +{ + drive->vdma = 1; + return 0; +} + +static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) +{ + hwif->tuneproc = &cs5520_tune_drive; + hwif->speedproc = &cs5520_tune_chipset; + hwif->ide_dma_check = &cs5520_config_drive_xfer_rate; + hwif->ide_dma_on = &cs5520_dma_on; + + if(!noautodma) + hwif->autodma = 1; + + if(!hwif->dma_base) + { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->atapi_dma = 0; + hwif->ultra_mask = 0; + hwif->swdma_mask = 0; + hwif->mwdma_mask = 0; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +/* + * The 5510/5520 are a bit weird. They don't quite set up the way + * the PCI helper layer expects so we must do much of the set up + * work longhand. + */ + +static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ata_index_t index; + ide_pci_device_t *d = &cyrix_chipsets[id->driver_data]; + + ide_setup_pci_noise(dev, d); + + /* We must not grab the entire device, it has 'ISA' space in its + BARS too and we will freak out other bits of the kernel */ + if(pci_enable_device_bars(dev, 1<<2)) + { + printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name); + return 1; + } + pci_set_master(dev); + pci_set_dma_mask(dev, 0xFFFFFFFF); + init_chipset_cs5520(dev, d->name); + + index.all = 0xf0f0; + + /* + * Now the chipset is configured we can let the core + * do all the device setup for us + */ + + ide_pci_setup_ports(dev, d, 1, 14, &index); + + printk("Index.b %d %d\n", index.b.low, index.b.high); + mdelay(2000); + if((index.b.low & 0xf0) != 0xf0) + probe_hwif_init(&ide_hwifs[index.b.low]); + if((index.b.high & 0xf0) != 0xf0) + probe_hwif_init(&ide_hwifs[index.b.high]); + + return 0; +} + +static struct pci_device_id cs5520_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "CyrixIDE", + .id_table = cs5520_pci_tbl, + .probe = cs5520_init_one, +}; + +static int cs5520_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void cs5520_ide_exit(void) +{ + return ide_pci_unregister_driver(&driver); +} + +module_init(cs5520_ide_init); +module_exit(cs5520_ide_exit); + +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("PCI driver module for Cyrix 5510/5520 IDE"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; + diff -Nru a/drivers/ide/pci/cs5520.h b/drivers/ide/pci/cs5520.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ide/pci/cs5520.h Wed Nov 27 14:36:32 2002 @@ -0,0 +1,66 @@ +#ifndef CS5520_H +#define CS5520_H + +#include +#include +#include + +#define DISPLAY_CS5520_TIMINGS + +#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 cs5520_proc; + +static int cs5520_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t cs5520_procs[] __initdata = { + { + name: "cs5520", + set: 1, + get_info: cs5520_get_info, + parent: NULL, + }, +}; +#endif /* defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static unsigned int init_chipset_cs5520(struct pci_dev *, const char *); +static void init_hwif_cs5520(ide_hwif_t *); +static void cs5520_init_setup_dma(struct pci_dev *dev, struct ide_pci_device_s *d, ide_hwif_t *hwif); + +static ide_pci_device_t cyrix_chipsets[] __devinitdata = { + { + vendor: PCI_VENDOR_ID_CYRIX, + device: PCI_DEVICE_ID_CYRIX_5510, + name: "Cyrix 5510", + init_chipset: init_chipset_cs5520, + init_setup_dma: cs5520_init_setup_dma, + init_iops: NULL, + init_hwif: init_hwif_cs5520, + isa_ports: 1, + channels: 2, + autodma: AUTODMA, + bootable: ON_BOARD, + extra: 0, + }, + { + vendor: PCI_VENDOR_ID_CYRIX, + device: PCI_DEVICE_ID_CYRIX_5520, + name: "Cyrix 5520", + init_chipset: init_chipset_cs5520, + init_setup_dma: cs5520_init_setup_dma, + init_iops: NULL, + init_hwif: init_hwif_cs5520, + isa_ports: 1, + channels: 2, + autodma: AUTODMA, + bootable: ON_BOARD, + extra: 0, + } +}; + + +#endif /* CS5520_H */ + + diff -Nru a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c --- a/drivers/ide/pci/cs5530.c Wed Nov 27 14:36:28 2002 +++ b/drivers/ide/pci/cs5530.c Wed Nov 27 14:36:28 2002 @@ -135,8 +135,6 @@ } } -#ifdef CONFIG_BLK_DEV_IDEDMA - /** * cs5530_config_dma - select/set DMA and UDMA modes * @drive: drive to tune @@ -256,7 +254,6 @@ */ return hwif->ide_dma_on(drive); /* success */ } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /** * init_chipset_5530 - set up 5530 bridge @@ -396,13 +393,11 @@ hwif->ultra_mask = 0x07; hwif->mwdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &cs5530_config_dma; if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } /** diff -Nru a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c --- a/drivers/ide/pci/cy82c693.c Wed Nov 27 14:36:28 2002 +++ b/drivers/ide/pci/cy82c693.c Wed Nov 27 14:36:28 2002 @@ -123,10 +123,10 @@ p_pclk->time_8 = (u8)clk1; } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * set DMA mode a specific channel for CY82C693 */ + static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) { u8 index = 0, data = 0; @@ -213,7 +213,6 @@ } return __ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * tune ide drive - set PIO mode @@ -405,13 +404,11 @@ hwif->mwdma_mask = 0x04; hwif->swdma_mask = 0x04; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_on = &cy82c693_ide_dma_on; if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static __initdata ide_hwif_t *primary; diff -Nru a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c --- a/drivers/ide/pci/generic.c Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/pci/generic.c Wed Nov 27 14:36:30 2002 @@ -50,12 +50,10 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void init_dma_generic (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c --- a/drivers/ide/pci/hpt34x.c Wed Nov 27 14:36:29 2002 +++ b/drivers/ide/pci/hpt34x.c Wed Nov 27 14:36:29 2002 @@ -159,13 +159,13 @@ (void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities * after the drive is reported by the OS. Initally for designed for * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. */ + static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, hpt34x_ratemask(drive)); @@ -224,7 +224,6 @@ #endif /* CONFIG_HPT34X_AUTODMA */ return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * If the BIOS does not set the IO base addaress to XX00, 343 will fail. @@ -306,13 +305,11 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &hpt34x_config_drive_xfer_rate; if (!noautodma) hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_hpt34x (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c --- a/drivers/ide/pci/hpt366.c Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/pci/hpt366.c Wed Nov 27 14:36:30 2002 @@ -216,7 +216,6 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA struct pci_dev *dev = HWIF(drive)->pci_dev; u8 mode = hpt3xx_ratemask(drive); @@ -264,9 +263,6 @@ break; } return speed; -#else - return min(speed, (u8)XFER_PIO_4); -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static int check_in_drive_lists (ide_drive_t *drive, const char **list) @@ -297,7 +293,7 @@ { struct pci_dev *dev = HWIF(drive)->pci_dev; u8 speed = hpt3xx_ratefilter(drive, xferspeed); -// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); +// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; u8 drive_fast = 0; @@ -444,7 +440,6 @@ (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities @@ -654,7 +649,6 @@ pci_write_config_byte(dev, mscreg, msc_stat|0x30); return __ide_dma_end(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * Since SUN Cobalt is attempting to do this operation, I should disclose @@ -1030,7 +1024,6 @@ hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!(hwif->udma_four)) hwif->udma_four = ((ata66 & regmask) ? 0 : 1); hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; @@ -1053,7 +1046,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/it8172.c b/drivers/ide/pci/it8172.c --- a/drivers/ide/pci/it8172.c Wed Nov 27 14:36:31 2002 +++ b/drivers/ide/pci/it8172.c Wed Nov 27 14:36:31 2002 @@ -151,7 +151,6 @@ */ switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_4: case XFER_UDMA_2: //u_speed = 2 << (drive->dn * 4); break; case XFER_UDMA_5: @@ -162,7 +161,6 @@ case XFER_MW_DMA_1: case XFER_MW_DMA_0: case XFER_SW_DMA_2: break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: case XFER_PIO_3: case XFER_PIO_2: @@ -183,7 +181,6 @@ return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int it8172_config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, it8172_ratemask(drive)); @@ -239,7 +236,6 @@ } return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_it8172 (struct pci_dev *dev, const char *name) { @@ -282,13 +278,11 @@ hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &it8172_config_drive_xfer_rate; if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* !CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_it8172 (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c --- a/drivers/ide/pci/ns87415.c Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/pci/ns87415.c Wed Nov 27 14:36:30 2002 @@ -83,7 +83,6 @@ ns87415_prepare_drive (drive, drive->using_dma); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int ns87415_ide_dma_end (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -132,7 +131,6 @@ return HWIF(drive)->ide_dma_off_quietly(drive); return __ide_dma_check(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static void __init init_hwif_ns87415 (ide_hwif_t *hwif) { @@ -209,7 +207,6 @@ if (!hwif->dma_base) return; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->OUTB(0x60, hwif->dma_status); hwif->ide_dma_read = &ns87415_ide_dma_read; hwif->ide_dma_write = &ns87415_ide_dma_write; @@ -220,7 +217,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_ns87415 (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/nvidia.c b/drivers/ide/pci/nvidia.c --- a/drivers/ide/pci/nvidia.c Wed Nov 27 14:36:32 2002 +++ b/drivers/ide/pci/nvidia.c Wed Nov 27 14:36:32 2002 @@ -38,7 +38,7 @@ static int nforce_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); + unsigned long bibma = pci_resource_start(bmide_dev, 4); u8 c0 = 0, c1 = 0; /* @@ -109,7 +109,6 @@ pio_timing &= ~(0x03 << drive->dn); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_7: case XFER_UDMA_6: speed = XFER_UDMA_5; @@ -155,7 +154,6 @@ case XFER_SW_DMA_0: dma_pio_timing |= 0xA8; break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: dma_pio_timing |= 0x20; break; @@ -176,9 +174,7 @@ pio_timing |= (0x03 << drive->dn); -#ifdef CONFIG_BLK_DEV_IDEDMA pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing); -#endif /* CONFIG_BLK_DEV_IDEDMA */ pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing); pci_write_config_byte(dev, 0x5c, pio_timing); @@ -191,7 +187,6 @@ (void) nforce_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities @@ -251,9 +246,8 @@ } return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -unsigned int __init init_chipset_nforce (struct pci_dev *dev, const char *name) +static unsigned int __init init_chipset_nforce (struct pci_dev *dev, const char *name) { #if defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) if (!nforce_proc) { @@ -318,7 +312,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!(hwif->udma_four)) hwif->udma_four = ata66_nforce(hwif); hwif->ide_dma_check = &nforce_config_drive_xfer_rate; @@ -326,7 +319,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } /* FIXME - not needed */ diff -Nru a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c --- a/drivers/ide/pci/opti621.c Wed Nov 27 14:36:29 2002 +++ b/drivers/ide/pci/opti621.c Wed Nov 27 14:36:29 2002 @@ -343,13 +343,10 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - } static void __init init_dma_opti621 (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c --- a/drivers/ide/pci/pdc202xx_new.c Wed Nov 27 14:36:31 2002 +++ b/drivers/ide/pci/pdc202xx_new.c Wed Nov 27 14:36:31 2002 @@ -165,7 +165,6 @@ pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); } -#ifdef CONFIG_BLK_DEV_IDEDMA } else { if ((BP & 0xF0) && (CP & 0x0F)) { /* clear DMA modes of upper 842 bits of B Register */ @@ -177,7 +176,6 @@ pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F); pci_read_config_byte(dev, (drive_pci)|0x02, &CP); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ } pci_read_config_byte(dev, (drive_pci), &AP); @@ -185,7 +183,6 @@ pci_read_config_byte(dev, (drive_pci)|0x02, &CP); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_6: speed = XFER_UDMA_5; case XFER_UDMA_5: case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; @@ -199,7 +196,6 @@ case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: TA = 0x01; TB = 0x04; break; case XFER_PIO_3: TA = 0x02; TB = 0x06; break; case XFER_PIO_2: TA = 0x03; TB = 0x08; break; @@ -211,11 +207,9 @@ if (speed < XFER_SW_DMA_0) { pci_write_config_byte(dev, (drive_pci), AP|TA); pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); -#ifdef CONFIG_BLK_DEV_IDEDMA } else { pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); -#endif /* CONFIG_BLK_DEV_IDEDMA */ } #if PDC202XX_DECODE_REGISTER_INFO @@ -243,28 +237,18 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); -#ifdef CONFIG_BLK_DEV_IDEDMA u32 indexreg = hwif->dma_vendor1; u32 datareg = hwif->dma_vendor3; -#else /* !CONFIG_BLK_DEV_IDEDMA */ - struct pci_dev *dev = hwif->pci_dev; - u32 high_16 = pci_resource_start(dev, 4); - u32 indexreg = high_16 + (hwif->channel ? 0x09 : 0x01); - u32 datareg = (indexreg + 2); -#endif /* CONFIG_BLK_DEV_IDEDMA */ u8 thold = 0x10; u8 adj = (drive->dn%2) ? 0x08 : 0x00; u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); -#ifdef CONFIG_BLK_DEV_IDEDMA if (speed == XFER_UDMA_2) { hwif->OUTB((thold + adj), indexreg); hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ switch (speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_7: speed = XFER_UDMA_6; case XFER_UDMA_6: set_ultra(0x1a, 0x01, 0xcb); break; @@ -277,7 +261,6 @@ case XFER_MW_DMA_2: set_ata2(0x69, 0x25); break; case XFER_MW_DMA_1: set_ata2(0x6b, 0x27); break; case XFER_MW_DMA_0: set_ata2(0xdf, 0x5f); break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: set_pio(0x23, 0x09, 0x25); break; case XFER_PIO_3: set_pio(0x27, 0x0d, 0x35); break; case XFER_PIO_2: set_pio(0x23, 0x26, 0x64); break; @@ -301,7 +284,7 @@ { u8 speed = 0; - pio = (pio == 5) ? 4 : pio; + if (pio == 5) pio = 4; speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); return ((int) pdcnew_tune_chipset(drive, speed)); @@ -312,8 +295,6 @@ (void) config_chipset_for_pio(drive, pio); } -#ifdef CONFIG_BLK_DEV_IDEDMA - static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) { hwif->OUTB(0x0b, hwif->dma_vendor1); @@ -458,8 +439,6 @@ return __ide_dma_timeout(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - static void pdcnew_new_reset (ide_drive_t *drive) { /* @@ -471,12 +450,8 @@ static void pdcnew_reset_host (ide_hwif_t *hwif) { -#ifdef CONFIG_BLK_DEV_IDEDMA // unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); unsigned long high_16 = hwif->dma_master; -#else /* !CONFIG_BLK_DEV_IDEDMA */ - unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); -#endif /* CONFIG_BLK_DEV_IDEDMA */ u8 udma_speed_flag = hwif->INB(high_16|0x001f); hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f)); @@ -571,8 +546,6 @@ hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; @@ -581,7 +554,6 @@ if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ #if PDC202_DEBUG_CABLE printk("%s: %s-pin cable\n", hwif->name, hwif->udma_four ? "80" : "40"); diff -Nru a/drivers/ide/pci/pdc202xx_new.h b/drivers/ide/pci/pdc202xx_new.h --- a/drivers/ide/pci/pdc202xx_new.h Wed Nov 27 14:36:27 2002 +++ b/drivers/ide/pci/pdc202xx_new.h Wed Nov 27 14:36:27 2002 @@ -26,41 +26,6 @@ NULL }; -static inline u8 *pdcnew_pio_verbose (u32 drive_pci) -{ - if ((drive_pci & 0x000ff000) == 0x000ff000) return("NOTSET"); - if ((drive_pci & 0x00000401) == 0x00000401) return("PIO 4"); - if ((drive_pci & 0x00000602) == 0x00000602) return("PIO 3"); - if ((drive_pci & 0x00000803) == 0x00000803) return("PIO 2"); - if ((drive_pci & 0x00000C05) == 0x00000C05) return("PIO 1"); - if ((drive_pci & 0x00001309) == 0x00001309) return("PIO 0"); - return("PIO ?"); -} - -static inline u8 *pdcnew_dma_verbose (u32 drive_pci) -{ - if ((drive_pci & 0x00036000) == 0x00036000) return("MWDMA 2"); - if ((drive_pci & 0x00046000) == 0x00046000) return("MWDMA 1"); - if ((drive_pci & 0x00056000) == 0x00056000) return("MWDMA 0"); - if ((drive_pci & 0x00056000) == 0x00056000) return("SWDMA 2"); - if ((drive_pci & 0x00068000) == 0x00068000) return("SWDMA 1"); - if ((drive_pci & 0x000BC000) == 0x000BC000) return("SWDMA 0"); - return("PIO---"); -} - -static inline u8 *pdcnew_ultra_verbose (u32 drive_pci, u16 slow_cable) -{ - if ((drive_pci & 0x000ff000) == 0x000ff000) - return("NOTSET"); - if ((drive_pci & 0x00012000) == 0x00012000) - return((slow_cable) ? "UDMA 2" : "UDMA 4"); - if ((drive_pci & 0x00024000) == 0x00024000) - return((slow_cable) ? "UDMA 1" : "UDMA 3"); - if ((drive_pci & 0x00036000) == 0x00036000) - return("UDMA 0"); - return(pdcnew_dma_verbose(drive_pci)); -} - /* A Register */ #define SYNC_ERRDY_EN 0xC0 diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c --- a/drivers/ide/pci/pdc202xx_old.c Wed Nov 27 14:36:32 2002 +++ b/drivers/ide/pci/pdc202xx_old.c Wed Nov 27 14:36:32 2002 @@ -264,7 +264,6 @@ pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); } -#ifdef CONFIG_BLK_DEV_IDEDMA } else { if ((BP & 0xF0) && (CP & 0x0F)) { /* clear DMA modes of upper 842 bits of B Register */ @@ -276,7 +275,6 @@ pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F); pci_read_config_byte(dev, (drive_pci)|0x02, &CP); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ } pci_read_config_byte(dev, (drive_pci), &AP); @@ -284,7 +282,6 @@ pci_read_config_byte(dev, (drive_pci)|0x02, &CP); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_6: speed = XFER_UDMA_5; case XFER_UDMA_5: case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; @@ -298,7 +295,6 @@ case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: TA = 0x01; TB = 0x04; break; case XFER_PIO_3: TA = 0x02; TB = 0x06; break; case XFER_PIO_2: TA = 0x03; TB = 0x08; break; @@ -310,11 +306,9 @@ if (speed < XFER_SW_DMA_0) { pci_write_config_byte(dev, (drive_pci), AP|TA); pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); -#ifdef CONFIG_BLK_DEV_IDEDMA } else { pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); -#endif /* CONFIG_BLK_DEV_IDEDMA */ } #if PDC202XX_DECODE_REGISTER_INFO @@ -347,23 +341,16 @@ * 180, 120, 90, 90, 90, 60, 30 * 11, 5, 4, 3, 2, 1, 0 */ -static int config_chipset_for_pio (ide_drive_t *drive, u8 pio) +static void config_chipset_for_pio (ide_drive_t *drive, u8 pio) { u8 speed = 0; - pio = (pio == 5) ? 4 : pio; + if (pio == 5) pio = 4; speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); - return ((int) pdc202xx_tune_chipset(drive, speed)); + pdc202xx_tune_chipset(drive, speed); } -static void pdc202xx_tune_drive (ide_drive_t *drive, u8 pio) -{ - (void) config_chipset_for_pio(drive, pio); -} - -#ifdef CONFIG_BLK_DEV_IDEDMA - static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif) { u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10); @@ -618,8 +605,6 @@ return __ide_dma_timeout(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - static void pdc202xx_reset_host (ide_hwif_t *hwif) { #ifdef CONFIG_BLK_DEV_IDEDMA @@ -692,12 +677,8 @@ static int pdc202xx_tristate (ide_drive_t * drive, int state) { ide_hwif_t *hwif = HWIF(drive); -#ifdef CONFIG_BLK_DEV_IDEDMA // unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); unsigned long high_16 = hwif->dma_master; -#else /* !CONFIG_BLK_DEV_IDEDMA */ - unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); -#endif /* CONFIG_BLK_DEV_IDEDMA */ u8 sc1f = hwif->INB(high_16|0x001f); if (!hwif) @@ -761,7 +742,7 @@ static void __init init_hwif_pdc202xx (ide_hwif_t *hwif) { hwif->autodma = 0; - hwif->tuneproc = &pdc202xx_tune_drive; + hwif->tuneproc = &config_chipset_for_pio; hwif->quirkproc = &pdc202xx_quirkproc; if (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20265) @@ -783,8 +764,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate; hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq; hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout; @@ -800,7 +779,6 @@ if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ #if PDC202_DEBUG_CABLE printk("%s: %s-pin cable\n", hwif->name, hwif->udma_four ? "80" : "40"); diff -Nru a/drivers/ide/pci/pdcadma.c b/drivers/ide/pci/pdcadma.c --- a/drivers/ide/pci/pdcadma.c Wed Nov 27 14:36:31 2002 +++ b/drivers/ide/pci/pdcadma.c Wed Nov 27 14:36:31 2002 @@ -55,7 +55,6 @@ } #endif /* defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) */ -#ifdef CONFIG_BLK_DEV_IDEDMA /* * pdcadma_dma functions() initiates/aborts (U)DMA read/write * operations on a drive. @@ -81,8 +80,6 @@ int (*ide_dma_timeout)(ide_drive_t *drive); #endif - -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_pdcadma (struct pci_dev *dev, const char *name) { diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c --- a/drivers/ide/pci/piix.c Wed Nov 27 14:36:27 2002 +++ b/drivers/ide/pci/piix.c Wed Nov 27 14:36:27 2002 @@ -373,7 +373,7 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = hwif->channel ? 0x42 : 0x40; - u8 speed = ide_rate_filter(piix_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(piix_ratemask(drive), xferspeed); int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; int v_flag = 0x01 << drive->dn; @@ -392,7 +392,6 @@ pci_read_config_byte(dev, 0x55, ®55); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_4: case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; case XFER_UDMA_5: @@ -402,7 +401,6 @@ case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_SW_DMA_2: break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: case XFER_PIO_3: case XFER_PIO_2: @@ -444,8 +442,6 @@ return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA - /** * piix_config_drive_for_dma - configure drive for DMA * @drive: IDE drive to configure @@ -518,7 +514,6 @@ } return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /** * init_chipset_piix - set up the PIIX chipset @@ -570,10 +565,8 @@ static void __init init_hwif_piix (ide_hwif_t *hwif) { -#ifdef CONFIG_BLK_DEV_IDEDMA u8 reg54h = 0, reg55h = 0, ata66 = 0; u8 mask = hwif->channel ? 0xc0 : 0x30; -#endif /* !CONFIG_BLK_DEV_IDEDMA */ #ifndef CONFIG_IA64 if (!hwif->irq) @@ -599,7 +592,6 @@ hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; -#ifdef CONFIG_BLK_DEV_IDEDMA switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_INTEL_82371MX: hwif->mwdma_mask = 0x80; @@ -630,7 +622,6 @@ hwif->drives[1].autodma = hwif->autodma; hwif->drives[0].autodma = hwif->autodma; -#endif /* !CONFIG_BLK_DEV_IDEDMA */ } /** diff -Nru a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ide/pci/sc1200.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,593 @@ +/* + * linux/drivers/ide/sc1200.c Version 0.9 24-Oct-2002 + * + * Copyright (C) 2000-2002 Mark Lord + * May be copied or modified under the terms of the GNU General Public License + * + * Development of this chipset driver was funded + * by the nice folks at National Semiconductor. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide_modes.h" +#include "sc1200.h" + +#define DISPLAY_SC1200_TIMINGS + +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static int sc1200_get_info(char *, char **, off_t, int); +extern int (*sc1200_display_info)(char *, char **, off_t, int); /* ide-proc.c */ +extern char *ide_media_verbose(ide_drive_t *); +static u8 sc1200_proc = 0; + +#define SC1200_REV_A 0x00 +#define SC1200_REV_B1 0x01 +#define SC1200_REV_B3 0x02 +#define SC1200_REV_C1 0x03 +#define SC1200_REV_D1 0x04 + +#define PCI_CLK_33 0x00 +#define PCI_CLK_48 0x01 +#define PCI_CLK_66 0x02 +#define PCI_CLK_33A 0x03 + +static unsigned short sc1200_get_pci_clock (void) +{ + unsigned char chip_id, silicon_revision; + unsigned int pci_clock; + /* + * Check the silicon revision, as not all versions of the chip + * have the register with the fast PCI bus timings. + */ + chip_id = inb (0x903c); + silicon_revision = inb (0x903d); + + // Read the fast pci clock frequency + if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) { + pci_clock = PCI_CLK_33; + } else { + // check clock generator configuration (cfcc) + // the clock is in bits 8 and 9 of this word + + pci_clock = inw (0x901e); + pci_clock >>= 8; + pci_clock &= 0x03; + if (pci_clock == PCI_CLK_33A) + pci_clock = PCI_CLK_33; + } + return pci_clock; +} + +static struct pci_dev *bmide_dev; + +static int sc1200_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + u32 bibma = pci_resource_start(bmide_dev, 4); + u8 c0 = 0, c1 = 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + + c0 = inb_p((unsigned short)bibma + 0x02); + c1 = inb_p((unsigned short)bibma + 0x0a); + + p += sprintf(p, "\n National SCx200 Chipset.\n"); + p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); + p += sprintf(p, " %sabled %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s %s %s\n", + (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); + + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + + return p-buffer; +} +#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ + +extern char *ide_xfer_verbose (byte xfer_rate); + +/* + * Set a new transfer mode at the drive + */ +int sc1200_set_xfer_mode (ide_drive_t *drive, byte mode) +{ + printk("%s: sc1200_set_xfer_mode(%s)\n", drive->name, ide_xfer_verbose(mode)); + return ide_config_drive_speed(drive, mode); +} + +/* + * Here are the standard PIO mode 0-4 timings for each "format". + * Format-0 uses fast data reg timings, with slower command reg timings. + * Format-1 uses fast timings for all registers, but won't work with all drives. + */ +static const unsigned int sc1200_pio_timings[4][5] = + {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, // format0 33Mhz + {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}, // format1, 33Mhz + {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021}, // format1, 48Mhz + {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}}; // format1, 66Mhz + +/* + * After chip reset, the PIO timings are set to 0x00009172, which is not valid. + */ +//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) + +static int sc1200_autoselect_dma_mode (ide_drive_t *drive) +{ + int udma_ok = 1, mode = 0; + ide_hwif_t *hwif = HWIF(drive); + int unit = drive->select.b.unit; + ide_drive_t *mate = &hwif->drives[unit^1]; + struct hd_driveid *id = drive->id; + + /* + * The SC1200 specifies that two drives sharing a cable cannot + * mix UDMA/MDMA. It has to be one or the other, for the pair, + * though different timings can still be chosen for each drive. + * We could set the appropriate timing bits on the fly, + * but that might be a bit confusing. So, for now we statically + * handle this requirement by looking at our mate drive to see + * what it is capable of, before choosing a mode for our own drive. + */ + if (mate->present) { + struct hd_driveid *mateid = mate->id; + if (mateid && (mateid->capability & 1) && !hwif->ide_dma_bad_drive(mate)) { + if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) + udma_ok = 1; + else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) + udma_ok = 0; + else + udma_ok = 1; + } + } + /* + * Now see what the current drive is capable of, + * selecting UDMA only if the mate said it was ok. + */ + if (id && (id->capability & 1) && hwif->autodma && !hwif->ide_dma_bad_drive(drive)) { + if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { + if (id->dma_ultra & 4) + mode = XFER_UDMA_2; + else if (id->dma_ultra & 2) + mode = XFER_UDMA_1; + else if (id->dma_ultra & 1) + mode = XFER_UDMA_0; + } + if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { + if (id->dma_mword & 4) + mode = XFER_MW_DMA_2; + else if (id->dma_mword & 2) + mode = XFER_MW_DMA_1; + else if (id->dma_mword & 1) + mode = XFER_MW_DMA_0; + } + } + return mode; +} + +/* + * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes + * for both the chipset and drive. + */ +static int sc1200_config_dma2 (ide_drive_t *drive, int mode) +{ + ide_hwif_t *hwif = HWIF(drive); + int unit = drive->select.b.unit; + unsigned int reg, timings; + unsigned short pci_clock; + unsigned int basereg = hwif->channel ? 0x50 : 0x40; + + /* + * Default to DMA-off in case we run into trouble here. + */ + hwif->ide_dma_off_quietly(drive); /* turn off DMA while we fiddle */ + outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */ + + /* + * Tell the drive to switch to the new mode; abort on failure. + */ + if (!mode || sc1200_set_xfer_mode(drive, mode)) { + printk("SC1200: set xfer mode failure\n"); + return 1; /* failure */ + } + + pci_clock = sc1200_get_pci_clock(); + + /* + * Now tune the chipset to match the drive: + * + * Note that each DMA mode has several timings associated with it. + * The correct timing depends on the fast PCI clock freq. + */ + timings = 0; + switch (mode) { + case XFER_UDMA_0: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00921250; break; + case PCI_CLK_48: timings = 0x00932470; break; + case PCI_CLK_66: timings = 0x009436a1; break; + } + break; + case XFER_UDMA_1: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00911140; break; + case PCI_CLK_48: timings = 0x00922260; break; + case PCI_CLK_66: timings = 0x00933481; break; + } + break; + case XFER_UDMA_2: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00911030; break; + case PCI_CLK_48: timings = 0x00922140; break; + case PCI_CLK_66: timings = 0x00923261; break; + } + break; + case XFER_MW_DMA_0: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00077771; break; + case PCI_CLK_48: timings = 0x000bbbb2; break; + case PCI_CLK_66: timings = 0x000ffff3; break; + } + break; + case XFER_MW_DMA_1: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00012121; break; + case PCI_CLK_48: timings = 0x00024241; break; + case PCI_CLK_66: timings = 0x00035352; break; + } + break; + case XFER_MW_DMA_2: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00002020; break; + case PCI_CLK_48: timings = 0x00013131; break; + case PCI_CLK_66: timings = 0x00015151; break; + } + break; + } + + if (timings == 0) { + printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock); + return 1; /* failure */ + } + + if (unit == 0) { /* are we configuring drive0? */ + pci_read_config_dword(hwif->pci_dev, basereg+4, ®); + timings |= reg & 0x80000000; /* preserve PIO format bit */ + pci_write_config_dword(hwif->pci_dev, basereg+4, timings); + } else { + pci_write_config_dword(hwif->pci_dev, basereg+12, timings); + } + + outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */ + + /* + * Finally, turn DMA on in software, and exit. + */ + return hwif->ide_dma_on(drive); /* success */ +} + +/* + * sc1200_config_dma() handles selection/setting of DMA/UDMA modes + * for both the chipset and drive. + */ +static int sc1200_config_dma (ide_drive_t *drive) +{ + return sc1200_config_dma2(drive, sc1200_autoselect_dma_mode(drive)); +} + + +/* Replacement for the standard ide_dma_end action in + * dma_proc. + * + * returns 1 on error, 0 otherwise + */ +int sc1200_ide_dma_end (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte dma_stat; + + dma_stat = inb(dma_base+2); /* get DMA status */ + + if (!(dma_stat & 4)) + printk(" ide_dma_end dma_stat=%0x err=%x newerr=%x\n", + dma_stat, ((dma_stat&7)!=4), ((dma_stat&2)==2)); + + outb(dma_stat|0x1b, dma_base+2); /* clear the INTR & ERROR bits */ + outb(inb(dma_base)&~1, dma_base); /* !! DO THIS HERE !! stop DMA */ + + drive->waiting_for_dma = 0; + ide_destroy_dmatable(drive); /* purge DMA mappings */ + + return (dma_stat & 7) != 4; /* verify good DMA status */ +} + +/* + * sc1200_tuneproc() handles selection/setting of PIO modes + * for both the chipset and drive. + * + * All existing BIOSs for this chipset guarantee that all drives + * will have valid default PIO timings set up before we get here. + */ +static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned int format; + static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; + int mode = -1; + + switch (pio) { + case 200: mode = XFER_UDMA_0; break; + case 201: mode = XFER_UDMA_1; break; + case 202: mode = XFER_UDMA_2; break; + case 100: mode = XFER_MW_DMA_0; break; + case 101: mode = XFER_MW_DMA_1; break; + case 102: mode = XFER_MW_DMA_2; break; + } + if (mode != -1) { + printk("SC1200: %s: changing (U)DMA mode\n", drive->name); + (void)sc1200_config_dma2(drive, mode); + return; + } + + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio); + if (!sc1200_set_xfer_mode(drive, modes[pio])) { + unsigned int basereg = hwif->channel ? 0x50 : 0x40; + pci_read_config_dword (hwif->pci_dev, basereg+4, &format); + format = (format >> 31) & 1; + if (format) + format += sc1200_get_pci_clock(); + pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]); + } +} + +static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) +{ + int h; + + for (h = 0; h < MAX_HWIFS; h++) { + ide_hwif_t *hwif = &ide_hwifs[h]; + if (prev) { + if (hwif == prev) + prev = NULL; // found previous, now look for next match + } else { + if (hwif && hwif->pci_dev == dev) + return hwif; // found next match + } + } + return NULL; // not found +} + +typedef struct sc1200_saved_state_s { + __u32 regs[4]; +} sc1200_saved_state_t; + +static int sc1200_save_state (struct pci_dev *dev, u32 state) +{ + ide_hwif_t *hwif = NULL; + +printk("SC1200: save_state(%u)\n", state); + if (state != 0) + return 0; // we only save state when going from full power to less + // + // Loop over all interfaces that are part of this PCI device: + // + while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { + sc1200_saved_state_t *ss; + unsigned int basereg, r; + // + // allocate a permanent save area, if not already allocated + // + ss = (sc1200_saved_state_t *)hwif->config_data; + if (ss == NULL) { + ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL); + if (ss == NULL) + return -ENOMEM; + (sc1200_saved_state_t *)hwif->config_data = ss; + } + ss = (sc1200_saved_state_t *)hwif->config_data; + // + // Save timing registers: this may be unnecessary if BIOS also does it + // + basereg = hwif->channel ? 0x50 : 0x40; + for (r = 0; r < 4; ++r) { + pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]); + } + } + return 0; +} + +static int sc1200_suspend (struct pci_dev *dev, u32 state) +{ + ide_hwif_t *hwif = NULL; + + printk("SC1200: suspend(%u)\n", state); + /* You don't need to iterate over disks -- sysfs should have done that for you already */ + + pci_disable_device(dev); + pci_set_power_state(dev,state); + dev->current_state = state; + return 0; +} + +static int sc1200_resume (struct pci_dev *dev) +{ + ide_hwif_t *hwif = NULL; + +printk("SC1200: resume\n"); + pci_set_power_state(dev,0); // bring chip back from sleep state + dev->current_state = 0; + pci_enable_device(dev); + // + // loop over all interfaces that are part of this pci device: + // + while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { + unsigned int basereg, r, d, format; + sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data; +printk("%s: SC1200: resume\n", hwif->name); + + // + // Restore timing registers: this may be unnecessary if BIOS also does it + // + basereg = hwif->channel ? 0x50 : 0x40; + if (ss != NULL) { + for (r = 0; r < 4; ++r) { + pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]); + } + } + // + // Re-program drive PIO modes + // + pci_read_config_dword(hwif->pci_dev, basereg+4, &format); + format = (format >> 31) & 1; + if (format) + format += sc1200_get_pci_clock(); + for (d = 0; d < 2; ++d) { + ide_drive_t *drive = &(hwif->drives[d]); + if (drive->present) { + unsigned int pio, timings; + pci_read_config_dword(hwif->pci_dev, basereg+(drive->select.b.unit << 3), &timings); + for (pio = 0; pio <= 4; ++pio) { + if (sc1200_pio_timings[format][pio] == timings) + break; + } + if (pio > 4) + pio = 255; /* autotune */ + (void)sc1200_tuneproc(drive, pio); + } + } + // + // Re-program drive DMA modes + // + for (d = 0; d < MAX_DRIVES; ++d) { + ide_drive_t *drive = &(hwif->drives[d]); + if (drive->present && !hwif->ide_dma_bad_drive(drive)) { + int was_using_dma = drive->using_dma; + hwif->ide_dma_off_quietly(drive); + sc1200_config_dma(drive); + if (!was_using_dma && drive->using_dma) { + hwif->ide_dma_off_quietly(drive); + } + } + } + } + return 0; +} + +/* + * Initialize the sc1200 bridge for reliable IDE DMA operation. + */ +static unsigned int __init init_chipset_sc1200 (struct pci_dev *dev, const char *name) +{ +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) + if (!bmide_dev) { + sc1200_proc = 1; + bmide_dev = dev; + ide_pci_register_host_proc(&sc1200_procs[0]); + } +#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + +/* + * This gets invoked by the IDE driver once for each channel, + * and performs channel-specific pre-initialization before drive probing. + */ +static void __init init_hwif_sc1200 (ide_hwif_t *hwif) +{ + if (hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; + hwif->autodma = 0; + if (hwif->dma_base) { + hwif->ide_dma_check = &sc1200_config_dma; + hwif->ide_dma_end = &sc1200_ide_dma_end; + if (!noautodma) + hwif->autodma = 1; + hwif->tuneproc = &sc1200_tuneproc; + } + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x07; + hwif->mwdma_mask = 0x07; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_sc1200 (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + + +static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &sc1200_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id sc1200_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "SC1200 IDE", + .id_table = sc1200_pci_tbl, + .probe = sc1200_init_one, + .save_state = sc1200_save_state, + .suspend = sc1200_suspend, + .resume = sc1200_resume, +}; + +static int sc1200_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void sc1200_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(sc1200_ide_init); +module_exit(sc1200_ide_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; diff -Nru a/drivers/ide/pci/sc1200.h b/drivers/ide/pci/sc1200.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ide/pci/sc1200.h Wed Nov 27 14:36:32 2002 @@ -0,0 +1,54 @@ +#ifndef SC1200_H +#define SC1200_H + +#include +#include +#include + +#define DISPLAY_SC1200_TIMINGS + +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 sc1200_proc; + +static int sc1200_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t sc1200_procs[] __initdata = { + { + name: "sc1200", + set: 1, + get_info: sc1200_get_info, + parent: NULL, + }, +}; +#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ + +static unsigned int init_chipset_sc1200(struct pci_dev *, const char *); +static void init_hwif_sc1200(ide_hwif_t *); +static void init_dma_sc1200(ide_hwif_t *, unsigned long); + +static ide_pci_device_t sc1200_chipsets[] __devinitdata = { + { /* 0 */ + vendor: PCI_VENDOR_ID_NS, + device: PCI_DEVICE_ID_NS_SCx200_IDE, + name: "SC1200", + init_chipset: init_chipset_sc1200, + init_iops: NULL, + init_hwif: init_hwif_sc1200, + init_dma: init_dma_sc1200, + channels: 2, + autodma: AUTODMA, + enablebits: {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + bootable: ON_BOARD, + extra: 0, + },{ + vendor: 0, + device: 0, + channels: 0, + bootable: EOL, + } +}; + +#endif /* SC1200_H */ diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c --- a/drivers/ide/pci/serverworks.c Wed Nov 27 14:36:27 2002 +++ b/drivers/ide/pci/serverworks.c Wed Nov 27 14:36:27 2002 @@ -251,7 +251,7 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); u8 pio = ide_get_best_pio_mode(drive, 255, 5, NULL); u8 unit = (drive->select.b.unit & 0x01); u8 csb5 = svwks_csb_check(dev); @@ -259,6 +259,13 @@ u8 dma_timing = 0, pio_timing = 0; u16 csb5_pio = 0; + /* If we are about to put a disk into UDMA mode we screwed up. + Our code assumes we never _ever_ do this on an OSB4 */ + + if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 && + drive->media == ide_disk && speed >= XFER_UDMA_0) + BUG(); + pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing); pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing); pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); @@ -331,7 +338,6 @@ csb5_pio |= ((speed - XFER_PIO_0) << (4*drive->dn)); break; -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_MW_DMA_0: @@ -351,7 +357,6 @@ dma_timing |= dma_modes[2]; ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit)); ultra_enable |= (0x01 << drive->dn); -#endif default: break; } @@ -360,11 +365,9 @@ if (csb5) pci_write_config_word(dev, 0x4A, csb5_pio); -#ifdef CONFIG_BLK_DEV_IDEDMA pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing); pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing); pci_write_config_byte(dev, 0x54, ultra_enable); -#endif /* CONFIG_BLK_DEV_IDEDMA */ return (ide_config_drive_speed(drive, speed)); } @@ -412,7 +415,6 @@ (void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, svwks_ratemask(drive)); @@ -470,6 +472,12 @@ static int svwks_ide_dma_end (ide_drive_t *drive) { + /* + * We never place the OSB4 into a UDMA mode with a disk + * medium, that means the UDMA "all my data is 4 byte shifted" + * problem cannot occur. + */ +#if 0 ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = hwif->INB(hwif->dma_status); @@ -483,9 +491,9 @@ while(1) cpu_relax(); } +#endif return __ide_dma_end(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_svwks (struct pci_dev *dev, const char *name) { @@ -703,7 +711,6 @@ return; } -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &svwks_config_drive_xfer_rate; if (hwif->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) hwif->ide_dma_end = &svwks_ide_dma_end; @@ -719,7 +726,6 @@ hwif->drives[1].autotune = (!(dma_stat & 0x40)); // hwif->drives[0].autodma = hwif->autodma; // hwif->drives[1].autodma = hwif->autodma; -#endif /* !CONFIG_BLK_DEV_IDEDMA */ } /* diff -Nru a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c --- a/drivers/ide/pci/siimage.c Wed Nov 27 14:36:29 2002 +++ b/drivers/ide/pci/siimage.c Wed Nov 27 14:36:29 2002 @@ -205,7 +205,6 @@ siimage_tuneproc(drive, (speed - XFER_PIO_0)); mode |= ((unit) ? 0x10 : 0x01); break; -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_MW_DMA_0: @@ -226,7 +225,6 @@ mode |= ((unit) ? 0x30 : 0x03); config_siimage_chipset_for_pio(drive, 0); break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ default: return 1; } @@ -246,7 +244,6 @@ return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, siimage_ratemask(drive)); @@ -256,7 +253,7 @@ if ((!(speed))) return 0; - if (HWIF(drive)->speedproc(drive, speed)) + if (ide_set_xfer_rate(drive, speed)) return 0; if (!drive->init_speed) @@ -392,7 +389,6 @@ #endif return temp; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static int siimage_busproc (ide_drive_t * drive, int state) { @@ -811,7 +807,6 @@ if (hwif->pci_dev->device != PCI_DEVICE_ID_SII_3112) hwif->atapi_dma = 1; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &siimage_config_drive_for_dma; if (!(hwif->udma_four)) hwif->udma_four = ata66_siimage(hwif); @@ -827,7 +822,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_siimage (ide_hwif_t *hwif, unsigned long dmabase) diff -Nru a/drivers/ide/pci/siimage.h b/drivers/ide/pci/siimage.h --- a/drivers/ide/pci/siimage.h Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/pci/siimage.h Wed Nov 27 14:36:30 2002 @@ -62,14 +62,14 @@ // while (count--) { *(u32 *)addr = readl(port); addr += 4; } } -inline void sii_outb (u8 addr, u32 port) +inline void sii_outb (u8 value, u32 port) { - writeb(addr, port); + writeb(value, port); } -inline void sii_outw (u16 addr, u32 port) +inline void sii_outw (u16 value, u32 port) { - writew(addr, port); + writew(value, port); } inline void sii_outsw (u32 port, void *addr, u32 count) @@ -77,9 +77,9 @@ while (count--) { writew(*(u16 *)addr, port); addr += 2; } } -inline void sii_outl (u32 addr, u32 port) +inline void sii_outl (u32 value, u32 port) { - writel(addr, port); + writel(value, port); } inline void sii_outsl (u32 port, void *addr, u32 count) diff -Nru a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c --- a/drivers/ide/pci/sis5513.c Wed Nov 27 14:36:30 2002 +++ b/drivers/ide/pci/sis5513.c Wed Nov 27 14:36:30 2002 @@ -703,7 +703,6 @@ /* Config chip for mode */ switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_6: case XFER_UDMA_5: case XFER_UDMA_4: @@ -745,7 +744,6 @@ case XFER_SW_DMA_1: case XFER_SW_DMA_0: break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4)); case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3)); case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2)); @@ -764,7 +762,6 @@ (void) config_chipset_for_pio(drive, pio); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) */ @@ -835,8 +832,6 @@ return sis5513_config_drive_xfer_rate(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - /* Chip detection and general config */ static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name) { @@ -999,7 +994,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!host_dev) return; @@ -1013,7 +1007,6 @@ } hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif return; } diff -Nru a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c --- a/drivers/ide/pci/trm290.c Wed Nov 27 14:36:28 2002 +++ b/drivers/ide/pci/trm290.c Wed Nov 27 14:36:28 2002 @@ -176,7 +176,6 @@ trm290_prepare_drive(drive, drive->using_dma); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int trm290_ide_dma_write (ide_drive_t *drive /*, struct request *rq */) { ide_hwif_t *hwif = HWIF(drive); @@ -297,7 +296,6 @@ status = hwif->INW(hwif->dma_status); return (status == 0x00ff); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * Invoked from ide-dma.c at boot time. @@ -344,13 +342,11 @@ ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_write = &trm290_ide_dma_write; hwif->ide_dma_read = &trm290_ide_dma_read; hwif->ide_dma_begin = &trm290_ide_dma_begin; hwif->ide_dma_end = &trm290_ide_dma_end; hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; -#endif /* CONFIG_BLK_DEV_IDEDMA */ hwif->selectproc = &trm290_selectproc; hwif->autodma = 0; /* play it safe for now */ diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c --- a/drivers/ide/pci/via82cxxx.c Wed Nov 27 14:36:27 2002 +++ b/drivers/ide/pci/via82cxxx.c Wed Nov 27 14:36:27 2002 @@ -383,8 +383,6 @@ via_set_drive(drive, XFER_PIO_0 + MIN(pio, 5)); } -#ifdef CONFIG_BLK_DEV_IDEDMA - /** * via82cxxx_ide_dma_check - set up for DMA if possible * @drive: IDE drive to set up @@ -411,8 +409,6 @@ return HWIF(drive)->ide_dma_off_quietly(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - /** * init_chipset_via82cxxx - initialization handler * @dev: PCI device @@ -608,7 +604,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!(hwif->udma_four)) hwif->udma_four = ((via_enabled & via_80w) >> hwif->channel) & 1; hwif->ide_dma_check = &via82cxxx_ide_dma_check; @@ -616,7 +611,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } /** diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c --- a/drivers/ide/setup-pci.c Wed Nov 27 14:36:29 2002 +++ b/drivers/ide/setup-pci.c Wed Nov 27 14:36:29 2002 @@ -10,6 +10,7 @@ * Split the set up function into multiple functions * Use pci_set_master * Fix misreporting of I/O v MMIO problems + * Initial fixups for simplex devices */ /* @@ -42,6 +43,8 @@ * based on io_base port if possible. Return the matching hwif, * or a new hwif. If we find an error (clashing, out of devices, etc) * return NULL + * + * FIXME: we need to handle mmio matches here too */ static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name) @@ -144,34 +147,9 @@ return -EOPNOTSUPP; } } - -#if 0 - /* - * At this point we have enabled the device, but may previously - * have done a BAR4 enable alone. We should be prepared to assign - * resources here. - */ - - /* - * Setup base registers for IDE command/control - * spaces for each interface: - */ - for (reg = 0; reg < 4; reg++) { - struct resource *res = dev->resource + reg; - if ((res->flags & IORESOURCE_IO) == 0) - continue; - if (!res->start) { - if(pci_assign_resource(dev, reg)) { - printk(KERN_ERR "%s: Missing I/O address #%d\n", name, reg); - return -ENXIO; - } - } - } -#endif return 0; } -#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA_FORCED /* * Long lost data from 2.0.34 that is now in 2.0.39 @@ -192,9 +170,6 @@ * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: * If need be we set up the DMA base. Where a device has a partner that * is already in DMA mode we check and enforce IDE simplex rules. - * - * FIXME: currently we are sometimes enforicng simplex when it is not - * needed. We fail the safe way but why is it occurring ?? */ static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif) @@ -274,7 +249,14 @@ simplex_stat = hwif->INB(dma_base + 2); if (simplex_stat & 0x80) { /* simplex device? */ - +#if 0 +/* + * At this point we haven't probed the drives so we can't make the + * appropriate decision. Really we should defer this problem + * until we tune the drive then try to grab DMA ownership if we want + * to be the DMA end. This has to be become dynamic to handle hot + * plug. + */ /* Don't enable DMA on a simplex channel with no drives */ if (!hwif->drives[0].present && !hwif->drives[1].present) { @@ -283,7 +265,9 @@ dma_base = 0; } /* If our other channel has DMA then we cannot */ - else if(hwif->mate && hwif->mate->dma_base) + else +#endif + if(hwif->mate && hwif->mate->dma_base) { printk(KERN_INFO "%s: simplex device: " "DMA disabled\n", @@ -295,9 +279,8 @@ } return dma_base; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -static void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d) +void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d) { if ((d->vendor != dev->vendor) && (d->device != dev->device)) { printk(KERN_INFO "%s: unknown IDE controller at PCI slot " @@ -309,6 +292,9 @@ } } +EXPORT_SYMBOL_GPL(ide_setup_pci_noise); + + /** * ide_pci_enable - do PCI enables * @dev: PCI device @@ -414,8 +400,7 @@ ".\n", d->name); return -EINVAL; } - - + /** * ide_hwif_configure - configure an IDE interface * @dev: PCI device holding interface @@ -434,16 +419,19 @@ unsigned long ctl = 0, base = 0; ide_hwif_t *hwif; - /* Possibly we should fail if these checks report true */ - ide_pci_check_iomem(dev, d, 2*port); - ide_pci_check_iomem(dev, d, 2*port+1); + if(!d->isa_ports) + { + /* Possibly we should fail if these checks report true */ + ide_pci_check_iomem(dev, d, 2*port); + ide_pci_check_iomem(dev, d, 2*port+1); - ctl = pci_resource_start(dev, 2*port+1); - base = pci_resource_start(dev, 2*port); - if ((ctl && !base) || (base && !ctl)) { - printk(KERN_ERR "%s: inconsistent baseregs (BIOS) " - "for port %d, skipping\n", d->name, port); - return NULL; + ctl = pci_resource_start(dev, 2*port+1); + base = pci_resource_start(dev, 2*port); + if ((ctl && !base) || (base && !ctl)) { + printk(KERN_ERR "%s: inconsistent baseregs (BIOS) " + "for port %d, skipping\n", d->name, port); + return NULL; + } } if (!ctl) { @@ -500,8 +488,9 @@ * Set up BM-DMA capability * (PnP BIOS should have done this) */ - if ((d->device != PCI_DEVICE_ID_CYRIX_5530_IDE) - && (d->vendor != PCI_VENDOR_ID_CYRIX)) { + if (!((d->device == PCI_DEVICE_ID_CYRIX_5530_IDE && d->vendor == PCI_VENDOR_ID_CYRIX) + ||(d->device == PCI_DEVICE_ID_NS_SCx200_IDE && d->vendor == PCI_VENDOR_ID_NS))) + { /* * default DMA off if we had to * configure it here @@ -575,75 +564,33 @@ return ret; } -/* - * ide_setup_pci_device() looks at the primary/secondary interfaces - * on a PCI IDE device and, if they are enabled, prepares the IDE driver - * for use with them. This generic code works for most PCI chipsets. - * - * One thing that is not standardized is the location of the - * primary/secondary interface "enable/disable" bits. For chipsets that - * we "know" about, this information is in the ide_pci_device_t struct; - * for all other chipsets, we just assume both interfaces are enabled. +/** + * ide_pci_setup_ports - configure ports/devices on PCI IDE + * @dev: PCI device + * @d: IDE pci device info + * @autodma: Should we enable DMA + * @pciirq: IRQ line + * @index: ata index to update + * + * Scan the interfaces attached to this device and do any + * neccessary per port setup. Attach the devices and ask the + * generic DMA layer to do its work for us. + * + * Normally called automaticall from do_ide_pci_setup_device, + * but is also used directly as a helper function by some controllers + * where the chipset setup is not the default PCI IDE one. */ -static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d, u8 noisy) + +void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int autodma, int pciirq, ata_index_t *index) { - u32 port, at_least_one_hwif_enabled = 0, autodma = 0; - int pciirq = 0; - int tried_config = 0; - int drive0_tune, drive1_tune; - ata_index_t index; - u8 tmp = 0; + int port; + int at_least_one_hwif_enabled = 0; ide_hwif_t *hwif, *mate = NULL; static int secondpdc = 0; + int drive0_tune, drive1_tune; + u8 tmp; - index.all = 0xf0f0; - - if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0) - return index; - - /* - * Can we trust the reported IRQ? - */ - pciirq = dev->irq; - - if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { - if (noisy) - printk(KERN_INFO "%s: not 100%% native mode: " - "will probe irqs later\n", d->name); - /* - * This allows offboard ide-pci cards the enable a BIOS, - * verify interrupt settings of split-mirror pci-config - * space, place chipset into init-mode, and/or preserve - * an interrupt if the card is not native ide support. - */ - pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : 0; - } else if (tried_config) { - if (noisy) - printk(KERN_INFO "%s: will probe irqs later\n", d->name); - pciirq = 0; - } else if (!pciirq) { - if (noisy) - printk(KERN_WARNING "%s: bad irq (%d): will probe later\n", - d->name, pciirq); - pciirq = 0; - } else { - if (d->init_chipset) - { - if(d->init_chipset(dev, d->name) < 0) - return index; - } - if (noisy) -#ifdef __sparc__ - printk(KERN_INFO "%s: 100%% native mode on irq %s\n", - d->name, __irq_itoa(pciirq)); -#else - printk(KERN_INFO "%s: 100%% native mode on irq %d\n", - d->name, pciirq); -#endif - } - - if(pciirq < 0) /* Error not an IRQ */ - return index; + index->all = 0xf0f0; /* * Set up the IDE ports @@ -671,7 +618,7 @@ controller_ok: if (d->channels <= port) - return index; + break; if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL) continue; @@ -680,25 +627,27 @@ hwif->gendev.parent = &dev->dev; if (hwif->channel) { - index.b.high = hwif->index; + index->b.high = hwif->index; } else { - index.b.low = hwif->index; + index->b.low = hwif->index; } if (d->init_iops) d->init_iops(hwif); -#ifdef CONFIG_BLK_DEV_IDEDMA if (d->autodma == NODMA) goto bypass_legacy_dma; if (d->autodma == NOAUTODMA) autodma = 0; if (autodma) hwif->autodma = 1; - ide_hwif_setup_dma(dev, d, hwif); + + if(d->init_setup_dma) + d->init_setup_dma(dev, d, hwif); + else + ide_hwif_setup_dma(dev, d, hwif); bypass_legacy_dma: -#endif /* CONFIG_BLK_DEV_IDEDMA */ drive0_tune = hwif->drives[0].autotune; drive1_tune = hwif->drives[1].autotune; @@ -708,7 +657,13 @@ * for each enabled hwif */ d->init_hwif(hwif); - + + /* + * This is in the wrong place. The driver may + * do set up based on the autotune value and this + * will then trash it. Torben please move it and + * propogate the fixes into the drivers + */ if (drive0_tune == IDE_TUNE_BIOS) /* biostimings */ hwif->drives[0].autotune = IDE_TUNE_BIOS; if (drive1_tune == IDE_TUNE_BIOS) @@ -719,6 +674,76 @@ } if (!at_least_one_hwif_enabled) printk(KERN_INFO "%s: neither IDE port enabled (BIOS)\n", d->name); +} + +EXPORT_SYMBOL_GPL(ide_pci_setup_ports); + +/* + * ide_setup_pci_device() looks at the primary/secondary interfaces + * on a PCI IDE device and, if they are enabled, prepares the IDE driver + * for use with them. This generic code works for most PCI chipsets. + * + * One thing that is not standardized is the location of the + * primary/secondary interface "enable/disable" bits. For chipsets that + * we "know" about, this information is in the ide_pci_device_t struct; + * for all other chipsets, we just assume both interfaces are enabled. + */ +static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d, u8 noisy) +{ + int autodma = 0; + int pciirq = 0; + int tried_config = 0; + ata_index_t index = { .b = { .low = 0xff, .high = 0xff } }; + + if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0) + return index; + + /* + * Can we trust the reported IRQ? + */ + pciirq = dev->irq; + + if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { + if (noisy) + printk(KERN_INFO "%s: not 100%% native mode: " + "will probe irqs later\n", d->name); + /* + * This allows offboard ide-pci cards the enable a BIOS, + * verify interrupt settings of split-mirror pci-config + * space, place chipset into init-mode, and/or preserve + * an interrupt if the card is not native ide support. + */ + pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : 0; + } else if (tried_config) { + if (noisy) + printk(KERN_INFO "%s: will probe irqs later\n", d->name); + pciirq = 0; + } else if (!pciirq) { + if (noisy) + printk(KERN_WARNING "%s: bad irq (%d): will probe later\n", + d->name, pciirq); + pciirq = 0; + } else { + if (d->init_chipset) + { + if(d->init_chipset(dev, d->name) < 0) + return index; + } + if (noisy) +#ifdef __sparc__ + printk(KERN_INFO "%s: 100%% native mode on irq %s\n", + d->name, __irq_itoa(pciirq)); +#else + printk(KERN_INFO "%s: 100%% native mode on irq %d\n", + d->name, pciirq); +#endif + } + + if(pciirq < 0) /* Error not an IRQ */ + return index; + + ide_pci_setup_ports(dev, d, autodma, pciirq, &index); + return index; } diff -Nru a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c --- a/drivers/input/gameport/fm801-gp.c Wed Nov 27 14:36:30 2002 +++ b/drivers/input/gameport/fm801-gp.c Wed Nov 27 14:36:30 2002 @@ -116,7 +116,7 @@ gameport_register_port(&gp->gameport); printk(KERN_INFO "gameport: %s at pci%s speed %d kHz\n", - pci->name, pci->slot_name, gp->gameport.speed); + pci->dev.name, pci->slot_name, gp->gameport.speed); return 0; } diff -Nru a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c --- a/drivers/input/gameport/ns558.c Wed Nov 27 14:36:31 2002 +++ b/drivers/input/gameport/ns558.c Wed Nov 27 14:36:31 2002 @@ -236,7 +236,7 @@ port->gameport.id.version = 0x100; sprintf(port->phys, "isapnp%d.%d/gameport0", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - sprintf(port->name, "%s", dev->name[0] ? dev->name : "NS558 PnP Gameport"); + sprintf(port->name, "%s", dev->dev.name[0] ? dev->dev.name : "NS558 PnP Gameport"); gameport_register_port(&port->gameport); diff -Nru a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c --- a/drivers/input/gameport/vortex.c Wed Nov 27 14:36:31 2002 +++ b/drivers/input/gameport/vortex.c Wed Nov 27 14:36:31 2002 @@ -127,7 +127,7 @@ vortex->gameport.cooked_read = vortex_cooked_read; vortex->gameport.open = vortex_open; - vortex->gameport.name = dev->name; + vortex->gameport.name = dev->dev.name; vortex->gameport.phys = vortex->phys; vortex->gameport.id.bustype = BUS_PCI; vortex->gameport.id.vendor = dev->vendor; @@ -146,7 +146,7 @@ gameport_register_port(&vortex->gameport); printk(KERN_INFO "gameport: %s at pci%s speed %d kHz\n", - dev->name, dev->slot_name, vortex->gameport.speed); + dev->dev.name, dev->slot_name, vortex->gameport.speed); return 0; } diff -Nru a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c --- a/drivers/isdn/act2000/module.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/act2000/module.c Wed Nov 27 14:36:31 2002 @@ -398,12 +398,6 @@ break; chan->l2prot = (c->arg >> 8); return 0; - case ISDN_CMD_GETL2: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - return chan->l2prot; case ISDN_CMD_SETL3: if (!card->flags & ACT2000_FLAGS_RUNNING) return -ENODEV; @@ -415,33 +409,6 @@ break; chan->l3prot = (c->arg >> 8); return 0; - case ISDN_CMD_GETL3: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - return chan->l3prot; - case ISDN_CMD_GETEAZ: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - printk(KERN_DEBUG "act2000 CMD_GETEAZ not implemented\n"); - return 0; - case ISDN_CMD_SETSIL: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - printk(KERN_DEBUG "act2000 CMD_SETSIL not implemented\n"); - return 0; - case ISDN_CMD_GETSIL: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - printk(KERN_DEBUG "act2000 CMD_GETSIL not implemented\n"); - return 0; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - return 0; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - return 0; } return -EINVAL; @@ -620,6 +587,7 @@ INIT_WORK(&card->rcv_tq, (void *) (void *) actcapi_dispatch, card); INIT_WORK(&card->poll_tq, (void *) (void *) act2000_receive, card); init_timer(&card->ptimer); + SET_MODULE_OWNER(&card->interface); card->interface.channels = ACT2000_BCH; card->interface.maxbufsize = 4000; card->interface.command = if_command; diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c --- a/drivers/isdn/capi/capi.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/capi/capi.c Wed Nov 27 14:36:32 2002 @@ -1289,9 +1289,7 @@ memset(drv, 0, sizeof(struct tty_driver)); drv->magic = TTY_DRIVER_MAGIC; -#if (LINUX_VERSION_CODE > 0x20100) drv->driver_name = "capi_nc"; -#endif drv->name = "capi/%d"; drv->major = capi_ttymajor; drv->minor_start = 0; @@ -1323,15 +1321,11 @@ drv->stop = capinc_tty_stop; drv->start = capinc_tty_start; drv->hangup = capinc_tty_hangup; -#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ drv->break_ctl = capinc_tty_break_ctl; -#endif drv->flush_buffer = capinc_tty_flush_buffer; drv->set_ldisc = capinc_tty_set_ldisc; -#if (LINUX_VERSION_CODE >= 131343) drv->send_xchar = capinc_tty_send_xchar; drv->read_proc = capinc_tty_read_proc; -#endif if (tty_register_driver(drv)) { printk(KERN_ERR "Couldn't register capi_nc driver\n"); return -1; diff -Nru a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c --- a/drivers/isdn/capi/capidrv.c Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/capi/capidrv.c Wed Nov 27 14:36:30 2002 @@ -1787,45 +1787,6 @@ bchan->msn[0] = 0; return 0; - case ISDN_CMD_LOCK: - if (debugmode > 1) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg); - MOD_INC_USE_COUNT; - break; - - case ISDN_CMD_UNLOCK: - if (debugmode > 1) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n", - card->contrnr, c->arg); - MOD_DEC_USE_COUNT; - break; - -/* never called */ - case ISDN_CMD_GETL2: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n", - card->contrnr); - return -ENODEV; - case ISDN_CMD_GETL3: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n", - card->contrnr); - return -ENODEV; - case ISDN_CMD_GETEAZ: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n", - card->contrnr); - return -ENODEV; - case ISDN_CMD_SETSIL: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n", - card->contrnr); - return -ENODEV; - case ISDN_CMD_GETSIL: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n", - card->contrnr); - return -ENODEV; default: printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n", card->contrnr, c->command); diff -Nru a/drivers/isdn/eicon/divas.h b/drivers/isdn/eicon/divas.h --- a/drivers/isdn/eicon/divas.h Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/eicon/divas.h Wed Nov 27 14:36:31 2002 @@ -103,8 +103,7 @@ int card_id; /* unique id assigned to this card */ int card_type; /* use DIA_CARD_TYPE_xxx above */ int bus_type; /* use DIA_BUS_TYPE_xxx above */ - int bus_num; /* bus number (instance number of bus type) */ - int func_num; /* adapter function number (PCI register) */ + struct pci_dev *pdev; int slot; /* slot number in bus */ unsigned char irq; /* IRQ number */ int reset_base; /* Reset register for I/O mapped cards */ diff -Nru a/drivers/isdn/eicon/eicon_mod.c b/drivers/isdn/eicon/eicon_mod.c --- a/drivers/isdn/eicon/eicon_mod.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/eicon/eicon_mod.c Wed Nov 27 14:36:27 2002 @@ -529,12 +529,6 @@ break; chan->l2prot = (c->arg >> 8); return 0; - case ISDN_CMD_GETL2: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - return chan->l2prot; case ISDN_CMD_SETL3: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; @@ -548,33 +542,6 @@ } #endif return 0; - case ISDN_CMD_GETL3: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - return chan->l3prot; - case ISDN_CMD_GETEAZ: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n"); - return 0; - case ISDN_CMD_SETSIL: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n"); - return 0; - case ISDN_CMD_GETSIL: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n"); - return 0; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - return 0; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - return 0; #ifdef CONFIG_ISDN_TTY_FAX case ISDN_CMD_FAXCMD: if (!card->flags & EICON_FLAGS_RUNNING) @@ -877,6 +844,7 @@ tasklet_init(&card->snd_tq, eicon_transmit, (unsigned long)card); tasklet_init(&card->rcv_tq, eicon_rcv_dispatch, (unsigned long)card); tasklet_init(&card->ack_tq, eicon_ack_dispatch, (unsigned long)card); + SET_MODULE_OWNER(&card->interface); card->interface.maxbufsize = 4000; card->interface.command = if_command; card->interface.writebuf_skb = if_sendbuf; diff -Nru a/drivers/isdn/eicon/lincfg.c b/drivers/isdn/eicon/lincfg.c --- a/drivers/isdn/eicon/lincfg.c Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/eicon/lincfg.c Wed Nov 27 14:36:30 2002 @@ -42,310 +42,182 @@ int DivasCardsDiscover(void) { + struct pci_dev *pdev = NULL; word wNumCards = 0, wDeviceIndex = 0; - byte byBus, byFunc; - word wPCIConsultation, PCItmp; + word PCItmp; dword j, i; unsigned int PCIserial; dia_card_t Card; byte *b; - while (wDeviceIndex < 10) - { - wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_MAESTRAQ, - wDeviceIndex, - &byBus, &byFunc); - - if (wPCIConsultation == PCIBIOS_SUCCESSFUL) - { - - dword dwRAM, dwDivasIOBase, dwCFG, dwCTL; - byte byIRQ; - - printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n"); - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2,(unsigned int *) &dwRAM); - dwRAM &= 0xFFC00000; - - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1,(unsigned int *) &dwDivasIOBase); - dwDivasIOBase &= 0xFFFFFF00; - - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0,(unsigned int *) &dwCFG); - dwCFG &= 0xFFFFFF00; - - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_3,(unsigned int *) &dwCTL); - dwCTL &= 0xFFFFE000; - - - pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ); - /* Retrieve the serial number */ - - pcibios_write_config_word(byBus,byFunc,0x4E,0x00FC); - - for (j=0, PCItmp=0; j<10000 && !PCItmp; j++) - { - pcibios_read_config_word(byBus,byFunc,0x4E, &PCItmp); - PCItmp &= 0x8000; // extract done flag - } - - pcibios_read_config_dword(byBus,byFunc,0x50, &PCIserial); - + while ((pdev = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_MAESTRAQ, + pdev))) { + dword dwRAM, dwDivasIOBase, dwCFG, dwCTL; + + printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n"); + + dwRAM = pci_resource_start(pdev, 2); + dwDivasIOBase = pci_resource_start(pdev, 1); + dwCFG = pci_resource_start(pdev, 0); + dwCTL = pci_resource_start(pdev, 3); + + /* Retrieve the serial number */ + pci_write_config_word(pdev, 0x4E, 0x00FC); + for (j=0, PCItmp=0; j<10000 && !PCItmp; j++) { + pci_read_config_word(pdev, 0x4E, &PCItmp); + PCItmp &= 0x8000; // extract done flag + } + pci_read_config_dword(pdev, 0x50, &PCIserial); - Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000); - Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000); - Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100); - Card.io_base=dwDivasIOBase; - - Card.irq = byIRQ; - - Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q; - Card.bus_type = DIA_BUS_TYPE_PCI; - - FPGA_Done = 0; - - /* Create four virtual card structures as we want to treat - the 4Bri card as 4 Bri cards*/ - for(i=0;i<4;i++) - { - - b=Card.memory[DIVAS_RAM_MEMORY]; - b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1); - DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET)); - Card.memory[DIVAS_RAM_MEMORY]=b; + Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000); + Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000); + Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100); + Card.io_base=dwDivasIOBase; + + Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q; + Card.bus_type = DIA_BUS_TYPE_PCI; + Card.pdev = pdev; + Card.irq = pdev->irq; + + FPGA_Done = 0; + + /* Create four virtual card structures as we want to treat + the 4Bri card as 4 Bri cards*/ + for(i=0;i<4;i++) { + b=Card.memory[DIVAS_RAM_MEMORY]; + b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1); + DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET)); + Card.memory[DIVAS_RAM_MEMORY]=b; - b = Card.memory[DIVAS_RAM_MEMORY]; - b += MQ_SM_OFFSET; - Card.memory[DIVAS_SHARED_MEMORY] = b; - - Card.bus_num = byBus; - Card.func_num = byFunc; - Card.slot = -1; - - - /* Fill in Name */ - Card.name[0] = 'D'; - Card.name[1] = 'I'; - Card.name[2] = 'V'; - Card.name[3] = 'A'; - Card.name[4] = 'S'; - Card.name[5] = 'Q'; - Card.name[6] = '0' + i; - Card.name[7] = '\0'; - - Card.serial = PCIserial; - - Card.card_id = wNumCards; - - if (DivasCardNew(&Card) != 0) - { - // Force for loop to terminate - i = 4; - continue; - } - wNumCards++; - - }//for - } - wDeviceIndex++; - } - - wDeviceIndex = 0; + b = Card.memory[DIVAS_RAM_MEMORY]; + b += MQ_SM_OFFSET; + Card.memory[DIVAS_SHARED_MEMORY] = b; - while (wDeviceIndex < 10) - { - wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_MAESTRA, - wDeviceIndex, - &byBus, &byFunc); - - if (wPCIConsultation == PCIBIOS_SUCCESSFUL) - { - dword dwPLXIOBase, dwDivasIOBase; - byte byIRQ; - - printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n"); - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase); - dwPLXIOBase &= 0xFFFFFF80; + Card.slot = -1; - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase); - dwDivasIOBase &= 0xFFFFFFFC; + sprintf(Card.name, "DIVASQ%ld", i); - pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ); + Card.serial = PCIserial; Card.card_id = wNumCards; - Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B; - Card.bus_type = DIA_BUS_TYPE_PCI; - Card.irq = byIRQ; - Card.reset_base = dwPLXIOBase; - Card.io_base = dwDivasIOBase; - Card.bus_num = byBus; - Card.func_num = byFunc; - Card.slot = -1; - Card.name[0] = 'D'; - Card.name[1] = 'I'; - Card.name[2] = 'V'; - Card.name[3] = 'A'; - Card.name[4] = 'S'; - Card.name[5] = 'B'; - Card.name[6] = '\0'; - - if (check_region(Card.io_base, 0x20)) - { - printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F); - wDeviceIndex++; - continue; - } - - if (check_region(Card.reset_base, 0x80)) - { - printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F); - wDeviceIndex++; - continue; - } - if (DivasCardNew(&Card) != 0) - { - wDeviceIndex++; - continue; + if (DivasCardNew(&Card) != 0) { + break; } wNumCards++; - } - wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_MAESTRAQ_U, - wDeviceIndex, - &byBus, &byFunc); - - if (wPCIConsultation == PCIBIOS_SUCCESSFUL) - { - dword dwPLXIOBase, dwDivasIOBase; - byte byIRQ; + } + } - printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n"); + pdev = NULL; + while ((pdev = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_MAESTRA, + pdev))) { + dword dwPLXIOBase, dwDivasIOBase; + + printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n"); + dwPLXIOBase = pci_resource_start(pdev, 1); + dwDivasIOBase = pci_resource_start(pdev, 2); + + Card.card_id = wNumCards; + Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B; + Card.bus_type = DIA_BUS_TYPE_PCI; + Card.pdev = pdev; + Card.irq = pdev->irq; + Card.reset_base = dwPLXIOBase; + Card.io_base = dwDivasIOBase; + Card.slot = -1; + strcpy(Card.name, "DIVASB"); - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase); - dwPLXIOBase &= 0xFFFFFF80; + if (check_region(Card.io_base, 0x20)) { + printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F); + } - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase); - dwDivasIOBase &= 0xFFFFFFFC; + if (check_region(Card.reset_base, 0x80)) { + printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F); + continue; + } + + if (DivasCardNew(&Card) != 0) { + continue; + } + wNumCards++; + } - pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ); + pdev = NULL; + while ((pdev = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_MAESTRAQ_U, + pdev))) { + dword dwPLXIOBase, dwDivasIOBase; - Card.card_id = wNumCards; - Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B; - Card.bus_type = DIA_BUS_TYPE_PCI; - Card.irq = byIRQ; - Card.reset_base = dwPLXIOBase; - Card.io_base = dwDivasIOBase; - Card.bus_num = byBus; - Card.func_num = byFunc; - Card.slot = -1; - Card.name[0] = 'D'; - Card.name[1] = 'I'; - Card.name[2] = 'V'; - Card.name[3] = 'A'; - Card.name[4] = 'S'; - Card.name[5] = 'B'; - Card.name[6] = '\0'; - - if (check_region(Card.io_base, 0x20)) - { - printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F); - wDeviceIndex++; - continue; - } + printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n"); - if (check_region(Card.reset_base, 0x80)) - { - printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F); - wDeviceIndex++; - continue; - } + dwPLXIOBase = pci_resource_start(pdev, 1); + dwDivasIOBase = pci_resource_start(pdev, 2); + + Card.card_id = wNumCards; + Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B; + Card.bus_type = DIA_BUS_TYPE_PCI; + Card.pdev = pdev; + Card.irq = pdev->irq; + Card.reset_base = dwPLXIOBase; + Card.io_base = dwDivasIOBase; + Card.slot = -1; + strcpy(Card.name, "DIVASB"); + + if (check_region(Card.io_base, 0x20)) { + printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F); + continue; + } - if (DivasCardNew(&Card) != 0) - { - wDeviceIndex++; - continue; - } - wNumCards++; + if (check_region(Card.reset_base, 0x80)) { + printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F); + continue; } - wDeviceIndex++; + if (DivasCardNew(&Card) != 0) { + continue; + } + wNumCards++; } wDeviceIndex = 0; - while (wDeviceIndex < 10) - { - wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_MAESTRAP, - wDeviceIndex, - &byBus, &byFunc); - - if (wPCIConsultation == PCIBIOS_SUCCESSFUL) - { - dword dwRAM, dwREG, dwCFG; - byte byIRQ; + pdev = NULL; + while ((pdev = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_MAESTRAQ_U, + pdev))) { + dword dwRAM, dwREG, dwCFG; - printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n"); - - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0, (unsigned int *) &dwRAM); - dwRAM &= 0xFFFFF000; - - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwREG); - dwREG &= 0xFFFFF000; - - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_4, (unsigned int *) &dwCFG); - dwCFG &= 0xFFFFF000; - - pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ); - - Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000); - Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000); - Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000); - Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET; - -/* pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase); - dwPLXIOBase &= 0xFFFFFFFc; - - pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase); - dwDivasIOBase &= 0xFFFFFF80; - - pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ); -*/ - Card.card_id = wNumCards; - Card.card_type = DIA_CARD_TYPE_DIVA_SERVER; - Card.bus_type = DIA_BUS_TYPE_PCI; - Card.irq = byIRQ; -/* Card.reset_base = dwPLXIOBase; - Card.io_base = dwDivasIOBase;*/ - Card.bus_num = byBus; - Card.func_num = byFunc; - Card.slot = -1; - Card.name[0] = 'D'; - Card.name[1] = 'I'; - Card.name[2] = 'V'; - Card.name[3] = 'A'; - Card.name[4] = 'S'; - Card.name[5] = 'P'; - Card.name[6] = '\0'; - - if (DivasCardNew(&Card) != 0) - { - wDeviceIndex++; - continue; - } - wNumCards++; + printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n"); + + dwRAM = pci_resource_start(pdev, 0); + dwREG = pci_resource_start(pdev, 2); + dwCFG = pci_resource_start(pdev, 4); + + Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000); + Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000); + Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000); + Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET; + + Card.card_id = wNumCards; + Card.card_type = DIA_CARD_TYPE_DIVA_SERVER; + Card.bus_type = DIA_BUS_TYPE_PCI; + Card.pdev = pdev; + Card.irq = pdev->irq; + Card.slot = -1; + strcpy(Card.name, "DIVASP"); + if (DivasCardNew(&Card) != 0) { + continue; } - - wDeviceIndex++; + wNumCards++; } printk(KERN_INFO "Divas: %d cards detected\n", wNumCards); - if(wNumCards == 0) - { + if(wNumCards == 0) { return -1; } @@ -357,8 +229,7 @@ Divas_major = register_chrdev(0, "Divas", &Divas_fops); - if (Divas_major < 0) - { + if (Divas_major < 0) { printk(KERN_WARNING "Divas: Unable to register character driver\n"); return -1; } diff -Nru a/drivers/isdn/eicon/linio.c b/drivers/isdn/eicon/linio.c --- a/drivers/isdn/eicon/linio.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/eicon/linio.c Wed Nov 27 14:36:28 2002 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -67,8 +68,7 @@ switch (cfg->bus_type) { case DIA_BUS_TYPE_PCI: - c->bus_num = cfg->bus_num; - c->func_num = cfg->func_num; + c->pdev = cfg->pdev; c->io_base = cfg->io_base; c->reset_base = cfg->reset_base; c->card_type = cfg->card_type; @@ -625,16 +625,15 @@ void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value) { - switch (size) - { + switch (size) { case sizeof(byte): - pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value); + pci_write_config_byte(card->pdev, offset, * (byte *) value); break; case sizeof(word): - pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value); + pci_write_config_word(card->pdev, offset, * (word *) value); break; case sizeof(dword): - pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value); + pci_write_config_dword(card->pdev, offset, * (dword *) value); break; default: printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n"); @@ -643,16 +642,15 @@ void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value) { - switch (size) - { + switch (size) { case sizeof(byte): - pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value); + pci_read_config_byte(card->pdev, offset, (byte *) value); break; case sizeof(word): - pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value); + pci_read_config_word(card->pdev, offset, (word *) value); break; case sizeof(dword): - pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value); + pci_read_config_dword(card->pdev, offset, (unsigned int *) value); break; default: printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n"); diff -Nru a/drivers/isdn/eicon/uxio.h b/drivers/isdn/eicon/uxio.h --- a/drivers/isdn/eicon/uxio.h Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/eicon/uxio.h Wed Nov 27 14:36:27 2002 @@ -28,8 +28,7 @@ int reset_base; int card_type; byte *mapped; - int bus_num; - int func_num; + struct pci_dev *pdev; int slot; int irq; byte *pDRAM; diff -Nru a/drivers/isdn/hardware/eicon/i4lididrv.c b/drivers/isdn/hardware/eicon/i4lididrv.c --- a/drivers/isdn/hardware/eicon/i4lididrv.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/hardware/eicon/i4lididrv.c Wed Nov 27 14:36:32 2002 @@ -589,12 +589,6 @@ chan->l2prot = (c->arg >> 8); memcpy(chan->a_para, c->parm.aux.para, sizeof(chan->a_para)); return 0; - case ISDN_CMD_GETL2: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - return chan->l2prot; case ISDN_CMD_SETL3: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; @@ -608,33 +602,6 @@ } #endif return 0; - case ISDN_CMD_GETL3: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - return chan->l3prot; - case ISDN_CMD_GETEAZ: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - eicon_log(card, 1, "%s: CMD_GETEAZ not implemented\n", DRIVERLNAME); - return 0; - case ISDN_CMD_SETSIL: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - eicon_log(card, 1, "%s: CMD_SETSIL not implemented\n",DRIVERLNAME); - return 0; - case ISDN_CMD_GETSIL: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - eicon_log(card, 1, "%s: CMD_GETSIL not implemented\n", DRIVERLNAME); - return 0; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - return 0; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - return 0; #ifdef CONFIG_ISDN_TTY_FAX case ISDN_CMD_FAXCMD: if (!card->flags & EICON_FLAGS_RUNNING) @@ -961,6 +928,7 @@ skb_queue_head_init(&card->sackq); skb_queue_head_init(&card->statq); card->statq_entries = 0; + SET_MODULE_OWNER(&card->interface); card->interface.maxbufsize = 4000; card->interface.command = if_command; card->interface.writebuf_skb = if_sendbuf; diff -Nru a/drivers/isdn/hardware/eicon/mi_pc.h b/drivers/isdn/hardware/eicon/mi_pc.h --- a/drivers/isdn/hardware/eicon/mi_pc.h Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/hardware/eicon/mi_pc.h Wed Nov 27 14:36:30 2002 @@ -65,7 +65,7 @@ #define _MP_LED1 0x04 /* 1 = on */ #define _MP_DSP_RESET 0x02 /* active lo */ #define _MP_RISC_RESET 0x81 /* active hi, bit 7 for compatibility with old boards */ -/* CPU exeption context structure in MP shared ram after trap */ +/* CPU exception context structure in MP shared ram after trap */ typedef struct mp_xcptcontext_s MP_XCPTC; struct mp_xcptcontext_s { dword sr; diff -Nru a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c --- a/drivers/isdn/hisax/amd7930.c Wed Nov 27 14:36:29 2002 +++ b/drivers/isdn/hisax/amd7930.c Wed Nov 27 14:36:29 2002 @@ -115,14 +115,7 @@ dev_kfree_skb(bcs->hw.amd7930.tx_skb); bcs->hw.amd7930.tx_skb = NULL; } - - if ((skb = skb_dequeue(&bcs->squeue))) { - Bchan_fill_fifo(bcs, skb); - } else { - clear_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->event |= 1 << B_XMTBUFREADY; - schedule_work(&bcs->work); - } + xmit_ready_b(bcs); } static void diff -Nru a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c --- a/drivers/isdn/hisax/amd7930_fn.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/amd7930_fn.c Wed Nov 27 14:36:31 2002 @@ -268,18 +268,6 @@ } -void -Amd7930_sched_event(struct IsdnCardState *cs, int event) // ok -{ - - if (cs->debug & L1_DEB_ISAC) { - debugl1(cs, "AMD7930: sched_event 0x%X", event); - } - - test_and_set_bit(event, &cs->event); - schedule_work(&cs->work); -} - static void Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag) { @@ -339,7 +327,7 @@ /* throw damaged packets away, reset recieve-buffer, indicate RX */ ptr = cs->rcvbuf; cs->rcvidx = 0; - Amd7930_sched_event(cs, D_RCVBUFREADY); + sched_d_event(cs, D_RCVBUFREADY); } } /* Packet to long, overflow */ @@ -455,7 +443,7 @@ 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)) - Amd7930_sched_event(cs, D_CLEARBUSY); + sched_d_event(cs, D_CLEARBUSY); /* restart frame */ if (cs->tx_skb) { skb_push(cs->tx_skb, cs->tx_cnt); @@ -473,7 +461,7 @@ 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)) - Amd7930_sched_event(cs, D_CLEARBUSY); + sched_d_event(cs, D_CLEARBUSY); /* restart TX-Frame */ if (cs->tx_skb) { skb_push(cs->tx_skb, cs->tx_cnt); @@ -494,7 +482,7 @@ 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)) - Amd7930_sched_event(cs, D_CLEARBUSY); + sched_d_event(cs, D_CLEARBUSY); if (cs->tx_skb) { if (cs->tx_skb->len) Amd7930_fill_Dfifo(cs); @@ -523,7 +511,7 @@ 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)) - Amd7930_sched_event(cs, D_CLEARBUSY); + sched_d_event(cs, D_CLEARBUSY); if (cs->tx_skb) { if (cs->debug & L1_DEB_ISAC) @@ -541,7 +529,7 @@ Amd7930_fill_Dfifo(cs); } else - Amd7930_sched_event(cs, D_XMTBUFREADY); + sched_d_event(cs, D_XMTBUFREADY); /* AMD interrupts on */ AmdIrqOn(cs); } @@ -556,7 +544,7 @@ cs->dc.amd7930.ph_state = (lsr & 0x7) + 2; - Amd7930_sched_event(cs, D_L1STATECHANGE); + sched_d_event(cs, D_L1STATECHANGE); /* AMD interrupts on */ AmdIrqOn(cs); } @@ -662,7 +650,7 @@ 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)) - Amd7930_sched_event(cs, D_CLEARBUSY); + sched_d_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c --- a/drivers/isdn/hisax/asuscom.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/hisax/asuscom.c Wed Nov 27 14:36:32 2002 @@ -172,10 +172,7 @@ struct IsdnCardState *cs = dev_id; u_char val; - if (!cs) { - printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); Start_HSCX: if (val) @@ -202,6 +199,7 @@ writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0); writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0); writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock(&cs->lock); } static void @@ -295,7 +293,7 @@ return(0); case CARD_INIT: cs->debug |= L1_DEB_IPAC; - inithscxisac(cs, 3); + inithscxisac(cs); return(0); case CARD_TEST: return(0); diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c --- a/drivers/isdn/hisax/avm_a1.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/avm_a1.c Wed Nov 27 14:36:27 2002 @@ -106,10 +106,7 @@ struct IsdnCardState *cs = dev_id; u_char val, sval; - if (!cs) { - printk(KERN_WARNING "AVM A1: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); while (((sval = bytein(cs->hw.avm.cfg_reg)) & 0xf) != 0x7) { if (!(sval & AVM_A1_STAT_TIMER)) { byteout(cs->hw.avm.cfg_reg, 0x1E); @@ -133,6 +130,7 @@ writereg(cs->hw.avm.isac, ISAC_MASK, 0x0); writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0); writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0); + spin_unlock(&cs->lock); } inline static void @@ -163,10 +161,9 @@ release_ioregs(cs, 0x3f); return(0); case CARD_INIT: - inithscxisac(cs, 1); byteout(cs->hw.avm.cfg_reg, 0x16); byteout(cs->hw.avm.cfg_reg, 0x1E); - inithscxisac(cs, 2); + inithscxisac(cs); return(0); case CARD_TEST: return(0); diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c --- a/drivers/isdn/hisax/avm_a1p.c Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/hisax/avm_a1p.c Wed Nov 27 14:36:30 2002 @@ -179,10 +179,7 @@ struct IsdnCardState *cs = dev_id; u_char val, sval; - if (!cs) { - printk(KERN_WARNING "AVM A1 PCMCIA: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) { if (cs->debug & L1_DEB_INTSTAT) debugl1(cs, "avm IntStatus %x", sval); @@ -203,6 +200,7 @@ WriteISAC(cs, ISAC_MASK, 0x00); WriteHSCX(cs, 0, HSCX_MASK, 0x00); WriteHSCX(cs, 1, HSCX_MASK, 0x00); + spin_unlock(&cs->lock); } static int @@ -224,10 +222,7 @@ 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); - inithscxisac(cs, 2); + inithscxisac(cs); return 0; case CARD_TEST: diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c --- a/drivers/isdn/hisax/avm_pci.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/avm_pci.c Wed Nov 27 14:36:28 2002 @@ -191,13 +191,6 @@ return(NULL); } -void inline -hdlc_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - void write_ctrl(struct BCState *bcs, int which) { @@ -252,7 +245,7 @@ bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS; write_ctrl(bcs, 1); bcs->hw.hdlc.ctrl.sr.cmd = 0; - hdlc_sched_event(bcs, B_XMTBUFREADY); + sched_b_event(bcs, B_XMTBUFREADY); break; case (L1_MODE_HDLC): bcs->mode = mode; @@ -263,7 +256,7 @@ bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS; write_ctrl(bcs, 1); bcs->hw.hdlc.ctrl.sr.cmd = 0; - hdlc_sched_event(bcs, B_XMTBUFREADY); + sched_b_event(bcs, B_XMTBUFREADY); break; } } @@ -323,35 +316,24 @@ hdlc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int count, cnt =0; + int count, more, cnt =0; int fifo_size = 32; - u_char *p; - u_int *ptr; + unsigned char *p; + unsigned int *ptr; - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "hdlc_fill_fifo"); - if (!bcs->tx_skb) - return; - if (bcs->tx_skb->len <= 0) + p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); + if (!p) return; - bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME; - if (bcs->tx_skb->len > fifo_size) { - count = fifo_size; - } else { - count = bcs->tx_skb->len; - if (bcs->mode != L1_MODE_TRANS) - bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME; - } - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len); - ptr = (u_int *) p = bcs->tx_skb->data; - skb_pull(bcs->tx_skb, count); - bcs->tx_cnt -= count; - bcs->hw.hdlc.count += count; + if (more) + bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME; + else + bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME; + bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count); write_ctrl(bcs, 3); /* sets the correct index too */ if (cs->subtyp == AVM_FRITZ_PCI) { + ptr = (unsigned int *) p; while (cntdebug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - if (cs->subtyp == AVM_FRITZ_PNP) - p = (u_char *) ptr; - t += sprintf(t, "hdlc_fill_fifo %c cnt %d", - bcs->channel ? 'B' : 'A', count); - QuickHex(t, p, count); - debugl1(cs, bcs->blog); - } } static void -fill_hdlc(struct BCState *bcs) +reset_xmit(struct BCState *bcs) { - unsigned long flags; - spin_lock_irqsave(&avm_pci_lock, flags); + bcs->hw.hdlc.ctrl.sr.xml = 0; + bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS; + write_ctrl(bcs, 1); + bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS; + write_ctrl(bcs, 1); hdlc_fill_fifo(bcs); - spin_unlock_irqrestore(&avm_pci_lock, flags); } static inline void -HDLC_irq(struct BCState *bcs, u_int stat) { +HDLC_irq(struct BCState *bcs, u_int stat) +{ int len; struct sk_buff *skb; if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat); + if (stat & HDLC_INT_RPR) { if (stat & HDLC_STAT_RDO) { if (bcs->cs->debug & L1_DEB_HSCX) @@ -425,7 +401,7 @@ skb_queue_tail(&bcs->rqueue, skb); } bcs->hw.hdlc.rcvidx = 0; - hdlc_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } else { if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs, "invalid frame"); @@ -437,46 +413,9 @@ } } if (stat & HDLC_INT_XDU) { - /* Here we lost an TX interrupt, so - * restart transmitting the whole frame. - */ - if (bcs->tx_skb) { - skb_push(bcs->tx_skb, bcs->hw.hdlc.count); - bcs->tx_cnt += bcs->hw.hdlc.count; - bcs->hw.hdlc.count = 0; -// hdlc_sched_event(bcs, B_XMTBUFREADY); - if (bcs->cs->debug & L1_DEB_WARN) - debugl1(bcs->cs, "ch%d XDU", bcs->channel); - } else if (bcs->cs->debug & L1_DEB_WARN) - debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel); - bcs->hw.hdlc.ctrl.sr.xml = 0; - bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS; - write_ctrl(bcs, 1); - bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS; - write_ctrl(bcs, 1); - hdlc_fill_fifo(bcs); + xmit_xdu_b(bcs, reset_xmit); } else if (stat & HDLC_INT_XPR) { - if (bcs->tx_skb) { - if (bcs->tx_skb->len) { - hdlc_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.hdlc.count); - dev_kfree_skb_irq(bcs->tx_skb); - bcs->hw.hdlc.count = 0; - bcs->tx_skb = NULL; - } - } - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->hw.hdlc.count = 0; - test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); - hdlc_fill_fifo(bcs); - } else { - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - hdlc_sched_event(bcs, B_XMTBUFREADY); - } + xmit_xpr_b(bcs); } } @@ -484,10 +423,9 @@ HDLC_irq_main(struct IsdnCardState *cs) { u_int stat; - long flags; struct BCState *bcs; - spin_lock_irqsave(&avm_pci_lock, flags); + spin_lock(&cs->lock); if (cs->subtyp == AVM_FRITZ_PCI) { stat = ReadHDLCPCI(cs, 0, HDLC_STATUS); } else { @@ -516,45 +454,23 @@ } else HDLC_irq(bcs, stat); } - spin_unlock_irqrestore(&avm_pci_lock, flags); + spin_unlock(&cs->lock); } void hdlc_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; - unsigned long flags; switch (pr) { case (PH_DATA | REQUEST): - spin_lock_irqsave(&avm_pci_lock, flags); - if (st->l1.bcs->tx_skb) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - spin_unlock_irqrestore(&avm_pci_lock, flags); - } else { - st->l1.bcs->tx_skb = skb; - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->hw.hdlc.count = 0; - spin_unlock_irqrestore(&avm_pci_lock, flags); - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "hdlc_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.hdlc.count = 0; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); @@ -639,7 +555,7 @@ } void __init -clear_pending_hdlc_ints(struct IsdnCardState *cs) +inithdlc(struct IsdnCardState *cs) { u_int val; @@ -666,11 +582,7 @@ val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3); debugl1(cs, "HDLC 2 VIN %x", val); } -} -void __init -inithdlc(struct IsdnCardState *cs) -{ cs->bcs[0].BC_SetStack = setstack_hdlc; cs->bcs[1].BC_SetStack = setstack_hdlc; cs->bcs[0].BC_Close = close_hdlcstate; @@ -731,17 +643,12 @@ release_region(cs->hw.avm.cfg_reg, 32); return(0); case CARD_INIT: - clear_pending_isac_ints(cs); initisac(cs); - clear_pending_hdlc_ints(cs); inithdlc(cs); outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER, cs->hw.avm.cfg_reg + 2); - WriteISAC(cs, ISAC_MASK, 0); outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); - /* RESET Receiver and Transmitter */ - WriteISAC(cs, ISAC_CMDR, 0x41); return(0); case CARD_TEST: return(0); @@ -880,7 +787,7 @@ cs->writeisac = &WriteISAC; cs->readisacfifo = &ReadISACfifo; cs->writeisacfifo = &WriteISACfifo; - cs->BC_Send_Data = &fill_hdlc; + cs->BC_Send_Data = &hdlc_fill_fifo; cs->cardmsg = &AVM_card_msg; cs->irq_func = &avm_pcipnp_interrupt; ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:"); diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c --- a/drivers/isdn/hisax/bkm_a4t.c Wed Nov 27 14:36:29 2002 +++ b/drivers/isdn/hisax/bkm_a4t.c Wed Nov 27 14:36:29 2002 @@ -139,10 +139,7 @@ u_char val = 0; I20_REGISTER_FILE *pI20_Regs; - if (!cs) { - printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); /* ISDN interrupt pending? */ @@ -169,6 +166,7 @@ /* Reenable ISDN interrupt */ pI20_Regs->i20IntCtrl |= intISDN; } + spin_unlock(&cs->lock); } void @@ -243,8 +241,6 @@ release_io_bkm(cs); return (0); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_jade_ints(cs); initisac(cs); initjade(cs); /* Enable ints */ diff -Nru a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c --- a/drivers/isdn/hisax/bkm_a8.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/bkm_a8.c Wed Nov 27 14:36:31 2002 @@ -153,13 +153,10 @@ struct IsdnCardState *cs = dev_id; u_char ista, val, icnt = 5; - if (!cs) { - printk(KERN_WARNING "HiSax: Scitel Quadro: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA); if (!(ista & 0x3f)) /* not this IPAC */ - return; + goto unlock; Start_IPAC: if (cs->debug & L1_DEB_IPAC) debugl1(cs, "IPAC ISTA %02X", ista); @@ -196,6 +193,8 @@ sct_quadro_subtypes[cs->subtyp]); writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF); writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0); + unlock: + spin_unlock(&cs->lock); } @@ -251,7 +250,7 @@ case CARD_INIT: cs->debug |= L1_DEB_IPAC; set_ipac_active(cs, 1); - inithscxisac(cs, 3); + inithscxisac(cs); /* Enable ints */ enable_bkm_int(cs, 1); return (0); diff -Nru a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c --- a/drivers/isdn/hisax/callc.c Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/hisax/callc.c Wed Nov 27 14:36:30 2002 @@ -29,8 +29,6 @@ extern struct IsdnCard cards[]; extern int nrcards; -extern void HiSax_mod_dec_use_count(struct IsdnCardState *cs); -extern void HiSax_mod_inc_use_count(struct IsdnCardState *cs); static int init_b_st(struct Channel *chanp, int incoming); static void release_b_st(struct Channel *chanp); @@ -1068,7 +1066,6 @@ setstack_isdnl2(st, tmp); setstack_l3dc(st, chanp); st->lli.userdata = chanp; - st->lli.l2writewakeup = NULL; st->lli.l3l4 = dchan_l3l4; return 0; @@ -1186,13 +1183,30 @@ } static void +ll_writewakeup(struct Channel *chanp, struct sk_buff *skb) +{ + isdn_ctrl ic; + + if (skb->pkt_type != PACKET_NOACK) { + if (chanp->debug & 0x800) + link_debug(chanp, 0, "llwakeup: %d", skb->truesize); + ic.driver = chanp->cs->myid; + ic.command = ISDN_STAT_BSENT; + ic.arg = chanp->chan; + ic.parm.length = skb->truesize; + chanp->cs->iif.statcallb(&ic); + } + dev_kfree_skb(skb); +} + +static void lldata_handler(struct PStack *st, int pr, void *arg) { struct Channel *chanp = (struct Channel *) st->lli.userdata; struct sk_buff *skb = arg; switch (pr) { - case (DL_DATA | INDICATION): + case (DL_DATA | INDICATION): if (chanp->data_open) { if (chanp->debug & 0x800) link_debug(chanp, 0, "lldata: %d", skb->len); @@ -1202,6 +1216,9 @@ dev_kfree_skb(skb); } break; + case (DL_DATA | CONFIRM): + ll_writewakeup(chanp, skb); + break; case (DL_ESTABLISH | INDICATION): case (DL_ESTABLISH | CONFIRM): FsmEvent(&chanp->fi, EV_BC_EST, NULL); @@ -1234,6 +1251,9 @@ dev_kfree_skb(skb); } break; + case (PH_DATA | CONFIRM): + ll_writewakeup(chanp, skb); + break; case (PH_ACTIVATE | INDICATION): case (PH_ACTIVATE | CONFIRM): FsmEvent(&chanp->fi, EV_BC_EST, NULL); @@ -1249,21 +1269,6 @@ } } -static void -ll_writewakeup(struct PStack *st, int len) -{ - struct Channel *chanp = st->lli.userdata; - isdn_ctrl ic; - - if (chanp->debug & 0x800) - link_debug(chanp, 0, "llwakeup: %d", len); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BSENT; - ic.arg = chanp->chan; - ic.parm.length = len; - chanp->cs->iif.statcallb(&ic); -} - static int init_b_st(struct Channel *chanp, int incoming) { @@ -1314,8 +1319,6 @@ setstack_l3bc(st, chanp); st->l3.l2l3 = lldata_handler; st->lli.userdata = chanp; - st->lli.l1writewakeup = NULL; - st->lli.l2writewakeup = ll_writewakeup; st->l2.l2m.debug = chanp->debug & 16; st->l2.debug = chanp->debug & 64; break; @@ -1326,7 +1329,6 @@ case (ISDN_PROTO_L2_FAX): st->l2.l1l2 = lltrans_handler; st->lli.userdata = chanp; - st->lli.l1writewakeup = ll_writewakeup; setstack_transl2(st); setstack_l3bc(st, chanp); break; @@ -1584,22 +1586,6 @@ break; } break; - case (ISDN_CMD_LOCK): - HiSax_mod_inc_use_count(csta); -#ifdef MODULE - if (csta->channel[0].debug & 0x400) - HiSax_putstatus(csta, " LOCK ", "modcnt %lx", - MOD_USE_COUNT); -#endif /* MODULE */ - break; - case (ISDN_CMD_UNLOCK): - HiSax_mod_dec_use_count(csta); -#ifdef MODULE - if (csta->channel[0].debug & 0x400) - HiSax_putstatus(csta, " UNLOCK ", "modcnt %lx", - MOD_USE_COUNT); -#endif /* MODULE */ - break; case (ISDN_CMD_IOCTL): switch (ic->arg) { case (0): @@ -1623,14 +1609,6 @@ printk(KERN_DEBUG "HiSax: delay card %d set to %d ms\n", csta->cardnr + 1, num); break; - case (3): - for (i = 0; i < *(unsigned int *) ic->parm.num; i++) - HiSax_mod_dec_use_count(NULL); - break; - case (4): - for (i = 0; i < *(unsigned int *) ic->parm.num; i++) - HiSax_mod_inc_use_count(NULL); - break; case (5): /* set card in leased mode */ num = *(unsigned int *) ic->parm.num; if ((num <1) || (num > 2)) { @@ -1693,12 +1671,6 @@ } L4L3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); break; -#ifdef MODULE - case (55): - MOD_USE_COUNT = 0; - HiSax_mod_inc_use_count(NULL); - break; -#endif /* MODULE */ case (11): num = csta->debug & DEB_DLOG_HEX; csta->debug = *(unsigned int *) ic->parm.num; diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c --- a/drivers/isdn/hisax/config.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/config.c Wed Nov 27 14:36:31 2002 @@ -942,6 +942,8 @@ cs->status_write = cs->status_buf; cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; cs->typ = card->typ; + spin_lock_init(&cs->lock); + SET_MODULE_OWNER(&cs->iif); strcpy(cs->iif.id, id); cs->iif.channels = 2; cs->iif.maxbufsize = MAX_DATA_SIZE; @@ -1769,6 +1771,7 @@ hisax_d_if->cs = cs; cs->hw.hisax_d_if = hisax_d_if; cs->cardmsg = hisax_cardmsg; + cs->iif.owner = hisax_d_if->owner; // FIXME should be done before registering INIT_WORK(&cs->work, hisax_bh, cs); cs->channel[0].d_st->l1.l2l1 = hisax_d_l2l1; for (i = 0; i < 2; i++) { @@ -1795,12 +1798,6 @@ #include "isdnl1.h" -static void hisax_sched_event(struct IsdnCardState *cs, int event) -{ - cs->event |= 1 << event; - schedule_work(&cs->work); -} - static void hisax_bh(void *data) { struct IsdnCardState *cs = data; @@ -1822,12 +1819,6 @@ } } -static void hisax_b_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - static inline void D_L2L1(struct hisax_d_if *d_if, int pr, void *arg) { struct hisax_if *ifc = (struct hisax_if *) d_if; @@ -1850,15 +1841,15 @@ switch (pr) { case PH_ACTIVATE | INDICATION: set_bit(0, &d_if->ph_state); - hisax_sched_event(cs, D_L1STATECHANGE); + sched_d_event(cs, D_L1STATECHANGE); break; case PH_DEACTIVATE | INDICATION: clear_bit(0, &d_if->ph_state); - hisax_sched_event(cs, D_L1STATECHANGE); + sched_d_event(cs, D_L1STATECHANGE); break; case PH_DATA | INDICATION: skb_queue_tail(&cs->rq, arg); - hisax_sched_event(cs, D_RCVBUFREADY); + sched_d_event(cs, D_RCVBUFREADY); break; case PH_DATA | CONFIRM: skb = skb_dequeue(&cs->sq); @@ -1876,7 +1867,7 @@ break; case PH_DATA_E | INDICATION: skb_queue_tail(&d_if->erq, arg); - hisax_sched_event(cs, E_RCVBUFREADY); + sched_d_event(cs, E_RCVBUFREADY); break; default: printk("pr %#x\n", pr); @@ -1904,12 +1895,12 @@ break; case PH_DATA | INDICATION: skb_queue_tail(&bcs->rqueue, arg); - hisax_b_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); break; case PH_DATA | CONFIRM: - bcs->tx_cnt -= (int) arg; - if (bcs->st->lli.l1writewakeup) - bcs->st->lli.l1writewakeup(bcs->st, (int) arg); + skb = arg; + bcs->tx_cnt -= skb->truesize; + xmit_complete_b(bcs); skb = skb_dequeue(&bcs->squeue); if (skb) { B_L2L1(b_if, PH_DATA | REQUEST, skb); @@ -2050,33 +2041,6 @@ skb->len); } dev_kfree_skb_any(skb); - } -} - -void HiSax_mod_dec_use_count(struct IsdnCardState *cs) -{ - struct module *mod; - - if (cs && cs->cardmsg == hisax_cardmsg) { - mod = cs->hw.hisax_d_if->owner; - if (mod) - __MOD_DEC_USE_COUNT(mod); - } else { - MOD_DEC_USE_COUNT; - } -} - -void HiSax_mod_inc_use_count(struct IsdnCardState *cs) -{ - struct module *mod; - - if (cs && cs->cardmsg == hisax_cardmsg) { - mod = cs->hw.hisax_d_if->owner; - if (mod) - // hope we do win the race... - try_inc_mod_count(mod); - } else { - MOD_INC_USE_COUNT; } } diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c --- a/drivers/isdn/hisax/diva.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/hisax/diva.c Wed Nov 27 14:36:32 2002 @@ -307,10 +307,7 @@ u_char val, sval; int cnt=5; - if (!cs) { - printk(KERN_WARNING "Diva: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) { val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40); if (val) @@ -328,6 +325,7 @@ writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0); writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0); writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock(&cs->lock); } static void @@ -456,46 +454,19 @@ Memhscx_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int more, count, cnt; + int more, count; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; - u_char *ptr,*p; - unsigned long flags; + unsigned char *p; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "hscx_fill_fifo"); - - if (!bcs->tx_skb) - return; - if (bcs->tx_skb->len <= 0) + p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); + if (!p) return; - more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; - if (bcs->tx_skb->len > fifo_size) { - more = !0; - count = fifo_size; - } else - count = bcs->tx_skb->len; - cnt = count; MemwaitforXFW(cs, bcs->hw.hscx.hscx); - spin_lock_irqsave(&diva_lock, flags); - p = ptr = bcs->tx_skb->data; - skb_pull(bcs->tx_skb, count); - bcs->tx_cnt -= count; - bcs->hw.hscx.count += count; - while(cnt--) + while (count--) memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0, *p++); MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); - spin_unlock_irqrestore(&diva_lock, flags); - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "hscx_fill_fifo %c cnt %d", - bcs->hw.hscx.hscx ? 'B' : 'A', count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } } static inline void @@ -542,7 +513,7 @@ } } bcs->hw.hscx.rcvidx = 0; - hscx_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } if (val & 0x40) { /* RPF */ Memhscx_empty_fifo(bcs, fifo_size); @@ -555,34 +526,20 @@ skb_queue_tail(&bcs->rqueue, skb); } bcs->hw.hscx.rcvidx = 0; - hscx_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } } - if (val & 0x10) { /* XPR */ - if (bcs->tx_skb) { - if (bcs->tx_skb->len) { - Memhscx_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.hscx.count); - dev_kfree_skb_irq(bcs->tx_skb); - bcs->hw.hscx.count = 0; - bcs->tx_skb = NULL; - } - } - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->hw.hscx.count = 0; - test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); - Memhscx_fill_fifo(bcs); - } else { - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - hscx_sched_event(bcs, B_XMTBUFREADY); - } + if (val & 0x10) { + xmit_xpr_b(bcs);/* XPR */ } } +static void +Memhscx_reset_xmit(struct BCState *bcs) +{ + MemWriteHSCXCMDR(bcs->cs, bcs->hw.hscx.hscx, 0x01); +} + static inline void Memhscx_int_main(struct IsdnCardState *cs, u_char val) { @@ -594,23 +551,10 @@ bcs = cs->bcs + 1; exval = MemReadHSCX(cs, 1, HSCX_EXIR); if (exval & 0x40) { - if (bcs->mode == 1) - Memhscx_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.hscx.count); - bcs->tx_cnt += bcs->hw.hscx.count; - bcs->hw.hscx.count = 0; - } - MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "HSCX B EXIR %x Lost TX", exval); - } - } else if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX B EXIR %x", exval); + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B EXIR %x", exval); + xmit_xdu_b(bcs, Memhscx_reset_xmit); + } } if (val & 0xf8) { if (cs->debug & L1_DEB_HSCX) @@ -621,23 +565,10 @@ bcs = cs->bcs; exval = MemReadHSCX(cs, 0, HSCX_EXIR); if (exval & 0x40) { - if (bcs->mode == L1_MODE_TRANS) - Memhscx_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.hscx.count); - bcs->tx_cnt += bcs->hw.hscx.count; - bcs->hw.hscx.count = 0; - } - MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "HSCX A EXIR %x Lost TX", exval); - } - } else if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX A EXIR %x", exval); + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A EXIR %x", exval); + xmit_xdu_b(bcs, Memhscx_reset_xmit); + } } if (val & 0x04) { // ICA exval = MemReadHSCX(cs, 0, HSCX_ISTA); @@ -714,7 +645,7 @@ cfg = (u_char *) cs->hw.diva.pci_cfg; val = *cfg; if (!(val &PITA_INT0_STATUS)) return; // other shared IRQ - interrupt_ipacx(cs); // handler for chip + interrupt_ipacx(cs); // handler for chip *cfg = PITA_INT0_STATUS; // Reset PLX interrupt } @@ -860,7 +791,7 @@ ireg = (unsigned int *)cs->hw.diva.pci_cfg; *ireg = PITA_INT0_ENABLE; } - inithscxisac(cs, 3); + inithscxisac(cs); return(0); case CARD_TEST: return(0); @@ -1163,7 +1094,7 @@ cs->writeisacfifo = &MemWriteISACfifo_IPACX; cs->BC_Read_Reg = &MemReadHSCX_IPACX; cs->BC_Write_Reg = &MemWriteHSCX_IPACX; - cs->BC_Send_Data = 0; // function located in ipacx module + cs->BC_Send_Data = &ipacx_fill_fifo; cs->irq_func = &diva_irq_ipacx_pci; printk(KERN_INFO "Diva: IPACX Design Id: %x\n", MemReadISAC_IPACX(cs, IPACX_ID) &0x3F); diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c --- a/drivers/isdn/hisax/elsa.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/elsa.c Wed Nov 27 14:36:28 2002 @@ -308,15 +308,12 @@ u_char val; int icnt=5; - if (!cs) { - printk(KERN_WARNING "Elsa: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) { /* The card tends to generate interrupts while being removed causing us to just crash the kernel. bad. */ printk(KERN_WARNING "Elsa: card not available!\n"); - return; + goto unlock; } #if ARCOFI_USE if (cs->hw.elsa.MFlag) { @@ -378,6 +375,8 @@ writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0); + unlock: + spin_unlock(&cs->lock); } static void @@ -679,7 +678,6 @@ return(0); case CARD_INIT: cs->debug |= L1_DEB_IPAC; - inithscxisac(cs, 1); if ((cs->subtyp == ELSA_QS1000) || (cs->subtyp == ELSA_QS3000)) { @@ -687,7 +685,7 @@ } if (cs->hw.elsa.trig) byteout(cs->hw.elsa.trig, 0xff); - inithscxisac(cs, 2); + inithscxisac(cs); return(0); case CARD_TEST: if ((cs->subtyp == ELSA_PCMCIA) || diff -Nru a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c --- a/drivers/isdn/hisax/elsa_ser.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/elsa_ser.c Wed Nov 27 14:36:28 2002 @@ -292,30 +292,10 @@ return(ret); } -inline void -modem_fill(struct BCState *bcs) { - - if (bcs->tx_skb) { - if (bcs->tx_skb->len) { - write_modem(bcs); - return; - } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, - bcs->hw.hscx.count); - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - } - } - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->hw.hscx.count = 0; - test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); - write_modem(bcs); - } else { - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - hscx_sched_event(bcs, B_XMTBUFREADY); - } +static void +modem_fill(struct BCState *bcs) +{ + xmit_xpr_b(bcs); } static inline void receive_chars(struct IsdnCardState *cs, @@ -349,7 +329,7 @@ cs->hw.elsa.rcvcnt); skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb); } - hscx_sched_event(cs->hw.elsa.bcs, B_RCVBUFREADY); + sched_b_event(cs->hw.elsa.bcs, B_RCVBUFREADY); } else { char tmp[128]; char *t = tmp; @@ -580,7 +560,7 @@ } else { st->l1.bcs->tx_skb = skb; test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->hw.hscx.count = 0; + st->l1.bcs->count = 0; spin_unlock_irqrestore(&elsa_ser_lock, flags); write_modem(st->l1.bcs); } @@ -613,6 +593,7 @@ if (open_hscxstate(st->l1.hardware, bcs)) return (-1); st->l1.l2l1 = hscx_l2l1; + // bcs->cs->BC_Send_Data = hscx_fill_fifo; break; case L1_MODE_MODEM: bcs->mode = L1_MODE_MODEM; @@ -628,6 +609,7 @@ bcs->tx_cnt = 0; bcs->cs->hw.elsa.bcs = bcs; st->l1.l2l1 = modem_l2l1; + bcs->cs->BC_Send_Data = modem_fill; break; } st->l1.bcs = bcs; diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c --- a/drivers/isdn/hisax/enternow_pci.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/enternow_pci.c Wed Nov 27 14:36:31 2002 @@ -75,7 +75,6 @@ const char *enternow_pci_rev = "$Revision: 1.1.2.1 $"; -static spinlock_t enternow_pci_lock = SPIN_LOCK_UNLOCKED; /* *************************** I/O-Interface functions ************************************* */ @@ -231,13 +230,8 @@ { struct IsdnCardState *cs = dev_id; BYTE sval, ir; - unsigned long flags; - - if (!cs) { - printk(KERN_WARNING "enter:now PCI: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); sval = InByte(cs->hw.njet.base + NETJET_IRQSTAT1); @@ -251,7 +245,6 @@ /* DMA-Interrupt: B-channel-stuff */ /* set bits in sval to indicate which page is free */ - spin_lock_irqsave(&enternow_pci_lock, flags); /* set bits in sval to indicate which page is free */ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) @@ -265,14 +258,8 @@ sval = sval | 0x02; else /* the 1st read page is free */ sval = sval | 0x01; - if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ - { - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - spin_unlock_irqrestore(&enternow_pci_lock, flags); - return; - } + if (sval != cs->hw.njet.last_is0) { /* we have a DMA interrupt */ cs->hw.njet.irqstat0 = sval; - spin_unlock_irqrestore(&enternow_pci_lock, flags); if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) /* we have a read dma int */ @@ -281,9 +268,8 @@ (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE)) /* we have a write dma int */ write_tiger(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - spin_unlock_irqrestore(&enternow_pci_lock, flags); + } + spin_unlock(&cs->lock); } @@ -296,7 +282,6 @@ int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; - unsigned long flags; #if CONFIG_PCI #ifdef __BIG_ENDIAN @@ -306,7 +291,6 @@ printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_ENTERNOW) return(0); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); for ( ;; ) { @@ -343,9 +327,6 @@ cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD - save_flags(flags); - sti(); - /* Reset an */ cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); @@ -359,8 +340,6 @@ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - restore_flags(flags); cs->hw.njet.auxd = 0x00; // war 0xc0 cs->hw.njet.dmactrl = 0; diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c --- a/drivers/isdn/hisax/gazel.c Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/hisax/gazel.c Wed Nov 27 14:36:30 2002 @@ -259,10 +259,7 @@ u_char valisac, valhscx; int count = 0; - if (!cs) { - printk(KERN_WARNING "Gazel: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); do { valhscx = ReadHSCX(cs, 1, HSCX_ISTA); if (valhscx) @@ -279,6 +276,7 @@ WriteISAC(cs, ISAC_MASK, 0x0); WriteHSCX(cs, 0, HSCX_MASK, 0x0); WriteHSCX(cs, 1, HSCX_MASK, 0x0); + spin_unlock(&cs->lock); } @@ -421,7 +419,7 @@ release_io_gazel(cs); return (0); case CARD_INIT: - inithscxisac(cs, 1); + inithscxisac(cs); if ((cs->subtyp==R647)||(cs->subtyp==R685)) { int i; for (i=0;i<(2+MAX_WAITING_CALLS);i++) { diff -Nru a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c --- a/drivers/isdn/hisax/hfc_2bds0.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/hfc_2bds0.c Wed Nov 27 14:36:27 2002 @@ -106,15 +106,11 @@ static inline int WaitNoBusy(struct IsdnCardState *cs) { - long flags; int to = 130; while ((ReadReg(cs, HFCD_STATUS, HFCD_STATUS) & HFCD_BUSY) && to) { - save_flags(flags); - sti(); udelay(1); to--; - restore_flags(flags); } if (!to) printk(KERN_WARNING "HiSax: WaitNoBusy timeout\n"); @@ -125,13 +121,10 @@ SelFiFo(struct IsdnCardState *cs, u_char FiFo) { u_char cip; - long flags; - if (cs->hw.hfcD.fifo == FiFo) return(1); - save_flags(flags); - cli(); + switch(FiFo) { case 0: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B1; break; @@ -146,16 +139,13 @@ case 5: cip = HFCD_FIFO | HFCD_Z1 | HFCD_REC; break; default: - restore_flags(flags); debugl1(cs, "SelFiFo Error"); return(0); } cs->hw.hfcD.fifo = FiFo; WaitNoBusy(cs); cs->BC_Write_Reg(cs, HFCD_DATA, cip, 0); - sti(); WaitForBusy(cs); - restore_flags(flags); return(2); } static int @@ -198,13 +188,6 @@ return (val); } -static void -hfc_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - static struct sk_buff *hfc_empty_fifo(struct BCState *bcs, int count) { @@ -213,22 +196,18 @@ struct IsdnCardState *cs = bcs->cs; int idx; int chksum; - long flags; u_char stat, cip; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_empty_fifo"); idx = 0; - save_flags(flags); if (count > HSCX_BUFMAX + 3) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfc_empty_fifo: incoming packet too large"); cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); while (idx++ < count) { - cli(); WaitNoBusy(cs); ReadReg(cs, HFCD_DATA_NODEB, cip); - sti(); } skb = NULL; } else if (count < 4) { @@ -238,7 +217,6 @@ #ifdef ERROR_STATISTIC bcs->err_inv++; #endif - cli(); while ((idx++ < count) && WaitNoBusy(cs)) ReadReg(cs, HFCD_DATA_NODEB, cip); skb = NULL; @@ -248,31 +226,25 @@ ptr = skb_put(skb, count - 3); idx = 0; cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); - cli(); while (idx < (count - 3)) { - cli(); if (!WaitNoBusy(cs)) break; *ptr = ReadReg(cs, HFCD_DATA_NODEB, cip); - sti(); ptr++; idx++; } if (idx != count - 3) { - sti(); debugl1(cs, "RFIFO BUSY error"); printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); dev_kfree_skb_irq(skb); skb = NULL; } else { - cli(); WaitNoBusy(cs); chksum = (ReadReg(cs, HFCD_DATA, cip) << 8); WaitNoBusy(cs); chksum += ReadReg(cs, HFCD_DATA, cip); WaitNoBusy(cs); stat = ReadReg(cs, HFCD_DATA, cip); - sti(); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x", bcs->channel, chksum, stat); @@ -286,15 +258,11 @@ } } } - sti(); WaitForBusy(cs); - cli(); WaitNoBusy(cs); stat = ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F2_INC | HFCB_REC | HFCB_CHANNEL(bcs->channel)); - sti(); WaitForBusy(cs); - restore_flags(flags); return (skb); } @@ -302,7 +270,6 @@ hfc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - long flags; int idx, fcnt; int count; u_char cip; @@ -311,8 +278,6 @@ return; if (bcs->tx_skb->len <= 0) return; - save_flags(flags); - cli(); SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel)); cip = HFCB_FIFO | HFCB_F1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel); WaitNoBusy(cs); @@ -322,7 +287,6 @@ WaitNoBusy(cs); bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip); bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel)); - sti(); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2, @@ -333,7 +297,6 @@ if (fcnt > 30) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo more as 30 frames"); - restore_flags(flags); return; } count = GetFreeFifoBytes_B(bcs); @@ -344,77 +307,45 @@ if (count < bcs->tx_skb->len) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo no fifo mem"); - restore_flags(flags); return; } cip = HFCB_FIFO | HFCB_FIFO_IN | HFCB_SEND | HFCB_CHANNEL(bcs->channel); idx = 0; - cli(); WaitForBusy(cs); WaitNoBusy(cs); WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); while (idx < bcs->tx_skb->len) { - cli(); if (!WaitNoBusy(cs)) break; WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]); - sti(); idx++; } if (idx != bcs->tx_skb->len) { - sti(); debugl1(cs, "FIFO Send BUSY error"); printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); } else { bcs->tx_cnt -= bcs->tx_skb->len; - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; + xmit_complete_b(bcs); } WaitForBusy(cs); - cli(); WaitNoBusy(cs); ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F1_INC | HFCB_SEND | HFCB_CHANNEL(bcs->channel)); - sti(); WaitForBusy(cs); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - restore_flags(flags); return; } -static void -hfc_send_data(struct BCState *bcs) -{ - struct IsdnCardState *cs = bcs->cs; - - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfc_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs,"send_data %d blocked", bcs->channel); -} - void main_rec_2bds0(struct BCState *bcs) { - long flags; struct IsdnCardState *cs = bcs->cs; int z1, z2, rcnt; u_char f1, f2, cip; int receive, count = 5; struct sk_buff *skb; - save_flags(flags); Begin: count--; - cli(); - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - debugl1(cs,"rec_data %d blocked", bcs->channel); - restore_flags(flags); - return; - } SelFiFo(cs, HFCB_REC | HFCB_CHANNEL(bcs->channel)); cip = HFCB_FIFO | HFCB_F1 | HFCB_REC | HFCB_CHANNEL(bcs->channel); WaitNoBusy(cs); @@ -422,15 +353,12 @@ cip = HFCB_FIFO | HFCB_F2 | HFCB_REC | HFCB_CHANNEL(bcs->channel); WaitNoBusy(cs); f2 = ReadReg(cs, HFCD_DATA, cip); - sti(); if (f1 != f2) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc rec %d f1(%d) f2(%d)", bcs->channel, f1, f2); - cli(); z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel)); z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel)); - sti(); rcnt = z1 - z2; if (rcnt < 0) rcnt += cs->hw.hfcD.bfifosize; @@ -439,10 +367,8 @@ debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)", bcs->channel, z1, z2, rcnt); if ((skb = hfc_empty_fifo(bcs, rcnt))) { - cli(); skb_queue_tail(&bcs->rqueue, skb); - sti(); - hfc_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } rcnt = f1 -f2; if (rcnt<0) @@ -453,10 +379,8 @@ receive = 0; } else receive = 0; - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; - restore_flags(flags); return; } @@ -512,40 +436,16 @@ hfc_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->cs->BC_Send_Data(st->l1.bcs); - restore_flags(flags); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); - break; - } - save_flags(flags); - cli(); -/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); -*/ st->l1.bcs->tx_skb = skb; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - restore_flags(flags); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); @@ -642,18 +542,10 @@ DChannel_proc_xmt(cs); } -void -sched_event_D(struct IsdnCardState *cs, int event) -{ - test_and_set_bit(event, &cs->event); - schedule_work(&cs->work); -} - static int receive_dmsg(struct IsdnCardState *cs) { struct sk_buff *skb; - long flags; int idx; int rcnt, z1, z2; u_char stat, cip, f1, f2; @@ -661,13 +553,6 @@ int count=5; u_char *ptr; - save_flags(flags); - cli(); - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - debugl1(cs, "rec_dmsg blocked"); - restore_flags(flags); - return(1); - } SelFiFo(cs, 4 | HFCD_REC); cip = HFCD_FIFO | HFCD_F1 | HFCD_REC; WaitNoBusy(cs); @@ -685,39 +570,32 @@ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)", f1, f2, z1, z2, rcnt); - sti(); idx = 0; cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC; if (rcnt > MAX_DFRAME_LEN + 3) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "empty_fifo d: incoming packet too large"); while (idx < rcnt) { - cli(); if (!(WaitNoBusy(cs))) break; ReadReg(cs, HFCD_DATA_NODEB, cip); - sti(); idx++; } } else if (rcnt < 4) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "empty_fifo d: incoming packet too small"); - cli(); while ((idx++ < rcnt) && WaitNoBusy(cs)) ReadReg(cs, HFCD_DATA_NODEB, cip); } else if ((skb = dev_alloc_skb(rcnt - 3))) { ptr = skb_put(skb, rcnt - 3); while (idx < (rcnt - 3)) { - cli(); if (!(WaitNoBusy(cs))) break; *ptr = ReadReg(cs, HFCD_DATA_NODEB, cip); - sti(); idx++; ptr++; } if (idx != (rcnt - 3)) { - sti(); debugl1(cs, "RFIFO D BUSY error"); printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n"); dev_kfree_skb_irq(skb); @@ -726,14 +604,12 @@ cs->err_rx++; #endif } else { - cli(); WaitNoBusy(cs); chksum = (ReadReg(cs, HFCD_DATA, cip) << 8); WaitNoBusy(cs); chksum += ReadReg(cs, HFCD_DATA, cip); WaitNoBusy(cs); stat = ReadReg(cs, HFCD_DATA, cip); - sti(); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "empty_dfifo chksum %x stat %x", chksum, stat); @@ -746,33 +622,26 @@ #endif } else { skb_queue_tail(&cs->rq, skb); - sched_event_D(cs, D_RCVBUFREADY); + sched_d_event(cs, D_RCVBUFREADY); } } } else printk(KERN_WARNING "HFC: D receive out of memory\n"); - sti(); WaitForBusy(cs); cip = HFCD_FIFO | HFCD_F2_INC | HFCD_REC; - cli(); WaitNoBusy(cs); stat = ReadReg(cs, HFCD_DATA, cip); - sti(); WaitForBusy(cs); cip = HFCD_FIFO | HFCD_F2 | HFCD_REC; - cli(); WaitNoBusy(cs); f2 = cs->readisac(cs, cip) & 0xf; } - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - restore_flags(flags); return(1); } static void hfc_fill_dfifo(struct IsdnCardState *cs) { - long flags; int idx, fcnt; int count; u_char cip; @@ -782,8 +651,6 @@ if (cs->tx_skb->len <= 0) return; - save_flags(flags); - cli(); SelFiFo(cs, 4 | HFCD_SEND); cip = HFCD_FIFO | HFCD_F1 | HFCD_SEND; WaitNoBusy(cs); @@ -792,7 +659,6 @@ cip = HFCD_FIFO | HFCD_F2 | HFCD_SEND; cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf; cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND); - sti(); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)", cs->hw.hfcD.f1, cs->hw.hfcD.f2, @@ -803,7 +669,6 @@ if (fcnt > 14) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_Dfifo more as 14 frames"); - restore_flags(flags); return; } count = GetFreeFifoBytes_D(cs); @@ -813,37 +678,29 @@ if (count < cs->tx_skb->len) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfc_fill_Dfifo no fifo mem"); - restore_flags(flags); return; } cip = HFCD_FIFO | HFCD_FIFO_IN | HFCD_SEND; idx = 0; - cli(); WaitForBusy(cs); WaitNoBusy(cs); WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx++]); while (idx < cs->tx_skb->len) { - cli(); if (!(WaitNoBusy(cs))) break; WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx]); - sti(); idx++; } if (idx != cs->tx_skb->len) { - sti(); debugl1(cs, "DFIFO Send BUSY error"); printk(KERN_WARNING "HFC S DFIFO channel BUSY Error\n"); } WaitForBusy(cs); - cli(); WaitNoBusy(cs); ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND); dev_kfree_skb_any(cs->tx_skb); cs->tx_skb = NULL; - sti(); WaitForBusy(cs); - restore_flags(flags); return; } @@ -864,12 +721,10 @@ u_char exval; struct BCState *bcs; int count=15; - long flags; if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFCD irq %x %s", val, - test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? - "locked" : "unlocked"); + debugl1(cs, "HFCD irq %x", val); + val &= cs->hw.hfcD.int_m1; if (val & 0x40) { /* TE state machine irq */ exval = cs->readisac(cs, HFCD_STATES) & 0xf; @@ -877,17 +732,10 @@ debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state, exval); cs->dc.hfcd.ph_state = exval; - sched_event_D(cs, D_L1STATECHANGE); + sched_d_event(cs, D_L1STATECHANGE); val &= ~0x40; } while (val) { - save_flags(flags); - cli(); - if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - cs->hw.hfcD.int_s1 |= val; - restore_flags(flags); - return; - } if (cs->hw.hfcD.int_s1 & 0x18) { exval = val; val = cs->hw.hfcD.int_s1; @@ -912,23 +760,7 @@ if (cs->debug) debugl1(cs, "hfcd spurious 0x01 IRQ"); } else { - if (bcs->tx_skb) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfc_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs,"fill_data %d blocked", bcs->channel); - } else { - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfc_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs,"fill_data %d blocked", bcs->channel); - } else { - hfc_sched_event(bcs, B_XMTBUFREADY); - } - } + xmit_xpr_b(bcs); } } if (val & 0x02) { @@ -936,60 +768,15 @@ if (cs->debug) debugl1(cs, "hfcd spurious 0x02 IRQ"); } else { - if (bcs->tx_skb) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfc_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs,"fill_data %d blocked", bcs->channel); - } else { - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfc_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs,"fill_data %d blocked", bcs->channel); - } else { - hfc_sched_event(bcs, B_XMTBUFREADY); - } - } + xmit_xpr_b(bcs); } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ - 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)) - sched_event_D(cs, D_CLEARBUSY); - if (cs->tx_skb) { - if (cs->tx_skb->len) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfc_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - debugl1(cs, "hfc_fill_dfifo irq blocked"); - } - goto afterXPR; - } else { - dev_kfree_skb_irq(cs->tx_skb); - cs->tx_cnt = 0; - cs->tx_skb = NULL; - } - } - if ((cs->tx_skb = skb_dequeue(&cs->sq))) { - cs->tx_cnt = 0; - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfc_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - debugl1(cs, "hfc_fill_dfifo irq blocked"); - } - } else - sched_event_D(cs, D_XMTBUFREADY); + xmit_xpr_d(cs); } - afterXPR: if (cs->hw.hfcD.int_s1 && count--) { val = cs->hw.hfcD.int_s1; cs->hw.hfcD.int_s1 = 0; @@ -997,7 +784,6 @@ debugl1(cs, "HFCD irq %x loop %d", val, 15-count); } else val = 0; - restore_flags(flags); } } @@ -1009,64 +795,13 @@ 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 - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfc_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "hfc_fill_dfifo blocked"); - - } + xmit_data_req_d(cs, skb); 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 - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfc_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "hfc_fill_dfifo blocked"); + case (PH_PULL |INDICATION): + xmit_pull_ind_d(cs, skb); 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); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_d(st); break; case (HW_RESET | REQUEST): cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */ @@ -1135,7 +870,8 @@ cs->bcs[0].hw.hfc.send = init_send_hfcd(32); if (!cs->bcs[1].hw.hfc.send) cs->bcs[1].hw.hfc.send = init_send_hfcd(32); - cs->BC_Send_Data = &hfc_send_data; + cs->BC_Send_Data = hfc_fill_fifo; + cs->DC_Send_Data = hfc_fill_dfifo; cs->bcs[0].BC_SetStack = setstack_2b; cs->bcs[1].BC_SetStack = setstack_2b; cs->bcs[0].BC_Close = close_2bs0; diff -Nru a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c --- a/drivers/isdn/hisax/hfc_2bs0.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/hfc_2bs0.c Wed Nov 27 14:36:27 2002 @@ -21,18 +21,14 @@ WaitForBusy(struct IsdnCardState *cs) { int to = 130; - long flags; u_char val; - save_flags(flags); - cli(); while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 | (cs->hw.hfc.cip & 3)); udelay(1); to--; } - restore_flags(flags); if (!to) { printk(KERN_WARNING "HiSax: waitforBusy timeout\n"); return (0); @@ -82,26 +78,17 @@ return (val); } -void -hfc_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - static void hfc_clear_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - long flags; int idx, cnt; int rcnt, z1, z2; u_char cip, f1, f2; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_clear_fifo"); - save_flags(flags); - cli(); + cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); @@ -148,7 +135,6 @@ z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel)); z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel)); } - restore_flags(flags); return; } @@ -251,7 +237,6 @@ hfc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - long flags; int idx, fcnt; int count; int z1, z2; @@ -262,8 +247,6 @@ if (bcs->tx_skb->len <= 0) return; - save_flags(flags); - cli(); cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel); if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); @@ -286,7 +269,6 @@ if (fcnt > 30) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo more as 30 frames"); - restore_flags(flags); return; } count = GetFreeFifoBytes(bcs); @@ -306,7 +288,6 @@ if (count < bcs->tx_skb->len) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo no fifo mem"); - restore_flags(flags); return; } cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel); @@ -321,34 +302,28 @@ bcs->tx_cnt -= count; if (PACKET_NOACK == bcs->tx_skb->pkt_type) count = -1; - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; + + xmit_complete_b(bcs); if (bcs->mode != L1_MODE_TRANS) { WaitForBusy(cs); WaitNoBusy(cs); cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel)); } - if (bcs->st->lli.l1writewakeup && (count >= 0)) - bcs->st->lli.l1writewakeup(bcs->st, count); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } - restore_flags(flags); return; } void main_irq_hfc(struct BCState *bcs) { - long flags; struct IsdnCardState *cs = bcs->cs; int z1, z2, rcnt; u_char f1, f2, cip; int receive, transmit, count = 5; struct sk_buff *skb; - save_flags(flags); Begin: - cli(); count--; cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { @@ -381,17 +356,14 @@ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)", bcs->channel, z1, z2, rcnt); - /* sti(); */ if ((skb = hfc_empty_fifo(bcs, rcnt))) { skb_queue_tail(&bcs->rqueue, skb); - hfc_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } } receive = 1; } - restore_flags(flags); udelay(1); - cli(); if (bcs->tx_skb) { transmit = 1; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); @@ -407,10 +379,9 @@ transmit = 0; } else { transmit = 0; - hfc_sched_event(bcs, B_XMTBUFREADY); + sched_b_event(bcs, B_XMTBUFREADY); } } - restore_flags(flags); if ((receive || transmit) && count) goto Begin; return; @@ -474,40 +445,16 @@ hfc_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->cs->BC_Send_Data(st->l1.bcs); - restore_flags(flags); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); - break; - } - save_flags(flags); - cli(); - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->tx_skb = skb; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - restore_flags(flags); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c --- a/drivers/isdn/hisax/hfc_pci.c Wed Nov 27 14:36:29 2002 +++ b/drivers/isdn/hisax/hfc_pci.c Wed Nov 27 14:36:29 2002 @@ -73,21 +73,15 @@ void release_io_hfcpci(struct IsdnCardState *cs) { - unsigned long flags; - printk(KERN_INFO "HiSax: release hfcpci at %p\n", cs->hw.hfcpci.pci_io); - 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_UNINTERRUPTIBLE); schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ - pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */ + pci_disable_device(cs->hw.hfcpci.pdev); del_timer(&cs->hw.hfcpci.timer); iounmap(cs->hw.hfcpci.pci_io); pci_free_consistent(cs->hw.hfcpci.pdev, 32768, cs->hw.hfcpci.fifos, cs->hw.hfcpci.fifos_dma); @@ -100,18 +94,13 @@ static void 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 */ + pci_disable_device(cs->hw.hfcpci.pdev); 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 */ + pci_set_master(cs->hw.hfcpci.pdev); Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ - sti(); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ @@ -170,7 +159,6 @@ 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); } /***************************************************/ @@ -186,27 +174,6 @@ */ } - -/*********************************/ -/* schedule a new D-channel task */ -/*********************************/ -static void -sched_event_D_pci(struct IsdnCardState *cs, int event) -{ - test_and_set_bit(event, &cs->event); - schedule_work(&cs->work); -} - -/*********************************/ -/* schedule a new b_channel task */ -/*********************************/ -static void -hfcpci_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - /************************************************/ /* select a b-channel entry matching and active */ /************************************************/ @@ -285,12 +252,9 @@ u_char *ptr, *ptr1, new_f2; struct sk_buff *skb; struct IsdnCardState *cs = bcs->cs; - unsigned long flags; int total, maxlen, new_z2; z_type *zp; - save_flags(flags); - sti(); if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfcpci_empty_fifo"); zp = &bz->za[bz->f2]; /* point to Z-Regs */ @@ -333,7 +297,6 @@ bz->f2 = new_f2; /* next buffer */ } - restore_flags(flags); return (skb); } @@ -353,10 +316,6 @@ z_type *zp; df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx; - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - debugl1(cs, "rec_dmsg blocked"); - return (1); - } while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) { zp = &df->za[df->f2 & D_FREG_MASK]; rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); @@ -399,11 +358,10 @@ df->za[df->f2 & D_FREG_MASK].z2 = cpu_to_le16((le16_to_cpu(zp->z2) + total) & (D_FIFO_SIZE - 1)); skb_queue_tail(&cs->rq, skb); - sched_event_D_pci(cs, D_RCVBUFREADY); + sched_d_event(cs, D_RCVBUFREADY); } else printk(KERN_WARNING "HFC-PCI: D receive out of memory\n"); } - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); return (1); } @@ -451,10 +409,8 @@ ptr1 = bdata; /* start of buffer */ memcpy(ptr, ptr1, fcnt); /* rest */ } - cli(); skb_queue_tail(&bcs->rqueue, skb); - sti(); - hfcpci_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } *z2r = cpu_to_le16(new_z2); /* new position */ @@ -467,7 +423,6 @@ void main_rec_hfcpci(struct BCState *bcs) { - long flags; struct IsdnCardState *cs = bcs->cs; int rcnt, real_fifo; int receive, count = 5; @@ -476,8 +431,6 @@ u_char *bdata; z_type *zp; - - save_flags(flags); if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) { bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; @@ -489,13 +442,6 @@ } Begin: count--; - cli(); - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - debugl1(cs, "rec_data %d blocked", bcs->channel); - restore_flags(flags); - return; - } - sti(); if (bz->f1 != bz->f2) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)", @@ -510,10 +456,8 @@ debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)", bcs->channel, le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt); if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) { - cli(); skb_queue_tail(&bcs->rqueue, skb); - sti(); - hfcpci_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } rcnt = bz->f1 - bz->f2; if (rcnt < 0) @@ -531,10 +475,9 @@ 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; - restore_flags(flags); return; } @@ -544,7 +487,6 @@ static void hfcpci_fill_dfifo(struct IsdnCardState *cs) { - long flags; int fcnt; int count, new_z1, maxlen; dfifo_type *df; @@ -601,12 +543,9 @@ src += maxlen; /* new position */ memcpy(dst, src, count); } - save_flags(flags); - cli(); df->za[new_f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1); /* for next buffer */ df->za[df->f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1); /* new pos actual buffer */ df->f1 = new_f1; /* next frame */ - restore_flags(flags); dev_kfree_skb_any(cs->tx_skb); cs->tx_skb = NULL; @@ -620,7 +559,6 @@ hfcpci_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - unsigned long flags; int maxlen, fcnt; int count, new_z1; bzfifo_type *bz; @@ -633,9 +571,6 @@ if (bcs->tx_skb->len <= 0) return; - save_flags(flags); - sti(); - if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) { bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b2; @@ -684,12 +619,9 @@ bcs->channel, bcs->tx_skb->len); dev_kfree_skb_any(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) @@ -703,7 +635,6 @@ if (fcnt > (MAX_B_FRAMES - 1)) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_Bfifo more as 14 frames"); - restore_flags(flags); return; } /* now determine free bytes in FIFO buffer */ @@ -719,7 +650,6 @@ if (count < bcs->tx_skb->len) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo no fifo mem"); - restore_flags(flags); return; } count = bcs->tx_skb->len; /* get frame len */ @@ -742,17 +672,11 @@ memcpy(dst, src, count); } bcs->tx_cnt -= bcs->tx_skb->len; - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); + xmit_complete_b(bcs); - cli(); bz->za[new_f1].z1 = cpu_to_le16(new_z1); /* for next buffer */ bz->f1 = new_f1; /* next frame */ - restore_flags(flags); - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); return; } @@ -798,13 +722,10 @@ static int hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { - unsigned long 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_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */ Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* HFC ST G0 */ udelay(10); @@ -818,7 +739,6 @@ cs->hw.hfcpci.nt_mode = 1; cs->hw.hfcpci.nt_timer = 0; cs->stlist->l1.l2l1 = dch_nt_l2l1; - restore_flags(flags); debugl1(cs, "NT mode activated"); return (0); } @@ -826,8 +746,6 @@ (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 */ @@ -850,7 +768,6 @@ 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 */ @@ -860,7 +777,6 @@ static void receive_emsg(struct IsdnCardState *cs) { - long flags; int rcnt; int receive, count = 5; bzfifo_type *bz; @@ -870,18 +786,10 @@ int total, maxlen, new_z2; u_char e_buffer[256]; - save_flags(flags); bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; Begin: count--; - cli(); - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - debugl1(cs, "echo_rec_data blocked"); - restore_flags(flags); - return; - } - sti(); if (bz->f1 != bz->f2) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)", @@ -953,10 +861,8 @@ receive = 0; } else receive = 0; - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; - restore_flags(flags); return; } /* receive_emsg */ @@ -970,7 +876,6 @@ u_char exval; struct BCState *bcs; int count = 15; - long flags; u_char val, stat; if (!cs) { @@ -988,9 +893,7 @@ return; if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFC-PCI irq %x %s", val, - test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? - "locked" : "unlocked"); + debugl1(cs, "HFC-PCI irq %x", val); val &= cs->hw.hfcpci.int_m1; if (val & 0x40) { /* state machine irq */ exval = Read_hfc(cs, HFCPCI_STATES) & 0xf; @@ -998,25 +901,18 @@ debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state, exval); cs->dc.hfcpci.ph_state = exval; - sched_event_D_pci(cs, D_L1STATECHANGE); + sched_d_event(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); + sched_d_event(cs, D_L1STATECHANGE); } val &= ~0x80; Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); } while (val) { - save_flags(flags); - cli(); - if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - cs->hw.hfcpci.int_s1 |= val; - restore_flags(flags); - return; - } if (cs->hw.hfcpci.int_s1 & 0x18) { exval = val; val = cs->hw.hfcpci.int_s1; @@ -1043,23 +939,7 @@ if (cs->debug) debugl1(cs, "hfcpci spurious 0x01 IRQ"); } else { - if (bcs->tx_skb) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcpci_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "fill_data %d blocked", bcs->channel); - } else { - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcpci_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "fill_data %d blocked", bcs->channel); - } else { - hfcpci_sched_event(bcs, B_XMTBUFREADY); - } - } + xmit_xpr_b(bcs); } } if (val & 0x02) { @@ -1067,60 +947,15 @@ if (cs->debug) debugl1(cs, "hfcpci spurious 0x02 IRQ"); } else { - if (bcs->tx_skb) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcpci_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "fill_data %d blocked", bcs->channel); - } else { - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcpci_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "fill_data %d blocked", bcs->channel); - } else { - hfcpci_sched_event(bcs, B_XMTBUFREADY); - } - } + xmit_xpr_b(bcs); } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ - 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)) - sched_event_D_pci(cs, D_CLEARBUSY); - if (cs->tx_skb) { - if (cs->tx_skb->len) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcpci_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - debugl1(cs, "hfcpci_fill_dfifo irq blocked"); - } - goto afterXPR; - } else { - dev_kfree_skb_irq(cs->tx_skb); - cs->tx_cnt = 0; - cs->tx_skb = NULL; - } - } - if ((cs->tx_skb = skb_dequeue(&cs->sq))) { - cs->tx_cnt = 0; - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcpci_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - debugl1(cs, "hfcpci_fill_dfifo irq blocked"); - } - } else - sched_event_D_pci(cs, D_XMTBUFREADY); + xmit_xpr_d(cs); } - afterXPR: if (cs->hw.hfcpci.int_s1 && count--) { val = cs->hw.hfcpci.int_s1; cs->hw.hfcpci.int_s1 = 0; @@ -1128,7 +963,6 @@ debugl1(cs, "HFC-PCI irq %x loop %d", val, 15 - count); } else val = 0; - restore_flags(flags); } } @@ -1148,68 +982,16 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; - unsigned long flags; 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 - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcpci_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "hfcpci_fill_dfifo blocked"); - - } + xmit_data_req_d(cs, skb); 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 - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcpci_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "hfcpci_fill_dfifo blocked"); + xmit_pull_ind_d(cs, skb); 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); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_d(st); break; case (HW_RESET | REQUEST): Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3); /* HFC ST 3 */ @@ -1236,21 +1018,15 @@ 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: @@ -1258,11 +1034,8 @@ 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; default: if (cs->debug & L1_DEB_WARN) @@ -1280,21 +1053,6 @@ st->l1.l1hw = HFCPCI_l1hw; } -/**************************************/ -/* send B-channel data if not blocked */ -/**************************************/ -static void -hfcpci_send_data(struct BCState *bcs) -{ - struct IsdnCardState *cs = bcs->cs; - - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcpci_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "send_data %d blocked", bcs->channel); -} - /***************************************************************/ /* activate/deactivate hardware for selected channels and mode */ /***************************************************************/ @@ -1302,7 +1060,6 @@ mode_hfcpci(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - unsigned long flags; int fifo2; if (cs->debug & L1_DEB_HSCX) @@ -1311,8 +1068,6 @@ bcs->mode = mode; bcs->channel = bc; 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; @@ -1417,7 +1172,6 @@ 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); } /******************************/ @@ -1427,40 +1181,16 @@ hfcpci_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->cs->BC_Send_Data(st->l1.bcs); - restore_flags(flags); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); - break; - } - save_flags(flags); - cli(); -/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - */ st->l1.bcs->tx_skb = skb; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - restore_flags(flags); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); @@ -1538,7 +1268,6 @@ hfcpci_bh(void *data) { struct IsdnCardState *cs = data; - unsigned long flags; /* struct PStack *stptr; */ if (!cs) @@ -1566,8 +1295,6 @@ } 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; @@ -1589,17 +1316,13 @@ 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; @@ -1624,7 +1347,8 @@ cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); INIT_WORK(&cs->work, hfcpci_bh, cs); - cs->BC_Send_Data = &hfcpci_send_data; + cs->BC_Send_Data = hfcpci_fill_fifo; + cs->DC_Send_Data = hfcpci_fill_dfifo; cs->bcs[0].BC_SetStack = setstack_2b; cs->bcs[1].BC_SetStack = setstack_2b; cs->bcs[0].BC_Close = close_hfcpci; @@ -1641,8 +1365,6 @@ static int hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - long flags; - if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFCPCI: card_msg %x", mt); switch (mt) { @@ -1654,8 +1376,6 @@ return (0); case CARD_INIT: inithfcpci(cs); - save_flags(flags); - sti(); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ /* now switch timer interrupt off */ @@ -1663,7 +1383,6 @@ Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); /* reinit mode reg */ Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); - restore_flags(flags); return (0); case CARD_TEST: return (0); @@ -1712,8 +1431,6 @@ if (tmp_hfcpci) { 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; cs->hw.hfcpci.pdev = tmp_hfcpci; if (!cs->irq) { @@ -1731,16 +1448,13 @@ return (0); } /* Allocate memory for FIFOS */ - /* Because the HFC-PCI needs a 32K physical alignment, we */ - /* need to allocate the double mem and align the address */ cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma); if (!cs->hw.hfcpci.fifos) { printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); return 0; } - pcibios_write_config_dword(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, 0x80, - (u_int)cs->hw.hfcpci.fifos_dma); + pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80, + (u_int)cs->hw.hfcpci.fifos_dma); 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", @@ -1749,7 +1463,6 @@ (u_int) cs->hw.hfcpci.fifos_dma, cs->irq, HZ); printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID)); - 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_m1 = 0; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c --- a/drivers/isdn/hisax/hfc_sx.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/hfc_sx.c Wed Nov 27 14:36:27 2002 @@ -61,25 +61,19 @@ /******************************/ static inline void Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val) -{ unsigned long flags; +{ - save_flags(flags); - cli(); byteout(cs->hw.hfcsx.base+1, regnum); byteout(cs->hw.hfcsx.base, val); - restore_flags(flags); } static inline u_char Read_hfc(struct IsdnCardState *cs, u_char regnum) -{ unsigned long flags; +{ u_char ret; - save_flags(flags); - cli(); byteout(cs->hw.hfcsx.base+1, regnum); ret = bytein(cs->hw.hfcsx.base); - restore_flags(flags); return(ret); } @@ -89,20 +83,16 @@ /**************************************************/ static void fifo_select(struct IsdnCardState *cs, u_char fifo) -{ unsigned long flags; - +{ if (fifo == cs->hw.hfcsx.last_fifo) return; /* still valid */ - save_flags(flags); - cli(); byteout(cs->hw.hfcsx.base+1, HFCSX_FIF_SEL); byteout(cs->hw.hfcsx.base, fifo); while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */ udelay(4); byteout(cs->hw.hfcsx.base, fifo); while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */ - restore_flags(flags); } /******************************************/ @@ -111,16 +101,12 @@ /******************************************/ static void reset_fifo(struct IsdnCardState *cs, u_char fifo) -{ unsigned long flags; - - save_flags(flags); - cli(); +{ fifo_select(cs, fifo); /* first select the fifo */ byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM); byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.cirm | 0x80); /* reset cmd */ udelay(1); while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */ - restore_flags(flags); } @@ -325,15 +311,9 @@ void release_io_hfcsx(struct IsdnCardState *cs) { - unsigned long flags; - - save_flags(flags); - cli(); cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); - restore_flags(flags); Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET); /* Reset On */ - sti(); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */ @@ -370,17 +350,12 @@ static void reset_hfcsx(struct IsdnCardState *cs) { - long flags; - - save_flags(flags); - cli(); cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); printk(KERN_INFO "HFC_SX: resetting card\n"); while (1) { Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */ - sti(); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */ @@ -440,7 +415,6 @@ cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE; Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); if (Read_hfc(cs, HFCSX_INT_S2)); - restore_flags(flags); } /***************************************************/ @@ -457,26 +431,6 @@ } -/*********************************/ -/* schedule a new D-channel task */ -/*********************************/ -static void -sched_event_D_sx(struct IsdnCardState *cs, int event) -{ - test_and_set_bit(event, &cs->event); - schedule_work(&cs->work); -} - -/*********************************/ -/* schedule a new b_channel task */ -/*********************************/ -static void -hfcsx_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - /************************************************/ /* select a b-channel entry matching and active */ /************************************************/ @@ -495,27 +449,20 @@ /*******************************/ /* D-channel receive procedure */ /*******************************/ -static -int +static int receive_dmsg(struct IsdnCardState *cs) { struct sk_buff *skb; int count = 5; - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - debugl1(cs, "rec_dmsg blocked"); - return (1); - } - do { skb = read_fifo(cs, HFCSX_SEL_D_RX, 0); if (skb) { skb_queue_tail(&cs->rq, skb); - sched_event_D_sx(cs, D_RCVBUFREADY); + sched_d_event(cs, D_RCVBUFREADY); } } while (--count && skb); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); return (1); } @@ -525,38 +472,24 @@ void main_rec_hfcsx(struct BCState *bcs) { - long flags; struct IsdnCardState *cs = bcs->cs; int count = 5; struct sk_buff *skb; - save_flags(flags); - Begin: count--; - cli(); - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - debugl1(cs, "rec_data %d blocked", bcs->channel); - restore_flags(flags); - return; - } - sti(); skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX, (bcs->mode == L1_MODE_TRANS) ? HFCSX_BTRANS_THRESHOLD : 0); if (skb) { - cli(); skb_queue_tail(&bcs->rqueue, skb); - sti(); - hfcsx_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && skb) goto Begin; - restore_flags(flags); return; } @@ -575,7 +508,6 @@ dev_kfree_skb_any(cs->tx_skb); cs->tx_skb = NULL; } - return; } /**************************/ @@ -585,34 +517,22 @@ hfcsx_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - unsigned long flags; if (!bcs->tx_skb) return; if (bcs->tx_skb->len <= 0) return; - save_flags(flags); - sti(); - if (write_fifo(cs, bcs->tx_skb, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX, (bcs->mode == L1_MODE_TRANS) ? HFCSX_BTRANS_THRESHOLD : 0)) { - bcs->tx_cnt -= bcs->tx_skb->len; - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_cnt -= bcs->tx_skb->len; + xmit_complete_b(bcs); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } - - cli(); - restore_flags(flags); - return; } /**********************************************/ @@ -656,13 +576,10 @@ static int hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { - unsigned long flags; int i = *(unsigned int *) ic->parm.num; if ((ic->arg == 98) && (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) { - save_flags(flags); - cli(); Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0); /* HFC ST G0 */ udelay(10); cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT; @@ -675,7 +592,6 @@ cs->hw.hfcsx.nt_mode = 1; cs->hw.hfcsx.nt_timer = 0; cs->stlist->l1.l2l1 = dch_nt_l2l1; - restore_flags(flags); debugl1(cs, "NT mode activated"); return (0); } @@ -683,8 +599,6 @@ (cs->hw.hfcsx.nt_mode) || (ic->arg != 12)) return (-EINVAL); - save_flags(flags); - cli(); if (i) { cs->logecho = 1; cs->hw.hfcsx.trm |= 0x20; /* enable echo chan */ @@ -705,7 +619,6 @@ Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm); Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - restore_flags(flags); return (0); } /* hfcsx_auxcmd */ @@ -715,21 +628,10 @@ static void receive_emsg(struct IsdnCardState *cs) { - unsigned long flags; int count = 5; u_char *ptr; struct sk_buff *skb; - - save_flags(flags); - cli(); - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - debugl1(cs, "echo_rec_data blocked"); - restore_flags(flags); - return; - } - sti(); - do { skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0); if (skb) { @@ -752,10 +654,6 @@ dev_kfree_skb_any(skb); } } while (--count && skb); - - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - restore_flags(flags); - return; } /* receive_emsg */ @@ -769,7 +667,6 @@ u_char exval; struct BCState *bcs; int count = 15; - long flags; u_char val, stat; if (!cs) { @@ -787,9 +684,7 @@ return; if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFC-SX irq %x %s", val, - test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? - "locked" : "unlocked"); + debugl1(cs, "HFC-SX irq %x", val); val &= cs->hw.hfcsx.int_m1; if (val & 0x40) { /* state machine irq */ exval = Read_hfc(cs, HFCSX_STATES) & 0xf; @@ -797,25 +692,18 @@ debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state, exval); cs->dc.hfcsx.ph_state = exval; - sched_event_D_sx(cs, D_L1STATECHANGE); + sched_d_event(cs, D_L1STATECHANGE); val &= ~0x40; } if (val & 0x80) { /* timer irq */ if (cs->hw.hfcsx.nt_mode) { if ((--cs->hw.hfcsx.nt_timer) < 0) - sched_event_D_sx(cs, D_L1STATECHANGE); + sched_d_event(cs, D_L1STATECHANGE); } val &= ~0x80; Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER); } while (val) { - save_flags(flags); - cli(); - if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - cs->hw.hfcsx.int_s1 |= val; - restore_flags(flags); - return; - } if (cs->hw.hfcsx.int_s1 & 0x18) { exval = val; val = cs->hw.hfcsx.int_s1; @@ -842,23 +730,7 @@ if (cs->debug) debugl1(cs, "hfcsx spurious 0x01 IRQ"); } else { - if (bcs->tx_skb) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcsx_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "fill_data %d blocked", bcs->channel); - } else { - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcsx_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "fill_data %d blocked", bcs->channel); - } else { - hfcsx_sched_event(bcs, B_XMTBUFREADY); - } - } + xmit_xpr_b(bcs); } } if (val & 0x02) { @@ -866,60 +738,15 @@ if (cs->debug) debugl1(cs, "hfcsx spurious 0x02 IRQ"); } else { - if (bcs->tx_skb) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcsx_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "fill_data %d blocked", bcs->channel); - } else { - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcsx_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "fill_data %d blocked", bcs->channel); - } else { - hfcsx_sched_event(bcs, B_XMTBUFREADY); - } - } + xmit_xpr_b(bcs); } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ - 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)) - sched_event_D_sx(cs, D_CLEARBUSY); - if (cs->tx_skb) { - if (cs->tx_skb->len) { - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcsx_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - debugl1(cs, "hfcsx_fill_dfifo irq blocked"); - } - goto afterXPR; - } else { - dev_kfree_skb_irq(cs->tx_skb); - cs->tx_cnt = 0; - cs->tx_skb = NULL; - } - } - if ((cs->tx_skb = skb_dequeue(&cs->sq))) { - cs->tx_cnt = 0; - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcsx_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - debugl1(cs, "hfcsx_fill_dfifo irq blocked"); - } - } else - sched_event_D_sx(cs, D_XMTBUFREADY); + xmit_xpr_d(cs); } - afterXPR: if (cs->hw.hfcsx.int_s1 && count--) { val = cs->hw.hfcsx.int_s1; cs->hw.hfcsx.int_s1 = 0; @@ -927,7 +754,6 @@ debugl1(cs, "HFC-SX irq %x loop %d", val, 15 - count); } else val = 0; - restore_flags(flags); } } @@ -947,68 +773,16 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; - unsigned long flags; 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 - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcsx_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "hfcsx_fill_dfifo blocked"); - - } + xmit_data_req_d(cs, skb); 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 - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcsx_fill_dfifo(cs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "hfcsx_fill_dfifo blocked"); + case (PH_PULL |INDICATION): + xmit_pull_ind_d(cs, skb); 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); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_d(st); break; case (HW_RESET | REQUEST): Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3); /* HFC ST 3 */ @@ -1035,21 +809,15 @@ case (1): Write_hfc(cs, HFCSX_B1_SSL, 0x80); /* tx slot */ Write_hfc(cs, HFCSX_B1_RSL, 0x80); /* rx slot */ - save_flags(flags); - cli(); cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1; Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); - restore_flags(flags); break; case (2): Write_hfc(cs, HFCSX_B2_SSL, 0x81); /* tx slot */ Write_hfc(cs, HFCSX_B2_RSL, 0x81); /* rx slot */ - save_flags(flags); - cli(); cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08; Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); - restore_flags(flags); break; default: @@ -1057,11 +825,8 @@ debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg); return; } - save_flags(flags); - cli(); cs->hw.hfcsx.trm |= 0x80; /* enable IOM-loop */ Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm); - restore_flags(flags); break; default: if (cs->debug & L1_DEB_WARN) @@ -1079,21 +844,6 @@ st->l1.l1hw = HFCSX_l1hw; } -/**************************************/ -/* send B-channel data if not blocked */ -/**************************************/ -static void -hfcsx_send_data(struct BCState *bcs) -{ - struct IsdnCardState *cs = bcs->cs; - - if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - hfcsx_fill_fifo(bcs); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - debugl1(cs, "send_data %d blocked", bcs->channel); -} - /***************************************************************/ /* activate/deactivate hardware for selected channels and mode */ /***************************************************************/ @@ -1101,7 +851,6 @@ mode_hfcsx(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - unsigned long flags; int fifo2; if (cs->debug & L1_DEB_HSCX) @@ -1110,8 +859,6 @@ bcs->mode = mode; bcs->channel = bc; fifo2 = bc; - save_flags(flags); - cli(); if (cs->chanlimit > 1) { cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */ cs->hw.hfcsx.sctrl_e &= ~0x80; @@ -1205,7 +952,6 @@ reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX); reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX); } - restore_flags(flags); } /******************************/ @@ -1215,40 +961,16 @@ hfcsx_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->cs->BC_Send_Data(st->l1.bcs); - restore_flags(flags); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); - break; - } - save_flags(flags); - cli(); -/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - */ st->l1.bcs->tx_skb = skb; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - restore_flags(flags); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); @@ -1326,11 +1048,7 @@ hfcsx_bh(void *data) { struct IsdnCardState *cs = data; - unsigned long flags; -/* struct PStack *stptr; - */ - if (!cs) - return; + if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { if (!cs->hw.hfcsx.nt_mode) switch (cs->dc.hfcsx.ph_state) { @@ -1354,8 +1072,6 @@ } else { switch (cs->dc.hfcsx.ph_state) { case (2): - save_flags(flags); - cli(); if (cs->hw.hfcsx.nt_timer < 0) { cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; @@ -1377,17 +1093,13 @@ cs->hw.hfcsx.nt_timer = NT_T1_COUNT; Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3); /* allow G2 -> G3 transition */ } - restore_flags(flags); break; case (1): case (3): case (4): - save_flags(flags); - cli(); cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - restore_flags(flags); break; default: break; @@ -1412,7 +1124,8 @@ cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); INIT_WORK(&cs->work, hfcsx_bh, cs); - cs->BC_Send_Data = &hfcsx_send_data; + cs->BC_Send_Data = hfcsx_fill_fifo; + cs->DC_Send_Data = hfcsx_fill_dfifo; cs->bcs[0].BC_SetStack = setstack_2b; cs->bcs[1].BC_SetStack = setstack_2b; cs->bcs[0].BC_Close = close_hfcsx; @@ -1429,8 +1142,6 @@ static int hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - long flags; - if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFCSX: card_msg %x", mt); switch (mt) { @@ -1442,8 +1153,6 @@ return (0); case CARD_INIT: inithfcsx(cs); - save_flags(flags); - sti(); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ /* now switch timer interrupt off */ @@ -1451,7 +1160,6 @@ Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); /* reinit mode reg */ Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); - restore_flags(flags); return (0); case CARD_TEST: return (0); @@ -1476,7 +1184,6 @@ { struct IsdnCardState *cs = card->cs; char tmp[64]; - unsigned long flags; strcpy(tmp, hfcsx_revision); printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp)); @@ -1560,16 +1267,12 @@ release_region(cs->hw.hfcsx.base, 2); return(0); } - save_flags(flags); - cli(); if (!(cs->hw.hfcsx.extra = (void *) kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) { - restore_flags(flags); release_region(cs->hw.hfcsx.base, 2); printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); return(0); } - restore_flags(flags); printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n", diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h --- a/drivers/isdn/hisax/hisax.h Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/hisax.h Wed Nov 27 14:36:31 2002 @@ -278,8 +278,6 @@ struct LLInterface { void (*l3l4) (struct PStack *, int, void *); void *userdata; - void (*l1writewakeup) (struct PStack *, int); - void (*l2writewakeup) (struct PStack *, int); }; @@ -353,7 +351,6 @@ struct hscx_hw { int hscx; int rcvidx; - int count; /* Current skb sent count */ u_char *rcvbuf; /* B-Channel receive Buffer */ u_char tsaxr0; u_char tsaxr1; @@ -362,7 +359,6 @@ struct w6692B_hw { int bchan; int rcvidx; - int count; /* Current skb sent count */ u_char *rcvbuf; /* B-Channel receive Buffer */ }; @@ -378,7 +374,6 @@ struct isar_hw { int dpath; int rcvidx; - int txcnt; int mml; u_char state; u_char cmd; @@ -413,7 +408,6 @@ } ctrl; u_int stat; int rcvidx; - int count; /* Current skb sent count */ u_char *rcvbuf; /* B-Channel receive Buffer */ }; @@ -489,8 +483,9 @@ struct IsdnCardState *cs; int tx_cnt; /* B-Channel transmit counter */ struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ - struct sk_buff_head rqueue; /* B-Channel receive Queue */ - struct sk_buff_head squeue; /* B-Channel send Queue */ + struct sk_buff_head rqueue; /* B-Channel receive queue */ + struct sk_buff_head squeue; /* B-Channel send queue */ + struct sk_buff_head cmpl_queue; /* B-Channel send complete queue */ struct PStack *st; u_char *blog; u_char *conmsg; @@ -505,6 +500,7 @@ int err_rdo; int err_inv; #endif + int count; union { struct hscx_hw hscx; struct hdlc_hw hdlc; @@ -685,8 +681,6 @@ unsigned char bswapped; 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 */ void *fifos; /* FIFO memory */ dma_addr_t fifos_dma; @@ -872,7 +866,6 @@ #define FLG_TWO_DCHAN 4 #define FLG_L1_DBUSY 5 #define FLG_DBUSY_TIMER 6 -#define FLG_LOCK_ATOMIC 7 #define FLG_ARCOFI_TIMER 8 #define FLG_ARCOFI_ERROR 9 #define FLG_HW_L1_UINT 10 @@ -881,6 +874,7 @@ struct IsdnCardState { unsigned char typ; unsigned char subtyp; + spinlock_t lock; int protocol; unsigned int irq; unsigned long irq_flags; @@ -930,6 +924,7 @@ void (*BC_Send_Data) (struct BCState *); int (*cardmsg) (struct IsdnCardState *, int, void *); void (*setstack_d) (struct PStack *, struct IsdnCardState *); + void (*DC_Send_Data) (struct IsdnCardState *); void (*DC_Close) (struct IsdnCardState *); void (*irq_func) (int, void *, struct pt_regs *); int (*auxcmd) (struct IsdnCardState *, isdn_ctrl *); @@ -1408,4 +1403,3 @@ { st->l3.l4l3(st, pr, arg); } - diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c --- a/drivers/isdn/hisax/hisax_fcpcipnp.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c Wed Nov 27 14:36:31 2002 @@ -528,8 +528,7 @@ } bcs->tx_cnt = 0; bcs->tx_skb = NULL; - B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize); - dev_kfree_skb_irq(skb); + B_L1L2(bcs, PH_DATA | CONFIRM, skb); } static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat) diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.c b/drivers/isdn/hisax/hisax_hfcpci.c --- a/drivers/isdn/hisax/hisax_hfcpci.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/hisax_hfcpci.c Wed Nov 27 14:36:28 2002 @@ -1294,8 +1294,7 @@ } bcs->tx_skb = NULL; - B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize); - dev_kfree_skb_irq(skb); + B_L1L2(bcs, PH_DATA | CONFIRM, skb); } // ---------------------------------------------------------------------- diff -Nru a/drivers/isdn/hisax/hisax_hscx.c b/drivers/isdn/hisax/hisax_hscx.c --- a/drivers/isdn/hisax/hisax_hscx.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/hisax_hscx.c Wed Nov 27 14:36:28 2002 @@ -226,8 +226,7 @@ } hscx->tx_cnt = 0; hscx->tx_skb = NULL; - B_L1L2(hscx, PH_DATA | CONFIRM, (void *) skb->truesize); - dev_kfree_skb_irq(skb); + B_L1L2(hscx, PH_DATA | CONFIRM, skb); } static inline void hscx_exi_interrupt(struct hscx *hscx) diff -Nru a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c --- a/drivers/isdn/hisax/hscx.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/hscx.c Wed Nov 27 14:36:27 2002 @@ -92,49 +92,19 @@ } void -hscx_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - -void hscx_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.hscx.count = 0; - restore_flags(flags); - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "hscx_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.hscx.count = 0; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); @@ -168,6 +138,7 @@ } skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); + skb_queue_purge(&bcs->cmpl_queue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; @@ -196,6 +167,7 @@ } skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); + skb_queue_head_init(&bcs->cmpl_queue); } bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); @@ -220,10 +192,21 @@ } void __init -clear_pending_hscx_ints(struct IsdnCardState *cs) +inithscx(struct IsdnCardState *cs) { int val, eval; + cs->bcs[0].BC_SetStack = setstack_hscx; + cs->bcs[1].BC_SetStack = setstack_hscx; + cs->bcs[0].BC_Close = close_hscxstate; + cs->bcs[1].BC_Close = close_hscxstate; + cs->bcs[0].hw.hscx.hscx = 0; + cs->bcs[1].hw.hscx.hscx = 1; + cs->bcs[0].hw.hscx.tsaxr0 = 0x2f; + cs->bcs[0].hw.hscx.tsaxr1 = 3; + cs->bcs[1].hw.hscx.tsaxr0 = 0x2f; + cs->bcs[1].hw.hscx.tsaxr1 = 3; + val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA); debugl1(cs, "HSCX B ISTA %x", val); if (val & 0x01) { @@ -243,40 +226,18 @@ /* disable all IRQ */ cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF); cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF); -} -void __init -inithscx(struct IsdnCardState *cs) -{ - cs->bcs[0].BC_SetStack = setstack_hscx; - cs->bcs[1].BC_SetStack = setstack_hscx; - cs->bcs[0].BC_Close = close_hscxstate; - cs->bcs[1].BC_Close = close_hscxstate; - cs->bcs[0].hw.hscx.hscx = 0; - cs->bcs[1].hw.hscx.hscx = 1; - cs->bcs[0].hw.hscx.tsaxr0 = 0x2f; - cs->bcs[0].hw.hscx.tsaxr1 = 3; - cs->bcs[1].hw.hscx.tsaxr0 = 0x2f; - cs->bcs[1].hw.hscx.tsaxr1 = 3; modehscx(cs->bcs, 0, 0); modehscx(cs->bcs + 1, 0, 0); + + /* Reenable all IRQ */ + cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0); + cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0); } void __init -inithscxisac(struct IsdnCardState *cs, int part) +inithscxisac(struct IsdnCardState *cs) { - if (part & 1) { - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); - } - if (part & 2) { - /* Reenable all IRQ */ - cs->writeisac(cs, ISAC_MASK, 0); - cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0); - cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0); - /* RESET Receiver and Transmitter */ - cs->writeisac(cs, ISAC_CMDR, 0x41); - } + initisac(cs); + inithscx(cs); } diff -Nru a/drivers/isdn/hisax/hscx.h b/drivers/isdn/hisax/hscx.h --- a/drivers/isdn/hisax/hscx.h Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/hscx.h Wed Nov 27 14:36:31 2002 @@ -35,8 +35,5 @@ #define HSCX_MASK 0x20 extern int HscxVersion(struct IsdnCardState *cs, char *s); -extern void hscx_sched_event(struct BCState *bcs, int event); extern void modehscx(struct BCState *bcs, int mode, int bc); -extern void clear_pending_hscx_ints(struct IsdnCardState *cs); -extern void inithscx(struct IsdnCardState *cs); -extern void inithscxisac(struct IsdnCardState *cs, int part); +extern void inithscxisac(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c --- a/drivers/isdn/hisax/hscx_irq.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/hisax/hscx_irq.c Wed Nov 27 14:36:32 2002 @@ -43,23 +43,16 @@ static inline void WriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data) { - long flags; - - save_flags(flags); - cli(); waitforCEC(cs, hscx); WRITEHSCX(cs, hscx, HSCX_CMDR, data); - restore_flags(flags); } - static void hscx_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, "hscx_empty_fifo"); @@ -73,11 +66,8 @@ } ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; bcs->hw.hscx.rcvidx += count; - save_flags(flags); - cli(); READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); - restore_flags(flags); if (cs->debug & L1_DEB_HSCX_FIFO) { char *t = bcs->blog; @@ -95,8 +85,6 @@ int more, count; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; u_char *ptr; - long flags; - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hscx_fill_fifo"); @@ -114,15 +102,12 @@ count = bcs->tx_skb->len; waitforXFW(cs, bcs->hw.hscx.hscx); - save_flags(flags); - cli(); ptr = bcs->tx_skb->data; skb_pull(bcs->tx_skb, count); bcs->tx_cnt -= count; - bcs->hw.hscx.count += count; + bcs->count += count; WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); - restore_flags(flags); if (cs->debug & L1_DEB_HSCX_FIFO) { char *t = bcs->blog; @@ -189,7 +174,7 @@ } } bcs->hw.hscx.rcvidx = 0; - hscx_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } if (val & 0x40) { /* RPF */ hscx_empty_fifo(bcs, fifo_size); @@ -202,34 +187,20 @@ skb_queue_tail(&bcs->rqueue, skb); } bcs->hw.hscx.rcvidx = 0; - hscx_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } } - if (val & 0x10) { /* XPR */ - if (bcs->tx_skb) { - if (bcs->tx_skb->len) { - hscx_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.hscx.count); - dev_kfree_skb_irq(bcs->tx_skb); - bcs->hw.hscx.count = 0; - bcs->tx_skb = NULL; - } - } - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->hw.hscx.count = 0; - test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); - hscx_fill_fifo(bcs); - } else { - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - hscx_sched_event(bcs, B_XMTBUFREADY); - } + if (val & 0x10) { + xmit_xpr_b(bcs); } } +static void +reset_xmit(struct BCState *bcs) +{ + WriteHSCXCMDR(bcs->cs, bcs->hw.hscx.hscx, 0x01); +} + static inline void hscx_int_main(struct IsdnCardState *cs, u_char val) { @@ -237,30 +208,15 @@ u_char exval; struct BCState *bcs; + spin_lock(&cs->lock); if (val & 0x01) { bcs = cs->bcs + 1; exval = READHSCX(cs, 1, HSCX_EXIR); - if (exval & 0x40) { - 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. - */ - if (bcs->tx_skb) { - skb_push(bcs->tx_skb, bcs->hw.hscx.count); - bcs->tx_cnt += bcs->hw.hscx.count; - bcs->hw.hscx.count = 0; - } - WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "HSCX B EXIR %x Lost TX", exval); - } - } else if (cs->debug & L1_DEB_HSCX) + if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HSCX B EXIR %x", exval); + if (exval & 0x40) { + xmit_xdu_b(bcs, reset_xmit); + } } if (val & 0xf8) { if (cs->debug & L1_DEB_HSCX) @@ -270,27 +226,11 @@ if (val & 0x02) { bcs = cs->bcs; exval = READHSCX(cs, 0, HSCX_EXIR); - if (exval & 0x40) { - if (bcs->mode == L1_MODE_TRANS) - hscx_fill_fifo(bcs); - else { - /* 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; - bcs->hw.hscx.count = 0; - } - WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "HSCX A EXIR %x Lost TX", exval); - } - } else if (cs->debug & L1_DEB_HSCX) + if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HSCX A EXIR %x", exval); + if (exval & 0x40) { + xmit_xdu_b(bcs, reset_xmit); + } } if (val & 0x04) { exval = READHSCX(cs, 0, HSCX_ISTA); @@ -298,4 +238,5 @@ debugl1(cs, "HSCX A interrupt %x", exval); hscx_interrupt(cs, exval, 0); } + spin_unlock(&cs->lock); } diff -Nru a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c --- a/drivers/isdn/hisax/icc.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/icc.c Wed Nov 27 14:36:27 2002 @@ -146,29 +146,15 @@ icc_fill_fifo(struct IsdnCardState *cs) { int count, more; - u_char *ptr; + unsigned char *p; unsigned long flags; - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, "icc_fill_fifo"); - - if (!cs->tx_skb) - return; - - count = cs->tx_skb->len; - if (count <= 0) + p = xmit_fill_fifo_d(cs, 32, &count, &more); + if (!p) return; - more = 0; - if (count > 32) { - more = !0; - count = 32; - } spin_lock_irqsave(&icc_lock, flags); - ptr = cs->tx_skb->data; - skb_pull(cs->tx_skb, count); - cs->tx_cnt += count; - cs->writeisacfifo(cs, ptr, count); + cs->writeisacfifo(cs, p, count); cs->writeisac(cs, ICC_CMDR, more ? 0x8 : 0xa); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { debugl1(cs, "icc_fill_fifo dbusytimer running"); @@ -178,20 +164,6 @@ cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); spin_unlock_irqrestore(&icc_lock, flags); - if (cs->debug & L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "icc_fill_fifo cnt %d", count); - QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); - } -} - -void -icc_sched_event(struct IsdnCardState *cs, int event) -{ - test_and_set_bit(event, &cs->event); - schedule_work(&cs->work); } void @@ -240,7 +212,7 @@ spin_unlock_irqrestore(&icc_lock, flags); } cs->rcvidx = 0; - icc_sched_event(cs, D_RCVBUFREADY); + sched_d_event(cs, D_RCVBUFREADY); } if (val & 0x40) { /* RPF */ icc_empty_fifo(cs, 32); @@ -251,27 +223,8 @@ debugl1(cs, "ICC RSC interrupt"); } if (val & 0x10) { /* XPR */ - 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)) - icc_sched_event(cs, D_CLEARBUSY); - if (cs->tx_skb) { - if (cs->tx_skb->len) { - icc_fill_fifo(cs); - goto afterXPR; - } else { - dev_kfree_skb_irq(cs->tx_skb); - cs->tx_cnt = 0; - cs->tx_skb = NULL; - } - } - if ((cs->tx_skb = skb_dequeue(&cs->sq))) { - cs->tx_cnt = 0; - icc_fill_fifo(cs); - } else - icc_sched_event(cs, D_XMTBUFREADY); + xmit_xpr_d(cs); } - afterXPR: if (val & 0x04) { /* CISQ */ exval = cs->readisac(cs, ICC_CIR0); if (cs->debug & L1_DEB_ISAC) @@ -280,7 +233,7 @@ cs->dc.icc.ph_state = (exval >> 2) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state); - icc_sched_event(cs, D_L1STATECHANGE); + sched_d_event(cs, D_L1STATECHANGE); } if (exval & 1) { exval = cs->readisac(cs, ICC_CIR1); @@ -302,23 +255,7 @@ printk(KERN_WARNING "HiSax: ICC XMR\n"); } if (exval & 0x40) { /* XDU */ - debugl1(cs, "ICC XDU"); - printk(KERN_WARNING "HiSax: ICC 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)) - icc_sched_event(cs, D_CLEARBUSY); - if (cs->tx_skb) { /* Restart frame */ - skb_push(cs->tx_skb, cs->tx_cnt); - cs->tx_cnt = 0; - icc_fill_fifo(cs); - } else { - printk(KERN_WARNING "HiSax: ICC XDU no skb\n"); - debugl1(cs, "ICC XDU no skb"); - } + xmit_xdu_d(cs, NULL); } if (exval & 0x04) { /* MOS */ v1 = cs->readisac(cs, ICC_MOSR); @@ -388,14 +325,14 @@ cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0x0a; cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); - icc_sched_event(cs, D_RX_MON0); + sched_d_event(cs, D_RX_MON0); } if (v1 & 0x40) { cs->dc.icc.mocr &= 0x0f; cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0xa0; cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); - icc_sched_event(cs, D_RX_MON1); + sched_d_event(cs, D_RX_MON1); } if (v1 & 0x02) { if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc && @@ -407,11 +344,11 @@ cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) - icc_sched_event(cs, D_TX_MON0); + sched_d_event(cs, D_TX_MON0); goto AfterMOX0; } if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { - icc_sched_event(cs, D_TX_MON0); + sched_d_event(cs, D_TX_MON0); goto AfterMOX0; } cs->writeisac(cs, ICC_MOX0, @@ -430,11 +367,11 @@ cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) - icc_sched_event(cs, D_TX_MON1); + sched_d_event(cs, D_TX_MON1); goto AfterMOX1; } if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { - icc_sched_event(cs, D_TX_MON1); + sched_d_event(cs, D_TX_MON1); goto AfterMOX1; } cs->writeisac(cs, ICC_MOX1, @@ -457,55 +394,13 @@ 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 - icc_fill_fifo(cs); - } + xmit_data_req_d(cs, skb); 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 - icc_fill_fifo(cs); + xmit_pull_ind_d(cs, skb); 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); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_d(st); break; case (HW_RESET | REQUEST): if ((cs->dc.icc.ph_state == ICC_IND_EI1) || @@ -557,7 +452,7 @@ 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)) - icc_sched_event(cs, D_CLEARBUSY); + sched_d_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -623,15 +518,37 @@ void __init initicc(struct IsdnCardState *cs) { + int val, eval; + INIT_WORK(&cs->work, icc_bh, cs); cs->setstack_d = setstack_icc; + cs->DC_Send_Data = icc_fill_fifo; cs->DC_Close = DC_Close_icc; cs->dc.icc.mon_tx = NULL; cs->dc.icc.mon_rx = NULL; cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); - cs->writeisac(cs, ICC_MASK, 0xff); + + val = cs->readisac(cs, ICC_STAR); + debugl1(cs, "ICC STAR %x", val); + val = cs->readisac(cs, ICC_MODE); + debugl1(cs, "ICC MODE %x", val); + val = cs->readisac(cs, ICC_ADF2); + debugl1(cs, "ICC ADF2 %x", val); + val = cs->readisac(cs, ICC_ISTA); + debugl1(cs, "ICC ISTA %x", val); + if (val & 0x01) { + eval = cs->readisac(cs, ICC_EXIR); + debugl1(cs, "ICC EXIR %x", eval); + } + val = cs->readisac(cs, ICC_CIR0); + debugl1(cs, "ICC CIR0 %x", val); + cs->dc.icc.ph_state = (val >> 2) & 0xf; + sched_d_event(cs, D_L1STATECHANGE); + /* Disable all IRQ */ + cs->writeisac(cs, ICC_MASK, 0xFF); + cs->dc.icc.mocr = 0xaa; if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ @@ -655,29 +572,4 @@ ph_command(cs, ICC_CMD_RES); cs->writeisac(cs, ICC_MASK, 0x0); ph_command(cs, ICC_CMD_DI); -} - -void __init -clear_pending_icc_ints(struct IsdnCardState *cs) -{ - int val, eval; - - val = cs->readisac(cs, ICC_STAR); - debugl1(cs, "ICC STAR %x", val); - val = cs->readisac(cs, ICC_MODE); - debugl1(cs, "ICC MODE %x", val); - val = cs->readisac(cs, ICC_ADF2); - debugl1(cs, "ICC ADF2 %x", val); - val = cs->readisac(cs, ICC_ISTA); - debugl1(cs, "ICC ISTA %x", val); - if (val & 0x01) { - eval = cs->readisac(cs, ICC_EXIR); - debugl1(cs, "ICC EXIR %x", eval); - } - val = cs->readisac(cs, ICC_CIR0); - debugl1(cs, "ICC CIR0 %x", val); - cs->dc.icc.ph_state = (val >> 2) & 0xf; - icc_sched_event(cs, D_L1STATECHANGE); - /* Disable all IRQ */ - cs->writeisac(cs, ICC_MASK, 0xFF); } diff -Nru a/drivers/isdn/hisax/icc.h b/drivers/isdn/hisax/icc.h --- a/drivers/isdn/hisax/icc.h Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/icc.h Wed Nov 27 14:36:31 2002 @@ -68,4 +68,3 @@ extern void ICCVersion(struct IsdnCardState *cs, char *s); extern void initicc(struct IsdnCardState *cs); extern void icc_interrupt(struct IsdnCardState *cs, u_char val); -extern void clear_pending_icc_ints(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c --- a/drivers/isdn/hisax/ipacx.c Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/hisax/ipacx.c Wed Nov 27 14:36:30 2002 @@ -23,7 +23,6 @@ #define MAX_DFRAME_LEN_L1 300 #define B_FIFO_SIZE 64 #define D_FIFO_SIZE 32 -static spinlock_t ipacx_lock = SPIN_LOCK_UNLOCKED; // ipacx interrupt mask values #define _MASK_IMASK 0x2E // global mask @@ -39,16 +38,13 @@ static void dbusy_timer_handler(struct IsdnCardState *cs); static void ipacx_new_ph(struct IsdnCardState *cs); static void dch_bh(void *data); -static void dch_sched_event(struct IsdnCardState *cs, int event); static void dch_empty_fifo(struct IsdnCardState *cs, int count); static void dch_fill_fifo(struct IsdnCardState *cs); static inline void dch_int(struct IsdnCardState *cs); static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs); static void __devinit dch_init(struct IsdnCardState *cs); static void bch_l2l1(struct PStack *st, int pr, void *arg); -static void bch_sched_event(struct BCState *bcs, int event); static void bch_empty_fifo(struct BCState *bcs, int count); -static void bch_fill_fifo(struct BCState *bcs); static void bch_int(struct IsdnCardState *cs, u_char hscx); static void bch_mode(struct BCState *bcs, int mode, int bc); static void bch_close_state(struct BCState *bcs); @@ -79,8 +75,8 @@ event = cs->readisac(cs, IPACX_CIR0) >> 4; if (cs->debug &L1_DEB_ISAC) debugl1(cs, "cic_int(event=%#x)", event); - cs->dc.isac.ph_state = event; - dch_sched_event(cs, D_L1STATECHANGE); + cs->dc.isac.ph_state = event; + sched_d_event(cs, D_L1STATECHANGE); } //========================================================== @@ -99,51 +95,14 @@ 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 - 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 - if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0); -#endif - dch_fill_fifo(cs); - } + xmit_data_req_d(cs, skb); 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 - if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); -#endif - dch_fill_fifo(cs); + xmit_pull_ind_d(cs, skb); break; - case (PH_PULL | REQUEST): -#ifdef L2FRAME_DEBUG - if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL"); -#endif - if (!cs->tx_skb) { - clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l2.l1l2(st, PH_PULL | CONFIRM, NULL); - } else - set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_d(st); break; - case (HW_RESET | REQUEST): case (HW_ENABLE | REQUEST): ph_command(cs, IPACX_CMD_TIM); @@ -300,22 +259,11 @@ } //---------------------------------------------------------- -// proceed with bottom half handler dch_bh() -//---------------------------------------------------------- -static void -dch_sched_event(struct IsdnCardState *cs, int event) -{ - set_bit(event, &cs->event); - schedule_work(&cs->work); -} - -//---------------------------------------------------------- // Fill buffer from receive FIFO //---------------------------------------------------------- static void dch_empty_fifo(struct IsdnCardState *cs, int count) { - unsigned long flags; u_char *ptr; if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO)) @@ -333,10 +281,8 @@ ptr = cs->rcvbuf + cs->rcvidx; cs->rcvidx += count; - spin_lock_irqsave(&ipacx_lock, flags); cs->readisacfifo(cs, ptr, count); cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC - spin_unlock_irqrestore(&ipacx_lock, flags); if (cs->debug &L1_DEB_ISAC_FIFO) { char *t = cs->dlog; @@ -353,29 +299,20 @@ static void dch_fill_fifo(struct IsdnCardState *cs) { - unsigned long flags; - int count; - u_char cmd, *ptr; + int count, more; + unsigned char cmd, *p; - if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO)) - debugl1(cs, "dch_fill_fifo()"); - - if (!cs->tx_skb) return; - count = cs->tx_skb->len; - if (count <= 0) return; + p = xmit_fill_fifo_d(cs, 32, &count, &more); + if (!p) + return; - if (count > D_FIFO_SIZE) { - count = D_FIFO_SIZE; + if (more) { cmd = 0x08; // XTF } else { cmd = 0x0A; // XTF | XME } - spin_lock_irqsave(&ipacx_lock, flags); - ptr = cs->tx_skb->data; - skb_pull(cs->tx_skb, count); - cs->tx_cnt += count; - cs->writeisacfifo(cs, ptr, count); + cs->writeisacfifo(cs, p, count); cs->writeisac(cs, IPACX_CMDRD, cmd); // set timeout for transmission contol @@ -386,15 +323,6 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); - spin_unlock_irqrestore(&ipacx_lock, flags); - - if (cs->debug &L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "dch_fill_fifo() cnt %d", count); - QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); - } } //---------------------------------------------------------- @@ -405,7 +333,6 @@ { struct sk_buff *skb; u_char istad, rstad; - unsigned long flags; int count; istad = cs->readisac(cs, IPACX_ISTAD); @@ -429,7 +356,6 @@ count &= D_FIFO_SIZE-1; if (count == 0) count = D_FIFO_SIZE; dch_empty_fifo(cs, count); - spin_lock_irqsave(&ipacx_lock, flags); if ((count = cs->rcvidx) > 0) { cs->rcvidx = 0; if (!(skb = dev_alloc_skb(count))) @@ -439,10 +365,9 @@ skb_queue_tail(&cs->rq, skb); } } - spin_unlock_irqrestore(&ipacx_lock, flags); } cs->rcvidx = 0; - dch_sched_event(cs, D_RCVBUFREADY); + sched_d_event(cs, D_RCVBUFREADY); } if (istad &0x40) { // RPF @@ -454,43 +379,13 @@ cs->writeisac(cs, IPACX_CMDRD, 0x40); //RRES } - if (istad &0x10) { // XPR - 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)) - dch_sched_event(cs, D_CLEARBUSY); - if (cs->tx_skb) { - if (cs->tx_skb->len) { - dch_fill_fifo(cs); - goto afterXPR; - } - else { - dev_kfree_skb_irq(cs->tx_skb); - cs->tx_skb = NULL; - cs->tx_cnt = 0; - } - } - if ((cs->tx_skb = skb_dequeue(&cs->sq))) { - cs->tx_cnt = 0; - dch_fill_fifo(cs); - } - else { - dch_sched_event(cs, D_XMTBUFREADY); - } - } - afterXPR: + if (istad &0x10) { // XPR + xmit_xpr_d(cs); + } if (istad &0x0C) { // XDU or XMR - if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): XDU"); - if (cs->tx_skb) { - skb_push(cs->tx_skb, cs->tx_cnt); // retransmit - cs->tx_cnt = 0; - dch_fill_fifo(cs); - } else { - printk(KERN_WARNING "HiSax: ISAC XDU no skb\n"); - debugl1(cs, "ISAC XDU no skb"); - } - } + xmit_xdu_d(cs, NULL); + } } //---------------------------------------------------------- @@ -510,7 +405,7 @@ INIT_WORK(&cs->work, dch_bh, cs); cs->setstack_d = dch_setstack; - + cs->DC_Send_Data = dch_fill_fifo; cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); @@ -533,38 +428,16 @@ bch_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; - unsigned long flags; switch (pr) { case (PH_DATA | REQUEST): - spin_lock_irqsave(&ipacx_lock, flags); - if (st->l1.bcs->tx_skb) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - spin_unlock_irqrestore(&ipacx_lock, flags); - } else { - st->l1.bcs->tx_skb = skb; - set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->hw.hscx.count = 0; - spin_unlock_irqrestore(&ipacx_lock, flags); - bch_fill_fifo(st->l1.bcs); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "HiSax bch_l2l1(): this shouldn't happen\n"); - break; - } - set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->tx_skb = skb; - st->l1.bcs->hw.hscx.count = 0; - bch_fill_fifo(st->l1.bcs); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l2.l1l2(st, PH_PULL | CONFIRM, NULL); - } else - set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); @@ -584,16 +457,6 @@ } //---------------------------------------------------------- -// proceed with bottom half handler BChannel_bh() -//---------------------------------------------------------- -static void -bch_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - -//---------------------------------------------------------- // Read B channel fifo to receive buffer //---------------------------------------------------------- static void @@ -601,7 +464,6 @@ { u_char *ptr, hscx; struct IsdnCardState *cs; - unsigned long flags; int cnt; cs = bcs->cs; @@ -619,7 +481,6 @@ } // Read data uninterruptible - spin_lock_irqsave(&ipacx_lock, flags); ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; cnt = count; while (cnt--) *ptr++ = cs->BC_Read_Reg(cs, hscx, IPACX_RFIFOB); @@ -627,7 +488,6 @@ ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; bcs->hw.hscx.rcvidx += count; - spin_unlock_irqrestore(&ipacx_lock, flags); if (cs->debug &L1_DEB_HSCX_FIFO) { char *t = bcs->blog; @@ -641,52 +501,34 @@ //---------------------------------------------------------- // Fill buffer to transmit FIFO //---------------------------------------------------------- -static void -bch_fill_fifo(struct BCState *bcs) +void +ipacx_fill_fifo(struct BCState *bcs) { - struct IsdnCardState *cs; - int more, count, cnt; - u_char *ptr, *p, hscx; - unsigned long flags; + struct IsdnCardState *cs = bcs->cs; + int more, count; + unsigned char hscx = bcs->hw.hscx.hscx; + unsigned char *p; - cs = bcs->cs; - if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO)) - debugl1(cs, "bch_fill_fifo()"); + p = xmit_fill_fifo_b(bcs, B_FIFO_SIZE, &count, &more); + if (!p) + return; - if (!bcs->tx_skb) return; - if (bcs->tx_skb->len <= 0) return; + while (count--) + cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++); - hscx = bcs->hw.hscx.hscx; - more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; - if (bcs->tx_skb->len > B_FIFO_SIZE) { - more = 1; - count = B_FIFO_SIZE; - } else { - count = bcs->tx_skb->len; - } - cnt = count; - - spin_lock_irqsave(&ipacx_lock, flags); - p = ptr = bcs->tx_skb->data; - skb_pull(bcs->tx_skb, count); - bcs->tx_cnt -= count; - bcs->hw.hscx.count += count; - while (cnt--) cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++); cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, (more ? 0x08 : 0x0a)); - spin_unlock_irqrestore(&ipacx_lock, flags); - - if (cs->debug &L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } } //---------------------------------------------------------- // B channel interrupt handler //---------------------------------------------------------- + +static void +reset_xmit(struct BCState *bcs) +{ + bcs->cs->BC_Write_Reg(bcs->cs, bcs->hw.hscx.hscx, IPACX_CMDRB, 0x01); // XRES +} + static void bch_int(struct IsdnCardState *cs, u_char hscx) { @@ -730,7 +572,7 @@ } } bcs->hw.hscx.rcvidx = 0; - bch_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } if (istab &0x40) { // RPF @@ -745,57 +587,22 @@ skb_queue_tail(&bcs->rqueue, skb); } bcs->hw.hscx.rcvidx = 0; - bch_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } } if (istab &0x20) { // RFO if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: RFO error", hscx); - cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES + debugl1(cs, "bch_int() B-%d: RFO error", hscx); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES } if (istab &0x10) { // XPR - if (bcs->tx_skb) { - if (bcs->tx_skb->len) { - bch_fill_fifo(bcs); - goto afterXPR; - } - else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) { - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - } - dev_kfree_skb_irq(bcs->tx_skb); - bcs->hw.hscx.count = 0; - bcs->tx_skb = NULL; - } - } - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->hw.hscx.count = 0; - set_bit(BC_FLG_BUSY, &bcs->Flag); - bch_fill_fifo(bcs); - } else { - clear_bit(BC_FLG_BUSY, &bcs->Flag); - bch_sched_event(bcs, B_XMTBUFREADY); - } - } - afterXPR: + xmit_xpr_b(bcs); + } if (istab &0x04) { // XDU - if (bcs->mode == L1_MODE_TRANS) { - bch_fill_fifo(bcs); - } - else { - if (bcs->tx_skb) { // restart transmitting the whole frame - skb_push(bcs->tx_skb, bcs->hw.hscx.count); - bcs->tx_cnt += bcs->hw.hscx.count; - bcs->hw.hscx.count = 0; - } - cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01); // XRES - if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d XDU error", hscx); - } + xmit_xdu_b(bcs, reset_xmit); } } @@ -942,13 +749,15 @@ interrupt_ipacx(struct IsdnCardState *cs) { u_char ista; - + + spin_lock(&cs->lock); while ((ista = cs->readisac(cs, IPACX_ISTA))) { if (ista &0x80) bch_int(cs, 0); // B channel interrupts if (ista &0x40) bch_int(cs, 1); if (ista &0x01) dch_int(cs); // D channel if (ista &0x10) cic_int(cs); // Layer 1 state } + spin_unlock(&cs->lock); } //---------------------------------------------------------- diff -Nru a/drivers/isdn/hisax/ipacx.h b/drivers/isdn/hisax/ipacx.h --- a/drivers/isdn/hisax/ipacx.h Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/ipacx.h Wed Nov 27 14:36:27 2002 @@ -157,5 +157,6 @@ extern void init_ipacx(struct IsdnCardState *cs, int part); extern void interrupt_ipacx(struct IsdnCardState *cs); +extern void ipacx_fill_fifo(struct BCState *bcs); #endif diff -Nru a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c --- a/drivers/isdn/hisax/isac.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/isac.c Wed Nov 27 14:36:28 2002 @@ -22,7 +22,6 @@ #define DBUSY_TIMER_VALUE 80 #define ARCOFI_USE 1 -static spinlock_t isac_lock = SPIN_LOCK_UNLOCKED; static char *ISACVer[] __devinitdata = {"2086/2186 V1.1", "2085 B1", "2085 B2", @@ -118,7 +117,6 @@ isac_empty_fifo(struct IsdnCardState *cs, int count) { u_char *ptr; - unsigned long flags; if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) debugl1(cs, "isac_empty_fifo"); @@ -133,10 +131,8 @@ } ptr = cs->rcvbuf + cs->rcvidx; cs->rcvidx += count; - spin_lock_irqsave(&isac_lock, flags); cs->readisacfifo(cs, ptr, count); cs->writeisac(cs, ISAC_CMDR, 0x80); - spin_unlock_irqrestore(&isac_lock, flags); if (cs->debug & L1_DEB_ISAC_FIFO) { char *t = cs->dlog; @@ -150,29 +146,13 @@ isac_fill_fifo(struct IsdnCardState *cs) { int count, more; - u_char *ptr; - unsigned long flags; - - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, "isac_fill_fifo"); - - if (!cs->tx_skb) - return; + unsigned char *p; - count = cs->tx_skb->len; - if (count <= 0) + p = xmit_fill_fifo_d(cs, 32, &count, &more); + if (!p) return; - more = 0; - if (count > 32) { - more = !0; - count = 32; - } - spin_lock_irqsave(&isac_lock, flags); - ptr = cs->tx_skb->data; - skb_pull(cs->tx_skb, count); - cs->tx_cnt += count; - cs->writeisacfifo(cs, ptr, count); + cs->writeisacfifo(cs, p, count); cs->writeisac(cs, ISAC_CMDR, more ? 0x8 : 0xa); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { debugl1(cs, "isac_fill_fifo dbusytimer running"); @@ -181,21 +161,6 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); - spin_unlock_irqrestore(&isac_lock, flags); - if (cs->debug & L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "isac_fill_fifo cnt %d", count); - QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); - } -} - -void -isac_sched_event(struct IsdnCardState *cs, int event) -{ - test_and_set_bit(event, &cs->event); - schedule_work(&cs->work); } void @@ -204,7 +169,6 @@ u_char exval, v1; struct sk_buff *skb; unsigned int count; - unsigned long flags; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC interrupt %x", val); @@ -231,7 +195,6 @@ if (count == 0) count = 32; isac_empty_fifo(cs, count); - spin_lock_irqsave(&isac_lock, flags); if ((count = cs->rcvidx) > 0) { cs->rcvidx = 0; if (!(skb = alloc_skb(count, GFP_ATOMIC))) @@ -241,10 +204,9 @@ skb_queue_tail(&cs->rq, skb); } } - spin_unlock_irqrestore(&isac_lock, flags); } cs->rcvidx = 0; - isac_sched_event(cs, D_RCVBUFREADY); + sched_d_event(cs, D_RCVBUFREADY); } if (val & 0x40) { /* RPF */ isac_empty_fifo(cs, 32); @@ -255,27 +217,8 @@ debugl1(cs, "ISAC RSC interrupt"); } if (val & 0x10) { /* XPR */ - 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)) - isac_sched_event(cs, D_CLEARBUSY); - if (cs->tx_skb) { - if (cs->tx_skb->len) { - isac_fill_fifo(cs); - goto afterXPR; - } else { - dev_kfree_skb_irq(cs->tx_skb); - cs->tx_cnt = 0; - cs->tx_skb = NULL; - } - } - if ((cs->tx_skb = skb_dequeue(&cs->sq))) { - cs->tx_cnt = 0; - isac_fill_fifo(cs); - } else - isac_sched_event(cs, D_XMTBUFREADY); + xmit_xpr_d(cs); } - afterXPR: if (val & 0x04) { /* CISQ */ exval = cs->readisac(cs, ISAC_CIR0); if (cs->debug & L1_DEB_ISAC) @@ -284,7 +227,7 @@ cs->dc.isac.ph_state = (exval >> 2) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state); - isac_sched_event(cs, D_L1STATECHANGE); + sched_d_event(cs, D_L1STATECHANGE); } if (exval & 1) { exval = cs->readisac(cs, ISAC_CIR1); @@ -306,23 +249,7 @@ printk(KERN_WARNING "HiSax: ISAC XMR\n"); } 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)) - isac_sched_event(cs, D_CLEARBUSY); - if (cs->tx_skb) { /* Restart frame */ - skb_push(cs->tx_skb, cs->tx_cnt); - cs->tx_cnt = 0; - isac_fill_fifo(cs); - } else { - printk(KERN_WARNING "HiSax: ISAC XDU no skb\n"); - debugl1(cs, "ISAC XDU no skb"); - } + xmit_xdu_d(cs, NULL); } if (exval & 0x04) { /* MOS */ v1 = cs->readisac(cs, ISAC_MOSR); @@ -392,14 +319,14 @@ cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0x0a; cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); - isac_sched_event(cs, D_RX_MON0); + sched_d_event(cs, D_RX_MON0); } if (v1 & 0x40) { cs->dc.isac.mocr &= 0x0f; cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0xa0; cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); - isac_sched_event(cs, D_RX_MON1); + sched_d_event(cs, D_RX_MON1); } if (v1 & 0x02) { if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && @@ -411,11 +338,11 @@ cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) - isac_sched_event(cs, D_TX_MON0); + sched_d_event(cs, D_TX_MON0); goto AfterMOX0; } if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) { - isac_sched_event(cs, D_TX_MON0); + sched_d_event(cs, D_TX_MON0); goto AfterMOX0; } cs->writeisac(cs, ISAC_MOX0, @@ -434,11 +361,11 @@ cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) - isac_sched_event(cs, D_TX_MON1); + sched_d_event(cs, D_TX_MON1); goto AfterMOX1; } if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) { - isac_sched_event(cs, D_TX_MON1); + sched_d_event(cs, D_TX_MON1); goto AfterMOX1; } cs->writeisac(cs, ISAC_MOX1, @@ -461,55 +388,13 @@ 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 - isac_fill_fifo(cs); - } + xmit_data_req_d(cs, skb); 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 - isac_fill_fifo(cs); + xmit_pull_ind_d(cs, skb); 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); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_d(st); break; case (HW_RESET | REQUEST): if ((cs->dc.isac.ph_state == ISAC_IND_EI) || @@ -559,7 +444,7 @@ 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)) - isac_sched_event(cs, D_CLEARBUSY); + sched_d_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -625,8 +510,26 @@ void __devinit initisac(struct IsdnCardState *cs) { + int val, eval; + + val = cs->readisac(cs, ISAC_STAR); + debugl1(cs, "ISAC STAR %x", val); + val = cs->readisac(cs, ISAC_MODE); + debugl1(cs, "ISAC MODE %x", val); + val = cs->readisac(cs, ISAC_ADF2); + debugl1(cs, "ISAC ADF2 %x", val); + val = cs->readisac(cs, ISAC_ISTA); + debugl1(cs, "ISAC ISTA %x", val); + if (val & 0x01) { + eval = cs->readisac(cs, ISAC_EXIR); + debugl1(cs, "ISAC EXIR %x", eval); + } + /* Disable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0xFF); + INIT_WORK(&cs->work, isac_bh, cs); cs->setstack_d = setstack_isac; + cs->DC_Send_Data = isac_fill_fifo; cs->DC_Close = DC_Close_isac; cs->dc.isac.mon_tx = NULL; cs->dc.isac.mon_rx = NULL; @@ -656,29 +559,12 @@ } ph_command(cs, ISAC_CMD_RS); cs->writeisac(cs, ISAC_MASK, 0x0); -} -void __devinit -clear_pending_isac_ints(struct IsdnCardState *cs) -{ - int val, eval; - - val = cs->readisac(cs, ISAC_STAR); - debugl1(cs, "ISAC STAR %x", val); - val = cs->readisac(cs, ISAC_MODE); - debugl1(cs, "ISAC MODE %x", val); - val = cs->readisac(cs, ISAC_ADF2); - debugl1(cs, "ISAC ADF2 %x", val); - val = cs->readisac(cs, ISAC_ISTA); - debugl1(cs, "ISAC ISTA %x", val); - if (val & 0x01) { - eval = cs->readisac(cs, ISAC_EXIR); - debugl1(cs, "ISAC EXIR %x", eval); - } val = cs->readisac(cs, ISAC_CIR0); debugl1(cs, "ISAC CIR0 %x", val); cs->dc.isac.ph_state = (val >> 2) & 0xf; - isac_sched_event(cs, D_L1STATECHANGE); - /* Disable all IRQ */ - cs->writeisac(cs, ISAC_MASK, 0xFF); + sched_d_event(cs, D_L1STATECHANGE); + + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); } diff -Nru a/drivers/isdn/hisax/isac.h b/drivers/isdn/hisax/isac.h --- a/drivers/isdn/hisax/isac.h Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/hisax/isac.h Wed Nov 27 14:36:32 2002 @@ -66,4 +66,3 @@ extern void ISACVersion(struct IsdnCardState *cs, char *s); extern void initisac(struct IsdnCardState *cs); extern void isac_interrupt(struct IsdnCardState *cs, u_char val); -extern void clear_pending_isac_ints(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c --- a/drivers/isdn/hisax/isar.c Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/hisax/isar.c Wed Nov 27 14:36:30 2002 @@ -190,7 +190,6 @@ u_short sadr, left, *sp; u_char *p = buf; u_char *msg, *tmpmsg, *mp, tmp[64]; - unsigned long flags; struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; struct {u_short sadr; @@ -344,7 +343,6 @@ /* NORMAL mode entered */ /* Enable IRQs of ISAR */ cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA); - spin_lock_irqsave(&isar_lock, flags); cnt = 1000; /* max 1s */ while ((!ireg->bstat) && cnt) { udelay(1000); @@ -352,7 +350,7 @@ } if (!cnt) { printk(KERN_ERR"isar no general status event received\n"); - ret = 1;goto reterrflg; + ret = 1;goto reterror; } else { printk(KERN_DEBUG"isar general status event %x\n", ireg->bstat); @@ -364,7 +362,7 @@ ireg->iis = 0; if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) { printk(KERN_ERR"isar sendmsg self tst failed\n"); - ret = 1;goto reterrflg; + ret = 1;goto reterror; } cnt = 10000; /* max 100 ms */ while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { @@ -374,7 +372,7 @@ udelay(1000); if (!cnt) { printk(KERN_ERR"isar no self tst response\n"); - ret = 1;goto reterrflg; + ret = 1;goto reterror; } if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1) && (ireg->par[0] == 0)) { @@ -382,12 +380,12 @@ } else { printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n", ireg->cmsb, ireg->clsb, ireg->par[0]); - ret = 1;goto reterrflg; + ret = 1;goto reterror; } ireg->iis = 0; if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) { printk(KERN_ERR"isar RQST SVN failed\n"); - ret = 1;goto reterrflg; + ret = 1;goto reterror; } cnt = 30000; /* max 300 ms */ while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { @@ -397,7 +395,7 @@ udelay(1000); if (!cnt) { printk(KERN_ERR"isar no SVN response\n"); - ret = 1;goto reterrflg; + ret = 1;goto reterror; } else { if ((ireg->cmsb == ISAR_CTRL_SWVER) && (ireg->clsb == 1)) printk(KERN_DEBUG"isar software version %#x\n", @@ -405,14 +403,12 @@ else { printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n", ireg->cmsb, ireg->clsb, cnt); - ret = 1;goto reterrflg; + ret = 1;goto reterror; } } cs->debug = debug; isar_setup(cs); ret = 0; -reterrflg: - spin_unlock_irqrestore(&isar_lock, flags); reterror: cs->debug = debug; if (ret) @@ -424,9 +420,6 @@ } extern void BChannel_bh(struct BCState *); -#define B_LL_NOCARRIER 8 -#define B_LL_CONNECT 9 -#define B_LL_OK 10 static void isar_bh(void *data) @@ -442,13 +435,6 @@ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK); } -static void -isar_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - static inline void send_DLE_ETX(struct BCState *bcs) { @@ -458,7 +444,7 @@ if ((skb = dev_alloc_skb(2))) { memcpy(skb_put(skb, 2), dleetx, 2); skb_queue_tail(&bcs->rqueue, skb); - isar_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); } @@ -510,7 +496,7 @@ if ((skb = dev_alloc_skb(ireg->clsb))) { rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb)); skb_queue_tail(&bcs->rqueue, skb); - isar_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); @@ -551,7 +537,7 @@ memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2), bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2); skb_queue_tail(&bcs->rqueue, skb); - isar_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } bcs->hw.isar.rcvidx = 0; } @@ -576,7 +562,7 @@ insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx), bcs->hw.isar.rcvbuf, ireg->clsb); skb_queue_tail(&bcs->rqueue, skb); - isar_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); if (ireg->cmsb & SART_NMD) { /* ABORT */ if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: no more data"); @@ -587,7 +573,7 @@ ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); bcs->hw.isar.state = STFAX_ESCAPE; - isar_sched_event(bcs, B_LL_NOCARRIER); + sched_b_event(bcs, B_LL_NOCARRIER); } } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); @@ -635,9 +621,9 @@ bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx); skb_queue_tail(&bcs->rqueue, skb); - isar_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); send_DLE_ETX(bcs); - isar_sched_event(bcs, B_LL_OK); + sched_b_event(bcs, B_LL_OK); } bcs->hw.isar.rcvidx = 0; } @@ -651,7 +637,7 @@ sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); bcs->hw.isar.state = STFAX_ESCAPE; - isar_sched_event(bcs, B_LL_NOCARRIER); + sched_b_event(bcs, B_LL_NOCARRIER); } break; default: @@ -668,7 +654,6 @@ int count; u_char msb; u_char *ptr; - unsigned long flags; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "isar_fill_fifo"); @@ -686,9 +671,8 @@ count = bcs->tx_skb->len; msb = HDLC_FED; } - spin_lock_irqsave(&isar_lock, flags); ptr = bcs->tx_skb->data; - if (!bcs->hw.isar.txcnt) { + if (!bcs->count) { msb |= HDLC_FST; if ((bcs->mode == L1_MODE_FAX) && (bcs->hw.isar.cmd == PCTRL_CMD_FTH)) { @@ -702,7 +686,7 @@ } skb_pull(bcs->tx_skb, count); bcs->tx_cnt -= count; - bcs->hw.isar.txcnt += count; + bcs->count += count; switch (bcs->mode) { case L1_MODE_NULL: printk(KERN_ERR"isar_fill_fifo wrong mode 0\n"); @@ -737,7 +721,6 @@ printk(KERN_ERR"isar_fill_fifo mode(%x) error\n", bcs->mode); break; } - spin_unlock_irqrestore(&isar_lock, flags); } inline @@ -760,9 +743,7 @@ isar_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.isar.txcnt); + xmit_complete_b(bcs); if (bcs->mode == L1_MODE_FAX) { if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) { @@ -775,13 +756,11 @@ } } } - dev_kfree_skb_any(bcs->tx_skb); - bcs->hw.isar.txcnt = 0; - bcs->tx_skb = NULL; + bcs->count = 0; } } if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->hw.isar.txcnt = 0; + bcs->count = 0; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); isar_fill_fifo(bcs); } else { @@ -794,11 +773,11 @@ } test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag); } else { - isar_sched_event(bcs, B_LL_CONNECT); + sched_b_event(bcs, B_LL_CONNECT); } } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - isar_sched_event(bcs, B_XMTBUFREADY); + sched_b_event(bcs, B_XMTBUFREADY); } } @@ -1057,7 +1036,7 @@ &bcs->Flag); add_timer(&bcs->hw.isar.ftimer); } else { - isar_sched_event(bcs, B_LL_CONNECT); + sched_b_event(bcs, B_LL_CONNECT); } } else { if (cs->debug & L1_DEB_WARN) @@ -1102,10 +1081,10 @@ } } else if (bcs->hw.isar.state == STFAX_ACTIV) { if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) { - isar_sched_event(bcs, B_LL_OK); + sched_b_event(bcs, B_LL_OK); } else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) { send_DLE_ETX(bcs); - isar_sched_event(bcs, B_LL_NOCARRIER); + sched_b_event(bcs, B_LL_NOCARRIER); } else { ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR); } @@ -1161,11 +1140,9 @@ void isar_int_main(struct IsdnCardState *cs) { - unsigned long flags; struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; struct BCState *bcs; - spin_lock_irqsave(&isar_lock, flags); get_irq_infos(cs, ireg); switch (ireg->iis & ISAR_IIS_MSCMSD) { case ISAR_IIS_RDATA: @@ -1251,7 +1228,6 @@ ireg->iis, ireg->cmsb, ireg->clsb); break; } - spin_unlock_irqrestore(&isar_lock, flags); } static void @@ -1261,7 +1237,7 @@ bcs->Flag); test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag); if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) { - isar_sched_event(bcs, B_LL_CONNECT); + sched_b_event(bcs, B_LL_CONNECT); } } @@ -1565,42 +1541,16 @@ isar_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; - unsigned long flags; switch (pr) { case (PH_DATA | REQUEST): - spin_lock_irqsave(&isar_lock, flags); - if (st->l1.bcs->tx_skb) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - spin_unlock_irqrestore(&isar_lock, flags); - } else { - st->l1.bcs->tx_skb = skb; - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - if (st->l1.bcs->cs->debug & L1_DEB_HSCX) - debugl1(st->l1.bcs->cs, "DRQ set BC_FLG_BUSY"); - st->l1.bcs->hw.isar.txcnt = 0; - spin_unlock_irqrestore(&isar_lock, flags); - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n"); - break; - } - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - if (st->l1.bcs->cs->debug & L1_DEB_HSCX) - debugl1(st->l1.bcs->cs, "PUI set BC_FLG_BUSY"); - st->l1.bcs->tx_skb = skb; - st->l1.bcs->hw.isar.txcnt = 0; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c --- a/drivers/isdn/hisax/isdnl1.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/isdnl1.c Wed Nov 27 14:36:28 2002 @@ -298,6 +298,16 @@ } } +static void +BChannel_proc_cmpl(struct BCState *bcs) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(&bcs->cmpl_queue))) { + L1L2(bcs->st, PH_DATA | CONFIRM, skb); + } +} + void BChannel_bh(void *data) { @@ -307,6 +317,8 @@ BChannel_proc_rcv(bcs); if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event)) BChannel_proc_xmt(bcs); + if (test_and_clear_bit(B_CMPLREADY, &bcs->event)) + BChannel_proc_cmpl(bcs); } void diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h --- a/drivers/isdn/hisax/isdnl1.h Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/isdnl1.h Wed Nov 27 14:36:31 2002 @@ -17,8 +17,13 @@ #define D_TX_MON1 7 #define E_RCVBUFREADY 8 -#define B_RCVBUFREADY 0 -#define B_XMTBUFREADY 1 +#define B_RCVBUFREADY 0 +#define B_XMTBUFREADY 1 +#define B_CMPLREADY 2 + +#define B_LL_NOCARRIER 8 +#define B_LL_CONNECT 9 +#define B_LL_OK 10 extern void debugl1(struct IsdnCardState *cs, char *fmt, ...); extern void DChannel_proc_xmt(struct IsdnCardState *cs); @@ -29,3 +34,376 @@ #ifdef L2FRAME_DEBUG extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir); #endif + +static inline void +sched_b_event(struct BCState *bcs, int event) +{ + set_bit(event, &bcs->event); + schedule_work(&bcs->work); +} + +static inline void +sched_d_event(struct IsdnCardState *cs, int event) +{ + set_bit(event, &cs->event); + schedule_work(&cs->work); +} + +/* called with the card lock held */ +static inline void +xmit_complete_b(struct BCState *bcs) +{ + skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb); + sched_b_event(bcs, B_CMPLREADY); + bcs->tx_skb = NULL; +} + +/* called with the card lock held */ +static inline void +xmit_complete_d(struct IsdnCardState *cs) +{ + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_skb = NULL; +} + +/* called with the card lock held */ +static inline void +xmit_ready_b(struct BCState *bcs) +{ + bcs->tx_skb = skb_dequeue(&bcs->squeue); + if (bcs->tx_skb) { + bcs->count = 0; + set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->cs->BC_Send_Data(bcs); + } else { + clear_bit(BC_FLG_BUSY, &bcs->Flag); + sched_b_event(bcs, B_XMTBUFREADY); + } +} + +/* called with the card lock held */ +static inline void +xmit_ready_d(struct IsdnCardState *cs) +{ + cs->tx_skb = skb_dequeue(&cs->sq); + if (cs->tx_skb) { + cs->tx_cnt = 0; + cs->DC_Send_Data(cs); + } else { + sched_d_event(cs, D_XMTBUFREADY); + } +} + +static inline void +xmit_data_req_b(struct BCState *bcs, struct sk_buff *skb) +{ + struct IsdnCardState *cs = bcs->cs; + unsigned long flags; + + spin_lock_irqsave(&cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&cs->lock, flags); +} + +static inline void +xmit_data_req_d(struct IsdnCardState *cs, struct sk_buff *skb) +{ + unsigned long flags; + + spin_lock_irqsave(&cs->lock, flags); + 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 + 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 + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + cs->DC_Send_Data(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); +} + +static inline void +xmit_pull_ind_b(struct BCState *bcs, struct sk_buff *skb) +{ + struct IsdnCardState *cs = bcs->cs; + unsigned long flags; + + spin_lock_irqsave(&cs->lock, flags); + if (bcs->tx_skb) { + WARN_ON(1); + } else { + set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&cs->lock, flags); +} + +static inline void +xmit_pull_ind_d(struct IsdnCardState *cs, struct sk_buff *skb) +{ + unsigned long flags; + + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + WARN_ON(1); + } else { + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); +#ifdef L2FRAME_DEBUG + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + cs->tx_skb = skb; + cs->tx_cnt = 0; + cs->DC_Send_Data(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); +} + +/* If busy, the PH_PULL | CONFIRM scheduling is handled under + * the card lock by xmit_ready_b() above, so no race */ +static inline void +xmit_pull_req_b(struct PStack *st) +{ + struct BCState *bcs = st->l1.bcs; + struct IsdnCardState *cs = bcs->cs; + unsigned long flags; + int busy = 0; + + spin_lock_irqsave(&cs->lock, flags); + if (bcs->tx_skb) { + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + busy = 1; + } + spin_unlock_irqrestore(&cs->lock, flags); + if (!busy) + L1L2(st, PH_PULL | CONFIRM, NULL); +} + +/* If busy, the PH_PULL | CONFIRM scheduling is handled under + * the card lock by xmit_ready_d() above, so no race */ +static inline void +xmit_pull_req_d(struct PStack *st) +{ + struct IsdnCardState *cs = st->l1.hardware; + unsigned long flags; + int busy = 0; + +#ifdef L2FRAME_DEBUG + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + busy = 1; + } + spin_unlock_irqrestore(&cs->lock, flags); + if (!busy) + L1L2(st, PH_PULL | CONFIRM, NULL); +} + +/* called with the card lock held */ +static inline void +xmit_restart_b(struct BCState *bcs) +{ +#ifdef ERROR_STATISTIC + bcs->err_tx++; +#endif + if (!bcs->tx_skb) { + WARN_ON(1); + return; + } + skb_push(bcs->tx_skb, bcs->count); + bcs->tx_cnt += bcs->count; + bcs->count = 0; +} + +/* called with the card lock held */ +static inline void +xmit_restart_d(struct IsdnCardState *cs) +{ +#ifdef ERROR_STATISTIC + cs->err_tx++; +#endif + if (!cs->tx_skb) { + WARN_ON(1); + return; + } + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; +} + +/* Useful for HSCX/ISAC work-alike's */ +/* ---------------------------------------------------------------------- */ + +/* XPR - transmit pool ready */ +/* called with the card lock held */ +static inline void +xmit_xpr_b(struct BCState *bcs) +{ + /* current frame? */ + if (bcs->tx_skb) { + /* last frame not done yet? */ + if (bcs->tx_skb->len) { + bcs->cs->BC_Send_Data(bcs); + return; + } + xmit_complete_b(bcs); + bcs->count = 0; + } + xmit_ready_b(bcs); +} + +/* XPR - transmit pool ready */ +/* called with the card lock held */ +static inline void +xmit_xpr_d(struct IsdnCardState *cs) +{ + 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)) + sched_d_event(cs, D_CLEARBUSY); + /* current frame? */ + if (cs->tx_skb) { + /* last frame not done yet? */ + if (cs->tx_skb->len) { + cs->DC_Send_Data(cs); + return; + } + xmit_complete_d(cs); + cs->tx_cnt = 0; + } + xmit_ready_d(cs); +} + +/* XDU - transmit data underrun */ +/* called with the card lock held */ +static inline void +xmit_xdu_b(struct BCState *bcs, void (*reset_xmit)(struct BCState *bcs)) +{ + struct IsdnCardState *cs = bcs->cs; + + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX %c EXIR XDU", 'A' + bcs->channel); + + if (bcs->mode == L1_MODE_TRANS) { + cs->BC_Send_Data(bcs); + } else { + xmit_restart_b(bcs); + reset_xmit(bcs); + } +} + +/* XDU - transmit data underrun */ +/* called with the card lock held */ +static inline void +xmit_xdu_d(struct IsdnCardState *cs, void (*reset_xmit)(struct IsdnCardState *cs)) +{ + printk(KERN_WARNING "HiSax: D XDU\n"); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "D XDU"); + + 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)) + sched_d_event(cs, D_CLEARBUSY); + + xmit_restart_d(cs); + if (reset_xmit) + reset_xmit(cs); +} + +static inline unsigned char * +xmit_fill_fifo_b(struct BCState *bcs, int fifo_size, int *count, int *more) +{ + struct IsdnCardState *cs = bcs->cs; + unsigned char *p; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, __FUNCTION__); + + if (!bcs->tx_skb || bcs->tx_skb->len <= 0) { + WARN_ON(1); + return NULL; + } + + *more = (bcs->mode == L1_MODE_TRANS); + if (bcs->tx_skb->len > fifo_size) { + *more = 1; + *count = fifo_size; + } else { + *count = bcs->tx_skb->len; + } + p = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, *count); + bcs->tx_cnt -= *count; + bcs->count += *count; + + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "%s %c cnt %d", __FUNCTION__, + bcs->hw.hscx.hscx ? 'B' : 'A', *count); + QuickHex(t, p, *count); + debugl1(cs, bcs->blog); + } + return p; +} + +static inline unsigned char * +xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more) +{ + unsigned char *p; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, __FUNCTION__); + + if (!cs->tx_skb || cs->tx_skb->len <= 0) { + WARN_ON(1); + return NULL; + } + + *more = 0; + if (cs->tx_skb->len > fifo_size) { + *more = 1; + *count = fifo_size; + } else { + *count = cs->tx_skb->len; + } + + p = cs->tx_skb->data; + skb_pull(cs->tx_skb, *count); + cs->tx_cnt += *count; + + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "%s cnt %d", __FUNCTION__, *count); + QuickHex(t, p, *count); + debugl1(cs, cs->dlog); + } + return p; +} diff -Nru a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c --- a/drivers/isdn/hisax/isdnl2.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/isdnl2.c Wed Nov 27 14:36:28 2002 @@ -403,7 +403,7 @@ setva(struct PStack *st, unsigned int nr) { struct Layer2 *l2 = &st->l2; - int len; + struct sk_buff *skb; while (l2->va != nr) { (l2->va)++; @@ -411,14 +411,11 @@ l2->va %= 128; else l2->va %= 8; - len = l2->windowar[l2->sow]->len; - if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type) - len = -1; - dev_kfree_skb(l2->windowar[l2->sow]); + skb = l2->windowar[l2->sow]; l2->windowar[l2->sow] = NULL; l2->sow = (l2->sow + 1) % l2->window; - if (st->lli.l2writewakeup && (len >=0)) - st->lli.l2writewakeup(st, len); + + L2L3(st, DL_DATA | CONFIRM, skb); } } @@ -1685,6 +1682,9 @@ } if (ret) FreeSkb(skb); + break; + case (PH_DATA | CONFIRM): + dev_kfree_skb(skb); break; case (PH_PULL | CONFIRM): FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg); diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c --- a/drivers/isdn/hisax/isurf.c Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/hisax/isurf.c Wed Nov 27 14:36:30 2002 @@ -89,11 +89,7 @@ u_char val; int cnt = 5; - if (!cs) { - printk(KERN_WARNING "ISurf: Spurious interrupt!\n"); - return; - } - + spin_lock(&cs->lock); val = readb(cs->hw.isurf.isar + ISAR_IRQBIT); Start_ISAR: if (val & ISAR_IRQSTA) @@ -121,6 +117,7 @@ writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb(); writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb(); writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb(); + spin_unlock(&cs->lock); } void @@ -155,14 +152,9 @@ release_io_isurf(cs); return(0); case CARD_INIT: - clear_pending_isac_ints(cs); writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb(); initisac(cs); initisar(cs); - /* Reenable ISAC IRQ */ - cs->writeisac(cs, ISAC_MASK, 0); - /* RESET Receiver and Transmitter */ - cs->writeisac(cs, ISAC_CMDR, 0x41); return(0); case CARD_TEST: return(0); @@ -180,8 +172,6 @@ reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET | ISURF_ARCOFI_RESET); initisac(cs); - cs->writeisac(cs, ISAC_MASK, 0); - cs->writeisac(cs, ISAC_CMDR, 0x41); } return(ret); } diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c --- a/drivers/isdn/hisax/ix1_micro.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/hisax/ix1_micro.c Wed Nov 27 14:36:32 2002 @@ -141,10 +141,7 @@ struct IsdnCardState *cs = dev_id; u_char val; - if (!cs) { - printk(KERN_WARNING "IX1: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40); Start_HSCX: if (val) @@ -171,6 +168,7 @@ writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0); writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0); writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0); + spin_unlock(&cs->lock); } void @@ -205,7 +203,7 @@ release_io_ix1micro(cs); return(0); case CARD_INIT: - inithscxisac(cs, 3); + inithscxisac(cs); return(0); case CARD_TEST: return(0); diff -Nru a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c --- a/drivers/isdn/hisax/jade.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/jade.c Wed Nov 27 14:36:28 2002 @@ -134,49 +134,20 @@ cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00); } -void -jade_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - static void jade_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; - unsigned long flags; switch (pr) { case (PH_DATA | REQUEST): - spin_lock_irqsave(&jade_lock, flags); - if (st->l1.bcs->tx_skb) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - spin_unlock_irqrestore(&jade_lock, flags); - } else { - st->l1.bcs->tx_skb = skb; - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->hw.hscx.count = 0; - spin_unlock_irqrestore(&jade_lock, flags); - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "jade_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.hscx.count = 0; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); @@ -263,40 +234,32 @@ } void __init -clear_pending_jade_ints(struct IsdnCardState *cs) +initjade(struct IsdnCardState *cs) { int val; - char tmp[64]; + + cs->bcs[0].BC_SetStack = setstack_jade; + cs->bcs[1].BC_SetStack = setstack_jade; + cs->bcs[0].BC_Close = close_jadestate; + cs->bcs[1].BC_Close = close_jadestate; + cs->bcs[0].hw.hscx.hscx = 0; + cs->bcs[1].hw.hscx.hscx = 1; cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00); cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00); val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR); - sprintf(tmp, "jade B ISTA %x", val); - debugl1(cs, tmp); + debugl1(cs, "jade B ISTA %x", val); val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR); - sprintf(tmp, "jade A ISTA %x", val); - debugl1(cs, tmp); + debugl1(cs, "jade A ISTA %x", val); val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR); - sprintf(tmp, "jade B STAR %x", val); - debugl1(cs, tmp); + debugl1(cs, "jade B STAR %x", val); val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR); - sprintf(tmp, "jade A STAR %x", val); - debugl1(cs, tmp); + debugl1(cs, "jade A STAR %x", val); + /* Unmask ints */ cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8); cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8); -} - -void __init -initjade(struct IsdnCardState *cs) -{ - cs->bcs[0].BC_SetStack = setstack_jade; - cs->bcs[1].BC_SetStack = setstack_jade; - cs->bcs[0].BC_Close = close_jadestate; - cs->bcs[1].BC_Close = close_jadestate; - cs->bcs[0].hw.hscx.hscx = 0; - cs->bcs[1].hw.hscx.hscx = 1; /* Stop DSP audio tx/rx */ jade_write_indirect(cs, 0x11, 0x0f); diff -Nru a/drivers/isdn/hisax/jade.h b/drivers/isdn/hisax/jade.h --- a/drivers/isdn/hisax/jade.h Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/jade.h Wed Nov 27 14:36:28 2002 @@ -130,7 +130,6 @@ extern int JadeVersion(struct IsdnCardState *cs, char *s); extern void jade_sched_event(struct BCState *bcs, int event); extern void modejade(struct BCState *bcs, int mode, int bc); -extern void clear_pending_jade_ints(struct IsdnCardState *cs); extern void initjade(struct IsdnCardState *cs); #endif /* __JADE_H__ */ diff -Nru a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c --- a/drivers/isdn/hisax/jade_irq.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/jade_irq.c Wed Nov 27 14:36:27 2002 @@ -49,7 +49,6 @@ { u_char *ptr; struct IsdnCardState *cs = bcs->cs; - unsigned long flags; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "jade_empty_fifo"); @@ -63,10 +62,8 @@ } ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; bcs->hw.hscx.rcvidx += count; - spin_lock_irqsave(&jade_irq_lock, flags); READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); - spin_unlock_irqrestore(&jade_irq_lock, flags); if (cs->debug & L1_DEB_HSCX_FIFO) { char *t = bcs->blog; @@ -83,41 +80,17 @@ struct IsdnCardState *cs = bcs->cs; int more, count; int fifo_size = 32; - u_char *ptr; - unsigned long flags; + int hscx = bcs->hw.hscx.hscx; + unsigned char *p; - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "jade_fill_fifo"); - - if (!bcs->tx_skb) - return; - if (bcs->tx_skb->len <= 0) + p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); + if (!p) return; - more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; - if (bcs->tx_skb->len > fifo_size) { - more = !0; - count = fifo_size; - } else - count = bcs->tx_skb->len; - - waitforXFW(cs, bcs->hw.hscx.hscx); - spin_lock_irqsave(&jade_irq_lock, flags); - ptr = bcs->tx_skb->data; - skb_pull(bcs->tx_skb, count); - bcs->tx_cnt -= count; - bcs->hw.hscx.count += count; - WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); - WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME)); - spin_unlock_irqrestore(&jade_irq_lock, flags); - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "jade_fill_fifo %c cnt %d", - bcs->hw.hscx.hscx ? 'B' : 'A', count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } + waitforXFW(cs, hscx); + WRITEJADEFIFO(cs, hscx, p, count); + WriteJADECMDR(cs, hscx, jade_HDLC_XCMD, + more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME)); } @@ -164,7 +137,7 @@ } } bcs->hw.hscx.rcvidx = 0; - jade_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } if (val & 0x40) { /* RPF */ jade_empty_fifo(bcs, fifo_size); @@ -177,34 +150,20 @@ skb_queue_tail(&bcs->rqueue, skb); } bcs->hw.hscx.rcvidx = 0; - jade_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } } if (val & 0x10) { /* XPR */ - if (bcs->tx_skb) { - if (bcs->tx_skb->len) { - jade_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.hscx.count); - dev_kfree_skb_irq(bcs->tx_skb); - bcs->hw.hscx.count = 0; - bcs->tx_skb = NULL; - } - } - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->hw.hscx.count = 0; - test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); - jade_fill_fifo(bcs); - } else { - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - jade_sched_event(bcs, B_XMTBUFREADY); - } + xmit_xpr_b(bcs); } } +static void +reset_xmit(struct BCState *bcs) +{ + WriteJADECMDR(bcs->cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES); +} + static inline void jade_int_main(struct IsdnCardState *cs, u_char val, int jade) { @@ -216,23 +175,7 @@ val &= ~jadeISR_RFO; } if (val & jadeISR_XDU) { - /* relevant in HDLC mode only */ - /* don't reset XPR here */ - if (bcs->mode == 1) - jade_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.hscx.count); - bcs->tx_cnt += bcs->hw.hscx.count; - bcs->hw.hscx.count = 0; - } - WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES); - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val); - } + xmit_xdu_b(bcs, reset_xmit); } if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) { if (cs->debug & L1_DEB_HSCX) diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c --- a/drivers/isdn/hisax/mic.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/mic.c Wed Nov 27 14:36:31 2002 @@ -137,10 +137,7 @@ struct IsdnCardState *cs = dev_id; u_char val; - if (!cs) { - printk(KERN_WARNING "mic: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40); Start_HSCX: if (val) @@ -167,6 +164,7 @@ writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0); writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0); writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock(&cs->lock); } void @@ -188,8 +186,7 @@ release_io_mic(cs); return(0); case CARD_INIT: - inithscx(cs); /* /RTSA := ISAC RST */ - inithscxisac(cs, 3); + inithscxisac(cs); return(0); case CARD_TEST: return(0); diff -Nru a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c --- a/drivers/isdn/hisax/netjet.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/netjet.c Wed Nov 27 14:36:28 2002 @@ -432,8 +432,7 @@ memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } - bcs->event |= 1 << B_RCVBUFREADY; - schedule_work(&bcs->work); + sched_b_event(bcs, B_RCVBUFREADY); if (bcs->cs->debug & L1_DEB_RECEIVE_FRAME) printframe(bcs->cs, bcs->hw.tiger.rcvbuf, count, "rec"); @@ -760,11 +759,7 @@ if (!bcs->tx_skb) { debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt); } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; + xmit_complete_b(bcs); } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->hw.tiger.free = cnt - s_cnt; @@ -788,8 +783,7 @@ debugl1(bcs->cs, "tiger write_raw: fill rest %d", cnt - s_cnt); } - bcs->event |= 1 << B_XMTBUFREADY; - schedule_work(&bcs->work); + sched_b_event(bcs, B_XMTBUFREADY); } } } else if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) { @@ -838,36 +832,16 @@ tiger_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; - unsigned long flags; switch (pr) { case (PH_DATA | REQUEST): - spin_lock_irqsave(&netjet_lock, flags); - if (st->l1.bcs->tx_skb) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - spin_unlock_irqrestore(&netjet_lock, flags); - } else { - st->l1.bcs->tx_skb = skb; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - spin_unlock_irqrestore(&netjet_lock, flags); - } + xmit_data_req_b(st->l1.bcs, skb); break; case (PH_PULL | INDICATION): - if (st->l1.bcs->tx_skb) { - printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n"); - break; - } - spin_lock_irqsave(&netjet_lock, flags); - st->l1.bcs->tx_skb = skb; - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - spin_unlock_irqrestore(&netjet_lock, flags); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c --- a/drivers/isdn/hisax/niccy.c Wed Nov 27 14:36:29 2002 +++ b/drivers/isdn/hisax/niccy.c Wed Nov 27 14:36:29 2002 @@ -147,11 +147,8 @@ { struct IsdnCardState *cs = dev_id; u_char val; - - if (!cs) { - printk(KERN_WARNING "Niccy: Spurious interrupt!\n"); - return; - } + + spin_lock(&cs->lock); if (cs->subtyp == NICCY_PCI) { int ival; ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); @@ -185,6 +182,7 @@ writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0); writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0); writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0); + spin_unlock(&cs->lock); } void @@ -214,7 +212,7 @@ val |= PCI_IRQ_ENABLE; outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); } - inithscxisac(cs, 3); + inithscxisac(cs); } static int diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c --- a/drivers/isdn/hisax/nj_s.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/nj_s.c Wed Nov 27 14:36:28 2002 @@ -16,7 +16,6 @@ #include "netjet.h" const char *NETjet_S_revision = "$Revision: 2.7.6.6 $"; -static spinlock_t nj_s_lock = SPIN_LOCK_UNLOCKED; static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) { @@ -32,12 +31,8 @@ { struct IsdnCardState *cs = dev_id; u_char val, sval; - unsigned long flags; - if (!cs) { - printk(KERN_WARNING "NETjet-S: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) & NETJET_ISACIRQ)) { val = NETjet_ReadIC(cs, ISAC_ISTA); @@ -49,7 +44,6 @@ NETjet_WriteIC(cs, ISAC_MASK, 0x0); } } - spin_lock_irqsave(&nj_s_lock, flags); /* start new code 13/07/00 GE */ /* set bits in sval to indicate which page is free */ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < @@ -66,12 +60,7 @@ sval = sval | 0x01; if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ { - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - spin_unlock_irqrestore(&nj_s_lock, flags); - return; - } cs->hw.njet.irqstat0 = sval; - spin_unlock_irqrestore(&nj_s_lock, flags); if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) /* we have a read dma int */ @@ -81,10 +70,7 @@ /* we have a write dma int */ write_tiger(cs); /* end new code 13/07/00 GE */ - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - spin_unlock_irqrestore(&nj_s_lock, flags); - + } /* if (!testcnt--) { cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.base + NETJET_DMACTRL, @@ -92,15 +78,12 @@ byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); } */ + spin_unlock(&cs->lock); } static void reset_netjet_s(struct IsdnCardState *cs) { - long flags; - - save_flags(flags); - sti(); cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); @@ -110,7 +93,6 @@ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - restore_flags(flags); cs->hw.njet.auxd = 0; cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); @@ -130,10 +112,7 @@ return(0); case CARD_INIT: inittiger(cs); - clear_pending_isac_ints(cs); initisac(cs); - /* Reenable all IRQ */ - cs->writeisac(cs, ISAC_MASK, 0); return(0); case CARD_TEST: return(0); @@ -149,7 +128,6 @@ int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; - unsigned long flags; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" @@ -158,7 +136,6 @@ printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_NETJET_S) return(0); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); #if CONFIG_PCI @@ -200,9 +177,6 @@ cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - save_flags(flags); - sti(); - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); @@ -214,8 +188,6 @@ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - restore_flags(flags); cs->hw.njet.auxd = 0xC0; cs->hw.njet.dmactrl = 0; diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c --- a/drivers/isdn/hisax/nj_u.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/nj_u.c Wed Nov 27 14:36:28 2002 @@ -16,7 +16,6 @@ #include "netjet.h" const char *NETjet_U_revision = "$Revision: 2.8.6.6 $"; -static spinlock_t nj_u_lock = SPIN_LOCK_UNLOCKED; static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) { @@ -32,12 +31,8 @@ { struct IsdnCardState *cs = dev_id; u_char val, sval; - unsigned long flags; - if (!cs) { - printk(KERN_WARNING "NETspider-U: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) & NETJET_ISACIRQ)) { val = NETjet_ReadIC(cs, ICC_ISTA); @@ -49,7 +44,6 @@ NETjet_WriteIC(cs, ICC_MASK, 0x0); } } - spin_lock_irqsave(&nj_u_lock, flags); /* start new code 13/07/00 GE */ /* set bits in sval to indicate which page is free */ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < @@ -66,12 +60,7 @@ sval = sval | 0x01; if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ { - if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - spin_unlock_irqrestore(&nj_u_lock, flags); - return; - } cs->hw.njet.irqstat0 = sval; - spin_unlock_irqrestore(&nj_u_lock, flags); if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) /* we have a read dma int */ @@ -81,10 +70,7 @@ /* we have a write dma int */ write_tiger(cs); /* end new code 13/07/00 GE */ - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else - spin_unlock_irqrestore(&nj_u_lock, flags); - + } /* if (!testcnt--) { cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.base + NETJET_DMACTRL, @@ -92,15 +78,12 @@ byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); } */ + spin_unlock(&cs->lock); } static void reset_netjet_u(struct IsdnCardState *cs) { - long flags; - - save_flags(flags); - sti(); cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); @@ -110,7 +93,7 @@ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - restore_flags(flags); + cs->hw.njet.auxd = 0xC0; cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.auxa, 0); @@ -131,7 +114,6 @@ return(0); case CARD_INIT: inittiger(cs); - clear_pending_icc_ints(cs); initicc(cs); /* Reenable all IRQ */ cs->writeisac(cs, ICC_MASK, 0); @@ -150,7 +132,6 @@ int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; - long flags; #if CONFIG_PCI #endif #ifdef __BIG_ENDIAN @@ -160,7 +141,6 @@ printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_NETJET_U) return(0); - test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); #if CONFIG_PCI @@ -194,8 +174,6 @@ cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - save_flags(flags); - sti(); cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); @@ -207,8 +185,6 @@ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - restore_flags(flags); cs->hw.njet.auxd = 0xC0; cs->hw.njet.dmactrl = 0; diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c --- a/drivers/isdn/hisax/s0box.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/s0box.c Wed Nov 27 14:36:27 2002 @@ -156,10 +156,7 @@ u_char val; int count = 0; - if (!cs) { - printk(KERN_WARNING "Teles: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA); Start_HSCX: if (val) @@ -189,6 +186,7 @@ writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0); writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0); writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0); + spin_unlock(&cs->lock); } void @@ -207,7 +205,7 @@ release_io_s0box(cs); break; case CARD_INIT: - inithscxisac(cs, 3); + inithscxisac(cs); break; case CARD_TEST: break; diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c --- a/drivers/isdn/hisax/saphir.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/hisax/saphir.c Wed Nov 27 14:36:27 2002 @@ -133,10 +133,7 @@ struct IsdnCardState *cs = dev_id; u_char val; - if (!cs) { - printk(KERN_WARNING "saphir: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40); Start_HSCX: if (val) @@ -168,6 +165,7 @@ writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0); writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0); writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0); + spin_unlock(&cs->lock); } static void @@ -235,7 +233,7 @@ release_io_saphir(cs); return(0); case CARD_INIT: - inithscxisac(cs, 3); + inithscxisac(cs); return(0); case CARD_TEST: return(0); diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c --- a/drivers/isdn/hisax/sedlbauer.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/hisax/sedlbauer.c Wed Nov 27 14:36:32 2002 @@ -369,11 +369,7 @@ u_char val; int cnt = 5; - if (!cs) { - printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n"); - return; - } - + spin_lock(&cs->lock); val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT); Start_ISAR: if (val & ISAR_IRQSTA) @@ -402,6 +398,7 @@ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK); + spin_unlock(&cs->lock); } void @@ -479,17 +476,12 @@ return(0); case CARD_INIT: if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { - clear_pending_isac_ints(cs); writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0); initisac(cs); initisar(cs); - /* Reenable all IRQ */ - cs->writeisac(cs, ISAC_MASK, 0); - /* RESET Receiver and Transmitter */ - cs->writeisac(cs, ISAC_CMDR, 0x41); } else { - inithscxisac(cs, 3); + inithscxisac(cs); } return(0); case CARD_TEST: diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c --- a/drivers/isdn/hisax/sportster.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/hisax/sportster.c Wed Nov 27 14:36:28 2002 @@ -104,10 +104,7 @@ struct IsdnCardState *cs = dev_id; u_char val; - if (!cs) { - printk(KERN_WARNING "Sportster: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = READHSCX(cs, 1, HSCX_ISTA); Start_HSCX: if (val) @@ -130,6 +127,7 @@ } /* get a new irq impulse if there any pending */ bytein(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ +1); + spin_unlock(&cs->lock); } void @@ -168,10 +166,9 @@ release_io_sportster(cs); return(0); case CARD_INIT: - inithscxisac(cs, 1); + inithscxisac(cs); cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - inithscxisac(cs, 2); return(0); case CARD_TEST: return(0); diff -Nru a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c --- a/drivers/isdn/hisax/st5481_b.c Wed Nov 27 14:36:29 2002 +++ b/drivers/isdn/hisax/st5481_b.c Wed Nov 27 14:36:29 2002 @@ -82,12 +82,7 @@ if (!skb->len) { // Frame sent b_out->tx_skb = NULL; - B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize); - dev_kfree_skb_any(skb); - -/* if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */ -/* st5481B_sched_event(bcs, B_XMTBUFREADY); */ -/* } */ + B_L1L2(bcs, PH_DATA | CONFIRM, skb); } } else { if (bcs->mode == L1_MODE_TRANS) { diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c --- a/drivers/isdn/hisax/teleint.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/hisax/teleint.c Wed Nov 27 14:36:32 2002 @@ -172,10 +172,7 @@ struct IsdnCardState *cs = dev_id; u_char val; - if (!cs) { - printk(KERN_WARNING "TeleInt: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA); Start_ISAC: if (val) @@ -188,6 +185,7 @@ } writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF); writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0); + spin_unlock(&cs->lock); } static void @@ -242,11 +240,7 @@ return(0); case CARD_INIT: inithfc(cs); - clear_pending_isac_ints(cs); initisac(cs); - /* Reenable all IRQ */ - cs->writeisac(cs, ISAC_MASK, 0); - cs->writeisac(cs, ISAC_CMDR, 0x41); cs->hw.hfc.timer.expires = jiffies + 1; add_timer(&cs->hw.hfc.timer); return(0); diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c --- a/drivers/isdn/hisax/teles0.c Wed Nov 27 14:36:30 2002 +++ b/drivers/isdn/hisax/teles0.c Wed Nov 27 14:36:30 2002 @@ -150,10 +150,7 @@ u_char val; int count = 0; - if (!cs) { - printk(KERN_WARNING "Teles0: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); Start_HSCX: if (val) @@ -181,6 +178,7 @@ writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); + spin_unlock(&cs->lock); } void @@ -251,7 +249,7 @@ release_io_teles0(cs); return(0); case CARD_INIT: - inithscxisac(cs, 3); + inithscxisac(cs); return(0); case CARD_TEST: return(0); diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c --- a/drivers/isdn/hisax/teles3.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/hisax/teles3.c Wed Nov 27 14:36:32 2002 @@ -108,10 +108,7 @@ u_char val; int count = 0; - if (!cs) { - printk(KERN_WARNING "Teles: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA); Start_HSCX: if (val) @@ -141,6 +138,7 @@ writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0); writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0); writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0); + spin_unlock(&cs->lock); } inline static void @@ -238,7 +236,7 @@ release_io_teles3(cs); return(0); case CARD_INIT: - inithscxisac(cs, 3); + inithscxisac(cs); return(0); case CARD_TEST: return(0); diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c --- a/drivers/isdn/hisax/telespci.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/telespci.c Wed Nov 27 14:36:31 2002 @@ -233,10 +233,7 @@ struct IsdnCardState *cs = dev_id; u_char val; - if (!cs) { - printk(KERN_WARNING "TelesPCI: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); if (val) hscx_int_main(cs, val); @@ -252,6 +249,7 @@ writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); + spin_unlock(&cs->lock); } void @@ -270,7 +268,7 @@ release_io_telespci(cs); return(0); case CARD_INIT: - inithscxisac(cs, 3); + inithscxisac(cs); return(0); case CARD_TEST: return(0); diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c --- a/drivers/isdn/hisax/w6692.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/hisax/w6692.c Wed Nov 27 14:36:31 2002 @@ -43,8 +43,6 @@ const char *w6692_revision = "$Revision: 1.12.6.6 $"; -static spinlock_t w6692_lock = SPIN_LOCK_UNLOCKED; - #define DBUSY_TIMER_VALUE 80 static char *W6692Ver[] __initdata = @@ -134,25 +132,10 @@ */ } -void -W6692_sched_event(struct IsdnCardState *cs, int event) -{ - test_and_set_bit(event, &cs->event); - schedule_work(&cs->work); -} - -static void -W6692B_sched_event(struct BCState *bcs, int event) -{ - bcs->event |= 1 << event; - schedule_work(&bcs->work); -} - static void W6692_empty_fifo(struct IsdnCardState *cs, int count) { u_char *ptr; - unsigned long flags; if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) debugl1(cs, "W6692_empty_fifo"); @@ -167,10 +150,8 @@ } ptr = cs->rcvbuf + cs->rcvidx; cs->rcvidx += count; - spin_lock_irqsave(&w6692_lock, flags); cs->readW6692fifo(cs, ptr, count); cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); - spin_unlock_irqrestore(&w6692_lock, flags); if (cs->debug & L1_DEB_ISAC_FIFO) { char *t = cs->dlog; @@ -184,31 +165,14 @@ W6692_fill_fifo(struct IsdnCardState *cs) { int count, more; - u_char *ptr; - unsigned long flags; + unsigned char *p; - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, "W6692_fill_fifo"); - - if (!cs->tx_skb) + p = xmit_fill_fifo_d(cs, W_D_FIFO_THRESH, &count, &more); + if (!p) 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; - } - spin_lock_irqsave(&w6692_lock, flags); - ptr = cs->tx_skb->data; - skb_pull(cs->tx_skb, count); - cs->tx_cnt += count; - cs->writeW6692fifo(cs, ptr, count); + cs->writeW6692fifo(cs, p, count); cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME)); - spin_unlock_irqrestore(&w6692_lock , flags); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { debugl1(cs, "W6692_fill_fifo dbusytimer running"); del_timer(&cs->dbusytimer); @@ -216,13 +180,6 @@ 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 @@ -230,7 +187,6 @@ { u_char *ptr; struct IsdnCardState *cs = bcs->cs; - unsigned long flags; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "W6692B_empty_fifo"); @@ -244,10 +200,8 @@ } ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx; bcs->hw.w6692.rcvidx += count; - spin_lock_irqsave(&w6692_lock, flags); READW6692BFIFO(cs, bcs->channel, ptr, count); cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); - spin_unlock_irqrestore(&w6692_lock , flags); if (cs->debug & L1_DEB_HSCX_FIFO) { char *t = bcs->blog; @@ -263,41 +217,21 @@ { struct IsdnCardState *cs = bcs->cs; int more, count; - u_char *ptr; - unsigned long flags; - - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "W6692B_fill_fifo"); + unsigned char *p; - if (!bcs->tx_skb) - return; - if (bcs->tx_skb->len <= 0) + p = xmit_fill_fifo_b(bcs, W_B_FIFO_THRESH, &count, &more); + if (!p) 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; - - spin_lock_irqsave(&w6692_lock, flags); - ptr = bcs->tx_skb->data; - skb_pull(bcs->tx_skb, count); - bcs->tx_cnt -= count; - bcs->hw.w6692.count += count; - WRITEW6692BFIFO(cs, bcs->channel, ptr, count); + WRITEW6692BFIFO(cs, bcs->channel, p, count); cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME)); - spin_unlock_irqrestore(&w6692_lock , flags); - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; +} - t += sprintf(t, "W6692B_fill_fifo %c cnt %d", - bcs->channel + '1', count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } +static void +reset_xmit(struct BCState *bcs) +{ + bcs->cs->BC_Write_Reg(bcs->cs, bcs->channel, W_B_CMDR, + W_B_CMDR_XRST | W_B_CMDR_RACT); } static void @@ -345,7 +279,7 @@ } } bcs->hw.w6692.rcvidx = 0; - W6692B_sched_event(bcs, B_RCVBUFREADY); + sched_b_event(bcs, B_RCVBUFREADY); } if (val & W_B_EXI_RMR) { /* RMR */ W6692B_empty_fifo(bcs, W_B_FIFO_THRESH); @@ -358,48 +292,14 @@ skb_queue_tail(&bcs->rqueue, skb); } bcs->hw.w6692.rcvidx = 0; - W6692B_sched_event(bcs, B_RCVBUFREADY); + sched_b_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_irq(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); - } + xmit_xpr_b(bcs); } 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, 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); - } + xmit_xdu_b(bcs, reset_xmit); } } @@ -410,13 +310,10 @@ u_char val, exval, v1; struct sk_buff *skb; unsigned int count; - unsigned long flags; int icnt = 5; - if (!cs) { - printk(KERN_WARNING "W6692: Spurious interrupt!\n"); - return; - } + spin_lock(&cs->lock); + val = cs->readW6692(cs, W_ISTA); StartW6692: @@ -441,7 +338,6 @@ if (count == 0) count = W_D_FIFO_THRESH; W6692_empty_fifo(cs, count); - spin_lock_irqsave(&w6692_lock, flags); if ((count = cs->rcvidx) > 0) { cs->rcvidx = 0; if (!(skb = alloc_skb(count, GFP_ATOMIC))) @@ -451,36 +347,16 @@ skb_queue_tail(&cs->rq, skb); } } - spin_unlock_irqrestore(&w6692_lock , flags); } cs->rcvidx = 0; - W6692_sched_event(cs, D_RCVBUFREADY); + sched_d_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_irq(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); + xmit_xpr_d(cs); } - afterXFR: if (val & (W_INT_XINT0 | W_INT_XINT1)) { /* XINT0/1 - never */ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "W6692 spurious XINT!"); @@ -490,21 +366,7 @@ 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); - } + xmit_xdu_d(cs, NULL); } if (exval & W_D_EXI_RDOV) { /* RDOV */ debugl1(cs, "W6692 D-channel RDOV"); @@ -527,7 +389,7 @@ 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); + sched_d_event(cs, D_L1STATECHANGE); } if (v1 & W_CIR_SCC) { v1 = cs->readW6692(cs, W_SQR); @@ -558,6 +420,7 @@ printk(KERN_WARNING "W6692 IRQ LOOP\n"); cs->writeW6692(cs, W_IMASK, 0xff); } + spin_unlock(&cs->lock); } static void @@ -569,55 +432,13 @@ 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); - } + xmit_data_req_d(cs, skb); 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); + case (PH_PULL |INDICATION): + xmit_pull_ind_d(cs, skb); 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); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_d(st); break; case (HW_RESET | REQUEST): if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) @@ -652,7 +473,7 @@ 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); + sched_d_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -743,38 +564,16 @@ W6692_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; - unsigned long flags; switch (pr) { case (PH_DATA | REQUEST): - spin_lock_irqsave(&w6692_lock, flags); - if (st->l1.bcs->tx_skb) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - spin_unlock_irqrestore(&w6692_lock , 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; - spin_unlock_irqrestore(&w6692_lock , flags); - st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); - } + xmit_data_req_b(st->l1.bcs, skb); 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); + xmit_pull_ind_b(st->l1.bcs, skb); break; case (PH_PULL | REQUEST): - if (!st->l1.bcs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - L1L2(st, PH_PULL | CONFIRM, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + xmit_pull_req_b(st); break; case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); @@ -1072,6 +871,7 @@ cs->BC_Read_Reg = &ReadW6692B; cs->BC_Write_Reg = &WriteW6692B; cs->BC_Send_Data = &W6692B_fill_fifo; + cs->DC_Send_Data = &W6692_fill_fifo; cs->cardmsg = &w6692_card_msg; cs->irq_func = &W6692_interrupt; cs->irq_flags |= SA_SHIRQ; diff -Nru a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c --- a/drivers/isdn/i4l/isdn_common.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/i4l/isdn_common.c Wed Nov 27 14:36:28 2002 @@ -42,7 +42,46 @@ /* ====================================================================== */ -static struct isdn_slot slots[ISDN_MAX_CHANNELS]; +/* Description of hardware-level-driver */ +struct isdn_driver { + int di; + char id[20]; + atomic_t refcnt; + unsigned long flags; /* Misc driver Flags */ + unsigned long features; + int channels; /* Number of channels */ + wait_queue_head_t st_waitq; /* Wait-Queue for status-reads */ + int maxbufsize; /* Maximum Buffersize supported*/ + int stavail; /* Chars avail on Status-device*/ + isdn_if *interface; /* Interface to driver */ + char msn2eaz[10][ISDN_MSNLEN]; /* MSN->EAZ */ + spinlock_t lock; + struct isdn_slot *slots; + struct fsm_inst fi; +} driver; + +static void drv_destroy(struct isdn_driver *drv); + +static inline struct isdn_driver * +get_drv(struct isdn_driver *drv) +{ + printk("get_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), + atomic_read(&drv->refcnt) + 1); + atomic_inc(&drv->refcnt); + return drv; +} + +static inline void +put_drv(struct isdn_driver *drv) +{ + printk("put_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), + atomic_read(&drv->refcnt) - 1); + if (atomic_dec_and_test(&drv->refcnt)) { + drv_destroy(drv); + } +} + +/* ====================================================================== */ static struct fsm slot_fsm; static void slot_debug(struct fsm_inst *fi, char *fmt, ...); @@ -338,6 +377,7 @@ slot->ibytes = 0; slot->obytes = 0; slot->usage = ISDN_USAGE_NONE; + put_drv(slot->drv); isdn_info_update(); return 0; } @@ -396,7 +436,7 @@ char *p = buf; va_start(args, fmt); - p += sprintf(p, "slot %d(%d:%d): ", slot-slots, slot->di, slot->ch); + p += sprintf(p, "slot (%d:%d): ", slot->di, slot->ch); p += vsprintf(p, fmt, args); va_end(args); printk(KERN_DEBUG "%s\n", buf); @@ -422,23 +462,6 @@ #define DRV_FLAG_REJBUS 1 -/* Description of hardware-level-driver */ -struct isdn_driver { - int di; - char id[20]; - atomic_t refcnt; - unsigned long flags; /* Misc driver Flags */ - unsigned long features; - int locks; /* Number of locks */ - int channels; /* Number of channels */ - wait_queue_head_t st_waitq; /* Wait-Queue for status-reads */ - int maxbufsize; /* Maximum Buffersize supported*/ - int stavail; /* Chars avail on Status-device*/ - isdn_if *interface; /* Interface to driver */ - char msn2eaz[10][ISDN_MSNLEN]; /* MSN->EAZ */ - struct fsm_inst fi; -} driver; - static int __drv_command(struct isdn_driver *drv, isdn_ctrl *cmd); static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED; @@ -469,7 +492,7 @@ out: if (retval > 0) - slots->obytes += retval; + slot->obytes += retval; return retval; } @@ -504,28 +527,10 @@ static void drv_destroy(struct isdn_driver *drv) { + kfree(drv->slots); kfree(drv); } -static inline struct isdn_driver * -get_drv(struct isdn_driver *drv) -{ - printk("get_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), - atomic_read(&drv->refcnt) + 1); - atomic_inc(&drv->refcnt); - return drv; -} - -static inline void -put_drv(struct isdn_driver *drv) -{ - printk("put_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), - atomic_read(&drv->refcnt) - 1); - if (atomic_dec_and_test(&drv->refcnt)) { - drv_destroy(drv); - } -} - static struct isdn_driver * get_drv_by_nr(int di) { @@ -577,10 +582,9 @@ /* * driver state machine */ -static int isdn_add_channels(struct isdn_driver *, int, int, int); +static int isdn_add_channels(struct isdn_driver *, int); static void isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb); static int isdn_status_callback(isdn_ctrl * c); -static int isdn_dc2minor(int di, int ch); static void isdn_v110_add_features(struct isdn_driver *drv); @@ -623,30 +627,12 @@ { struct isdn_driver *drv = fi->userdata; unsigned long flags; - int i; spin_lock_irqsave(&drivers_lock, flags); drivers[drv->di] = NULL; spin_unlock_irqrestore(&drivers_lock, flags); put_drv(drv); - while (drv->locks > 0) { - isdn_ctrl cmd; - cmd.driver = drv->di; - cmd.arg = 0; - cmd.command = ISDN_CMD_UNLOCK; - __drv_command(drv, &cmd); - drv->locks--; - } - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (slots[i].di == drv->di) { - slots[i].di = -1; - slots[i].drv = NULL; - slots[i].ch = -1; - slots[i].usage &= ~ISDN_USAGE_DISABLED; - isdn_unregister_devfs(i); - } - } dev->channels -= drv->channels; isdn_info_update(); @@ -654,16 +640,6 @@ } static int -drv_stat_addch(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - isdn_ctrl *c = arg; - - isdn_add_channels(drv, c->driver, c->arg, 1); - isdn_info_update(); -} - -static int drv_stat_stavail(struct fsm_inst *fi, int pr, void *arg) { struct isdn_driver *drv = fi->userdata; @@ -681,13 +657,9 @@ { struct isdn_driver *drv = fi->userdata; isdn_ctrl *c = arg; - int sl = isdn_dc2minor(drv->di, c->arg & 0xff); + int ch = c->arg & 0xff; - if (sl < 0) { - isdn_BUG(); - return 1; - } - return fsm_event(&slots[sl].fi, pr, arg); + return fsm_event(&drv->slots[ch].fi, pr, arg); } static struct fsm_node drv_fn_tbl[] = { @@ -695,7 +667,6 @@ { ST_DRV_LOADED, EV_STAT_RUN, drv_stat_run }, { ST_DRV_LOADED, EV_STAT_STAVAIL, drv_stat_stavail }, - { ST_DRV_LOADED, EV_STAT_ADDCH, drv_stat_addch }, { ST_DRV_LOADED, EV_STAT_UNLOAD, drv_stat_unload }, { ST_DRV_RUNNING, EV_STAT_STOP, drv_stat_stop }, @@ -745,7 +716,6 @@ isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb) { struct isdn_driver *drv; - int sl; drv = get_drv_by_nr(di); if (!drv) { @@ -759,12 +729,7 @@ isdn_BUG(); goto out; } - sl = isdn_dc2minor(di, ch); - if (sl < 0) { - isdn_BUG(); - goto out; - } - if (fsm_event(&slots[sl].fi, EV_DATA_IND, skb)) + if (fsm_event(&drv->slots[ch].fi, EV_DATA_IND, skb)) dev_kfree_skb(skb); out: put_drv(drv); @@ -942,6 +907,8 @@ memset(drv, 0, sizeof(*drv)); atomic_set(&drv->refcnt, 0); + spin_lock_init(&drv->lock); + init_waitqueue_head(&drv->st_waitq); drv->fi.fsm = &drv_fsm; drv->fi.state = ST_DRV_NULL; drv->fi.debug = 1; @@ -963,7 +930,7 @@ goto fail_unlock; strcpy(drv->id, iif->id); - if (isdn_add_channels(drv, drvidx, iif->channels, 0)) + if (isdn_add_channels(drv, iif->channels)) goto fail_unlock; drv->di = drvidx; @@ -993,23 +960,14 @@ static void isdn_lock_driver(struct isdn_driver *drv) { - isdn_ctrl cmd; - - cmd.driver = drv->di; - cmd.arg = 0; - cmd.command = ISDN_CMD_LOCK; - __drv_command(drv, &cmd); + // FIXME don't ignore return value + try_module_get(drv->interface->owner); } static void isdn_unlock_driver(struct isdn_driver *drv) { - isdn_ctrl cmd; - - cmd.driver = drv->di; - cmd.arg = 0; - cmd.command = ISDN_CMD_UNLOCK; - __drv_command(drv, &cmd); + module_put(drv->interface->owner); } #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) @@ -1121,24 +1079,10 @@ } static int -isdn_dc2minor(int di, int ch) -{ - int i; - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (slots[i].ch == ch && slots[i].di == di) - return i; - return -1; -} - -static int __drv_command(struct isdn_driver *drv, isdn_ctrl *c) { #ifdef ISDN_DEBUG_COMMAND switch (c->command) { - case ISDN_CMD_LOCK: - printk(KERN_DEBUG "ISDN_CMD_LOCK %d/%ld\n", c->driver, c->arg & 0xff); break; - case ISDN_CMD_UNLOCK: - printk(KERN_DEBUG "ISDN_CMD_UNLOCK %d/%ld\n", c->driver, c->arg & 0xff); break; case ISDN_CMD_SETL2: printk(KERN_DEBUG "ISDN_CMD_SETL2 %d/%ld\n", c->driver, c->arg & 0xff); break; case ISDN_CMD_SETL3: @@ -1177,19 +1121,14 @@ #include int -isdn_capi_rec_hl_msg(capi_msg *cm) { - - int di; - int ch; - - di = (cm->adr.Controller & 0x7f) -1; - ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f); +isdn_capi_rec_hl_msg(capi_msg *cm) +{ switch(cm->Command) { - case CAPI_FACILITY: - /* in the moment only handled in tty */ - return(isdn_tty_capi_facility(cm)); - default: - return(-1); + case CAPI_FACILITY: + /* in the moment only handled in tty */ + return isdn_tty_capi_facility(cm); + default: + return -1; } } @@ -1206,64 +1145,112 @@ return v; } -static __inline int -isdn_minor2drv(int minor) +static struct isdn_slot * +get_slot_by_minor(int minor) { - return slots[minor].di; + int di, ch; + struct isdn_driver *drv; + + for (di = 0; di < ISDN_MAX_CHANNELS; di++) { + drv = get_drv_by_nr(di); + if (!drv) + continue; + + for (ch = 0; ch < drv->channels; ch++) { + if (minor-- == 0) + goto found; + } + put_drv(drv); + } + return NULL; + + found: + return drv->slots + ch; } -static __inline int -isdn_minor2chan(int minor) +static inline void +put_slot(struct isdn_slot *slot) { - return slots[minor].ch; + put_drv(slot->drv); } static char * isdn_statstr(void) { static char istatbuf[2048]; + struct isdn_slot *slot; char *p; int i; sprintf(istatbuf, "idmap:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%s ", (slots[i].di < 0) ? "-" : isdn_drv_drvid(slots[i].di)); + slot = get_slot_by_minor(i); + if (slot) { + sprintf(p, "%s ", slot->drv->id); + put_slot(slot); + } else { + sprintf(p, "- "); + } p = istatbuf + strlen(istatbuf); } sprintf(p, "\nchmap:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%d ", slots[i].ch); + slot = get_slot_by_minor(i); + if (slot) { + sprintf(p, "%d ", slot->ch); + put_slot(slot); + } else { + sprintf(p, "-1 "); + } p = istatbuf + strlen(istatbuf); } sprintf(p, "\ndrmap:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%d ", slots[i].di); - p = istatbuf + strlen(istatbuf); + slot = get_slot_by_minor(i); + if (slot) { + sprintf(p, "%d ", slot->di); + put_slot(slot); + } else { + sprintf(p, "-1 "); + } } sprintf(p, "\nusage:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%d ", slots[i].usage); + slot = get_slot_by_minor(i); + if (slot) { + sprintf(p, "%d ", slot->usage); + put_slot(slot); + } else { + sprintf(p, "0 "); + } p = istatbuf + strlen(istatbuf); } sprintf(p, "\nflags:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_DRIVERS; i++) { - if (drivers[i]) { + slot = get_slot_by_minor(i); + if (slot) { sprintf(p, "0 "); - p = istatbuf + strlen(istatbuf); + put_slot(slot); } else { sprintf(p, "? "); - p = istatbuf + strlen(istatbuf); } + p = istatbuf + strlen(istatbuf); } sprintf(p, "\nphone:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%s ", slots[i].num); + slot = get_slot_by_minor(i); + if (slot) { + sprintf(p, "%s ", slot->num); + put_slot(slot); + } else { + sprintf(p, " "); + } p = istatbuf + strlen(istatbuf); } sprintf(p, "\n"); @@ -1392,7 +1379,9 @@ static int isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) { + static unsigned long zero_ul = 0UL; int ret; + struct isdn_slot *slot; switch (cmd) { case IIOCGETDVR: @@ -1407,8 +1396,15 @@ sizeof(ulong) * ISDN_MAX_CHANNELS * 2))) return ret; for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - put_user(slots[i].ibytes, p++); - put_user(slots[i].obytes, p++); + slot = get_slot_by_minor(i); + if (slot) { + put_user(slot->ibytes, p++); + put_user(slot->obytes, p++); + put_slot(slot); + } else { + put_user(zero_ul, p++); + put_user(zero_ul, p++); + } } return 0; } else @@ -1441,29 +1437,27 @@ isdn_ctrl_open(struct inode *ino, struct file *file) { unsigned int minor = minor(ino->i_rdev); - int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); - struct isdn_driver *drv; + struct isdn_slot *slot = get_slot_by_minor(minor - ISDN_MINOR_CTRL); - drv = get_drv_by_nr(drvidx); - if (!drv) + if (!slot) return -ENODEV; - isdn_lock_driver(drv); + isdn_lock_driver(slot->drv); + file->private_data = slot; - file->private_data = drv; return 0; } static int isdn_ctrl_release(struct inode *ino, struct file *file) { - struct isdn_driver *drv = file->private_data; + struct isdn_slot *slot = file->private_data; if (dev->profd == current) dev->profd = NULL; - isdn_unlock_driver(drv); - put_drv(drv); + isdn_unlock_driver(slot->drv); + put_slot(slot); return 0; } @@ -1471,24 +1465,22 @@ static ssize_t isdn_ctrl_read(struct file *file, char *buf, size_t count, loff_t * off) { - struct isdn_driver *drv = file->private_data; - unsigned int minor = minor(file->f_dentry->d_inode->i_rdev); + struct isdn_slot *slot = file->private_data; DECLARE_WAITQUEUE(wait, current); unsigned long flags; int len = 0; - if (off != &file->f_pos) return -ESPIPE; - if (!drv->interface->readstat) { + if (!slot->drv->interface->readstat) { isdn_BUG(); return 0; } - add_wait_queue(&drv->st_waitq, &wait); + add_wait_queue(&slot->drv->st_waitq, &wait); for (;;) { spin_lock_irqsave(&stat_lock, flags); - len = drv->stavail; + len = slot->drv->stavail; spin_unlock_irqrestore(&stat_lock, flags); if (len > 0) break; @@ -1503,7 +1495,7 @@ schedule(); } __set_current_state(TASK_RUNNING); - remove_wait_queue(&drv->st_waitq, &wait); + remove_wait_queue(&slot->drv->st_waitq, &wait); if (len < 0) return len; @@ -1511,15 +1503,15 @@ if (count > len) count = len; - len = drv->interface->readstat(buf, count, 1, drv->di, - isdn_minor2chan(minor)); + len = slot->drv->interface->readstat(buf, count, 1, slot->di, + slot->ch); spin_lock_irqsave(&stat_lock, flags); if (len) { - drv->stavail -= len; + slot->drv->stavail -= len; } else { isdn_BUG(); - drv->stavail = 0; + slot->drv->stavail = 0; } spin_unlock_irqrestore(&stat_lock, flags); @@ -1530,20 +1522,19 @@ static ssize_t isdn_ctrl_write(struct file *file, const char *buf, size_t count, loff_t *off) { - struct isdn_driver *drv = file->private_data; - unsigned int minor = minor(file->f_dentry->d_inode->i_rdev); + struct isdn_slot *slot = file->private_data; int retval; - if (off != &file->f_pos) - return -ESPIPE; - - if (!drv->interface->writecmd) { + if (off != &file->f_pos) { + retval = -ESPIPE; + goto out; + } + if (!slot->drv->interface->writecmd) { retval = -EINVAL; goto out; } - retval = drv->interface-> - writecmd(buf, count, 1, drv->di, - isdn_minor2chan(minor - ISDN_MINOR_CTRL)); + retval = slot->drv->interface->writecmd(buf, count, 1, slot->di, + slot->ch); out: return retval; @@ -1552,12 +1543,12 @@ static unsigned int isdn_ctrl_poll(struct file *file, poll_table *wait) { - struct isdn_driver *drv = file->private_data; + struct isdn_slot *slot = file->private_data; unsigned int mask = 0; - poll_wait(file, &drv->st_waitq, wait); + poll_wait(file, &slot->drv->st_waitq, wait); mask = POLLOUT | POLLWRNORM; - if (drv->stavail) + if (slot->drv->stavail) mask |= POLLIN | POLLRDNORM; return mask; @@ -1869,46 +1860,61 @@ isdn_get_free_slot(int usage, int l2_proto, int l3_proto, int pre_dev, int pre_chan, char *msn) { + struct isdn_driver *drv; struct isdn_slot *slot; - int i; + int di, ch; unsigned long flags; unsigned long features; - save_flags(flags); - cli(); features = ((1 << l2_proto) | (0x10000 << l3_proto)); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - slot = &slots[i]; - - if (!slot->drv || slot->drv->fi.state != ST_DRV_RUNNING) - continue; - - if (!USG_NONE(slots[i].usage)) - continue; - - if (slots[i].usage & ISDN_USAGE_DISABLED) + for (di = 0; di < ISDN_MAX_DRIVERS; di++) { + if (pre_dev >= 0 && pre_dev != di) continue; - if (slots[i].di == -1) + drv = get_drv_by_nr(di); + if (!drv) continue; - if (strcmp(isdn_map_eaz2msn(msn, slot->di), "-") == 0) - continue; + if (drv->fi.state != ST_DRV_RUNNING) + goto put; - if (!(drivers[slot->di]->features & features) == features) - continue; + if ((drv->features & features) != features) + goto put; + + spin_lock_irqsave(&drv->lock, flags); + for (ch = 0; ch < drv->channels; ch++) { + if (pre_chan >= 0 && pre_chan != ch) + continue; + + slot = &drv->slots[ch]; + + if (!USG_NONE(slot->usage)) + continue; + + if (slot->usage & ISDN_USAGE_DISABLED) + continue; - if (pre_dev < 0 || pre_chan < 0 || - (pre_dev == slot->di && pre_chan == slot->ch)) { - slot->usage = usage; - isdn_info_update(); - fsm_event(&slot->fi, EV_SLOT_BIND, NULL); - return slot; + if (strcmp(isdn_map_eaz2msn(msn, drv->di), "-") == 0) + continue; + + goto found; + } + spin_unlock_irqrestore(&drv->lock, flags); + + put: + put_drv(drv); } - restore_flags(flags); return NULL; + + found: + slot->usage = usage; + spin_unlock_irqrestore(&drv->lock, flags); + + isdn_info_update(); + fsm_event(&slot->fi, EV_SLOT_BIND, NULL); + return slot; } /* @@ -1930,38 +1936,38 @@ } static int -isdn_add_channels(struct isdn_driver *d, int drvidx, int n, int adding) +isdn_add_channels(struct isdn_driver *drv, int n) { - int j, k, m; - ulong flags; - - init_waitqueue_head(&d->st_waitq); - - if (n < 1) return 0; + struct isdn_slot *slot; + int ch; - m = (adding) ? d->channels + n : n; + if (n < 1) + return 0; if (dev->channels + n > ISDN_MAX_CHANNELS) { printk(KERN_WARNING "register_isdn: Max. %d channels supported\n", ISDN_MAX_CHANNELS); - return -1; + return -EBUSY; } dev->channels += n; - save_flags(flags); - cli(); - for (j = d->channels; j < m; j++) { - for (k = 0; k < ISDN_MAX_CHANNELS; k++) { - if (slots[k].ch < 0) { - slots[k].ch = j; - slots[k].di = drvidx; - slots[k].drv = d; - isdn_register_devfs(k); - break; - } - } + drv->slots = kmalloc(sizeof(struct isdn_slot) * n, GFP_KERNEL); + if (!drv->slots) + return -ENOMEM; + + for (ch = 0; ch < n; ch++) { + slot = drv->slots + ch; + + slot->ch = ch; + slot->di = drv->di; + slot->drv = drv; + strcpy(slot->num, "???"); + slot->fi.fsm = &slot_fsm; + slot->fi.state = ST_SLOT_NULL; + slot->fi.debug = 1; + slot->fi.userdata = slot; + slot->fi.printdebug = slot_debug; } - restore_flags(flags); - d->channels = m; + drv->channels = n; return 0; } @@ -2242,7 +2248,6 @@ */ static int __init isdn_init(void) { - int i; int retval; retval = fsm_new(&slot_fsm); @@ -2261,16 +2266,7 @@ memset(dev, 0, sizeof(*dev)); init_MUTEX(&dev->sem); init_waitqueue_head(&dev->info_waitq); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - slots[i].di = -1; - slots[i].ch = -1; - strcpy(slots[i].num, "???"); - slots[i].fi.fsm = &slot_fsm; - slots[i].fi.state = ST_SLOT_NULL; - slots[i].fi.debug = 1; - slots[i].fi.userdata = slots + i; - slots[i].fi.printdebug = slot_debug; - } + retval = register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops); if (retval) { printk(KERN_WARNING "isdn: Could not register control devices\n"); diff -Nru a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c --- a/drivers/isdn/icn/icn.c Wed Nov 27 14:36:32 2002 +++ b/drivers/isdn/icn/icn.c Wed Nov 27 14:36:32 2002 @@ -1441,42 +1441,10 @@ card->l2_proto[a & 255] = (a >> 8); } break; - case ISDN_CMD_GETL2: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ICN_BCH) - return card->l2_proto[c->arg & 255]; - else - return -ENODEV; case ISDN_CMD_SETL3: if (!card->flags & ICN_FLAGS_RUNNING) return -ENODEV; return 0; - case ISDN_CMD_GETL3: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ICN_BCH) - return ISDN_PROTO_L3_TRANS; - else - return -ENODEV; - case ISDN_CMD_GETEAZ: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_SETSIL: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_GETSIL: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - break; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - break; default: return -EINVAL; } @@ -1577,6 +1545,7 @@ } memset((char *) card, 0, sizeof(icn_card)); card->port = port; + SET_MODULE_OWNER(&card->interface); card->interface.hl_hdrlen = 1; card->interface.channels = ICN_BCH; card->interface.maxbufsize = 4000; diff -Nru a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c --- a/drivers/isdn/isdnloop/isdnloop.c Wed Nov 27 14:36:27 2002 +++ b/drivers/isdn/isdnloop/isdnloop.c Wed Nov 27 14:36:27 2002 @@ -1345,42 +1345,10 @@ card->l2_proto[a & 255] = (a >> 8); } break; - case ISDN_CMD_GETL2: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ISDNLOOP_BCH) - return card->l2_proto[c->arg & 255]; - else - return -ENODEV; case ISDN_CMD_SETL3: if (!card->flags & ISDNLOOP_FLAGS_RUNNING) return -ENODEV; return 0; - case ISDN_CMD_GETL3: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ISDNLOOP_BCH) - return ISDN_PROTO_L3_TRANS; - else - return -ENODEV; - case ISDN_CMD_GETEAZ: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_SETSIL: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_GETSIL: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - break; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - break; default: return -EINVAL; } @@ -1482,6 +1450,7 @@ return (isdnloop_card *) 0; } memset((char *) card, 0, sizeof(isdnloop_card)); + SET_MODULE_OWNER(&card->interface); card->interface.channels = ISDNLOOP_BCH; card->interface.hl_hdrlen = 1; /* scratch area for storing ack flag*/ card->interface.maxbufsize = 4000; diff -Nru a/drivers/isdn/pcbit/capi.h b/drivers/isdn/pcbit/capi.h --- a/drivers/isdn/pcbit/capi.h Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/pcbit/capi.h Wed Nov 27 14:36:31 2002 @@ -63,8 +63,7 @@ extern int capi_decode_debug_188(u_char *hdr, ushort hdrlen); #endif -extern __inline__ -struct pcbit_chan * +static inline struct pcbit_chan * capi_channel(struct pcbit_dev *dev, struct sk_buff *skb) { ushort callref; diff -Nru a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c --- a/drivers/isdn/pcbit/drv.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/pcbit/drv.c Wed Nov 27 14:36:31 2002 @@ -171,9 +171,10 @@ dev->dev_if = dev_if; - dev_if->channels = 2; - + SET_MODULE_OWNER(dev_if); + dev_if->channels = 2; + dev_if->features = (ISDN_FEATURE_P_EURO | ISDN_FEATURE_L3_TRANS | ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS ); @@ -276,15 +277,6 @@ case ISDN_CMD_SETL2: chan->proto = (ctl->arg >> 8); break; - case ISDN_CMD_GETL2: - return chan->proto; - break; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - break; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - break; case ISDN_CMD_CLREAZ: pcbit_clear_msn(dev); break; @@ -294,14 +286,6 @@ case ISDN_CMD_SETL3: if ((ctl->arg >> 8) != ISDN_PROTO_L3_TRANS) printk(KERN_DEBUG "L3 protocol unknown\n"); - break; - case ISDN_CMD_GETL3: - return ISDN_PROTO_L3_TRANS; - break; - case ISDN_CMD_GETEAZ: - case ISDN_CMD_SETSIL: - case ISDN_CMD_GETSIL: - printk(KERN_DEBUG "pcbit_command: code %d not implemented yet\n", ctl->command); break; default: printk(KERN_DEBUG "pcbit_command: unknown command\n"); diff -Nru a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c --- a/drivers/isdn/sc/command.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/sc/command.c Wed Nov 27 14:36:28 2002 @@ -27,15 +27,8 @@ int answer(int card, unsigned long channel); int clreaz(int card, unsigned long channel); int seteaz(int card, unsigned long channel, char *); -int geteaz(int card, unsigned long channel, char *); -int setsil(int card, unsigned long channel, char *); -int getsil(int card, unsigned long channel, char *); int setl2(int card, unsigned long arg); -int getl2(int card, unsigned long arg); int setl3(int card, unsigned long arg); -int getl3(int card, unsigned long arg); -int lock(void); -int unlock(void); int acceptb(int card, unsigned long channel); extern int cinst; @@ -63,17 +56,17 @@ "ISDN_CMD_HANGUP", "ISDN_CMD_CLREAZ", "ISDN_CMD_SETEAZ", - "ISDN_CMD_GETEAZ", - "ISDN_CMD_SETSIL", - "ISDN_CMD_GETSIL", + NULL, + NULL, + NULL, "ISDN_CMD_SETL2", - "ISDN_CMD_GETL2", + NULL, "ISDN_CMD_SETL3", - "ISDN_CMD_GETL3", - "ISDN_CMD_LOCK", - "ISDN_CMD_UNLOCK", - "ISDN_CMD_SUSPEND", - "ISDN_CMD_RESUME" }; + NULL, + NULL, + NULL, + NULL, + NULL, }; /* * Translates ISDN4Linux protocol codes to strings for debug messages @@ -144,24 +137,10 @@ return clreaz(card, cmd->arg); case ISDN_CMD_SETEAZ: return seteaz(card, cmd->arg, cmd->parm.num); - case ISDN_CMD_GETEAZ: - return geteaz(card, cmd->arg, cmd->parm.num); - case ISDN_CMD_SETSIL: - return setsil(card, cmd->arg, cmd->parm.num); - case ISDN_CMD_GETSIL: - return getsil(card, cmd->arg, cmd->parm.num); case ISDN_CMD_SETL2: return setl2(card, cmd->arg); - case ISDN_CMD_GETL2: - return getl2(card, cmd->arg); case ISDN_CMD_SETL3: return setl3(card, cmd->arg); - case ISDN_CMD_GETL3: - return getl3(card, cmd->arg); - case ISDN_CMD_LOCK: - return lock(); - case ISDN_CMD_UNLOCK: - return unlock(); default: return -EINVAL; } @@ -358,23 +337,6 @@ } /* - * Get the layer 2 protocol - */ -int getl2(int card, unsigned long channel) { - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - pr_debug("%s: Level 2 protocol for channel %d reported as %s\n", - adapter[card]->devicename, channel+1, - l2protos[adapter[card]->channel[channel].l2_proto]); - - return adapter[card]->channel[channel].l2_proto; -} - -/* * Set the layer 3 protocol */ int setl3(int card, unsigned long channel) @@ -392,23 +354,6 @@ return 0; } -/* - * Get the layer 3 protocol - */ -int getl3(int card, unsigned long arg) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - pr_debug("%s: Level 3 protocol for channel %d reported as %s\n", - adapter[card]->devicename, arg+1, - l3protos[adapter[card]->channel[arg].l3_proto]); - return adapter[card]->channel[arg].l3_proto; -} - - int acceptb(int card, unsigned long channel) { if(!IS_VALID_CARD(card)) { @@ -454,61 +399,6 @@ pr_debug("%s: EAZ list for channel %d set to: %s\n", adapter[card]->devicename, arg+1, adapter[card]->channel[arg].eazlist); - return 0; -} - -int geteaz(int card, unsigned long arg, char *num) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - strcpy(num, adapter[card]->channel[arg].eazlist); - pr_debug("%s: EAZ List for channel %d reported: %s\n", - adapter[card]->devicename, arg+1, - adapter[card]->channel[arg].eazlist); - return 0; -} - -int setsil(int card, unsigned long arg, char *num) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - strcpy(adapter[card]->channel[arg].sillist, num); - pr_debug("%s: Service Indicators for channel %d set: %s\n", - adapter[card]->devicename, arg+1, - adapter[card]->channel[arg].sillist); - return 0; -} - -int getsil(int card, unsigned long arg, char *num) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - strcpy(num, adapter[card]->channel[arg].sillist); - pr_debug("%s: SIL for channel %d reported: %s\n", - adapter[card]->devicename, arg+1, - adapter[card]->channel[arg].sillist); - return 0; -} - - -int lock() -{ - MOD_INC_USE_COUNT; - return 0; -} - -int unlock() -{ - MOD_DEC_USE_COUNT; return 0; } diff -Nru a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c --- a/drivers/isdn/sc/init.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/sc/init.c Wed Nov 27 14:36:31 2002 @@ -6,6 +6,7 @@ #include #include +#include #include "includes.h" #include "hardware.h" #include "card.h" @@ -286,6 +287,7 @@ } memset(interface, 0, sizeof(isdn_if)); + SET_MODULE_OWNER(interface); interface->hl_hdrlen = 0; interface->channels = channels; interface->maxbufsize = BUFFER_SIZE; diff -Nru a/drivers/isdn/tpam/tpam_commands.c b/drivers/isdn/tpam/tpam_commands.c --- a/drivers/isdn/tpam/tpam_commands.c Wed Nov 27 14:36:28 2002 +++ b/drivers/isdn/tpam/tpam_commands.c Wed Nov 27 14:36:28 2002 @@ -27,7 +27,6 @@ static int tpam_command_ioctl_loopmode(tpam_card *, u8); static int tpam_command_dial(tpam_card *, u32, u8 *); static int tpam_command_setl2(tpam_card *, u32, u8); -static int tpam_command_getl2(tpam_card *, u32); static int tpam_command_acceptd(tpam_card *, u32); static int tpam_command_acceptb(tpam_card *, u32); static int tpam_command_hangup(tpam_card *, u32); @@ -93,14 +92,6 @@ case ISDN_CMD_SETL2: return tpam_command_setl2(card, c->arg & 0xff, c->arg >> 8); - case ISDN_CMD_GETL2: - return tpam_command_getl2(card, c->arg); - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - return 0; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - return 0; case ISDN_CMD_PROCEED: return tpam_command_proceed(card, c->arg); default: @@ -368,30 +359,6 @@ return -EINVAL; } return 0; -} - -/* - * Return the level2 protocol (modem or HDLC). - * - * card: the board - * channel: the channel number - * - * Return: ISDN_PROTO_L2_HDLC/MODEM if OK, <0 if error. - */ -static int tpam_command_getl2(tpam_card *card, u32 channel) { - - dprintk("TurboPAM(tpam_command_getl2): card=%d, channel=%lu\n", - card->id, (unsigned long)channel); - - /* board must be running */ - if (!card->running) - return -ENODEV; - - /* return the current mode */ - if (card->channels[channel].realhdlc) - return ISDN_PROTO_L2_HDLC; - else - return ISDN_PROTO_L2_MODEM; } /* diff -Nru a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c --- a/drivers/isdn/tpam/tpam_main.c Wed Nov 27 14:36:31 2002 +++ b/drivers/isdn/tpam/tpam_main.c Wed Nov 27 14:36:31 2002 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -131,6 +132,7 @@ copy_to_pam_dword(card, (void *)0x01840070, 0x00000010); /* fill the ISDN link layer structure */ + SET_MODULE_OWNER(&card->interface); card->interface.channels = TPAM_NBCHANNEL; card->interface.maxbufsize = TPAM_MAXBUFSIZE; card->interface.features = diff -Nru a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c --- a/drivers/macintosh/via-pmu.c Wed Nov 27 14:36:31 2002 +++ b/drivers/macintosh/via-pmu.c Wed Nov 27 14:36:31 2002 @@ -2605,7 +2605,7 @@ disable_kernel_backlight--; spin_unlock_irqrestore(&pmu_lock, flags); } -#endif defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) +#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ kfree(pp); } unlock_kernel(); diff -Nru a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c --- a/drivers/md/dm-ioctl.c Wed Nov 27 14:36:28 2002 +++ b/drivers/md/dm-ioctl.c Wed Nov 27 14:36:28 2002 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -16,6 +15,8 @@ #include #include +#include + #define DM_DRIVER_EMAIL "dm@uk.sistina.com" /*----------------------------------------------------------------- @@ -177,6 +178,7 @@ static int register_with_devfs(struct hash_cell *hc) { struct gendisk *disk = dm_disk(hc->md); + hc->devfs_entry = devfs_register(_dev_dir, hc->name, DEVFS_FL_CURRENT_OWNER, disk->major, disk->first_minor, @@ -459,11 +461,11 @@ if (!bdev) return -ENXIO; - if (disk->policy) - param->flags |= DM_READONLY_FLAG; - param->open_count = bdev->bd_openers; bdput(bdev); + + if (disk->policy) + param->flags |= DM_READONLY_FLAG; table = dm_get_table(md); param->target_count = dm_table_get_num_targets(table); diff -Nru a/drivers/md/dm-table.c b/drivers/md/dm-table.c --- a/drivers/md/dm-table.c Wed Nov 27 14:36:32 2002 +++ b/drivers/md/dm-table.c Wed Nov 27 14:36:32 2002 @@ -146,6 +146,25 @@ return 0; } +static void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size) +{ + unsigned long size; + void *addr; + + /* + * Check that we're not going to overflow. + */ + if (nmemb > (ULONG_MAX / elem_size)) + return NULL; + + size = nmemb * elem_size; + addr = vmalloc(size); + if (addr) + memset(addr, 0, size); + + return addr; +} + /* * highs, and targets are managed as dynamic arrays during a * table load. @@ -159,9 +178,8 @@ /* * Allocate both the target array and offset array at once. */ - n_highs = (sector_t *) vcalloc(sizeof(struct dm_target) + - sizeof(sector_t), - num); + n_highs = (sector_t *) dm_vcalloc(sizeof(struct dm_target) + + sizeof(sector_t), num); if (!n_highs) return -ENOMEM; @@ -624,7 +642,7 @@ total += t->counts[i]; } - indexes = (sector_t *) vcalloc(total, (unsigned long) NODE_SIZE); + indexes = (sector_t *) dm_vcalloc(total, (unsigned long) NODE_SIZE); if (!indexes) return -ENOMEM; diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c --- a/drivers/md/dm.c Wed Nov 27 14:36:31 2002 +++ b/drivers/md/dm.c Wed Nov 27 14:36:31 2002 @@ -15,7 +15,7 @@ #include static const char *_name = DM_NAME; -#define MAX_DEVICES 256 +#define MAX_DEVICES (1 << KDEV_MINOR_BITS) #define SECTOR_SHIFT 9 static int major = 0; @@ -41,8 +41,6 @@ struct mapped_device { struct rw_semaphore lock; - - kdev_t kdev; atomic_t holders; unsigned long flags; @@ -485,13 +483,25 @@ return 0; } +/*----------------------------------------------------------------- + * A bitset is used to keep track of allocated minor numbers. + *---------------------------------------------------------------*/ +static spinlock_t _minor_lock = SPIN_LOCK_UNLOCKED; +static unsigned long _minor_bits[MAX_DEVICES / BITS_PER_LONG]; + +static void free_minor(int minor) +{ + spin_lock(&_minor_lock); + clear_bit(minor, _minor_bits); + spin_unlock(&_minor_lock); +} + /* * See if the device with a specific minor # is free. */ -static int specific_dev(int minor, struct mapped_device *md) +static int specific_minor(int minor) { - struct gendisk *disk; - int part; + int r = -EBUSY; if (minor >= MAX_DEVICES) { DMWARN("request for a mapped_device beyond MAX_DEVICES (%d)", @@ -499,26 +509,27 @@ return -EINVAL; } - disk = get_gendisk(MKDEV(_major, minor), &part); - if (disk) { - put_disk(disk); - return -EBUSY; - } + spin_lock(&_minor_lock); + if (!test_and_set_bit(minor, _minor_bits)) + r = minor; + spin_unlock(&_minor_lock); - return minor; + return r; } -static int any_old_dev(struct mapped_device *md) +static int next_free_minor(void) { - int i; + int minor, r = -EBUSY; - for (i = 0; i < MAX_DEVICES; i++) - if (specific_dev(i, md) >= 0) { - DMWARN("allocating minor = %d", i); - return i; - } + spin_lock(&_minor_lock); + minor = find_first_zero_bit(_minor_bits, MAX_DEVICES); + if (minor != MAX_DEVICES) { + set_bit(minor, _minor_bits); + r = minor; + } + spin_unlock(&_minor_lock); - return -EBUSY; + return r; } /* @@ -534,15 +545,15 @@ } /* get a minor number for the dev */ - minor = (minor < 0) ? any_old_dev(md) : specific_dev(minor, md); + minor = (minor < 0) ? next_free_minor() : specific_minor(minor); if (minor < 0) { kfree(md); return NULL; } + DMWARN("allocating minor %d.", minor); memset(md, 0, sizeof(*md)); init_rwsem(&md->lock); - md->kdev = mk_kdev(_major, minor); atomic_set(&md->holders, 1); md->queue.queuedata = md; @@ -550,6 +561,7 @@ md->disk = alloc_disk(1); if (!md->disk) { + free_minor(md->disk->first_minor); kfree(md); return NULL; } @@ -569,6 +581,7 @@ static void free_dev(struct mapped_device *md) { + free_minor(md->disk->first_minor); del_gendisk(md->disk); put_disk(md->disk); kfree(md); @@ -749,6 +762,10 @@ return 0; } +/* + * The gendisk is only valid as long as you have a reference + * count on 'md'. + */ struct gendisk *dm_disk(struct mapped_device *md) { return md->disk; diff -Nru a/drivers/media/dvb/av7110/Makefile b/drivers/media/dvb/av7110/Makefile --- a/drivers/media/dvb/av7110/Makefile Wed Nov 27 14:36:31 2002 +++ b/drivers/media/dvb/av7110/Makefile Wed Nov 27 14:36:31 2002 @@ -6,5 +6,7 @@ obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ + include $(TOPDIR)/Rules.make diff -Nru a/drivers/media/dvb/av7110/av7110.c b/drivers/media/dvb/av7110/av7110.c --- a/drivers/media/dvb/av7110/av7110.c Wed Nov 27 14:36:27 2002 +++ b/drivers/media/dvb/av7110/av7110.c Wed Nov 27 14:36:27 2002 @@ -89,7 +89,7 @@ static void SetMode(av7110_t *av7110, int mode); void pes_to_ts(u8 const *buf, long int length, u16 pid, p2t_t *p); -void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, dvb_demux_feed_t *feed); +void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, struct dvb_demux_feed *feed); static u32 vidmem = 0; static u32 vidlow = 0; @@ -392,9 +392,9 @@ static int -record_cb(pes2ts_t *p2t, u8 *buf, size_t len) +record_cb(dvb_filter_pes2ts_t *p2t, u8 *buf, size_t len) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) p2t->priv; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) p2t->priv; if (!(dvbdmxfeed->ts_type & TS_PACKET)) return 0; @@ -404,13 +404,13 @@ return dvbdmxfeed->cb.ts(buf, len, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK); else - return pes2ts(p2t, buf, len); + return dvb_filter_pes2ts(p2t, buf, len); } static int -pes2ts_cb(void *priv, unsigned char *data) +dvb_filter_pes2ts_cb(void *priv, unsigned char *data) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) priv; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) priv; dvbdmxfeed->cb.ts(data, 188, 0, 0, &dvbdmxfeed->feed.ts, @@ -420,9 +420,9 @@ static int AV_StartRecord(av7110_t *av7110, int av, - dvb_demux_feed_t *dvbdmxfeed) + struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; if (av7110->playing||(av7110->rec_mode&av)) return -EBUSY; @@ -432,20 +432,30 @@ switch (av7110->rec_mode) { case RP_AUDIO: - pes2ts_init(&av7110->p2t[0], dvbdmx->pesfilter[0]->pid, - pes2ts_cb, (void *)dvbdmx->pesfilter[0]); + dvb_filter_pes2ts_init (&av7110->p2t[0], + dvbdmx->pesfilter[0]->pid, + dvb_filter_pes2ts_cb, + (void *)dvbdmx->pesfilter[0]); outcom(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0); break; + case RP_VIDEO: - pes2ts_init(&av7110->p2t[1], dvbdmx->pesfilter[1]->pid, - pes2ts_cb, (void *)dvbdmx->pesfilter[1]); + dvb_filter_pes2ts_init (&av7110->p2t[1], + dvbdmx->pesfilter[1]->pid, + dvb_filter_pes2ts_cb, + (void *)dvbdmx->pesfilter[1]); outcom(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0); break; + case RP_AV: - pes2ts_init(&av7110->p2t[0], dvbdmx->pesfilter[0]->pid, - pes2ts_cb, (void *)dvbdmx->pesfilter[0]); - pes2ts_init(&av7110->p2t[1], dvbdmx->pesfilter[1]->pid, - pes2ts_cb, (void *)dvbdmx->pesfilter[1]); + dvb_filter_pes2ts_init (&av7110->p2t[0], + dvbdmx->pesfilter[0]->pid, + dvb_filter_pes2ts_cb, + (void *)dvbdmx->pesfilter[0]); + dvb_filter_pes2ts_init (&av7110->p2t[1], + dvbdmx->pesfilter[1]->pid, + dvb_filter_pes2ts_cb, + (void *)dvbdmx->pesfilter[1]); outcom(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0); break; } @@ -463,8 +473,8 @@ outcom(av7110, COMTYPE_REC_PLAY, __Stop, 0); if (av7110->playing == RP_NONE) { - reset_ipack(&av7110->ipack[0]); - reset_ipack(&av7110->ipack[1]); + dvb_filter_ipack_reset(&av7110->ipack[0]); + dvb_filter_ipack_reset(&av7110->ipack[1]); } av7110->playing|=av; @@ -814,7 +824,7 @@ static inline int DvbDmxFilterCallback(u8 * buffer1, size_t buffer1_len, u8 * buffer2, size_t buffer2_len, - dvb_demux_filter_t *dvbdmxfilter, + struct dvb_demux_filter *dvbdmxfilter, dmx_success_t success, av7110_t *av7110) { @@ -896,7 +906,7 @@ // FIXME: use bottom half or tasklet if (av7110->feeding && mem[0]==0x47) - DvbDmxSWFilterPackets(&av7110->demux, mem, 512); + dvb_dmx_swfilter_packets(&av7110->demux, mem, 512); } #else static @@ -922,7 +932,7 @@ } else { if (av7110->ttbp>1000*188 && av7110->ttbp<1024*188) { if (av7110->feeding) - DvbDmxSWFilterPackets(&av7110->demux, + dvb_dmx_swfilter_packets(&av7110->demux, mem+av7110->ttbp, 1024- av7110->ttbp / 188); } @@ -937,7 +947,7 @@ // FIXME: use bottom half or tasklet if (av7110->feeding && mem[0]==0x47) - DvbDmxSWFilterPackets(&av7110->demux, mem, num); + dvb_dmx_swfilter_packets(&av7110->demux, mem, num); } #endif @@ -1001,7 +1011,7 @@ switch (type&0xff) { case DATA_TS_RECORD: - DvbDmxSWFilterPackets(&av7110->demux, + dvb_dmx_swfilter_packets(&av7110->demux, (const u8 *)av7110->debi_virt, av7110->debilen/188); spin_lock(&av7110->debilock); @@ -2008,8 +2018,8 @@ av7110->arm_app=(buf[6] << 16) + buf[7]; av7110->avtype=(buf[8] << 16) + buf[9]; - printk ("av7110 (%d): AV711%d - firm %08x, rtsl %08x, vid %08x, app %08x\n", - av7110->saa->dvb_adapter->num, av7110->avtype, av7110->arm_fw, + printk ("DVB: AV711%d(%d) - firm %08x, rtsl %08x, vid %08x, app %08x\n", + av7110->avtype, av7110->saa->dvb_adapter->num, av7110->arm_fw, av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app); return; @@ -2483,9 +2493,12 @@ if (umem) { if (copy_from_user(av7110->kbuf[type], buf, n)) return -EFAULT; - instant_repack(av7110->kbuf[type], n, &av7110->ipack[type]); - } else - instant_repack((u8 *)buf, n, &av7110->ipack[type]); + dvb_filter_instant_repack(av7110->kbuf[type], n, + &av7110->ipack[type]); + } else { + dvb_filter_instant_repack((u8 *)buf, n, + &av7110->ipack[type]); + } todo -= n; buf += n; } @@ -2517,7 +2530,8 @@ n=IPACKS*2; if (copy_from_user(av7110->kbuf[type], buf, n)) return -EFAULT; - instant_repack(av7110->kbuf[type], n, &av7110->ipack[type]); + dvb_filter_instant_repack(av7110->kbuf[type], n, + &av7110->ipack[type]); // memcpy(dvb->kbuf[type], buf, n); todo -= n; buf += n; @@ -2525,7 +2539,7 @@ return count-todo; } -void init_p2t(p2t_t *p, dvb_demux_feed_t *feed) +void init_p2t(p2t_t *p, struct dvb_demux_feed *feed) { memset(p->pes,0,TS_SIZE); p->counter = 0; @@ -2721,7 +2735,7 @@ void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, - dvb_demux_feed_t *feed) + struct dvb_demux_feed *feed) { int l, pes_start; @@ -3104,7 +3118,7 @@ static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned int mask=0; @@ -3124,24 +3138,24 @@ static struct file_operations dvb_fops = { - ioctl: dvb_ioctl, - mmap: dvb_mmap, - llseek: no_llseek + .ioctl = dvb_ioctl, + .mmap = dvb_mmap, + .llseek = no_llseek }; /* template for video_device-structure */ static struct video_device dvb_template = { - owner: THIS_MODULE, - name: "DVB Board", - type: VID_TYPE_TUNER | + .owner = THIS_MODULE, + .name = "DVB Board", + .type = VID_TYPE_TUNER | VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | VID_TYPE_SCALES, - hardware: VID_HARDWARE_SAA7146, - fops: &dvb_fops + .hardware = VID_HARDWARE_SAA7146, + .fops = &dvb_fops }; @@ -3182,9 +3196,9 @@ ******************************************************************************/ static int -StartHWFilter(dvb_demux_filter_t *dvbdmxfilter) +StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) { - dvb_demux_feed_t *dvbdmxfeed=dvbdmxfilter->feed; + struct dvb_demux_feed *dvbdmxfeed=dvbdmxfilter->feed; av7110_t *av7110=(av7110_t *) dvbdmxfeed->demux->priv; u16 buf[20]; int ret, i; @@ -3220,7 +3234,7 @@ } static int -StopHWFilter(dvb_demux_filter_t *dvbdmxfilter) +StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) { av7110_t *av7110=(av7110_t *) dvbdmxfilter->feed->demux->priv; u16 buf[3]; @@ -3252,9 +3266,9 @@ static int -dvb_write_to_decoder(dvb_demux_feed_t *dvbdmxfeed, u8 *buf, size_t count) +dvb_write_to_decoder(struct dvb_demux_feed *dvbdmxfeed, u8 *buf, size_t count) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; ipack *ipack=&av7110->ipack[dvbdmxfeed->pes_type]; @@ -3277,7 +3291,7 @@ return -1; } if (buf[1]&0x40) - send_ipack_rest(ipack); + dvb_filter_ipack_flush(ipack); if (buf[3]&0x20) { // adaptation field? count-=buf[4]+1; @@ -3287,14 +3301,15 @@ } } - instant_repack(buf+4, count-4, &av7110->ipack[dvbdmxfeed->pes_type]); + dvb_filter_instant_repack(buf+4, count-4, + &av7110->ipack[dvbdmxfeed->pes_type]); return 0; } static void -dvb_feed_start_pid(dvb_demux_feed_t *dvbdmxfeed) +dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; u16 *pid=dvbdmx->pids, npids[5]; int i; @@ -3329,9 +3344,9 @@ } static void -dvb_feed_stop_pid(dvb_demux_feed_t *dvbdmxfeed) +dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; u16 *pid=dvbdmx->pids, npids[5]; int i; @@ -3365,9 +3380,9 @@ } static int -dvb_start_feed(dvb_demux_feed_t *dvbdmxfeed) +dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; if (!dvbdmx->dmx.frontend) @@ -3425,9 +3440,9 @@ static int -dvb_stop_feed(dvb_demux_feed_t *dvbdmxfeed) +dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; if (av7110->saa->card_type>=DVB_CARD_TT_BUDGET) @@ -3468,8 +3483,8 @@ static void restart_feeds(av7110_t *av7110) { - dvb_demux_t *dvbdmx=&av7110->demux; - dvb_demux_feed_t *feed; + struct dvb_demux *dvbdmx=&av7110->demux; + struct dvb_demux_feed *feed; int mode; int i; @@ -3660,7 +3675,7 @@ static int dvb_ca_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; int err=dvb_generic_open(inode, file); @@ -3673,7 +3688,7 @@ static unsigned int dvb_ca_poll(struct file *file, poll_table *wait) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned int mask=0; @@ -3702,7 +3717,7 @@ dvb_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned long arg=(unsigned long) parg; @@ -3716,7 +3731,7 @@ case CA_GET_CAP: { - ca_cap_t cap; + ca_caps_t cap; cap.slot_num=2; #ifdef NEW_CI @@ -3788,7 +3803,7 @@ dvb_ca_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos); @@ -3797,7 +3812,7 @@ static ssize_t dvb_ca_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos); @@ -3812,7 +3827,7 @@ static unsigned int dvb_video_poll(struct file *file, poll_table *wait) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned int mask=0; @@ -3834,7 +3849,7 @@ dvb_video_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; if (av7110->videostate.stream_source!=VIDEO_SOURCE_MEMORY) @@ -3847,7 +3862,7 @@ dvb_audio_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; if (av7110->audiostate.stream_source!=AUDIO_SOURCE_MEMORY) { @@ -3876,7 +3891,7 @@ for (i=0; iipack[1]); + dvb_filter_ipack_flush(&av7110->ipack[1]); } @@ -3884,7 +3899,7 @@ dvb_video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned long arg=(unsigned long) parg; int ret=0; @@ -4041,7 +4056,7 @@ case VIDEO_CLEAR_BUFFER: ring_buffer_flush(&av7110->avout); - reset_ipack(&av7110->ipack[1]); + dvb_filter_ipack_reset(&av7110->ipack[1]); if (av7110->playing==RP_AV) { outcom(av7110, COMTYPE_REC_PLAY, @@ -4073,7 +4088,7 @@ dvb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned long arg=(unsigned long) parg; int ret=0; @@ -4164,7 +4179,7 @@ case AUDIO_CLEAR_BUFFER: ring_buffer_flush(&av7110->aout); - reset_ipack(&av7110->ipack[0]); + dvb_filter_ipack_reset(&av7110->ipack[0]); if (av7110->playing==RP_AV) outcom(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); @@ -4192,7 +4207,7 @@ dvb_osd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; #ifdef CONFIG_DVB_AV7110_OSD @@ -4204,7 +4219,7 @@ static int dvb_video_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; int err; @@ -4220,7 +4235,7 @@ static int dvb_video_release(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; AV_Stop(av7110, RP_VIDEO); @@ -4229,7 +4244,7 @@ static int dvb_audio_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; int err=dvb_generic_open(inode, file); @@ -4242,7 +4257,7 @@ static int dvb_audio_release(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; AV_Stop(av7110, RP_AUDIO); @@ -4256,75 +4271,70 @@ ******************************************************************************/ static struct file_operations dvb_video_fops = { - owner: THIS_MODULE, - read: 0, - write: dvb_video_write, - ioctl: dvb_generic_ioctl, - open: dvb_video_open, - release: dvb_video_release, - poll: dvb_video_poll, + .owner = THIS_MODULE, + .write = dvb_video_write, + .ioctl = dvb_generic_ioctl, + .open = dvb_video_open, + .release = dvb_video_release, + .poll = dvb_video_poll, }; -static dvb_device_t dvbdev_video = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_video_fops, - kernel_ioctl: dvb_video_ioctl, +static struct dvb_device dvbdev_video = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_video_fops, + .kernel_ioctl = dvb_video_ioctl, }; static struct file_operations dvb_audio_fops = { - owner: THIS_MODULE, - read: 0, - write: dvb_audio_write, - ioctl: dvb_generic_ioctl, - open: dvb_audio_open, - release: dvb_audio_release, - poll: dvb_audio_poll, + .owner = THIS_MODULE, + .write = dvb_audio_write, + .ioctl = dvb_generic_ioctl, + .open = dvb_audio_open, + .release = dvb_audio_release, + .poll = dvb_audio_poll, }; -static dvb_device_t dvbdev_audio = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_audio_fops, - kernel_ioctl: dvb_audio_ioctl, +static struct dvb_device dvbdev_audio = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_audio_fops, + .kernel_ioctl = dvb_audio_ioctl, }; static struct file_operations dvb_ca_fops = { - owner: THIS_MODULE, - read: dvb_ca_read, - write: dvb_ca_write, - ioctl: dvb_generic_ioctl, - open: dvb_ca_open, - release: dvb_generic_release, - poll: dvb_ca_poll, + .owner = THIS_MODULE, + .read = dvb_ca_read, + .write = dvb_ca_write, + .ioctl = dvb_generic_ioctl, + .open = dvb_ca_open, + .release = dvb_generic_release, + .poll = dvb_ca_poll, }; -static dvb_device_t dvbdev_ca = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_ca_fops, - kernel_ioctl: dvb_ca_ioctl, +static struct dvb_device dvbdev_ca = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_ca_fops, + .kernel_ioctl = dvb_ca_ioctl, }; static struct file_operations dvb_osd_fops = { - owner: THIS_MODULE, - read: 0, - write: 0, - ioctl: dvb_generic_ioctl, - open: dvb_generic_open, - release: dvb_generic_release, - poll: 0, + .owner = THIS_MODULE, + .ioctl = dvb_generic_ioctl, + .open = dvb_generic_open, + .release = dvb_generic_release, }; -static dvb_device_t dvbdev_osd = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_osd_fops, - kernel_ioctl: dvb_osd_ioctl, +static struct dvb_device dvbdev_osd = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_osd_fops, + .kernel_ioctl = dvb_osd_ioctl, }; @@ -4359,7 +4369,7 @@ { int ret, i; dmx_frontend_t *dvbfront=&av7110->hw_frontend; - dvb_demux_t *dvbdemux=&av7110->demux; + struct dvb_demux *dvbdemux=&av7110->demux; if (av7110->registered) return -1; @@ -4414,7 +4424,7 @@ DMX_SECTION_FILTERING| DMX_MEMORY_BASED_FILTERING); - DvbDmxInit(&av7110->demux); + dvb_dmx_init(&av7110->demux); dvbfront->id="hw_frontend"; @@ -4426,7 +4436,7 @@ av7110->dmxdev.demux=&dvbdemux->dmx; av7110->dmxdev.capabilities=0; - DmxDevInit(&av7110->dmxdev, av7110->dvb_adapter); + dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); } if (av7110->saa->card_type>=DVB_CARD_TT_BUDGET) { @@ -4443,7 +4453,7 @@ DMX_SECTION_FILTERING| DMX_MEMORY_BASED_FILTERING); - DvbDmxInit(&av7110->demux); + dvb_dmx_init(&av7110->demux); dvbfront->id="hw_frontend"; dvbfront->vendor="VLSI"; @@ -4454,7 +4464,7 @@ av7110->dmxdev.demux=&dvbdemux->dmx; av7110->dmxdev.capabilities=0; - DmxDevInit(&av7110->dmxdev, av7110->dvb_adapter); + dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); } ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, @@ -4505,7 +4515,7 @@ static void dvb_unregister(av7110_t *av7110) { - dvb_demux_t *dvbdemux=&av7110->demux; + struct dvb_demux *dvbdemux=&av7110->demux; if (!av7110->registered) return; @@ -4516,8 +4526,8 @@ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend); dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend); - DmxDevRelease(&av7110->dmxdev); - DvbDmxRelease(&av7110->demux); + dvb_dmxdev_release(&av7110->dmxdev); + dvb_dmx_release(&av7110->demux); if (av7110->saa->card_type==DVB_CARD_TT_SIEMENS) dvb_remove_frontend_notifier (av7110->dvb_adapter, @@ -4584,9 +4594,9 @@ av7110->vidmode=VIDEO_MODE_PAL; - init_ipack(&av7110->ipack[0], IPACKS, play_audio_cb); + dvb_filter_ipack_init(&av7110->ipack[0], IPACKS, play_audio_cb); av7110->ipack[0].data=(void *) av7110; - init_ipack(&av7110->ipack[1], IPACKS, play_video_cb); + dvb_filter_ipack_init(&av7110->ipack[1], IPACKS, play_video_cb); av7110->ipack[1].data=(void *) av7110; @@ -4705,8 +4715,8 @@ saa7146_write(av7110->saa_mem, ISR,(MASK_19 | MASK_03)); ci_ll_release(&av7110->ci_rbuffer, &av7110->ci_wbuffer); - free_ipack(&av7110->ipack[0]); - free_ipack(&av7110->ipack[1]); + dvb_filter_ipack_free(&av7110->ipack[0]); + dvb_filter_ipack_free(&av7110->ipack[1]); vfree(av7110->iobuf); pci_free_consistent(av7110->saa->device, 8192, av7110->debi_virt, av7110->debi_bus); diff -Nru a/drivers/media/dvb/av7110/av7110.h b/drivers/media/dvb/av7110/av7110.h --- a/drivers/media/dvb/av7110/av7110.h Wed Nov 27 14:36:31 2002 +++ b/drivers/media/dvb/av7110/av7110.h Wed Nov 27 14:36:31 2002 @@ -479,7 +479,7 @@ u8 counter; long int pos; int frags; - dvb_demux_feed_t *feed; + struct dvb_demux_feed *feed; } p2t_t; @@ -561,7 +561,7 @@ int vidmode; dmxdev_t dmxdev; - dvb_demux_t demux; + struct dvb_demux demux; char demux_id[16]; dmx_frontend_t hw_frontend; @@ -580,9 +580,9 @@ #define TRICK_FREEZE 3 struct audio_status audiostate; - dvb_demux_filter_t *handle2filter[32]; + struct dvb_demux_filter *handle2filter[32]; p2t_t p2t_filter[MAXFILT]; - pes2ts_t p2t[2]; + dvb_filter_pes2ts_t p2t[2]; struct ipack_s ipack[2]; u8 *kbuf[2]; @@ -621,11 +621,11 @@ ring_buffer_t ci_wbuffer; - dvb_adapter_t *dvb_adapter; - dvb_device_t *video_dev; - dvb_device_t *audio_dev; - dvb_device_t *ca_dev; - dvb_device_t *osd_dev; + struct dvb_adapter *dvb_adapter; + struct dvb_device *video_dev; + struct dvb_device *audio_dev; + struct dvb_device *ca_dev; + struct dvb_device *osd_dev; int dsp_dev; } av7110_t; diff -Nru a/drivers/media/dvb/av7110/saa7146.c b/drivers/media/dvb/av7110/saa7146.c --- a/drivers/media/dvb/av7110/saa7146.c Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/av7110/saa7146.c Wed Nov 27 14:36:28 2002 @@ -1399,7 +1399,7 @@ /* if any error is still present, a fatal error has occured ... */ if ( SAA7146_I2C_BBR != (status = i2c_status_check(saa)) ) { hprintk("saa7146: i2c_reset: fatal error, status:0x%08x\n",status); - return -1; + return -EIO; } return 0; diff -Nru a/drivers/media/dvb/av7110/saa7146_core.c b/drivers/media/dvb/av7110/saa7146_core.c --- a/drivers/media/dvb/av7110/saa7146_core.c Wed Nov 27 14:36:31 2002 +++ b/drivers/media/dvb/av7110/saa7146_core.c Wed Nov 27 14:36:31 2002 @@ -33,8 +33,8 @@ #include "saa7146_core.h" #include "saa7146_v4l.h" #include "av7110.h" -#include "../dvb-core/compat.h" -#include "../dvb-core/dvb_i2c.h" +#include "compat.h" +#include "dvb_i2c.h" /* insmod parameter: here you can specify the number of video-buffers to be allocated. for simple capturing 2 buffers (double-buffering) @@ -197,23 +197,23 @@ int do_master_xfer (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num) { struct saa7146 *a = i2c->data; - int result, count; + int count; int i = 0; dprintk(KERN_ERR "saa7146_core.o: master_xfer called, num:%d\n",num); /* prepare the message(s), get number of u32s to transfer */ count = prepare(msgs, num, a->i2c); - if ( 0 > count ) { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not prepare i2c-message\n"); + + if (count < 0) { + hprintk(KERN_ERR "saa7146_core.o: could not prepare i2c-message\n"); return -EIO; } /* reset the i2c-device if necessary */ - result = i2c_reset( a ); - if ( 0 > result ) { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not reset i2c-bus\n"); - return result; + if (i2c_reset(a) < 0) { + hprintk(KERN_ERR "saa7146_core.o: could not reset i2c-bus\n"); + return -EIO; } for(i = 0; i < count; i++) { @@ -222,31 +222,17 @@ * we do not start the whole rps1-engine... */ - result = i2c_write_out( a, &a->i2c[i], - SAA7146_I2C_TIMEOUT ); - - if ( 0 != result) { /* if address-error occured, don't retry */ - if ( result == -EREMOTEIO ) - { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: error in address phase\n"); - return result; - } - hprintk(KERN_ERR "saa7146_core.o: master_xfer: error transferring, trying again\n"); - break; - } + if (i2c_write_out(a, &a->i2c[i], SAA7146_I2C_TIMEOUT) < 0) { + hprintk (KERN_ERR "saa7146_core.o: " + "i2c error in address phase\n"); + return -EREMOTEIO; } - - /* see if an error occured & the last retry failed */ - if (0 != result) { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not transfer i2c-message\n"); - return -EIO; } /* if any things had to be read, get the results */ - result = clean_up(msgs, num, a->i2c); - if ( 0 > result ) { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not cleanup\n"); + if (clean_up(msgs, num, a->i2c) < 0) { + hprintk(KERN_ERR "saa7146_core.o: i2c cleanup failed!\n"); return -EIO; } @@ -259,13 +245,19 @@ static int master_xfer (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num) { + struct saa7146 *saa = i2c->data; int retries = SAA7146_I2C_RETRIES; int ret; + if (down_interruptible (&saa->i2c_sem)) + return -ERESTARTSYS; + do { ret = do_master_xfer (i2c, msgs, num); } while (ret != num && retries--); + up (&saa->i2c_sem); + return ret; } @@ -273,6 +265,8 @@ /* registering functions to load algorithms at runtime */ int i2c_saa7146_add_bus (struct saa7146 *saa) { + init_MUTEX(&saa->i2c_sem); + /* enable i2c-port pins */ saa7146_write (saa->mem, MC1, (MASK_08 | MASK_24)); @@ -389,9 +383,9 @@ struct saa7146_debi_transfer *dt = arg; - printk("saa7146_core.o: SAA7146_DEBI_TRANSFER\n"); - printk("saa7146_core.o: timeout:%d, swap:%d, slave16:%d, increment:%d, intel:%d, tien:%d\n", dt->timeout, dt->swap, dt->slave16, dt->increment, dt->intel, dt->tien); - printk("saa7146_core.o: address:0x%04x, num_bytes:%d, direction:%d, mem:0x%08x\n",dt->address,dt->address,dt->direction,dt->mem); + dprintk("saa7146_core.o: SAA7146_DEBI_TRANSFER\n"); + dprintk("saa7146_core.o: timeout:%d, swap:%d, slave16:%d, increment:%d, intel:%d, tien:%d\n", dt->timeout, dt->swap, dt->slave16, dt->increment, dt->intel, dt->tien); + dprintk("saa7146_core.o: address:0x%04x, num_bytes:%d, direction:%d, mem:0x%08x\n",dt->address,dt->address,dt->direction,dt->mem); debi_transfer(saa, dt); break; @@ -622,7 +616,7 @@ } /* print status message */ - printk(KERN_ERR "saa7146_core.o: %s: bus:%d, rev:%d, mem:0x%08x.\n", saa->name, saa->device->bus->number, saa->revision, (unsigned int) saa->mem); + dprintk("saa7146_core.o: %s: bus:%d, rev:%d, mem:0x%08x.\n", saa->name, saa->device->bus->number, saa->revision, (unsigned int) saa->mem); /* enable bus-mastering */ pci_set_master( saa->device ); @@ -827,7 +821,7 @@ int __devinit saa7146_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { - struct dvb_adapter_s *adap; + struct dvb_adapter *adap; struct saa7146 *saa; int card_type; struct card_info *cinfo= (struct card_info *) ent->driver_data; diff -Nru a/drivers/media/dvb/av7110/saa7146_core.h b/drivers/media/dvb/av7110/saa7146_core.h --- a/drivers/media/dvb/av7110/saa7146_core.h Wed Nov 27 14:36:31 2002 +++ b/drivers/media/dvb/av7110/saa7146_core.h Wed Nov 27 14:36:31 2002 @@ -1,17 +1,11 @@ #ifndef __SAA7146_CORE__ #define __SAA7146_CORE__ -#include /* definitions of u32 etc. */ -#include "../dvb-core/dvbdev.h" +#include +#include + +#include "dvbdev.h" -#if LINUX_VERSION_CODE < 0x020300 -#define DECLARE_MUTEX(foo) struct semaphore foo = MUTEX -#define DECLARE_MUTEX_LOCKED(foo) struct semaphore foo = MUTEX_LOCKED -#define WAIT_QUEUE struct wait_queue* -#define init_waitqueue_head(wq) *(wq) = NULL; -#else -#define WAIT_QUEUE wait_queue_head_t -#endif /* maximum number of capture frames we support */ #define SAA7146_MAX_BUF 5 @@ -37,12 +31,13 @@ char name[32]; /* give it a nice name */ struct list_head list_head; - - dvb_adapter_t *dvb_adapter; - struct dvb_i2c_bus *i2c_bus; struct pci_dev *device; int card_type; + struct dvb_adapter *dvb_adapter; + struct dvb_i2c_bus *i2c_bus; + struct semaphore i2c_sem; + void* data[SAA7146_MAX_EXTENSIONS]; /* data hooks for extensions */ int (*command) (struct dvb_i2c_bus *i, unsigned int cmd, void *arg); @@ -70,8 +65,8 @@ int grab_format[SAA7146_MAX_BUF]; /* video format of grabs */ int grab_port[SAA7146_MAX_BUF]; /* video port for grab */ - WAIT_QUEUE rps0_wq; /* rps0 interrupt queue (=> capture) */ - WAIT_QUEUE rps1_wq; /* rps1 interrupt queue (=> i2c, ...) */ + wait_queue_head_t rps0_wq; /* rps0 interrupt queue (=> capture) */ + wait_queue_head_t rps1_wq; /* rps1 interrupt queue (=> i2c, ...) */ }; #define SAA7146_IRQ_RPS0 diff -Nru a/drivers/media/dvb/av7110/saa7146_v4l.c b/drivers/media/dvb/av7110/saa7146_v4l.c --- a/drivers/media/dvb/av7110/saa7146_v4l.c Wed Nov 27 14:36:32 2002 +++ b/drivers/media/dvb/av7110/saa7146_v4l.c Wed Nov 27 14:36:32 2002 @@ -320,7 +320,6 @@ /* set corresponding buffer to ´unused´ */ saa->frame_stat[i] = GBUFFER_UNUSED; -printk ("saa7146_v4l.o: SAA7146_V4L_CSYNC, frame %i done.\n", i); break; } diff -Nru a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c --- a/drivers/media/dvb/dvb-core/dmxdev.c Wed Nov 27 14:36:31 2002 +++ b/drivers/media/dvb/dvb-core/dmxdev.c Wed Nov 27 14:36:31 2002 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "dmxdev.h" @@ -40,19 +41,19 @@ #define dprintk if (debug) printk inline dmxdev_filter_t * -DmxDevFile2Filter(struct file *file) +dvb_dmxdev_file_to_filter(struct file *file) { return (dmxdev_filter_t *) file->private_data; } inline dmxdev_dvr_t * -DmxDevFile2DVR(dmxdev_t *dmxdev, struct file *file) +dvb_dmxdev_file_to_dvr(dmxdev_t *dmxdev, struct file *file) { return (dmxdev_dvr_t *) file->private_data; } static inline void -DmxDevBufferInit(dmxdev_buffer_t *buffer) +dvb_dmxdev_buffer_init(dmxdev_buffer_t *buffer) { buffer->data=0; buffer->size=8192; @@ -63,7 +64,7 @@ } static inline int -DmxDevBufferWrite(dmxdev_buffer_t *buf, uint8_t *src, int len) +dvb_dmxdev_buffer_write(dmxdev_buffer_t *buf, uint8_t *src, int len) { int split; int free; @@ -98,7 +99,7 @@ } static ssize_t -DmxDevBufferRead(dmxdev_buffer_t *src, int non_blocking, +dvb_dmxdev_buffer_read(dmxdev_buffer_t *src, int non_blocking, char *buf, size_t count, loff_t *ppos) { unsigned long todo=count; @@ -108,6 +109,7 @@ return 0; if ((error=src->error)) { + src->pwrite=src->pread; src->error=0; return error; } @@ -125,6 +127,7 @@ return count-todo; if ((error=src->error)) { + src->pwrite=src->pread; src->error=0; return error; } @@ -172,7 +175,7 @@ } static inline void -DmxDevDVRStateSet(dmxdev_dvr_t *dmxdevdvr, int state) +dvb_dmxdev_dvr_state_set(dmxdev_dvr_t *dmxdevdvr, int state) { spin_lock_irq(&dmxdevdvr->dev->lock); dmxdevdvr->state=state; @@ -181,7 +184,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; dmx_frontend_t *front; @@ -198,7 +201,7 @@ } if ((file->f_flags&O_ACCMODE)==O_RDONLY) { - DmxDevBufferInit(&dmxdev->dvr_buffer); + dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); dmxdev->dvr_buffer.size=DVR_BUFFER_SIZE; dmxdev->dvr_buffer.data=vmalloc(DVR_BUFFER_SIZE); if (!dmxdev->dvr_buffer.data) { @@ -230,7 +233,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; if (down_interruptible (&dmxdev->mutex)) @@ -258,7 +261,7 @@ static ssize_t dvb_dvr_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; int ret; @@ -276,12 +279,12 @@ static ssize_t dvb_dvr_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; int ret; //down(&dmxdev->mutex); - ret= DmxDevBufferRead(&dmxdev->dvr_buffer, + ret= dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, file->f_flags&O_NONBLOCK, buf, count, ppos); //up(&dmxdev->mutex); @@ -289,7 +292,7 @@ } static inline void -DmxDevFilterStateSet(dmxdev_filter_t *dmxdevfilter, int state) +dvb_dmxdev_filter_state_set(dmxdev_filter_t *dmxdevfilter, int state) { spin_lock_irq(&dmxdevfilter->dev->lock); dmxdevfilter->state=state; @@ -297,7 +300,7 @@ } static int -DmxDevSetBufferSize(dmxdev_filter_t *dmxdevfilter, unsigned long size) +dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size) { dmxdev_buffer_t *buf=&dmxdevfilter->buffer; void *mem; @@ -327,7 +330,7 @@ } static void -DmxDevFilterTimeout(unsigned long data) +dvb_dmxdev_filter_timeout(unsigned long data) { dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *)data; @@ -339,13 +342,13 @@ } static void -DmxDevFilterTimer(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_timer(dmxdev_filter_t *dmxdevfilter) { struct dmx_sct_filter_params *para=&dmxdevfilter->params.sec; del_timer(&dmxdevfilter->timer); if (para->timeout) { - dmxdevfilter->timer.function=DmxDevFilterTimeout; + dmxdevfilter->timer.function=dvb_dmxdev_filter_timeout; dmxdevfilter->timer.data=(unsigned long) dmxdevfilter; dmxdevfilter->timer.expires=jiffies+1+(HZ/2+HZ*para->timeout)/1000; add_timer(&dmxdevfilter->timer); @@ -353,7 +356,7 @@ } static int -DmxDevSectionCallback(u8 *buffer1, size_t buffer1_len, +dvb_dmxdev_section_callback(u8 *buffer1, size_t buffer1_len, u8 *buffer2, size_t buffer2_len, dmx_section_filter_t *filter, dmx_success_t success) @@ -375,9 +378,9 @@ buffer1[0], buffer1[1], buffer1[2], buffer1[3], buffer1[4], buffer1[5]); - ret=DmxDevBufferWrite(&dmxdevfilter->buffer, buffer1, buffer1_len); + ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, buffer1_len); if (ret==buffer1_len) { - ret=DmxDevBufferWrite(&dmxdevfilter->buffer, buffer2, buffer2_len); + ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, buffer2_len); } if (ret<0) { dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread; @@ -391,7 +394,7 @@ } static int -DmxDevTSCallback(u8 *buffer1, size_t buffer1_len, +dvb_dmxdev_ts_callback(u8 *buffer1, size_t buffer1_len, u8 *buffer2, size_t buffer2_len, dmx_ts_feed_t *feed, dmx_success_t success) @@ -415,9 +418,9 @@ wake_up(&buffer->queue); return 0; } - ret=DmxDevBufferWrite(buffer, buffer1, buffer1_len); + ret=dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); if (ret==buffer1_len) - ret=DmxDevBufferWrite(buffer, buffer2, buffer2_len); + ret=dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); if (ret<0) { buffer->pwrite=buffer->pread; buffer->error=-EOVERFLOW; @@ -431,9 +434,9 @@ /* stop feed but only mark the specified filter as stopped (state set) */ static int -DmxDevFeedStop(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_feed_stop(dmxdev_filter_t *dmxdevfilter) { - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); switch (dmxdevfilter->type) { case DMXDEV_TYPE_SEC: @@ -453,9 +456,9 @@ /* start feed associated with the specified filter */ static int -DmxDevFeedStart(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_feed_start(dmxdev_filter_t *dmxdevfilter) { - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_GO); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_GO); switch (dmxdevfilter->type) { case DMXDEV_TYPE_SEC: @@ -475,7 +478,7 @@ otherwise release the feed */ static int -DmxDevFeedRestart(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_feed_restart(dmxdev_filter_t *dmxdevfilter) { int i; dmxdev_t *dmxdev=dmxdevfilter->dev; @@ -485,7 +488,7 @@ if (dmxdev->filter[i].state>=DMXDEV_STATE_GO && dmxdev->filter[i].type==DMXDEV_TYPE_SEC && dmxdev->filter[i].pid==pid) { - DmxDevFeedStart(&dmxdev->filter[i]); + dvb_dmxdev_feed_start(&dmxdev->filter[i]); return 0; } @@ -497,7 +500,7 @@ } static int -DmxDevFilterStop(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_stop(dmxdev_filter_t *dmxdevfilter) { if (dmxdevfilter->statefeed.sec) break; - DmxDevFeedStop(dmxdevfilter); + dvb_dmxdev_feed_stop(dmxdevfilter); if (dmxdevfilter->filter.sec) dmxdevfilter->feed.sec-> release_filter(dmxdevfilter->feed.sec, dmxdevfilter->filter.sec); - DmxDevFeedRestart(dmxdevfilter); + dvb_dmxdev_feed_restart(dmxdevfilter); dmxdevfilter->feed.sec=0; break; case DMXDEV_TYPE_PES: if (!dmxdevfilter->feed.ts) break; - DmxDevFeedStop(dmxdevfilter); + dvb_dmxdev_feed_stop(dmxdevfilter); dmxdevfilter->dev->demux-> release_ts_feed(dmxdevfilter->dev->demux, dmxdevfilter->feed.ts); @@ -533,19 +536,19 @@ } static inline int -DmxDevFilterReset(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_reset(dmxdev_filter_t *dmxdevfilter) { if (dmxdevfilter->statetype=DMXDEV_TYPE_NONE; dmxdevfilter->pid=0xffff; - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_ALLOCATED); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); return 0; } static int -DmxDevFilterStart(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter) { dmxdev_t *dmxdev=dmxdevfilter->dev; void *mem; @@ -554,7 +557,7 @@ if (dmxdevfilter->statestate>=DMXDEV_STATE_GO) - DmxDevFilterStop(dmxdevfilter); + dvb_dmxdev_filter_stop(dmxdevfilter); mem=dmxdevfilter->buffer.data; if (!mem) { @@ -566,6 +569,8 @@ return -ENOMEM; } + dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread=0; + switch (dmxdevfilter->type) { case DMXDEV_TYPE_SEC: { @@ -588,10 +593,9 @@ /* if no feed found, try to allocate new one */ if (!*secfeed) { - ret=dmxdev->demux-> - allocate_section_feed(dmxdev->demux, + ret=dmxdev->demux->allocate_section_feed(dmxdev->demux, secfeed, - DmxDevSectionCallback); + dvb_dmxdev_section_callback); if (ret<0) { printk ("DVB (%s): could not alloc feed\n", __FUNCTION__); @@ -604,18 +608,17 @@ if (ret<0) { printk ("DVB (%s): could not set feed\n", __FUNCTION__); - DmxDevFeedRestart(dmxdevfilter); + dvb_dmxdev_feed_restart(dmxdevfilter); return ret; } } else - DmxDevFeedStop(dmxdevfilter); + dvb_dmxdev_feed_stop(dmxdevfilter); ret=(*secfeed)->allocate_filter(*secfeed, secfilter); if (ret<0) { - DmxDevFeedRestart(dmxdevfilter); - dmxdevfilter->feed.sec-> - start_filtering(*secfeed); + dvb_dmxdev_feed_restart(dmxdevfilter); + dmxdevfilter->feed.sec->start_filtering(*secfeed); dprintk ("could not get filter\n"); return ret; } @@ -636,15 +639,14 @@ (*secfilter)->filter_mask[2]=0; dmxdevfilter->todo=0; - dmxdevfilter->feed.sec-> - start_filtering(dmxdevfilter->feed.sec); - DmxDevFilterTimer(dmxdevfilter); + dmxdevfilter->feed.sec->start_filtering(dmxdevfilter->feed.sec); + dvb_dmxdev_filter_timer(dmxdevfilter); break; } case DMXDEV_TYPE_PES: { - struct timespec timeout = {0 }; + struct timespec timeout = { 0 }; struct dmx_pes_filter_params *para=&dmxdevfilter->params.pes; dmx_output_t otype; int ret; @@ -670,31 +672,29 @@ ret=dmxdev->demux->allocate_ts_feed(dmxdev->demux, tsfeed, - DmxDevTSCallback); + dvb_dmxdev_ts_callback); if (ret<0) return ret; (*tsfeed)->priv=(void *) dmxdevfilter; ret=(*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes, 188, 32768, 0, timeout); if (ret<0) { - dmxdev->demux-> - release_ts_feed(dmxdev->demux, *tsfeed); + dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed); return ret; } - dmxdevfilter->feed.ts-> - start_filtering(dmxdevfilter->feed.ts); + dmxdevfilter->feed.ts->start_filtering(dmxdevfilter->feed.ts); break; } default: return -EINVAL; } - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_GO); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_GO); return 0; } static int dvb_demux_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; int i; dmxdev_filter_t *dmxdevfilter; @@ -714,9 +714,9 @@ dmxdevfilter->dvbdev=dmxdev->dvbdev; file->private_data=dmxdevfilter; - DmxDevBufferInit(&dmxdevfilter->buffer); + dvb_dmxdev_buffer_init(&dmxdevfilter->buffer); dmxdevfilter->type=DMXDEV_TYPE_NONE; - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_ALLOCATED); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); dmxdevfilter->feed.ts=0; init_timer(&dmxdevfilter->timer); @@ -725,13 +725,13 @@ } int -DmxDevFilterFree(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_free(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter) { if (down_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; - DmxDevFilterStop(dmxdevfilter); - DmxDevFilterReset(dmxdevfilter); + dvb_dmxdev_filter_stop(dmxdevfilter); + dvb_dmxdev_filter_reset(dmxdevfilter); if (dmxdevfilter->buffer.data) { void *mem=dmxdevfilter->buffer.data; @@ -741,7 +741,7 @@ spin_unlock_irq(&dmxdev->lock); vfree(mem); } - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_FREE); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE); wake_up(&dmxdevfilter->buffer.queue); up(&dmxdev->mutex); return 0; @@ -758,33 +758,33 @@ static int -DmxDevFilterSet(dmxdev_t *dmxdev, +dvb_dmxdev_filter_set(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter, struct dmx_sct_filter_params *params) { dprintk ("function : %s\n", __FUNCTION__); - DmxDevFilterStop(dmxdevfilter); + dvb_dmxdev_filter_stop(dmxdevfilter); dmxdevfilter->type=DMXDEV_TYPE_SEC; dmxdevfilter->pid=params->pid; memcpy(&dmxdevfilter->params.sec, params, sizeof(struct dmx_sct_filter_params)); invert_mode(&dmxdevfilter->params.sec.filter); - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); if (params->flags&DMX_IMMEDIATE_START) - return DmxDevFilterStart(dmxdevfilter); + return dvb_dmxdev_filter_start(dmxdevfilter); return 0; } static int -DmxDevPesFilterSet(dmxdev_t *dmxdev, +dvb_dmxdev_pes_filter_set(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter, struct dmx_pes_filter_params *params) { - DmxDevFilterStop(dmxdevfilter); + dvb_dmxdev_filter_stop(dmxdevfilter); if (params->pes_type>DMX_PES_OTHER || params->pes_type<0) return -EINVAL; @@ -793,16 +793,16 @@ dmxdevfilter->pid=params->pid; memcpy(&dmxdevfilter->params, params, sizeof(struct dmx_pes_filter_params)); - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); if (params->flags&DMX_IMMEDIATE_START) - return DmxDevFilterStart(dmxdevfilter); + return dvb_dmxdev_filter_start(dmxdevfilter); return 0; } static ssize_t -DmxDevReadSec(dmxdev_filter_t *dfil, struct file *file, +dvb_dmxdev_read_sec(dmxdev_filter_t *dfil, struct file *file, char *buf, size_t count, loff_t *ppos) { int result, hcount; @@ -812,7 +812,7 @@ hcount=3+dfil->todo; if (hcount>count) hcount=count; - result=DmxDevBufferRead(&dfil->buffer, file->f_flags&O_NONBLOCK, + result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK, buf, hcount, ppos); if (result<0) { dfil->todo=0; @@ -832,7 +832,7 @@ } if (count>dfil->todo) count=dfil->todo; - result=DmxDevBufferRead(&dfil->buffer, file->f_flags&O_NONBLOCK, + result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK, buf, count, ppos); if (result<0) return result; @@ -844,16 +844,16 @@ ssize_t dvb_demux_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(file); + dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file); //dmxdev_t *dmxdev=dmxdevfilter->dev; int ret=0; // semaphore should not be necessary (I hope ...) //down(&dmxdev->mutex); if (dmxdevfilter->type==DMXDEV_TYPE_SEC) - ret=DmxDevReadSec(dmxdevfilter, file, buf, count, ppos); + ret=dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos); else - ret=DmxDevBufferRead(&dmxdevfilter->buffer, + ret=dvb_dmxdev_buffer_read(&dmxdevfilter->buffer, file->f_flags&O_NONBLOCK, buf, count, ppos); //up(&dmxdev->mutex); @@ -864,7 +864,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(file); + dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file); dmxdev_t *dmxdev=dmxdevfilter->dev; unsigned long arg=(unsigned long) parg; int ret=0; @@ -877,25 +877,25 @@ if (dmxdevfilter->statedev; - return DmxDevFilterFree(dmxdev, dmxdevfilter); + return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter); } static struct file_operations dvb_demux_fops = { - owner: THIS_MODULE, - read: dvb_demux_read, - write: 0, - ioctl: dvb_demux_ioctl, - open: dvb_demux_open, - release: dvb_demux_release, - poll: dvb_demux_poll, + .owner = THIS_MODULE, + .read = dvb_demux_read, + .ioctl = dvb_demux_ioctl, + .open = dvb_demux_open, + .release = dvb_demux_release, + .poll = dvb_demux_poll, }; -static dvb_device_t dvbdev_demux = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_demux_fops +static struct dvb_device dvbdev_demux = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_demux_fops }; static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; int ret=0; @@ -1008,13 +1007,13 @@ static int dvb_dvr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - return generic_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl); + return video_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl); } static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; dprintk ("function : %s\n", __FUNCTION__); @@ -1040,24 +1039,24 @@ } static struct file_operations dvb_dvr_fops = { - owner: THIS_MODULE, - read: dvb_dvr_read, - write: dvb_dvr_write, - ioctl: dvb_dvr_ioctl, - open: dvb_dvr_open, - release: dvb_dvr_release, - poll: dvb_dvr_poll, + .owner = THIS_MODULE, + .read = dvb_dvr_read, + .write = dvb_dvr_write, + .ioctl = dvb_dvr_ioctl, + .open = dvb_dvr_open, + .release = dvb_dvr_release, + .poll =dvb_dvr_poll, }; -static dvb_device_t dvbdev_dvr = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_dvr_fops +static struct dvb_device dvbdev_dvr = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_dvr_fops }; int -DmxDevInit(dmxdev_t *dmxdev, dvb_adapter_t *dvb_adapter) +dvb_dmxdev_init(dmxdev_t *dmxdev, struct dvb_adapter *dvb_adapter) { int i; @@ -1079,22 +1078,22 @@ for (i=0; ifilternum; i++) { dmxdev->filter[i].dev=dmxdev; dmxdev->filter[i].buffer.data=0; - DmxDevFilterStateSet(&dmxdev->filter[i], DMXDEV_STATE_FREE); + dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE); dmxdev->dvr[i].dev=dmxdev; dmxdev->dvr[i].buffer.data=0; - DmxDevFilterStateSet(&dmxdev->filter[i], DMXDEV_STATE_FREE); - DmxDevDVRStateSet(&dmxdev->dvr[i], DMXDEV_STATE_FREE); + dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE); + dvb_dmxdev_dvr_state_set(&dmxdev->dvr[i], DMXDEV_STATE_FREE); } dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, DVB_DEVICE_DEMUX); dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dmxdev, DVB_DEVICE_DVR); - DmxDevBufferInit(&dmxdev->dvr_buffer); + dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); MOD_INC_USE_COUNT; return 0; } void -DmxDevRelease(dmxdev_t *dmxdev) +dvb_dmxdev_release(dmxdev_t *dmxdev) { dvb_unregister_device(dmxdev->dvbdev); dvb_unregister_device(dmxdev->dvr_dvbdev); diff -Nru a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h --- a/drivers/media/dvb/dvb-core/dmxdev.h Wed Nov 27 14:36:32 2002 +++ b/drivers/media/dvb/dvb-core/dmxdev.h Wed Nov 27 14:36:32 2002 @@ -64,7 +64,7 @@ typedef struct dmxdev_filter_s { - dvb_device_t *dvbdev; + struct dvb_device *dvbdev; union { dmx_section_filter_t *sec; @@ -102,8 +102,8 @@ typedef struct dmxdev_s { - dvb_device_t *dvbdev; - dvb_device_t *dvr_dvbdev; + struct dvb_device *dvbdev; + struct dvb_device *dvr_dvbdev; dmxdev_filter_t *filter; dmxdev_dvr_t *dvr; @@ -122,7 +122,7 @@ } dmxdev_t; -int DmxDevInit(dmxdev_t *dmxdev, dvb_adapter_t *); -void DmxDevRelease(dmxdev_t *dmxdev); +int dvb_dmxdev_init(dmxdev_t *dmxdev, struct dvb_adapter *); +void dvb_dmxdev_release(dmxdev_t *dmxdev); #endif /* _DMXDEV_H_ */ diff -Nru a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c --- a/drivers/media/dvb/dvb-core/dvb_demux.c Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/dvb-core/dvb_demux.c Wed Nov 27 14:36:28 2002 @@ -182,7 +182,7 @@ ******************************************************************************/ static inline int -DvbDmxSWFilterPayload(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) +dvb_dmx_swfilter_payload(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf) { int p, count; //int ccok; @@ -208,8 +208,8 @@ static int -DvbDmxSWFilterSectionFilter(dvb_demux_feed_t *dvbdmxfeed, - dvb_demux_filter_t *f) +dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *dvbdmxfeed, + struct dvb_demux_filter *f) { dmx_section_filter_t *filter=&f->filter; int i; @@ -229,10 +229,10 @@ } static inline int -DvbDmxSWFilterSectionFeed(dvb_demux_feed_t *dvbdmxfeed) +dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *dvbdmxfeed) { u8 *buf=dvbdmxfeed->secbuf; - dvb_demux_filter_t *f; + struct dvb_demux_filter *f; if (dvbdmxfeed->secbufp!=dvbdmxfeed->seclen) return -1; @@ -241,7 +241,7 @@ if (!(f=dvbdmxfeed->filter)) return 0; do - if (DvbDmxSWFilterSectionFilter(dvbdmxfeed, f)<0) + if (dvb_dmx_swfilter_sectionfilter(dvbdmxfeed, f)<0) return -1; while ((f=f->next) && dvbdmxfeed->feed.sec.is_filtering); @@ -251,7 +251,7 @@ } static inline int -DvbDmxSWFilterSectionPacket(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) +dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf) { int p, count; int ccok, rest; @@ -286,7 +286,7 @@ memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p+1, buf[p]); dvbdmxfeed->secbufp+=buf[p]; - DvbDmxSWFilterSectionFeed(dvbdmxfeed); + dvb_dmx_swfilter_section_feed(dvbdmxfeed); } } p+=buf[p]+1; // skip rest of last section @@ -301,7 +301,7 @@ dvbdmxfeed->secbufp=dvbdmxfeed->seclen; p+=dvbdmxfeed->seclen; count=188-p; - DvbDmxSWFilterSectionFeed(dvbdmxfeed); + dvb_dmx_swfilter_section_feed(dvbdmxfeed); // filling bytes until packet end? if (count && buf[p]==0xff) @@ -337,7 +337,7 @@ if (rest<=count) { // section completed in this TS packet memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, rest); dvbdmxfeed->secbufp+=rest; - DvbDmxSWFilterSectionFeed(dvbdmxfeed); + dvb_dmx_swfilter_section_feed(dvbdmxfeed); } else { // section continues in following ts packet memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, count); dvbdmxfeed->secbufp+=count; @@ -346,7 +346,7 @@ } static inline void -DvbDmxSWFilterPacketType(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) +dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf) { switch(dvbdmxfeed->type) { case DMX_TYPE_TS: @@ -354,7 +354,7 @@ break; if (dvbdmxfeed->ts_type & TS_PACKET) { if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY) - DvbDmxSWFilterPayload(dvbdmxfeed, buf); + dvb_dmx_swfilter_payload(dvbdmxfeed, buf); else dvbdmxfeed->cb.ts((u8 *)buf, 188, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK); @@ -368,7 +368,7 @@ case DMX_TYPE_SEC: if (!dvbdmxfeed->feed.sec.is_filtering) break; - if (DvbDmxSWFilterSectionPacket(dvbdmxfeed, buf)<0) + if (dvb_dmx_swfilter_section_packet(dvbdmxfeed, buf)<0) dvbdmxfeed->seclen=dvbdmxfeed->secbufp=0; break; @@ -377,27 +377,27 @@ } } -void inline -DvbDmxSWFilterPacket(dvb_demux_t *dvbdmx, const u8 *buf) +void +dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf) { - dvb_demux_feed_t *dvbdmxfeed; + struct dvb_demux_feed *dvbdmxfeed; if (!(dvbdmxfeed=dvbdmx->pid2feed[ts_pid(buf)])) return; - DvbDmxSWFilterPacketType(dvbdmxfeed, buf); + dvb_dmx_swfilter_packet_type(dvbdmxfeed, buf); } void -DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count) +dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, int count) { - dvb_demux_feed_t *dvbdmxfeed; + struct dvb_demux_feed *dvbdmxfeed; spin_lock(&dvbdmx->lock); if ((dvbdmxfeed=dvbdmx->pid2feed[0x2000])) dvbdmxfeed->cb.ts((u8 *)buf, count*188, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK); while (count) { - DvbDmxSWFilterPacket(dvbdmx, buf); + dvb_dmx_swfilter_packet(dvbdmx, buf); count--; buf+=188; } @@ -405,7 +405,7 @@ } static inline void -DvbDmxSWFilter(dvb_demux_t *dvbdmx, const u8 *buf, size_t count) +dvb_dmx_swfilter(struct dvb_demux *dvbdmx, const u8 *buf, size_t count) { int p=0,i, j; @@ -416,7 +416,7 @@ return; } memcpy(&dvbdmx->tsbuf[i], buf, j); - DvbDmxSWFilterPacket(dvbdmx, dvbdmx->tsbuf); + dvb_dmx_swfilter_packet(dvbdmx, dvbdmx->tsbuf); dvbdmx->tsbufp=0; p+=j; } @@ -424,7 +424,7 @@ while (p=188) { - DvbDmxSWFilterPacket(dvbdmx, buf+p); + dvb_dmx_swfilter_packet(dvbdmx, buf+p); p+=188; } else { i=count-p; @@ -444,8 +444,8 @@ ****************************************************************************** ******************************************************************************/ -static dvb_demux_filter_t * -DvbDmxFilterAlloc(dvb_demux_t *dvbdmx) +static struct dvb_demux_filter * +dvb_dmx_filter_alloc(struct dvb_demux *dvbdmx) { int i; @@ -458,8 +458,8 @@ return &dvbdmx->filter[i]; } -static dvb_demux_feed_t * -DvbDmxFeedAlloc(dvb_demux_t *dvbdmx) +static struct dvb_demux_feed * +dvb_dmx_feed_alloc(struct dvb_demux *dvbdmx) { int i; @@ -478,10 +478,10 @@ ******************************************************************************/ static int -dmx_pid_set(u16 pid, dvb_demux_feed_t *dvbdmxfeed) +dmx_pid_set(u16 pid, struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; - dvb_demux_feed_t **pid2feed=dvbdmx->pid2feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed **pid2feed=dvbdmx->pid2feed; if (pid>DMX_MAX_PID) return -EINVAL; @@ -510,8 +510,8 @@ struct timespec timeout ) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -576,8 +576,8 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed_s* feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -608,8 +608,8 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed_s* feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -637,13 +637,13 @@ dmx_ts_feed_t **feed, dmx_ts_cb callback) { - dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; - dvb_demux_feed_t *dvbdmxfeed; + struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; + struct dvb_demux_feed *dvbdmxfeed; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; - if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) { + if (!(dvbdmxfeed=dvb_dmx_feed_alloc(dvbdmx))) { up(&dvbdmx->mutex); return -EBUSY; } @@ -663,7 +663,7 @@ (*feed)->stop_filtering=dmx_ts_feed_stop_filtering; - if (!(dvbdmxfeed->filter=DvbDmxFilterAlloc(dvbdmx))) { + if (!(dvbdmxfeed->filter=dvb_dmx_filter_alloc(dvbdmx))) { dvbdmxfeed->state=DMX_STATE_FREE; up(&dvbdmx->mutex); return -EBUSY; @@ -679,8 +679,8 @@ static int dvbdmx_release_ts_feed(dmx_demux_t *demux, dmx_ts_feed_t *feed) { - dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; @@ -715,14 +715,14 @@ dmx_section_feed_allocate_filter(struct dmx_section_feed_s* feed, dmx_section_filter_t** filter) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdemux=dvbdmxfeed->demux; - dvb_demux_filter_t *dvbdmxfilter; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdemux=dvbdmxfeed->demux; + struct dvb_demux_filter *dvbdmxfilter; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; - dvbdmxfilter=DvbDmxFilterAlloc(dvbdemux); + dvbdmxfilter=dvb_dmx_filter_alloc(dvbdemux); if (!dvbdmxfilter) { up(&dvbdemux->mutex); return -ENOSPC; @@ -747,8 +747,8 @@ u16 pid, size_t circular_buffer_size, int descramble, int check_crc) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; if (pid>0x1fff) return -EINVAL; @@ -789,11 +789,11 @@ return 0; } -static void prepare_secfilters(dvb_demux_feed_t *dvbdmxfeed) +static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) { int i; dmx_section_filter_t *sf; - dvb_demux_filter_t *f; + struct dvb_demux_filter *f; u8 mask, mode, doneq; if (!(f=dvbdmxfeed->filter)) @@ -815,8 +815,8 @@ static int dmx_section_feed_start_filtering(dmx_section_feed_t *feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -854,8 +854,8 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed_s* feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -878,9 +878,9 @@ dmx_section_feed_release_filter(dmx_section_feed_t *feed, dmx_section_filter_t* filter) { - dvb_demux_filter_t *dvbdmxfilter=(dvb_demux_filter_t *) filter, *f; - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_filter *dvbdmxfilter=(struct dvb_demux_filter *) filter, *f; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; @@ -911,13 +911,13 @@ dmx_section_feed_t **feed, dmx_section_cb callback) { - dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; - dvb_demux_feed_t *dvbdmxfeed; + struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; + struct dvb_demux_feed *dvbdmxfeed; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; - if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) { + if (!(dvbdmxfeed=dvb_dmx_feed_alloc(dvbdmx))) { up(&dvbdmx->mutex); return -EBUSY; } @@ -946,8 +946,8 @@ static int dvbdmx_release_section_feed(dmx_demux_t *demux, dmx_section_feed_t *feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; @@ -977,7 +977,7 @@ static int dvbdmx_open(dmx_demux_t *demux) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (dvbdemux->users>=MAX_DVB_DEMUX_USERS) return -EUSERS; @@ -987,7 +987,7 @@ static int dvbdmx_close(struct dmx_demux_s *demux) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (dvbdemux->users==0) return -ENODEV; @@ -998,7 +998,7 @@ static int dvbdmx_write(dmx_demux_t *demux, const char *buf, size_t count) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if ((!demux->frontend) || (demux->frontend->source!=DMX_MEMORY_FE)) @@ -1007,7 +1007,7 @@ if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; - DvbDmxSWFilter(dvbdemux, buf, count); + dvb_dmx_swfilter(dvbdemux, buf, count); up(&dvbdemux->mutex); return count; } @@ -1016,7 +1016,7 @@ static int dvbdmx_add_frontend(dmx_demux_t *demux, dmx_frontend_t *frontend) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; struct list_head *pos, *head=&dvbdemux->frontend_list; if (!(frontend->id && frontend->vendor && frontend->model)) @@ -1035,7 +1035,7 @@ dvbdmx_remove_frontend(dmx_demux_t *demux, dmx_frontend_t *frontend) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; struct list_head *pos, *n, *head=&dvbdemux->frontend_list; list_for_each_safe (pos, n, head) @@ -1052,7 +1052,7 @@ static struct list_head * dvbdmx_get_frontends(dmx_demux_t *demux) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (list_empty(&dvbdemux->frontend_list)) return NULL; @@ -1062,7 +1062,7 @@ static int dvbdmx_connect_frontend(dmx_demux_t *demux, dmx_frontend_t *frontend) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (demux->frontend) return -EINVAL; @@ -1077,7 +1077,7 @@ static int dvbdmx_disconnect_frontend(dmx_demux_t *demux) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; @@ -1089,24 +1089,24 @@ static int dvbdmx_get_pes_pids(dmx_demux_t *demux, u16 *pids) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; memcpy(pids, dvbdemux->pids, 5*sizeof(u16)); return 0; } int -DvbDmxInit(dvb_demux_t *dvbdemux) +dvb_dmx_init(struct dvb_demux *dvbdemux) { int i; dmx_demux_t *dmx=&dvbdemux->dmx; dvbdemux->users=0; - dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(dvb_demux_filter_t)); + dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter)); if (!dvbdemux->filter) return -ENOMEM; - dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(dvb_demux_feed_t)); + dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed)); if (!dvbdemux->feed) { vfree(dvbdemux->filter); return -ENOMEM; @@ -1125,7 +1125,7 @@ dvbdemux->pids[i]=0xffff; } dvbdemux->playing=dvbdemux->recording=0; - memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(dvb_demux_feed_t *)); + memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(struct dvb_demux_feed *)); dvbdemux->tsbufp=0; dmx->frontend=0; @@ -1159,7 +1159,7 @@ } int -DvbDmxRelease(dvb_demux_t *dvbdemux) +dvb_dmx_release(struct dvb_demux *dvbdemux) { dmx_demux_t *dmx=&dvbdemux->dmx; diff -Nru a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h --- a/drivers/media/dvb/dvb-core/dvb_demux.h Wed Nov 27 14:36:29 2002 +++ b/drivers/media/dvb/dvb-core/dvb_demux.h Wed Nov 27 14:36:29 2002 @@ -39,14 +39,14 @@ #define DVB_DEMUX_MASK_MAX 18 -typedef struct dvb_demux_filter_s { +struct dvb_demux_filter { dmx_section_filter_t filter; u8 maskandmode [DMX_MAX_FILTER_SIZE]; u8 maskandnotmode [DMX_MAX_FILTER_SIZE]; int doneq; - struct dvb_demux_filter_s *next; - struct dvb_demux_feed_s *feed; + struct dvb_demux_filter *next; + struct dvb_demux_feed *feed; int index; int state; int type; @@ -56,11 +56,10 @@ u16 hw_handle; struct timer_list timer; int ts_state; +}; - //u16 pid; //to be removed -} dvb_demux_filter_t; -typedef struct dvb_demux_feed_s { +struct dvb_demux_feed { union { dmx_ts_feed_t ts; dmx_section_feed_t sec; @@ -71,7 +70,7 @@ dmx_section_cb sec; } cb; - struct dvb_demux_s *demux; + struct dvb_demux *demux; int type; int state; u16 pid; @@ -81,7 +80,7 @@ int check_crc; struct timespec timeout; - dvb_demux_filter_t *filter; + struct dvb_demux_filter *filter; int cb_length; int ts_type; @@ -93,42 +92,43 @@ int cc; u16 peslen; -} dvb_demux_feed_t; +}; -typedef struct dvb_demux_s { +struct dvb_demux { dmx_demux_t dmx; void *priv; int filternum; int feednum; - int (*start_feed)(dvb_demux_feed_t *); - int (*stop_feed)(dvb_demux_feed_t *); - int (*write_to_decoder)(dvb_demux_feed_t *, u8 *, size_t); + int (*start_feed)(struct dvb_demux_feed *); + int (*stop_feed)(struct dvb_demux_feed *); + int (*write_to_decoder)(struct dvb_demux_feed *, u8 *, size_t); int users; #define MAX_DVB_DEMUX_USERS 10 - dvb_demux_filter_t *filter; - dvb_demux_feed_t *feed; + struct dvb_demux_filter *filter; + struct dvb_demux_feed *feed; struct list_head frontend_list; - dvb_demux_feed_t *pesfilter[DMX_TS_PES_OTHER]; + struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER]; u16 pids[DMX_TS_PES_OTHER]; int playing; int recording; #define DMX_MAX_PID 0x2000 - dvb_demux_feed_t *pid2feed[DMX_MAX_PID+1]; + struct dvb_demux_feed *pid2feed[DMX_MAX_PID+1]; u8 tsbuf[188]; int tsbufp; struct semaphore mutex; spinlock_t lock; -} dvb_demux_t; +}; -int DvbDmxInit(dvb_demux_t *dvbdemux); -int DvbDmxRelease(dvb_demux_t *dvbdemux); -void DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count); +int dvb_dmx_init(struct dvb_demux *dvbdemux); +int dvb_dmx_release(struct dvb_demux *dvbdemux); +void dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf); +void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, int count); #endif /* _DVB_DEMUX_H_ */ diff -Nru a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c --- a/drivers/media/dvb/dvb-core/dvb_filter.c Wed Nov 27 14:36:32 2002 +++ b/drivers/media/dvb/dvb-core/dvb_filter.c Wed Nov 27 14:36:32 2002 @@ -24,454 +24,23 @@ -void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, - pes2ts_cb_t *cb, void *priv) -{ - unsigned char *buf=p2ts->buf; - - buf[0]=0x47; - buf[1]=(pid>>8); - buf[2]=pid&0xff; - p2ts->cc=0; - p2ts->cb=cb; - p2ts->priv=priv; -} - -int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len) -{ - unsigned char *buf=p2ts->buf; - int ret=0, rest; - - //len=6+((pes[4]<<8)|pes[5]); - - buf[1]|=0x40; - while (len>=184) { - buf[3]=0x10|((p2ts->cc++)&0x0f); - memcpy(buf+4, pes, 184); - if ((ret=p2ts->cb(p2ts->priv, buf))) - return ret; - len-=184; pes+=184; - buf[1]&=~0x40; - } - if (!len) - return 0; - buf[3]=0x30|((p2ts->cc++)&0x0f); - rest=183-len; - if (rest) { - buf[5]=0x00; - if (rest-1) - memset(buf+6, 0xff, rest-1); - } - buf[4]=rest; - memcpy(buf+5+rest, pes, len); - return p2ts->cb(p2ts->priv, buf); -} - -void reset_ipack(ipack *p) -{ - p->found = 0; - p->cid = 0; - p->plength = 0; - p->flag1 = 0; - p->flag2 = 0; - p->hlength = 0; - p->mpeg = 0; - p->check = 0; - p->which = 0; - p->done = 0; - p->count = 0; -} - -void init_ipack(ipack *p, int size, - void (*func)(u8 *buf, int size, void *priv)) -{ - if ( !(p->buf = vmalloc(size*sizeof(u8))) ){ - printk ("Couldn't allocate memory for ipack\n"); - } - p->size = size; - p->func = func; - p->repack_subids = 0; - reset_ipack(p); -} - -void free_ipack(ipack * p) -{ - if (p->buf) vfree(p->buf); -} - -void send_ipack(ipack *p) -{ - int off; - AudioInfo ai; - int ac3_off = 0; - int streamid=0; - int nframes= 0; - int f=0; - - switch ( p->mpeg ){ - case 2: - if (p->count < 10) return; - p->buf[3] = p->cid; - - p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); - p->buf[5] = (u8)((p->count-6) & 0x00FF); - if (p->repack_subids && p->cid == PRIVATE_STREAM1){ - - off = 9+p->buf[8]; - streamid = p->buf[off]; - if ((streamid & 0xF8) == 0x80){ - ai.off = 0; - ac3_off = ((p->buf[off+2] << 8)| - p->buf[off+3]); - if (ac3_off < p->count) - f=get_ac3info(p->buf+off+3+ac3_off, - p->count-ac3_off, &ai,0); - if ( !f ){ - nframes = (p->count-off-3-ac3_off)/ - ai.framesize + 1; - p->buf[off+2] = (ac3_off >> 8)& 0xFF; - p->buf[off+3] = (ac3_off)& 0xFF; - p->buf[off+1] = nframes; - - ac3_off += nframes * ai.framesize - - p->count; - } - } - } - p->func(p->buf, p->count, p->data); - - p->buf[6] = 0x80; - p->buf[7] = 0x00; - p->buf[8] = 0x00; - p->count = 9; - if (p->repack_subids && p->cid == PRIVATE_STREAM1 - && (streamid & 0xF8)==0x80 ){ - p->count += 4; - p->buf[9] = streamid; - p->buf[10] = (ac3_off >> 8)& 0xFF; - p->buf[11] = (ac3_off)& 0xFF; - p->buf[12] = 0; - } - - break; - case 1: - if (p->count < 8) return; - p->buf[3] = p->cid; - - p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); - p->buf[5] = (u8)((p->count-6) & 0x00FF); - p->func(p->buf, p->count, p->data); - - p->buf[6] = 0x0F; - p->count = 7; - break; - } -} - -void send_ipack_rest(ipack *p) -{ - if (p->plength != MMAX_PLENGTH-6 || p->found<=6) - return; - p->plength = p->found-6; - p->found = 0; - send_ipack(p); - reset_ipack(p); -} - -static void write_ipack(ipack *p, u8 *data, int count) -{ - u8 headr[3] = { 0x00, 0x00, 0x01} ; - - if (p->count < 6){ - memcpy(p->buf, headr, 3); - p->count = 6; - } - - if (p->count + count < p->size){ - memcpy(p->buf+p->count, data, count); - p->count += count; - } else { - int rest = p->size - p->count; - memcpy(p->buf+p->count, data, rest); - p->count += rest; - send_ipack(p); - if (count - rest > 0) - write_ipack(p, data+rest, count-rest); - } -} - -int instant_repack(u8 *buf, int count, ipack *p) -{ - int l; - int c=0; - - while (c < count && (p->mpeg == 0 || - (p->mpeg == 1 && p->found < 7) || - (p->mpeg == 2 && p->found < 9)) - && (p->found < 5 || !p->done)){ - switch ( p->found ){ - case 0: - case 1: - if (buf[c] == 0x00) p->found++; - else p->found = 0; - c++; - break; - case 2: - if (buf[c] == 0x01) p->found++; - else if (buf[c] == 0) { - p->found = 2; - } else p->found = 0; - c++; - break; - case 3: - p->cid = 0; - switch (buf[c]){ - case PROG_STREAM_MAP: - case PRIVATE_STREAM2: - case PROG_STREAM_DIR: - case ECM_STREAM : - case EMM_STREAM : - case PADDING_STREAM : - case DSM_CC_STREAM : - case ISO13522_STREAM: - p->done = 1; - case PRIVATE_STREAM1: - case VIDEO_STREAM_S ... VIDEO_STREAM_E: - case AUDIO_STREAM_S ... AUDIO_STREAM_E: - p->found++; - p->cid = buf[c]; - c++; - break; - default: - p->found = 0; - break; - } - break; - - case 4: - if (count-c > 1){ - p->plen[0] = buf[c]; - c++; - p->plen[1] = buf[c]; - c++; - p->found+=2; - p->plength=(p->plen[0]<<8)|p->plen[1]; - } else { - p->plen[0] = buf[c]; - p->found++; - return count; - } - break; - case 5: - p->plen[1] = buf[c]; - c++; - p->found++; - p->plength=(p->plen[0]<<8)|p->plen[1]; - break; - case 6: - if (!p->done){ - p->flag1 = buf[c]; - c++; - p->found++; - if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2; - else { - p->hlength = 0; - p->which = 0; - p->mpeg = 1; - p->flag2 = 0; - } - } - break; - - case 7: - if ( !p->done && p->mpeg == 2) { - p->flag2 = buf[c]; - c++; - p->found++; - } - break; - - case 8: - if ( !p->done && p->mpeg == 2) { - p->hlength = buf[c]; - c++; - p->found++; - } - break; - - default: - - break; - } - } - - if (c == count) return count; - - if (!p->plength) p->plength = MMAX_PLENGTH-6; - - if ( p->done || ((p->mpeg == 2 && p->found >= 9) || - (p->mpeg == 1 && p->found >= 7)) ){ - switch (p->cid){ - - case AUDIO_STREAM_S ... AUDIO_STREAM_E: - case VIDEO_STREAM_S ... VIDEO_STREAM_E: - case PRIVATE_STREAM1: - - if (p->mpeg == 2 && p->found == 9) { - write_ipack(p, &p->flag1, 1); - write_ipack(p, &p->flag2, 1); - write_ipack(p, &p->hlength, 1); - } - - if (p->mpeg == 1 && p->found == 7) - write_ipack(p, &p->flag1, 1); - - if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) && - p->found < 14) { - while (c < count && p->found < 14) { - p->pts[p->found-9] = buf[c]; - write_ipack(p, buf+c, 1); - c++; - p->found++; - } - if (c == count) return count; - } - - if (p->mpeg == 1 && p->which < 2000) { - - if (p->found == 7) { - p->check = p->flag1; - p->hlength = 1; - } - - while (!p->which && c < count && - p->check == 0xFF){ - p->check = buf[c]; - write_ipack(p, buf+c, 1); - c++; - p->found++; - p->hlength++; - } - - if ( c == count) return count; - - if ( (p->check & 0xC0) == 0x40 && !p->which){ - p->check = buf[c]; - write_ipack(p, buf+c, 1); - c++; - p->found++; - p->hlength++; - - p->which = 1; - if ( c == count) return count; - p->check = buf[c]; - write_ipack(p, buf+c, 1); - c++; - p->found++; - p->hlength++; - p->which = 2; - if ( c == count) return count; - } - - if (p->which == 1){ - p->check = buf[c]; - write_ipack(p, buf+c, 1); - c++; - p->found++; - p->hlength++; - p->which = 2; - if ( c == count) return count; - } - - if ( (p->check & 0x30) && p->check != 0xFF){ - p->flag2 = (p->check & 0xF0) << 2; - p->pts[0] = p->check; - p->which = 3; - } - - if ( c == count) return count; - if (p->which > 2){ - if ((p->flag2 & PTS_DTS_FLAGS) - == PTS_ONLY){ - while (c < count && - p->which < 7){ - p->pts[p->which-2] = - buf[c]; - write_ipack(p,buf+c,1); - c++; - p->found++; - p->which++; - p->hlength++; - } - if ( c == count) return count; - } else if ((p->flag2 & PTS_DTS_FLAGS) - == PTS_DTS){ - while (c < count && - p->which< 12){ - if (p->which< 7) - p->pts[p->which - -2] = - buf[c]; - write_ipack(p,buf+c,1); - c++; - p->found++; - p->which++; - p->hlength++; - } - if ( c == count) return count; - } - p->which = 2000; - } - - } - - while (c < count && p->found < p->plength+6){ - l = count -c; - if (l+p->found > p->plength+6) - l = p->plength+6-p->found; - write_ipack(p, buf+c, l); - p->found += l; - c += l; - } - - break; - } - - - if ( p->done ){ - if( p->found + count - c < p->plength+6){ - p->found += count-c; - c = count; - } else { - c += p->plength+6 - p->found; - p->found = p->plength+6; - } - } - - if (p->plength && p->found == p->plength+6) { - send_ipack(p); - reset_ipack(p); - if (c < count) - instant_repack(buf+c, count-c, p); - } - } - return count; -} - - - +#if 0 +static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, void (*pes_write)(u8 *buf, int count, void *data), void *priv) { - init_ipack(pa, IPACKS, pes_write); - init_ipack(pv, IPACKS, pes_write); + dvb_filter_ipack_init(pa, IPACKS, pes_write); + dvb_filter_ipack_init(pv, IPACKS, pes_write); pa->pid = pida; pv->pid = pidv; pa->data = priv; pv->data = priv; } +#endif +#if 0 +static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188) { u8 off = 0; @@ -483,28 +52,31 @@ if (buf[1]&PAY_START) { if (p->plength == MMAX_PLENGTH-6 && p->found>6){ p->plength = p->found-6; - p->found = 0; + p->found = 0; send_ipack(p); - reset_ipack(p); - } + dvb_filter_ipack_reset(p); + } } if (buf[3] & ADAPT_FIELD) { // adaptation field? off = buf[4] + 1; if (off+4 > 187) return; } - instant_repack(buf+4+off, TS_SIZE-4-off, p); + dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p); } +#endif +#if 0 /* needs 5 byte input, returns picture coding type*/ +static int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr) { uint8_t pct; - + if (pr) printk( "Pic header: "); pic->temporal_reference[field] = (( headr[0] << 2 ) | (headr[1] & 0x03) )& 0x03ff; if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]); - + pct = ( headr[1] >> 2 ) & 0x07; pic->picture_coding_type[field] = pct; if (pr) { @@ -518,29 +90,31 @@ case P_FRAME: printk( " P-FRAME"); break; - } - } - + } + } + pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) | ( (headr[3] & 0x1F) << 11) ) & 0xffff; - + if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay); - + pic->picture_header_parameter = ( headr[3] & 0xe0 ) | ((headr[4] & 0x80) >> 3); if ( pct == B_FRAME ){ pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f; - } + } if (pr) printk( " pic head param: 0x%x", pic->picture_header_parameter); return pct; -} - +} +#endif +#if 0 /* needs 4 byte input */ +static int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr) { if (pr) printk("GOP header: "); @@ -556,20 +130,23 @@ pic->closed_gop = 1; } else { pic->closed_gop = 0; - } + } if (pr) printk("closed: %d", pic->closed_gop); if ( ( headr[3] & 0x20 ) != 0 ){ pic->broken_link = 1; - } else { + } else { pic->broken_link = 0; - } + } if (pr) printk(" broken: %d\n", pic->broken_link); return 0; } +#endif +#if 0 /* needs 8 byte input */ +static int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr) { int sw; @@ -583,37 +160,37 @@ sw = (int)((headr[3]&0xF0) >> 4) ; switch( sw ){ - case 1: + case 1: if (pr) printk("Videostream: ASPECT: 1:1"); vi->aspect_ratio = 100; - break; - case 2: + break; + case 2: if (pr) printk("Videostream: ASPECT: 4:3"); vi->aspect_ratio = 133; - break; - case 3: + break; + case 3: if (pr) printk("Videostream: ASPECT: 16:9"); vi->aspect_ratio = 177; - break; + break; case 4: if (pr) printk("Videostream: ASPECT: 2.21:1"); vi->aspect_ratio = 221; - break; + break; case 5 ... 15: if (pr) printk("Videostream: ASPECT: reserved"); vi->aspect_ratio = 0; - break; - + break; + default: vi->aspect_ratio = 0; return -1; - } + } if (pr) printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size); @@ -644,29 +221,29 @@ printk(" FRate: 29.97 fps"); vi->framerate = 29970; form = VIDEO_MODE_NTSC; - break; - case 5: + break; + case 5: if (pr) printk(" FRate: 30 fps"); vi->framerate = 30000; form = VIDEO_MODE_NTSC; - break; - case 6: + break; + case 6: if (pr) printk(" FRate: 50 fps"); vi->framerate = 50000; form = VIDEO_MODE_PAL; - break; - case 7: + break; + case 7: if (pr) printk(" FRate: 60 fps"); vi->framerate = 60000; form = VIDEO_MODE_NTSC; - break; - } - + break; + } + vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03); - + vi->vbv_buffer_size = (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5); @@ -680,13 +257,17 @@ return 0; } +#endif + +#if 0 +static int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr) { uint8_t *headr; int found = 0; int c = 0; - + while (found < 4 && c+4 < count){ uint8_t *b; @@ -696,7 +277,7 @@ else { c++; } - } + } if (! found) return -1; c += 4; @@ -706,7 +287,11 @@ vi->off = c-4; return 0; } +#endif + +#if 0 +static int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr) { uint8_t *headr; @@ -721,9 +306,9 @@ if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) found = 2; else { - c++; - } - } + c++; + } + } if (!found) return -1; @@ -745,7 +330,7 @@ printk(" BRate: reserved"); else printk(" BRate: %d kb/s", ai->bit_rate/1000); - } + } fr = (headr[2] & 0x0c ) >> 2; ai->frequency = freq[fr]*100; @@ -755,11 +340,13 @@ else printk(" Freq: %d kHz\n",ai->frequency); - } + } ai->off = c; return 0; } - +#endif + +static int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr) { uint8_t *headr; @@ -767,27 +354,27 @@ int c = 0; uint8_t frame = 0; int fr = 0; - + while ( !found && c < count){ uint8_t *b = mbuf+c; - + if ( b[0] == 0x0b && b[1] == 0x77 ) found = 1; else { - c++; - } - } - + c++; + } + } + if (!found) return -1; if (pr) printk("Audiostream: AC3"); - + ai->off = c; if (c+5 >= count) return -1; - + ai->layer = 0; // 0 for AC3 headr = mbuf+c+2; - + frame = (headr[2]&0x3f); ai->bit_rate = ac3_bitrates[frame >> 1]*1000; @@ -809,6 +396,9 @@ return 0; } + +#if 0 +static uint8_t *skip_pes_header(uint8_t **bufp) { uint8_t *inbuf = *bufp; @@ -816,10 +406,10 @@ uint8_t *pts = NULL; int skip = 0; -int mpeg1_skip_table[16] = { - 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff -}; + static const int mpeg1_skip_table[16] = { + 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff + }; if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */ @@ -830,8 +420,8 @@ } else { /* mpeg1 */ for (buf = inbuf + 6; *buf == 0xff; buf++) if (buf == inbuf + 6 + 16) { - break; - } + break; + } if ((*buf & 0xc0) == 0x40) buf += 2; skip = mpeg1_skip_table [*buf >> 4]; @@ -843,9 +433,11 @@ *bufp = buf; return pts; -} - +} +#endif +#if 0 +static void initialize_quant_matrix( uint32_t *matrix ) { int i; @@ -870,7 +462,10 @@ for ( i = 16 ; i < 32 ; i++ ) matrix[i] = 0x10101010; } +#endif +#if 0 +static void initialize_mpg_picture(mpg_picture *pic) { int i; @@ -895,8 +490,10 @@ pic->gop_flag = 0; pic->sequence_end_flag = 0; } +#endif - +#if 0 +static void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic ) { int16_t last_h_offset; @@ -912,7 +509,7 @@ pic->progressive_frame = 1; pic->picture_coding_parameter = 0x000010; } - + /* Reset flag */ pic->picture_display_extension_flag[field_type] = 0; @@ -930,9 +527,12 @@ } else { pic->frame_centre_horizontal_offset[3] = last_h_offset; pic->frame_centre_vertical_offset[3] = last_v_offset; - } + } } +#endif +#if 0 +static void init_mpg_picture( mpg_picture *pic, int chan, int32_t field_type) { pic->picture_header = 0; @@ -960,3 +560,442 @@ pic->last_frame_centre_vertical_offset = 0; pic->channel = chan; } +#endif + +void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid, + dvb_filter_pes2ts_cb_t *cb, void *priv) +{ + unsigned char *buf=p2ts->buf; + + buf[0]=0x47; + buf[1]=(pid>>8); + buf[2]=pid&0xff; + p2ts->cc=0; + p2ts->cb=cb; + p2ts->priv=priv; +} + +int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len) +{ + unsigned char *buf=p2ts->buf; + int ret=0, rest; + + //len=6+((pes[4]<<8)|pes[5]); + + buf[1]|=0x40; + while (len>=184) { + buf[3]=0x10|((p2ts->cc++)&0x0f); + memcpy(buf+4, pes, 184); + if ((ret=p2ts->cb(p2ts->priv, buf))) + return ret; + len-=184; pes+=184; + buf[1]&=~0x40; + } + if (!len) + return 0; + buf[3]=0x30|((p2ts->cc++)&0x0f); + rest=183-len; + if (rest) { + buf[5]=0x00; + if (rest-1) + memset(buf+6, 0xff, rest-1); + } + buf[4]=rest; + memcpy(buf+5+rest, pes, len); + return p2ts->cb(p2ts->priv, buf); +} + +void dvb_filter_ipack_reset(ipack *p) +{ + p->found = 0; + p->cid = 0; + p->plength = 0; + p->flag1 = 0; + p->flag2 = 0; + p->hlength = 0; + p->mpeg = 0; + p->check = 0; + p->which = 0; + p->done = 0; + p->count = 0; +} + +void dvb_filter_ipack_init(ipack *p, int size, + void (*func)(u8 *buf, int size, void *priv)) +{ + if ( !(p->buf = vmalloc(size*sizeof(u8))) ){ + printk ("Couldn't allocate memory for ipack\n"); + } + p->size = size; + p->func = func; + p->repack_subids = 0; + dvb_filter_ipack_reset(p); +} + +void dvb_filter_ipack_free(ipack * p) +{ + if (p->buf) vfree(p->buf); +} + +static +void send_ipack(ipack *p) +{ + int off; + AudioInfo ai; + int ac3_off = 0; + int streamid=0; + int nframes= 0; + int f=0; + + switch ( p->mpeg ){ + case 2: + if (p->count < 10) return; + p->buf[3] = p->cid; + + p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); + p->buf[5] = (u8)((p->count-6) & 0x00FF); + if (p->repack_subids && p->cid == PRIVATE_STREAM1){ + + off = 9+p->buf[8]; + streamid = p->buf[off]; + if ((streamid & 0xF8) == 0x80){ + ai.off = 0; + ac3_off = ((p->buf[off+2] << 8)| + p->buf[off+3]); + if (ac3_off < p->count) + f=get_ac3info(p->buf+off+3+ac3_off, + p->count-ac3_off, &ai,0); + if ( !f ){ + nframes = (p->count-off-3-ac3_off)/ + ai.framesize + 1; + p->buf[off+2] = (ac3_off >> 8)& 0xFF; + p->buf[off+3] = (ac3_off)& 0xFF; + p->buf[off+1] = nframes; + + ac3_off += nframes * ai.framesize - + p->count; + } + } + } + p->func(p->buf, p->count, p->data); + + p->buf[6] = 0x80; + p->buf[7] = 0x00; + p->buf[8] = 0x00; + p->count = 9; + if (p->repack_subids && p->cid == PRIVATE_STREAM1 + && (streamid & 0xF8)==0x80 ){ + p->count += 4; + p->buf[9] = streamid; + p->buf[10] = (ac3_off >> 8)& 0xFF; + p->buf[11] = (ac3_off)& 0xFF; + p->buf[12] = 0; + } + + break; + case 1: + if (p->count < 8) return; + p->buf[3] = p->cid; + + p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); + p->buf[5] = (u8)((p->count-6) & 0x00FF); + p->func(p->buf, p->count, p->data); + + p->buf[6] = 0x0F; + p->count = 7; + break; + } +} + +void dvb_filter_ipack_flush(ipack *p) +{ + if (p->plength != MMAX_PLENGTH-6 || p->found<=6) + return; + p->plength = p->found-6; + p->found = 0; + send_ipack(p); + dvb_filter_ipack_reset(p); +} + +static +void write_ipack(ipack *p, u8 *data, int count) +{ + u8 headr[3] = { 0x00, 0x00, 0x01} ; + + if (p->count < 6){ + memcpy(p->buf, headr, 3); + p->count = 6; + } + + if (p->count + count < p->size){ + memcpy(p->buf+p->count, data, count); + p->count += count; + } else { + int rest = p->size - p->count; + memcpy(p->buf+p->count, data, rest); + p->count += rest; + send_ipack(p); + if (count - rest > 0) + write_ipack(p, data+rest, count-rest); + } +} + + +int dvb_filter_instant_repack(u8 *buf, int count, ipack *p) +{ + int l; + int c=0; + + while (c < count && (p->mpeg == 0 || + (p->mpeg == 1 && p->found < 7) || + (p->mpeg == 2 && p->found < 9)) + && (p->found < 5 || !p->done)){ + switch ( p->found ){ + case 0: + case 1: + if (buf[c] == 0x00) p->found++; + else p->found = 0; + c++; + break; + case 2: + if (buf[c] == 0x01) p->found++; + else if (buf[c] == 0) { + p->found = 2; + } else p->found = 0; + c++; + break; + case 3: + p->cid = 0; + switch (buf[c]){ + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + p->done = 1; + case PRIVATE_STREAM1: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + p->found++; + p->cid = buf[c]; + c++; + break; + default: + p->found = 0; + break; + } + break; + + case 4: + if (count-c > 1){ + p->plen[0] = buf[c]; + c++; + p->plen[1] = buf[c]; + c++; + p->found+=2; + p->plength=(p->plen[0]<<8)|p->plen[1]; + } else { + p->plen[0] = buf[c]; + p->found++; + return count; + } + break; + case 5: + p->plen[1] = buf[c]; + c++; + p->found++; + p->plength=(p->plen[0]<<8)|p->plen[1]; + break; + case 6: + if (!p->done){ + p->flag1 = buf[c]; + c++; + p->found++; + if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2; + else { + p->hlength = 0; + p->which = 0; + p->mpeg = 1; + p->flag2 = 0; + } + } + break; + + case 7: + if ( !p->done && p->mpeg == 2) { + p->flag2 = buf[c]; + c++; + p->found++; + } + break; + + case 8: + if ( !p->done && p->mpeg == 2) { + p->hlength = buf[c]; + c++; + p->found++; + } + break; + + default: + + break; + } + } + + if (c == count) return count; + + if (!p->plength) p->plength = MMAX_PLENGTH-6; + + if ( p->done || ((p->mpeg == 2 && p->found >= 9) || + (p->mpeg == 1 && p->found >= 7)) ){ + switch (p->cid){ + + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case PRIVATE_STREAM1: + + if (p->mpeg == 2 && p->found == 9) { + write_ipack(p, &p->flag1, 1); + write_ipack(p, &p->flag2, 1); + write_ipack(p, &p->hlength, 1); + } + + if (p->mpeg == 1 && p->found == 7) + write_ipack(p, &p->flag1, 1); + + if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) && + p->found < 14) { + while (c < count && p->found < 14) { + p->pts[p->found-9] = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + } + if (c == count) return count; + } + + if (p->mpeg == 1 && p->which < 2000) { + + if (p->found == 7) { + p->check = p->flag1; + p->hlength = 1; + } + + while (!p->which && c < count && + p->check == 0xFF){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + } + + if ( c == count) return count; + + if ( (p->check & 0xC0) == 0x40 && !p->which){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + + p->which = 1; + if ( c == count) return count; + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return count; + } + + if (p->which == 1){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return count; + } + + if ( (p->check & 0x30) && p->check != 0xFF){ + p->flag2 = (p->check & 0xF0) << 2; + p->pts[0] = p->check; + p->which = 3; + } + + if ( c == count) return count; + if (p->which > 2){ + if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_ONLY){ + while (c < count && + p->which < 7){ + p->pts[p->which-2] = + buf[c]; + write_ipack(p,buf+c,1); + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return count; + } else if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_DTS){ + while (c < count && + p->which< 12){ + if (p->which< 7) + p->pts[p->which + -2] = + buf[c]; + write_ipack(p,buf+c,1); + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return count; + } + p->which = 2000; + } + + } + + while (c < count && p->found < p->plength+6){ + l = count -c; + if (l+p->found > p->plength+6) + l = p->plength+6-p->found; + write_ipack(p, buf+c, l); + p->found += l; + c += l; + } + + break; + } + + + if ( p->done ){ + if( p->found + count - c < p->plength+6){ + p->found += count-c; + c = count; + } else { + c += p->plength+6 - p->found; + p->found = p->plength+6; + } + } + + if (p->plength && p->found == p->plength+6) { + send_ipack(p); + dvb_filter_ipack_reset(p); + if (c < count) + dvb_filter_instant_repack(buf+c, count-c, p); + } + } + return count; +} + diff -Nru a/drivers/media/dvb/dvb-core/dvb_filter.h b/drivers/media/dvb/dvb-core/dvb_filter.h --- a/drivers/media/dvb/dvb-core/dvb_filter.h Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/dvb-core/dvb_filter.h Wed Nov 27 14:36:28 2002 @@ -6,18 +6,18 @@ #include "demux.h" -typedef int (pes2ts_cb_t) (void *, unsigned char *); +typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *); -typedef struct pes2ts_s { +typedef struct dvb_filter_pes2ts_s { unsigned char buf[188]; unsigned char cc; - pes2ts_cb_t *cb; + dvb_filter_pes2ts_cb_t *cb; void *priv; -} pes2ts_t; +} dvb_filter_pes2ts_t; -void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, - pes2ts_cb_t *cb, void *priv); -int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len); +void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid, + dvb_filter_pes2ts_cb_t *cb, void *priv); +int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len); #define PROG_STREAM_MAP 0xBC @@ -224,26 +224,11 @@ } AudioInfo; -void reset_ipack(ipack *p); -int instant_repack(u8 *buf, int count, ipack *p); -void init_ipack(ipack *p, int size, +void dvb_filter_ipack_reset(ipack *p); +int dvb_filter_instant_repack(u8 *buf, int count, ipack *p); +void dvb_filter_ipack_init(ipack *p, int size, void (*func)(u8 *buf, int size, void *priv)); -void free_ipack(ipack * p); -void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, - void (*pes_write)(u8 *buf, int count, void *data), - void *priv); -void ts_to_pes(ipack *p, u8 *buf); -void send_ipack(ipack *p); -void send_ipack_rest(ipack *p); -int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr); -int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr); -int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr); -uint8_t *skip_pes_header(uint8_t **bufp); -void initialize_quant_matrix( uint32_t *matrix ); -void initialize_mpg_picture(mpg_picture *pic); -void init_mpg_picture( mpg_picture *pic, int chan, int32_t field_type); -void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic ); -int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr); -int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr); -int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr); +void dvb_filter_ipack_free(ipack * p); +void dvb_filter_ipack_flush(ipack *p); + #endif diff -Nru a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c --- a/drivers/media/dvb/dvb-core/dvb_frontend.c Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c Wed Nov 27 14:36:28 2002 @@ -83,7 +83,7 @@ struct dvb_frontend_ioctl_data { struct list_head list_head; - struct dvb_adapter_s *adapter; + struct dvb_adapter *adapter; int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); int (*after_ioctl) (struct dvb_frontend *frontend, @@ -336,9 +336,6 @@ struct dvb_frontend *frontend = &fe->frontend; int err; - dprintk ("%s: f == %i, drift == %i\n", - __FUNCTION__, param->frequency, fe->lnb_drift); - dvb_bend_frequency (fe, 0); if (first_trial) { @@ -352,6 +349,9 @@ sizeof (struct dvb_frontend_parameters)); } + dprintk ("%s: f == %i, drift == %i\n", + __FUNCTION__, param->frequency, fe->lnb_drift); + param->frequency += fe->lnb_drift + fe->bending; err = dvb_frontend_internal_ioctl (frontend, FE_SET_FRONTEND, param); param->frequency -= fe->lnb_drift + fe->bending; @@ -367,9 +367,8 @@ struct dvb_frontend *frontend = &fe->frontend; struct dvb_frontend_parameters *init_param; - printk ("%s: initialising frontend %i:%i (%s)...\n", __FUNCTION__, - frontend->i2c->adapter->num, frontend->i2c->id, - fe->info->name); + printk ("DVB: initialising frontend %i:%i (%s)...\n", + frontend->i2c->adapter->num, frontend->i2c->id, fe->info->name); dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL); @@ -436,15 +435,20 @@ */ { int j = fe->lost_sync_count; - int stepsize = fe->info->frequency_stepsize; - - if (j % 32 == 0) - fe->lnb_drift = 0; + int stepsize; - if (j % 2) - fe->lnb_drift += stepsize * ((j+1)/2); + if (fe->info->type == FE_QPSK) + stepsize = fe->parameters.u.qpsk.symbol_rate / 16000; else + stepsize = fe->info->frequency_stepsize * 2; + + if (j % 32 == 0) { + fe->lnb_drift = 0; + } else { fe->lnb_drift = -fe->lnb_drift; + if (j % 2) + fe->lnb_drift += stepsize; + } dvb_frontend_set_parameters (fe, &fe->parameters, 0); } @@ -511,7 +515,8 @@ fe->lost_sync_count = 0; } else { fe->lost_sync_count++; - + if (fe->lost_sync_count < 10) /* XXX FIXME CHECKME! */ + continue; dvb_frontend_recover (fe); delay = HZ/5; if (jiffies - fe->lost_sync_jiffies > TIMEOUT) { @@ -627,7 +632,7 @@ static int dvb_frontend_open (struct inode *inode, struct file *file) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; struct dvb_frontend_data *fe = dvbdev->priv; int ret; @@ -648,7 +653,7 @@ static int dvb_frontend_release (struct inode *inode, struct file *file) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; struct dvb_frontend_data *fe = dvbdev->priv; dprintk ("%s\n", __FUNCTION__); @@ -661,7 +666,7 @@ int -dvb_add_frontend_ioctls (struct dvb_adapter_s *adapter, +dvb_add_frontend_ioctls (struct dvb_adapter *adapter, int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), int (*after_ioctl) (struct dvb_frontend *frontend, @@ -715,7 +720,7 @@ void -dvb_remove_frontend_ioctls (struct dvb_adapter_s *adapter, +dvb_remove_frontend_ioctls (struct dvb_adapter *adapter, int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), int (*after_ioctl) (struct dvb_frontend *frontend, @@ -748,7 +753,7 @@ int -dvb_add_frontend_notifier (struct dvb_adapter_s *adapter, +dvb_add_frontend_notifier (struct dvb_adapter *adapter, void (*callback) (fe_status_t s, void *data), void *data) { @@ -791,7 +796,7 @@ void -dvb_remove_frontend_notifier (struct dvb_adapter_s *adapter, +dvb_remove_frontend_notifier (struct dvb_adapter *adapter, void (*callback) (fe_status_t s, void *data)) { struct list_head *entry; @@ -827,11 +832,11 @@ static struct file_operations dvb_frontend_fops = { - owner: THIS_MODULE, - ioctl: dvb_generic_ioctl, - poll: dvb_frontend_poll, - open: dvb_frontend_open, - release: dvb_frontend_release + .owner = THIS_MODULE, + .ioctl = dvb_generic_ioctl, + .poll = dvb_frontend_poll, + .open = dvb_frontend_open, + .release = dvb_frontend_release }; @@ -845,9 +850,11 @@ { struct list_head *entry; struct dvb_frontend_data *fe; - dvb_device_t dvbdev_template = { users: 1, writers: 1, - fops: &dvb_frontend_fops, - kernel_ioctl: dvb_frontend_ioctl + static const struct dvb_device dvbdev_template = { + .users = 1, + .writers = 1, + .fops = &dvb_frontend_fops, + .kernel_ioctl = dvb_frontend_ioctl }; dprintk ("%s\n", __FUNCTION__); @@ -878,7 +885,9 @@ list_for_each (entry, &frontend_ioctl_list) { struct dvb_frontend_ioctl_data *ioctl; - ioctl = list_entry (entry, struct dvb_frontend_ioctl_data, list_head); + ioctl = list_entry (entry, + struct dvb_frontend_ioctl_data, + list_head); if (ioctl->adapter == i2c->adapter) { fe->frontend.before_ioctl = ioctl->before_ioctl; @@ -936,3 +945,4 @@ MODULE_PARM(dvb_shutdown_timeout,"i"); MODULE_PARM_DESC(dvb_frontend_debug, "enable verbose debug messages"); MODULE_PARM_DESC(dvb_shutdown_timeout, "wait seconds after close() before suspending hardware"); + diff -Nru a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h --- a/drivers/media/dvb/dvb-core/dvb_frontend.h Wed Nov 27 14:36:32 2002 +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h Wed Nov 27 14:36:32 2002 @@ -90,7 +90,7 @@ * Return value: number of frontends where the ioctl's were applied. */ extern int -dvb_add_frontend_ioctls (struct dvb_adapter_s *adapter, +dvb_add_frontend_ioctls (struct dvb_adapter *adapter, int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), int (*after_ioctl) (struct dvb_frontend *frontend, @@ -99,18 +99,18 @@ extern void -dvb_remove_frontend_ioctls (struct dvb_adapter_s *adapter, +dvb_remove_frontend_ioctls (struct dvb_adapter *adapter, int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), int (*after_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg)); extern int -dvb_add_frontend_notifier (struct dvb_adapter_s *adapter, +dvb_add_frontend_notifier (struct dvb_adapter *adapter, void (*callback) (fe_status_t s, void *data), void *data); extern void -dvb_remove_frontend_notifier (struct dvb_adapter_s *adapter, +dvb_remove_frontend_notifier (struct dvb_adapter *adapter, void (*callback) (fe_status_t s, void *data)); #endif diff -Nru a/drivers/media/dvb/dvb-core/dvb_i2c.c b/drivers/media/dvb/dvb-core/dvb_i2c.c --- a/drivers/media/dvb/dvb-core/dvb_i2c.c Wed Nov 27 14:36:31 2002 +++ b/drivers/media/dvb/dvb-core/dvb_i2c.c Wed Nov 27 14:36:31 2002 @@ -173,7 +173,7 @@ dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num), void *data, - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id) { struct dvb_i2c_bus *i2c; @@ -200,7 +200,7 @@ struct dvb_i2c_bus* dvb_find_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num), - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id) { struct list_head *entry; @@ -231,7 +231,7 @@ void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num), - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id) { struct dvb_i2c_bus *i2c = dvb_find_i2c_bus (xfer, adapter, id); diff -Nru a/drivers/media/dvb/dvb-core/dvb_i2c.h b/drivers/media/dvb/dvb-core/dvb_i2c.h --- a/drivers/media/dvb/dvb-core/dvb_i2c.h Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/dvb-core/dvb_i2c.h Wed Nov 27 14:36:28 2002 @@ -32,7 +32,7 @@ struct list_head list_head; int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num); void *data; - struct dvb_adapter_s *adapter; + struct dvb_adapter *adapter; int id; struct list_head client_list; }; @@ -43,13 +43,13 @@ struct i2c_msg msgs[], int num), void *data, - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id); extern void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num), - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id); diff -Nru a/drivers/media/dvb/dvb-core/dvb_ksyms.c b/drivers/media/dvb/dvb-core/dvb_ksyms.c --- a/drivers/media/dvb/dvb-core/dvb_ksyms.c Wed Nov 27 14:36:32 2002 +++ b/drivers/media/dvb/dvb-core/dvb_ksyms.c Wed Nov 27 14:36:32 2002 @@ -9,11 +9,12 @@ #include "dvb_net.h" -EXPORT_SYMBOL(DmxDevInit); -EXPORT_SYMBOL(DmxDevRelease); -EXPORT_SYMBOL(DvbDmxInit); -EXPORT_SYMBOL(DvbDmxRelease); -EXPORT_SYMBOL(DvbDmxSWFilterPackets); +EXPORT_SYMBOL(dvb_dmxdev_init); +EXPORT_SYMBOL(dvb_dmxdev_release); +EXPORT_SYMBOL(dvb_dmx_init); +EXPORT_SYMBOL(dvb_dmx_release); +EXPORT_SYMBOL(dvb_dmx_swfilter_packet); +EXPORT_SYMBOL(dvb_dmx_swfilter_packets); EXPORT_SYMBOL(dvb_register_frontend); EXPORT_SYMBOL(dvb_unregister_frontend); @@ -37,13 +38,12 @@ EXPORT_SYMBOL(dvb_generic_ioctl); EXPORT_SYMBOL(dvb_generic_open); EXPORT_SYMBOL(dvb_generic_release); -EXPORT_SYMBOL(generic_usercopy); -EXPORT_SYMBOL(init_ipack); -EXPORT_SYMBOL(reset_ipack); -EXPORT_SYMBOL(free_ipack); -EXPORT_SYMBOL(send_ipack_rest); -EXPORT_SYMBOL(instant_repack); -EXPORT_SYMBOL(pes2ts_init); -EXPORT_SYMBOL(pes2ts); +EXPORT_SYMBOL(dvb_filter_ipack_init); +EXPORT_SYMBOL(dvb_filter_ipack_reset); +EXPORT_SYMBOL(dvb_filter_ipack_free); +EXPORT_SYMBOL(dvb_filter_ipack_flush); +EXPORT_SYMBOL(dvb_filter_instant_repack); +EXPORT_SYMBOL(dvb_filter_pes2ts_init); +EXPORT_SYMBOL(dvb_filter_pes2ts); diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c --- a/drivers/media/dvb/dvb-core/dvb_net.c Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/dvb-core/dvb_net.c Wed Nov 27 14:36:28 2002 @@ -435,7 +435,7 @@ int dvb_net_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dvb_net_t *dvbnet=(dvb_net_t *) dvbdev->priv; if (((file->f_flags&O_ACCMODE)==O_RDONLY)) @@ -462,21 +462,18 @@ } static struct file_operations dvb_net_fops = { - owner: THIS_MODULE, - read: 0, - write: 0, - ioctl: dvb_generic_ioctl, - open: dvb_generic_open, - release: dvb_generic_release, - poll: 0, + .owner = THIS_MODULE, + .ioctl = dvb_generic_ioctl, + .open = dvb_generic_open, + .release = dvb_generic_release, }; -static dvb_device_t dvbdev_net = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_net_fops, - kernel_ioctl: dvb_net_ioctl, +static struct dvb_device dvbdev_net = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_net_fops, + .kernel_ioctl = dvb_net_ioctl, }; void @@ -493,7 +490,7 @@ } int -dvb_net_init(dvb_adapter_t *adap, dvb_net_t *dvbnet, dmx_demux_t *demux) +dvb_net_init(struct dvb_adapter *adap, dvb_net_t *dvbnet, dmx_demux_t *demux) { int i; diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h --- a/drivers/media/dvb/dvb-core/dvb_net.h Wed Nov 27 14:36:27 2002 +++ b/drivers/media/dvb/dvb-core/dvb_net.h Wed Nov 27 14:36:27 2002 @@ -47,7 +47,7 @@ } dvb_net_priv_t; typedef struct dvb_net_s { - dvb_device_t *dvbdev; + struct dvb_device *dvbdev; int card_num; int dev_num; @@ -58,6 +58,6 @@ void dvb_net_release(dvb_net_t *); -int dvb_net_init(dvb_adapter_t *, dvb_net_t *, dmx_demux_t *); +int dvb_net_init(struct dvb_adapter *, dvb_net_t *, dmx_demux_t *); #endif diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c --- a/drivers/media/dvb/dvb-core/dvbdev.c Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/dvb-core/dvbdev.c Wed Nov 27 14:36:28 2002 @@ -37,6 +37,7 @@ #include #include #include +#include #include "compat.h" #include "dvbdev.h" @@ -69,17 +70,17 @@ static -dvb_device_t* dvbdev_find_device (int minor) +struct dvb_device* dvbdev_find_device (int minor) { struct list_head *entry; list_for_each (entry, &dvb_adapter_list) { struct list_head *entry0; - dvb_adapter_t *adap; - adap = list_entry (entry, dvb_adapter_t, list_head); + struct dvb_adapter *adap; + adap = list_entry (entry, struct dvb_adapter, list_head); list_for_each (entry0, &adap->device_list) { - dvb_device_t *dev; - dev = list_entry (entry0, dvb_device_t, list_head); + struct dvb_device *dev; + dev = list_entry (entry0, struct dvb_device, list_head); if (nums2minor(adap->num, dev->type, dev->id) == minor) return dev; } @@ -92,7 +93,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev; + struct dvb_device *dvbdev; dvbdev = dvbdev_find_device (minor(inode->i_rdev)); @@ -118,13 +119,8 @@ static struct file_operations dvb_device_fops = { - owner: THIS_MODULE, - read: NULL, - write: NULL, - ioctl: NULL, - open: dvb_device_open, - release: NULL, - poll: NULL, + .owner = THIS_MODULE, + .open = dvb_device_open, }; #endif /* CONFIG_DVB_DEVFS_ONLY */ @@ -132,7 +128,7 @@ int dvb_generic_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; if (!dvbdev) return -ENODEV; @@ -153,7 +149,7 @@ int dvb_generic_release(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; if (!dvbdev) return -ENODEV; @@ -166,73 +162,10 @@ } -/* - * helper function -- handles userspace copying for ioctl arguments - */ -int -generic_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - parg = (void *)arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; - } - - err = -EFAULT; - if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd))) - goto out; - break; - } - - /* call driver */ - if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) - err = -EINVAL; - - if (err < 0) - goto out; - - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; - } - -out: - if (mbuf) - kfree(mbuf); - - return err; -} - - int dvb_generic_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; if (!dvbdev) return -ENODEV; @@ -240,20 +173,20 @@ if (!dvbdev->kernel_ioctl) return -EINVAL; - return generic_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl); + return video_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl); } static -int dvbdev_get_free_id (struct dvb_adapter_s *adap, int type) +int dvbdev_get_free_id (struct dvb_adapter *adap, int type) { u32 id = 0; while (id < DVB_MAX_IDS) { struct list_head *entry; list_for_each (entry, &adap->device_list) { - dvb_device_t *dev; - dev = list_entry (entry, dvb_device_t, list_head); + struct dvb_device *dev; + dev = list_entry (entry, struct dvb_device, list_head); if (dev->type == type && dev->id == id) goto skip; } @@ -265,12 +198,12 @@ } -int dvb_register_device(dvb_adapter_t *adap, dvb_device_t **pdvbdev, - dvb_device_t *template, void *priv, int type) +int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + const struct dvb_device *template, void *priv, int type) { u32 id; char name [20]; - dvb_device_t *dvbdev; + struct dvb_device *dvbdev; if (down_interruptible (&dvbdev_register_lock)) return -ERESTARTSYS; @@ -282,7 +215,7 @@ return -ENFILE; } - *pdvbdev = dvbdev = kmalloc(sizeof(dvb_device_t), GFP_KERNEL); + *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL); if (!dvbdev) { up(&dvbdev_register_lock); @@ -291,7 +224,7 @@ up (&dvbdev_register_lock); - memcpy(dvbdev, template, sizeof(dvb_device_t)); + memcpy(dvbdev, template, sizeof(struct dvb_device)); dvbdev->type = type; dvbdev->id = id; dvbdev->adapter = adap; @@ -307,15 +240,15 @@ S_IFCHR | S_IRUSR | S_IWUSR, dvbdev->fops, dvbdev); - dprintk("%s: register adapter%d/%s @ minor: %i (0x%02x) - dvbdev: %p\n", - __FUNCTION__, adap->num, name, nums2minor(adap->num, type, id), - nums2minor(adap->num, type, id), dvbdev); + dprintk("DVB: register adapter%d/%s @ minor: %i (0x%02x)\n", + adap->num, name, nums2minor(adap->num, type, id), + nums2minor(adap->num, type, id)); return 0; } -void dvb_unregister_device(dvb_device_t *dvbdev) +void dvb_unregister_device(struct dvb_device *dvbdev) { if (!dvbdev) return; @@ -334,8 +267,8 @@ while (1) { struct list_head *entry; list_for_each (entry, &dvb_adapter_list) { - dvb_adapter_t *adap; - adap = list_entry (entry, dvb_adapter_t, list_head); + struct dvb_adapter *adap; + adap = list_entry (entry, struct dvb_adapter, list_head); if (adap->num == num) goto skip; } @@ -348,10 +281,10 @@ } -int dvb_register_adapter(dvb_adapter_t **padap, char *name) +int dvb_register_adapter(struct dvb_adapter **padap, char *name) { char dirname[16]; - dvb_adapter_t *adap; + struct dvb_adapter *adap; int num; if (down_interruptible (&dvbdev_register_lock)) @@ -362,17 +295,17 @@ return -ENFILE; } - if (!(*padap = adap = kmalloc(sizeof(dvb_adapter_t), GFP_KERNEL))) { + if (!(*padap = adap = kmalloc(sizeof(struct dvb_adapter), GFP_KERNEL))) { up(&dvbdev_register_lock); return -ENOMEM; } - memset (adap, 0, sizeof(dvb_adapter_t)); + memset (adap, 0, sizeof(struct dvb_adapter)); INIT_LIST_HEAD (&adap->device_list); MOD_INC_USE_COUNT; - printk ("%s: registering new adapter (%s).\n", __FUNCTION__, name); + printk ("DVB: registering new adapter (%s).\n", name); sprintf(dirname, "dvb/adapter%d", num); adap->devfs_handle = devfs_mk_dir(NULL, dirname, NULL); @@ -386,7 +319,7 @@ } -int dvb_unregister_adapter(dvb_adapter_t *adap) +int dvb_unregister_adapter(struct dvb_adapter *adap) { devfs_unregister (adap->devfs_handle); if (down_interruptible (&dvbdev_register_lock)) diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h --- a/drivers/media/dvb/dvb-core/dvbdev.h Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/dvb-core/dvbdev.h Wed Nov 27 14:36:28 2002 @@ -43,49 +43,48 @@ #define DVB_DEVICE_OSD 8 -typedef struct dvb_adapter_s -{ +struct dvb_adapter { int num; devfs_handle_t devfs_handle; struct list_head list_head; struct list_head device_list; -} dvb_adapter_t; +}; -typedef struct dvb_device -{ +struct dvb_device { struct list_head list_head; struct file_operations *fops; devfs_handle_t devfs_handle; - dvb_adapter_t *adapter; + struct dvb_adapter *adapter; int type; u32 id; int users; int writers; - /* don't really need those !? */ + /* don't really need those !? -- FIXME: use video_usercopy */ int (*kernel_ioctl)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg); // FIXME: use generic_usercopy() + unsigned int cmd, void *arg); void *priv; -} dvb_device_t; +}; -int dvb_register_device(dvb_adapter_t *adap, dvb_device_t **pdvbdev, - dvb_device_t *template, void *priv, int type); -void dvb_unregister_device(struct dvb_device *dvbdev); +extern int dvb_register_adapter (struct dvb_adapter **padap, char *name); +extern int dvb_unregister_adapter (struct dvb_adapter *adap); -int dvb_register_adapter(dvb_adapter_t **padap, char *name); -int dvb_unregister_adapter(dvb_adapter_t *adap); +extern int dvb_register_device (struct dvb_adapter *adap, + struct dvb_device **pdvbdev, + const struct dvb_device *template, + void *priv, + int type); -int dvb_generic_ioctl(struct inode *inode, struct file *file, +extern void dvb_unregister_device (struct dvb_device *dvbdev); + +extern int dvb_generic_open (struct inode *inode, struct file *file); +extern int dvb_generic_release (struct inode *inode, struct file *file); +extern int dvb_generic_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -int dvb_generic_open(struct inode *inode, struct file *file); -int dvb_generic_release(struct inode *inode, struct file *file); -int generic_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)); -#endif /* #ifndef __DVBDEV_H */ +#endif /* #ifndef _DVBDEV_H_ */ + diff -Nru a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig --- a/drivers/media/dvb/frontends/Kconfig Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/frontends/Kconfig Wed Nov 27 14:36:28 2002 @@ -23,6 +23,30 @@ DVB adapter simply enable all supported frontends, the right one will get autodetected. +config DVB_ALPS_TDLB7 + tristate "Alps TDLB7 (OFDM)" + depends on DVB_CORE + help + A DVB-T tuner module. Say Y when you want to support this frontend. + + This tuner module needs some microcode located in a file called + "Sc_main.mc" in the windows driver. Please pass the module parameter + mcfile="/PATH/FILENAME" when loading alps_tdlb7.o. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the + right one will get autodetected. + +config DVB_ALPS_TDMB7 + tristate "Alps BSRV2 (OFDM)" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the + right one will get autodetected. + config DVB_GRUNDIG_29504_491 tristate "Grundig 29504-491 (QPSK)" depends on DVB_CORE diff -Nru a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile --- a/drivers/media/dvb/frontends/Makefile Wed Nov 27 14:36:27 2002 +++ b/drivers/media/dvb/frontends/Makefile Wed Nov 27 14:36:27 2002 @@ -6,6 +6,8 @@ obj-$(CONFIG_DVB_ALPS_BSRU6) += alps_bsru6.o obj-$(CONFIG_DVB_ALPS_BSRV2) += alps_bsrv2.o +obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o +obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o obj-$(CONFIG_DVB_GRUNDIG_29504_491) += grundig_29504-491.o obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o obj-$(CONFIG_DVB_VES1820) += ves1820.o diff -Nru a/drivers/media/dvb/frontends/alps_bsru6.c b/drivers/media/dvb/frontends/alps_bsru6.c --- a/drivers/media/dvb/frontends/alps_bsru6.c Wed Nov 27 14:36:32 2002 +++ b/drivers/media/dvb/frontends/alps_bsru6.c Wed Nov 27 14:36:32 2002 @@ -1,8 +1,9 @@ /* - Alps BSRU6 DVB QPSK frontend driver + Alps BSRU6 and LG TDQB-S00x DVB QPSK frontend driver Copyright (C) 2001-2002 Convergence Integrated Media GmbH - , + , , + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,12 +33,16 @@ #define M_CLK (88000000UL) - /* M=21, K=0, P=0, f_VCO = 4MHz*4*(M+1)/(K+1) = 352 MHz */ + static struct dvb_frontend_info bsru6_info = { +#ifdef CONFIG_ALPS_BSRU6_IS_LG_TDQBS00X + name: "LG TDQB-S00x", +#else name: "Alps BSRU6", +#endif type: FE_QPSK, frequency_min: 950000, frequency_max: 2150000, @@ -63,7 +68,8 @@ 0x05, 0x35, // SDAT:0 SCLT:0 I2CT:1 0x06, 0x00, // DAC mode and MSB 0x07, 0x00, // DAC LSB - 0x08, 0x43, // DiSEqC +// 0x08, 0x43, // DiSEqC + 0x08, 0x03, // DiSEqC 0x09, 0x00, 0x0a, 0x42, 0x0c, 0x51, // QPSK reverse:1 Nyquist:0 OP0 val:1 OP0 con:1 OP1 val:1 OP1 con:1 @@ -79,17 +85,20 @@ 0x15, 0xc9, // lock detector threshold 0x16, 0x1d, - 0x17, 0x0, + 0x17, 0x00, 0x18, 0x14, 0x19, 0xf2, 0x1a, 0x11, 0x1b, 0x9c, - 0x1c, 0x0, - 0x1d, 0x0, - 0x1e, 0xb, + 0x1c, 0x00, + 0x1d, 0x00, + 0x1e, 0x0b, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0xff, @@ -110,16 +119,37 @@ 0x33, 0xfc, // rs control 0x34, 0x93, // error control - 0x0b, 0x00, - 0x27, 0x00, 0x2f, 0x00, 0x30, 0x00, - 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, - 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, - 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00, - 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, - 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, - 0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, - 0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00 + 0x27, 0x00, + 0x2f, 0x00, + 0x30, 0x00, + 0x35, 0x00, + 0x36, 0x00, + 0x37, 0x00, + 0x38, 0x00, + 0x39, 0x00, + 0x3a, 0x00, + 0x3b, 0x00, + 0x3c, 0x00, + 0x3d, 0x00, + 0x3e, 0x00, + 0x3f, 0x00, + 0x40, 0x00, + 0x41, 0x00, + 0x42, 0x00, + 0x43, 0x00, + 0x44, 0x00, + 0x45, 0x00, + 0x46, 0x00, + 0x47, 0x00, + 0x48, 0x00, + 0x49, 0x00, + 0x4a, 0x00, + 0x4b, 0x00, + 0x4c, 0x00, + 0x4d, 0x00, + 0x4e, 0x00, + 0x4f, 0x00 }; @@ -231,12 +261,27 @@ static -int stv0299_set_inversion (struct dvb_i2c_bus *i2c, int inversion) +int stv0299_set_inversion (struct dvb_i2c_bus *i2c, + fe_spectral_inversion_t inversion) { u8 val; dprintk ("%s\n", __FUNCTION__); +#ifdef CONFIG_ALPS_BSRU6_IS_LG_TDQBS00X /* reversed I/Q pins */ + switch (inversion) { + case INVERSION_AUTO: + return -EOPNOTSUPP; + case INVERSION_OFF: + val = stv0299_readreg (i2c, 0x0c); + return stv0299_writereg (i2c, 0x0c, val & 0xfe); + case INVERSION_ON: + val = stv0299_readreg (i2c, 0x0c); + return stv0299_writereg (i2c, 0x0c, val | 0x01); + default: + return -EINVAL; + }; +#else switch (inversion) { case INVERSION_AUTO: return -EOPNOTSUPP; @@ -248,7 +293,8 @@ return stv0299_writereg (i2c, 0x0c, val & 0xfe); default: return -EINVAL; - } + }; +#endif } @@ -277,9 +323,10 @@ static -fe_code_rate_t stv0299_get_FEC (struct dvb_i2c_bus *i2c) +fe_code_rate_t stv0299_get_fec (struct dvb_i2c_bus *i2c) { - static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_1_2 }; + static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6, + FEC_7_8, FEC_1_2 }; u8 index; dprintk ("%s\n", __FUNCTION__); @@ -343,6 +390,9 @@ dprintk ("%s\n", __FUNCTION__); + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + return -ETIMEDOUT; + val = stv0299_readreg (i2c, 0x08); if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x6)) /* DiSEqC mode */ @@ -356,12 +406,7 @@ return -EREMOTEIO; } - /* Shouldn't we wait for idle state (FE=1, FF=0) here to - make certain all bytes have been sent ? - Hmm, actually we should do that before all mode changes too ... - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) */ - - if (stv0299_wait_diseqc_fifo (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) return -ETIMEDOUT; return 0; @@ -375,18 +420,18 @@ dprintk ("%s\n", __FUNCTION__); - val = stv0299_readreg (i2c, 0x08); - - if (stv0299_wait_diseqc_fifo (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) return -ETIMEDOUT; + val = stv0299_readreg (i2c, 0x08); + if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x2)) /* burst mode */ return -EREMOTEIO; if (stv0299_writereg (i2c, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff)) return -EREMOTEIO; - if (stv0299_wait_diseqc_fifo (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) return -ETIMEDOUT; if (stv0299_writereg (i2c, 0x08, val)) @@ -403,6 +448,9 @@ dprintk ("%s\n", __FUNCTION__); + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + return -ETIMEDOUT; + val = stv0299_readreg (i2c, 0x08); switch (tone) { @@ -445,8 +493,6 @@ u32 tmp; u8 aclk = 0xb4, bclk = 0x51; - dprintk ("%s\n", __FUNCTION__); - if (srate > M_CLK) srate = M_CLK; if (srate < 500000) @@ -479,7 +525,6 @@ } - static int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c) { @@ -608,7 +653,7 @@ p->frequency += derot_freq; p->inversion = (stv0299_readreg (i2c, 0x0c) & 1) ? INVERSION_OFF : INVERSION_ON; - p->u.qpsk.fec_inner = stv0299_get_FEC (i2c); + p->u.qpsk.fec_inner = stv0299_get_fec (i2c); p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c); break; } @@ -694,7 +739,7 @@ MODULE_PARM(debug,"i"); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -MODULE_DESCRIPTION("BSRU6 DVB Frontend driver"); +MODULE_DESCRIPTION("Alps BSRU6/LG TDQB-S00x DVB Frontend driver"); MODULE_AUTHOR("Ralph Metzler, Holger Waechtler"); MODULE_LICENSE("GPL"); diff -Nru a/drivers/media/dvb/frontends/alps_bsrv2.c b/drivers/media/dvb/frontends/alps_bsrv2.c --- a/drivers/media/dvb/frontends/alps_bsrv2.c Wed Nov 27 14:36:28 2002 +++ b/drivers/media/dvb/frontends/alps_bsrv2.c Wed Nov 27 14:36:28 2002 @@ -342,7 +342,7 @@ *ber = ves1893_readreg (i2c, 0x15); *ber |= (ves1893_readreg (i2c, 0x16) << 8); - *ber |= (ves1893_readreg (i2c, 0x17) << 16); + *ber |= ((ves1893_readreg (i2c, 0x17) & 0x0f) << 16); *ber *= 10; break; } diff -Nru a/drivers/media/dvb/frontends/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/frontends/alps_tdlb7.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,437 @@ +/* + Driver for Alps TDLB7 Frontend + + Copyright (C) 1999 Juergen Peitz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/* + + Wrote this code mainly to get my own card running. It's working for me, but I + hope somebody who knows more about linux programming and the DVB driver can + improve it. + + Reused a lot from the existing driver and tuner code. + Thanks to everybody who worked on it! + + This driver needs a copy of the microcode file 'Sc_main.mc' from the Haupauge + windows driver in the 'usr/lib/DVB/driver/frontends' directory. + You can also pass the complete file name with the module parameter 'mcfile'. + + The code only needs to be loaded once after a power on. Because loading the + microcode to the card takes some time, you can use the 'loadcode=0' module + parameter, if you only want to reload the dvb driver. + + Juergen Peitz + +*/ + + + +#define __KERNEL_SYSCALLS__ +#include +#include +#include +#include +#include + +#include "compat.h" +#include "dvb_frontend.h" + +static int debug = 0; + +static int loadcode = 1; + +static char * mcfile = "/usr/lib/DVB/driver/frontends/Sc_main.mc"; + +#define dprintk if (debug) printk + +/* microcode size for sp8870 */ +#define SP8870_CODE_SIZE 16384 + +/* starting point for microcode in file 'Sc_main.mc' */ +#define SP8870_CODE_OFFSET 0x0A + + +static int errno; + +static +struct dvb_frontend_info tdlb7_info = { + name: "Alps TDLB7", + type: FE_OFDM, + frequency_min: 470000000, + frequency_max: 860000000, + frequency_stepsize: 166666, +#if 0 + frequency_tolerance: ???, + symbol_rate_min: ???, + symbol_rate_max: ???, + symbol_rate_tolerance: ???, + notifier_delay: 0, +#endif + caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 +}; + + +static +int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data) +{ + u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff }; + struct i2c_msg msg = { addr: 0x71, flags: 0, buf: buf, len: 4 }; + int err; + + if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { + dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); + return -EREMOTEIO; + } + + return 0; +} + + +static +u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg) +{ + int ret; + u8 b0 [] = { reg >> 8 , reg & 0xff }; + u8 b1 [] = { 0, 0 }; + struct i2c_msg msg [] = { { addr: 0x71, flags: 0, buf: b0, len: 2 }, + { addr: 0x71, flags: I2C_M_RD, buf: b1, len: 2 } }; + + ret = i2c->xfer (i2c, msg, 2); + + if (ret != 2) + dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + + return (b1[0] << 8 | b1[1]); +} + + +static +int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]) +{ + int ret; + struct i2c_msg msg = { addr: 0x60, flags: 0, buf: data, len: 4 }; + + ret = i2c->xfer (i2c, &msg, 1); + + if (ret != 1) + printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); + + return (ret != 1) ? -1 : 0; +} + + +static +int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) +{ + u32 div = (freq + 36200000) / 166666; + u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x85, (pwr << 5) | 0x30 }; + + return sp5659_write (i2c, buf); +} + + +static +int sp8870_read_code(const char *fn, char **fp) +{ + int fd; + loff_t l; + char *dp; + + fd = open(fn, 0, 0); + if (fd == -1) { + printk(KERN_INFO "%s: Unable to load '%s'.\n", __FUNCTION__, fn); + return -1; + } + l = lseek(fd, 0L, 2); + if (l <= 0 || l < SP8870_CODE_OFFSET+SP8870_CODE_SIZE) { + printk(KERN_INFO "%s: code file too small '%s'\n", __FUNCTION__, fn); + sys_close(fd); + return -1; + } + lseek(fd, SP8870_CODE_OFFSET, 0); + *fp= dp = vmalloc(SP8870_CODE_SIZE); + if (dp == NULL) { + printk(KERN_INFO "%s: Out of memory loading '%s'.\n", __FUNCTION__, fn); + sys_close(fd); + return -1; + } + if (read(fd, dp, SP8870_CODE_SIZE) != SP8870_CODE_SIZE) { + printk(KERN_INFO "%s: Failed to read '%s'.\n",__FUNCTION__, fn); + vfree(dp); + sys_close(fd); + return -1; + } + sys_close(fd); + *fp = dp; + return 0; +} + + +static +int sp8870_load_code(struct dvb_i2c_bus *i2c) +{ + /* this takes a long time. is there a way to do it faster? */ + char *lcode; + struct i2c_msg msg; + unsigned char buf[255]; + int err; + int p=0; + int c; + mm_segment_t fs = get_fs(); + + sp8870_writereg(i2c,0x8F08,0x1FFF); + sp8870_writereg(i2c,0x8F0A,0x0000); + + set_fs(get_ds()); + if (sp8870_read_code(mcfile,(char**) &lcode)<0) return -1; + set_fs(fs); + while (pxfer (i2c, &msg, 1)) != 1) { + dprintk ("%s: i2c error (err == %i)\n", __FUNCTION__, err); + vfree(lcode); + return -EREMOTEIO; + } + + p+=252; + } + vfree(lcode); + return 0; +}; + + +static +int sp8870_init (struct dvb_i2c_bus *i2c) +{ + + dprintk ("%s\n", __FUNCTION__); + + sp8870_readreg(i2c,0x200); + sp8870_readreg(i2c,0x200); + sp8870_readreg(i2c,0x0F00); /* system controller stop */ + sp8870_readreg(i2c,0x0301); /* ???????? */ + sp8870_readreg(i2c,0x0309); /* integer carrier offset */ + sp8870_readreg(i2c,0x030A); /* fractional carrier offset */ + sp8870_readreg(i2c,0x0311); /* filter for 8 Mhz channel */ + sp8870_readreg(i2c,0x0319); /* sample rate correction bit [23..17] */ + sp8870_readreg(i2c,0x031A); /* sample rate correction bit [16..0] */ + sp8870_readreg(i2c,0x0338); /* ???????? */ + sp8870_readreg(i2c,0x0F00); + sp8870_readreg(i2c,0x0200); + + if (loadcode) { + dprintk("%s: loading mcfile '%s' !\n", __FUNCTION__, mcfile); + if (sp8870_load_code(i2c)==0) + dprintk("%s: microcode loaded!\n", __FUNCTION__); + }else{ + dprintk("%s: without loading mcfile!\n", __FUNCTION__); + } + + return 0; +} + + +static +int sp8870_reset (struct dvb_i2c_bus *i2c) +{ + dprintk("%s\n", __FUNCTION__); + sp8870_writereg(i2c,0x0F00,0x0000); /* system controller stop */ + sp8870_writereg(i2c,0x0301,0x0003); /* ???????? */ + sp8870_writereg(i2c,0x0309,0x0400); /* integer carrier offset */ + sp8870_writereg(i2c,0x030A,0x0000); /* fractional carrier offset */ + sp8870_writereg(i2c,0x0311,0x0000); /* filter for 8 Mhz channel */ + sp8870_writereg(i2c,0x0319,0x000A); /* sample rate correction bit [23..17] */ + sp8870_writereg(i2c,0x031A,0x0AAB); /* sample rate correction bit [16..0] */ + sp8870_writereg(i2c,0x0338,0x0000); /* ???????? */ + sp8870_writereg(i2c,0x0201,0x0000); /* interrupts for change of lock or tuner adjustment disabled */ + sp8870_writereg(i2c,0x0F00,0x0001); /* system controller start */ + + return 0; +} + +static +int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct dvb_i2c_bus *i2c = fe->i2c; + + switch (cmd) { + case FE_GET_INFO: + memcpy (arg, &tdlb7_info, sizeof(struct dvb_frontend_info)); + break; + + case FE_READ_STATUS: + { + fe_status_t *status = arg; + int sync = sp8870_readreg (i2c, 0x0200); + + *status=0; + + if (sync&0x04) // FIXME: find criteria for having signal + *status |= FE_HAS_SIGNAL; + + if (sync&0x04) // FIXME: find criteria + *status |= FE_HAS_CARRIER; + + if (sync&0x04) // FIXME + *status |= FE_HAS_VITERBI; + + if (sync&0x08) // FIXME + *status |= FE_HAS_SYNC; + + if (sync&0x04) + *status |= FE_HAS_LOCK; + break; + + } + + case FE_READ_BER: + { + u32 *ber=(u32 *) arg; + *ber=sp8870_readreg(i2c,0x0C07); // bit error rate before Viterbi + break; + + } + + case FE_READ_SIGNAL_STRENGTH: // not supported by hardware? + { + s32 *signal=(s32 *) arg; + *signal=0; + break; + } + + case FE_READ_SNR: // not supported by hardware? + { + s32 *snr=(s32 *) arg; + *snr=0; + break; + } + + case FE_READ_UNCORRECTED_BLOCKS: // not supported by hardware? + { + u32 *ublocks=(u32 *) arg; + *ublocks=0; + break; + } + + case FE_SET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + sp5659_set_tv_freq (i2c, p->frequency, 0); + // all other parameters are set by the on card + // system controller. Don't know how to pass + // distinct values to the card. + break; + } + + case FE_GET_FRONTEND: // how to do this? + { + break; + } + + case FE_SLEEP: // is this supported by hardware? + return -EOPNOTSUPP; + + case FE_INIT: + return sp8870_init (i2c); + + case FE_RESET: + return sp8870_reset (i2c); + + default: + return -EOPNOTSUPP; + }; + + return 0; +} + + +static +int tdlb7_attach (struct dvb_i2c_bus *i2c) +{ + + struct i2c_msg msg = { addr: 0x71, flags: 0, buf: NULL, len: 0 }; + + dprintk ("%s\n", __FUNCTION__); + + if (i2c->xfer (i2c, &msg, 1) != 1) + return -ENODEV; + + dvb_register_frontend (tdlb7_ioctl, i2c, NULL, &tdlb7_info); + + return 0; +} + + +static +void tdlb7_detach (struct dvb_i2c_bus *i2c) +{ + dprintk ("%s\n", __FUNCTION__); + + dvb_unregister_frontend (tdlb7_ioctl, i2c); +} + + +static +int __init init_tdlb7 (void) +{ + dprintk ("%s\n", __FUNCTION__); + + return dvb_register_i2c_device (THIS_MODULE, tdlb7_attach, tdlb7_detach); +} + + +static +void __exit exit_tdlb7 (void) +{ + dprintk ("%s\n", __FUNCTION__); + + dvb_unregister_i2c_device (tdlb7_attach); +} + + +module_init(init_tdlb7); +module_exit(exit_tdlb7); + + +MODULE_PARM(debug,"i"); +MODULE_PARM_DESC(debug, "enable verbose debug messages"); + +MODULE_PARM(loadcode,"i"); +MODULE_PARM_DESC(loadcode, "load tuner microcode"); + +MODULE_PARM(mcfile,"s"); +MODULE_PARM_DESC(mcfile, "where to find the microcode file"); + +MODULE_DESCRIPTION("TDLB7 DVB-T Frontend"); +MODULE_AUTHOR("Juergen Peitz"); +MODULE_LICENSE("GPL"); + + diff -Nru a/drivers/media/dvb/frontends/alps_tdmb7.c b/drivers/media/dvb/frontends/alps_tdmb7.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/frontends/alps_tdmb7.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,468 @@ +/* + Alps TDMB7 DVB OFDM frontend driver + + Copyright (C) 2001-2002 Convergence Integrated Media GmbH + Holger Waechtler + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include + +#include "compat.h" +#include "dvb_frontend.h" + + +static int debug = 0; +#define dprintk if (debug) printk + + +static +struct dvb_frontend_info tdmb7_info = { + name: "Alps TDMB7", + type: FE_OFDM, + frequency_min: 470000000, + frequency_max: 860000000, + frequency_stepsize: 166667, +#if 0 + frequency_tolerance: ???, + symbol_rate_min: ???, + symbol_rate_max: ???, + symbol_rate_tolerance: 500, /* ppm */ + notifier_delay: 0, +#endif + caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 +}; + + +static +inline void ddelay (int timeout) +{ + current->state=TASK_INTERRUPTIBLE; + schedule_timeout(timeout); +} + + +static +u8 init_tab [] = { + 0x04, 0x10, + 0x05, 0x09, + 0x06, 0x00, + 0x08, 0x04, + 0x09, 0x00, + 0x0a, 0x01, + 0x15, 0x40, + 0x16, 0x10, + 0x17, 0x87, + 0x18, 0x17, + 0x1a, 0x10, + 0x25, 0x04, + 0x2e, 0x00, + 0x39, 0x00, + 0x3a, 0x04, + 0x45, 0x08, + 0x46, 0x02, + 0x47, 0x05, +}; + + +static +int cx22700_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +{ + int ret; + u8 buf [] = { reg, data }; + struct i2c_msg msg = { addr: 0x43, flags: 0, buf: buf, len: 2 }; + + dprintk ("%s\n", __FUNCTION__); + + ret = i2c->xfer (i2c, &msg, 1); + + if (ret != 1) + printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n", + __FUNCTION__, reg, data, ret); + + return (ret != 1) ? -1 : 0; +} + + +static +u8 cx22700_readreg (struct dvb_i2c_bus *i2c, u8 reg) +{ + int ret; + u8 b0 [] = { reg }; + u8 b1 [] = { 0 }; + struct i2c_msg msg [] = { { addr: 0x43, flags: 0, buf: b0, len: 1 }, + { addr: 0x43, flags: I2C_M_RD, buf: b1, len: 1 } }; + + dprintk ("%s\n", __FUNCTION__); + + ret = i2c->xfer (i2c, msg, 2); + + if (ret != 2) + printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + + return b1[0]; +} + + +static +int pll_write (struct dvb_i2c_bus *i2c, u8 data [4]) +{ + struct i2c_msg msg = { addr: 0x61, flags: 0, buf: data, len: 4 }; + int ret; + + cx22700_writereg (i2c, 0x0a, 0x00); /* open i2c bus switch */ + ret = i2c->xfer (i2c, &msg, 1); + cx22700_writereg (i2c, 0x0a, 0x01); /* close i2c bus switch */ + + if (ret != 1) + printk("%s: i/o error (addr == 0x%02x, ret == %i)\n", __FUNCTION__, msg.addr, ret); + + return (ret != 1) ? -1 : 0; +} + + +/** + * set up the downconverter frequency divisor for a + * reference clock comparision frequency of 125 kHz. + */ +static +int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +{ + u32 div = (freq + 36166667) / 166667; +#if 1 //ALPS_SETTINGS + u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, ((div >> 10) & 0x60) | 0x85, + freq < 592000000 ? 0x40 : 0x80 }; +#else + u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, ((div >> 10) & 0x60) | 0x85, + freq < 470000000 ? 0x42 : freq < 862000000 ? 0x41 : 0x81 }; +#endif + + dprintk ("%s: freq == %i, div == %i\n", __FUNCTION__, freq, div); + + return pll_write (i2c, buf); +} + + +static +int cx22700_init (struct dvb_i2c_bus *i2c) +{ + int i; + + dprintk("cx22700_init: init chip\n"); + + cx22700_writereg (i2c, 0x00, 0x02); /* soft reset */ + cx22700_writereg (i2c, 0x00, 0x00); + + ddelay (HZ/100); + + for (i=0; icode_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8) + return -EINVAL; + + if (p->code_rate_LP < FEC_1_2 || p->code_rate_LP > FEC_7_8) + + if (p->code_rate_HP == FEC_4_5 || p->code_rate_LP == FEC_4_5) + return -EINVAL; + + if (p->guard_interval < GUARD_INTERVAL_1_32 || + p->guard_interval > GUARD_INTERVAL_1_4) + return -EINVAL; + + if (p->transmission_mode != TRANSMISSION_MODE_2K && + p->transmission_mode != TRANSMISSION_MODE_8K) + return -EINVAL; + + if (p->constellation != QPSK && + p->constellation != QAM_16 && + p->constellation != QAM_64) + return -EINVAL; + + if (p->hierarchy_information < HIERARCHY_NONE || + p->hierarchy_information > HIERARCHY_4) + return -EINVAL; + + if (p->bandwidth < BANDWIDTH_8_MHZ && p->bandwidth > BANDWIDTH_6_MHZ) + return -EINVAL; + + if (p->bandwidth == BANDWIDTH_7_MHZ) + cx22700_writereg (i2c, 0x09, cx22700_readreg (i2c, 0x09 | 0x10)); + else + cx22700_writereg (i2c, 0x09, cx22700_readreg (i2c, 0x09 & ~0x10)); + + val = qam_tab[p->constellation - QPSK]; + val |= p->hierarchy_information - HIERARCHY_NONE; + + cx22700_writereg (i2c, 0x04, val); + + val = fec_tab[p->code_rate_HP - FEC_1_2] << 3; + val |= fec_tab[p->code_rate_LP - FEC_1_2]; + + cx22700_writereg (i2c, 0x05, val); + + val = (p->guard_interval - GUARD_INTERVAL_1_32) << 2; + val |= p->transmission_mode - TRANSMISSION_MODE_2K; + + cx22700_writereg (i2c, 0x06, val); + + cx22700_writereg (i2c, 0x08, 0x04 | 0x02); /* use user tps parameters */ + cx22700_writereg (i2c, 0x08, 0x04); /* restart aquisition */ + + return 0; +} + + +static +int cx22700_get_tps (struct dvb_i2c_bus *i2c, struct dvb_ofdm_parameters *p) +{ + static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 }; + static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4, + FEC_5_6, FEC_7_8 }; + u8 val; + + dprintk ("%s\n", __FUNCTION__); + + if (!(cx22700_readreg(i2c, 0x07) & 0x20)) /* tps valid? */ + return -EAGAIN; + + val = cx22700_readreg (i2c, 0x01); + + if ((val & 0x7) > 4) + p->hierarchy_information = HIERARCHY_AUTO; + else + p->hierarchy_information = HIERARCHY_NONE + (val & 0x7); + + if (((val >> 3) & 0x3) > 2) + p->constellation = QAM_AUTO; + else + p->constellation = qam_tab[(val >> 3) & 0x3]; + + + val = cx22700_readreg (i2c, 0x02); + + if ((val >> 3) > 4) + p->code_rate_HP = FEC_AUTO; + else + p->code_rate_HP = fec_tab[val >> 3]; + + if ((val & 0x7) > 4) + p->code_rate_LP = FEC_AUTO; + else + p->code_rate_LP = fec_tab[val >> 3]; + + + val = cx22700_readreg (i2c, 0x03); + + p->guard_interval = GUARD_INTERVAL_1_32 + ((val >> 6) & 0x3); + p->transmission_mode = TRANSMISSION_MODE_2K + ((val >> 5) & 0x1); + + return 0; +} + + +static +int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct dvb_i2c_bus *i2c = fe->i2c; + + dprintk ("%s\n", __FUNCTION__); + + switch (cmd) { + case FE_GET_INFO: + memcpy (arg, &tdmb7_info, sizeof(struct dvb_frontend_info)); + break; + + case FE_READ_STATUS: + { + fe_status_t *status = (fe_status_t *) arg; + u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9) + | (cx22700_readreg (i2c, 0x0e) << 1); + u8 sync = cx22700_readreg (i2c, 0x07); + + *status = 0; + + if (rs_ber < 0xff00) + *status |= FE_HAS_SIGNAL; + + if (sync & 0x20) + *status |= FE_HAS_CARRIER; + + if (sync & 0x10) + *status |= FE_HAS_VITERBI; + + if (sync & 0x10) + *status |= FE_HAS_SYNC; + + if (sync & 0x10) + *status |= FE_HAS_LOCK; + + break; + } + + case FE_READ_BER: + *((uint32_t*) arg) = cx22700_readreg (i2c, 0x0c) & 0x7f; + break; + + case FE_READ_SIGNAL_STRENGTH: + { + u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9) + | (cx22700_readreg (i2c, 0x0e) << 1); + *((uint16_t*) arg) = ~rs_ber; + break; + } + case FE_READ_SNR: + { + u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9) + | (cx22700_readreg (i2c, 0x0e) << 1); + *((uint16_t*) arg) = ~rs_ber; + break; + } + case FE_READ_UNCORRECTED_BLOCKS: + *((uint32_t*) arg) = cx22700_readreg (i2c, 0x0f); + break; + + case FE_SET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + + cx22700_writereg (i2c, 0x00, 0x02); /* XXX CHECKME: soft reset*/ + cx22700_writereg (i2c, 0x00, 0x00); + + pll_set_tv_freq (i2c, p->frequency); + cx22700_set_inversion (i2c, p->inversion); + cx22700_set_tps (i2c, &p->u.ofdm); + cx22700_writereg (i2c, 0x37, 0x01); /* PAL loop filter off */ + cx22700_writereg (i2c, 0x00, 0x01); /* restart aquire */ + break; + } + + case FE_GET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + u8 reg09 = cx22700_readreg (i2c, 0x09); + + p->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF; + return cx22700_get_tps (i2c, &p->u.ofdm); + } + + case FE_INIT: + return cx22700_init (i2c); + + case FE_RESET: + break; + + default: + return -EOPNOTSUPP; + }; + + return 0; +} + + + +static +int tdmb7_attach (struct dvb_i2c_bus *i2c) +{ + struct i2c_msg msg = { addr: 0x43, flags: 0, buf: NULL, len: 0 }; + + dprintk ("%s\n", __FUNCTION__); + + if (i2c->xfer (i2c, &msg, 1) != 1) + return -ENODEV; + + dvb_register_frontend (tdmb7_ioctl, i2c, NULL, &tdmb7_info); + + return 0; +} + + +static +void tdmb7_detach (struct dvb_i2c_bus *i2c) +{ + dprintk ("%s\n", __FUNCTION__); + + dvb_unregister_frontend (tdmb7_ioctl, i2c); +} + + +static +int __init init_tdmb7 (void) +{ + dprintk ("%s\n", __FUNCTION__); + + return dvb_register_i2c_device (THIS_MODULE, tdmb7_attach, tdmb7_detach); +} + + +static +void __exit exit_tdmb7 (void) +{ + dprintk ("%s\n", __FUNCTION__); + + dvb_unregister_i2c_device (tdmb7_attach); +} + +module_init (init_tdmb7); +module_exit (exit_tdmb7); + +MODULE_PARM(debug,"i"); +MODULE_PARM_DESC(debug, "enable verbose debug messages"); +MODULE_DESCRIPTION("TDMB7 DVB Frontend driver"); +MODULE_AUTHOR("Holger Waechtler"); +MODULE_LICENSE("GPL"); + diff -Nru a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c --- a/drivers/media/dvb/frontends/ves1820.c Wed Nov 27 14:36:30 2002 +++ b/drivers/media/dvb/frontends/ves1820.c Wed Nov 27 14:36:30 2002 @@ -199,8 +199,8 @@ u8 b0 [] = { 0xff }; u8 pwm; int i; - struct i2c_msg msg [] = { { addr: 0x28, flags: 0, buf: b0, len: 1 }, - { addr: 0x28, flags: I2C_M_RD, buf: &pwm, len: 1 } }; + struct i2c_msg msg [] = { { addr: 0x50, flags: 0, buf: b0, len: 1 }, + { addr: 0x50, flags: I2C_M_RD, buf: &pwm, len: 1 } }; dprintk("VES1820: init chip\n"); @@ -433,12 +433,13 @@ } case FE_READ_BER: - *((u32*) arg) = ves1820_readreg(frontend->i2c, 0x14) | + { + u32 ber = ves1820_readreg(frontend->i2c, 0x14) | (ves1820_readreg(frontend->i2c, 0x15) << 8) | - (ves1820_readreg(frontend->i2c, 0x16) << 16); - /* XXX FIXME: scale!!*/ + ((ves1820_readreg(frontend->i2c, 0x16) & 0x0f) << 16); + *((u32*) arg) = 10 * ber; break; - + } case FE_READ_SIGNAL_STRENGTH: { u8 gain = ves1820_readreg(frontend->i2c, 0x17); diff -Nru a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c --- a/drivers/media/radio/radio-sf16fmi.c Wed Nov 27 14:36:31 2002 +++ b/drivers/media/radio/radio-sf16fmi.c Wed Nov 27 14:36:31 2002 @@ -82,24 +82,15 @@ static inline int fmi_setfreq(struct fmi_device *dev) { - int myport = dev->port; + int myport = dev->port; unsigned long freq = dev->curfreq; - int i; - + down(&lock); - + outbits(16, RSF16_ENCODE(freq), myport); outbits(8, 0xC0, myport); - for(i=0; i< 100; i++) - { - udelay(1400); - cond_resched(); - } -/* If this becomes allowed use it ... current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ/7); -*/ - up(&lock); if (dev->curvol) fmi_unmute(myport); return 0; @@ -110,7 +101,7 @@ int val; int res; int myport = dev->port; - int i; + down(&lock); val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ diff -Nru a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c --- a/drivers/media/video/bttv-cards.c Wed Nov 27 14:36:30 2002 +++ b/drivers/media/video/bttv-cards.c Wed Nov 27 14:36:30 2002 @@ -2990,7 +2990,7 @@ /* print which chipset we have */ while ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8,dev))) - printk(KERN_INFO "bttv: Host bridge is %s\n",dev->name); + printk(KERN_INFO "bttv: Host bridge is %s\n",dev->dev.name); /* print warnings about any quirks found */ if (triton1) diff -Nru a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c --- a/drivers/media/video/bw-qcam.c Wed Nov 27 14:36:28 2002 +++ b/drivers/media/video/bw-qcam.c Wed Nov 27 14:36:28 2002 @@ -89,27 +89,27 @@ MODULE_PARM(video_nr,"i"); #endif -extern __inline__ int read_lpstatus(struct qcam_device *q) +static inline int read_lpstatus(struct qcam_device *q) { return parport_read_status(q->pport); } -extern __inline__ int read_lpcontrol(struct qcam_device *q) +static inline int read_lpcontrol(struct qcam_device *q) { return parport_read_control(q->pport); } -extern __inline__ int read_lpdata(struct qcam_device *q) +static inline int read_lpdata(struct qcam_device *q) { return parport_read_data(q->pport); } -extern __inline__ void write_lpdata(struct qcam_device *q, int d) +static inline void write_lpdata(struct qcam_device *q, int d) { parport_write_data(q->pport, d); } -extern __inline__ void write_lpcontrol(struct qcam_device *q, int d) +static inline void write_lpcontrol(struct qcam_device *q, int d) { parport_write_control(q->pport, d); } @@ -506,7 +506,7 @@ the supplied buffer. It returns the number of bytes read, or -1 on error. */ -extern __inline__ int qc_readbytes(struct qcam_device *q, char buffer[]) +static inline int qc_readbytes(struct qcam_device *q, char buffer[]) { int ret=1; unsigned int hi, lo; diff -Nru a/drivers/media/video/pms.c b/drivers/media/video/pms.c --- a/drivers/media/video/pms.c Wed Nov 27 14:36:31 2002 +++ b/drivers/media/video/pms.c Wed Nov 27 14:36:31 2002 @@ -69,12 +69,12 @@ -extern __inline__ void mvv_write(u8 index, u8 value) +static inline void mvv_write(u8 index, u8 value) { outw(index|(value<<8), io_port); } -extern __inline__ u8 mvv_read(u8 index) +static inline u8 mvv_read(u8 index) { outb(index, io_port); return inb(data_port); diff -Nru a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c --- a/drivers/media/video/saa7111.c Wed Nov 27 14:36:29 2002 +++ b/drivers/media/video/saa7111.c Wed Nov 27 14:36:29 2002 @@ -34,7 +34,7 @@ #include #include -#include +#include #include @@ -43,8 +43,9 @@ /* ----------------------------------------------------------------------- */ struct saa7111 { - struct i2c_bus *bus; + struct i2c_client *client; int addr; + struct semaphore lock; unsigned char reg[32]; int norm; @@ -60,74 +61,32 @@ #define I2C_DELAY 10 -/* ----------------------------------------------------------------------- */ - -static int saa7111_write(struct saa7111 *dev, unsigned char subaddr, - unsigned char data) -{ - int ack; - - LOCK_I2C_BUS(dev->bus); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - i2c_sendbyte(dev->bus, subaddr, I2C_DELAY); - ack = i2c_sendbyte(dev->bus, data, I2C_DELAY); - dev->reg[subaddr] = data; - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - return ack; -} - -static int saa7111_write_block(struct saa7111 *dev, - unsigned const char *data, unsigned int len) -{ - int ack = -1; - unsigned subaddr; - - while (len > 1) { - LOCK_I2C_BUS(dev->bus); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY); - ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); - len -= 2; - while (len > 1 && *data == ++subaddr) { - data++; - ack = - i2c_sendbyte(dev->bus, - (dev->reg[subaddr] = - *data++), I2C_DELAY); - len -= 2; - } - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - } - return ack; -} - -static int saa7111_read(struct saa7111 *dev, unsigned char subaddr) -{ - int data; - - LOCK_I2C_BUS(dev->bus); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - i2c_sendbyte(dev->bus, subaddr, I2C_DELAY); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY); - data = i2c_readbyte(dev->bus, 1); - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - return data; -} +static unsigned short normal_i2c[] = { 34>>1, I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; +static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; + +static struct i2c_client_address_data addr_data = { + .normal_i2c = normal_i2c, + .normal_i2c_range = normal_i2c_range, + .probe = probe, + .probe_range = probe_range, + .ignore = ignore, + .ignore_range = ignore_range, + .force = force +}; +static struct i2c_client client_template; /* ----------------------------------------------------------------------- */ -static int saa7111_attach(struct i2c_device *device) +static int saa7111_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind) { int i; struct saa7111 *decoder; - + struct i2c_client *client; static const unsigned char init[] = { 0x00, 0x00, /* 00 - ID byte */ 0x01, 0x00, /* 01 - reserved */ @@ -158,20 +117,25 @@ 0x16, 0x00, /* 16 - VBI */ 0x17, 0x00, /* 17 - VBI */ }; + client = kmalloc(sizeof(*client), GFP_KERNEL); + if(client == NULL) + return -ENOMEM; + client_template.adapter = adap; + client_template.addr = addr; + memcpy(client, &client_template, sizeof(*client)); - MOD_INC_USE_COUNT; - - device->data = decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL); + decoder = kmalloc(sizeof(*decoder), GFP_KERNEL); if (decoder == NULL) { - MOD_DEC_USE_COUNT; + kfree(client); return -ENOMEM; } - memset(decoder, 0, sizeof(struct saa7111)); - strcpy(device->name, "saa7111"); - decoder->bus = device->bus; - decoder->addr = device->addr; + memset(decoder, 0, sizeof(*decoder)); + strcpy(client->name, "saa7111"); + decoder->client = client; + client->data = decoder; + decoder->addr = addr; decoder->norm = VIDEO_MODE_NTSC; decoder->input = 0; decoder->enable = 1; @@ -180,29 +144,38 @@ decoder->hue = 32768; decoder->sat = 32768; - i = saa7111_write_block(decoder, init, sizeof(init)); + i = i2c_master_send(client, init, sizeof(init)); if (i < 0) { printk(KERN_ERR "%s_attach: init status %d\n", - device->name, i); + client->name, i); } else { printk(KERN_INFO "%s_attach: chip version %x\n", - device->name, saa7111_read(decoder, 0x00) >> 4); + client->name, i2c_smbus_read_byte_data(client, 0x00) >> 4); } + init_MUTEX(&decoder->lock); + i2c_attach_client(client); + MOD_INC_USE_COUNT; return 0; } +static int saa7111_probe(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, saa7111_attach); +} - -static int saa7111_detach(struct i2c_device *device) +static int saa7111_detach(struct i2c_client *client) { - kfree(device->data); + struct saa7111 *decoder = client->data; + i2c_detach_client(client); + kfree(decoder); + kfree(client); MOD_DEC_USE_COUNT; return 0; } -static int saa7111_command(struct i2c_device *device, unsigned int cmd, +static int saa7111_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct saa7111 *decoder = device->data; + struct saa7111 *decoder = client->data; switch (cmd) { @@ -214,11 +187,11 @@ for (i = 0; i < 32; i += 16) { int j; - printk("KERN_DEBUG %s: %03x", device->name, + printk("KERN_DEBUG %s: %03x", client->name, i); for (j = 0; j < 16; ++j) { printk(" %02x", - saa7111_read(decoder, + i2c_smbus_read_byte_data(client, i + j)); } printk("\n"); @@ -246,7 +219,7 @@ int status; int res; - status = saa7111_read(decoder, 0x1f); + status = i2c_smbus_read_byte_data(client, 0x1f); res = 0; if ((status & (1 << 6)) == 0) { res |= DECODER_STATUS_GOOD; @@ -281,19 +254,19 @@ switch (*iarg) { case VIDEO_MODE_NTSC: - saa7111_write(decoder, 0x08, + i2c_smbus_write_byte_data(client, 0x08, (decoder-> reg[0x08] & 0x3f) | 0x40); break; case VIDEO_MODE_PAL: - saa7111_write(decoder, 0x08, + i2c_smbus_write_byte_data(client, 0x08, (decoder-> reg[0x08] & 0x3f) | 0x00); break; case VIDEO_MODE_AUTO: - saa7111_write(decoder, 0x08, + i2c_smbus_write_byte_data(client, 0x08, (decoder-> reg[0x08] & 0x3f) | 0x80); break; @@ -317,12 +290,12 @@ if (decoder->input != *iarg) { decoder->input = *iarg; /* select mode */ - saa7111_write(decoder, 0x02, + i2c_smbus_write_byte_data(client, 0x02, (decoder-> reg[0x02] & 0xf8) | decoder->input); /* bypass chrominance trap for modes 4..7 */ - saa7111_write(decoder, 0x09, + i2c_smbus_write_byte_data(client, 0x09, (decoder-> reg[0x09] & 0x7f) | ((decoder->input > @@ -357,26 +330,26 @@ // If output should be enabled, we have to reverse the above. if (decoder->enable) { - saa7111_write(decoder, 0x02, + i2c_smbus_write_byte_data(client, 0x02, (decoder-> reg[0x02] & 0xf8) | decoder->input); - saa7111_write(decoder, 0x08, + i2c_smbus_write_byte_data(client, 0x08, (decoder-> reg[0x08] & 0xfb)); - saa7111_write(decoder, 0x11, + i2c_smbus_write_byte_data(client, 0x11, (decoder-> reg[0x11] & 0xf3) | 0x0c); } else { - saa7111_write(decoder, 0x02, + i2c_smbus_write_byte_data(client, 0x02, (decoder-> reg[0x02] & 0xf8)); - saa7111_write(decoder, 0x08, + i2c_smbus_write_byte_data(client, 0x08, (decoder-> reg[0x08] & 0xfb) | 0x04); - saa7111_write(decoder, 0x11, + i2c_smbus_write_byte_data(client, 0x11, (decoder-> reg[0x11] & 0xf3)); } @@ -391,25 +364,25 @@ if (decoder->bright != pic->brightness) { /* We want 0 to 255 we get 0-65535 */ decoder->bright = pic->brightness; - saa7111_write(decoder, 0x0a, + i2c_smbus_write_byte_data(client, 0x0a, decoder->bright >> 8); } if (decoder->contrast != pic->contrast) { /* We want 0 to 127 we get 0-65535 */ decoder->contrast = pic->contrast; - saa7111_write(decoder, 0x0b, + i2c_smbus_write_byte_data(client, 0x0b, decoder->contrast >> 9); } if (decoder->sat != pic->colour) { /* We want 0 to 127 we get 0-65535 */ decoder->sat = pic->colour; - saa7111_write(decoder, 0x0c, + i2c_smbus_write_byte_data(client, 0x0c, decoder->sat >> 9); } if (decoder->hue != pic->hue) { /* We want -128 to 127 we get 0-65535 */ decoder->hue = pic->hue; - saa7111_write(decoder, 0x0d, + i2c_smbus_write_byte_data(client, 0x0d, (decoder->hue - 32768) >> 8); } } @@ -425,23 +398,28 @@ /* ----------------------------------------------------------------------- */ static struct i2c_driver i2c_driver_saa7111 = { - "saa7111", /* name */ - I2C_DRIVERID_VIDEODECODER, /* ID */ - I2C_SAA7111, I2C_SAA7111 + 1, - - saa7111_attach, - saa7111_detach, - saa7111_command + .name = "saa7111", /* name */ + .id = I2C_DRIVERID_SAA7111A, /* ID */ + .flags = I2C_DF_NOTIFY, + .attach_adapter = saa7111_probe, + .detach_client = saa7111_detach, + .command = saa7111_command +}; + +static struct i2c_client client_template = { + .name = "saa7111_client", + .id = -1, + .driver = &i2c_driver_saa7111 }; static int saa7111_init(void) { - return i2c_register_driver(&i2c_driver_saa7111); + return i2c_add_driver(&i2c_driver_saa7111); } static void saa7111_exit(void) { - i2c_unregister_driver(&i2c_driver_saa7111); + i2c_del_driver(&i2c_driver_saa7111); } module_init(saa7111_init); diff -Nru a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c --- a/drivers/media/video/saa7185.c Wed Nov 27 14:36:27 2002 +++ b/drivers/media/video/saa7185.c Wed Nov 27 14:36:27 2002 @@ -43,7 +43,7 @@ #include #include -#include +#include #include @@ -52,9 +52,10 @@ /* ----------------------------------------------------------------------- */ struct saa7185 { - struct i2c_bus *bus; + struct i2c_client *client; int addr; unsigned char reg[128]; + struct semaphore lock; int norm; int enable; @@ -69,66 +70,25 @@ #define I2C_DELAY 10 /* ----------------------------------------------------------------------- */ +static unsigned short normal_i2c[] = { 34>>1, I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; +static unsigned short probe[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; +static unsigned short probe_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; +static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END }; +static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; + +static struct i2c_client_address_data addr_data = { + .normal_i2c = normal_i2c, + .normal_i2c_range = normal_i2c_range, + .probe = probe, + .probe_range = probe_range, + .ignore = ignore, + .ignore_range = ignore_range, + .force = force +}; -static int saa7185_read(struct saa7185 *dev) -{ - int ack; - - LOCK_I2C_BUS(dev->bus); - - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY); - ack = i2c_readbyte(dev->bus, 1); - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - return ack; -} - -static int saa7185_write(struct saa7185 *dev, unsigned char subaddr, - unsigned char data) -{ - int ack; - - DEBUG(printk - (KERN_DEBUG "SAA7185: %02x set to %02x\n", subaddr, data); - ) - LOCK_I2C_BUS(dev->bus); - - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - i2c_sendbyte(dev->bus, subaddr, I2C_DELAY); - ack = i2c_sendbyte(dev->bus, data, I2C_DELAY); - dev->reg[subaddr] = data; - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - return ack; -} - -static int saa7185_write_block(struct saa7185 *dev, - unsigned const char *data, unsigned int len) -{ - int ack = -1; - unsigned subaddr; - - while (len > 1) { - LOCK_I2C_BUS(dev->bus); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY); - ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); - len -= 2; - while (len > 1 && *data == ++subaddr) { - data++; - ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); - len -= 2; - } - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - } - return ack; -} - -/* ----------------------------------------------------------------------- */ +static struct i2c_client client_template; static const unsigned char init_common[] = { 0x3a, 0x0f, /* CBENB=0, V656=0, VY2C=1, YUV2C=1, MY2C=1, MUV2C=1 */ @@ -222,58 +182,71 @@ 0x66, 0x21, /* FSC3 */ }; -static int saa7185_attach(struct i2c_device *device) +static int saa7185_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind) { int i; struct saa7185 *encoder; + struct i2c_client client; - MOD_INC_USE_COUNT; - - device->data = encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL); + client = kmalloc(sizeof(*client), GFP_KERNEL); + if (client == NULL) + return -ENOMEM; + client_template.adapter = adap; + client_template.addr = addr; + memcpy(client, &client_template, sizeof(*client)); + encoder = kmalloc(sizeof(*decoder), GFP_KERNEL); if (encoder == NULL) { - MOD_DEC_USE_COUNT; + kfree(client); return -ENOMEM; } - memset(encoder, 0, sizeof(struct saa7185)); - strcpy(device->name, "saa7185"); - encoder->bus = device->bus; - encoder->addr = device->addr; + memset(encoder, 0, sizeof(*decoder)); + strcpy(client->name, "saa7185"); + encoder->client = client; + client->data = encoder; + encoder->addr = addr; encoder->norm = VIDEO_MODE_NTSC; encoder->enable = 1; - i = saa7185_write_block(encoder, init_common, sizeof(init_common)); + i = i2c_master_send(client, init_common, sizeof(init_common)); if (i >= 0) { - i = saa7185_write_block(encoder, init_ntsc, + i = i2c_master_send(client, init_ntsc, sizeof(init_ntsc)); } if (i < 0) { - printk(KERN_ERR "%s_attach: init error %d\n", device->name, + printk(KERN_ERR "%s_attach: init error %d\n", client->name, i); } else { printk(KERN_INFO "%s_attach: chip version %d\n", - device->name, saa7185_read(encoder) >> 5); + client->name, i2c_smbus_read_byte(client) >> 5); } - + init_MUTEX(&decoder->lock); + i2c_attach_client(client); + MOD_INC_USE_COUNT; return 0; } +static int saa7185_probe(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, saa7185_attach); +} - -static int saa7185_detach(struct i2c_device *device) +static int saa7185_detach(struct i2c_client *client) { - struct saa7185 *encoder = device->data; - saa7185_write(encoder, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */ - //saa7185_write(encoder, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */ + struct saa7185 *encoder = client->data; + i2c_detach_client(client); + i2c_smbus_write_byte_data(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */ + //i2c_smbus_write_byte_data(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */ kfree(encoder); + kfree(client); MOD_DEC_USE_COUNT; return 0; } -static int saa7185_command(struct i2c_device *device, unsigned int cmd, +static int saa7185_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct saa7185 *encoder = device->data; + struct saa7185 *encoder = client->data; switch (cmd) { @@ -297,12 +270,12 @@ switch (*iarg) { case VIDEO_MODE_NTSC: - saa7185_write_block(encoder, init_ntsc, + i2c_master_send(client, init_ntsc, sizeof(init_ntsc)); break; case VIDEO_MODE_PAL: - saa7185_write_block(encoder, init_pal, + i2c_master_send(client, init_pal, sizeof(init_pal)); break; @@ -326,19 +299,19 @@ case 0: /* Switch RTCE to 1 */ - saa7185_write(encoder, 0x61, + i2c_smbus_write_byte_data(client, 0x61, (encoder-> reg[0x61] & 0xf7) | 0x08); - saa7185_write(encoder, 0x6e, 0x01); + i2c_smbus_write_byte_data(client, 0x6e, 0x01); break; case 1: /* Switch RTCE to 0 */ - saa7185_write(encoder, 0x61, + i2c_smbus_write_byte_data(client, 0x61, (encoder-> reg[0x61] & 0xf7) | 0x00); /* SW: a slight sync problem... */ - saa7185_write(encoder, 0x6e, 0x00); + i2c_smbus_write_byte_data(client, 0x6e, 0x00); break; default: @@ -364,7 +337,7 @@ int *iarg = arg; encoder->enable = !!*iarg; - saa7185_write(encoder, 0x61, + i2c_smbus_write_byte_data(client, 0x61, (encoder-> reg[0x61] & 0xbf) | (encoder-> enable ? 0x00 : @@ -382,23 +355,28 @@ /* ----------------------------------------------------------------------- */ static struct i2c_driver i2c_driver_saa7185 = { - "saa7185", /* name */ - I2C_DRIVERID_VIDEOENCODER, /* ID */ - I2C_SAA7185, I2C_SAA7185 + 1, - - saa7185_attach, - saa7185_detach, - saa7185_command + .name = "saa7185", /* name */ + .id = I2C_DRIVERID_SAA7185B, /* ID */ + .flags = I2C_DF_NOTIFY, + .attach_adapter = saa7185_probe, + .detach_client = saa7185_detach, + .command = saa7185_command +}; + +static struct i2c_client client_template = { + .name = "saa7185_client", + .id = -1, + .driver = &i2c_driver_saa7185 }; static int saa7185_init(void) { - return i2c_register_driver(&i2c_driver_saa7185); + return i2c_add_driver(&i2c_driver_saa7185); } static void saa7185_exit(void) { - i2c_unregister_driver(&i2c_driver_saa7185); + i2c_del_driver(&i2c_driver_saa7185); } module_init(saa7185_init); diff -Nru a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c --- a/drivers/media/video/stradis.c Wed Nov 27 14:36:31 2002 +++ b/drivers/media/video/stradis.c Wed Nov 27 14:36:31 2002 @@ -1428,6 +1428,9 @@ if (copy_from_user(saa->dmavid2, vw.clips, VIDEO_CLIPMAP_SIZE)) return -EFAULT; + } + else if (vw.clipcount > 16384) { + return -EINVAL; } else if (vw.clipcount > 0) { if ((vcp = vmalloc(sizeof(struct video_clip) * (vw.clipcount))) == NULL) diff -Nru a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c --- a/drivers/media/video/w9966.c Wed Nov 27 14:36:28 2002 +++ b/drivers/media/video/w9966.c Wed Nov 27 14:36:28 2002 @@ -568,7 +568,7 @@ if (state) { timeout = jiffies + 100; while (!w9966_i2c_getscl(cam)) { - if (jiffies > timeout) + if (time_after(jiffies, timeout)) return -1; } } diff -Nru a/drivers/media/video/zr36067.c b/drivers/media/video/zr36067.c --- a/drivers/media/video/zr36067.c Wed Nov 27 14:36:32 2002 +++ b/drivers/media/video/zr36067.c Wed Nov 27 14:36:32 2002 @@ -1416,7 +1416,7 @@ zr36060_sleep(zr, 0); post_office_write(zr, 3, 0, 0); udelay(2); - default: + default:; } return 0; } @@ -3758,7 +3758,7 @@ * Write the overlay mask if clips are wanted. */ - if (vw.clipcount > 2048) + if (vw.clipcount < 0 || vw.clipcount > 2048) return -EINVAL; if (vw.clipcount) { vcp = diff -Nru a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c --- a/drivers/message/fusion/mptbase.c Wed Nov 27 14:36:28 2002 +++ b/drivers/message/fusion/mptbase.c Wed Nov 27 14:36:28 2002 @@ -49,7 +49,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptbase.c,v 1.122 2002/10/03 13:10:11 pdelaney Exp $ + * $Id: mptbase.c,v 1.123 2002/10/17 20:15:56 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -1156,7 +1156,7 @@ dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n")); /* - * NOTE: The 929, 929X and 1030 will appear as 2 separate PCI devices, + * NOTE: The 929, 929X, 1030 and 1035 will appear as 2 separate PCI devices, * one for each channel. */ pci_for_each_dev(pdev) { @@ -1170,18 +1170,14 @@ (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929X) && (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919X) && (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) && -#if 0 - /* FIXME! C103x family */ - (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030_ZC) && - (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1035) && -#endif + (pdev->device != MPI_MANUFACTPAGE_DEVID_1030_53C1035) && 1) { dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device)); continue; } /* GRRRRR - * dual function devices (929, 929X, 1030) may be presented in Func 1,0 order, + * dual function devices (929, 929X, 1030, 1035) may be presented in Func 1,0 order, * but we'd really really rather have them in Func 0,1 order. * Do some kind of look ahead here... */ @@ -1445,15 +1441,24 @@ ioc->chip_type = C1030; ioc->prod_name = "LSI53C1030"; { + u8 revision; + /* 1030 Chip Fix. Disable Split transactions - * for PCIX. Set bits 4 - 6 to zero. + * for PCIX. Set bits 4 - 6 to zero if Rev < C0( = 8) */ - u16 pcixcmd = 0; - pci_read_config_word(pdev, 0x6a, &pcixcmd); - pcixcmd &= 0xFF8F; - pci_write_config_word(pdev, 0x6a, pcixcmd); + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + if (revision < 0x08) { + u16 pcixcmd = 0; + pci_read_config_word(pdev, 0x6a, &pcixcmd); + pcixcmd &= 0xFF8F; + pci_write_config_word(pdev, 0x6a, pcixcmd); + } } } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { + ioc->chip_type = C1035; + ioc->prod_name = "LSI53C1035"; + } sprintf(ioc->name, "ioc%d", ioc->id); @@ -1500,9 +1505,10 @@ mpt_adapters[ioc->id] = ioc; /* NEW! 20010220 -sralston - * Check for "bound ports" (929, 929X, 1030) to reduce redundant resets. + * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. */ - if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) || (ioc->chip_type == FC929X)) + if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) + || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X)) mpt_detect_bound_ports(ioc, pdev); if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { @@ -1746,7 +1752,7 @@ /* * mpt_detect_bound_ports - Search for PCI bus/dev_function * which matches PCI bus/dev_function (+/-1) for newly discovered 929, - * 929X or 1030. + * 929X, 1030 or 1035. * @ioc: Pointer to MPT adapter structure * @pdev: Pointer to (struct pci_dev) structure * @@ -1806,8 +1812,7 @@ /* Disable the FW */ state = mpt_GetIocState(this, 1); if (state == MPI_IOC_STATE_OPERATIONAL) { - if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP) != 0) - (void) KickStart(this, 1, NO_SLEEP); + SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP); } if (this->cached_fw != NULL) { @@ -1819,7 +1824,6 @@ } } - /* Disable adapter interrupts! */ CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); this->active = 0; @@ -2291,9 +2295,6 @@ ioc->reply_sz = ioc->req_sz; ioc->reply_depth = MIN(MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth); - /* 1030 - should we use a smaller DEFAULT_REPLY_DEPTH? - * FIX - */ dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n", ioc->name, ioc->reply_sz, ioc->reply_depth)); dprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n", @@ -2891,6 +2892,7 @@ */ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); while ((diag0val & MPI_DIAG_DRWE) == 0) { + CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); @@ -3126,6 +3128,18 @@ int cnt = 0; dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); + if ((int)ioc->chip_type > (int)FC929) { + /* Always issue a Msg Unit Reset first. This will clear some + * SCSI bus hang conditions. + */ + SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); + + if (sleepFlag == CAN_SLEEP) { + schedule_timeout(HZ); + } else { + mdelay (1000); + } + } hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag); if (hard_reset_done < 0) @@ -5841,6 +5855,15 @@ while (! Q_IS_EMPTY(&MptAdapters)) { this = MptAdapters.head; + + /* Disable interrupts! */ + CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); + + this->active = 0; + + /* Clear any lingering interrupt */ + CHIPREG_WRITE32(&this->chip->IntStatus, 0); + Q_DEL_ITEM(this); mpt_adapter_dispose(this); } diff -Nru a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h --- a/drivers/message/fusion/mptbase.h Wed Nov 27 14:36:28 2002 +++ b/drivers/message/fusion/mptbase.h Wed Nov 27 14:36:28 2002 @@ -13,7 +13,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptbase.h,v 1.134 2002/10/03 13:10:12 pdelaney Exp $ + * $Id: mptbase.h,v 1.136 2002/10/21 13:51:54 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -80,8 +80,8 @@ #define COPYRIGHT "Copyright (c) 1999-2002 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "2.02.01.07" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.02.01.07" +#define MPT_LINUX_VERSION_COMMON "2.03.00.02" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.03.00.02" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -301,6 +301,7 @@ FC919 = 0x0919, FC929 = 0x0929, C1030 = 0x1030, + C1035 = 0x1035, FCUNK = 0xFBAD } CHIP_TYPE; @@ -368,6 +369,7 @@ typedef struct _VirtDevice { struct _VirtDevice *forw; struct _VirtDevice *back; + struct scsi_device *device; rwlock_t VdevLock; int ref_cnt; u8 tflags; @@ -912,6 +914,10 @@ MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ struct scsi_cmnd *abortSCpnt; MPT_LOCAL_REPLY localReply; /* internal cmd reply struct */ + unsigned long hard_resets; /* driver forced bus resets count */ + unsigned long soft_resets; /* fw/external bus resets count */ + unsigned long timeouts; /* cmd timeouts */ + ushort sel_timeout[MPT_MAX_FC_DEVICES]; } MPT_SCSI_HOST; /* diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c --- a/drivers/message/fusion/mptctl.c Wed Nov 27 14:36:27 2002 +++ b/drivers/message/fusion/mptctl.c Wed Nov 27 14:36:27 2002 @@ -34,7 +34,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptctl.c,v 1.60 2002/10/03 13:10:13 pdelaney Exp $ + * $Id: mptctl.c,v 1.61 2002/10/17 20:15:57 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -136,14 +136,8 @@ static int mptctl_replace_fw (unsigned long arg); static int mptctl_do_reset(unsigned long arg); - -static int mptctl_compaq_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -static int mptctl_cpq_getpciinfo(unsigned long arg); -static int mptctl_cpq_getdriver(unsigned long arg); -static int mptctl_cpq_ctlr_status(unsigned long arg); -static int mptctl_cpq_target_address(unsigned long arg); -static int mptctl_cpq_passthru(unsigned long arg); -static int mptctl_compaq_scsiio(VENDOR_IOCTL_REQ *pVenReq, cpqfc_passthru_t *pPass); +static int mptctl_hp_hostinfo(unsigned long arg); +static int mptctl_hp_targetinfo(unsigned long arg); /* * Private function calls. @@ -415,7 +409,7 @@ /* Send request */ if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc->id)) == NULL) { - dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n", + dctlprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n", ioctl->ioc->name)); mptctl_free_tm_flags(ioctl->ioc); @@ -623,21 +617,13 @@ } ret = -ENXIO; /* (-6) No such device or address */ - - /* Test for Compaq-specific IOCTL's. - */ - if ((cmd == CPQFCTS_GETPCIINFO) || (cmd == CPQFCTS_CTLR_STATUS) || - (cmd == CPQFCTS_GETDRIVVER) || (cmd == CPQFCTS_SCSI_PASSTHRU) || - (cmd == CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS)) - return mptctl_compaq_ioctl(file, cmd, arg); - /* Verify intended MPT adapter - set iocnum and the adapter * pointer (iocp) */ iocnumX = khdr.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_ioctl() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_ioctl() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnumX)); return -ENODEV; } @@ -683,6 +669,12 @@ case MPTHARDRESET: ret = mptctl_do_reset(arg); break; + case HP_GETHOSTINFO: + ret = mptctl_hp_hostinfo(arg); + break; + case HP_GETTARGETINFO: + ret = mptctl_hp_targetinfo(arg); + break; default: ret = -EINVAL; } @@ -708,7 +700,7 @@ } if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) { - dtmprintk((KERN_ERR "%s@%d::mptctl_do_reset - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s@%d::mptctl_do_reset - ioc%d not found!\n", __FILE__, __LINE__, krinfo.hdr.iocnum)); return -ENODEV; /* (-6) No such device or address */ } @@ -816,7 +808,7 @@ dctlprintk((KERN_INFO "DbG: kfwdl.ioc = %04xh\n", ioc)); if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) { - dtmprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n", + dctlprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n", __FILE__, __LINE__, ioc)); return -ENODEV; /* (-6) No such device or address */ } @@ -1252,7 +1244,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1379,7 +1371,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1510,7 +1502,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_readtest() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_readtest() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1568,7 +1560,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_eventquery() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_eventquery() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1606,7 +1598,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_eventenable() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_eventenable() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1654,7 +1646,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_eventreport() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_eventreport() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1708,7 +1700,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1794,7 +1786,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1842,7 +1834,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1926,6 +1918,14 @@ int target = (int) pScsiReq->TargetID; int dataSize; + if ((target < 0) || (target >= ioc->sh->max_id)) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Target ID out of bounds. \n", + __FILE__, __LINE__); + rc = -ENODEV; + goto done_free_mem; + } + pScsiReq->MsgFlags = mpt_msg_flags(); /* verify that app has not requested @@ -2049,9 +2049,37 @@ } break; + case MPI_FUNCTION_IOC_INIT: + { + IOCInit_t *pInit = (IOCInit_t *) mf; + u32 high_addr, sense_high; + + /* Verify that all entries in the IOC INIT match + * existing setup (and in LE format). + */ + if (sizeof(dma_addr_t) == sizeof(u64)) { + high_addr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32)); + sense_high= cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32)); + } else { + high_addr = 0; + sense_high= 0; + } + + if ((pInit->Flags != 0) || (pInit->MaxDevices != ioc->facts.MaxDevices) || + (pInit->MaxBuses != ioc->facts.MaxBuses) || + (pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) || + (pInit->HostMfaHighAddr != high_addr) || + (pInit->SenseBufferHighAddr != sense_high)) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n", + __FILE__, __LINE__); + rc = -EFAULT; + goto done_free_mem; + } + } + break; default: /* - * MPI_FUNCTION_IOC_INIT * MPI_FUNCTION_PORT_ENABLE * MPI_FUNCTION_TARGET_CMD_BUFFER_POST * MPI_FUNCTION_TARGET_ASSIST @@ -2357,131 +2385,85 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Routine for the Compaq IOCTL commands. +/* Prototype Routine for the HP HOST INFO command. * * Outputs: None. * Return: 0 if successful - * -EBUSY if previous command timout and IOC reset is not complete. * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - * -ETIME if timer expires - * -ENOMEM if memory allocation error - */ -static int -mptctl_compaq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int iocnum = 0; - unsigned iocnumX = 0; - int ret; - int nonblock = (file->f_flags & O_NONBLOCK); - MPT_ADAPTER *iocp = NULL; - - if (cmd == CPQFCTS_SCSI_PASSTHRU) { - /* Update the iocnum */ - if (copy_from_user(&iocnumX, (int *)arg, sizeof(int))) { - printk(KERN_ERR "%s::mptctl_compaq_ioctl() @%d - " - "Unable to read controller number @ %p\n", - __FILE__, __LINE__, (void*)arg); - return -EFAULT; - } - iocnumX &= 0xFF; - } - - if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || - (iocp == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_compaq_ioctl() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnumX)); - return -ENODEV; - } - - /* All of these commands require an interrupt or - * are unknown/illegal. - */ - if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) - return ret; - - dctlprintk((MYIOC_s_INFO_FMT ": mptctl_compaq_ioctl()\n", iocp->name)); - - switch(cmd) { - case CPQFCTS_GETPCIINFO: - ret = mptctl_cpq_getpciinfo(arg); - break; - case CPQFCTS_GETDRIVVER: - ret = mptctl_cpq_getdriver(arg); - break; - case CPQFCTS_CTLR_STATUS: - ret = mptctl_cpq_ctlr_status(arg); - break; - case CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS: - ret = mptctl_cpq_target_address(arg); - break; - case CPQFCTS_SCSI_PASSTHRU: - ret = mptctl_cpq_passthru(arg); - break; - default: - ret = -EINVAL; - } - - up(&mptctl_syscall_sem_ioc[iocp->id]); - - return ret; - -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_getpciinfo - Get PCI Information in format desired by Compaq - * - * Outputs: None. - * Return: 0 if successful * -EBUSY if previous command timout and IOC reset is not complete. - * -EFAULT if data unavailable * -ENODEV if no such device/adapter * -ETIME if timer expires + * -ENOMEM if memory allocation error */ static int -mptctl_cpq_getpciinfo(unsigned long arg) +mptctl_hp_hostinfo(unsigned long arg) { - cpqfc_pci_info_struct *uarg = (cpqfc_pci_info_struct *) arg; - cpqfc_pci_info_struct karg; + hp_host_info_t *uarg = (hp_host_info_t *) arg; MPT_ADAPTER *ioc; struct pci_dev *pdev; + char *pbuf; + dma_addr_t buf_dma; + hp_host_info_t karg; CONFIGPARMS cfg; ConfigPageHeader_t hdr; - int iocnum = 0, iocnumX = 0; - dma_addr_t buf_dma; - u8 *pbuf = NULL; - int failed; + int iocnum; + int rc; - dctlprintk((": mptctl_cpq_pciinfo called.\n")); - if (copy_from_user(&karg, uarg, sizeof(cpqfc_pci_info_struct))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_pciinfo - " - "Unable to read in cpqfc_pci_info_struct @ %p\n", + dctlprintk((": mptctl_hp_hostinfo called.\n")); + if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) { + printk(KERN_ERR "%s@%d::mptctl_hp_host_info - " + "Unable to read in hp_host_info struct @ %p\n", __FILE__, __LINE__, (void*)uarg); - return -EINVAL; + return -EFAULT; } - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || + if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_pciinfo() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } + /* Fill in the data and return the structure to the calling + * program + */ pdev = (struct pci_dev *) ioc->pcidev; - /* Populate the structure. */ - karg.bus = pdev->bus->number; - karg.bus_type = 1; /* 1 = PCI; 4 = unknown */ - karg.device_fn = PCI_FUNC(pdev->devfn); - karg.slot_number = PCI_SLOT(pdev->devfn); - karg.vendor_id = pdev->vendor; - karg.device_id = pdev->device; - karg.board_id = (karg.device_id | (karg.vendor_id << 16)); - karg.class_code = pdev->class; + karg.vendor = pdev->vendor; + karg.device = pdev->device; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - karg.sub_vendor_id = pdev->subsystem_vendor; - karg.sub_device_id = pdev->subsystem_device; + karg.subsystem_id = pdev->subsystem_device; + karg.subsystem_vendor = pdev->subsystem_vendor; #endif + karg.devfn = pdev->devfn; + karg.bus = pdev->bus->number; + + /* Save the SCSI host no. if + * SCSI driver loaded + */ + if (ioc->sh != NULL) + karg.host_no = ioc->sh->host_no; + else + karg.host_no = -1; + + /* Reformat the fw_version into a string + */ + karg.fw_version[0] = ioc->facts.FWVersion.Struct.Major >= 10 ? + ((ioc->facts.FWVersion.Struct.Major / 10) + '0') : '0'; + karg.fw_version[1] = (ioc->facts.FWVersion.Struct.Major % 10 ) + '0'; + karg.fw_version[2] = '.'; + karg.fw_version[3] = ioc->facts.FWVersion.Struct.Minor >= 10 ? + ((ioc->facts.FWVersion.Struct.Minor / 10) + '0') : '0'; + karg.fw_version[4] = (ioc->facts.FWVersion.Struct.Minor % 10 ) + '0'; + karg.fw_version[5] = '.'; + karg.fw_version[6] = ioc->facts.FWVersion.Struct.Unit >= 10 ? + ((ioc->facts.FWVersion.Struct.Unit / 10) + '0') : '0'; + karg.fw_version[7] = (ioc->facts.FWVersion.Struct.Unit % 10 ) + '0'; + karg.fw_version[8] = '.'; + karg.fw_version[9] = ioc->facts.FWVersion.Struct.Dev >= 10 ? + ((ioc->facts.FWVersion.Struct.Dev / 10) + '0') : '0'; + karg.fw_version[10] = (ioc->facts.FWVersion.Struct.Dev % 10 ) + '0'; + karg.fw_version[11] = '\0'; /* Issue a config request to get the device serial number */ @@ -2496,8 +2478,7 @@ cfg.dir = 0; /* read */ cfg.timeout = 10; - failed = 1; - + strncpy(karg.serial_number, " ", 24); if (mpt_config(ioc, &cfg) == 0) { if (cfg.hdr->PageLength > 0) { /* Issue the second config page request */ @@ -2508,242 +2489,207 @@ cfg.physAddr = buf_dma; if (mpt_config(ioc, &cfg) == 0) { ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf; - strncpy(karg.serial_number, pdata->BoardTracerNumber, 17); - failed = 0; + if (strlen(pdata->BoardTracerNumber) > 1) + strncpy(karg.serial_number, pdata->BoardTracerNumber, 24); } pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma); pbuf = NULL; } } } - if (failed) - strncpy(karg.serial_number, " ", 17); - - /* Copy the data from kernel memory to user memory - */ - if (copy_to_user((char *)arg, &karg, - sizeof(cpqfc_pci_info_struct))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_pciinfo - " - "Unable to write out cpqfc_pci_info_struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } + rc = mpt_GetIocState(ioc, 1); + switch (rc) { + case MPI_IOC_STATE_OPERATIONAL: + karg.ioc_status = HP_STATUS_OK; + break; - return 0; -} + case MPI_IOC_STATE_FAULT: + karg.ioc_status = HP_STATUS_FAILED; + break; -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_getdriver - Get Driver Version in format desired by Compaq - * - * Outputs: None. - * Return: 0 if successful - * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - */ -static int -mptctl_cpq_getdriver(unsigned long arg) -{ - int *uarg = (int *)arg; - int karg; - MPT_ADAPTER *ioc = NULL; - int iocnum = 0, iocnumX = 0; - int ii, jj; - char version[10]; - char val; - char *vptr = NULL; - char *pptr = NULL; - - dctlprintk((": mptctl_cpq_getdriver called.\n")); - if (copy_from_user(&karg, uarg, sizeof(int))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_getdriver - " - "Unable to read in struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; + case MPI_IOC_STATE_RESET: + case MPI_IOC_STATE_READY: + default: + karg.ioc_status = HP_STATUS_OTHER; + break; } - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_cpq_getdriver() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); - return -ENODEV; - } + karg.base_io_addr = pdev->PCI_BASEADDR_START(0); - strncpy(version, MPT_LINUX_VERSION_COMMON, 8); + if ((int)ioc->chip_type <= (int) FC929) + karg.bus_phys_width = HP_BUS_WIDTH_UNK; + else + karg.bus_phys_width = HP_BUS_WIDTH_16; - karg = 0; - vptr = version; - ii = 3; - while (ii > 0) { - pptr = strchr(vptr, '.'); - if (pptr) { - *pptr = '\0'; - val = 0; - for (jj=0; vptr[jj]>='0' && vptr[jj]<='9'; jj++) - val = 10 * val + (vptr[jj] - '0'); - karg |= (val << (8*ii)); - pptr++; - vptr = pptr; - } else - break; - ii--; + karg.hard_resets = 0; + karg.soft_resets = 0; + karg.timeouts = 0; + if (ioc->sh != NULL) { + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + + if (hd) { + karg.hard_resets = hd->hard_resets; + karg.soft_resets = hd->soft_resets; + karg.timeouts = hd->timeouts; + } } /* Copy the data from kernel memory to user memory */ if (copy_to_user((char *)arg, &karg, - sizeof(int))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_getdriver - " - "Unable to write out stuct @ %p\n", + sizeof(hp_host_info_t))) { + printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - " + "Unable to write out hp_host_info @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } return 0; + } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_ctlr_status - Get controller status in format desired by Compaq +/* Prototype Routine for the HP TARGET INFO command. * * Outputs: None. * Return: 0 if successful * -EFAULT if data unavailable + * -EBUSY if previous command timout and IOC reset is not complete. * -ENODEV if no such device/adapter + * -ETIME if timer expires + * -ENOMEM if memory allocation error */ static int -mptctl_cpq_ctlr_status(unsigned long arg) +mptctl_hp_targetinfo(unsigned long arg) { - cpqfc_ctlr_status *uarg = (cpqfc_ctlr_status *) arg; - cpqfc_ctlr_status karg; + hp_target_info_t *uarg = (hp_target_info_t *) arg; + SCSIDevicePage0_t *pg0_alloc; + SCSIDevicePage3_t *pg3_alloc; MPT_ADAPTER *ioc; - int iocnum = 0, iocnumX = 0; + MPT_SCSI_HOST *hd = NULL; + hp_target_info_t karg; + int iocnum; + int data_sz; + dma_addr_t page_dma; + CONFIGPARMS cfg; + ConfigPageHeader_t hdr; + int tmp, np, rc = 0; - dctlprintk((": mptctl_cpq_pciinfo called.\n")); - if (copy_from_user(&karg, uarg, sizeof(cpqfc_ctlr_status))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_ctlr_status - " - "Unable to read in cpqfc_ctlr_status @ %p\n", + dctlprintk((": mptctl_hp_targetinfo called.\n")); + if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) { + printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - " + "Unable to read in hp_host_targetinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } - - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_cpq_ctlr_status() @%d - ioc%d not found!\n", + + if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || + (ioc == NULL)) { + dctlprintk((KERN_ERR "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } - karg.status = ioc->last_state; - karg.offline_reason = 0; - - /* Copy the data from kernel memory to user memory + /* There is nothing to do for FCP parts. */ - if (copy_to_user((char *)arg, &karg, - sizeof(cpqfc_ctlr_status))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_ctlr_status - " - "Unable to write out cpqfc_ctlr_status @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } - - return 0; -} + if ((int) ioc->chip_type <= (int) FC929) + return 0; -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_target_address - Get WWN Information in format desired by Compaq - * - * Outputs: None. - * Return: 0 if successful - * -EBUSY if previous command timout and IOC reset is not complete. - * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - * -ETIME if timer expires - */ -static int -mptctl_cpq_target_address(unsigned long arg) -{ - Scsi_FCTargAddress *uarg = (Scsi_FCTargAddress *) arg; - Scsi_FCTargAddress karg; - MPT_ADAPTER *ioc; - int iocnum = 0, iocnumX = 0; - CONFIGPARMS cfg; - ConfigPageHeader_t hdr; - dma_addr_t buf_dma; - u8 *pbuf = NULL; - FCPortPage0_t *ppp0; - int ii, failed; - u32 low, high; - - dctlprintk((": mptctl_cpq_target_address called.\n")); - if (copy_from_user(&karg, uarg, sizeof(Scsi_FCTargAddress))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_target_address - " - "Unable to read in Scsi_FCTargAddress @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } + if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL)) + return 0; - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_cpq_target_address() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + if (ioc->sh->host_no != karg.hdr.host) return -ENODEV; - } - - karg.host_port_id = 0; + + /* Get the data transfer speeds + */ + data_sz = ioc->spi_data.sdp0length * 4; + pg0_alloc = (SCSIDevicePage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma); + if (pg0_alloc) { + hdr.PageVersion = ioc->spi_data.sdp0version; + hdr.PageLength = data_sz; + hdr.PageNumber = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; + + cfg.hdr = &hdr; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + cfg.dir = 0; + cfg.timeout = 0; + cfg.physAddr = page_dma; + + cfg.pageAddr = (karg.hdr.channel << 8) | karg.hdr.id; + + if ((rc = mpt_config(ioc, &cfg)) == 0) { + np = le32_to_cpu(pg0_alloc->NegotiatedParameters); + karg.negotiated_width = np & MPI_SCSIDEVPAGE0_NP_WIDE ? + HP_BUS_WIDTH_16 : HP_BUS_WIDTH_8; + + if (np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) { + tmp = (np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8; + if (tmp < 0x09) + karg.negotiated_speed = HP_DEV_SPEED_ULTRA320; + else if (tmp <= 0x09) + karg.negotiated_speed = HP_DEV_SPEED_ULTRA160; + else if (tmp <= 0x0A) + karg.negotiated_speed = HP_DEV_SPEED_ULTRA2; + else if (tmp <= 0x0C) + karg.negotiated_speed = HP_DEV_SPEED_ULTRA; + else if (tmp <= 0x25) + karg.negotiated_speed = HP_DEV_SPEED_FAST; + else + karg.negotiated_speed = HP_DEV_SPEED_ASYNC; + } else + karg.negotiated_speed = HP_DEV_SPEED_ASYNC; + } + + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg0_alloc, page_dma); + } + + /* Set defaults + */ + karg.message_rejects = -1; + karg.phase_errors = -1; + karg.parity_errors = -1; + karg.select_timeouts = -1; - /* Issue a config request to get the device wwn + /* Get the target error parameters */ hdr.PageVersion = 0; hdr.PageLength = 0; - hdr.PageNumber = 0; - hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + hdr.PageNumber = 3; + hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; + cfg.hdr = &hdr; - cfg.physAddr = -1; - cfg.pageAddr = 0; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; /* read */ - cfg.timeout = 10; - - failed = 1; - - if (mpt_config(ioc, &cfg) == 0) { - if (cfg.hdr->PageLength > 0) { - /* Issue the second config page request */ - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - - pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma); - if (pbuf) { - cfg.physAddr = buf_dma; - if (mpt_config(ioc, &cfg) == 0) { - ppp0 = (FCPortPage0_t *) pbuf; - - low = le32_to_cpu(ppp0->WWNN.Low); - high = le32_to_cpu(ppp0->WWNN.High); - - for (ii = 0; ii < 4; ii++) { - karg.host_wwn[7-ii] = low & 0xFF; - karg.host_wwn[3-ii] = high & 0xFF; - low = (low >> 8); - high = (high >> 8); - } - failed = 0; - } - pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma); - pbuf = NULL; + cfg.dir = 0; + cfg.timeout = 0; + cfg.physAddr = -1; + if ((mpt_config(ioc, &cfg) == 0) && (cfg.hdr->PageLength > 0)) { + /* Issue the second config page request */ + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + data_sz = (int) cfg.hdr->PageLength * 4; + pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent( + ioc->pcidev, data_sz, &page_dma); + if (pg3_alloc) { + cfg.physAddr = page_dma; + cfg.pageAddr = (karg.hdr.channel << 8) | karg.hdr.id; + if ((rc = mpt_config(ioc, &cfg)) == 0) { + karg.message_rejects = (u32) le16_to_cpu(pg3_alloc->MsgRejectCount); + karg.phase_errors = (u32) le16_to_cpu(pg3_alloc->PhaseErrorCount); + karg.parity_errors = (u32) le16_to_cpu(pg3_alloc->ParityErrorCount); } + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg3_alloc, page_dma); } } - - if (failed) { - for (ii = 7; ii >= 0; ii--) - karg.host_wwn[ii] = 0; - } + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + if (hd != NULL) + karg.select_timeouts = hd->sel_timeout[karg.hdr.id]; /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, - sizeof(Scsi_FCTargAddress))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_target_address - " - "Unable to write out Scsi_FCTargAddress @ %p\n", + if (copy_to_user((char *)arg, &karg, sizeof(hp_target_info_t))) { + printk(KERN_ERR "%s@%d::mptctl_hp_target_info - " + "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } @@ -2752,161 +2698,6 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_passthru - Construct and issue a SCSI IO Passthru - * - * Requires the SCSI host driver to be loaded. - * I386 version. - * - * Outputs: None. - * Return: 0 if successful - * -EBUSY if previous command timout and IOC reset is not complete. - * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - * -ETIME if timer expires - */ -static int -mptctl_cpq_passthru(unsigned long arg) -{ - VENDOR_IOCTL_REQ *uarg = (VENDOR_IOCTL_REQ *) arg; - VENDOR_IOCTL_REQ karg; - cpqfc_passthru_t kpass; - MPT_ADAPTER *ioc; - int iocnum = 0, iocnumX = 0; - int rc; - - dctlprintk((": mptctl_cpq_passthru called.\n")); - if (copy_from_user(&karg, uarg, sizeof(VENDOR_IOCTL_REQ))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_passthru - " - "Unable to read in VENDOR_IOCTL_REQ @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } - - /* Set the IOC number */ - iocnumX = karg.lc & 0xFF; - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_cpq_passthru() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); - return -ENODEV; - } - - if (ioc->sh == NULL) { - printk(KERN_ERR "%s::mptctl_cpq_passthru() @%d - SCSI Host driver not loaded!\n", - __FILE__, __LINE__); - return -EFAULT; - } - - /* Read in the second buffer */ - if (copy_from_user(&kpass, uarg->argp, sizeof(cpqfc_passthru_t))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_passthru - " - "Unable to read in cpqfc_passthru_t @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } - - - /* Generate the SCSI IO command and issue */ - rc = mptctl_compaq_scsiio(&karg, &kpass); - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_compaq_scsiio - Reformat Compaq structures into driver structures - * Call the generic _do_mpt_command function. - * - * Requires the SCSI host driver to be loaded. - * I386 version. - * - * Outputs: None. - * Return: 0 if successful - * -EBUSY if previous command timout and IOC reset is not complete. - * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - * -ETIME if timer expires - */ -static int -mptctl_compaq_scsiio(VENDOR_IOCTL_REQ *pVenReq, cpqfc_passthru_t *pPass) -{ - struct mpt_ioctl_command karg; - SCSIIORequest_t request ; - SCSIIORequest_t *pMf; - int ii, rc; - u8 opcode; - - /* Fill in parameters to karg */ - karg.hdr.iocnum = pVenReq->lc; - karg.hdr.port = 0; - karg.hdr.maxDataSize = 0; /* not used */ - karg.timeout = 0; /* use default */ - - karg.replyFrameBufPtr = NULL; /* no reply data */ - karg.maxReplyBytes = 0; - - karg.senseDataPtr = pPass->sense_data; - karg.maxSenseBytes = pPass->sense_len; /* max is 40 */ - - if (pPass->rw_flag == MPT_COMPAQ_WRITE) { - karg.dataOutBufPtr = pPass->bufp; - karg.dataOutSize = pPass->len; - karg.dataInBufPtr = NULL; - karg.dataInSize = 0; - } else { - karg.dataInBufPtr = pPass->bufp; - karg.dataInSize = pPass->len; - karg.dataOutBufPtr = NULL; - karg.dataOutSize = 0; - } - - karg.dataSgeOffset = (sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION))/4; - - /* Construct the Message frame */ - pMf = &request; - - pMf->TargetID = (u8) pVenReq->ld; /* ???? FIXME */ - pMf->Bus = (u8) pPass->bus; - pMf->ChainOffset = 0; - pMf->Function = MPI_FUNCTION_SCSI_IO_REQUEST; - - /* May need some tweaking here */ - opcode = (u8) pPass->cdb[0]; - if (opcode < 0x20) - pMf->CDBLength = 6; - else if (opcode < 0x60) - pMf->CDBLength = 10; - else if ((opcode < 0xC0) && (opcode >= 0xA0)) - pMf->CDBLength = 12; - else - pMf->CDBLength = 16; - - pMf->SenseBufferLength = karg.maxSenseBytes; /* max is 40 */ - pMf->Reserved = 0; - pMf->MsgFlags = 0; /* set later */ - pMf->MsgContext = 0; /* set later */ - - for (ii = 0; ii < 8; ii++) - pMf->LUN[ii] = 0; - pMf->LUN[1] = 0; /* ???? FIXME */ - - /* Tag values set by _do_mpt_command */ - if (pPass->rw_flag == MPT_COMPAQ_WRITE) - pMf->Control = MPI_SCSIIO_CONTROL_WRITE; - else - pMf->Control = MPI_SCSIIO_CONTROL_READ; - - for (ii = 0; ii < 16; ii++) - pMf->CDB[ii] = pPass->cdb[ii]; - - pMf->DataLength = pPass->len; - - /* All remaining fields are set by the next function - */ - rc = mptctl_do_mpt_command (karg, (char *)pMf, 1); - return rc; -} - - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51) #define owner_THIS_MODULE owner: THIS_MODULE, @@ -2971,7 +2762,7 @@ iocnumX = kfw32.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - dtmprintk((KERN_ERR MYNAM "::sparc32_mptfwxfer_ioctl @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR MYNAM "::sparc32_mptfwxfer_ioctl @%d - ioc%d not found!\n", __LINE__, iocnumX)); return -ENODEV; } @@ -3011,7 +2802,7 @@ iocnumX = karg32.hdr.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - dtmprintk((KERN_ERR MYNAM "::sparc32_mpt_command @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR MYNAM "::sparc32_mpt_command @%d - ioc%d not found!\n", __LINE__, iocnumX)); return -ENODEV; } @@ -3044,70 +2835,6 @@ return ret; } -static int -sparc32_mptctl_cpq_passthru(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *filp) -{ - VENDOR_IOCTL_REQ32 *uarg = (VENDOR_IOCTL_REQ32 *) arg; - VENDOR_IOCTL_REQ32 karg32; - VENDOR_IOCTL_REQ karg; - cpqfc_passthru32_t kpass32; - cpqfc_passthru_t kpass; - MPT_ADAPTER *ioc; - int nonblock = (filp->f_flags & O_NONBLOCK); - int iocnum = 0, iocnumX = 0; - int rc; - int ii; - - dctlprintk((KERN_INFO MYNAM "::sparc32_mptctl_cpq_passthru() called\n")); - - if (copy_from_user(&karg32, (char *)arg, sizeof(karg32))) - return -EFAULT; - - /* Verify intended MPT adapter */ - iocnumX = karg32.lc & 0xFF; - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR MYNAM "::sparc32_mpt_command @%d - ioc%d not found!\n", - __LINE__, iocnumX)); - return -ENODEV; - } - - if ((rc = mptctl_syscall_down(ioc, nonblock)) != 0) - return rc; - - /* Copy data to karg */ - karg.ld = karg32.ld; - karg.node = karg32.node; - karg.lc = karg32.lc; - karg.nexus = karg32.nexus; - karg.argp = (void *)(unsigned long)karg32.argp; - - /* Read in the second buffer */ - if (copy_from_user(&kpass32, karg.argp, sizeof(cpqfc_passthru32_t))) { - printk(KERN_ERR "%s@%d::sparc32_mptctl_cpq_passthru - " - "Unable to read in cpqfc_passthru_t @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } - - /* Copy the 32bit buffer to kpass */ - for (ii = 0; ii < 16; ii++) - kpass.cdb[ii] = kpass32.cdb[ii]; - kpass.bus = kpass32.bus; - kpass.pdrive = kpass32.pdrive; - kpass.len = kpass32.len; - kpass.sense_len = kpass32.sense_len; - kpass.bufp = (void *)(unsigned long)kpass32.bufp; - kpass.rw_flag = kpass32.rw_flag; - - /* Generate the SCSI IO command and issue */ - rc = mptctl_compaq_scsiio(&karg, &kpass); - - up(&mptctl_syscall_sem_ioc[ioc->id]); - return rc; -} - #endif /*} linux >= 2.3.x */ #endif /*} sparc */ @@ -3176,15 +2903,9 @@ err = register_ioctl32_conversion(MPTFWDOWNLOAD32, sparc32_mptfwxfer_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_GETPCIINFO, NULL); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_CTLR_STATUS, NULL); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_GETDRIVVER, NULL); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS, NULL); + err = register_ioctl32_conversion(HP_GETHOSTINFO, NULL); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_SCSI_PASSTHRU32, sparc32_mptctl_cpq_passthru); + err = register_ioctl32_conversion(HP_GETTARGETINFO, NULL); if (++where && err) goto out_fail; #endif /*} linux >= 2.3.x */ #endif /*} sparc */ @@ -3233,11 +2954,8 @@ unregister_ioctl32_conversion(MPTHARDRESET); unregister_ioctl32_conversion(MPTCOMMAND32); unregister_ioctl32_conversion(MPTFWDOWNLOAD32); - unregister_ioctl32_conversion(CPQFCTS_GETPCIINFO); - unregister_ioctl32_conversion(CPQFCTS_GETDRIVVER); - unregister_ioctl32_conversion(CPQFCTS_CTLR_STATUS); - unregister_ioctl32_conversion(CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS); - unregister_ioctl32_conversion(CPQFCTS_SCSI_PASSTHRU32); + unregister_ioctl32_conversion(HP_GETHOSTINFO); + unregister_ioctl32_conversion(HP_GETTARGETINFO); #endif /*} linux >= 2.3.x */ #endif /*} sparc */ diff -Nru a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h --- a/drivers/message/fusion/mptctl.h Wed Nov 27 14:36:30 2002 +++ b/drivers/message/fusion/mptctl.h Wed Nov 27 14:36:30 2002 @@ -20,7 +20,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptctl.h,v 1.11 2002/10/03 13:10:13 pdelaney Exp $ + * $Id: mptctl.h,v 1.12 2002/10/17 20:15:58 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -310,95 +310,91 @@ #endif /*}*/ - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - /* - * COMPAQ Specific IOCTL Defines and Structures - */ +/* + * HP Specific IOCTL Defines and Structures + */ #define CPQFCTS_IOC_MAGIC 'Z' +#define HP_IOC_MAGIC 'Z' +#define HP_GETHOSTINFO _IOR(HP_IOC_MAGIC, 20, hp_host_info_t) +#define HP_GETTARGETINFO _IOR(HP_IOC_MAGIC, 21, hp_target_info_t) -#define CPQFCTS_GETPCIINFO _IOR(CPQFCTS_IOC_MAGIC, 1, cpqfc_pci_info_struct) -#define CPQFCTS_GETDRIVVER _IOR(CPQFCTS_IOC_MAGIC, 9, int) -#define CPQFCTS_CTLR_STATUS _IOR(CPQFCTS_IOC_MAGIC, 3, struct _cpqfc_ctlr_status) -#define CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS _IOR(CPQFCTS_IOC_MAGIC, 13, struct scsi_fctargaddress) -#define CPQFCTS_SCSI_PASSTHRU _IOWR(CPQFCTS_IOC_MAGIC, 11, VENDOR_IOCTL_REQ) -#if defined(__sparc__) && defined(__sparc_v9__) -#define CPQFCTS_SCSI_PASSTHRU32 _IOWR(CPQFCTS_IOC_MAGIC, 11, VENDOR_IOCTL_REQ32) -#endif - -typedef struct { - unsigned short bus; - unsigned short bus_type; - unsigned short device_fn; - u32 board_id; - u32 slot_number; - unsigned short vendor_id; - unsigned short device_id; - unsigned short class_code; - unsigned short sub_vendor_id; - unsigned short sub_device_id; - u8 serial_number[81]; -} cpqfc_pci_info_struct; - - -typedef struct scsi_fctargaddress { - unsigned int host_port_id; - u8 host_wwn[8]; /* WW Network Name */ -} Scsi_FCTargAddress; - -typedef struct _cpqfc_ctlr_status { - u32 status; - u32 offline_reason; -} cpqfc_ctlr_status; - - -/* Compaq SCSI I/O Passthru structures. +/* All HP IOCTLs must include this header */ -#define MPT_COMPAQ_READ 0x26 -#define MPT_COMPAQ_WRITE 0x27 - -typedef struct { - int lc; /* controller number */ - int node; /* node number */ - int ld; /* target logical id */ - u32 nexus; - void *argp; -} VENDOR_IOCTL_REQ; - -#if defined(__KERNEL__) && defined(__sparc__) && defined(__sparc_v9__) /*{*/ -typedef struct { - int lc; /* controller number */ - int node; /* node number */ - int ld; /* target logical id */ - u32 nexus; - u32 argp; -} VENDOR_IOCTL_REQ32; -#endif - -typedef struct { - char cdb[16]; /* cdb */ - unsigned short bus; /* bus number */ - unsigned short pdrive; /* physical drive */ - int len; /* data area size */ - int sense_len; /* sense size */ - char sense_data[40]; /* sense buffer */ - void *bufp; /* data buffer pointer */ - char rw_flag; -} cpqfc_passthru_t; - -#if defined(__KERNEL__) && defined(__sparc__) && defined(__sparc_v9__) /*{*/ -typedef struct { - char cdb[16]; /* cdb */ - unsigned short bus; /* bus number */ - unsigned short pdrive; /* physical drive */ - int len; /* data area size */ - int sense_len; /* sense size */ - char sense_data[40]; /* sense buffer */ - u32 bufp; /* data buffer pointer */ - char rw_flag; -} cpqfc_passthru32_t; -#endif +typedef struct _hp_header { + unsigned int iocnum; + unsigned int host; + unsigned int channel; + unsigned int id; + unsigned int lun; +} hp_header_t; + +/* + * Header: + * iocnum required (input) + * host ignored + * channe ignored + * id ignored + * lun ignored + */ +typedef struct _hp_host_info { + hp_header_t hdr; + u16 vendor; + u16 device; + u16 subsystem_vendor; + u16 subsystem_id; + u8 devfn; + u8 bus; + ushort host_no; /* SCSI Host number, if scsi driver not loaded*/ + u8 fw_version[16]; /* string */ + u8 serial_number[24]; /* string */ + u32 ioc_status; + u32 bus_phys_width; + u32 base_io_addr; + u32 rsvd; + unsigned long hard_resets; /* driver initiated resets */ + unsigned long soft_resets; /* ioc, external resets */ + unsigned long timeouts; /* num timeouts */ +} hp_host_info_t; + +/* + * Header: + * iocnum required (input) + * host required + * channel required (bus number) + * id required + * lun ignored + * + * All error values between 0 and 0xFFFF in size. + */ +typedef struct _hp_target_info { + hp_header_t hdr; + u32 parity_errors; + u32 phase_errors; + u32 select_timeouts; + u32 message_rejects; + u32 negotiated_speed; + u8 negotiated_width; + u8 rsvd[7]; /* 8 byte alignment */ +} hp_target_info_t; + +#define HP_STATUS_OTHER 1 +#define HP_STATUS_OK 2 +#define HP_STATUS_FAILED 3 + +#define HP_BUS_WIDTH_UNK 1 +#define HP_BUS_WIDTH_8 2 +#define HP_BUS_WIDTH_16 3 +#define HP_BUS_WIDTH_32 4 + +#define HP_DEV_SPEED_ASYNC 2 +#define HP_DEV_SPEED_FAST 3 +#define HP_DEV_SPEED_ULTRA 4 +#define HP_DEV_SPEED_ULTRA2 5 +#define HP_DEV_SPEED_ULTRA160 6 +#define HP_DEV_SPEED_SCSI1 7 +#define HP_DEV_SPEED_ULTRA320 8 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff -Nru a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c --- a/drivers/message/fusion/mptlan.c Wed Nov 27 14:36:30 2002 +++ b/drivers/message/fusion/mptlan.c Wed Nov 27 14:36:30 2002 @@ -26,7 +26,7 @@ * Copyright (c) 2000-2002 LSI Logic Corporation * Originally By: Noah Romer * - * $Id: mptlan.c,v 1.52 2002/05/06 13:45:07 sshirron Exp $ + * $Id: mptlan.c,v 1.53 2002/10/17 20:15:58 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* diff -Nru a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h --- a/drivers/message/fusion/mptlan.h Wed Nov 27 14:36:31 2002 +++ b/drivers/message/fusion/mptlan.h Wed Nov 27 14:36:31 2002 @@ -8,7 +8,6 @@ #include #endif -#include #include #include // #include diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c --- a/drivers/message/fusion/mptscsih.c Wed Nov 27 14:36:29 2002 +++ b/drivers/message/fusion/mptscsih.c Wed Nov 27 14:36:29 2002 @@ -26,7 +26,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptscsih.c,v 1.102 2002/10/03 13:10:14 pdelaney Exp $ + * $Id: mptscsih.c,v 1.103 2002/10/17 20:15:59 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -78,6 +78,9 @@ #include /* notifier code */ #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45) +#include "../../scsi/sd.h" +#endif #include "mptbase.h" #include "mptscsih.h" @@ -198,7 +201,7 @@ static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); static void mptscsih_domainValidation(void *hd); static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); -static void mptscsih_qas_check(MPT_SCSI_HOST *hd); +static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); static int mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int target); static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); static void mptscsih_fillbuf(char *buffer, int size, int index, int width); @@ -399,6 +402,9 @@ case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ /* Spoof to SCSI Selection Timeout! */ sc->result = DID_NO_CONNECT << 16; + + if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF) + hd->sel_timeout[pScsiReq->TargetID]++; break; case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ @@ -1289,11 +1295,17 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) sh->max_sectors = MPT_SCSI_MAX_SECTORS; #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) || defined CONFIG_HIGHIO sh->highmem_io = 1; #endif sh->this_id = this->pfacts[portnum].PortSCSIID; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44) + /* OS entry to allow host drivers to force + * a queue depth on a per device basis. + */ + sh->select_queue_depths = mptscsih_select_queue_depths; +#endif /* Required entry. */ sh->unique_id = this->id; @@ -2546,14 +2558,13 @@ /* Isse the Task Mgmt request. */ + if (hd->hard_resets < -1) + hd->hard_resets++; rc = mptscsih_IssueTaskMgmt(hd, type, target, lun, ctx2abort, sleepFlag); if (rc) { -#ifdef MPT_SCSI_USE_NEW_EH - hd->tmState = TM_STATE_ERROR; -#endif printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); } else { - printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name); + dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name)); } } #ifdef DROP_TEST @@ -2681,7 +2692,6 @@ { MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; - unsigned long flags; u32 ctx2abort; int scpnt_idx; @@ -2696,10 +2706,11 @@ return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n", - hd->ioc->name, SCpnt); - printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", - hd->ioc->name, atomic_read(&queue_depth)); + printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p, numIOs=%d)\n", + hd->ioc->name, SCpnt, atomic_read(&queue_depth)); + + if (hd->timeouts < -1) + hd->timeouts++; /* Find this command */ @@ -2753,11 +2764,9 @@ ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; hd->abortSCpnt = SCpnt; - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - SCpnt->target, SCpnt->lun, ctx2abort, CAN_SLEEP) - < 0 - || hd->tmState == TM_STATE_ERROR) { + SCpnt->target, SCpnt->lun, ctx2abort, NO_SLEEP) + < 0) { /* The TM request failed and the subsequent FW-reload failed! * Fatal error case. @@ -2765,14 +2774,6 @@ printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n", hd->ioc->name, SCpnt); - /* If command not found, do not do callback, - * just return failed. CHECKME - */ - if (hd->ScsiLookup[scpnt_idx] != NULL) { - SCpnt->result = STS_BUSY; - SCpnt->scsi_done(SCpnt); - } - /* We must clear our pending flag before clearing our state. */ hd->tmPending = 0; @@ -2780,34 +2781,8 @@ return FAILED; } + return FAILED; - /* Our task management request will either complete or time out. So we - * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, - * we encountered an error executing the task management request. - */ - while (hd->tmPending == 1){ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - } - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (hd->tmState == TM_STATE_ERROR){ - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " - "TM timeout error! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return FAILED; - } - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " - "Abort was successful! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - - return SUCCESS; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2823,7 +2798,6 @@ mptscsih_dev_reset(Scsi_Cmnd * SCpnt) { MPT_SCSI_HOST *hd; - unsigned long flags; /* If we can't locate our host adapter structure, return FAILED status. */ @@ -2834,10 +2808,13 @@ return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", - hd->ioc->name, SCpnt); - printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", - hd->ioc->name, atomic_read(&queue_depth)); + printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p, numIOs=%d)\n", + hd->ioc->name, SCpnt, atomic_read(&queue_depth)); + + /* Unsupported for SCSI. Suppored for FCP + */ + if (hd->is_spi) + return FAILED; /* Wait a fixed amount of time for the TM pending flag to be cleared. * If we time out, then we return a FAILED status to the caller. This @@ -2853,7 +2830,7 @@ } if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - SCpnt->target, 0, 0, CAN_SLEEP) + SCpnt->target, 0, 0, NO_SLEEP) < 0){ /* The TM request failed and the subsequent FW-reload failed! * Fatal error case. @@ -2864,34 +2841,8 @@ hd->tmState = TM_STATE_NONE; return FAILED; } - - /* Our task management request will either complete or time out. So we - * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, - * we encountered an error executing the task management request. - */ - while (hd->tmPending == 1){ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - } - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (hd->tmState == TM_STATE_ERROR){ - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: " - "TM timeout error! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return FAILED; - } - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: " - "Device reset was successful! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return SUCCESS; + } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2907,7 +2858,6 @@ mptscsih_bus_reset(Scsi_Cmnd * SCpnt) { MPT_SCSI_HOST *hd; - unsigned long flags; /* If we can't locate our host adapter structure, return FAILED status. */ @@ -2918,10 +2868,11 @@ return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n", - hd->ioc->name, SCpnt); - printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", - hd->ioc->name, atomic_read(&queue_depth)); + printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p, numIOs=%d)\n", + hd->ioc->name, SCpnt, atomic_read(&queue_depth)); + + if (hd->timeouts < -1) + hd->timeouts++; /* Wait a fixed amount of time for the TM pending flag to be cleared. * If we time out, then we return a FAILED status to the caller. This @@ -2932,13 +2883,13 @@ nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " "Timed out waiting for previous TM to complete! " "(sc = %p)\n", - hd->ioc->name, SCpnt ) ); + hd->ioc->name, SCpnt)); return FAILED; } /* We are now ready to execute the task management request. */ if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - 0, 0, 0, CAN_SLEEP) + 0, 0, 0, NO_SLEEP) < 0){ /* The TM request failed and the subsequent FW-reload failed! @@ -2952,32 +2903,6 @@ return FAILED; } - /* Our task management request will either complete or time out. So we - * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, - * we encountered an error executing the task management request. - */ - while (hd->tmPending == 1){ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - } - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (hd->tmState == TM_STATE_ERROR){ - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " - "TM timeout error! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return FAILED; - } - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " - "Bus reset was successful! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return SUCCESS; } @@ -3013,7 +2938,7 @@ /* If our attempts to reset the host failed, then return a failed * status. The host will be taken off line by the SCSI mid-layer. */ - if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){ + if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0){ status = FAILED; } else { /* Make sure TM pending is cleared and TM state is set to @@ -3056,9 +2981,7 @@ break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - + mdelay(250); } while (--loop_count); return status; @@ -3093,6 +3016,9 @@ return SCSI_ABORT_NOT_RUNNING; } + if (hd->timeouts < -1) + hd->timeouts++; + if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { /* Cmd not found in ScsiLookup. * If found in doneQ, delete from Q. @@ -3166,7 +3092,7 @@ SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx); /* For the time being, force bus reset on any abort - * requests for the 1030 FW. + * requests for the 1030/1035 FW. */ if (hd->is_spi) mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; @@ -3226,6 +3152,9 @@ return SCSI_RESET_SUCCESS; } + if (hd->timeouts < -1) + hd->timeouts++; + if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { /* Cmd not found in ScsiLookup. * If found in doneQ, delete from Q. @@ -3583,9 +3512,6 @@ } } } -#ifdef MPT_SCSI_USE_NEW_EH - hd->tmState = TM_STATE_ERROR; -#endif } else { dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n")); @@ -3629,6 +3555,9 @@ spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending = 0; spin_unlock_irqrestore(&ioc->FreeQlock, flags); +#ifdef MPT_SCSI_USE_NEW_EH + hd->tmState = TM_STATE_NONE; +#endif return 1; } @@ -3638,14 +3567,18 @@ * This is anyones guess quite frankly. */ int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int *ip) { +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) +mptscsih_bios_param(Disk * disk, struct block_device *bdev, int *ip) +{ + sector_t capacity = disk->capacity; #else mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip) { - sector_t capacity = disk->capacity; + unsigned capacity = disk->capacity; #endif int size; @@ -3666,20 +3599,63 @@ * Called once per device the bus scan. Use it to force the queue_depth * member to 1 if a device does not support Q tags. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) int -mptscsih_slave_attach(Scsi_Device *device) +mptscsih_slave_configure(Scsi_Device *device) { + struct Scsi_Host *host = device->host; VirtDevice *pTarget; - pTarget = device->hostdata; - if (!device->tagged_supported || - !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) { - scsi_adjust_queue_depth(device, 0, 1); - } else { - scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, - device->host->can_queue >> 1); + MPT_SCSI_HOST *hd; + + hd = (MPT_SCSI_HOST *)host->hostdata; + if (hd && (hd->Targets != NULL)) { + pTarget = hd->Targets[device->id]; + if (pTarget) { + if (!device->tagged_supported || + !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) { + scsi_adjust_queue_depth(device, 0, 1); + } else { + scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, + device->host->can_queue >> 1); + } + } } return 0; } +#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) */ +void +mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList) +{ + struct scsi_device *device; + VirtDevice *pTarget; + MPT_SCSI_HOST *hd; + int ii, max; + + for (device = sdList; device != NULL; device = device->next) { + + if (device->host != sh) + continue; + + hd = (MPT_SCSI_HOST *) sh->hostdata; + if (hd == NULL) + continue; + + if (hd->Targets != NULL) { + if (hd->is_spi) + max = MPT_MAX_SCSI_DEVICES; + else + max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; + + for (ii=0; ii < max; ii++) { + pTarget = hd->Targets[ii]; + if (pTarget && !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) { + device->queue_depth = 1; + } + } + } + } +} +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -4126,6 +4102,9 @@ spin_unlock_irqrestore(&ioc->FreeQlock, flags); hd->resetPending = 0; hd->numTMrequests = 0; +#ifdef MPT_SCSI_USE_NEW_EH + hd->tmState = TM_STATE_NONE; +#endif /* 6. If there was an internal command, * wake this process up. @@ -4167,10 +4146,13 @@ /* FIXME! */ break; case MPI_EVENT_IOC_BUS_RESET: /* 04 */ - /* FIXME! */ - break; case MPI_EVENT_EXT_BUS_RESET: /* 05 */ - /* FIXME! */ + hd = NULL; + if (ioc->sh) { + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + if (hd && (hd->is_spi) && (hd->soft_resets < -1)) + hd->soft_resets++; + } break; case MPI_EVENT_LOGOUT: /* 09 */ /* FIXME! */ @@ -4804,9 +4786,10 @@ } if (vdev) { - if (hd->ioc->spi_data.isRaid & (1 << target_id)) + if (hd->ioc->spi_data.isRaid & (1 << target_id)) { vdev->raidVolume = 1; - else + ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id)); + } else vdev->raidVolume = 0; } @@ -4868,6 +4851,8 @@ u8 version, nfactor; u8 noQas = 1; + ddvtprintk((KERN_INFO "set Target: (id %d) byte56 0x%x\n", id, byte56)); + /* Set flags based on Inquiry data */ if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { @@ -4886,12 +4871,18 @@ */ if ((byte56 & 0x04) == 0) factor = MPT_ULTRA2; + else if ((byte56 & 0x03) == 0) + factor = MPT_ULTRA160; else factor = MPT_ULTRA320; - /* bit 1 QAS support, non-raid only + /* If RAID, never disable QAS + * else if non RAID, do not disable + * QAS if bit 1 is set + * bit 1 QAS support, non-raid only + * bit 0 IU support */ - if ((target->raidVolume == 0) && (byte56 & 0x02) != 0) + if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0)) noQas = 0; offset = pspi_data->maxSyncOffset; @@ -4976,6 +4967,7 @@ VirtDevice *vdev; int ii; + ddvtprintk((KERN_INFO "Disabling QAS!\n")); pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS; for (ii = 0; ii < id; ii++) { vdev = hd->Targets[id]; @@ -5204,6 +5196,17 @@ //negoFlags = MPT_TARGET_NO_NEGO_SYNC; } +#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION + /* Force to async and narrow if DV has not been executed + * for this ID + */ + if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) { + width = 0; + factor = MPT_ASYNC; + offset = 0; + } +#endif + /* If id is not a raid volume, get the updated * transmission settings from the target structure. */ @@ -5313,13 +5316,6 @@ */ del_timer(&hd->TMtimer); -#ifdef MPT_SCSI_USE_NEW_EH - /* Set the error flag to 1 so that the function that started the - * task management request knows it timed out. - */ - hd->tmState = TM_STATE_ERROR; -#endif - /* Call the reset handler. Already had a TM request * timeout - so issue a diagnostic reset */ @@ -5853,6 +5849,12 @@ else pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); + if (cmd == CMD_RequestSense) { + pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); + ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n", + hd->ioc->name, cmd)); + } + for (ii=0; ii < 16; ii++) pScsiReq->CDB[ii] = CDB[ii]; @@ -6184,7 +6186,7 @@ post_pendingQ_commands(hd); if (hd->ioc->spi_data.noQas) - mptscsih_qas_check(hd); + mptscsih_qas_check(hd, id); } } } @@ -6218,7 +6220,7 @@ /* Write SDP1 if no QAS has been enabled */ -static void mptscsih_qas_check(MPT_SCSI_HOST *hd) +static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) { VirtDevice *pTarget = NULL; int ii; @@ -6227,6 +6229,9 @@ return; for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { + if (ii == id) + continue; + if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0) continue; @@ -6510,6 +6515,7 @@ rc = hd->pLocal->completion; if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) { dv.max.width = 0; + doFallback = 0; } else goto target_done; } @@ -7059,6 +7065,10 @@ dv.cmd = MPT_SAVE; mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); +#if 0 + /* Double writes to SDP1 can cause problems, + * skip here since unnecessary + */ /* Save the final negotiated settings to * SCSI device page 1. */ @@ -7067,13 +7077,14 @@ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; cfg.dir = 1; mpt_config(hd->ioc, &cfg); +#endif } /* If this is a RAID Passthrough, enable internal IOs */ if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) { if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0) - ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name)); + ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name)); } /* Done with the DV scan of the current target @@ -7227,8 +7238,7 @@ pPage1->Configuration = le32_to_cpu(configuration); } ddvprintk(("width %d, factor %x, offset %x request %x config %x\n", - dv->now.width, dv->now.factor, - dv->now.offset, val, configuration)); + width, factor, offset, val, configuration)); break; case MPT_FALLBACK: diff -Nru a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h --- a/drivers/message/fusion/mptscsih.h Wed Nov 27 14:36:32 2002 +++ b/drivers/message/fusion/mptscsih.h Wed Nov 27 14:36:32 2002 @@ -20,7 +20,7 @@ * (mailto:netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptscsih.h,v 1.19 2002/10/03 13:10:15 pdelaney Exp $ + * $Id: mptscsih.h,v 1.20 2002/10/17 20:16:00 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -206,12 +206,11 @@ #define x_scsi_dev_reset mptscsih_dev_reset #define x_scsi_host_reset mptscsih_host_reset #define x_scsi_bios_param mptscsih_bios_param -#define x_scsi_slave_attach mptscsih_slave_attach +#define x_scsi_slave_configure mptscsih_slave_configure #define x_scsi_taskmgmt_bh mptscsih_taskmgmt_bh #define x_scsi_old_abort mptscsih_old_abort #define x_scsi_old_reset mptscsih_old_reset -#define x_scsi_slave_attach mptscsih_slave_attach /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -231,13 +230,15 @@ extern int x_scsi_old_reset(Scsi_Cmnd *, unsigned int); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) -extern int x_scsi_bios_param(Scsi_Device *, struct block_device *, sector_t, int[]); +extern int x_scsi_bios_param(struct scsi_device * sdev, struct block_device *bdev, + sector_t capacity, int *ip); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) +extern int x_scsi_bios_param(Disk *, struct block_device *, int *); #else extern int x_scsi_bios_param(Disk *, kdev_t, int *); #endif -extern int x_scsi_slave_attach(Scsi_Device *); +extern int x_scsi_slave_configure(Scsi_Device *); extern void x_scsi_taskmgmt_bh(void *); -extern int x_scsi_slave_attach(Scsi_Device *); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) #define PROC_SCSI_DECL @@ -247,7 +248,7 @@ #ifdef MPT_SCSI_USE_NEW_EH -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) #define MPT_SCSIHOST { \ PROC_SCSI_DECL \ @@ -255,8 +256,6 @@ .detect = x_scsi_detect, \ .release = x_scsi_release, \ .info = x_scsi_info, \ - .queuecommand = x_scsi_queuecommand, \ - .slave_attach = x_scsi_slave_attach, \ .eh_abort_handler = x_scsi_abort, \ .eh_device_reset_handler = x_scsi_dev_reset, \ .eh_bus_reset_handler = x_scsi_bus_reset, \ @@ -267,27 +266,32 @@ .sg_tablesize = MPT_SCSI_SG_DEPTH, \ .max_sectors = MPT_SCSI_MAX_SECTORS, \ .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .unchecked_isa_dma = 0, \ .use_clustering = ENABLE_CLUSTERING, \ - .slave_attach x_scsi_slave_attach, \ } #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) */ #define MPT_SCSIHOST { \ + .next = NULL, \ PROC_SCSI_DECL \ .name = "MPT SCSI Host", \ .detect = x_scsi_detect, \ .release = x_scsi_release, \ .info = x_scsi_info, \ + .command = NULL, \ .queuecommand = x_scsi_queuecommand, \ + .eh_strategy_handler = NULL, \ .eh_abort_handler = x_scsi_abort, \ .eh_device_reset_handler = x_scsi_dev_reset, \ .eh_bus_reset_handler = x_scsi_bus_reset, \ + .eh_host_reset_handler = NULL, \ .bios_param = x_scsi_bios_param, \ .can_queue = MPT_SCSI_CAN_QUEUE, \ .this_id = -1, \ .sg_tablesize = MPT_SCSI_SG_DEPTH, \ .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .unchecked_isa_dma = 0, \ .use_clustering = ENABLE_CLUSTERING, \ .use_new_eh_code = 1 \ } @@ -297,11 +301,13 @@ #else /* MPT_SCSI_USE_NEW_EH */ #define MPT_SCSIHOST { \ + .next = NULL, \ PROC_SCSI_DECL \ .name = "MPT SCSI Host", \ .detect = x_scsi_detect, \ .release = x_scsi_release, \ .info = x_scsi_info, \ + .command = NULL, \ .queuecommand = x_scsi_queuecommand, \ .abort = x_scsi_old_abort, \ .reset = x_scsi_old_reset, \ @@ -310,6 +316,7 @@ .this_id = -1, \ .sg_tablesize = MPT_SCSI_SG_DEPTH, \ .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .unchecked_isa_dma = 0, \ .use_clustering = ENABLE_CLUSTERING \ } #endif /* MPT_SCSI_USE_NEW_EH */ diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c --- a/drivers/message/i2o/i2o_block.c Wed Nov 27 14:36:31 2002 +++ b/drivers/message/i2o/i2o_block.c Wed Nov 27 14:36:31 2002 @@ -1669,7 +1669,6 @@ if(i2o_install_handler(&i2o_block_handler)<0) { unregister_blkdev(MAJOR_NR, "i2o_block"); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); printk(KERN_ERR "i2o_block: unable to register OSM.\n"); return -EINVAL; } @@ -1682,8 +1681,7 @@ evt_pid = kernel_thread(i2ob_evt, NULL, CLONE_SIGHAND); if(evt_pid < 0) { - printk(KERN_ERR - "i2o_block: Could not initialize event thread. Aborting\n"); + printk(KERN_ERR "i2o_block: Could not initialize event thread. Aborting\n"); i2o_remove_handler(&i2o_block_handler); return 0; } diff -Nru a/drivers/message/i2o/i2o_core.c b/drivers/message/i2o/i2o_core.c --- a/drivers/message/i2o/i2o_core.c Wed Nov 27 14:36:31 2002 +++ b/drivers/message/i2o/i2o_core.c Wed Nov 27 14:36:31 2002 @@ -3344,6 +3344,9 @@ u16 detailed_status = msg[4]&0xFFFF; struct i2o_handler *h = i2o_handlers[msg[2] & (MAX_I2O_MODULES-1)]; + if (cmd == I2O_CMD_UTIL_EVT_REGISTER) + return; // No status in this reply + printk("%s%s: ", severity, str); if (cmd < 0x1F) // Utility cmd diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c --- a/drivers/message/i2o/i2o_scsi.c Wed Nov 27 14:36:31 2002 +++ b/drivers/message/i2o/i2o_scsi.c Wed Nov 27 14:36:31 2002 @@ -57,7 +57,6 @@ #include #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" -#include "../../scsi/sd.h" #if BITS_PER_LONG == 64 #error FIXME: driver does not support 64-bit platforms @@ -336,15 +335,10 @@ return; } -struct i2o_handler i2o_scsi_handler= -{ - i2o_scsi_reply, - NULL, - NULL, - NULL, - "I2O SCSI OSM", - 0, - I2O_CLASS_SCSI_PERIPHERAL +struct i2o_handler i2o_scsi_handler = { + .reply = i2o_scsi_reply, + .name = "I2O SCSI OSM", + .class = I2O_CLASS_SCSI_PERIPHERAL, }; /** @@ -918,6 +912,7 @@ unsigned long msg; u32 m; int tid; + unsigned long timeout; printk(KERN_WARNING "i2o_scsi: Aborting command block.\n"); @@ -930,21 +925,21 @@ return FAILED; } c = hostdata->controller; - - /* - * Obtain an I2O message. Right now we _have_ to obtain one - * until the scsi layer stuff is cleaned up. - * - * FIXME: we are in error context so we could sleep retry - * a bit and then bail in the improved scsi layer. - */ - + + spin_unlock_irq(host->host_lock); + + timeout = jiffies+2*HZ; do { - mb(); m = le32_to_cpu(I2O_POST_READ32(c)); + if(m != 0xFFFFFFFF) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + mb(); } - while(m==0xFFFFFFFF); + while(time_before(jiffies, timeout)); + msg = c->mem_offset + m; i2o_raw_writel(FIVE_WORD_MSG_SIZE, msg); @@ -955,6 +950,8 @@ wmb(); i2o_post_message(c,m); wmb(); + + spin_lock_irq(host->host_lock); return SUCCESS; } @@ -977,14 +974,20 @@ struct i2o_scsi_host *hostdata; u32 m; unsigned long msg; + unsigned long timeout; + /* * Find the TID for the bus */ - printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n"); host = SCpnt->host; + + spin_unlock_irq(host->host_lock); + + printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n"); + hostdata = (struct i2o_scsi_host *)host->hostdata; tid = hostdata->bus_task; c = hostdata->controller; @@ -994,15 +997,19 @@ * will be aborted by the IOP. We need to catch the reply * possibly ? */ - - m = le32_to_cpu(I2O_POST_READ32(c)); + + timeout = jiffies+2*HZ; + do + { + m = le32_to_cpu(I2O_POST_READ32(c)); + if(m != 0xFFFFFFFF) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + mb(); + } + while(time_before(jiffies, timeout)); - /* - * No free messages, try again next time - no big deal - */ - - if(m == 0xFFFFFFFF) - return SCSI_RESET_PUNT; msg = c->mem_offset + m; i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg); @@ -1012,7 +1019,12 @@ /* Now store unit,tid so we can tie the completion back to a specific device */ __raw_writel(c->unit << 16 | tid, msg+12); wmb(); + + /* We want the command to complete after we return */ + spin_lock_irq(host->host_lock); i2o_post_message(c,m); + + /* Should we wait for the reset to complete ? */ return SUCCESS; } @@ -1044,8 +1056,9 @@ /** * i2o_scsi_bios_param - Invent disk geometry - * @disk: device + * @sdev: scsi device * @dev: block layer device + * @capacity: size in sectors * @ip: geometry array * * This is anyones guess quite frankly. We use the same rules everyone diff -Nru a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c --- a/drivers/net/appletalk/ltpc.c Wed Nov 27 14:36:28 2002 +++ b/drivers/net/appletalk/ltpc.c Wed Nov 27 14:36:28 2002 @@ -1059,26 +1059,39 @@ int autoirq; unsigned long flags; unsigned long f; + int portfound=0; SET_MODULE_OWNER(dev); save_flags(flags); /* probe for the I/O port address */ - if (io != 0x240 && !check_region(0x220,8)) { + if (io != 0x240 && request_region(0x220,8,"ltpc")) { x = inb_p(0x220+6); - if ( (x!=0xff) && (x>=0xf0) ) io = 0x220; + if ( (x!=0xff) && (x>=0xf0) ) { + io = 0x220; + portfound=1; + } + else { + release_region(0x220,8); + } } - if (io != 0x220 && !check_region(0x240,8)) { + if (io != 0x220 && request_region(0x240,8,"ltpc")) { y = inb_p(0x240+6); - if ( (y!=0xff) && (y>=0xf0) ) io = 0x240; + if ( (y!=0xff) && (y>=0xf0) ){ + io = 0x240; + portfound=1; + } + else { + release_region(0x240,8); + } } - if(io) { - /* found it, now grab it */ - request_region(io,8,"ltpc"); - } else { + if(io && !portfound && request_region(io,8,"ltpc")){ + portfound = 1; + } + if(!portfound) { /* give up in despair */ printk ("LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y); diff -Nru a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c --- a/drivers/net/arcnet/com20020-pci.c Wed Nov 27 14:36:28 2002 +++ b/drivers/net/arcnet/com20020-pci.c Wed Nov 27 14:36:28 2002 @@ -90,7 +90,7 @@ dev->base_addr = ioaddr; dev->irq = pdev->irq; dev->dev_addr[0] = node; - lp->card_name = pdev->name; + lp->card_name = pdev->dev.name; lp->card_flags = id->driver_data; lp->backplane = backplane; lp->clockp = clockp & 7; diff -Nru a/drivers/net/de600.c b/drivers/net/de600.c --- a/drivers/net/de600.c Wed Nov 27 14:36:32 2002 +++ b/drivers/net/de600.c Wed Nov 27 14:36:32 2002 @@ -444,7 +444,10 @@ return -ENODEV; } - request_region(DE600_IO, 3, "de600"); + if (!request_region(DE600_IO, 3, "de600")) { + printk(KERN_WARNING "DE600: port 0x%x busy\n", DE600_IO); + return -EBUSY; + } printk(", Ethernet Address: %02X", dev->dev_addr[0]); for (i = 1; i < ETH_ALEN; i++) diff -Nru a/drivers/net/depca.c b/drivers/net/depca.c --- a/drivers/net/depca.c Wed Nov 27 14:36:30 2002 +++ b/drivers/net/depca.c Wed Nov 27 14:36:30 2002 @@ -463,8 +463,6 @@ static void depca_dbg_open(struct net_device *dev); #ifdef MODULE -int init_module(void); -void cleanup_module(void); static int autoprobed = 1, loading_module = 1; # else static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 }; diff -Nru a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c --- a/drivers/net/ewrk3.c Wed Nov 27 14:36:32 2002 +++ b/drivers/net/ewrk3.c Wed Nov 27 14:36:32 2002 @@ -332,8 +332,6 @@ #ifdef MODULE -int init_module(void); -void cleanup_module(void); static int autoprobed = 1, loading_module = 1; #else @@ -2083,7 +2081,25 @@ MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)"); MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)"); -int init_module(void) +static void ewrk3_exit_module(void) +{ + int i; + + for( i=0; ipriv) { + kfree(ewrk3_devs[i]->priv); + ewrk3_devs[i]->priv = NULL; + } + ewrk3_devs[i]->irq = 0; + + release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE); + kfree(ewrk3_devs[i]); + ewrk3_devs[i] = NULL; + } +} + +static int ewrk3_init_module(void) { int i=0; @@ -2107,27 +2123,14 @@ return ndevs ? 0 : -EIO; error: - cleanup_module(); + ewrk3_exit_module(); return -ENOMEM; } -void cleanup_module(void) -{ - int i; - - for( i=0; ipriv) { - kfree(ewrk3_devs[i]->priv); - ewrk3_devs[i]->priv = NULL; - } - ewrk3_devs[i]->irq = 0; - release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE); - kfree(ewrk3_devs[i]); - ewrk3_devs[i] = NULL; - } -} +/* Hack for breakage in new module stuff */ +module_exit(ewrk3_exit_module); +module_init(ewrk3_init_module); #endif /* MODULE */ MODULE_LICENSE("GPL"); diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c --- a/drivers/net/fc/iph5526.c Wed Nov 27 14:36:28 2002 +++ b/drivers/net/fc/iph5526.c Wed Nov 27 14:36:28 2002 @@ -3791,8 +3791,10 @@ sprintf(fi->name, "fc%d", count); host = scsi_register(tmpt, sizeof(struct iph5526_hostdata)); - if(host==NULL) + if(host==NULL) { + kfree(fc[count]); return no_of_hosts; + } hostdata = (struct iph5526_hostdata *)host->hostdata; memset(hostdata, 0 , sizeof(struct iph5526_hostdata)); diff -Nru a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig --- a/drivers/net/hamradio/Kconfig Wed Nov 27 14:36:27 2002 +++ b/drivers/net/hamradio/Kconfig Wed Nov 27 14:36:27 2002 @@ -185,120 +185,6 @@ say M here and read . This is recommended. The module will be called baycom_par.o. -config SOUNDMODEM - tristate "Soundcard modem driver" - depends on PARPORT && AX25 - ---help--- - This experimental driver allows a standard Sound Blaster or - WindowsSoundSystem compatible sound card to be used as a packet - radio modem (NOT as a telephone modem!), to send digital traffic - over amateur radio. - - To configure the driver, use the sethdlc, smdiag and smmixer - utilities available in the standard ax25 utilities package. For - information on how to key the transmitter, see - and - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called soundmodem.o. - -config SOUNDMODEM_SBC - bool "soundmodem support for Soundblaster and compatible cards" - depends on SOUNDMODEM - help - This option enables the soundmodem driver to use Sound Blaster and - compatible cards. If you have a dual mode card (i.e. a WSS cards - with a Sound Blaster emulation) you should say N here and Y to - "Sound card modem support for WSS and Crystal cards", below, because - this usually results in better performance. This option also - supports SB16/32/64 in full-duplex mode. - -config SOUNDMODEM_WSS - bool "soundmodem support for WSS and Crystal cards" - depends on SOUNDMODEM - help - This option enables the soundmodem driver to use WindowsSoundSystem - compatible cards. These cards feature a codec chip from either - Analog Devices (such as AD1848, AD1845, AD1812) or Crystal - Semiconductors (such as CS4248, CS423x). This option also supports - the WSS full-duplex operation which currently works with Crystal - CS423x chips. If you don't need full-duplex operation, do not enable - it to save performance. - -config SOUNDMODEM_AFSK1200 - bool "soundmodem support for 1200 baud AFSK modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 1200 baud AFSK modem, - compatible to popular modems using TCM3105 or AM7911. The - demodulator requires about 12% of the CPU power of a Pentium 75 CPU - per channel. - -config SOUNDMODEM_AFSK2400_7 - bool "soundmodem support for 2400 baud AFSK modulation (7.3728MHz crystal)" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 2400 baud AFSK modem, - compatible to TCM3105 modems (over-)clocked with a 7.3728MHz - crystal. Note that the availability of this driver does _not_ imply - that I recommend building such links. It is only here since users - especially in eastern Europe have asked me to do so. In fact this - modulation scheme has many disadvantages, mainly its incompatibility - with many transceiver designs and the fact that the TCM3105 (if - used) is operated widely outside its specifications. - -config SOUNDMODEM_AFSK2400_8 - bool "soundmodem support for 2400 baud AFSK modulation (8MHz crystal)" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 2400 baud AFSK modem, - compatible to TCM3105 modems (over-)clocked with an 8MHz crystal. - Note that the availability of this driver does _not_ imply that I - recommend building such links. It is only here since users - especially in eastern Europe have asked me to do so. In fact this - modulation scheme has many disadvantages, mainly its incompatibility - with many transceiver designs and the fact that the TCM3105 (if - used) is operated widely outside its specifications. - -config SOUNDMODEM_AFSK2666 - bool "soundmodem support for 2666 baud AFSK modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 2666 baud AFSK modem. - This modem is experimental, and not compatible to anything - else I know of. - -config SOUNDMODEM_HAPN4800 - bool "soundmodem support for 4800 baud HAPN-1 modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 4800 baud HAPN-1 - compatible modem. This modulation seems to be widely used 'down - under' and in the Netherlands. Here, nobody uses it, so I could not - test if it works. It is compatible to itself, however :-) - -config SOUNDMODEM_PSK4800 - bool "soundmodem support for 4800 baud PSK modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 4800 baud 8PSK modem. - This modem is experimental, and not compatible to anything - else I know of. - -config SOUNDMODEM_FSK9600 - bool "soundmodem support for 9600 baud FSK G3RUH modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 9600 baud FSK modem, - compatible to the G3RUH standard. The demodulator requires about 4% - of the CPU power of a Pentium 75 CPU per channel. You can say Y to - both 1200 baud AFSK and 9600 baud FSK if you want (but obviously you - can only use one protocol at a time, depending on what the other end - can understand). - config YAM tristate "YAM driver for AX.25" depends on AX25 diff -Nru a/drivers/net/hamradio/Makefile b/drivers/net/hamradio/Makefile --- a/drivers/net/hamradio/Makefile Wed Nov 27 14:36:27 2002 +++ b/drivers/net/hamradio/Makefile Wed Nov 27 14:36:27 2002 @@ -22,6 +22,5 @@ obj-$(CONFIG_BAYCOM_SER_HDX) += baycom_ser_hdx.o hdlcdrv.o obj-$(CONFIG_BAYCOM_PAR) += baycom_par.o hdlcdrv.o obj-$(CONFIG_BAYCOM_EPP) += baycom_epp.o hdlcdrv.o -obj-$(CONFIG_SOUNDMODEM) += soundmodem/ hdlcdrv.o include $(TOPDIR)/Rules.make diff -Nru a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c --- a/drivers/net/hamradio/baycom_epp.c Wed Nov 27 14:36:32 2002 +++ b/drivers/net/hamradio/baycom_epp.c Wed Nov 27 14:36:32 2002 @@ -54,7 +54,6 @@ #include #include #include -#include #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) /* prototypes for ax25_encapsulate and ax25_rebuild_header */ #include @@ -1200,7 +1199,6 @@ struct baycom_state *bc; struct baycom_ioctl bi; struct hdlcdrv_ioctl hi; - struct sm_ioctl si; baycom_paranoia_check(dev, "baycom_ioctl", -EINVAL); bc = (struct baycom_state *)dev->priv; @@ -1208,28 +1206,6 @@ return -ENOIOCTLCMD; if (get_user(cmd, (int *)ifr->ifr_data)) return -EFAULT; -#ifdef BAYCOM_DEBUG - if (cmd == BAYCOMCTL_GETDEBUG) { - bi.data.dbg.debug1 = bc->ptt_keyed; - bi.data.dbg.debug2 = bc->debug_vals.last_intcnt; - bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr; - bc->debug_vals.last_intcnt = 0; - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } - if (cmd == SMCTL_GETDEBUG) { - si.data.dbg.int_rate = bc->debug_vals.last_intcnt; - si.data.dbg.mod_cycles = bc->debug_vals.mod_cycles; - si.data.dbg.demod_cycles = bc->debug_vals.demod_cycles; - si.data.dbg.dma_residue = 0; - bc->debug_vals.mod_cycles = bc->debug_vals.demod_cycles = 0; - bc->debug_vals.last_intcnt = 0; - if (copy_to_user(ifr->ifr_data, &si, sizeof(si))) - return -EFAULT; - return 0; - } -#endif /* BAYCOM_DEBUG */ if (copy_from_user(&hi, ifr->ifr_data, sizeof(hi))) return -EFAULT; diff -Nru a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c --- a/drivers/net/hamradio/dmascc.c Wed Nov 27 14:36:30 2002 +++ b/drivers/net/hamradio/dmascc.c Wed Nov 27 14:36:30 2002 @@ -235,6 +235,8 @@ int state; unsigned long tx_start; int rr0; + spinlock_t *register_lock; /* Per scc_info */ + spinlock_t ring_lock; }; struct scc_info { @@ -243,6 +245,7 @@ struct net_device dev[2]; struct scc_priv priv[2]; struct scc_info *next; + spinlock_t register_lock; /* Per device register lock */ }; @@ -371,7 +374,7 @@ /* Cards found = 0 */ n = 0; /* Warning message */ - if (!io[0]) printk("dmascc: autoprobing (dangerous)\n"); + if (!io[0]) printk(KERN_INFO "dmascc: autoprobing (dangerous)\n"); /* Run autodetection for each card type */ for (h = 0; h < NUM_TYPES; h++) { @@ -456,7 +459,7 @@ if (n) return 0; /* If no adapter found, return error */ - printk("dmascc: no adapters found\n"); + printk(KERN_INFO "dmascc: no adapters found\n"); return -EIO; } @@ -475,18 +478,21 @@ /* Allocate memory */ info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA); if (!info) { - printk("dmascc: could not allocate memory for %s at %#3x\n", + printk(KERN_ERR "dmascc: could not allocate memory for %s at %#3x\n", hw[type].name, card_base); return -1; } /* Initialize what is necessary for write_scc and write_scc_data */ memset(info, 0, sizeof(struct scc_info)); + spin_lock_init(&info->register_lock); + priv = &info->priv[0]; priv->type = type; priv->card_base = card_base; priv->scc_cmd = scc_base + SCCA_CMD; priv->scc_data = scc_base + SCCA_DATA; + priv->register_lock = &info->register_lock; /* Reset SCC */ write_scc(priv, R9, FHWRES | MIE | NV); @@ -510,7 +516,6 @@ write_scc(priv, R15, 0); /* Start IRQ auto-detection */ - sti(); irqs = probe_irq_on(); /* Enable interrupts */ @@ -543,7 +548,7 @@ } if (irq <= 0) { - printk("dmascc: could not find irq of %s at %#3x (irq=%d)\n", + printk(KERN_ERR "dmascc: could not find irq of %s at %#3x (irq=%d)\n", hw[type].name, card_base, irq); kfree(info); return -1; @@ -558,6 +563,8 @@ priv->dev = dev; priv->info = info; priv->channel = i; + spin_lock_init(&priv->ring_lock); + priv->register_lock = &info->register_lock; priv->card_base = card_base; priv->scc_cmd = scc_base + (i ? SCCB_CMD : SCCA_CMD); priv->scc_data = scc_base + (i ? SCCB_DATA : SCCA_DATA); @@ -594,7 +601,7 @@ memcpy(dev->dev_addr, ax25_test, 7); rtnl_lock(); if (register_netdevice(dev)) { - printk("dmascc: could not register %s\n", dev->name); + printk(KERN_ERR "dmascc: could not register %s\n", dev->name); } rtnl_unlock(); } @@ -603,7 +610,7 @@ info->next = first; first = info; - printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name, + printk(KERN_INFO "dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name, chipnames[chip], card_base, irq); return 0; } @@ -623,13 +630,12 @@ outb_p(val, priv->scc_cmd); return; default: - save_flags(flags); - cli(); + spin_lock_irqsave(priv->register_lock, flags); outb_p(0, priv->card_base + PI_DREQ_MASK); if (reg) outb_p(reg, priv->scc_cmd); outb_p(val, priv->scc_cmd); outb(1, priv->card_base + PI_DREQ_MASK); - restore_flags(flags); + spin_unlock_irqrestore(priv->register_lock, flags); return; } } @@ -647,12 +653,11 @@ default: if (fast) outb_p(val, priv->scc_data); else { - save_flags(flags); - cli(); + spin_lock_irqsave(priv->register_lock, flags); outb_p(0, priv->card_base + PI_DREQ_MASK); outb_p(val, priv->scc_data); outb(1, priv->card_base + PI_DREQ_MASK); - restore_flags(flags); + spin_unlock_irqrestore(priv->register_lock, flags); } return; } @@ -670,13 +675,12 @@ if (reg) outb_p(reg, priv->scc_cmd); return inb_p(priv->scc_cmd); default: - save_flags(flags); - cli(); + spin_lock_irqsave(&priv->register_lock, flags); outb_p(0, priv->card_base + PI_DREQ_MASK); if (reg) outb_p(reg, priv->scc_cmd); rc = inb_p(priv->scc_cmd); outb(1, priv->card_base + PI_DREQ_MASK); - restore_flags(flags); + spin_unlock_irqrestore(priv->register_lock, flags); return rc; } } @@ -691,12 +695,11 @@ case TYPE_TWIN: return inb_p(priv->scc_data); default: - save_flags(flags); - cli(); + spin_lock_irqsave(priv->register_lock, flags); outb_p(0, priv->card_base + PI_DREQ_MASK); rc = inb_p(priv->scc_data); outb(1, priv->card_base + PI_DREQ_MASK); - restore_flags(flags); + spin_unlock_irqrestore(priv->register_lock, flags); return rc; } } @@ -905,9 +908,8 @@ priv->tx_len[i] = skb->len-1; /* Clear interrupts while we touch our circular buffers */ - save_flags(flags); - cli(); + spin_lock_irqsave(&priv->ring_lock, flags); /* Move the ring buffer's head */ priv->tx_head = (i + 1) % NUM_TX_BUF; priv->tx_count++; @@ -928,7 +930,7 @@ } /* Turn interrupts back on and free buffer */ - restore_flags(flags); + spin_unlock_irqrestore(&priv->ring_lock, flags); dev_kfree_skb(skb); return 0; @@ -951,6 +953,7 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) { struct scc_info *info = dev_id; + spin_lock(info->priv[0].register_lock); /* At this point interrupts are enabled, and the interrupt under service is already acknowledged, but masked off. @@ -978,6 +981,7 @@ } } } else z8530_isr(info); + spin_unlock(info->priv[0].register_lock); } @@ -1002,7 +1006,7 @@ i++; } if (i < 0) { - printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is); + printk(KERN_ERR "dmascc: stuck in ISR with RR3=0x%02x.\n", is); } /* Ok, no interrupts pending from this 8530. The INT line should be inactive now. */ @@ -1099,11 +1103,9 @@ struct sk_buff *skb; unsigned char *data; - save_flags(flags); - cli(); - + spin_lock_irqsave(&priv->ring_lock, flags); while (priv->rx_count) { - restore_flags(flags); + spin_unlock_irqrestore(&priv->ring_lock, flags); cb = priv->rx_len[i]; /* Allocate buffer */ skb = dev_alloc_skb(cb+1); @@ -1123,14 +1125,12 @@ priv->stats.rx_packets++; priv->stats.rx_bytes += cb; } - save_flags(flags); - cli(); + spin_lock_irqsave(&priv->ring_lock, flags); /* Move tail */ priv->rx_tail = i = (i + 1) % NUM_RX_BUF; priv->rx_count--; } - - restore_flags(flags); + spin_unlock_irqrestore(&priv->ring_lock, flags); } @@ -1319,12 +1319,11 @@ else write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); /* Write first byte(s) */ - save_flags(flags); - cli(); + spin_lock_irqsave(priv->register_lock, flags); for (i = 0; i < n; i++) write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1); enable_dma(priv->param.dma); - restore_flags(flags); + spin_unlock_irqrestore(priv->register_lock, flags); } else { write_scc(priv, R15, TxUIE); write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); diff -Nru a/drivers/net/hamradio/soundmodem/Makefile b/drivers/net/hamradio/soundmodem/Makefile --- a/drivers/net/hamradio/soundmodem/Makefile Wed Nov 27 14:36:27 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,42 +0,0 @@ -# -# Makefile for the soundmodem device driver. -# - -obj-$(CONFIG_SOUNDMODEM) += soundmodem.o - -soundmodem-y := sm.o -soundmodem-$(CONFIG_SOUNDMODEM_SBC) += sm_sbc.o -soundmodem-$(CONFIG_SOUNDMODEM_WSS) += sm_wss.o -soundmodem-$(CONFIG_SOUNDMODEM_AFSK1200) += sm_afsk1200.o -soundmodem-$(CONFIG_SOUNDMODEM_AFSK2400_7) += sm_afsk2400_7.o -soundmodem-$(CONFIG_SOUNDMODEM_AFSK2400_8) += sm_afsk2400_8.o -soundmodem-$(CONFIG_SOUNDMODEM_AFSK2666) += sm_afsk2666.o -soundmodem-$(CONFIG_SOUNDMODEM_HAPN4800) += sm_hapn4800.o -soundmodem-$(CONFIG_SOUNDMODEM_PSK4800) += sm_psk4800.o -soundmodem-$(CONFIG_SOUNDMODEM_FSK9600) += sm_fsk9600.o -soundmodem-objs := $(soundmodem-y) - -host-progs := gentbl -HOST_LOADLIBES := -lm - -# Files generated that shall be removed upon make clean -clean-files := sm_tbl_afsk1200.h sm_tbl_afsk2400_7.h \ - sm_tbl_afsk2400_8.h sm_tbl_afsk2666.h \ - sm_tbl_psk4800.h sm_tbl_hapn4800.h \ - sm_tbl_fsk9600.h - -include $(TOPDIR)/Rules.make - -# Dependencies on generates files need to be listed explicitly - -$(obj)/sm_afsk1200.o: $(obj)/sm_tbl_afsk1200.h -$(obj)/sm_afsk2400_7.o: $(obj)/sm_tbl_afsk2400_7.h -$(obj)/sm_afsk2400_8.o: $(obj)/sm_tbl_afsk2400_8.h -$(obj)/sm_afsk2666.o: $(obj)/sm_tbl_afsk2666.h -$(obj)/sm_psk4800.o: $(obj)/sm_tbl_psk4800.h -$(obj)/sm_hapn4800.o: $(obj)/sm_tbl_hapn4800.h -$(obj)/sm_fsk9600.o: $(obj)/sm_tbl_fsk9600.h - -$(obj)/sm_tbl_%: $(obj)/gentbl - cd $(obj) && ./gentbl - diff -Nru a/drivers/net/hamradio/soundmodem/gentbl.c b/drivers/net/hamradio/soundmodem/gentbl.c --- a/drivers/net/hamradio/soundmodem/gentbl.c Wed Nov 27 14:36:29 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,689 +0,0 @@ -/*****************************************************************************/ - -/* - * gentbl.c -- soundcard radio modem driver table generator. - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include -#include -#include -#include - -/* -------------------------------------------------------------------- */ - -static void gentbl_offscostab(FILE *f, unsigned int nbits) -{ - int i; - - fprintf(f, "\n/*\n * small cosine table in U8 format\n */\n" - "#define OFFSCOSTABBITS %u\n" - "#define OFFSCOSTABSIZE (1<>%d)&0x%x]\n\n", - 16-nbits, (1<>%d)&0x%x]\n" - "#define SIN(x) COS((x)+0xc000)\n\n", 16-nbits, - (1< max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 3 || j < 255) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "fsk9600: txfilt4: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - min = max = 0; - memset(c, 0, sizeof(c)); -#if 0 - memcpy(c+2, fsk96_tx_coeff_5, sizeof(fsk96_tx_coeff_5)); -#else - for (i = 0; i < 36; i++) - c[4+i] = sinc(1.2*((i-17.5)/5.0))*hamming(i/35.0)/4.5; -#endif - fprintf(f, "static unsigned char fsk96_txfilt_5[] = {\n\t"); - for (i = 0; i < 5; i++) { - for (j = 0; j < 256; j++) { - for (k = 1, s = 0, l = i; k < 256; k <<= 1) { - if (j & k) { - for (m = 0; m < 5; m++, l++) - s += c[l]; - } else { - for (m = 0; m < 5; m++, l++) - s -= c[l]; - } - } - s *= 0.75; - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 4 || j < 255) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "fsk9600: txfilt5: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); -} - -/* -------------------------------------------------------------------- */ - -#define AFSK26_SAMPLERATE 16000 - -#define AFSK26_NUMCAR 2 -#define AFSK26_FIRSTCAR 2000 -#define AFSK26_MSK_LEN 6 -#define AFSK26_RXOVER 2 - -#define AFSK26_DEMCORRLEN (2*AFSK26_MSK_LEN) - -#define AFSK26_WINDOW(x) ((1-cos(2.0*M_PI*(x)))/2.0) - -#define AFSK26_AMPL(x) (((x)?1.0:0.7)) - -#undef AFSK26_AMPL -#define AFSK26_AMPL(x) 1 - -static void gentbl_afsk2666(FILE *f) -{ - int i, j, k, l, o, v, sumi, sumq; - float window[AFSK26_DEMCORRLEN*AFSK26_RXOVER]; - int cfreq[AFSK26_NUMCAR]; - - fprintf(f, "\n/*\n * afsk2666 specific tables\n */\n" - "#define AFSK26_DEMCORRLEN %d\n" - "#define AFSK26_SAMPLERATE %d\n\n", AFSK26_DEMCORRLEN, - AFSK26_SAMPLERATE); - fprintf(f, "static const unsigned int afsk26_carfreq[%d] = { ", - AFSK26_NUMCAR); - for (i = 0; i < AFSK26_NUMCAR; i++) { - cfreq[i] = 0x10000*AFSK26_FIRSTCAR/AFSK26_SAMPLERATE+ - 0x10000*i/AFSK26_MSK_LEN/2; - fprintf(f, "0x%x", cfreq[i]); - if (i < AFSK26_NUMCAR-1) - fprintf(f, ", "); - } - fprintf(f, " };\n\n"); - for (i = 0; i < AFSK26_DEMCORRLEN*AFSK26_RXOVER; i++) - window[i] = AFSK26_WINDOW(((float)i)/(AFSK26_DEMCORRLEN* - AFSK26_RXOVER)) * 127.0; - fprintf(f, "\nstatic const struct {\n\t" - "int i[%d];\n\tint q[%d];\n} afsk26_dem_tables[%d][%d] = {\n", - AFSK26_DEMCORRLEN, AFSK26_DEMCORRLEN, AFSK26_RXOVER, AFSK26_NUMCAR); - for (o = AFSK26_RXOVER-1; o >= 0; o--) { - fprintf(f, "\t{\n"); - for (i = 0; i < AFSK26_NUMCAR; i++) { - j = cfreq[i]; - fprintf(f, "\t\t{{ "); - for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumi = 0; l >= 0; - l--, k = (k+j)&0xffffu) { - sumi += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]* - cos(M_PI*k/32768.0)); - fprintf(f, "%6d%s", v, l ? ", " : " }, { "); - } - for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumq = 0; l >= 0; - l--, k = (k+j)&0xffffu) { - sumq += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]* - sin(M_PI*k/32768.0)); - fprintf(f, "%6d%s", v, l ? ", " : " }}"); - } - if (i < 1) - fprintf(f, ","); - fprintf(f, "\n#define AFSK26_DEM_SUM_I_%d_%d %d\n" - "#define AFSK26_DEM_SUM_Q_%d_%d %d\n", - AFSK26_RXOVER-1-o, i, sumi, AFSK26_RXOVER-1-o, i, sumq); - } - fprintf(f, "\t}%s\n", o ? "," : ""); - } - fprintf(f, "};\n\n"); -} - -/* -------------------------------------------------------------------- */ - -#define ATAN_TABLEN 1024 - -static void gentbl_atantab(FILE *f) -{ - int i; - short x; - - fprintf(f, "\n/*\n" - " * arctan table (indexed by i/q; should really be indexed by i/(i+q)\n" - " */\n""#define ATAN_TABLEN %d\n\n" - "static const unsigned short atan_tab[ATAN_TABLEN+2] = {", - ATAN_TABLEN); - for (i = 0; i <= ATAN_TABLEN; i++) { - if (!(i & 7)) - fprintf(f, "\n\t"); - x = atan(i / (float)ATAN_TABLEN) / M_PI * 0x8000; - fprintf(f, "%6d, ", x); - } - fprintf(f, "%6d\n};\n\n", x); - -} - -/* -------------------------------------------------------------------- */ - -#define PSK48_TXF_OVERSAMPLING 5 -#define PSK48_TXF_NUMSAMPLES 16 -#define PSK48_RXF_LEN 64 - -static const float psk48_tx_coeff[80] = { - -0.000379, -0.000640, -0.000000, 0.000772, - 0.000543, -0.000629, -0.001187, -0.000000, - 0.001634, 0.001183, -0.001382, -0.002603, - -0.000000, 0.003481, 0.002472, -0.002828, - -0.005215, -0.000000, 0.006705, 0.004678, - -0.005269, -0.009584, -0.000000, 0.012065, - 0.008360, -0.009375, -0.017028, -0.000000, - 0.021603, 0.015123, -0.017229, -0.032012, - -0.000000, 0.043774, 0.032544, -0.040365, - -0.084963, -0.000000, 0.201161, 0.374060, - 0.374060, 0.201161, -0.000000, -0.084963, - -0.040365, 0.032544, 0.043774, -0.000000, - -0.032012, -0.017229, 0.015123, 0.021603, - -0.000000, -0.017028, -0.009375, 0.008360, - 0.012065, -0.000000, -0.009584, -0.005269, - 0.004678, 0.006705, -0.000000, -0.005215, - -0.002828, 0.002472, 0.003481, -0.000000, - -0.002603, -0.001382, 0.001183, 0.001634, - -0.000000, -0.001187, -0.000629, 0.000543, - 0.000772, -0.000000, -0.000640, -0.000379 -}; - -static const float psk48_rx_coeff[PSK48_RXF_LEN] = { - -0.000219, 0.000360, 0.000873, 0.001080, - 0.000747, -0.000192, -0.001466, -0.002436, - -0.002328, -0.000699, 0.002101, 0.004809, - 0.005696, 0.003492, -0.001633, -0.007660, - -0.011316, -0.009627, -0.001780, 0.009712, - 0.019426, 0.021199, 0.011342, -0.008583, - -0.030955, -0.044093, -0.036634, -0.002651, - 0.054742, 0.123101, 0.184198, 0.220219, - 0.220219, 0.184198, 0.123101, 0.054742, - -0.002651, -0.036634, -0.044093, -0.030955, - -0.008583, 0.011342, 0.021199, 0.019426, - 0.009712, -0.001780, -0.009627, -0.011316, - -0.007660, -0.001633, 0.003492, 0.005696, - 0.004809, 0.002101, -0.000699, -0.002328, - -0.002436, -0.001466, -0.000192, 0.000747, - 0.001080, 0.000873, 0.000360, -0.000219 -}; - -static void gentbl_psk4800(FILE *f) -{ - int i, j, k; - short x; - - fprintf(f, "\n/*\n * psk4800 specific tables\n */\n" - "#define PSK48_TXF_OVERSAMPLING %d\n" - "#define PSK48_TXF_NUMSAMPLES %d\n\n" - "#define PSK48_SAMPLERATE 8000\n" - "#define PSK48_CAR_FREQ 2000\n" - "#define PSK48_PSK_LEN 5\n" - "#define PSK48_RXF_LEN %u\n" - "#define PSK48_PHASEINC (0x10000*PSK48_CAR_FREQ/PSK48_SAMPLERATE)\n" - "#define PSK48_SPHASEINC (0x10000/(2*PSK48_PSK_LEN))\n\n" - "static const short psk48_tx_table[PSK48_TXF_OVERSAMPLING*" - "PSK48_TXF_NUMSAMPLES*8*2] = {", - PSK48_TXF_OVERSAMPLING, PSK48_TXF_NUMSAMPLES, PSK48_RXF_LEN); - for (i = 0; i < PSK48_TXF_OVERSAMPLING; i++) { - for (j = 0; j < PSK48_TXF_NUMSAMPLES; j++) { - fprintf(f, "\n\t"); - for (k = 0; k < 8; k++) { - x = 32767.0 * cos(k*M_PI/4.0) * - psk48_tx_coeff[j * PSK48_TXF_OVERSAMPLING + i]; - fprintf(f, "%6d, ", x); - } - fprintf(f, "\n\t"); - for (k = 0; k < 8; k++) { - x = 32767.0 * sin(k*M_PI/4.0) * - psk48_tx_coeff[j * PSK48_TXF_OVERSAMPLING + i]; - fprintf(f, "%6d", x); - if (k != 7 || j != PSK48_TXF_NUMSAMPLES-1 || - i != PSK48_TXF_OVERSAMPLING-1) - fprintf(f, ", "); - } - } - } - fprintf(f, "\n};\n\n"); - - fprintf(f, "static const short psk48_rx_coeff[PSK48_RXF_LEN] = {\n\t"); - for (i = 0; i < PSK48_RXF_LEN; i++) { - fprintf(f, "%6d", (int)(psk48_rx_coeff[i]*32767.0)); - if (i < PSK48_RXF_LEN-1) - fprintf(f, ",%s", (i & 7) == 7 ? "\n\t" : ""); - } - fprintf(f, "\n};\n\n"); -} - -/* -------------------------------------------------------------------- */ - -static void gentbl_hapn4800(FILE *f) -{ - int i, j, k, l; - float s; - float c[44]; - float min, max; - - fprintf(f, "\n/*\n * hapn4800 specific tables\n */\n\n"); - /* - * firstly generate tables for the FM transmitter modulator - */ - min = max = 0; - memset(c, 0, sizeof(c)); - for (i = 0; i < 24; i++) - c[8+i] = sinc(1.5*((i-11.5)/8.0))*hamming(i/23.0)/2.4; - for (i = 0; i < 24; i++) - c[i] -= c[i+8]; - fprintf(f, "static unsigned char hapn48_txfilt_8[] = {\n\t"); - for (i = 0; i < 8; i++) { - for (j = 0; j < 16; j++) { - for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 8) { - if (j & k) - s += c[l]; - else - s -= c[l]; - } - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 7 || j < 15) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "hapn4800: txfilt8: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - min = max = 0; - memset(c, 0, sizeof(c)); - for (i = 0; i < 30; i++) - c[10+i] = sinc(1.5*((i-14.5)/10.0))*hamming(i/29.0)/2.4; - for (i = 0; i < 30; i++) - c[i] -= c[i+10]; - fprintf(f, "static unsigned char hapn48_txfilt_10[] = {\n\t"); - for (i = 0; i < 10; i++) { - for (j = 0; j < 16; j++) { - for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 10) { - if (j & k) - s += c[l]; - else - s -= c[l]; - } - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 9 || j < 15) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "hapn4800: txfilt10: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - /* - * secondly generate tables for the PM transmitter modulator - */ - min = max = 0; - memset(c, 0, sizeof(c)); - for (i = 0; i < 25; i++) - c[i] = sinc(1.4*((i-12.0)/8.0))*hamming(i/24.0)/6.3; - for (i = 0; i < 25; i++) - for (j = 1; j < 8; j++) - c[i] += c[i+j]; - fprintf(f, "static unsigned char hapn48_txfilt_pm8[] = {\n\t"); - for (i = 0; i < 8; i++) { - for (j = 0; j < 16; j++) { - for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 8) { - if (j & k) - s += c[l]; - else - s -= c[l]; - } - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 7 || j < 15) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "hapn4800: txfiltpm8: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - min = max = 0; - memset(c, 0, sizeof(c)); - for (i = 0; i < 31; i++) - c[10+i] = sinc(1.4*((i-15.0)/10.0))*hamming(i/30.0)/7.9; - for (i = 0; i < 31; i++) - for (j = 1; j < 10; j++) - c[i] += c[i+j]; - fprintf(f, "static unsigned char hapn48_txfilt_pm10[] = {\n\t"); - for (i = 0; i < 10; i++) { - for (j = 0; j < 16; j++) { - for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 10) { - if (j & k) - s += c[l]; - else - s -= c[l]; - } - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 9 || j < 15) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "hapn4800: txfiltpm10: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - -} - -/* -------------------------------------------------------------------- */ - -#define AFSK24_SAMPLERATE 16000 -#define AFSK24_CORRLEN 14 - -static void gentbl_afsk2400(FILE *f, float tcm3105clk) -{ - int i, sum, v; - - fprintf(f, "\n/*\n * afsk2400 specific tables (tcm3105 clk %7fHz)\n */\n" - "#define AFSK24_TX_FREQ_LO %d\n" - "#define AFSK24_TX_FREQ_HI %d\n" - "#define AFSK24_BITPLL_INC %d\n" - "#define AFSK24_SAMPLERATE %d\n\n", tcm3105clk, - (int)(tcm3105clk/3694.0), (int)(tcm3105clk/2015.0), - 0x10000*2400/AFSK24_SAMPLERATE, AFSK24_SAMPLERATE); - -#define ARGLO(x) 2.0*M_PI*(double)x*(tcm3105clk/3694.0)/(double)AFSK24_SAMPLERATE -#define ARGHI(x) 2.0*M_PI*(double)x*(tcm3105clk/2015.0)/(double)AFSK24_SAMPLERATE -#define WINDOW(x) hamming((float)(x)/(AFSK24_CORRLEN-1.0)) - - fprintf(f, "static const int afsk24_tx_lo_i[] = {\n\t"); - for(sum = i = 0; i < AFSK24_CORRLEN; i++) { - sum += (v = 127.0*cos(ARGLO(i))*WINDOW(i)); - fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' '); - } - fprintf(f, "\n};\n#define SUM_AFSK24_TX_LO_I %d\n\n" - "static const int afsk24_tx_lo_q[] = {\n\t", sum); - for(sum = i = 0; i < AFSK24_CORRLEN; i++) { - sum += (v = 127.0*sin(ARGLO(i))*WINDOW(i)); - fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' '); - } - fprintf(f, "\n};\n#define SUM_AFSK24_TX_LO_Q %d\n\n" - "static const int afsk24_tx_hi_i[] = {\n\t", sum); - for(sum = i = 0; i < AFSK24_CORRLEN; i++) { - sum += (v = 127.0*cos(ARGHI(i))*WINDOW(i)); - fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' '); - } - fprintf(f, "\n};\n#define SUM_AFSK24_TX_HI_I %d\n\n" - "static const int afsk24_tx_hi_q[] = {\n\t", sum); - for(sum = i = 0; i < AFSK24_CORRLEN; i++) { - sum += (v = 127.0*sin(ARGHI(i))*WINDOW(i)); - fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' '); - } - fprintf(f, "\n};\n#define SUM_AFSK24_TX_HI_Q %d\n\n", sum); -#undef ARGLO -#undef ARGHI -#undef WINDOW -} - -/* -------------------------------------------------------------------- */ - -static char *progname; - -static void gentbl_banner(FILE *f) -{ - fprintf(f, "/*\n * THIS FILE IS GENERATED AUTOMATICALLY BY %s, " - "DO NOT EDIT!\n */\n\n", progname); -} - -/* -------------------------------------------------------------------- */ - -int main(int argc, char *argv[]) -{ - FILE *f; - - progname = argv[0]; - if (!(f = fopen("sm_tbl_afsk1200.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_offscostab(f, 6); - gentbl_costab(f, 6); - gentbl_afsk1200(f); - fclose(f); - if (!(f = fopen("sm_tbl_afsk2666.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_offscostab(f, 6); - gentbl_costab(f, 6); - gentbl_afsk2666(f); - fclose(f); - if (!(f = fopen("sm_tbl_psk4800.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_psk4800(f); - gentbl_costab(f, 8); - gentbl_atantab(f); - fclose(f); - if (!(f = fopen("sm_tbl_hapn4800.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_hapn4800(f); - fclose(f); - if (!(f = fopen("sm_tbl_fsk9600.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_fsk9600(f); - fclose(f); - if (!(f = fopen("sm_tbl_afsk2400_8.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_offscostab(f, 6); - gentbl_costab(f, 6); - gentbl_afsk2400(f, 8000000); - fclose(f); - if (!(f = fopen("sm_tbl_afsk2400_7.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_offscostab(f, 6); - gentbl_costab(f, 6); - gentbl_afsk2400(f, 7372800); - fclose(f); - exit(0); -} - - -/* -------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm.c b/drivers/net/hamradio/soundmodem/sm.c --- a/drivers/net/hamradio/soundmodem/sm.c Wed Nov 27 14:36:31 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,759 +0,0 @@ -/*****************************************************************************/ - -/* - * sm.c -- soundcard radio modem driver. - * - * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - * - * Command line options (insmod command line) - * - * mode mode string; eg. "wss:afsk1200" - * iobase base address of the soundcard; common values are 0x220 for sbc, - * 0x530 for wss - * irq interrupt number; common values are 7 or 5 for sbc, 11 for wss - * dma dma number; common values are 0 or 1 - * - * - * History: - * 0.1 21.09.1996 Started - * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user) - * 0.4 21.01.1997 Separately compileable soundcard/modem modules - * 0.5 03.03.1997 fixed LPT probing (check_lpt result was interpreted the wrong way round) - * 0.6 16.04.1997 init code/data tagged - * 0.7 30.07.1997 fixed halfduplex interrupt handlers/hotfix for CS423X - * 0.8 14.04.1998 cleanups - * 0.9 03.08.1999 adapt to Linus' new __setup/__initcall - * use parport lowlevel drivers instead of directly writing to a parallel port - * removed some pre-2.2 kernel compatibility cruft - * 0.10 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts - * 0.11 12.02.2000 adapted to softnet driver interface - * 0.12 03.07.2000 fix interface name handling - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sm.h" - -/* --------------------------------------------------------------------- */ - -/*static*/ const char sm_drvname[] = "soundmodem"; -static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "soundmodem: version 0.12 compiled " __TIME__ " " __DATE__ "\n"; - -/* --------------------------------------------------------------------- */ - -/*static*/ const struct modem_tx_info *sm_modem_tx_table[] = { -#ifdef CONFIG_SOUNDMODEM_AFSK1200 - &sm_afsk1200_tx, -#endif /* CONFIG_SOUNDMODEM_AFSK1200 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2400_7 - &sm_afsk2400_7_tx, -#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2400_8 - &sm_afsk2400_8_tx, -#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2666 - &sm_afsk2666_tx, -#endif /* CONFIG_SOUNDMODEM_AFSK2666 */ -#ifdef CONFIG_SOUNDMODEM_PSK4800 - &sm_psk4800_tx, -#endif /* CONFIG_SOUNDMODEM_PSK4800 */ -#ifdef CONFIG_SOUNDMODEM_HAPN4800 - &sm_hapn4800_8_tx, - &sm_hapn4800_10_tx, - &sm_hapn4800_pm8_tx, - &sm_hapn4800_pm10_tx, -#endif /* CONFIG_SOUNDMODEM_HAPN4800 */ -#ifdef CONFIG_SOUNDMODEM_FSK9600 - &sm_fsk9600_4_tx, - &sm_fsk9600_5_tx, -#endif /* CONFIG_SOUNDMODEM_FSK9600 */ - NULL -}; - -/*static*/ const struct modem_rx_info *sm_modem_rx_table[] = { -#ifdef CONFIG_SOUNDMODEM_AFSK1200 - &sm_afsk1200_rx, -#endif /* CONFIG_SOUNDMODEM_AFSK1200 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2400_7 - &sm_afsk2400_7_rx, -#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2400_8 - &sm_afsk2400_8_rx, -#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2666 - &sm_afsk2666_rx, -#endif /* CONFIG_SOUNDMODEM_AFSK2666 */ -#ifdef CONFIG_SOUNDMODEM_PSK4800 - &sm_psk4800_rx, -#endif /* CONFIG_SOUNDMODEM_PSK4800 */ -#ifdef CONFIG_SOUNDMODEM_HAPN4800 - &sm_hapn4800_8_rx, - &sm_hapn4800_10_rx, - &sm_hapn4800_pm8_rx, - &sm_hapn4800_pm10_rx, -#endif /* CONFIG_SOUNDMODEM_HAPN4800 */ -#ifdef CONFIG_SOUNDMODEM_FSK9600 - &sm_fsk9600_4_rx, - &sm_fsk9600_5_rx, -#endif /* CONFIG_SOUNDMODEM_FSK9600 */ - NULL -}; - -static const struct hardware_info *sm_hardware_table[] = { -#ifdef CONFIG_SOUNDMODEM_SBC - &sm_hw_sbc, - &sm_hw_sbcfdx, -#endif /* CONFIG_SOUNDMODEM_SBC */ -#ifdef CONFIG_SOUNDMODEM_WSS - &sm_hw_wss, - &sm_hw_wssfdx, -#endif /* CONFIG_SOUNDMODEM_WSS */ - NULL -}; - -/* --------------------------------------------------------------------- */ - -#define NR_PORTS 4 - -static struct net_device sm_device[NR_PORTS]; - -/* --------------------------------------------------------------------- */ - -#define UART_RBR(iobase) (iobase+0) -#define UART_THR(iobase) (iobase+0) -#define UART_IER(iobase) (iobase+1) -#define UART_IIR(iobase) (iobase+2) -#define UART_FCR(iobase) (iobase+2) -#define UART_LCR(iobase) (iobase+3) -#define UART_MCR(iobase) (iobase+4) -#define UART_LSR(iobase) (iobase+5) -#define UART_MSR(iobase) (iobase+6) -#define UART_SCR(iobase) (iobase+7) -#define UART_DLL(iobase) (iobase+0) -#define UART_DLM(iobase) (iobase+1) - -#define SER_EXTENT 8 - -#define MIDI_DATA(iobase) (iobase) -#define MIDI_STATUS(iobase) (iobase+1) -#define MIDI_READ_FULL 0x80 /* attention: negative logic!! */ -#define MIDI_WRITE_EMPTY 0x40 /* attention: negative logic!! */ - -#define MIDI_EXTENT 2 - -/* ---------------------------------------------------------------------- */ - -#define PARAM_TXDELAY 1 -#define PARAM_PERSIST 2 -#define PARAM_SLOTTIME 3 -#define PARAM_TXTAIL 4 -#define PARAM_FULLDUP 5 -#define PARAM_HARDWARE 6 -#define PARAM_RETURN 255 - -#define SP_SER 1 -#define SP_PAR 2 -#define SP_MIDI 4 - -/* - * ===================== port checking routines ======================== - */ - -enum uart { c_uart_unknown, c_uart_8250, - c_uart_16450, c_uart_16550, c_uart_16550A}; -static const char *uart_str[] = - { "unknown", "8250", "16450", "16550", "16550A" }; - -static enum uart check_uart(unsigned int iobase) -{ - unsigned char b1,b2,b3; - enum uart u; - enum uart uart_tab[] = - { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A }; - - if (iobase <= 0 || iobase > 0x1000-SER_EXTENT) - return c_uart_unknown; - if (check_region(iobase, SER_EXTENT)) - return c_uart_unknown; - b1 = inb(UART_MCR(iobase)); - outb(b1 | 0x10, UART_MCR(iobase)); /* loopback mode */ - b2 = inb(UART_MSR(iobase)); - outb(0x1a, UART_MCR(iobase)); - b3 = inb(UART_MSR(iobase)) & 0xf0; - outb(b1, UART_MCR(iobase)); /* restore old values */ - outb(b2, UART_MSR(iobase)); - if (b3 != 0x90) - return c_uart_unknown; - inb(UART_RBR(iobase)); - inb(UART_RBR(iobase)); - outb(0x01, UART_FCR(iobase)); /* enable FIFOs */ - u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3]; - if (u == c_uart_16450) { - outb(0x5a, UART_SCR(iobase)); - b1 = inb(UART_SCR(iobase)); - outb(0xa5, UART_SCR(iobase)); - b2 = inb(UART_SCR(iobase)); - if ((b1 != 0x5a) || (b2 != 0xa5)) - u = c_uart_8250; - } - return u; -} - -/* --------------------------------------------------------------------- */ - -static int check_midi(unsigned int iobase) -{ - unsigned long timeout; - unsigned long flags; - unsigned char b; - - if (iobase <= 0 || iobase > 0x1000-MIDI_EXTENT) - return 0; - if (check_region(iobase, MIDI_EXTENT)) - return 0; - timeout = jiffies + (HZ / 100); - while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY) - if ((signed)(jiffies - timeout) > 0) - return 0; - save_flags(flags); - cli(); - outb(0xff, MIDI_DATA(iobase)); - b = inb(MIDI_STATUS(iobase)); - restore_flags(flags); - if (!(b & MIDI_WRITE_EMPTY)) - return 0; - while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY) - if ((signed)(jiffies - timeout) > 0) - return 0; - return 1; -} - -/* --------------------------------------------------------------------- */ - -void sm_output_status(struct sm_state *sm) -{ - int invert_dcd = 0; - int invert_ptt = 0; - - int ptt = /*hdlcdrv_ptt(&sm->hdrv)*/(sm->dma.ptt_cnt > 0) ^ invert_ptt; - int dcd = (!!sm->hdrv.hdlcrx.dcd) ^ invert_dcd; - - if (sm->hdrv.ptt_out.flags & SP_SER) { - outb(dcd | (ptt << 1), UART_MCR(sm->hdrv.ptt_out.seriobase)); - outb(0x40 & (-ptt), UART_LCR(sm->hdrv.ptt_out.seriobase)); - } - if (sm->hdrv.ptt_out.flags & SP_PAR && sm->pardev && sm->pardev->port) - parport_write_data(sm->pardev->port, ptt | (dcd << 1)); - if (sm->hdrv.ptt_out.flags & SP_MIDI && hdlcdrv_ptt(&sm->hdrv)) - outb(0, MIDI_DATA(sm->hdrv.ptt_out.midiiobase)); -} - -/* --------------------------------------------------------------------- */ - -static void sm_output_open(struct sm_state *sm, const char *ifname) -{ - enum uart u = c_uart_unknown; - struct parport *pp = NULL; - - sm->hdrv.ptt_out.flags = 0; - if (sm->hdrv.ptt_out.seriobase > 0 && - sm->hdrv.ptt_out.seriobase <= 0x1000-SER_EXTENT && - ((u = check_uart(sm->hdrv.ptt_out.seriobase))) != c_uart_unknown) { - sm->hdrv.ptt_out.flags |= SP_SER; - request_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT, "sm ser ptt"); - outb(0, UART_IER(sm->hdrv.ptt_out.seriobase)); - /* 5 bits, 1 stop, no parity, no break, Div latch access */ - outb(0x80, UART_LCR(sm->hdrv.ptt_out.seriobase)); - outb(0, UART_DLM(sm->hdrv.ptt_out.seriobase)); - outb(1, UART_DLL(sm->hdrv.ptt_out.seriobase)); /* as fast as possible */ - /* LCR and MCR set by output_status */ - } - sm->pardev = NULL; - if (sm->hdrv.ptt_out.pariobase > 0) { - pp = parport_enumerate(); - while (pp && pp->base != sm->hdrv.ptt_out.pariobase) - pp = pp->next; - if (!pp) - printk(KERN_WARNING "%s: parport at address 0x%x not found\n", sm_drvname, sm->hdrv.ptt_out.pariobase); - else if ((~pp->modes) & (PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) - printk(KERN_WARNING "%s: parport at address 0x%x cannot be used\n", sm_drvname, sm->hdrv.ptt_out.pariobase); - else { - sm->pardev = parport_register_device(pp, ifname, NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); - if (!sm->pardev) { - pp = NULL; - printk(KERN_WARNING "%s: cannot register parport device (address 0x%x)\n", sm_drvname, sm->hdrv.ptt_out.pariobase); - } else { - if (parport_claim(sm->pardev)) { - parport_unregister_device(sm->pardev); - sm->pardev = NULL; - printk(KERN_WARNING "%s: cannot claim parport at address 0x%x\n", sm_drvname, sm->hdrv.ptt_out.pariobase); - } else - sm->hdrv.ptt_out.flags |= SP_PAR; - } - } - } - if (sm->hdrv.ptt_out.midiiobase > 0 && - sm->hdrv.ptt_out.midiiobase <= 0x1000-MIDI_EXTENT && - check_midi(sm->hdrv.ptt_out.midiiobase)) { - sm->hdrv.ptt_out.flags |= SP_MIDI; - request_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT, - "sm midi ptt"); - } - sm_output_status(sm); - - printk(KERN_INFO "%s: ptt output:", sm_drvname); - if (sm->hdrv.ptt_out.flags & SP_SER) - printk(" serial interface at 0x%x, uart %s", sm->hdrv.ptt_out.seriobase, - uart_str[u]); - if (sm->hdrv.ptt_out.flags & SP_PAR) - printk(" parallel interface at 0x%x", sm->hdrv.ptt_out.pariobase); - if (sm->hdrv.ptt_out.flags & SP_MIDI) - printk(" mpu401 (midi) interface at 0x%x", sm->hdrv.ptt_out.midiiobase); - if (!sm->hdrv.ptt_out.flags) - printk(" none"); - printk("\n"); -} - -/* --------------------------------------------------------------------- */ - -static void sm_output_close(struct sm_state *sm) -{ - /* release regions used for PTT output */ - sm->hdrv.hdlctx.ptt = sm->hdrv.hdlctx.calibrate = 0; - sm_output_status(sm); - if (sm->hdrv.ptt_out.flags & SP_SER) - release_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT); - if (sm->hdrv.ptt_out.flags & SP_PAR && sm->pardev) { - parport_release(sm->pardev); - parport_unregister_device(sm->pardev); - } - if (sm->hdrv.ptt_out.flags & SP_MIDI) - release_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT); - sm->hdrv.ptt_out.flags = 0; -} - -/* --------------------------------------------------------------------- */ - -static int sm_open(struct net_device *dev); -static int sm_close(struct net_device *dev); -static int sm_ioctl(struct net_device *dev, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd); - -/* --------------------------------------------------------------------- */ - -static const struct hdlcdrv_ops sm_ops = { - sm_drvname, sm_drvinfo, sm_open, sm_close, sm_ioctl -}; - -/* --------------------------------------------------------------------- */ - -static int sm_open(struct net_device *dev) -{ - struct sm_state *sm; - int err; - - if (!dev || !dev->priv || - ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) { - printk(KERN_ERR "sm_open: invalid device struct\n"); - return -EINVAL; - } - sm = (struct sm_state *)dev->priv; - - if (!sm->mode_tx || !sm->mode_rx || !sm->hwdrv || !sm->hwdrv->open) - return -ENODEV; - sm->hdrv.par.bitrate = sm->mode_rx->bitrate; - err = sm->hwdrv->open(dev, sm); - if (err) - return err; - sm_output_open(sm, dev->name); - MOD_INC_USE_COUNT; - printk(KERN_INFO "%s: %s mode %s.%s at iobase 0x%lx irq %u dma %u dma2 %u\n", - sm_drvname, sm->hwdrv->hw_name, sm->mode_tx->name, - sm->mode_rx->name, dev->base_addr, dev->irq, dev->dma, sm->hdrv.ptt_out.dma2); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sm_close(struct net_device *dev) -{ - struct sm_state *sm; - int err = -ENODEV; - - if (!dev || !dev->priv || - ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) { - printk(KERN_ERR "sm_close: invalid device struct\n"); - return -EINVAL; - } - sm = (struct sm_state *)dev->priv; - - - if (sm->hwdrv && sm->hwdrv->close) - err = sm->hwdrv && sm->hwdrv->close(dev, sm); - sm_output_close(sm); - MOD_DEC_USE_COUNT; - printk(KERN_INFO "%s: close %s at iobase 0x%lx irq %u dma %u\n", - sm_drvname, sm->hwdrv->hw_name, dev->base_addr, dev->irq, dev->dma); - return err; -} - -/* --------------------------------------------------------------------- */ - -static int sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, ':'); - const struct hardware_info **hwp = sm_hardware_table; - - if (!cp) - cp = mode; - else { - *cp++ = '\0'; - while (hwp && (*hwp) && (*hwp)->hw_name && strcmp((*hwp)->hw_name, mode)) - hwp++; - if (!hwp || !*hwp || !(*hwp)->hw_name) - return -EINVAL; - if ((*hwp)->loc_storage > sizeof(sm->hw)) { - printk(KERN_ERR "%s: insufficient storage for hw driver %s (%d)\n", - sm_drvname, (*hwp)->hw_name, (*hwp)->loc_storage); - return -EINVAL; - } - sm->hwdrv = *hwp; - } - if (!*cp) - return 0; - if (sm->hwdrv && sm->hwdrv->sethw) - return sm->hwdrv->sethw(dev, sm, cp); - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int sm_ioctl(struct net_device *dev, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - struct sm_state *sm; - struct sm_ioctl bi; - unsigned long flags; - unsigned int newdiagmode; - unsigned int newdiagflags; - char *cp; - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp = sm_modem_rx_table; - const struct hardware_info **hwp = sm_hardware_table; - - if (!dev || !dev->priv || - ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) { - printk(KERN_ERR "sm_ioctl: invalid device struct\n"); - return -EINVAL; - } - sm = (struct sm_state *)dev->priv; - - if (cmd != SIOCDEVPRIVATE) { - if (!sm->hwdrv || !sm->hwdrv->ioctl) - return sm->hwdrv->ioctl(dev, sm, ifr, hi, cmd); - return -ENOIOCTLCMD; - } - switch (hi->cmd) { - default: - if (sm->hwdrv && sm->hwdrv->ioctl) - return sm->hwdrv->ioctl(dev, sm, ifr, hi, cmd); - return -ENOIOCTLCMD; - - case HDLCDRVCTL_GETMODE: - cp = hi->data.modename; - if (sm->hwdrv && sm->hwdrv->hw_name) - cp += sprintf(cp, "%s:", sm->hwdrv->hw_name); - else - cp += sprintf(cp, ":"); - if (sm->mode_tx && sm->mode_tx->name) - cp += sprintf(cp, "%s", sm->mode_tx->name); - else - cp += sprintf(cp, ""); - if (!sm->mode_rx || !sm->mode_rx || - strcmp(sm->mode_rx->name, sm->mode_tx->name)) { - if (sm->mode_rx && sm->mode_rx->name) - cp += sprintf(cp, ",%s", sm->mode_rx->name); - else - cp += sprintf(cp, ","); - } - if (copy_to_user(ifr->ifr_data, hi, sizeof(*hi))) - return -EFAULT; - return 0; - - case HDLCDRVCTL_SETMODE: - if (netif_running(dev) || !capable(CAP_NET_ADMIN)) - return -EACCES; - hi->data.modename[sizeof(hi->data.modename)-1] = '\0'; - return sethw(dev, sm, hi->data.modename); - - case HDLCDRVCTL_MODELIST: - cp = hi->data.modename; - while (*hwp) { - if ((*hwp)->hw_name) - cp += sprintf(cp, "%s:,", (*hwp)->hw_name); - hwp++; - } - while (*mtp) { - if ((*mtp)->name) - cp += sprintf(cp, ">%s,", (*mtp)->name); - mtp++; - } - while (*mrp) { - if ((*mrp)->name) - cp += sprintf(cp, "<%s,", (*mrp)->name); - mrp++; - } - cp[-1] = '\0'; - if (copy_to_user(ifr->ifr_data, hi, sizeof(*hi))) - return -EFAULT; - return 0; - -#ifdef SM_DEBUG - case SMCTL_GETDEBUG: - if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi))) - return -EFAULT; - bi.data.dbg.int_rate = sm->debug_vals.last_intcnt; - bi.data.dbg.mod_cycles = sm->debug_vals.mod_cyc; - bi.data.dbg.demod_cycles = sm->debug_vals.demod_cyc; - bi.data.dbg.dma_residue = sm->debug_vals.dma_residue; - sm->debug_vals.mod_cyc = sm->debug_vals.demod_cyc = - sm->debug_vals.dma_residue = 0; - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; -#endif /* SM_DEBUG */ - - case SMCTL_DIAGNOSE: - if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi))) - return -EFAULT; - newdiagmode = bi.data.diag.mode; - newdiagflags = bi.data.diag.flags; - if (newdiagmode > SM_DIAGMODE_CONSTELLATION) - return -EINVAL; - bi.data.diag.mode = sm->diag.mode; - bi.data.diag.flags = sm->diag.flags; - bi.data.diag.samplesperbit = sm->mode_rx->sperbit; - if (sm->diag.mode != newdiagmode) { - save_flags(flags); - cli(); - sm->diag.ptr = -1; - sm->diag.flags = newdiagflags & ~SM_DIAGFLAG_VALID; - sm->diag.mode = newdiagmode; - restore_flags(flags); - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } - if (sm->diag.ptr < 0 || sm->diag.mode == SM_DIAGMODE_OFF) { - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } - if (bi.data.diag.datalen > DIAGDATALEN) - bi.data.diag.datalen = DIAGDATALEN; - if (sm->diag.ptr < bi.data.diag.datalen) { - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } - if (copy_to_user(bi.data.diag.data, sm->diag.data, - bi.data.diag.datalen * sizeof(short))) - return -EFAULT; - bi.data.diag.flags |= SM_DIAGFLAG_VALID; - save_flags(flags); - cli(); - sm->diag.ptr = -1; - sm->diag.flags = newdiagflags & ~SM_DIAGFLAG_VALID; - sm->diag.mode = newdiagmode; - restore_flags(flags); - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } -} - -/* --------------------------------------------------------------------- */ - -/* - * command line settable parameters - */ -static char *mode[NR_PORTS] = { [0 ... NR_PORTS-1] = NULL }; -static int iobase[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; -static int irq[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; -static int dma[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; -static int dma2[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; -static int serio[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 }; -static int pario[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 }; -static int midiio[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 }; - -MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); -MODULE_PARM_DESC(mode, "soundmodem operating mode; eg. sbc:afsk1200 or wss:fsk9600"); -MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(iobase, "soundmodem base address"); -MODULE_PARM(irq, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(irq, "soundmodem interrupt"); -MODULE_PARM(dma, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(dma, "soundmodem dma channel"); -MODULE_PARM(dma2, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(dma2, "soundmodem 2nd dma channel; full duplex only"); -MODULE_PARM(serio, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(serio, "soundmodem PTT output on serial port"); -MODULE_PARM(pario, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(pario, "soundmodem PTT output on parallel port"); -MODULE_PARM(midiio, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(midiio, "soundmodem PTT output on midi port"); - -MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); -MODULE_DESCRIPTION("Soundcard amateur radio modem driver"); - -/* --------------------------------------------------------------------- */ - -static int __init init_soundmodem(void) -{ - int i, j, found = 0; - char set_hw = 1; - struct sm_state *sm; - - printk(sm_drvinfo); - /* - * register net devices - */ - for (i = 0; i < NR_PORTS; i++) { - struct net_device *dev = sm_device+i; - char ifname[IFNAMSIZ]; - - sprintf(ifname, "sm%d", i); - if (!mode[i]) - set_hw = 0; - else { - if (!strncmp(mode[i], "sbc", 3)) { - if (iobase[i] == -1) - iobase[i] = 0x220; - if (irq[i] == -1) - irq[i] = 5; - if (dma[i] == -1) - dma[i] = 1; - } else { - if (iobase[i] == -1) - iobase[i] = 0x530; - if (irq[i] == -1) - irq[i] = 11; - if (dma[i] == -1) - dma[i] = 1; - } - } - if (!set_hw) - iobase[i] = irq[i] = 0; - j = hdlcdrv_register_hdlcdrv(dev, &sm_ops, sizeof(struct sm_state), ifname, iobase[i], irq[i], dma[i]); - if (!j) { - sm = (struct sm_state *)dev->priv; - sm->hdrv.ptt_out.dma2 = dma2[i]; - sm->hdrv.ptt_out.seriobase = serio[i]; - sm->hdrv.ptt_out.pariobase = pario[i]; - sm->hdrv.ptt_out.midiiobase = midiio[i]; - if (set_hw && sethw(dev, sm, mode[i])) - set_hw = 0; - found++; - } else { - printk(KERN_WARNING "%s: cannot register net device\n", sm_drvname); - } - } - if (!found) - return -ENXIO; - return 0; -} - -static void __exit cleanup_soundmodem(void) -{ - int i; - - printk(KERN_INFO "sm: cleanup_module called\n"); - - for(i = 0; i < NR_PORTS; i++) { - struct net_device *dev = sm_device+i; - struct sm_state *sm = (struct sm_state *)dev->priv; - - if (sm) { - if (sm->hdrv.magic != HDLCDRV_MAGIC) - printk(KERN_ERR "sm: invalid magic in " - "cleanup_module\n"); - else - hdlcdrv_unregister_hdlcdrv(dev); - } - } -} - -module_init(init_soundmodem); -module_exit(cleanup_soundmodem); - -/* --------------------------------------------------------------------- */ - -#ifndef MODULE - -/* - * format: soundmodem=io,irq,dma[,dma2[,serio[,pario]]],mode - * mode: hw:modem - * hw: sbc, wss, wssfdx - * modem: afsk1200, fsk9600 - */ - -static int __init sm_setup(char *str) -{ - static unsigned nr_dev; - int ints[8]; - - if (nr_dev >= NR_PORTS) - return 0; - str = get_options(str, 8, ints); - mode[nr_dev] = str; - if (ints[0] >= 1) - iobase[nr_dev] = ints[1]; - if (ints[0] >= 2) - irq[nr_dev] = ints[2]; - if (ints[0] >= 3) - dma[nr_dev] = ints[3]; - if (ints[0] >= 4) - dma2[nr_dev] = ints[4]; - if (ints[0] >= 5) - serio[nr_dev] = ints[5]; - if (ints[0] >= 6) - pario[nr_dev] = ints[6]; - if (ints[0] >= 7) - midiio[nr_dev] = ints[7]; - nr_dev++; - return 1; -} - -__setup("soundmodem=", sm_setup); - -#endif /* MODULE */ -/* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm.h b/drivers/net/hamradio/soundmodem/sm.h --- a/drivers/net/hamradio/soundmodem/sm.h Wed Nov 27 14:36:27 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,383 +0,0 @@ -/*****************************************************************************/ - -/* - * sm.h -- soundcard radio modem driver internal header. - * - * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#ifndef _SM_H -#define _SM_H - -/* ---------------------------------------------------------------------- */ - -#include -#include -#include -#include -#include - -#define SM_DEBUG - -/* ---------------------------------------------------------------------- */ -/* - * Information that need to be kept for each board. - */ - -struct sm_state { - struct hdlcdrv_state hdrv; - - const struct modem_tx_info *mode_tx; - const struct modem_rx_info *mode_rx; - - const struct hardware_info *hwdrv; - - struct pardevice *pardev; - - /* - * Hardware (soundcard) access routines state - */ - struct { - void *ibuf; - unsigned int ifragsz; - unsigned int ifragptr; - unsigned int i16bit; - void *obuf; - unsigned int ofragsz; - unsigned int ofragptr; - unsigned int o16bit; - int ptt_cnt; - } dma; - - union { - long hw[32/sizeof(long)]; - } hw; - - /* - * state of the modem code - */ - union { - long m[48/sizeof(long)]; - } m; - union { - long d[256/sizeof(long)]; - } d; - -#define DIAGDATALEN 64 - struct diag_data { - unsigned int mode; - unsigned int flags; - volatile int ptr; - short data[DIAGDATALEN]; - } diag; - - -#ifdef SM_DEBUG - struct debug_vals { - unsigned long last_jiffies; - unsigned cur_intcnt; - unsigned last_intcnt; - unsigned mod_cyc; - unsigned demod_cyc; - unsigned dma_residue; - } debug_vals; -#endif /* SM_DEBUG */ -}; - -/* ---------------------------------------------------------------------- */ -/* - * Mode definition structure - */ - -struct modem_tx_info { - const char *name; - unsigned int loc_storage; - int srate; - int bitrate; - void (*modulator_u8)(struct sm_state *, unsigned char *, unsigned int); - void (*modulator_s16)(struct sm_state *, short *, unsigned int); - void (*init)(struct sm_state *); -}; - -struct modem_rx_info { - const char *name; - unsigned int loc_storage; - int srate; - int bitrate; - unsigned int overlap; - unsigned int sperbit; - void (*demodulator_u8)(struct sm_state *, const unsigned char *, unsigned int); - void (*demodulator_s16)(struct sm_state *, const short *, unsigned int); - void (*init)(struct sm_state *); -}; - -/* ---------------------------------------------------------------------- */ -/* - * Soundcard driver definition structure - */ - -struct hardware_info { - char *hw_name; /* used for request_{region,irq,dma} */ - unsigned int loc_storage; - /* - * mode specific open/close - */ - int (*open)(struct net_device *, struct sm_state *); - int (*close)(struct net_device *, struct sm_state *); - int (*ioctl)(struct net_device *, struct sm_state *, struct ifreq *, - struct hdlcdrv_ioctl *, int); - int (*sethw)(struct net_device *, struct sm_state *, char *); -}; - -/* --------------------------------------------------------------------- */ - -extern const char sm_drvname[]; -extern const char sm_drvinfo[]; - -/* --------------------------------------------------------------------- */ -/* - * ===================== diagnostics stuff =============================== - */ - -static inline void diag_trigger(struct sm_state *sm) -{ - if (sm->diag.ptr < 0) - if (!(sm->diag.flags & SM_DIAGFLAG_DCDGATE) || sm->hdrv.hdlcrx.dcd) - sm->diag.ptr = 0; -} - -/* --------------------------------------------------------------------- */ - -#define SHRT_MAX ((short)(((unsigned short)(~0U))>>1)) -#define SHRT_MIN (-SHRT_MAX-1) - -static inline void diag_add(struct sm_state *sm, int valinp, int valdemod) -{ - int val; - - if ((sm->diag.mode != SM_DIAGMODE_INPUT && - sm->diag.mode != SM_DIAGMODE_DEMOD) || - sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0) - return; - val = (sm->diag.mode == SM_DIAGMODE_DEMOD) ? valdemod : valinp; - /* clip */ - if (val > SHRT_MAX) - val = SHRT_MAX; - if (val < SHRT_MIN) - val = SHRT_MIN; - sm->diag.data[sm->diag.ptr++] = val; -} - -/* --------------------------------------------------------------------- */ - -static inline void diag_add_one(struct sm_state *sm, int val) -{ - if ((sm->diag.mode != SM_DIAGMODE_INPUT && - sm->diag.mode != SM_DIAGMODE_DEMOD) || - sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0) - return; - /* clip */ - if (val > SHRT_MAX) - val = SHRT_MAX; - if (val < SHRT_MIN) - val = SHRT_MIN; - sm->diag.data[sm->diag.ptr++] = val; -} - -/* --------------------------------------------------------------------- */ - -static inline void diag_add_constellation(struct sm_state *sm, int vali, int valq) -{ - if ((sm->diag.mode != SM_DIAGMODE_CONSTELLATION) || - sm->diag.ptr >= DIAGDATALEN-1 || sm->diag.ptr < 0) - return; - /* clip */ - if (vali > SHRT_MAX) - vali = SHRT_MAX; - if (vali < SHRT_MIN) - vali = SHRT_MIN; - if (valq > SHRT_MAX) - valq = SHRT_MAX; - if (valq < SHRT_MIN) - valq = SHRT_MIN; - sm->diag.data[sm->diag.ptr++] = vali; - sm->diag.data[sm->diag.ptr++] = valq; -} - -/* --------------------------------------------------------------------- */ -/* - * ===================== utility functions =============================== - */ - -#if 0 -static inline unsigned int hweight32(unsigned int w) - __attribute__ ((unused)); -static inline unsigned int hweight16(unsigned short w) - __attribute__ ((unused)); -static inline unsigned int hweight8(unsigned char w) - __attribute__ ((unused)); - -static inline unsigned int hweight32(unsigned int w) -{ - unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); - res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); - return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); -} - -static inline unsigned int hweight16(unsigned short w) -{ - unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555); - res = (res & 0x3333) + ((res >> 2) & 0x3333); - res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); - return (res & 0x00FF) + ((res >> 8) & 0x00FF); -} - -static inline unsigned int hweight8(unsigned char w) -{ - unsigned short res = (w & 0x55) + ((w >> 1) & 0x55); - res = (res & 0x33) + ((res >> 2) & 0x33); - return (res & 0x0F) + ((res >> 4) & 0x0F); -} - -#endif - -static inline unsigned int gcd(unsigned int x, unsigned int y) - __attribute__ ((unused)); -static inline unsigned int lcm(unsigned int x, unsigned int y) - __attribute__ ((unused)); - -static inline unsigned int gcd(unsigned int x, unsigned int y) -{ - for (;;) { - if (!x) - return y; - if (!y) - return x; - if (x > y) - x %= y; - else - y %= x; - } -} - -static inline unsigned int lcm(unsigned int x, unsigned int y) -{ - return x * y / gcd(x, y); -} - -/* --------------------------------------------------------------------- */ -/* - * ===================== profiling ======================================= - */ - - -#ifdef __i386__ - -#include - -/* - * only do 32bit cycle counter arithmetic; we hope we won't overflow. - * in fact, overflowing modems would require over 2THz CPU clock speeds :-) - */ - -#define time_exec(var,cmd) \ -({ \ - if (cpu_has_tsc) { \ - unsigned int cnt1, cnt2; \ - rdtscl(cnt1); \ - cmd; \ - rdtscl(cnt2); \ - var = cnt2-cnt1; \ - } else { \ - cmd; \ - } \ -}) - -#else /* __i386__ */ - -#define time_exec(var,cmd) cmd - -#endif /* __i386__ */ - -/* --------------------------------------------------------------------- */ - -extern const struct modem_tx_info sm_afsk1200_tx; -extern const struct modem_tx_info sm_afsk2400_7_tx; -extern const struct modem_tx_info sm_afsk2400_8_tx; -extern const struct modem_tx_info sm_afsk2666_tx; -extern const struct modem_tx_info sm_psk4800_tx; -extern const struct modem_tx_info sm_hapn4800_8_tx; -extern const struct modem_tx_info sm_hapn4800_10_tx; -extern const struct modem_tx_info sm_hapn4800_pm8_tx; -extern const struct modem_tx_info sm_hapn4800_pm10_tx; -extern const struct modem_tx_info sm_fsk9600_4_tx; -extern const struct modem_tx_info sm_fsk9600_5_tx; - -extern const struct modem_rx_info sm_afsk1200_rx; -extern const struct modem_rx_info sm_afsk2400_7_rx; -extern const struct modem_rx_info sm_afsk2400_8_rx; -extern const struct modem_rx_info sm_afsk2666_rx; -extern const struct modem_rx_info sm_psk4800_rx; -extern const struct modem_rx_info sm_hapn4800_8_rx; -extern const struct modem_rx_info sm_hapn4800_10_rx; -extern const struct modem_rx_info sm_hapn4800_pm8_rx; -extern const struct modem_rx_info sm_hapn4800_pm10_rx; -extern const struct modem_rx_info sm_fsk9600_4_rx; -extern const struct modem_rx_info sm_fsk9600_5_rx; - -extern const struct hardware_info sm_hw_sbc; -extern const struct hardware_info sm_hw_sbcfdx; -extern const struct hardware_info sm_hw_wss; -extern const struct hardware_info sm_hw_wssfdx; - -extern const struct modem_tx_info *sm_modem_tx_table[]; -extern const struct modem_rx_info *sm_modem_rx_table[]; -extern const struct hardware_info *sm_hardware_table[]; - -/* --------------------------------------------------------------------- */ - -void sm_output_status(struct sm_state *sm); -/*void sm_output_open(struct sm_state *sm);*/ -/*void sm_output_close(struct sm_state *sm);*/ - -/* --------------------------------------------------------------------- */ - -extern void inline sm_int_freq(struct sm_state *sm) -{ -#ifdef SM_DEBUG - unsigned long cur_jiffies = jiffies; - /* - * measure the interrupt frequency - */ - sm->debug_vals.cur_intcnt++; - if ((cur_jiffies - sm->debug_vals.last_jiffies) >= HZ) { - sm->debug_vals.last_jiffies = cur_jiffies; - sm->debug_vals.last_intcnt = sm->debug_vals.cur_intcnt; - sm->debug_vals.cur_intcnt = 0; - } -#endif /* SM_DEBUG */ -} - -/* --------------------------------------------------------------------- */ -#endif /* _SM_H */ diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk1200.c b/drivers/net/hamradio/soundmodem/sm_afsk1200.c --- a/drivers/net/hamradio/soundmodem/sm_afsk1200.c Wed Nov 27 14:36:32 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,272 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_afsk1200.c -- soundcard radio modem driver, 1200 baud AFSK modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include "sm.h" -#include "sm_tbl_afsk1200.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_afsk12 { - unsigned int shreg; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; - unsigned char last_rxbit; -}; - -struct mod_state_afsk12 { - unsigned int shreg; - unsigned char tx_bit; - unsigned int bit_pll; - unsigned int dds_inc; - unsigned int txphase; -}; - -/* --------------------------------------------------------------------- */ - -static const int dds_inc[2] = { - AFSK12_TX_FREQ_LO*0x10000/AFSK12_SAMPLE_RATE, - AFSK12_TX_FREQ_HI*0x10000/AFSK12_SAMPLE_RATE -}; - -static void modulator_1200_u8(struct sm_state *sm, unsigned char *buf, - unsigned int buflen) -{ - struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!((st->txphase++) & 7)) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - } - st->dds_inc = dds_inc[st->tx_bit & 1]; - *buf++ = OFFSCOS(st->bit_pll); - st->bit_pll += st->dds_inc; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_1200_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!((st->txphase++) & 7)) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - } - st->dds_inc = dds_inc[st->tx_bit & 1]; - *buf++ = COS(st->bit_pll); - st->bit_pll += st->dds_inc; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int convolution8_u8(const unsigned char *st, const int *coeff, int csum) -{ - int sum = -0x80 * csum; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - - sum >>= 7; - return sum * sum; -} - -static __inline__ int convolution8_s16(const short *st, const int *coeff, int csum) -{ - int sum = 0; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - - sum >>= 15; - return sum * sum; -} - -static __inline__ int do_filter_1200_u8(const unsigned char *buf) -{ - int sum = convolution8_u8(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I); - sum += convolution8_u8(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q); - sum -= convolution8_u8(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I); - sum -= convolution8_u8(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q); - return sum; -} - -static __inline__ int do_filter_1200_s16(const short *buf) -{ - int sum = convolution8_s16(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I); - sum += convolution8_s16(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q); - sum -= convolution8_s16(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I); - sum -= convolution8_s16(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q); - return sum; -} - -/* --------------------------------------------------------------------- */ - -static const int pll_corr[2] = { -0x1000, 0x1000 }; - -static void demodulator_1200_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_1200_u8(buf); - st->dcd_shreg <<= 1; - st->bit_pll += 0x2000; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - st->bit_pll += pll_corr - [st->bit_pll < 0x9000]; - j = 4 * hweight8(st->dcd_shreg & 0x38) - - hweight16(st->dcd_shreg & 0x7c0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, (((int)*buf)-0x80) << 8, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_1200_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_1200_s16(buf); - st->dcd_shreg <<= 1; - st->bit_pll += 0x2000; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - st->bit_pll += pll_corr - [st->bit_pll < 0x9000]; - j = 4 * hweight8(st->dcd_shreg & 0x38) - - hweight16(st->dcd_shreg & 0x7c0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, *buf, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_1200(struct sm_state *sm) -{ - struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_afsk1200_tx = { - "afsk1200", sizeof(struct mod_state_afsk12), - AFSK12_SAMPLE_RATE, 1200, modulator_1200_u8, modulator_1200_s16, NULL -}; - -const struct modem_rx_info sm_afsk1200_rx = { - "afsk1200", sizeof(struct demod_state_afsk12), - AFSK12_SAMPLE_RATE, 1200, 8, AFSK12_SAMPLE_RATE/1200, - demodulator_1200_u8, demodulator_1200_s16, demod_init_1200 -}; - -/* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c b/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c --- a/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c Wed Nov 27 14:36:31 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,296 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_afsk2400_7.c -- soundcard radio modem driver, 2400 baud AFSK modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -/* - * This driver is intended to be compatible with TCM3105 modems - * overclocked to 7.3728MHz. The mark and space frequencies therefore - * lie at 3658 and 1996 Hz. - * Note that I do _not_ recommend the building of such links, I provide - * this only for the users who live in the coverage area of such - * a "legacy" link. - */ - -#include "sm.h" -#include "sm_tbl_afsk2400_7.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_afsk24 { - unsigned int shreg; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; - unsigned char last_rxbit; -}; - -struct mod_state_afsk24 { - unsigned int shreg; - unsigned char tx_bit; - unsigned int bit_pll; - unsigned int tx_seq; - unsigned int phinc; -}; - -/* --------------------------------------------------------------------- */ - -static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE, - AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE }; - -static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (st->tx_seq < 0x5555) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - st->phinc = dds_inc[st->tx_bit & 1]; - } - st->tx_seq += 0x5555; - st->tx_seq &= 0xffff; - *buf = OFFSCOS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (st->tx_seq < 0x5555) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - st->phinc = dds_inc[st->tx_bit & 1]; - } - st->tx_seq += 0x5555; - st->tx_seq &= 0xffff; - *buf = COS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum) -{ - int sum = -0x80 * csum; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - sum += (st[-12] * coeff[12]); - sum += (st[-13] * coeff[13]); - - sum >>= 7; - return sum * sum; -} - -static __inline__ int convolution14_s16(const short *st, const int *coeff, int csum) -{ - int sum = 0; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - sum += (st[-12] * coeff[12]); - sum += (st[-13] * coeff[13]); - - sum >>= 15; - return sum * sum; -} - -static __inline__ int do_filter_2400_u8(const unsigned char *buf) -{ - int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); - sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); - sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); - sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); - return sum; -} - -static __inline__ int do_filter_2400_s16(const short *buf) -{ - int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); - sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); - sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); - sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); - return sum; -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_2400_u8(buf); - st->dcd_shreg <<= 1; - st->bit_pll += AFSK24_BITPLL_INC; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) - st->bit_pll += AFSK24_BITPLL_INC/2; - else - st->bit_pll -= AFSK24_BITPLL_INC/2; - j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) - - hweight16(st->dcd_shreg & 0x1e0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, (((int)*buf)-0x80) << 8, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_2400_s16(buf); - st->dcd_shreg <<= 1; - st->bit_pll += AFSK24_BITPLL_INC; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) - st->bit_pll += AFSK24_BITPLL_INC/2; - else - st->bit_pll -= AFSK24_BITPLL_INC/2; - j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) - - hweight16(st->dcd_shreg & 0x1e0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, *buf, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_2400(struct sm_state *sm) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_afsk2400_7_tx = { - "afsk2400_7", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400, - modulator_2400_u8, modulator_2400_s16, NULL -}; - -const struct modem_rx_info sm_afsk2400_7_rx = { - "afsk2400_7", sizeof(struct demod_state_afsk24), - AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400, - demodulator_2400_u8, demodulator_2400_s16, demod_init_2400 -}; - -/* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c b/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c --- a/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c Wed Nov 27 14:36:31 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,296 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_afsk2400_8.c -- soundcard radio modem driver, 2400 baud AFSK modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -/* - * This driver is intended to be compatible with TCM3105 modems - * overclocked to 8MHz. The mark and space frequencies therefore - * lie at 3970 and 2165 Hz. - * Note that I do _not_ recommend the building of such links, I provide - * this only for the users who live in the coverage area of such - * a "legacy" link. - */ - -#include "sm.h" -#include "sm_tbl_afsk2400_8.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_afsk24 { - unsigned int shreg; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; - unsigned char last_rxbit; -}; - -struct mod_state_afsk24 { - unsigned int shreg; - unsigned char tx_bit; - unsigned int bit_pll; - unsigned int tx_seq; - unsigned int phinc; -}; - -/* --------------------------------------------------------------------- */ - -static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE, - AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE }; - -static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (st->tx_seq < 0x5555) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - st->phinc = dds_inc[st->tx_bit & 1]; - } - st->tx_seq += 0x5555; - st->tx_seq &= 0xffff; - *buf = OFFSCOS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (st->tx_seq < 0x5555) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - st->phinc = dds_inc[st->tx_bit & 1]; - } - st->tx_seq += 0x5555; - st->tx_seq &= 0xffff; - *buf = COS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum) -{ - int sum = -0x80 * csum; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - sum += (st[-12] * coeff[12]); - sum += (st[-13] * coeff[13]); - - sum >>= 7; - return sum * sum; -} - -static __inline__ int convolution14_s16(const short *st, const int *coeff, int csum) -{ - int sum = 0; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - sum += (st[-12] * coeff[12]); - sum += (st[-13] * coeff[13]); - - sum >>= 15; - return sum * sum; -} - -static __inline__ int do_filter_2400_u8(const unsigned char *buf) -{ - int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); - sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); - sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); - sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); - return sum; -} - -static __inline__ int do_filter_2400_s16(const short *buf) -{ - int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); - sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); - sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); - sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); - return sum; -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_2400_u8(buf); - st->dcd_shreg <<= 1; - st->bit_pll += AFSK24_BITPLL_INC; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) - st->bit_pll += AFSK24_BITPLL_INC/2; - else - st->bit_pll -= AFSK24_BITPLL_INC/2; - j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) - - hweight16(st->dcd_shreg & 0x1e0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, (((int)*buf)-0x80) << 8, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_2400_s16(buf); - st->dcd_shreg <<= 1; - st->bit_pll += AFSK24_BITPLL_INC; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) - st->bit_pll += AFSK24_BITPLL_INC/2; - else - st->bit_pll -= AFSK24_BITPLL_INC/2; - j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) - - hweight16(st->dcd_shreg & 0x1e0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, *buf, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_2400(struct sm_state *sm) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_afsk2400_8_tx = { - "afsk2400_8", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400, - modulator_2400_u8, modulator_2400_s16, NULL -}; - -const struct modem_rx_info sm_afsk2400_8_rx = { - "afsk2400_8", sizeof(struct demod_state_afsk24), - AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400, - demodulator_2400_u8, demodulator_2400_s16, demod_init_2400 -}; - -/* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk2666.c b/drivers/net/hamradio/soundmodem/sm_afsk2666.c --- a/drivers/net/hamradio/soundmodem/sm_afsk2666.c Wed Nov 27 14:36:31 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,356 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_afsk2666.c -- soundcard radio modem driver, 2666 baud AFSK modem - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include "sm.h" -#include "sm_tbl_afsk2666.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_afsk26 { - unsigned int shreg; - unsigned long descram; - int dem_sum[8]; - int dem_sum_mean; - int dem_cnt; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; -}; - -struct mod_state_afsk26 { - unsigned int shreg; - unsigned long scram; - unsigned int bit_pll; - unsigned int phinc; - unsigned int tx_seq; -}; - -/* --------------------------------------------------------------------- */ - -#define DESCRAM_TAP1 0x20000 -#define DESCRAM_TAP2 0x01000 -#define DESCRAM_TAP3 0x00001 - -#define DESCRAM_TAPSH1 17 -#define DESCRAM_TAPSH2 12 -#define DESCRAM_TAPSH3 0 - -#define SCRAM_TAP1 0x20000 /* X^17 */ -#define SCRAM_TAPN 0x00021 /* X^0+X^5 */ - -/* --------------------------------------------------------------------- */ - -static void modulator_2666_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_afsk26 *st = (struct mod_state_afsk26 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = ((st->scram << 1) | (st->scram & 1)); - st->scram ^= (!(st->shreg & 1)); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->phinc = afsk26_carfreq[!(st->scram & (SCRAM_TAP1 << 2))]; - } - if (st->tx_seq >= 6) - st->tx_seq = 0; - *buf = OFFSCOS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_2666_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_afsk26 *st = (struct mod_state_afsk26 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = ((st->scram << 1) | (st->scram & 1)); - st->scram ^= (!(st->shreg & 1)); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->phinc = afsk26_carfreq[!(st->scram & (SCRAM_TAP1 << 2))]; - } - if (st->tx_seq >= 6) - st->tx_seq = 0; - *buf = COS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int convolution12_u8(const unsigned char *st, const int *coeff, int csum) -{ - int sum = -0x80 * csum; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - - return sum; -} - -static __inline__ int convolution12_s16(const short *st, const int *coeff, int csum) -{ - int sum = 0; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - - sum >>= 8; - return sum; -} - -/* ---------------------------------------------------------------------- */ - -#if 0 -static int binexp(unsigned int i) -{ - int ret = 31; - - if (!i) - return 0; - if (i < 0x10000LU) { - i <<= 16; - ret -= 16; - } - if (i < 0x1000000LU) { - i <<= 8; - ret -= 8; - } - if (i < 0x10000000LU) { - i <<= 4; - ret -= 4; - } - if (i < 0x40000000LU) { - i <<= 2; - ret -= 2; - } - if (i < 0x80000000LU) - ret -= 1; - return ret; -} - -static const sqrt_tab[16] = { - 00000, 16384, 23170, 28378, 32768, 36636, 40132, 43348, - 46341, 49152, 51811, 54340, 56756, 59073, 61303, 63455 -}; - - -static unsigned int int_sqrt_approx(unsigned int i) -{ - unsigned int j; - - if (i < 16) - return sqrt_tab[i] >> 14; - j = binexp(i) >> 1; - i >>= (j * 2 - 2); - return (sqrt_tab[i & 0xf] << j) >> 15; -} -#endif - -/* --------------------------------------------------------------------- */ - -extern unsigned int est_pwr(int i, int q) -{ - unsigned int ui = abs(i); - unsigned int uq = abs(q); - - if (uq > ui) { - unsigned int tmp; - tmp = ui; - ui = uq; - uq = tmp; - } - if (uq > (ui >> 1)) - return 7*(ui>>3) + 9*(uq>>4); - else - return ui + (uq>>2); -} - -/* --------------------------------------------------------------------- */ - -static void demod_one_sample(struct sm_state *sm, struct demod_state_afsk26 *st, int curval, - int loi, int loq, int hii, int hiq) -{ - static const int pll_corr[2] = { -0xa00, 0xa00 }; - unsigned char curbit; - unsigned int descx; - int val; - - /* - * estimate power - */ - val = est_pwr(hii, hiq) - est_pwr(loi, loq); - /* - * estimate center value - */ - st->dem_sum[0] += val >> 8; - if ((++st->dem_cnt) >= 256) { - st->dem_cnt = 0; - st->dem_sum_mean = (st->dem_sum[0]+st->dem_sum[1]+ - st->dem_sum[2]+st->dem_sum[3]+ - st->dem_sum[4]+st->dem_sum[5]+ - st->dem_sum[6]+st->dem_sum[7]) >> 3; - memmove(st->dem_sum+1, st->dem_sum, - sizeof(st->dem_sum)-sizeof(st->dem_sum[0])); - st->dem_sum[0] = 0; - } - /* - * decision and bit clock regen - */ - val -= st->dem_sum_mean; - diag_add(sm, curval, val); - - st->dcd_shreg <<= 1; - st->bit_pll += 0x1555; - curbit = (val > 0); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < (0x8000+0x1555)]; - st->dcd_sum0 += 4*hweight8(st->dcd_shreg & 0x1e) - - hweight16(st->dcd_shreg & 0xfe00); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, curbit); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 400; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffffu; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2666_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_afsk26 *st = (struct demod_state_afsk26 *)(&sm->d); - - for (; buflen > 0; buflen--, buf++) { - demod_one_sample(sm, st, (*buf-0x80)<<8, - convolution12_u8(buf, afsk26_dem_tables[0][0].i, AFSK26_DEM_SUM_I_0_0), - convolution12_u8(buf, afsk26_dem_tables[0][0].q, AFSK26_DEM_SUM_Q_0_0), - convolution12_u8(buf, afsk26_dem_tables[0][1].i, AFSK26_DEM_SUM_I_0_1), - convolution12_u8(buf, afsk26_dem_tables[0][1].q, AFSK26_DEM_SUM_Q_0_1)); - demod_one_sample(sm, st, (*buf-0x80)<<8, - convolution12_u8(buf, afsk26_dem_tables[1][0].i, AFSK26_DEM_SUM_I_1_0), - convolution12_u8(buf, afsk26_dem_tables[1][0].q, AFSK26_DEM_SUM_Q_1_0), - convolution12_u8(buf, afsk26_dem_tables[1][1].i, AFSK26_DEM_SUM_I_1_1), - convolution12_u8(buf, afsk26_dem_tables[1][1].q, AFSK26_DEM_SUM_Q_1_1)); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2666_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_afsk26 *st = (struct demod_state_afsk26 *)(&sm->d); - - for (; buflen > 0; buflen--, buf++) { - demod_one_sample(sm, st, *buf, - convolution12_s16(buf, afsk26_dem_tables[0][0].i, AFSK26_DEM_SUM_I_0_0), - convolution12_s16(buf, afsk26_dem_tables[0][0].q, AFSK26_DEM_SUM_Q_0_0), - convolution12_s16(buf, afsk26_dem_tables[0][1].i, AFSK26_DEM_SUM_I_0_1), - convolution12_s16(buf, afsk26_dem_tables[0][1].q, AFSK26_DEM_SUM_Q_0_1)); - demod_one_sample(sm, st, *buf, - convolution12_s16(buf, afsk26_dem_tables[1][0].i, AFSK26_DEM_SUM_I_1_0), - convolution12_s16(buf, afsk26_dem_tables[1][0].q, AFSK26_DEM_SUM_Q_1_0), - convolution12_s16(buf, afsk26_dem_tables[1][1].i, AFSK26_DEM_SUM_I_1_1), - convolution12_s16(buf, afsk26_dem_tables[1][1].q, AFSK26_DEM_SUM_Q_1_1)); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_2666(struct sm_state *sm) -{ - struct demod_state_afsk26 *st = (struct demod_state_afsk26 *)(&sm->d); - - st->dcd_time = 400; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_afsk2666_tx = { - "afsk2666", sizeof(struct mod_state_afsk26), AFSK26_SAMPLERATE, 2666, - modulator_2666_u8, modulator_2666_s16, NULL -}; - -const struct modem_rx_info sm_afsk2666_rx = { - "afsk2666", sizeof(struct demod_state_afsk26), AFSK26_SAMPLERATE, 2666, 12, 6, - demodulator_2666_u8, demodulator_2666_s16, demod_init_2666 -}; - -/* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm_fsk9600.c b/drivers/net/hamradio/soundmodem/sm_fsk9600.c --- a/drivers/net/hamradio/soundmodem/sm_fsk9600.c Wed Nov 27 14:36:31 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,391 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_fsk9600.c -- soundcard radio modem driver, - * 9600 baud G3RUH compatible FSK modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include "sm.h" -#include "sm_tbl_fsk9600.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_fsk96 { - unsigned int shreg; - unsigned long descram; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; -}; - -struct mod_state_fsk96 { - unsigned int shreg; - unsigned long scram; - unsigned char tx_bit; - unsigned char *txtbl; - unsigned int txphase; -}; - -/* --------------------------------------------------------------------- */ - -#define DESCRAM_TAP1 0x20000 -#define DESCRAM_TAP2 0x01000 -#define DESCRAM_TAP3 0x00001 - -#define DESCRAM_TAPSH1 17 -#define DESCRAM_TAPSH2 12 -#define DESCRAM_TAPSH3 0 - -#define SCRAM_TAP1 0x20000 /* X^17 */ -#define SCRAM_TAPN 0x00021 /* X^0+X^5 */ - -/* --------------------------------------------------------------------- */ - -static void modulator_9600_4_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!st->txphase++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff); - } - if (st->txphase >= 4) - st->txphase = 0; - *buf++ = *st->txtbl; - st->txtbl += 0x100; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_9600_4_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!st->txphase++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff); - } - if (st->txphase >= 4) - st->txphase = 0; - *buf++ = ((*st->txtbl)-0x80) << 8; - st->txtbl += 0x100; - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_9600_4_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - static const int pll_corr[2] = { -0x1000, 0x1000 }; - unsigned char curbit; - unsigned int descx; - - for (; buflen > 0; buflen--, buf++) { - st->dcd_shreg <<= 1; - st->bit_pll += 0x4000; - curbit = (*buf >= 0x80); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < 0xa000]; - st->dcd_sum0 += 8 * hweight8(st->dcd_shreg & 0x0c) - - !!(st->dcd_shreg & 0x10); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, ((short)(*buf - 0x80)) << 8); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_9600_4_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - static const int pll_corr[2] = { -0x1000, 0x1000 }; - unsigned char curbit; - unsigned int descx; - - for (; buflen > 0; buflen--, buf++) { - st->dcd_shreg <<= 1; - st->bit_pll += 0x4000; - curbit = (*buf >= 0); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < 0xa000]; - st->dcd_sum0 += 8 * hweight8(st->dcd_shreg & 0x0c) - - !!(st->dcd_shreg & 0x10); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, *buf); - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_9600_5_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!st->txphase++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff); - } - if (st->txphase >= 5) - st->txphase = 0; - *buf++ = *st->txtbl; - st->txtbl += 0x100; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_9600_5_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!st->txphase++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff); - } - if (st->txphase >= 5) - st->txphase = 0; - *buf++ = ((*st->txtbl)-0x80)<<8; - st->txtbl += 0x100; - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_9600_5_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - static const int pll_corr[2] = { -0x1000, 0x1000 }; - unsigned char curbit; - unsigned int descx; - - for (; buflen > 0; buflen--, buf++) { - st->dcd_shreg <<= 1; - st->bit_pll += 0x3333; - curbit = (*buf >= 0x80); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < 0x9999]; - st->dcd_sum0 += 16 * hweight8(st->dcd_shreg & 0x0c) - - hweight8(st->dcd_shreg & 0x70); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, ((short)(*buf - 0x80)) << 8); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_9600_5_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - static const int pll_corr[2] = { -0x1000, 0x1000 }; - unsigned char curbit; - unsigned int descx; - - for (; buflen > 0; buflen--, buf++) { - st->dcd_shreg <<= 1; - st->bit_pll += 0x3333; - curbit = (*buf >= 0); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < 0x9999]; - st->dcd_sum0 += 16 * hweight8(st->dcd_shreg & 0x0c) - - hweight8(st->dcd_shreg & 0x70); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, *buf); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_9600(struct sm_state *sm) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - - st->dcd_time = 240; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_fsk9600_4_tx = { - "fsk9600", sizeof(struct mod_state_fsk96), 38400, 9600, - modulator_9600_4_u8, modulator_9600_4_s16, NULL -}; - -const struct modem_rx_info sm_fsk9600_4_rx = { - "fsk9600", sizeof(struct demod_state_fsk96), 38400, 9600, 1, 4, - demodulator_9600_4_u8, demodulator_9600_4_s16, demod_init_9600 -}; - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_fsk9600_5_tx = { - "fsk9600", sizeof(struct mod_state_fsk96), 48000, 9600, - modulator_9600_5_u8, modulator_9600_5_s16, NULL -}; - -const struct modem_rx_info sm_fsk9600_5_rx = { - "fsk9600", sizeof(struct demod_state_fsk96), 48000, 9600, 1, 5, - demodulator_9600_5_u8, demodulator_9600_5_s16, demod_init_9600 -}; - -/* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm_hapn4800.c b/drivers/net/hamradio/soundmodem/sm_hapn4800.c --- a/drivers/net/hamradio/soundmodem/sm_hapn4800.c Wed Nov 27 14:36:28 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,560 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_hapn4800.c -- soundcard radio modem driver, 4800 baud HAPN modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - * - * This module implements a (hopefully) HAPN (Hamilton Area Packet - * Network) compatible 4800 baud modem. - * The HAPN modem uses kind of "duobinary signalling" (not really, - * duobinary signalling gives ... 0 0 -1 0 1 0 0 ... at the sampling - * instants, whereas HAPN signalling gives ... 0 0 -1 1 0 0 ..., see - * Proakis, Digital Communications). - * The code is untested. It is compatible with itself (i.e. it can decode - * the packets it sent), but I could not test if it is compatible with - * any "real" HAPN modem, since noone uses it in my region of the world. - * Feedback therefore welcome. - */ - -#include "sm.h" -#include "sm_tbl_hapn4800.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_hapn48 { - unsigned int shreg; - unsigned int bit_pll; - unsigned char last_bit; - unsigned char last_bit2; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; - int lvlhi, lvllo; -}; - -struct mod_state_hapn48 { - unsigned int shreg; - unsigned char tx_bit; - unsigned int tx_seq; - const unsigned char *tbl; -}; - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 10) - st->tx_seq = 0; - *buf = *st->tbl; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_10_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 10) - st->tx_seq = 0; - *buf = ((*st->tbl)-0x80)<<8; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 8) - st->tx_seq = 0; - *buf = *st->tbl; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_8_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 8) - st->tx_seq = 0; - *buf = ((*st->tbl)-0x80)<<8; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_pm10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 10) - st->tx_seq = 0; - *buf = *st->tbl; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_pm10_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 10) - st->tx_seq = 0; - *buf = ((*st->tbl)-0x80)<<8; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_pm8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 8) - st->tx_seq = 0; - *buf = *st->tbl; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_pm8_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 8) - st->tx_seq = 0; - *buf = ((*st->tbl)-0x80)<<8; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_hapn4800_10_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - static const int pll_corr[2] = { -0x800, 0x800 }; - int curst, cursync; - int inv; - - for (; buflen > 0; buflen--, buf++) { - inv = ((int)(buf[-2])-0x80) << 8; - st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ - st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (inv > st->lvlhi) - st->lvlhi = inv; - if (inv < st->lvllo) - st->lvllo = inv; - if (buflen & 1) - st->dcd_shreg <<= 1; - st->bit_pll += 0x199a; - curst = cursync = 0; - if (inv > st->lvlhi >> 1) { - curst = 1; - cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && - buf[-2] > buf[-0] && buf[-2] > buf[-4]); - } else if (inv < st->lvllo >> 1) { - curst = -1; - cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && - buf[-2] < buf[-0] && buf[-2] < buf[-4]); - } - if (cursync) { - st->dcd_shreg |= cursync; - st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x8ccdu]; - st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x18c6318c) - - hweight32(st->dcd_shreg & 0xe739ce70); - } - hdlcdrv_channelbit(&sm->hdrv, cursync); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->last_bit2 = st->last_bit; - if (curst < 0) - st->last_bit = 0; - else if (curst > 0) - st->last_bit = 1; - st->shreg >>= 1; - st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, inv); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_hapn4800_10_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - static const int pll_corr[2] = { -0x800, 0x800 }; - int curst, cursync; - int inv; - - for (; buflen > 0; buflen--, buf++) { - inv = buf[-2]; - st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ - st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (inv > st->lvlhi) - st->lvlhi = inv; - if (inv < st->lvllo) - st->lvllo = inv; - if (buflen & 1) - st->dcd_shreg <<= 1; - st->bit_pll += 0x199a; - curst = cursync = 0; - if (inv > st->lvlhi >> 1) { - curst = 1; - cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && - buf[-2] > buf[-0] && buf[-2] > buf[-4]); - } else if (inv < st->lvllo >> 1) { - curst = -1; - cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && - buf[-2] < buf[-0] && buf[-2] < buf[-4]); - } - if (cursync) { - st->dcd_shreg |= cursync; - st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x8ccdu]; - st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x18c6318c) - - hweight32(st->dcd_shreg & 0xe739ce70); - } - hdlcdrv_channelbit(&sm->hdrv, cursync); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->last_bit2 = st->last_bit; - if (curst < 0) - st->last_bit = 0; - else if (curst > 0) - st->last_bit = 1; - st->shreg >>= 1; - st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, inv); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_hapn4800_8_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - static const int pll_corr[2] = { -0x800, 0x800 }; - int curst, cursync; - int inv; - - for (; buflen > 0; buflen--, buf++) { - inv = ((int)(buf[-2])-0x80) << 8; - st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ - st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (inv > st->lvlhi) - st->lvlhi = inv; - if (inv < st->lvllo) - st->lvllo = inv; - if (buflen & 1) - st->dcd_shreg <<= 1; - st->bit_pll += 0x2000; - curst = cursync = 0; - if (inv > st->lvlhi >> 1) { - curst = 1; - cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && - buf[-2] > buf[-0] && buf[-2] > buf[-4]); - } else if (inv < st->lvllo >> 1) { - curst = -1; - cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && - buf[-2] < buf[-0] && buf[-2] < buf[-4]); - } - if (cursync) { - st->dcd_shreg |= cursync; - st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x9000u]; - st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x44444444) - - hweight32(st->dcd_shreg & 0xbbbbbbbb); - } - hdlcdrv_channelbit(&sm->hdrv, cursync); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->last_bit2 = st->last_bit; - if (curst < 0) - st->last_bit = 0; - else if (curst > 0) - st->last_bit = 1; - st->shreg >>= 1; - st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, inv); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_hapn4800_8_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - static const int pll_corr[2] = { -0x800, 0x800 }; - int curst, cursync; - int inv; - - for (; buflen > 0; buflen--, buf++) { - inv = buf[-2]; - st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ - st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (inv > st->lvlhi) - st->lvlhi = inv; - if (inv < st->lvllo) - st->lvllo = inv; - if (buflen & 1) - st->dcd_shreg <<= 1; - st->bit_pll += 0x2000; - curst = cursync = 0; - if (inv > st->lvlhi >> 1) { - curst = 1; - cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && - buf[-2] > buf[-0] && buf[-2] > buf[-4]); - } else if (inv < st->lvllo >> 1) { - curst = -1; - cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && - buf[-2] < buf[-0] && buf[-2] < buf[-4]); - } - if (cursync) { - st->dcd_shreg |= cursync; - st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x9000u]; - st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x44444444) - - hweight32(st->dcd_shreg & 0xbbbbbbbb); - } - hdlcdrv_channelbit(&sm->hdrv, cursync); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->last_bit2 = st->last_bit; - if (curst < 0) - st->last_bit = 0; - else if (curst > 0) - st->last_bit = 1; - st->shreg >>= 1; - st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, inv); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_hapn4800(struct sm_state *sm) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_hapn4800_8_tx = { - "hapn4800", sizeof(struct mod_state_hapn48), 38400, 4800, - modulator_hapn4800_8_u8, modulator_hapn4800_8_s16, NULL -}; - -const struct modem_rx_info sm_hapn4800_8_rx = { - "hapn4800", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8, - demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800 -}; - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_hapn4800_10_tx = { - "hapn4800", sizeof(struct mod_state_hapn48), 48000, 4800, - modulator_hapn4800_10_u8, modulator_hapn4800_10_s16, NULL -}; - -const struct modem_rx_info sm_hapn4800_10_rx = { - "hapn4800", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10, - demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800 -}; - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_hapn4800_pm8_tx = { - "hapn4800pm", sizeof(struct mod_state_hapn48), 38400, 4800, - modulator_hapn4800_pm8_u8, modulator_hapn4800_pm8_s16, NULL -}; - -const struct modem_rx_info sm_hapn4800_pm8_rx = { - "hapn4800pm", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8, - demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800 -}; - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_hapn4800_pm10_tx = { - "hapn4800pm", sizeof(struct mod_state_hapn48), 48000, 4800, - modulator_hapn4800_pm10_u8, modulator_hapn4800_pm10_s16, NULL -}; - -const struct modem_rx_info sm_hapn4800_pm10_rx = { - "hapn4800pm", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10, - demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800 -}; - -/* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm_psk4800.c b/drivers/net/hamradio/soundmodem/sm_psk4800.c --- a/drivers/net/hamradio/soundmodem/sm_psk4800.c Wed Nov 27 14:36:29 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,418 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_psk4800.c -- soundcard radio modem driver, 4800 baud 8PSK modem - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include "sm.h" -#include "sm_tbl_psk4800.h" - -/* --------------------------------------------------------------------- */ - -#define DESCRAM_TAP1 0x20000 -#define DESCRAM_TAP2 0x01000 -#define DESCRAM_TAP3 0x00001 - -#define DESCRAM_TAPSH1 17 -#define DESCRAM_TAPSH2 12 -#define DESCRAM_TAPSH3 0 - -#define SCRAM_TAP1 0x20000 /* X^17 */ -#define SCRAM_TAPN 0x00021 /* X^0+X^5 */ - -#define SCRAM_SHIFT 17 - -/* --------------------------------------------------------------------- */ - -struct demod_state_psk48 { - /* - * input mixer and lowpass - */ - short infi[PSK48_RXF_LEN/2], infq[PSK48_RXF_LEN/2]; - unsigned int downmixer; - int ovrphase; - short magi, magq; - /* - * sampling instant recovery - */ - int pwrhist[5]; - unsigned int s_phase; - int cur_sync; - /* - * phase recovery - */ - short cur_phase_dev; - short last_ph_err; - unsigned short pskph; - unsigned int phase; - unsigned short last_pskph; - unsigned char cur_raw, last_raw, rawbits; - /* - * decoding - */ - unsigned int shreg; - unsigned long descram; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; -}; - -struct mod_state_psk48 { - unsigned char txbits[PSK48_TXF_NUMSAMPLES]; - unsigned short txphase; - unsigned int shreg; - unsigned long scram; - const short *tbl; - unsigned int txseq; -}; - -/* --------------------------------------------------------------------- */ - -static void modulator_4800_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_psk48 *st = (struct mod_state_psk48 *)(&sm->m); - int i, j; - int si, sq; - - for (; buflen > 0; buflen--, buf++) { - if (!st->txseq++) { - memmove(st->txbits+1, st->txbits, - sizeof(st->txbits)-sizeof(st->txbits[0])); - for (i = 0; i < 3; i++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | - (st->shreg & 1); - st->shreg >>= 1; - if (st->scram & SCRAM_TAP1) - st->scram ^= SCRAM_TAPN; - } - j = (st->scram >> (SCRAM_SHIFT+3)) & 7; - st->txbits[0] -= (j ^ (j >> 1)); - st->txbits[0] &= 7; - st->tbl = psk48_tx_table; - } - if (st->txseq >= PSK48_TXF_OVERSAMPLING) - st->txseq = 0; - for (j = si = sq = 0; j < PSK48_TXF_NUMSAMPLES; j++, st->tbl += 16) { - si += st->tbl[st->txbits[j]]; - sq += st->tbl[st->txbits[j]+8]; - } - *buf = ((si*COS(st->txphase)+ sq*SIN(st->txphase)) >> 23) + 0x80; - st->txphase = (st->txphase + PSK48_PHASEINC) & 0xffffu; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_4800_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_psk48 *st = (struct mod_state_psk48 *)(&sm->m); - int i, j; - int si, sq; - - for (; buflen > 0; buflen--, buf++) { - if (!st->txseq++) { - memmove(st->txbits+1, st->txbits, - sizeof(st->txbits)-sizeof(st->txbits[0])); - for (i = 0; i < 3; i++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | - (st->shreg & 1); - st->shreg >>= 1; - if (st->scram & SCRAM_TAP1) - st->scram ^= SCRAM_TAPN; - } - j = (st->scram >> (SCRAM_SHIFT+3)) & 7; - st->txbits[0] -= (j ^ (j >> 1)); - st->txbits[0] &= 7; - st->tbl = psk48_tx_table; - } - if (st->txseq >= PSK48_TXF_OVERSAMPLING) - st->txseq = 0; - for (j = si = sq = 0; j < PSK48_TXF_NUMSAMPLES; j++, st->tbl += 16) { - si += st->tbl[st->txbits[j]]; - sq += st->tbl[st->txbits[j]+8]; - } - *buf = (si*COS(st->txphase)+ sq*SIN(st->txphase)) >> 15; - st->txphase = (st->txphase + PSK48_PHASEINC) & 0xffffu; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ unsigned short tbl_atan(short q, short i) -{ - short tmp; - unsigned short argoffs = 0; - - if (i == 0 && q == 0) - return 0; - switch (((q < 0) << 1) | (i < 0)) { - case 0: - break; - case 1: - tmp = q; - q = -i; - i = tmp; - argoffs = 0x4000; - break; - case 3: - q = -q; - i = -i; - argoffs = 0x8000; - break; - case 2: - tmp = -q; - q = i; - i = tmp; - argoffs = 0xc000; - break; - } - if (q > i) { - tmp = i / q * ATAN_TABLEN; - return (argoffs+0x4000-atan_tab[((i<<15)/q*ATAN_TABLEN>>15)]) - &0xffffu; - } - return (argoffs+atan_tab[((q<<15)/i*ATAN_TABLEN)>>15])&0xffffu; -} - -#define ATAN(q,i) tbl_atan(q, i) - -/* --------------------------------------------------------------------- */ - -static void demod_psk48_baseband(struct sm_state *sm, struct demod_state_psk48 *st, - short vali, short valq) -{ - int i, j; - - st->magi = vali; - st->magq = valq; - memmove(st->pwrhist+1, st->pwrhist, - sizeof(st->pwrhist)-sizeof(st->pwrhist[0])); - st->pwrhist[0] = st->magi * st->magi + - st->magq * st->magq; - st->cur_sync = ((st->pwrhist[4] >> 2) > st->pwrhist[2] && - (st->pwrhist[0] >> 2) > st->pwrhist[2] && - st-> pwrhist[3] > st->pwrhist[2] && - st->pwrhist[1] > st->pwrhist[2]); - st->s_phase &= 0xffff; - st->s_phase += PSK48_SPHASEINC; - st->dcd_shreg <<= 1; - if (st->cur_sync) { - if (st->s_phase >= (0x8000 + 5*PSK48_SPHASEINC/2)) - st->s_phase -= PSK48_SPHASEINC/6; - else - st->s_phase += PSK48_SPHASEINC/6; - st->dcd_sum0 = 4*hweight8(st->dcd_shreg & 0xf8)- - hweight16(st->dcd_shreg & 0x1f00); - } - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->s_phase < 0x10000) - return; - /* - * sample one constellation - */ - st->last_pskph = st->pskph; - st->pskph = (ATAN(st->magq, st->magi)- - st->phase) & 0xffffu; - st->last_ph_err = (st->pskph & 0x1fffu) - 0x1000; - st->phase += st->last_ph_err/16; - st->last_raw = st->cur_raw; - st->cur_raw = ((st->pskph >> 13) & 7); - i = (st->cur_raw - st->last_raw) & 7; - st->rawbits = i ^ (i >> 1) ^ (i >> 2); - st->descram = (st->descram << 3) | (st->rawbits); - hdlcdrv_channelbit(&sm->hdrv, st->descram & 4); - hdlcdrv_channelbit(&sm->hdrv, st->descram & 2); - hdlcdrv_channelbit(&sm->hdrv, st->descram & 1); - i = (((st->descram >> DESCRAM_TAPSH1) & 7) ^ - ((st->descram >> DESCRAM_TAPSH2) & 7) ^ - ((st->descram >> DESCRAM_TAPSH3) & 7)); - for (j = 4; j; j >>= 1) { - st->shreg >>= 1; - st->shreg |= (!!(i & j)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - -#if 0 - st->dcd_shreg <<= 1; - st->bit_pll += 0x4000; - curbit = (*buf >= 0x80); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr - [st->bit_pll < 0xa000]; - st->dcd_sum0 += 8 * - hweight8(st->dcd_shreg & 0x0c) - - !!(st->dcd_shreg & 0x10); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffffu; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, ((short)(*buf - 0x80)) << 8); -#endif - - diag_trigger(sm); - diag_add_constellation(sm, (vali*COS(st->phase)+ valq*SIN(st->phase)) >> 13, - (valq*COS(st->phase) - vali*SIN(st->phase)) >> 13); -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_4800_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_psk48 *st = (struct demod_state_psk48 *)(&sm->d); - int i, si, sq; - const short *coeff; - - for (; buflen > 0; buflen--, buf++) { - memmove(st->infi+1, st->infi, - sizeof(st->infi)-sizeof(st->infi[0])); - memmove(st->infq+1, st->infq, - sizeof(st->infq)-sizeof(st->infq[0])); - si = *buf; - si &= 0xff; - si -= 128; - diag_add_one(sm, si << 8); - st->infi[0] = (si * COS(st->downmixer))>>7; - st->infq[0] = (si * SIN(st->downmixer))>>7; - st->downmixer = (st->downmixer-PSK48_PHASEINC)&0xffffu; - for (i = si = sq = 0, coeff = psk48_rx_coeff; i < (PSK48_RXF_LEN/2); - i++, coeff += 2) { - si += st->infi[i] * (*coeff); - sq += st->infq[i] * (*coeff); - } - demod_psk48_baseband(sm, st, si >> 15, sq >> 15); - for (i = si = sq = 0, coeff = psk48_rx_coeff + 1; i < (PSK48_RXF_LEN/2); - i++, coeff += 2) { - si += st->infi[i] * (*coeff); - sq += st->infq[i] * (*coeff); - } - demod_psk48_baseband(sm, st, si >> 15, sq >> 15); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_4800_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_psk48 *st = (struct demod_state_psk48 *)(&sm->d); - int i, si, sq; - const short *coeff; - - for (; buflen > 0; buflen--, buf++) { - memmove(st->infi+1, st->infi, - sizeof(st->infi)-sizeof(st->infi[0])); - memmove(st->infq+1, st->infq, - sizeof(st->infq)-sizeof(st->infq[0])); - si = *buf; - diag_add_one(sm, si); - st->infi[0] = (si * COS(st->downmixer))>>15; - st->infq[0] = (si * SIN(st->downmixer))>>15; - st->downmixer = (st->downmixer-PSK48_PHASEINC)&0xffffu; - for (i = si = sq = 0, coeff = psk48_rx_coeff; i < (PSK48_RXF_LEN/2); - i++, coeff += 2) { - si += st->infi[i] * (*coeff); - sq += st->infq[i] * (*coeff); - } - demod_psk48_baseband(sm, st, si >> 15, sq >> 15); - for (i = si = sq = 0, coeff = psk48_rx_coeff + 1; i < (PSK48_RXF_LEN/2); - i++, coeff += 2) { - si += st->infi[i] * (*coeff); - sq += st->infq[i] * (*coeff); - } - demod_psk48_baseband(sm, st, si >> 15, sq >> 15); - } -} - -/* --------------------------------------------------------------------- */ - -static void mod_init_4800(struct sm_state *sm) -{ - struct mod_state_psk48 *st = (struct mod_state_psk48 *)(&sm->m); - - st->scram = 1; -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_4800(struct sm_state *sm) -{ - struct demod_state_psk48 *st = (struct demod_state_psk48 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_psk4800_tx = { - "psk4800", sizeof(struct mod_state_psk48), - PSK48_SAMPLERATE, 4800, - modulator_4800_u8, modulator_4800_s16, mod_init_4800 -}; - -const struct modem_rx_info sm_psk4800_rx = { - "psk4800", sizeof(struct demod_state_psk48), - PSK48_SAMPLERATE, 4800, 1, PSK48_TXF_OVERSAMPLING, - demodulator_4800_u8, demodulator_4800_s16, demod_init_4800 -}; - -/* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm_sbc.c b/drivers/net/hamradio/soundmodem/sm_sbc.c --- a/drivers/net/hamradio/soundmodem/sm_sbc.c Wed Nov 27 14:36:31 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,942 +0,0 @@ - - -/* - * sm_sbc.c -- soundcard radio modem driver soundblaster hardware driver - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include "sm.h" -#include "smdma.h" - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 -#include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -static inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -static inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -/* --------------------------------------------------------------------- */ - -struct sc_state_sbc { - unsigned char revhi, revlo; - unsigned char fmt[2]; - unsigned int sr[2]; -}; - -#define SCSTATE ((struct sc_state_sbc *)(&sm->hw)) - -/* --------------------------------------------------------------------- */ -/* - * the sbc converter's registers - */ -#define DSP_RESET(iobase) (iobase+0x6) -#define DSP_READ_DATA(iobase) (iobase+0xa) -#define DSP_WRITE_DATA(iobase) (iobase+0xc) -#define DSP_WRITE_STATUS(iobase) (iobase+0xc) -#define DSP_DATA_AVAIL(iobase) (iobase+0xe) -#define DSP_MIXER_ADDR(iobase) (iobase+0x4) -#define DSP_MIXER_DATA(iobase) (iobase+0x5) -#define DSP_INTACK_16BIT(iobase) (iobase+0xf) -#define SBC_EXTENT 16 - -/* --------------------------------------------------------------------- */ -/* - * SBC commands - */ -#define SBC_OUTPUT 0x14 -#define SBC_INPUT 0x24 -#define SBC_BLOCKSIZE 0x48 -#define SBC_HI_OUTPUT 0x91 -#define SBC_HI_INPUT 0x99 -#define SBC_LO_OUTPUT_AUTOINIT 0x1c -#define SBC_LO_INPUT_AUTOINIT 0x2c -#define SBC_HI_OUTPUT_AUTOINIT 0x90 -#define SBC_HI_INPUT_AUTOINIT 0x98 -#define SBC_IMMED_INT 0xf2 -#define SBC_GET_REVISION 0xe1 -#define ESS_GET_REVISION 0xe7 -#define SBC_SPEAKER_ON 0xd1 -#define SBC_SPEAKER_OFF 0xd3 -#define SBC_DMA_ON 0xd0 -#define SBC_DMA_OFF 0xd4 -#define SBC_SAMPLE_RATE 0x40 -#define SBC_SAMPLE_RATE_OUT 0x41 -#define SBC_SAMPLE_RATE_IN 0x42 -#define SBC_MONO_8BIT 0xa0 -#define SBC_MONO_16BIT 0xa4 -#define SBC_STEREO_8BIT 0xa8 -#define SBC_STEREO_16BIT 0xac - -#define SBC4_OUT8_AI 0xc6 -#define SBC4_IN8_AI 0xce -#define SBC4_MODE_UNS_MONO 0x00 -#define SBC4_MODE_SIGN_MONO 0x10 - -#define SBC4_OUT16_AI 0xb6 -#define SBC4_IN16_AI 0xbe - -/* --------------------------------------------------------------------- */ - -static int inline reset_dsp(struct net_device *dev) -{ - int i; - - outb(1, DSP_RESET(dev->base_addr)); - udelay(300); - outb(0, DSP_RESET(dev->base_addr)); - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80) - if (inb(DSP_READ_DATA(dev->base_addr)) == 0xaa) - return 1; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void inline write_dsp(struct net_device *dev, unsigned char data) -{ - int i; - - for (i = 0; i < 0xffff; i++) - if (!(inb(DSP_WRITE_STATUS(dev->base_addr)) & 0x80)) { - outb(data, DSP_WRITE_DATA(dev->base_addr)); - return; - } -} - -/* --------------------------------------------------------------------- */ - -static int inline read_dsp(struct net_device *dev, unsigned char *data) -{ - int i; - - if (!data) - return 0; - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80) { - *data = inb(DSP_READ_DATA(dev->base_addr)); - return 1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int config_resources(struct net_device *dev, struct sm_state *sm, int fdx) -{ - unsigned char irqreg = 0, dmareg = 0, realirq, realdma; - unsigned long flags; - - switch (dev->irq) { - case 2: - case 9: - irqreg |= 0x01; - break; - - case 5: - irqreg |= 0x02; - break; - - case 7: - irqreg |= 0x04; - break; - - case 10: - irqreg |= 0x08; - break; - - default: - return -ENODEV; - } - - switch (dev->dma) { - case 0: - dmareg |= 0x01; - break; - - case 1: - dmareg |= 0x02; - break; - - case 3: - dmareg |= 0x08; - break; - - default: - return -ENODEV; - } - - if (fdx) { - switch (sm->hdrv.ptt_out.dma2) { - case 5: - dmareg |= 0x20; - break; - - case 6: - dmareg |= 0x40; - break; - - case 7: - dmareg |= 0x80; - break; - - default: - return -ENODEV; - } - } - save_flags(flags); - cli(); - outb(0x80, DSP_MIXER_ADDR(dev->base_addr)); - outb(irqreg, DSP_MIXER_DATA(dev->base_addr)); - realirq = inb(DSP_MIXER_DATA(dev->base_addr)); - outb(0x81, DSP_MIXER_ADDR(dev->base_addr)); - outb(dmareg, DSP_MIXER_DATA(dev->base_addr)); - realdma = inb(DSP_MIXER_DATA(dev->base_addr)); - restore_flags(flags); - if ((~realirq) & irqreg || (~realdma) & dmareg) { - printk(KERN_ERR "%s: sbc resource registers cannot be set; PnP device " - "and IRQ/DMA specified wrongly?\n", sm_drvname); - return -EINVAL; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void inline sbc_int_ack_8bit(struct net_device *dev) -{ - inb(DSP_DATA_AVAIL(dev->base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static void inline sbc_int_ack_16bit(struct net_device *dev) -{ - inb(DSP_INTACK_16BIT(dev->base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static void setup_dma_dsp(struct net_device *dev, struct sm_state *sm, int send) -{ - unsigned long flags; - static const unsigned char sbcmode[2][2] = { - { SBC_LO_INPUT_AUTOINIT, SBC_LO_OUTPUT_AUTOINIT }, - { SBC_HI_INPUT_AUTOINIT, SBC_HI_OUTPUT_AUTOINIT } - }; - static const unsigned char sbc4mode[2] = { SBC4_IN8_AI, SBC4_OUT8_AI }; - static const unsigned char sbcskr[2] = { SBC_SPEAKER_OFF, SBC_SPEAKER_ON }; - unsigned int nsamps; - - send = !!send; - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname); - return; - } - save_flags(flags); - cli(); - sbc_int_ack_8bit(dev); - write_dsp(dev, SBC_SAMPLE_RATE); /* set sampling rate */ - write_dsp(dev, SCSTATE->fmt[send]); - write_dsp(dev, sbcskr[send]); - nsamps = dma_setup(sm, send, dev->dma) - 1; - sbc_int_ack_8bit(dev); - if (SCSTATE->revhi >= 4) { - write_dsp(dev, sbc4mode[send]); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, nsamps & 0xff); - write_dsp(dev, nsamps >> 8); - } else { - write_dsp(dev, SBC_BLOCKSIZE); - write_dsp(dev, nsamps & 0xff); - write_dsp(dev, nsamps >> 8); - write_dsp(dev, sbcmode[SCSTATE->fmt[send] >= 180][send]); - /* hispeed mode if sample rate > 13kHz */ - } - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned int curfrag; - - if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC) - return; - cli(); - sbc_int_ack_8bit(dev); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag); - enable_dma(dev->dma); - sm_int_freq(sm); - sti(); - if (sm->dma.ptt_cnt <= 0) { - dma_receive(sm, curfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - if (hdlcdrv_ptt(&sm->hdrv)) { - /* starting to transmit */ - disable_dma(dev->dma); - hdlcdrv_transmitter(dev, &sm->hdrv); /* prefill HDLC buffer */ - dma_start_transmit(sm); - setup_dma_dsp(dev, sm, 1); - dma_transmit(sm); - } - } else if (dma_end_transmit(sm, curfrag)) { - /* stopping transmission */ - disable_dma(dev->dma); - sti(); - dma_init_receive(sm); - setup_dma_dsp(dev, sm, 0); - } else - dma_transmit(sm); - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); - -} - -/* --------------------------------------------------------------------- */ - -static int sbc_open(struct net_device *dev, struct sm_state *sm) -{ - int err; - unsigned int dmasz, u; - - if (sizeof(sm->m) < sizeof(struct sc_state_sbc)) { - printk(KERN_ERR "sm sbc: sbc state too big: %d > %d\n", - sizeof(struct sc_state_sbc), sizeof(sm->m)); - return -ENODEV; - } - if (!dev || !sm) - return -ENXIO; - if (dev->base_addr <= 0 || dev->base_addr > 0x1000-SBC_EXTENT || - dev->irq < 2 || dev->irq > 15 || dev->dma > 3) - return -ENXIO; - if (check_region(dev->base_addr, SBC_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n", - sm_drvname, dev->base_addr); - return -ENODEV; - } - write_dsp(dev, SBC_GET_REVISION); - if (!read_dsp(dev, &SCSTATE->revhi) || - !read_dsp(dev, &SCSTATE->revlo)) - return -ENODEV; - printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname, - SCSTATE->revhi, SCSTATE->revlo); - if (SCSTATE->revhi < 2) { - printk(KERN_ERR "%s: your card is an antiquity, at least DSP " - "rev 2.00 required\n", sm_drvname); - return -ENODEV; - } - if (SCSTATE->revhi < 3 && - (SCSTATE->fmt[0] >= 180 || SCSTATE->fmt[1] >= 180)) { - printk(KERN_ERR "%s: sbc io 0x%lx: DSP rev %d.%02d too " - "old, at least 3.00 required\n", sm_drvname, - dev->base_addr, SCSTATE->revhi, SCSTATE->revlo); - return -ENODEV; - } - if (SCSTATE->revhi >= 4 && - (err = config_resources(dev, sm, 0))) { - printk(KERN_ERR "%s: invalid IRQ and/or DMA specified\n", sm_drvname); - return err; - } - /* - * initialize some variables - */ - dma_init_receive(sm); - dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz; - u = NUM_FRAGMENTS * sm->dma.ofragsz; - if (u > dmasz) - dmasz = u; - if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - dma_init_transmit(sm); - dma_init_receive(sm); - - memset(&sm->m, 0, sizeof(sm->m)); - memset(&sm->d, 0, sizeof(sm->d)); - if (sm->mode_tx->init) - sm->mode_tx->init(sm); - if (sm->mode_rx->init) - sm->mode_rx->init(sm); - - if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree(sm->dma.obuf); - return -EBUSY; - } - if (request_irq(dev->irq, sbc_interrupt, SA_INTERRUPT, - sm->hwdrv->hw_name, dev)) { - free_dma(dev->dma); - kfree(sm->dma.obuf); - return -EBUSY; - } - request_region(dev->base_addr, SBC_EXTENT, sm->hwdrv->hw_name); - setup_dma_dsp(dev, sm, 0); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sbc_close(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm) - return -EINVAL; - /* - * disable interrupts - */ - disable_dma(dev->dma); - reset_dsp(dev); - free_irq(dev->irq, dev); - free_dma(dev->dma); - release_region(dev->base_addr, SBC_EXTENT); - kfree(sm->dma.obuf); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sbc_sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, '.'); - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp; - - if (!strcmp(mode, "off")) { - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return 0; - } - if (cp) - *cp++ = '\0'; - else - cp = mode; - for (; *mtp; mtp++) { - if ((*mtp)->loc_storage > sizeof(sm->m)) { - printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n", - sm_drvname, (*mtp)->name, (*mtp)->loc_storage); - continue; - } - if (!(*mtp)->name || strcmp((*mtp)->name, mode)) - continue; - if ((*mtp)->srate < 5000 || (*mtp)->srate > 44100) - continue; - if (!(*mtp)->modulator_u8) - continue; - for (mrp = sm_modem_rx_table; *mrp; mrp++) { - if ((*mrp)->loc_storage > sizeof(sm->d)) { - printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n", - sm_drvname, (*mrp)->name, (*mrp)->loc_storage); - continue; - } - if (!(*mrp)->demodulator_u8) - continue; - if ((*mrp)->name && !strcmp((*mrp)->name, cp) && - (*mrp)->srate >= 5000 && (*mrp)->srate <= 44100) { - sm->mode_tx = *mtp; - sm->mode_rx = *mrp; - SCSTATE->fmt[0] = 256-((1000000L+sm->mode_rx->srate/2)/ - sm->mode_rx->srate); - SCSTATE->fmt[1] = 256-((1000000L+sm->mode_tx->srate/2)/ - sm->mode_tx->srate); - sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100; - sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100; - if (sm->dma.ifragsz < sm->mode_rx->overlap) - sm->dma.ifragsz = sm->mode_rx->overlap; - sm->dma.i16bit = sm->dma.o16bit = 0; - return 0; - } - } - } - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int sbc_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - struct sm_ioctl bi; - unsigned long flags; - int i; - - if (cmd != SIOCDEVPRIVATE) - return -ENOIOCTLCMD; - - if (hi->cmd == HDLCDRVCTL_MODEMPARMASK) - return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | - HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_SERIOBASE | - HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE; - - if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi))) - return -EFAULT; - - switch (bi.cmd) { - default: - return -ENOIOCTLCMD; - - case SMCTL_GETMIXER: - i = 0; - bi.data.mix.sample_rate = sm->mode_rx->srate; - bi.data.mix.bit_rate = sm->hdrv.par.bitrate; - bi.data.mix.mixer_type = SM_MIXER_INVALID; - switch (SCSTATE->revhi) { - case 2: - bi.data.mix.mixer_type = SM_MIXER_CT1335; - break; - case 3: - bi.data.mix.mixer_type = SM_MIXER_CT1345; - break; - case 4: - bi.data.mix.mixer_type = SM_MIXER_CT1745; - break; - } - if (bi.data.mix.mixer_type != SM_MIXER_INVALID && - bi.data.mix.reg < 0x80) { - save_flags(flags); - cli(); - outb(bi.data.mix.reg, DSP_MIXER_ADDR(dev->base_addr)); - bi.data.mix.data = inb(DSP_MIXER_DATA(dev->base_addr)); - restore_flags(flags); - i = 1; - } - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return i; - - case SMCTL_SETMIXER: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - switch (SCSTATE->revhi) { - case 2: - if (bi.data.mix.mixer_type != SM_MIXER_CT1335) - return -EINVAL; - break; - case 3: - if (bi.data.mix.mixer_type != SM_MIXER_CT1345) - return -EINVAL; - break; - case 4: - if (bi.data.mix.mixer_type != SM_MIXER_CT1745) - return -EINVAL; - break; - default: - return -ENODEV; - } - if (bi.data.mix.reg >= 0x80) - return -EACCES; - save_flags(flags); - cli(); - outb(bi.data.mix.reg, DSP_MIXER_ADDR(dev->base_addr)); - outb(bi.data.mix.data, DSP_MIXER_DATA(dev->base_addr)); - restore_flags(flags); - return 0; - - } - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - -} - -/* --------------------------------------------------------------------- */ - -const struct hardware_info sm_hw_sbc = { - "sbc", sizeof(struct sc_state_sbc), - sbc_open, sbc_close, sbc_ioctl, sbc_sethw -}; - -/* --------------------------------------------------------------------- */ - -static void setup_dma_fdx_dsp(struct net_device *dev, struct sm_state *sm) -{ - unsigned long flags; - unsigned int isamps, osamps; - - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname); - return; - } - save_flags(flags); - cli(); - sbc_int_ack_8bit(dev); - sbc_int_ack_16bit(dev); - /* should eventually change to set rates individually by SBC_SAMPLE_RATE_{IN/OUT} */ - write_dsp(dev, SBC_SAMPLE_RATE_IN); - write_dsp(dev, SCSTATE->sr[0] >> 8); - write_dsp(dev, SCSTATE->sr[0] & 0xff); - write_dsp(dev, SBC_SAMPLE_RATE_OUT); - write_dsp(dev, SCSTATE->sr[1] >> 8); - write_dsp(dev, SCSTATE->sr[1] & 0xff); - write_dsp(dev, SBC_SPEAKER_ON); - if (sm->dma.o16bit) { - /* - * DMA channel 1 (8bit) does input (capture), - * DMA channel 2 (16bit) does output (playback) - */ - isamps = dma_setup(sm, 0, dev->dma) - 1; - osamps = dma_setup(sm, 1, sm->hdrv.ptt_out.dma2) - 1; - sbc_int_ack_8bit(dev); - sbc_int_ack_16bit(dev); - write_dsp(dev, SBC4_IN8_AI); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, isamps & 0xff); - write_dsp(dev, isamps >> 8); - write_dsp(dev, SBC4_OUT16_AI); - write_dsp(dev, SBC4_MODE_SIGN_MONO); - write_dsp(dev, osamps & 0xff); - write_dsp(dev, osamps >> 8); - } else { - /* - * DMA channel 1 (8bit) does output (playback), - * DMA channel 2 (16bit) does input (capture) - */ - isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1; - osamps = dma_setup(sm, 1, dev->dma) - 1; - sbc_int_ack_8bit(dev); - sbc_int_ack_16bit(dev); - write_dsp(dev, SBC4_OUT8_AI); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, osamps & 0xff); - write_dsp(dev, osamps >> 8); - write_dsp(dev, SBC4_IN16_AI); - write_dsp(dev, SBC4_MODE_SIGN_MONO); - write_dsp(dev, isamps & 0xff); - write_dsp(dev, isamps >> 8); - } - dma_init_receive(sm); - dma_init_transmit(sm); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbcfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned char intsrc, pbint = 0, captint = 0; - unsigned int ocfrag, icfrag; - unsigned long flags; - - if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC) - return; - save_flags(flags); - cli(); - outb(0x82, DSP_MIXER_ADDR(dev->base_addr)); - intsrc = inb(DSP_MIXER_DATA(dev->base_addr)); - if (intsrc & 0x01) { - sbc_int_ack_8bit(dev); - if (sm->dma.o16bit) { - captint = 1; - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - dma_ptr(sm, 0, dev->dma, &icfrag); - enable_dma(dev->dma); - } else { - pbint = 1; - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - dma_ptr(sm, 1, dev->dma, &ocfrag); - enable_dma(dev->dma); - } - } - if (intsrc & 0x02) { - sbc_int_ack_16bit(dev); - if (sm->dma.o16bit) { - pbint = 1; - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - dma_ptr(sm, 1, sm->hdrv.ptt_out.dma2, &ocfrag); - enable_dma(sm->hdrv.ptt_out.dma2); - } else { - captint = 1; - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag); - enable_dma(sm->hdrv.ptt_out.dma2); - } - } - restore_flags(flags); - sm_int_freq(sm); - sti(); - if (pbint) { - if (dma_end_transmit(sm, ocfrag)) - dma_clear_transmit(sm); - dma_transmit(sm); - } - if (captint) { - dma_receive(sm, icfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - } - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); -} - -/* --------------------------------------------------------------------- */ - -static int sbcfdx_open(struct net_device *dev, struct sm_state *sm) -{ - int err; - - if (sizeof(sm->m) < sizeof(struct sc_state_sbc)) { - printk(KERN_ERR "sm sbc: sbc state too big: %d > %d\n", - sizeof(struct sc_state_sbc), sizeof(sm->m)); - return -ENODEV; - } - if (!dev || !sm) - return -ENXIO; - if (dev->base_addr <= 0 || dev->base_addr > 0x1000-SBC_EXTENT || - dev->irq < 2 || dev->irq > 15 || dev->dma > 3) - return -ENXIO; - if (check_region(dev->base_addr, SBC_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n", - sm_drvname, dev->base_addr); - return -ENODEV; - } - write_dsp(dev, SBC_GET_REVISION); - if (!read_dsp(dev, &SCSTATE->revhi) || - !read_dsp(dev, &SCSTATE->revlo)) - return -ENODEV; - printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname, - SCSTATE->revhi, SCSTATE->revlo); - if (SCSTATE->revhi < 4) { - printk(KERN_ERR "%s: at least DSP rev 4.00 required\n", sm_drvname); - return -ENODEV; - } - if ((err = config_resources(dev, sm, 1))) { - printk(KERN_ERR "%s: invalid IRQ and/or DMA specified\n", sm_drvname); - return err; - } - /* - * initialize some variables - */ - if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) { - kfree(sm->dma.ibuf); - return -ENOMEM; - } - dma_init_transmit(sm); - dma_init_receive(sm); - - memset(&sm->m, 0, sizeof(sm->m)); - memset(&sm->d, 0, sizeof(sm->d)); - if (sm->mode_tx->init) - sm->mode_tx->init(sm); - if (sm->mode_rx->init) - sm->mode_rx->init(sm); - - if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - return -EBUSY; - } - if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - free_dma(dev->dma); - return -EBUSY; - } - if (request_irq(dev->irq, sbcfdx_interrupt, SA_INTERRUPT, - sm->hwdrv->hw_name, dev)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - free_dma(dev->dma); - free_dma(sm->hdrv.ptt_out.dma2); - return -EBUSY; - } - request_region(dev->base_addr, SBC_EXTENT, sm->hwdrv->hw_name); - setup_dma_fdx_dsp(dev, sm); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sbcfdx_close(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm) - return -EINVAL; - /* - * disable interrupts - */ - disable_dma(dev->dma); - disable_dma(sm->hdrv.ptt_out.dma2); - reset_dsp(dev); - free_irq(dev->irq, dev); - free_dma(dev->dma); - free_dma(sm->hdrv.ptt_out.dma2); - release_region(dev->base_addr, SBC_EXTENT); - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sbcfdx_sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, '.'); - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp; - - if (!strcmp(mode, "off")) { - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return 0; - } - if (cp) - *cp++ = '\0'; - else - cp = mode; - for (; *mtp; mtp++) { - if ((*mtp)->loc_storage > sizeof(sm->m)) { - printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n", - sm_drvname, (*mtp)->name, (*mtp)->loc_storage); - continue; - } - if (!(*mtp)->name || strcmp((*mtp)->name, mode)) - continue; - if ((*mtp)->srate < 5000 || (*mtp)->srate > 44100) - continue; - for (mrp = sm_modem_rx_table; *mrp; mrp++) { - if ((*mrp)->loc_storage > sizeof(sm->d)) { - printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n", - sm_drvname, (*mrp)->name, (*mrp)->loc_storage); - continue; - } - if ((*mrp)->name && !strcmp((*mrp)->name, cp) && - (*mtp)->srate >= 5000 && (*mtp)->srate <= 44100 && - (*mrp)->srate == (*mtp)->srate) { - sm->mode_tx = *mtp; - sm->mode_rx = *mrp; - SCSTATE->sr[0] = sm->mode_rx->srate; - SCSTATE->sr[1] = sm->mode_tx->srate; - sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100; - sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100; - if (sm->dma.ifragsz < sm->mode_rx->overlap) - sm->dma.ifragsz = sm->mode_rx->overlap; - if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_u8) { - sm->dma.i16bit = 1; - sm->dma.o16bit = 0; - sm->dma.ifragsz <<= 1; - } else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_s16) { - sm->dma.i16bit = 0; - sm->dma.o16bit = 1; - sm->dma.ofragsz <<= 1; - } else { - printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, - sm->mode_rx->name, sm->mode_tx->name); - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return -EINVAL; - } - return 0; - } - } - } - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int sbcfdx_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - if (cmd != SIOCDEVPRIVATE) - return -ENOIOCTLCMD; - - if (hi->cmd == HDLCDRVCTL_MODEMPARMASK) - return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | - HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_DMA2 | HDLCDRV_PARMASK_SERIOBASE | - HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE; - - return sbc_ioctl(dev, sm, ifr, hi, cmd); -} - -/* --------------------------------------------------------------------- */ - -const struct hardware_info sm_hw_sbcfdx = { - "sbcfdx", sizeof(struct sc_state_sbc), - sbcfdx_open, sbcfdx_close, sbcfdx_ioctl, sbcfdx_sethw -}; - -/* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/soundmodem/sm_wss.c b/drivers/net/hamradio/soundmodem/sm_wss.c --- a/drivers/net/hamradio/soundmodem/sm_wss.c Wed Nov 27 14:36:29 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,968 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_wss.c -- soundcard radio modem driver, WSS (half duplex) driver - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include -#include -#include -#include - -#include -#include - -#include "sm.h" -#include "smdma.h" - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 -#include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -static inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -static inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -/* --------------------------------------------------------------------- */ - -struct sc_state_wss { - unsigned char revwss, revid, revv, revcid; - unsigned char fmt[2]; - unsigned char crystal; -}; - -#define SCSTATE ((struct sc_state_wss *)(&sm->hw)) - -/* --------------------------------------------------------------------- */ - -#define WSS_CONFIG(iobase) (iobase+0) -#define WSS_STATUS(iobase) (iobase+3) -#define WSS_CODEC_IA(iobase) (iobase+4) -#define WSS_CODEC_ID(iobase) (iobase+5) -#define WSS_CODEC_STATUS(iobase) (iobase+6) -#define WSS_CODEC_DATA(iobase) (iobase+7) - -#define WSS_EXTENT 8 - -#define CS423X_HOTFIX - -/* --------------------------------------------------------------------- */ - -static void write_codec(struct net_device *dev, unsigned char idx, - unsigned char data) -{ - int timeout = 900000; - - /* wait until codec ready */ - while (timeout > 0 && inb(WSS_CODEC_IA(dev->base_addr)) & 0x80) - timeout--; - outb(idx, WSS_CODEC_IA(dev->base_addr)); - outb(data, WSS_CODEC_ID(dev->base_addr)); -} - - -/* --------------------------------------------------------------------- */ - -static unsigned char read_codec(struct net_device *dev, unsigned char idx) -{ - int timeout = 900000; - - /* wait until codec ready */ - while (timeout > 0 && inb(WSS_CODEC_IA(dev->base_addr)) & 0x80) - timeout--; - outb(idx & 0x1f, WSS_CODEC_IA(dev->base_addr)); - return inb(WSS_CODEC_ID(dev->base_addr)); -} - -/* --------------------------------------------------------------------- */ - -extern void inline wss_ack_int(struct net_device *dev) -{ - outb(0, WSS_CODEC_STATUS(dev->base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static int wss_srate_tab[16] = { - 8000, 5510, 16000, 11025, 27420, 18900, 32000, 22050, - -1, 37800, -1, 44100, 48000, 33075, 9600, 6620 -}; - -static int wss_srate_index(int srate) -{ - int i; - - for (i = 0; i < (sizeof(wss_srate_tab)/sizeof(wss_srate_tab[0])); i++) - if (srate == wss_srate_tab[i] && wss_srate_tab[i] > 0) - return i; - return -1; -} - -/* --------------------------------------------------------------------- */ - -static int wss_set_codec_fmt(struct net_device *dev, struct sm_state *sm, unsigned char fmt, - unsigned char fmt2, char fdx, char fullcalib) -{ - unsigned long time; - unsigned long flags; - - save_flags(flags); - cli(); - /* Clock and data format register */ - write_codec(dev, 0x48, fmt); - if (SCSTATE->crystal) { - write_codec(dev, 0x5c, fmt2 & 0xf0); - /* MCE and interface config reg */ - write_codec(dev, 0x49, (fdx ? 0 : 0x4) | (fullcalib ? 0x18 : 0)); - } else - /* MCE and interface config reg */ - write_codec(dev, 0x49, fdx ? 0x8 : 0xc); - outb(0xb, WSS_CODEC_IA(dev->base_addr)); /* leave MCE */ - if (SCSTATE->crystal && !fullcalib) { - restore_flags(flags); - return 0; - } - /* - * wait for ACI start - */ - time = 1000; - while (!(read_codec(dev, 0x0b) & 0x20)) - if (!(--time)) { - printk(KERN_WARNING "%s: ad1848 auto calibration timed out (1)\n", - sm_drvname); - restore_flags(flags); - return -1; - } - /* - * wait for ACI end - */ - sti(); - time = jiffies + HZ/4; - while ((read_codec(dev, 0x0b) & 0x20) && ((signed)(jiffies - time) < 0)); - restore_flags(flags); - if ((signed)(jiffies - time) >= 0) { - printk(KERN_WARNING "%s: ad1848 auto calibration timed out (2)\n", - sm_drvname); - return -1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wss_init_codec(struct net_device *dev, struct sm_state *sm, char fdx, - unsigned char src_l, unsigned char src_r, - int igain_l, int igain_r, - int ogain_l, int ogain_r) -{ - unsigned char tmp, reg0, reg1, reg6, reg7; - static const signed char irqtab[16] = - { -1, -1, 0x10, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20, -1, -1, - -1, -1 }; - static const signed char dmatab[4] = { 1, 2, -1, 3 }; - - tmp = inb(WSS_STATUS(dev->base_addr)); - if ((tmp & 0x3f) != 0x04 && (tmp & 0x3f) != 0x00 && - (tmp & 0x3f) != 0x0f) { - printk(KERN_WARNING "sm: WSS card id register not found, " - "address 0x%lx, ID register 0x%02x\n", - dev->base_addr, (int)tmp); - /* return -1; */ - SCSTATE->revwss = 0; - } else { - if ((tmp & 0x80) && ((dev->dma == 0) || - ((dev->irq >= 8) && (dev->irq != 9)))) { - printk(KERN_ERR "%s: WSS: DMA0 and/or IRQ8..IRQ15 " - "(except IRQ9) cannot be used on an 8bit " - "card\n", sm_drvname); - return -1; - } - if (dev->irq > 15 || irqtab[dev->irq] == -1) { - printk(KERN_ERR "%s: WSS: invalid interrupt %d\n", - sm_drvname, (int)dev->irq); - return -1; - } - if (dev->dma > 3 || dmatab[dev->dma] == -1) { - printk(KERN_ERR "%s: WSS: invalid dma channel %d\n", - sm_drvname, (int)dev->dma); - return -1; - } - tmp = irqtab[dev->irq] | dmatab[dev->dma]; - /* irq probe */ - outb((tmp & 0x38) | 0x40, WSS_CONFIG(dev->base_addr)); - if (!(inb(WSS_STATUS(dev->base_addr)) & 0x40)) { - outb(0, WSS_CONFIG(dev->base_addr)); - printk(KERN_ERR "%s: WSS: IRQ%d is not free!\n", - sm_drvname, dev->irq); - } - outb(tmp, WSS_CONFIG(dev->base_addr)); - SCSTATE->revwss = inb(WSS_STATUS(dev->base_addr)) & 0x3f; - } - /* - * initialize the codec - */ - if (igain_l < 0) - igain_l = 0; - if (igain_r < 0) - igain_r = 0; - if (ogain_l > 0) - ogain_l = 0; - if (ogain_r > 0) - ogain_r = 0; - reg0 = (src_l << 6) & 0xc0; - reg1 = (src_r << 6) & 0xc0; - if (reg0 == 0x80 && igain_l >= 20) { - reg0 |= 0x20; - igain_l -= 20; - } - if (reg1 == 0x80 && igain_r >= 20) { - reg1 |= 0x20; - igain_r -= 20; - } - if (igain_l > 23) - igain_l = 23; - if (igain_r > 23) - igain_r = 23; - reg0 |= igain_l * 2 / 3; - reg1 |= igain_r * 2 / 3; - reg6 = (ogain_l < -95) ? 0x80 : (ogain_l * (-2) / 3); - reg7 = (ogain_r < -95) ? 0x80 : (ogain_r * (-2) / 3); - write_codec(dev, 9, 0); - write_codec(dev, 0, 0x45); - if (read_codec(dev, 0) != 0x45) - goto codec_err; - write_codec(dev, 0, 0xaa); - if (read_codec(dev, 0) != 0xaa) - goto codec_err; - write_codec(dev, 12, 0x40); /* enable MODE2 */ - write_codec(dev, 16, 0); - write_codec(dev, 0, 0x45); - SCSTATE->crystal = (read_codec(dev, 16) != 0x45); - write_codec(dev, 0, 0xaa); - SCSTATE->crystal &= (read_codec(dev, 16) != 0xaa); - if (SCSTATE->crystal) { - SCSTATE->revcid = read_codec(dev, 0x19); - SCSTATE->revv = (SCSTATE->revcid >> 5) & 7; - SCSTATE->revcid &= 7; - write_codec(dev, 0x10, 0x80); /* maximum output level */ - write_codec(dev, 0x11, 0x02); /* xtal enable and no HPF */ - write_codec(dev, 0x12, 0x80); /* left line input control */ - write_codec(dev, 0x13, 0x80); /* right line input control */ - write_codec(dev, 0x16, 0); /* disable alternative freq sel */ - write_codec(dev, 0x1a, 0xe0); /* mono IO disable */ - write_codec(dev, 0x1b, 0x00); /* left out no att */ - write_codec(dev, 0x1d, 0x00); /* right out no att */ - } - - if (wss_set_codec_fmt(dev, sm, SCSTATE->fmt[0], SCSTATE->fmt[0], fdx, 1)) - goto codec_err; - - write_codec(dev, 0, reg0); /* left input control */ - write_codec(dev, 1, reg1); /* right input control */ - write_codec(dev, 2, 0x80); /* left aux#1 input control */ - write_codec(dev, 3, 0x80); /* right aux#1 input control */ - write_codec(dev, 4, 0x80); /* left aux#2 input control */ - write_codec(dev, 5, 0x80); /* right aux#2 input control */ - write_codec(dev, 6, reg6); /* left dac control */ - write_codec(dev, 7, reg7); /* right dac control */ - write_codec(dev, 0xa, 0x2); /* pin control register */ - write_codec(dev, 0xd, 0x0); /* digital mix control */ - SCSTATE->revid = read_codec(dev, 0xc) & 0xf; - /* - * print revisions - */ - if (SCSTATE->crystal) - printk(KERN_INFO "%s: Crystal CODEC ID %d, Chip revision %d, " - " Chip ID %d\n", sm_drvname, (int)SCSTATE->revid, - (int)SCSTATE->revv, (int)SCSTATE->revcid); - else - printk(KERN_INFO "%s: WSS revision %d, CODEC revision %d\n", - sm_drvname, (int)SCSTATE->revwss, - (int)SCSTATE->revid); - return 0; - codec_err: - outb(0, WSS_CONFIG(dev->base_addr)); - printk(KERN_ERR "%s: no WSS soundcard found at address 0x%lx\n", - sm_drvname, dev->base_addr); - return -1; -} - -/* --------------------------------------------------------------------- */ - -static void setup_dma_wss(struct net_device *dev, struct sm_state *sm, int send) -{ - unsigned long flags; - static const unsigned char codecmode[2] = { 0x0e, 0x0d }; - unsigned char oldcodecmode; - long abrt; - unsigned char fmt; - unsigned int numsamps; - - send = !!send; - fmt = SCSTATE->fmt[send]; - save_flags(flags); - cli(); - /* - * perform the final DMA sequence to disable the codec request - */ - oldcodecmode = read_codec(dev, 9); - write_codec(dev, 9, 0xc); /* disable codec */ - wss_ack_int(dev); - if (read_codec(dev, 11) & 0x10) { - dma_setup(sm, oldcodecmode & 1, dev->dma); - abrt = 0; - while ((read_codec(dev, 11) & 0x10) || ((++abrt) >= 0x10000)); - } -#ifdef CS423X_HOTFIX - if (read_codec(dev, 0x8) != fmt || SCSTATE->crystal) - wss_set_codec_fmt(dev, sm, fmt, fmt, 0, 0); -#else /* CS423X_HOTFIX */ - if (read_codec(dev, 0x8) != fmt) - wss_set_codec_fmt(dev, sm, fmt, fmt, 0, 0); -#endif /* CS423X_HOTFIX */ - numsamps = dma_setup(sm, send, dev->dma) - 1; - write_codec(dev, 15, numsamps & 0xff); - write_codec(dev, 14, numsamps >> 8); - write_codec(dev, 9, codecmode[send]); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned int curfrag; - unsigned int nums; - - if (!dev || !sm || !sm->mode_rx || !sm->mode_tx || - sm->hdrv.magic != HDLCDRV_MAGIC) - return; - cli(); - wss_ack_int(dev); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - nums = dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag) - 1; - write_codec(dev, 15, nums & 0xff); - write_codec(dev, 14, nums >> 8); - enable_dma(dev->dma); - sm_int_freq(sm); - sti(); - if (sm->dma.ptt_cnt <= 0) { - dma_receive(sm, curfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - if (hdlcdrv_ptt(&sm->hdrv)) { - /* starting to transmit */ - disable_dma(dev->dma); - hdlcdrv_transmitter(dev, &sm->hdrv); /* prefill HDLC buffer */ - dma_start_transmit(sm); - setup_dma_wss(dev, sm, 1); - dma_transmit(sm); - } - } else if (dma_end_transmit(sm, curfrag)) { - /* stopping transmission */ - disable_dma(dev->dma); - dma_init_receive(sm); - setup_dma_wss(dev, sm, 0); - } else - dma_transmit(sm); - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); -} - -/* --------------------------------------------------------------------- */ - -static int wss_open(struct net_device *dev, struct sm_state *sm) -{ - unsigned int dmasz, u; - - if (sizeof(sm->m) < sizeof(struct sc_state_wss)) { - printk(KERN_ERR "sm wss: wss state too big: %d > %d\n", - sizeof(struct sc_state_wss), sizeof(sm->m)); - return -ENODEV; - } - if (!dev || !sm || !sm->mode_rx || !sm->mode_tx) - return -ENXIO; - if (dev->base_addr <= 0 || dev->base_addr > 0x1000-WSS_EXTENT || - dev->irq < 2 || dev->irq > 15 || dev->dma > 3) - return -ENXIO; - if (check_region(dev->base_addr, WSS_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (wss_init_codec(dev, sm, 0, 1, 1, 0, 0, -45, -45)) - return -ENODEV; - /* - * initialize some variables - */ - dma_init_receive(sm); - dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz; - u = NUM_FRAGMENTS * sm->dma.ofragsz; - if (u > dmasz) - dmasz = u; - if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - dma_init_transmit(sm); - dma_init_receive(sm); - - memset(&sm->m, 0, sizeof(sm->m)); - memset(&sm->d, 0, sizeof(sm->d)); - if (sm->mode_tx->init) - sm->mode_tx->init(sm); - if (sm->mode_rx->init) - sm->mode_rx->init(sm); - - if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree(sm->dma.obuf); - return -EBUSY; - } - if (request_irq(dev->irq, wss_interrupt, SA_INTERRUPT, - sm->hwdrv->hw_name, dev)) { - free_dma(dev->dma); - kfree(sm->dma.obuf); - return -EBUSY; - } - request_region(dev->base_addr, WSS_EXTENT, sm->hwdrv->hw_name); - setup_dma_wss(dev, sm, 0); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wss_close(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm) - return -EINVAL; - /* - * disable interrupts - */ - disable_dma(dev->dma); - write_codec(dev, 9, 0xc); /* disable codec */ - free_irq(dev->irq, dev); - free_dma(dev->dma); - release_region(dev->base_addr, WSS_EXTENT); - kfree(sm->dma.obuf); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wss_sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, '.'); - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp; - int i, j; - - if (!strcmp(mode, "off")) { - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return 0; - } - if (cp) - *cp++ = '\0'; - else - cp = mode; - for (; *mtp; mtp++) { - if ((*mtp)->loc_storage > sizeof(sm->m)) { - printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n", - sm_drvname, (*mtp)->name, (*mtp)->loc_storage); - continue; - } - if (!(*mtp)->name || strcmp((*mtp)->name, mode)) - continue; - if ((i = wss_srate_index((*mtp)->srate)) < 0) - continue; - for (mrp = sm_modem_rx_table; *mrp; mrp++) { - if ((*mrp)->loc_storage > sizeof(sm->d)) { - printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n", - sm_drvname, (*mrp)->name, (*mrp)->loc_storage); - continue; - } - if ((*mrp)->name && !strcmp((*mrp)->name, cp) && - ((j = wss_srate_index((*mrp)->srate)) >= 0)) { - sm->mode_tx = *mtp; - sm->mode_rx = *mrp; - SCSTATE->fmt[0] = j; - SCSTATE->fmt[1] = i; - sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100; - sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100; - if (sm->dma.ifragsz < sm->mode_rx->overlap) - sm->dma.ifragsz = sm->mode_rx->overlap; - /* prefer same data format if possible to minimize switching times */ - sm->dma.i16bit = sm->dma.o16bit = 2; - if (sm->mode_rx->srate == sm->mode_tx->srate) { - if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_s16) - sm->dma.i16bit = sm->dma.o16bit = 1; - else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_u8) - sm->dma.i16bit = sm->dma.o16bit = 0; - } - if (sm->dma.i16bit == 2) { - if (sm->mode_rx->demodulator_s16) - sm->dma.i16bit = 1; - else if (sm->mode_rx->demodulator_u8) - sm->dma.i16bit = 0; - } - if (sm->dma.o16bit == 2) { - if (sm->mode_tx->modulator_s16) - sm->dma.o16bit = 1; - else if (sm->mode_tx->modulator_u8) - sm->dma.o16bit = 0; - } - if (sm->dma.i16bit == 2 || sm->dma.o16bit == 2) { - printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, - sm->mode_rx->name, sm->mode_tx->name); - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return -EINVAL; - } -#ifdef __BIG_ENDIAN - /* big endian 16bit only works on crystal cards... */ - if (sm->dma.i16bit) { - SCSTATE->fmt[0] |= 0xc0; - sm->dma.ifragsz <<= 1; - } - if (sm->dma.o16bit) { - SCSTATE->fmt[1] |= 0xc0; - sm->dma.ofragsz <<= 1; - } -#else /* __BIG_ENDIAN */ - if (sm->dma.i16bit) { - SCSTATE->fmt[0] |= 0x40; - sm->dma.ifragsz <<= 1; - } - if (sm->dma.o16bit) { - SCSTATE->fmt[1] |= 0x40; - sm->dma.ofragsz <<= 1; - } -#endif /* __BIG_ENDIAN */ - return 0; - } - } - } - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int wss_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - struct sm_ioctl bi; - int i; - - if (cmd != SIOCDEVPRIVATE) - return -ENOIOCTLCMD; - - if (hi->cmd == HDLCDRVCTL_MODEMPARMASK) - return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | - HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_SERIOBASE | - HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE; - - if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi))) - return -EFAULT; - - switch (bi.cmd) { - default: - return -ENOIOCTLCMD; - - case SMCTL_GETMIXER: - i = 0; - bi.data.mix.sample_rate = sm->mode_rx->srate; - bi.data.mix.bit_rate = sm->hdrv.par.bitrate; - bi.data.mix.mixer_type = SCSTATE->crystal ? - SM_MIXER_CRYSTAL : SM_MIXER_AD1848; - if (((SCSTATE->crystal ? 0x2c0c20fflu: 0x20fflu) - >> bi.data.mix.reg) & 1) { - bi.data.mix.data = read_codec(dev, bi.data.mix.reg); - i = 1; - } - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return i; - - case SMCTL_SETMIXER: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - if ((bi.data.mix.mixer_type != SM_MIXER_CRYSTAL || - !SCSTATE->crystal) && - (bi.data.mix.mixer_type != SM_MIXER_AD1848 || - bi.data.mix.reg >= 0x10)) - return -EINVAL; - if (!((0x2c0c20fflu >> bi.data.mix.reg) & 1)) - return -EACCES; - write_codec(dev, bi.data.mix.reg, bi.data.mix.data); - return 0; - - } - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - -} - -/* --------------------------------------------------------------------- */ - -const struct hardware_info sm_hw_wss = { - "wss", sizeof(struct sc_state_wss), - wss_open, wss_close, wss_ioctl, wss_sethw -}; - -/* --------------------------------------------------------------------- */ - -static void setup_fdx_dma_wss(struct net_device *dev, struct sm_state *sm) -{ - unsigned long flags; - unsigned char oldcodecmode, codecdma; - long abrt; - unsigned int osamps, isamps; - - save_flags(flags); - cli(); - /* - * perform the final DMA sequence to disable the codec request - */ - oldcodecmode = read_codec(dev, 9); - write_codec(dev, 9, 0); /* disable codec DMA */ - wss_ack_int(dev); - if ((codecdma = read_codec(dev, 11)) & 0x10) { - dma_setup(sm, 1, dev->dma); - dma_setup(sm, 0, sm->hdrv.ptt_out.dma2); - abrt = 0; - while (((codecdma = read_codec(dev, 11)) & 0x10) || ((++abrt) >= 0x10000)); - } - wss_set_codec_fmt(dev, sm, SCSTATE->fmt[1], SCSTATE->fmt[0], 1, 1); - osamps = dma_setup(sm, 1, dev->dma) - 1; - isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1; - write_codec(dev, 15, osamps & 0xff); - write_codec(dev, 14, osamps >> 8); - if (SCSTATE->crystal) { - write_codec(dev, 31, isamps & 0xff); - write_codec(dev, 30, isamps >> 8); - } - write_codec(dev, 9, 3); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wssfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned long flags; - unsigned char cry_int_src; - unsigned icfrag, ocfrag, isamps, osamps; - - if (!dev || !sm || !sm->mode_rx || !sm->mode_tx || - sm->hdrv.magic != HDLCDRV_MAGIC) - return; - save_flags(flags); - cli(); - if (SCSTATE->crystal) { - /* Crystal has an essentially different interrupt handler! */ - cry_int_src = read_codec(dev, 0x18); - wss_ack_int(dev); - if (cry_int_src & 0x10) { /* playback interrupt */ - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1; - write_codec(dev, 15, osamps & 0xff); - write_codec(dev, 14, osamps >> 8); - enable_dma(dev->dma); - } - if (cry_int_src & 0x20) { /* capture interrupt */ - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1; - write_codec(dev, 31, isamps & 0xff); - write_codec(dev, 30, isamps >> 8); - enable_dma(sm->hdrv.ptt_out.dma2); - } - restore_flags(flags); - sm_int_freq(sm); - sti(); - if (cry_int_src & 0x10) { - if (dma_end_transmit(sm, ocfrag)) - dma_clear_transmit(sm); - dma_transmit(sm); - } - if (cry_int_src & 0x20) { - dma_receive(sm, icfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - } - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); - return; - } - wss_ack_int(dev); - disable_dma(dev->dma); - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(dev->dma); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1; - isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1; - write_codec(dev, 15, osamps & 0xff); - write_codec(dev, 14, osamps >> 8); - if (SCSTATE->crystal) { - write_codec(dev, 31, isamps & 0xff); - write_codec(dev, 30, isamps >> 8); - } - enable_dma(dev->dma); - enable_dma(sm->hdrv.ptt_out.dma2); - restore_flags(flags); - sm_int_freq(sm); - sti(); - if (dma_end_transmit(sm, ocfrag)) - dma_clear_transmit(sm); - dma_transmit(sm); - dma_receive(sm, icfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); -} - -/* --------------------------------------------------------------------- */ - -static int wssfdx_open(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm || !sm->mode_rx || !sm->mode_tx) - return -ENXIO; - if (dev->base_addr <= 0 || dev->base_addr > 0x1000-WSS_EXTENT || - dev->irq < 2 || dev->irq > 15 || dev->dma > 3) - return -ENXIO; - if (check_region(dev->base_addr, WSS_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (wss_init_codec(dev, sm, 1, 1, 1, 0, 0, -45, -45)) - return -ENODEV; - /* - * initialize some variables - */ - if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) { - kfree(sm->dma.ibuf); - return -ENOMEM; - } - dma_init_transmit(sm); - dma_init_receive(sm); - - memset(&sm->m, 0, sizeof(sm->m)); - memset(&sm->d, 0, sizeof(sm->d)); - if (sm->mode_tx->init) - sm->mode_tx->init(sm); - if (sm->mode_rx->init) - sm->mode_rx->init(sm); - - if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - return -EBUSY; - } - if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - free_dma(dev->dma); - return -EBUSY; - } - if (request_irq(dev->irq, wssfdx_interrupt, SA_INTERRUPT, - sm->hwdrv->hw_name, dev)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - free_dma(dev->dma); - free_dma(sm->hdrv.ptt_out.dma2); - return -EBUSY; - } - request_region(dev->base_addr, WSS_EXTENT, sm->hwdrv->hw_name); - setup_fdx_dma_wss(dev, sm); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wssfdx_close(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm) - return -EINVAL; - /* - * disable interrupts - */ - disable_dma(dev->dma); - disable_dma(sm->hdrv.ptt_out.dma2); - write_codec(dev, 9, 0xc); /* disable codec */ - free_irq(dev->irq, dev); - free_dma(dev->dma); - free_dma(sm->hdrv.ptt_out.dma2); - release_region(dev->base_addr, WSS_EXTENT); - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wssfdx_sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, '.'); - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp; - int i; - - if (!strcmp(mode, "off")) { - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return 0; - } - if (cp) - *cp++ = '\0'; - else - cp = mode; - for (; *mtp; mtp++) { - if ((*mtp)->loc_storage > sizeof(sm->m)) { - printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n", - sm_drvname, (*mtp)->name, (*mtp)->loc_storage); - continue; - } - if (!(*mtp)->name || strcmp((*mtp)->name, mode)) - continue; - if ((i = wss_srate_index((*mtp)->srate)) < 0) - continue; - for (mrp = sm_modem_rx_table; *mrp; mrp++) { - if ((*mrp)->loc_storage > sizeof(sm->d)) { - printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n", - sm_drvname, (*mrp)->name, (*mrp)->loc_storage); - continue; - } - if ((*mrp)->name && !strcmp((*mrp)->name, cp) && - (*mtp)->srate == (*mrp)->srate) { - sm->mode_tx = *mtp; - sm->mode_rx = *mrp; - SCSTATE->fmt[0] = SCSTATE->fmt[1] = i; - sm->dma.ifragsz = sm->dma.ofragsz = (sm->mode_rx->srate + 50)/100; - if (sm->dma.ifragsz < sm->mode_rx->overlap) - sm->dma.ifragsz = sm->mode_rx->overlap; - sm->dma.i16bit = sm->dma.o16bit = 2; - if (sm->mode_rx->demodulator_s16) { - sm->dma.i16bit = 1; - sm->dma.ifragsz <<= 1; -#ifdef __BIG_ENDIAN /* big endian 16bit only works on crystal cards... */ - SCSTATE->fmt[0] |= 0xc0; -#else /* __BIG_ENDIAN */ - SCSTATE->fmt[0] |= 0x40; -#endif /* __BIG_ENDIAN */ - } else if (sm->mode_rx->demodulator_u8) - sm->dma.i16bit = 0; - if (sm->mode_tx->modulator_s16) { - sm->dma.o16bit = 1; - sm->dma.ofragsz <<= 1; -#ifdef __BIG_ENDIAN /* big endian 16bit only works on crystal cards... */ - SCSTATE->fmt[1] |= 0xc0; -#else /* __BIG_ENDIAN */ - SCSTATE->fmt[1] |= 0x40; -#endif /* __BIG_ENDIAN */ - } else if (sm->mode_tx->modulator_u8) - sm->dma.o16bit = 0; - if (sm->dma.i16bit == 2 || sm->dma.o16bit == 2) { - printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, - sm->mode_rx->name, sm->mode_tx->name); - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return -EINVAL; - } - return 0; - } - } - } - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int wssfdx_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - if (cmd != SIOCDEVPRIVATE) - return -ENOIOCTLCMD; - - if (hi->cmd == HDLCDRVCTL_MODEMPARMASK) - return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | - HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_DMA2 | - HDLCDRV_PARMASK_SERIOBASE | HDLCDRV_PARMASK_PARIOBASE | - HDLCDRV_PARMASK_MIDIIOBASE; - - return wss_ioctl(dev, sm, ifr, hi, cmd); -} - -/* --------------------------------------------------------------------- */ - -const struct hardware_info sm_hw_wssfdx = { - "wssfdx", sizeof(struct sc_state_wss), - wssfdx_open, wssfdx_close, wssfdx_ioctl, wssfdx_sethw -}; - -/* --------------------------------------------------------------------- */ - -#undef SCSTATE diff -Nru a/drivers/net/hamradio/soundmodem/smdma.h b/drivers/net/hamradio/soundmodem/smdma.h --- a/drivers/net/hamradio/soundmodem/smdma.h Wed Nov 27 14:36:27 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,217 +0,0 @@ -/*****************************************************************************/ - -/* - * smdma.h -- soundcard radio modem driver dma buffer routines. - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#ifndef _SMDMA_H -#define _SMDMA_H - -/* ---------------------------------------------------------------------- */ - -#include "sm.h" - -/* ---------------------------------------------------------------------- */ - -#define DMA_MODE_AUTOINIT 0x10 -#define NUM_FRAGMENTS 4 - -/* - * NOTE: make sure that hdlcdrv_hdlcbuffer contains enough space - * for the modulator to fill the whole DMA buffer without underrun - * at the highest possible baud rate, otherwise the TX state machine will - * not work correctly. That is (9k6 FSK): HDLCDRV_HDLCBUFFER > 6*NUM_FRAGMENTS - */ - -/* --------------------------------------------------------------------- */ -/* - * ===================== DMA buffer management =========================== - */ - -/* - * returns the number of samples per fragment - */ -static __inline__ unsigned int dma_setup(struct sm_state *sm, int send, unsigned int dmanr) -{ - if (send) { - disable_dma(dmanr); - clear_dma_ff(dmanr); - set_dma_mode(dmanr, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dmanr, virt_to_bus(sm->dma.obuf)); - set_dma_count(dmanr, sm->dma.ofragsz * NUM_FRAGMENTS); - enable_dma(dmanr); - if (sm->dma.o16bit) - return sm->dma.ofragsz/2; - return sm->dma.ofragsz; - } else { - disable_dma(dmanr); - clear_dma_ff(dmanr); - set_dma_mode(dmanr, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(dmanr, virt_to_bus(sm->dma.ibuf)); - set_dma_count(dmanr, sm->dma.ifragsz * NUM_FRAGMENTS); - enable_dma(dmanr); - if (sm->dma.i16bit) - return sm->dma.ifragsz/2; - return sm->dma.ifragsz; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ unsigned int dma_ptr(struct sm_state *sm, int send, unsigned int dmanr, - unsigned int *curfrag) -{ - unsigned int dmaptr, sz, frg, offs; - - dmaptr = get_dma_residue(dmanr); - if (send) { - sz = sm->dma.ofragsz * NUM_FRAGMENTS; - if (dmaptr == 0 || dmaptr > sz) - dmaptr = sz; - dmaptr--; - frg = dmaptr / sm->dma.ofragsz; - offs = (dmaptr % sm->dma.ofragsz) + 1; - *curfrag = NUM_FRAGMENTS - 1 - frg; -#ifdef SM_DEBUG - if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue) - sm->debug_vals.dma_residue = offs; -#endif /* SM_DEBUG */ - if (sm->dma.o16bit) - return offs/2; - return offs; - } else { - sz = sm->dma.ifragsz * NUM_FRAGMENTS; - if (dmaptr == 0 || dmaptr > sz) - dmaptr = sz; - dmaptr--; - frg = dmaptr / sm->dma.ifragsz; - offs = (dmaptr % sm->dma.ifragsz) + 1; - *curfrag = NUM_FRAGMENTS - 1 - frg; -#ifdef SM_DEBUG - if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue) - sm->debug_vals.dma_residue = offs; -#endif /* SM_DEBUG */ - if (sm->dma.i16bit) - return offs/2; - return offs; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int dma_end_transmit(struct sm_state *sm, unsigned int curfrag) -{ - unsigned int diff = (NUM_FRAGMENTS + curfrag - sm->dma.ofragptr) % NUM_FRAGMENTS; - - sm->dma.ofragptr = curfrag; - if (sm->dma.ptt_cnt <= 0) { - sm->dma.ptt_cnt = 0; - return 0; - } - sm->dma.ptt_cnt -= diff; - if (sm->dma.ptt_cnt <= 0) { - sm->dma.ptt_cnt = 0; - return -1; - } - return 0; -} - -static __inline__ void dma_transmit(struct sm_state *sm) -{ - void *p; - - while (sm->dma.ptt_cnt < NUM_FRAGMENTS && hdlcdrv_ptt(&sm->hdrv)) { - p = (unsigned char *)sm->dma.obuf + sm->dma.ofragsz * - ((sm->dma.ofragptr + sm->dma.ptt_cnt) % NUM_FRAGMENTS); - if (sm->dma.o16bit) { - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator_s16(sm, p, sm->dma.ofragsz/2)); - } else { - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator_u8(sm, p, sm->dma.ofragsz)); - } - sm->dma.ptt_cnt++; - } -} - -static __inline__ void dma_init_transmit(struct sm_state *sm) -{ - sm->dma.ofragptr = 0; - sm->dma.ptt_cnt = 0; -} - -static __inline__ void dma_start_transmit(struct sm_state *sm) -{ - sm->dma.ofragptr = 0; - if (sm->dma.o16bit) { - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator_s16(sm, sm->dma.obuf, sm->dma.ofragsz/2)); - } else { - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator_u8(sm, sm->dma.obuf, sm->dma.ofragsz)); - } - sm->dma.ptt_cnt = 1; -} - -static __inline__ void dma_clear_transmit(struct sm_state *sm) -{ - sm->dma.ptt_cnt = 0; - memset(sm->dma.obuf, (sm->dma.o16bit) ? 0 : 0x80, sm->dma.ofragsz * NUM_FRAGMENTS); -} - -/* --------------------------------------------------------------------- */ - -static __inline__ void dma_receive(struct sm_state *sm, unsigned int curfrag) -{ - void *p; - - while (sm->dma.ifragptr != curfrag) { - if (sm->dma.ifragptr) - p = (unsigned char *)sm->dma.ibuf + - sm->dma.ifragsz * sm->dma.ifragptr; - else { - p = (unsigned char *)sm->dma.ibuf + NUM_FRAGMENTS * sm->dma.ifragsz; - memcpy(p, sm->dma.ibuf, sm->dma.ifragsz); - } - if (sm->dma.o16bit) { - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator_s16(sm, p, sm->dma.ifragsz/2)); - } else { - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator_u8(sm, p, sm->dma.ifragsz)); - } - sm->dma.ifragptr = (sm->dma.ifragptr + 1) % NUM_FRAGMENTS; - } -} - -static __inline__ void dma_init_receive(struct sm_state *sm) -{ - sm->dma.ifragptr = 0; -} - -/* --------------------------------------------------------------------- */ -#endif /* _SMDMA_H */ - - - diff -Nru a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c --- a/drivers/net/irda/ali-ircc.c Wed Nov 27 14:36:29 2002 +++ b/drivers/net/irda/ali-ircc.c Wed Nov 27 14:36:29 2002 @@ -281,15 +281,13 @@ self->io.fifo_size = 16; /* SIR: 16, FIR: 32 Benjamin 2000/11/1 */ /* Reserve the ioports that we need */ - ret = check_region(self->io.fir_base, self->io.fir_ext); - if (ret < 0) { + if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) { WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__, self->io.fir_base); dev_self[i] = NULL; kfree(self); return -ENODEV; } - request_region(self->io.fir_base, self->io.fir_ext, driver_name); /* Initialize QoS for this device */ irda_init_max_qos_capabilies(&self->qos); diff -Nru a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c --- a/drivers/net/irda/vlsi_ir.c Wed Nov 27 14:36:27 2002 +++ b/drivers/net/irda/vlsi_ir.c Wed Nov 27 14:36:27 2002 @@ -162,7 +162,7 @@ return 0; out += sprintf(out, "\n%s (vid/did: %04x/%04x)\n", - pdev->name, (int)pdev->vendor, (int)pdev->device); + pdev->dev.name, (int)pdev->vendor, (int)pdev->device); out += sprintf(out, "pci-power-state: %u\n", (unsigned) pdev->current_state); out += sprintf(out, "resources: irq=%u / io=0x%04x / dma_mask=0x%016Lx\n", pdev->irq, (unsigned)pci_resource_start(pdev, 0), (u64)pdev->dma_mask); @@ -1517,7 +1517,7 @@ if (vlsi_start_hw(idev)) printk(KERN_CRIT "%s: failed to restart hw - %s(%s) unusable!\n", - __FUNCTION__, idev->pdev->name, ndev->name); + __FUNCTION__, idev->pdev->dev.name, ndev->name); else netif_start_queue(ndev); } @@ -1765,7 +1765,7 @@ pdev->current_state = 0; /* hw must be running now */ printk(KERN_INFO "%s: IrDA PCI controller %s detected\n", - drivername, pdev->name); + drivername, pdev->dev.name); if ( !pci_resource_start(pdev,0) || !(pci_resource_flags(pdev,0) & IORESOURCE_IO) ) { @@ -1863,7 +1863,7 @@ * ndev->destructor called (if present) when going to free */ - printk(KERN_INFO "%s: %s removed\n", drivername, pdev->name); + printk(KERN_INFO "%s: %s removed\n", drivername, pdev->dev.name); } #ifdef CONFIG_PM @@ -1879,7 +1879,7 @@ { if (state < 1 || state > 3 ) { printk( KERN_ERR "%s - %s: invalid pm state request: %u\n", - __FUNCTION__, pdev->name, state); + __FUNCTION__, pdev->dev.name, state); return -1; } return 0; @@ -1892,11 +1892,11 @@ if (state < 1 || state > 3 ) { printk( KERN_ERR "%s - %s: invalid pm state request: %u\n", - __FUNCTION__, pdev->name, state); + __FUNCTION__, pdev->dev.name, state); return 0; } if (!ndev) { - printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->name); + printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->dev.name); return 0; } idev = ndev->priv; @@ -1908,7 +1908,7 @@ } else printk(KERN_ERR "%s - %s: invalid suspend request %u -> %u\n", - __FUNCTION__, pdev->name, pdev->current_state, state); + __FUNCTION__, pdev->dev.name, pdev->current_state, state); up(&idev->sem); return 0; } @@ -1935,14 +1935,14 @@ vlsi_irda_dev_t *idev; if (!ndev) { - printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->name); + printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->dev.name); return 0; } idev = ndev->priv; down(&idev->sem); if (pdev->current_state == 0) { up(&idev->sem); - printk(KERN_ERR "%s - %s: already resumed\n", __FUNCTION__, pdev->name); + printk(KERN_ERR "%s - %s: already resumed\n", __FUNCTION__, pdev->dev.name); return 0; } diff -Nru a/drivers/net/macsonic.c b/drivers/net/macsonic.c --- a/drivers/net/macsonic.c Wed Nov 27 14:36:27 2002 +++ b/drivers/net/macsonic.c Wed Nov 27 14:36:27 2002 @@ -195,6 +195,7 @@ if ((lp->rba = (char *) kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) { printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name); + kfree(lp); return -ENOMEM; } diff -Nru a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c --- a/drivers/net/myri_sbus.c Wed Nov 27 14:36:27 2002 +++ b/drivers/net/myri_sbus.c Wed Nov 27 14:36:27 2002 @@ -1085,6 +1085,7 @@ #endif return 0; err: unregister_netdev(dev); + /* This will also free the co-allocated 'dev->priv' */ kfree(dev); return -ENODEV; } @@ -1141,6 +1142,7 @@ struct myri_eth *next = root_myri_dev->next_module; unregister_netdev(root_myri_dev->dev); + /* this will also free the co-allocated 'root_myri_dev' */ kfree(root_myri_dev->dev); root_myri_dev = next; } diff -Nru a/drivers/net/pcmcia/aironet4500_cs.c b/drivers/net/pcmcia/aironet4500_cs.c --- a/drivers/net/pcmcia/aironet4500_cs.c Wed Nov 27 14:36:27 2002 +++ b/drivers/net/pcmcia/aironet4500_cs.c Wed Nov 27 14:36:27 2002 @@ -39,11 +39,6 @@ #include #include #include -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE -#include -#endif -#endif #include #include diff -Nru a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c --- a/drivers/net/pcmcia/pcnet_cs.c Wed Nov 27 14:36:31 2002 +++ b/drivers/net/pcmcia/pcnet_cs.c Wed Nov 27 14:36:31 2002 @@ -300,7 +300,8 @@ memset(info, 0, sizeof(*info)); link = &info->link; dev = &info->dev; link->priv = info; - + + init_timer(&link->release); link->release.function = &pcnet_release; link->release.data = (u_long)link; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c --- a/drivers/net/pcmcia/smc91c92_cs.c Wed Nov 27 14:36:31 2002 +++ b/drivers/net/pcmcia/smc91c92_cs.c Wed Nov 27 14:36:31 2002 @@ -357,6 +357,7 @@ memset(smc, 0, sizeof(struct smc_private)); link = &smc->link; dev = &smc->dev; spin_lock_init(&smc->lock); + init_timer(&link->release); link->release.function = &smc91c92_release; link->release.data = (u_long)link; link->io.NumPorts1 = 16; diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c --- a/drivers/net/pppoe.c Wed Nov 27 14:36:31 2002 +++ b/drivers/net/pppoe.c Wed Nov 27 14:36:31 2002 @@ -644,8 +644,10 @@ release_sock(sk); return error; err_put: - dev_put(po->pppoe_dev); - po->pppoe_dev = NULL; + if (po->pppoe_dev) { + dev_put(po->pppoe_dev); + po->pppoe_dev = NULL; + } goto end; } diff -Nru a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h --- a/drivers/net/sk98lin/h/skgehw.h Wed Nov 27 14:36:32 2002 +++ b/drivers/net/sk98lin/h/skgehw.h Wed Nov 27 14:36:32 2002 @@ -813,7 +813,7 @@ /* Bit 31..12: reserved */ #define IS_IRQ_MST_ERR (1L<<11) /* Bit 11: IRQ master error */ /* PERR,RMABORT,RTABORT,DATAPERR */ -#define IS_IRQ_STAT (1L<<10) /* Bit 10: IRQ status execption */ +#define IS_IRQ_STAT (1L<<10) /* Bit 10: IRQ status exception */ /* RMABORT, RTABORT, DATAPERR */ #define IS_NO_STAT_M1 (1L<<9) /* Bit 9: No Rx Status from MAC1*/ #define IS_NO_STAT_M2 (1L<<8) /* Bit 8: No Rx Status from MAC2*/ diff -Nru a/drivers/net/skfp/h/skfbi.h b/drivers/net/skfp/h/skfbi.h --- a/drivers/net/skfp/h/skfbi.h Wed Nov 27 14:36:29 2002 +++ b/drivers/net/skfp/h/skfbi.h Wed Nov 27 14:36:29 2002 @@ -1308,7 +1308,7 @@ #define IS_I2C_READY (1L<<27) /* Bit 27: (ML) IRQ on end of I2C tx */ #define IS_IRQ_SW (1L<<26) /* Bit 26: (ML) SW forced IRQ */ #define IS_EXT_REG (1L<<25) /* Bit 25: (ML) IRQ from external reg*/ -#define IS_IRQ_STAT (1L<<24) /* Bit 24: IRQ status execption */ +#define IS_IRQ_STAT (1L<<24) /* Bit 24: IRQ status exception */ /* PERR, RMABORT, RTABORT DATAPERR */ #define IS_IRQ_MST_ERR (1L<<23) /* Bit 23: IRQ master error */ /* RMABORT, RTABORT, DATAPERR */ @@ -1360,7 +1360,7 @@ #define IRQ_I2C_READY (1L<<27) /* Bit 27: (ML) IRQ on end of I2C tx */ #define IRQ_SW (1L<<26) /* Bit 26: (ML) SW forced IRQ */ #define IRQ_EXT_REG (1L<<25) /* Bit 25: (ML) IRQ from external reg*/ -#define IRQ_STAT (1L<<24) /* Bit 24: IRQ status execption */ +#define IRQ_STAT (1L<<24) /* Bit 24: IRQ status exception */ /* PERR, RMABORT, RTABORT DATAPERR */ #define IRQ_MST_ERR (1L<<23) /* Bit 23: IRQ master error */ /* RMABORT, RTABORT, DATAPERR */ diff -Nru a/drivers/net/slip.c b/drivers/net/slip.c --- a/drivers/net/slip.c Wed Nov 27 14:36:32 2002 +++ b/drivers/net/slip.c Wed Nov 27 14:36:32 2002 @@ -261,7 +261,7 @@ if (xbuff == NULL || rbuff == NULL) { #endif if (mtu >= sl->mtu) { - printk("%s: unable to grow slip buffers, MTU change cancelled.\n", + printk(KERN_WARNING "%s: unable to grow slip buffers, MTU change cancelled.\n", dev->name); err = -ENOBUFS; } @@ -348,7 +348,7 @@ if ((c = sl->rbuff[0]) & SL_TYPE_COMPRESSED_TCP) { /* ignore compressed packets when CSLIP is off */ if (!(sl->mode & SL_MODE_CSLIP)) { - printk("%s: compressed packet ignored\n", sl->dev->name); + printk(KERN_WARNING "%s: compressed packet ignored\n", sl->dev->name); return; } /* make sure we've reserved enough space for uncompress to use */ @@ -365,7 +365,7 @@ /* turn on header compression */ sl->mode |= SL_MODE_CSLIP; sl->mode &= ~SL_MODE_ADAPTIVE; - printk("%s: header compression turned on\n", sl->dev->name); + printk(KERN_INFO "%s: header compression turned on\n", sl->dev->name); } sl->rbuff[0] &= 0x4f; if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) { @@ -379,7 +379,7 @@ skb = dev_alloc_skb(count); if (skb == NULL) { - printk("%s: memory squeeze, dropping packet.\n", sl->dev->name); + printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", sl->dev->name); sl->rx_dropped++; return; } @@ -400,7 +400,7 @@ int actual, count; if (len > sl->mtu) { /* Sigh, shouldn't occur BUT ... */ - printk ("%s: truncating oversized transmit packet!\n", sl->dev->name); + printk(KERN_WARNING "%s: truncating oversized transmit packet!\n", sl->dev->name); sl->tx_dropped++; sl_unlock(sl); return; @@ -487,7 +487,7 @@ /* 20 sec timeout not reached */ goto out; } - printk("%s: transmit timed out, %s?\n", dev->name, + printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ? "bad line quality" : "driver error"); sl->xleft = 0; @@ -510,7 +510,7 @@ spin_lock(&sl->lock); if (!netif_running(dev)) { spin_unlock(&sl->lock); - printk("%s: xmit call when iface is down\n", dev->name); + printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name); dev_kfree_skb(skb); return 0; } @@ -1332,7 +1332,7 @@ ".\n", SLIP_VERSION, slip_maxdev ); #if defined(SL_INCLUDE_CSLIP) && !defined(MODULE) - printk("CSLIP: code copyright 1989 Regents of the University of California.\n"); + printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California.\n"); #endif #ifdef CONFIG_SLIP_SMART printk(KERN_INFO "SLIP linefill/keepalive option.\n"); @@ -1341,7 +1341,7 @@ slip_ctrls = (slip_ctrl_t **) kmalloc(sizeof(void*)*slip_maxdev, GFP_KERNEL); if (slip_ctrls == NULL) { - printk("SLIP: Can't allocate slip_ctrls[] array! Uaargh! (-> No SLIP available)\n"); + printk(KERN_ERR "SLIP: Can't allocate slip_ctrls[] array! Uaargh! (-> No SLIP available)\n"); return -ENOMEM; } @@ -1364,7 +1364,7 @@ sl_ldisc.receive_room = slip_receive_room; sl_ldisc.write_wakeup = slip_write_wakeup; if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) { - printk("SLIP: can't register line discipline (err = %d)\n", status); + printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status); } @@ -1418,7 +1418,7 @@ if (slc) { unregister_netdev(&slc->dev); if (slc->ctrl.tty) { - printk("%s: tty discipline is still running\n", slc->dev.name); + printk(KERN_ERR "%s: tty discipline is still running\n", slc->dev.name); /* Pin module forever */ MOD_INC_USE_COUNT; busy++; @@ -1436,7 +1436,7 @@ } if ((i = tty_register_ldisc(N_SLIP, NULL))) { - printk("SLIP: can't unregister line discipline (err = %d)\n", i); + printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i); } } #endif /* MODULE */ @@ -1498,7 +1498,7 @@ /* keepalive still high :(, we must hangup */ if( sl->outfill ) /* outfill timer must be deleted too */ (void)del_timer(&sl->outfill_timer); - printk("%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name); + printk(KERN_DEBUG "%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name); tty_hangup(sl->tty); /* this must hangup tty & close slip */ /* I think we need not something else */ goto out; diff -Nru a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c --- a/drivers/net/sunbmac.c Wed Nov 27 14:36:30 2002 +++ b/drivers/net/sunbmac.c Wed Nov 27 14:36:30 2002 @@ -1209,6 +1209,7 @@ bp->bblock_dvma); unregister_netdev(dev); + /* This also frees the co-located 'dev->priv' */ kfree(dev); return -ENODEV; } diff -Nru a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c --- a/drivers/net/tokenring/3c359.c Wed Nov 27 14:36:32 2002 +++ b/drivers/net/tokenring/3c359.c Wed Nov 27 14:36:32 2002 @@ -315,7 +315,7 @@ dev->irq=pdev->irq; dev->base_addr=pci_resource_start(pdev,0) ; dev->init=NULL ; /* Must be null with new api, otherwise get called twice */ - xl_priv->xl_card_name = (char *)pdev->name ; + xl_priv->xl_card_name = (char *)pdev->dev.name ; xl_priv->xl_mmio=ioremap(pci_resource_start(pdev,1), XL_IO_SPACE); xl_priv->pdev = pdev ; diff -Nru a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c --- a/drivers/net/tokenring/madgemc.c Wed Nov 27 14:36:32 2002 +++ b/drivers/net/tokenring/madgemc.c Wed Nov 27 14:36:32 2002 @@ -226,16 +226,12 @@ goto getout; } - request_region(dev->base_addr, MADGEMC_IO_EXTENT, "madgemc"); -#if 0 - /* why is this not working? */ - if (request_region(dev->base_addr, MADGEMC_IO_EXTENT, + if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT, "madgemc")) { printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", slot, dev->base_addr); dev->base_addr += MADGEMC_SIF_OFFSET; goto getout; } -#endif dev->base_addr += MADGEMC_SIF_OFFSET; /* diff -Nru a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c --- a/drivers/net/tokenring/olympic.c Wed Nov 27 14:36:31 2002 +++ b/drivers/net/tokenring/olympic.c Wed Nov 27 14:36:31 2002 @@ -230,7 +230,7 @@ dev->irq=pdev->irq; dev->base_addr=pci_resource_start(pdev, 0); dev->init=NULL; /* Must be NULL otherwise we get called twice */ - olympic_priv->olympic_card_name = (char *)pdev->name ; + olympic_priv->olympic_card_name = (char *)pdev->dev.name ; olympic_priv->olympic_mmio = ioremap(pci_resource_start(pdev,1),256); olympic_priv->olympic_lap = ioremap(pci_resource_start(pdev,2),2048); olympic_priv->pdev = pdev ; @@ -654,8 +654,8 @@ printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7]) ); printk("RXCDA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCDA),&olympic_priv->olympic_rx_ring[0]); - printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr = -%08x\n",olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ; + printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr = %08x\n", + olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ; #endif writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ); diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c --- a/drivers/net/wan/cosa.c Wed Nov 27 14:36:27 2002 +++ b/drivers/net/wan/cosa.c Wed Nov 27 14:36:27 2002 @@ -610,7 +610,8 @@ static int cosa_sppp_open(struct net_device *d) { struct channel_data *chan = d->priv; - int err, flags; + int err; + unsigned long flags; if (!(chan->cosa->firmware_status & COSA_FW_START)) { printk(KERN_NOTICE "%s: start the firmware first (status %d)\n", @@ -681,7 +682,7 @@ static int cosa_sppp_close(struct net_device *d) { struct channel_data *chan = d->priv; - int flags; + unsigned long flags; netif_stop_queue(d); sppp_close(d); @@ -778,7 +779,7 @@ char *buf, size_t count, loff_t *ppos) { DECLARE_WAITQUEUE(wait, current); - int flags; + unsigned long flags; struct channel_data *chan = (struct channel_data *)file->private_data; struct cosa_data *cosa = chan->cosa; char *kbuf; @@ -855,7 +856,7 @@ DECLARE_WAITQUEUE(wait, current); struct channel_data *chan = (struct channel_data *)file->private_data; struct cosa_data *cosa = chan->cosa; - unsigned int flags; + unsigned long flags; char *kbuf; if (!(cosa->firmware_status & COSA_FW_START)) { @@ -1242,7 +1243,7 @@ static int cosa_start_tx(struct channel_data *chan, char *buf, int len) { struct cosa_data *cosa = chan->cosa; - int flags; + unsigned long flags; #ifdef DEBUG_DATA int i; @@ -1268,7 +1269,7 @@ static void put_driver_status(struct cosa_data *cosa) { - unsigned flags=0; + unsigned long flags; int status; spin_lock_irqsave(&cosa->lock, flags); @@ -1336,7 +1337,7 @@ */ static void cosa_kick(struct cosa_data *cosa) { - unsigned flags, flags1; + unsigned long flags, flags1; char *s = "(probably) IRQ"; if (test_bit(RXBIT, &cosa->rxtx)) diff -Nru a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c --- a/drivers/net/wan/hostess_sv11.c Wed Nov 27 14:36:31 2002 +++ b/drivers/net/wan/hostess_sv11.c Wed Nov 27 14:36:31 2002 @@ -284,9 +284,11 @@ goto dmafail; } } - save_flags(flags); - cli(); - + + /* Kill our private IRQ line the hostess can end up chattering + until the configuration is set */ + disable_irq(irq); + /* * Begin normal initialise */ @@ -294,7 +296,7 @@ if(z8530_init(dev)!=0) { printk(KERN_ERR "Z8530 series device not found.\n"); - restore_flags(flags); + enable_irq(irq); goto dmafail2; } z8530_channel_load(&dev->chanB, z8530_dead_port); @@ -303,8 +305,8 @@ else z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream_85230); - restore_flags(flags); - + enable_irq(irq); + /* * Now we can take the IRQ @@ -399,7 +401,7 @@ int init_module(void) { - printk(KERN_INFO "SV-11 Z85230 Synchronous Driver v 0.02.\n"); + printk(KERN_INFO "SV-11 Z85230 Synchronous Driver v 0.03.\n"); printk(KERN_INFO "(c) Copyright 2001, Red Hat Inc.\n"); if((sv11_unit=sv11_init(io,irq))==NULL) return -ENODEV; diff -Nru a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c --- a/drivers/net/wan/pc300_drv.c Wed Nov 27 14:36:32 2002 +++ b/drivers/net/wan/pc300_drv.c Wed Nov 27 14:36:32 2002 @@ -3688,3 +3688,9 @@ module_init(cpc_init); module_exit(cpc_cleanup_module); + +MODULE_DESCRIPTION("Cyclades-PC300 cards driver"); +MODULE_AUTHOR( "Author: Ivan Passos \r\n" + "Maintainer: Henrique Gobbi base_addr > 0x1ff - && !check_region( dev->base_addr, SBNI_IO_EXTENT ) + && request_region( dev->base_addr, SBNI_IO_EXTENT, dev->name ) && sbni_probe1( dev, dev->base_addr, dev->irq ) ) return 0; @@ -249,7 +249,7 @@ for( i = 0; netcard_portlist[ i ]; ++i ) { int ioaddr = netcard_portlist[ i ]; - if( !check_region( ioaddr, SBNI_IO_EXTENT ) + if( request_region( ioaddr, SBNI_IO_EXTENT, dev->name ) && sbni_probe1( dev, ioaddr, 0 )) return 0; } @@ -280,7 +280,7 @@ pci_irq_line = pdev->irq; /* Avoid already found cards from previous calls */ - if( check_region( pci_ioaddr, SBNI_IO_EXTENT ) ) { + if( !pci_request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) { pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys ); if( subsys != 2 || /* Dual adapter is present */ check_region( pci_ioaddr += 4, SBNI_IO_EXTENT ) ) @@ -309,9 +309,6 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq ) { struct net_local *nl; - - if( !request_region( ioaddr, SBNI_IO_EXTENT, dev->name ) ) - return 0; if( sbni_card_probe( ioaddr ) ) { release_region( ioaddr, SBNI_IO_EXTENT ); diff -Nru a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c --- a/drivers/net/wan/sdla_fr.c Wed Nov 27 14:36:32 2002 +++ b/drivers/net/wan/sdla_fr.c Wed Nov 27 14:36:32 2002 @@ -162,14 +162,9 @@ #include /* frame relay firmware API definitions */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include - #include - #include - -#else - #include -#endif +#include +#include +#include #include /* Dynamic Route Creation */ #include /* eth_type_trans() used for bridging */ diff -Nru a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c --- a/drivers/net/wan/sealevel.c Wed Nov 27 14:36:31 2002 +++ b/drivers/net/wan/sealevel.c Wed Nov 27 14:36:31 2002 @@ -302,9 +302,8 @@ if(request_dma(dev->chanA.rxdma, "SeaLevel (RX)")!=0) goto dmafail; - save_flags(flags); - cli(); - + disable_irq(irq); + /* * Begin normal initialise */ @@ -312,7 +311,7 @@ if(z8530_init(dev)!=0) { printk(KERN_ERR "Z8530 series device not found.\n"); - restore_flags(flags); + enable_irq(irq); goto dmafail2; } if(dev->type==Z85C30) @@ -330,7 +329,7 @@ * Now we can take the IRQ */ - restore_flags(flags); + enable_irq(irq); for(u=0; u<2; u++) { @@ -446,7 +445,7 @@ int init_module(void) { - printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.01.\n"); + printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.02.\n"); printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n"); if((slvl_unit=slvl_init(io,irq, txdma, rxdma, slow))==NULL) return -ENODEV; diff -Nru a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c --- a/drivers/net/wireless/airo_cs.c Wed Nov 27 14:36:28 2002 +++ b/drivers/net/wireless/airo_cs.c Wed Nov 27 14:36:28 2002 @@ -242,6 +242,11 @@ /* Allocate space for private device-specific data */ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + if (!local) { + printk(KERN_ERR "airo_cs: no memory for new device\n"); + kfree (link); + return NULL; + } memset(local, 0, sizeof(local_info_t)); link->priv = local; diff -Nru a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c --- a/drivers/oprofile/cpu_buffer.c Wed Nov 27 14:36:27 2002 +++ b/drivers/oprofile/cpu_buffer.c Wed Nov 27 14:36:27 2002 @@ -20,6 +20,7 @@ #include #include #include +#include #include "cpu_buffer.h" #include "oprof.h" diff -Nru a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog --- a/drivers/parport/ChangeLog Wed Nov 27 14:36:31 2002 +++ b/drivers/parport/ChangeLog Wed Nov 27 14:36:31 2002 @@ -1,8 +1,7 @@ -2001-11-14 Tim Waugh +2002-04-25 Tim Waugh - * parport_pc.c (parport_pc_pci_probe): Hooks for PCI cards before - and after probing for ports. - * parport_serial.c (parport_register): Likewise. + * parport_serial.c, parport_pc.c: Move some SIIG cards around. + Patch from Andrey Panin. 2002-01-20 Tim Waugh @@ -21,17 +20,17 @@ * daisy.c: Apply patch from Max Vorobiev to make parport_daisy_select work for ECP/EPP modes. -2002-01-04 Tim Waugh - - * share.c (parport_claim_or_block): Sleep interruptibly to prevent - a possible deadlock. - 2002-01-13 Niels Kristian Bech Jensen * parport_pc.c: Change some occurrences of frob_set_mode to ECR_WRITE. This fixes PLIP. -2001-10-25 Damian Gruszka +2002-01-04 Tim Waugh + + * share.c (parport_claim_or_block): Sleep interruptibly to prevent + a possible deadlock. + +2001-12-07 Damian Gruszka * parport_pc.c (ECR_WRITE): Define. If there are forbidden bits in the ECR register for some chips, this will be a useful place to @@ -68,7 +67,7 @@ (parport_irq_probe): If no IRQ is found, take ackIntEn out of the writable bit set. -2001-10-25 Tim Waugh +2001-12-07 Tim Waugh * parport_pc.c (parport_pc_fifo_write_block_pio): Correct typo. (parport_pc_init_state): Only set ackIntEn if we know which IRQ @@ -85,6 +84,16 @@ too buggy at the moment. Use 'dma=auto' to restore the previous behaviour. +2001-12-07 Tim Waugh + + * daisy.c (DEBUG): Undefine. + +2001-12-06 Tim Waugh + + * ieee1284_ops.c (parport_ieee1284_ecp_read_data): Mask off + PARPORT_CONTROL_AUTOFD as well. Bug spotted by Joe + . + 2001-12-03 Rich Liu * parport_pc.c (sio_ite_8872_probe): ITE8873 is a single-port @@ -94,11 +103,11 @@ * parport_pc.c: Fix compiler warning. -2001-12-06 Tim Waugh +2001-11-14 Tim Waugh - * ieee1284_ops.c (parport_ieee1284_ecp_read_data): Mask off - PARPORT_CONTROL_AUTOFD as well. Bug spotted by Joe - . + * parport_pc.c (parport_pc_pci_probe): Hooks for PCI cards before + and after probing for ports. + * parport_serial.c (parport_register): Likewise. 2001-11-12 Tim Waugh diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c --- a/drivers/parport/parport_pc.c Wed Nov 27 14:36:32 2002 +++ b/drivers/parport/parport_pc.c Wed Nov 27 14:36:32 2002 @@ -2709,6 +2709,7 @@ oxsemi_954, oxsemi_840, aks_0100, + mobility_pp, }; @@ -2792,6 +2793,7 @@ /* oxsemi_954 */ { 1, { { 0, -1 }, } }, /* oxsemi_840 */ { 1, { { 0, -1 }, } }, /* aks_0100 */ { 1, { { 0, 1 }, } }, + /* mobility_pp */ { 1, { { 0, 1 }, } }, }; static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = { @@ -2873,6 +2875,7 @@ { 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a }, { 0x1409, 0x7268, 0x1409, 0x0104, 0, 0, timedia_4018 }, { 0x1409, 0x7268, 0x1409, 0x9018, 0, 0, timedia_9018a }, + { 0x14f2, 0x0121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, mobility_pp }, { PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_2P_EPP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp }, { PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_1P_ECP, diff -Nru a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c --- a/drivers/parport/parport_serial.c Wed Nov 27 14:36:31 2002 +++ b/drivers/parport/parport_serial.c Wed Nov 27 14:36:31 2002 @@ -41,6 +41,11 @@ avlab_2s1p, avlab_2s1p_650, avlab_2s1p_850, + siig_1s1p_10x, + siig_2s1p_10x, + siig_2p1s_20x, + siig_1s1p_20x, + siig_2s1p_20x, }; @@ -74,6 +79,11 @@ /* avlab_2s1p */ { 1, { { 2, 3}, } }, /* avlab_2s1p_650 */ { 1, { { 2, 3}, } }, /* avlab_2s1p_850 */ { 1, { { 2, 3}, } }, + /* siig_1s1p_10x */ { 1, { { 3, 4 }, } }, + /* siig_2s1p_10x */ { 1, { { 4, 5 }, } }, + /* siig_2p1s_20x */ { 2, { { 1, 2 }, { 3, 4 }, } }, + /* siig_1s1p_20x */ { 1, { { 1, 2 }, } }, + /* siig_2s1p_20x */ { 1, { { 2, 3 }, } }, }; static struct pci_device_id parport_serial_pci_tbl[] __devinitdata = { @@ -92,6 +102,37 @@ { 0x14db, 0x2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p}, { 0x14db, 0x2161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_650}, { 0x14db, 0x2162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_850}, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x }, + { 0, } /* terminate list */ }; MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl); @@ -107,6 +148,16 @@ int first_uart_offset; }; +static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable) +{ + return pci_siig10x_fn(dev, NULL, enable); +} + +static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable) +{ + return pci_siig20x_fn(dev, NULL, enable); +} + static struct pci_board_no_ids pci_boards[] __devinitdata = { /* * PCI Flags, Number of Ports, Base (Maximum) Baud Rate, @@ -129,6 +180,11 @@ /* avlab_2s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, +/* siig_1s1p_10x */ { SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn }, +/* siig_2s1p_10x */ { SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn }, +/* siig_2p1s_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn }, +/* siig_1s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn }, +/* siig_2s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn }, }; struct parport_serial_private { diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c --- a/drivers/pci/pci.c Wed Nov 27 14:36:28 2002 +++ b/drivers/pci/pci.c Wed Nov 27 14:36:28 2002 @@ -729,6 +729,7 @@ __setup("pci=", pci_setup); #if defined(CONFIG_ISA) || defined(CONFIG_EISA) +/* FIXME: Some boxes have multiple ISA bridges! */ struct pci_dev *isa_bridge; EXPORT_SYMBOL(isa_bridge); #endif diff -Nru a/drivers/pci/pci.ids b/drivers/pci/pci.ids --- a/drivers/pci/pci.ids Wed Nov 27 14:36:30 2002 +++ b/drivers/pci/pci.ids Wed Nov 27 14:36:30 2002 @@ -497,8 +497,8 @@ 1011 500b DE500B Fast Ethernet 1014 0001 10/100 EtherJet Cardbus 1025 0315 ALN315 Fast Ethernet - 1033 800c PC-9821-CS01 - 1033 800d PC-9821NR-B06 + 1033 800c PC-9821-CS01 100BASE-TX Interface Card + 1033 800d PC-9821NR-B06 100BASE-TX Interface Card 108d 0016 Rapidfire 2327 10/100 Ethernet 108d 0017 GoCard 2250 Ethernet 10/100 Cardbus 10b8 2005 SMC8032DT Extreme Ethernet 10/100 @@ -1049,17 +1049,21 @@ 0003 ATM Controller 0004 R4000 PCI Bridge 0005 PCI to 486-like bus Bridge - 0006 GUI Accelerator + 0006 PC-9800 Graphic Accelerator 0007 PCI to UX-Bus Bridge - 0008 GUI Accelerator - 0009 GUI Accelerator for W98 + 0008 PC-9800 Graphic Accelerator + 0009 PCI to PC9800 Core-Graph Bridge + 0016 PCI to VL Bridge 001a [Nile II] 0021 Vrc4373 [Nile I] 0029 PowerVR PCX1 002a PowerVR 3D + 002c Star Alpha 2 + 002d PCI to C-bus Bridge 0035 USB 1179 0001 USB 12ee 7000 Root Hub + 003b PCI to C-bus Bridge 003e NAPCCARD Cardbus Controller 0046 PowerVR PCX2 [midas] 005a Vrc5074 [Nile 4] @@ -3489,7 +3493,7 @@ 5811 FW323 dead 0800 FireWire Host Bus Adapter 11c2 Sand Microelectronics -11c3 NEC Corp +11c3 NEC Corporation 11c4 Document Technologies, Inc 11c5 Shiva Corporation 11c6 Dainippon Screen Mfg. Co. Ltd diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c --- a/drivers/pci/quirks.c Wed Nov 27 14:36:27 2002 +++ b/drivers/pci/quirks.c Wed Nov 27 14:36:27 2002 @@ -212,6 +212,19 @@ } /* + * ATI Northbridge setups MCE the processor if you even + * read somewhere between 0x3b0->0x3bb or read 0x3d3 + */ + +static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev) +{ + printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n"); + /* Mae rhaid in i beidio a edrych ar y lleoliad I/O hyn */ + request_region(0x3b0, 0x0C, "RadeonIGP"); + request_region(0x3d3, 0x01, "RadeonIGP"); +} + +/* * Let's make the southbridge information explicit instead * of having to worry about people probing the ACPI areas, * for example.. (Yes, it happens, and if you read the wrong @@ -313,6 +326,35 @@ pci_write_config_byte (dev, 0x58, tmp); } +/* + * The AMD io apic can hang the box when an apic irq is masked. + * We check all revs >= B0 (yet not in the pre production!) as the bug + * is currently marked NoFix + * + * We have multiple reports of hangs with this chipset that went away with + * noapic specified. For the moment we assume its the errata. We may be wrong + * of course. However the advice is demonstrably good even if so.. + */ + +static void __devinit quirk_amd_ioapic(struct pci_dev *dev) +{ + u8 rev; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + if(rev >= 0x02) + { + printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n"); + printk(KERN_WARNING " : booting with the \"noapic\" option.\n"); + } +} + +static void __init quirk_ioapic_rmw(struct pci_dev *dev) +{ + if (dev->devfn == 0 && dev->bus->number == 0) + sis_apic_bug = 1; +} + + #endif /* CONFIG_X86_IO_APIC */ @@ -412,28 +454,6 @@ } /* - * The AMD io apic can hang the box when an apic irq is masked. - * We check all revs >= B0 (yet not in the pre production!) as the bug - * is currently marked NoFix - * - * We have multiple reports of hangs with this chipset that went away with - * noapic specified. For the moment we assume its the errata. We may be wrong - * of course. However the advice is demonstrably good even if so.. - */ - -static void __devinit quirk_amd_ioapic(struct pci_dev *dev) -{ - u8 rev; - - pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - if(rev >= 0x02) - { - printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n"); - printk(KERN_WARNING " : booting with the \"noapic\" option.\n"); - } -} - -/* * Following the PCI ordering rules is optional on the AMD762. I'm not * sure what the designers were smoking but let's not inhale... * @@ -477,6 +497,24 @@ } /* + * Common misconfiguration of the MediaGX/Geode PCI master that will + * reduce PCI bandwidth from 70MB/s to 25MB/s. See the GXM/GXLV/GX1 + * datasheets found at http://www.national.com/ds/GX for info on what + * these bits do. + */ + +static void __init quirk_mediagx_master(struct pci_dev *dev) +{ + u8 reg; + pci_read_config_byte(dev, 0x41, ®); + if (reg & 2) { + reg &= ~2; + printk(KERN_INFO "PCI: Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg); + pci_write_config_byte(dev, 0x41, reg); + } +} + +/* * The main table of quirks. */ @@ -491,6 +529,7 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton }, @@ -521,6 +560,8 @@ #ifdef CONFIG_X86_IO_APIC { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SIS, PCI_ANY_ID, quirk_ioapic_rmw }, #endif { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi }, @@ -528,8 +569,8 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_IGP, quirk_ati_exploding_mce }, /* * i82380FB mobile docking controller: its PCI-to-PCI bridge * is subtractive decoding (transparent), and does indicate this @@ -537,6 +578,9 @@ * instead of 0x01. */ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge }, + + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master }, + { 0 } }; diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c --- a/drivers/pcmcia/cardbus.c Wed Nov 27 14:36:28 2002 +++ b/drivers/pcmcia/cardbus.c Wed Nov 27 14:36:28 2002 @@ -283,6 +283,8 @@ dev->hdr_type = hdr & 0x7f; pci_setup_device(dev); + if (pci_enable_device(dev)) + continue; strcpy(dev->dev.bus_id, dev->slot_name); @@ -300,7 +302,6 @@ pci_writeb(dev, PCI_INTERRUPT_LINE, irq); } - pci_enable_device(dev); /* XXX check return */ device_register(&dev->dev); pci_insert_device(dev, bus); } diff -Nru a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c --- a/drivers/pcmcia/sa1100_assabet.c Wed Nov 27 14:36:31 2002 +++ b/drivers/pcmcia/sa1100_assabet.c Wed Nov 27 14:36:31 2002 @@ -6,13 +6,14 @@ */ #include #include -#include #include +#include #include #include #include #include +#include #include #include "sa1100_generic.h" diff -Nru a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c --- a/drivers/pcmcia/sa1100_badge4.c Wed Nov 27 14:36:28 2002 +++ b/drivers/pcmcia/sa1100_badge4.c Wed Nov 27 14:36:28 2002 @@ -31,40 +31,41 @@ * * PCM Vcc: * - * PCM Vcc on BadgePAD 4 can be jumpered for 3.3V (short pins 1 and 3 - * on JP6) or 5V (short pins 3 and 5 on JP6). N.B., 5V supply rail - * is enabled by the SA-1110's BADGE4_GPIO_PCMEN5V (GPIO 24). + * PCM Vcc on BadgePAD 4 can be jumpered for 3v3 (short pins 1 and 3 + * on JP6) or 5v0 (short pins 3 and 5 on JP6). * * PCM Vpp: * - * PCM Vpp on BadgePAD 4 can be jumpered for 12V (short pins 2 and 4 - * on JP6) or tied to PCM Vcc (short pins 4 and 6 on JP6). N.B., 12V - * operation requires that the power supply actually supply 12V. + * PCM Vpp on BadgePAD 4 can be jumpered for 12v0 (short pins 4 and 6 + * on JP6) or tied to PCM Vcc (short pins 2 and 4 on JP6). N.B., + * 12v0 operation requires that the power supply actually supply 12v0 + * via pin 7 of JP7. * * CF Vcc: * - * CF Vcc on BadgePAD 4 can be jumpered either for 3.3V (short pins 1 - * and 2 on JP10) or 5V (short pins 2 and 3 on JP10). The note above - * about the 5V supply rail applies. - * - * There's no way programmatically to determine how a given board is - * jumpered. This code assumes a default jumpering: 5V PCM Vcc (pins - * 3 and 5 shorted) and PCM Vpp = PCM Vcc (pins 4 and 6 shorted) and - * no jumpering for CF Vcc. If this isn't correct, Override these - * defaults with a pcmv setup argument: pcmv=,,. E.g. pcmv=33,120,50 indicates 3.3V PCM Vcc, 12.0V PCM Vpp, - * and 5.0V CF Vcc. + * CF Vcc on BadgePAD 4 can be jumpered either for 3v3 (short pins 1 + * and 2 on JP10) or 5v0 (short pins 2 and 3 on JP10). + * + * Unfortunately there's no way programmatically to determine how a + * given board is jumpered. This code assumes a default jumpering + * as described below. + * + * If the defaults aren't correct, you may override them with a pcmv + * setup argument: pcmv=,,. The units are + * tenths of volts; e.g. pcmv=33,120,50 indicates 3v3 PCM Vcc, 12v0 + * PCM Vpp, and 5v0 CF Vcc. * */ -static int badge4_pcmvcc = 50; -static int badge4_pcmvpp = 50; -static int badge4_cfvcc = 33; +static int badge4_pcmvcc = 50; /* pins 3 and 5 jumpered on JP6 */ +static int badge4_pcmvpp = 50; /* pins 2 and 4 jumpered on JP6 */ +static int badge4_cfvcc = 33; /* pins 1 and 2 jumpered on JP10 */ static int badge4_pcmcia_init(struct pcmcia_init *init) { - printk(KERN_INFO __FUNCTION__ - ": badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n", + printk(KERN_INFO + "%s: badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n", + __FUNCTION__, badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc); return sa1111_pcmcia_init(init); @@ -74,7 +75,7 @@ { int rc = sa1111_pcmcia_shutdown(); - /* be sure to disable 5V use */ + /* be sure to disable 5v0 use */ badge4_set_5V(BADGE4_5V_PCMCIA_SOCK0, 0); badge4_set_5V(BADGE4_5V_PCMCIA_SOCK1, 0); @@ -105,7 +106,8 @@ (conf->vcc != badge4_pcmvcc)) { complain_about_jumpering(__FUNCTION__, "pcmvcc", badge4_pcmvcc, conf->vcc); - return -1; + // Apply power regardless of the jumpering. + // return -1; } if ((conf->vpp != 0) && (conf->vpp != badge4_pcmvpp)) { @@ -156,7 +158,7 @@ .socket_suspend = sa1111_pcmcia_socket_suspend, }; -int __init pcmcia_badge4_init(void) +int pcmcia_badge4_init(void) { int ret = -ENODEV; @@ -166,7 +168,7 @@ return ret; } -void __exit pcmcia_badge4_exit(void) +void __devexit pcmcia_badge4_exit(void) { sa1100_unregister_pcmcia(&badge4_pcmcia_ops); } diff -Nru a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c --- a/drivers/pcmcia/sa1111_generic.c Wed Nov 27 14:36:28 2002 +++ b/drivers/pcmcia/sa1111_generic.c Wed Nov 27 14:36:28 2002 @@ -7,9 +7,9 @@ */ #include #include -#include #include #include +#include #include #include diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c Wed Nov 27 14:36:30 2002 +++ b/drivers/pcmcia/tcic.c Wed Nov 27 14:36:30 2002 @@ -392,7 +392,11 @@ printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: "); sock = 0; - if (check_region(tcic_base, 16) == 0) { + if (!request_region(tcic_base, 16, "tcic-2")) { + printk("could not allocate ports,\n "); + return -ENODEV; + } + else { tcic_setw(TCIC_ADDR, 0); if (tcic_getw(TCIC_ADDR) == 0) { tcic_setw(TCIC_ADDR, 0xc3a5); @@ -408,15 +412,12 @@ if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2; } } - } else - printk("could not allocate ports, "); - + } if (sock == 0) { printk("not found.\n"); + release_region(tcic_base, 16); return -ENODEV; } - - request_region(tcic_base, 16, "tcic-2"); sockets = 0; for (i = 0; i < sock; i++) { diff -Nru a/drivers/pnp/core.c b/drivers/pnp/core.c --- a/drivers/pnp/core.c Wed Nov 27 14:36:28 2002 +++ b/drivers/pnp/core.c Wed Nov 27 14:36:28 2002 @@ -164,7 +164,7 @@ return bus_register(&pnp_bus_type); } -core_initcall(pnp_init); +subsys_initcall(pnp_init); EXPORT_SYMBOL(pnp_protocol_register); EXPORT_SYMBOL(pnp_protocol_unregister); diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c --- a/drivers/pnp/interface.c Wed Nov 27 14:36:28 2002 +++ b/drivers/pnp/interface.c Wed Nov 27 14:36:28 2002 @@ -11,6 +11,7 @@ #include #include #include +#include #include "base.h" diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c --- a/drivers/pnp/isapnp/core.c Wed Nov 27 14:36:30 2002 +++ b/drivers/pnp/isapnp/core.c Wed Nov 27 14:36:30 2002 @@ -1167,7 +1167,7 @@ return 0; } -subsys_initcall(isapnp_init); +device_initcall(isapnp_init); /* format is: noisapnp */ diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c --- a/drivers/pnp/system.c Wed Nov 27 14:36:32 2002 +++ b/drivers/pnp/system.c Wed Nov 27 14:36:32 2002 @@ -120,4 +120,4 @@ return pnp_register_driver(&system_pnp_driver); } -core_initcall(pnp_system_init); +subsys_initcall(pnp_system_init); diff -Nru a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c --- a/drivers/sbus/char/bpp.c Wed Nov 27 14:36:27 2002 +++ b/drivers/sbus/char/bpp.c Wed Nov 27 14:36:27 2002 @@ -95,7 +95,7 @@ /* * These are for data access. * Control lines accesses are hidden in set_bits() and get_bits(). - * The exeption is the probe procedure, which is system-dependent. + * The exception is the probe procedure, which is system-dependent. */ #define bpp_outb_p(data, base) outb_p((data), (base)) #define bpp_inb(base) inb(base) diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c --- a/drivers/scsi/3w-xxxx.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/3w-xxxx.c Wed Nov 27 14:36:31 2002 @@ -189,6 +189,7 @@ #include #include #include +#include #include #include diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c --- a/drivers/scsi/53c700.c Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/53c700.c Wed Nov 27 14:36:28 2002 @@ -170,8 +170,8 @@ STATIC int NCR_700_proc_directory_info(char *, char **, off_t, int, int, int); STATIC void NCR_700_chip_setup(struct Scsi_Host *host); STATIC void NCR_700_chip_reset(struct Scsi_Host *host); -STATIC int NCR_700_slave_attach(Scsi_Device *SDpnt); -STATIC void NCR_700_slave_detach(Scsi_Device *SDpnt); +STATIC int NCR_700_slave_configure(Scsi_Device *SDpnt); +STATIC void NCR_700_slave_destroy(Scsi_Device *SDpnt); static char *NCR_700_phase[] = { "", @@ -285,8 +285,8 @@ tpnt->cmd_per_lun = NCR_700_CMD_PER_LUN; tpnt->use_clustering = DISABLE_CLUSTERING; tpnt->proc_info = NCR_700_proc_directory_info; - tpnt->slave_attach = NCR_700_slave_attach; - tpnt->slave_detach = NCR_700_slave_detach; + tpnt->slave_configure = NCR_700_slave_configure; + tpnt->slave_destroy = NCR_700_slave_destroy; tpnt->use_blk_tcq = 1; tpnt->highmem_io = 1; @@ -1513,7 +1513,7 @@ host->host_no, SCp, SCp == NULL ? NULL : SCp->host_scribble, dsp, dsp - hostdata->pScript); /* clear all the negotiated parameters */ - for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) + list_for_each_entry(SDp, &host->my_devices, siblings) SDp->hostdata = 0; /* clear all the slots and their pending commands */ @@ -1740,7 +1740,7 @@ len += sprintf(&buf[len],"\ Target Depth Active Next Tag\n\ ====== ===== ====== ========\n"); - for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) { + list_for_each_entry(SDp, &host->my_devices, siblings) { len += sprintf(&buf[len]," %2d:%2d %4d %4d %4d\n", SDp->id, SDp->lun, SDp->current_queue_depth, NCR_700_get_depth(SDp), SDp->current_tag); } if((len -= offset) <= 0) @@ -1999,7 +1999,7 @@ } STATIC int -NCR_700_slave_attach(Scsi_Device *SDp) +NCR_700_slave_configure(Scsi_Device *SDp) { /* to do here: allocate memory; build a queue_full list */ if(SDp->tagged_supported) { @@ -2012,7 +2012,7 @@ } STATIC void -NCR_700_slave_detach(Scsi_Device *SDp) +NCR_700_slave_destroy(Scsi_Device *SDp) { /* to do here: deallocate memory */ } diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c --- a/drivers/scsi/BusLogic.c Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/BusLogic.c Wed Nov 27 14:36:32 2002 @@ -1,3 +1,4 @@ + /* Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters @@ -2702,14 +2703,14 @@ } /* - BusLogic_SlaveAttach will actually set the queue depth on individual + BusLogic_SlaveConfigure will actually set the queue depth on individual scsi devices as they are permanently added to the device chain. We shamelessly rip off the SelectQueueDepths code to make this work mostly like it used to. Since we don't get called once at the end of the scan but instead get called for each device, we have to do things a bit differently. */ -int BusLogic_SlaveAttach(SCSI_Device_T *Device) +int BusLogic_SlaveConfigure(SCSI_Device_T *Device) { BusLogic_HostAdapter_T *HostAdapter = (BusLogic_HostAdapter_T *) Device->host->hostdata; diff -Nru a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h --- a/drivers/scsi/BusLogic.h Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/BusLogic.h Wed Nov 27 14:36:30 2002 @@ -57,7 +57,7 @@ extern int BusLogic_BIOSDiskParameters(struct scsi_device *, struct block_device *, sector_t, int *); extern int BusLogic_ProcDirectoryInfo(char *, char **, off_t, int, int, int); -extern int BusLogic_SlaveAttach(SCSI_Device_T *); +extern int BusLogic_SlaveConfigure(SCSI_Device_T *); /* @@ -72,7 +72,7 @@ release: BusLogic_ReleaseHostAdapter, /* Release Host Adapter */ \ info: BusLogic_DriverInfo, /* Driver Info Function */ \ queuecommand: BusLogic_QueueCommand, /* Queue Command Function */ \ - slave_attach: BusLogic_SlaveAttach, /* Configure a SCSI_Device*/ \ + slave_configure:BusLogic_SlaveConfigure, /* Configure a SCSI_Device*/ \ bios_param: BusLogic_BIOSDiskParameters, /* BIOS Disk Parameters */ \ unchecked_isa_dma: 1, /* Default Initial Value */ \ max_sectors: 128, /* I/O queue len limit */ \ diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c --- a/drivers/scsi/NCR53C9x.c Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/NCR53C9x.c Wed Nov 27 14:36:28 2002 @@ -865,13 +865,13 @@ copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\n"); for(i = 0; i < 15; i++) { if(esp->targets_present & (1 << i)) { - Scsi_Device *SDptr = esp->ehost->host_queue; + Scsi_Device *SDptr; struct esp_device *esp_dev; - while((SDptr->host != esp->ehost) && - (SDptr->id != i) && - (SDptr->next)) - SDptr = SDptr->next; + list_for_each_entry(SDptr, &esp->ehost->my_devices, + siblings) + if(SDptr->id == i) + break; esp_dev = SDptr->hostdata; copy_info(&info, "%d\t\t", i); diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c --- a/drivers/scsi/NCR53c406a.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/NCR53c406a.c Wed Nov 27 14:36:30 2002 @@ -55,7 +55,6 @@ #include #include "scsi.h" #include "hosts.h" -#include "NCR53c406a.h" /* ============================================================= */ diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c --- a/drivers/scsi/aacraid/linit.c Wed Nov 27 14:36:29 2002 +++ b/drivers/scsi/aacraid/linit.c Wed Nov 27 14:36:29 2002 @@ -128,7 +128,7 @@ static int aac_eh_bus_reset(Scsi_Cmnd* cmd); static int aac_eh_reset(Scsi_Cmnd* cmd); -static int aac_slave_attach(Scsi_Device *); +static int aac_slave_configure(Scsi_Device *); /** * aac_detect - Probe for aacraid cards @@ -518,13 +518,13 @@ } /** - * aac_slave_attach - do device specific setup + * aac_slave_configure - do device specific setup * @dev: SCSI device we are attaching * * Currently, all we do is set the queue depth on the device. */ -static int aac_slave_attach(Scsi_Device * dev ) +static int aac_slave_configure(Scsi_Device * dev ) { if(dev->tagged_supported) @@ -685,7 +685,7 @@ ioctl: aac_ioctl, queuecommand: aac_queuecommand, bios_param: aac_biosparm, - slave_attach: aac_slave_attach, + slave_configure: aac_slave_configure, can_queue: AAC_NUM_IO_FIB, this_id: 16, sg_tablesize: 16, diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c --- a/drivers/scsi/advansys.c Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/advansys.c Wed Nov 27 14:36:28 2002 @@ -674,7 +674,7 @@ 1. hacks for lk 2.5 series (D. Gilbert) 3.3GJD (10/14/02): - 1. change select_queue_depths to slave_attach + 1. change select_queue_depths to slave_configure 2. make cmd_per_lun be sane again I. Known Problems/Fix List (XXX) @@ -4209,7 +4209,7 @@ */ STATIC void advansys_interrupt(int, void *, struct pt_regs *); -STATIC int advansys_slave_attach(Scsi_Device *); +STATIC int advansys_slave_configure(Scsi_Device *); STATIC void asc_scsi_done_list(Scsi_Cmnd *, int from_isr); STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *); STATIC int asc_build_req(asc_board_t *, Scsi_Cmnd *); @@ -4398,7 +4398,7 @@ * Display target driver information for each device attached * to the board. */ - for (scd = shp->host_queue; scd; scd = scd->next) + list_for_each_entry (scd, &shp->my_devices, siblings) { if (scd->host == shp) { cp = boardp->prtbuf; @@ -6345,7 +6345,7 @@ * specified host adapter. */ STATIC int -advansys_slave_attach(Scsi_Device *device) +advansys_slave_configure(Scsi_Device *device) { asc_board_t *boardp; @@ -6368,7 +6368,7 @@ } else { scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun); } - ASC_DBG3(1, "advansys_slave_attach: shp 0x%lx, id %d, depth %d\n", + ASC_DBG3(1, "advansys_slave_configure: shp 0x%lx, id %d, depth %d\n", (ulong) shp, device->id, device->queue_depth); return 0; } @@ -9386,8 +9386,8 @@ #if ASC_LINUX_KERNEL24 printk( -" host_queue 0x%lx, hostt 0x%lx\n", - (ulong) s->host_queue, (ulong) s->hostt); +" hostt 0x%lx\n", + (ulong) s->hostt); #elif ASC_LINUX_KERNEL22 printk( " host_queue 0x%lx, hostt 0x%lx, block 0x%lx,\n", diff -Nru a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h --- a/drivers/scsi/advansys.h Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/advansys.h Wed Nov 27 14:36:32 2002 @@ -54,7 +54,7 @@ int advansys_reset(Scsi_Cmnd *); int advansys_biosparam(struct scsi_device *, struct block_device *, sector_t, int[]); -static int advansys_slave_attach(Scsi_Device *); +static int advansys_slave_configure(Scsi_Device *); #ifdef CONFIG_PROC_FS #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,28) extern struct proc_dir_entry proc_scsi_advansys; @@ -81,7 +81,7 @@ queuecommand: advansys_queuecommand, \ eh_bus_reset_handler: advansys_reset, \ bios_param: advansys_biosparam, \ - slave_attach: advansys_slave_attach, \ + slave_configure: advansys_slave_configure, \ /* \ * Because the driver may control an ISA adapter 'unchecked_isa_dma' \ * must be set. The flag will be cleared in advansys_detect for non-ISA \ diff -Nru a/drivers/scsi/aha152x.h b/drivers/scsi/aha152x.h --- a/drivers/scsi/aha152x.h Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/aha152x.h Wed Nov 27 14:36:31 2002 @@ -42,7 +42,6 @@ eh_bus_reset_handler: aha152x_bus_reset, \ eh_host_reset_handler: aha152x_host_reset, \ release: aha152x_release, \ - slave_attach: 0, \ bios_param: aha152x_biosparam, \ can_queue: 1, \ this_id: 7, \ diff -Nru a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c --- a/drivers/scsi/aic7xxx/aic7770.c Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/aic7xxx/aic7770.c Wed Nov 27 14:36:32 2002 @@ -50,6 +50,7 @@ #define ID_AHA_274x 0x04907771 #define ID_AHA_284xB 0x04907756 /* BIOS enabled */ #define ID_AHA_284x 0x04907757 /* BIOS disabled*/ +#define ID_AIC_7782 0x04907782 static void aha2840_load_seeprom(struct ahc_softc *ahc); static ahc_device_setup_t ahc_aic7770_VL_setup; @@ -76,6 +77,13 @@ ID_AIC7770, 0xFFFFFFFF, "Adaptec aic7770 SCSI adapter", + ahc_aic7770_EISA_setup + }, + { + /* (Olivetti 2 channel EISA) */ + ID_AIC_7782, + 0xFFFFFFFF, + "Adaptec aic7782 SCSI adapter", ahc_aic7770_EISA_setup } }; diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux.c b/drivers/scsi/aic7xxx/aic7xxx_linux.c --- a/drivers/scsi/aic7xxx/aic7xxx_linux.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/aic7xxx/aic7xxx_linux.c Wed Nov 27 14:36:30 2002 @@ -428,7 +428,7 @@ static void ahc_linux_release_sim_queue(u_long arg); static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); -static int ahc_linux_slave_attach(Scsi_Device *device); +static int ahc_linux_slave_configure(Scsi_Device *device); static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, Scsi_Device *device); static struct ahc_linux_target* ahc_linux_alloc_target(struct ahc_softc*, @@ -1446,7 +1446,7 @@ * off the input host adapter. */ static int -ahc_linux_slave_attach(Scsi_Device * device) +ahc_linux_slave_configure(Scsi_Device * device) { struct ahc_softc *ahc; u_long flags; diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h --- a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h Wed Nov 27 14:36:29 2002 +++ b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h Wed Nov 27 14:36:29 2002 @@ -72,7 +72,7 @@ eh_abort_handler: ahc_linux_abort, \ eh_device_reset_handler: ahc_linux_dev_reset, \ eh_bus_reset_handler: ahc_linux_bus_reset, \ - slave_attach: ahc_linux_slave_attach, \ + slave_configure: ahc_linux_slave_configure, \ bios_param: AIC7XXX_BIOSPARAM, \ can_queue: 253, /* max simultaneous cmds */\ this_id: -1, /* scsi id of host adapter */\ diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h Wed Nov 27 14:36:29 2002 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h Wed Nov 27 14:36:29 2002 @@ -72,6 +72,7 @@ #include #include #include +#include #ifndef KERNEL_VERSION #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) diff -Nru a/drivers/scsi/aic7xxx_old/aic7xxx.h b/drivers/scsi/aic7xxx_old/aic7xxx.h --- a/drivers/scsi/aic7xxx_old/aic7xxx.h Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/aic7xxx_old/aic7xxx.h Wed Nov 27 14:36:27 2002 @@ -35,8 +35,9 @@ release: aic7xxx_release, \ info: aic7xxx_info, \ queuecommand: aic7xxx_queue, \ - slave_attach: aic7xxx_slave_attach, \ - slave_detach: aic7xxx_slave_detach, \ + slave_alloc: aic7xxx_slave_alloc, \ + slave_configure: aic7xxx_slave_configure, \ + slave_destroy: aic7xxx_slave_destroy, \ bios_param: aic7xxx_biosparam, \ eh_abort_handler: aic7xxx_abort, \ eh_device_reset_handler: aic7xxx_bus_device_reset, \ @@ -56,8 +57,9 @@ extern int aic7xxx_detect(Scsi_Host_Template *); extern int aic7xxx_command(Scsi_Cmnd *); extern int aic7xxx_release(struct Scsi_Host *); -extern int aic7xxx_slave_attach(Scsi_Device *); -extern void aic7xxx_slave_detach(Scsi_Device *); +static int aic7xxx_slave_alloc(Scsi_Device *); +static int aic7xxx_slave_configure(Scsi_Device *); +static void aic7xxx_slave_destroy(Scsi_Device *); extern int aic7xxx_abort(Scsi_Cmnd *); extern int aic7xxx_bus_device_reset(Scsi_Cmnd *); extern int aic7xxx_reset(Scsi_Cmnd *); diff -Nru a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c --- a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c Wed Nov 27 14:36:31 2002 @@ -313,7 +313,7 @@ p->user[tindex].options); if(sdptr->simple_tags) { - size += sprintf(BLS, " Tagged Command Queueing Enabled, Ordered Tags %s\n", sdptr->ordered_tags ? "Enabled" : "Disabled"); + size += sprintf(BLS, " Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->new_queue_depth, aic_dev->max_q_depth); } if(aic_dev->barrier_total) size += sprintf(BLS, " Total transfers %ld:\n (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n", diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c --- a/drivers/scsi/aic7xxx_old.c Wed Nov 27 14:36:29 2002 +++ b/drivers/scsi/aic7xxx_old.c Wed Nov 27 14:36:29 2002 @@ -3137,36 +3137,18 @@ struct scsi_device *sd; unsigned char active_scb, tcl, scb_tag; int i = 0, init_lists = FALSE; - struct aic_dev_data *aic_dev, *remove_aic_dev = NULL; + struct aic_dev_data *aic_dev; /* * Restore this when we're done */ active_scb = aic_inb(p, SCBPTR); - /* - * If we are still scanning devices, this device may not be linked into - * our host controller yet. So, we grab the temporary aic_dev that we - * allocate during the device scan (by getting device->hostdata for the - * active device) and if the list struct in the aic_dev is empty, we - * add it to p->aic_devs. Then at the end of the function, if we added - * the aic_dev to our host struct so our loop would work, then we just - * remove it. - */ scb_tag = aic_inb(p, SCB_TAG); - if(scb_tag < p->scb_data->numscbs) - { - scbp = p->scb_data->scb_array[scb_tag]; - remove_aic_dev = (struct aic_dev_data *)scbp->cmd->device->hostdata; - if(list_empty(&remove_aic_dev->list)) - list_add_tail(&remove_aic_dev->list, &p->aic_devs); - else - remove_aic_dev = NULL; - } if (aic7xxx_verbose & (VERBOSE_RESET_PROCESS | VERBOSE_ABORT_PROCESS)) { - printk(INFO_LEAD "Reset device, hardware_scb %d, aic_dev %p,\n", - p->host_no, channel, target, lun, active_scb, remove_aic_dev); + printk(INFO_LEAD "Reset device, hardware_scb %d,\n", + p->host_no, channel, target, lun, active_scb); printk(INFO_LEAD "Current scb %d, SEQADDR 0x%x, LASTPHASE " "0x%x\n", p->host_no, channel, target, lun, scb_tag, @@ -3230,8 +3212,6 @@ } } } - if (remove_aic_dev) - list_del(&remove_aic_dev->list); if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS)) printk(INFO_LEAD "Cleaning QINFIFO.\n", p->host_no, channel, target, lun ); @@ -3956,6 +3936,7 @@ unsigned char target, lun, tindex; unsigned char queue_flag = FALSE; char channel; + int result; target = ((aic_inb(p, SAVED_TCL) >> 4) & 0x0f); if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 ) @@ -4457,69 +4438,42 @@ printk(INFO_LEAD "Target busy\n", p->host_no, CTL_OF_SCB(scb)); } #endif -#if 0 if (queue_flag) { - if ( p->dev_last_queue_full[tindex] != - p->dev_active_cmds[tindex] ) - { - p->dev_last_queue_full[tindex] = - p->dev_active_cmds[tindex]; - p->dev_last_queue_full_count[tindex] = 0; - } - else - { - p->dev_last_queue_full_count[tindex]++; - } - if ( (p->dev_last_queue_full_count[tindex] > 14) && - (p->dev_active_cmds[tindex] > 4) ) - { - int diff, lun; - if (p->dev_active_cmds[tindex] > p->dev_lun_queue_depth[tindex]) - /* We don't know what to do here, so bail. */ - break; + int diff; + result = scsi_track_queue_full(cmd->device, + aic_dev->active_cmds); + if ( result < 0 ) + { + if (aic7xxx_verbose & VERBOSE_NEGOTIATION2) + printk(INFO_LEAD "Tagged Command Queueing disabled.\n", + p->host_no, CTL_OF_SCB(scb)); + diff = aic_dev->max_q_depth - p->host->cmd_per_lun; + aic_dev->temp_q_depth = 1; + aic_dev->max_q_depth = 1; + } + else if ( result > 0 ) + { if (aic7xxx_verbose & VERBOSE_NEGOTIATION2) printk(INFO_LEAD "Queue depth reduced to %d\n", p->host_no, - CTL_OF_SCB(scb), p->dev_active_cmds[tindex]); - diff = p->dev_lun_queue_depth[tindex] - - p->dev_active_cmds[tindex]; - p->dev_lun_queue_depth[tindex] -= diff; - for(lun = 0; lun < p->host->max_lun; lun++) - { - if(p->Scsi_Dev[tindex][lun] != NULL) - { - p->dev_max_queue_depth[tindex] -= diff; - scsi_adjust_queue_depth(p->Scsi_Dev[tindex][lun], 1, - p->dev_lun_queue_depth[tindex]); - if(p->dev_temp_queue_depth[tindex] > p->dev_max_queue_depth[tindex]) - p->dev_temp_queue_depth[tindex] = p->dev_max_queue_depth[tindex]; - } - } - p->dev_last_queue_full[tindex] = 0; - p->dev_last_queue_full_count[tindex] = 0; - } - else if (p->dev_active_cmds[tindex] == 0) - { - if (aic7xxx_verbose & VERBOSE_NEGOTIATION) - { - printk(INFO_LEAD "QUEUE_FULL status received with 0 " - "commands active.\n", p->host_no, CTL_OF_SCB(scb)); - printk(INFO_LEAD "Tagged Command Queueing disabled\n", - p->host_no, CTL_OF_SCB(scb)); - } - p->dev_max_queue_depth[tindex] = 1; - p->dev_temp_queue_depth[tindex] = 1; - scb->tag_action = 0; - scb->hscb->control &= ~(MSG_ORDERED_Q_TAG|MSG_SIMPLE_Q_TAG); - } - else - { - aic_dev->flags[tindex] |= DEVICE_WAS_BUSY; - p->dev_temp_queue_depth[tindex] = - p->dev_active_cmds[tindex]; - } - } -#endif + CTL_OF_SCB(scb), result); + diff = aic_dev->max_q_depth - result; + aic_dev->max_q_depth = result; + /* temp_q_depth could have been dropped to 1 for an untagged + * command that might be coming up */ + if(aic_dev->temp_q_depth > result) + aic_dev->temp_q_depth = result; + } + /* We should free up the no unused SCB entries. But, that's + * a difficult thing to do because we use a direct indexed + * array, so we can't just take any entries and free them, + * we *have* to free the ones at the end of the array, and + * they very well could be in use right now, which means + * in order to do this right, we have to add a delayed + * freeing mechanism tied into the scb_free() code area. + * We'll add that later. + */ + } break; } @@ -6623,19 +6577,42 @@ /*+F************************************************************************* * Function: - * aic7xxx_alloc_aic_dev + * aic7xxx_slave_alloc * * Description: * Set up the initial aic_dev struct pointers *-F*************************************************************************/ -static struct aic_dev_data * -aic7xxx_alloc_aic_dev(struct aic7xxx_host *p, Scsi_Device *SDptr) +static int +aic7xxx_slave_alloc(Scsi_Device *SDptr) { + struct aic7xxx_host *p = (struct aic7xxx_host *)SDptr->host->hostdata; struct aic_dev_data *aic_dev; aic_dev = kmalloc(sizeof(struct aic_dev_data), GFP_ATOMIC | GFP_KERNEL); if(!aic_dev) - return aic_dev; + return 1; + /* + * Check to see if channel was scanned. + */ + + if (!(p->flags & AHC_A_SCANNED) && (SDptr->channel == 0)) + { + if (aic7xxx_verbose & VERBOSE_PROBE2) + printk(INFO_LEAD "Scanning channel for devices.\n", + p->host_no, 0, -1, -1); + p->flags |= AHC_A_SCANNED; + } + else + { + if (!(p->flags & AHC_B_SCANNED) && (SDptr->channel == 1)) + { + if (aic7xxx_verbose & VERBOSE_PROBE2) + printk(INFO_LEAD "Scanning channel for devices.\n", + p->host_no, 1, -1, -1); + p->flags |= AHC_B_SCANNED; + } + } + memset(aic_dev, 0, sizeof(struct aic_dev_data)); SDptr->hostdata = aic_dev; aic_dev->SDptr = SDptr; @@ -6643,7 +6620,8 @@ aic_dev->temp_q_depth = 1; scbq_init(&aic_dev->delayed_scbs); INIT_LIST_HEAD(&aic_dev->list); - return aic_dev; + list_add_tail(&aic_dev->list, &p->aic_devs); + return 0; } /*+F************************************************************************* @@ -6752,13 +6730,13 @@ /*+F************************************************************************* * Function: - * aic7xxx_slave_detach + * aic7xxx_slave_destroy * * Description: * prepare for this device to go away *-F*************************************************************************/ -void -aic7xxx_slave_detach(Scsi_Device *sdpnt) +static void +aic7xxx_slave_destroy(Scsi_Device *sdpnt) { struct aic_dev_data *aic_dev = sdpnt->hostdata; @@ -6770,15 +6748,15 @@ /*+F************************************************************************* * Function: - * aic7xxx_slave_attach + * aic7xxx_slave_configure * * Description: * Configure the device we are attaching to the controller. This is * where we get to do things like scan the INQUIRY data, set queue * depths, allocate command structs, etc. *-F*************************************************************************/ -int -aic7xxx_slave_attach(Scsi_Device *sdpnt) +static int +aic7xxx_slave_configure(Scsi_Device *sdpnt) { struct aic7xxx_host *p = (struct aic7xxx_host *) sdpnt->host->hostdata; struct aic_dev_data *aic_dev; @@ -6786,12 +6764,6 @@ aic_dev = (struct aic_dev_data *)sdpnt->hostdata; - if(!aic_dev) { - aic_dev = aic7xxx_alloc_aic_dev(p, sdpnt); - } - if(!aic_dev) - return 1; - aic7xxx_init_transinfo(p, aic_dev); aic7xxx_device_queue_depth(p, sdpnt); if(list_empty(&aic_dev->list)) @@ -10337,39 +10309,7 @@ p = (struct aic7xxx_host *) cmd->host->hostdata; aic_dev = cmd->device->hostdata; - if(!aic_dev) { - aic_dev = aic7xxx_alloc_aic_dev(p, cmd->device); - if(!aic_dev) - return 1; - } - else - { - aic_dev = AIC_DEV(cmd); - } - #ifdef AIC7XXX_VERBOSE_DEBUGGING - /* - * Check to see if channel was scanned. - */ - - if (!(p->flags & AHC_A_SCANNED) && (cmd->channel == 0)) - { - if (aic7xxx_verbose & VERBOSE_PROBE2) - printk(INFO_LEAD "Scanning channel for devices.\n", - p->host_no, 0, -1, -1); - p->flags |= AHC_A_SCANNED; - } - else - { - if (!(p->flags & AHC_B_SCANNED) && (cmd->channel == 1)) - { - if (aic7xxx_verbose & VERBOSE_PROBE2) - printk(INFO_LEAD "Scanning channel for devices.\n", - p->host_no, 1, -1, -1); - p->flags |= AHC_B_SCANNED; - } - } - if (aic_dev->active_cmds > aic_dev->max_q_depth) { printk(WARN_LEAD "Commands queued exceeds queue " @@ -10975,7 +10915,8 @@ aic7xxx_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]) { - int heads, sectors, cylinders, ret; + sector_t heads, sectors, cylinders; + int ret; struct aic7xxx_host *p; unsigned char *buf; @@ -10992,18 +10933,22 @@ heads = 64; sectors = 32; - cylinders = (unsigned long)capacity / (heads * sectors); + cylinders = capacity >> 11; if ((p->flags & AHC_EXTEND_TRANS_A) && (cylinders > 1024)) { heads = 255; sectors = 63; - cylinders = (unsigned long)capacity / (heads * sectors); + cylinders = capacity >> 14; + if(capacity > (65535 * heads * sectors)) + cylinders = 65535; + else + cylinders = ((unsigned int)capacity) / (unsigned int)(heads * sectors); } - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; + geom[0] = (int)heads; + geom[1] = (int)sectors; + geom[2] = (int)cylinders; return (0); } diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c --- a/drivers/scsi/cpqfcTSinit.c Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/cpqfcTSinit.c Wed Nov 27 14:36:27 2002 @@ -1601,7 +1601,7 @@ scsi_cdb[0] = RELEASE; // allocate with wait = true, interruptible = false - SCpnt = scsi_allocate_device(ScsiDev, 1, 0); + SCpnt = scsi_allocate_device(ScsiDev, 1); { CPQFC_DECLARE_COMPLETION(wait); diff -Nru a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c --- a/drivers/scsi/cpqfcTSworker.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/cpqfcTSworker.c Wed Nov 27 14:36:31 2002 @@ -3487,7 +3487,6 @@ static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, PFC_LOGGEDIN_PORT pLoggedInPort) { -// Scsi_Device *sdev = HostAdapter->host_queue; CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; Scsi_Cmnd* *SCptr = &cpqfcHBAdata->LinkDnCmnd[0]; Scsi_Cmnd *Cmnd; diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c --- a/drivers/scsi/dmx3191d.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/dmx3191d.c Wed Nov 27 14:36:30 2002 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "scsi.h" diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c --- a/drivers/scsi/dpt_i2o.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/dpt_i2o.c Wed Nov 27 14:36:31 2002 @@ -355,7 +355,7 @@ } -static int adpt_slave_attach(Scsi_Device * device) +static int adpt_slave_configure(Scsi_Device * device) { struct Scsi_Host *host = device->host; adpt_hba* pHba; @@ -2509,20 +2509,13 @@ Scsi_Cmnd* cmd = NULL; Scsi_Device* d = NULL; - if( pHba->host->host_queue != NULL ) { - d = pHba->host->host_queue; - if(!d){ - return; - } - while( d->next != NULL ){ - for(cmd = d->device_queue; cmd ; cmd = cmd->next){ - if(cmd->serial_number == 0){ - continue; - } - cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1); - cmd->scsi_done(cmd); + list_for_each_entry(d, &pHba->host->my_devices, siblings) { + for(cmd = d->device_queue; cmd ; cmd = cmd->next){ + if(cmd->serial_number == 0){ + continue; } - d = d->next; + cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1); + cmd->scsi_done(cmd); } } } diff -Nru a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h --- a/drivers/scsi/dpti.h Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/dpti.h Wed Nov 27 14:36:27 2002 @@ -44,7 +44,7 @@ static int adpt_abort(Scsi_Cmnd * cmd); static int adpt_reset(Scsi_Cmnd* cmd); static int adpt_release(struct Scsi_Host *host); -static int adpt_slave_attach(Scsi_Device *); +static int adpt_slave_configure(Scsi_Device *); static const char *adpt_info(struct Scsi_Host *pSHost); static int adpt_bios_param(struct scsi_device * sdev, struct block_device *dev, @@ -93,7 +93,7 @@ eh_bus_reset_handler: adpt_bus_reset, \ eh_host_reset_handler: adpt_reset, \ bios_param: adpt_bios_param, \ - slave_attach: adpt_slave_attach, \ + slave_configure: adpt_slave_configure, \ can_queue: MAX_TO_IOP_MESSAGES, /* max simultaneous cmds */\ this_id: 7, /* scsi id of host adapter */\ sg_tablesize: 0, /* max scatter-gather cmds */\ diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c --- a/drivers/scsi/dtc.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/dtc.c Wed Nov 27 14:36:31 2002 @@ -78,15 +78,16 @@ #include #include #include +#include +#include +#include +#include #include #include "scsi.h" #include "hosts.h" #include "dtc.h" #define AUTOPROBE_IRQ #include "NCR5380.h" -#include -#include -#include #define DTC_PUBLIC_RELEASE 2 diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c --- a/drivers/scsi/eata.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/eata.c Wed Nov 27 14:36:31 2002 @@ -464,6 +464,7 @@ #endif +#include #include #include #include @@ -474,18 +475,18 @@ #include #include #include -#include "scsi.h" -#include "hosts.h" -#include -#include -#include "eata.h" +#include #include -#include #include #include #include #include #include +#include "scsi.h" +#include "hosts.h" +#include +#include +#include "eata.h" #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) #error "Adjust your defines" @@ -802,7 +803,7 @@ static int pci_probe = FALSE; #endif -static int eata2x_slave_attach(Scsi_Device *dev) { +static int eata2x_slave_configure(Scsi_Device *dev) { int j, tqd, utqd; char *tag_suffix, *link_suffix; struct Scsi_Host *host = dev->host; diff -Nru a/drivers/scsi/eata.h b/drivers/scsi/eata.h --- a/drivers/scsi/eata.h Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/eata.h Wed Nov 27 14:36:28 2002 @@ -9,7 +9,7 @@ static int eata2x_eh_host_reset(Scsi_Cmnd *); static int eata2x_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); -static int eata2x_slave_attach(Scsi_Device *); +static int eata2x_slave_configure(Scsi_Device *); #define EATA_VERSION "8.00.00" @@ -23,7 +23,7 @@ eh_bus_reset_handler: NULL, \ eh_host_reset_handler: eata2x_eh_host_reset, \ bios_param: eata2x_bios_param, \ - slave_attach: eata2x_slave_attach, \ + slave_configure: eata2x_slave_configure, \ this_id: 7, \ unchecked_isa_dma: 1, \ use_clustering: ENABLE_CLUSTERING \ diff -Nru a/drivers/scsi/eata_dma_proc.c b/drivers/scsi/eata_dma_proc.c --- a/drivers/scsi/eata_dma_proc.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/eata_dma_proc.c Wed Nov 27 14:36:31 2002 @@ -431,11 +431,11 @@ } size = sprintf(buffer+len,"Attached devices: %s\n", - (HBA_ptr->host_queue)?"":"none"); + (!list_empty(&HBA_ptr->my_devices))?"":"none"); len += size; pos = begin + len; - for(scd = HBA_ptr->host_queue; scd; scd = scd->next) { + list_for_each_entry(scd, &HBA_ptr->my_devices, siblings) { proc_print_scsidevice(scd, buffer, &size, len); len += size; pos = begin + len; diff -Nru a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c --- a/drivers/scsi/eata_pio.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/eata_pio.c Wed Nov 27 14:36:31 2002 @@ -58,6 +58,7 @@ #include #include #include +#include #include #include "eata_pio.h" #include "eata_dma_proc.h" @@ -805,13 +806,13 @@ u32 base, x; while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { - DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->name)); + DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->dev.name)); if (pci_enable_device(dev)) continue; pci_set_master(dev); base = pci_resource_flags(dev, 0); if (base & IORESOURCE_MEM) { - printk("eata_pio: invalid base address of device %s\n", dev->name); + printk("eata_pio: invalid base address of device %s\n", dev->dev.name); continue; } base = pci_resource_start(dev, 0); diff -Nru a/drivers/scsi/eata_pio_proc.c b/drivers/scsi/eata_pio_proc.c --- a/drivers/scsi/eata_pio_proc.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/eata_pio_proc.c Wed Nov 27 14:36:31 2002 @@ -81,11 +81,11 @@ goto stop_output; size = sprintf(buffer+len,"Attached devices: %s\n", - (HBA_ptr->host_queue)?"":"none"); + (!list_empty(&HBA_ptr->my_devices))?"":"none"); len += size; pos = begin + len; - for(scd = HBA_ptr->host_queue; scd; scd = scd->next) { + list_for_each_entry(scd, &HBA_ptr->my_devices; siblings) { proc_print_scsidevice(scd, buffer, &size, len); len += size; pos = begin + len; diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c --- a/drivers/scsi/esp.c Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/esp.c Wed Nov 27 14:36:32 2002 @@ -1364,13 +1364,13 @@ copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\tWide\n"); for (i = 0; i < 15; i++) { if (esp->targets_present & (1 << i)) { - Scsi_Device *SDptr = esp->ehost->host_queue; + Scsi_Device *SDptr; struct esp_device *esp_dev; - while ((SDptr->host != esp->ehost) && - (SDptr->id != i) && - (SDptr->next)) - SDptr = SDptr->next; + list_for_each_entry(SDptr, &esp->ehost->my_devices, + siblings) + if(SDptr->id == i) + break; esp_dev = SDptr->hostdata; copy_info(&info, "%d\t\t", i); @@ -1562,24 +1562,6 @@ lun = SCptr->lun; target = SCptr->target; - /* - * We check that esp_dev != NULL. If it is, we allocate it or bail. - */ - if (!esp_dev) { - esp_dev = kmalloc(sizeof(struct esp_device), GFP_ATOMIC); - if (!esp_dev) { - /* We're SOL. Print a message and bail */ - printk(KERN_WARNING "esp: no mem for esp_device %d/%d\n", - target, lun); - esp->current_SC = NULL; - SCptr->result = DID_ERROR << 16; - SCptr->done(SCptr); - return; - } - memset(esp_dev, 0, sizeof(struct esp_device)); - SDptr->hostdata = esp_dev; - } - esp->snip = 0; esp->msgout_len = 0; @@ -4357,12 +4339,24 @@ spin_unlock_irqrestore(esp->ehost->host_lock, flags); } -static void esp_slave_detach(Scsi_Device* SDptr) +static int esp_slave_alloc(Scsi_Device *SDptr) +{ + struct esp_device *esp_dev = + kmalloc(sizeof(struct esp_device), GFP_ATOMIC); + + if (!esp_dev) + return -ENOMEM; + memset(esp_dev, 0, sizeof(struct esp_device)); + SDptr->hostdata = esp_dev; + return 0; +} + +static void esp_slave_destroy(Scsi_Device *SDptr) { struct esp *esp = (struct esp *) SDptr->host->hostdata; + esp->targets_present &= ~(1 << SDptr->id); - if (SDptr->hostdata) - kfree(SDptr->hostdata); + kfree(SDptr->hostdata); SDptr->hostdata = NULL; } @@ -4372,7 +4366,8 @@ .proc_info = esp_proc_info, .name = "Sun ESP 100/100a/200", .detect = esp_detect, - .slave_detach = esp_slave_detach, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .info = esp_info, .command = esp_command, .queuecommand = esp_queue, diff -Nru a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c --- a/drivers/scsi/fcal.c Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/fcal.c Wed Nov 27 14:36:27 2002 @@ -70,7 +70,7 @@ static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd); -int fcal_slave_attach(Scsi_Device *device) +int fcal_slave_configure(Scsi_Device *device) { int depth_to_use; @@ -229,7 +229,7 @@ #endif SPRINTF ("Initiator AL-PA: %02x\n", fc->sid); - SPRINTF ("\nAttached devices: %s\n", host->host_queue ? "" : "none"); + SPRINTF ("\nAttached devices: %s\n", !list_empty(&host->my_devices) ? "" : "none"); for (i = 0; i < fc->posmap->len; i++) { unsigned char alpa = fc->posmap->list[i]; @@ -246,8 +246,8 @@ alpa, u1[0], u1[1], u2[0], u2[1]); } else { Scsi_Device *scd; - for (scd = host->host_queue ; scd; scd = scd->next) - if (scd->host->host_no == hostno && scd->id == target) { + list_for_each_entry (scd, &host->my_devices, siblings) + if (scd->id == target) { SPRINTF (" [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x] ", alpa, target, u1[0], u1[1], u2[0], u2[1]); SPRINTF ("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? diff -Nru a/drivers/scsi/fcal.h b/drivers/scsi/fcal.h --- a/drivers/scsi/fcal.h Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/fcal.h Wed Nov 27 14:36:27 2002 @@ -23,7 +23,7 @@ int fcal_detect(Scsi_Host_Template *); int fcal_release(struct Scsi_Host *); int fcal_proc_info (char *, char **, off_t, int, int, int); -int fcal_slave_attach(Scsi_Device *); +int fcal_slave_configure(Scsi_Device *); #define FCAL { \ name: "Fibre Channel Arbitrated Loop",\ @@ -31,7 +31,7 @@ release: fcal_release, \ proc_info: fcal_proc_info, \ queuecommand: fcp_scsi_queuecommand, \ - slave_attach: fcal_slave_attach, \ + slave_configure: fcal_slave_configure, \ can_queue: FCAL_CAN_QUEUE, \ this_id: -1, \ sg_tablesize: 1, \ diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c --- a/drivers/scsi/g_NCR5380.c Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/g_NCR5380.c Wed Nov 27 14:36:28 2002 @@ -814,7 +814,7 @@ PRINTP(" %d pending writes" ANDP hostdata->pendingw); if (hostdata->pendingr || hostdata->pendingw) PRINTP("\n"); - for (dev = scsi_ptr->host_queue; dev; dev = dev->next) { + list_for_each_entry (dev, &scsi_ptr->my_devices, siblings) { unsigned long br = hostdata->bytes_read[dev->id]; unsigned long bw = hostdata->bytes_write[dev->id]; long tr = hostdata->time_read[dev->id] / HZ; diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c --- a/drivers/scsi/gdth.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/gdth.c Wed Nov 27 14:36:31 2002 @@ -4599,7 +4599,7 @@ #if LINUX_VERSION_CODE >= 0x020322 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); + scp = scsi_allocate_device(sdev, 1); scp->cmd_len = 12; scp->use_sg = 0; #else @@ -4673,7 +4673,7 @@ memset(cmnd, 0xff, MAX_COMMAND_SIZE); #if LINUX_VERSION_CODE >= 0x020322 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); + scp = scsi_allocate_device(sdev, 1); scp->cmd_len = 12; scp->use_sg = 0; #else diff -Nru a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c --- a/drivers/scsi/gdth_proc.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/gdth_proc.c Wed Nov 27 14:36:30 2002 @@ -48,7 +48,7 @@ #if LINUX_VERSION_CODE >= 0x020322 sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]); - scp = scsi_allocate_device(sdev, 1, FALSE); + scp = scsi_allocate_device(sdev, 1); if (!scp) return -ENOMEM; scp->cmd_len = 12; @@ -712,7 +712,7 @@ #if LINUX_VERSION_CODE >= 0x020322 sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]); - scp = scsi_allocate_device(sdev, 1, FALSE); + scp = scsi_allocate_device(sdev, 1); if (!scp) return -ENOMEM; scp->cmd_len = 12; diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c --- a/drivers/scsi/hosts.c Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/hosts.c Wed Nov 27 14:36:27 2002 @@ -208,6 +208,48 @@ return 0; } +static int scsi_check_device_busy(struct scsi_device *sdev) +{ + struct Scsi_Host *shost = sdev->host; + struct scsi_cmnd *scmd; + + /* + * Loop over all of the commands associated with the + * device. If any of them are busy, then set the state + * back to inactive and bail. + */ + for (scmd = sdev->device_queue; scmd; scmd = scmd->next) { + if (scmd->request && scmd->request->rq_status != RQ_INACTIVE) + goto active; + + /* + * No, this device is really free. Mark it as such, and + * continue on. + */ + scmd->state = SCSI_STATE_DISCONNECTING; + if (scmd->request) + scmd->request->rq_status = RQ_SCSI_DISCONNECTING; + } + + return 0; + +active: + printk(KERN_ERR "SCSI device not inactive - rq_status=%d, target=%d, " + "pid=%ld, state=%d, owner=%d.\n", + scmd->request->rq_status, scmd->target, + scmd->pid, scmd->state, scmd->owner); + + list_for_each_entry(sdev, &shost->my_devices, siblings) { + for (scmd = sdev->device_queue; scmd; scmd = scmd->next) { + if (scmd->request->rq_status == RQ_SCSI_DISCONNECTING) + scmd->request->rq_status = RQ_INACTIVE; + } + } + + printk(KERN_ERR "Device busy???\n"); + return 1; +} + /** * scsi_remove_host - check a scsi host for release and release * @shost: a pointer to a scsi host to release @@ -218,59 +260,25 @@ int scsi_remove_host(struct Scsi_Host *shost) { struct scsi_device *sdev; - struct scsi_cmnd *scmd; + struct list_head *le, *lh; /* * FIXME Do ref counting. We force all of the devices offline to * help prevent race conditions where other hosts/processors could * try and get in and queue a command. */ - for (sdev = shost->host_queue; sdev; sdev = sdev->next) + list_for_each_entry(sdev, &shost->my_devices, siblings) sdev->online = FALSE; - for (sdev = shost->host_queue; sdev; sdev = sdev->next) { - /* - * Loop over all of the commands associated with the - * device. If any of them are busy, then set the state - * back to inactive and bail. - */ - for (scmd = sdev->device_queue; scmd; scmd = scmd->next) { - if (scmd->request && scmd->request->rq_status != - RQ_INACTIVE) { - printk(KERN_ERR "SCSI device not inactive" - "- rq_status=%d, target=%d, pid=%ld," - "state=%d, owner=%d.\n", - scmd->request->rq_status, - scmd->target, scmd->pid, - scmd->state, scmd->owner); - for (sdev = shost->host_queue; sdev; - sdev = sdev->next) { - for (scmd = sdev->device_queue; scmd; - scmd = scmd->next) - if (scmd->request->rq_status == - RQ_SCSI_DISCONNECTING) - scmd->request->rq_status = RQ_INACTIVE; - } - printk(KERN_ERR "Device busy???\n"); - return 1; - } - /* - * No, this device is really free. Mark it as such, and - * continue on. - */ - scmd->state = SCSI_STATE_DISCONNECTING; - if (scmd->request) - scmd->request->rq_status = - RQ_SCSI_DISCONNECTING; /* Mark as - busy */ - } - } + list_for_each_entry(sdev, &shost->my_devices, siblings) + if (scsi_check_device_busy(sdev)) + return 1; /* * Next we detach the high level drivers from the Scsi_Device * structures */ - for (sdev = shost->host_queue; sdev; sdev = sdev->next) { + list_for_each_entry(sdev, &shost->my_devices, siblings) { scsi_detach_device(sdev); /* If something still attached, punt */ @@ -285,14 +293,8 @@ /* Next we free up the Scsi_Cmnd structures for this host */ - for (sdev = shost->host_queue; sdev; - sdev = shost->host_queue) { - blk_cleanup_queue(&sdev->request_queue); - /* Next free up the Scsi_Device structures for this host */ - shost->host_queue = sdev->next; - if (sdev->inquiry) - kfree(sdev->inquiry); - kfree(sdev); + list_for_each_safe(le, lh, &shost->my_devices) { + scsi_free_sdev(list_entry(le, Scsi_Device, siblings)); } return 0; @@ -302,23 +304,21 @@ { Scsi_Host_Template *sht = shost->hostt; struct scsi_device *sdev; - int error = 0; + int error = 0, saved_error = 0; printk(KERN_INFO "scsi%d : %s\n", shost->host_no, sht->info ? sht->info(shost) : sht->name); device_register(&shost->host_driverfs_dev); - scan_scsis(shost, 0, 0, 0, 0); + scsi_scan_host(shost); - for (sdev = shost->host_queue; sdev; sdev = sdev->next) { - if (sdev->host->hostt != sht) - continue; /* XXX(hch): can this really happen? */ + list_for_each_entry (sdev, &shost->my_devices, siblings) { error = scsi_attach_device(sdev); if (error) - break; + saved_error = error; } - return error; + return saved_error; } /** @@ -370,7 +370,6 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes) { struct Scsi_Host *shost, *shost_scr; - struct list_head *lh; int gfp_mask; DECLARE_MUTEX_LOCKED(sem); @@ -401,6 +400,7 @@ spin_lock_init(&shost->default_lock); scsi_assign_lock(shost, &shost->default_lock); atomic_set(&shost->host_active,0); + INIT_LIST_HEAD(&shost->my_devices); init_waitqueue_head(&shost->host_wait); shost->dma_channel = 0xff; @@ -449,8 +449,7 @@ * orders the scsi_host_list by host number and just do a * list_add_tail. */ - list_for_each(lh, &scsi_host_list) { - shost_scr = list_entry(lh, struct Scsi_Host, sh_list); + list_for_each_entry(shost_scr, &scsi_host_list, sh_list) { if (shost->host_no < shost_scr->host_no) { __list_add(&shost->sh_list, shost_scr->sh_list.prev, &shost_scr->sh_list); @@ -683,10 +682,7 @@ * Notes: * Attach a single Scsi_Device to the Scsi_Host - this should * be made to look like a "pseudo-device" that points to the - * HA itself. For the moment, we include it at the head of - * the host_queue itself - I don't think we want to show this - * to the HA in select_queue_depths(), as this would probably confuse - * matters. + * HA itself. * * Note - this device is not accessible from any high-level * drivers (including generics), which is probably not diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h --- a/drivers/scsi/hosts.h Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/hosts.h Wed Nov 27 14:36:28 2002 @@ -187,59 +187,73 @@ int (*reset)(int,int); /* - * Once the device has responded to an INQUIRY and we know the device - * is online, call into the low level driver with the Scsi_Device * - * (so that the low level driver may save it off in a safe location - * for later use in calling scsi_adjust_queue_depth() or possibly - * other scsi_* functions) and char * to the INQUIRY return data buffer. - * This way, low level drivers will no longer have to snoop INQUIRY data - * to see if a drive supports PPR message protocol for Ultra160 speed - * negotiations or other similar items. Instead it can simply wait until - * the scsi mid layer calls them with the data in hand and then it can - * do it's checking of INQUIRY data. This will happen once for each new - * device added on this controller (including once for each lun on - * multi-lun devices, so low level drivers should take care to make - * sure that if they do tagged queueing on a per physical unit basis - * instead of a per logical unit basis that they have the mid layer - * allocate tags accordingly). + * slave_alloc() - Optional + * + * Before the mid layer attempts to scan for a new device where none + * currently exists, it will call this entry in your driver. Should + * your driver need to allocate any structs or perform any other init + * items in order to send commands to a currently unused target/lun + * combo, then this is where you can perform those allocations. This + * is specifically so that drivers won't have to perform any kind of + * "is this a new device" checks in their queuecommand routine, + * thereby making the hot path a bit quicker. + * + * Return values: 0 on success, non-0 on failure * + * Deallocation: If we didn't find any devices at this ID, you will + * get an immediate call to slave_destroy(). If we find something here + * then you will get a call to slave_configure(), then the device will be + * used for however long it is kept around, then when the device is + * removed from the system (or * possibly at reboot time), you will + * then get a call to slave_detach(). This is assuming you implement + * slave_configure and slave_destroy. However, if you allocate memory + * and hang it off the device struct, then you must implement the + * slave_destroy() routine at a minimum in order to avoid leaking memory + * each time a device is tore down. + */ + int (* slave_alloc)(Scsi_Device *); + + /* + * slave_configure() - Optional + * + * Once the device has responded to an INQUIRY and we know the device + * is online, we call into the low level driver with the Scsi_Device * + * If the low level device driver implements this function, it *must* + * perform the task of setting the queue depth on the device. All other + * tasks are optional and depend on what the driver supports and various + * implementation details. + * * Things currently recommended to be handled at this time include: * - * 1. Checking for tagged queueing capability and if able then calling - * scsi_adjust_queue_depth() with the device pointer and the - * suggested new queue depth. - * 2. Checking for things such as SCSI level or DT bit in order to - * determine if PPR message protocols are appropriate on this - * device (or any other scsi INQUIRY data specific things the - * driver wants to know in order to properly handle this device). + * 1. Setting the device queue depth. Proper setting of this is + * described in the comments for scsi_adjust_queue_depth. + * 2. Determining if the device supports the various synchronous + * negotiation protocols. The device struct will already have + * responded to INQUIRY and the results of the standard items + * will have been shoved into the various device flag bits, eg. + * device->sdtr will be true if the device supports SDTR messages. * 3. Allocating command structs that the device will need. * 4. Setting the default timeout on this device (if needed). - * 5. Saving the Scsi_Device pointer so that the low level driver - * will be able to easily call back into scsi_adjust_queue_depth - * again should it be determined that the queue depth for this - * device should be lower or higher than it is initially set to. - * 6. Allocate device data structures as needed that can be attached - * to the Scsi_Device * via SDpnt->host_device_ptr - * 7. Anything else the low level driver might want to do on a device + * 5. Anything else the low level driver might want to do on a device * specific setup basis... - * 8. Return 0 on success, non-0 on error. The device will be marked - * as offline on error so that no access will occur. + * 6. Return 0 on success, non-0 on error. The device will be marked + * as offline on error so that no access will occur. If you return + * non-0, your slave_detach routine will never get called for this + * device, so don't leave any loose memory hanging around, clean + * up after yourself before returning non-0 */ - int (* slave_attach)(Scsi_Device *); + int (* slave_configure)(Scsi_Device *); /* - * If we are getting ready to remove a device from the scsi chain then - * we call into the low level driver to let them know. Once a low - * level driver has been informed that a drive is going away, the low - * level driver *must* remove it's pointer to the Scsi_Device because - * it is going to be kfree()'ed shortly. It is no longer safe to call - * any mid layer functions with this Scsi_Device *. Additionally, the - * mid layer will not make any more calls into the low level driver's - * queue routine with this device, so it is safe for the device driver - * to deallocate all structs/commands/etc that is has allocated - * specifically for this device at the time of this call. + * slave_destroy() - Optional + * + * Immediately prior to deallocating the device and after all activity + * has ceased the mid layer calls this point so that the low level driver + * may completely detach itself from the scsi device and vice versa. + * The low level driver is responsible for freeing any memory it allocated + * in the slave_alloc or slave_configure calls. */ - void (* slave_detach)(Scsi_Device *); + void (* slave_destroy)(Scsi_Device *); /* * This function determines the bios parameters for a given @@ -359,8 +373,6 @@ * struct private is a way of marking it in a sort of C++ type of way. */ struct list_head sh_list; - Scsi_Device * host_queue; - struct list_head all_scsi_hosts; struct list_head my_devices; spinlock_t default_lock; @@ -519,7 +531,7 @@ /* * Prototypes for functions/data in scsi_scan.c */ -extern void scan_scsis(struct Scsi_Host *, uint, uint, uint, uint); +extern void scsi_scan_host(struct Scsi_Host *); struct Scsi_Device_Template { @@ -585,9 +597,7 @@ int channel, int pun, int lun) { Scsi_Device *sdev; - for (sdev = shost->host_queue; - sdev != NULL; - sdev = sdev->next) + list_for_each_entry (sdev, &shost->my_devices, siblings) if (sdev->channel == channel && sdev->id == pun && sdev->lun ==lun) break; diff -Nru a/drivers/scsi/i60uscsi.c b/drivers/scsi/i60uscsi.c --- a/drivers/scsi/i60uscsi.c Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/i60uscsi.c Wed Nov 27 14:36:28 2002 @@ -566,10 +566,10 @@ ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST); if (waitSCSIRSTdone(pHCB) == FALSE) { spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return (SCSI_RESET_ERROR); + return FAILED; } else { spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return (SCSI_RESET_SUCCESS); + return SUCCESS; } } @@ -581,7 +581,7 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target, unsigned int ResetFlags) +int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target) { /* I need Host Control Block Information */ ORC_SCB *pScb; ESCB *pVirEscb; @@ -608,11 +608,11 @@ if (i == ORC_MAXQUEUE) { printk("Unable to Reset - No SCB Found\n"); spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return (SCSI_RESET_NOT_RUNNING); + return FAILED; } if ((pScb = orc_alloc_scb(pHCB)) == NULL) { spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return (SCSI_RESET_NOT_RUNNING); + return FAILED; } pScb->SCB_Opcode = ORC_BUSDEVRST; pScb->SCB_Target = target; @@ -626,12 +626,10 @@ pScb->SCB_SGLen = 0; pVirEscb->SCB_Srb = 0; - if (ResetFlags & SCSI_RESET_SYNCHRONOUS) { - pVirEscb->SCB_Srb = SCpnt; - } + pVirEscb->SCB_Srb = SCpnt; orc_exec_scb(pHCB, pScb); /* Start execute SCB */ spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return SCSI_RESET_PENDING; + return SUCCESS; } @@ -838,21 +836,21 @@ if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) { if (pVirScb->SCB_TagMsg == 0) { spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); - return (SCSI_ABORT_BUSY); + return FAILED; } else { if (abort_SCB(hcsp, pVirScb)) { pVirEscb->SCB_Srb = NULL; spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); - return (SCSI_ABORT_SUCCESS); + return SUCCESS; } else { spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); - return (SCSI_ABORT_NOT_RUNNING); + return FAILED; } } } } spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); - return (SCSI_ABORT_NOT_RUNNING); + return FAILED; } /*********************************************************************** diff -Nru a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c --- a/drivers/scsi/in2000.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/in2000.c Wed Nov 27 14:36:31 2002 @@ -1885,14 +1885,14 @@ 0 }; -static const unsigned short base_tab[] in2000__INITDATA = { +static unsigned short base_tab[] in2000__INITDATA = { 0x220, 0x200, 0x110, 0x100, }; -static const int int_tab[] in2000__INITDATA = { +static int int_tab[] in2000__INITDATA = { 15, 14, 11, diff -Nru a/drivers/scsi/ini9100u.h b/drivers/scsi/ini9100u.h --- a/drivers/scsi/ini9100u.h Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/ini9100u.h Wed Nov 27 14:36:30 2002 @@ -105,7 +105,6 @@ eh_host_reset_handler: NULL, \ abort: i91u_abort, \ reset: i91u_reset, \ - slave_attach: NULL, \ bios_param: i91u_biosparam, \ can_queue: 1, \ this_id: 1, \ diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c --- a/drivers/scsi/inia100.c Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/inia100.c Wed Nov 27 14:36:28 2002 @@ -126,7 +126,7 @@ extern void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp); extern void orc_release_dma(ORC_HCS * hcsp, Scsi_Cmnd * cmnd); extern void orc_interrupt(ORC_HCS * hcsp); -extern int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target, unsigned int ResetFlags); +extern int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target); extern int orc_reset_scsi_bus(ORC_HCS * pHCB); extern int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb); extern int orc_abort_srb(ORC_HCS * hcsp, Scsi_Cmnd *SCpnt); @@ -366,7 +366,11 @@ printk("inia100: initial orchid fail!!\n"); goto out_unalloc; } - request_region(pHCB->HCS_Base, 256, "inia100"); /* Register */ + if (!request_region(pHCB->HCS_Base, 256, "inia100")) { + printk(KERN_WARNING "inia100: io port 0x%x, is busy.\n", + pHCB->HCS_Base); + return (0); + } hreg->io_port = pHCB->HCS_Base; hreg->n_io_port = 0xff; @@ -514,7 +518,7 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) +static int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) { register ORC_SCB *pSCB; ORC_HCS *pHCB; /* Point to Host adapter control block */ @@ -541,7 +545,7 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -int inia100_abort(Scsi_Cmnd * SCpnt) +static int inia100_abort(Scsi_Cmnd * SCpnt) { ORC_HCS *hcsp; @@ -557,15 +561,25 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -int inia100_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) +static int inia100_bus_reset(Scsi_Cmnd * SCpnt) { /* I need Host Control Block Information */ ORC_HCS *pHCB; pHCB = (ORC_HCS *) SCpnt->host->hostdata; + return orc_reset_scsi_bus(pHCB); +} - if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) - return orc_reset_scsi_bus(pHCB); - else - return orc_device_reset(pHCB, SCpnt, SCpnt->target, reset_flags); +/***************************************************************************** + Function name : inia100_device_reset + Description : Reset the device + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +static int inia100_device_reset(Scsi_Cmnd * SCpnt) +{ /* I need Host Control Block Information */ + ORC_HCS *pHCB; + pHCB = (ORC_HCS *) SCpnt->host->hostdata; + return orc_device_reset(pHCB, SCpnt, SCpnt->target); } @@ -648,41 +662,6 @@ return; } -/***************************************************************************** - Function name : inia100_biosparam - Description : Return the "logical geometry" - Input : pHCB - Pointer to host adapter structure - Output : None. - Return : pSRB - Pointer to SCSI request block. -*****************************************************************************/ -int inia100_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *info_array) -{ - ORC_HCS *pHcb; /* Point to Host adapter control block */ - ORC_TCS *pTcb; - - pHcb = (ORC_HCS *) sdev->host->hostdata; - pTcb = &pHcb->HCS_Tcs[sdev->id]; - - if (pTcb->TCS_DrvHead) { - info_array[0] = pTcb->TCS_DrvHead; - info_array[1] = pTcb->TCS_DrvSector; - info_array[2] = (unsigned long)capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector; - } else { - if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) { - info_array[0] = 255; - info_array[1] = 63; - info_array[2] = (unsigned long)capacity / 255 / 63; - } else { - info_array[0] = 64; - info_array[1] = 32; - info_array[2] = capacity >> 11; - } - } - return 0; -} - - /* * Interrupt handler (main routine of the driver) */ @@ -710,7 +689,7 @@ /* * Release ressources */ -int inia100_release(struct Scsi_Host *hreg) +static int inia100_release(struct Scsi_Host *hreg) { ORC_HCS *pHCB = (ORC_HCS *)hreg->hostdata; diff -Nru a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h --- a/drivers/scsi/inia100.h Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/inia100.h Wed Nov 27 14:36:27 2002 @@ -75,14 +75,12 @@ #include #include -extern int inia100_detect(Scsi_Host_Template *); -extern int inia100_release(struct Scsi_Host *); -extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -extern int inia100_abort(Scsi_Cmnd *); -extern int inia100_reset(Scsi_Cmnd *, unsigned int); - -extern int inia100_biosparam(struct scsi_device *, struct block_device *, - sector_t, int *); +static int inia100_detect(Scsi_Host_Template *); +static int inia100_release(struct Scsi_Host *); +static int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +static int inia100_abort(Scsi_Cmnd *); +static int inia100_device_reset(Scsi_Cmnd *); +static int inia100_bus_reset(Scsi_Cmnd *); #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02d" @@ -92,8 +90,9 @@ detect: inia100_detect, \ release: inia100_release, \ queuecommand: inia100_queue, \ - abort: inia100_abort, \ - reset: inia100_reset, \ + eh_abort_handler:inia100_abort, \ + eh_bus_reset_handler: inia100_bus_reset, \ + eh_device_reset_handler:inia100_device_reset, \ can_queue: 1, \ this_id: 1, \ sg_tablesize: SG_ALL, \ diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c --- a/drivers/scsi/ips.c Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/ips.c Wed Nov 27 14:36:27 2002 @@ -83,7 +83,7 @@ /* 2.3.18 and later */ /* - Sync with other changes from the 2.3 kernels */ /* 4.00.06 - Fix timeout with initial FFDC command */ -/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig */ +/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig */ /* 4.10.00 - Add support for ServeRAID 4M/4L */ /* 4.10.13 - Fix for dynamic unload and proc file system */ /* 4.20.03 - Rename version to coincide with new release schedules */ @@ -190,6 +190,7 @@ #ifdef MODULE static char *ips = NULL; MODULE_PARM(ips, "s"); + MODULE_LICENSE("GPL"); #endif /* @@ -433,7 +434,7 @@ int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *)); int ips_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); -int ips_slave_attach(Scsi_Device *); +int ips_slave_configure(Scsi_Device *); const char * ips_info(struct Scsi_Host *); void do_ipsintr(int, void *, struct pt_regs *); static int ips_hainit(ips_ha_t *); @@ -856,7 +857,7 @@ ips_name, ips_next_controller, mem_addr, mem_len); #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) - if (check_mem_region(mem_addr, mem_len)) { + if (!request_mem_region(mem_addr, mem_len, "ips")) { /* Couldn't allocate io space */ printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n", ips_name, ips_next_controller, io_addr, io_len); @@ -866,7 +867,6 @@ continue; } - request_mem_region(mem_addr, mem_len, "ips"); #endif base = mem_addr & PAGE_MASK; @@ -884,7 +884,7 @@ DEBUG_VAR(1, "(%s%d) detect, IO region %x, size: %d", ips_name, ips_next_controller, io_addr, io_len); - if (check_region(io_addr, io_len)) { + if (!request_region(io_addr, io_len, "ips")) { /* Couldn't allocate io space */ printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n", ips_name, ips_next_controller, io_addr, io_len); @@ -893,8 +893,6 @@ continue; } - - request_region(io_addr, io_len, "ips"); } /* get planer status */ @@ -1866,7 +1864,7 @@ /****************************************************************************/ /* */ -/* Routine Name: ips_slave_attach */ +/* Routine Name: ips_slave_configure */ /* */ /* Routine Description: */ /* */ @@ -1874,7 +1872,7 @@ /* */ /****************************************************************************/ int -ips_slave_attach(Scsi_Device *SDptr) +ips_slave_configure(Scsi_Device *SDptr) { ips_ha_t *ha; int min; @@ -7329,12 +7327,11 @@ uint32_t base; uint32_t offs; - if (check_mem_region(mem_addr, mem_len)) { + if (!request_mem_region(mem_addr, mem_len, "ips")) { printk(KERN_WARNING "Couldn't allocate IO Memory space %x len %d.\n", mem_addr, mem_len); return -1; } - request_mem_region(mem_addr, mem_len, "ips"); base = mem_addr & PAGE_MASK; offs = mem_addr - base; ioremap_ptr = ioremap(base, PAGE_SIZE); @@ -7346,11 +7343,10 @@ /* setup I/O mapped area (if applicable) */ if (io_addr) { - if (check_region(io_addr, io_len)) { + if (!request_region(io_addr, io_len, "ips")) { printk(KERN_WARNING "Couldn't allocate IO space %x len %d.\n", io_addr, io_len); return -1; } - request_region(io_addr, io_len, "ips"); } /* get the revision ID */ diff -Nru a/drivers/scsi/ips.h b/drivers/scsi/ips.h --- a/drivers/scsi/ips.h Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/ips.h Wed Nov 27 14:36:28 2002 @@ -61,7 +61,7 @@ extern int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *)); extern int ips_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); - extern int ips_slave_attach(Scsi_Device *); + extern int ips_slave_configure(Scsi_Device *); extern const char * ips_info(struct Scsi_Host *); extern void do_ips(int, void *, struct pt_regs *); @@ -471,7 +471,7 @@ queuecommand : ips_queue, \ eh_abort_handler : ips_eh_abort, \ eh_host_reset_handler : ips_eh_reset, \ - slave_attach : ips_slave_attach, \ + slave_configure : ips_slave_configure,\ bios_param : ips_biosparam, \ can_queue : 0, \ this_id: -1, \ diff -Nru a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h --- a/drivers/scsi/megaraid.h Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/megaraid.h Wed Nov 27 14:36:30 2002 @@ -974,13 +974,11 @@ mega_ioctl_mbox * mbox); #endif -static int megadev_open (struct inode *, struct file *); static int megadev_ioctl_entry (struct inode *, struct file *, unsigned int, unsigned long); static int megadev_ioctl (struct inode *, struct file *, unsigned int, unsigned long); static mega_scb *megadev_doioctl (mega_host_config *, Scsi_Cmnd *); -static int megadev_close (struct inode *, struct file *); static void megadev_ioctl_done (Scsi_Cmnd *); static int mega_init_scb (mega_host_config *); static void enq_scb_freelist (mega_host_config *, mega_scb *, diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c --- a/drivers/scsi/ncr53c8xx.c Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/ncr53c8xx.c Wed Nov 27 14:36:28 2002 @@ -8496,7 +8496,7 @@ ** Linux select queue depths function */ -int ncr53c8xx_slave_attach(Scsi_Device *device) +int ncr53c8xx_slave_configure(Scsi_Device *device) { struct Scsi_Host *host = device->host; ncb_p np; diff -Nru a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h --- a/drivers/scsi/ncr53c8xx.h Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/ncr53c8xx.h Wed Nov 27 14:36:28 2002 @@ -59,7 +59,7 @@ const char *ncr53c8xx_info(struct Scsi_Host *host); int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int); -int ncr53c8xx_slave_attach(Scsi_Device *); +int ncr53c8xx_slave_configure(Scsi_Device *); #ifdef MODULE int ncr53c8xx_release(struct Scsi_Host *); @@ -75,7 +75,7 @@ release: ncr53c8xx_release, \ info: ncr53c8xx_info, \ queuecommand: ncr53c8xx_queue_command,\ - slave_attach: ncr53c8xx_slave_attach, \ + slave_configure:ncr53c8xx_slave_configure,\ abort: ncr53c8xx_abort, \ reset: ncr53c8xx_reset, \ can_queue: SCSI_NCR_CAN_QUEUE, \ diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c --- a/drivers/scsi/pas16.c Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/pas16.c Wed Nov 27 14:36:27 2002 @@ -119,14 +119,16 @@ #include #include #include +#include +#include +#include + #include "scsi.h" #include "hosts.h" #include "pas16.h" #define AUTOPROBE_IRQ #include "NCR5380.h" -#include -#include static int pas_maxi = 0; static int pas_wmaxi = 0; diff -Nru a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c --- a/drivers/scsi/pcmcia/aha152x_stub.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/pcmcia/aha152x_stub.c Wed Nov 27 14:36:31 2002 @@ -297,7 +297,7 @@ for (host = scsi_host_get_next(NULL); host; host = scsi_host_get_next(host)) if (host->hostt == &driver_template) - for (dev = host->host_queue; dev; dev = dev->next) { + list_for_each_entry (dev, &host->my_devices, siblings) { u_long arg[2], id; kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c --- a/drivers/scsi/pcmcia/fdomain_stub.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/pcmcia/fdomain_stub.c Wed Nov 27 14:36:30 2002 @@ -261,7 +261,7 @@ for (host = scsi_host_get_next(NULL); host; host = scsi_host_get_next(host)) if (host->hostt == &driver_template) - for (dev = host->host_queue; dev; dev = dev->next) { + list_for_each_entry (dev, &host->my_devices, siblings) { u_long arg[2], id; kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c --- a/drivers/scsi/pcmcia/nsp_cs.c Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/pcmcia/nsp_cs.c Wed Nov 27 14:36:32 2002 @@ -1779,7 +1779,7 @@ for (host = scsi_hostlist; host != NULL; host = host->next) { #endif if (host->hostt == &driver_template) { - for (dev = host->host_queue; dev != NULL; dev = dev->next) { + list_for_each_entry (dev, &host->my_devices, siblings) { u_long arg[2], id; kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c --- a/drivers/scsi/pcmcia/qlogic_stub.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/pcmcia/qlogic_stub.c Wed Nov 27 14:36:30 2002 @@ -284,7 +284,7 @@ for (host = scsi_host_get_next(NULL); host; host = scsi_host_get_next(host)) if (host->hostt == &driver_template) - for (dev = host->host_queue; dev; dev = dev->next) { + list_for_each_entry (dev, &host->my_devices, siblings) { u_long arg[2], id; kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + diff -Nru a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c --- a/drivers/scsi/pluto.c Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/pluto.c Wed Nov 27 14:36:28 2002 @@ -71,7 +71,7 @@ up(&fc_sem); } -int pluto_slave_attach(Scsi_Device *device) +int pluto_slave_configure(Scsi_Device *device) { int depth_to_use; diff -Nru a/drivers/scsi/pluto.h b/drivers/scsi/pluto.h --- a/drivers/scsi/pluto.h Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/pluto.h Wed Nov 27 14:36:30 2002 @@ -41,7 +41,7 @@ int pluto_detect(Scsi_Host_Template *); int pluto_release(struct Scsi_Host *); const char * pluto_info(struct Scsi_Host *); -int pluto_slave_attach(Scsi_Device *); +int pluto_slave_configure(Scsi_Device *); #define PLUTO { \ name: "Sparc Storage Array 100/200", \ @@ -49,7 +49,7 @@ release: pluto_release, \ info: pluto_info, \ queuecommand: fcp_scsi_queuecommand, \ - slave_attach: pluto_slave_attach, \ + slave_configure: pluto_slave_configure, \ can_queue: PLUTO_CAN_QUEUE, \ this_id: -1, \ sg_tablesize: 1, \ diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/qla1280.c Wed Nov 27 14:36:32 2002 @@ -381,7 +381,7 @@ static void qla1280_next(struct scsi_qla_host *, scsi_lu_t *, int); static void qla1280_putq_t(scsi_lu_t *, srb_t *); static void qla1280_done_q_put(srb_t *, srb_t **, srb_t **); -static int qla1280_slave_attach(Scsi_Device *); +static int qla1280_slave_configure(Scsi_Device *); #if STOP_ON_ERROR static void qla1280_panic(char *, struct Scsi_Host *host); #endif @@ -1794,7 +1794,7 @@ } /************************************************************************** - * qla1280_slave_attach + * qla1280_slave_configure * * Description: * Determines the queue depth for a given device. There are two ways @@ -1805,7 +1805,7 @@ * default queue depth (dependent on the number of hardware SCBs). **************************************************************************/ static int -qla1280_slave_attach(Scsi_Device * device) +qla1280_slave_configure(Scsi_Device * device) { struct scsi_qla_host *p = (struct scsi_qla_host *)device->host->hostdata; int bus = device->channel; diff -Nru a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h --- a/drivers/scsi/qla1280.h Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/qla1280.h Wed Nov 27 14:36:32 2002 @@ -1315,7 +1315,7 @@ int qla1280_reset(Scsi_Cmnd *, unsigned int); int qla1280_biosparam(struct scsi_device *, struct block_device *, sector_t, int[]); -static int qla1280_slave_attach(Scsi_Device *); +static int qla1280_slave_configure(Scsi_Device *); void qla1280_intr_handler(int, void *, struct pt_regs *); void qla1280_setup(char *s, int *dummy); @@ -1334,7 +1334,7 @@ /* use_new_eh_code: 0, */ \ abort: qla1280_abort, \ reset: qla1280_reset, \ - slave_attach: qla1280_slave_attach, \ + slave_configure: qla1280_slave_configure, \ bios_param: qla1280_biosparam, \ can_queue: 255, /* max simultaneous cmds */\ this_id: -1, /* scsi id of host adapter */\ diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/scsi.c Wed Nov 27 14:36:30 2002 @@ -347,6 +347,33 @@ } /* + * FIXME(eric) - this is not at all optimal. Given that + * single lun devices are rare and usually slow + * (i.e. CD changers), this is good enough for now, but + * we may want to come back and optimize this later. + * + * Scan through all of the devices attached to this + * host, and see if any are active or not. If so, + * we need to defer this command. + * + * We really need a busy counter per device. This would + * allow us to more easily figure out whether we should + * do anything here or not. + */ +static int check_all_luns(struct Scsi_Host *shost, struct scsi_device *myself) +{ + struct scsi_device *sdev; + + list_for_each_entry(sdev, &myself->same_target_siblings, + same_target_siblings) { + if (atomic_read(&sdev->device_active)) + return 1; + } + + return 0; +} + +/* * Function: scsi_allocate_device * * Purpose: Allocate a command descriptor. @@ -372,172 +399,87 @@ * This function is deprecated, and drivers should be * rewritten to use Scsi_Request instead of Scsi_Cmnd. */ - -Scsi_Cmnd *scsi_allocate_device(Scsi_Device * device, int wait, - int interruptable) +struct scsi_cmnd *scsi_allocate_device(struct scsi_device *sdev, int wait) { - struct Scsi_Host *host; - Scsi_Cmnd *SCpnt = NULL; - Scsi_Device *SDpnt; + DECLARE_WAITQUEUE(wq, current); + struct Scsi_Host *shost = sdev->host; + struct scsi_cmnd *scmnd; unsigned long flags; - - if (!device) - panic("No device passed to scsi_allocate_device().\n"); - - host = device->host; - + spin_lock_irqsave(&device_request_lock, flags); - - while (1 == 1) { - SCpnt = NULL; - if (!device->device_blocked) { - if (device->single_lun) { - /* - * FIXME(eric) - this is not at all optimal. Given that - * single lun devices are rare and usually slow - * (i.e. CD changers), this is good enough for now, but - * we may want to come back and optimize this later. - * - * Scan through all of the devices attached to this - * host, and see if any are active or not. If so, - * we need to defer this command. - * - * We really need a busy counter per device. This would - * allow us to more easily figure out whether we should - * do anything here or not. - */ - for (SDpnt = host->host_queue; - SDpnt; - SDpnt = SDpnt->next) { - /* - * Only look for other devices on the same bus - * with the same target ID. - */ - if (SDpnt->channel != device->channel - || SDpnt->id != device->id - || SDpnt == device) { - continue; - } - if( atomic_read(&SDpnt->device_active) != 0) - { - break; - } - } - if (SDpnt) { - /* - * Some other device in this cluster is busy. - * If asked to wait, we need to wait, otherwise - * return NULL. - */ - SCpnt = NULL; - goto busy; - } - } - /* - * Now we can check for a free command block for this device. - */ - for (SCpnt = device->device_queue; SCpnt; SCpnt = SCpnt->next) { - if (SCpnt->request == NULL) - break; - } - } + while (1) { + if (sdev->device_blocked) + goto busy; + if (sdev->single_lun && check_all_luns(shost, sdev)) + goto busy; + /* - * If we couldn't find a free command block, and we have been - * asked to wait, then do so. + * Now we can check for a free command block for this device. */ - if (SCpnt) { - break; - } - busy: + for (scmnd = sdev->device_queue; scmnd; scmnd = scmnd->next) + if (!scmnd->request) + goto found; + +busy: + if (!wait) + goto fail; + /* - * If we have been asked to wait for a free block, then - * wait here. + * We need to wait for a free commandblock. We need to + * insert ourselves into the list before we release the + * lock. This way if a block were released the same + * microsecond that we released the lock, the call + * to schedule() wouldn't block (well, it might switch, + * but the current task will still be schedulable. */ - if (wait) { - DECLARE_WAITQUEUE(wait, current); - - /* - * We need to wait for a free commandblock. We need to - * insert ourselves into the list before we release the - * lock. This way if a block were released the same - * microsecond that we released the lock, the call - * to schedule() wouldn't block (well, it might switch, - * but the current task will still be schedulable. - */ - add_wait_queue(&device->scpnt_wait, &wait); - if( interruptable ) { - set_current_state(TASK_INTERRUPTIBLE); - } else { - set_current_state(TASK_UNINTERRUPTIBLE); - } - - spin_unlock_irqrestore(&device_request_lock, flags); - - /* - * This should block until a device command block - * becomes available. - */ - schedule(); + add_wait_queue(&sdev->scpnt_wait, &wq); + set_current_state(TASK_UNINTERRUPTIBLE); - spin_lock_irqsave(&device_request_lock, flags); - - remove_wait_queue(&device->scpnt_wait, &wait); - /* - * FIXME - Isn't this redundant?? Someone - * else will have forced the state back to running. - */ - set_current_state(TASK_RUNNING); - /* - * In the event that a signal has arrived that we need - * to consider, then simply return NULL. Everyone - * that calls us should be prepared for this - * possibility, and pass the appropriate code back - * to the user. - */ - if( interruptable ) { - if (signal_pending(current)) { - spin_unlock_irqrestore(&device_request_lock, flags); - return NULL; - } - } - } else { - spin_unlock_irqrestore(&device_request_lock, flags); - return NULL; - } - } - - SCpnt->request = NULL; - atomic_inc(&SCpnt->host->host_active); - atomic_inc(&SCpnt->device->device_active); - - SCpnt->buffer = NULL; - SCpnt->bufflen = 0; - SCpnt->request_buffer = NULL; - SCpnt->request_bufflen = 0; - - SCpnt->use_sg = 0; /* Reset the scatter-gather flag */ - SCpnt->old_use_sg = 0; - SCpnt->transfersize = 0; /* No default transfer size */ - SCpnt->cmd_len = 0; - - SCpnt->sc_data_direction = SCSI_DATA_UNKNOWN; - SCpnt->sc_request = NULL; - SCpnt->sc_magic = SCSI_CMND_MAGIC; - - SCpnt->result = 0; - SCpnt->underflow = 0; /* Do not flag underflow conditions */ - SCpnt->old_underflow = 0; - SCpnt->resid = 0; - SCpnt->state = SCSI_STATE_INITIALIZING; - SCpnt->owner = SCSI_OWNER_HIGHLEVEL; + spin_unlock_irqrestore(&device_request_lock, flags); + schedule(); + spin_lock_irqsave(&device_request_lock, flags); + + remove_wait_queue(&sdev->scpnt_wait, &wq); + set_current_state(TASK_RUNNING); + } + +found: + scmnd->request = NULL; + atomic_inc(&scmnd->host->host_active); + atomic_inc(&scmnd->device->device_active); + + scmnd->buffer = NULL; + scmnd->bufflen = 0; + scmnd->request_buffer = NULL; + scmnd->request_bufflen = 0; + + scmnd->use_sg = 0; /* Reset the scatter-gather flag */ + scmnd->old_use_sg = 0; + scmnd->transfersize = 0; /* No default transfer size */ + scmnd->cmd_len = 0; + + scmnd->sc_data_direction = SCSI_DATA_UNKNOWN; + scmnd->sc_request = NULL; + scmnd->sc_magic = SCSI_CMND_MAGIC; + + scmnd->result = 0; + scmnd->underflow = 0; /* Do not flag underflow conditions */ + scmnd->old_underflow = 0; + scmnd->resid = 0; + scmnd->state = SCSI_STATE_INITIALIZING; + scmnd->owner = SCSI_OWNER_HIGHLEVEL; spin_unlock_irqrestore(&device_request_lock, flags); SCSI_LOG_MLQUEUE(5, printk("Activating command for device %d (%d)\n", - SCpnt->target, - atomic_read(&SCpnt->host->host_active))); + scmnd->target, + atomic_read(&scmnd->host->host_active))); + + return scmnd; - return SCpnt; +fail: + spin_unlock_irqrestore(&device_request_lock, flags); + return NULL; } inline void __scsi_release_command(Scsi_Cmnd * SCpnt) @@ -1662,6 +1604,58 @@ } /* + * Function: scsi_track_queue_full() + * + * Purpose: This function will track successive QUEUE_FULL events on a + * specific SCSI device to determine if and when there is a + * need to adjust the queue depth on the device. + * + * Arguments: SDpnt - SCSI Device in question + * depth - Current number of outstanding SCSI commands on + * this device, not counting the one returned as + * QUEUE_FULL. + * + * Returns: 0 - No change needed + * >0 - Adjust queue depth to this new depth + * -1 - Drop back to untagged operation using host->cmd_per_lun + * as the untagged command depth + * + * Lock Status: None held on entry + * + * Notes: Low level drivers may call this at any time and we will do + * "The Right Thing." We are interrupt context safe. + */ +int scsi_track_queue_full(Scsi_Device *SDptr, int depth) +{ + if((jiffies >> 4) != SDptr->last_queue_full_time) { + SDptr->last_queue_full_time = (jiffies >> 4); + if(SDptr->last_queue_full_depth == depth) + SDptr->last_queue_full_count++; + else { + SDptr->last_queue_full_count = 1; + SDptr->last_queue_full_depth = depth; + } + if(SDptr->last_queue_full_count > 10) { + if(SDptr->last_queue_full_depth < 8) { + /* Drop back to untagged */ + scsi_adjust_queue_depth(SDptr, 0 /* untagged */, + SDptr->host->cmd_per_lun); + return -1; + } + if(SDptr->ordered_tags) + scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, + depth); + else + scsi_adjust_queue_depth(SDptr, MSG_SIMPLE_TAG, + depth); + return depth; + } + } + return 0; +} + + +/* * scsi_strcpy_devinfo: called from scsi_dev_info_list_add to copy into * devinfo vendor and model strings. */ @@ -1961,8 +1955,8 @@ " configured\n"); return 1; } - if (sdev->host->hostt->slave_attach != NULL) { - if (sdev->host->hostt->slave_attach(sdev) != 0) { + if (sdev->host->hostt->slave_configure != NULL) { + if (sdev->host->hostt->slave_configure(sdev) != 0) { printk(KERN_INFO "scsi: failed low level driver" " attach, some SCSI device might not be" " configured\n"); @@ -1989,8 +1983,6 @@ void scsi_slave_detach(struct scsi_device *sdev) { if (--sdev->attached == 0) { - if (sdev->host->hostt->slave_detach != NULL) - sdev->host->hostt->slave_detach(sdev); scsi_release_commandblocks(sdev); } } @@ -2033,19 +2025,9 @@ driver_register(&tpnt->scsi_driverfs_driver); for (shpnt = scsi_host_get_next(NULL); shpnt; - shpnt = scsi_host_get_next(shpnt)) { - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - if (tpnt->attach) - /* - * XXX check result when the upper level - * attach return values are fixed, and - * stop attaching on failure. - */ - (*tpnt->attach) (SDpnt); - - } - } + shpnt = scsi_host_get_next(shpnt)) + list_for_each_entry (SDpnt, &shpnt->my_devices, siblings) + (*tpnt->attach) (SDpnt); return 0; } @@ -2063,11 +2045,8 @@ for (shpnt = scsi_host_get_next(NULL); shpnt; shpnt = scsi_host_get_next(shpnt)) { - for (SDpnt = shpnt->host_queue; SDpnt; - SDpnt = SDpnt->next) { - if (tpnt->detach) - (*tpnt->detach) (SDpnt); - } + list_for_each_entry(SDpnt, &shpnt->my_devices, siblings) + (*tpnt->detach) (SDpnt); } /* * Extract the template from the linked list. diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/scsi.h Wed Nov 27 14:36:28 2002 @@ -15,23 +15,10 @@ #ifndef _SCSI_H #define _SCSI_H -#include /* for CONFIG_SCSI_LOGGING */ -#include -#include -#include - - -/* - * Some of the public constants are being moved to this file. - * We include it here so that what came from where is transparent. - */ +#include /* for CONFIG_SCSI_LOGGING */ +#include /* some morons don't know struct pointers */ #include -#include - -#include -#include -#include /* * These are the values that the SCpnt->sc_data_direction and @@ -396,6 +383,7 @@ * Forward-declaration of structs for prototypes. */ struct Scsi_Host; +struct scatterlist; /* * Add some typedefs so that we can prototyope a bunch of the functions. @@ -445,10 +433,6 @@ * Prototypes for functions in scsi_lib.c */ extern int scsi_maybe_unblock_host(Scsi_Device * SDpnt); -extern Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, - int sectors); -extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *); -extern int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt); extern void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt); extern int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int); extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, @@ -466,12 +450,13 @@ extern void scsi_release_commandblocks(Scsi_Device * SDpnt); extern void scsi_build_commandblocks(Scsi_Device * SDpnt); extern void scsi_adjust_queue_depth(Scsi_Device *, int, int); +extern int scsi_track_queue_full(Scsi_Device *, int); extern int scsi_slave_attach(struct scsi_device *sdev); extern void scsi_slave_detach(struct scsi_device *sdev); extern void scsi_done(Scsi_Cmnd * SCpnt); extern void scsi_finish_command(Scsi_Cmnd *); extern int scsi_retry_command(Scsi_Cmnd *); -extern Scsi_Cmnd *scsi_allocate_device(Scsi_Device *, int, int); +extern Scsi_Cmnd *scsi_allocate_device(Scsi_Device *, int); extern void __scsi_release_command(Scsi_Cmnd *); extern void scsi_release_command(Scsi_Cmnd *); extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd, @@ -511,9 +496,11 @@ extern void scsi_proc_host_rm(struct Scsi_Host *); extern struct proc_dir_entry *proc_scsi; +extern void proc_print_scsidevice(Scsi_Device * sdev, char *buffer, int *size, int len); #else -static inline int scsi_init_procfs(void) { return 0; }; -static inline void scsi_exit_procfs(void) { }; +static inline int scsi_init_procfs(void) { return 0; } +static inline void scsi_exit_procfs(void) { ; } +static inline void proc_print_scsidevice(Scsi_Device * sdev, char *buffer, int *size, int len) { ; } static inline void scsi_proc_host_add(struct Scsi_Host *); static inline void scsi_proc_host_rm(struct Scsi_Host *); @@ -525,6 +512,8 @@ extern struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *, uint, uint, uint); extern void scsi_free_sdev(struct scsi_device *); +extern int scsi_add_single_device(uint, uint, uint, uint); +extern int scsi_remove_single_device(uint, uint, uint, uint); /* * Prototypes for functions in constants.c @@ -551,7 +540,7 @@ unsigned flags; }; -extern struct dev_info scsi_static_device_list[] __initdata; +extern struct dev_info scsi_static_device_list[]; /* * scsi_dev_info_list: structure to hold black/white listed devices. @@ -599,6 +588,11 @@ Scsi_Cmnd *current_cmnd; /* currently active command */ unsigned short current_queue_depth;/* How deep of a queue we have */ unsigned short new_queue_depth; /* How deep of a queue we want */ + unsigned short last_queue_full_depth; /* These two are used by */ + unsigned short last_queue_full_count; /* scsi_track_queue_full() */ + unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same + jiffie count on our counter, they + could all be from the same event. */ unsigned int id, lun, channel; diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c --- a/drivers/scsi/scsi_debug.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/scsi_debug.c Wed Nov 27 14:36:31 2002 @@ -812,13 +812,13 @@ spin_unlock_irqrestore(&queued_arr_lock, iflags); } -static int scsi_debug_slave_attach(struct scsi_device * sdp) +static int scsi_debug_slave_configure(struct scsi_device * sdp) { int k; struct sdebug_dev_info * devip; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: slave_attach <%u %u %u %u>\n", + printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; @@ -838,13 +838,13 @@ return 0; } -static void scsi_debug_slave_detach(struct scsi_device * sdp) +static void scsi_debug_slave_destroy(struct scsi_device * sdp) { struct sdebug_dev_info * devip = (struct sdebug_dev_info *)sdp->hostdata; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: slave_detach <%u %u %u %u>\n", + printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (devip) { /* make this slot avaliable for re-use */ diff -Nru a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h --- a/drivers/scsi/scsi_debug.h Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/scsi_debug.h Wed Nov 27 14:36:30 2002 @@ -2,8 +2,8 @@ #include -static int scsi_debug_slave_attach(struct scsi_device *); -static void scsi_debug_slave_detach(struct scsi_device *); +static int scsi_debug_slave_configure(struct scsi_device *); +static void scsi_debug_slave_destroy(struct scsi_device *); static int scsi_debug_queuecommand(struct scsi_cmnd *, void (*done) (struct scsi_cmnd *)); static int scsi_debug_ioctl(struct scsi_device *, int, void *); @@ -27,8 +27,8 @@ .proc_info = scsi_debug_proc_info, .name = "SCSI DEBUG", .info = scsi_debug_info, - .slave_attach = scsi_debug_slave_attach, - .slave_detach = scsi_debug_slave_detach, + .slave_configure = scsi_debug_slave_configure, + .slave_destroy = scsi_debug_slave_destroy, .ioctl = scsi_debug_ioctl, .queuecommand = scsi_debug_queuecommand, .eh_abort_handler = scsi_debug_abort, diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/scsi_error.c Wed Nov 27 14:36:27 2002 @@ -201,7 +201,7 @@ int devices_failed = 0; - for (sdev = shost->host_queue; sdev; sdev = sdev->next) { + list_for_each_entry(sdev, &shost->my_devices, siblings) { for (scmd = sc_list; scmd; scmd = scmd->bh_next) { if (scmd->device == sdev) { ++total_failures; @@ -246,7 +246,8 @@ Scsi_Device *sdev; Scsi_Cmnd *scmd; - for (found = 0, sdev = shost->host_queue; sdev; sdev = sdev->next) { + found = 0; + list_for_each_entry(sdev, &shost->my_devices, siblings) { for (scmd = sdev->device_queue; scmd; scmd = scmd->next) { if (scsi_eh_eflags_chk(scmd, SCSI_EH_CMD_ERR)) { scmd->bh_next = *sc_list; @@ -961,7 +962,7 @@ SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Trying BDR\n", __FUNCTION__)); - for (sdev = shost->host_queue; sdev; sdev = sdev->next) { + list_for_each_entry(sdev, &shost->my_devices, siblings) { for (scmd = sc_todo; scmd; scmd = scmd->bh_next) if ((scmd->device == sdev) && scsi_eh_eflags_chk(scmd, SCSI_EH_CMD_ERR)) @@ -1015,7 +1016,7 @@ /* * Mark all affected devices to expect a unit attention. */ - for (sdev = scmd->host->host_queue; sdev; sdev = sdev->next) + list_for_each_entry(sdev, &scmd->host->my_devices, siblings) if (scmd->channel == sdev->channel) { sdev->was_reset = 1; sdev->expecting_cc_ua = 1; @@ -1051,7 +1052,7 @@ /* * Mark all affected devices to expect a unit attention. */ - for (sdev = scmd->host->host_queue; sdev; sdev = sdev->next) + list_for_each_entry(sdev, &scmd->host->my_devices, siblings) if (scmd->channel == sdev->channel) { sdev->was_reset = 1; sdev->expecting_cc_ua = 1; @@ -1457,7 +1458,7 @@ * onto the head of the SCSI request queue for the device. There * is no point trying to lock the door of an off-line device. */ - for (sdev = shost->host_queue; sdev; sdev = sdev->next) + list_for_each_entry(sdev, &shost->my_devices, siblings) if (sdev->online && sdev->locked) scsi_eh_lock_door(sdev); @@ -1478,7 +1479,7 @@ * requests are started. */ spin_lock_irqsave(shost->host_lock, flags); - for (sdev = shost->host_queue; sdev; sdev = sdev->next) { + list_for_each_entry(sdev, &shost->my_devices, siblings) { if ((shost->can_queue > 0 && (shost->host_busy >= shost->can_queue)) || (shost->host_blocked) diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/scsi_lib.c Wed Nov 27 14:36:30 2002 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -95,7 +96,7 @@ * fields related to error handling. Typically this will * be called once for each command, as required. */ -int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt) +static int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt) { SCpnt->owner = SCSI_OWNER_MIDLEVEL; SCpnt->reset_chain = NULL; @@ -241,7 +242,7 @@ * use function pointers to pick the right one. */ if (SDpnt->single_lun && blk_queue_empty(q) && SDpnt->device_busy ==0) { - for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { + list_for_each_entry(SDpnt, &SHpnt->my_devices, siblings) { if (((SHpnt->can_queue > 0) && (SHpnt->host_busy >= SHpnt->can_queue)) || (SHpnt->host_blocked) @@ -264,7 +265,7 @@ */ all_clear = 1; if (SHpnt->some_device_starved) { - for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { + list_for_each_entry(SDpnt, &SHpnt->my_devices, siblings) { if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue)) || (SHpnt->host_blocked) || (SHpnt->host_self_blocked)) { @@ -306,11 +307,10 @@ * We are guaranteeing that the request queue will be goosed * at some point during this call. */ -static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt, +static Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors, - int requeue, - int frequeue) + int requeue) { request_queue_t *q = &SCpnt->device->request_queue; struct request *req = SCpnt->request; @@ -337,12 +337,9 @@ add_disk_randomness(req->rq_disk); spin_lock_irqsave(q->queue_lock, flags); - if (blk_rq_tagged(req)) blk_queue_end_tag(q, req); - end_that_request_last(req); - spin_unlock_irqrestore(q->queue_lock, flags); /* @@ -350,39 +347,11 @@ * need to worry about launching another command. */ __scsi_release_command(SCpnt); - - if (frequeue) - scsi_queue_next_request(q, NULL); - + scsi_queue_next_request(q, NULL); return NULL; } /* - * Function: scsi_end_request() - * - * Purpose: Post-processing of completed commands called from interrupt - * handler or a bottom-half handler. - * - * Arguments: SCpnt - command that is complete. - * uptodate - 1 if I/O indicates success, 0 for I/O error. - * sectors - number of sectors we want to mark. - * - * Lock status: Assumed that lock is not held upon entry. - * - * Returns: Nothing - * - * Notes: This is called for block device requests in order to - * mark some number of sectors as complete. - * - * We are guaranteeing that the request queue will be goosed - * at some point during this call. - */ -Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors) -{ - return __scsi_end_request(SCpnt, uptodate, sectors, 1, 1); -} - -/* * Function: scsi_release_buffers() * * Purpose: Completion processing for block device I/O requests. @@ -429,6 +398,29 @@ } /* + * Function: scsi_get_request_dev() + * + * Purpose: Find the upper-level driver that is responsible for this + * request + * + * Arguments: request - I/O request we are preparing to queue. + * + * Lock status: No locks assumed to be held, but as it happens the + * q->queue_lock is held when this is called. + * + * Returns: Nothing + * + * Notes: The requests in the request queue may have originated + * from any block device driver. We need to find out which + * one so that we can later form the appropriate command. + */ +static struct Scsi_Device_Template *scsi_get_request_dev(struct request *req) +{ + struct gendisk *p = req->rq_disk; + return p ? *(struct Scsi_Device_Template **)p->private_data : NULL; +} + +/* * Function: scsi_io_completion() * * Purpose: Completion processing for block device I/O requests. @@ -527,11 +519,7 @@ * requeueing right here - we will requeue down below * when we handle the bad sectors. */ - SCpnt = __scsi_end_request(SCpnt, - 1, - good_sectors, - result == 0, - 1); + SCpnt = scsi_end_request(SCpnt, 1, good_sectors, result == 0); /* * If the command completed without error, then either finish off the @@ -574,7 +562,8 @@ * and quietly refuse further access. */ SCpnt->device->changed = 1; - SCpnt = scsi_end_request(SCpnt, 0, this_count); + SCpnt = scsi_end_request(SCpnt, 0, + this_count, 1); return; } else { /* @@ -606,14 +595,14 @@ scsi_queue_next_request(q, SCpnt); result = 0; } else { - SCpnt = scsi_end_request(SCpnt, 0, this_count); + SCpnt = scsi_end_request(SCpnt, 0, this_count, 1); return; } break; case NOT_READY: printk(KERN_INFO "Device %s not ready.\n", req->rq_disk ? req->rq_disk->disk_name : ""); - SCpnt = scsi_end_request(SCpnt, 0, this_count); + SCpnt = scsi_end_request(SCpnt, 0, this_count, 1); return; break; case MEDIUM_ERROR: @@ -623,7 +612,7 @@ (int) SCpnt->target, (int) SCpnt->lun); print_command(SCpnt->data_cmnd); print_sense("sd", SCpnt); - SCpnt = scsi_end_request(SCpnt, 0, block_sectors); + SCpnt = scsi_end_request(SCpnt, 0, block_sectors, 1); return; default: break; @@ -656,35 +645,12 @@ * We sometimes get this cruft in the event that a medium error * isn't properly reported. */ - SCpnt = scsi_end_request(SCpnt, 0, req->current_nr_sectors); + SCpnt = scsi_end_request(SCpnt, 0, req->current_nr_sectors, 1); return; } } /* - * Function: scsi_get_request_dev() - * - * Purpose: Find the upper-level driver that is responsible for this - * request - * - * Arguments: request - I/O request we are preparing to queue. - * - * Lock status: No locks assumed to be held, but as it happens the - * q->queue_lock is held when this is called. - * - * Returns: Nothing - * - * Notes: The requests in the request queue may have originated - * from any block device driver. We need to find out which - * one so that we can later form the appropriate command. - */ -struct Scsi_Device_Template *scsi_get_request_dev(struct request *req) -{ - struct gendisk *p = req->rq_disk; - return p ? *(struct Scsi_Device_Template **)p->private_data : NULL; -} - -/* * Function: scsi_init_io() * * Purpose: SCSI I/O initialize function. @@ -763,7 +729,7 @@ /* * kill it. there should be no leftover blocks in this request */ - SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors); + SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors, 1); BUG_ON(SCpnt); ret = BLKPREP_KILL; out: @@ -797,8 +763,7 @@ SRpnt = (Scsi_Request *) req->special; if( SRpnt->sr_magic == SCSI_REQ_MAGIC ) { - SCpnt = scsi_allocate_device(SRpnt->sr_device, - FALSE, FALSE); + SCpnt = scsi_allocate_device(SRpnt->sr_device, 0); if (!SCpnt) return BLKPREP_DEFER; scsi_init_cmd_from_req(SCpnt, SRpnt); @@ -809,9 +774,9 @@ * Now try and find a command block that we can use. */ if (req->special) { - SCpnt = (Scsi_Cmnd *) req->special; + SCpnt = (Scsi_Cmnd *) req->special; } else { - SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE); + SCpnt = scsi_allocate_device(SDpnt, 0); } /* * if command allocation failure, wait a bit @@ -1085,7 +1050,7 @@ SHpnt->host_self_blocked = FALSE; /* Now that we are unblocked, try to start the queues. */ - for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next) + list_for_each_entry(SDloop, &SHpnt->my_devices, siblings) scsi_queue_next_request(&SDloop->request_queue, NULL); } @@ -1113,7 +1078,7 @@ void scsi_report_bus_reset(struct Scsi_Host * SHpnt, int channel) { Scsi_Device *SDloop; - for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next) { + list_for_each_entry(SDloop, &SHpnt->my_devices, siblings) { if (channel == SDloop->channel) { SDloop->was_reset = 1; SDloop->expecting_cc_ua = 1; diff -Nru a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c --- a/drivers/scsi/scsi_proc.c Wed Nov 27 14:36:27 2002 +++ b/drivers/scsi/scsi_proc.c Wed Nov 27 14:36:27 2002 @@ -16,14 +16,13 @@ * Michael A. Griffith */ -#include #include +#include #include #include #include #include #include -#include #include #include @@ -282,7 +281,7 @@ */ for (shost = scsi_host_get_next(NULL); shost; shost = scsi_host_get_next(shost)) { - if (shost->host_queue != NULL) { + if (!list_empty(&shost->my_devices)) { break; } } @@ -292,7 +291,7 @@ pos = begin + len; for (shost = scsi_host_get_next(NULL); shost; shost = scsi_host_get_next(shost)) { - for (sdev = shost->host_queue; sdev; sdev = sdev->next) { + list_for_each_entry(sdev, &shost->my_devices, siblings) { proc_print_scsidevice(sdev, buffer, &size, len); len += size; pos = begin + len; @@ -360,7 +359,7 @@ shpnt = scsi_host_get_next(shpnt)) { printk(KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) " "(ret all flg) (to/cmd to ito) cmd snse result\n"); - for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { + list_for_each_entry(SDpnt, &shpnt->my_devices, siblings) { for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) { /* (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result %d %x */ printk(KERN_INFO "(%3d) %2d:%1d:%2d:%2d (%6s %4llu %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n", @@ -399,11 +398,8 @@ static int proc_scsi_gen_write(struct file * file, const char * buf, unsigned long length, void *data) { - Scsi_Device *sdev; - struct Scsi_Host *shost; - char *p; int host, channel, id, lun; - char * buffer; + char *buffer, *p; int err; if (!buf || length>PAGE_SIZE) @@ -529,35 +525,9 @@ id = simple_strtoul(p + 1, &p, 0); lun = simple_strtoul(p + 1, &p, 0); - printk(KERN_INFO "scsi singledevice %d %d %d %d\n", host, channel, - id, lun); - - for (shost = scsi_host_get_next(NULL); shost; - shost = scsi_host_get_next(shost)) { - if (shost->host_no == host) { - break; - } - } - err = -ENXIO; - if (!shost) - goto out; - - for (sdev = shost->host_queue; sdev; sdev = sdev->next) { - if ((sdev->channel == channel - && sdev->id == id - && sdev->lun == lun)) { - break; - } - } - - err = -ENOSYS; - if (sdev) - goto out; /* We do not yet support unplugging */ - - scan_scsis(shost, 1, channel, id, lun); - err = length; - goto out; - } + err = scsi_add_single_device(host, channel, id, lun); + if (err >= 0) + err = length; /* * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi * with "0 1 2 3" replaced by your "Host Channel Id Lun". @@ -569,7 +539,7 @@ * hardware and thoroughly confuse the SCSI subsystem. * */ - else if (!strncmp("remove-single-device", buffer + 5, 20)) { + } else if (!strncmp("remove-single-device", buffer + 5, 20)) { p = buffer + 26; host = simple_strtoul(p, &p, 0); @@ -577,39 +547,7 @@ id = simple_strtoul(p + 1, &p, 0); lun = simple_strtoul(p + 1, &p, 0); - - for (shost = scsi_host_get_next(NULL); shost; - shost = scsi_host_get_next(shost)) { - if (shost->host_no == host) { - break; - } - } - err = -ENODEV; - if (!shost) - goto out; - - for (sdev = shost->host_queue; sdev; sdev = sdev->next) { - if ((sdev->channel == channel - && sdev->id == id - && sdev->lun == lun)) { - break; - } - } - - if (sdev == NULL) - goto out; /* there is no such device attached */ - - err = -EBUSY; - if (sdev->access_count) - goto out; - - scsi_detach_device(sdev); - - if (sdev->attached == 0) { - devfs_unregister (sdev->de); - scsi_free_sdev(sdev); - err = 0; - } + err = scsi_remove_single_device(host, channel, id, lun); } out: diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/scsi_scan.c Wed Nov 27 14:36:31 2002 @@ -168,6 +168,7 @@ {"DELL", "PV530F", NULL, BLIST_SPARSELUN}, {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP VA7400 */ + {"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */ {"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */ {"CNSI", "G7324", NULL, BLIST_SPARSELUN}, /* Chaparral G7324 RAID */ {"CNSi", "G8324", NULL, BLIST_SPARSELUN}, /* Chaparral G8324 RAID */ @@ -181,6 +182,12 @@ {"COMPAQ", "MSA1000", NULL, BLIST_FORCELUN}, {"HP", "C1557A", NULL, BLIST_FORCELUN}, {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN}, + {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN}, + {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, + {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, + {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, + {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, { NULL, NULL, NULL, 0 }, }; @@ -468,7 +475,7 @@ struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel, uint id, uint lun) { - struct scsi_device *sdev; + struct scsi_device *sdev, *device; sdev = kmalloc(sizeof(*sdev), GFP_ATOMIC); if (sdev == NULL) @@ -483,6 +490,8 @@ sdev->lun = lun; sdev->channel = channel; sdev->online = TRUE; + INIT_LIST_HEAD(&sdev->siblings); + INIT_LIST_HEAD(&sdev->same_target_siblings); /* * Some low level driver could use device->type */ @@ -493,6 +502,12 @@ * doesn't */ sdev->borken = 1; + if (shost->hostt->slave_alloc) + if (shost->hostt->slave_alloc(sdev)) { + kfree(sdev); + return NULL; + } + scsi_initialize_queue(sdev, shost); sdev->request_queue.queuedata = (void *) sdev; @@ -500,16 +515,21 @@ init_waitqueue_head(&sdev->scpnt_wait); /* - * Add it to the end of the shost->host_queue list. + * If there are any same target siblings, add this to the + * sibling list */ - if (shost->host_queue != NULL) { - sdev->prev = shost->host_queue; - while (sdev->prev->next != NULL) - sdev->prev = sdev->prev->next; - sdev->prev->next = sdev; - } else - shost->host_queue = sdev; - + list_for_each_entry(device, &shost->my_devices, siblings) { + if(device->id == sdev->id && + device->channel == sdev->channel) { + list_add_tail(&sdev->same_target_siblings, + &device->same_target_siblings); + break; + } + } + /* + * Add it to the end of the shost->my_devices list. + */ + list_add_tail(&sdev->siblings, &shost->my_devices); } return (sdev); } @@ -524,14 +544,13 @@ **/ void scsi_free_sdev(struct scsi_device *sdev) { - if (sdev->prev != NULL) - sdev->prev->next = sdev->next; - else - sdev->host->host_queue = sdev->next; - if (sdev->next != NULL) - sdev->next->prev = sdev->prev; + list_del(&sdev->siblings); + list_del(&sdev->same_target_siblings); blk_cleanup_queue(&sdev->request_queue); + scsi_release_commandblocks(sdev); + if (sdev->host->hostt->slave_destroy) + sdev->host->hostt->slave_destroy(sdev); if (sdev->inquiry != NULL) kfree(sdev->inquiry); kfree(sdev); @@ -1082,32 +1101,6 @@ } /** - * scsi_find_scsi_level - return the scsi_level of a matching target - * - * Description: - * Return the scsi_level of any Scsi_Device matching @channel, @id, - * and @shost. - * Notes: - * Needs to issue an INQUIRY to LUN 0 if no Scsi_Device matches, and - * if the INQUIRY can't be sent return a failure. - **/ -static int scsi_find_scsi_level(unsigned int channel, unsigned int id, - struct Scsi_Host *shost) -{ - int res = SCSI_2; - Scsi_Device *sdev; - - for (sdev = shost->host_queue; sdev; sdev = sdev->next) - if ((id == sdev->id) && (channel == sdev->channel)) - return (int) sdev->scsi_level; - /* - * FIXME No matching target id is configured, this needs to get - * the INQUIRY for LUN 0, and use it to determine the scsi_level. - */ - return res; -} - -/** * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY * @sreq: used to send the INQUIRY * @inq_result: area to store the INQUIRY result @@ -1469,6 +1462,17 @@ if (sdevscan->current_queue_depth == 0) goto alloc_failed; + /* + * Since we reuse the same sdevscan over and over with different + * target and lun values, we have to destroy and then recreate + * any possible low level attachments since they very will might + * also store the id and lun numbers in some form and need updating + * with each scan. + */ + if (sdevscan->host->hostt->slave_destroy) + sdevscan->host->hostt->slave_destroy(sdevscan); + if (sdevscan->host->hostt->slave_alloc) + sdevscan->host->hostt->slave_alloc(sdevscan); sreq = scsi_allocate_request(sdevscan); if (sreq == NULL) goto alloc_failed; @@ -1703,6 +1707,22 @@ */ return 0; } + /* + * Since we reuse the same sdevscan over and over with different + * target and lun values, we have to destroy and then recreate + * any possible low level attachments since they very will might + * also store the id and lun numbers in some form and need updating + * with each scan. + * + * This is normally handled in probe_and_add_lun, but since this + * one particular function wants to scan lun 0 on each device + * itself and will possibly pick up a resed sdevscan when doing + * so, it also needs this hack. + */ + if (sdevscan->host->hostt->slave_destroy) + sdevscan->host->hostt->slave_destroy(sdevscan); + if (sdevscan->host->hostt->slave_alloc) + sdevscan->host->hostt->slave_alloc(sdevscan); sreq = scsi_allocate_request(sdevscan); sprintf(devname, "host %d channel %d id %d", sdevscan->host->host_no, @@ -1862,6 +1882,74 @@ } +int scsi_add_single_device(uint host, uint channel, uint id, uint lun) +{ + struct scsi_device *sdevscan, *sdev; + struct Scsi_Host *shost; + int error = -ENODEV; + + shost = scsi_host_hn_get(host); + if (!shost) + return -ENODEV; + sdev = scsi_find_device(shost, channel, id, lun); + if (sdev) + goto out; + + error = -ENOMEM; + sdevscan = scsi_alloc_sdev(shost, channel, id, lun); + if (!sdevscan) + goto out; + + if(!list_empty(&sdevscan->same_target_siblings)) { + sdev = list_entry(&sdevscan->same_target_siblings, Scsi_Device, + same_target_siblings); + sdevscan->scsi_level = sdev->scsi_level; + sdev = NULL; + } else + sdevscan->scsi_level = SCSI_2; + error = scsi_probe_and_add_lun(sdevscan, &sdev, NULL); + scsi_free_sdev(sdevscan); + + if (error != SCSI_SCAN_LUN_PRESENT) + goto out; + + scsi_attach_device(sdev); + error = 0; + +out: + scsi_host_put(shost); + return error; +} + +int scsi_remove_single_device(uint host, uint channel, uint id, uint lun) +{ + struct scsi_device *sdev; + struct Scsi_Host *shost; + int error = -ENODEV; + + shost = scsi_host_hn_get(host); + if (!shost) + return -ENODEV; + sdev = scsi_find_device(shost, channel, id, lun); + if (!sdev) + goto out; + + error = -EBUSY; + if (sdev->access_count) + goto out; + scsi_detach_device(sdev); + if (sdev->attached) + goto out; + + devfs_unregister(sdev->de); + scsi_free_sdev(sdev); + error = 0; + +out: + scsi_host_put(shost); + return error; +} + /** * scsi_scan_target - scan a target id, possibly including all LUNs on the * target. @@ -1927,111 +2015,56 @@ } /** - * scsi_scan_selected_lun - probe and add one LUN + * scsi_scan_host - scan the given adapter + * @shost: adapter to scan * * Description: - * Probe a single LUN on @shost, @channel, @id and @lun. If the LUN is - * found, set the queue depth, allocate command blocks, and call - * init/attach/finish of the upper level (sd, sg, etc.) drivers. + * Iterate and call scsi_scan_target to scan all possible target id's + * on all possible channels. **/ -static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel, - uint id, uint lun) +void scsi_scan_host(struct Scsi_Host *shost) { - Scsi_Device *sdevscan, *sdev = NULL; - int res; + struct scsi_device *sdevscan; + uint channel, id, order_id; - if ((channel > shost->max_channel) || (id >= shost->max_id) || - (lun >= shost->max_lun)) - return; - - sdevscan = scsi_alloc_sdev(shost, channel, id, lun); + /* + * The blk layer queue allocation is a bit expensive to + * repeat for each channel and id - for FCP max_id is near + * 255: each call to scsi_alloc_sdev() implies a call to + * blk_init_queue, and then blk_init_free_list, where 2 * + * queue_nr_requests requests are allocated. Don't do so + * here for scsi_scan_selected_lun, since we end up + * calling select_queue_depths with an extra Scsi_Device + * on the host_queue list. + */ + sdevscan = scsi_alloc_sdev(shost, 0, 0, 0); if (sdevscan == NULL) return; - - sdevscan->scsi_level = scsi_find_scsi_level(channel, id, shost); - res = scsi_probe_and_add_lun(sdevscan, &sdev, NULL); - scsi_free_sdev(sdevscan); - - if (res != SCSI_SCAN_LUN_PRESENT) - return; - - scsi_attach_device(sdev); -} - -/** - * scan_scsis - scan the given adapter, or scan a single LUN - * @shost: adapter to scan - * @hardcoded: 1 if a single channel/id/lun should be scanned, else 0 - * @hchannel: channel to scan for hardcoded case - * @hid: target id to scan for hardcoded case - * @hlun: lun to scan for hardcoded case - * - * Description: - * If @hardcoded is 1, call scsi_scan_selected_lun to scan a single - * LUN; else, iterate and call scsi_scan_target to scan all possible - * target id's on all possible channels. - **/ -void scan_scsis(struct Scsi_Host *shost, uint hardcoded, uint hchannel, - uint hid, uint hlun) -{ - if (hardcoded == 1) { + /* + * The sdevscan host, channel, id and lun are filled in as + * needed to scan. + */ + for (channel = 0; channel <= shost->max_channel; channel++) { /* - * XXX Overload hchannel/hid/hlun to figure out what to - * scan, and use the standard scanning code rather than - * this function - that way, an entire bus (or fabric), or - * target id can be scanned. There are problems with queue - * depth and the init/attach/finish that must be resolved - * before (re-)scanning can handle finding more than one new - * LUN. + * XXX adapter drivers when possible (FCP, iSCSI) + * could modify max_id to match the current max, + * not the absolute max. * - * For example, set hchannel 0 and hid to 5, and hlun to -1 - * in order to scan all LUNs on channel 0, target id 5. - */ - scsi_scan_selected_lun(shost, hchannel, hid, hlun); - } else { - Scsi_Device *sdevscan; - uint channel; - unsigned int id, order_id; - - /* - * The blk layer queue allocation is a bit expensive to - * repeat for each channel and id - for FCP max_id is near - * 255: each call to scsi_alloc_sdev() implies a call to - * blk_init_queue, and then blk_init_free_list, where 2 * - * queue_nr_requests requests are allocated. Don't do so - * here for scsi_scan_selected_lun, since we end up - * calling select_queue_depths with an extra Scsi_Device - * on the host_queue list. - */ - sdevscan = scsi_alloc_sdev(shost, 0, 0, 0); - if (sdevscan == NULL) - return; - /* - * The sdevscan host, channel, id and lun are filled in as - * needed to scan. + * XXX add a shost id iterator, so for example, + * the FC ID can be the same as a target id + * without a huge overhead of sparse id's. */ - for (channel = 0; channel <= shost->max_channel; channel++) { - /* - * XXX adapter drivers when possible (FCP, iSCSI) - * could modify max_id to match the current max, - * not the absolute max. - * - * XXX add a shost id iterator, so for example, - * the FC ID can be the same as a target id - * without a huge overhead of sparse id's. - */ - for (id = 0; id < shost->max_id; ++id) { - if (shost->reverse_ordering) - /* - * Scan from high to low id. - */ - order_id = shost->max_id - id - 1; - else - order_id = id; - scsi_scan_target(sdevscan, shost, channel, - order_id); - } + for (id = 0; id < shost->max_id; ++id) { + if (shost->reverse_ordering) + /* + * Scan from high to low id. + */ + order_id = shost->max_id - id - 1; + else + order_id = id; + scsi_scan_target(sdevscan, shost, channel, + order_id); } - scsi_free_sdev(sdevscan); } + scsi_free_sdev(sdevscan); } diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c --- a/drivers/scsi/scsi_syms.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/scsi_syms.c Wed Nov 27 14:36:30 2002 @@ -68,6 +68,7 @@ EXPORT_SYMBOL(scsi_block_requests); EXPORT_SYMBOL(scsi_unblock_requests); EXPORT_SYMBOL(scsi_adjust_queue_depth); +EXPORT_SYMBOL(scsi_track_queue_full); EXPORT_SYMBOL(scsi_get_host_dev); EXPORT_SYMBOL(scsi_free_host_dev); @@ -75,7 +76,6 @@ EXPORT_SYMBOL(scsi_sleep); EXPORT_SYMBOL(scsi_io_completion); -EXPORT_SYMBOL(scsi_end_request); EXPORT_SYMBOL(scsi_register_blocked_host); EXPORT_SYMBOL(scsi_deregister_blocked_host); diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/sg.c Wed Nov 27 14:36:30 2002 @@ -474,9 +474,7 @@ sb_len = (hp->mx_sb_len > sb_len) ? sb_len : hp->mx_sb_len; len = 8 + (int) srp->sense_b[7]; /* Additional sense length field */ len = (len > sb_len) ? sb_len : len; - if ((err = verify_area(VERIFY_WRITE, hp->sbp, len))) - goto err_out; - if (__copy_to_user(hp->sbp, srp->sense_b, len)) { + if (copy_to_user(hp->sbp, srp->sense_b, len)) { err = -EFAULT; goto err_out; } diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/st.c Wed Nov 27 14:36:31 2002 @@ -3673,19 +3673,18 @@ buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma, i); if (buffer == NULL) { printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n"); - return 1; + goto out_slave_detach; } disk = alloc_disk(1); if (!disk) { printk(KERN_ERR "st: out of memory. Device not attached.\n"); - return 1; + goto out_buffer_free; } write_lock(&st_dev_arr_lock); if (st_nr_dev >= st_dev_max) { Scsi_Tape **tmp_da; - ST_buffer **tmp_ba; int tmp_dev_max; tmp_dev_max = st_nr_dev + ST_DEV_ARR_LUMP; @@ -3695,23 +3694,14 @@ write_unlock(&st_dev_arr_lock); printk(KERN_ERR "st: Too many tape devices (max. %d).\n", ST_MAX_TAPES); - put_disk(disk); - scsi_slave_detach(SDp); - return 1; + goto out_put_disk; } tmp_da = kmalloc(tmp_dev_max * sizeof(Scsi_Tape *), GFP_ATOMIC); - tmp_ba = kmalloc(tmp_dev_max * sizeof(ST_buffer *), GFP_ATOMIC); - if (tmp_da == NULL || tmp_ba == NULL) { - if (tmp_da != NULL) - kfree(tmp_da); - if (tmp_ba != NULL) - kfree(tmp_ba); + if (tmp_da == NULL) { write_unlock(&st_dev_arr_lock); printk(KERN_ERR "st: Can't extend device array.\n"); - put_disk(disk); - scsi_slave_detach(SDp); - return 1; + goto out_put_disk; } memset(tmp_da, 0, tmp_dev_max * sizeof(Scsi_Tape *)); @@ -3735,9 +3725,7 @@ if (tpnt == NULL) { write_unlock(&st_dev_arr_lock); printk(KERN_ERR "st: Can't allocate device descriptor.\n"); - put_disk(disk); - scsi_slave_detach(SDp); - return 1; + goto out_put_disk; } memset(tpnt, 0, sizeof(Scsi_Tape)); tpnt->disk = disk; @@ -3840,14 +3828,14 @@ tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev; tpnt->driverfs_dev_r[mode].bus = &scsi_driverfs_bus_type; tpnt->driverfs_dev_r[mode].driver_data = - (void *)(long)__mkdev(MAJOR_NR, dev_num + (mode << 5)); + (void *)(long)__mkdev(SCSI_TAPE_MAJOR, dev_num + (mode << 5)); device_register(&tpnt->driverfs_dev_r[mode]); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_type); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); tpnt->de_r[mode] = devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, - MAJOR_NR, dev_num + (mode << 5), + SCSI_TAPE_MAJOR, dev_num + (mode << 5), S_IFCHR | S_IRUGO | S_IWUGO, &st_fops, NULL); /* No-rewind entry */ @@ -3859,7 +3847,7 @@ tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev; tpnt->driverfs_dev_n[mode].bus = &scsi_driverfs_bus_type; tpnt->driverfs_dev_n[mode].driver_data = - (void *)(long)__mkdev(MAJOR_NR, dev_num + (mode << 5) + 128); + (void *)(long)__mkdev(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128); device_register(&tpnt->driverfs_dev_n[mode]); device_create_file(&tpnt->driverfs_dev_n[mode], &dev_attr_type); @@ -3867,7 +3855,7 @@ &dev_attr_kdev); tpnt->de_n[mode] = devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, - MAJOR_NR, dev_num + (mode << 5) + 128, + SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128, S_IFCHR | S_IRUGO | S_IWUGO, &st_fops, NULL); } @@ -3880,6 +3868,14 @@ tape_name(tpnt), tpnt->try_dio ? "yes" : "no", tpnt->max_pfn); return 0; + +out_put_disk: + put_disk(disk); +out_buffer_free: + kfree(buffer); +out_slave_detach: + scsi_slave_detach(SDp); + return 1; }; static void st_detach(Scsi_Device * SDp) @@ -3891,20 +3887,15 @@ for (i = 0; i < st_dev_max; i++) { tpnt = scsi_tapes[i]; if (tpnt != NULL && tpnt->device == SDp) { - tpnt->device = NULL; + scsi_tapes[i] = 0; + st_nr_dev--; + write_unlock(&st_dev_arr_lock); + devfs_unregister_tape(tpnt->disk->number); for (mode = 0; mode < ST_NBR_MODES; ++mode) { devfs_unregister (tpnt->de_r[mode]); tpnt->de_r[mode] = NULL; devfs_unregister (tpnt->de_n[mode]); tpnt->de_n[mode] = NULL; - } - devfs_unregister_tape(tpnt->disk->number); - scsi_tapes[i] = 0; - scsi_slave_detach(SDp); - st_nr_dev--; - write_unlock(&st_dev_arr_lock); - - for (mode = 0; mode < ST_NBR_MODES; ++mode) { device_remove_file(&tpnt->driverfs_dev_r[mode], &dev_attr_type); device_remove_file(&tpnt->driverfs_dev_r[mode], @@ -3916,11 +3907,14 @@ &dev_attr_kdev); device_unregister(&tpnt->driverfs_dev_n[mode]); } + tpnt->device = NULL; + if (tpnt->buffer) { tpnt->buffer->orig_frp_segs = 0; normalize_buffer(tpnt->buffer); kfree(tpnt->buffer); } + scsi_slave_detach(SDp); put_disk(tpnt->disk); kfree(tpnt); return; @@ -3944,9 +3938,10 @@ if (register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) { if (scsi_register_device(&st_template) == 0) return 0; + unregister_chrdev(SCSI_TAPE_MAJOR, "st"); } - printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", MAJOR_NR); + printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR); return 1; } @@ -3959,8 +3954,9 @@ if (scsi_tapes != NULL) { for (i=0; i < st_dev_max; ++i) if (scsi_tapes[i]) { - put_disk(scsi_tapes[i]->disk); - kfree(scsi_tapes[i]); + printk(KERN_WARNING "st: scsi_tapes[] not " + "empty after scsi_unregister_device\n"); + st_detach(scsi_tapes[i]->device); } kfree(scsi_tapes); } diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c --- a/drivers/scsi/sym53c8xx.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/sym53c8xx.c Wed Nov 27 14:36:31 2002 @@ -13525,7 +13525,7 @@ return DEF_DEPTH; } -int sym53c8xx_slave_attach(Scsi_Device *device) +int sym53c8xx_slave_configure(Scsi_Device *device) { struct Scsi_Host *host = device->host; ncb_p np; diff -Nru a/drivers/scsi/sym53c8xx.h b/drivers/scsi/sym53c8xx.h --- a/drivers/scsi/sym53c8xx.h Wed Nov 27 14:36:29 2002 +++ b/drivers/scsi/sym53c8xx.h Wed Nov 27 14:36:29 2002 @@ -74,7 +74,7 @@ const char *sym53c8xx_info(struct Scsi_Host *host); int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int sym53c8xx_reset(Scsi_Cmnd *, unsigned int); -int sym53c8xx_slave_attach(Scsi_Device *); +int sym53c8xx_slave_configure(Scsi_Device *); #ifdef MODULE int sym53c8xx_release(struct Scsi_Host *); @@ -90,7 +90,7 @@ release: sym53c8xx_release, \ info: sym53c8xx_info, \ queuecommand: sym53c8xx_queue_command,\ - slave_attach: sym53c8xx_slave_attach, \ + slave_configure:sym53c8xx_slave_configure,\ abort: sym53c8xx_abort, \ reset: sym53c8xx_reset, \ can_queue: SCSI_NCR_CAN_QUEUE, \ diff -Nru a/drivers/scsi/sym53c8xx_2/sym53c8xx.h b/drivers/scsi/sym53c8xx_2/sym53c8xx.h --- a/drivers/scsi/sym53c8xx_2/sym53c8xx.h Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/sym53c8xx_2/sym53c8xx.h Wed Nov 27 14:36:32 2002 @@ -89,7 +89,7 @@ int sym53c8xx_eh_bus_reset_handler(Scsi_Cmnd *); int sym53c8xx_eh_host_reset_handler(Scsi_Cmnd *); -int sym53c8xx_slave_attach(Scsi_Device *); +int sym53c8xx_slave_configure(Scsi_Device *); #ifdef MODULE int sym53c8xx_release(struct Scsi_Host *); @@ -111,7 +111,7 @@ release: sym53c8xx_release, \ info: sym53c8xx_info, \ queuecommand: sym53c8xx_queue_command, \ - slave_attach: sym53c8xx_slave_attach, \ + slave_configure: sym53c8xx_slave_configure, \ eh_abort_handler: sym53c8xx_eh_abort_handler, \ eh_device_reset_handler:sym53c8xx_eh_device_reset_handler, \ eh_bus_reset_handler: sym53c8xx_eh_bus_reset_handler, \ diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c --- a/drivers/scsi/sym53c8xx_2/sym_glue.c Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c Wed Nov 27 14:36:32 2002 @@ -1328,7 +1328,7 @@ * Linux entry point for device queue sizing. */ int -sym53c8xx_slave_attach(Scsi_Device *device) +sym53c8xx_slave_configure(Scsi_Device *device) { struct Scsi_Host *host = device->host; hcb_p np; diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c --- a/drivers/scsi/t128.c Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/t128.c Wed Nov 27 14:36:31 2002 @@ -111,15 +111,17 @@ #include #include #include +#include +#include +#include +#include +#include + #include "scsi.h" #include "hosts.h" #include "t128.h" #define AUTOPROBE_IRQ #include "NCR5380.h" -#include -#include -#include -#include static struct override { unsigned long address; @@ -143,7 +145,7 @@ #define NO_BASES (sizeof (bases) / sizeof (struct base)) -static const struct signature { +static struct signature { const char *string; int offset; } signatures[] __initdata = { diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c --- a/drivers/scsi/u14-34f.c Wed Nov 27 14:36:28 2002 +++ b/drivers/scsi/u14-34f.c Wed Nov 27 14:36:28 2002 @@ -630,7 +630,7 @@ static int max_queue_depth = MAX_CMD_PER_LUN; #endif -static int u14_34f_slave_attach(Scsi_Device *dev) { +static int u14_34f_slave_configure(Scsi_Device *dev) { int j, tqd, utqd; char *tag_suffix, *link_suffix; struct Scsi_Host *host = dev->host; diff -Nru a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h --- a/drivers/scsi/u14-34f.h Wed Nov 27 14:36:31 2002 +++ b/drivers/scsi/u14-34f.h Wed Nov 27 14:36:31 2002 @@ -8,7 +8,7 @@ static int u14_34f_eh_abort(Scsi_Cmnd *); static int u14_34f_eh_host_reset(Scsi_Cmnd *); static int u14_34f_bios_param(struct scsi_device *, struct block_device *, sector_t, int *); -static int u14_34f_slave_attach(Scsi_Device *); +static int u14_34f_slave_configure(Scsi_Device *); #define U14_34F_VERSION "8.00.00" @@ -22,7 +22,7 @@ eh_bus_reset_handler: NULL, \ eh_host_reset_handler: u14_34f_eh_host_reset, \ bios_param: u14_34f_bios_param, \ - slave_attach: u14_34f_slave_attach, \ + slave_configure: u14_34f_slave_configure, \ this_id: 7, \ unchecked_isa_dma: 1, \ use_clustering: ENABLE_CLUSTERING \ diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c --- a/drivers/scsi/ultrastor.c Wed Nov 27 14:36:30 2002 +++ b/drivers/scsi/ultrastor.c Wed Nov 27 14:36:30 2002 @@ -1047,7 +1047,7 @@ printk("Ux4F interrupt: bad MSCP address %x\n", (unsigned int) mscp); /* A command has been lost. Reset and report an error for all commands. */ - ultrastor_reset(NULL, 0); + ultrastor_host_reset(dev_id); return; } #endif diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c --- a/drivers/scsi/wd7000.c Wed Nov 27 14:36:32 2002 +++ b/drivers/scsi/wd7000.c Wed Nov 27 14:36:32 2002 @@ -1434,23 +1434,21 @@ /* * Display driver information for each device attached to the board. */ - scd = host->host_queue; + SPRINTF("\nAttached devices: %s\n", !list_empty(&host->my_devices) ? + "" : "none"); - SPRINTF("\nAttached devices: %s\n", scd ? "" : "none"); + list_for_each_entry (scd, &host->my_devices, siblings) { + SPRINTF(" [Channel: %02d, Id: %02d, Lun: %02d] ", scd->channel, scd->id, scd->lun); + SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(short) scd->type] : "Unknown device"); - for (; scd; scd = scd->next) - if (scd->host->host_no == hostno) { - SPRINTF(" [Channel: %02d, Id: %02d, Lun: %02d] ", scd->channel, scd->id, scd->lun); - SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(short) scd->type] : "Unknown device"); + for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++) + SPRINTF("%c", scd->vendor[i]); + SPRINTF(" "); - for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++) - SPRINTF("%c", scd->vendor[i]); - SPRINTF(" "); - - for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++) - SPRINTF("%c", scd->model[i]); - SPRINTF("\n"); - } + for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++) + SPRINTF("%c", scd->model[i]); + SPRINTF("\n"); + } SPRINTF("\n"); diff -Nru a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c --- a/drivers/serial/8250_acorn.c Wed Nov 27 14:36:31 2002 +++ b/drivers/serial/8250_acorn.c Wed Nov 27 14:36:31 2002 @@ -55,8 +55,6 @@ unsigned long cardaddr, address; int port; - ecard_claim (ec); - info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -64,6 +62,8 @@ memset(info, 0, sizeof(struct serial_card_info)); info->num_ports = type->num_ports; + ecard_set_drvdata(ec, info); + cardaddr = ecard_address(ec, type->type, type->speed); for (port = 0; port < info->num_ports; port ++) { @@ -98,8 +98,6 @@ } kfree(info); - - ecard_release(ec); } static struct serial_card_type atomwide_type = { diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig --- a/drivers/serial/Kconfig Wed Nov 27 14:36:31 2002 +++ b/drivers/serial/Kconfig Wed Nov 27 14:36:31 2002 @@ -365,7 +365,7 @@ config V850E_NB85E_UART bool "NEC V850E on-chip UART support" - depends on V850E_NB85E || V850E2_ANNA + depends on V850E_NB85E || V850E2_ANNA || V850E_AS85EP1 default y config V850E_NB85E_UART_CONSOLE diff -Nru a/drivers/serial/nb85e_uart.c b/drivers/serial/nb85e_uart.c --- a/drivers/serial/nb85e_uart.c Wed Nov 27 14:36:31 2002 +++ b/drivers/serial/nb85e_uart.c Wed Nov 27 14:36:31 2002 @@ -25,10 +25,10 @@ /* Initial UART state. This may be overridden by machine-dependent headers. */ #ifndef NB85E_UART_INIT_BAUD -#define NB85E_UART_INIT_BAUD 38400 +#define NB85E_UART_INIT_BAUD 115200 #endif #ifndef NB85E_UART_INIT_CFLAGS -#define NB85E_UART_INIT_CFLAGS (B38400 | CS8 | CREAD) +#define NB85E_UART_INIT_CFLAGS (B115200 | CS8 | CREAD) #endif /* A string used for prefixing printed descriptions; since the same UART @@ -304,7 +304,7 @@ port->icount.tx++; if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS) - uart_event (port, EVT_WRITE_WAKEUP); + uart_write_wakeup (port); } no_xmit: diff -Nru a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig --- a/drivers/usb/core/Kconfig Wed Nov 27 14:36:31 2002 +++ b/drivers/usb/core/Kconfig Wed Nov 27 14:36:31 2002 @@ -38,18 +38,6 @@ Most users want to say Y here. -config USB_LONG_TIMEOUT - bool "Long timeout for slow-responding devices (some MGE Ellipse UPSes)" - depends on USB - help - This option makes the standard time out a bit longer. Basically, - some devices are just slow to respond, so this makes usb more - patient. There should be no harm in selecting this, but it is - needed for some MGE Ellipse UPSes. - - If you have an MGE Ellipse UPS, or you see timeouts in HID - transactions, say Y; otherwise say N. - config USB_BANDWIDTH bool "Enforce USB bandwidth allocation (EXPERIMENTAL)" depends on USB && EXPERIMENTAL diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c --- a/drivers/usb/core/devio.c Wed Nov 27 14:36:30 2002 +++ b/drivers/usb/core/devio.c Wed Nov 27 14:36:30 2002 @@ -53,6 +53,7 @@ struct dev_state *ps; struct task_struct *task; unsigned int signr; + unsigned int intf; void *userbuffer; void *userurb; struct urb *urb; @@ -273,23 +274,47 @@ } } -static void destroy_all_async(struct dev_state *ps) +static void destroy_async (struct dev_state *ps, struct list_head *list) { - struct async *as; - unsigned long flags; + struct async *as; + unsigned long flags; - spin_lock_irqsave(&ps->lock, flags); - while (!list_empty(&ps->async_pending)) { - as = list_entry(ps->async_pending.next, struct async, asynclist); - list_del_init(&as->asynclist); - spin_unlock_irqrestore(&ps->lock, flags); + spin_lock_irqsave(&ps->lock, flags); + while (!list_empty(list)) { + as = list_entry(list->next, struct async, asynclist); + list_del_init(&as->asynclist); + spin_unlock_irqrestore(&ps->lock, flags); /* usb_unlink_urb calls the completion handler with status == -ENOENT */ - usb_unlink_urb(as->urb); - spin_lock_irqsave(&ps->lock, flags); - } - spin_unlock_irqrestore(&ps->lock, flags); - while ((as = async_getcompleted(ps))) - free_async(as); + usb_unlink_urb(as->urb); + spin_lock_irqsave(&ps->lock, flags); + } + spin_unlock_irqrestore(&ps->lock, flags); + while ((as = async_getcompleted(ps))) + free_async(as); +} + +static void destroy_async_on_interface (struct dev_state *ps, unsigned int intf) +{ + struct async *as; + struct list_head *p, hitlist; + unsigned long flags; + + INIT_LIST_HEAD(&hitlist); + spin_lock_irqsave(&ps->lock, flags); + for (p = ps->async_pending.next; p != &ps->async_pending; ) { + as = list_entry(p, struct async, asynclist); + p = p->next; + + if (as->intf == intf) + list_move_tail(&as->asynclist, &hitlist); + } + spin_unlock_irqrestore(&ps->lock, flags); + destroy_async(ps, &hitlist); +} + +extern __inline__ void destroy_all_async(struct dev_state *ps) +{ + destroy_async(ps, &ps->async_pending); } /* @@ -751,7 +776,7 @@ struct async *as; struct usb_ctrlrequest *dr = NULL; unsigned int u, totlen, isofrmlen; - int ret, interval = 0; + int ret, interval = 0, intf = -1; if (copy_from_user(&uurb, arg, sizeof(uurb))) return -EFAULT; @@ -763,9 +788,9 @@ if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX)) return -EINVAL; if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { - if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0) - return ret; - if ((ret = checkintf(ps, ret))) + if ((intf = findintfep(ps->dev, uurb.endpoint)) < 0) + return intf; + if ((ret = checkintf(ps, intf))) return ret; } switch(uurb.type) { @@ -889,6 +914,7 @@ else as->userbuffer = NULL; as->signr = uurb.signr; + as->intf = intf; as->task = current; if (!(uurb.endpoint & USB_DIR_IN)) { if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) { @@ -1035,7 +1061,10 @@ return -EFAULT; if ((ret = findintfif(ps->dev, intf)) < 0) return ret; - return releaseintf(ps, intf); + if ((ret = releaseintf(ps, intf)) < 0) + return ret; + destroy_async_on_interface (ps, intf); + return 0; } static int proc_ioctl (struct dev_state *ps, void *arg) diff -Nru a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c --- a/drivers/usb/host/ohci-mem.c Wed Nov 27 14:36:31 2002 +++ b/drivers/usb/host/ohci-mem.c Wed Nov 27 14:36:31 2002 @@ -14,7 +14,8 @@ * - data used only by the HCD ... kmalloc is fine * - async and periodic schedules, shared by HC and HCD ... these * need to use pci_pool or pci_alloc_consistent - * - driver buffers, read/written by HC ... single shot DMA mapped + * - driver buffers, read/written by HC ... the hcd glue or the + * device driver provides us with dma addresses * * There's also PCI "register" data, which is memory mapped. * No memory seen by this driver is pagable. @@ -41,95 +42,6 @@ /*-------------------------------------------------------------------------*/ -/* Recover a TD/ED using its collision chain */ -static inline void * -dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma) -{ - struct hash_t * scan = entry->head; - while (scan && scan->dma != dma) - scan = scan->next; - return scan ? scan->virt : 0; -} - -static inline struct td * -dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma) -{ - td_dma &= TD_MASK; - return (struct td *) dma_to_ed_td(&(hc->td_hash [TD_HASH_FUNC(td_dma)]), - td_dma); -} - -// FIXME: when updating the hashtables this way, mem_flags is unusable... - -/* Add a hash entry for a TD/ED; return true on success */ -static inline int -hash_add_ed_td ( - struct hash_list_t *entry, - void *virt, - dma_addr_t dma, - int mem_flags -) -{ - struct hash_t * scan; - - scan = (struct hash_t *) kmalloc (sizeof *scan, mem_flags); - if (!scan) - return 0; - - if (!entry->tail) { - entry->head = entry->tail = scan; - } else { - entry->tail->next = scan; - entry->tail = scan; - } - - scan->virt = virt; - scan->dma = dma; - scan->next = NULL; - return 1; -} - -static inline int -hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags) -{ - return hash_add_ed_td (&(hc->td_hash [TD_HASH_FUNC (td->td_dma)]), - td, td->td_dma, mem_flags); -} - - -static inline void -hash_free_ed_td (struct hash_list_t *entry, void *virt) -{ - struct hash_t *scan, *prev; - scan = prev = entry->head; - - // Find and unlink hash entry - while (scan && scan->virt != virt) { - prev = scan; - scan = scan->next; - } - if (scan) { - if (scan == entry->head) { - if (entry->head == entry->tail) - entry->head = entry->tail = NULL; - else - entry->head = scan->next; - } else if (scan == entry->tail) { - entry->tail = prev; - prev->next = NULL; - } else - prev->next = scan->next; - kfree(scan); - } -} - -static inline void -hash_free_td (struct ohci_hcd *hc, struct td * td) -{ - hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td); -} - - static int ohci_mem_init (struct ohci_hcd *ohci) { ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev, @@ -161,6 +73,21 @@ } } +/*-------------------------------------------------------------------------*/ + +/* ohci "done list" processing needs this mapping */ +static inline struct td * +dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma) +{ + struct td *td; + + td_dma &= TD_MASK; + td = hc->td_hash [TD_HASH_FUNC(td_dma)]; + while (td && td->td_dma != td_dma) + td = td->td_hash; + return td; +} + /* TDs ... */ static struct td * td_alloc (struct ohci_hcd *hc, int mem_flags) @@ -170,12 +97,17 @@ td = pci_pool_alloc (hc->td_cache, mem_flags, &dma); if (td) { + int hash; + + /* in case hc fetches it, make it look dead */ + memset (td, 0, sizeof *td); + td->hwNextTD = cpu_to_le32 (dma); td->td_dma = dma; + /* hash it for later reverse mapping */ - if (!hash_add_td (hc, td, mem_flags)) { - pci_pool_free (hc->td_cache, td, dma); - return NULL; - } + hash = TD_HASH_FUNC (dma); + td->td_hash = hc->td_hash [hash]; + hc->td_hash [hash] = td; } return td; } @@ -183,10 +115,18 @@ static void td_free (struct ohci_hcd *hc, struct td *td) { - hash_free_td (hc, td); + struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)]; + + while (*prev && *prev != td) + prev = &(*prev)->td_hash; + if (*prev) + *prev = td->td_hash; + else + dev_dbg (*hc->hcd.controller, "bad hash for td %p\n", td); pci_pool_free (hc->td_cache, td, td->td_dma); } +/*-------------------------------------------------------------------------*/ /* EDs ... */ static struct ed * diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h --- a/drivers/usb/host/ohci.h Wed Nov 27 14:36:32 2002 +++ b/drivers/usb/host/ohci.h Wed Nov 27 14:36:32 2002 @@ -111,6 +111,7 @@ /* rest are purely for the driver's use */ __u8 index; struct ed *ed; + struct td *td_hash; /* dma-->td hashtable */ struct td *next_dl_td; struct urb *urb; @@ -320,23 +321,9 @@ #define URB_DEL 1 - -/* Hash struct used for TD/ED hashing */ -struct hash_t { - void *virt; - dma_addr_t dma; - struct hash_t *next; // chaining for collision cases -}; - -/* List of TD/ED hash entries */ -struct hash_list_t { - struct hash_t *head; - struct hash_t *tail; -}; - #define TD_HASH_SIZE 64 /* power'o'two */ - -#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE) +// sizeof (struct td) ~= 64 == 2^6 ... +#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE) /* @@ -373,7 +360,7 @@ */ struct pci_pool *td_cache; struct pci_pool *ed_cache; - struct hash_list_t td_hash [TD_HASH_SIZE]; + struct td *td_hash [TD_HASH_SIZE]; /* * driver state diff -Nru a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig --- a/drivers/usb/media/Kconfig Wed Nov 27 14:36:27 2002 +++ b/drivers/usb/media/Kconfig Wed Nov 27 14:36:27 2002 @@ -120,15 +120,26 @@ tristate "USB Philips Cameras" depends on USB && VIDEO_DEV ---help--- - Say Y or M here if you want to use one of these Philips USB webcams: - PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or - the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported - by this driver and never will be. + Say Y or M here if you want to use one of these Philips & OEM + webcams: + * Philips PCA645, PCA646 + * Philips PCVC675, PCVC680, PCVC690 + * Philips PCVC730, PCVC740, PCVC750 + * Askey VC010 + * Logitech QuickCam Pro 3000, 4000, 'Zoom' and 'Notebook' + * Samsung MPC-C10, MPC-C30 + * Creative Webcam 5 + * SOTECT Afina Eye + * Visionite VCS-UC300, VCS-UM100 + + The PCA635, PCVC665 and PCVC720 are not supported by this driver + and never will be, but the 665 and 720 are supported by other + drivers. - This driver has an optional plugin, which is distributed as a binary - module only. It contains code that allow you to use higher - resolutions and framerates but may not be distributed as source. - But even without this plugin you can these cams for most + This driver has an optional plugin (called PWCX), which is + distributed as a binary module only. It contains code that allow you + to use higher resolutions and framerates but may not be distributed + as source. But even without this plugin you can these cams for most applications. See for more information and diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c --- a/drivers/usb/media/ov511.c Wed Nov 27 14:36:28 2002 +++ b/drivers/usb/media/ov511.c Wed Nov 27 14:36:28 2002 @@ -60,7 +60,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.62 for Linux 2.5" +#define DRIVER_VERSION "v1.63 for Linux 2.5" #define EMAIL "mark@alpha.dyndns.org" #define DRIVER_AUTHOR "Mark McClelland & Bret Wallach \ & Orion Sky Lawlor & Kevin Moore & Charl P. Botha \ @@ -121,6 +121,7 @@ static int unit_video[OV511_MAX_UNIT_VIDEO]; static int remove_zeros; static int mirror; +static int ov518_color; MODULE_PARM(autobright, "i"); MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness"); @@ -193,6 +194,8 @@ "Remove zero-padding from uncompressed incoming data"); MODULE_PARM(mirror, "i"); MODULE_PARM_DESC(mirror, "Reverse image horizontally"); +MODULE_PARM(ov518_color, "i"); +MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -259,6 +262,7 @@ { 100, "Lifeview RoboCam" }, { 102, "AverMedia InterCam Elite" }, { 112, "MediaForte MV300" }, /* or OV7110 evaluation kit */ + { 134, "Ezonics EZCam II" }, { 192, "Webeye 2000B" }, { 253, "Alpha Vision Tech. AlphaCam SE" }, { -1, NULL } @@ -293,6 +297,7 @@ { -1, NULL } }; +#if defined(CONFIG_VIDEO_PROC_FS) static struct symbolic_list senlist[] = { { SEN_OV76BE, "OV76BE" }, { SEN_OV7610, "OV7610" }, @@ -308,6 +313,7 @@ { SEN_SAA7111A, "SAA7111A" }, { -1, NULL } }; +#endif /* URB error codes: */ static struct symbolic_list urb_errlist[] = { @@ -321,20 +327,6 @@ }; /********************************************************************** - * Prototypes - **********************************************************************/ - -static void ov51x_clear_snapshot(struct usb_ov511 *); -static inline int sensor_get_picture(struct usb_ov511 *, - struct video_picture *); -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) -static int sensor_get_exposure(struct usb_ov511 *, unsigned char *); -static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int, - unsigned long); -static int ov51x_check_snapshot(struct usb_ov511 *); -#endif - -/********************************************************************** * Memory management **********************************************************************/ @@ -396,11 +388,19 @@ * Based on the CPiA driver version 0.7.4 -claudio **********************************************************************/ -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) +#if defined(CONFIG_VIDEO_PROC_FS) static struct proc_dir_entry *ov511_proc_entry = NULL; extern struct proc_dir_entry *video_proc_entry; +/* Prototypes */ +static void ov51x_clear_snapshot(struct usb_ov511 *); +static int sensor_get_picture(struct usb_ov511 *, struct video_picture *); +static int sensor_get_exposure(struct usb_ov511 *, unsigned char *); +static int ov51x_check_snapshot(struct usb_ov511 *); +static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int, + unsigned long); + static struct file_operations ov511_control_fops = { .ioctl = ov51x_control_ioctl, }; @@ -460,6 +460,8 @@ symbolic(senlist, ov->sensor)); out += sprintf(out, "packet_size : %d\n", ov->packet_size); out += sprintf(out, "framebuffer : 0x%p\n", ov->fbuf); + out += sprintf(out, "packet_numbering: %d\n", ov->packet_numbering); + out += sprintf(out, "topology : %s\n", ov->usb_path); len = out - page; len -= off; @@ -637,7 +639,12 @@ remove_proc_entry("ov511", video_proc_entry); } -#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ +#else +static inline void create_proc_ov511_cam(struct usb_ov511 *ov) { } +static inline void destroy_proc_ov511_cam(struct usb_ov511 *ov) { } +static inline void proc_ov511_create(void) { } +static inline void proc_ov511_destroy(void) { } +#endif /* #ifdef CONFIG_VIDEO_PROC_FS */ /********************************************************************** * @@ -1116,7 +1123,7 @@ * when calling this. This should not be called from outside the i2c I/O * functions. */ -static inline int +static int i2c_set_slave_internal(struct usb_ov511 *ov, unsigned char slave) { int rc; @@ -1357,7 +1364,7 @@ } } -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) +#if defined(CONFIG_VIDEO_PROC_FS) /* Checks the status of the snapshot button. Returns 1 if it was pressed since * it was last cleared, and zero in all other cases (including errors) */ static int @@ -1970,7 +1977,7 @@ /* -------------------------------------------------------------------------- */ -static inline int +static int sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p) { int rc; @@ -2001,7 +2008,7 @@ return 0; } -static inline int +static int sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p) { int rc; @@ -2032,7 +2039,7 @@ return 0; } -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) +#if defined(CONFIG_VIDEO_PROC_FS) // FIXME: Exposure range is only 0x00-0x7f in interlace mode /* Sets current exposure for sensor. This only has an effect if auto-exposure * is off */ @@ -2117,7 +2124,7 @@ #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ /* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */ -static inline void +static void ov51x_led_control(struct usb_ov511 *ov, int enable) { PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); @@ -2198,7 +2205,7 @@ * Unsupported: KS0127, KS0127B, SAA7111A * Returns: 0 for success */ -static inline int +static int sensor_set_banding_filter(struct usb_ov511 *ov, int enable) { int rc; @@ -2226,7 +2233,7 @@ * Unsupported: KS0127, KS0127B, SAA7111A * Returns: 0 for success */ -static inline int +static int sensor_set_auto_brightness(struct usb_ov511 *ov, int enable) { int rc; @@ -2254,7 +2261,7 @@ * Unsupported: KS0127, KS0127B, SAA7111A * Returns: 0 for success */ -static inline int +static int sensor_set_auto_exposure(struct usb_ov511 *ov, int enable) { PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); @@ -2333,7 +2340,7 @@ return 0; } -static inline int +static int sensor_set_mirror(struct usb_ov511 *ov, int enable) { PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); @@ -2434,7 +2441,7 @@ i2c_w(ov, 0x14, qvga?0x24:0x04); break; case SEN_OV6630: - i2c_w(ov, 0x14, qvga?0xa4:0x84); + i2c_w(ov, 0x14, qvga?0xa0:0x80); break; default: err("Invalid sensor"); @@ -2448,13 +2455,33 @@ /* these aren't valid on the OV6620/OV7620/6630? */ i2c_w_mask(ov, 0x0e, 0x40, 0x40); } - i2c_w_mask(ov, 0x13, 0x20, 0x20); + + if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 + && ov518_color) { + i2c_w_mask(ov, 0x12, 0x00, 0x10); + i2c_w_mask(ov, 0x13, 0x00, 0x20); + } else { + i2c_w_mask(ov, 0x13, 0x20, 0x20); + } } else { if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { /* not valid on the OV6620/OV7620/6630? */ i2c_w_mask(ov, 0x0e, 0x00, 0x40); } - i2c_w_mask(ov, 0x13, 0x00, 0x20); + + /* The OV518 needs special treatment. Although both the OV518 + * and the OV6630 support a 16-bit video bus, only the 8 bit Y + * bus is actually used. The UV bus is tied to ground. + * Therefore, the OV6630 needs to be in 8-bit multiplexed + * output mode */ + + if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 + && ov518_color) { + i2c_w_mask(ov, 0x12, 0x10, 0x10); + i2c_w_mask(ov, 0x13, 0x20, 0x20); + } else { + i2c_w_mask(ov, 0x13, 0x00, 0x20); + } } /******** Clock programming ********/ @@ -2781,8 +2808,29 @@ reg_w(ov, 0x3d, 0); reg_w(ov, 0x3e, 0); - reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); - reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + if (ov->bridge == BRG_OV518 && ov518_color) { + /* OV518 needs U and V swapped */ + i2c_w_mask(ov, 0x15, 0x00, 0x01); + + if (mode == VIDEO_PALETTE_GREY) { + /* Set 16-bit input format (UV data are ignored) */ + reg_w_mask(ov, 0x20, 0x00, 0x08); + + /* Set 8-bit (4:0:0) output format */ + reg_w_mask(ov, 0x28, 0x00, 0xf0); + reg_w_mask(ov, 0x38, 0x00, 0xf0); + } else { + /* Set 8-bit (YVYU) input format */ + reg_w_mask(ov, 0x20, 0x08, 0x08); + + /* Set 12-bit (4:2:0) output format */ + reg_w_mask(ov, 0x28, 0x80, 0xf0); + reg_w_mask(ov, 0x38, 0x80, 0xf0); + } + } else { + reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + } hsegs = width / 16; vsegs = height / 4; @@ -3074,7 +3122,7 @@ } /* - * For RAW BW (YUV400) images, data shows up in 256 byte segments. + * For RAW BW (YUV 4:0:0) images, data show up in 256 byte segments. * The segments represent 4 squares of 8x8 pixels as follows: * * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 @@ -3105,7 +3153,7 @@ } /* - * For YUV4:2:0 images, the data shows up in 384 byte segments. + * For YUV 4:2:0 images, the data show up in 384 byte segments. * The first 64 bytes of each segment are U, the next 64 are V. The U and * V are arranged as follows: * @@ -3124,8 +3172,8 @@ * ... ... ... * 56 57 ... 63 120 121 ... 127 ... 248 249 ... 255 * - * Note that the U and V data in one segment represents a 16 x 16 pixel - * area, but the Y data represents a 32 x 8 pixel area. If the width is not an + * Note that the U and V data in one segment represent a 16 x 16 pixel + * area, but the Y data represent a 32 x 8 pixel area. If the width is not an * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the * next horizontal stripe. * @@ -3133,7 +3181,7 @@ * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480 * this puts the data on the standard output and can be analyzed with the * parseppm.c utility I wrote. That's a much faster way for figuring out how - * this data is scrambled. + * these data are scrambled. */ /* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0. @@ -4285,7 +4333,6 @@ } file->private_data = NULL; - return 0; } @@ -4752,7 +4799,7 @@ return rc; } -static inline int +static int ov51x_v4l1_read(struct file *file, char *buf, size_t cnt, loff_t *ppos) { struct video_device *vdev = file->private_data; @@ -4882,7 +4929,7 @@ PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld", count, frame->bytes_read); - /* If all data has been read... */ + /* If all data have been read... */ if (frame->bytes_read >= get_frame_length(frame)) { frame->bytes_read = 0; @@ -4966,7 +5013,7 @@ .fops = &ov511_fops, }; -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) +#if defined(CONFIG_VIDEO_PROC_FS) static int ov51x_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ularg) @@ -5453,14 +5500,12 @@ { OV511_I2C_BUS, 0x4f, 0x04 }, // Do 50-53 have any effect? // Toggle 0x12[2] off and on here? - { OV511_DONE_BUS, 0x0, 0x00 }, + { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ }; - /* This chip is undocumented so many of these are guesses. OK=verified, - * A=Added since 6620, U=unknown function (not a 6620 reg) */ static struct ov511_regvals aRegvalsNorm6x30[] = { /*OK*/ { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ - /*00?*/ { OV511_I2C_BUS, 0x11, 0x01 }, + { OV511_I2C_BUS, 0x11, 0x00 }, /*OK*/ { OV511_I2C_BUS, 0x03, 0x60 }, /*0A?*/ { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ { OV511_I2C_BUS, 0x07, 0xa8 }, @@ -5468,16 +5513,8 @@ /*OK*/ { OV511_I2C_BUS, 0x0c, 0x24 }, /*OK*/ { OV511_I2C_BUS, 0x0d, 0x24 }, /*A*/ { OV511_I2C_BUS, 0x0e, 0x20 }, - -// /*24?*/ { OV511_I2C_BUS, 0x12, 0x28 }, /* Enable AGC */ -// { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */ - -// /*A*/ { OV511_I2C_BUS, 0x13, 0x21 }, -// /*A*/ { OV511_I2C_BUS, 0x13, 0x25 }, /* Tristate Y and UV busses */ - // /*04?*/ { OV511_I2C_BUS, 0x14, 0x80 }, - /* 0x16: 0x06 helps frame stability with moving objects */ - /*03?*/ { OV511_I2C_BUS, 0x16, 0x06 }, + { OV511_I2C_BUS, 0x16, 0x03 }, // /*OK*/ { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ // 21 & 22? The suggested values look wrong. Go with default /*A*/ { OV511_I2C_BUS, 0x23, 0xc0 }, @@ -5490,49 +5527,34 @@ /*OK*/ { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ // /*OK*/ { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ -// /*U*/ { OV511_I2C_BUS, 0x2c, 0xa0 }, { OV511_I2C_BUS, 0x2d, 0x99 }, // /*A*/ { OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620 // /*d2?*/ { OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */ -// /*U*/ { OV511_I2C_BUS, 0x36, 0x8f }, // May not be necessary -// /*U*/ { OV511_I2C_BUS, 0x37, 0x80 }, // May not be necessary // /*8b?*/ { OV511_I2C_BUS, 0x38, 0x83 }, // /*40?*/ { OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7 // { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ // { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ // { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ - /*OK*/ { OV511_I2C_BUS, 0x3d, 0x80 }, + { OV511_I2C_BUS, 0x3d, 0x80 }, // /*A*/ { OV511_I2C_BUS, 0x3f, 0x0e }, -// /*U*/ { OV511_I2C_BUS, 0x40, 0x00 }, -// /*U*/ { OV511_I2C_BUS, 0x41, 0x00 }, -// /*U*/ { OV511_I2C_BUS, 0x42, 0x80 }, -// /*U*/ { OV511_I2C_BUS, 0x43, 0x3f }, -// /*U*/ { OV511_I2C_BUS, 0x44, 0x80 }, -// /*U*/ { OV511_I2C_BUS, 0x45, 0x20 }, -// /*U*/ { OV511_I2C_BUS, 0x46, 0x20 }, -// /*U*/ { OV511_I2C_BUS, 0x47, 0x80 }, -// /*U*/ { OV511_I2C_BUS, 0x48, 0x7f }, -// /*U*/ { OV511_I2C_BUS, 0x49, 0x00 }, /* These next two registers (0x4a, 0x4b) are undocumented. They * control the color balance */ // /*OK?*/ { OV511_I2C_BUS, 0x4a, 0x80 }, // Check these // /*OK?*/ { OV511_I2C_BUS, 0x4b, 0x80 }, -// /*U*/ { OV511_I2C_BUS, 0x4c, 0xd0 }, - /*d2?*/ { OV511_I2C_BUS, 0x4d, 0x10 }, /* This reduces noise a bit */ + { OV511_I2C_BUS, 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ /*c1?*/ { OV511_I2C_BUS, 0x4e, 0x40 }, - /*04?*/ { OV511_I2C_BUS, 0x4f, 0x07 }, -// /*U*/ { OV511_I2C_BUS, 0x50, 0xff }, - /*U*/ { OV511_I2C_BUS, 0x54, 0x23 }, -// /*U*/ { OV511_I2C_BUS, 0x55, 0xff }, -// /*U*/ { OV511_I2C_BUS, 0x56, 0x12 }, - /*U*/ { OV511_I2C_BUS, 0x57, 0x81 }, -// /*U*/ { OV511_I2C_BUS, 0x58, 0x75 }, - /*U*/ { OV511_I2C_BUS, 0x59, 0x01 }, - /*U*/ { OV511_I2C_BUS, 0x5a, 0x2c }, - /*U*/ { OV511_I2C_BUS, 0x5b, 0x0f }, -// /*U*/ { OV511_I2C_BUS, 0x5c, 0x10 }, - { OV511_DONE_BUS, 0x0, 0x00 }, + + /* UV average mode, color killer: strongest */ + { OV511_I2C_BUS, 0x4f, 0x07 }, + + { OV511_I2C_BUS, 0x54, 0x23 }, /* Max AGC gain: 18dB */ + { OV511_I2C_BUS, 0x57, 0x81 }, /* (default) */ + { OV511_I2C_BUS, 0x59, 0x01 }, /* AGC dark current comp: +1 */ + { OV511_I2C_BUS, 0x5a, 0x2c }, /* (undocumented) */ + { OV511_I2C_BUS, 0x5b, 0x0f }, /* AWB chrominance levels */ +// { OV511_I2C_BUS, 0x5c, 0x10 }, + { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ }; PDEBUG(4, "starting sensor configuration"); @@ -5553,16 +5575,19 @@ return -1; } - if ((rc & 3) == 0) + if ((rc & 3) == 0) { ov->sensor = SEN_OV6630; - else if ((rc & 3) == 1) + info("Sensor is an OV6630"); + } else if ((rc & 3) == 1) { ov->sensor = SEN_OV6620; - else if ((rc & 3) == 2) + info("Sensor is an OV6620"); + } else if ((rc & 3) == 2) { ov->sensor = SEN_OV6630; - else if ((rc & 3) == 3) + info("Sensor is an OV6630AE"); + } else if ((rc & 3) == 3) { ov->sensor = SEN_OV6630; - - info("Sensor is an %s", symbolic(senlist, ov->sensor)); + info("Sensor is an OV6630AF"); + } /* Set sensor-specific vars */ ov->maxwidth = 352; @@ -5922,7 +5947,7 @@ { OV511_REG_BUS, 0x5d, 0x03 }, { OV511_REG_BUS, 0x24, 0x9f }, { OV511_REG_BUS, 0x25, 0x90 }, - { OV511_REG_BUS, 0x20, 0x00 }, /* Was 0x08 */ + { OV511_REG_BUS, 0x20, 0x00 }, { OV511_REG_BUS, 0x51, 0x04 }, { OV511_REG_BUS, 0x71, 0x19 }, { OV511_DONE_BUS, 0x0, 0x00 }, @@ -5935,7 +5960,7 @@ { OV511_REG_BUS, 0x5d, 0x03 }, { OV511_REG_BUS, 0x24, 0x9f }, { OV511_REG_BUS, 0x25, 0x90 }, - { OV511_REG_BUS, 0x20, 0x60 }, /* Was 0x08 */ + { OV511_REG_BUS, 0x20, 0x60 }, { OV511_REG_BUS, 0x51, 0x02 }, { OV511_REG_BUS, 0x71, 0x19 }, { OV511_REG_BUS, 0x40, 0xff }, @@ -6151,6 +6176,11 @@ ov->buf_state = BUF_NOT_ALLOCATED; + if (usb_make_path(dev, ov->usb_path, OV511_USB_PATH_LEN) < 0) { + err("usb_make_path error"); + goto error_dealloc; + } + /* Allocate control transfer buffer. */ /* Must be kmalloc()'ed, for DMA compatibility */ ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL); @@ -6212,20 +6242,16 @@ goto error; } - info("Device registered on minor %d", ov->vdev.minor); + info("Device at %s registered to minor %d", ov->usb_path, + ov->vdev.minor); -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) create_proc_ov511_cam(ov); -#endif dev_set_drvdata (&intf->dev, ov); - return 0; + return 0; error: -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) - /* Safe to call even if entry doesn't exist */ destroy_proc_ov511_cam(ov); -#endif if (ov->cbuf) { down(&ov->cbuf_lock); @@ -6274,12 +6300,9 @@ wake_up_interruptible(&ov->wq); ov->streaming = 0; - ov51x_unlink_isoc(ov); -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) destroy_proc_ov511_cam(ov); -#endif ov->dev = NULL; @@ -6396,9 +6419,7 @@ static int __init usb_ov511_init(void) { -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) proc_ov511_create(); -#endif if (usb_register(&ov511_driver) < 0) return -1; @@ -6414,9 +6435,7 @@ usb_deregister(&ov511_driver); info("driver deregistered"); -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) proc_ov511_destroy(); -#endif } module_init(usb_ov511_init); diff -Nru a/drivers/usb/media/ov511.h b/drivers/usb/media/ov511.h --- a/drivers/usb/media/ov511.h Wed Nov 27 14:36:29 2002 +++ b/drivers/usb/media/ov511.h Wed Nov 27 14:36:29 2002 @@ -253,6 +253,9 @@ /* Control transfers use up to 4 bytes */ #define OV511_CBUF_SIZE 4 +/* Size of usb_make_path() buffer */ +#define OV511_USB_PATH_LEN 64 + /* Bridge types */ enum { BRG_UNKNOWN, @@ -450,6 +453,7 @@ int customid; char *desc; unsigned char iface; + char usb_path[OV511_USB_PATH_LEN]; /* Determined by sensor type */ int maxwidth; diff -Nru a/drivers/usb/media/pwc-ctrl.c b/drivers/usb/media/pwc-ctrl.c --- a/drivers/usb/media/pwc-ctrl.c Wed Nov 27 14:36:32 2002 +++ b/drivers/usb/media/pwc-ctrl.c Wed Nov 27 14:36:32 2002 @@ -256,8 +256,10 @@ memcpy(buf, pEntry->mode, 3); ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); - if (ret < 0) + if (ret < 0) { + Debug("Failed to send video command... %d\n", ret); return ret; + } if (pEntry->compressed && pdev->decompressor != NULL) pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); @@ -1103,12 +1105,7 @@ buf[0] = on_value; buf[1] = off_value; - return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), - SET_STATUS_CTL, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - LED_FORMATTER, - pdev->vcinterface, - &buf, 2, HZ / 2); + return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2); } int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) @@ -1122,13 +1119,7 @@ return 0; } - ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), - GET_STATUS_CTL, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - LED_FORMATTER, - pdev->vcinterface, - &buf, 2, HZ / 2); - + ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2); if (ret < 0) return ret; *on_value = buf[0] * 100; @@ -1279,7 +1270,6 @@ ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); if (ret < 0) return ret; -//Debug("pwc_get_dynamic_noise = %d\n", buf); return buf; } @@ -1363,12 +1353,10 @@ case VIDIOCPWCPROBE: { - struct pwc_probe probe; + struct pwc_probe *probe = arg; - strcpy(probe.name, pdev->vdev->name); - probe.type = pdev->type; - if (copy_to_user(arg, &probe, sizeof(probe))) - ret = -EFAULT; + strcpy(probe->name, pdev->vdev->name); + probe->type = pdev->type; break; } diff -Nru a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c --- a/drivers/usb/media/pwc-if.c Wed Nov 27 14:36:31 2002 +++ b/drivers/usb/media/pwc-if.c Wed Nov 27 14:36:31 2002 @@ -1,6 +1,6 @@ /* Linux driver for Philips webcam USB and Video4Linux interface part. - (C) 1999-2001 Nemosoft Unv. + (C) 1999-2002 Nemosoft Unv. 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 @@ -42,32 +42,31 @@ - Alistar Moire: QuickCam 3000 Pro device/product ID - Tony Hoyle: Creative Labs Webcam 5 device/product ID - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged - - Jk Fang: SOTEC device/product ID + - Jk Fang: SOTEC Afina Eye ID + - Xavier Roche: QuickCam Pro 4000 ID + - Jens Knudsen: QuickCam Zoom ID + - J. Debert: QuickCam for Notebooks ID */ #include #include +#include #include #include #include #include #include -#include #include #include "pwc.h" #include "pwc-ioctl.h" #include "pwc-uncompress.h" -#if !defined(MAP_NR) -#define MAP_NR(a) virt_to_page(a) -#endif - /* Function prototypes and driver templates */ /* hotplug device table support */ static struct usb_device_id pwc_device_table [] = { - { USB_DEVICE(0x0471, 0x0302) }, + { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */ { USB_DEVICE(0x0471, 0x0303) }, { USB_DEVICE(0x0471, 0x0304) }, { USB_DEVICE(0x0471, 0x0307) }, @@ -76,12 +75,17 @@ { USB_DEVICE(0x0471, 0x0310) }, { USB_DEVICE(0x0471, 0x0311) }, { USB_DEVICE(0x0471, 0x0312) }, - { USB_DEVICE(0x069A, 0x0001) }, - { USB_DEVICE(0x046D, 0x08b0) }, - { USB_DEVICE(0x055D, 0x9000) }, + { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ + { USB_DEVICE(0x046D, 0x08b0) }, /* Logitech QuickCam Pro 3000 */ + { USB_DEVICE(0x046D, 0x08b1) }, /* Logitech QuickCam for Notebooks */ + { USB_DEVICE(0x046D, 0x08b2) }, /* Logitech QuickCam Pro 4000 */ + { USB_DEVICE(0x046D, 0x08b3) }, /* Logitech QuickCam Zoom */ + { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */ { USB_DEVICE(0x055D, 0x9001) }, - { USB_DEVICE(0x041E, 0x400C) }, - { USB_DEVICE(0x04CC, 0x8116) }, + { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ + { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ + { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */ + { USB_DEVICE(0x0d81, 0x1900) }, { } }; MODULE_DEVICE_TABLE(usb, pwc_device_table); @@ -106,7 +110,7 @@ static int default_mbufs = 2; /* Default number of mmap() buffers */ int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX; static int power_save = 0; -static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */ +static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */ static struct { int type; @@ -167,7 +171,7 @@ succeeded. The pwc_device struct links back to both structures. When a device is unplugged while in use it will be removed from the - list of known USB devices; I also de-register as a V4L device, but + list of known USB devices; I also de-register it as a V4L device, but unfortunately I can't free the memory since the struct is still in use by the file descriptor. This free-ing is then deferend until the first opportunity. Crude, but it works. @@ -240,7 +244,7 @@ int i; void *kbuf; - Trace(TRACE_MEMORY, "Entering allocate_buffers(%p).\n", pdev); + Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); if (pdev == NULL) return -ENXIO; @@ -315,7 +319,9 @@ for (; i < MAX_IMAGES; i++) pdev->image_ptr[i] = NULL; - Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n"); + kbuf = NULL; + + Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); return 0; } @@ -369,6 +375,7 @@ rvfree(pdev->image_data, default_mbufs * pdev->len_per_image); } pdev->image_data = NULL; + Trace(TRACE_MEMORY, "Leaving free_buffers().\n"); } @@ -570,12 +577,10 @@ pdev->fill_image = (pdev->fill_image + 1) % default_mbufs; } -/* 2001-10-14: The YUV420 is still there, but you can only set it from within - a program (YUV420P being the default) */ +/* 2002-10-11: YUV420P is the only palette remaining. */ static int pwc_set_palette(struct pwc_device *pdev, int pal) { - if ( pal == VIDEO_PALETTE_YUV420 - || pal == VIDEO_PALETTE_YUV420P + if ( pal == VIDEO_PALETTE_YUV420P #if PWC_DEBUG || pal == VIDEO_PALETTE_RAW #endif @@ -613,7 +618,7 @@ } #endif if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - Trace(TRACE_OPEN, "pwc_isoc_handler(): URB unlinked.\n"); + Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); return; } if (urb->status != -EINPROGRESS && urb->status != 0) { @@ -686,9 +691,22 @@ #if PWC_DEBUG Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); #endif - pdev->drop_frames = 2; + pdev->drop_frames += 2; pdev->vframes_error++; } + if ((ptr[0] ^ pdev->vmirror) & 0x01) { + if (ptr[0] & 0x01) + Info("Snapshot button pressed.\n"); + else + Info("Snapshot button released.\n"); + } + if ((ptr[0] ^ pdev->vmirror) & 0x02) { + if (ptr[0] & 0x02) + Info("Image is mirrored.\n"); + else + Info("Image is normal.\n"); + } + pdev->vmirror = ptr[0] & 0x03; /* Sometimes the trailer of the 730 is still sent as a 4 byte packet after a short frame; this condition is filtered out specifically. A 4 byte frame doesn't make sense anyway. @@ -705,7 +723,7 @@ /* In case we were instructed to drop the frame, do so silently. The buffer pointers are not updated either (but the counters are reset below). */ - if (pdev->drop_frames) + if (pdev->drop_frames > 0) pdev->drop_frames--; else { /* Check for underflow first */ @@ -741,17 +759,23 @@ } /* .. flen < last_packet_size */ pdev->vlast_packet_size = flen; } /* ..status == 0 */ -#ifdef PWC_DEBUG +#if PWC_DEBUG /* This is normally not interesting to the user, unless you are really debugging something */ - else - Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); + else { + static int iso_error = 0; + iso_error++; + if (iso_error < 20) + Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); + } #endif } if (awake) wake_up_interruptible(&pdev->frameq); urb->dev = pdev->udev; - usb_submit_urb(urb, GFP_ATOMIC); + i = usb_submit_urb(urb, GFP_ATOMIC); + if (i != 0) + Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i); } @@ -762,7 +786,6 @@ int i, j, ret; struct usb_host_interface *idesc; - int cur_alt; if (pdev == NULL) return -EFAULT; @@ -770,12 +793,11 @@ return 0; pdev->vsync = 0; udev = pdev->udev; - + /* Get the current alternate interface, adjust packet size */ if (!udev->actconfig) return -EFAULT; - cur_alt = udev->actconfig->interface[0].act_altsetting; - idesc = &udev->actconfig->interface[0].altsetting[cur_alt]; + idesc = &udev->actconfig->interface[0].altsetting[pdev->valternate]; if (!idesc) return -EFAULT; @@ -792,7 +814,13 @@ return -ENFILE; /* Odd error, that should be noticable */ } + /* Set alternate interface */ ret = 0; + Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate); + ret = usb_set_interface(pdev->udev, 0, pdev->valternate); + if (ret < 0) + return ret; + for (i = 0; i < MAX_ISO_BUFS; i++) { urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); if (urb == NULL) { @@ -801,6 +829,7 @@ break; } pdev->sbuf[i].urb = urb; + Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb); } if (ret) { /* De-allocate in reverse order */ @@ -812,8 +841,7 @@ } return ret; } - - + /* init URB structure */ for (i = 0; i < MAX_ISO_BUFS; i++) { urb = pdev->sbuf[i].urb; @@ -829,7 +857,7 @@ urb->start_frame = 0; urb->number_of_packets = ISO_FRAMES_PER_DESC; for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { - urb->iso_frame_desc[j].offset = j * pdev->vmax_packet_size; + urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; urb->iso_frame_desc[j].length = pdev->vmax_packet_size; } } @@ -840,11 +868,12 @@ if (ret) Err("isoc_init() submit_urb %d failed with error %d\n", i, ret); else - Trace(TRACE_OPEN, "pwc_isoc_init(): URB submitted.\n"); + Trace(TRACE_OPEN, "URB 0x%p submitted.\n", pdev->sbuf[i].urb); } - /* data should stream in now */ + /* All is done... */ pdev->iso_init = 1; + Trace(TRACE_OPEN, "<< pwc_isoc_init()\n"); return 0; } @@ -852,21 +881,34 @@ { int i; + Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n"); if (pdev == NULL) return; - if (!pdev->iso_init) - return; + + /* Unlinking ISOC buffers one by one */ + for (i = 0; i < MAX_ISO_BUFS; i++) { + struct urb *urb; + + urb = pdev->sbuf[i].urb; + if (urb != 0) { + if (pdev->iso_init) { + Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb); + usb_unlink_urb(urb); + } + Trace(TRACE_MEMORY, "Freeing URB\n"); + usb_free_urb(urb); + pdev->sbuf[i].urb = NULL; + } + } + /* Stop camera, but only if we are sure the camera is still there */ - if (!pdev->unplugged) + if (!pdev->unplugged) { + Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); usb_set_interface(pdev->udev, 0, 0); - /* Unlinking ISOC buffers one by one */ - for (i = MAX_ISO_BUFS - 1; i >= 0; i--) { - //pdev->sbuf[i].urb->next = NULL; - usb_unlink_urb(pdev->sbuf[i].urb); - usb_free_urb(pdev->sbuf[i].urb); - pdev->sbuf[i].urb = NULL; } + pdev->iso_init = 0; + Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n"); } int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) @@ -881,11 +923,10 @@ ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); if (ret) /* That failed... restore old mode (we know that worked) */ ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); - else /* Set (new) alternate interface */ - ret = usb_set_interface(pdev->udev, 0, pdev->valternate); if (!ret) - ret = pwc_isoc_init(pdev); - pdev->drop_frames = 1; /* try to avoid garbage during switch */ + if (pwc_isoc_init(pdev) < 0) + Info("Failed to restart ISOC transfer in pwc_try_video_mode.\n"); + pdev->drop_frames++; /* try to avoid garbage during switch */ return ret; } @@ -921,7 +962,7 @@ struct video_device *vdev = video_devdata(file); struct pwc_device *pdev; - Trace(TRACE_OPEN, "video_open called(0x%p).\n", vdev); + Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); pdev = (struct pwc_device *)vdev->priv; if (pdev == NULL) @@ -932,10 +973,30 @@ down(&pdev->modlock); if (!pdev->usb_init) { Trace(TRACE_OPEN, "Doing first time initialization.\n"); - /* Reset camera */ - if (usb_set_interface(pdev->udev, 0, 0)) - Info("Failed to set alternate interface to 0.\n"); pdev->usb_init = 1; + + if (pwc_trace & TRACE_OPEN) { + /* Query CMOS sensor type */ + const char *sensor_type = NULL; + + i = pwc_get_cmos_sensor(pdev); + switch(i) { + case -1: /* Unknown, show nothing */; break; + case 0x00: sensor_type = "Hyundai CMOS sensor"; break; + case 0x20: sensor_type = "Sony CCD sensor + TDA8787"; break; + case 0x2E: sensor_type = "Sony CCD sensor + Exas 98L59"; break; + case 0x2F: sensor_type = "Sony CCD sensor + ADI 9804"; break; + case 0x30: sensor_type = "Sharp CCD sensor + TDA8787"; break; + case 0x3E: sensor_type = "Sharp CCD sensor + Exas 98L59"; break; + case 0x3F: sensor_type = "Sharp CCD sensor + ADI 9804"; break; + case 0x40: sensor_type = "UPA 1021 sensor"; break; + case 0x100: sensor_type = "VGA sensor"; break; + case 0x101: sensor_type = "PAL MR sensor"; break; + default: sensor_type = "unknown type of sensor"; break; + } + if (sensor_type != NULL) + Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i); + } } /* Turn on camera */ @@ -1000,12 +1061,6 @@ return i; } - i = usb_set_interface(pdev->udev, 0, pdev->valternate); - if (i) { - Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i); - up(&pdev->modlock); - return -EINVAL; - } i = pwc_isoc_init(pdev); if (i) { Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); @@ -1023,7 +1078,7 @@ if (pdev->decompressor != NULL) pdev->decompressor->lock(); up(&pdev->modlock); - Trace(TRACE_OPEN, "video_open() returning 0.\n"); + Trace(TRACE_OPEN, "<< video_open() returns 0.\n"); return 0; } @@ -1034,15 +1089,12 @@ struct pwc_device *pdev; int i; - Trace(TRACE_OPEN, "video_close called(0x%p).\n", vdev); + Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev); pdev = (struct pwc_device *)vdev->priv; if (pdev->vopen == 0) Info("video_close() called on closed device?\n"); - /* Free isoc URBs */ - pwc_isoc_cleanup(pdev); - /* Dump statistics, but only if a reasonable amount of frames were processed (to prevent endless log-entries in case of snap-shot programs) @@ -1050,15 +1102,14 @@ if (pdev->vframe_count > 20) Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error); - if (!pdev->unplugged) { - /* Normal close: stop isochronuous and interrupt endpoint */ - Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n"); - usb_set_interface(pdev->udev, 0, 0); + /* Free isoc URBs, stop camera */ + pwc_isoc_cleanup(pdev); + if (!pdev->unplugged) { /* Turn LEDs off */ if (pwc_set_leds(pdev, 0, 0) < 0) - Info("Failed to set LED on/off time..\n"); - /* Power down camere to save energy */ + Info("Failed to set LED on/off time.\n"); + /* Power down camera to save energy */ if (power_save) { i = pwc_camera_power(pdev, 0); if (i < 0) @@ -1077,6 +1128,7 @@ if (pdev->unplugged) wake_up(&pdev->remove_ok); file->private_data = NULL; + Trace(TRACE_OPEN, "<< video_close()\n"); return 0; } @@ -1514,7 +1566,6 @@ Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size); pdev = vdev->priv; - /* FIXME - audit mmap during a read */ pos = (unsigned long)pdev->image_data; while (size > 0) { page = kvirt_to_pa(pos); @@ -1547,14 +1598,14 @@ int vendor_id, product_id, type_id; int i, hint; int video_nr = -1; /* default: use next available device */ - char serial_number[30]; + char serial_number[30], *name; free_mem_leak(); /* Check if we can handle this device */ - Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", - udev->descriptor.idVendor, udev->descriptor.idProduct, - intf->altsetting->desc.bInterfaceNumber); + Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", + udev->descriptor.idVendor, udev->descriptor.idProduct, + intf->altsetting->desc.bInterfaceNumber); /* the interfaces are probed one by one. We are only interested in the video interface (0) now. @@ -1570,38 +1621,47 @@ switch (product_id) { case 0x0302: Info("Philips PCA645VC USB webcam detected.\n"); + name = "Philips 645 webcam"; type_id = 645; break; case 0x0303: Info("Philips PCA646VC USB webcam detected.\n"); + name = "Philips 646 webcam"; type_id = 646; break; case 0x0304: Info("Askey VC010 type 2 USB webcam detected.\n"); + name = "Askey VC010 webcam"; type_id = 646; break; case 0x0307: Info("Philips PCVC675K (Vesta) USB webcam detected.\n"); + name = "Philips 675 webcam"; type_id = 675; break; case 0x0308: Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n"); + name = "Philips 680 webcam"; type_id = 680; break; case 0x030C: Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n"); + name = "Philips 690 webcam"; type_id = 690; break; case 0x0310: Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n"); + name = "Philips 730 webcam"; type_id = 730; break; case 0x0311: Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n"); + name = "Philips 740 webcam"; type_id = 740; break; case 0x0312: Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n"); + name = "Philips 750 webcam"; type_id = 750; break; default: @@ -1613,6 +1673,7 @@ switch(product_id) { case 0x0001: Info("Askey VC010 type 1 USB webcam detected.\n"); + name = "Askey VC010 webcam"; type_id = 645; break; default: @@ -1623,9 +1684,25 @@ else if (vendor_id == 0x046d) { switch(product_id) { case 0x08b0: - Info("Logitech QuickCam 3000 Pro detected.\n"); + Info("Logitech QuickCam Pro 3000 USB webcam detected.\n"); + name = "Logitech QuickCam Pro 3000"; type_id = 730; - break; + break; + case 0x08b1: + Info("Logitech QuickCam for Noteboos USB webcam detected.\n"); + name = "Logitech QuickCam Notebook"; + type_id = 740; /* ?? unknown sensor */ + break; + case 0x08b2: + Info("Logitech QuickCam 4000 Pro USB webcam detected.\n"); + name = "Logitech QuickCam Pro 4000"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b3: + Info("Logitech QuickCam Zoom USB webcam detected.\n"); + name = "Logitech QuickCam Zoom"; + type_id = 740; /* ?? unknown sensor */ + break; default: return -ENODEV; break; @@ -1639,10 +1716,12 @@ switch(product_id) { case 0x9000: Info("Samsung MPC-C10 USB webcam detected.\n"); + name = "Samsung MPC-C10"; type_id = 675; break; case 0x9001: Info("Samsung MPC-C30 USB webcam detected.\n"); + name = "Samsung MPC-C30"; type_id = 675; break; default: @@ -1654,6 +1733,7 @@ switch(product_id) { case 0x400c: Info("Creative Labs Webcam 5 detected.\n"); + name = "Creative Labs Webcam 5"; type_id = 730; break; default: @@ -1664,7 +1744,8 @@ else if (vendor_id == 0x04cc) { switch(product_id) { case 0x8116: - Info("SOTEC CMS-001 USB webcam detected.\n"); + Info("Sotec Afina Eye USB webcam detected.\n"); + name = "Sotec Afina Eye"; type_id = 730; break; default: @@ -1672,7 +1753,25 @@ break; } } - else return -ENODEV; /* Not Philips, Askey, Logitech, Samsung, Creative or SOTEC, for sure. */ + else if (vendor_id == 0x0d81) { + switch(product_id) { + case 0x1900: + Info("Visionite VCS-UC300 USB webcam detected.\n"); + name = "Visionite VCS-UC300"; + type_id = 740; /* CCD sensor */ + break; + case 0x1910: + Info("Visionite VCS-UM100 USB webcam detected.\n"); + name = "Visionite VCS-UM100"; + type_id = 730; /* CMOS sensor */ + break; + default: + return -ENODEV; + break; + } + } + else + return -ENODEV; /* Not any of the know types; but the list keeps growing. */ memset(serial_number, 0, 30); usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29); @@ -1706,7 +1805,7 @@ return -ENOMEM; } memcpy(vdev, &pwc_template, sizeof(pwc_template)); - sprintf(vdev->name, "Philips %d webcam", pdev->type); + strcpy(vdev->name, name); SET_MODULE_OWNER(vdev); pdev->vdev = vdev; vdev->priv = pdev; @@ -1714,7 +1813,6 @@ pdev->release = udev->descriptor.bcdDevice; Trace(TRACE_PROBE, "Release: %04x\n", pdev->release); - /* Now search device_hint[] table for a match, so we can hint a node number. */ for (hint = 0; hint < MAX_DEV_HINTS; hint++) { if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) && @@ -1761,40 +1859,41 @@ dev_set_drvdata (&intf->dev, NULL); if (pdev == NULL) { Err("pwc_disconnect() Called without private pointer.\n"); - goto out_err; + goto disconnect_out; } if (pdev->udev == NULL) { Err("pwc_disconnect() already called for %p\n", pdev); - goto out_err; + goto disconnect_out; } if (pdev->udev != interface_to_usbdev(intf)) { Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); - goto out_err; + goto disconnect_out; } #ifdef PWC_MAGIC if (pdev->magic != PWC_MAGIC) { Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n"); - goto out_err; + goto disconnect_out; } -#endif - +#endif + pdev->unplugged = 1; if (pdev->vdev != NULL) { - video_unregister_device(pdev->vdev); + Trace(TRACE_PROBE, "Unregistering video device.\n"); + video_unregister_device(pdev->vdev); if (pdev->vopen) { Info("Disconnected while device/video is open!\n"); - + /* Wake up any processes that might be waiting for a frame, let them return an error condition */ wake_up(&pdev->frameq); - + /* Wait until we get a 'go' from _close(). This used to have a gigantic race condition, since we kfree() - stuff here, but we have to wait until close() - is finished. + stuff here, but we have to wait until close() + is finished. */ - + Trace(TRACE_PROBE, "Sleeping on remove_ok.\n"); add_wait_queue(&pdev->remove_ok, &wait); set_current_state(TASK_UNINTERRUPTIBLE); @@ -1808,26 +1907,25 @@ } else { /* Normal disconnect; remove from available devices */ - Trace(TRACE_PROBE, "Unregistering video device normally.\n"); kfree(pdev->vdev); pdev->vdev = NULL; } } +disconnect_out: /* search device_hint[] table if we occupy a slot, by any chance */ for (hint = 0; hint < MAX_DEV_HINTS; hint++) if (device_hint[hint].pdev == pdev) device_hint[hint].pdev = NULL; pdev->udev = NULL; -out_err: unlock_kernel(); kfree(pdev); } /* *grunt* We have to do atoi ourselves :-( */ -static int pwc_atoi(char *s) +static int pwc_atoi(const char *s) { int k = 0; @@ -1872,7 +1970,7 @@ MODULE_PARM(dev_hint, "0-10s"); MODULE_PARM_DESC(dev_hint, "Device node hints"); -MODULE_DESCRIPTION("Philips USB webcam driver"); +MODULE_DESCRIPTION("Philips & OEM USB webcam driver"); MODULE_AUTHOR("Nemosoft Unv. "); MODULE_LICENSE("GPL"); @@ -1882,11 +1980,12 @@ char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" }; Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n"); - Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30, the Creative WebCam 5 and the SOTEC CMS-001.\n"); + Info("Also supports the Askey VC010, various Logitech QuickCams, Samsung MPC-C10 and MPC-C30,\n"); + Info("the Creative WebCam 5, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); if (fps) { - if (fps < 5 || fps > 30) { - Err("Framerate out of bounds (5-30).\n"); + if (fps < 4 || fps > 30) { + Err("Framerate out of bounds (4-30).\n"); return -EINVAL; } default_fps = fps; @@ -1938,9 +2037,9 @@ if (power_save) Info("Enabling power save on open/close.\n"); if (leds[0] >= 0) - led_on = leds[0] / 100; + led_on = leds[0]; if (leds[1] >= 0) - led_off = leds[1] / 100; + led_off = leds[1]; /* Big device node whoopla. Basicly, it allows you to assign a device node (/dev/videoX) to a camera, based on its type @@ -1999,7 +2098,7 @@ device_hint[i].serial_number[k] = '\0'; } } -#ifdef PWC_DEBUG +#if PWC_DEBUG Debug("device_hint[%d]:\n", i); Debug(" type : %d\n", device_hint[i].type); Debug(" serial# : %s\n", device_hint[i].serial_number); diff -Nru a/drivers/usb/media/pwc-misc.c b/drivers/usb/media/pwc-misc.c --- a/drivers/usb/media/pwc-misc.c Wed Nov 27 14:36:29 2002 +++ b/drivers/usb/media/pwc-misc.c Wed Nov 27 14:36:29 2002 @@ -1,6 +1,6 @@ /* Linux driver for Philips webcam Various miscellaneous functions and tables. - (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl) + (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff -Nru a/drivers/usb/media/pwc-uncompress.c b/drivers/usb/media/pwc-uncompress.c --- a/drivers/usb/media/pwc-uncompress.c Wed Nov 27 14:36:30 2002 +++ b/drivers/usb/media/pwc-uncompress.c Wed Nov 27 14:36:30 2002 @@ -1,6 +1,6 @@ /* Linux driver for Philips webcam Decompression frontend. - (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl) + (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl) 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 @@ -77,7 +77,7 @@ { struct pwc_frame_buf *fbuf; int n, line, col, stride; - void *yuv, *image, *dst; + void *yuv, *image; u16 *src; u16 *dsty, *dstu, *dstv; @@ -114,19 +114,6 @@ to get the desired output format/size. */ switch (pdev->vpalette) { - case VIDEO_PALETTE_YUV420: - /* Calculate byte offsets per line in image & view */ - n = (pdev->image.x * 3) / 2; - col = (pdev->view.x * 3) / 2; - /* Offset into image */ - dst = image + (pdev->view.x * pdev->offset.y + pdev->offset.x) * 3 / 2; - for (line = 0; line < pdev->image.y; line++) { - memcpy(dst, yuv, n); - yuv += n; - dst += col; - } - break; - case VIDEO_PALETTE_YUV420P: /* * We do some byte shuffling here to go from the @@ -163,17 +150,20 @@ dstu += (stride >> 1); } break; + default: + Err("Unsupported palette!"); + break; } } else { /* Compressed; the decompressor routines will write the data - in interlaced or planar format immediately. + in planar format immediately. */ if (pdev->decompressor) pdev->decompressor->decompress( &pdev->image, &pdev->view, &pdev->offset, - yuv, image, - pdev->vpalette == VIDEO_PALETTE_YUV420P ? 1 : 0, + yuv, image, + 1, pdev->decompress_data, pdev->vbandlength); else return -ENXIO; /* No such device or address: missing decompressor */ diff -Nru a/drivers/usb/media/pwc-uncompress.h b/drivers/usb/media/pwc-uncompress.h --- a/drivers/usb/media/pwc-uncompress.h Wed Nov 27 14:36:28 2002 +++ b/drivers/usb/media/pwc-uncompress.h Wed Nov 27 14:36:28 2002 @@ -1,4 +1,4 @@ -/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl) +/* (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff -Nru a/drivers/usb/media/pwc.h b/drivers/usb/media/pwc.h --- a/drivers/usb/media/pwc.h Wed Nov 27 14:36:31 2002 +++ b/drivers/usb/media/pwc.h Wed Nov 27 14:36:31 2002 @@ -60,8 +60,8 @@ /* Version block */ #define PWC_MAJOR 8 -#define PWC_MINOR 7 -#define PWC_VERSION "8.7" +#define PWC_MINOR 9 +#define PWC_VERSION "8.9" #define PWC_NAME "pwc" /* Turn certain features on/off */ @@ -130,7 +130,7 @@ int vcinterface; /* video control interface */ int valternate; /* alternate interface needed */ int vframes, vsize; /* frames-per-second & size (see PSZ_*) */ - int vpalette; /* YUV, RGB24, RGB32, etc */ + int vpalette; /* YUV */ int vframe_count; /* received frames */ int vframes_dumped; /* counter for dumped frames */ int vframes_error; /* frames received in error */ @@ -140,7 +140,8 @@ int vbandlength; /* compressed band length; 0 is uncompressed */ char vsnapshot; /* snapshot mode */ char vsync; /* used by isoc handler */ - + char vmirror; /* for ToUCaM series */ + /* The image acquisition requires 3 to 4 steps: 1. data is gathered in short packets from the USB controller 2. data is synchronized and packed into a frame buffer diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c --- a/drivers/usb/media/vicam.c Wed Nov 27 14:36:28 2002 +++ b/drivers/usb/media/vicam.c Wed Nov 27 14:36:28 2002 @@ -1,7 +1,7 @@ /* * USB ViCam WebCam driver * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), - * John Tyner (fill in email address) + * John Tyner (jtyner@cs.ucr.edu) * * Supports 3COM HomeConnect PC Digital WebCam * @@ -29,7 +29,7 @@ * Andy Armstrong who reverse engineered the color encoding and * Pavel Machek and Chris Cheney who worked on reverse engineering the * camera controls and wrote the first generation driver. - * */ + */ #include #include @@ -51,19 +51,25 @@ #define DBG(fmn,args...) do {} while(0) #endif -/* Version Information */ -#define DRIVER_VERSION "v1.0" -#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org" -#define DRIVER_DESC "ViCam WebCam Driver" +#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org" +#define DRIVER_DESC "ViCam WebCam Driver" /* Define these values to match your device */ #define USB_VICAM_VENDOR_ID 0x04c1 #define USB_VICAM_PRODUCT_ID 0x009d -#define VICAM_BYTES_PER_PIXEL 3 -#define VICAM_MAX_READ_SIZE (512*242+128) -#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240) -#define VICAM_FRAMES 2 +#define VICAM_BYTES_PER_PIXEL 3 +#define VICAM_MAX_READ_SIZE (512*242+128) +#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240) +#define VICAM_FRAMES 2 + +#define VICAM_HEADER_SIZE 64 + +#define clamp( x, l, h ) max_t( __typeof__( x ), \ + ( l ), \ + min_t( __typeof__( x ), \ + ( h ), \ + ( x ) ) ) /* Not sure what all the bytes in these char * arrays do, but they're necessary to make @@ -408,7 +414,8 @@ struct video_device vdev; // v4l video device struct usb_device *udev; // usb device - struct semaphore busy_lock; // guard against SMP multithreading + /* guard against simultaneous accesses to the camera */ + struct semaphore cam_lock; int is_initialized; u8 open_count; @@ -424,17 +431,21 @@ static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id); static void vicam_disconnect(struct usb_interface *intf); static void read_frame(struct vicam_camera *cam, int framenum); +static void vicam_decode_color(const u8 *, u8 *); -static int -send_control_msg(struct usb_device *udev, u8 request, u16 value, u16 index, - unsigned char *cp, u16 size) +static int __send_control_msg(struct vicam_camera *cam, + u8 request, + u16 value, + u16 index, + unsigned char *cp, + u16 size) { int status; /* cp must be memory that has been allocated by kmalloc */ - status = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), + status = usb_control_msg(cam->udev, + usb_sndctrlpipe(cam->udev, 0), request, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, @@ -450,6 +461,22 @@ return status; } +static int send_control_msg(struct vicam_camera *cam, + u8 request, + u16 value, + u16 index, + unsigned char *cp, + u16 size) +{ + int status = -ENODEV; + down(&cam->cam_lock); + if (cam->udev) { + status = __send_control_msg(cam, request, value, + index, cp, size); + } + up(&cam->cam_lock); + return status; +} static int initialize_camera(struct vicam_camera *cam) { @@ -465,14 +492,13 @@ { .data = setup3, .size = sizeof(setup3) }, { .data = NULL, .size = 0 } }; - - struct usb_device *udev = cam->udev; + int err, i; for (i = 0, err = 0; firmware[i].data && !err; i++) { memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size); - err = send_control_msg(udev, 0xff, 0, 0, + err = send_control_msg(cam, 0xff, 0, 0, cam->cntrlbuf, firmware[i].size); } @@ -484,11 +510,11 @@ { int status; - if ((status = send_control_msg(cam->udev, 0x50, state, 0, NULL, 0)) < 0) + if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0) return status; if (state) { - send_control_msg(cam->udev, 0x55, 1, 0, NULL, 0); + send_control_msg(cam, 0x55, 1, 0, NULL, 0); } return 0; @@ -504,10 +530,6 @@ if (!cam) return -ENODEV; - /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) - return -EINTR; - switch (ioctlnr) { /* query capabilites */ case VIDIOCGCAP: @@ -694,6 +716,9 @@ DBG("VIDIOCSYNC: %d\n", frame); read_frame(cam, frame); + vicam_decode_color(cam->raw_image, + cam->framebuf + + frame * VICAM_MAX_FRAME_SIZE ); break; } @@ -724,7 +749,6 @@ break; } - up(&cam->busy_lock); return retval; } @@ -741,26 +765,25 @@ "vicam video_device improperly initialized"); } - if ( down_interruptible(&cam->busy_lock) ) - return -EINTR; + /* the videodev_lock held above us protects us from + * simultaneous opens...for now. we probably shouldn't + * rely on this fact forever. + */ if (cam->open_count > 0) { printk(KERN_INFO "vicam_open called on already opened camera"); - up(&cam->busy_lock); return -EBUSY; } cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); if (!cam->raw_image) { - up(&cam->busy_lock); return -ENOMEM; } cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); if (!cam->framebuf) { kfree(cam->raw_image); - up(&cam->busy_lock); return -ENOMEM; } @@ -768,7 +791,6 @@ if (!cam->cntrlbuf) { kfree(cam->raw_image); rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - up(&cam->busy_lock); return -ENOMEM; } @@ -785,8 +807,6 @@ cam->needsDummyRead = 1; cam->open_count++; - up(&cam->busy_lock); - file->private_data = cam; return 0; @@ -796,118 +816,105 @@ vicam_close(struct inode *inode, struct file *file) { struct vicam_camera *cam = file->private_data; + int open_count; + struct usb_device *udev; + DBG("close\n"); + + /* it's not the end of the world if + * we fail to turn the camera off. + */ + set_camera_power(cam, 0); kfree(cam->raw_image); rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); kfree(cam->cntrlbuf); + down(&cam->cam_lock); + cam->open_count--; + open_count = cam->open_count; + udev = cam->udev; + + up(&cam->cam_lock); + + if (!open_count && !udev) { + kfree(cam); + } return 0; } -inline int pin(int x) +static void vicam_decode_color(const u8 *data, u8 *rgb) { - return((x > 255) ? 255 : ((x < 0) ? 0 : x)); -} + /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB + * Copyright (C) 2002 Monroe Williams (monroe@pobox.com) + */ -inline void writepixel(char *rgb, int Y, int Cr, int Cb) -{ - Y = 1160 * (Y - 16); - - rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 ); - rgb[1] = pin( ( ( Y - ( 392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 ); - rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 ); -} - -#define DATA_HEADER_SIZE 64 - -// -------------------------------------------------------------------------------- -// vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB -// -// Copyright (C) 2002 Monroe Williams (monroe@pobox.com) -// -------------------------------------------------------------------------------- - -static void vicam_decode_color( char *data, char *rgb) -{ - int x,y; - int Cr, Cb; - int sign; - int prevX, nextX, prevY, nextY; - int skip; - unsigned char *src; - unsigned char *dst; + int i, prevY, nextY; prevY = 512; nextY = 512; - src = data + DATA_HEADER_SIZE; - dst = rgb; - - for(y = 1; y < 241; y += 2) - { - // even line - sign = 1; - prevX = 1; - nextX = 1; - - skip = 0; + data += VICAM_HEADER_SIZE; - dst = rgb + (y-1)*320*3; - - for(x = 0; x < 512; x++) - { - if(x == 512-1) - nextX = -1; - - Cr = sign * ((src[prevX] - src[0]) + (src[nextX] - src[0])) >> 1; - Cb = sign * ((src[prevY] - src[prevX + prevY]) + (src[prevY] - src[nextX + prevY]) + (src[nextY] - src[prevX + nextY]) + (src[nextY] - src[nextX + nextY])) >> 2; + for( i = 0; i < 240; i++, data += 512 ) { + const int y = ( i * 242 ) / 240; - writepixel( - dst + ((x*5)>>3)*3, - src[0] + (sign * (Cr >> 1)), - Cr, - Cb); + int j, prevX, nextX; + int Y, Cr, Cb; - src++; - sign *= -1; - prevX = -1; - } - - prevY = -512; - - if(y == (242 - 2)) + if ( y == 242 - 1 ) { nextY = -512; + } - // odd line - sign = 1; prevX = 1; nextX = 1; - skip = 0; + for ( j = 0; j < 320; j++, rgb += 3 ) { + const int x = ( j * 512 ) / 320; + const u8 * const src = &data[x]; - dst = rgb + (y)*320*3; - - for(x = 0; x < 512; x++) - { - if(x == 512-1) + if ( x == 512 - 1 ) { nextX = -1; - - Cr = sign * ((src[prevX + prevY] - src[prevY]) + (src[nextX + prevY] - src[prevY]) + (src[prevX + nextY] - src[nextY]) + (src[nextX + nextY] - src[nextY])) >> 2; - Cb = sign * ((src[0] - src[prevX]) + (src[0] - src[nextX])) >> 1; + } - writepixel( - dst + ((x * 5)>>3)*3, - src[0] - (sign * (Cb >> 1)), - Cr, - Cb); + Cr = ( src[prevX] - src[0] ) + + ( src[nextX] - src[0] ); + Cr /= 2; + + Cb = ( src[prevY] - src[prevX + prevY] ) + + ( src[prevY] - src[nextX + prevY] ) + + ( src[nextY] - src[prevX + nextY] ) + + ( src[nextY] - src[nextX + nextY] ); + Cb /= 4; + + Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 ); + + if ( i & 1 ) { + int Ct = Cr; + Cr = Cb; + Cb = Ct; + } + + if ( ( x ^ i ) & 1 ) { + Cr = -Cr; + Cb = -Cb; + } + + rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) + + 500 ) / 900, 0, 255 ); + rgb[1] = clamp( ( ( Y - ( 392 * Cb ) - + ( 813 * Cr ) ) + + 500 ) / 1000, 0, 255 ); + rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) + + 500 ) / 1300, 0, 255 ); - src++; - sign *= -1; prevX = -1; } + + prevY = -512; } } @@ -953,12 +960,18 @@ request[8] = 0; // bytes 9-15 do not seem to affect exposure or image quality - n = send_control_msg(cam->udev, 0x51, 0x80, 0, request, 16); + down(&cam->cam_lock); + + if (!cam->udev) { + goto done; + } + + n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16); if (n < 0) { printk(KERN_ERR " Problem sending frame capture control message"); - return; + goto done; } n = usb_bulk_msg(cam->udev, @@ -971,9 +984,8 @@ n); } - vicam_decode_color(cam->raw_image, - cam->framebuf + - framenum * VICAM_MAX_FRAME_SIZE ); + done: + up(&cam->cam_lock); } static int @@ -983,17 +995,16 @@ DBG("read %d bytes.\n", (int) count); - if ( down_interruptible(&cam->busy_lock) ) - return -EINTR; - if (*ppos >= VICAM_MAX_FRAME_SIZE) { *ppos = 0; - up(&cam->busy_lock); return 0; } if (*ppos == 0) { read_frame(cam, 0); + vicam_decode_color(cam->raw_image, + cam->framebuf + + 0 * VICAM_MAX_FRAME_SIZE); } count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos); @@ -1008,8 +1019,6 @@ *ppos = 0; } - up(&cam->busy_lock); - return count; } @@ -1034,10 +1043,6 @@ return -EINVAL; */ - /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) - return -EINTR; - pos = (unsigned long)cam->framebuf; while (size > 0) { page = kvirt_to_pa(pos); @@ -1052,8 +1057,6 @@ size = 0; } - up(&cam->busy_lock); - return 0; } @@ -1285,7 +1288,7 @@ cam->shutter_speed = 15; - init_MUTEX(&cam->busy_lock); + init_MUTEX(&cam->cam_lock); memcpy(&cam->vdev, &vicam_template, sizeof (vicam_template)); @@ -1312,17 +1315,43 @@ static void vicam_disconnect(struct usb_interface *intf) { + int open_count; struct vicam_camera *cam = dev_get_drvdata(&intf->dev); - dev_set_drvdata ( &intf->dev, NULL ); - - cam->udev = NULL; - + + /* we must unregister the device before taking its + * cam_lock. This is because the video open call + * holds the same lock as video unregister. if we + * unregister inside of the cam_lock and open also + * uses the cam_lock, we get deadlock. + */ + video_unregister_device(&cam->vdev); + /* stop the camera from being used */ + + down(&cam->cam_lock); + + /* mark the camera as gone */ + + cam->udev = NULL; + vicam_destroy_proc_entry(cam); - kfree(cam); + /* the only thing left to do is synchronize with + * our close/release function on who should release + * the camera memory. if there are any users using the + * camera, it's their job. if there are no users, + * it's ours. + */ + + open_count = cam->open_count; + + up(&cam->cam_lock); + + if (!open_count) { + kfree(cam); + } printk(KERN_DEBUG "ViCam-based WebCam disconnected\n"); } diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c --- a/drivers/usb/misc/tiglusb.c Wed Nov 27 14:36:27 2002 +++ b/drivers/usb/misc/tiglusb.c Wed Nov 27 14:36:27 2002 @@ -185,7 +185,7 @@ pipe = usb_rcvbulkpipe (s->dev, 1); result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read, - &bytes_read, HZ / (timeout / 10)); + &bytes_read, HZ * 10 / timeout); if (result == -ETIMEDOUT) { /* NAK */ ret = result; if (!bytes_read) { @@ -242,7 +242,7 @@ pipe = usb_sndbulkpipe (s->dev, 2); result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_write, - &bytes_written, HZ / (timeout / 10)); + &bytes_written, HZ * 10 / timeout); if (result == -ETIMEDOUT) { /* NAK */ warn ("tiglusb_write, NAK received."); @@ -453,6 +453,8 @@ if (ints[0] > 0) { timeout = ints[1]; } + if (!timeout) + timeout = TIMAXTIME; return 1; } @@ -494,6 +496,9 @@ info (DRIVER_DESC ", " DRIVER_VERSION); + if (!timeout) + timeout = TIMAXTIME; + return 0; } @@ -516,6 +521,6 @@ MODULE_LICENSE (DRIVER_LICENSE); MODULE_PARM (timeout, "i"); -MODULE_PARM_DESC (timeout, "Timeout (default=1.5 seconds)"); +MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)"); /* --------------------------------------------------------------------- */ diff -Nru a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig --- a/drivers/usb/serial/Kconfig Wed Nov 27 14:36:31 2002 +++ b/drivers/usb/serial/Kconfig Wed Nov 27 14:36:31 2002 @@ -400,5 +400,10 @@ The module will be called omninet.o. If you want to compile it as a module, say M here and read . +config USB_EZUSB + bool + depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT + default y + endmenu diff -Nru a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile --- a/drivers/usb/serial/Makefile Wed Nov 27 14:36:28 2002 +++ b/drivers/usb/serial/Makefile Wed Nov 27 14:36:28 2002 @@ -7,6 +7,7 @@ obj-$(CONFIG_USB_SERIAL) += usbserial.o usbserial-obj-$(CONFIG_USB_SERIAL_CONSOLE) += console.o +usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o @@ -29,9 +30,9 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o # Objects that export symbols. -export-objs := usb-serial.o +export-objs := usb-serial.o ezusb.o -usbserial-objs := usb-serial.o $(usbserial-obj-y) +usbserial-objs := usb-serial.o generic.o $(usbserial-obj-y) include $(TOPDIR)/Rules.make diff -Nru a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/serial/ezusb.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,67 @@ +/* + * EZ-USB specific functions used by some of the USB to Serial drivers. + * + * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + static int debug = 1; +#else + static int debug; +#endif + +#include "usb-serial.h" + +/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ +#define CPUCS_REG 0x7F92 + +int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest) +{ + int result; + unsigned char *transfer_buffer; + + /* dbg("ezusb_writememory %x, %d", address, length); */ + if (!serial->dev) { + dbg("%s - no physical device present, failing.", __FUNCTION__); + return -ENODEV; + } + + transfer_buffer = kmalloc (length, GFP_KERNEL); + if (!transfer_buffer) { + err("%s - kmalloc(%d) failed.", __FUNCTION__, length); + return -ENOMEM; + } + memcpy (transfer_buffer, data, length); + result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3*HZ); + kfree (transfer_buffer); + return result; +} + +int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit) +{ + int response; + dbg("%s - %d", __FUNCTION__, reset_bit); + response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0); + if (response < 0) { + err("%s- %d failed", __FUNCTION__, reset_bit); + } + return response; +} + + +EXPORT_SYMBOL(ezusb_writememory); +EXPORT_SYMBOL(ezusb_set_reset); + diff -Nru a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/serial/generic.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,304 @@ +/* + * USB Serial Converter Generic functions + * + * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + static int debug = 1; +#else + static int debug; +#endif + +#include "usb-serial.h" + + +#ifdef CONFIG_USB_SERIAL_GENERIC +static __u16 vendor = 0x05f9; +static __u16 product = 0xffff; + +MODULE_PARM(vendor, "h"); +MODULE_PARM_DESC(vendor, "User specified USB idVendor"); + +MODULE_PARM(product, "h"); +MODULE_PARM_DESC(product, "User specified USB idProduct"); + +static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ + +/* All of the device info needed for the Generic Serial Converter */ +struct usb_serial_device_type usb_serial_generic_device = { + .owner = THIS_MODULE, + .name = "Generic", + .id_table = generic_device_ids, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, + .shutdown = usb_serial_generic_shutdown, +}; +#endif + +int usb_serial_generic_register (int _debug) +{ + int retval = 0; + + debug = _debug; +#ifdef CONFIG_USB_SERIAL_GENERIC + generic_device_ids[0].idVendor = vendor; + generic_device_ids[0].idProduct = product; + generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; + + /* register our generic driver with ourselves */ + retval = usb_serial_register (&usb_serial_generic_device); +#endif + return retval; +} + +void usb_serial_generic_deregister (void) +{ +#ifdef CONFIG_USB_SERIAL_GENERIC + /* remove our generic driver */ + usb_serial_deregister (&usb_serial_generic_device); +#endif +} + +int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) +{ + struct usb_serial *serial = port->serial; + int result = 0; + + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; + + dbg("%s - port %d", __FUNCTION__, port->number); + + /* force low_latency on so that our tty_push actually forces the data through, + otherwise it is scheduled, and with high data rates (like with OHCI) data + can get lost. */ + if (port->tty) + port->tty->low_latency = 1; + + /* if we have a bulk interrupt, start reading from it */ + if (serial->num_bulk_in) { + /* Start reading from the device */ + usb_fill_bulk_urb (port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + ((serial->type->read_bulk_callback) ? + serial->type->read_bulk_callback : + usb_serial_generic_read_bulk_callback), + port); + result = usb_submit_urb(port->read_urb, GFP_KERNEL); + if (result) + err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); + } + + return result; +} + +static void generic_cleanup (struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (serial->dev) { + /* shutdown any bulk reads that might be going on */ + if (serial->num_bulk_out) + usb_unlink_urb (port->write_urb); + if (serial->num_bulk_in) + usb_unlink_urb (port->read_urb); + } +} + +void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp) +{ + dbg("%s - port %d", __FUNCTION__, port->number); + generic_cleanup (port); +} + +int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial *serial = port->serial; + int result; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (count == 0) { + dbg("%s - write request of 0 bytes", __FUNCTION__); + return (0); + } + + /* only do something if we have a bulk out endpoint */ + if (serial->num_bulk_out) { + if (port->write_urb->status == -EINPROGRESS) { + dbg("%s - already writing", __FUNCTION__); + return (0); + } + + count = (count > port->bulk_out_size) ? port->bulk_out_size : count; + + if (from_user) { + if (copy_from_user(port->write_urb->transfer_buffer, buf, count)) + return -EFAULT; + } + else { + memcpy (port->write_urb->transfer_buffer, buf, count); + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer); + + /* set up our urb */ + usb_fill_bulk_urb (port->write_urb, serial->dev, + usb_sndbulkpipe (serial->dev, + port->bulk_out_endpointAddress), + port->write_urb->transfer_buffer, count, + ((serial->type->write_bulk_callback) ? + serial->type->write_bulk_callback : + usb_serial_generic_write_bulk_callback), port); + + /* send the data out the bulk port */ + result = usb_submit_urb(port->write_urb, GFP_ATOMIC); + if (result) + err("%s - failed submitting write urb, error %d", __FUNCTION__, result); + else + result = count; + + return result; + } + + /* no bulk out, so return 0 bytes written */ + return (0); +} + +int usb_serial_generic_write_room (struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + int room = 0; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (serial->num_bulk_out) { + if (port->write_urb->status != -EINPROGRESS) + room = port->bulk_out_size; + } + + dbg("%s - returns %d", __FUNCTION__, room); + return (room); +} + +int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + int chars = 0; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (serial->num_bulk_out) { + if (port->write_urb->status == -EINPROGRESS) + chars = port->write_urb->transfer_buffer_length; + } + + dbg("%s - returns %d", __FUNCTION__, chars); + return (chars); +} + +void usb_serial_generic_read_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + int i; + int result; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!serial) { + dbg("%s - bad serial pointer, exiting", __FUNCTION__); + return; + } + + if (urb->status) { + dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); + return; + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + + tty = port->tty; + if (tty && urb->actual_length) { + for (i = 0; i < urb->actual_length ; ++i) { + /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ + if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + /* this doesn't actually push the data through unless tty->low_latency is set */ + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } + + /* Continue trying to always read */ + usb_fill_bulk_urb (port->read_urb, serial->dev, + usb_rcvbulkpipe (serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + ((serial->type->read_bulk_callback) ? + serial->type->read_bulk_callback : + usb_serial_generic_read_bulk_callback), port); + result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (result) + err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); +} + +void usb_serial_generic_write_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!serial) { + dbg("%s - bad serial pointer, exiting", __FUNCTION__); + return; + } + + if (urb->status) { + dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); + return; + } + + usb_serial_port_softint((void *)port); + + schedule_work(&port->work); +} + +void usb_serial_generic_shutdown (struct usb_serial *serial) +{ + int i; + + dbg("%s", __FUNCTION__); + + /* stop reads and writes on all ports */ + for (i=0; i < serial->num_ports; ++i) { + generic_cleanup (&serial->port[i]); + } +} + diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c --- a/drivers/usb/serial/ipaq.c Wed Nov 27 14:36:31 2002 +++ b/drivers/usb/serial/ipaq.c Wed Nov 27 14:36:31 2002 @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * (26/11/2002) ganesh + * Added insmod options to specify product and vendor id. + * Use modprobe ipaq vendor=0xfoo product=0xbar + * * (26/7/2002) ganesh * Fixed up broken error handling in ipaq_open. Retry the "kickstart" * packet much harder - this drastically reduces connection failures. @@ -63,10 +67,13 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.2" + +#define DRIVER_VERSION "v0.4" #define DRIVER_AUTHOR "Ganesh Varadarajan " #define DRIVER_DESC "USB Compaq iPAQ, HP Jornada, Casio EM500 driver" +static int product, vendor; + /* Function prototypes for an ipaq */ static int ipaq_open (struct usb_serial_port *port, struct file *filp); static void ipaq_close (struct usb_serial_port *port, struct file *filp); @@ -85,6 +92,8 @@ static struct usb_device_id ipaq_id_table [] = { + /* The first entry is a placeholder for the insmod-specified device */ + { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) }, { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_548_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) }, @@ -521,9 +530,14 @@ static int __init ipaq_init(void) { + spin_lock_init(&write_list_lock); usb_serial_register(&ipaq_device); - usb_register(&ipaq_driver); info(DRIVER_DESC " " DRIVER_VERSION); + if (vendor) { + ipaq_id_table[0].idVendor = vendor; + ipaq_id_table[0].idProduct = product; + } + usb_register(&ipaq_driver); return 0; } @@ -546,3 +560,8 @@ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); +MODULE_PARM(vendor, "h"); +MODULE_PARM_DESC(vendor, "User specified USB idVendor"); + +MODULE_PARM(product, "h"); +MODULE_PARM_DESC(product, "User specified USB idProduct"); diff -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c --- a/drivers/usb/serial/keyspan.c Wed Nov 27 14:36:27 2002 +++ b/drivers/usb/serial/keyspan.c Wed Nov 27 14:36:27 2002 @@ -346,7 +346,7 @@ if (this_urb->status == -EINPROGRESS) { if (this_urb->transfer_flags & URB_ASYNC_UNLINK) break; - if (jiffies - p_priv->tx_start_time[flip] < 10 * HZ) + if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ)) break; this_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(this_urb); diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c --- a/drivers/usb/serial/usb-serial.c Wed Nov 27 14:36:29 2002 +++ b/drivers/usb/serial/usb-serial.c Wed Nov 27 14:36:29 2002 @@ -345,41 +345,12 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.7" +#define DRIVER_VERSION "v1.8" #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" #define DRIVER_DESC "USB Serial Driver core" -/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */ -/* need to always compile these in, as some of the other devices use these functions as their own. */ -/* if a driver does not provide a function pointer, the generic function will be called. */ -int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); -int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); -static void generic_close (struct usb_serial_port *port, struct file *filp); -static int generic_write_room (struct usb_serial_port *port); -static int generic_chars_in_buffer (struct usb_serial_port *port); -static void generic_read_bulk_callback (struct urb *urb); -static void generic_write_bulk_callback (struct urb *urb); -static void generic_shutdown (struct usb_serial *serial); - #ifdef CONFIG_USB_SERIAL_GENERIC -static __u16 vendor = 0x05f9; -static __u16 product = 0xffff; - -static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ - -/* All of the device info needed for the Generic Serial Converter */ -static struct usb_serial_device_type generic_device = { - .owner = THIS_MODULE, - .name = "Generic", - .id_table = generic_device_ids, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = NUM_DONT_CARE, - .num_bulk_out = NUM_DONT_CARE, - .num_ports = 1, - .shutdown = generic_shutdown, -}; - /* we want to look at all devices, as the vendor/product id can change * depending on the command line argument */ static struct usb_device_id generic_serial_ids[] = { @@ -387,27 +358,6 @@ {} }; -static int generic_register (void) -{ - generic_device_ids[0].idVendor = vendor; - generic_device_ids[0].idProduct = product; - generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; - - /* register our generic driver with ourselves */ - return usb_serial_register (&generic_device); -} - -static void generic_deregister (void) -{ - /* remove our generic driver */ - usb_serial_deregister (&generic_device); -} - -#else - -static inline int generic_register (void) { return 0; } -static inline void generic_deregister (void) { } - #endif /* CONFIG_USB_SERIAL_GENERIC */ /* Driver structure we register with the USB core */ @@ -488,45 +438,6 @@ return; } -#ifdef USES_EZUSB_FUNCTIONS -/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ -#define CPUCS_REG 0x7F92 - -int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest) -{ - int result; - unsigned char *transfer_buffer; - - /* dbg("ezusb_writememory %x, %d", address, length); */ - if (!serial->dev) { - dbg("%s - no physical device present, failing.", __FUNCTION__); - return -ENODEV; - } - - transfer_buffer = kmalloc (length, GFP_KERNEL); - if (!transfer_buffer) { - err("%s - kmalloc(%d) failed.", __FUNCTION__, length); - return -ENOMEM; - } - memcpy (transfer_buffer, data, length); - result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3*HZ); - kfree (transfer_buffer); - return result; -} - -int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit) -{ - int response; - dbg("%s - %d", __FUNCTION__, reset_bit); - response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0); - if (response < 0) { - err("%s- %d failed", __FUNCTION__, reset_bit); - } - return response; -} - -#endif /* USES_EZUSB_FUNCTIONS */ - /***************************************************************************** * Driver tty interface functions *****************************************************************************/ @@ -593,7 +504,7 @@ if (port->serial->type->close) port->serial->type->close(port, filp); else - generic_close(port, filp); + usb_serial_generic_close(port, filp); port->open_count = 0; } @@ -672,7 +583,7 @@ if (serial->type->write_room) retval = serial->type->write_room(port); else - retval = generic_write_room(port); + retval = usb_serial_generic_write_room(port); exit: up (&port->sem); @@ -701,7 +612,7 @@ if (serial->type->chars_in_buffer) retval = serial->type->chars_in_buffer(port); else - retval = generic_chars_in_buffer(port); + retval = usb_serial_generic_chars_in_buffer(port); exit: up (&port->sem); @@ -844,7 +755,7 @@ if (serial->type->shutdown) serial->type->shutdown(serial); else - generic_shutdown(serial); + usb_serial_generic_shutdown(serial); } static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) @@ -889,235 +800,6 @@ return ((count < begin+length-off) ? count : begin+length-off); } -/***************************************************************************** - * generic devices specific driver functions - *****************************************************************************/ -int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) -{ - struct usb_serial *serial = port->serial; - int result = 0; - - if (port_paranoia_check (port, __FUNCTION__)) - return -ENODEV; - - dbg("%s - port %d", __FUNCTION__, port->number); - - /* force low_latency on so that our tty_push actually forces the data through, - otherwise it is scheduled, and with high data rates (like with OHCI) data - can get lost. */ - if (port->tty) - port->tty->low_latency = 1; - - /* if we have a bulk interrupt, start reading from it */ - if (serial->num_bulk_in) { - /* Start reading from the device */ - usb_fill_bulk_urb (port->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - ((serial->type->read_bulk_callback) ? - serial->type->read_bulk_callback : - generic_read_bulk_callback), - port); - result = usb_submit_urb(port->read_urb, GFP_KERNEL); - if (result) - err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); - } - - return result; -} - -static void generic_cleanup (struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - - dbg("%s - port %d", __FUNCTION__, port->number); - - if (serial->dev) { - /* shutdown any bulk reads that might be going on */ - if (serial->num_bulk_out) - usb_unlink_urb (port->write_urb); - if (serial->num_bulk_in) - usb_unlink_urb (port->read_urb); - } -} - -static void generic_close (struct usb_serial_port *port, struct file * filp) -{ - dbg("%s - port %d", __FUNCTION__, port->number); - generic_cleanup (port); -} - -int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) -{ - struct usb_serial *serial = port->serial; - int result; - - dbg("%s - port %d", __FUNCTION__, port->number); - - if (count == 0) { - dbg("%s - write request of 0 bytes", __FUNCTION__); - return (0); - } - - /* only do something if we have a bulk out endpoint */ - if (serial->num_bulk_out) { - if (port->write_urb->status == -EINPROGRESS) { - dbg("%s - already writing", __FUNCTION__); - return (0); - } - - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; - - if (from_user) { - if (copy_from_user(port->write_urb->transfer_buffer, buf, count)) - return -EFAULT; - } - else { - memcpy (port->write_urb->transfer_buffer, buf, count); - } - - usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer); - - /* set up our urb */ - usb_fill_bulk_urb (port->write_urb, serial->dev, - usb_sndbulkpipe (serial->dev, - port->bulk_out_endpointAddress), - port->write_urb->transfer_buffer, count, - ((serial->type->write_bulk_callback) ? - serial->type->write_bulk_callback : - generic_write_bulk_callback), port); - - /* send the data out the bulk port */ - result = usb_submit_urb(port->write_urb, GFP_ATOMIC); - if (result) - err("%s - failed submitting write urb, error %d", __FUNCTION__, result); - else - result = count; - - return result; - } - - /* no bulk out, so return 0 bytes written */ - return (0); -} - -static int generic_write_room (struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - int room = 0; - - dbg("%s - port %d", __FUNCTION__, port->number); - - if (serial->num_bulk_out) { - if (port->write_urb->status != -EINPROGRESS) - room = port->bulk_out_size; - } - - dbg("%s - returns %d", __FUNCTION__, room); - return (room); -} - -static int generic_chars_in_buffer (struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - int chars = 0; - - dbg("%s - port %d", __FUNCTION__, port->number); - - if (serial->num_bulk_out) { - if (port->write_urb->status == -EINPROGRESS) - chars = port->write_urb->transfer_buffer_length; - } - - dbg("%s - returns %d", __FUNCTION__, chars); - return (chars); -} - -static void generic_read_bulk_callback (struct urb *urb) -{ - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - struct tty_struct *tty; - unsigned char *data = urb->transfer_buffer; - int i; - int result; - - dbg("%s - port %d", __FUNCTION__, port->number); - - if (!serial) { - dbg("%s - bad serial pointer, exiting", __FUNCTION__); - return; - } - - if (urb->status) { - dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); - return; - } - - usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); - - tty = port->tty; - if (tty && urb->actual_length) { - for (i = 0; i < urb->actual_length ; ++i) { - /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ - if(tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(tty); - } - /* this doesn't actually push the data through unless tty->low_latency is set */ - tty_insert_flip_char(tty, data[i], 0); - } - tty_flip_buffer_push(tty); - } - - /* Continue trying to always read */ - usb_fill_bulk_urb (port->read_urb, serial->dev, - usb_rcvbulkpipe (serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - ((serial->type->read_bulk_callback) ? - serial->type->read_bulk_callback : - generic_read_bulk_callback), port); - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if (result) - err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); -} - -static void generic_write_bulk_callback (struct urb *urb) -{ - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - - dbg("%s - port %d", __FUNCTION__, port->number); - - if (!serial) { - dbg("%s - bad serial pointer, exiting", __FUNCTION__); - return; - } - - if (urb->status) { - dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); - return; - } - - usb_serial_port_softint((void *)port); - - schedule_work(&port->work); -} - -static void generic_shutdown (struct usb_serial *serial) -{ - int i; - - dbg("%s", __FUNCTION__); - - /* stop reads and writes on all ports */ - for (i=0; i < serial->num_ports; ++i) { - generic_cleanup (&serial->port[i]); - } -} - void usb_serial_port_softint(void *private) { struct usb_serial_port *port = (struct usb_serial_port *)private; @@ -1268,7 +950,6 @@ (dev->descriptor.idProduct == PL2303_PRODUCT_ID)) || ((dev->descriptor.idVendor == ATEN_VENDOR_ID) && (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) { - //if (ifnum == 1) { if (interface != &dev->actconfig->interface[0]) { /* check out the endpoints of the other interface*/ //interface = &dev->actconfig->interface[ifnum ^ 1]; @@ -1303,7 +984,7 @@ info("%s converter detected", type->name); #ifdef CONFIG_USB_SERIAL_GENERIC - if (type == &generic_device) { + if (type == &usb_serial_generic_device) { num_ports = num_bulk_out; if (num_ports == 0) { err("Generic device with no bulk out, not allowed."); @@ -1359,7 +1040,7 @@ port->bulk_in_buffer, buffer_size, ((serial->type->read_bulk_callback) ? serial->type->read_bulk_callback : - generic_read_bulk_callback), + usb_serial_generic_read_bulk_callback), port); } @@ -1385,7 +1066,7 @@ port->bulk_out_buffer, buffer_size, ((serial->type->write_bulk_callback) ? serial->type->write_bulk_callback : - generic_write_bulk_callback), + usb_serial_generic_write_bulk_callback), port); } @@ -1504,10 +1185,10 @@ port = &serial->port[i]; down (&port->sem); if (port->tty != NULL) { + port->tty->driver_data = NULL; while (port->open_count > 0) { __serial_close(port, NULL); } - port->tty->driver_data = NULL; } up (&port->sem); } @@ -1607,7 +1288,7 @@ } /* register the generic driver, if we should */ - result = generic_register(); + result = usb_serial_generic_register(debug); if (result < 0) { err("%s - registering generic driver failed", __FUNCTION__); goto exit; @@ -1637,7 +1318,7 @@ tty_unregister_driver(&serial_tty_driver); exit_generic: - generic_deregister(); + usb_serial_generic_deregister(); exit: err ("%s - returning with error %d", __FUNCTION__, result); @@ -1649,7 +1330,7 @@ { usb_serial_console_exit(); - generic_deregister(); + usb_serial_generic_deregister(); usb_deregister(&usb_serial_driver); tty_unregister_driver(&serial_tty_driver); @@ -1699,12 +1380,6 @@ EXPORT_SYMBOL(usb_serial_probe); EXPORT_SYMBOL(usb_serial_disconnect); EXPORT_SYMBOL(usb_serial_port_softint); -#ifdef USES_EZUSB_FUNCTIONS - EXPORT_SYMBOL(ezusb_writememory); - EXPORT_SYMBOL(ezusb_set_reset); -#endif - - /* Module information */ @@ -1714,11 +1389,3 @@ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); - -#ifdef CONFIG_USB_SERIAL_GENERIC -MODULE_PARM(vendor, "h"); -MODULE_PARM_DESC(vendor, "User specified USB idVendor"); - -MODULE_PARM(product, "h"); -MODULE_PARM_DESC(product, "User specified USB idProduct"); -#endif diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h --- a/drivers/usb/serial/usb-serial.h Wed Nov 27 14:36:32 2002 +++ b/drivers/usb/serial/usb-serial.h Wed Nov 27 14:36:32 2002 @@ -237,24 +237,8 @@ extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); extern void usb_serial_disconnect(struct usb_interface *iface); -/* determine if we should include the EzUSB loader functions */ -#undef USES_EZUSB_FUNCTIONS -#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE) - #define USES_EZUSB_FUNCTIONS -#endif -#if defined(CONFIG_USB_SERIAL_XIRCOM) || defined(CONFIG_USB_SERIAL_XIRCOM_MODULE) - #define USES_EZUSB_FUNCTIONS -#endif -#if defined(CONFIG_USB_SERIAL_KEYSPAN) || defined(CONFIG_USB_SERIAL_KEYSPAN_MODULE) - #define USES_EZUSB_FUNCTIONS -#endif -#if defined(CONFIG_USB_SERIAL_WHITEHEAT) || defined(CONFIG_USB_SERIAL_WHITEHEAT_MODULE) - #define USES_EZUSB_FUNCTIONS -#endif -#ifdef USES_EZUSB_FUNCTIONS extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest); extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); -#endif /* USB Serial console functions */ #ifdef CONFIG_USB_SERIAL_CONSOLE @@ -265,10 +249,20 @@ static inline void usb_serial_console_exit (void) { } #endif -/* Functions needed by the usb serial console code */ +/* Functions needed by other parts of the usbserial core */ extern struct usb_serial *usb_serial_get_by_minor (unsigned int minor); extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); extern int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); +extern int usb_serial_generic_write_room (struct usb_serial_port *port); +extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port); +extern void usb_serial_generic_read_bulk_callback (struct urb *urb); +extern void usb_serial_generic_write_bulk_callback (struct urb *urb); +extern void usb_serial_generic_shutdown (struct usb_serial *serial); +extern int usb_serial_generic_register (int debug); +extern void usb_serial_generic_deregister (void); + +extern struct usb_serial_device_type usb_serial_generic_device; /* Inline functions to check the sanity of a pointer that is passed to us */ static inline int serial_paranoia_check (struct usb_serial *serial, const char *function) diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c Wed Nov 27 14:36:28 2002 +++ b/drivers/usb/serial/visor.c Wed Nov 27 14:36:28 2002 @@ -186,6 +186,7 @@ { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) }, { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, @@ -209,6 +210,7 @@ { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, diff -Nru a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h --- a/drivers/usb/serial/visor.h Wed Nov 27 14:36:28 2002 +++ b/drivers/usb/serial/visor.h Wed Nov 27 14:36:28 2002 @@ -28,6 +28,7 @@ #define PALM_M125_ID 0x0040 #define PALM_M130_ID 0x0050 #define PALM_TUNGSTEN_T_ID 0x0060 +#define PALM_TUNGSTEN_Z_ID 0x0031 #define PALM_ZIRE_ID 0x0070 #define SONY_VENDOR_ID 0x054C diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c --- a/drivers/usb/serial/whiteheat.c Wed Nov 27 14:36:28 2002 +++ b/drivers/usb/serial/whiteheat.c Wed Nov 27 14:36:28 2002 @@ -202,10 +202,23 @@ #define THROTTLED 0x01 #define ACTUALLY_THROTTLED 0x02 +static int urb_pool_size = 8; + +struct whiteheat_urb_wrap { + struct list_head list; + struct urb *urb; +}; + struct whiteheat_private { spinlock_t lock; __u8 flags; __u8 mcr; + struct list_head rx_urbs_free; + struct list_head rx_urbs_submitted; + struct list_head rx_urb_q; + struct work_struct rx_work; + struct list_head tx_urbs_free; + struct list_head tx_urbs_submitted; }; @@ -215,6 +228,11 @@ static void command_port_write_callback(struct urb *urb); static void command_port_read_callback(struct urb *urb); +static int start_port_read(struct usb_serial_port *port); +static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head); +static struct list_head *list_first(struct list_head *head); +static void rx_data_softint(void *private); + static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize); static int firm_open(struct usb_serial_port *port); static int firm_close(struct usb_serial_port *port); @@ -330,6 +348,11 @@ __u8 command[2] = { WHITEHEAT_GET_HW_INFO, 0 }; __u8 result[sizeof(*hw_info) + 1]; int i; + int j; + struct urb *urb; + int buf_size; + struct whiteheat_urb_wrap *wrap; + struct list_head *tmp; command_port = &serial->port[COMMAND_PORT]; @@ -373,18 +396,80 @@ port = &serial->port[i]; info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); - if (info == NULL) - goto no_memory; + if (info == NULL) { + err("%s: Out of memory for port structures\n", serial->type->name); + goto no_private; + } spin_lock_init(&info->lock); info->flags = 0; info->mcr = 0; + INIT_WORK(&info->rx_work, rx_data_softint, port); + + INIT_LIST_HEAD(&info->rx_urbs_free); + INIT_LIST_HEAD(&info->rx_urbs_submitted); + INIT_LIST_HEAD(&info->rx_urb_q); + INIT_LIST_HEAD(&info->tx_urbs_free); + INIT_LIST_HEAD(&info->tx_urbs_submitted); + + for (j = 0; j < urb_pool_size; j++) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("No free urbs available"); + goto no_rx_urb; + } + buf_size = port->read_urb->transfer_buffer_length; + urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("Couldn't allocate urb buffer"); + goto no_rx_buf; + } + wrap = kmalloc(sizeof(*wrap), GFP_KERNEL); + if (!wrap) { + err("Couldn't allocate urb wrapper"); + goto no_rx_wrap; + } + usb_fill_bulk_urb(urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + urb->transfer_buffer, buf_size, + whiteheat_read_callback, port); + wrap->urb = urb; + list_add(&wrap->list, &info->rx_urbs_free); + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("No free urbs available"); + goto no_tx_urb; + } + buf_size = port->write_urb->transfer_buffer_length; + urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("Couldn't allocate urb buffer"); + goto no_tx_buf; + } + wrap = kmalloc(sizeof(*wrap), GFP_KERNEL); + if (!wrap) { + err("Couldn't allocate urb wrapper"); + goto no_tx_wrap; + } + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + urb->transfer_buffer, buf_size, + whiteheat_write_callback, port); + wrap->urb = urb; + list_add(&wrap->list, &info->tx_urbs_free); + } + port->private = info; } command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); - if (command_info == NULL) - goto no_memory; + if (command_info == NULL) { + err("%s: Out of memory for port structures\n", serial->type->name); + goto no_command_private; + } spin_lock_init(&command_info->lock); command_info->port_running = 0; @@ -402,12 +487,35 @@ err("%s: please contact support@connecttech.com\n", serial->type->name); return -ENODEV; -no_memory: - for (i--; i >= 0; i--) { +no_command_private: + for (i = serial->num_ports - 1; i >= 0; i--) { port = &serial->port[i]; - kfree(port->private); + info = port->private; + for (j = urb_pool_size - 1; j >= 0; j--) { + tmp = list_first(&info->tx_urbs_free); + list_del(tmp); + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + kfree(wrap); +no_tx_wrap: + kfree(urb->transfer_buffer); +no_tx_buf: + usb_free_urb(urb); +no_tx_urb: + tmp = list_first(&info->rx_urbs_free); + list_del(tmp); + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + kfree(wrap); +no_rx_wrap: + kfree(urb->transfer_buffer); +no_rx_buf: + usb_free_urb(urb); +no_rx_urb: + } + kfree(info); +no_private: } - err("%s: Out of memory for port structures\n", serial->type->name); return -ENOMEM; } @@ -416,6 +524,11 @@ { struct usb_serial_port *command_port; struct usb_serial_port *port; + struct whiteheat_private *info; + struct whiteheat_urb_wrap *wrap; + struct urb *urb; + struct list_head *tmp; + struct list_head *tmp2; int i; dbg("%s", __FUNCTION__); @@ -423,12 +536,27 @@ /* free up our private data for our command port */ command_port = &serial->port[COMMAND_PORT]; kfree (command_port->private); - command_port->private = NULL; for (i = 0; i < serial->num_ports; i++) { port = &serial->port[i]; - kfree(port->private); - port->private = NULL; + info = port->private; + list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) { + list_del(tmp); + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + kfree(wrap); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + } + list_for_each_safe(tmp, tmp2, &info->tx_urbs_free) { + list_del(tmp); + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + kfree(wrap); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + } + kfree(info); } return; @@ -446,6 +574,9 @@ if (retval) goto exit; + if (port->tty) + port->tty->low_latency = 1; + /* send an open port command */ retval = firm_open(port); if (retval) { @@ -469,8 +600,7 @@ usb_clear_halt(port->serial->dev, port->write_urb->pipe); /* Start reading from the device */ - port->read_urb->dev = port->serial->dev; - retval = usb_submit_urb(port->read_urb, GFP_KERNEL); + retval = start_port_read(port); if (retval) { err("%s - failed submitting read urb, error %d", __FUNCTION__, retval); firm_close(port); @@ -486,6 +616,13 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) { + struct whiteheat_private *info = port->private; + struct whiteheat_urb_wrap *wrap; + struct urb *urb; + struct list_head *tmp; + struct list_head *tmp2; + unsigned long flags; + dbg("%s - port %d", __FUNCTION__, port->number); /* filp is NULL when called from usb_serial_disconnect */ @@ -515,8 +652,26 @@ firm_close(port); /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); + spin_lock_irqsave(&info->lock, flags); + list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + usb_unlink_urb(urb); + list_del(tmp); + list_add(tmp, &info->rx_urbs_free); + } + list_for_each_safe(tmp, tmp2, &info->rx_urb_q) { + list_del(tmp); + list_add(tmp, &info->rx_urbs_free); + } + list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) { + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + usb_unlink_urb(urb); + list_del(tmp); + list_add(tmp, &info->tx_urbs_free); + } + spin_unlock_irqrestore(&info->lock, flags); stop_command_port(port->serial); @@ -527,7 +682,14 @@ static int whiteheat_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; + struct whiteheat_private *info = port->private; + struct whiteheat_urb_wrap *wrap; + struct urb *urb; int result; + int bytes; + int sent = 0; + unsigned long flags; + struct list_head *tmp; dbg("%s - port %d", __FUNCTION__, port->number); @@ -536,43 +698,65 @@ return (0); } - if (port->write_urb->status == -EINPROGRESS) { - dbg ("%s - already writing", __FUNCTION__); - return (0); - } - - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; + while (count) { + spin_lock_irqsave(&info->lock, flags); + if (list_empty(&info->tx_urbs_free)) { + spin_unlock_irqrestore(&info->lock, flags); + break; + } + tmp = list_first(&info->tx_urbs_free); + list_del(tmp); + spin_unlock_irqrestore(&info->lock, flags); - if (from_user) { - if (copy_from_user(port->write_urb->transfer_buffer, buf, count)) - return -EFAULT; - } - else { - memcpy (port->write_urb->transfer_buffer, buf, count); - } + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count; + if (from_user) { + if (copy_from_user(urb->transfer_buffer, buf + sent, bytes)) + return -EFAULT; + } else { + memcpy (urb->transfer_buffer, buf + sent, bytes); + } - usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer); + usb_serial_debug_data (__FILE__, __FUNCTION__, bytes, urb->transfer_buffer); - port->write_urb->dev = serial->dev; - port->write_urb->transfer_buffer_length = count; - result = usb_submit_urb(port->write_urb, GFP_ATOMIC); - if (result) - err("%s - failed submitting write urb, error %d", __FUNCTION__, result); - else - result = count; + urb->dev = serial->dev; + urb->transfer_buffer_length = bytes; + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) { + err("%s - failed submitting write urb, error %d", __FUNCTION__, result); + sent = result; + spin_lock_irqsave(&info->lock, flags); + list_add(tmp, &info->tx_urbs_free); + spin_unlock_irqrestore(&info->lock, flags); + break; + } else { + sent += bytes; + count -= bytes; + spin_lock_irqsave(&info->lock, flags); + list_add(tmp, &info->tx_urbs_submitted); + spin_unlock_irqrestore(&info->lock, flags); + } + } - return result; + return sent; } static int whiteheat_write_room(struct usb_serial_port *port) { + struct whiteheat_private *info = port->private; + struct list_head *tmp; int room = 0; + unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); - if (port->write_urb->status != -EINPROGRESS) - room = port->bulk_out_size; + spin_lock_irqsave(&info->lock, flags); + list_for_each(tmp, &info->tx_urbs_free) + room++; + spin_unlock_irqrestore(&info->lock, flags); + room *= port->bulk_out_size; dbg("%s - returns %d", __FUNCTION__, room); return (room); @@ -715,12 +899,20 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port) { + struct whiteheat_private *info = port->private; + struct list_head *tmp; + struct whiteheat_urb_wrap *wrap; int chars = 0; + unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); - if (port->write_urb->status == -EINPROGRESS) - chars = port->write_urb->transfer_buffer_length; + spin_lock_irqsave(&info->lock, flags); + list_for_each(tmp, &info->tx_urbs_submitted) { + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + chars += wrap->urb->transfer_buffer_length; + } + spin_unlock_irqrestore(&info->lock, flags); dbg ("%s - returns %d", __FUNCTION__, chars); return (chars); @@ -745,25 +937,19 @@ static void whiteheat_unthrottle (struct usb_serial_port *port) { struct whiteheat_private *info = (struct whiteheat_private *)port->private; - int result; + int actually_throttled; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&info->lock, flags); - - if (info->flags & ACTUALLY_THROTTLED) { - /* Continue trying to always read */ - port->read_urb->dev = port->serial->dev; - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if (result) - err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); - } - + actually_throttled = info->flags & ACTUALLY_THROTTLED; info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED); - spin_unlock_irqrestore(&info->lock, flags); + if (actually_throttled) + rx_data_softint(port); + return; } @@ -846,53 +1032,50 @@ { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - struct tty_struct *tty; + struct whiteheat_urb_wrap *wrap; unsigned char *data = urb->transfer_buffer; - int i; - int result; struct whiteheat_private *info = (struct whiteheat_private *)port->private; - unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); + spin_lock(&info->lock); + wrap = urb_to_wrap(urb, &info->rx_urbs_submitted); + if (!wrap) { + spin_unlock(&info->lock); + err("%s - Not my urb!", __FUNCTION__); + return; + } + list_del(&wrap->list); + spin_unlock(&info->lock); + if (!serial) { dbg("%s - bad serial pointer, exiting", __FUNCTION__); + spin_lock(&info->lock); + list_add(&wrap->list, &info->rx_urbs_free); + spin_unlock(&info->lock); return; } if (urb->status) { dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); + spin_lock(&info->lock); + list_add(&wrap->list, &info->rx_urbs_free); + spin_unlock(&info->lock); return; } usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); - tty = port->tty; - if (tty && urb->actual_length) { - for (i = 0; i < urb->actual_length ; ++i) { - /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ - if(tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(tty); - } - /* this doesn't actually push the data through unless tty->low_latency is set */ - tty_insert_flip_char(tty, data[i], 0); - } - tty_flip_buffer_push(tty); - } - - spin_lock_irqsave(&info->lock, flags); + spin_lock(&info->lock); + list_add_tail(&wrap->list, &info->rx_urb_q); if (info->flags & THROTTLED) { info->flags |= ACTUALLY_THROTTLED; - spin_unlock_irqrestore(&info->lock, flags); + spin_unlock(&info->lock); return; } - spin_unlock_irqrestore(&info->lock, flags); + spin_unlock(&info->lock); - /* Continue trying to always read */ - port->read_urb->dev = serial->dev; - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if (result) - err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); + schedule_work(&info->rx_work); } @@ -900,9 +1083,22 @@ { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + struct whiteheat_private *info = port->private; + struct whiteheat_urb_wrap *wrap; dbg("%s - port %d", __FUNCTION__, port->number); + spin_lock(&info->lock); + wrap = urb_to_wrap(urb, &info->tx_urbs_submitted); + if (!wrap) { + spin_unlock(&info->lock); + err("%s - Not my urb!", __FUNCTION__); + return; + } + list_del(&wrap->list); + list_add(&wrap->list, &info->tx_urbs_free); + spin_unlock(&info->lock); + if (!serial) { dbg("%s - bad serial pointer, exiting", __FUNCTION__); return; @@ -1176,6 +1372,122 @@ } +static int start_port_read(struct usb_serial_port *port) { + struct whiteheat_private *info = port->private; + struct whiteheat_urb_wrap *wrap; + struct urb *urb; + int retval = 0; + unsigned long flags; + struct list_head *tmp; + struct list_head *tmp2; + + spin_lock_irqsave(&info->lock, flags); + + list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) { + list_del(tmp); + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + urb->dev = port->serial->dev; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) { + list_add(tmp, &info->rx_urbs_free); + list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + usb_unlink_urb(urb); + list_del(tmp); + list_add(tmp, &info->rx_urbs_free); + } + break; + } + list_add(tmp, &info->rx_urbs_submitted); + } + + spin_unlock_irqrestore(&info->lock, flags); + + return retval; +} + + +static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head *head) { + struct whiteheat_urb_wrap *wrap; + struct list_head *tmp; + + list_for_each(tmp, head) { + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + if (wrap->urb == urb) + return wrap; + } + + return NULL; +} + + +static struct list_head *list_first(struct list_head *head) { + return head->next; +} + + +static void rx_data_softint(void *private) { + struct usb_serial_port *port = (struct usb_serial_port *)private; + struct whiteheat_private *info = port->private; + struct tty_struct *tty = port->tty; + struct whiteheat_urb_wrap *wrap; + struct urb *urb; + unsigned long flags; + struct list_head *tmp; + struct list_head *tmp2; + int result; + int sent = 0; + + spin_lock_irqsave(&info->lock, flags); + if (info->flags & THROTTLED) { + spin_unlock_irqrestore(&info->lock, flags); + return; + } + + list_for_each_safe(tmp, tmp2, &info->rx_urb_q) { + list_del(tmp); + spin_unlock_irqrestore(&info->lock, flags); + + wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); + urb = wrap->urb; + + if (tty && urb->actual_length) { + if (urb->actual_length > TTY_FLIPBUF_SIZE - tty->flip.count) { + spin_lock_irqsave(&info->lock, flags); + list_add(tmp, &info->rx_urb_q); + spin_unlock_irqrestore(&info->lock, flags); + tty_flip_buffer_push(tty); + schedule_work(&info->rx_work); + return; + } + + memcpy(tty->flip.char_buf_ptr, urb->transfer_buffer, urb->actual_length); + tty->flip.char_buf_ptr += urb->actual_length; + tty->flip.count += urb->actual_length; + sent += urb->actual_length; + } + + urb->dev = port->serial->dev; + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) { + err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); + spin_lock_irqsave(&info->lock, flags); + list_add(tmp, &info->rx_urbs_free); + continue; + } + + spin_lock_irqsave(&info->lock, flags); + list_add(tmp, &info->rx_urbs_submitted); + } + spin_unlock_irqrestore(&info->lock, flags); + + if (sent) + tty_flip_buffer_push(tty); +} + + /***************************************************************************** * Connect Tech's White Heat module functions *****************************************************************************/ @@ -1203,6 +1515,9 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL"); + +MODULE_PARM(urb_pool_size, "i"); +MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug enabled or not"); diff -Nru a/drivers/video/68328fb.c b/drivers/video/68328fb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/video/68328fb.c Wed Nov 27 14:36:32 2002 @@ -0,0 +1,986 @@ +/* + * linux/arch/m68knommu/console/68328fb.c -- Low level implementation of the + * mc68328 LCD frame buffer device + * + * Copyright (C) 1998,1999 Kenneth Albanowski , + * The Silver Hammer Group, Ltd. + * + * + * This file is based on the Amiga CyberVision frame buffer device (Cyberfb.c): + * + * Copyright (C) 1996 Martin Apel + * Geert Uytterhoeven + * + * + * This file is based on the Amiga frame buffer device (amifb.c): + * + * Copyright (C) 1995 Geert Uytterhoeven + * + * + * History: + * - 17 Feb 98: Original version by Kenneth Albanowski + * + * + * 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. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include