Index: wli-2.6.10-rc3-1/Documentation/DMA-API.txt =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/DMA-API.txt 2004-12-22 09:07:07.674555170 -0800 +++ wli-2.6.10-rc3-1/Documentation/DMA-API.txt 2004-12-22 10:04:34.854504162 -0800 @@ -160,7 +160,7 @@ Checks to see if the mask is possible and updates the device parameters if it is. -Returns: 1 if successful and 0 if not +Returns: 0 if successful and a negative error if not. u64 dma_get_required_mask(struct device *dev) Index: wli-2.6.10-rc3-1/Documentation/arm/Sharp-LH/IOBarrier =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/arm/Sharp-LH/IOBarrier 2004-12-22 09:07:07.702550914 -0800 +++ wli-2.6.10-rc3-1/Documentation/arm/Sharp-LH/IOBarrier 2004-12-22 10:04:34.868502034 -0800 @@ -5,7 +5,7 @@ the signals that control access to some peripherals, most notably the SMC91C9111 ethernet controller, are not properly handled. -The symptom is that back to back IO with the peripheral returns +The symptom is that some back to back IO with the peripheral returns unreliable data. With the SMC chip, you'll see errors about the bank register being 'screwed'. @@ -13,20 +13,33 @@ for every memory access. It is driven through the CPLD from the CS7 line of the CPU's static memory controller which is optimized to eliminate unnecessary transitions. Yet, the SMC requires a transition -for every access. The Sharp website has more information on the -effect of this power conservation feature on peripheral interfacing. +for every write access. The Sharp website has more information about +the effect this power-conserving feature has on peripheral +interfacing. -The solution is to follow every access to the SMC chip with an access -to another memory region that will force the CPU to release the chip -select line. Note that it is important to guarantee that the access -will force the CPU off-chip. We map a page of SDRAM as if it were an -uncacheable IO device and read from it after every SMC IO operation. +The solution is to follow every write access to the SMC chip with an +access to another memory region that will force the CPU to release the +chip select line. It is important to guarantee that this access +forces the CPU off-chip. We map a page of SDRAM as if it were an +uncacheable IO device and read from it after every SMC IO write +operation. SMC IO BARRIER IO -You might be tempted to believe that we must access another device +Only this sequence is important. It does not matter that there is no +BARRIER IO before the access to the SMC chip because the AEN latch +only needs occurs after the SMC IO write cycle. The routines that +implement this work-around make an additional concession which is to +disable interrupts during the IO sequence. Other hardware devices +(the LogicPD CPLD) have registers in the same the physical memory +region as the SMC chip. An interrupt might allow an access to one of +those registers while SMC IO is being performed. + +You might be tempted to think that we have to access another device attached to the static memory controller, but the empirical evidence indicates that this is not so. Mapping 0x00000000 (flash) and 0xc0000000 (SDRAM) appear to have the same effect. Using SDRAM seems -to be faster. +to be faster. Choosing to access an undecoded memory region is not +desirable as there is no way to know how that chip select will be used +in the future. Index: wli-2.6.10-rc3-1/Documentation/dvb/README.dibusb =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/dvb/README.dibusb 2004-12-16 06:19:17.000000000 -0800 +++ wli-2.6.10-rc3-1/Documentation/dvb/README.dibusb 2004-12-22 10:04:34.875500970 -0800 @@ -1,43 +1,91 @@ +Documentation for dib3000mb frontend driver and dibusb device driver +==================================================================== +Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de), -Documentation for dib3000mb frontend driver and dibusb device driver +dibusb and dib3000mb/mc drivers based on GPL code, which has -The drivers should work with +Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) -- Twinhan VisionPlus VisionDTV USB-Ter DVB-T Device (VP7041) - http://www.twinhan.com/ +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, version 2. -- CTS Portable (Chinese Television System) - http://www.2cts.tv/ctsportable/ -- KWorld V-Stream XPERT DTV - DVB-T USB - http://www.kworld.com.tw/asp/pindex.asp?id=4&pid=13 +Supported devices USB1.1 +======================== + +Produced and reselled by Twinhan: +--------------------------------- +- TwinhanDTV USB-Ter DVB-T Device (VP7041) + http://www.twinhan.com/product_terrestrial_3.asp + +- TwinhanDTV Magic Box (VP7041e) + http://www.twinhan.com/product_terrestrial_4.asp - HAMA DVB-T USB device http://www.hama.de/portal/articleId*110620/action*2598 -- DiBcom USB DVB-T reference device +- CTS Portable (Chinese Television System) + http://www.2cts.tv/ctsportable/ -- Ultima Electronic/Artec T1 USB TVBOX - http://www.arteceuro.com/products-tvbox.html +- Unknown USB DVB-T device with vendor ID Hyper-Paltek -- Compro Videomate DVB-U2000 - DVB-T USB - http://www.comprousa.com/products/vmu2000.htm -- Unknown USB DVB-T device with vendor ID Hyper-Paltek +Produced and reselled by KWorld: +-------------------------------- +- KWorld V-Stream XPERT DTV DVB-T USB + http://www.kworld.com.tw/en/product/DVBT-USB/DVBT-USB.html + +- JetWay DTV DVB-T USB + http://www.jetway.com.tw/evisn/product/lcd-tv/DVT-USB/dtv-usb.htm + +- ADSTech Instant TV DVB-T USB + http://www.adstech.com/products/PTV-333/intro/PTV-333_intro.asp?pid=PTV-333 + + +Others: +------- +- Ultima Electronic/Artec T1 USB TVBOX (AN2135 and AN2235) + http://82.161.246.249/products-tvbox.html -Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de), +- Compro Videomate DVB-U2000 - DVB-T USB + http://www.comprousa.com/products/vmu2000.htm -both drivers based on GPL code, which has +- Grandtec USB DVB-T + http://www.grand.com.tw/ -Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) +- Avermedia AverTV DVBT USB + http://www.avermedia.com/ -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, version 2. +- DiBcom USB DVB-T reference device (non-public) -NEWS: +Supported devices USB2.0 +======================== +- Twinhan MagicBox II + http://www.twinhan.com/product_terrestrial_7.asp + +- Yakumo DVB-T mobile + http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T + +- DiBcom USB2.0 DVB-T reference device (non-public) + + +0. NEWS: + 2004-12-06 - possibility for demod i2c-address probing + - new usb IDs (Compro,Artec) + 2004-11-23 - merged changes from DiB3000MC_ver2.1 + - revised the debugging + - possibility to deliver the complete TS for USB2.0 + 2004-11-21 - first working version of the dib3000mc/p frontend driver. + 2004-11-12 - added additional remote control keys. Thanks to Uwe Hanke. + 2004-11-07 - added remote control support. Thanks to David Matthews. + 2004-11-05 - added support for a new devices (Grandtec/Avermedia/Artec) + - merged my changes (for dib3000mb/dibusb) to the FE_REFACTORING, because it became HEAD + - moved transfer control (pid filter, fifo control) from usb driver to frontend, it seems + better settled there (added xfer_ops-struct) + - created a common files for frontends (mc/p/mb) 2004-09-28 - added support for a new device (Unkown, vendor ID is Hyper-Paltek) 2004-09-20 - added support for a new device (Compro DVB-U2000), thanks to Amaury Demol for reporting @@ -49,7 +97,7 @@ (old news for vp7041.c) 2004-07-15 - found out, by accident, that the device has a TUA6010XS for - frequency generator + PLL 2004-07-12 - figured out, that the driver should also work with the CTS Portable (Chinese Television System) 2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working @@ -67,7 +115,7 @@ 1. How to use? NOTE: This driver was developed using Linux 2.6.6., -it is working with 2.6.7, 2.6.8.1. +it is working with 2.6.7, 2.6.8.1, 2.6.9 . Linux 2.4.x support is not planned, but patches are very welcome. @@ -81,8 +129,15 @@ You can either use "get_dvb_firmware dibusb" to download the firmware or you can get it directly via +for USB1.1 (AN2135) http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-5.0.0.11.fw?rev=1.1&content-type=text/plain +for USB1.1 (AN2235) (a few Artec T1 devices) +http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-an2235-1.fw?rev=1.1&content-type=text/plain + +for USB2.0 (FX2) +http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-6.0.0.5.fw?rev=1.1&content-type=text/plain + 1.2. Compiling Since the driver is in the linux kernel, activating the driver in @@ -94,15 +149,16 @@ Hotplug is able to load the driver, when it is needed (because you plugged in the device). -If you want to enable debug output, you have to load the driver manually. +If you want to enable debug output, you have to load the driver manually and +from withing the dvb-kernel cvs repository. first have a look, which debug level are available: -modinfo dvb-dibusb modinfo dib3000mb +modinfo dvb-dibusb -modprobe dvb-dibusb debug= modprobe dib3000mb debug= +modprobe dvb-dibusb debug= should do the trick. @@ -118,21 +174,17 @@ 2. Known problems and bugs TODO: -- remote control tasklet - signal-quality and strength calculations -- debug messages restructure -- i2c address probing -- 2.1. Adding support for devices It is not possible to determine the range of devices based on the DiBcom -reference design. This is because the reference design of DiBcom can be sold -to third persons, without telling DiBcom (so done with the Twinhan VP7041 and +reference designs. This is because the reference design of DiBcom can be sold +to thirds, without telling DiBcom (so done with the Twinhan VP7041 and the HAMA device). When you think you have a device like this and the driver does not recognizes it, -please send the ****load.inf and the ****cap.inf of the Windows driver to me. +please send the ****load*.inf and the ****cap*.inf of the Windows driver to me. Sometimes the Vendor or Product ID is identical to the ones of Twinhan, even though it is not a Twinhan device (e.g. HAMA), then please send me the name @@ -144,7 +196,29 @@ the linux-dvb mailing list, _after_ you have tried compiling and modprobing it. -2.2. Comments +2.2. USB1.1 Bandwidth limitation + +Most of the current supported devices are USB1.1 and thus they have a +maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub. +This is not enough for receiving the complete transport stream of a +DVB-T channel (which can be about 16 MBit/s). Normally this is not a +problem, if you only want to watch TV, but watching a channel while +recording another channel on the same frequency simply does not work. +This applies to all USB1.1 DVB-T devices. + +A special problem of the dibusb for the USB1.1 is, that the USB control +IC has a problem with write accesses while having MPEG2-streaming +enabled. When you set another pid while receiving MPEG2-TS it happens, that +the stream is disturbed and probably data is lost (results in distortions of +the video or strange beeps within the audio stream). DiBcom is preparing a +firmware especially for Linux which perhaps solves the problem. + +Especially VDR users are victoms of this bug. VDR frequently requests new PIDs +due the automatic scanning (introduced in 1.3.x, afaik) and epg-scan. Disabling +these features is maybe a solution. Additionally this behaviour of VDR exceeds +the USB1.1 bandwidth. + +2.3. Comments Patches, comments and suggestions are very very welcome @@ -153,6 +227,9 @@ providing specs, code and help, on which the dvb-dibusb and dib3000mb are based. + David Matthews for identifying a new device type (Artec T1 with AN2235) + and for extending dibusb with remote control event handling. Thank you. + Alex Woods for frequently answering question about usb and dvb stuff, a big thank you Index: wli-2.6.10-rc3-1/Documentation/dvb/cards.txt =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/dvb/cards.txt 2004-12-16 06:19:17.000000000 -0800 +++ wli-2.6.10-rc3-1/Documentation/dvb/cards.txt 2004-12-22 10:04:34.877500666 -0800 @@ -38,7 +38,7 @@ Comtech DVBT-6k07 (SP5730 PLL) (NxtWave Communications NXT6000 demodulator) - sp887x : Microtune 7202D - - dib3000mb : DiBcom 3000-MB Frontend + - dib3000mb : DiBcom 3000-MB demodulator DVB-S/C/T: - dst : TwinHan DST Frontend @@ -69,7 +69,17 @@ o DiBcom DVB-T USB based devices: - Twinhan VisionPlus VisionDTV USB-Ter DVB-T Device - - KWorld V-Stream XPERT DTV - DVB-T USB - HAMA DVB-T USB device + - CTS Portable (Chinese Television System) + - KWorld V-Stream XPERT DTV DVB-T USB + - JetWay DTV DVB-T USB + - ADSTech Instant TV DVB-T USB + - Ultima Electronic/Artec T1 USB TVBOX (AN2135 and AN2235) + - Compro Videomate DVB-U2000 - DVB-T USB + - Grandtec USB DVB-T + - Avermedia AverTV DVBT USB + - DiBcom USB DVB-T reference device (non-public) + - Yakumo DVB-T mobile USB2.0 + - DiBcom USB2.0 DVB-T reference device (non-public) o Experimental support for the analog module of the Siemens DVB-C PCI card Index: wli-2.6.10-rc3-1/Documentation/dvb/get_dvb_firmware =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/dvb/get_dvb_firmware 2004-12-16 06:19:17.000000000 -0800 +++ wli-2.6.10-rc3-1/Documentation/dvb/get_dvb_firmware 2004-12-22 10:04:34.880500210 -0800 @@ -21,7 +21,7 @@ use File::Temp qw/ tempdir /; use IO::Handle; -@components = ( "alps_tdlb7", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t", "dec2540t", "dec3000s", "vp7041", "dibusb" ); +@components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t", "dec2540t", "dec3000s", "vp7041", "dibusb" ); # Check args syntax() if (scalar(@ARGV) != 1); @@ -32,7 +32,7 @@ if ($cid eq $components[$i]) { $outfile = eval($cid); die $@ if $@; - print STDERR "Firmware $outfile extracted successfully. Now copy it to /usr/lib/hotplug/firmware/.\n"; + print STDERR "Firmware $outfile extracted successfully. Now copy it to either /lib/firmware or /usr/lib/hotplug/firmware/ (depending on your hotplug version).\n"; exit(0); } } @@ -47,11 +47,11 @@ # --------------------------------------------------------------- # Firmware-specific extraction subroutines -sub alps_tdlb7 { +sub sp8870 { my $sourcefile = "tt_Premium_217g.zip"; my $url = "http://www.technotrend.de/new/217g/$sourcefile"; my $hash = "53970ec17a538945a6d8cb608a7b3899"; - my $outfile = "dvb-fe-tdlb7.fw"; + my $outfile = "dvb-fe-sp8870.fw"; my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); checkstandard(); Index: wli-2.6.10-rc3-1/Documentation/ioctl/cdrom.txt =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/ioctl/cdrom.txt 2004-12-16 06:19:17.000000000 -0800 +++ wli-2.6.10-rc3-1/Documentation/ioctl/cdrom.txt 2004-12-22 10:04:34.886499298 -0800 @@ -34,7 +34,7 @@ (struct cdrom_multisession) CDROM_GET_MCN Obtain the "Universal Product Code" if available (struct cdrom_mcn) - CDROM_GET_UPC CDROM_GET_MCN (deprecated) + CDROM_GET_UPC Deprecated, use CDROM_GET_MCN instead. CDROMRESET hard-reset the drive CDROMVOLREAD Get the drive's volume setting (struct cdrom_volctrl) @@ -44,8 +44,8 @@ CDROMSEEK seek msf address CDROMPLAYBLK scsi-cd only, (struct cdrom_blk) CDROMREADALL read all 2646 bytes - CDROMGETSPINDOWN - CDROMSETSPINDOWN + CDROMGETSPINDOWN return 4-bit spindown value + CDROMSETSPINDOWN set 4-bit spindown value CDROMCLOSETRAY pendant of CDROMEJECT CDROM_SET_OPTIONS Set behavior options CDROM_CLEAR_OPTIONS Clear behavior options @@ -79,10 +79,12 @@ General: Unless otherwise specified, all ioctl calls return 0 on success - and -1 with errno set to an appropriate value on error. + and -1 with errno set to an appropriate value on error. (Some + ioctls return non-negative data values.) - Unless otherwise specified, all ioctl calls return EFAULT on a - failed attempt to copy data to or from user address space. + Unless otherwise specified, all ioctl calls return -1 and set + errno to EFAULT on a failed attempt to copy data to or from user + address space. Individual drivers may return error codes not listed here. @@ -136,6 +138,9 @@ ENOSYS cd drive not audio-capable. notes: + MSF stands for minutes-seconds-frames + LBA stands for logical block address + Segment is described as start and end times, where each time is described as minutes:seconds:frames. A frame is 1/75 of a second. @@ -196,8 +201,11 @@ error return: ENOSYS cd drive not audio-capable. EINVAL entry.cdte_format not CDROM_MSF or CDROM_LBA + EINVAL requested track out of bounds + EIO I/O error reading TOC notes: + TOC stands for Table Of Contents MSF stands for minutes-seconds-frames LBA stands for logical block address @@ -216,6 +224,10 @@ error return: ENOSYS cd drive not audio-capable. + notes: + Exact interpretation of this ioctl depends on the device, + but most seem to spin the drive down. + CDROMSTART Start the cdrom drive @@ -230,6 +242,11 @@ error return: ENOSYS cd drive not audio-capable. + notes: + Exact interpretation of this ioctl depends on the device, + but most seem to spin the drive up and/or close the tray. + Other devices ignore the ioctl completely. + CDROMEJECT Ejects the cdrom media @@ -241,9 +258,12 @@ outputs: none - error return: + error returns: ENOSYS cd drive not capable of ejecting - EBUSY other processes have drive open or door is locked + EBUSY other processes are accessing drive, or door is locked + + notes: + See CDROM_LOCKDOOR, below. @@ -257,9 +277,12 @@ outputs: none - error return: + error returns: ENOSYS cd drive not capable of ejecting - EBUSY other processes have drive open or door is locked + EBUSY other processes are accessing drive, or door is locked + + notes: + See CDROM_LOCKDOOR, below. @@ -577,7 +600,7 @@ inputs: New values for drive options. The logical 'or' of: - CDO_AUTO_CLOSE close tray on first open + CDO_AUTO_CLOSE close tray on first open(2) CDO_AUTO_EJECT open tray on last release CDO_USE_FFLAGS use O_NONBLOCK information on open CDO_LOCK lock tray on open files @@ -918,6 +941,10 @@ outputs: The next writable block. + notes: + If the device does not support this ioctl directly, the + ioctl will return CDROM_LAST_WRITTEN + 7. + CDROM_LAST_WRITTEN get last block written on disc @@ -925,11 +952,15 @@ usage: long last; - ioctl(fd, CDROM_NEXT_WRITABLE, &last); + ioctl(fd, CDROM_LAST_WRITTEN, &last); inputs: none outputs: The last block written on disc - + notes: + If the device does not support this ioctl directly, the + result is derived from the disc's table of contents. If the + table of contents can't be read, this ioctl returns an + error. Index: wli-2.6.10-rc3-1/Documentation/ioctl/hdio.txt =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/ioctl/hdio.txt 2004-12-16 06:19:17.000000000 -0800 +++ wli-2.6.10-rc3-1/Documentation/ioctl/hdio.txt 2004-12-22 10:04:34.893498234 -0800 @@ -28,7 +28,7 @@ HDIO_GET_IDENTITY get IDE identification info HDIO_GET_WCACHE get write cache mode on|off HDIO_GET_ACOUSTIC get acoustic value - HDIO_GET_ADDRESS + HDIO_GET_ADDRESS get sector addressing mode HDIO_GET_BUSSTATE get the bus state of the hwif HDIO_TRISTATE_HWIF execute a channel tristate HDIO_DRIVE_RESET execute a device reset @@ -55,8 +55,8 @@ HDIO_SET_QDMA change use-qdma flag HDIO_SET_ADDRESS change lba addressing modes - HDIO_SET_IDE_SCSI - HDIO_SET_SCSI_IDE + HDIO_SET_IDE_SCSI Set scsi emulation mode on/off + HDIO_SET_SCSI_IDE not implemented yet The information that follows was determined from reading kernel source @@ -73,8 +73,9 @@ Unless otherwise specified, all ioctl calls return 0 on success and -1 with errno set to an appropriate value on error. - Unless otherwise specified, all ioctl calls return EFAULT on a - failed attempt to copy data to or from user address space. + Unless otherwise specified, all ioctl calls return -1 and set + errno to EFAULT on a failed attempt to copy data to or from user + address space. Unless otherwise specified, all data structures and constants are defined in @@ -145,7 +146,7 @@ usage: - long val; + unsigned long val; ioctl(fd, HDIO_SET_UNMASKINTR, val); inputs: @@ -204,7 +205,7 @@ This is tightly woven into the driver->do_special can not touch. DON'T do it again until a total personality rewrite - is committed." + is committed. If blockmode has already been set, this ioctl will fail with EBUSY @@ -371,14 +372,12 @@ usage: - int nice; + unsigned long nice; ... ioctl(fd, HDIO_SET_NICE, nice); inputs: - args[0] io address to probe - args[1] control address to probe - args[2] irq number + bitmask of nice flags. outputs: none @@ -392,6 +391,9 @@ This ioctl sets the DSC_OVERLAP and NICE_1 flags from values provided by the user. + Nice flags are listed in , starting with + IDE_NICE_DSC_OVERLAP. These values represent shifts. + @@ -509,7 +511,7 @@ notes: - Aborts any current command, prevent anything else from being + Abort any current command, prevent anything else from being queued, execute a reset on the device, and issue BLKRRPART ioctl on the block device. @@ -523,6 +525,10 @@ Note: If you don't have a copy of the ANSI ATA specification handy, you should probably ignore this ioctl. + Execute an ATA disk command directly by writing the "taskfile" + registers of the drive. Requires ADMIN and RAWIO access + privileges. + usage: struct { @@ -541,27 +547,27 @@ (See below for details on memory area passed to ioctl.) - io_ports[] values to be written to taskfile registers - hob_ports[] values to be written to taskfile registers + io_ports[8] values to be written to taskfile registers + hob_ports[8] high-order bytes, for extended commands. out_flags flags indicating which registers are valid in_flags flags indicating which registers should be returned data_phase see below req_cmd command type to be executed out_size size of output buffer outbuf buffer of data to be transmitted to disk - inbuf buffer of data to be received from disk + inbuf buffer of data to be received from disk (see [1]) outputs: io_ports[] values returned in the taskfile registers - hob_ports[] values returned in the taskfile registers - out_flags flags indicating which registers are valid + hob_ports[] high-order bytes, for extended commands. + out_flags flags indicating which registers are valid (see [2]) in_flags flags indicating which registers should be returned - outbuf buffer of data to be transmitted to disk + outbuf buffer of data to be transmitted to disk (see [1]) inbuf buffer of data to be received from disk error returns: - EACCES CAP_SYS_ADMIN or CAP_SYS_RAWIO privelege not set. + EACCES CAP_SYS_ADMIN or CAP_SYS_RAWIO privilege not set. ENOMSG Device is not a disk drive. ENOMEM Unable to allocate memory for task EFAULT req_cmd == TASKFILE_IN_OUT (not implemented as of 2.6.8) @@ -571,9 +577,14 @@ notes: - Execute an ATA disk command directly by writing the "taskfile" - registers of the drive. Requires ADMIN and RAWIO access - privileges. + [1] Currently (2.6.8), both the input and output buffers are + copied from the user and written back to the user, even when + not used. This may be a bug. + + [2] The out_flags and in_flags are returned to the user after + the ioctl completes. Currently (2.6.8) these are the same + as the input values, unchanged. In the future, they may have + more significance. Extreme caution should be used with using this ioctl. A mistake can easily corrupt data or hang the system. @@ -590,7 +601,7 @@ hob_ports[8] high-order bytes, for extended commands out_flags flags indicating which entries in the io_ports[] and hob_ports[] arrays - contain valid values. + contain valid values. Type ide_reg_valid_t. in_flags flags indicating which entries in the io_ports[] and hob_ports[] arrays are expected to contain valid values @@ -600,8 +611,11 @@ out_size output (user->drive) buffer size, bytes in_size input (drive->user) buffer size, bytes - Unused fields of io_ports[] and hob_ports[] should be set to - zero. + This ioctl does not necessarily respect all flags in the + out_flags and in_flags values -- some taskfile registers + may be written or read even if not requested in the flags. + Unused fields of io_ports[] and hob_ports[] should be set + to zero. The data_phase field describes the data transfer to be performed. Value is one of: @@ -631,10 +645,6 @@ IDE_DRIVE_TASK_OUT IDE_DRIVE_TASK_RAW_WRITE - Currently (2.6.8), both the input and output buffers are - copied from the user and written back to the user, even when - not used. - @@ -666,11 +676,17 @@ args[0] status args[1] error args[2] NSECTOR + args[3] undefined + args[4+] NSECTOR * 512 bytes of data returned by the command. error returns: EACCES Access denied: requires CAP_SYS_RAWIO ENOMEM Unable to allocate memory for task + notes: + + Taskfile registers IDE_LCYL, IDE_HCYL, and IDE_SELECT are + set to zero before executing the command. Index: wli-2.6.10-rc3-1/Documentation/kernel-parameters.txt =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/kernel-parameters.txt 2004-12-16 06:19:17.000000000 -0800 +++ wli-2.6.10-rc3-1/Documentation/kernel-parameters.txt 2004-12-22 10:04:34.859503402 -0800 @@ -699,6 +699,9 @@ 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. + [IA-32] Use together with memmap= to avoid physical + address space collisions. Without memmap= PCI devices + could be placed at addresses belonging to unused RAM. mem=nopentium [BUGS=IA-32] Disable usage of 4MB pages for kernel memory. @@ -1269,11 +1272,6 @@ specialix= [HW,SERIAL] Specialix multi-serial port adapter See Documentation/specialix.txt. - 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. - spia_io_base= [HW,MTD] spia_fio_base= spia_pedr= Index: wli-2.6.10-rc3-1/Documentation/memory.txt =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/memory.txt 2004-12-22 09:07:07.688553042 -0800 +++ wli-2.6.10-rc3-1/Documentation/memory.txt 2004-12-22 10:04:34.861503098 -0800 @@ -21,6 +21,8 @@ All of these problems can be addressed with the "mem=XXXM" boot option (where XXX is the size of RAM to use in megabytes). It can also tell Linux to use less memory than is actually installed. +If you use "mem=" on a machine with PCI, consider using "memmap=" to avoid +physical address space collisions. See the documentation of your boot loader (LILO, loadlin, etc.) about how to pass options to the kernel. @@ -44,7 +46,9 @@ * Disabling the cache from the BIOS. * Try passing the "mem=4M" option to the kernel to limit - Linux to using a very small amount of memory. + Linux to using a very small amount of memory. Use "memmap="-option + together with "mem=" on systems with PCI to avoid physical address + space collisions. Other tricks: Index: wli-2.6.10-rc3-1/Documentation/rocket.txt =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/rocket.txt 2004-12-22 09:07:07.691552586 -0800 +++ wli-2.6.10-rc3-1/Documentation/rocket.txt 2004-12-22 10:04:34.865502490 -0800 @@ -20,8 +20,27 @@ into them. Installations instructions for the external module are in the included README and HW_INSTALL files. -RocketPort ISA and RocketModem II PCI boards are also supported by this -driver, but must use the external module driver for configuration reasons. +RocketPort ISA and RocketModem II PCI boards currently are only supported by +this driver in module form. + +The RocketPort ISA board requires I/O ports to be configured by the DIP +switches on the board. See the section "ISA Rocketport Boards" below for +information on how to set the DIP switches. + +You pass the I/O port to the driver using the following module parameters: + +board1 : I/O port for the first ISA board +board2 : I/O port for the second ISA board +board3 : I/O port for the third ISA board +board4 : I/O port for the fourth ISA board + +There is a set of utilities and scripts provided with the external driver +( downloadable from http://www.comtrol.com ) that ease the configuration and +setup of the ISA cards. + +The RocketModem II PCI boards require firmware to be loaded into the card +before it will function. The driver has only been tested as a module for this +board. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -55,12 +74,95 @@ >mknod /dev/ttyR1 c 46 1 >mknod /dev/ttyR2 c 46 2 -The Linux script MAKEDEV will create the first 16 ttyRx device names (nodes) for you: +The Linux script MAKEDEV will create the first 16 ttyRx device names (nodes) +for you: >/dev/MAKEDEV ttyR =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +ISA Rocketport Boards +--------------------- + +You must assign and configure the I/O addresses used by the ISA Rocketport +card before installing and using it. This is done by setting a set of DIP +switches on the Rocketport board. + + +SETTING THE I/O ADDRESS +----------------------- + +Before installing RocketPort(R) or RocketPort RA boards, you must find +a range of I/O addresses for it to use. The first RocketPort card +requires a 68-byte contiguous block of I/O addresses, starting at one +of the following: 0x100h, 0x140h, 0x180h, 0x200h, 0x240h, 0x280h, +0x300h, 0x340h, 0x380h. This I/O address must be reflected in the DIP +switiches of *all* of the Rocketport cards. + +The second, third, and fourth RocketPort cards require a 64-byte +contiguous block of I/O addresses, starting at one of the following +I/O addresses: 0x100h, 0x140h, 0x180h, 0x1C0h, 0x200h, 0x240h, 0x280h, +0x2C0h, 0x300h, 0x340h, 0x380h, 0x3C0h. The I/O address used by the +second, third, and fourth Rocketport cards (if present) are set via +software control. The DIP switch settings for the I/O address must be +set to the value of the first Rocketport cards. + +In order to destinguish each of the card from the others, each card +must have a unique board ID set on the dip switches. The first +Rocketport board must be set with the DIP switches corresponding to +the first board, the second board must be set with the DIP switches +corresponding to the second board, etc. IMPORTANT: The board ID is +the only place where the DIP switch settings should differ between the +various Rocketport boards in a system. + +The I/O address range used by any of the RocketPort cards must not +conflict with any other cards in the system, including other +RocketPort cards. Below, you will find a list of commonly used I/O +address ranges which may be in use by other devices in your system. +On a Linux system, "cat /proc/ioports" will also be helpful in +identifying what I/O addresses are being used by devics on your +system. + +Remember, the FIRST RocketPort uses 68 I/O addresses. So, if you set it +for 0x100, it will occupy 0x100 to 0x143. This would mean that you +CAN NOT set the second, third or fourth board for address 0x140 since +the first 4 bytes of that range are used by the first board. You would +need to set the second, third, or fourth board to one of the next available +blocks such as 0x180. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +RocketPort and RocketPort RA SW1 Settings: + + +-------------------------------+ + | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | + +-------+-------+---------------+ + | Unused| Card | I/O Port Block| + +-------------------------------+ + +DIP Switches DIP Switches +7 8 6 5 +=================== =================== +On On UNUSED, MUST BE ON. On On First Card <==== Default + On Off Second Card + Off On Third Card + Off Off Fourth Card + +DIP Switches I/O Address Range +4 3 2 1 Used by the First Card +===================================== +On Off On Off 100-143 +On Off Off On 140-183 +On Off Off Off 180-1C3 <==== Default +Off On On Off 200-243 +Off On Off On 240-283 +Off On Off Off 280-2C3 +Off Off On Off 300-343 +Off Off Off On 340-383 +Off Off Off Off 380-3C3 + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + REPORTING BUGS -------------- Index: wli-2.6.10-rc3-1/Documentation/scsi/ChangeLog.megaraid =================================================================== --- wli-2.6.10-rc3-1.orig/Documentation/scsi/ChangeLog.megaraid 2004-12-16 06:19:17.000000000 -0800 +++ wli-2.6.10-rc3-1/Documentation/scsi/ChangeLog.megaraid 2004-12-22 10:04:34.896497778 -0800 @@ -1,3 +1,10 @@ +Release Date : Thu Dec 9 19:02:14 EST 2004 - Sreenivas Bagalkote + +Current Version : 2.20.4.1 (scsi module), 2.20.2.3 (cmm module) +Older Version : 2.20.4.1 (scsi module), 2.20.2.2 (cmm module) + +i. Fix a bug in kioc's dma buffer deallocation + Release Date : Thu Nov 4 18:24:56 EST 2004 - Sreenivas Bagalkote Current Version : 2.20.4.1 (scsi module), 2.20.2.2 (cmm module) Index: wli-2.6.10-rc3-1/MAINTAINERS =================================================================== --- wli-2.6.10-rc3-1.orig/MAINTAINERS 2004-12-16 06:19:18.000000000 -0800 +++ wli-2.6.10-rc3-1/MAINTAINERS 2004-12-22 10:04:34.851504618 -0800 @@ -1731,6 +1731,12 @@ L: linux-net@vger.kernel.org S: Maintained +PHRAM MTD DRIVER +P: Jörn Engel +M: joern@wh.fh-wedel.de +L: linux-mtd@lists.infradead.org +S: Maintained + POSIX CLOCKS and TIMERS P: George Anzinger M: george@mvista.com @@ -2489,6 +2495,13 @@ L: sensors@stimpy.netroedge.com S: Maintained +W83L51xD SD/MMC CARD INTERFACE DRIVER +P: Pierre Ossman +M: drzeus-wbsd@drzeus.cx +L: wbsd-devel@list.drzeus.cx +W: http://projects.drzeus.cx/wbsd +S: Maintained + W83L785TS HARDWARE MONITOR DRIVER P: Jean Delvare M: khali@linux-fr.org Index: wli-2.6.10-rc3-1/arch/arm/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/Kconfig 2004-12-16 06:19:18.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/Kconfig 2004-12-22 10:04:34.900497170 -0800 @@ -317,31 +317,40 @@ config FIQ bool - depends on ARCH_ACORN || ARCH_L7200 || ARCH_LH7A400 + depends on ARCH_ACORN || ARCH_L7200 default y # Compressed boot loader in ROM. Yes, we really want to ask about # TEXT and BSS so we preserve their values in the config files. -config ZBOOT_ROM - bool "Compressed boot loader in ROM/flash" - help - Say Y here if you intend to execute your compressed kernel image (zImage) - directly from ROM or flash. If unsure, say N. - config ZBOOT_ROM_TEXT hex "Compressed ROM boot loader base address" default "0" help - The base address for zImage. Unless you have special requirements, you - should not change this value. + The physical address at which the ROM-able zImage is to be + placed in the target. Platforms which normally make use of + ROM-able zImage formats normally set this to a suitable + value in their defconfig file. + + If ZBOOT_ROM is not enabled, this has no effect. config ZBOOT_ROM_BSS hex "Compressed ROM boot loader BSS address" default "0" help - The base address of 64KiB of read/write memory, which must be available - while the decompressor is running. Unless you have special requirements, - you should not change this value. + The base address of 64KiB of read/write memory in the target + for the ROM-able zImage, which must be available while the + decompressor is running. Platforms which normally make use of + ROM-able zImage formats normally set this to a suitable + value in their defconfig file. + + If ZBOOT_ROM is not enabled, this has no effect. + +config ZBOOT_ROM + bool "Compressed boot loader in ROM/flash" + depends on ZBOOT_ROM_TEXT != ZBOOT_ROM_BSS + help + Say Y here if you intend to execute your compressed kernel image + (zImage) directly from ROM or flash. If unsure, say N. config XIP_KERNEL bool "Kernel Execute-In-Place from ROM" Index: wli-2.6.10-rc3-1/arch/arm/configs/ep80219_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/configs/ep80219_defconfig 2004-12-22 09:07:07.767541034 -0800 +++ wli-2.6.10-rc3-1/arch/arm/configs/ep80219_defconfig 2004-12-22 10:04:34.910495650 -0800 @@ -1,10 +1,13 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 15 17:03:41 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options @@ -16,6 +19,7 @@ # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +29,20 @@ # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,6 +52,7 @@ # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -59,6 +67,7 @@ # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -67,7 +76,9 @@ # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # # IOP3xx Implementation Options @@ -94,6 +105,7 @@ CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_MINICACHE=y @@ -110,6 +122,7 @@ # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # CONFIG_PCI_LEGACY_PROC is not set CONFIG_PCI_NAMES=y @@ -119,7 +132,6 @@ CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -148,8 +160,8 @@ CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set CONFIG_MTD_REDBOOT_PARTS=y -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y # CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set @@ -191,7 +203,10 @@ # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xf0000000 +CONFIG_MTD_PHYSMAP_LEN=0x00800000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set @@ -232,8 +247,19 @@ # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -243,9 +269,11 @@ # CONFIG_MD_LINEAR is not set CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=y # CONFIG_MD_RAID6 is not set # CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y # CONFIG_DM_CRYPT is not set # CONFIG_DM_SNAPSHOT is not set @@ -280,6 +308,9 @@ # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -299,7 +330,6 @@ # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -362,7 +392,6 @@ # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -375,6 +404,7 @@ # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # @@ -449,7 +479,8 @@ # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -458,6 +489,7 @@ # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set @@ -519,7 +551,6 @@ # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set # # Input Device Drivers @@ -554,7 +585,6 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -567,7 +597,6 @@ # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -575,7 +604,6 @@ # # Ftape, the floppy tape device driver # -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -590,6 +618,7 @@ # # CONFIG_I2C_ALGOBIT is not set # CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support @@ -612,9 +641,11 @@ # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set # # Hardware Sensors Chip support @@ -622,20 +653,25 @@ # CONFIG_I2C_SENSOR is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set # CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set # CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set @@ -685,6 +721,7 @@ # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -709,6 +746,7 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -754,6 +792,7 @@ CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -799,7 +838,6 @@ # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -815,6 +853,12 @@ # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# # # USB Gadget Support @@ -822,16 +866,22 @@ # CONFIG_USB_GADGET is not set # +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_INFO is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_KERNEL is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # Index: wli-2.6.10-rc3-1/arch/arm/configs/integrator_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/configs/integrator_defconfig 2004-12-22 09:07:07.767541034 -0800 +++ wli-2.6.10-rc3-1/arch/arm/configs/integrator_defconfig 2004-12-22 10:04:34.926493218 -0800 @@ -1,139 +1,167 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Mon Dec 20 16:08:21 2004 # CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set +CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_GENERIC_IOMAP=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support # CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y # # System Type # -# CONFIG_ARCH_ARCA5K is not set # CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set CONFIG_ARCH_INTEGRATOR=y +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # -# Archimedes/A5000 Implementations -# - -# -# Archimedes/A5000 Implementations (select only ONE) -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_BITSY is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set +# Integrator Options +# +CONFIG_ARCH_INTEGRATOR_AP=y +# CONFIG_ARCH_INTEGRATOR_CP is not set +# CONFIG_INTEGRATOR_IMPD1 is not set # # Processor Type # -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set +CONFIG_CPU_32=y CONFIG_CPU_ARM720T=y CONFIG_CPU_ARM920T=y -CONFIG_CPU_ARM920_CPU_IDLE=y -CONFIG_CPU_ARM920_I_CACHE_ON=y -CONFIG_CPU_ARM920_D_CACHE_ON=y -# CONFIG_CPU_ARM920_WRITETHROUGH is not set +# CONFIG_CPU_ARM926T is not set # CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_SA110 is not set -# CONFIG_CPU_SA1100 is not set -# CONFIG_DISCONTIGMEM is not set +# CONFIG_CPU_ARM1022 is not set +# CONFIG_CPU_ARM1026 is not set +# CONFIG_CPU_V6 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_ABRT_LV4T=y +CONFIG_CPU_CACHE_V4=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set # # General setup # -CONFIG_PCI_INTEGRATOR=y CONFIG_PCI=y -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -CONFIG_CPU_CLOCK=y +CONFIG_ICST525=y +CONFIG_ARM_AMBA=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEBUG is not set +# CONFIG_CPU_FREQ_PROC_INTF is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +# CONFIG_CPU_FREQ_24_API is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_INTEGRATOR=y +CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_FPE_NWFPE is not set -CONFIG_FPE_FASTFPE=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y + +# +# At least one math emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set CONFIG_PM=y +# CONFIG_PREEMPT is not set +# CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="root=1f03 mem=32M" +CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp mem=32M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -150,8 +178,9 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set # CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_BOOTLDR_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_AFS_PARTS=y # @@ -161,259 +190,264 @@ CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set +# CONFIG_INFTL is not set # # RAM/ROM/Flash chip drivers # CONFIG_MTD_CFI=y -# CONFIG_MTD_CFI_VIRTUAL_ER is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y CONFIG_MTD_CFI_ADV_OPTIONS=y CONFIG_MTD_CFI_NOSWAP=y # CONFIG_MTD_CFI_BE_BYTE_SWAP is not set # CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LART_BIT_SWAP is not set # CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set -# CONFIG_MTD_JEDEC is not set +# CONFIG_MTD_ABSENT is not set # # Mapping drivers for chip access # +# CONFIG_MTD_COMPLEX_MAPPINGS is not set # CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_SUN_UFLASH is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_SA1100_REDBOOT_PARTITIONS is not set -# CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_DBOX2 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_CFI_FLAGADM is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -CONFIG_MTD_ARMFLASH=y +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_EDB7312 is not set # # Self-contained MTD device drivers # # CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set # # Disk-On-Chip Device Drivers # -# CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set +# CONFIG_MTD_DOC2001PLUS is not set # # NAND Flash Device Drivers # # CONFIG_MTD_NAND is not set -# CONFIG_MTD_NAND_SPIA is not set # -# Plug and Play configuration +# Plug and Play support # -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y CONFIG_PACKET_MMAP=y -CONFIG_NETLINK=y -# CONFIG_RTNETLINK is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set -CONFIG_INET_ECN=y +# CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_NETFILTER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set -# CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set +# CONFIG_SMC91X is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -# CONFIG_TULIP is not set -# CONFIG_DE4X5 is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set -# CONFIG_DM9102 is not set -CONFIG_EEPRO100=y -CONFIG_EEPRO100_PM=y -# CONFIG_LNE390 is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_E100_NAPI is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set # CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set # -# Wireless LAN (non-hamradio) +# Ethernet (10000 Mbit) # -# CONFIG_NET_RADIO is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support +# Wireless LAN (non-hamradio) # -# CONFIG_HAMRADIO is not set +# CONFIG_NET_RADIO is not set # -# IrDA (infrared) support +# Wan interfaces # -# CONFIG_IRDA is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # -# ATA/IDE/MFM/RLL support +# SCSI device support # -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_HD is not set +# CONFIG_SCSI is not set # -# SCSI support +# Fusion MPT device support # -# CONFIG_SCSI is not set # # IEEE 1394 (FireWire) support @@ -424,11 +458,6 @@ # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set # # ISDN subsystem @@ -436,62 +465,85 @@ # CONFIG_ISDN is not set # -# Input core support +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces # -# CONFIG_INPUT is not set +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set -CONFIG_SERIAL_AMBA=y -CONFIG_SERIAL_AMBA_CONSOLE=y -CONFIG_SERIAL_INTEGRATOR=y -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 # -# I2C support +# Serial drivers # -# CONFIG_I2C is not set +# CONFIG_SERIAL_8250 is not set # -# Mice +# Non-8250 serial port support # -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set +CONFIG_SERIAL_AMBA_PL010=y +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set # CONFIG_DTLK is not set @@ -501,9 +553,13 @@ # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set # # Multimedia devices @@ -511,75 +567,100 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -CONFIG_MINIX_FS=y +# CONFIG_JFFS2_FS_NAND is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=y -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y -CONFIG_SUNRPC=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -590,51 +671,70 @@ # CONFIG_AMIGA_PARTITION is not set # CONFIG_ATARI_PARTITION is not set # CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# # CONFIG_NLS is not set # -# Console drivers +# Profiling support # -CONFIG_KMI_KEYB=y -CONFIG_KMI_MOUSE=y -CONFIG_PC_KEYMAP=y -CONFIG_VGA_CONSOLE=y -CONFIG_FB=y +# CONFIG_PROFILING is not set # -# Frame-buffer support +# Graphics support # CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_CLGEN is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set -# CONFIG_FB_ACORN is not set -# CONFIG_FB_CLPS711X is not set +# CONFIG_FB_ARMCLCD is not set # CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_SA1100 is not set -# CONFIG_FB_E1355 is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_RIVA is not set +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G450=y +CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_MULTIHEAD=y +# CONFIG_FB_RADEON_OLD is not set +# CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set -# CONFIG_FB_3DFX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set # CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set # # Sound @@ -642,19 +742,63 @@ # CONFIG_SOUND is not set # +# Misc devices +# + +# # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set # # Kernel hacking # +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y Index: wli-2.6.10-rc3-1/arch/arm/configs/iq31244_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/configs/iq31244_defconfig 2004-12-22 09:07:07.768540882 -0800 +++ wli-2.6.10-rc3-1/arch/arm/configs/iq31244_defconfig 2004-12-22 10:04:34.935491850 -0800 @@ -1,10 +1,13 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 15 16:58:36 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options @@ -16,6 +19,7 @@ # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +29,20 @@ # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,6 +52,7 @@ # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -59,6 +67,7 @@ # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -67,7 +76,9 @@ # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # # IOP3xx Implementation Options @@ -94,6 +105,7 @@ CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_MINICACHE=y @@ -110,6 +122,7 @@ # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # CONFIG_PCI_LEGACY_PROC is not set CONFIG_PCI_NAMES=y @@ -119,7 +132,6 @@ CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -148,8 +160,8 @@ CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set CONFIG_MTD_REDBOOT_PARTS=y -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y # CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set @@ -191,7 +203,10 @@ # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xf0000000 +CONFIG_MTD_PHYSMAP_LEN=0x00800000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set @@ -232,8 +247,19 @@ # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -243,9 +269,11 @@ # CONFIG_MD_LINEAR is not set CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=y # CONFIG_MD_RAID6 is not set # CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y # CONFIG_DM_CRYPT is not set # CONFIG_DM_SNAPSHOT is not set @@ -280,6 +308,9 @@ # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -299,7 +330,6 @@ # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -418,7 +448,8 @@ # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -427,6 +458,7 @@ # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set @@ -488,7 +520,6 @@ # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set # # Input Device Drivers @@ -523,7 +554,6 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -536,7 +566,6 @@ # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -544,7 +573,6 @@ # # Ftape, the floppy tape device driver # -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -559,6 +587,7 @@ # # CONFIG_I2C_ALGOBIT is not set # CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support @@ -581,9 +610,11 @@ # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set # # Hardware Sensors Chip support @@ -591,20 +622,25 @@ # CONFIG_I2C_SENSOR is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set # CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set # CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set @@ -654,6 +690,7 @@ # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -678,6 +715,7 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -723,6 +761,7 @@ CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -768,7 +807,6 @@ # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -784,6 +822,12 @@ # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# # # USB Gadget Support @@ -791,16 +835,22 @@ # CONFIG_USB_GADGET is not set # +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_INFO is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_KERNEL is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # Index: wli-2.6.10-rc3-1/arch/arm/configs/iq80321_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/configs/iq80321_defconfig 2004-12-22 09:07:07.768540882 -0800 +++ wli-2.6.10-rc3-1/arch/arm/configs/iq80321_defconfig 2004-12-22 10:04:34.942490786 -0800 @@ -1,10 +1,13 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 15 16:48:43 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options @@ -16,6 +19,7 @@ # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +29,20 @@ # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,6 +52,7 @@ # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -59,6 +67,7 @@ # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -67,7 +76,9 @@ # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # # IOP3xx Implementation Options @@ -94,6 +105,7 @@ CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_MINICACHE=y @@ -110,6 +122,7 @@ # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # CONFIG_PCI_LEGACY_PROC is not set CONFIG_PCI_NAMES=y @@ -119,7 +132,6 @@ CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -148,8 +160,8 @@ CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set CONFIG_MTD_REDBOOT_PARTS=y -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y # CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set @@ -191,7 +203,10 @@ # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xf0000000 +CONFIG_MTD_PHYSMAP_LEN=0x00800000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=1 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set @@ -232,8 +247,19 @@ # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -268,6 +294,9 @@ # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -287,7 +316,6 @@ # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -413,7 +441,6 @@ # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set # # Input Device Drivers @@ -448,7 +475,6 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -461,7 +487,6 @@ # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -469,7 +494,6 @@ # # Ftape, the floppy tape device driver # -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -510,6 +534,7 @@ # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -534,6 +559,7 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -579,6 +605,7 @@ CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -624,7 +651,6 @@ # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -640,6 +666,12 @@ # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# # # USB Gadget Support @@ -647,16 +679,22 @@ # CONFIG_USB_GADGET is not set # +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_INFO is not set CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_KERNEL is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # Index: wli-2.6.10-rc3-1/arch/arm/configs/iq80331_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/configs/iq80331_defconfig 2004-12-22 09:07:07.769540730 -0800 +++ wli-2.6.10-rc3-1/arch/arm/configs/iq80331_defconfig 2004-12-22 10:04:34.950489570 -0800 @@ -1,10 +1,13 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 15 16:43:39 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options @@ -16,6 +19,7 @@ # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,6 +29,7 @@ # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -32,11 +37,13 @@ # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,6 +53,7 @@ # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -60,6 +68,7 @@ # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -68,7 +77,9 @@ # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # # IOP3xx Implementation Options @@ -94,6 +105,7 @@ CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_MINICACHE=y @@ -110,6 +122,7 @@ # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # CONFIG_PCI_LEGACY_PROC is not set CONFIG_PCI_NAMES=y @@ -119,7 +132,6 @@ CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -149,8 +161,8 @@ CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set CONFIG_MTD_REDBOOT_PARTS=y -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y # CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set @@ -196,7 +208,10 @@ # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xc0000000 +CONFIG_MTD_PHYSMAP_LEN=0x00800000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=1 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set @@ -237,8 +252,19 @@ # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -248,9 +274,11 @@ CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=y # CONFIG_MD_RAID6 is not set # CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y # CONFIG_DM_CRYPT is not set # CONFIG_DM_SNAPSHOT is not set @@ -285,6 +313,9 @@ # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -304,7 +335,6 @@ # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -423,7 +453,8 @@ # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -432,6 +463,7 @@ # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set @@ -493,7 +525,6 @@ # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set # # Input Device Drivers @@ -528,7 +559,6 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -541,7 +571,6 @@ # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -549,7 +578,6 @@ # # Ftape, the floppy tape device driver # -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -590,6 +618,7 @@ # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -614,6 +643,7 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -653,6 +683,7 @@ CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -698,7 +729,6 @@ # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -714,6 +744,12 @@ # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# # # USB Gadget Support @@ -721,23 +757,31 @@ # CONFIG_USB_GADGET is not set # +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# # Kernel hacking # -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # Index: wli-2.6.10-rc3-1/arch/arm/configs/versatile_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/configs/versatile_defconfig 2004-12-22 09:07:07.770540578 -0800 +++ wli-2.6.10-rc3-1/arch/arm/configs/versatile_defconfig 2004-12-22 10:04:34.954488962 -0800 @@ -65,7 +65,7 @@ # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_OMAP is not set -CONFIG_ARCH_VERSATILE_PB=y +CONFIG_ARCH_VERSATILE=y # # CLPS711X/EP721X Implementations @@ -110,6 +110,12 @@ # # +# Versatile platform type +# +CONFIG_ARCH_VERSATILE_PB=y +# CONFIG_MACH_VERSATILE_AB is not set + +# # Processor Type # CONFIG_CPU_32=y @@ -144,8 +150,8 @@ # # At least one math emulation must be selected # -# CONFIG_FPE_NWFPE is not set -CONFIG_FPE_FASTFPE=y +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set Index: wli-2.6.10-rc3-1/arch/arm/kernel/entry-armv.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/kernel/entry-armv.S 2004-12-16 06:19:18.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/kernel/entry-armv.S 2004-12-22 10:04:34.960488050 -0800 @@ -1657,6 +1657,8 @@ ENTRY(__trap_init) stmfd sp!, {r4 - r6, lr} + mov r0, #0xff000000 + orr r0, r0, #0x00ff0000 @ high vectors position adr r1, .LCvectors @ set up the vectors ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr} stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr} Index: wli-2.6.10-rc3-1/arch/arm/kernel/fiq.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/kernel/fiq.c 2004-12-22 09:07:07.775539818 -0800 +++ wli-2.6.10-rc3-1/arch/arm/kernel/fiq.c 2004-12-22 10:04:34.962487746 -0800 @@ -46,32 +46,16 @@ #include #include -#define FIQ_VECTOR (vectors_base() + 0x1c) - static unsigned long no_fiq_insn; -static inline void unprotect_page_0(void) -{ - modify_domain(DOMAIN_USER, DOMAIN_MANAGER); -} - -static inline void protect_page_0(void) -{ - modify_domain(DOMAIN_USER, DOMAIN_CLIENT); -} - /* Default reacquire function * - we always relinquish FIQ control * - we always reacquire FIQ control */ static int fiq_def_op(void *ref, int relinquish) { - if (!relinquish) { - unprotect_page_0(); - *(unsigned long *)FIQ_VECTOR = no_fiq_insn; - protect_page_0(); - flush_icache_range(FIQ_VECTOR, FIQ_VECTOR + 4); - } + if (!relinquish) + set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn)); return 0; } @@ -93,12 +77,10 @@ void set_fiq_handler(void *start, unsigned int length) { - unprotect_page_0(); - - memcpy((void *)FIQ_VECTOR, start, length); - - protect_page_0(); - flush_icache_range(FIQ_VECTOR, FIQ_VECTOR + length); + memcpy((void *)0xffff001c, start, length); + flush_icache_range(0xffff001c, 0xffff001c + length); + if (!vectors_high()) + flush_icache_range(0x1c, 0x1c + length); } /* @@ -198,6 +180,5 @@ void __init init_FIQ(void) { - no_fiq_insn = *(unsigned long *)FIQ_VECTOR; - set_fs(get_fs()); + no_fiq_insn = *(unsigned long *)0xffff001c; } Index: wli-2.6.10-rc3-1/arch/arm/kernel/setup.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/kernel/setup.c 2004-12-16 06:19:18.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/kernel/setup.c 2004-12-22 10:04:34.967486986 -0800 @@ -132,21 +132,21 @@ #define lp2 io_res[2] static const char *cache_types[16] = { - "VIVT write-through", - "VIVT write-back", - "VIVT write-back", + "write-through", + "write-back", + "write-back", "undefined 3", "undefined 4", "undefined 5", - "VIVT write-back", - "VIVT write-back", + "write-back", + "write-back", "undefined 8", "undefined 9", "undefined 10", "undefined 11", "undefined 12", "undefined 13", - "VIPT write-back", + "write-back", "undefined 15", }; @@ -236,7 +236,8 @@ unsigned int info = read_cpuid(CPUID_CACHETYPE); if (info != processor_id) { - printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(info)]); + printk("CPU: D %s %s cache\n", cache_is_vivt() ? "VIVT" : "VIPT", + cache_types[CACHE_TYPE(info)]); if (CACHE_S(info)) { dump_cache("CPU: I cache", CACHE_ISIZE(info)); dump_cache("CPU: D cache", CACHE_DSIZE(info)); @@ -255,7 +256,7 @@ } else if ((processor_id & 0x0000f000) == 0x00007000) { cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3; } else { - cpu_arch = (processor_id >> 16) & 15; + cpu_arch = (processor_id >> 16) & 7; if (cpu_arch) cpu_arch += CPU_ARCH_ARMv3; } Index: wli-2.6.10-rc3-1/arch/arm/kernel/sys_arm.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/kernel/sys_arm.c 2004-12-22 09:07:07.780539058 -0800 +++ wli-2.6.10-rc3-1/arch/arm/kernel/sys_arm.c 2004-12-22 10:04:34.969486682 -0800 @@ -51,6 +51,13 @@ return error; } +/* + * This is the lowest virtual address we can permit any user space + * mapping to be mapped at. This is particularly important for + * non-high vector CPUs. + */ +#define MIN_MAP_ADDR (PAGE_SIZE) + /* common code for old and new mmaps */ inline long do_mmap2( unsigned long addr, unsigned long len, @@ -62,11 +69,7 @@ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - /* - * If we are doing a fixed mapping, and address < PAGE_SIZE, - * then deny it. - */ - if (flags & MAP_FIXED && addr < PAGE_SIZE && vectors_base() == 0) + if (flags & MAP_FIXED && addr < MIN_MAP_ADDR) goto out; error = -EBADF; @@ -119,12 +122,7 @@ { unsigned long ret = -EINVAL; - /* - * If we are doing a fixed mapping, and address < PAGE_SIZE, - * then deny it. - */ - if (flags & MREMAP_FIXED && new_addr < PAGE_SIZE && - vectors_base() == 0) + if (flags & MREMAP_FIXED && new_addr < MIN_MAP_ADDR) goto out; down_write(¤t->mm->mmap_sem); Index: wli-2.6.10-rc3-1/arch/arm/kernel/traps.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/kernel/traps.c 2004-12-22 09:07:07.781538906 -0800 +++ wli-2.6.10-rc3-1/arch/arm/kernel/traps.c 2004-12-22 10:04:34.972486226 -0800 @@ -328,20 +328,11 @@ */ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode) { - unsigned int vectors = vectors_base(); - console_verbose(); printk(KERN_CRIT "Bad mode in %s handler detected: mode %s\n", handler[reason], processor_modes[proc_mode]); - /* - * Dump out the vectors and stub routines. Maybe a better solution - * would be to dump them out only if we detect that they are corrupted. - */ - dump_mem(KERN_CRIT "Vectors: ", vectors, vectors + 0x40); - dump_mem(KERN_CRIT "Stubs: ", vectors + 0x200, vectors + 0x4b8); - die("Oops - bad mode", regs, 0); local_irq_disable(); panic("bad mode"); @@ -537,7 +528,7 @@ void __readwrite_bug(const char *fn) { - printk("%s called, but not implemented", fn); + printk("%s called, but not implemented\n", fn); BUG(); } EXPORT_SYMBOL(__readwrite_bug); @@ -575,13 +566,9 @@ void __init trap_init(void) { - extern void __trap_init(unsigned long); - unsigned long base = vectors_base(); + extern void __trap_init(void); - __trap_init(base); - flush_icache_range(base, base + PAGE_SIZE); - if (base != 0) - printk(KERN_DEBUG "Relocating machine vectors to 0x%08lx\n", - base); + __trap_init(); + flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); modify_domain(DOMAIN_USER, DOMAIN_CLIENT); } Index: wli-2.6.10-rc3-1/arch/arm/kernel/vmlinux.lds.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/kernel/vmlinux.lds.S 2004-12-16 06:19:18.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/kernel/vmlinux.lds.S 2004-12-22 10:04:34.974485922 -0800 @@ -56,6 +56,10 @@ __initramfs_start = .; usr/built-in.o(.init.ramfs) __initramfs_end = .; + . = ALIGN(64); + __per_cpu_start = .; + *(.data.percpu) + __per_cpu_end = .; #ifndef CONFIG_XIP_KERNEL __init_begin = _stext; *(.init.data) Index: wli-2.6.10-rc3-1/arch/arm/lib/getuser.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/lib/getuser.S 2004-12-22 09:07:07.785538298 -0800 +++ wli-2.6.10-rc3-1/arch/arm/lib/getuser.S 2004-12-22 10:04:34.977485466 -0800 @@ -17,7 +17,7 @@ * * Inputs: r0 contains the address * Outputs: r0 is the error code - * r1, r2 contains the zero-extended value + * r2, r3 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see include/asm-arm/uaccess.h @@ -32,39 +32,39 @@ .global __get_user_1 __get_user_1: -1: ldrbt r1, [r0] +1: ldrbt r2, [r0] mov r0, #0 mov pc, lr .global __get_user_2 __get_user_2: -2: ldrbt r1, [r0], #1 -3: ldrbt r2, [r0] +2: ldrbt r2, [r0], #1 +3: ldrbt r3, [r0] #ifndef __ARMEB__ - orr r1, r1, r2, lsl #8 + orr r2, r2, r3, lsl #8 #else - orr r1, r2, r1, lsl #8 + orr r2, r3, r2, lsl #8 #endif mov r0, #0 mov pc, lr .global __get_user_4 __get_user_4: -4: ldrt r1, [r0] +4: ldrt r2, [r0] mov r0, #0 mov pc, lr .global __get_user_8 __get_user_8: -5: ldrt r1, [r0], #4 -6: ldrt r2, [r0] +5: ldrt r2, [r0], #4 +6: ldrt r3, [r0] mov r0, #0 mov pc, lr __get_user_bad_8: - mov r2, #0 + mov r3, #0 __get_user_bad: - mov r1, #0 + mov r2, #0 mov r0, #-EFAULT mov pc, lr Index: wli-2.6.10-rc3-1/arch/arm/lib/putuser.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/lib/putuser.S 2004-12-22 09:07:07.787537994 -0800 +++ wli-2.6.10-rc3-1/arch/arm/lib/putuser.S 2004-12-22 10:04:34.979485162 -0800 @@ -16,7 +16,7 @@ * __put_user_X * * Inputs: r0 contains the address - * r1, r2 contains the value + * r2, r3 contains the value * Outputs: r0 is the error code * lr corrupted * @@ -32,33 +32,33 @@ .global __put_user_1 __put_user_1: -1: strbt r1, [r0] +1: strbt r2, [r0] mov r0, #0 mov pc, lr .global __put_user_2 __put_user_2: - mov ip, r1, lsr #8 + mov ip, r2, lsr #8 #ifndef __ARMEB__ -2: strbt r1, [r0], #1 +2: strbt r2, [r0], #1 3: strbt ip, [r0] #else 2: strbt ip, [r0], #1 -3: strbt r1, [r0] +3: strbt r2, [r0] #endif mov r0, #0 mov pc, lr .global __put_user_4 __put_user_4: -4: strt r1, [r0] +4: strt r2, [r0] mov r0, #0 mov pc, lr .global __put_user_8 __put_user_8: -5: strt r1, [r0], #4 -6: strt r2, [r0] +5: strt r2, [r0], #4 +6: strt r3, [r0] mov r0, #0 mov pc, lr Index: wli-2.6.10-rc3-1/arch/arm/mach-ixp4xx/common-pci.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-ixp4xx/common-pci.c 2004-12-16 06:19:18.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-ixp4xx/common-pci.c 2004-12-22 10:04:34.982484706 -0800 @@ -238,7 +238,7 @@ return 0xffffffff; } -static int ixp4xx_pci_read_config(struct pci_bus *bus, u16 devfn, int where, int size, u32 *value) +static int ixp4xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { u32 n, byte_enables, addr, data; u8 bus_num = bus->number; @@ -261,7 +261,7 @@ return PCIBIOS_SUCCESSFUL; } -static int ixp4xx_pci_write_config(struct pci_bus *bus, u16 devfn, int where, int size, u32 value) +static int ixp4xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { u32 n, byte_enables, addr, data; u8 bus_num = bus->number; Index: wli-2.6.10-rc3-1/arch/arm/mach-lh7a40x/arch-lpd7a40x.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-lh7a40x/arch-lpd7a40x.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-lh7a40x/arch-lpd7a40x.c 2004-12-22 10:04:34.984484402 -0800 @@ -267,7 +267,7 @@ BOOT_PARAMS (0xc0000100) MAPIO (lpd7a400_map_io) INITIRQ (lh7a400_init_irq) - .timer = &lpd7a40x_timer, + .timer = &lh7a40x_timer, INIT_MACHINE (lpd7a40x_init) MACHINE_END @@ -281,7 +281,7 @@ BOOT_PARAMS (0xc0000100) MAPIO (lpd7a400_map_io) INITIRQ (lh7a404_init_irq) - .timer = &lpd7a40x_timer, + .timer = &lh7a40x_timer, INIT_MACHINE (lpd7a40x_init) MACHINE_END Index: wli-2.6.10-rc3-1/arch/arm/mach-lh7a40x/common.h =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-lh7a40x/common.h 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-lh7a40x/common.h 2004-12-22 10:04:34.986484098 -0800 @@ -1,9 +1,14 @@ -/* - * linux/arch/arm/mach-lh7a40x/common.h +/* arch/arm/mach-lh7a40x/common.h + * + * Copyright (C) 2004 Marc Singer + * + * 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. * - * Header file for common stuff. */ -struct sys_timer; + extern struct sys_timer lh7a40x_timer; extern void lh7a400_init_irq (void); +extern void lh7a404_init_irq (void); Index: wli-2.6.10-rc3-1/arch/arm/mach-lh7a40x/time.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-lh7a40x/time.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-lh7a40x/time.c 2004-12-22 10:04:34.987483946 -0800 @@ -71,5 +71,5 @@ } struct sys_timer lh7a40x_timer = { - .init = &lh7a40x_timer, + .init = &lh7a40x_timer_init, }; Index: wli-2.6.10-rc3-1/arch/arm/mach-s3c2410/clock.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-s3c2410/clock.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-s3c2410/clock.c 2004-12-22 10:04:34.990483490 -0800 @@ -243,7 +243,7 @@ }; struct clk s3c24xx_clkout0 = { - .name = "clkout1", + .name = "clkout0", .id = -1, }; Index: wli-2.6.10-rc3-1/arch/arm/mach-s3c2410/pm.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-s3c2410/pm.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-s3c2410/pm.c 2004-12-22 10:04:34.993483034 -0800 @@ -187,6 +187,8 @@ #define DBG(fmt...) printk(KERN_DEBUG fmt) #define s3c2410_pm_debug_init() do { } while(0) + +static struct sleep_save uart_save[] = {}; #endif #if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0 @@ -378,8 +380,6 @@ #else -static struct sleep_save uart_save[] = {}; - #define s3c2410_pm_check_prepare() do { } while(0) #define s3c2410_pm_check_restore() do { } while(0) #define s3c2410_pm_check_store() do { } while(0) Index: wli-2.6.10-rc3-1/arch/arm/mach-s3c2410/time.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-s3c2410/time.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-s3c2410/time.c 2004-12-22 10:04:34.997482426 -0800 @@ -37,7 +37,49 @@ #include "clock.h" static unsigned long timer_startval; -static unsigned long timer_ticks_usec; +static unsigned long timer_usec_ticks; + +#define TIMER_USEC_SHIFT 16 + +/* we use the shifted arithmetic to work out the ratio of timer ticks + * to usecs, as often the peripheral clock is not a nice even multiple + * of 1MHz. + * + * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok + * for the current HZ value of 200 without producing overflows. + * + * Original patch by Dimitry Andric, updated by Ben Dooks +*/ + + +/* timer_mask_usec_ticks + * + * given a clock and divisor, make the value to pass into timer_ticks_to_usec + * to scale the ticks into usecs +*/ + +static inline unsigned long +timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk) +{ + unsigned long den = pclk / 1000; + + return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den; +} + +/* timer_ticks_to_usec + * + * convert timer ticks to usec. +*/ + +static inline unsigned long timer_ticks_to_usec(unsigned long ticks) +{ + unsigned long res; + + res = ticks * timer_usec_ticks; + res += 1 << (TIMER_USEC_SHIFT - 4); /* round up slightly */ + + return res >> TIMER_USEC_SHIFT; +} /*** * Returns microsecond since last clock interrupt. Note that interrupts @@ -50,31 +92,31 @@ static unsigned long s3c2410_gettimeoffset (void) { unsigned long tdone; - unsigned long usec; unsigned long irqpend; + unsigned long tval; /* work out how many ticks have gone since last timer interrupt */ - tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4)); + tval = __raw_readl(S3C2410_TCNTO(4)); + tdone = timer_startval - tval; /* check to see if there is an interrupt pending */ irqpend = __raw_readl(S3C2410_SRCPND); if (irqpend & SRCPND_TIMER4) { /* re-read the timer, and try and fix up for the missed - * interrupt */ - - tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4)); - tdone += 1<<16; - } + * interrupt. Note, the interrupt may go off before the + * timer has re-loaded from wrapping. + */ - /* currently, tcnt is in 12MHz units, but this may change - * for non-bast machines... - */ + tval = __raw_readl(S3C2410_TCNTO(4)); + tdone = timer_startval - tval; - usec = tdone / timer_ticks_usec; + if (tval != 0) + tdone += timer_startval; + } - return usec; + return timer_ticks_to_usec(tdone); } @@ -120,8 +162,9 @@ /* configure the system for whichever machine is in use */ if (machine_is_bast() || machine_is_vr1000()) { - timer_ticks_usec = 12; /* timer is at 12MHz */ - tcnt = (timer_ticks_usec * (1000*1000)) / HZ; + /* timer is at 12MHz, scaler is 1 */ + timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); + tcnt = 12000000 / HZ; tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1; @@ -129,13 +172,15 @@ /* for the h1940 (and others), we use the pclk from the core * to generate the timer values. since values around 50 to * 70MHz are not values we can directly generate the timer - * value from, we need to pre-scaleand divide before using it. + * value from, we need to pre-scale and divide before using it. + * + * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz + * (8.45 ticks per usec) */ /* this is used as default if no other timer can be found */ - timer_ticks_usec = s3c24xx_pclk / (1000*1000); - timer_ticks_usec /= 6; + timer_usec_ticks = timer_mask_usec_ticks(6, s3c24xx_pclk); tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; tcfg1 |= S3C2410_TCFG1_MUX4_DIV2; @@ -146,8 +191,12 @@ tcnt = (s3c24xx_pclk / 6) / HZ; } - printk("setup_timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx\n", - tcon, tcnt, tcfg0, tcfg1); + /* timers reload after counting zero, so reduce the count by 1 */ + + tcnt--; + + printk("timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n", + tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks); /* check to see if timer is within 16bit range... */ if (tcnt > 0xffff) { Index: wli-2.6.10-rc3-1/arch/arm/mach-sa1100/assabet.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-sa1100/assabet.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-sa1100/assabet.c 2004-12-22 10:04:35.000481970 -0800 @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -94,6 +95,11 @@ ASSABET_BCR_clear(ASSABET_BCR_LCD_ON); } + +/* + * Assabet flash support code. + */ + #ifdef ASSABET_REV_4 /* * Phase 4 Assabet has two 28F160B3 flash parts in bank 0: @@ -156,6 +162,42 @@ } }; + +/* + * Assabet IrDA support code. + */ + +static int assabet_irda_set_power(struct device *dev, unsigned int state) +{ + static unsigned int bcr_state[4] = { + ASSABET_BCR_IRDA_MD0, + ASSABET_BCR_IRDA_MD1|ASSABET_BCR_IRDA_MD0, + ASSABET_BCR_IRDA_MD1, + 0 + }; + + if (state < 4) { + state = bcr_state[state]; + ASSABET_BCR_clear(state ^ (ASSABET_BCR_IRDA_MD1| + ASSABET_BCR_IRDA_MD0)); + ASSABET_BCR_set(state); + } + return 0; +} + +static void assabet_irda_set_speed(struct device *dev, unsigned int speed) +{ + if (speed < 4000000) + ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL); + else + ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL); +} + +static struct irda_platform_data assabet_irda_data = { + .set_power = assabet_irda_set_power, + .set_speed = assabet_irda_set_speed, +}; + static void __init assabet_init(void) { /* @@ -203,6 +245,7 @@ sa11x0_set_flash_data(&assabet_flash_data, assabet_flash_resources, ARRAY_SIZE(assabet_flash_resources)); + sa11x0_set_irda_data(&assabet_irda_data); } /* Index: wli-2.6.10-rc3-1/arch/arm/mach-sa1100/generic.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-sa1100/generic.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-sa1100/generic.c 2004-12-22 10:04:35.003481514 -0800 @@ -283,6 +283,38 @@ sa11x0mtd_device.num_resources = nr; } +static struct resource sa11x0ir_resources[] = { + { + .start = __PREG(Ser2UTCR0), + .end = __PREG(Ser2UTCR0) + 0x24 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = __PREG(Ser2HSCR0), + .end = __PREG(Ser2HSCR0) + 0x1c - 1, + .flags = IORESOURCE_MEM, + }, { + .start = __PREG(Ser2HSCR2), + .end = __PREG(Ser2HSCR2) + 0x04 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_Ser2ICP, + .end = IRQ_Ser2ICP, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device sa11x0ir_device = { + .name = "sa11x0-ir", + .id = -1, + .num_resources = ARRAY_SIZE(sa11x0ir_resources), + .resource = sa11x0ir_resources, +}; + +void sa11x0_set_irda_data(struct irda_platform_data *irda) +{ + sa11x0ir_device.dev.platform_data = irda; +} + static struct platform_device *sa11x0_devices[] __initdata = { &sa11x0udc_device, &sa11x0uart1_device, @@ -298,6 +330,9 @@ { pm_power_off = sa1100_power_off; + if (sa11x0ir_device.dev.platform_data) + platform_device_register(&sa11x0ir_device); + return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices)); } Index: wli-2.6.10-rc3-1/arch/arm/mach-sa1100/generic.h =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-sa1100/generic.h 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-sa1100/generic.h 2004-12-22 10:04:35.005481210 -0800 @@ -33,3 +33,6 @@ extern void sa11x0_set_flash_data(struct flash_platform_data *flash, struct resource *res, int nr); + +struct irda_platform_data; +void sa11x0_set_irda_data(struct irda_platform_data *irda); Index: wli-2.6.10-rc3-1/arch/arm/mach-sa1100/h3600.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-sa1100/h3600.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-sa1100/h3600.c 2004-12-22 10:04:35.009480602 -0800 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -119,9 +120,34 @@ .flags = IORESOURCE_MEM, }; +/* + * This turns the IRDA power on or off on the Compaq H3600 + */ +static int h3600_irda_set_power(struct device *dev, unsigned int state) +{ + assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state ); + + return 0; +} + +static void h3600_irda_set_speed(struct device *dev, int speed) +{ + if (speed < 4000000) { + clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL); + } else { + set_h3600_egpio(IPAQ_EGPIO_IR_FSEL); + } +} + +static struct irda_platform_data h3600_irda_data = { + .set_power = h3600_irda_set_power, + .set_speed = h3600_irda_set_speed, +}; + static void h3xxx_mach_init(void) { sa11x0_set_flash_data(&h3xxx_flash_data, &h3xxx_flash_resource, 1); + sa11x0_set_irda_data(&h3600_irda_data); } /* Index: wli-2.6.10-rc3-1/arch/arm/mach-sa1100/lart.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-sa1100/lart.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-sa1100/lart.c 2004-12-22 10:04:35.010480450 -0800 @@ -17,6 +17,8 @@ #include "generic.h" +#warning "include/asm/arch-sa1100/ide.h needs fixing for lart" + static struct map_desc lart_io_desc[] __initdata = { /* virtual physical length type */ { 0xe8000000, 0x00000000, 0x00400000, MT_DEVICE }, /* main flash memory */ Index: wli-2.6.10-rc3-1/arch/arm/mach-sa1100/simpad.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-sa1100/simpad.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-sa1100/simpad.c 2004-12-22 10:04:35.014479842 -0800 @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include @@ -18,6 +20,7 @@ #include #include +#include #include #include #include @@ -83,6 +86,45 @@ .pm = simpad_uart_pm, }; + +static struct mtd_partition simpad_partitions[] = { + { + .name = "SIMpad boot firmware", + .size = 0x00080000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "SIMpad kernel", + .size = 0x0010000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "SIMpad root jffs2", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + } +}; + +static struct flash_platform_data simpad_flash_data = { + .map_name = "cfi_probe", + .parts = simpad_partitions, + .nr_parts = ARRAY_SIZE(simpad_partitions), +}; + + +static struct resource simpad_flash_resources [] = { + { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_16M -1, + .flags = IORESOURCE_MEM, + }, { + .start = SA1100_CS1_PHYS, + .end = SA1100_CS1_PHYS + SZ_16M -1, + .flags = IORESOURCE_MEM, + } +}; + + + static void __init simpad_map_io(void) { sa1100_map_io(); @@ -113,84 +155,9 @@ PCFR = 0; PSDR = 0; - -} - -#ifdef CONFIG_PROC_FS - -static char* name[]={ - "VCC_5V_EN", - "VCC_3V_EN", - "EN1", - "EN0", - "DISPLAY_ON", - "PCMCIA_BUFF_DIS", - "MQ_RESET", - "PCMCIA_RESET", - "DECT_POWER_ON", - "IRDA_SD", - "RS232_ON", - "SD_MEDIAQ", - "LED2_ON", - "IRDA_MODE", - "ENABLE_5V", - "RESET_SIMCARD" -}; - -static int proc_cs3_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - int len, i; - - p += sprintf(p, "Chipselect3 : %x\n", (uint)cs3_shadow); - for (i = 0; i <= 15; i++) { - if(cs3_shadow & (1<read_proc = proc_cs3_read; - proc_cs3->write_proc = (void*)proc_cs3_write; - } -#endif - - - - return 0; + sa11x0_set_flash_data(&simpad_flash_data, simpad_flash_resources, + ARRAY_SIZE(simpad_flash_resources)); } - -arch_initcall(cs3_init); static void simpad_power_off(void) { Index: wli-2.6.10-rc3-1/arch/arm/mach-versatile/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-versatile/Kconfig 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-versatile/Kconfig 2004-12-22 10:04:35.015479690 -0800 @@ -7,7 +7,7 @@ help Include support for the ARM(R) Versatile/PB platform. -config ARCH_VERSATILE_AB +config MACH_VERSATILE_AB bool "Support Versatile/AB platform" default n help Index: wli-2.6.10-rc3-1/arch/arm/mach-versatile/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-versatile/Makefile 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-versatile/Makefile 2004-12-22 10:04:35.017479386 -0800 @@ -4,4 +4,4 @@ obj-y := core.o clock.o obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o -obj-$(CONFIG_ARCH_VERSATILE_AB) += versatile_ab.o +obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o Index: wli-2.6.10-rc3-1/arch/arm/mach-versatile/core.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mach-versatile/core.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mach-versatile/core.c 2004-12-22 10:04:35.021478778 -0800 @@ -189,7 +189,7 @@ { IO_ADDRESS(VERSATILE_SIC_BASE), VERSATILE_SIC_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(VERSATILE_VIC_BASE), VERSATILE_VIC_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(VERSATILE_SCTL_BASE), VERSATILE_SCTL_BASE, SZ_4K * 9, MT_DEVICE }, -#ifdef CONFIG_ARCH_VERSATILE_AB +#ifdef CONFIG_MACH_VERSATILE_AB { IO_ADDRESS(VERSATILE_GPIO0_BASE), VERSATILE_GPIO0_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(VERSATILE_IB2_BASE), VERSATILE_IB2_BASE, SZ_64M, MT_DEVICE }, #endif @@ -341,7 +341,7 @@ unsigned long sys_lock = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET; #if defined(CONFIG_ARCH_VERSATILE_PB) unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC4_OFFSET; -#elif defined(CONFIG_ARCH_VERSATILE_AB) +#elif defined(CONFIG_MACH_VERSATILE_AB) unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC1_OFFSET; #endif u32 val; @@ -512,7 +512,7 @@ val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH; writel(val, sys_clcd); -#ifdef CONFIG_ARCH_VERSATILE_AB +#ifdef CONFIG_MACH_VERSATILE_AB /* * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off */ @@ -561,7 +561,7 @@ val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH; writel(val, sys_clcd); -#ifdef CONFIG_ARCH_VERSATILE_AB +#ifdef CONFIG_MACH_VERSATILE_AB /* * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on */ Index: wli-2.6.10-rc3-1/arch/arm/mm/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mm/Kconfig 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mm/Kconfig 2004-12-22 10:04:35.024478322 -0800 @@ -121,8 +121,8 @@ # ARM926T config CPU_ARM926T bool "Support ARM926T processor" if ARCH_INTEGRATOR - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || ARCH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP1610 || ARCH_OMAP5912 - default y if ARCH_VERSATILE_PB || ARCH_VERSATILE_AB + depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP1610 || ARCH_OMAP5912 + default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_CACHE_VIVT Index: wli-2.6.10-rc3-1/arch/arm/mm/copypage-v6.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mm/copypage-v6.c 2004-12-22 09:07:07.862526594 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mm/copypage-v6.c 2004-12-22 10:04:35.025478170 -0800 @@ -15,6 +15,7 @@ #include #include #include +#include #if SHMLBA > 16384 #error FIX ME Index: wli-2.6.10-rc3-1/arch/arm/mm/mm-armv.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mm/mm-armv.c 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mm/mm-armv.c 2004-12-22 10:04:35.030477410 -0800 @@ -158,7 +158,7 @@ init_pgd = pgd_offset_k(0); - if (vectors_base() == 0) { + if (!vectors_high()) { /* * This lock is here just to satisfy pmd_alloc and pte_lock */ @@ -317,12 +317,18 @@ .prot_sect = PMD_TYPE_SECT | PMD_SECT_MINICACHE, .domain = DOMAIN_KERNEL, }, - [MT_VECTORS] = { + [MT_LOW_VECTORS] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_EXEC, .prot_l1 = PMD_TYPE_TABLE, .domain = DOMAIN_USER, }, + [MT_HIGH_VECTORS] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_USER | L_PTE_EXEC, + .prot_l1 = PMD_TYPE_TABLE, + .domain = DOMAIN_USER, + }, [MT_MEMORY] = { .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, @@ -357,13 +363,12 @@ } if (cpu_arch <= CPU_ARCH_ARMv5) { - mem_types[MT_DEVICE].prot_l1 |= PMD_BIT4; - mem_types[MT_DEVICE].prot_sect |= PMD_BIT4; - mem_types[MT_CACHECLEAN].prot_sect |= PMD_BIT4; - mem_types[MT_MINICLEAN].prot_sect |= PMD_BIT4; - mem_types[MT_VECTORS].prot_l1 |= PMD_BIT4; - mem_types[MT_MEMORY].prot_sect |= PMD_BIT4; - mem_types[MT_ROM].prot_sect |= PMD_BIT4; + for (i = 0; i < ARRAY_SIZE(mem_types); i++) { + if (mem_types[i].prot_l1) + mem_types[i].prot_l1 |= PMD_BIT4; + if (mem_types[i].prot_sect) + mem_types[i].prot_sect |= PMD_BIT4; + } } /* @@ -387,13 +392,16 @@ cp = &cache_policies[cachepolicy]; if (cpu_arch >= CPU_ARCH_ARMv5) { - mem_types[MT_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; + mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; + mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; } else { - mem_types[MT_VECTORS].prot_pte |= cp->pte; + mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte; + mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte; mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); } - mem_types[MT_VECTORS].prot_l1 |= ecc_mask; + mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; + mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; mem_types[MT_ROM].prot_sect |= cp->pmd; @@ -420,6 +428,8 @@ ecc_mask ? "en" : "dis", cp->policy); } +#define vectors_base() (vectors_high() ? 0xffff0000 : 0) + /* * Create the page directory entries and any necessary * page tables for the mapping specified by `md'. We @@ -587,16 +597,22 @@ } while (address != 0); /* - * Create a mapping for the machine vectors at virtual address 0 - * or 0xffff0000. We should always try the high mapping. + * Create a mapping for the machine vectors at the high-vectors + * location (0xffff0000). If we aren't using high-vectors, also + * create a mapping at the low-vectors virtual address. */ init_maps->physical = virt_to_phys(init_maps); - init_maps->virtual = vectors_base(); + init_maps->virtual = 0xffff0000; init_maps->length = PAGE_SIZE; - init_maps->type = MT_VECTORS; - + init_maps->type = MT_HIGH_VECTORS; create_mapping(init_maps); + if (!vectors_high()) { + init_maps->virtual = 0; + init_maps->type = MT_LOW_VECTORS; + create_mapping(init_maps); + } + flush_cache_all(); flush_tlb_all(); } Index: wli-2.6.10-rc3-1/arch/arm/mm/proc-v6.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mm/proc-v6.S 2004-12-22 09:07:07.865526138 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mm/proc-v6.S 2004-12-22 10:04:35.032477106 -0800 @@ -201,6 +201,11 @@ mov r10, #0x1f @ domains 0, 1 = manager mcr p15, 0, r10, c3, c0, 0 @ load domain access register mrc p15, 0, r0, c1, c0, 0 @ read control register +#ifdef CONFIG_VFP + mrc p15, 0, r10, c1, c0, 2 + orr r10, r10, #(3 << 20) + mcr p15, 0, r10, c1, c0, 2 @ Enable full access to VFP +#endif ldr r10, cr1_clear @ get mask for bits to clear bic r0, r0, r10 @ clear bits them ldr r10, cr1_set @ get mask for bits to set @@ -250,8 +255,8 @@ */ .type __v6_proc_info, #object __v6_proc_info: - .long 0x00070000 - .long 0x00ff0000 + .long 0x0007b000 + .long 0x0007f000 .long 0x00000c0e b __v6_setup .long cpu_arch_name Index: wli-2.6.10-rc3-1/arch/arm/mm/proc-xscale.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/arm/mm/proc-xscale.S 2004-12-22 09:07:07.866525986 -0800 +++ wli-2.6.10-rc3-1/arch/arm/mm/proc-xscale.S 2004-12-22 10:04:35.036476498 -0800 @@ -679,6 +679,11 @@ .asciz "XScale-IXP42x Family" .size cpu_ixp42x_name, . - cpu_ixp42x_name + .type cpu_ixp46x_name, #object +cpu_ixp46x_name: + .asciz "XScale-IXP46x Family" + .size cpu_ixp46x_name, . - cpu_ixp46x_name + .type cpu_ixp2400_name, #object cpu_ixp2400_name: .asciz "XScale-IXP2400" @@ -831,6 +836,22 @@ .long xscale_cache_fns .size __ixp42x_proc_info, . - __ixp42x_proc_info + .type __ixp46x_proc_info, #object +__ixp46x_proc_info: + .long 0x69054200 + .long 0xffffff00 + .long 0x00000c0e + b __xscale_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_ixp46x_name + .long xscale_processor_functions + .long v4wbi_tlb_fns + .long xscale_mc_user_fns + .long xscale_cache_fns + .size __ixp46x_proc_info, . - __ixp46x_proc_info + .type __pxa255_proc_info,#object __pxa255_proc_info: .long 0x69052d00 Index: wli-2.6.10-rc3-1/arch/i386/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/i386/Kconfig 2004-12-16 06:19:19.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/i386/Kconfig 2004-12-22 10:04:35.042475586 -0800 @@ -200,7 +200,7 @@ bool "586/K5/5x86/6x86/6x86MX" help Select this for an 586 or 686 series processor such as the AMD K5, - the Intel 5x86 or 6x86, or the Intel 6x86MX. This choice does not + the Cyrix 5x86, 6x86 and 6x86MX. This choice does not assume the RDTSC (Read Time Stamp Counter) instruction. config M586TSC Index: wli-2.6.10-rc3-1/arch/i386/kernel/entry.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/i386/kernel/entry.S 2004-12-16 06:19:20.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/i386/kernel/entry.S 2004-12-22 10:04:35.045475130 -0800 @@ -235,6 +235,7 @@ /* if something modifies registers it must also disable sysexit */ movl EIP(%esp), %edx movl OLDESP(%esp), %ecx + xorl %ebp,%ebp sti sysexit Index: wli-2.6.10-rc3-1/arch/i386/kernel/process.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/i386/kernel/process.c 2004-12-16 06:19:20.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/i386/kernel/process.c 2004-12-22 10:04:35.049474522 -0800 @@ -99,6 +99,8 @@ safe_halt(); else local_irq_enable(); + } else { + cpu_relax(); } } Index: wli-2.6.10-rc3-1/arch/i386/kernel/quirks.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/i386/kernel/quirks.c 2004-12-16 06:19:20.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/i386/kernel/quirks.c 2004-12-22 10:04:35.050474370 -0800 @@ -1,10 +1,11 @@ /* * This file contains work-arounds for x86 and x86_64 platform bugs. */ +#include #include #include -#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) +#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI) void __devinit quirk_intel_irqbalance(struct pci_dev *dev) { Index: wli-2.6.10-rc3-1/arch/i386/kernel/time.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/i386/kernel/time.c 2004-12-16 06:19:20.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/i386/kernel/time.c 2004-12-22 10:04:35.053473914 -0800 @@ -381,9 +381,9 @@ void __init hpet_time_init(void) { xtime.tv_sec = get_cmos_time(); - wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = -xtime.tv_nsec; + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); if (hpet_enable() >= 0) { printk("Using HPET for base-timer\n"); @@ -409,9 +409,9 @@ } #endif xtime.tv_sec = get_cmos_time(); - wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = -xtime.tv_nsec; + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); cur_timer = select_timer(); printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); Index: wli-2.6.10-rc3-1/arch/i386/kernel/vm86.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/i386/kernel/vm86.c 2004-12-16 06:19:20.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/i386/kernel/vm86.c 2004-12-22 10:04:35.056473458 -0800 @@ -723,7 +723,14 @@ irqbits |= irq_bit; if (vm86_irqs[intno].sig) send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1); - /* else user will poll for IRQs */ + spin_unlock_irqrestore(&irqbits_lock, flags); + /* + * IRQ will be re-enabled when user asks for the irq (whether + * polling or as a result of the signal) + */ + disable_irq(intno); + return IRQ_HANDLED; + out: spin_unlock_irqrestore(&irqbits_lock, flags); return IRQ_NONE; Index: wli-2.6.10-rc3-1/arch/ia64/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ia64/Makefile 2004-12-16 06:19:20.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ia64/Makefile 2004-12-22 10:04:35.058473154 -0800 @@ -82,7 +82,9 @@ archclean: $(Q)$(MAKE) $(clean)=$(boot) -CLEAN_FILES += include/asm-ia64/.offsets.h.stamp include/asm-ia64/offsets.h vmlinux.gz bootloader +CLEAN_FILES += include/asm-ia64/.offsets.h.stamp vmlinux.gz bootloader + +MRPROPER_FILES += include/asm-ia64/offsets.h prepare: include/asm-ia64/offsets.h Index: wli-2.6.10-rc3-1/arch/ia64/kernel/perfmon.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ia64/kernel/perfmon.c 2004-12-16 06:19:20.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ia64/kernel/perfmon.c 2004-12-22 10:04:35.079469962 -0800 @@ -1998,7 +1998,7 @@ /* * XXX: check for signals : - * - ok of explicit close + * - ok for explicit close * - not ok when coming from exit_files() */ schedule(); @@ -4978,26 +4978,14 @@ static void pfm_context_force_terminate(pfm_context_t *ctx, struct pt_regs *regs) { - if (ctx->ctx_fl_system) { - printk(KERN_ERR "perfmon: pfm_context_force_terminate [%d] is system-wide\n", current->pid); - return; - } - /* - * we stop the whole thing, we do no need to flush - * we know we WERE masked - */ - pfm_clear_psr_up(); - ia64_psr(regs)->up = 0; - ia64_psr(regs)->sp = 1; + int ret; - /* - * disconnect the task from the context and vice-versa - */ - current->thread.pfm_context = NULL; - current->thread.flags &= ~IA64_THREAD_PM_VALID; - ctx->ctx_task = NULL; + DPRINT(("entering for [%d]\n", current->pid)); - DPRINT(("context terminated\n")); + ret = pfm_context_unload(ctx, NULL, 0, regs); + if (ret) { + printk(KERN_ERR "pfm_context_force_terminate: [%d] unloaded failed with %d\n", current->pid, ret); + } /* * and wakeup controlling task, indicating we are now disconnected @@ -5370,9 +5358,8 @@ if (ovfl_notify == 0) reset_pmds = ovfl_pmds; } - DPRINT(("ovfl_pmds=0x%lx reset_pmds=0x%lx\n", - ovfl_pmds, - reset_pmds)); + DPRINT_ovfl(("ovfl_pmds=0x%lx reset_pmds=0x%lx\n", ovfl_pmds, reset_pmds)); + /* * reset the requested PMD registers using the short reset values */ @@ -6367,6 +6354,9 @@ * XXX: sampling situation is not taken into account here */ mask2 = ctx->ctx_used_pmds[0]; + + DPRINT(("is_self=%d ovfl_val=0x%lx mask2=0x%lx\n", is_self, ovfl_val, mask2)); + for (i = 0; mask2; i++, mask2>>=1) { /* skip non used pmds */ @@ -6405,7 +6395,7 @@ } } - DPRINT(("[%d] is_self=%d ctx_pmd[%d]=0x%lx pmd_val=0x%lx\n", task->pid, is_self, i, val, pmd_val)); + DPRINT(("[%d] ctx_pmd[%d]=0x%lx pmd_val=0x%lx\n", task->pid, i, val, pmd_val)); if (is_self) task->thread.pmds[i] = pmd_val; Index: wli-2.6.10-rc3-1/arch/ia64/kernel/setup.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ia64/kernel/setup.c 2004-12-16 06:19:20.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ia64/kernel/setup.c 2004-12-22 10:04:35.083469354 -0800 @@ -289,6 +289,15 @@ return -1; } +static inline void +mark_bsp_online (void) +{ +#ifdef CONFIG_SMP + /* If we register an early console, allow CPU 0 to printk */ + cpu_set(smp_processor_id(), cpu_online_map); +#endif +} + void __init setup_arch (char **cmdline_p) { @@ -306,11 +315,8 @@ machvec_init(acpi_get_sysname()); #endif -#ifdef CONFIG_SMP - /* If we register an early console, allow CPU 0 to printk */ - if (!early_console_setup(*cmdline_p)) - cpu_set(smp_processor_id(), cpu_online_map); -#endif + if (early_console_setup(*cmdline_p) == 0) + mark_bsp_online(); #ifdef CONFIG_ACPI_BOOT /* Initialize the ACPI boot-time table parser */ Index: wli-2.6.10-rc3-1/arch/m32r/kernel/time.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m32r/kernel/time.c 2004-12-16 06:19:21.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m32r/kernel/time.c 2004-12-22 10:04:35.086468898 -0800 @@ -275,8 +275,8 @@ xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_sec = -xtime.tv_sec; - wall_to_monotonic.tv_nsec = -xtime.tv_nsec; + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ Index: wli-2.6.10-rc3-1/arch/m68k/configs/amiga_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/amiga_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/amiga_defconfig 2004-12-22 10:04:35.093467834 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:46:49 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:25 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -137,6 +137,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -722,6 +723,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -953,7 +958,7 @@ # Library routines # CONFIG_CRC_CCITT=m -CONFIG_CRC32=m +CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m Index: wli-2.6.10-rc3-1/arch/m68k/configs/apollo_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/apollo_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/apollo_defconfig 2004-12-22 10:04:35.097467226 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:47:18 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:29 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -122,6 +122,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -581,6 +582,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set Index: wli-2.6.10-rc3-1/arch/m68k/configs/atari_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/atari_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/atari_defconfig 2004-12-22 10:04:35.100466770 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:48:18 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:34 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -129,6 +129,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -634,6 +635,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -865,7 +870,7 @@ # Library routines # CONFIG_CRC_CCITT=m -CONFIG_CRC32=m +CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m Index: wli-2.6.10-rc3-1/arch/m68k/configs/bvme6000_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/bvme6000_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/bvme6000_defconfig 2004-12-22 10:04:35.104466162 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:48:27 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:38 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -122,6 +122,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -580,6 +581,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set Index: wli-2.6.10-rc3-1/arch/m68k/configs/hp300_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/hp300_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/hp300_defconfig 2004-12-22 10:04:35.107465706 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:48:53 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:44 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -123,6 +123,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -582,6 +583,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set Index: wli-2.6.10-rc3-1/arch/m68k/configs/mac_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/mac_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/mac_defconfig 2004-12-22 10:04:35.111465098 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:49:04 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:47 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -124,6 +124,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -643,6 +644,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set Index: wli-2.6.10-rc3-1/arch/m68k/configs/mvme147_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/mvme147_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/mvme147_defconfig 2004-12-22 10:04:35.114464642 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:49:10 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:49 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -122,6 +122,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -597,6 +598,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set Index: wli-2.6.10-rc3-1/arch/m68k/configs/mvme16x_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/mvme16x_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/mvme16x_defconfig 2004-12-22 10:04:35.118464034 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:49:35 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:52 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -122,6 +122,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -596,6 +597,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -827,7 +832,7 @@ # Library routines # CONFIG_CRC_CCITT=m -CONFIG_CRC32=m +CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m Index: wli-2.6.10-rc3-1/arch/m68k/configs/q40_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/q40_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/q40_defconfig 2004-12-22 10:04:35.122463426 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:49:42 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:55 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -127,6 +127,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -673,6 +674,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -900,7 +905,7 @@ # Library routines # CONFIG_CRC_CCITT=m -CONFIG_CRC32=m +CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m Index: wli-2.6.10-rc3-1/arch/m68k/configs/sun3_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/sun3_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/sun3_defconfig 2004-12-22 10:04:35.126462818 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:49:50 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:58 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -110,6 +110,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -586,6 +587,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -815,7 +820,7 @@ # Library routines # CONFIG_CRC_CCITT=m -CONFIG_CRC32=m +CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m Index: wli-2.6.10-rc3-1/arch/m68k/configs/sun3x_defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/configs/sun3x_defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/configs/sun3x_defconfig 2004-12-22 10:04:35.129462362 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:49:55 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:22:01 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -121,6 +121,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -596,6 +597,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -825,7 +830,7 @@ # Library routines # CONFIG_CRC_CCITT=m -CONFIG_CRC32=m +CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m Index: wli-2.6.10-rc3-1/arch/m68k/defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/m68k/defconfig 2004-12-16 06:19:22.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/m68k/defconfig 2004-12-22 10:04:35.089468442 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2-m68k -# Mon Nov 15 12:48:44 2004 +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:41 2004 # CONFIG_M68K=y CONFIG_MMU=y @@ -115,6 +115,7 @@ # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -452,6 +453,10 @@ # CONFIG_USB_ARCH_HAS_OHCI is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set Index: wli-2.6.10-rc3-1/arch/ppc/boot/common/util.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc/boot/common/util.S 2004-12-22 09:07:08.253467162 -0800 +++ wli-2.6.10-rc3-1/arch/ppc/boot/common/util.S 2004-12-22 10:04:35.132461906 -0800 @@ -27,6 +27,7 @@ .text +#ifdef CONFIG_6xx .globl disable_6xx_mmu disable_6xx_mmu: /* Establish default MSR value, exception prefix 0xFFF. @@ -94,6 +95,7 @@ sync isync blr +#endif .globl _setup_L2CR _setup_L2CR: Index: wli-2.6.10-rc3-1/arch/ppc/kernel/process.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc/kernel/process.c 2004-12-16 06:19:25.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc/kernel/process.c 2004-12-22 10:04:35.136461298 -0800 @@ -321,7 +321,7 @@ trap = TRAP(regs); if (trap == 0x300 || trap == 0x600) printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr); - printk("TASK = %p[%d] '%s' THREAD: %p", + printk("TASK = %p[%d] '%s' THREAD: %p\n", current, current->pid, current->comm, current->thread_info); printk("Last syscall: %ld ", current->thread.last_syscall); @@ -370,6 +370,10 @@ last_task_used_math = NULL; if (last_task_used_altivec == current) last_task_used_altivec = NULL; +#ifdef CONFIG_SPE + if (last_task_used_spe == current) + last_task_used_spe = NULL; +#endif } void flush_thread(void) @@ -378,6 +382,10 @@ last_task_used_math = NULL; if (last_task_used_altivec == current) last_task_used_altivec = NULL; +#ifdef CONFIG_SPE + if (last_task_used_spe == current) + last_task_used_spe = NULL; +#endif } void @@ -480,6 +488,10 @@ last_task_used_math = NULL; if (last_task_used_altivec == current) last_task_used_altivec = NULL; +#ifdef CONFIG_SPE + if (last_task_used_spe == current) + last_task_used_spe = NULL; +#endif memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); current->thread.fpscr = 0; #ifdef CONFIG_ALTIVEC Index: wli-2.6.10-rc3-1/arch/ppc/kernel/signal.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc/kernel/signal.c 2004-12-16 06:19:25.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc/kernel/signal.c 2004-12-22 10:04:35.139460842 -0800 @@ -319,7 +319,7 @@ if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) { /* restore spe registers from the stack */ if (__copy_from_user(current->thread.evr, &sr->mc_vregs, - sizeof(sr->mc_vregs))) + ELF_NEVRREG * sizeof(u32))) return 1; } else if (current->thread.used_spe) memset(¤t->thread.evr, 0, ELF_NEVRREG * sizeof(u32)); Index: wli-2.6.10-rc3-1/arch/ppc/platforms/prep_pci.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc/platforms/prep_pci.c 2004-12-16 06:19:25.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc/platforms/prep_pci.c 2004-12-22 10:04:35.145459930 -0800 @@ -49,10 +49,10 @@ 0, /* Slot 1 - unused */ 5, /* Slot 2 - SCSI - NCR825A */ 0, /* Slot 3 - unused */ - 1, /* Slot 4 - Ethernet - DEC2114x */ + 3, /* Slot 4 - Ethernet - DEC2114x */ 0, /* Slot 5 - unused */ - 3, /* Slot 6 - PCI Card slot #1 */ - 4, /* Slot 7 - PCI Card slot #2 */ + 2, /* Slot 6 - PCI Card slot #1 */ + 3, /* Slot 7 - PCI Card slot #2 */ 5, /* Slot 8 - PCI Card slot #3 */ 5, /* Slot 9 - PCI Bridge */ /* added here in case we ever support PCI bridges */ Index: wli-2.6.10-rc3-1/arch/ppc/syslib/ppc4xx_dma.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc/syslib/ppc4xx_dma.c 2004-12-22 09:07:08.309458650 -0800 +++ wli-2.6.10-rc3-1/arch/ppc/syslib/ppc4xx_dma.c 2004-12-22 10:04:35.148459474 -0800 @@ -466,7 +466,7 @@ /* clear all polarity signals and then "or" in new signal levels */ polarity &= ~GET_DMA_POLARITY(dmanr); - polarity |= p_dma_ch->polarity; + polarity |= p_init->polarity; #if DCRN_POL > 0 mtdcr(DCRN_POL, polarity); #endif Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/entry.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/entry.S 2004-12-16 06:19:25.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/entry.S 2004-12-22 10:04:35.152458866 -0800 @@ -162,7 +162,7 @@ /* check for syscall tracing or audit */ ld r9,TI_FLAGS(r12) - andi. r0,r9,_TIF_SYSCALL_T_OR_A + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) bne- syscall_exit_trace syscall_exit_trace_cont: @@ -265,16 +265,21 @@ _GLOBAL(ppc32_sigsuspend) bl .save_nvgprs bl .sys32_sigsuspend - b syscall_exit + b 70f _GLOBAL(ppc64_rt_sigsuspend) bl .save_nvgprs bl .sys_rt_sigsuspend - b syscall_exit + b 70f _GLOBAL(ppc32_rt_sigsuspend) bl .save_nvgprs bl .sys32_rt_sigsuspend + /* If sigsuspend() returns zero, we are going into a signal handler */ +70: cmpdi 0,r3,0 + beq .ret_from_except + /* If it returned -EINTR, we need to return via syscall_exit to set + the SO bit in cr0 and potentially stop for ptrace. */ b syscall_exit _GLOBAL(ppc_fork) @@ -317,7 +322,7 @@ blt syscall_exit clrrdi r4,r1,THREAD_SHIFT ld r4,TI_FLAGS(r4) - andi. r4,r4,_TIF_SYSCALL_T_OR_A + andi. r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) beq+ 81f bl .do_syscall_trace_leave 81: b .ret_from_except Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/pSeries_lpar.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/pSeries_lpar.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/pSeries_lpar.c 2004-12-22 10:04:35.155458410 -0800 @@ -259,6 +259,22 @@ return found; } +void vpa_init(int cpu) +{ + int hwcpu = get_hard_smp_processor_id(cpu); + unsigned long vpa = (unsigned long)&(paca[cpu].lppaca); + long ret; + unsigned long flags; + + /* Register the Virtual Processor Area (VPA) */ + flags = 1UL << (63 - 18); + ret = register_vpa(flags, hwcpu, __pa(vpa)); + + if (ret) + printk(KERN_ERR "WARNING: vpa_init: VPA registration for " + "cpu %d (hw %d) of area %lx returns %ld\n", + cpu, hwcpu, __pa(vpa), ret); +} long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long prpn, Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/pSeries_setup.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/pSeries_setup.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/pSeries_setup.c 2004-12-22 10:04:35.158457954 -0800 @@ -234,6 +234,9 @@ #endif pSeries_nvram_init(); + + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) + vpa_init(boot_cpuid); } static int __init pSeries_init_panel(void) Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/pSeries_smp.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/pSeries_smp.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/pSeries_smp.c 2004-12-22 10:04:35.160457650 -0800 @@ -59,16 +59,6 @@ extern void pseries_secondary_smp_init(unsigned long); -static void vpa_init(int cpu) -{ - unsigned long flags, pcpu = get_hard_smp_processor_id(cpu); - - /* Register the Virtual Processor Area (VPA) */ - flags = 1UL << (63 - 18); - register_vpa(flags, pcpu, __pa((unsigned long)&(paca[cpu].lppaca))); -} - - /* Get state of physical CPU. * Return codes: * 0 - The processor is in the RTAS stopped state Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/pmac_pci.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/pmac_pci.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/pmac_pci.c 2004-12-22 10:04:35.164457042 -0800 @@ -739,8 +739,8 @@ pmac_check_ht_link(); - /* Tell pci.c to use the common resource allocation mecanism */ - pci_probe_only = 0; + /* Tell pci.c to not use the common resource allocation mecanism */ + pci_probe_only = 1; /* Allow all IO */ io_page_mask = -1; Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/prom_init.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/prom_init.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/prom_init.c 2004-12-22 10:04:35.170456130 -0800 @@ -1108,6 +1108,16 @@ } } +static void __init prom_close_stdin(void) +{ + unsigned long offset = reloc_offset(); + struct prom_t *_prom = PTRRELOC(&prom); + ihandle val; + + if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0) + call_prom("close", 1, 0, val); +} + static int __init prom_find_machine_type(void) { unsigned long offset = reloc_offset(); @@ -1686,6 +1696,9 @@ prom_printf("copying OF device tree ...\n"); flatten_device_tree(); + /* in case stdin is USB and still active on IBM machines... */ + prom_close_stdin(); + /* * Call OF "quiesce" method to shut down pending DMA's from * devices etc... Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/ptrace.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/ptrace.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/ptrace.c 2004-12-22 10:04:35.172455826 -0800 @@ -318,7 +318,8 @@ if (unlikely(current->audit_context)) audit_syscall_exit(current, 0); /* FIXME: pass pt_regs */ - if (test_thread_flag(TIF_SYSCALL_TRACE) + if ((test_thread_flag(TIF_SYSCALL_TRACE) + || test_thread_flag(TIF_SINGLESTEP)) && (current->ptrace & PT_PTRACED)) do_syscall_trace(); } Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/setup.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/setup.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/setup.c 2004-12-22 10:04:35.177455066 -0800 @@ -1020,11 +1020,11 @@ /* set up the bootmem stuff with available memory */ do_init_bootmem(); + ppc_md.setup_arch(); + /* Select the correct idle loop for the platform. */ idle_setup(); - ppc_md.setup_arch(); - paging_init(); ppc64_boot_msg(0x15, "Setup Done"); } Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/signal.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/signal.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/signal.c 2004-12-22 10:04:35.181454458 -0800 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -98,7 +99,7 @@ current->state = TASK_INTERRUPTIBLE; schedule(); if (do_signal(&saveset, regs)) - return regs->gpr[3]; + return 0; } } @@ -387,7 +388,7 @@ return 0; } -static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, +static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for @@ -452,7 +453,10 @@ if (err) goto badframe; - return; + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + + return 1; badframe: #if DEBUG_SIG @@ -460,25 +464,30 @@ regs, frame, newsp); #endif force_sigsegv(signr, current); + return 0; } /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) +static int handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { + int ret; + /* Set up Signal Frame */ - setup_rt_frame(sig, ka, info, oldset, regs); + ret = setup_rt_frame(sig, ka, info, oldset, regs); - if (!(ka->sa.sa_flags & SA_NODEFER)) { + if (ret && !(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } + + return ret; } static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) @@ -538,8 +547,7 @@ /* Whee! Actually deliver the signal. */ if (TRAP(regs) == 0x0C00) syscall_restart(regs, &ka); - handle_signal(signr, &ka, &info, oldset, regs); - return 1; + return handle_signal(signr, &ka, &info, oldset, regs); } if (TRAP(regs) == 0x0C00) { /* System Call! */ Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/signal32.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/signal32.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/signal32.c 2004-12-22 10:04:35.187453546 -0800 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -284,14 +285,12 @@ schedule(); if (do_signal32(&saveset, regs)) /* - * If a signal handler needs to be called, - * do_signal32() has set R3 to the signal number (the - * first argument of the signal handler), so don't - * overwrite that with EINTR ! - * In the other cases, do_signal32() doesn't touch - * R3, so it's still set to -EINTR (see above). + * Returning 0 means we return to userspace via + * ret_from_except and thus restore all user + * registers from *regs. This is what we need + * to do when a signal has been delivered. */ - return regs->gpr[3]; + return 0; } } @@ -587,14 +586,12 @@ schedule(); if (do_signal32(&saveset, regs)) /* - * If a signal handler needs to be called, - * do_signal32() has set R3 to the signal number (the - * first argument of the signal handler), so don't - * overwrite that with EINTR ! - * In the other cases, do_signal32() doesn't touch - * R3, so it's still set to -EINTR (see above). + * Returning 0 means we return to userspace via + * ret_from_except and thus restore all user + * registers from *regs. This is what we need + * to do when a signal has been delivered. */ - return regs->gpr[3]; + return 0; } } @@ -653,9 +650,9 @@ * Set up a signal frame for a "real-time" signal handler * (one which gets siginfo). */ -static void handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, unsigned long newsp) +static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, + struct pt_regs * regs, unsigned long newsp) { struct rt_sigframe32 __user *rt_sf; struct mcontext32 __user *frame; @@ -704,7 +701,10 @@ regs->trap = 0; regs->result = 0; - return; + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + + return 1; badframe: #if DEBUG_SIG @@ -712,6 +712,7 @@ regs, frame, newsp); #endif force_sigsegv(sig, current); + return 0; } static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig) @@ -822,7 +823,7 @@ /* * OK, we're invoking a handler */ -static void handle_signal32(unsigned long sig, struct k_sigaction *ka, +static int handle_signal32(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, unsigned long newsp) { @@ -867,7 +868,10 @@ regs->trap = 0; regs->result = 0; - return; + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + + return 1; badframe: #if DEBUG_SIG @@ -875,6 +879,7 @@ regs, frame, *newspp); #endif force_sigsegv(sig, current); + return 0; } /* @@ -984,11 +989,11 @@ /* Whee! Actually deliver the signal. */ if (ka.sa.sa_flags & SA_SIGINFO) - handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp); + ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp); else - handle_signal32(signr, &ka, &info, oldset, regs, newsp); + ret = handle_signal32(signr, &ka, &info, oldset, regs, newsp); - if (!(ka.sa.sa_flags & SA_NODEFER)) { + if (ret && !(ka.sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka.sa.sa_mask); @@ -997,5 +1002,5 @@ spin_unlock_irq(¤t->sighand->siglock); } - return 1; + return ret; } Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/smp.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/smp.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/smp.c 2004-12-22 10:04:35.190453090 -0800 @@ -76,8 +76,6 @@ extern int cpu_idle(void *unused); void smp_call_function_interrupt(void); -extern long register_vpa(unsigned long flags, unsigned long proc, - unsigned long vpa); int smt_enabled_at_boot = 1; Index: wli-2.6.10-rc3-1/arch/ppc64/kernel/xics.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/ppc64/kernel/xics.c 2004-12-16 06:19:26.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/ppc64/kernel/xics.c 2004-12-22 10:04:35.193452634 -0800 @@ -504,7 +504,7 @@ np; np = of_find_node_by_type(np, "cpu")) { ireg = (uint *)get_property(np, "reg", &ilen); - if (ireg && ireg[0] == hard_smp_processor_id()) { + if (ireg && ireg[0] == boot_cpuid_phys) { ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); i = ilen / sizeof(int); Index: wli-2.6.10-rc3-1/arch/sparc/defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/defconfig 2004-12-22 10:13:19.408759794 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/defconfig 2004-12-22 11:03:28.632288282 -0800 @@ -11,12 +11,12 @@ # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -25,17 +25,21 @@ # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,15 +49,15 @@ # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # -# General setup +# General machine setup # CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y -# CONFIG_SMP is not set CONFIG_SPARC32=y CONFIG_SBUS=y CONFIG_SBUSCHAR=y @@ -66,10 +70,10 @@ CONFIG_PCI=y # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set -CONFIG_SUN_OPENPROMFS=m +CONFIG_SUN_OPENPROMFS=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_MISC=m +CONFIG_BINFMT_MISC=y CONFIG_SUNOS_EMUL=y # @@ -80,6 +84,8 @@ # # Generic Driver Options # +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_DEBUG_DRIVER is not set # @@ -90,7 +96,6 @@ # # Console display driver support # -# CONFIG_MDA_CONSOLE is not set # CONFIG_PROM_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y @@ -102,7 +107,6 @@ # # Serial drivers # -# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support @@ -119,15 +123,14 @@ # # Misc Linux/SPARC drivers # -CONFIG_SUN_OPENPROMIO=m -CONFIG_SUN_MOSTEK_RTC=m +CONFIG_SUN_OPENPROMIO=y +CONFIG_SUN_MOSTEK_RTC=y # CONFIG_SUN_BPP is not set # CONFIG_SUN_VIDEOPIX is not set -# CONFIG_SUN_AURORA is not set # CONFIG_TADPOLE_TS102_UCTRL is not set # CONFIG_SUN_JSFLASH is not set CONFIG_APM_RTC_IS_GMT=y -CONFIG_RTC=m +CONFIG_RTC=y # # Block devices @@ -137,13 +140,22 @@ # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_CARMEL is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -167,9 +179,9 @@ CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR=y # CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SG=y # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs @@ -181,21 +193,22 @@ # # SCSI Transport Attributes # -CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -204,13 +217,14 @@ # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLOGICPTI=m +# CONFIG_SCSI_QLOGICPTI is not set CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set # CONFIG_SCSI_QLA22XX is not set @@ -246,7 +260,7 @@ # CONFIG_PACKET_MMAP is not set CONFIG_NETLINK_DEV=y CONFIG_UNIX=y -CONFIG_NET_KEY=m +CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set @@ -258,28 +272,21 @@ # CONFIG_NET_IPGRE is not set # CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -CONFIG_XFRM_USER=m +# CONFIG_XFRM_USER is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -CONFIG_SCTP_DBG_OBJCNT=y -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y +# CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -292,27 +299,27 @@ # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # -CONFIG_NET_PKTGEN=m +# CONFIG_NET_PKTGEN is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set CONFIG_NETDEVICES=y -CONFIG_DUMMY=m +CONFIG_DUMMY=y # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set -CONFIG_TUN=m +CONFIG_TUN=y # CONFIG_ETHERTAP is not set # @@ -324,11 +331,11 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -CONFIG_MII=m +CONFIG_MII=y CONFIG_SUNLANCE=y -CONFIG_HAPPYMEAL=m -CONFIG_SUNBMAC=m -CONFIG_SUNQE=m +CONFIG_HAPPYMEAL=y +CONFIG_SUNBMAC=y +CONFIG_SUNQE=y # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set @@ -399,34 +406,26 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_JOYDEV=y # CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=m -CONFIG_INPUT_EVBUG=m +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=y # # Input I/O drivers # # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=m +# CONFIG_SERIO is not set # CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=m -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set # # Input Device Drivers # -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=m -CONFIG_KEYBOARD_SUNKBD=m -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_KEYBOARD is not set CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=m -CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set @@ -436,31 +435,23 @@ # File systems # CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT3_FS is not set # CONFIG_JBD is not set -CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -CONFIG_XFS_FS=m -CONFIG_XFS_RT=y -CONFIG_XFS_QUOTA=y -CONFIG_XFS_SECURITY=y -CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=m +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set -CONFIG_QUOTACTL=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set # # CD-ROM/DVD Filesystems # -CONFIG_ISO9660_FS=m +CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set # CONFIG_UDF_FS is not set @@ -468,7 +459,8 @@ # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -478,9 +470,9 @@ CONFIG_PROC_KCORE=y CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS_XATTR=y -# CONFIG_DEVPTS_FS_SECURITY is not set -# CONFIG_TMPFS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -491,8 +483,7 @@ # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set @@ -506,23 +497,22 @@ # Network File Systems # CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFS_DIRECTIO=y # CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y +# CONFIG_ROOT_NFS is not set CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y -CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -CONFIG_AFS_FS=m -CONFIG_RXRPC=m +# CONFIG_AFS_FS is not set # # Partition Types @@ -559,6 +549,7 @@ # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -572,7 +563,7 @@ # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set +CONFIG_NLS_UTF8=y # # Sound @@ -583,6 +574,12 @@ # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# # # USB Gadget Support @@ -598,47 +595,30 @@ # Kernel hacking # CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_HIGHMEM is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set # CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_STACK_USAGE is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # # Cryptographic options # -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO is not set # # Library routines # +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y +CONFIG_LIBCRC32C=y Index: wli-2.6.10-rc3-1/arch/sparc/kernel/entry.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/kernel/entry.S 2004-12-16 06:19:27.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/kernel/entry.S 2004-12-22 10:04:35.200451570 -0800 @@ -1508,7 +1508,7 @@ .globl ret_sys_call ret_sys_call: ld [%curptr + TI_FLAGS], %l6 - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 set PSR_C, %g2 bgeu 1f @@ -1587,7 +1587,7 @@ st %o0, [%sp + STACKFRAME_SZ + PT_I0] set PSR_C, %g2 - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK bgeu 1f ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 @@ -1678,7 +1678,7 @@ st %o0, [%sp + STACKFRAME_SZ + PT_I0] set PSR_C, %g2 - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK bgeu 1f ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 Index: wli-2.6.10-rc3-1/arch/sparc/kernel/pcic.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/kernel/pcic.c 2004-12-22 10:13:57.129025442 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/kernel/pcic.c 2004-12-22 10:44:30.971239050 -0800 @@ -161,7 +161,7 @@ static int pcic0_up; static struct linux_pcic pcic0; -unsigned int pcic_regs; +void * __iomem pcic_regs; volatile int pcic_speculative; volatile int pcic_trapped; @@ -313,8 +313,7 @@ pcic0_up = 1; pcic->pcic_res_regs.name = "pcic_registers"; - pcic->pcic_regs = (unsigned long) - ioremap(regs[0].phys_addr, regs[0].reg_size); + pcic->pcic_regs = ioremap(regs[0].phys_addr, regs[0].reg_size); if (!pcic->pcic_regs) { prom_printf("PCIC: Error, cannot map PCIC registers.\n"); prom_halt(); @@ -328,7 +327,7 @@ } pcic->pcic_res_cfg_addr.name = "pcic_cfg_addr"; - if ((pcic->pcic_config_space_addr = (unsigned long) + if ((pcic->pcic_config_space_addr = ioremap(regs[2].phys_addr, regs[2].reg_size * 2)) == 0) { prom_printf("PCIC: Error, cannot map" "PCI Configuration Space Address.\n"); @@ -340,7 +339,7 @@ * must be the same. Thus, we need adjust size of data. */ pcic->pcic_res_cfg_data.name = "pcic_cfg_data"; - if ((pcic->pcic_config_space_data = (unsigned long) + if ((pcic->pcic_config_space_data = ioremap(regs[3].phys_addr, regs[3].reg_size * 2)) == 0) { prom_printf("PCIC: Error, cannot map" "PCI Configuration Space Data.\n"); @@ -976,7 +975,7 @@ * We do not use horroble macroses here because we want to * advance pointer by sizeof(size). */ -void outsb(unsigned long addr, const void *src, unsigned long count) { +void outsb(void * __iomem addr, const void *src, unsigned long count) { while (count) { count -= 1; writeb(*(const char *)src, addr); @@ -985,7 +984,7 @@ } } -void outsw(unsigned long addr, const void *src, unsigned long count) { +void outsw(void * __iomem addr, const void *src, unsigned long count) { while (count) { count -= 2; writew(*(const short *)src, addr); @@ -994,7 +993,7 @@ } } -void outsl(unsigned long addr, const void *src, unsigned long count) { +void outsl(void * __iomem addr, const void *src, unsigned long count) { while (count) { count -= 4; writel(*(const long *)src, addr); @@ -1003,7 +1002,7 @@ } } -void insb(unsigned long addr, void *dst, unsigned long count) { +void insb(void * __iomem addr, void *dst, unsigned long count) { while (count) { count -= 1; *(unsigned char *)dst = readb(addr); @@ -1012,7 +1011,7 @@ } } -void insw(unsigned long addr, void *dst, unsigned long count) { +void insw(void * __iomem addr, void *dst, unsigned long count) { while (count) { count -= 2; *(unsigned short *)dst = readw(addr); @@ -1021,7 +1020,7 @@ } } -void insl(unsigned long addr, void *dst, unsigned long count) { +void insl(void * __iomem addr, void *dst, unsigned long count) { while (count) { count -= 4; /* Index: wli-2.6.10-rc3-1/arch/sparc/kernel/signal.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/kernel/signal.c 2004-12-22 10:13:57.370988658 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/kernel/signal.c 2004-12-22 10:41:48.597923546 -0800 @@ -1016,6 +1016,7 @@ sigsegv_and_return: force_sig(SIGSEGV, current); + return -EFAULT; } static inline void Index: wli-2.6.10-rc3-1/arch/sparc/kernel/sun4d_smp.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/kernel/sun4d_smp.c 2004-12-22 10:14:01.801315146 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/kernel/sun4d_smp.c 2004-12-22 10:28:47.127725074 -0800 @@ -122,8 +122,7 @@ /* Fix idle thread fields. */ __asm__ __volatile__("ld [%0], %%g6\n\t" - "sta %%g6, [%%g0] %1\n\t" - : : "r" (¤t_set[cpuid]), "i" (ASI_M_VIKING_TMP2) + : : "r" (¤t_set[cpuid]) : "memory" /* paranoid */); cpu_leds[cpuid] = 0x9; @@ -460,25 +459,18 @@ void __init smp4d_blackbox_current(unsigned *addr) { - /* We have a nice Linux current register :) */ - int rd = addr[1] & 0x3e000000; + int rd = *addr & 0x3e000000; - addr[0] = 0x10800006; /* b .+24 */ - addr[1] = 0xc0800820 | rd; /* lda [%g0] ASI_M_VIKING_TMP2, reg */ + addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ + addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */ + addr[4] = 0x01000000; /* nop */ } void __init sun4d_init_smp(void) { int i; - extern unsigned int patchme_store_new_current[]; extern unsigned int t_nmi[], linux_trap_ipi15_sun4d[], linux_trap_ipi15_sun4m[]; - /* Store current into Linux current register :) */ - __asm__ __volatile__("sta %%g6, [%%g0] %0" : : "i"(ASI_M_VIKING_TMP2)); - - /* Patch switch_to */ - patchme_store_new_current[0] = (patchme_store_new_current[0] & 0x3e000000) | 0xc0a00820; - /* Patch ipi15 trap table */ t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); Index: wli-2.6.10-rc3-1/arch/sparc/lib/bitext.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/lib/bitext.c 2004-12-22 10:14:04.510903226 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/lib/bitext.c 2004-12-22 10:22:39.257649826 -0800 @@ -29,10 +29,17 @@ int offset, count; /* siamese twins */ int off_new; int align1; - int i; + int i, color; - if (align == 0) - align = 1; + if (t->num_colors) { + /* align is overloaded to be the page color */ + color = align; + align = t->num_colors; + } else { + color = 0; + if (align == 0) + align = 1; + } align1 = align - 1; if ((align & align1) != 0) BUG(); @@ -40,6 +47,7 @@ BUG(); if (len <= 0 || len > t->size) BUG(); + color &= align1; spin_lock(&t->lock); if (len < t->last_size) @@ -49,7 +57,7 @@ count = 0; for (;;) { off_new = find_next_zero_bit(t->map, t->size, offset); - off_new = (off_new + align1) & ~align1; + off_new = ((off_new + align1) & ~align1) + color; count += off_new - offset; offset = off_new; if (offset >= t->size) @@ -121,6 +129,4 @@ spin_lock_init(&t->lock); t->map = map; t->size = size; - t->last_size = 0; - t->first_free = 0; } Index: wli-2.6.10-rc3-1/arch/sparc/mm/fault.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/mm/fault.c 2004-12-22 10:13:56.349144002 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/mm/fault.c 2004-12-22 10:55:08.495320658 -0800 @@ -294,16 +294,17 @@ * the fault. */ switch (handle_mm_fault(mm, vma, address, write)) { - case 1: - current->min_flt++; - break; - case 2: + case VM_FAULT_SIGBUS: + goto do_sigbus; + case VM_FAULT_OOM: + goto out_of_memory; + case VM_FAULT_MAJOR: current->maj_flt++; break; - case 0: - goto do_sigbus; + case VM_FAULT_MINOR: default: - goto out_of_memory; + current->min_flt++; + break; } up_read(&mm->mmap_sem); return; @@ -535,8 +536,11 @@ if(!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } - if (!handle_mm_fault(mm, vma, address, write)) + switch (handle_mm_fault(mm, vma, address, write)) { + case VM_FAULT_SIGBUS: + case VM_FAULT_OOM: goto do_sigbus; + } up_read(&mm->mmap_sem); return; bad_area: Index: wli-2.6.10-rc3-1/arch/sparc/mm/io-unit.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/mm/io-unit.c 2004-12-22 10:14:01.800315298 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/mm/io-unit.c 2004-12-22 10:28:47.121725986 -0800 @@ -196,7 +196,7 @@ pte_t *ptep; long i; - pgdp = pgd_offset(init_task.mm, addr); + pgdp = pgd_offset(&init_mm, addr); pmdp = pmd_offset(pgdp, addr); ptep = pte_offset_map(pmdp, addr); Index: wli-2.6.10-rc3-1/arch/sparc/mm/iommu.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/mm/iommu.c 2004-12-22 10:14:04.511903074 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/mm/iommu.c 2004-12-22 10:22:39.261649218 -0800 @@ -119,6 +119,13 @@ prom_halt(); } bit_map_init(&iommu->usemap, bitmap, IOMMU_NPTES); + /* To be coherent on HyperSparc, the page color of DVMA + * and physical addresses must match. + */ + if (srmmu_modtype == HyperSparc) + iommu->usemap.num_colors = vac_cache_size >> PAGE_SHIFT; + else + iommu->usemap.num_colors = 1; printk("IOMMU: impl %d vers %d table 0x%p[%d B] map [%d b]\n", impl, vers, iommu->page_table, @@ -128,7 +135,9 @@ } /* This begs to be btfixup-ed by srmmu. */ -static void iommu_viking_flush_iotlb(iopte_t *iopte, unsigned int niopte) +/* Flush the iotlb entries to ram. */ +/* This could be better if we didn't have to flush whole pages. */ +static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte) { unsigned long start; unsigned long end; @@ -145,6 +154,11 @@ viking_flush_page(start); start += PAGE_SIZE; } + } else { + while(start < end) { + __flush_page_to_ram(start); + start += PAGE_SIZE; + } } } @@ -156,7 +170,8 @@ unsigned int busa, busa0; int i; - ioptex = bit_map_string_get(&iommu->usemap, npages, 1); + /* page color = pfn of page */ + ioptex = bit_map_string_get(&iommu->usemap, npages, page_to_pfn(page)); if (ioptex < 0) panic("iommu out"); busa0 = iommu->start + (ioptex << PAGE_SHIFT); @@ -172,8 +187,7 @@ page++; } - iommu_viking_flush_iotlb(iopte0, npages); - flush_cache_all(); // hack to fix dma errors with hypersparc + iommu_flush_iotlb(iopte0, npages); return busa0; } @@ -328,7 +342,9 @@ if ((addr & ~PAGE_MASK) != 0) BUG(); if ((len & ~PAGE_MASK) != 0) BUG(); - ioptex = bit_map_string_get(&iommu->usemap, len >> PAGE_SHIFT, 1); + /* page color = physical address */ + ioptex = bit_map_string_get(&iommu->usemap, len >> PAGE_SHIFT, + addr >> PAGE_SHIFT); if (ioptex < 0) panic("iommu out"); @@ -372,7 +388,7 @@ * to handle the latter case as well. */ flush_cache_all(); - iommu_viking_flush_iotlb(first, len >> PAGE_SHIFT); + iommu_flush_iotlb(first, len >> PAGE_SHIFT); flush_tlb_all(); iommu_invalidate(iommu->regs); Index: wli-2.6.10-rc3-1/arch/sparc/prom/ranges.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc/prom/ranges.c 2004-12-22 10:14:01.802314994 -0800 +++ wli-2.6.10-rc3-1/arch/sparc/prom/ranges.c 2004-12-22 10:28:47.131724466 -0800 @@ -34,7 +34,7 @@ } } -static void +void prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1, struct linux_prom_ranges *ranges2, int nranges2) { Index: wli-2.6.10-rc3-1/arch/sparc64/defconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc64/defconfig 2004-12-16 06:19:27.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/sparc64/defconfig 2004-12-22 10:04:35.208450354 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.10-rc2 -# Tue Nov 16 11:09:23 2004 +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 8 21:14:26 2004 # CONFIG_64BIT=y CONFIG_MMU=y @@ -233,6 +233,7 @@ CONFIG_BLK_DEV_SX8=m CONFIG_BLK_DEV_UB=m # CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_INITRAMFS_SOURCE="" CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 @@ -387,7 +388,6 @@ CONFIG_SCSI_QLOGIC_FC=y CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLOGIC_1280_1040 is not set CONFIG_SCSI_QLOGICPTI=m CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set @@ -1045,6 +1045,11 @@ # Active AVM cards # CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m # # Active Eicon DIVA Server cards @@ -1178,6 +1183,7 @@ CONFIG_I2C_SENSOR=m CONFIG_SENSORS_ADM1021=m CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m CONFIG_SENSORS_ADM1031=m CONFIG_SENSORS_ASB100=m CONFIG_SENSORS_DS1621=m @@ -1439,39 +1445,6 @@ CONFIG_DVB_CORE=m # -# DVB-S (satellite) frontends -# -CONFIG_DVB_STV0299=m -CONFIG_DVB_CX24110=m -CONFIG_DVB_GRUNDIG_29504_491=m -CONFIG_DVB_MT312=m -CONFIG_DVB_VES1X93=m - -# -# DVB-T (terrestrial) frontends -# -CONFIG_DVB_SP887X=m -CONFIG_DVB_ALPS_TDLB7=m -CONFIG_DVB_ALPS_TDMB7=m -CONFIG_DVB_CX22702=m -CONFIG_DVB_GRUNDIG_29504_401=m -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_NXT6000=m -CONFIG_DVB_MT352=m -CONFIG_DVB_DIB3000MB=m - -# -# DVB-C (cable) frontends -# -CONFIG_DVB_ATMEL_AT76C651=m -CONFIG_DVB_VES1820=m - -# -# Misc. Frontend Modules -# -CONFIG_DVB_TWINHAN_DST=m - -# # Supported SAA7146 based PCI Adapters # CONFIG_DVB_AV7110=m @@ -1487,6 +1460,8 @@ # CONFIG_DVB_TTUSB_BUDGET is not set CONFIG_DVB_TTUSB_DEC=m CONFIG_DVB_DIBUSB=m +CONFIG_DVB_DIBUSB_MISDESIGNED_AN2235=y +CONFIG_DVB_DIBCOM_DEBUG=y CONFIG_DVB_CINERGYT2=m # CONFIG_DVB_CINERGYT2_TUNING is not set @@ -1499,6 +1474,45 @@ # Supported BT878 Adapters # CONFIG_DVB_BT8XX=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA80XX=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_DIB3000MB=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_ATMEL_AT76C651=m +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m CONFIG_VIDEO_VIDEOBUF=m @@ -1634,6 +1648,10 @@ # CONFIG_USB_MIDI is not set CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set CONFIG_USB_STORAGE_RW_DETECT=y Index: wli-2.6.10-rc3-1/arch/sparc64/kernel/binfmt_elf32.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc64/kernel/binfmt_elf32.c 2004-12-22 09:07:08.440438738 -0800 +++ wli-2.6.10-rc3-1/arch/sparc64/kernel/binfmt_elf32.c 2004-12-22 10:04:35.210450050 -0800 @@ -79,7 +79,7 @@ #define elf_check_arch(x) (((x)->e_machine == EM_SPARC) || ((x)->e_machine == EM_SPARC32PLUS)) -#define ELF_ET_DYN_BASE 0x08000000 +#define ELF_ET_DYN_BASE 0x70000000 #include Index: wli-2.6.10-rc3-1/arch/sparc64/kernel/entry.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc64/kernel/entry.S 2004-12-16 06:19:27.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/sparc64/kernel/entry.S 2004-12-22 10:04:35.216449138 -0800 @@ -1778,7 +1778,7 @@ stx %l0, [%curptr + TI_FLAGS] 1: - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK bgeu,pn %xcc, 1f andcc %l0, _TIF_SYSCALL_TRACE, %l6 80: Index: wli-2.6.10-rc3-1/arch/sparc64/kernel/smp.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc64/kernel/smp.c 2004-12-22 09:07:08.446437826 -0800 +++ wli-2.6.10-rc3-1/arch/sparc64/kernel/smp.c 2004-12-22 10:04:35.221448378 -0800 @@ -103,15 +103,6 @@ void __init smp_callin(void) { int cpuid = hard_smp_processor_id(); - extern int bigkernel; - extern unsigned long kern_locked_tte_data; - - if (bigkernel) { - prom_dtlb_load(sparc64_highest_locked_tlbent()-1, - kern_locked_tte_data + 0x400000, KERNBASE + 0x400000); - prom_itlb_load(sparc64_highest_locked_tlbent()-1, - kern_locked_tte_data + 0x400000, KERNBASE + 0x400000); - } inherit_locked_prom_mappings(0); Index: wli-2.6.10-rc3-1/arch/sparc64/kernel/trampoline.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc64/kernel/trampoline.S 2004-12-22 09:07:08.450437218 -0800 +++ wli-2.6.10-rc3-1/arch/sparc64/kernel/trampoline.S 2004-12-22 10:04:35.224447922 -0800 @@ -90,7 +90,9 @@ sllx %g2, 32, %g2 wr %g2, 0, %tick_cmpr - /* Call OBP by hand to lock KERNBASE into i/d tlbs. */ + /* Call OBP by hand to lock KERNBASE into i/d tlbs. + * We lock 2 consequetive entries if we are 'bigkernel'. + */ mov %o0, %l0 sethi %hi(prom_entry_lock), %g2 @@ -136,6 +138,46 @@ call %o1 add %sp, (2047 + 128), %o0 + sethi %hi(bigkernel), %g2 + lduw [%g2 + %lo(bigkernel)], %g2 + cmp %g2, 0 + be,pt %icc, do_dtlb + nop + + sethi %hi(call_method), %g2 + or %g2, %lo(call_method), %g2 + stx %g2, [%sp + 2047 + 128 + 0x00] + mov 5, %g2 + stx %g2, [%sp + 2047 + 128 + 0x08] + mov 1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x10] + sethi %hi(itlb_load), %g2 + or %g2, %lo(itlb_load), %g2 + stx %g2, [%sp + 2047 + 128 + 0x18] + sethi %hi(mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + stx %g2, [%sp + 2047 + 128 + 0x20] + sethi %hi(KERNBASE + 0x400000), %g2 + stx %g2, [%sp + 2047 + 128 + 0x28] + sethi %hi(kern_locked_tte_data), %g2 + ldx [%g2 + %lo(kern_locked_tte_data)], %g2 + sethi %hi(0x400000), %g1 + add %g2, %g1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x30] + + mov 14, %g2 + BRANCH_IF_ANY_CHEETAH(g1,g5,1f) + + mov 62, %g2 +1: + stx %g2, [%sp + 2047 + 128 + 0x38] + sethi %hi(p1275buf), %g2 + or %g2, %lo(p1275buf), %g2 + ldx [%g2 + 0x08], %o1 + call %o1 + add %sp, (2047 + 128), %o0 + +do_dtlb: sethi %hi(call_method), %g2 or %g2, %lo(call_method), %g2 stx %g2, [%sp + 2047 + 128 + 0x00] @@ -168,6 +210,47 @@ call %o1 add %sp, (2047 + 128), %o0 + sethi %hi(bigkernel), %g2 + lduw [%g2 + %lo(bigkernel)], %g2 + cmp %g2, 0 + be,pt %icc, do_unlock + nop + + sethi %hi(call_method), %g2 + or %g2, %lo(call_method), %g2 + stx %g2, [%sp + 2047 + 128 + 0x00] + mov 5, %g2 + stx %g2, [%sp + 2047 + 128 + 0x08] + mov 1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x10] + sethi %hi(dtlb_load), %g2 + or %g2, %lo(dtlb_load), %g2 + stx %g2, [%sp + 2047 + 128 + 0x18] + sethi %hi(mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + stx %g2, [%sp + 2047 + 128 + 0x20] + sethi %hi(KERNBASE + 0x400000), %g2 + stx %g2, [%sp + 2047 + 128 + 0x28] + sethi %hi(kern_locked_tte_data), %g2 + ldx [%g2 + %lo(kern_locked_tte_data)], %g2 + sethi %hi(0x400000), %g1 + add %g2, %g1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x30] + + mov 14, %g2 + BRANCH_IF_ANY_CHEETAH(g1,g5,1f) + + mov 62, %g2 +1: + + stx %g2, [%sp + 2047 + 128 + 0x38] + sethi %hi(p1275buf), %g2 + or %g2, %lo(p1275buf), %g2 + ldx [%g2 + 0x08], %o1 + call %o1 + add %sp, (2047 + 128), %o0 + +do_unlock: sethi %hi(prom_entry_lock), %g2 stb %g0, [%g2 + %lo(prom_entry_lock)] membar #StoreStore | #StoreLoad Index: wli-2.6.10-rc3-1/arch/sparc64/solaris/entry64.S =================================================================== --- wli-2.6.10-rc3-1.orig/arch/sparc64/solaris/entry64.S 2004-12-22 09:07:08.456436306 -0800 +++ wli-2.6.10-rc3-1/arch/sparc64/solaris/entry64.S 2004-12-22 10:04:35.226447618 -0800 @@ -109,7 +109,7 @@ sra %o0, 0, %o0 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK sllx %g2, 32, %g2 bgeu,pn %xcc, 1f andcc %l6, _TIF_SYSCALL_TRACE, %l6 Index: wli-2.6.10-rc3-1/arch/um/Kconfig_block =================================================================== --- wli-2.6.10-rc3-1.orig/arch/um/Kconfig_block 2004-12-16 06:19:28.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/um/Kconfig_block 2004-12-22 10:04:35.228447314 -0800 @@ -43,6 +43,10 @@ config BLK_DEV_RAM tristate "RAM disk support" +config BLK_DEV_RAM_COUNT + int "Default number of RAM disks" if BLK_DEV_RAM + default "16" + config BLK_DEV_RAM_SIZE int "Default RAM disk size" depends on BLK_DEV_RAM Index: wli-2.6.10-rc3-1/arch/x86_64/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/arch/x86_64/Kconfig 2004-12-16 06:19:28.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/x86_64/Kconfig 2004-12-22 10:04:35.231446858 -0800 @@ -306,6 +306,7 @@ config GART_IOMMU bool "IOMMU support" + depends on PCI help Support the K8 IOMMU. Needed to run systems with more than 4GB of memory properly with 32-bit PCI devices that do not support DAC (Double Address Index: wli-2.6.10-rc3-1/arch/x86_64/kernel/signal.c =================================================================== --- wli-2.6.10-rc3-1.orig/arch/x86_64/kernel/signal.c 2004-12-16 06:19:28.000000000 -0800 +++ wli-2.6.10-rc3-1/arch/x86_64/kernel/signal.c 2004-12-22 10:04:35.234446402 -0800 @@ -357,7 +357,7 @@ #endif /* Are we from a system call? */ - if (regs->orig_rax >= 0) { + if ((long)regs->orig_rax >= 0) { /* If so, check system call restarting.. */ switch (regs->rax) { case -ERESTART_RESTARTBLOCK: @@ -442,7 +442,7 @@ no_signal: /* Did we come from a system call? */ - if (regs->orig_rax >= 0) { + if ((long)regs->orig_rax >= 0) { /* Restart the system call - no handlers present */ long res = regs->rax; if (res == -ERESTARTNOHAND || Index: wli-2.6.10-rc3-1/drivers/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/Kconfig 2004-12-22 09:07:08.546422626 -0800 +++ wli-2.6.10-rc3-1/drivers/Kconfig 2004-12-22 10:04:35.236446098 -0800 @@ -54,4 +54,6 @@ source "drivers/usb/Kconfig" +source "drivers/mmc/Kconfig" + endmenu Index: wli-2.6.10-rc3-1/drivers/atm/iphase.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/atm/iphase.c 2004-12-16 06:19:29.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/atm/iphase.c 2004-12-22 10:04:35.248444274 -0800 @@ -615,12 +615,13 @@ return tmp; } +static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb); + static int ia_que_tx (IADEV *iadev) { struct sk_buff *skb; int num_desc; struct atm_vcc *vcc; struct ia_vcc *iavcc; - static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb); num_desc = ia_avail_descs(iadev); while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) { Index: wli-2.6.10-rc3-1/drivers/atm/zatm.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/atm/zatm.c 2004-12-16 06:19:29.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/atm/zatm.c 2004-12-22 10:04:35.253443514 -0800 @@ -1605,7 +1605,7 @@ goto out_disable; zatm_dev->pci_dev = pci_dev; - ZATM_DEV(dev) = zatm_dev; + dev = (struct atm_dev *)zatm_dev; zatm_dev->copper = (int)ent->driver_data; if ((ret = zatm_init(dev)) || (ret = zatm_start(dev))) goto out_release; Index: wli-2.6.10-rc3-1/drivers/block/cciss.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/block/cciss.c 2004-12-16 06:19:30.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/block/cciss.c 2004-12-22 10:04:35.263441994 -0800 @@ -1100,7 +1100,7 @@ return(status); } default: - return -EBADRQC; + return -ENOTTY; } } Index: wli-2.6.10-rc3-1/drivers/block/cfq-iosched.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/block/cfq-iosched.c 2004-12-16 06:19:30.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/block/cfq-iosched.c 2004-12-22 10:04:35.269441082 -0800 @@ -867,6 +867,9 @@ struct cfq_data *cfqd = cfqq->cfqd; unsigned long now, elapsed; + if (!blk_fs_request(crq->request)) + return; + /* * accounted bit is necessary since some drivers will call * elv_next_request() many times for the same request (eg ide) @@ -912,6 +915,9 @@ { struct cfq_data *cfqd = cfqq->cfqd; + if (!crq->accounted) + return; + WARN_ON(!cfqd->rq_in_driver); cfqd->rq_in_driver--; Index: wli-2.6.10-rc3-1/drivers/bluetooth/hci_usb.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/bluetooth/hci_usb.c 2004-12-16 06:19:30.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/bluetooth/hci_usb.c 2004-12-22 10:04:35.274440322 -0800 @@ -67,7 +67,7 @@ #endif #ifdef CONFIG_BT_HCIUSB_SCO -static int isoc = 1; +static int isoc = 2; #endif #define VERSION "2.7" @@ -898,7 +898,7 @@ switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { case USB_ENDPOINT_XFER_ISOC: if (ep->desc.wMaxPacketSize < size || - uif->desc.bAlternateSetting > 2) + uif->desc.bAlternateSetting != isoc) break; size = ep->desc.wMaxPacketSize; @@ -1037,7 +1037,7 @@ module_exit(hci_usb_exit); #ifdef CONFIG_BT_HCIUSB_SCO -module_param(isoc, bool, 0); +module_param(isoc, int, 0644); MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support"); #endif Index: wli-2.6.10-rc3-1/drivers/cdrom/sbpcd.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/cdrom/sbpcd.c 2004-12-22 09:07:08.652406514 -0800 +++ wli-2.6.10-rc3-1/drivers/cdrom/sbpcd.c 2004-12-22 10:04:35.293437434 -0800 @@ -1161,11 +1161,11 @@ return; } /*==========================================================================*/ +static int cmd_out_T(void); + static int get_state_T(void) { int i; - - static int cmd_out_T(void); clr_cmdbuf(); current_drive->n_bytes=1; @@ -1308,13 +1308,14 @@ return (i); } /*==========================================================================*/ +static int cc_DriveReset(void); + static int cmd_out_T(void) { #undef CMDT_TRIES #define CMDT_TRIES 1000 #define TEST_FALSE_FF 1 - - static int cc_DriveReset(void); + int i, j, l=0, m, ntries; unsigned long flags; Index: wli-2.6.10-rc3-1/drivers/char/pty.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/char/pty.c 2004-12-16 06:19:31.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/char/pty.c 2004-12-22 10:04:35.296436978 -0800 @@ -55,9 +55,9 @@ if (!tty->link) return; tty->link->packet = 0; + set_bit(TTY_OTHER_CLOSED, &tty->link->flags); wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->write_wait); - set_bit(TTY_OTHER_CLOSED, &tty->link->flags); if (tty->driver->subtype == PTY_TYPE_MASTER) { set_bit(TTY_OTHER_CLOSED, &tty->flags); #ifdef CONFIG_UNIX98_PTYS Index: wli-2.6.10-rc3-1/drivers/char/random.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/char/random.c 2004-12-16 06:19:31.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/char/random.c 2004-12-22 10:04:35.305435610 -0800 @@ -572,8 +572,8 @@ * it's cheap to do so and helps slightly in the expected case where * the entropy is concentrated in the low-order bits. */ -static void add_entropy_words(struct entropy_store *r, const __u32 *in, - int nwords) +static void __add_entropy_words(struct entropy_store *r, const __u32 *in, + int nwords, __u32 out[16]) { static __u32 const twist_table[8] = { 0, 0x3b6e20c8, 0x76dc4190, 0x4db26158, @@ -626,9 +626,23 @@ r->input_rotate = input_rotate; r->add_ptr = add_ptr; + if (out) { + for (i = 0; i < 16; i++) { + out[i] = r->pool[add_ptr]; + add_ptr = (add_ptr - 1) & wordmask; + } + } + spin_unlock_irqrestore(&r->lock, flags); } +static inline void add_entropy_words(struct entropy_store *r, const __u32 *in, + int nwords) +{ + __add_entropy_words(r, in, nwords, NULL); +} + + /* * Credit (or debit) the entropy store with n bits of entropy */ @@ -1342,7 +1356,7 @@ size_t nbytes, int flags) { ssize_t ret, i; - __u32 tmp[TMP_BUF_SIZE]; + __u32 tmp[TMP_BUF_SIZE], data[16]; __u32 x; unsigned long cpuflags; @@ -1422,7 +1436,15 @@ HASH_TRANSFORM(tmp, r->pool+i); add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1); } - + + /* + * To avoid duplicates, we atomically extract a + * portion of the pool while mixing, and hash one + * final time. + */ + __add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1, data); + HASH_TRANSFORM(tmp, data); + /* * In case the hash function has some recognizable * output pattern, we fold it in half. Index: wli-2.6.10-rc3-1/drivers/char/rtc.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/char/rtc.c 2004-12-22 10:13:56.618103114 -0800 +++ wli-2.6.10-rc3-1/drivers/char/rtc.c 2004-12-22 10:52:10.211423930 -0800 @@ -878,7 +878,7 @@ &rtc_fops }; -#ifdef RTC_IRQ +#if defined(RTC_IRQ) && !defined(__sparc__) static irqreturn_t (*rtc_int_handler_ptr)(int irq, void *dev_id, struct pt_regs *regs); #endif Index: wli-2.6.10-rc3-1/drivers/char/vt.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/char/vt.c 2004-12-16 06:19:31.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/char/vt.c 2004-12-22 10:04:35.315434090 -0800 @@ -768,6 +768,8 @@ * [this is to be used together with some user program * like resize that changes the hardware videomode] */ +#define VC_RESIZE_MAXCOL (32767) +#define VC_RESIZE_MAXROW (32767) int vc_resize(int currcons, unsigned int cols, unsigned int lines) { unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; @@ -780,6 +782,9 @@ if (!vc_cons_allocated(currcons)) return -ENXIO; + if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW) + return -EINVAL; + new_cols = (cols ? cols : video_num_columns); new_rows = (lines ? lines : video_num_lines); new_row_size = new_cols << 1; Index: wli-2.6.10-rc3-1/drivers/char/watchdog/ixp4xx_wdt.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/char/watchdog/ixp4xx_wdt.c 2004-12-16 06:19:31.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/char/watchdog/ixp4xx_wdt.c 2004-12-22 10:04:35.317433786 -0800 @@ -216,7 +216,7 @@ module_init(ixp4xx_wdt_init); module_exit(ixp4xx_wdt_exit); -MODULE_AUTHOR("Deepak Saxena ); +MODULE_AUTHOR("Deepak Saxena "); MODULE_DESCRIPTION("IXP4xx Network Processor Watchdog"); module_param(heartbeat, int, 0); Index: wli-2.6.10-rc3-1/drivers/ide/ide-cd.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/ide-cd.c 2004-12-16 06:19:33.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/ide-cd.c 2004-12-22 10:04:35.329431962 -0800 @@ -890,8 +890,14 @@ ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry); return ide_started; } else { + unsigned long flags; + /* packet command */ - HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); + spin_lock_irqsave(&ide_lock, flags); + hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG); + ndelay(400); + spin_unlock_irqrestore(&ide_lock, flags); + return (*handler) (drive); } } @@ -2353,25 +2359,31 @@ /* Read the multisession information. */ if (toc->hdr.first_track != CDROM_LEADOUT) { /* Read the multisession information. */ - stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, + stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp, sizeof(ms_tmp), sense); if (stat) return stat; + + toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba); } else { - ms_tmp.ent.addr.msf.minute = 0; - ms_tmp.ent.addr.msf.second = 2; - ms_tmp.ent.addr.msf.frame = 0; ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT; + toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */ } #if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) + if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) { + /* Re-read multisession information using MSF format */ + stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, + sizeof(ms_tmp), sense); + if (stat) + return stat; + msf_from_bcd (&ms_tmp.ent.addr.msf); + toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute, + ms_tmp.ent.addr.msf.second, + ms_tmp.ent.addr.msf.frame); + } #endif /* not STANDARD_ATAPI */ - toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute, - ms_tmp.ent.addr.msf.second, - ms_tmp.ent.addr.msf.frame); - toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); /* Now try to get the total cdrom capacity. */ Index: wli-2.6.10-rc3-1/drivers/ide/ide-dma.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/ide-dma.c 2004-12-16 06:19:33.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/ide-dma.c 2004-12-22 10:04:35.333431354 -0800 @@ -131,11 +131,9 @@ { "CD-ROM Drive/F5A", "ALL" }, { "WPI CDD-820", "ALL" }, { "SAMSUNG CD-ROM SC-148C", "ALL" }, - { "SAMSUNG CD-ROM SC-148F", "ALL" }, { "SAMSUNG CD-ROM SC", "ALL" }, { "SanDisk SDP3B-64" , "ALL" }, { "SAMSUNG CD-ROM SN-124", "ALL" }, - { "PLEXTOR CD-R PX-W8432T", "ALL" }, { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, { "_NEC DV5800A", "ALL" }, { NULL , NULL } Index: wli-2.6.10-rc3-1/drivers/ide/ide-probe.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/ide-probe.c 2004-12-16 06:19:33.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/ide-probe.c 2004-12-22 10:04:35.338430594 -0800 @@ -1327,9 +1327,6 @@ for (index = 0; index < MAX_HWIFS; ++index) probe[index] = !ide_hwifs[index].present; - /* - * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports - */ for (index = 0; index < MAX_HWIFS; ++index) if (probe[index]) probe_hwif(&ide_hwifs[index]); Index: wli-2.6.10-rc3-1/drivers/ide/legacy/ali14xx.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/legacy/ali14xx.c 2004-12-22 09:07:08.770388578 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/legacy/ali14xx.c 2004-12-22 10:04:35.340430290 -0800 @@ -226,6 +226,8 @@ probe_hwif_init(hwif); probe_hwif_init(mate); + create_proc_ide_interfaces(); + return 0; } Index: wli-2.6.10-rc3-1/drivers/ide/legacy/dtc2278.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/legacy/dtc2278.c 2004-12-22 09:07:08.771388426 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/legacy/dtc2278.c 2004-12-22 10:04:35.342429986 -0800 @@ -141,6 +141,8 @@ probe_hwif_init(hwif); probe_hwif_init(mate); + create_proc_ide_interfaces(); + return 0; } Index: wli-2.6.10-rc3-1/drivers/ide/legacy/ht6560b.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/legacy/ht6560b.c 2004-12-22 09:07:08.772388274 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/legacy/ht6560b.c 2004-12-22 10:04:35.344429682 -0800 @@ -352,6 +352,8 @@ probe_hwif_init(hwif); probe_hwif_init(mate); + create_proc_ide_interfaces(); + return 0; release_region: Index: wli-2.6.10-rc3-1/drivers/ide/legacy/qd65xx.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/legacy/qd65xx.c 2004-12-16 06:19:33.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/legacy/qd65xx.c 2004-12-22 10:04:35.347429226 -0800 @@ -429,6 +429,9 @@ qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA, &qd6500_tune_drive); + + create_proc_ide_interfaces(); + return 1; } @@ -459,6 +462,8 @@ &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + create_proc_ide_interfaces(); + return 1; } else { ide_hwif_t *mate; @@ -477,6 +482,8 @@ &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + create_proc_ide_interfaces(); + return 0; /* no other qd65xx possible */ } } Index: wli-2.6.10-rc3-1/drivers/ide/legacy/umc8672.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/legacy/umc8672.c 2004-12-22 09:07:08.774387970 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/legacy/umc8672.c 2004-12-22 10:04:35.349428922 -0800 @@ -161,6 +161,8 @@ probe_hwif_init(hwif); probe_hwif_init(mate); + create_proc_ide_interfaces(); + return 0; } Index: wli-2.6.10-rc3-1/drivers/ide/pci/alim15x3.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/pci/alim15x3.c 2004-12-16 06:19:33.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/pci/alim15x3.c 2004-12-22 10:04:35.353428314 -0800 @@ -8,6 +8,7 @@ * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) * May be copied or modified under the terms of the GNU General Public License * Copyright (C) 2002 Alan Cox + * ALi (now ULi M5228) support by Clear Zhang * * (U)DMA capable version of ali 1533/1543(C), 1535(D) * @@ -799,8 +800,9 @@ s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; int irq = -1; - - hwif->irq = hwif->channel ? 15 : 14; + + if (hwif->pci_dev->device == PCI_DEVICE_ID_AL_M5229) + hwif->irq = hwif->channel ? 15 : 14; if (isa_dev) { /* @@ -889,6 +891,7 @@ static struct pci_device_id alim15x3_pci_tbl[] = { { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5228, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl); Index: wli-2.6.10-rc3-1/drivers/ide/pci/atiixp.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/pci/atiixp.c 2004-12-16 06:19:33.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/pci/atiixp.c 2004-12-22 10:04:35.355428010 -0800 @@ -347,6 +347,7 @@ static struct pci_device_id atiixp_pci_tbl[] = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl); Index: wli-2.6.10-rc3-1/drivers/ide/pci/pdc202xx_old.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ide/pci/pdc202xx_old.c 2004-12-16 06:19:33.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/ide/pci/pdc202xx_old.c 2004-12-22 10:04:35.359427402 -0800 @@ -230,7 +230,7 @@ { u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10); pci_read_config_word(hwif->pci_dev, 0x50, &CIS); - return ((u8)(CIS & mask)); + return (CIS & mask) ? 1 : 0; } /* Index: wli-2.6.10-rc3-1/drivers/ieee1394/ohci1394.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/ieee1394/ohci1394.c 2004-12-16 06:19:33.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/ieee1394/ohci1394.c 2004-12-22 10:04:35.371425578 -0800 @@ -2933,8 +2933,8 @@ d->ctrlClear = 0; d->cmdPtr = 0; - d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL); - d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); + d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_ATOMIC); + d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC); if (d->buf_cpu == NULL || d->buf_bus == NULL) { PRINT(KERN_ERR, "Failed to allocate dma buffer"); @@ -2945,8 +2945,8 @@ memset(d->buf_bus, 0, d->num_desc * sizeof(dma_addr_t)); d->prg_cpu = kmalloc(d->num_desc * sizeof(struct dma_cmd*), - GFP_KERNEL); - d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); + GFP_ATOMIC); + d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC); if (d->prg_cpu == NULL || d->prg_bus == NULL) { PRINT(KERN_ERR, "Failed to allocate dma prg"); @@ -2956,7 +2956,7 @@ memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*)); memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t)); - d->spb = kmalloc(d->split_buf_size, GFP_KERNEL); + d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC); if (d->spb == NULL) { PRINT(KERN_ERR, "Failed to allocate split buffer"); Index: wli-2.6.10-rc3-1/drivers/input/gameport/fm801-gp.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/input/gameport/fm801-gp.c 2004-12-22 09:07:08.801383866 -0800 +++ wli-2.6.10-rc3-1/drivers/input/gameport/fm801-gp.c 2004-12-22 10:04:35.373425274 -0800 @@ -98,8 +98,8 @@ pci_enable_device(pci); gp->gameport.io = pci_resource_start(pci, 0); if ((gp->res_port = request_region(gp->gameport.io, 0x10, "FM801 GP")) == NULL) { - kfree(gp); printk("unable to grab region 0x%x-0x%x\n", gp->gameport.io, gp->gameport.io + 0x0f); + kfree(gp); return -1; } Index: wli-2.6.10-rc3-1/drivers/isdn/hisax/avm_pci.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/isdn/hisax/avm_pci.c 2004-12-22 09:07:08.831379306 -0800 +++ wli-2.6.10-rc3-1/drivers/isdn/hisax/avm_pci.c 2004-12-22 10:04:35.378424514 -0800 @@ -794,13 +794,13 @@ #ifdef CONFIG_PCI if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, dev_avm))) { + if (pci_enable_device(dev_avm)) + return(0); cs->irq = dev_avm->irq; if (!cs->irq) { printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); return(0); } - if (pci_enable_device(dev_avm)) - return(0); cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); if (!cs->hw.avm.cfg_reg) { printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); Index: wli-2.6.10-rc3-1/drivers/media/common/saa7146_core.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/common/saa7146_core.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/common/saa7146_core.c 2004-12-22 10:04:35.386423298 -0800 @@ -25,11 +25,11 @@ struct semaphore saa7146_devices_lock; static int initialized = 0; -int saa7146_num = 0; +static int saa7146_num = 0; unsigned int saa7146_debug = 0; -MODULE_PARM(saa7146_debug,"i"); +module_param(saa7146_debug, int, 0644); MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)"); #if 0 @@ -48,7 +48,7 @@ * gpio and debi helper functions ****************************************************************************/ -/* write "data" to the gpio-pin "pin" */ +/* write "data" to the gpio-pin "pin" -- unused */ void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data) { u32 value = 0; @@ -67,7 +67,7 @@ } /* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */ -int saa7146_wait_for_debi_done(struct saa7146_dev *dev) +int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) { unsigned long start; @@ -80,6 +80,8 @@ DEB_S(("timed out while waiting for registers getting programmed\n")); return -ETIMEDOUT; } + if (nobusyloop) + msleep(1); } /* wait for transfer to complete */ @@ -92,6 +94,8 @@ DEB_S(("timed out while waiting for transfer completion\n")); return -ETIMEDOUT; } + if (nobusyloop) + msleep(1); } return 0; @@ -248,10 +252,9 @@ /********************************************************************************/ /* interrupt handler */ - static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) { - struct saa7146_dev *dev = (struct saa7146_dev*)dev_id; + struct saa7146_dev *dev = dev_id; u32 isr = 0; /* read out the interrupt status register */ @@ -289,7 +292,7 @@ if (0 != (isr & (MASK_16|MASK_17))) { u32 status = saa7146_read(dev, I2C_STATUS); if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) { - IER_DISABLE(dev, MASK_16|MASK_17); + SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); /* only wake up if we expect something */ if( 0 != dev->i2c_op ) { u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2; @@ -308,7 +311,7 @@ if( 0 != isr ) { ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr)); ERR(("disabling interrupt source(s)!\n")); - IER_DISABLE(dev,isr); + SAA7146_IER_DISABLE(dev,isr); } return IRQ_HANDLED; } @@ -318,16 +321,15 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent) { - unsigned long adr = 0, len = 0; - struct saa7146_dev* dev = kmalloc (sizeof(struct saa7146_dev),GFP_KERNEL); - struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data; struct saa7146_extension* ext = pci_ext->ext; - int err = 0; + struct saa7146_dev *dev; + int err = -ENOMEM; - if (!(dev = kmalloc (sizeof(struct saa7146_dev),GFP_KERNEL))) { + dev = kmalloc(sizeof(struct saa7146_dev), GFP_KERNEL); + if (!dev) { ERR(("out of memory.\n")); - return -ENOMEM; + goto out; } /* clear out mem for sure */ @@ -335,38 +337,37 @@ DEB_EE(("pci:%p\n",pci)); - if (pci_enable_device(pci)) { + err = pci_enable_device(pci); + if (err < 0) { ERR(("pci_enable_device() failed.\n")); - err = -EIO; - goto pci_error; + goto err_free; } /* enable bus-mastering */ pci_set_master(pci); dev->pci = pci; + /* get chip-revision; this is needed to enable bug-fixes */ - if( 0 > pci_read_config_dword(dev->pci, PCI_CLASS_REVISION, &dev->revision)) { + err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision); + if (err < 0) { ERR(("pci_read_config_dword() failed.\n")); - err = -ENODEV; - goto pci_error; + goto err_disable; } dev->revision &= 0xf; /* remap the memory from virtual to physical adress */ - adr = pci_resource_start(pci,0); - len = pci_resource_len(pci,0); - - if (!request_mem_region(pci_resource_start(pci,0), pci_resource_len(pci,0), "saa7146")) { - ERR(("request_mem_region() failed.\n")); - err = -ENODEV; - goto pci_error; - } - if (!(dev->mem = ioremap(adr,len))) { + err = pci_request_region(pci, 0, "saa7146"); + if (err < 0) + goto err_disable; + + dev->mem = ioremap(pci_resource_start(pci, 0), + pci_resource_len(pci, 0)); + if (!dev->mem) { ERR(("ioremap() failed.\n")); err = -ENODEV; - goto ioremap_error; + goto err_release; } /* we don't do a master reset here anymore, it screws up @@ -386,42 +387,40 @@ saa7146_write(dev, MC2, 0xf8000000); /* request an interrupt for the saa7146 */ - if (request_irq(dev->pci->irq, interrupt_hw, SA_SHIRQ | SA_INTERRUPT, - dev->name, dev)) - { + err = request_irq(pci->irq, interrupt_hw, SA_SHIRQ | SA_INTERRUPT, + dev->name, dev); + if (err < 0) { ERR(("request_irq() failed.\n")); - err = -ENODEV; - goto irq_error; + goto err_unmap; } - /* get memory for various stuff */ - dev->d_rps0.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_rps0.dma_handle); - if( NULL == dev->d_rps0.cpu_addr ) { err = -ENOMEM; - goto kmalloc_error_1; - } + + /* get memory for various stuff */ + dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, + &dev->d_rps0.dma_handle); + if (!dev->d_rps0.cpu_addr) + goto err_free_irq; memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM); - dev->d_rps1.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_rps1.dma_handle); - if( NULL == dev->d_rps1.cpu_addr ) { - err = -ENOMEM; - goto kmalloc_error_2; - } + dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, + &dev->d_rps1.dma_handle); + if (!dev->d_rps1.cpu_addr) + goto err_free_rps0; memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM); - dev->d_i2c.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_i2c.dma_handle); - if( NULL == dev->d_i2c.cpu_addr ) { - err = -ENOMEM; - goto kmalloc_error_3; - } + dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, + &dev->d_i2c.dma_handle); + if (!dev->d_i2c.cpu_addr) + goto err_free_rps1; memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM); /* the rest + print status message */ /* create a nice device name */ - sprintf(&dev->name[0], "saa7146 (%d)",saa7146_num); + sprintf(dev->name, "saa7146 (%d)", saa7146_num); - INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision,dev->pci->irq,dev->pci->subsystem_vendor,dev->pci->subsystem_device)); + INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device)); dev->ext = ext; pci_set_drvdata(pci,dev); @@ -438,18 +437,18 @@ /* set some sane pci arbitrition values */ saa7146_write(dev, PCI_BT_V1, 0x1c00101f); - if( 0 != ext->probe) { - if( 0 != ext->probe(dev) ) { - DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); + /* TODO: use the status code of the callback */ + err = -ENODEV; - goto probe_error; - } + + if (ext->probe && ext->probe(dev)) { + DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); + goto err_free_i2c; } - if( 0 != ext->attach(dev,pci_ext) ) { + if (ext->attach(dev, pci_ext)) { DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); - err = -ENODEV; - goto attach_error; + goto err_unprobe; } INIT_LIST_HEAD(&dev->item); @@ -457,30 +456,46 @@ saa7146_num++; err = 0; - goto out; -attach_error: -probe_error: +out: + return err; + +err_unprobe: pci_set_drvdata(pci,NULL); - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle); -kmalloc_error_3: - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle); -kmalloc_error_2: - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle); -kmalloc_error_1: - free_irq(dev->pci->irq, (void *)dev); -irq_error: +err_free_i2c: + pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, + dev->d_i2c.dma_handle); +err_free_rps1: + pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, + dev->d_rps1.dma_handle); +err_free_rps0: + pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, + dev->d_rps0.dma_handle); +err_free_irq: + free_irq(pci->irq, (void *)dev); +err_unmap: iounmap(dev->mem); -ioremap_error: - release_mem_region(adr,len); -pci_error: +err_release: + pci_release_region(pci, 0); +err_disable: + pci_disable_device(pci); +err_free: kfree(dev); -out: - return err; + goto out; } static void saa7146_remove_one(struct pci_dev *pdev) { - struct saa7146_dev* dev = (struct saa7146_dev*) pci_get_drvdata(pdev); + struct saa7146_dev* dev = pci_get_drvdata(pdev); + struct { + void *addr; + dma_addr_t dma; + } dev_map[] = { + { dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle }, + { dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle }, + { dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle }, + { NULL, 0 } + }, *p; + DEB_EE(("dev:%p\n",dev)); dev->ext->detach(dev); @@ -491,17 +506,15 @@ /* disable all irqs, release irq-routine */ saa7146_write(dev, IER, 0); - free_irq(dev->pci->irq, (void *)dev); + free_irq(pdev->irq, dev); - /* free kernel memory */ - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle); - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle); - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle); + for (p = dev_map; p->addr; p++) + pci_free_consistent(pdev, SAA7146_RPS_MEM, p->addr, p->dma); iounmap(dev->mem); - release_mem_region(pci_resource_start(dev->pci,0), pci_resource_len(dev->pci,0)); - + pci_release_region(pdev, 0); list_del(&dev->item); + pci_disable_device(pdev); kfree(dev); saa7146_num--; Index: wli-2.6.10-rc3-1/drivers/media/common/saa7146_fops.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/common/saa7146_fops.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/common/saa7146_fops.c 2004-12-22 10:04:35.389422842 -0800 @@ -1,4 +1,5 @@ #include +#include #define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1) @@ -32,17 +33,6 @@ return 1; } -int saa7146_res_check(struct saa7146_fh *fh, unsigned int bit) -{ - return (fh->resources & bit); -} - -int saa7146_res_locked(struct saa7146_dev *dev, unsigned int bit) -{ - struct saa7146_vv *vv = dev->vv_data; - return (vv->resources & bit); -} - void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) { struct saa7146_dev *dev = fh->dev; Index: wli-2.6.10-rc3-1/drivers/media/common/saa7146_hlp.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/common/saa7146_hlp.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/common/saa7146_hlp.c 2004-12-22 10:04:35.394422082 -0800 @@ -9,11 +9,6 @@ *clip_format |= (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16)); } -static void calculate_bcs_ctrl_register(struct saa7146_dev *dev, int brightness, int contrast, int colour, u32 *bcs_ctrl) -{ - *bcs_ctrl = ((brightness << 24) | (contrast << 16) | (colour << 0)); -} - static void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl) { *hps_ctrl &= ~(MASK_30 | MASK_31 | MASK_28); @@ -62,7 +57,7 @@ }; /* table of attenuation values for horizontal scaling */ -u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0}; +static u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0}; /* calculate horizontal scale registers */ static int calculate_h_scale_registers(struct saa7146_dev *dev, @@ -208,7 +203,7 @@ }; /* table of attenuation values for vertical scaling */ -u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0}; +static u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0}; /* calculate vertical scale registers */ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field, @@ -620,18 +615,6 @@ saa7146_write(dev, MC2, (MASK_05 | MASK_21)); } -void saa7146_set_picture_prop(struct saa7146_dev *dev, int brightness, int contrast, int colour) -{ - u32 bcs_ctrl = 0; - - calculate_bcs_ctrl_register(dev, brightness, contrast, colour, &bcs_ctrl); - saa7146_write(dev, BCS_CTRL, bcs_ctrl); - - /* update the bcs register */ - saa7146_write(dev, MC2, (MASK_06 | MASK_22)); -} - - /* select input-source */ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync) { Index: wli-2.6.10-rc3-1/drivers/media/common/saa7146_i2c.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/common/saa7146_i2c.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/common/saa7146_i2c.c 2004-12-22 10:04:35.397421626 -0800 @@ -1,7 +1,7 @@ #include #include -u32 saa7146_i2c_func(struct i2c_adapter *adapter) +static u32 saa7146_i2c_func(struct i2c_adapter *adapter) { //fm DEB_I2C(("'%s'.\n", adapter->name)); @@ -190,7 +190,7 @@ saa7146_write(dev, I2C_TRANSFER, *dword); dev->i2c_op = 1; - IER_ENABLE(dev, MASK_16|MASK_17); + SAA7146_IER_ENABLE(dev, MASK_16|MASK_17); saa7146_write(dev, MC2, (MASK_00 | MASK_16)); wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0); Index: wli-2.6.10-rc3-1/drivers/media/common/saa7146_vbi.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/common/saa7146_vbi.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/common/saa7146_vbi.c 2004-12-22 10:04:35.400421170 -0800 @@ -91,7 +91,7 @@ saa7146_write(dev, MC2, MASK_04|MASK_20); /* enable rps1 irqs */ - IER_ENABLE(dev,MASK_28); + SAA7146_IER_ENABLE(dev,MASK_28); /* prepare to wait to be woken up by the irq-handler */ add_wait_queue(&vv->vbi_wq, &wait); @@ -109,7 +109,7 @@ current->state = TASK_RUNNING; /* disable rps1 irqs */ - IER_DISABLE(dev,MASK_28); + SAA7146_IER_DISABLE(dev,MASK_28); /* stop video-dma3 */ saa7146_write(dev, MC1, MASK_20); @@ -130,7 +130,7 @@ return 0; } -void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) +static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) { struct saa7146_vv *vv = dev->vv_data; @@ -190,7 +190,7 @@ WRITE_RPS1(CMD_STOP); /* enable rps1 irqs */ - IER_ENABLE(dev, MASK_28); + SAA7146_IER_ENABLE(dev, MASK_28); /* write the address of the rps-program */ saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); @@ -325,7 +325,7 @@ saa7146_write(dev, MC1, MASK_29); /* disable rps1 irqs */ - IER_DISABLE(dev, MASK_28); + SAA7146_IER_DISABLE(dev, MASK_28); /* shut down dma 3 transfers */ saa7146_write(dev, MC1, MASK_20); Index: wli-2.6.10-rc3-1/drivers/media/common/saa7146_video.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/common/saa7146_video.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/common/saa7146_video.c 2004-12-22 10:04:35.405420410 -0800 @@ -2,7 +2,7 @@ static int max_memory = 32; -MODULE_PARM(max_memory,"i"); +module_param(max_memory, int, 0644); MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)"); #define IS_CAPTURE_ACTIVE(fh) \ @@ -760,7 +760,7 @@ saa7146_write(dev, MC2, MASK_27 ); /* enable rps0 irqs */ - IER_ENABLE(dev, MASK_27); + SAA7146_IER_ENABLE(dev, MASK_27); vv->video_fh = fh; vv->video_status = STATUS_CAPTURE; @@ -805,7 +805,7 @@ saa7146_write(dev, MC1, MASK_28); /* disable rps0 irqs */ - IER_DISABLE(dev, MASK_27); + SAA7146_IER_DISABLE(dev, MASK_27); /* shut down all used video dma transfers */ saa7146_write(dev, MC1, dmas); Index: wli-2.6.10-rc3-1/drivers/media/dvb/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/Kconfig 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/Kconfig 2004-12-22 10:04:35.407420106 -0800 @@ -21,8 +21,6 @@ source "drivers/media/dvb/dvb-core/Kconfig" -source "drivers/media/dvb/frontends/Kconfig" - comment "Supported SAA7146 based PCI Adapters" depends on DVB_CORE && PCI source "drivers/media/dvb/ttpci/Kconfig" @@ -42,5 +40,8 @@ depends on DVB_CORE && PCI source "drivers/media/dvb/bt8xx/Kconfig" -endmenu +comment "Supported DVB Frontends" + depends on DVB_CORE +source "drivers/media/dvb/frontends/Kconfig" +endmenu Index: wli-2.6.10-rc3-1/drivers/media/dvb/b2c2/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/b2c2/Kconfig 2004-12-22 09:07:08.875372618 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/b2c2/Kconfig 2004-12-22 10:04:35.409419802 -0800 @@ -1,8 +1,24 @@ config DVB_B2C2_SKYSTAR - tristate "Technisat Skystar2 PCI" + tristate "B2C2/Technisat Air/Sky/CableStar 2 PCI" depends on DVB_CORE && PCI + select DVB_STV0299 + select DVB_MT352 + select DVB_MT312 help Support for the Skystar2 PCI DVB card by Technisat, which is equipped with the FlexCopII chipset by B2C2. Say Y if you own such a device and want to use it. + +config DVB_B2C2_USB + tristate "B2C2/Technisat Air/Sky/Cable2PC USB" + depends on DVB_CORE && USB && EXPERIMENTAL + select DVB_STV0299 + select DVB_MT352 + help + Support for the Air/Sky/Cable2PC USB DVB device by B2C2. Currently + this does nothing, but providing basic function for the used usb + protocol. + + Say Y if you own such a device and want to use it. + Index: wli-2.6.10-rc3-1/drivers/media/dvb/b2c2/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/b2c2/Makefile 2004-12-22 09:07:08.875372618 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/b2c2/Makefile 2004-12-22 10:04:35.411419498 -0800 @@ -1,3 +1,6 @@ +obj-b2c2-usb = b2c2-usb-core.o b2c2-common.o + obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o +obj-$(CONFIG_DVB_B2C2_USB) + = b2c2-usb.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ Index: wli-2.6.10-rc3-1/drivers/media/dvb/b2c2/skystar2.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/b2c2/skystar2.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/b2c2/skystar2.c 2004-12-22 10:04:35.426417218 -0800 @@ -50,6 +50,9 @@ #include "dvbdev.h" #include "demux.h" #include "dvb_net.h" +#include "stv0299.h" +#include "mt352.h" +#include "mt312.h" static int debug; @@ -77,6 +80,9 @@ u8 *buffer; }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) +#define __iomem +#endif struct adapter { struct pci_dev *pdev; @@ -118,6 +124,9 @@ int pid_count; int whole_bandwidth_count; u32 mac_filter; + + struct dvb_frontend* fe; + int (*fe_sleep)(struct dvb_frontend* fe); }; #define write_reg_dw(adapter,reg,value) writel(value, adapter->io_mem + reg) @@ -297,13 +306,6 @@ for (i = 0; i < num; i++) { ddprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i, msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len); - - /* allow only the mt312, mt352 and stv0299 frontends to access the bus */ - if ((msgs[i].addr != 0x0e) && (msgs[i].addr != 0x68) && - (msgs[i].addr != 0x61) && (msgs[i].addr != 0x0f)) { - up(&tmp->i2c_sem); - return -EREMOTEIO; - } } // read command @@ -314,10 +316,10 @@ up(&tmp->i2c_sem); if (ret != msgs[1].len) { - printk("%s: read error !\n", __FUNCTION__); + dprintk("%s: read error !\n", __FUNCTION__); for (i = 0; i < 2; i++) { - printk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i, + dprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i, msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len); } @@ -337,9 +339,9 @@ up(&tmp->i2c_sem); if (ret != msgs[0].len - 1) { - printk("%s: write error %i !\n", __FUNCTION__, ret); + dprintk("%s: write error %i !\n", __FUNCTION__, ret); - printk("message %d: flags=0x%x, addr=0x%x, buf[0]=0x%x, len=%d \n", i, + dprintk("message %d: flags=0x%x, addr=0x%x, buf[0]=0x%x, len=%d \n", i, msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len); return -EREMOTEIO; @@ -785,7 +787,7 @@ return flex_i2c_read(adapter, 0x20000000, 0x50, addr, buf, len); } -u8 calc_lrc(u8 *buf, int len) +static u8 calc_lrc(u8 *buf, int len) { int i; u8 sum; @@ -1773,6 +1775,7 @@ if (adapter->io_mem) iounmap(adapter->io_mem); + if (adapter != 0) kfree(adapter); } @@ -2134,12 +2137,11 @@ return 0; } - -int soft_diseqc(struct adapter *adapter, unsigned int cmd, void *arg) +static int flexcop_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { - switch (cmd) { - case FE_SET_TONE: - switch ((fe_sec_tone_mode_t) arg) { + struct adapter* adapter = (struct adapter*) fe->dvb->priv; + + switch(tone) { case SEC_TONE_ON: set_tuner_tone(adapter, 1); break; @@ -2149,129 +2151,312 @@ default: return -EINVAL; }; - break; - case FE_DISEQC_SEND_MASTER_CMD: + return 0; +} + +static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) { - struct dvb_diseqc_master_cmd *cmd = arg; + struct adapter* adapter = (struct adapter*) fe->dvb->priv; send_diseqc_msg(adapter, cmd->msg_len, cmd->msg, 0); - break; + + return 0; } - case FE_DISEQC_SEND_BURST: - send_diseqc_msg(adapter, 0, NULL, (unsigned long) arg); - break; +static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +{ + struct adapter* adapter = (struct adapter*) fe->dvb->priv; - default: - return -EOPNOTSUPP; - }; + send_diseqc_msg(adapter, 0, NULL, minicmd); return 0; } -static int flexcop_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int flexcop_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { - struct adapter *adapter = fe->before_after_data; + struct adapter* adapter = (struct adapter*) fe->dvb->priv; - struct dvb_frontend_info info; + dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__); - fe->ioctl(fe, FE_GET_INFO, &info); - - // we must use different DiSEqC hw + switch (voltage) { + case SEC_VOLTAGE_13: + dprintk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13); + set_tuner_polarity(adapter, 1); + return 0; - if (strcmp(info.name, "Zarlink MT312") == 0) { - //VP310 using mt312 driver for tuning only: diseqc not wired - //use FCII instead - if (!soft_diseqc(adapter, cmd, arg)) + case SEC_VOLTAGE_18: + dprintk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18); + set_tuner_polarity(adapter, 2); return 0; + + default: + return -EINVAL; + } } - switch (cmd) { - case FE_SLEEP: +static int flexcop_sleep(struct dvb_frontend* fe) { - dprintk("%s: FE_SLEEP\n", __FUNCTION__); + struct adapter* adapter = (struct adapter*) fe->dvb->priv; + dprintk("%s: FE_SLEEP\n", __FUNCTION__); set_tuner_polarity(adapter, 0); - // return -EOPNOTSUPP, to make DVB core also send "FE_SLEEP" command to frontend. - return -EOPNOTSUPP; + if (adapter->fe_sleep) return adapter->fe_sleep(fe); + return 0; } - case FE_SET_VOLTAGE: +static u32 flexcop_i2c_func(struct i2c_adapter *adapter) { - dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__); - - switch ((fe_sec_voltage_t) arg) { - case SEC_VOLTAGE_13: + printk("flexcop_i2c_func\n"); - dprintk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13); + return I2C_FUNC_I2C; +} - set_tuner_polarity(adapter, 1); +static struct i2c_algorithm flexcop_algo = { + .name = "flexcop i2c algorithm", + .id = I2C_ALGO_BIT, + .master_xfer = master_xfer, + .functionality = flexcop_i2c_func, +}; - return 0; - case SEC_VOLTAGE_18: - dprintk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18); - set_tuner_polarity(adapter, 2); +static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; - return 0; + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } + + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); - default: + return 0; +} - return -EINVAL; - }; - } +static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + struct adapter* adapter = (struct adapter*) fe->dvb->priv; + div = params->frequency / 125; - default: + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x84; // 0xC4 + buf[3] = 0x08; - return -EOPNOTSUPP; - }; + if (params->frequency < 1500000) buf[3] |= 0x10; + if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } +static u8 samsung_tbmu24112_inittab[] = { + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7D, + 0x05, 0x35, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0xC3, + 0x0C, 0x00, + 0x0D, 0x81, + 0x0E, 0x23, + 0x0F, 0x12, + 0x10, 0x7E, + 0x11, 0x84, + 0x12, 0xB9, + 0x13, 0x88, + 0x14, 0x89, + 0x15, 0xC9, + 0x16, 0x00, + 0x17, 0x5C, + 0x18, 0x00, + 0x19, 0x00, + 0x1A, 0x00, + 0x1C, 0x00, + 0x1D, 0x00, + 0x1E, 0x00, + 0x1F, 0x3A, + 0x20, 0x2E, + 0x21, 0x80, + 0x22, 0xFF, + 0x23, 0xC1, + 0x28, 0x00, + 0x29, 0x1E, + 0x2A, 0x14, + 0x2B, 0x0F, + 0x2C, 0x09, + 0x2D, 0x05, + 0x31, 0x1F, + 0x32, 0x19, + 0x33, 0xFE, + 0x34, 0x93, + 0xff, 0xff, + }; + +static struct stv0299_config samsung_tbmu24112_config = { + .demod_address = 0x68, + .inittab = samsung_tbmu24112_inittab, + .mclk = 88000000UL, + .invert = 0, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_LK, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, + .pll_set = samsung_tbmu24112_pll_set, +}; + + + -static int client_register(struct i2c_client *client) + +static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) { - struct adapter *adapter = (struct adapter*)i2c_get_adapdata(client->adapter); + static u8 mt352_clock_config [] = { 0x89, 0x10, 0x2d }; + static u8 mt352_reset [] = { 0x50, 0x80 }; + static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 }; + static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; + + mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(fe, mt352_reset, sizeof(mt352_reset)); + mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - dprintk("client_register\n"); + mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); + mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - if (client->driver->command) - return client->driver->command(client, FE_REGISTER, adapter->dvb_adapter); return 0; } -static int client_unregister(struct i2c_client *client) +int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) { - struct adapter *adapter = (struct adapter*)i2c_get_adapdata(client->adapter); + u32 div; + unsigned char bs = 0; + + #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; - dprintk("client_unregister\n"); + if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09; + if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a; + if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08; + + pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address + pllbuf[1] = div >> 8; + pllbuf[2] = div & 0xff; + pllbuf[3] = 0xcc; + pllbuf[4] = bs; - if (client->driver->command) - return client->driver->command(client, FE_UNREGISTER, adapter->dvb_adapter); return 0; } -u32 flexcop_i2c_func(struct i2c_adapter *adapter) +static struct mt352_config samsung_tdtc9251dh0_config = { + + .demod_address = 0x0f, + .demod_init = samsung_tdtc9251dh0_demod_init, + .pll_set = samsung_tdtc9251dh0_pll_set, +}; + +static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - printk("flexcop_i2c_func\n"); + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + struct adapter* adapter = (struct adapter*) fe->dvb->priv; - return I2C_FUNC_I2C; + div = (params->frequency + (125/2)) / 125; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = (div >> 0) & 0xff; + buf[2] = 0x84 | ((div >> 10) & 0x60); + buf[3] = 0x80; + + if (params->frequency < 1550000) + buf[3] |= 0x02; + + if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; } -static struct i2c_algorithm flexcop_algo = { - .name = "flexcop i2c algorithm", - .id = I2C_ALGO_BIT, - .master_xfer = master_xfer, - .functionality = flexcop_i2c_func, +static struct mt312_config skystar23_samsung_tbdu18132_config = { + + .demod_address = 0x0e, + .pll_set = skystar23_samsung_tbdu18132_pll_set, }; + + +static void frontend_init(struct adapter *skystar2) +{ + switch(skystar2->pdev->device) { + case 0x2103: // Technisat Skystar2 OR Technisat Airstar2 + + // try the skystar2 v2.6 first (stv0299/Samsung tbmu24112(sl1935)) + skystar2->fe = stv0299_attach(&samsung_tbmu24112_config, &skystar2->i2c_adap); + if (skystar2->fe != NULL) { + skystar2->fe->ops->set_voltage = flexcop_set_voltage; + skystar2->fe_sleep = skystar2->fe->ops->sleep; + skystar2->fe->ops->sleep = flexcop_sleep; + break; +} + + // try the airstar2 (mt352/Samsung tdtc9251dh0(??)) + skystar2->fe = mt352_attach(&samsung_tdtc9251dh0_config, &skystar2->i2c_adap); + if (skystar2->fe != NULL) { + skystar2->fe->ops->info.frequency_min = 474000000; + skystar2->fe->ops->info.frequency_max = 858000000; + break; + } + + // try the skystar2 v2.3 (vp310/Samsung tbdu18132(tsa5059)) + skystar2->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &skystar2->i2c_adap); + if (skystar2->fe != NULL) { + skystar2->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; + skystar2->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst; + skystar2->fe->ops->set_tone = flexcop_set_tone; + skystar2->fe->ops->set_voltage = flexcop_set_voltage; + skystar2->fe_sleep = skystar2->fe->ops->sleep; + skystar2->fe->ops->sleep = flexcop_sleep; + break; + } + break; + } + + if (skystar2->fe == NULL) { + printk("skystar2: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + skystar2->pdev->vendor, + skystar2->pdev->device, + skystar2->pdev->subsystem_vendor, + skystar2->pdev->subsystem_device); + } else { + if (dvb_register_frontend(skystar2->dvb_adapter, skystar2->fe)) { + printk("skystar2: Frontend registration failed!\n"); + if (skystar2->fe->ops->release) + skystar2->fe->ops->release(skystar2->fe); + skystar2->fe = NULL; + } + } +} + + static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct adapter *adapter; @@ -2298,8 +2483,10 @@ adapter = (struct adapter *) pci_get_drvdata(pdev); + dvb_adapter->priv = adapter; adapter->dvb_adapter = dvb_adapter; + init_MUTEX(&adapter->i2c_sem); @@ -2316,16 +2503,12 @@ adapter->i2c_adap.algo = &flexcop_algo; adapter->i2c_adap.algo_data = NULL; adapter->i2c_adap.id = I2C_ALGO_BIT; - adapter->i2c_adap.client_register = client_register; - adapter->i2c_adap.client_unregister = client_unregister; if (i2c_add_adapter(&adapter->i2c_adap) < 0) { dvb_unregister_adapter (adapter->dvb_adapter); return -ENOMEM; } - dvb_add_frontend_ioctls(adapter->dvb_adapter, flexcop_diseqc_ioctl, NULL, adapter); - dvbdemux = &adapter->demux; dvbdemux->priv = (void *) adapter; @@ -2361,6 +2544,9 @@ return ret; dvb_net_init(adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx); + + frontend_init(adapter); + return 0; } @@ -2385,9 +2571,9 @@ dvb_dmxdev_release(&adapter->dmxdev); dvb_dmx_release(&adapter->demux); - if (adapter->dvb_adapter != NULL) { - dvb_remove_frontend_ioctls(adapter->dvb_adapter, flexcop_diseqc_ioctl, NULL); + if (adapter->fe != NULL) dvb_unregister_frontend(adapter->fe); + if (adapter->dvb_adapter != NULL) { i2c_del_adapter(&adapter->i2c_adap); dvb_unregister_adapter(adapter->dvb_adapter); @@ -2398,7 +2584,7 @@ static struct pci_device_id skystar2_pci_tbl[] = { {0x000013d0, 0x00002103, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000}, - {0x000013d0, 0x00002200, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000}, //FCIII +/* {0x000013d0, 0x00002200, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000}, UNDEFINED HARDWARE - mail linuxtv.org list */ //FCIII {0,}, }; Index: wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/bt8xx/Kconfig 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/Kconfig 2004-12-22 10:04:35.428416914 -0800 @@ -1,6 +1,8 @@ config DVB_BT8XX tristate "Nebula/Pinnacle PCTV/Twinhan PCI cards" depends on DVB_CORE && PCI && VIDEO_BT848 + select DVB_MT352 + select DVB_SP887X help Support for PCI cards based on the Bt8xx PCI bridge. Examples are the Nebula cards, the Pinnacle PCTV cards and Twinhan DST cards. Index: wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/bt8xx/Makefile 2004-12-22 09:07:08.878372162 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/Makefile 2004-12-22 10:04:35.430416610 -0800 @@ -1,5 +1,5 @@ -obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o +obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends Index: wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/bt878.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/bt8xx/bt878.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/bt878.c 2004-12-22 10:04:35.433416154 -0800 @@ -44,7 +44,7 @@ #include "dmxdev.h" #include "dvbdev.h" #include "bt878.h" -#include "dst-bt878.h" +#include "dst_priv.h" /**************************************/ @@ -559,22 +559,11 @@ static int bt878_pci_driver_registered = 0; -/* This will be used later by dvb-bt8xx to only use the audio - * dma of certain cards */ -int bt878_find_audio_dma(void) -{ - // pci_register_driver(&bt878_pci_driver); - bt878_pci_driver_registered = 1; - return 0; -} - -EXPORT_SYMBOL(bt878_find_audio_dma); - /*******************************/ /* Module management functions */ /*******************************/ -int bt878_init_module(void) +static int bt878_init_module(void) { bt878_num = 0; bt878_pci_driver_registered = 0; @@ -586,13 +575,13 @@ /* bt878_check_chipset(); */ - /* later we register inside of bt878_find_audio_dma + /* later we register inside of bt878_find_audio_dma() * because we may want to ignore certain cards */ bt878_pci_driver_registered = 1; return pci_module_init(&bt878_pci_driver); } -void bt878_cleanup_module(void) +static void bt878_cleanup_module(void) { if (bt878_pci_driver_registered) { bt878_pci_driver_registered = 0; @@ -601,12 +590,10 @@ return; } -EXPORT_SYMBOL(bt878_init_module); -EXPORT_SYMBOL(bt878_cleanup_module); module_init(bt878_init_module); module_exit(bt878_cleanup_module); - +//MODULE_AUTHOR("XXX"); MODULE_LICENSE("GPL"); /* Index: wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/dvb-bt8xx.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/bt8xx/dvb-bt8xx.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/dvb-bt8xx.c 2004-12-22 10:04:35.469410682 -0800 @@ -126,7 +126,286 @@ return NULL; } -static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card) + +static int thomson_dtt7579_demod_init(struct dvb_frontend* fe) +{ + static u8 mt352_clock_config [] = { 0x89, 0x38, 0x38 }; + static u8 mt352_reset [] = { 0x50, 0x80 }; + static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0x20 }; + static u8 mt352_gpp_ctl_cfg [] = { 0x75, 0x33 }; + static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; + + mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(fe, mt352_reset, sizeof(mt352_reset)); + mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); + + mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); + mt352_write(fe, mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg)); + mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); + + return 0; +} + +static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +{ + u32 div; + unsigned char bs = 0; + unsigned char cp = 0; + + #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; + + if (params->frequency < 542000000) cp = 0xb4; + else if (params->frequency < 771000000) cp = 0xbc; + else cp = 0xf4; + + if (params->frequency == 0) bs = 0x03; + else if (params->frequency < 443250000) bs = 0x02; + else bs = 0x08; + + pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address + pllbuf[1] = div >> 8; + pllbuf[2] = div & 0xff; + pllbuf[3] = cp; + pllbuf[4] = bs; + + return 0; +} + +static struct mt352_config thomson_dtt7579_config = { + + .demod_address = 0x0f, + .demod_init = thomson_dtt7579_demod_init, + .pll_set = thomson_dtt7579_pll_set, +}; + + + +static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; + u8 cfg, cpump, band_select; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (36000000 + params->frequency + 83333) / 166666; + cfg = 0x88; + + if (params->frequency < 175000000) cpump = 2; + else if (params->frequency < 390000000) cpump = 1; + else if (params->frequency < 470000000) cpump = 2; + else if (params->frequency < 750000000) cpump = 2; + else cpump = 3; + + if (params->frequency < 175000000) band_select = 0x0e; + else if (params->frequency < 470000000) band_select = 0x05; + else band_select = 0x03; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = ((div >> 10) & 0x60) | cfg; + data[3] = cpump | band_select; + + i2c_transfer(card->i2c_adapter, &msg, 1); + return (div * 166666 - 36000000); +} + +static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) +{ + struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv; + + return request_firmware(fw, name, &bt->bt->dev->dev); +} + +struct sp887x_config microtune_mt7202dtf_config = { + + .demod_address = 0x70, + .pll_set = microtune_mt7202dtf_pll_set, + .request_firmware = microtune_mt7202dtf_request_firmware, +}; + + + +static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) +{ + static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d }; + static u8 mt352_reset [] = { 0x50, 0x80 }; + static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static u8 mt352_agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x40, 0x40 }; + static u8 mt352_av771_extra[] = { 0xB5, 0x7A }; + static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; + + + mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(fe, mt352_reset, sizeof(mt352_reset)); + mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); + + mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg)); + udelay(2000); + mt352_write(fe, mt352_av771_extra,sizeof(mt352_av771_extra)); + mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); + + return 0; +} + +static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +{ + u32 div; + unsigned char bs = 0; + unsigned char cp = 0; + + #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; + + if (params->frequency < 150000000) cp = 0xB4; + else if (params->frequency < 173000000) cp = 0xBC; + else if (params->frequency < 250000000) cp = 0xB4; + else if (params->frequency < 400000000) cp = 0xBC; + else if (params->frequency < 420000000) cp = 0xF4; + else if (params->frequency < 470000000) cp = 0xFC; + else if (params->frequency < 600000000) cp = 0xBC; + else if (params->frequency < 730000000) cp = 0xF4; + else cp = 0xFC; + + if (params->frequency < 150000000) bs = 0x01; + else if (params->frequency < 173000000) bs = 0x01; + else if (params->frequency < 250000000) bs = 0x02; + else if (params->frequency < 400000000) bs = 0x02; + else if (params->frequency < 420000000) bs = 0x02; + else if (params->frequency < 470000000) bs = 0x02; + else if (params->frequency < 600000000) bs = 0x08; + else if (params->frequency < 730000000) bs = 0x08; + else bs = 0x08; + + pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address + pllbuf[1] = div >> 8; + pllbuf[2] = div & 0xff; + pllbuf[3] = cp; + pllbuf[4] = bs; + + return 0; +} + +static struct mt352_config advbt771_samsung_tdtc9251dh0_config = { + + .demod_address = 0x0f, + .demod_init = advbt771_samsung_tdtc9251dh0_demod_init, + .pll_set = advbt771_samsung_tdtc9251dh0_pll_set, +}; + + +static struct dst_config dst_config = { + + .demod_address = 0x55, +}; + + +static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) }; + + div = (params->frequency + 36166667) / 166667; + + buf[0] = (div >> 8) & 0x7F; + buf[1] = div & 0xFF; + buf[2] = 0x85; + if ((params->frequency >= 47000000) && (params->frequency < 153000000)) + buf[3] = 0x01; + else if ((params->frequency >= 153000000) && (params->frequency < 430000000)) + buf[3] = 0x02; + else if ((params->frequency >= 430000000) && (params->frequency < 824000000)) + buf[3] = 0x0C; + else if ((params->frequency >= 824000000) && (params->frequency < 863000000)) + buf[3] = 0x8C; + else + return -EINVAL; + + i2c_transfer(card->i2c_adapter, &msg, 1); + return 0; +} + +static struct nxt6000_config vp3021_alps_tded4_config = { + + .demod_address = 0x0a, + .clock_inversion = 1, + .pll_set = vp3021_alps_tded4_pll_set, +}; + + +static void frontend_init(struct dvb_bt8xx_card *card, u32 type) +{ + switch(type) { +#ifdef BTTV_DVICO_DVBT_LITE + case BTTV_DVICO_DVBT_LITE: + card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter); + if (card->fe != NULL) { + card->fe->ops->info.frequency_min = 174000000; + card->fe->ops->info.frequency_max = 862000000; + break; + } + break; +#endif + +#ifdef BTTV_TWINHAN_VP3021 + case BTTV_TWINHAN_VP3021: +#else + case BTTV_NEBULA_DIGITV: +#endif + card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter); + if (card->fe != NULL) { + break; + } + break; + + case BTTV_AVDVBT_761: + card->fe = sp887x_attach(µtune_mt7202dtf_config, card->i2c_adapter); + if (card->fe != NULL) { + break; + } + break; + + case BTTV_AVDVBT_771: + card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter); + if (card->fe != NULL) { + card->fe->ops->info.frequency_min = 174000000; + card->fe->ops->info.frequency_max = 862000000; + break; + } + break; + + case BTTV_TWINHAN_DST: + card->fe = dst_attach(&dst_config, card->i2c_adapter, card->bt); + if (card->fe != NULL) { + break; + } + break; + } + + if (card->fe == NULL) { + printk("dvb-bt8xx: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + card->bt->dev->vendor, + card->bt->dev->device, + card->bt->dev->subsystem_vendor, + card->bt->dev->subsystem_device); + } else { + if (dvb_register_frontend(card->dvb_adapter, card->fe)) { + printk("dvb-bt8xx: Frontend registration failed!\n"); + if (card->fe->ops->release) + card->fe->ops->release(card->fe); + card->fe = NULL; + } + } +} + +static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) { int result; @@ -136,6 +415,7 @@ return result; } + card->dvb_adapter->priv = card; card->bt->adapter = card->i2c_adapter; @@ -207,6 +487,8 @@ tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card); + frontend_init(card, type); + return 0; } @@ -228,7 +510,7 @@ switch(sub->core->type) { - case BTTV_PINNACLESAT: +/* case BTTV_PINNACLESAT: UNDEFINED HARDWARE */ #ifdef BTTV_DVICO_DVBT_LITE case BTTV_DVICO_DVBT_LITE: #endif @@ -240,7 +522,11 @@ * DA_APP(parallel) */ break; +#ifdef BTTV_TWINHAN_VP3021 + case BTTV_TWINHAN_VP3021: +#else case BTTV_NEBULA_DIGITV: +#endif case BTTV_AVDVBT_761: card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5); card->op_sync_orin = 0; @@ -302,7 +588,7 @@ init_MUTEX(&card->bt->gpio_lock); card->bt->bttv_nr = sub->core->nr; - if ( (ret = dvb_bt8xx_load_card(card)) ) { + if ( (ret = dvb_bt8xx_load_card(card, sub->core->type)) ) { kfree(card); return ret; } @@ -324,6 +610,7 @@ card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw); dvb_dmxdev_release(&card->dmxdev); dvb_dmx_release(&card->demux); + if (card->fe) dvb_unregister_frontend(card->fe); dvb_unregister_adapter(card->dvb_adapter); kfree(card); @@ -331,24 +618,6 @@ return 0; } -static void dvb_bt8xx_i2c_info(struct bttv_sub_device *sub, - struct i2c_client *client, int attach) -{ - struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev); - - if (attach) { - printk("xxx attach\n"); - if (client->driver->command) - client->driver->command(client, FE_REGISTER, - card->dvb_adapter); - } else { - printk("xxx detach\n"); - if (client->driver->command) - client->driver->command(client, FE_UNREGISTER, - card->dvb_adapter); - } -} - static struct bttv_sub_driver driver = { .drv = { .name = "dvb-bt8xx", @@ -360,7 +629,6 @@ * .resume = dvb_bt8xx_resume, */ }, - .i2c_info = dvb_bt8xx_i2c_info, }; static int __init dvb_bt8xx_init(void) Index: wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/dvb-bt8xx.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/bt8xx/dvb-bt8xx.h 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/bt8xx/dvb-bt8xx.h 2004-12-22 10:04:35.470410530 -0800 @@ -26,6 +26,10 @@ #include "dvbdev.h" #include "dvb_net.h" #include "bttv.h" +#include "mt352.h" +#include "sp887x.h" +#include "dst.h" +#include "nxt6000.h" struct dvb_bt8xx_card { struct semaphore lock; @@ -44,4 +48,5 @@ struct i2c_adapter *i2c_adapter; struct dvb_net dvbnet; + struct dvb_frontend* fe; }; Index: wli-2.6.10-rc3-1/drivers/media/dvb/cinergyT2/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/cinergyT2/Kconfig 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/cinergyT2/Kconfig 2004-12-22 10:04:35.473410074 -0800 @@ -23,8 +23,10 @@ depends on DVB_CINERGYT2_TUNING default "32" help - USB Request Blocks for Highspeed Stream transfers are queued in a - for the Host Controller. Usually the default value is a safe choice. + USB Request Blocks for Highspeed Stream transfers are scheduled in + a queue for the Host Controller. + + Usually the default value is a safe choice. You may increase this number if you are using this device in a Server Environment with many high-traffic USB Highspeed devices @@ -44,6 +46,21 @@ sharing the same USB bus. +config DVB_CINERGYT2_QUERY_INTERVAL + int "Status update interval [milliseconds]" + depends on DVB_CINERGYT2_TUNING + default "250" + help + This is the interval for status readouts from the demodulator. + You may try lower values if you need more responsive signal quality + measurements. + + Please keep in mind that these updates cause traffic on the tuner + control bus and thus may or may not affect receiption sensitivity. + + The default value should be a safe choice for common applications. + + config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE bool "Register the onboard IR Remote Control Receiver as Input Device" depends on DVB_CINERGYT2_TUNING @@ -57,3 +74,12 @@ source code to find out how to add support for other controls. +config DVB_CINERGYT2_RC_QUERY_INTERVAL + int "Infrared Remote Controller update interval [milliseconds]" + depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE + default "100" + help + If you have a very fast-repeating remote control you can try lower + values, for normal consumer receivers the default value should be + a safe choice. + Index: wli-2.6.10-rc3-1/drivers/media/dvb/cinergyT2/cinergyT2.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/cinergyT2/cinergyT2.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/cinergyT2/cinergyT2.c 2004-12-22 10:04:35.488407794 -0800 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -35,16 +36,28 @@ #include "dvb_demux.h" #include "dvb_net.h" + + + + + + + + #ifdef CONFIG_DVB_CINERGYT2_TUNING #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT) #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE) + #define QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_QUERY_INTERVAL) #ifdef CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE + #define RC_QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL) #define ENABLE_RC (1) #endif #else #define STREAM_URB_COUNT (32) - #define STREAM_BUF_SIZE (512) + #define STREAM_BUF_SIZE (512) /* bytes */ #define ENABLE_RC (1) + #define RC_QUERY_INTERVAL (100) /* milliseconds */ + #define QUERY_INTERVAL (333) /* milliseconds */ #endif #define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" @@ -54,7 +67,12 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk(level, args...) \ - do { if ((debug & level)) { printk("%s: %s(): ",__stringify(KBUILD_MODNAME), __FUNCTION__); printk(args); } } while (0) +do { \ + if ((debug & level)) { \ + printk("%s: %s(): ", __stringify(KBUILD_MODNAME), \ + __FUNCTION__); \ + printk(args); } \ +} while (0) enum cinergyt2_ep1_cmd { CINERGYT2_EP1_PID_TABLE_RESET = 0x01, @@ -68,13 +86,34 @@ CINERGYT2_EP1_SLEEP_MODE = 0x09 }; +struct dvbt_set_parameters_msg { + uint8_t cmd; + uint32_t freq; + uint8_t bandwidth; + uint16_t tps; + uint8_t flags; +} __attribute__((packed)); + +struct dvbt_get_status_msg { + uint32_t freq; + uint8_t bandwidth; + uint16_t tps; + uint8_t flags; + uint16_t gain; + uint8_t snr; + uint32_t viterbi_error_rate; + uint32_t rs_error_rate; + uint32_t uncorrected_block_count; + uint8_t lock_bits; + uint8_t prev_lock_bits; +} __attribute__((packed)); + static struct dvb_frontend_info cinergyt2_fe_info = { .name = DRIVER_NAME, .type = FE_OFDM, .frequency_min = 174000000, .frequency_max = 862000000, .frequency_stepsize = 166667, - .notifier_delay = 0, .caps = FE_CAN_INVERSION_AUTO | 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 | @@ -93,6 +132,14 @@ struct dvb_net dvbnet; int streaming; + int sleeping; + + struct dvbt_set_parameters_msg param; + struct dvbt_get_status_msg status; + struct work_struct query_work; + + wait_queue_head_t poll_wq; + int pending_fe_events; void *streambuf; dma_addr_t streambuf_dmahandle; @@ -156,6 +203,45 @@ CINERGYT2_RC_EVENT_TYPE_NEC, 0xa35ceb04, KEY_NEXT }; +static int cinergyt2_command (struct cinergyt2 *cinergyt2, + char *send_buf, int send_buf_len, + char *recv_buf, int recv_buf_len) +{ + int actual_len; + char dummy; + int ret; + + ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1), + send_buf, send_buf_len, &actual_len, HZ); + + if (ret) + dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret); + + if (!recv_buf) + recv_buf = &dummy; + + ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1), + recv_buf, recv_buf_len, &actual_len, HZ); + + if (ret) + dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret); + + return ret ? ret : actual_len; +} + +static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable) +{ + char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; + cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); +} + +static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep) +{ + char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 }; + cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); + cinergyt2->sleeping = sleep; +} + static void cinergyt2_stream_irq (struct urb *urb, struct pt_regs *regs); static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb) @@ -236,9 +322,11 @@ { int i; + cinergyt2_control_stream_transfer(cinergyt2, 0); + for (i=0; istream_urb[i]) - usb_unlink_urb(cinergyt2->stream_urb[i]); + usb_kill_urb(cinergyt2->stream_urb[i]); } static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2) @@ -253,65 +341,23 @@ } } + cinergyt2_control_stream_transfer(cinergyt2, 1); return 0; } -static int cinergyt2_command (struct cinergyt2 *cinergyt2, - char *send_buf, int send_buf_len, - char *rec_buf, int rec_buf_len) -{ - int ret; - int actual_len; - char dummy; - - if (down_interruptible(&cinergyt2->sem)) - return -EBUSY; - - ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1), - send_buf, send_buf_len, &actual_len, HZ); - - if (ret) - dprintk(1, "usb_bulk_msg() (send) failed, err %i\n", ret); - - if (!rec_buf) - rec_buf = &dummy; - - ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1), - rec_buf, rec_buf_len, &actual_len, HZ); - - if (ret) - dprintk(1, "usb_bulk_msg() (read) failed, err %i\n", ret); - - up(&cinergyt2->sem); - - return ret ? ret : actual_len; -} - -static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable) -{ - char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; - cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); -} - -static void cinergyt2_control_sleep_mode (struct cinergyt2 *cinergyt2, int sleep) -{ - char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 }; - cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); -} - static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *demux = dvbdmxfeed->demux; struct cinergyt2 *cinergyt2 = demux->priv; + if (down_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; - if (cinergyt2->streaming == 0) { - if (cinergyt2_start_stream_xfer (cinergyt2) == 0) - cinergyt2_control_stream_transfer (cinergyt2, 1); - } + if (cinergyt2->streaming == 0) + cinergyt2_start_stream_xfer(cinergyt2); cinergyt2->streaming++; - + up(&cinergyt2->sem); return 0; } @@ -320,11 +366,13 @@ struct dvb_demux *demux = dvbdmxfeed->demux; struct cinergyt2 *cinergyt2 = demux->priv; - if (--cinergyt2->streaming == 0) { - cinergyt2_control_stream_transfer(cinergyt2, 0); + if (down_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; + + if (--cinergyt2->streaming == 0) cinergyt2_stop_stream_xfer(cinergyt2); - } + up(&cinergyt2->sem); return 0; } @@ -337,11 +385,10 @@ * * We replace errornous fields by default TPS fields (the ones with value 0). */ - -static uint16_t compute_tps (struct dvb_frontend_parameters *param) +static uint16_t compute_tps (struct dvb_frontend_parameters *p) { + struct dvb_ofdm_parameters *op = &p->u.ofdm; uint16_t tps = 0; - struct dvb_ofdm_parameters *op = ¶m->u.ofdm; switch (op->code_rate_HP) { case FEC_2_3: @@ -435,147 +482,135 @@ return tps; } -struct dvbt_set_parameters_msg { - uint8_t cmd; - uint32_t freq; - uint8_t bandwidth; - uint16_t tps; - uint8_t flags; -} __attribute__((packed)); - -struct dvbt_get_parameters_msg { - uint32_t freq; - uint8_t bandwidth; - uint16_t tps; - uint8_t flags; - uint16_t gain; - uint8_t snr; - uint32_t viterbi_error_rate; - uint32_t rs_error_rate; - uint32_t uncorrected_block_count; - uint8_t lock_bits; - uint8_t prev_lock_bits; -} __attribute__((packed)); - -static int cinergyt2_fe_open (struct inode *inode, struct file *file) +static int cinergyt2_open (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; - cinergyt2_control_sleep_mode((struct cinergyt2 *) dvbdev->priv, 0); - return dvb_generic_open(inode, file); + struct cinergyt2 *cinergyt2 = dvbdev->priv; + int err; + + if ((err = dvb_generic_open(inode, file))) + return err; + + if (down_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; + + if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + cinergyt2_sleep(cinergyt2, 0); + schedule_delayed_work(&cinergyt2->query_work, HZ/2); } -static int cinergyt2_fe_release (struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - cinergyt2_control_sleep_mode((struct cinergyt2 *) dvbdev->priv, 1); - return dvb_generic_release (inode, file); + up(&cinergyt2->sem); + return 0; } -static int cinergyt2_fe_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, void *arg) +static int cinergyt2_release (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; - int ret = 0; - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &cinergyt2_fe_info, sizeof(struct dvb_frontend_info)); - break; + if (down_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; - case FE_READ_STATUS: - { - struct dvbt_get_parameters_msg msg; - char cmd = CINERGYT2_EP1_GET_TUNER_STATUS; - fe_status_t *status = arg; - - *status = 0; - - cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg)); - - if (msg.lock_bits & (1 << 6)) - *status |= FE_HAS_LOCK; - if (msg.lock_bits & (1 << 5)) - *status |= FE_HAS_SYNC; - if (msg.lock_bits & (1 << 4)) - *status |= FE_HAS_CARRIER; - if (msg.lock_bits & (1 << 1)) - *status |= FE_HAS_VITERBI; + if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + cancel_delayed_work(&cinergyt2->query_work); + flush_scheduled_work(); + cinergyt2_sleep(cinergyt2, 1); + } - break; + up(&cinergyt2->sem); + + return dvb_generic_release(inode, file); } - case FE_READ_BER: +static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct *wait) { - struct dvbt_get_parameters_msg msg; - char cmd = CINERGYT2_EP1_GET_TUNER_STATUS; - u32 *ber = (u32 *) arg; + struct dvb_device *dvbdev = file->private_data; + struct cinergyt2 *cinergyt2 = dvbdev->priv; + poll_wait(file, &cinergyt2->poll_wq, wait); + return (POLLIN | POLLRDNORM | POLLPRI); + } - cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg)); - *ber = le32_to_cpu(msg.viterbi_error_rate); +static int cinergyt2_ioctl (struct inode *inode, struct file *file, + unsigned cmd, unsigned long arg) + { + struct dvb_device *dvbdev = file->private_data; + struct cinergyt2 *cinergyt2 = dvbdev->priv; + struct dvbt_get_status_msg *stat = &cinergyt2->status; + fe_status_t status = 0; - break; - } + switch (cmd) { + case FE_GET_INFO: + return copy_to_user((void*) arg, &cinergyt2_fe_info, + sizeof(struct dvb_frontend_info)); - case FE_READ_SIGNAL_STRENGTH: - { - struct dvbt_get_parameters_msg msg; - char cmd = CINERGYT2_EP1_GET_TUNER_STATUS; - u16 *signal = (u16 *) arg; + case FE_READ_STATUS: + if (0xffff - le16_to_cpu(stat->gain) > 30) + status |= FE_HAS_SIGNAL; + if (stat->lock_bits & (1 << 6)) + status |= FE_HAS_LOCK; + if (stat->lock_bits & (1 << 5)) + status |= FE_HAS_SYNC; + if (stat->lock_bits & (1 << 4)) + status |= FE_HAS_CARRIER; + if (stat->lock_bits & (1 << 1)) + status |= FE_HAS_VITERBI; - cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg)); + return copy_to_user((void *) arg, &status, sizeof(status)); - *signal = ~(le16_to_cpu(msg.gain)); + case FE_READ_BER: + return put_user(le32_to_cpu(stat->viterbi_error_rate), + (__u32 __user *) arg); - break; - } + case FE_READ_SIGNAL_STRENGTH: + return put_user(0xffff - le16_to_cpu(stat->gain), + (__u16 __user *) arg); case FE_READ_SNR: - { - struct dvbt_get_parameters_msg msg; - char cmd = CINERGYT2_EP1_GET_TUNER_STATUS; - u16 *snr = (u16 *) arg; + return put_user((stat->snr << 8) | stat->snr, + (__u16 __user *) arg); - cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg)); + case FE_READ_UNCORRECTED_BLOCKS: + /* UNC are already converted to host byte order... */ + return put_user(stat->uncorrected_block_count, + (__u32 __user *) arg); + + case FE_SET_FRONTEND: + { + struct dvbt_set_parameters_msg *param = &cinergyt2->param; + struct dvb_frontend_parameters p; + int err; - *snr = (msg.snr << 8) | msg.snr; + if ((file->f_flags & O_ACCMODE) == O_RDONLY) + return -EPERM; - break; - } + if (copy_from_user(&p, (void *) arg, sizeof(p))) + return -EFAULT; - case FE_READ_UNCORRECTED_BLOCKS: - { - struct dvbt_get_parameters_msg msg; - char cmd = CINERGYT2_EP1_GET_TUNER_STATUS; - u32 *ubc = (u32 *) arg; + if (down_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; - cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg)); + param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; + param->tps = cpu_to_le16(compute_tps(&p)); + param->freq = cpu_to_le32(p.frequency / 1000); + param->bandwidth = 8 - p.u.ofdm.bandwidth - BANDWIDTH_8_MHZ; - *ubc = le32_to_cpu(msg.uncorrected_block_count); + stat->lock_bits = 0; + cinergyt2->pending_fe_events++; + wake_up_interruptible(&cinergyt2->poll_wq); - break; - } - - case FE_SET_FRONTEND: - { - struct dvb_frontend_parameters *p = (void*) arg; - struct dvb_ofdm_parameters *op = &p->u.ofdm; - struct dvbt_set_parameters_msg msg; - - msg.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; - msg.tps = cpu_to_le16(compute_tps(p)); - msg.freq = cpu_to_le32(p->frequency / 1000); - msg.bandwidth = 8 - op->bandwidth - BANDWIDTH_8_MHZ; + err = cinergyt2_command(cinergyt2, + (char *) param, sizeof(*param), + NULL, 0); - cinergyt2_command(cinergyt2, (char *) &msg, sizeof(msg), NULL, 0); + up(&cinergyt2->sem); - break; + return (err < 0) ? err : 0; } case FE_GET_FRONTEND: /** - * trivial to implement (see struct dvbt_get_parameters_msg). + * trivial to implement (see struct dvbt_get_status_msg). * equivalent to FE_READ ioctls, but needs * TPS -> linux-dvb parameter set conversion. Feel free * to implement this and send us a patch if you need this @@ -583,33 +618,75 @@ */ break; + case FE_GET_EVENT: + { + /** + * for now we only fill the status field. the parameters + * are trivial to fill as soon FE_GET_FRONTEND is done. + */ + struct dvb_frontend_event *e = (void *) arg; + if (cinergyt2->pending_fe_events == 0) { + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + wait_event_interruptible(cinergyt2->poll_wq, + cinergyt2->pending_fe_events > 0); + } + cinergyt2->pending_fe_events = 0; + return cinergyt2_ioctl(inode, file, FE_READ_STATUS, + (unsigned long) &e->status); + } + default: + ; + } + + return -EINVAL; +} + +static int cinergyt2_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct dvb_device *dvbdev = file->private_data; + struct cinergyt2 *cinergyt2 = dvbdev->priv; + int ret = 0; + + lock_kernel(); + + if (vma->vm_flags & (VM_WRITE | VM_EXEC)) { + ret = -EPERM; + goto bailout; + } + + if (vma->vm_end > vma->vm_start + STREAM_URB_COUNT * STREAM_BUF_SIZE) { ret = -EINVAL; - break; + goto bailout; } + vma->vm_flags |= (VM_IO | VM_DONTCOPY); + vma->vm_file = file; + + ret = remap_pfn_range(vma, vma->vm_start, + virt_to_phys(cinergyt2->streambuf) >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot) ? -EAGAIN : 0; +bailout: + unlock_kernel(); return ret; } -static -struct file_operations cinergyt2_fe_fops = { +static struct file_operations cinergyt2_fops = { .owner = THIS_MODULE, - .ioctl = dvb_generic_ioctl, - /** - * do we really need this? If so, let's implement it via - * schedule_delayed_work() similiar to the IR code. - */ - /*.poll = cinergyt2_fe_poll, */ - .open = cinergyt2_fe_open, - .release = cinergyt2_fe_release + .ioctl = cinergyt2_ioctl, + .poll = cinergyt2_poll, + .open = cinergyt2_open, + .release = cinergyt2_release, + .mmap = cinergyt2_mmap }; static struct dvb_device cinergyt2_fe_template = { .users = ~0, .writers = 1, .readers = (~0)-1, - .fops = &cinergyt2_fe_fops, - .kernel_ioctl = cinergyt2_fe_ioctl + .fops = &cinergyt2_fops }; #ifdef ENABLE_RC @@ -620,6 +697,9 @@ struct cinergyt2_rc_event rc_events[12]; int n, len; + if (down_interruptible(&cinergyt2->sem)) + return; + len = cinergyt2_command(cinergyt2, buf, sizeof(buf), (char *) rc_events, sizeof(rc_events)); @@ -656,11 +736,45 @@ } } - schedule_delayed_work(&cinergyt2->rc_query_work, (HZ/5)); + schedule_delayed_work(&cinergyt2->rc_query_work, + msecs_to_jiffies(RC_QUERY_INTERVAL)); + + up(&cinergyt2->sem); } #endif -static int cinergyt2_probe (struct usb_interface *intf, const struct usb_device_id *id) +static void cinergyt2_query (void *data) +{ + struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data; + char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; + struct dvbt_get_status_msg *s = &cinergyt2->status; + uint8_t lock_bits; + uint32_t unc; + + if (down_interruptible(&cinergyt2->sem)) + return; + + unc = s->uncorrected_block_count; + lock_bits = s->lock_bits; + + cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s)); + + unc += le32_to_cpu(s->uncorrected_block_count); + s->uncorrected_block_count = unc; + + if (lock_bits != s->lock_bits) { + wake_up_interruptible(&cinergyt2->poll_wq); + cinergyt2->pending_fe_events++; + } + + schedule_delayed_work(&cinergyt2->query_work, + msecs_to_jiffies(QUERY_INTERVAL)); + + up(&cinergyt2->sem); +} + +static int cinergyt2_probe (struct usb_interface *intf, + const struct usb_device_id *id) { struct cinergyt2 *cinergyt2; int i, err; @@ -674,8 +788,11 @@ usb_set_intfdata (intf, (void *) cinergyt2); init_MUTEX(&cinergyt2->sem); + init_waitqueue_head (&cinergyt2->poll_wq); + INIT_WORK(&cinergyt2->query_work, cinergyt2_query, cinergyt2); cinergyt2->udev = interface_to_usbdev(intf); + cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) { dprintk(1, "unable to allocate stream urbs\n"); @@ -722,10 +839,6 @@ cinergyt2->rc_input_dev.keycodesize = sizeof(unsigned char); cinergyt2->rc_input_dev.keycodemax = KEY_MAX; cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control"; - cinergyt2->rc_input_dev.id.bustype = BUS_USB; - cinergyt2->rc_input_dev.id.vendor = 0x0001; - cinergyt2->rc_input_dev.id.product = 0x0001; - cinergyt2->rc_input_dev.id.version = 0x0100; for (i=0; irc_input_dev.keybit); @@ -735,9 +848,8 @@ cinergyt2->rc_input_event = KEY_MAX; INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2); - schedule_delayed_work(&cinergyt2->rc_query_work, HZ); + schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); #endif - return 0; bailout: @@ -753,6 +865,9 @@ { struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); + if (down_interruptible(&cinergyt2->sem)) + return; + #ifdef ENABLE_RC cancel_delayed_work(&cinergyt2->rc_query_work); flush_scheduled_work(); @@ -768,9 +883,56 @@ dvb_unregister_adapter(cinergyt2->adapter); cinergyt2_free_stream_urbs(cinergyt2); + up(&cinergyt2->sem); kfree(cinergyt2); } +static int cinergyt2_suspend (struct usb_interface *intf, u32 state) +{ + struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); + + if (down_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; + + if (state > 0) { /* state 0 seems to mean DEVICE_PM_ON */ + struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); +#ifdef ENABLE_RC + cancel_delayed_work(&cinergyt2->rc_query_work); +#endif + cancel_delayed_work(&cinergyt2->query_work); + if (cinergyt2->streaming) + cinergyt2_stop_stream_xfer(cinergyt2); + flush_scheduled_work(); + cinergyt2_sleep(cinergyt2, 1); + } + + up(&cinergyt2->sem); + return 0; +} + +static int cinergyt2_resume (struct usb_interface *intf) +{ + struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); + struct dvbt_set_parameters_msg *param = &cinergyt2->param; + + if (down_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; + + if (!cinergyt2->sleeping) { + cinergyt2_sleep(cinergyt2, 0); + cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0); + if (cinergyt2->streaming) + cinergyt2_start_stream_xfer(cinergyt2); + schedule_delayed_work(&cinergyt2->query_work, HZ/2); + } + +#ifdef ENABLE_RC + schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); +#endif + up(&cinergyt2->sem); + return 0; +} + static const struct usb_device_id cinergyt2_table [] __devinitdata = { { USB_DEVICE(0x0ccd, 0x0038) }, { 0 } @@ -780,9 +942,11 @@ static struct usb_driver cinergyt2_driver = { .owner = THIS_MODULE, - .name = "cinergyt2", + .name = "cinergyT2", .probe = cinergyt2_probe, .disconnect = cinergyt2_disconnect, + .suspend = cinergyt2_suspend, + .resume = cinergyt2_resume, .id_table = cinergyt2_table }; @@ -790,12 +954,10 @@ { int err; - if ((err = usb_register(&cinergyt2_driver)) < 0) { + if ((err = usb_register(&cinergyt2_driver)) < 0) dprintk(1, "usb_register() failed! (err %i)\n", err); - return err; - } - return 0; + return err; } static void __exit cinergyt2_exit (void) Index: wli-2.6.10-rc3-1/drivers/media/dvb/dibusb/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dibusb/Kconfig 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dibusb/Kconfig 2004-12-22 10:04:35.491407338 -0800 @@ -1,9 +1,11 @@ config DVB_DIBUSB - tristate "DiBcom/Twinhan/KWorld/Hama/Artec/Compro USB DVB-T devices" + tristate "DiBcom USB DVB-T devices (see help for device list)" depends on DVB_CORE && USB select FW_LOADER + select DVB_DIB3000MB + select DVB_DIB3000MC help - Support for USB 1.1 DVB-T devices based on a reference design made by + Support for USB 1.1 and 2.0 DVB-T devices based on reference designs made by DiBcom (http://www.dibcom.fr). Devices supported by this driver: @@ -15,19 +17,41 @@ DiBcom reference device (non-public) Ultima Electronic/Artec T1 USB TVBOX Compro Videomate DVB-U2000 - DVB-T USB + Grandtec DVB-T USB + Avermedia AverTV DVBT USB + Yakumo DVB-T mobile USB2.0 The VP7041 seems to be identical to "CTS Portable" (Chinese Television System). These devices can be understood as budget ones, they "only" deliver - the MPEG data. + (a part of) the MPEG2 transport stream. - Currently all known copies of the DiBcom reference design have the DiBcom 3000-MB - frontend onboard. Please enable and load this one manually in order to use this - device. - - A firmware is needed to use the device. See Documentation/dvb/README.dibusb + A firmware is needed to get the device working. See Documentation/dvb/README.dibusb details. Say Y if you own such a device and want to use it. You should build it as a module. + +config DVB_DIBUSB_MISDESIGNED_DEVICES + bool "Enable support for some misdesigned (see help) devices, which identify with wrong IDs" + depends on DVB_DIBUSB + help + Somehow Artec/Ultima Electronic forgot to program the eeprom of some of their + USB1.1/USB2.0 devices. + So comes that they identify with the default Vendor and Product ID of the Cypress + CY7C64613 (AN2235) or Cypress FX2. + + Affected device IDs: + 0x0574:0x2235 (Artec T1 USB1.1, cold) + 0x04b4:0x8613 (Artec T1 USB2.0, cold) + 0x0574:0x1002 (Artec T1 USB2.0, warm) + + Say Y if your device has one of the mentioned IDs. + +config DVB_DIBCOM_DEBUG + bool "Enable extended debug support for DiBcom USB device" + depends on DVB_DIBUSB + help + Say Y if you want to enable debuging. See modinfo dvb-dibusb for + debug levels. Index: wli-2.6.10-rc3-1/drivers/media/dvb/dibusb/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dibusb/Makefile 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dibusb/Makefile 2004-12-22 10:04:35.492407186 -0800 @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_DIBUSB) += dvb-dibusb.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ Index: wli-2.6.10-rc3-1/drivers/media/dvb/dibusb/dvb-dibusb.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dibusb/dvb-dibusb.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dibusb/dvb-dibusb.c 2004-12-22 10:04:35.510404450 -0800 @@ -7,9 +7,9 @@ * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) * * based on GPL code from DiBcom, which has - * * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) * + * Remote control code added by David Matthews (dm@prolingua.co.uk) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,9 +18,7 @@ * Acknowledgements * * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver - * sources, on which this driver (and the dib3000mb frontend) are based. - * - * + * sources, on which this driver (and the dib3000mb/mc/p frontends) are based. * * see Documentation/dvb/README.dibusb for more information */ @@ -32,19 +30,21 @@ #include #include #include +#include #include "dmxdev.h" #include "dvb_demux.h" #include "dvb_filter.h" #include "dvb_net.h" #include "dvb_frontend.h" +#include "dib3000.h" #include "dvb-dibusb.h" -/* debug */ +/* debug */ #ifdef CONFIG_DVB_DIBCOM_DEBUG -#define dprintk_new(level,args...) \ +#define dprintk(level,args...) \ do { if ((debug & level)) { printk(args); } } while (0) #define debug_dump(b,l) if (debug) {\ @@ -55,20 +55,25 @@ static int debug; module_param(debug, int, 0x644); -MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err (|-able))."); +MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err,32=rc (|-able))."); #else -#define dprintk_new(args...) +#define dprintk(args...) #define debug_dump(b,l) #endif -#define deb_info(args...) dprintk_new(0x01,args) -#define deb_xfer(args...) dprintk_new(0x02,args) -#define deb_alot(args...) dprintk_new(0x04,args) -#define deb_ts(args...) dprintk_new(0x08,args) -#define deb_err(args...) dprintk_new(0x10,args) +#define deb_info(args...) dprintk(0x01,args) +#define deb_xfer(args...) dprintk(0x02,args) +#define deb_alot(args...) dprintk(0x04,args) +#define deb_ts(args...) dprintk(0x08,args) +#define deb_err(args...) dprintk(0x10,args) +#define deb_rc(args...) dprintk(0x20,args) + +static int pid_parse; +module_param(pid_parse, int, 0x644); +MODULE_PARM_DESC(pid_parse, "enable pid parsing (filtering) when running at USB2.0"); /* Version information */ -#define DRIVER_VERSION "0.0" +#define DRIVER_VERSION "0.1" #define DRIVER_DESC "Driver for DiBcom based USB Budget DVB-T device" #define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de" @@ -83,25 +88,28 @@ if ((ret = down_interruptible(&dib->usb_sem))) return ret; - if (dib->streaming && wbuf[0] == DIBUSB_REQ_I2C_WRITE) - deb_err("BUG: writing to i2c, while TS-streaming destroys the stream. What" - " did you do ? Please enable debugging and send the syslog to the author. (%x reg: %x %x)", - wbuf[0],wbuf[2],wbuf[3]); + if (dib->feedcount && + wbuf[0] == DIBUSB_REQ_I2C_WRITE && + dib->dibdev->parm->type == DIBUSB1_1) + deb_err("BUG: writing to i2c, while TS-streaming destroys the stream." + "(%x reg: %x %x)\n", wbuf[0],wbuf[2],wbuf[3]); debug_dump(wbuf,wlen); - ret = usb_bulk_msg(dib->udev,COMMAND_PIPE, - wbuf,wlen,&actlen,DIBUSB_I2C_TIMEOUT); + ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev, + dib->dibdev->parm->cmd_pipe), wbuf,wlen,&actlen, + DIBUSB_I2C_TIMEOUT); if (ret) err("bulk message failed: %d (%d/%d)",ret,wlen,actlen); else ret = actlen != wlen ? -1 : 0; - /* an answer is expected */ + /* an answer is expected, and no error before */ if (!ret && rbuf && rlen) { - ret = usb_bulk_msg(dib->udev,RESULT_PIPE,rbuf,rlen, - &actlen,DIBUSB_I2C_TIMEOUT); + ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev, + dib->dibdev->parm->result_pipe),rbuf,rlen,&actlen, + DIBUSB_I2C_TIMEOUT); if (ret) err("recv bulk message failed: %d",ret); @@ -115,11 +123,6 @@ return ret; } -static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len) -{ - return dibusb_readwrite_usb(dib,buf,len,NULL,0); -} - static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { @@ -146,97 +149,21 @@ /* * DVB stuff */ - -static struct dibusb_pid * dibusb_get_free_pid(struct usb_dibusb *dib) -{ - int i; - unsigned long flags; - struct dibusb_pid *dpid = NULL; - - spin_lock_irqsave(&dib->pid_list_lock,flags); - for (i=0; i < DIBUSB_MAX_PIDS; i++) - if (!dib->pid_list[i].active) { - dpid = dib->pid_list + i; - dpid->active = 1; - break; - } - spin_unlock_irqrestore(&dib->pid_list_lock,flags); - return dpid; -} - -static int dibusb_start_xfer(struct usb_dibusb *dib) -{ - u8 b[4] = { - (DIB3000MB_REG_FIFO >> 8) & 0xff, - (DIB3000MB_REG_FIFO) & 0xff, - (DIB3000MB_FIFO_ACTIVATE >> 8) & 0xff, - (DIB3000MB_FIFO_ACTIVATE) & 0xff - }; - dib->streaming = 1; - deb_ts("start streaming\n"); - return dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0); -} - -static int dibusb_stop_xfer(struct usb_dibusb *dib) -{ - u8 b[4] = { - (DIB3000MB_REG_FIFO >> 8) & 0xff, - (DIB3000MB_REG_FIFO) & 0xff, - (DIB3000MB_FIFO_INHIBIT >> 8) & 0xff, - (DIB3000MB_FIFO_INHIBIT) & 0xff - }; - dib->streaming = 0; - deb_ts("stop streaming\n"); - return dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0); -} - -static int dibusb_set_pid(struct dibusb_pid *dpid) -{ - struct usb_dibusb *dib = dpid->dib; - u16 pid = dpid->pid | (dpid->active ? DIB3000MB_ACTIVATE_FILTERING : 0); - u8 b[4] = { - (dpid->reg >> 8) & 0xff, - (dpid->reg) & 0xff, - (pid >> 8) & 0xff, - (pid) & 0xff - }; - int ret; - - /* firmware bug, i2c write during mpeg transfer */ - if (dib->feedcount) { - deb_info("stop streaming\n"); - ret = dibusb_stop_xfer(dib); - } - - if (dpid->active) - dib->feedcount++; - else - dib->feedcount--; - - ret = dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0); - - if (ret == 0 && dib->feedcount) { - deb_info("start streaming\n"); - ret = dibusb_start_xfer(dib); - } - return ret; -} - static void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs) { struct usb_dibusb *dib = urb->context; - deb_xfer("urb complete feedcount: %d, status: %d\n",dib->feedcount,urb->status); + deb_ts("urb complete feedcount: %d, status: %d\n",dib->feedcount,urb->status); if (dib->feedcount > 0 && urb->status == 0) { - deb_xfer("URB return len: %d\n",urb->actual_length); + deb_ts("URB return len: %d\n",urb->actual_length); if (urb->actual_length % 188) - deb_xfer("TS Packets: %d, %d\n", urb->actual_length/188,urb->actual_length % 188); + deb_ts("TS Packets: %d, %d\n", urb->actual_length/188,urb->actual_length % 188); /* Francois recommends to drop not full-filled packets, even if they may * contain valid TS packets */ - if (urb->actual_length == DIBUSB_TS_DEFAULT_SIZE && dib->dvb_is_ready) + if (urb->actual_length == dib->dibdev->parm->default_size && dib->dvb_is_ready) dvb_dmx_swfilter_packets(&dib->demux, (u8*) urb->transfer_buffer,urb->actual_length/188); else deb_ts("URB dropped because of the " @@ -247,78 +174,198 @@ usb_submit_urb(urb,GFP_KERNEL); } - -static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +static int dibusb_ctrl_feed(struct usb_dibusb *dib, int pid, int onoff) { -// struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct usb_dibusb *dib = dvbdmxfeed->demux->priv; - struct dibusb_pid *dpid; + if (dib->dibdev->parm->firmware_bug && dib->feedcount) { + deb_ts("stop feeding\n"); + if (dib->xfer_ops.fifo_ctrl != NULL) { + if (dib->xfer_ops.fifo_ctrl(dib->fe,0)) { + err("error while inhibiting fifo."); + return -ENODEV; + } + } else { + err("fifo_ctrl is not set."); + return -ENODEV; + } + } - deb_ts("pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type); + dib->feedcount += onoff ? 1 : -1; - if ((dpid = dibusb_get_free_pid(dib)) == NULL) { + if (dib->pid_parse) { + if (dib->xfer_ops.pid_ctrl != NULL) { + if (dib->xfer_ops.pid_ctrl(dib->fe,pid,onoff) < 0) { err("no free pid in list."); return -ENODEV; } - dvbdmxfeed->priv = dpid; - dpid->pid = dvbdmxfeed->pid; + } else { + err("no pid ctrl callback."); + return -ENODEV; + } + } + /* + * start the feed, either if there is the firmware bug or + * if this was the first pid to set. + */ + if (dib->dibdev->parm->firmware_bug || dib->feedcount == onoff) { - dibusb_set_pid(dpid); + deb_ts("controlling pid parser\n"); + if (dib->xfer_ops.pid_parse != NULL) { + if (dib->xfer_ops.pid_parse(dib->fe,dib->pid_parse) < 0) { + err("could not handle pid_parser"); + } + } - return 0; + deb_ts("start feeding\n"); + if (dib->xfer_ops.fifo_ctrl != NULL) { + if (dib->xfer_ops.fifo_ctrl(dib->fe,1)) { + err("error while enabling fifo."); + return -ENODEV; + } + } else { + err("fifo_ctrl is not set."); + return -ENODEV; } - -static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) -{ - struct dibusb_pid *dpid = (struct dibusb_pid *) dvbdmxfeed->priv; - - deb_ts("stopfeed pid: 0x%04x, feedtype: %d\n",dvbdmxfeed->pid, dvbdmxfeed->type); - - if (dpid == NULL) - err("channel in dmxfeed->priv was NULL"); - else { - dpid->active = 0; - dpid->pid = 0; - dibusb_set_pid(dpid); } - return 0; } -/* - * firmware transfers - */ +static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct usb_dibusb *dib = dvbdmxfeed->demux->priv; + deb_ts("pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type); + dvbdmxfeed->priv = dib; + return dibusb_ctrl_feed(dib,dvbdmxfeed->pid,1); +} -/* - * do not use this, just a workaround for a bug, - * which will hopefully never occur :). - */ -static int dibusb_interrupt_read_loop(struct usb_dibusb *dib) +static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { - u8 b[1] = { DIBUSB_REQ_INTR_READ }; - return dibusb_write_usb(dib,b,1); + struct usb_dibusb *dib = (struct usb_dibusb *) dvbdmxfeed->priv; + if (dib == NULL) { + err("dib in dmxfeed->priv was NULL"); + return -EINVAL; } + deb_ts("dvbdmxfeed pid: 0x%04x, feedtype: %d\n", + dvbdmxfeed->pid, dvbdmxfeed->type); + return dibusb_ctrl_feed(dib,dvbdmxfeed->pid,0); +} + +/* Table to map raw key codes to key events. This should not be hard-wired + into the kernel. */ +static const struct { u8 c0, c1, c2; uint32_t key; } rc_keys [] = +{ + /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ + { 0x00, 0xff, 0x16, KEY_POWER }, + { 0x00, 0xff, 0x10, KEY_MUTE }, + { 0x00, 0xff, 0x03, KEY_1 }, + { 0x00, 0xff, 0x01, KEY_2 }, + { 0x00, 0xff, 0x06, KEY_3 }, + { 0x00, 0xff, 0x09, KEY_4 }, + { 0x00, 0xff, 0x1d, KEY_5 }, + { 0x00, 0xff, 0x1f, KEY_6 }, + { 0x00, 0xff, 0x0d, KEY_7 }, + { 0x00, 0xff, 0x19, KEY_8 }, + { 0x00, 0xff, 0x1b, KEY_9 }, + { 0x00, 0xff, 0x15, KEY_0 }, + { 0x00, 0xff, 0x05, KEY_CHANNELUP }, + { 0x00, 0xff, 0x02, KEY_CHANNELDOWN }, + { 0x00, 0xff, 0x1e, KEY_VOLUMEUP }, + { 0x00, 0xff, 0x0a, KEY_VOLUMEDOWN }, + { 0x00, 0xff, 0x11, KEY_RECORD }, + { 0x00, 0xff, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */ + { 0x00, 0xff, 0x14, KEY_PLAY }, + { 0x00, 0xff, 0x1a, KEY_STOP }, + { 0x00, 0xff, 0x40, KEY_REWIND }, + { 0x00, 0xff, 0x12, KEY_FASTFORWARD }, + { 0x00, 0xff, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */ + { 0x00, 0xff, 0x4c, KEY_PAUSE }, + { 0x00, 0xff, 0x4d, KEY_SCREEN }, /* Full screen mode. */ + { 0x00, 0xff, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ + /* additional keys TwinHan VisionPlus, the Artec seemingly not have */ + { 0x00, 0xff, 0x0c, KEY_CANCEL }, /* Cancel */ + { 0x00, 0xff, 0x1c, KEY_EPG }, /* EPG */ + { 0x00, 0xff, 0x00, KEY_TAB }, /* Tab */ + { 0x00, 0xff, 0x48, KEY_INFO }, /* Preview */ + { 0x00, 0xff, 0x04, KEY_LIST }, /* RecordList */ + { 0x00, 0xff, 0x0f, KEY_TEXT }, /* Teletext */ + /* Key codes for the KWorld/ADSTech/JetWay remote. */ + { 0x86, 0x6b, 0x12, KEY_POWER }, + { 0x86, 0x6b, 0x0f, KEY_SELECT }, /* source */ + { 0x86, 0x6b, 0x0c, KEY_UNKNOWN }, /* scan */ + { 0x86, 0x6b, 0x0b, KEY_EPG }, + { 0x86, 0x6b, 0x10, KEY_MUTE }, + { 0x86, 0x6b, 0x01, KEY_1 }, + { 0x86, 0x6b, 0x02, KEY_2 }, + { 0x86, 0x6b, 0x03, KEY_3 }, + { 0x86, 0x6b, 0x04, KEY_4 }, + { 0x86, 0x6b, 0x05, KEY_5 }, + { 0x86, 0x6b, 0x06, KEY_6 }, + { 0x86, 0x6b, 0x07, KEY_7 }, + { 0x86, 0x6b, 0x08, KEY_8 }, + { 0x86, 0x6b, 0x09, KEY_9 }, + { 0x86, 0x6b, 0x0a, KEY_0 }, + { 0x86, 0x6b, 0x18, KEY_ZOOM }, + { 0x86, 0x6b, 0x1c, KEY_UNKNOWN }, /* preview */ + { 0x86, 0x6b, 0x13, KEY_UNKNOWN }, /* snap */ + { 0x86, 0x6b, 0x00, KEY_UNDO }, + { 0x86, 0x6b, 0x1d, KEY_RECORD }, + { 0x86, 0x6b, 0x0d, KEY_STOP }, + { 0x86, 0x6b, 0x0e, KEY_PAUSE }, + { 0x86, 0x6b, 0x16, KEY_PLAY }, + { 0x86, 0x6b, 0x11, KEY_BACK }, + { 0x86, 0x6b, 0x19, KEY_FORWARD }, + { 0x86, 0x6b, 0x14, KEY_UNKNOWN }, /* pip */ + { 0x86, 0x6b, 0x15, KEY_ESC }, + { 0x86, 0x6b, 0x1a, KEY_UP }, + { 0x86, 0x6b, 0x1e, KEY_DOWN }, + { 0x86, 0x6b, 0x1f, KEY_LEFT }, + { 0x86, 0x6b, 0x1b, KEY_RIGHT }, +}; /* - * TODO: a tasklet should run with a delay of 1/10 second - * and feed an appropriate event device ? - * NEC protocol is used for remote controlls + * Read the remote control and feed the appropriate event. + * NEC protocol is used for remote controls */ static int dibusb_read_remote_control(struct usb_dibusb *dib) { u8 b[1] = { DIBUSB_REQ_POLL_REMOTE }, rb[5]; int ret; + int i; if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5))) return ret; - - switch (rb[0]) { case DIBUSB_RC_NEC_KEY_PRESSED: + /* rb[1-3] is the actual key, rb[4] is a checksum */ + deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + rb[1], rb[2], rb[3], rb[4]); + + if ((0xff - rb[3]) != rb[4]) { + deb_rc("remote control checksum failed.\n"); + break; + } + /* See if we can match the raw key code. */ + for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++) { + if (rc_keys[i].c0 == rb[1] && + rc_keys[i].c1 == rb[2] && + rc_keys[i].c2 == rb[3]) { + dib->rc_input_event = rc_keys[i].key; + deb_rc("Translated key 0x%04x\n", dib->rc_input_event); + /* Signal down and up events for this key. */ + input_report_key(&dib->rc_input_dev, dib->rc_input_event, 1); + input_report_key(&dib->rc_input_dev, dib->rc_input_event, 0); + input_sync(&dib->rc_input_dev); + break; + } + } + break; + case DIBUSB_RC_NEC_EMPTY: /* No (more) remote control keys. */ break; - case DIBUSB_RC_NEC_EMPTY: case DIBUSB_RC_NEC_KEY_REPEATED: + /* rb[1]..rb[4] are always zero.*/ + /* Repeats often seem to occur so for the moment just ignore this. */ + deb_rc("Key repeat\n"); + break; default: break; } @@ -326,18 +373,38 @@ return 0; } +#define RC_QUERY_INTERVAL (100) /* milliseconds */ + +/* Remote-control poll function - called every RC_QUERY_INTERVAL ms to see + whether the remote control has received anything. */ +static void dibusb_query_rc (void *data) +{ + struct usb_dibusb *dib = (struct usb_dibusb *) data; + /* TODO: need a lock here. We can simply skip checking for the remote control + if we're busy. */ + dibusb_read_remote_control(dib); + schedule_delayed_work(&dib->rc_query_work, + msecs_to_jiffies(RC_QUERY_INTERVAL)); +} + /* - * ioctl for the firmware + * Cypress controls */ -static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen) -{ - u8 b[34]; - int size = plen > 32 ? 32 : plen; - b[0] = DIBUSB_REQ_SET_IOCTL; - b[1] = cmd; - memcpy(&b[2],param,size); - return dibusb_write_usb(dib,b,2+size); +#if 0 +/* + * #if 0'ing the following functions as they are not in use _now_, + * but probably will be sometime. + */ + +/* + * do not use this, just a workaround for a bug, + * which will hopefully never occur :). + */ +static int dibusb_interrupt_read_loop(struct usb_dibusb *dib) +{ + u8 b[1] = { DIBUSB_REQ_INTR_READ }; + return dibusb_write_usb(dib,b,1); } /* @@ -349,6 +416,26 @@ return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1); } +#endif +static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len) +{ + return dibusb_readwrite_usb(dib,buf,len,NULL,0); +} + +/* + * ioctl for the firmware + */ +static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen) +{ + u8 b[34]; + int size = plen > 32 ? 32 : plen; + b[0] = DIBUSB_REQ_SET_IOCTL; + b[1] = cmd; + memcpy(&b[2],param,size); + + return dibusb_write_usb(dib,b,2+size); +} + static int dibusb_hw_wakeup(struct usb_dibusb *dib) { u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP }; @@ -387,19 +474,110 @@ return I2C_FUNC_I2C; } -static int dibusb_i2c_client_register (struct i2c_client *i2c) +static int thomson_cable_eu_pll_set(struct dvb_frontend* fe, struct + dvb_frontend_parameters* params); + +static struct dib3000_config thomson_cable_eu_config = { + .demod_address = 0x10, + .pll_addr = 194, + .pll_set = thomson_cable_eu_pll_set, +}; + +static int thomson_cable_eu_pll_set(struct dvb_frontend* fe, struct + dvb_frontend_parameters* params) { - struct usb_dibusb *dib = i2c_get_adapdata(i2c->adapter); - if (i2c->driver->command) - return i2c->driver->command(i2c,FE_REGISTER,dib->adapter); + struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; + u8 buf[4]; + struct i2c_msg msg = { + .addr = thomson_cable_eu_config.pll_addr, + .flags = 0, + .buf = buf, + .len = sizeof(buf) + }; + u32 tfreq = (params->frequency + 36125000) / 62500; + int vu,p0,p1,p2; + + if (params->frequency > 403250000) + vu = 1, p2 = 1, p1 = 0, p0 = 1; + else if (params->frequency > 115750000) + vu = 0, p2 = 1, p1 = 1, p0 = 0; + else if (params->frequency > 44250000) + vu = 0, p2 = 0, p1 = 1, p0 = 1; + else + return -EINVAL; + + buf[0] = (tfreq >> 8) & 0x7f; + buf[1] = tfreq & 0xff; + buf[2] = 0x8e; + buf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0; + + if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1) + return -EIO; + + msleep(1); return 0; } -static int dibusb_i2c_client_unregister (struct i2c_client *i2c) +static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct + dvb_frontend_parameters *params); + +static struct dib3000_config panasonic_cofdm_env57h1xd5 = { + .demod_address = 0x18, + .pll_addr = 192, + .pll_set = panasonic_cofdm_env57h1xd5_pll_set, +}; + +static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct + dvb_frontend_parameters *params) { - struct usb_dibusb *dib = i2c_get_adapdata(i2c->adapter); - if (i2c->driver->command) - return i2c->driver->command(i2c,FE_UNREGISTER,dib->adapter); + struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; + u8 buf[4]; + u32 freq = params->frequency; + u32 tfreq = (freq + 36125000) / 1000000 * 6 + 1; + u8 TA, T210, R210, ctrl1, cp210, p4321; + struct i2c_msg msg = { + .addr = panasonic_cofdm_env57h1xd5.pll_addr, + .flags = 0, + .buf = buf, + .len = sizeof(buf) + }; + + if (freq > 858000000) { + err("frequency cannot be larger than 858 MHz."); + return -EINVAL; + } + + // contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0 + TA = 1; + T210 = 0; + R210 = 0x2; + ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210; + +// ******** CHARGE PUMP CONFIG vs RF FREQUENCIES ***************** + if (freq < 470000000) + cp210 = 2; // VHF Low and High band ch E12 to E4 to E12 + else if (freq < 526000000) + cp210 = 4; // UHF band Ch E21 to E27 + else // if (freq < 862000000) + cp210 = 5; // UHF band ch E28 to E69 + +//********************* BW select ******************************* + if (freq < 153000000) + p4321 = 1; // BW selected for VHF low + else if (freq < 470000000) + p4321 = 2; // BW selected for VHF high E5 to E12 + else // if (freq < 862000000) + p4321 = 4; // BW selection for UHF E21 to E69 + + buf[0] = (tfreq >> 8) & 0xff; + buf[1] = (tfreq >> 0) & 0xff; + buf[2] = 0xff & ctrl1; + buf[3] = (cp210 << 5) | (p4321); + + if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1) + return -EIO; + + msleep(1); return 0; } @@ -410,6 +588,32 @@ .functionality = dibusb_i2c_func, }; +static void frontend_init(struct usb_dibusb* dib) +{ + switch (dib->dibdev->parm->type) { + case DIBUSB1_1: + case DIBUSB1_1_AN2235: + dib->fe = dib3000mb_attach(&thomson_cable_eu_config, &dib->i2c_adap,&dib->xfer_ops); + break; + case DIBUSB2_0: + dib->fe = dib3000mc_attach(&panasonic_cofdm_env57h1xd5,&dib->i2c_adap, &dib->xfer_ops); + break; + } + + if (dib->fe == NULL) { + printk("dvb-dibusb: A frontend driver was not found for device %04x/%04x\n", + dib->udev->descriptor.idVendor, + dib->udev->descriptor.idProduct); + } else { + if (dvb_register_frontend(dib->adapter, dib->fe)) { + printk("dvb-dibusb: Frontend registration failed!\n"); + if (dib->fe->ops->release) + dib->fe->ops->release(dib->fe); + dib->fe = NULL; + } + } +} + static int dibusb_dvb_init(struct usb_dibusb *dib) { int ret; @@ -423,6 +627,7 @@ deb_info("dvb_register_adapter failed: error %d", ret); goto err; } + dib->adapter->priv = dib; strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE); #ifdef I2C_ADAP_CLASS_TV_DIGITAL @@ -433,8 +638,6 @@ dib->i2c_adap.algo = &dibusb_algo; dib->i2c_adap.algo_data = NULL; dib->i2c_adap.id = I2C_ALGO_BIT; - dib->i2c_adap.client_register = dibusb_i2c_client_register, - dib->i2c_adap.client_unregister = dibusb_i2c_client_unregister, i2c_set_adapdata(&dib->i2c_adap, dib); @@ -446,8 +649,8 @@ dib->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; dib->demux.priv = (void *)dib; - dib->demux.filternum = DIBUSB_MAX_PIDS; - dib->demux.feednum = DIBUSB_MAX_PIDS; + /* get pidcount from demod */ + dib->demux.feednum = dib->demux.filternum = 16; dib->demux.start_feed = dibusb_start_feed; dib->demux.stop_feed = dibusb_stop_feed; dib->demux.write_to_decoder = NULL; @@ -466,6 +669,11 @@ dvb_net_init(dib->adapter, &dib->dvb_net, &dib->demux.dmx); + frontend_init(dib); + + /* Start the remote-control polling. */ + schedule_delayed_work(&dib->rc_query_work, msecs_to_jiffies(RC_QUERY_INTERVAL)); + goto success; err_dmx_dev: dvb_dmx_release(&dib->demux); @@ -482,12 +690,17 @@ static int dibusb_dvb_exit(struct usb_dibusb *dib) { + cancel_delayed_work(&dib->rc_query_work); + flush_scheduled_work(); + input_unregister_device(&dib->rc_input_dev); + dib->dvb_is_ready = 0; deb_info("unregistering DVB part\n"); dvb_net_release(&dib->dvb_net); dib->demux.dmx.close(&dib->demux.dmx); dvb_dmxdev_release(&dib->dmxdev); dvb_dmx_release(&dib->demux); + if (dib->fe != NULL) dvb_unregister_frontend(dib->fe); i2c_del_adapter(&dib->i2c_adap); dvb_unregister_adapter(dib->adapter); @@ -497,21 +710,36 @@ static int dibusb_exit(struct usb_dibusb *dib) { int i; - for (i = 0; i < DIBUSB_TS_NUM_URBS; i++) - if (dib->buf_urb[i] != NULL) { + if (dib->urb_list != NULL) { + for (i = 0; i < dib->dibdev->parm->num_urbs; i++) { + if (dib->urb_list[i] != NULL) { deb_info("killing URB no. %d.\n",i); - usb_kill_urb(dib->buf_urb[i]); // TODO kernel version ifdef for unlink_urb + + /* stop the URBs */ +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7) + usb_unlink_urb(dib->urb_list[i]); +#else + usb_kill_urb(dib->urb_list[i]); +#endif deb_info("freeing URB no. %d.\n",i); - usb_free_urb(dib->buf_urb[i]); + /* free the URBs */ + usb_free_urb(dib->urb_list[i]); + } + } + /* free the urb array */ + kfree(dib->urb_list); } - pci_free_consistent(NULL,DIBUSB_TS_BUFFER_SIZE,dib->buffer,dib->dma_handle); + + pci_free_consistent(NULL, + dib->dibdev->parm->urb_buf_size*dib->dibdev->parm->num_urbs,dib->buffer, + dib->dma_handle); return 0; } static int dibusb_init(struct usb_dibusb *dib) { - int ret,i; + int ret,i,bufsize; sema_init(&dib->usb_sem, 1); sema_init(&dib->i2c_sem, 1); @@ -519,46 +747,74 @@ * when reloading the driver w/o replugging the device * a timeout occures, this helps */ - usb_clear_halt(dib->udev,COMMAND_PIPE); - usb_clear_halt(dib->udev,RESULT_PIPE); - usb_clear_halt(dib->udev,DATA_PIPE); - - /* dibusb_reset_cpu(dib); */ + usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->parm->cmd_pipe)); + usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->parm->result_pipe)); + usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->parm->data_pipe)); + + /* allocate the array for the data transfer URBs */ + dib->urb_list = kmalloc(dib->dibdev->parm->num_urbs*sizeof(struct urb *),GFP_KERNEL); + if (dib->urb_list == NULL) + return -ENOMEM; + memset(dib->urb_list,0,dib->dibdev->parm->num_urbs*sizeof(struct urb *)); - if ((dib->buffer = pci_alloc_consistent(NULL,DIBUSB_TS_BUFFER_SIZE, &dib->dma_handle)) == NULL) { + bufsize = dib->dibdev->parm->num_urbs*dib->dibdev->parm->urb_buf_size; + deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize); + /* allocate the actual buffer for the URBs */ + if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) { + deb_info("not enough memory.\n"); + dibusb_exit(dib); return -ENOMEM; } - memset(dib->buffer,0,DIBUSB_TS_BUFFER_SIZE); - for (i = 0; i < DIBUSB_TS_NUM_URBS; i++) { - if (!(dib->buf_urb[i] = usb_alloc_urb(0,GFP_KERNEL))) { + deb_info("allocation complete\n"); + memset(dib->buffer,0,bufsize); + + /* allocate and submit the URBs */ + for (i = 0; i < dib->dibdev->parm->num_urbs; i++) { + if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_KERNEL))) { dibusb_exit(dib); return -ENOMEM; } deb_info("submitting URB no. %d\n",i); - usb_fill_bulk_urb( dib->buf_urb[i], dib->udev, DATA_PIPE, - &dib->buffer[i*DIBUSB_TS_URB_BUFFER_SIZE], DIBUSB_TS_URB_BUFFER_SIZE, + usb_fill_bulk_urb( dib->urb_list[i], dib->udev, + usb_rcvbulkpipe(dib->udev,dib->dibdev->parm->data_pipe), + &dib->buffer[i*dib->dibdev->parm->urb_buf_size], + dib->dibdev->parm->urb_buf_size, dibusb_urb_complete, dib); - dib->buf_urb[i]->transfer_flags = 0; - if ((ret = usb_submit_urb(dib->buf_urb[i],GFP_KERNEL))) { + dib->urb_list[i]->transfer_flags = 0; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7) + dib->urb_list[i]->timeout = 0; +#endif + + if ((ret = usb_submit_urb(dib->urb_list[i],GFP_KERNEL))) { err("could not submit buffer urb no. %d\n",i); dibusb_exit(dib); return ret; } } - for (i=0; i < DIBUSB_MAX_PIDS; i++) { - dib->pid_list[i].reg = i+DIB3000MB_REG_FIRST_PID; - dib->pid_list[i].pid = 0; - dib->pid_list[i].active = 0; - dib->pid_list[i].dib = dib; - } - - dib->feedcount = 0; - dib->streaming = 0; dib->dvb_is_ready = 0; + /* Initialise the remote-control structures.*/ + init_input_dev(&dib->rc_input_dev); + + dib->rc_input_dev.evbit[0] = BIT(EV_KEY); + dib->rc_input_dev.keycodesize = sizeof(unsigned char); + dib->rc_input_dev.keycodemax = KEY_MAX; + dib->rc_input_dev.name = DRIVER_DESC " remote control"; + + for (i=0; irc_input_dev.keybit); + + input_register_device(&dib->rc_input_dev); + + dib->rc_input_event = KEY_MAX; + + INIT_WORK(&dib->rc_query_work, dibusb_query_rc, dib); + + dibusb_hw_wakeup(dib); + if ((ret = dibusb_dvb_init(dib))) { dibusb_exit(dib); return ret; @@ -579,17 +835,20 @@ struct dibusb_device *dibdev) { const struct firmware *fw = NULL; + const char **fws; u16 addr; u8 *b,*p; int ret = 0,i; - for (i = 0; i < sizeof(valid_firmware_filenames)/sizeof(const char*); i++) { - if ((ret = request_firmware(&fw, valid_firmware_filenames[i], &udev->dev)) == 0) { - info("using firmware file (%s).",valid_firmware_filenames[i]); + fws = dibdev->parm->fw_filenames; + + for (i = 0; i < sizeof(fws)/sizeof(const char*); i++) { + if ((ret = request_firmware(&fw, fws[i], &udev->dev)) == 0) { + info("using firmware file (%s).",fws[i]); break; } deb_info("tried to find '%s' firmware - unsuccessful. (%d)\n", - valid_firmware_filenames[i],ret); + fws[i],ret); } if (fw == NULL) { @@ -609,7 +868,7 @@ /* stop the CPU */ reset = 1; - if ((ret = dibusb_writemem(udev,DIBUSB_CPU_CSREG,&reset,1)) != 1) + if ((ret = dibusb_writemem(udev,dibdev->parm->usb_cpu_csreg,&reset,1)) != 1) err("could not stop the USB controller CPU."); for(i = 0; p[i+3] == 0 && i < fw->size; ) { b = (u8 *) &p[i]; @@ -631,7 +890,7 @@ ret = 0; /* restart the CPU */ reset = 0; - if (ret || dibusb_writemem(udev,DIBUSB_CPU_CSREG,&reset,1) != 1) { + if (ret || dibusb_writemem(udev,dibdev->parm->usb_cpu_csreg,&reset,1) != 1) { err("could not restart the USB controller CPU."); ret = -EINVAL; } @@ -686,6 +945,27 @@ } memset(dib,0,sizeof(struct usb_dibusb)); + dib->pid_parse = 1; + switch (udev->speed) { + case USB_SPEED_LOW: + err("cannot handle USB speed because it is to sLOW."); + break; + case USB_SPEED_FULL: + info("running at FULL speed, will use pid parsing."); + break; + case USB_SPEED_HIGH: + if (!pid_parse) { + dib->pid_parse = 0; + info("running at HIGH speed, will deliver the complete TS."); + } else + info("running at HIGH speed, will use pid_parsing anyway."); + break; + case USB_SPEED_UNKNOWN: /* fall through */ + default: + err("cannot handle USB speed because it is unkown."); + break; + } + dib->udev = udev; dib->dibdev = dibdev; Index: wli-2.6.10-rc3-1/drivers/media/dvb/dibusb/dvb-dibusb.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dibusb/dvb-dibusb.h 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dibusb/dvb-dibusb.h 2004-12-22 10:04:35.520402930 -0800 @@ -7,136 +7,278 @@ * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. * - * - * * for more information see dvb-dibusb.c . */ #ifndef __DVB_DIBUSB_H__ #define __DVB_DIBUSB_H__ -#define DIBUSB_DEMOD_I2C_ADDR_DEFAULT 0x10 +#include "dib3000.h" -/* Vendor IDs */ -#define USB_VID_TWINHAN_ID 0x1822 -#define USB_VID_IMC_NETWORKS_ID 0x13d3 -#define USB_VID_EMPIA_ID 0xeb1a -#define USB_VID_DIBCOM_ID 0x10b8 -#define USB_VID_ULTIMA_ELECTRONIC_ID 0x05d8 -#define USB_VID_COMPRO_ID 0x185b -#define USB_VID_HYPER_PALTEK 0x1025 +typedef enum { + DIBUSB1_1 = 0, + DIBUSB2_0, + DIBUSB1_1_AN2235, +} dibusb_type; + +static const char * dibusb_fw_filenames1_1[] = { + "dvb-dibusb-5.0.0.11.fw" +}; + +static const char * dibusb_fw_filenames1_1_an2235[] = { + "dvb-dibusb-an2235-1.fw" +}; -/* Product IDs before loading the firmware */ -#define USB_PID_TWINHAN_VP7041_COLD_ID 0x3201 -#define USB_PID_KWORLD_VSTREAM_COLD_ID 0x17de -#define USB_PID_DIBCOM_MOD3000_COLD_ID 0x0bb8 -#define USB_PID_ULTIMA_TVBOX_COLD_ID 0x8105 -#define USB_PID_COMPRO_DVBU2000_COLD_ID 0xd000 -#define USB_PID_UNK_HYPER_PALTEK_COLD_ID 0x005e - -/* product ID afterwards */ -#define USB_PID_TWINHAN_VP7041_WARM_ID 0x3202 -#define USB_PID_KWORLD_VSTREAM_WARM_ID 0x17df -#define USB_PID_DIBCOM_MOD3000_WARM_ID 0x0bb9 -#define USB_PID_ULTIMA_TVBOX_WARM_ID 0x8106 -#define USB_PID_COMPRO_DVBU2000_WARM_ID 0xd001 -#define USB_PID_UNK_HYPER_PALTEK_WARM_ID 0x005f - -/* static array of valid firmware names, the best one first */ -static const char * valid_firmware_filenames[] = { - "dvb-dibusb-5.0.0.11.fw", +static const char * dibusb_fw_filenames2_0[] = { + "dvb-dibusb-6.0.0.5.fw" +}; + +struct dibusb_device_parameter { + dibusb_type type; + u8 demod_addr; + const char **fw_filenames; + const char *usb_controller; + u16 usb_cpu_csreg; + + int num_urbs; + int urb_buf_size; + int default_size; + int firmware_bug; + + int cmd_pipe; + int result_pipe; + int data_pipe; +}; + +static struct dibusb_device_parameter dibusb_dev_parm[3] = { + { .type = DIBUSB1_1, + .demod_addr = 0x10, + .fw_filenames = dibusb_fw_filenames1_1, + .usb_controller = "Cypress AN2135", + .usb_cpu_csreg = 0x7f92, + + .num_urbs = 3, + .urb_buf_size = 4096, + .default_size = 188*21, + .firmware_bug = 1, + + .cmd_pipe = 0x01, + .result_pipe = 0x81, + .data_pipe = 0x82, + }, + { .type = DIBUSB2_0, + .demod_addr = 0x18, + .fw_filenames = dibusb_fw_filenames2_0, + .usb_controller = "Cypress FX2", + .usb_cpu_csreg = 0xe600, + + .num_urbs = 3, + .urb_buf_size = 40960, + .default_size = 188*210, + .firmware_bug = 0, + + .cmd_pipe = 0x01, + .result_pipe = 0x81, + .data_pipe = 0x86, + }, + { .type = DIBUSB1_1_AN2235, + .demod_addr = 0x10, + .fw_filenames = dibusb_fw_filenames1_1_an2235, + .usb_controller = "Cypress CY7C64613 (AN2235)", + .usb_cpu_csreg = 0x7f92, + + .num_urbs = 3, + .urb_buf_size = 4096, + .default_size = 188*21, + .firmware_bug = 1, + + .cmd_pipe = 0x01, + .result_pipe = 0x81, + .data_pipe = 0x82, + } }; struct dibusb_device { + const char *name; u16 cold_product_id; u16 warm_product_id; - u8 demod_addr; - const char *name; + struct dibusb_device_parameter *parm; }; -#define DIBUSB_SUPPORTED_DEVICES 6 +/* Vendor IDs */ +#define USB_VID_ANCHOR 0x0547 +#define USB_VID_AVERMEDIA 0x14aa +#define USB_VID_COMPRO 0x185b +#define USB_VID_COMPRO_UNK 0x145f +#define USB_VID_CYPRESS 0x04b4 +#define USB_VID_DIBCOM 0x10b8 +#define USB_VID_EMPIA 0xeb1a +#define USB_VID_GRANDTEC 0x5032 +#define USB_VID_HYPER_PALTEK 0x1025 +#define USB_VID_IMC_NETWORKS 0x13d3 +#define USB_VID_TWINHAN 0x1822 +#define USB_VID_ULTIMA_ELECTRONIC 0x05d8 + +/* Product IDs */ +#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 +#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 +#define USB_PID_COMPRO_DVBU2000_COLD 0xd000 +#define USB_PID_COMPRO_DVBU2000_WARM 0xd001 +#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c +#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d +#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 +#define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9 +#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 +#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 +#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 +#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 +#define USB_PID_KWORLD_VSTREAM_COLD 0x17de +#define USB_PID_KWORLD_VSTREAM_WARM 0x17df +#define USB_PID_TWINHAN_VP7041_COLD 0x3201 +#define USB_PID_TWINHAN_VP7041_WARM 0x3202 +#define USB_PID_ULTIMA_TVBOX_COLD 0x8105 +#define USB_PID_ULTIMA_TVBOX_WARM 0x8106 +#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 +#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 +#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 +#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 +#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 +#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 +#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e +#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f +#define USB_PID_YAKUMO_DTT200U_COLD 0x0201 +#define USB_PID_YAKUMO_DTT200U_WARM 0x0301 + +#define DIBUSB_SUPPORTED_DEVICES 15 /* USB Driver stuff */ static struct dibusb_device dibusb_devices[DIBUSB_SUPPORTED_DEVICES] = { - { .cold_product_id = USB_PID_TWINHAN_VP7041_COLD_ID, - .warm_product_id = USB_PID_TWINHAN_VP7041_WARM_ID, - .name = "TwinhanDTV USB-Ter/Magic Box / HAMA USB DVB-T device", - .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT, - }, - { .cold_product_id = USB_PID_KWORLD_VSTREAM_COLD_ID, - .warm_product_id = USB_PID_KWORLD_VSTREAM_WARM_ID, - .name = "KWorld V-Stream XPERT DTV - DVB-T USB", - .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT, - }, - { .cold_product_id = USB_PID_DIBCOM_MOD3000_COLD_ID, - .warm_product_id = USB_PID_DIBCOM_MOD3000_WARM_ID, - .name = "DiBcom USB DVB-T reference design (MOD300)", - .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT, - }, - { .cold_product_id = USB_PID_ULTIMA_TVBOX_COLD_ID, - .warm_product_id = USB_PID_ULTIMA_TVBOX_WARM_ID, - .name = "Ultima Electronic/Artec T1 USB TVBOX", - .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT, - }, - { .cold_product_id = USB_PID_COMPRO_DVBU2000_COLD_ID, - .warm_product_id = USB_PID_COMPRO_DVBU2000_WARM_ID, - .name = "Compro Videomate DVB-U2000 - DVB-T USB", - .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT, - }, - { .cold_product_id = USB_PID_UNK_HYPER_PALTEK_COLD_ID, - .warm_product_id = USB_PID_UNK_HYPER_PALTEK_WARM_ID, - .name = "Unkown USB DVB-T device ???? please report the name to linux-dvb or to the author", - .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT, + { .name = "TwinhanDTV USB1.1 / Magic Box / HAMA USB1.1 DVB-T device", + .cold_product_id = USB_PID_TWINHAN_VP7041_COLD, + .warm_product_id = USB_PID_TWINHAN_VP7041_WARM, + .parm = &dibusb_dev_parm[0], + }, + { .name = "KWorld V-Stream XPERT DTV - DVB-T USB1.1", + .cold_product_id = USB_PID_KWORLD_VSTREAM_COLD, + .warm_product_id = USB_PID_KWORLD_VSTREAM_WARM, + .parm = &dibusb_dev_parm[0], + }, + { .name = "Grandtec USB1.1 DVB-T/DiBcom USB1.1 DVB-T reference design (MOD3000)", + .cold_product_id = USB_PID_DIBCOM_MOD3000_COLD, + .warm_product_id = USB_PID_DIBCOM_MOD3000_WARM, + .parm = &dibusb_dev_parm[0], + }, + { .name = "Artec T1 USB1.1 TVBOX with AN2135", + .cold_product_id = USB_PID_ULTIMA_TVBOX_COLD, + .warm_product_id = USB_PID_ULTIMA_TVBOX_WARM, + .parm = &dibusb_dev_parm[0], + }, + { .name = "Artec T1 USB1.1 TVBOX with AN2235", + .cold_product_id = USB_PID_ULTIMA_TVBOX_AN2235_COLD, + .warm_product_id = USB_PID_ULTIMA_TVBOX_AN2235_WARM, + .parm = &dibusb_dev_parm[2], + }, + { .name = "Artec T1 USB1.1 TVBOX with AN2235 (misdesigned)", + .cold_product_id = USB_PID_ULTIMA_TVBOX_ANCHOR_COLD, + .warm_product_id = 0, /* undefined, this design becomes USB_PID_DIBCOM_MOD3000_WARM in warm state */ + .parm = &dibusb_dev_parm[2], + }, + { .name = "Artec T1 USB2.0 TVBOX (please report the warm ID)", + .cold_product_id = USB_PID_ULTIMA_TVBOX_USB2_COLD, + .warm_product_id = 0, /* don't know, it is most likely that the device will get another USB ID in warm state */ + .parm = &dibusb_dev_parm[1], + }, + { .name = "Artec T1 USB2.0 TVBOX with FX2 IDs (misdesigned, please report the warm ID)", + .cold_product_id = USB_PID_ULTIMA_TVBOX_USB2_FX_COLD, + .warm_product_id = USB_PID_ULTIMA_TVBOX_USB2_FX_WARM, /* undefined, it could be that the device will get another USB ID in warm state */ + .parm = &dibusb_dev_parm[1], + }, + { .name = "Compro Videomate DVB-U2000 - DVB-T USB1.1", + .cold_product_id = USB_PID_COMPRO_DVBU2000_COLD, + .warm_product_id = USB_PID_COMPRO_DVBU2000_WARM, + .parm = &dibusb_dev_parm[0], + }, + { .name = "Compro Videomate DVB-U2000 - DVB-T USB1.1 (really ?? please report the name!)", + .cold_product_id = USB_PID_COMPRO_DVBU2000_UNK_COLD, + .warm_product_id = USB_PID_COMPRO_DVBU2000_UNK_WARM, + .parm = &dibusb_dev_parm[0], + }, + { .name = "Unkown USB1.1 DVB-T device ???? please report the name to the author", + .cold_product_id = USB_PID_UNK_HYPER_PALTEK_COLD, + .warm_product_id = USB_PID_UNK_HYPER_PALTEK_WARM, + .parm = &dibusb_dev_parm[0], + }, + { .name = "DiBcom USB2.0 DVB-T reference design (MOD3000P)", + .cold_product_id = USB_PID_DIBCOM_MOD3001_COLD, + .warm_product_id = USB_PID_DIBCOM_MOD3001_WARM, + .parm = &dibusb_dev_parm[1], + }, + { .name = "Grandtec DVB-T USB1.1", + .cold_product_id = USB_PID_GRANDTEC_DVBT_USB_COLD, + .warm_product_id = USB_PID_GRANDTEC_DVBT_USB_WARM, + .parm = &dibusb_dev_parm[0], + }, + { .name = "Avermedia AverTV DVBT USB1.1", + .cold_product_id = USB_PID_AVERMEDIA_DVBT_USB_COLD, + .warm_product_id = USB_PID_AVERMEDIA_DVBT_USB_WARM, + .parm = &dibusb_dev_parm[0], + }, + { .name = "Yakumo DVB-T mobile USB2.0", + .cold_product_id = USB_PID_YAKUMO_DTT200U_COLD, + .warm_product_id = USB_PID_YAKUMO_DTT200U_WARM, + .parm = &dibusb_dev_parm[1], } }; /* USB Driver stuff */ /* table of devices that work with this driver */ static struct usb_device_id dibusb_table [] = { - { USB_DEVICE(USB_VID_TWINHAN_ID, USB_PID_TWINHAN_VP7041_COLD_ID) }, - { USB_DEVICE(USB_VID_TWINHAN_ID, USB_PID_TWINHAN_VP7041_WARM_ID) }, - { USB_DEVICE(USB_VID_IMC_NETWORKS_ID,USB_PID_TWINHAN_VP7041_COLD_ID) }, - { USB_DEVICE(USB_VID_IMC_NETWORKS_ID,USB_PID_TWINHAN_VP7041_WARM_ID) }, - { USB_DEVICE(USB_VID_EMPIA_ID, USB_PID_KWORLD_VSTREAM_COLD_ID) }, - { USB_DEVICE(USB_VID_EMPIA_ID, USB_PID_KWORLD_VSTREAM_WARM_ID) }, - { USB_DEVICE(USB_VID_DIBCOM_ID, USB_PID_DIBCOM_MOD3000_COLD_ID) }, - { USB_DEVICE(USB_VID_DIBCOM_ID, USB_PID_DIBCOM_MOD3000_WARM_ID) }, - { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC_ID, USB_PID_ULTIMA_TVBOX_COLD_ID) }, - { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC_ID, USB_PID_ULTIMA_TVBOX_WARM_ID) }, - { USB_DEVICE(USB_VID_COMPRO_ID, USB_PID_COMPRO_DVBU2000_COLD_ID) }, - { USB_DEVICE(USB_VID_COMPRO_ID, USB_PID_COMPRO_DVBU2000_WARM_ID) }, - { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD_ID) }, - { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM_ID) }, + { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_COLD)}, + { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_WARM)}, + { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) }, + { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) }, + { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, + { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, + { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) }, + { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) }, + { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) }, + { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) }, + { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) }, + { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) }, + { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_COLD) }, + { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_WARM) }, + { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) }, + { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) }, + { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, + { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, + { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, + { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, + { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_COLD) }, + { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_WARM) }, + { USB_DEVICE(USB_PID_COMPRO_DVBU2000_UNK_COLD, USB_VID_COMPRO_UNK) }, + { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, + +/* + * activate the following define when you have one of the devices and want to + * build it from build-2.6 in dvb-kernel + */ +// #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES +#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES + { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, + { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) }, + { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) }, +#endif { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, dibusb_table); -/* CS register start/stop the usb controller cpu */ -#define DIBUSB_CPU_CSREG 0x7F92 - -// 0x10 is the I2C address of the first demodulator on the board -#define DIBUSB_DEMOD_I2C_ADDR_DEFAULT 0x10 #define DIBUSB_I2C_TIMEOUT HZ*5 -#define DIBUSB_MAX_PIDS 16 - -#define DIB3000MB_REG_FIRST_PID ( 153) - -struct usb_dibusb; - -struct dibusb_pid { - u16 reg; - u16 pid; - int active; - struct usb_dibusb *dib; -}; - -#define DIBUSB_TS_NUM_URBS 3 -#define DIBUSB_TS_URB_BUFFER_SIZE 4096 -#define DIBUSB_TS_BUFFER_SIZE (DIBUSB_TS_NUM_URBS * DIBUSB_TS_URB_BUFFER_SIZE) -#define DIBUSB_TS_DEFAULT_SIZE (188*21) - struct usb_dibusb { /* usb */ struct usb_device * udev; @@ -144,14 +286,13 @@ struct dibusb_device * dibdev; int feedcount; - int streaming; - struct urb * buf_urb[DIBUSB_TS_NUM_URBS]; + int pid_parse; + struct dib3000_xfer_ops xfer_ops; + + struct urb **urb_list; u8 *buffer; dma_addr_t dma_handle; - spinlock_t pid_list_lock; - struct dibusb_pid pid_list[DIBUSB_MAX_PIDS]; - /* I2C */ struct i2c_adapter i2c_adap; struct i2c_client i2c_client; @@ -166,16 +307,14 @@ struct dmxdev dmxdev; struct dvb_demux demux; struct dvb_net dvb_net; + struct dvb_frontend* fe; + + /* remote control */ + struct input_dev rc_input_dev; + struct work_struct rc_query_work; + int rc_input_event; }; -#define COMMAND_PIPE usb_sndbulkpipe(dib->udev, 0x01) -#define RESULT_PIPE usb_rcvbulkpipe(dib->udev, 0x81) -#define DATA_PIPE usb_rcvbulkpipe(dib->udev, 0x82) -/* - * last endpoint 0x83 only used for chaining the buffers - * of the endpoints in the cypress - */ -#define CHAIN_PIPE_DO_NOT_USE usb_rcvbulkpipe(dib->udev, 0x83) /* types of first byte of each buffer */ @@ -209,16 +348,4 @@ #define DIBUSB_IOCTL_POWER_SLEEP 0x00 #define DIBUSB_IOCTL_POWER_WAKEUP 0x01 - -/* - * values from the demodulator which are needed in - * the usb driver as well - */ - -#define DIB3000MB_REG_FIFO ( 145) -#define DIB3000MB_FIFO_INHIBIT ( 1) -#define DIB3000MB_FIFO_ACTIVATE ( 0) - -#define DIB3000MB_ACTIVATE_FILTERING (0x2000) - #endif Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/Makefile 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/Makefile 2004-12-22 10:04:35.521402778 -0800 @@ -4,6 +4,6 @@ dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ dvb_ca_en50221.o dvb_frontend.o \ - dvb_net.o dvb_ksyms.o dvb_ringbuffer.o + dvb_net.o dvb_ringbuffer.o obj-$(CONFIG_DVB_CORE) += dvb-core.o Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dmxdev.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dmxdev.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dmxdev.c 2004-12-22 10:04:35.526402018 -0800 @@ -42,18 +42,12 @@ #define dprintk if (debug) printk -inline struct dmxdev_filter * +static inline struct dmxdev_filter * dvb_dmxdev_file_to_filter(struct file *file) { return (struct dmxdev_filter *) file->private_data; } -inline struct dmxdev_dvr * -dvb_dmxdev_file_to_dvr(struct dmxdev *dmxdev, struct file *file) -{ - return (struct dmxdev_dvr *) file->private_data; -} - static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer) { buffer->data=NULL; @@ -846,7 +840,7 @@ } -ssize_t +static ssize_t dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct dmxdev_filter *dmxdevfilter=dvb_dmxdev_file_to_filter(file); @@ -1122,6 +1116,7 @@ return 0; } +EXPORT_SYMBOL(dvb_dmxdev_init); void dvb_dmxdev_release(struct dmxdev *dmxdev) @@ -1138,5 +1133,5 @@ } dmxdev->demux->close(dmxdev->demux); } - +EXPORT_SYMBOL(dvb_dmxdev_release); Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_ca_en50221.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dvb_ca_en50221.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_ca_en50221.c 2004-12-22 10:04:35.553397914 -0800 @@ -181,10 +181,12 @@ { int i; - if (hlen < nlen) return NULL; + if (hlen < nlen) + return NULL; for(i=0; i<= hlen - nlen; i++) { - if (!strncmp(haystack+i, needle, nlen)) return haystack+i; + if (!strncmp(haystack + i, needle, nlen)) + return haystack + i; } return NULL; @@ -211,7 +213,7 @@ } /* poll mode */ - slot_status = ca->pub->poll_slot_status(ca->pub, slot); + slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open); cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1: 0; cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1: 0; @@ -250,7 +252,8 @@ * * @return 0 on success, nonzero on error. */ -static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private* ca, int slot, u8 waitfor, int timeout_hz) +static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, + u8 waitfor, int timeout_hz) { unsigned long timeout; unsigned long start; @@ -263,7 +266,8 @@ while(1) { /* read the status and check for error */ int res = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS); - if (res < 0) return -EIO; + if (res < 0) + return -EIO; /* if we got the flags, it was successful! */ if (res & waitfor) { @@ -311,24 +315,33 @@ ca->slot_info[slot].link_buf_size = 2; /* read the buffer size from the CAM */ - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) return ret; - if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ/10)) != 0) return ret; - if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) return -EIO; - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) return ret; + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) + return ret; + if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0) + return ret; + if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) + return -EIO; + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) + return ret; /* store it, and choose the minimum of our buffer and the CAM's buffer size */ buf_size = (buf[0] << 8) | buf[1]; - if (buf_size > HOST_LINK_BUF_SIZE) buf_size = HOST_LINK_BUF_SIZE; + if (buf_size > HOST_LINK_BUF_SIZE) + buf_size = HOST_LINK_BUF_SIZE; ca->slot_info[slot].link_buf_size = buf_size; buf[0] = buf_size >> 8; buf[1] = buf_size & 0xff; dprintk("Chosen link buffer size of %i\n", buf_size); /* write the buffer size to the CAM */ - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) return ret; - if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ/10)) != 0) return ret; - if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) return -EIO; - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) return ret; + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) + return ret; + if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0) + return ret; + if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) + return -EIO; + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) + return ret; /* success */ return 0; @@ -355,7 +368,8 @@ int _address = *address; /* grab the next tuple length and type */ - if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0) return _tupleType; + if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0) + return _tupleType; if (_tupleType == 0xff) { dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType); *address += 2; @@ -363,7 +377,8 @@ *tupleLength = 0; return 0; } - if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address+2)) < 0) return _tupleLength; + if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address + 2)) < 0) + return _tupleLength; _address += 4; dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength); @@ -371,7 +386,9 @@ /* read in the whole tuple */ for(i=0; i< _tupleLength; i++) { tuple[i] = ca->pub->read_attribute_mem(ca->pub, slot, _address + (i*2)); - dprintk(" 0x%02x: 0x%02x %c\n", i, tuple[i] & 0xff, ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); + dprintk(" 0x%02x: 0x%02x %c\n", + i, tuple[i] & 0xff, + ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); } _address += (_tupleLength*2); @@ -409,40 +426,58 @@ // CISTPL_DEVICE_0A - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x1D) return -EINVAL; + if ((status = + dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x1D) + return -EINVAL; // CISTPL_DEVICE_0C - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x1C) return -EINVAL; + if ((status = + dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x1C) + return -EINVAL; // CISTPL_VERS_1 - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x15) return -EINVAL; + if ((status = + dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x15) + return -EINVAL; // CISTPL_MANFID - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x20) return -EINVAL; - if (tupleLength != 4) return -EINVAL; + if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, + &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x20) + return -EINVAL; + if (tupleLength != 4) + return -EINVAL; manfid = (tuple[1] << 8) | tuple[0]; devid = (tuple[3] << 8) | tuple[2]; // CISTPL_CONFIG - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x1A) return -EINVAL; - if (tupleLength < 3) return -EINVAL; + if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, + &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x1A) + return -EINVAL; + if (tupleLength < 3) + return -EINVAL; /* extract the configbase */ rasz = tuple[0] & 3; - if (tupleLength < (3 + rasz + 14)) return -EINVAL; + if (tupleLength < (3 + rasz + 14)) + return -EINVAL; ca->slot_info[slot].config_base = 0; for(i=0; i< rasz+1; i++) { ca->slot_info[slot].config_base |= (tuple[2+i] << (8*i)); @@ -450,8 +485,10 @@ /* check it contains the correct DVB string */ dvb_str = findstr(tuple, tupleLength, "DVB_CI_V", 8); - if (dvb_str == NULL) return -EINVAL; - if (tupleLength < ((dvb_str - (char*) tuple) + 12)) return -EINVAL; + if (dvb_str == NULL) + return -EINVAL; + if (tupleLength < ((dvb_str - (char *) tuple) + 12)) + return -EINVAL; /* is it a version we support? */ if (strncmp(dvb_str + 8, "1.00", 4)) { @@ -462,20 +499,25 @@ /* process the CFTABLE_ENTRY tuples, and any after those */ while((!end_chain) && (address < 0x1000)) { - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; + if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, + &tupleLength, tuple)) < 0) + return status; switch(tupleType) { case 0x1B: // CISTPL_CFTABLE_ENTRY - if (tupleLength < (2+11+17)) break; + if (tupleLength < (2 + 11 + 17)) + break; /* if we've already parsed one, just use it */ - if (got_cftableentry) break; + if (got_cftableentry) + break; /* get the config option */ ca->slot_info[slot].config_option = tuple[0] & 0x3f; /* OK, check it contains the correct strings */ if ((findstr(tuple, tupleLength, "DVB_HOST", 8) == NULL) || - (findstr(tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL)) break; + (findstr(tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL)) + break; got_cftableentry = 1; break; @@ -488,17 +530,17 @@ break; default: /* Unknown tuple type - just skip this tuple and move to the next one */ - dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType, tupleLength); + dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType, + tupleLength); break; } } - if ((address > 0x1000) || (!got_cftableentry)) return -EINVAL; + if ((address > 0x1000) || (!got_cftableentry)) + return -EINVAL; dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n", - manfid, devid, - ca->slot_info[slot].config_base, - ca->slot_info[slot].config_option); + manfid, devid, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option); // success! return 0; @@ -518,7 +560,9 @@ dprintk ("%s\n", __FUNCTION__); /* set the config option */ - ca->pub->write_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option); + ca->pub->write_attribute_mem(ca->pub, slot, + ca->slot_info[slot].config_base, + ca->slot_info[slot].config_option); /* check it */ configoption = ca->pub->read_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base); @@ -558,6 +602,11 @@ int buf_free; down_read(&ca->slot_info[slot].sem); + if (ca->slot_info[slot].rx_buffer.data == NULL) { + up_read(&ca->slot_info[slot].sem); + status = -EIO; + goto exit; + } buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); up_read(&ca->slot_info[slot].sem); @@ -568,7 +617,8 @@ } /* check if there is data available */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; if (!(status & STATUSREG_DA)) { /* no data */ status = 0; @@ -576,28 +626,33 @@ } /* read the amount of data */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) + goto exit; bytes_read = status << 8; - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) + goto exit; bytes_read |= status; /* check it will fit */ if (ebuf == NULL) { if (bytes_read > ca->slot_info[slot].link_buf_size) { - printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size!\n", ca->dvbdev->adapter->num); + printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n", + ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } if (bytes_read < 2) { - printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", ca->dvbdev->adapter->num); + printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } } else { if (bytes_read > ecount) { - printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", ca->dvbdev->adapter->num); + printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", + ca->dvbdev->adapter->num); status = -EIO; goto exit; } @@ -606,14 +661,16 @@ /* fill the buffer */ for(i=0; i < bytes_read; i++) { /* read byte and check */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) + goto exit; /* OK, store it in the buffer */ buf[i] = status; } /* check for read error (RE should now be 0) */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; if (status & STATUSREG_RE) { ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; @@ -623,13 +680,19 @@ /* OK, add it to the receive buffer, or copy into external buffer if supplied */ if (ebuf == NULL) { down_read(&ca->slot_info[slot].sem); + if (ca->slot_info[slot].rx_buffer.data == NULL) { + up_read(&ca->slot_info[slot].sem); + status = -EIO; + goto exit; + } dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read); up_read(&ca->slot_info[slot].sem); } else { memcpy(ebuf, buf, bytes_read); } - dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot, buf[0], (buf[1] & 0x80) == 0, bytes_read); + dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot, + buf[0], (buf[1] & 0x80) == 0, bytes_read); /* wake up readers when a last_fragment is received */ if ((buf[1] & 0x80) == 0x00) { @@ -664,20 +727,25 @@ // sanity check - if (bytes_write > ca->slot_info[slot].link_buf_size) return -EINVAL; + if (bytes_write > ca->slot_info[slot].link_buf_size) + return -EINVAL; /* check if interface is actually waiting for us to read from it, or if a read is in progress */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exitnowrite; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exitnowrite; if (status & (STATUSREG_DA|STATUSREG_RE)) { status = -EAGAIN; goto exitnowrite; } /* OK, set HC bit */ - if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_HC)) != 0) goto exit; + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, + IRQEN | CMDREG_HC)) != 0) + goto exit; /* check if interface is still free */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; if (!(status & STATUSREG_FR)) { /* it wasn't free => try again later */ status = -EAGAIN; @@ -685,16 +753,21 @@ } /* send the amount of data */ - if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0) goto exit; - if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW, bytes_write & 0xff)) != 0) goto exit; + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0) + goto exit; + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW, + bytes_write & 0xff)) != 0) + goto exit; /* send the buffer */ for(i=0; i < bytes_write; i++) { - if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0) goto exit; + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0) + goto exit; } /* check for write error (WE should now be 0) */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; if (status & STATUSREG_WE) { ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; @@ -702,7 +775,8 @@ } status = bytes_write; - dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot, buf[0], (buf[1] & 0x80) == 0, bytes_write); + dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot, + buf[0], (buf[1] & 0x80) == 0, bytes_write); exit: ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); @@ -710,6 +784,7 @@ exitnowrite: return status; } +EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq); @@ -730,7 +805,8 @@ down_write(&ca->slot_info[slot].sem); ca->pub->slot_shutdown(ca->pub, slot); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; - if (ca->slot_info[slot].rx_buffer.data) vfree(ca->slot_info[slot].rx_buffer.data); + if (ca->slot_info[slot].rx_buffer.data) + vfree(ca->slot_info[slot].rx_buffer.data); ca->slot_info[slot].rx_buffer.data = NULL; up_write(&ca->slot_info[slot].sem); @@ -743,6 +819,7 @@ /* success */ return 0; } +EXPORT_SYMBOL(dvb_ca_en50221_camready_irq); /** @@ -771,6 +848,7 @@ atomic_inc(&ca->slot_info[slot].camchange_count); dvb_ca_en50221_thread_wakeup(ca); } +EXPORT_SYMBOL(dvb_ca_en50221_frda_irq); /** @@ -815,7 +893,8 @@ break; case DVB_CA_SLOTSTATE_RUNNING: - if (ca->open) dvb_ca_en50221_read_data(ca, slot, NULL, 0); + if (ca->open) + dvb_ca_en50221_read_data(ca, slot, NULL, 0); break; } } @@ -851,7 +930,8 @@ ca->wakeup = 0; return 1; } - if (ca->exit) return 1; + if (ca->exit) + return 1; return 0; } @@ -901,7 +981,8 @@ break; } - if (delay < curdelay) curdelay = delay; + if (delay < curdelay) + curdelay = delay; } ca->delay = curdelay; @@ -918,6 +999,7 @@ char name[15]; int slot; int flags; + int status; int pktcount; void* rxbuf; @@ -938,7 +1020,9 @@ while(!ca->exit) { /* sleep for a bit */ if (!ca->wakeup) { - flags = wait_event_interruptible_timeout(ca->thread_queue, dvb_ca_en50221_thread_should_wakeup(ca), ca->delay); + flags = wait_event_interruptible_timeout(ca->thread_queue, + dvb_ca_en50221_thread_should_wakeup(ca), + ca->delay); if ((flags == -ERESTARTSYS) || ca->exit) { /* got signal or quitting */ break; @@ -952,7 +1036,8 @@ // check the cam status + deal with CAMCHANGEs while(dvb_ca_en50221_check_camstatus(ca, slot)) { /* clear down an old CI slot if necessary */ - if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) dvb_ca_en50221_slot_shutdown(ca, slot); + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) + dvb_ca_en50221_slot_shutdown(ca, slot); /* if a CAM is NOW present, initialise it */ if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) { @@ -979,7 +1064,8 @@ case DVB_CA_SLOTSTATE_WAITREADY: if (time_after(jiffies, ca->slot_info[slot].timeout)) { - printk("dvb_ca adaptor %d: PC card did not respond :(\n", ca->dvbdev->adapter->num); + printk("dvb_ca adaptor %d: PC card did not respond :(\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -988,20 +1074,25 @@ break; case DVB_CA_SLOTSTATE_VALIDATE: - if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { - printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", ca->dvbdev->adapter->num); + if (dvb_ca_en50221_parse_attributes(ca, slot) + != 0) { + printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; } if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { - printk("dvb_ca adapter %d: Unable to initialise CAM :(\n", ca->dvbdev->adapter->num); + printk("dvb_ca adapter %d: Unable to initialise CAM :(\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; } - if (ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_RS) != 0) { - printk("dvb_ca adapter %d: Unable to reset CAM IF\n", ca->dvbdev->adapter->num); + if (ca->pub->write_cam_control(ca->pub, slot, + CTRLIF_COMMAND, CMDREG_RS) != 0) { + printk("dvb_ca adapter %d: Unable to reset CAM IF\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -1016,7 +1107,8 @@ case DVB_CA_SLOTSTATE_WAITFR: if (time_after(jiffies, ca->slot_info[slot].timeout)) { - printk("dvb_ca adapter %d: DVB CAM did not respond :(\n", ca->dvbdev->adapter->num); + printk("dvb_ca adapter %d: DVB CAM did not respond :(\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -1044,7 +1136,9 @@ dvb_ca_en50221_thread_update_delay(ca); break; } + down_write(&ca->slot_info[slot].sem); dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE); + up_write(&ca->slot_info[slot].sem); ca->pub->slot_ts_enable(ca->pub, slot); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; @@ -1053,15 +1147,18 @@ break; case DVB_CA_SLOTSTATE_RUNNING: - if (!ca->open) break; + if (!ca->open) + continue; // no need to poll if the CAM supports IRQs - if (ca->slot_info[slot].da_irq_supported) break; + if (ca->slot_info[slot].da_irq_supported) + break; // poll mode pktcount = 0; - while(dvb_ca_en50221_read_data(ca, slot, NULL, 0) > 0) { - if (!ca->open) break; + while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) { + if (!ca->open) + break; /* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */ if (dvb_ca_en50221_check_camstatus(ca, slot)) { @@ -1105,7 +1202,8 @@ * * @return 0 on success, <0 on error. */ -static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) +static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *parg) { struct dvb_device* dvbdev=(struct dvb_device*) file->private_data; struct dvb_ca_private* ca = (struct dvb_ca_private*) dvbdev->priv; @@ -1120,15 +1218,16 @@ if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { dvb_ca_en50221_slot_shutdown(ca, slot); if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) - dvb_ca_en50221_camchange_irq(ca->pub, slot, DVB_CA_EN50221_CAMCHANGE_INSERTED); + dvb_ca_en50221_camchange_irq(ca->pub, + slot, + DVB_CA_EN50221_CAMCHANGE_INSERTED); } } ca->next_read_slot = 0; dvb_ca_en50221_thread_wakeup(ca); break; - case CA_GET_CAP: - { + case CA_GET_CAP: { struct ca_caps *caps = (struct ca_caps*) parg; caps->slot_num=ca->slot_count; @@ -1138,9 +1237,7 @@ break; } - - case CA_GET_SLOT_INFO: - { + case CA_GET_SLOT_INFO: { struct ca_slot_info *info=(struct ca_slot_info *)parg; if ((info->num > ca->slot_count) || (info->num < 0)) @@ -1148,8 +1245,8 @@ info->type = CA_CI_LINK; info->flags = 0; - if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE) && - (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) { + if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE) + && (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) { info->flags = CA_CI_MODULE_PRESENT; } if (ca->slot_info[info->num].slot_state == DVB_CA_SLOTSTATE_RUNNING) { @@ -1177,7 +1274,8 @@ * * @return 0 on success, <0 on error. */ -static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { return dvb_usercopy(inode, file, cmd, arg, dvb_ca_en50221_io_do_ioctl); } @@ -1193,7 +1291,8 @@ * * @return Number of bytes read, or <0 on error. */ -static ssize_t dvb_ca_en50221_io_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +static ssize_t dvb_ca_en50221_io_write(struct file *file, + const char __user * buf, size_t count, loff_t * ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv; @@ -1208,35 +1307,48 @@ dprintk ("%s\n", __FUNCTION__); /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ - if (count < 2) return -EINVAL; + if (count < 2) + return -EINVAL; /* extract slot & connection id */ - if (copy_from_user(&slot, buf, 1)) return -EFAULT; - if (copy_from_user(&connection_id, buf+1, 1)) return -EFAULT; + if (copy_from_user(&slot, buf, 1)) + return -EFAULT; + if (copy_from_user(&connection_id, buf + 1, 1)) + return -EFAULT; buf+=2; count-=2; /* check if the slot is actually running */ - if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) return -EINVAL; + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) + return -EINVAL; /* fragment the packets & store in the buffer */ while(fragpos < count) { fraglen = ca->slot_info[slot].link_buf_size - 2; - if ((count - fragpos) < fraglen) fraglen = count - fragpos; + if ((count - fragpos) < fraglen) + fraglen = count - fragpos; fragbuf[0] = connection_id; fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00; - if ((status = copy_from_user(fragbuf+2, buf+fragpos, fraglen)) != 0) goto exit; + if ((status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen)) != 0) + goto exit; timeout = jiffies + HZ/2; written = 0; while(!time_after(jiffies, timeout)) { + /* check the CAM hasn't been removed/reset in the meantime */ + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) { + status = -EIO; + goto exit; + } + status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen+2); if (status == (fraglen+2)) { written = 1; break; } - if (status != -EAGAIN) goto exit; + if (status != -EAGAIN) + goto exit; msleep(1); } @@ -1269,14 +1381,21 @@ slot = ca->next_read_slot; while((slot_count < ca->slot_count) && (!found)) { - if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) goto nextslot; + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) + goto nextslot; down_read(&ca->slot_info[slot].sem); + if (ca->slot_info[slot].rx_buffer.data == NULL) { + up_read(&ca->slot_info[slot].sem); + return 0; + } + idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); while(idx != -1) { dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0); - if (connection_id == -1) connection_id = hdr[0]; + if (connection_id == -1) + connection_id = hdr[0]; if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) { *_slot = slot; found = 1; @@ -1286,7 +1405,8 @@ idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); } - if (!found) up_read(&ca->slot_info[slot].sem); + if (!found) + up_read(&ca->slot_info[slot].sem); nextslot: slot = (slot + 1) % ca->slot_count; @@ -1308,7 +1428,8 @@ * * @return Number of bytes read, or <0 on error. */ -static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, + size_t count, loff_t * ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv; @@ -1326,19 +1447,24 @@ dprintk ("%s\n", __FUNCTION__); /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ - if (count < 2) return -EINVAL; + if (count < 2) + return -EINVAL; /* wait for some data */ if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) { /* if we're in nonblocking mode, exit immediately */ - if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; /* wait for some data */ - status = wait_event_interruptible(ca->wait_queue, dvb_ca_en50221_io_read_condition(ca, &result, &slot)); + status = wait_event_interruptible(ca->wait_queue, + dvb_ca_en50221_io_read_condition + (ca, &result, &slot)); } if ((status < 0) || (result < 0)) { - if (result) return result; + if (result) + return result; return status; } @@ -1352,7 +1478,8 @@ } dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0); - if (connection_id == -1) connection_id = hdr[0]; + if (connection_id == -1) + connection_id = hdr[0]; if (hdr[0] == connection_id) { if (pktlen < count) { if ((pktlen + fraglen - 2) > count) { @@ -1361,25 +1488,29 @@ fraglen -= 2; } - if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2, buf + pktlen, fraglen, 1)) < 0) { + if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2, + buf + pktlen, fraglen, 1)) < 0) { goto exit; } pktlen += fraglen; } - if ((hdr[1] & 0x80) == 0) last_fragment = 1; + if ((hdr[1] & 0x80) == 0) + last_fragment = 1; dispose = 1; } idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); - if (dispose) dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx); + if (dispose) + dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx); idx = idx2; dispose = 0; } while (!last_fragment); hdr[0] = slot; hdr[1] = connection_id; - if ((status = copy_to_user(buf, hdr, 2)) != 0) goto exit; + if ((status = copy_to_user(buf, hdr, 2)) != 0) + goto exit; status = pktlen; exit: @@ -1405,14 +1536,20 @@ dprintk ("%s\n", __FUNCTION__); + if (!try_module_get(ca->pub->owner)) + return -EIO; + err=dvb_generic_open(inode, file); if (err<0) return err; for(i=0; i< ca->slot_count; i++) { + if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { down_write(&ca->slot_info[i].sem); + if (ca->slot_info[i].rx_buffer.data != NULL) { dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer); + } up_write(&ca->slot_info[i].sem); } } @@ -1437,7 +1574,7 @@ { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv; - int err; + int err = 0; dprintk ("%s\n", __FUNCTION__); @@ -1446,8 +1583,9 @@ dvb_ca_en50221_thread_update_delay(ca); err=dvb_generic_release(inode, file); - if (err<0) - return err; + + module_put(ca->pub->owner); + return 0; } @@ -1476,7 +1614,8 @@ } /* if there is something, return now */ - if (mask) return mask; + if (mask) + return mask; /* wait for something to happen */ poll_wait(file, &ca->wait_queue, wait); @@ -1488,6 +1627,8 @@ return mask; } +EXPORT_SYMBOL(dvb_ca_en50221_init); + static struct file_operations dvb_ca_fops = { .owner = THIS_MODULE, @@ -1521,7 +1662,8 @@ * * @return 0 on success, nonzero on failure */ -int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* pubca, int flags, int slot_count) +int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, + struct dvb_ca_en50221 *pubca, int flags, int slot_count) { int ret; struct dvb_ca_private* ca = NULL; @@ -1529,10 +1671,13 @@ dprintk ("%s\n", __FUNCTION__); - if (slot_count < 1) return -EINVAL; + if (slot_count < 1) + return -EINVAL; /* initialise the system data */ - if ((ca = (struct dvb_ca_private*) kmalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) { + if ((ca = + (struct dvb_ca_private *) kmalloc(sizeof(struct dvb_ca_private), + GFP_KERNEL)) == NULL) { ret = -ENOMEM; goto error; } @@ -1556,7 +1701,8 @@ /* register the DVB device */ ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA); - if (ret) goto error; + if (ret) + goto error; /* now initialise each slot */ for(i=0; i< slot_count; i++) { @@ -1584,13 +1730,16 @@ error: if (ca != NULL) { - if (ca->dvbdev != NULL) dvb_unregister_device(ca->dvbdev); - if (ca->slot_info != NULL) kfree(ca->slot_info); + if (ca->dvbdev != NULL) + dvb_unregister_device(ca->dvbdev); + if (ca->slot_info != NULL) + kfree(ca->slot_info); kfree(ca); } pubca->private = NULL; return ret; } +EXPORT_SYMBOL(dvb_ca_en50221_release); @@ -1610,7 +1759,8 @@ /* shutdown the thread if there was one */ if (ca->thread_pid) { if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) { - printk("dvb_ca_release adapter %d: thread PID %d already died\n", ca->dvbdev->adapter->num, ca->thread_pid); + printk("dvb_ca_release adapter %d: thread PID %d already died\n", + ca->dvbdev->adapter->num, ca->thread_pid); } else { ca->exit = 1; mb(); Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_ca_en50221.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dvb_ca_en50221.h 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_ca_en50221.h 2004-12-22 10:04:35.555397610 -0800 @@ -42,6 +42,9 @@ /* Structure describing a CA interface */ struct dvb_ca_en50221 { + /* the module owning this structure */ + struct module* owner; + /* NOTE: the read_*, write_* and poll_slot_status functions must use locks as * they may be called from several threads at once */ @@ -62,7 +65,7 @@ * Poll slot status. * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set */ - int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot); + int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open); /* private data, used by caller */ void* data; Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_demux.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dvb_demux.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_demux.c 2004-12-22 10:04:35.561396698 -0800 @@ -424,7 +424,7 @@ feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); } } - +EXPORT_SYMBOL(dvb_dmx_swfilter_packet); void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count) { @@ -439,6 +439,7 @@ spin_unlock(&demux->lock); } +EXPORT_SYMBOL(dvb_dmx_swfilter_packets); void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) @@ -478,6 +479,7 @@ bailout: spin_unlock(&demux->lock); } +EXPORT_SYMBOL(dvb_dmx_swfilter); void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) { @@ -522,6 +524,7 @@ bailout: spin_unlock(&demux->lock); } +EXPORT_SYMBOL(dvb_dmx_swfilter_204); static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux) @@ -1163,6 +1166,7 @@ up(&dvbdemux->mutex); return 0; } +EXPORT_SYMBOL(dvbdmx_connect_frontend); int dvbdmx_disconnect_frontend(struct dmx_demux *demux) @@ -1176,6 +1180,7 @@ up(&dvbdemux->mutex); return 0; } +EXPORT_SYMBOL(dvbdmx_disconnect_frontend); static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids) @@ -1256,6 +1261,7 @@ return 0; } +EXPORT_SYMBOL(dvb_dmx_init); int dvb_dmx_release(struct dvb_demux *dvbdemux) @@ -1269,3 +1275,5 @@ vfree(dvbdemux->feed); return 0; } +EXPORT_SYMBOL(dvb_dmx_release); + Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_filter.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dvb_filter.c 2004-12-22 09:07:08.895369578 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_filter.c 2004-12-22 10:04:35.564396242 -0800 @@ -3,19 +3,20 @@ #include #include "dvb_filter.h" -unsigned int bitrates[3][16] = +#if 0 +static unsigned int bitrates[3][16] = {{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}}; +#endif -u32 freq[4] = {441, 480, 320, 0}; +static u32 freq[4] = {480, 441, 320, 0}; -unsigned int ac3_bitrates[32] = +static unsigned int ac3_bitrates[32] = {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640, 0,0,0,0,0,0,0,0,0,0,0,0,0}; -u32 ac3_freq[4] = {480, 441, 320, 0}; -u32 ac3_frames[3][32] = +static u32 ac3_frames[3][32] = {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024, 1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0}, {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114, @@ -389,6 +390,7 @@ return 0; } +EXPORT_SYMBOL(dvb_filter_get_ac3info); #if 0 @@ -563,6 +565,7 @@ p2ts->cb=cb; p2ts->priv=priv; } +EXPORT_SYMBOL(dvb_filter_pes2ts_init); int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, int len, int payload_start) @@ -597,4 +600,5 @@ memcpy(buf+5+rest, pes, len); return p2ts->cb(p2ts->priv, buf); } +EXPORT_SYMBOL(dvb_filter_pes2ts); Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_frontend.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dvb_frontend.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_frontend.c 2004-12-22 10:04:35.583393354 -0800 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -42,21 +43,20 @@ static int dvb_frontend_debug; static int dvb_shutdown_timeout = 5; -static int dvb_override_frequency_bending; static int dvb_force_auto_inversion; static int dvb_override_tune_delay; -static int do_frequency_bending; +static int dvb_powerdown_on_sleep = 1; module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); MODULE_PARM_DESC(dvb_frontend_debug, "Turn on/off frontend core debugging (default:off)."); module_param(dvb_shutdown_timeout, int, 0444); MODULE_PARM_DESC(dvb_shutdown_timeout, "wait seconds after close() before suspending hardware"); -module_param(dvb_override_frequency_bending, int, 0444); -MODULE_PARM_DESC(dvb_override_frequency_bending, "0: normal (default), 1: never use frequency bending, 2: always use frequency bending"); module_param(dvb_force_auto_inversion, int, 0444); MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); module_param(dvb_override_tune_delay, int, 0444); MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); +module_param(dvb_powerdown_on_sleep, int, 0444); +MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)"); #define dprintk if (dvb_frontend_debug) printk @@ -87,176 +87,9 @@ * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. */ -#define MAX_EVENT 8 - -struct dvb_fe_events { - struct dvb_frontend_event events[MAX_EVENT]; - int eventw; - int eventr; - int overflow; - wait_queue_head_t wait_queue; - struct semaphore sem; -}; - - -struct dvb_frontend_data { - struct dvb_frontend_info *info; - struct dvb_frontend frontend; - struct dvb_device *dvbdev; - struct dvb_frontend_parameters parameters; - struct dvb_fe_events events; - struct module *module; - struct semaphore sem; - struct list_head list_head; - wait_queue_head_t wait_queue; - pid_t thread_pid; - unsigned long release_jiffies; - int state; - int bending; - int lnb_drift; - int inversion; - int auto_step; - int auto_sub_step; - int started_auto_step; - int min_delay; - int max_drift; - int step_size; - int exit; - int wakeup; - fe_status_t status; -}; - - -struct dvb_frontend_ioctl_data { - struct list_head list_head; - 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); - void *before_after_data; -}; - - -struct dvb_frontend_notifier_data { - struct list_head list_head; - struct dvb_adapter *adapter; - void (*callback) (fe_status_t s, void *data); - void *data; -}; - - -static LIST_HEAD(frontend_list); -static LIST_HEAD(frontend_ioctl_list); -static LIST_HEAD(frontend_notifier_list); - static DECLARE_MUTEX(frontend_mutex); - -static int dvb_frontend_internal_ioctl (struct dvb_frontend *frontend, - unsigned int cmd, void *arg) -{ - int err = -EOPNOTSUPP; - - dprintk ("%s\n", __FUNCTION__); - - if (frontend->before_ioctl) - err = frontend->before_ioctl (frontend, cmd, arg); - - if (err == -EOPNOTSUPP) { - err = frontend->ioctl (frontend, cmd, arg); - - if ((err == -EOPNOTSUPP) && frontend->after_ioctl) - err = frontend->after_ioctl (frontend, cmd, arg); - } - - return err; -} - - -/** - * if 2 tuners are located side by side you can get interferences when - * they try to tune to the same frequency, so both lose sync. - * We will slightly mistune in this case. The AFC of the demodulator - * should make it still possible to receive the requested transponder - * on both tuners... - */ -static void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive) -{ - struct list_head *entry; - int stepsize = this_fe->info->frequency_stepsize; - int this_fe_adap_num = this_fe->frontend.dvb_adapter->num; - int frequency; - - if (!stepsize || recursive > 10) { - printk ("%s: too deep recursion, check frequency_stepsize " - "in your frontend code!\n", __FUNCTION__); - return; - } - - dprintk ("%s\n", __FUNCTION__); - - if (!recursive) { - if (down_interruptible (&frontend_mutex)) - return; - - this_fe->bending = 0; - } - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - int f; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.dvb_adapter->num != this_fe_adap_num) - continue; - - f = fe->parameters.frequency; - f += fe->lnb_drift; - f += fe->bending; - - frequency = this_fe->parameters.frequency; - frequency += this_fe->lnb_drift; - frequency += this_fe->bending; - - if (this_fe != fe && (fe->state != FESTATE_IDLE) && - frequency > f - stepsize && frequency < f + stepsize) - { - if (recursive % 2) - this_fe->bending += stepsize; - else - this_fe->bending = -this_fe->bending; - - dvb_bend_frequency (this_fe, recursive + 1); - goto done; - } - } -done: - if (!recursive) - up (&frontend_mutex); -} - - -static void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe, - fe_status_t s) -{ - dprintk ("%s\n", __FUNCTION__); - - if (((s ^ fe->status) & FE_HAS_LOCK) && (s & FE_HAS_LOCK)) - msleep (fe->info->notifier_delay); - - fe->status = s; - - /** - * now tell the Demux about the TS status changes... - */ - if (fe->frontend.notifier_callback) - fe->frontend.notifier_callback(fe->status, fe->frontend.notifier_data); -} - - -static void dvb_frontend_add_event (struct dvb_frontend_data *fe, fe_status_t status) +static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) { struct dvb_fe_events *events = &fe->events; struct dvb_frontend_event *e; @@ -280,21 +113,19 @@ sizeof (struct dvb_frontend_parameters)); if (status & FE_HAS_LOCK) - dvb_frontend_internal_ioctl (&fe->frontend, - FE_GET_FRONTEND, - &e->parameters); + if (fe->ops->get_frontend) + fe->ops->get_frontend(fe, &e->parameters); + events->eventw = wp; up (&events->sem); e->status = status; - dvb_call_frontend_notifiers (fe, status); wake_up_interruptible (&events->wait_queue); } - -static int dvb_frontend_get_event (struct dvb_frontend_data *fe, +static int dvb_frontend_get_event(struct dvb_frontend *fe, struct dvb_frontend_event *event, int flags) { struct dvb_fe_events *events = &fe->events; @@ -337,15 +168,14 @@ return 0; } -static void dvb_frontend_init (struct dvb_frontend_data *fe) +static void dvb_frontend_init(struct dvb_frontend *fe) { - struct dvb_frontend *frontend = &fe->frontend; - dprintk ("DVB: initialising frontend %i (%s)...\n", - frontend->dvb_adapter->num, - fe->info->name); + fe->dvb->num, + fe->ops->info.name); - dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL); + if (fe->ops->init) + fe->ops->init(fe); } static void update_delay (int *quality, int *delay, int min_delay, int locked) @@ -372,7 +202,7 @@ * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT * @returns Number of complete iterations that have been performed. */ -static int dvb_frontend_autotune(struct dvb_frontend_data *fe, int check_wrapped) +static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped) { int autoinversion; int ready = 0; @@ -380,7 +210,7 @@ u32 original_frequency = fe->parameters.frequency; /* are we using autoinversion? */ - autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && + autoinversion = ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)); /* setup parameters correctly */ @@ -441,19 +271,18 @@ return 1; } - /* perform frequency bending if necessary */ - if ((dvb_override_frequency_bending != 1) && do_frequency_bending) - dvb_bend_frequency(fe, 0); - - dprintk("%s: drift:%i bending:%i inversion:%i auto_step:%i " + dprintk("%s: drift:%i inversion:%i auto_step:%i " "auto_sub_step:%i started_auto_step:%i\n", - __FUNCTION__, fe->lnb_drift, fe->bending, fe->inversion, + __FUNCTION__, fe->lnb_drift, fe->inversion, fe->auto_step, fe->auto_sub_step, fe->started_auto_step); /* set the frontend itself */ - fe->parameters.frequency += fe->lnb_drift + fe->bending; - if (autoinversion) fe->parameters.inversion = fe->inversion; - dvb_frontend_internal_ioctl (&fe->frontend, FE_SET_FRONTEND, &fe->parameters); + fe->parameters.frequency += fe->lnb_drift; + if (autoinversion) + fe->parameters.inversion = fe->inversion; + if (fe->ops->set_frontend) + fe->ops->set_frontend(fe, &fe->parameters); + fe->parameters.frequency = original_frequency; fe->parameters.inversion = original_inversion; @@ -461,9 +290,7 @@ return 0; } - - -static int dvb_frontend_is_exiting (struct dvb_frontend_data *fe) +static int dvb_frontend_is_exiting(struct dvb_frontend *fe) { if (fe->exit) return 1; @@ -475,7 +302,7 @@ return 0; } -static int dvb_frontend_should_wakeup (struct dvb_frontend_data *fe) +static int dvb_frontend_should_wakeup(struct dvb_frontend *fe) { if (fe->wakeup) { fe->wakeup = 0; @@ -484,14 +311,18 @@ return dvb_frontend_is_exiting(fe); } -static void dvb_frontend_wakeup (struct dvb_frontend_data *fe) { +static void dvb_frontend_wakeup(struct dvb_frontend *fe) +{ fe->wakeup = 1; wake_up_interruptible(&fe->wait_queue); } +/* + * FIXME: use linux/kthread.h + */ static int dvb_frontend_thread (void *data) { - struct dvb_frontend_data *fe = (struct dvb_frontend_data *) data; + struct dvb_frontend *fe = (struct dvb_frontend *) data; unsigned long timeout; char name [15]; int quality = 0, delay = 3*HZ; @@ -500,27 +331,31 @@ dprintk ("%s\n", __FUNCTION__); - snprintf (name, sizeof(name), "kdvb-fe-%i", - fe->frontend.dvb_adapter->num); + snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num); lock_kernel (); daemonize (name); sigfillset (¤t->blocked); unlock_kernel (); - dvb_call_frontend_notifiers (fe, 0); + fe->status = 0; dvb_frontend_init (fe); fe->wakeup = 0; while (1) { up (&fe->sem); /* is locked when we enter the thread... */ - timeout = wait_event_interruptible_timeout(fe->wait_queue,0 != dvb_frontend_should_wakeup (fe), delay); - if (-ERESTARTSYS == timeout || 0 != dvb_frontend_is_exiting (fe)) { + timeout = wait_event_interruptible_timeout(fe->wait_queue, + dvb_frontend_should_wakeup(fe), + delay); + if (0 != dvb_frontend_is_exiting (fe)) { /* got signal or quitting */ break; } + if (current->flags & PF_FREEZE) + refrigerator(PF_FREEZE); + if (down_interruptible (&fe->sem)) break; @@ -531,13 +366,16 @@ continue; } +retune: /* get the frontend status */ if (fe->state & FESTATE_RETUNE) { s = 0; } else { - dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s); + if (fe->ops->read_status) + fe->ops->read_status(fe, &s); if (s != fe->status) { dvb_frontend_add_event (fe, s); + fe->status = s; } } /* if we're not tuned, and we have a lock, move to the TUNED state */ @@ -546,7 +384,7 @@ fe->state = FESTATE_TUNED; /* if we're tuned, then we have determined the correct inversion */ - if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && + if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)) { fe->parameters.inversion = fe->inversion; } @@ -572,7 +410,7 @@ /* don't actually do anything if we're in the LOSTLOCK state, * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ if ((fe->state & FESTATE_LOSTLOCK) && - (fe->info->caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) { + (fe->ops->info.caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); continue; } @@ -616,7 +454,7 @@ * occurs */ if (fe->state & FESTATE_RETUNE) { fe->state = FESTATE_TUNING_FAST; - wake_up_interruptible(&fe->wait_queue); + goto retune; } } @@ -628,10 +466,15 @@ * state until we get a lock */ dvb_frontend_autotune(fe, 0); } - }; + } - if (dvb_shutdown_timeout) - dvb_frontend_internal_ioctl (&fe->frontend, FE_SLEEP, NULL); + if (dvb_shutdown_timeout) { + if (dvb_powerdown_on_sleep) + if (fe->ops->set_voltage) + fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF); + if (fe->ops->sleep) + fe->ops->sleep(fe); + } fe->thread_pid = 0; mb(); @@ -640,8 +483,7 @@ return 0; } - -static void dvb_frontend_stop (struct dvb_frontend_data *fe) +static void dvb_frontend_stop(struct dvb_frontend *fe) { unsigned long ret; @@ -679,8 +521,7 @@ fe->thread_pid); } - -static int dvb_frontend_start (struct dvb_frontend_data *fe) +static int dvb_frontend_start(struct dvb_frontend *fe) { int ret; @@ -719,13 +560,12 @@ unsigned int cmd, void *parg) { struct dvb_device *dvbdev = file->private_data; - struct dvb_frontend_data *fe = dvbdev->priv; - struct dvb_frontend_tune_settings fetunesettings; - int err = 0; + struct dvb_frontend *fe = dvbdev->priv; + int err = -EOPNOTSUPP; dprintk ("%s\n", __FUNCTION__); - if (!fe || !fe->frontend.ioctl || fe->exit) + if (!fe || fe->exit) return -ENODEV; if ((file->f_flags & O_ACCMODE) == O_RDONLY && @@ -737,18 +577,103 @@ return -ERESTARTSYS; switch (cmd) { + case FE_GET_INFO: { + struct dvb_frontend_info* info = (struct dvb_frontend_info*) parg; + memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info)); + + /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't + * do it, it is done for it. */ + info->caps |= FE_CAN_INVERSION_AUTO; + err = 0; + break; + } + + case FE_READ_STATUS: + if (fe->ops->read_status) + err = fe->ops->read_status(fe, (fe_status_t*) parg); + break; + + case FE_READ_BER: + if (fe->ops->read_ber) + err = fe->ops->read_ber(fe, (__u32*) parg); + break; + + case FE_READ_SIGNAL_STRENGTH: + if (fe->ops->read_signal_strength) + err = fe->ops->read_signal_strength(fe, (__u16*) parg); + break; + + case FE_READ_SNR: + if (fe->ops->read_snr) + err = fe->ops->read_snr(fe, (__u16*) parg); + break; + + case FE_READ_UNCORRECTED_BLOCKS: + if (fe->ops->read_ucblocks) + err = fe->ops->read_ucblocks(fe, (__u32*) parg); + break; + + + case FE_DISEQC_RESET_OVERLOAD: + if (fe->ops->diseqc_reset_overload) { + err = fe->ops->diseqc_reset_overload(fe); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + case FE_DISEQC_SEND_MASTER_CMD: + if (fe->ops->diseqc_send_master_cmd) { + err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + case FE_DISEQC_SEND_BURST: + if (fe->ops->diseqc_send_burst) { + err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + case FE_SET_TONE: + if (fe->ops->set_tone) { + err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + case FE_SET_VOLTAGE: - if (fe->status) - dvb_call_frontend_notifiers (fe, 0); - dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg); + if (fe->ops->set_voltage) { + err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg); fe->state = FESTATE_DISEQC; + fe->status = 0; + } break; - case FE_SET_FRONTEND: - fe->state = FESTATE_RETUNE; + case FE_DISHNETWORK_SEND_LEGACY_CMD: + if (fe->ops->dishnetwork_send_legacy_command) { + err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + + case FE_DISEQC_RECV_SLAVE_REPLY: + if (fe->ops->diseqc_recv_slave_reply) + err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); + break; + + case FE_ENABLE_HIGH_LNB_VOLTAGE: + if (fe->ops->enable_high_lnb_voltage); + err = fe->ops->enable_high_lnb_voltage(fe, (int) parg); + break; + + case FE_SET_FRONTEND: { + struct dvb_frontend_tune_settings fetunesettings; memcpy (&fe->parameters, parg, sizeof (struct dvb_frontend_parameters)); @@ -762,7 +687,7 @@ fe->parameters.inversion = INVERSION_AUTO; fetunesettings.parameters.inversion = INVERSION_AUTO; } - if (fe->info->type == FE_OFDM) { + if (fe->ops->info.type == FE_OFDM) { /* without hierachical coding code_rate_LP is irrelevant, * so we tolerate the otherwise invalid FEC_NONE setting */ if (fe->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE && @@ -771,14 +696,13 @@ } /* get frontend-specific tuning settings */ - if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS, - &fetunesettings) == 0) { + if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) { fe->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; fe->max_drift = fetunesettings.max_drift; fe->step_size = fetunesettings.step_size; } else { /* default values */ - switch(fe->info->type) { + switch(fe->ops->info.type) { case FE_QPSK: fe->min_delay = HZ/20; fe->step_size = fe->parameters.u.qpsk.symbol_rate / 16000; @@ -793,44 +717,38 @@ case FE_OFDM: fe->min_delay = HZ/20; - fe->step_size = fe->info->frequency_stepsize * 2; - fe->max_drift = (fe->info->frequency_stepsize * 2) + 1; + fe->step_size = fe->ops->info.frequency_stepsize * 2; + fe->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1; break; case FE_ATSC: printk("dvb-core: FE_ATSC not handled yet.\n"); break; } } - if (dvb_override_tune_delay > 0) { + if (dvb_override_tune_delay > 0) fe->min_delay = (dvb_override_tune_delay * HZ) / 1000; - } + fe->state = FESTATE_RETUNE; dvb_frontend_wakeup(fe); dvb_frontend_add_event (fe, 0); + fe->status = 0; + err = 0; break; + } case FE_GET_EVENT: err = dvb_frontend_get_event (fe, parg, file->f_flags); break; + case FE_GET_FRONTEND: - memcpy (parg, &fe->parameters, - sizeof (struct dvb_frontend_parameters)); - /* fall-through... */ - default: - err = dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg); + if (fe->ops->get_frontend) { + memcpy (parg, &fe->parameters, sizeof (struct dvb_frontend_parameters)); + err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg); + } + break; }; up (&fe->sem); - if (err < 0) - return err; - - /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't - * do it, it is done for it. */ - if ((cmd == FE_GET_INFO) && (err == 0)) { - struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) parg; - tmp->caps |= FE_CAN_INVERSION_AUTO; - } - return err; } @@ -838,7 +756,7 @@ static unsigned int dvb_frontend_poll (struct file *file, struct poll_table_struct *wait) { struct dvb_device *dvbdev = file->private_data; - struct dvb_frontend_data *fe = dvbdev->priv; + struct dvb_frontend *fe = dvbdev->priv; dprintk ("%s\n", __FUNCTION__); @@ -854,7 +772,7 @@ static int dvb_frontend_open (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; - struct dvb_frontend_data *fe = dvbdev->priv; + struct dvb_frontend *fe = dvbdev->priv; int ret; dprintk ("%s\n", __FUNCTION__); @@ -871,11 +789,6 @@ fe->events.eventr = fe->events.eventw = 0; } - if (!ret && fe->module) { - if (!try_module_get(fe->module)) - return -EINVAL; - } - return ret; } @@ -883,207 +796,14 @@ static int dvb_frontend_release (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; - struct dvb_frontend_data *fe = dvbdev->priv; - int ret = 0; + struct dvb_frontend *fe = dvbdev->priv; dprintk ("%s\n", __FUNCTION__); if ((file->f_flags & O_ACCMODE) != O_RDONLY) fe->release_jiffies = jiffies; - ret = dvb_generic_release (inode, file); - - if (!ret && fe->module) - module_put(fe->module); - - return ret; -} - - - -int -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, - unsigned int cmd, void *arg), - void *before_after_data) -{ - struct dvb_frontend_ioctl_data *ioctl; - struct list_head *entry; - - dprintk ("%s\n", __FUNCTION__); - - if (down_interruptible (&frontend_mutex)) - return -ERESTARTSYS; - - ioctl = kmalloc (sizeof(struct dvb_frontend_ioctl_data), GFP_KERNEL); - - if (!ioctl) { - up (&frontend_mutex); - return -ENOMEM; - } - - ioctl->adapter = adapter; - ioctl->before_ioctl = before_ioctl; - ioctl->after_ioctl = after_ioctl; - ioctl->before_after_data = before_after_data; - - list_add_tail (&ioctl->list_head, &frontend_ioctl_list); - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.dvb_adapter == adapter && - fe->frontend.before_ioctl == NULL && - fe->frontend.after_ioctl == NULL) - { - fe->frontend.before_ioctl = before_ioctl; - fe->frontend.after_ioctl = after_ioctl; - fe->frontend.before_after_data = before_after_data; - } - } - - up (&frontend_mutex); - - return 0; -} - - -void -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)) -{ - struct list_head *entry, *n; - - dprintk ("%s\n", __FUNCTION__); - - down (&frontend_mutex); - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.dvb_adapter == adapter && - fe->frontend.before_ioctl == before_ioctl && - fe->frontend.after_ioctl == after_ioctl) - { - fe->frontend.before_ioctl = NULL; - fe->frontend.after_ioctl = NULL; - - } - } - - list_for_each_safe (entry, n, &frontend_ioctl_list) { - struct dvb_frontend_ioctl_data *ioctl; - - ioctl = list_entry (entry, struct dvb_frontend_ioctl_data, list_head); - - if (ioctl->adapter == adapter && - ioctl->before_ioctl == before_ioctl && - ioctl->after_ioctl == after_ioctl) - { - list_del (&ioctl->list_head); - kfree (ioctl); - - break; - } - } - - up (&frontend_mutex); -} - - -int -dvb_add_frontend_notifier (struct dvb_adapter *adapter, - void (*callback) (fe_status_t s, void *data), - void *data) -{ - struct dvb_frontend_notifier_data *notifier; - struct list_head *entry; - - dprintk ("%s\n", __FUNCTION__); - - if (down_interruptible (&frontend_mutex)) - return -ERESTARTSYS; - - notifier = kmalloc (sizeof(struct dvb_frontend_notifier_data), GFP_KERNEL); - - if (!notifier) { - up (&frontend_mutex); - return -ENOMEM; - } - - notifier->adapter = adapter; - notifier->callback = callback; - notifier->data = data; - - list_add_tail (¬ifier->list_head, &frontend_notifier_list); - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.dvb_adapter == adapter && - fe->frontend.notifier_callback == NULL) - { - fe->frontend.notifier_callback = callback; - fe->frontend.notifier_data = data; - } - } - - up (&frontend_mutex); - - return 0; -} - - -void -dvb_remove_frontend_notifier (struct dvb_adapter *adapter, - void (*callback) (fe_status_t s, void *data)) -{ - struct list_head *entry, *n; - - dprintk ("%s\n", __FUNCTION__); - - down (&frontend_mutex); - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.dvb_adapter == adapter && - fe->frontend.notifier_callback == callback) - { - fe->frontend.notifier_callback = NULL; - - } - } - - list_for_each_safe (entry, n, &frontend_notifier_list) { - struct dvb_frontend_notifier_data *notifier; - - notifier = list_entry (entry, struct dvb_frontend_notifier_data, list_head); - - if (notifier->adapter == adapter && - notifier->callback == callback) - { - list_del (¬ifier->list_head); - kfree (notifier); - - break; - } - } - - up (&frontend_mutex); + return dvb_generic_release (inode, file); } @@ -1095,18 +815,9 @@ .release = dvb_frontend_release }; - - -int -dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - struct dvb_adapter *dvb_adapter, - void *data, - struct dvb_frontend_info *info, - struct module *module) +int dvb_register_frontend(struct dvb_adapter* dvb, + struct dvb_frontend* fe) { - struct list_head *entry; - struct dvb_frontend_data *fe; static const struct dvb_device dvbdev_template = { .users = ~0, .writers = 1, @@ -1120,99 +831,39 @@ if (down_interruptible (&frontend_mutex)) return -ERESTARTSYS; - if (!(fe = kmalloc (sizeof (struct dvb_frontend_data), GFP_KERNEL))) { - up (&frontend_mutex); - return -ENOMEM; - } - - memset (fe, 0, sizeof (struct dvb_frontend_data)); - init_MUTEX (&fe->sem); init_waitqueue_head (&fe->wait_queue); init_waitqueue_head (&fe->events.wait_queue); init_MUTEX (&fe->events.sem); fe->events.eventw = fe->events.eventr = 0; fe->events.overflow = 0; - fe->module = module; - - fe->frontend.ioctl = ioctl; - fe->frontend.dvb_adapter = dvb_adapter; - fe->frontend.data = data; - fe->info = info; + fe->dvb = dvb; fe->inversion = INVERSION_OFF; - list_for_each (entry, &frontend_ioctl_list) { - struct dvb_frontend_ioctl_data *ioctl; - - ioctl = list_entry (entry, - struct dvb_frontend_ioctl_data, - list_head); - - if (ioctl->adapter == dvb_adapter) { - fe->frontend.before_ioctl = ioctl->before_ioctl; - fe->frontend.after_ioctl = ioctl->after_ioctl; - fe->frontend.before_after_data = ioctl->before_after_data; - break; - } - } - - list_for_each (entry, &frontend_notifier_list) { - struct dvb_frontend_notifier_data *notifier; - - notifier = list_entry (entry, - struct dvb_frontend_notifier_data, - list_head); - - if (notifier->adapter == dvb_adapter) { - fe->frontend.notifier_callback = notifier->callback; - fe->frontend.notifier_data = notifier->data; - break; - } - } - - list_add_tail (&fe->list_head, &frontend_list); - printk ("DVB: registering frontend %i (%s)...\n", - fe->frontend.dvb_adapter->num, - fe->info->name); + fe->dvb->num, + fe->ops->info.name); - dvb_register_device (dvb_adapter, &fe->dvbdev, &dvbdev_template, + dvb_register_device (fe->dvb, &fe->dvbdev, &dvbdev_template, fe, DVB_DEVICE_FRONTEND); - if ((info->caps & FE_NEEDS_BENDING) || (dvb_override_frequency_bending == 2)) - do_frequency_bending = 1; - up (&frontend_mutex); - return 0; } +EXPORT_SYMBOL(dvb_register_frontend); -int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - struct dvb_adapter *dvb_adapter) +int dvb_unregister_frontend(struct dvb_frontend* fe) { - struct list_head *entry, *n; - dprintk ("%s\n", __FUNCTION__); down (&frontend_mutex); - - list_for_each_safe (entry, n, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.ioctl == ioctl && fe->frontend.dvb_adapter == dvb_adapter) { dvb_unregister_device (fe->dvbdev); - list_del (entry); - up (&frontend_mutex); dvb_frontend_stop (fe); - kfree (fe); - return 0; - } - } - + if (fe->ops->release) + fe->ops->release(fe); + else + printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name); up (&frontend_mutex); - return -EINVAL; + return 0; } - +EXPORT_SYMBOL(dvb_unregister_frontend); Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_frontend.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dvb_frontend.h 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_frontend.h 2004-12-22 10:04:35.588392594 -0800 @@ -1,9 +1,12 @@ /* * dvb_frontend.h * - * Copyright (C) 2001 Ralph Metzler for convergence integrated media GmbH - * overhauled by Holger Waechtler for Convergence GmbH + * Copyright (C) 2001 convergence integrated media GmbH + * Copyright (C) 2004 convergence GmbH * + * Written by Ralph Metzler + * Overhauled by Holger Waechtler + * Kernel I2C stuff by Michael Hunold * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -38,8 +41,8 @@ #include "dvbdev.h" /* FIXME: Move to i2c-id.h */ -#define I2C_DRIVERID_DVBFE_ALPS_TDLB7 I2C_DRIVERID_EXP2 -#define I2C_DRIVERID_DVBFE_ALPS_TDMB7 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_SP8870 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_CX22700 I2C_DRIVERID_EXP2 #define I2C_DRIVERID_DVBFE_AT76C651 I2C_DRIVERID_EXP2 #define I2C_DRIVERID_DVBFE_CX24110 I2C_DRIVERID_EXP2 #define I2C_DRIVERID_DVBFE_CX22702 I2C_DRIVERID_EXP2 @@ -56,22 +59,8 @@ #define I2C_DRIVERID_DVBFE_TDA8083 I2C_DRIVERID_EXP2 #define I2C_DRIVERID_DVBFE_VES1820 I2C_DRIVERID_EXP2 #define I2C_DRIVERID_DVBFE_VES1X93 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_TDA80XX I2C_DRIVERID_EXP2 -/** - * when before_ioctl is registered and returns value 0, ioctl and after_ioctl - * are not executed. - */ - -struct dvb_frontend { - int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); - int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); - int (*after_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); - void (*notifier_callback) (fe_status_t s, void *data); - struct dvb_adapter *dvb_adapter; - void *before_after_data; /* can be used by hardware module... */ - void *notifier_data; /* can be used by hardware module... */ - void *data; /* can be used by hardware module... */ -}; struct dvb_frontend_tune_settings { int min_delay_ms; @@ -80,67 +69,79 @@ struct dvb_frontend_parameters parameters; }; +struct dvb_frontend; -/** - * private frontend command ioctl's. - * keep them in sync with the public ones defined in linux/dvb/frontend.h - * - * FE_SLEEP. Ioctl used to put frontend into a low power mode. - * FE_INIT. Ioctl used to initialise the frontend. - * FE_GET_TUNE_SETTINGS. Get the frontend-specific tuning loop settings for the supplied set of parameters. - */ -#define FE_SLEEP _IO('v', 80) -#define FE_INIT _IO('v', 81) -#define FE_GET_TUNE_SETTINGS _IOWR('v', 83, struct dvb_frontend_tune_settings) -#define FE_REGISTER _IO ('v', 84) -#define FE_UNREGISTER _IO ('v', 85) - -extern int -dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - struct dvb_adapter *dvb_adapter, - void *data, - struct dvb_frontend_info *info, - struct module *module); - -extern int -dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - struct dvb_adapter *dvb_adapter); - - -/** - * Add special ioctl code performed before and after the main ioctl - * to all frontend devices on the specified DVB adapter. - * This is necessairy because the 22kHz/13V-18V/DiSEqC stuff depends - * heavily on the hardware around the frontend, the same tuner can create - * these signals on about a million different ways... - * - * Return value: number of frontends where the ioctl's were applied. - */ -extern int -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, - unsigned int cmd, void *arg), - void *before_after_data); - - -extern void -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 *adapter, - void (*callback) (fe_status_t s, void *data), - void *data); -extern void -dvb_remove_frontend_notifier (struct dvb_adapter *adapter, - void (*callback) (fe_status_t s, void *data)); +struct dvb_frontend_ops { -#endif + struct dvb_frontend_info info; + + void (*release)(struct dvb_frontend* fe); + + int (*init)(struct dvb_frontend* fe); + int (*sleep)(struct dvb_frontend* fe); + + int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); + int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); + int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); + + int (*read_status)(struct dvb_frontend* fe, fe_status_t* status); + int (*read_ber)(struct dvb_frontend* fe, u32* ber); + int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength); + int (*read_snr)(struct dvb_frontend* fe, u16* snr); + int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks); + + int (*diseqc_reset_overload)(struct dvb_frontend* fe); + int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd); + int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply); + int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd); + int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); + int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); + int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, int arg); + int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd); +}; + +#define MAX_EVENT 8 + +struct dvb_fe_events { + struct dvb_frontend_event events[MAX_EVENT]; + int eventw; + int eventr; + int overflow; + wait_queue_head_t wait_queue; + struct semaphore sem; +}; + +struct dvb_frontend { + struct dvb_frontend_ops* ops; + struct dvb_adapter *dvb; + void* demodulator_priv; + + struct dvb_device *dvbdev; + struct dvb_frontend_parameters parameters; + struct dvb_fe_events events; + struct semaphore sem; + struct list_head list_head; + wait_queue_head_t wait_queue; + pid_t thread_pid; + unsigned long release_jiffies; + int state; + int bending; + int lnb_drift; + int inversion; + int auto_step; + int auto_sub_step; + int started_auto_step; + int min_delay; + int max_drift; + int step_size; + int exit; + int wakeup; + fe_status_t status; +}; + +extern int dvb_register_frontend(struct dvb_adapter* dvb, + struct dvb_frontend* fe); +extern int dvb_unregister_frontend(struct dvb_frontend* fe); + +#endif Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_net.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dvb_net.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvb_net.c 2004-12-22 10:04:35.606389858 -0800 @@ -6,13 +6,13 @@ * Copyright (C) 2002 Ralph Metzler * * ULE Decapsulation code: - * Copyright (C) 2003 gcs - Global Communication & Services GmbH. - * and Institute for Computer Sciences - * Salzburg University. + * Copyright (C) 2003, 2004 gcs - Global Communication & Services GmbH. + * and Department of Scientific Computing + * Paris Lodron University of Salzburg. * Hilmar Linder * and Wolfram Stering * - * ULE Decaps according to draft-fair-ipdvb-ule-01.txt. + * ULE Decaps according to draft-ietf-ipdvb-ule-03.txt. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,6 +30,31 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ +/* + * ULE ChangeLog: + * Feb 2004: hl/ws v1: Implementing draft-fair-ipdvb-ule-01.txt + * + * Dec 2004: hl/ws v2: Implementing draft-ietf-ipdvb-ule-03.txt: + * ULE Extension header handling. + * Bugreports by Moritz Vieth and Hanno Tersteegen, + * Fraunhofer Institute for Open Communication Systems + * Competence Center for Advanced Satellite Communications. + * Bugfixes and robustness improvements. + * Filtering on dest MAC addresses, if present (D-Bit = 0) + * ULE_DEBUG compile-time option. + */ + +/* + * FIXME / TODO (dvb_net.c): + * + * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero. + * + * TS_FEED callback is called once for every single TS cell although it is + * registered (in dvb_net_feed_start()) for 100 TS cells (used for dvb_net_ule()). + * + */ + +#include #include #include #include @@ -60,6 +85,10 @@ #define DVB_NET_MULTICAST_MAX 10 +#undef ULE_DEBUG + +#ifdef ULE_DEBUG + #define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) static void hexdump( const unsigned char *buf, unsigned short len ) @@ -89,6 +118,7 @@ } } +#endif struct dvb_net_priv { int in_use; @@ -110,18 +140,19 @@ #define RX_MODE_PROMISC 3 struct work_struct set_multicast_list_wq; struct work_struct restart_net_feed_wq; - unsigned char feedtype; - int need_pusi; - unsigned char tscc; /* TS continuity counter after sync. */ - struct sk_buff *ule_skb; - unsigned short ule_sndu_len; - unsigned short ule_sndu_type; - unsigned char ule_sndu_type_1; - unsigned char ule_dbit; /* whether the DestMAC address present - * bit is set or not. */ - unsigned char ule_ethhdr_complete; /* whether we have completed the Ethernet - * header for the current ULE SNDU. */ - int ule_sndu_remain; + unsigned char feedtype; /* Either FEED_TYPE_ or FEED_TYPE_ULE */ + int need_pusi; /* Set to 1, if synchronization on PUSI required. */ + unsigned char tscc; /* TS continuity counter after sync on PUSI. */ + struct sk_buff *ule_skb; /* ULE SNDU decodes into this buffer. */ + unsigned char *ule_next_hdr; /* Pointer into skb to next ULE extension header. */ + unsigned short ule_sndu_len; /* ULE SNDU length in bytes, w/o D-Bit. */ + unsigned short ule_sndu_type; /* ULE SNDU type field, complete. */ + unsigned char ule_sndu_type_1; /* ULE SNDU type field, if split across 2 TS cells. */ + unsigned char ule_dbit; /* Whether the DestMAC address present + * or not (bit is set). */ + unsigned char ule_bridged; /* Whether the ULE_BRIDGED extension header was found. */ + int ule_sndu_remain; /* Nr. of bytes still required for current ULE SNDU. */ + unsigned long ts_count; /* Current ts cell counter. */ }; @@ -141,7 +172,11 @@ skb->mac.raw=skb->data; skb_pull(skb,dev->hard_header_len); +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,8) + eth = skb->mac.ethernet; +#else eth = eth_hdr(skb); +#endif if (*eth->h_dest & 1) { if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) @@ -173,78 +208,194 @@ #define TS_SZ 188 #define TS_SYNC 0x47 #define TS_TEI 0x80 +#define TS_SC 0xC0 #define TS_PUSI 0x40 #define TS_AF_A 0x20 #define TS_AF_D 0x10 +/* ULE Extension Header handlers. */ + #define ULE_TEST 0 #define ULE_BRIDGED 1 -#define ULE_LLC 2 +int ule_test_sndu( struct dvb_net_priv *p ) +{ + return -1; +} + +int ule_bridged_sndu( struct dvb_net_priv *p ) +{ + /* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt. + * This has to be the last extension header, otherwise it won't work. + * Blame the authors! + */ + p->ule_bridged = 1; + return 0; +} + + +/** Handle ULE extension headers. + * Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding. + * Returns: >= 0: nr. of bytes consumed by next extension header + * -1: Mandatory extension header that is not recognized or TEST SNDU; discard. + */ +static int handle_one_ule_extension( struct dvb_net_priv *p ) +{ + /* Table of mandatory extension header handlers. The header type is the index. */ + static int (*ule_mandatory_ext_handlers[255])( struct dvb_net_priv *p ) = + { [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL, }; + + /* Table of optional extension header handlers. The header type is the index. */ + static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = { NULL, }; + + int ext_len = 0; + unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8; + unsigned char htype = p->ule_sndu_type & 0x00FF; + + /* Discriminate mandatory and optional extension headers. */ + if (hlen == 0) { + /* Mandatory extension header */ + if (ule_mandatory_ext_handlers[htype]) { + ext_len = ule_mandatory_ext_handlers[htype]( p ); + p->ule_next_hdr += ext_len; + if (! p->ule_bridged) { + p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr ); + p->ule_next_hdr += 2; + } else { + p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)) ); + /* This assures the extension handling loop will terminate. */ + } + } else + ext_len = -1; /* SNDU has to be discarded. */ + } else { + /* Optional extension header. Calculate the length. */ + ext_len = hlen << 2; + /* Process the optional extension header according to its type. */ + if (ule_optional_ext_handlers[htype]) + (void)ule_optional_ext_handlers[htype]( p ); + p->ule_next_hdr += ext_len; + p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr ); + p->ule_next_hdr += 2; + } + + return ext_len; +} + +static int handle_ule_extensions( struct dvb_net_priv *p ) +{ + int total_ext_len = 0, l; + + p->ule_next_hdr = p->ule_skb->data; + do { + l = handle_one_ule_extension( p ); + if (l == -1) return -1; /* Stop extension header processing and discard SNDU. */ + total_ext_len += l; + + } while (p->ule_sndu_type < 1536); + + return total_ext_len; +} + + +/** Prepare for a new ULE SNDU: reset the decoder state. */ static inline void reset_ule( struct dvb_net_priv *p ) { p->ule_skb = NULL; + p->ule_next_hdr = NULL; p->ule_sndu_len = 0; p->ule_sndu_type = 0; p->ule_sndu_type_1 = 0; p->ule_sndu_remain = 0; p->ule_dbit = 0xFF; - p->ule_ethhdr_complete = 0; + p->ule_bridged = 0; } -static const char eth_dest_addr[] = { 0x0b, 0x0a, 0x09, 0x08, 0x04, 0x03 }; - +/** + * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of + * TS cells of a single PID. + */ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) { struct dvb_net_priv *priv = (struct dvb_net_priv *)dev->priv; - unsigned long skipped = 0L, skblen = 0L; + unsigned long skipped = 0L; u8 *ts, *ts_end, *from_where = NULL, ts_remain = 0, how_much = 0, new_ts = 1; struct ethhdr *ethh = NULL; - unsigned int emergency_count = 0; + +#ifdef ULE_DEBUG + /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ + static unsigned char ule_hist[100*TS_SZ]; + static unsigned char *ule_where = ule_hist, ule_dump = 0; +#endif if (dev == NULL) { printk( KERN_ERR "NO netdev struct!\n" ); return; } - for (ts = (char *)buf, ts_end = (char *)buf + buf_len; ts < ts_end; ) { + /* For all TS cells in current buffer. + * Appearently, we are called for every single TS cell. + */ + for (ts = (char *)buf, ts_end = (char *)buf + buf_len; ts < ts_end; /* no default incr. */ ) { - if (emergency_count++ > 200) { - /* Huh?? */ - hexdump(ts, TS_SZ); - printk(KERN_WARNING "*** LOOP ALERT! ts %p ts_remain %u " - "how_much %u, ule_skb %p, ule_len %u, ule_remain %u\n", - ts, ts_remain, how_much, priv->ule_skb, - priv->ule_sndu_len, priv->ule_sndu_remain); - break; + if (new_ts) { + /* We are about to process a new TS cell. */ + +#ifdef ULE_DEBUG + if (ule_where >= &ule_hist[100*TS_SZ]) ule_where = ule_hist; + memcpy( ule_where, ts, TS_SZ ); + if (ule_dump) { + hexdump( ule_where, TS_SZ ); + ule_dump = 0; } + ule_where += TS_SZ; +#endif - if (new_ts) { - if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI)) { - printk(KERN_WARNING "Invalid TS cell: SYNC %#x, TEI %u.\n", - ts[0], ts[1] & TS_TEI >> 7); + /* Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control . */ + if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) { + printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n", + priv->ts_count, ts[0], ts[1] & TS_TEI >> 7, ts[3] & 0xC0 >> 6); + + /* Drop partly decoded SNDU, reset state, resync on PUSI. */ + if (priv->ule_skb) { + dev_kfree_skb( priv->ule_skb ); + /* Prepare for next SNDU. */ + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; + } + reset_ule(priv); + priv->need_pusi = 1; + + /* Continue with next TS cell. */ + ts += TS_SZ; + priv->ts_count++; continue; } + ts_remain = 184; from_where = ts + 4; } /* Synchronize on PUSI, if required. */ if (priv->need_pusi) { if (ts[1] & TS_PUSI) { - /* Find beginning of first ULE SNDU in current TS cell. - * priv->need_pusi = 0; */ + /* Find beginning of first ULE SNDU in current TS cell. */ + /* Synchronize continuity counter. */ priv->tscc = ts[3] & 0x0F; /* There is a pointer field here. */ if (ts[4] > ts_remain) { - printk(KERN_ERR "Invalid ULE packet " - "(pointer field %d)\n", ts[4]); + printk(KERN_ERR "%lu: Invalid ULE packet " + "(pointer field %d)\n", priv->ts_count, ts[4]); + ts += TS_SZ; + priv->ts_count++; continue; } + /* Skip to destination of pointer field. */ from_where = &ts[5] + ts[4]; ts_remain -= 1 + ts[4]; skipped = 0; } else { skipped++; + ts += TS_SZ; + priv->ts_count++; continue; } } @@ -255,32 +406,45 @@ priv->tscc = (priv->tscc + 1) & 0x0F; else { /* TS discontinuity handling: */ + printk(KERN_WARNING "%lu: TS discontinuity: got %#x, " + "exptected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc); + /* Drop partly decoded SNDU, reset state, resync on PUSI. */ if (priv->ule_skb) { dev_kfree_skb( priv->ule_skb ); /* Prepare for next SNDU. */ - reset_ule(priv); + // reset_ule(priv); moved to below. ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; } + reset_ule(priv); /* skip to next PUSI. */ - printk(KERN_WARNING "TS discontinuity: got %#x, " - "exptected %#x.\n", ts[3] & 0x0F, priv->tscc); priv->need_pusi = 1; + ts += TS_SZ; + priv->ts_count++; continue; } /* If we still have an incomplete payload, but PUSI is - * set, some TS cells are missing. + * set; some TS cells are missing. * This is only possible here, if we missed exactly 16 TS - * cells (continuity counter). */ + * cells (continuity counter wrap). */ if (ts[1] & TS_PUSI) { if (! priv->need_pusi) { - /* printk(KERN_WARNING "Skipping pointer field %u.\n", *from_where); */ if (*from_where > 181) { - printk(KERN_WARNING "*** Invalid pointer " - "field: %u. Current TS cell " - "follows:\n", *from_where); - hexdump( ts, TS_SZ ); - printk(KERN_WARNING "-------------------\n"); + /* Pointer field is invalid. Drop this TS cell and any started ULE SNDU. */ + printk(KERN_WARNING "%lu: Invalid pointer " + "field: %u.\n", priv->ts_count, *from_where); + + /* Drop partly decoded SNDU, reset state, resync on PUSI. */ + if (priv->ule_skb) { + dev_kfree_skb( priv->ule_skb ); + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; + } + reset_ule(priv); + priv->need_pusi = 1; + ts += TS_SZ; + priv->ts_count++; + continue; } /* Skip pointer field (we're processing a * packed payload). */ @@ -290,21 +454,26 @@ priv->need_pusi = 0; if (priv->ule_sndu_remain > 183) { + /* Current SNDU lacks more data than there could be available in the + * current TS cell. */ ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; ((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++; - printk(KERN_WARNING "Expected %d more SNDU bytes, but " - "got PUSI. Flushing incomplete payload.\n", - priv->ule_sndu_remain); + printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but " + "got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n", + priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain); dev_kfree_skb(priv->ule_skb); /* Prepare for next SNDU. */ reset_ule(priv); + /* Resync: go to where pointer field points to: start of next ULE SNDU. */ + from_where += ts[4]; + ts_remain -= ts[4]; } } } /* Check if new payload needs to be started. */ if (priv->ule_skb == NULL) { - /* Start a new payload w/ skb. + /* Start a new payload with skb. * Find ULE header. It is only guaranteed that the * length field (2 bytes) is contained in the current * TS. @@ -318,6 +487,7 @@ } if (! priv->ule_sndu_len) { + /* Got at least two bytes, thus extrace the SNDU length. */ priv->ule_sndu_len = from_where[0] << 8 | from_where[1]; if (priv->ule_sndu_len & 0x8000) { /* D-Bit is set: no dest mac present. */ @@ -326,17 +496,14 @@ } else priv->ule_dbit = 0; - /* printk(KERN_WARNING "ULE D-Bit: %d, SNDU len %u.\n", - priv->ule_dbit, priv->ule_sndu_len); */ - if (priv->ule_sndu_len > 32763) { - printk(KERN_WARNING "Invalid ULE SNDU length %u. " - "Resyncing.\n", priv->ule_sndu_len); - hexdump(ts, TS_SZ); + printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. " + "Resyncing.\n", priv->ts_count, priv->ule_sndu_len); priv->ule_sndu_len = 0; priv->need_pusi = 1; new_ts = 1; ts += TS_SZ; + priv->ts_count++; continue; } ts_remain -= 2; /* consume the 2 bytes SNDU length. */ @@ -354,11 +521,12 @@ case 1: priv->ule_sndu_type = from_where[0] << 8; priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ - /* ts_remain -= 1; from_where += 1; - * here not necessary, because we continue. */ + ts_remain -= 1; from_where += 1; + /* Continue w/ next TS. */ case 0: new_ts = 1; ts += TS_SZ; + priv->ts_count++; continue; default: /* complete ULE header is present in current TS. */ @@ -376,24 +544,9 @@ break; } - if (priv->ule_sndu_type == ULE_TEST) { - /* Test SNDU, discarded by the receiver. */ - printk(KERN_WARNING "Discarding ULE Test SNDU (%d bytes). " - "Resyncing.\n", priv->ule_sndu_len); - priv->ule_sndu_len = 0; - priv->need_pusi = 1; - continue; - } - - skblen = priv->ule_sndu_len; /* Including CRC32 */ - if (priv->ule_sndu_type != ULE_BRIDGED) { - skblen += ETH_HLEN; -#if 1 - if (! priv->ule_dbit) - skblen -= ETH_ALEN; -#endif - } - priv->ule_skb = dev_alloc_skb(skblen); + /* Allocate the skb (decoder target buffer) with the correct size, as follows: + * prepare for the largest case: bridged SNDU with MAC address (dbit = 0). */ + priv->ule_skb = dev_alloc_skb( priv->ule_sndu_len + ETH_HLEN + ETH_ALEN ); if (priv->ule_skb == NULL) { printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); @@ -401,130 +554,129 @@ return; } -#if 0 - if (priv->ule_sndu_type != ULE_BRIDGED) { - // skb_reserve(priv->ule_skb, 2); /* longword align L3 header */ - // Create Ethernet header. - ethh = (struct ethhdr *)skb_put( priv->ule_skb, ETH_HLEN ); - memset( ethh->h_source, 0x00, ETH_ALEN ); - if (priv->ule_dbit) { - // Dest MAC address not present --> generate our own. - memcpy( ethh->h_dest, eth_dest_addr, ETH_ALEN ); - } else { - // Dest MAC address could be split across two TS cells. - // FIXME: implement. - - printk( KERN_WARNING "%s: got destination MAC " - "address.\n", dev->name ); - memcpy( ethh->h_dest, eth_dest_addr, ETH_ALEN ); - } - ethh->h_proto = htons(priv->ule_sndu_type == ULE_LLC ? - priv->ule_sndu_len : priv->ule_sndu_type); - } -#endif - /* this includes the CRC32 _and_ dest mac, if !dbit! */ + /* This includes the CRC32 _and_ dest mac, if !dbit. */ priv->ule_sndu_remain = priv->ule_sndu_len; priv->ule_skb->dev = dev; + /* Leave space for Ethernet or bridged SNDU header (eth hdr plus one MAC addr). */ + skb_reserve( priv->ule_skb, ETH_HLEN + ETH_ALEN ); } /* Copy data into our current skb. */ how_much = min(priv->ule_sndu_remain, (int)ts_remain); - if ((priv->ule_ethhdr_complete < ETH_ALEN) && - (priv->ule_sndu_type != ULE_BRIDGED)) { - ethh = (struct ethhdr *)priv->ule_skb->data; - if (! priv->ule_dbit) { - if (how_much >= (ETH_ALEN - priv->ule_ethhdr_complete)) { - /* copy dest mac address. */ - memcpy(skb_put(priv->ule_skb, - (ETH_ALEN - priv->ule_ethhdr_complete)), - from_where, - (ETH_ALEN - priv->ule_ethhdr_complete)); - memset(ethh->h_source, 0x00, ETH_ALEN); - ethh->h_proto = htons(priv->ule_sndu_type == ULE_LLC ? - priv->ule_sndu_len : - priv->ule_sndu_type); - skb_put(priv->ule_skb, ETH_ALEN + 2); - - how_much -= (ETH_ALEN - priv->ule_ethhdr_complete); - priv->ule_sndu_remain -= (ETH_ALEN - - priv->ule_ethhdr_complete); - ts_remain -= (ETH_ALEN - priv->ule_ethhdr_complete); - from_where += (ETH_ALEN - priv->ule_ethhdr_complete); - priv->ule_ethhdr_complete = ETH_ALEN; - } - } else { - /* Generate whole Ethernet header. */ - memcpy(ethh->h_dest, eth_dest_addr, ETH_ALEN); - memset(ethh->h_source, 0x00, ETH_ALEN); - ethh->h_proto = htons(priv->ule_sndu_type == ULE_LLC ? - priv->ule_sndu_len : priv->ule_sndu_type); - skb_put(priv->ule_skb, ETH_HLEN); - priv->ule_ethhdr_complete = ETH_ALEN; - } - } - /* printk(KERN_WARNING "Copying %u bytes, ule_sndu_remain = %u, " - "ule_sndu_len = %u.\n", how_much, priv->ule_sndu_remain, - priv->ule_sndu_len); */ memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much); priv->ule_sndu_remain -= how_much; ts_remain -= how_much; from_where += how_much; - if ((priv->ule_ethhdr_complete < ETH_ALEN) && - (priv->ule_sndu_type != ULE_BRIDGED)) { - priv->ule_ethhdr_complete += how_much; - } - /* Check for complete payload. */ if (priv->ule_sndu_remain <= 0) { /* Check CRC32, we've got it in our skb already. */ unsigned short ulen = htons(priv->ule_sndu_len); unsigned short utype = htons(priv->ule_sndu_type); - struct kvec iov[4] = { + struct kvec iov[3] = { { &ulen, sizeof ulen }, { &utype, sizeof utype }, - { NULL, 0 }, - { priv->ule_skb->data + ETH_HLEN, - priv->ule_skb->len - ETH_HLEN - 4 } + { priv->ule_skb->data, priv->ule_skb->len - 4 } }; unsigned long ule_crc = ~0L, expected_crc; if (priv->ule_dbit) { /* Set D-bit for CRC32 verification, * if it was set originally. */ ulen |= 0x0080; - } else { - iov[2].iov_base = priv->ule_skb->data; - iov[2].iov_len = ETH_ALEN; } - ule_crc = iov_crc32(ule_crc, iov, 4); + + ule_crc = iov_crc32(ule_crc, iov, 3); expected_crc = *((u8 *)priv->ule_skb->tail - 4) << 24 | *((u8 *)priv->ule_skb->tail - 3) << 16 | *((u8 *)priv->ule_skb->tail - 2) << 8 | *((u8 *)priv->ule_skb->tail - 1); if (ule_crc != expected_crc) { - printk(KERN_WARNING "CRC32 check %s: %#lx / %#lx.\n", - ule_crc != expected_crc ? "FAILED" : "OK", - ule_crc, expected_crc); - hexdump(priv->ule_skb->data + ETH_HLEN, - priv->ule_skb->len - ETH_HLEN); + printk(KERN_WARNING "%lu: CRC32 check FAILED: %#lx / %#lx, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n", + priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0); + +#ifdef ULE_DEBUG + hexdump( iov[0].iov_base, iov[0].iov_len ); + hexdump( iov[1].iov_base, iov[1].iov_len ); + hexdump( iov[2].iov_base, iov[2].iov_len ); + + if (ule_where == ule_hist) { + hexdump( &ule_hist[98*TS_SZ], TS_SZ ); + hexdump( &ule_hist[99*TS_SZ], TS_SZ ); + } else if (ule_where == &ule_hist[TS_SZ]) { + hexdump( &ule_hist[99*TS_SZ], TS_SZ ); + hexdump( ule_hist, TS_SZ ); + } else { + hexdump( ule_where - TS_SZ - TS_SZ, TS_SZ ); + hexdump( ule_where - TS_SZ, TS_SZ ); + } + ule_dump = 1; +#endif ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; ((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++; dev_kfree_skb(priv->ule_skb); } else { + /* CRC32 verified OK. */ + /* Handle ULE Extension Headers. */ + if (priv->ule_sndu_type < 1536) { + /* There is an extension header. Handle it accordingly. */ + int l = handle_ule_extensions( priv ); + if (l < 0) { + /* Mandatory extension header unknown or TEST SNDU. Drop it. */ + // printk( KERN_WARNING "Dropping SNDU, extension headers.\n" ); + dev_kfree_skb( priv->ule_skb ); + goto sndu_done; + } + skb_pull( priv->ule_skb, l ); + } + /* CRC32 was OK. Remove it from skb. */ priv->ule_skb->tail -= 4; priv->ule_skb->len -= 4; + + /* Filter on receiver's destination MAC address, if present. */ + if (!priv->ule_dbit) { + /* The destination MAC address is the next data in the skb. */ + if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) { + /* MAC addresses don't match. Drop SNDU. */ + // printk( KERN_WARNING "Dropping SNDU, MAC address.\n" ); + dev_kfree_skb( priv->ule_skb ); + goto sndu_done; + } + if (! priv->ule_bridged) { + skb_push( priv->ule_skb, ETH_ALEN + 2 ); + ethh = (struct ethhdr *)priv->ule_skb->data; + memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN ); + memset( ethh->h_source, 0, ETH_ALEN ); + ethh->h_proto = htons( priv->ule_sndu_type ); + } else { + /* Skip the Receiver destination MAC address. */ + skb_pull( priv->ule_skb, ETH_ALEN ); + } + } else { + if (! priv->ule_bridged) { + skb_push( priv->ule_skb, ETH_HLEN ); + ethh = (struct ethhdr *)priv->ule_skb->data; + memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN ); + memset( ethh->h_source, 0, ETH_ALEN ); + ethh->h_proto = htons( priv->ule_sndu_type ); + } else { + /* skb is in correct state; nothing to do. */ + } + } + priv->ule_bridged = 0; + /* Stuff into kernel's protocol stack. */ priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev); /* If D-bit is set (i.e. destination MAC address not present), - * receive the packet anyhw. */ - /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) */ - priv->ule_skb->pkt_type = PACKET_HOST; + * receive the packet anyhow. */ + /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) + priv->ule_skb->pkt_type = PACKET_HOST; */ ((struct dvb_net_priv *) dev->priv)->stats.rx_packets++; ((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len; netif_rx(priv->ule_skb); } + sndu_done: /* Prepare for next SNDU. */ reset_ule(priv); } @@ -544,6 +696,7 @@ } else { new_ts = 1; ts += TS_SZ; + priv->ts_count++; if (priv->ule_skb == NULL) { priv->need_pusi = 1; priv->ule_sndu_type_1 = 0; @@ -661,6 +814,7 @@ static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev) { + dev_kfree_skb(skb); return 0; } @@ -722,7 +876,7 @@ unsigned char *mac = (unsigned char *) dev->dev_addr; dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode); - if (priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) + if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) printk("%s: BUG %d\n", __FUNCTION__, __LINE__); priv->secfeed=NULL; @@ -1047,13 +1201,14 @@ } -static int dvb_net_remove_if(struct dvb_net *dvbnet, int num) +static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num) { struct net_device *net = dvbnet->device[num]; - struct dvb_net_priv *priv = net->priv; + struct dvb_net_priv *priv; if (!dvbnet->state[num]) return -EINVAL; + priv = net->priv; if (priv->in_use) return -EBUSY; @@ -1114,10 +1269,18 @@ break; } case NET_REMOVE_IF: + { + int ret; + if (!capable(CAP_SYS_ADMIN)) return -EPERM; - module_put(dvbdev->adapter->module); - return dvb_net_remove_if(dvbnet, (int) (long) parg); + if ((unsigned int) parg >= DVB_NET_DEVICES_MAX) + return -EINVAL; + ret = dvb_net_remove_if(dvbnet, (unsigned int) parg); + if (!ret) + module_put(dvbdev->adapter->module); + return ret; + } /* binary compatiblity cruft */ case __NET_ADD_IF_OLD: @@ -1193,6 +1356,7 @@ dvb_net_remove_if(dvbnet, i); } } +EXPORT_SYMBOL(dvb_net_release); int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet, @@ -1210,4 +1374,4 @@ return 0; } - +EXPORT_SYMBOL(dvb_net_init); Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvbdev.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dvbdev.c 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvbdev.c 2004-12-22 10:04:35.609389402 -0800 @@ -132,6 +132,7 @@ dvbdev->users--; return 0; } +EXPORT_SYMBOL(dvb_generic_open); int dvb_generic_release(struct inode *inode, struct file *file) @@ -150,6 +151,7 @@ dvbdev->users++; return 0; } +EXPORT_SYMBOL(dvb_generic_release); int dvb_generic_ioctl(struct inode *inode, struct file *file, @@ -165,6 +167,7 @@ return dvb_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl); } +EXPORT_SYMBOL(dvb_generic_ioctl); static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) @@ -235,6 +238,7 @@ return 0; } +EXPORT_SYMBOL(dvb_register_device); void dvb_unregister_device(struct dvb_device *dvbdev) @@ -251,6 +255,7 @@ list_del(&dvbdev->list_head); kfree(dvbdev); } +EXPORT_SYMBOL(dvb_unregister_device); static int dvbdev_get_free_adapter_num (void) @@ -309,6 +314,7 @@ return num; } +EXPORT_SYMBOL(dvb_register_adapter); int dvb_unregister_adapter(struct dvb_adapter *adap) @@ -322,6 +328,7 @@ kfree (adap); return 0; } +EXPORT_SYMBOL(dvb_unregister_adapter); /* if the miracle happens and "generic_usercopy()" is included into the kernel, then this can vanish. please don't make the mistake and Index: wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvbdev.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/dvb-core/dvbdev.h 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/dvb-core/dvbdev.h 2004-12-22 10:04:35.611389098 -0800 @@ -49,6 +49,7 @@ struct list_head device_list; const char *name; u8 proposed_mac [6]; + void* priv; struct module *module; }; Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/Kconfig 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/Kconfig 2004-12-22 10:04:35.616388338 -0800 @@ -1,3 +1,6 @@ +menu "Customise DVB Frontends" + depends on DVB_CORE + comment "DVB-S (satellite) frontends" depends on DVB_CORE @@ -7,32 +10,23 @@ help A DVB-S tuner module. Say Y when you want to support this frontend. - Some examples are the Alps BSRU6, the Philips SU1278 and - the LG TDQB-S00x. - - 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_CX24110 - tristate "Connexant CX24110 based" + tristate "Conexant CX24110 based" 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 based" +config DVB_TDA8083 + tristate "Philips TDA8083 based" 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_TDA80XX + tristate "Philips TDA8044 or TDA8083 based" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_MT312 tristate "Zarlink MT312 based" @@ -40,81 +34,53 @@ 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_VES1X93 tristate "VLSI VES1893 or VES1993 based" 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. - comment "DVB-T (terrestrial) frontends" depends on DVB_CORE -config DVB_SP887X - tristate "Microtune sp887x based (i.e. Microtune DTF7072)" +config DVB_SP8870 + tristate "Spase sp8870 based" depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. This driver needs external firmware. Please use the command - "/Documentation/dvb/get_dvb_firmware sp887x" to + "/Documentation/dvb/get_dvb_firmware sp8870" to download/extract it, and then copy it to /usr/lib/hotplug/firmware. - 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_TDLB7 - tristate "Alps TDLB7 based" +config DVB_SP887X + tristate "Spase sp887x based" depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. This driver needs external firmware. Please use the command - "/Documentation/dvb/get_dvb_firmware alps_tdlb7" to + "/Documentation/dvb/get_dvb_firmware sp887x" to download/extract it, and then copy it to /usr/lib/hotplug/firmware. - 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 TDMB7 based" +config DVB_CX22700 + tristate "Conexant CX22700 based" depends on DVB_CORE help A DVB-T 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_CX22702 tristate "Conexant cx22702 demodulator (OFDM)" depends on DVB_CORE help A DVB-T 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_401 - tristate "Grundig 29504-401 based" +config DVB_L64781 + tristate "LSI L64781" depends on DVB_CORE help A DVB-T 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_TDA1004X tristate "Philips TDA10045H/TDA10046H based" depends on DVB_CORE @@ -126,30 +92,18 @@ "/Documentation/dvb/get_dvb_firmware tda10046" to download/extract them, and then copy them to /usr/lib/hotplug/firmware. - 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_NXT6000 tristate "NxtWave Communications NXT6000 based" depends on DVB_CORE help A DVB-T 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_MT352 tristate "Zarlink MT352 based" depends on DVB_CORE help A DVB-T 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_DIB3000MB tristate "DiBcom 3000-MB" depends on DVB_CORE @@ -157,13 +111,12 @@ A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. - Used on USB-powered devices. You should also say Y to DVB_DIBUSB - (DiBcom USB DVB-T Adapter) to support the actual device, - this is "only" the frontend/tuner. - - 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_DIB3000MC + tristate "DiBcom 3000-MC/P" + depends on DVB_CORE + help + A DVB-T tuner module. Designed for mobile usage. Say Y when you want + to support this frontend. comment "DVB-C (cable) frontends" depends on DVB_CORE @@ -174,27 +127,22 @@ help A DVB-C 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_VES1820 tristate "VLSI VES1820 based" depends on DVB_CORE help A DVB-C 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. - -comment "Misc. Frontend Modules" +config DVB_TDA10021 + tristate "Philips TDA10021 based" depends on DVB_CORE + help + A DVB-C tuner module. Say Y when you want to support this frontend. -config DVB_TWINHAN_DST - tristate "Twinhan DST based DVB-S/-T frontend" - depends on DVB_CORE && DVB_BT8XX +config DVB_STV0297 + tristate "ST STV0297 based" + depends on DVB_CORE help - Used in such cards as the VP-1020/1030, Twinhan DST, - VVmer TV@SAT. Say Y when you want to support frontends - using this asic. + A DVB-C tuner module. Say Y when you want to support this frontend. + +endmenu Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/Makefile 2004-12-16 06:19:34.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/Makefile 2004-12-22 10:04:35.618388034 -0800 @@ -4,15 +4,15 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -obj-$(CONFIG_DVB_TWINHAN_DST) += dst.o obj-$(CONFIG_DVB_STV0299) += stv0299.o -obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o -obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o +obj-$(CONFIG_DVB_SP8870) += sp8870.o +obj-$(CONFIG_DVB_CX22700) += cx22700.o obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o obj-$(CONFIG_DVB_CX24110) += cx24110.o -obj-$(CONFIG_DVB_GRUNDIG_29504_491) += grundig_29504-491.o -obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o -obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o +obj-$(CONFIG_DVB_TDA8083) += tda8083.o +obj-$(CONFIG_DVB_L64781) += l64781.o +obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o dib3000-common.o +obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dib3000-common.o obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o obj-$(CONFIG_DVB_VES1X93) += ves1x93.o @@ -21,4 +21,6 @@ obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_CX22702) += cx22702.o - +obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o +obj-$(CONFIG_DVB_TDA10021) += tda10021.o +obj-$(CONFIG_DVB_STV0297) += stv0297.o Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/at76c651.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/at76c651.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/at76c651.c 2004-12-22 10:04:35.629386362 -0800 @@ -24,9 +24,6 @@ * AT76C651 * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf * http://www.atmel.com/atmel/acrobat/doc1320.pdf - * - * TUA6010XS - * http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=19512 */ #include @@ -36,48 +33,34 @@ #include #include #include - #include "dvb_frontend.h" +#include "at76c651.h" -#define FRONTEND_NAME "dvbfe_at76c651" -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG FRONTEND_NAME ": " args); \ - } while (0) +struct at76c651_state { -static int debug; + struct i2c_adapter* i2c; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + struct dvb_frontend_ops ops; + const struct at76c651_config* config; -static struct dvb_frontend_info at76c651_info = { - .name = "Atmel AT76C651B with TUA6010XS", - .type = FE_QAM, - .frequency_min = 48250000, - .frequency_max = 863250000, - .frequency_stepsize = 62500, - /*.frequency_tolerance = */ /* FIXME: 12% of SR */ - .symbol_rate_min = 0, /* FIXME */ - .symbol_rate_max = 9360000, /* FIXME */ - .symbol_rate_tolerance = 4000, - .notifier_delay = 0, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | - FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER -}; + struct dvb_frontend frontend; -struct at76c651_state { + /* revision of the chip */ u8 revision; + + /* last QAM value set */ u8 qam; - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; }; +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "at76c651: " args); \ + } while (0) + + #if ! defined(__powerpc__) static __inline__ int __ilog2(unsigned long x) { @@ -93,14 +76,14 @@ } #endif -static int at76c651_writereg(struct i2c_adapter *i2c, u8 reg, u8 data) +static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data) { int ret; u8 buf[] = { reg, data }; struct i2c_msg msg = - { .addr = 0x1a >> 1, .flags = 0, .buf = buf, .len = 2 }; + { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; - ret = i2c_transfer(i2c, &msg, 1); + ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) dprintk("%s: writereg error " @@ -112,16 +95,16 @@ return (ret != 1) ? -EREMOTEIO : 0; } -static u8 at76c651_readreg(struct i2c_adapter *i2c, u8 reg) +static u8 at76c651_readreg(struct at76c651_state* state, u8 reg) { int ret; u8 val; struct i2c_msg msg[] = { - { .addr = 0x1a >> 1, .flags = 0, .buf = ®, .len = 1 }, - { .addr = 0x1a >> 1, .flags = I2C_M_RD, .buf = &val, .len = 1 } + { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 } }; - ret = i2c_transfer(i2c, msg, 2); + ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); @@ -129,112 +112,64 @@ return val; } -static int at76c651_reset(struct i2c_adapter *i2c) +static int at76c651_reset(struct at76c651_state* state) { - return at76c651_writereg(i2c, 0x07, 0x01); + return at76c651_writereg(state, 0x07, 0x01); } -static void at76c651_disable_interrupts(struct i2c_adapter *i2c) +static void at76c651_disable_interrupts(struct at76c651_state* state) { - at76c651_writereg(i2c, 0x0b, 0x00); + at76c651_writereg(state, 0x0b, 0x00); } static int at76c651_set_auto_config(struct at76c651_state *state) { - struct i2c_adapter *i2c = state->i2c; - /* * Autoconfig */ - at76c651_writereg(i2c, 0x06, 0x01); + at76c651_writereg(state, 0x06, 0x01); /* * Performance optimizations, should be done after autoconfig */ - at76c651_writereg(i2c, 0x10, 0x06); - at76c651_writereg(i2c, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10); - at76c651_writereg(i2c, 0x15, 0x28); - at76c651_writereg(i2c, 0x20, 0x09); - at76c651_writereg(i2c, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90); - at76c651_writereg(i2c, 0x30, 0x90); + at76c651_writereg(state, 0x10, 0x06); + at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10); + at76c651_writereg(state, 0x15, 0x28); + at76c651_writereg(state, 0x20, 0x09); + at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90); + at76c651_writereg(state, 0x30, 0x90); if (state->qam == 5) - at76c651_writereg(i2c, 0x35, 0x2A); + at76c651_writereg(state, 0x35, 0x2A); /* * Initialize A/D-converter */ if (state->revision == 0x11) { - at76c651_writereg(i2c, 0x2E, 0x38); - at76c651_writereg(i2c, 0x2F, 0x13); + at76c651_writereg(state, 0x2E, 0x38); + at76c651_writereg(state, 0x2F, 0x13); } - at76c651_disable_interrupts(i2c); + at76c651_disable_interrupts(state); /* * Restart operation */ - at76c651_reset(i2c); + at76c651_reset(state); return 0; } -static void at76c651_set_bbfreq(struct i2c_adapter *i2c) +static void at76c651_set_bbfreq(struct at76c651_state* state) { - at76c651_writereg(i2c, 0x04, 0x3f); - at76c651_writereg(i2c, 0x05, 0xee); + at76c651_writereg(state, 0x04, 0x3f); + at76c651_writereg(state, 0x05, 0xee); } -static int at76c651_pll_write(struct i2c_adapter *i2c, u8 *buf, size_t len) -{ - int ret; - struct i2c_msg msg = - { .addr = 0xc2 >> 1, .flags = 0, .buf = buf, .len = len }; - - at76c651_writereg(i2c, 0x0c, 0xc3); - - ret = i2c_transfer(i2c, &msg, 1); - - at76c651_writereg(i2c, 0x0c, 0xc2); - - if (ret < 0) - return ret; - else if (ret != 1) - return -EREMOTEIO; - - return 0; -} - -static int tua6010_setfreq(struct i2c_adapter *i2c, u32 freq) -{ - u32 div; - u8 buf[4]; - u8 vu, p2, p1, p0; - - if ((freq < 50000000) || (freq > 900000000)) - return -EINVAL; - - div = (freq + 36125000) / 62500; - - if (freq > 400000000) - vu = 1, p2 = 1, p1 = 0, p0 = 1; - else if (freq > 140000000) - vu = 0, p2 = 1, p1 = 1, p0 = 0; - else - vu = 0, p2 = 0, p1 = 1, p0 = 1; - - buf[0] = (div >> 8) & 0x7f; - buf[1] = (div >> 0) & 0xff; - buf[2] = 0x8e; - buf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0; - - return at76c651_pll_write(i2c, buf, 4); -} - -static int at76c651_set_symbol_rate(struct i2c_adapter *i2c, u32 symbol_rate) +static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate) { u8 exponent; u32 mantissa; @@ -251,9 +186,9 @@ exponent = __ilog2((symbol_rate << 4) / 903125); mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289; - at76c651_writereg(i2c, 0x00, mantissa >> 13); - at76c651_writereg(i2c, 0x01, mantissa >> 5); - at76c651_writereg(i2c, 0x02, (mantissa << 3) | exponent); + at76c651_writereg(state, 0x00, mantissa >> 13); + at76c651_writereg(state, 0x01, mantissa >> 5); + at76c651_writereg(state, 0x02, (mantissa << 3) | exponent); return 0; } @@ -292,13 +227,12 @@ } - return at76c651_writereg(state->i2c, 0x03, state->qam); + return at76c651_writereg(state, 0x03, state->qam); } -static int at76c651_set_inversion(struct i2c_adapter *i2c, - fe_spectral_inversion_t inversion) +static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion) { - u8 feciqinv = at76c651_readreg(i2c, 0x60); + u8 feciqinv = at76c651_readreg(state, 0x60); switch (inversion) { case INVERSION_OFF: @@ -318,59 +252,63 @@ return -EINVAL; } - return at76c651_writereg(i2c, 0x60, feciqinv); + return at76c651_writereg(state, 0x60, feciqinv); } -static int at76c651_set_parameters(struct at76c651_state *state, + + + + + + + + +static int at76c651_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct i2c_adapter *i2c = state->i2c; int ret; + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - if ((ret = tua6010_setfreq(i2c, p->frequency))) - return ret; + at76c651_writereg(state, 0x0c, 0xc3); + state->config->pll_set(fe, p); + at76c651_writereg(state, 0x0c, 0xc2); - if ((ret = at76c651_set_symbol_rate(i2c, p->u.qam.symbol_rate))) + if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate))) return ret; - if ((ret = at76c651_set_inversion(i2c, p->inversion))) + if ((ret = at76c651_set_inversion(state, p->inversion))) return ret; return at76c651_set_auto_config(state); } -static int at76c651_set_defaults(struct at76c651_state *state) +static int at76c651_set_defaults(struct dvb_frontend* fe) { - struct i2c_adapter *i2c = state->i2c; + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - at76c651_set_symbol_rate(i2c, 6900000); + at76c651_set_symbol_rate(state, 6900000); at76c651_set_qam(state, QAM_64); - at76c651_set_bbfreq(i2c); + at76c651_set_bbfreq(state); at76c651_set_auto_config(state); - return 0; + if (state->config->pll_init) { + at76c651_writereg(state, 0x0c, 0xc3); + state->config->pll_init(fe); + at76c651_writereg(state, 0x0c, 0xc2); } -static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct at76c651_state *state = fe->data; - struct i2c_adapter *i2c = state->i2c; - - switch (cmd) { - case FE_GET_INFO: - memcpy(arg, &at76c651_info, sizeof (struct dvb_frontend_info)); - break; + return 0; +} - case FE_READ_STATUS: +static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status) { - fe_status_t *status = arg; + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; u8 sync; /* * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0) */ - sync = at76c651_readreg(i2c, 0x80); - + sync = at76c651_readreg(state, 0x80); *status = 0; if (sync & (0x04 | 0x10)) /* AGC1 || TIM */ @@ -388,186 +326,138 @@ if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */ *status |= FE_HAS_LOCK; - break; - + return 0; } - case FE_READ_BER: +static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 *ber = arg; - *ber = (at76c651_readreg(i2c, 0x81) & 0x0F) << 16; - *ber |= at76c651_readreg(i2c, 0x82) << 8; - *ber |= at76c651_readreg(i2c, 0x83); + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; + + *ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16; + *ber |= at76c651_readreg(state, 0x82) << 8; + *ber |= at76c651_readreg(state, 0x83); *ber *= 10; - break; - } - case FE_READ_SIGNAL_STRENGTH: - { - u8 gain = ~at76c651_readreg(i2c, 0x91); - *(u16 *) arg = (gain << 8) | gain; - break; + return 0; } - case FE_READ_SNR: - *(u16 *)arg = 0xFFFF - - ((at76c651_readreg(i2c, 0x8F) << 8) | - at76c651_readreg(i2c, 0x90)); - break; - - case FE_READ_UNCORRECTED_BLOCKS: - *(u32 *)arg = at76c651_readreg(i2c, 0x82); - break; - - case FE_SET_FRONTEND: - return at76c651_set_parameters(state, arg); - - case FE_GET_FRONTEND: - break; - - case FE_SLEEP: - break; - - case FE_INIT: - return at76c651_set_defaults(state); - - case FE_GET_TUNE_SETTINGS: - { - struct dvb_frontend_tune_settings *fesettings = arg; - fesettings->min_delay_ms = 50; - fesettings->step_size = 0; - fesettings->max_drift = 0; - break; - } +static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength) + { + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - default: - return -ENOIOCTLCMD; - } + u8 gain = ~at76c651_readreg(state, 0x91); + *strength = (gain << 8) | gain; return 0; } -static struct i2c_client client_template; - -static int attach_adapter(struct i2c_adapter *adapter) +static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr) { - struct at76c651_state *state; - struct i2c_client *client; - int ret; - - if (at76c651_readreg(adapter, 0x0E) != 0x65) - return -ENODEV; + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - if (!(state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL))) - return -ENOMEM; + *snr = 0xFFFF - + ((at76c651_readreg(state, 0x8F) << 8) | + at76c651_readreg(state, 0x90)); - state->i2c = adapter; - state->revision = at76c651_readreg(adapter, 0x0F) & 0xFE; - - switch (state->revision) { - case 0x10: - at76c651_info.name[14] = 'A'; - break; - case 0x11: - at76c651_info.name[14] = 'B'; - break; - default: - kfree(state); - return -ENODEV; - } - - if (!(client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { - kfree(state); - return -ENOMEM; - } - - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = 0x1a >> 1; - i2c_set_clientdata(client, state); - - ret = i2c_attach_client(client); - if (ret) { - kfree(state); - kfree(client); - return ret; - } - - BUG_ON(!state->dvb); - - ret = dvb_register_frontend(at76c651_ioctl, state->dvb, state, - &at76c651_info, THIS_MODULE); - if (ret) { - i2c_detach_client(client); - kfree(client); - kfree(state); - return ret; - } return 0; - } +} -static int detach_client(struct i2c_client *client) -{ - struct at76c651_state *state = i2c_get_clientdata(client); +static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) + { + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - dvb_unregister_frontend(at76c651_ioctl, state->dvb); - i2c_detach_client(client); - BUG_ON(state->dvb); - kfree(client); - kfree(state); + *ucblocks = at76c651_readreg(state, 0x82); return 0; } -static int command(struct i2c_client *client, unsigned int cmd, void *arg) +static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings) { - struct at76c651_state *state = i2c_get_clientdata(client); - - switch (cmd) { - case FE_REGISTER: - state->dvb = arg; - break; - case FE_UNREGISTER: - state->dvb = NULL; - break; - default: - return -EOPNOTSUPP; - } - + fesettings->min_delay_ms = 50; + fesettings->step_size = 0; + fesettings->max_drift = 0; return 0; -} + } -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = FRONTEND_NAME, - .id = I2C_DRIVERID_DVBFE_AT76C651, - .flags = I2C_DF_NOTIFY, - .attach_adapter = attach_adapter, - .detach_client = detach_client, - .command = command, -}; +static void at76c651_release(struct dvb_frontend* fe) +{ + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; + kfree(state); + } -static struct i2c_client client_template = { - .name = FRONTEND_NAME, - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, -}; +static struct dvb_frontend_ops at76c651_ops; -static int __init at76c651_init(void) +struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, + struct i2c_adapter* i2c) { - return i2c_add_driver(&driver); -} + struct at76c651_state* state = NULL; -static void __exit at76c651_exit(void) -{ - if (i2c_del_driver(&driver)) - printk(KERN_ERR "at76c651: driver deregistration failed.\n"); -} + /* allocate memory for the internal state */ + state = (struct at76c651_state*) kmalloc(sizeof(struct at76c651_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->qam = 0; + + /* check if the demod is there */ + if (at76c651_readreg(state, 0x0e) != 0x65) goto error; + + /* finalise state setup */ + state->i2c = i2c; + state->revision = at76c651_readreg(state, 0x0f) & 0xfe; + memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops)); + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; +} + +static struct dvb_frontend_ops at76c651_ops = { + + .info = { + .name = "Atmel AT76C651B DVB-C", + .type = FE_QAM, + .frequency_min = 48250000, + .frequency_max = 863250000, + .frequency_stepsize = 62500, + /*.frequency_tolerance = */ /* FIXME: 12% of SR */ + .symbol_rate_min = 0, /* FIXME */ + .symbol_rate_max = 9360000, /* FIXME */ + .symbol_rate_tolerance = 4000, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | + FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER + }, + + .release = at76c651_release, + + .init = at76c651_set_defaults, + + .set_frontend = at76c651_set_parameters, + .get_tune_settings = at76c651_get_tune_settings, + + .read_status = at76c651_read_status, + .read_ber = at76c651_read_ber, + .read_signal_strength = at76c651_read_signal_strength, + .read_snr = at76c651_read_snr, + .read_ucblocks = at76c651_read_ucblocks, +}; -module_init(at76c651_init); -module_exit(at76c651_exit); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("at76c651/tua6010xs dvb-c frontend driver"); +MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver"); MODULE_AUTHOR("Andreas Oberritter "); MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(at76c651_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/cx22702.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/cx22702.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/cx22702.c 2004-12-22 10:04:35.646383778 -0800 @@ -1,8 +1,8 @@ /* - Conexant 22702 DVB OFDM frontend driver + Conexant 22702 DVB OFDM demodulator driver based on: - Alps TDMB7 DVB OFDM frontend driver + Alps TDMB7 DVB OFDM demodulator driver Copyright (C) 2001-2002 Convergence Integrated Media GmbH Holger Waechtler @@ -31,44 +31,28 @@ #include #include #include - #include "dvb_frontend.h" +#include "cx22702.h" -#define FRONTEND_NAME "dvbfe_cx22702" -#define I2C_EEPROM_SLAVE_ADDR 0x50 +struct cx22702_state { -#define PLLTYPE_DTT7592 1 -#define PLLTYPE_DTT7595 2 -#define PLLTYPE_DTT7579 3 + struct i2c_adapter* i2c; -static int debug = 0; + struct dvb_frontend_ops ops; -#define dprintk if (debug) printk + /* configuration settings */ + const struct cx22702_config* config; -static struct dvb_frontend_info cx22702_info = { - .name = "CX22702 Demod Thomson 759x/7579 PLL", - .type = FE_OFDM, - .frequency_min = 177000000, - .frequency_max = 858000000, - .frequency_stepsize = 166666, - .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 | FE_CAN_QAM_AUTO | - FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER -}; + struct dvb_frontend frontend; -struct cx22702_state { - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; - struct dvb_frontend_info cx22702_info; - char pll_type; - int pll_addr; - int demod_addr; + /* previous uncorrected block counter */ u8 prevUCBlocks; }; +static int debug = 0; +#define dprintk if (debug) printk + /* Register values to initialise the demod */ static u8 init_tab [] = { 0x00, 0x00, /* Stop aquisition */ @@ -99,15 +83,13 @@ 0xfd, 0x00, }; -static struct i2c_client client_template; - -static int cx22702_writereg (struct i2c_adapter *i2c, int demod_addr, u8 reg, u8 data) +static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data) { int ret; u8 buf [] = { reg, data }; - struct i2c_msg msg = { .addr = demod_addr, .flags = 0, .buf = buf, .len = 2 }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; - ret = i2c_transfer(i2c, &msg, 1); + ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n", @@ -116,17 +98,17 @@ return (ret != 1) ? -1 : 0; } -static u8 cx22702_readreg (struct i2c_adapter *i2c, int demod_addr, u8 reg) +static u8 cx22702_readreg (struct cx22702_state* state, u8 reg) { int ret; u8 b0 [] = { reg }; u8 b1 [] = { 0 }; struct i2c_msg msg [] = { - { .addr = demod_addr, .flags = 0, .buf = b0, .len = 1 }, - { .addr = demod_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - ret = i2c_transfer(i2c, msg, 2); + ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); @@ -134,232 +116,121 @@ return b1[0]; } -static int pll_readreg(struct i2c_adapter *i2c, int pll_addr, int demod_addr, u8 reg) +static int cx22702_set_inversion (struct cx22702_state *state, int inversion) { - u8 b0 [] = { reg }; - u8 b1 [] = { 0 }; + u8 val; - struct i2c_msg msg [] = { - { .addr = pll_addr, .flags = 0, .buf = b0, .len = 1 }, - { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } - }; - - cx22702_writereg (i2c, demod_addr, 0x0D, cx22702_readreg(i2c,demod_addr,0x0D) &0xfe); // Enable PLL bus - if (i2c_transfer(i2c, msg, 2) != 2) { - printk ("%s i2c pll request failed\n", __FUNCTION__); - cx22702_writereg (i2c, demod_addr, 0x0D, cx22702_readreg(i2c,demod_addr,0x0D) | 1); // Disable PLL bus - return -ENODEV; - } - cx22702_writereg (i2c, demod_addr, 0x0D, cx22702_readreg(i2c,demod_addr,0x0D) | 1); // Disable PLL bus + switch (inversion) { - return b1[0]; -} + case INVERSION_AUTO: + return -EOPNOTSUPP; -static int pll_write (struct i2c_adapter *i2c, int pll_addr, int demod_addr, u8 data [4]) -{ - int ret=0; - struct i2c_msg msg = { .addr = pll_addr, .flags = 0, .buf = data, .len = 4 }; + case INVERSION_ON: + val = cx22702_readreg (state, 0x0C); + return cx22702_writereg (state, 0x0C, val | 0x01); - cx22702_writereg (i2c, demod_addr, 0x0D, cx22702_readreg(i2c,demod_addr,0x0D) &0xfe); // Enable PLL bus - ret = i2c_transfer(i2c, &msg, 1); - cx22702_writereg (i2c, demod_addr, 0x0D, cx22702_readreg(i2c,demod_addr,0x0D) | 1); // Disable PLL bus + case INVERSION_OFF: + val = cx22702_readreg (state, 0x0C); + return cx22702_writereg (state, 0x0C, val & 0xfe); - if (ret != 1) - printk("%s: i/o error (addr == 0x%02x, ret == %i)\n", __FUNCTION__, msg.addr, ret); + default: + return -EINVAL; + + } - return (ret != 1) ? -1 : 0; } -static int pll_dtt759x_set_tv_freq (struct i2c_adapter *i2c, struct cx22702_state *state, u32 freq, int bandwidth) +/* Retrieve the demod settings */ +static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_parameters *p) { - int ret; - - u32 div = (freq + 36166667) / 166666; - - /* dividerhigh, dividerlow, control, bandwidth switch tuner args */ - unsigned char buf [4] = { - (div >> 8) & 0x7f, - div & 0xff, - 0x84, - 0x00 - }; + u8 val; - if(freq < 470000000) { - buf[3] = 0x02; - } else { - buf[3] = 0x08; - } + /* Make sure the TPS regs are valid */ + if (!(cx22702_readreg(state, 0x0A) & 0x20)) + return -EAGAIN; - if(bandwidth == BANDWIDTH_7_MHZ) { - buf[3] |= 0x10; + val = cx22702_readreg (state, 0x01); + switch( (val&0x18)>>3) { + case 0: p->constellation = QPSK; break; + case 1: p->constellation = QAM_16; break; + case 2: p->constellation = QAM_64; break; } - - // Now compensate for the charge pump osc - if(freq <= 264000000) { - buf[2] = buf[2] | 0x30; - } else if (freq <= 735000000) { - buf[2] = buf[2] | 0x38; - } else if (freq <= 835000000) { - buf[2] = buf[2] | 0x70; - } else if (freq <= 896000000) { - buf[2] = buf[2] | 0x78; + switch( val&0x07 ) { + case 0: p->hierarchy_information = HIERARCHY_NONE; break; + case 1: p->hierarchy_information = HIERARCHY_1; break; + case 2: p->hierarchy_information = HIERARCHY_2; break; + case 3: p->hierarchy_information = HIERARCHY_4; break; } - dprintk ("%s: freq == %i, div == 0x%04x\n", __FUNCTION__, (int) freq, (int) div); - - ret= pll_write (i2c, state->pll_addr, state->demod_addr, buf); - if(ret<0) { - dprintk ("%s: first pll_write failed\n",__FUNCTION__); - return ret; - } - /* Set the AGC during search */ - buf[2]=(buf[2] & 0xc7) | 0x18; - buf[3]=0xa0; - ret=pll_write (i2c, state->pll_addr, state->demod_addr, buf); - if(ret<0) { - dprintk ("%s: second pll_write failed\n",__FUNCTION__); - return ret; + val = cx22702_readreg (state, 0x02); + switch( (val&0x38)>>3 ) { + case 0: p->code_rate_HP = FEC_1_2; break; + case 1: p->code_rate_HP = FEC_2_3; break; + case 2: p->code_rate_HP = FEC_3_4; break; + case 3: p->code_rate_HP = FEC_5_6; break; + case 4: p->code_rate_HP = FEC_7_8; break; } - - /* Tuner needs a small amount of time */ - msleep(100); - - /* Set the AGC post-search */ - buf[3]=0x20; - ret=pll_write (i2c, state->pll_addr, state->demod_addr, buf); - if(ret<0) { - dprintk ("%s: third pll_write failed\n",__FUNCTION__); - return ret; + switch( val&0x07 ) { + case 0: p->code_rate_LP = FEC_1_2; break; + case 1: p->code_rate_LP = FEC_2_3; break; + case 2: p->code_rate_LP = FEC_3_4; break; + case 3: p->code_rate_LP = FEC_5_6; break; + case 4: p->code_rate_LP = FEC_7_8; break; } - return ret; + val = cx22702_readreg (state, 0x03); + switch( (val&0x0c)>>2 ) { + case 0: p->guard_interval = GUARD_INTERVAL_1_32; break; + case 1: p->guard_interval = GUARD_INTERVAL_1_16; break; + case 2: p->guard_interval = GUARD_INTERVAL_1_8; break; + case 3: p->guard_interval = GUARD_INTERVAL_1_4; break; } - -static int pll_dtt7579_set_tv_freq (struct i2c_adapter *i2c, struct cx22702_state *state, u32 freq, int bandwidth) -{ - int ret; - - u32 div = (freq + 36166667) / 166666; - - /* dividerhigh, dividerlow */ - unsigned char buf [4] = { - div >> 8, - div & 0xff, - 0x00, - 0x00 - }; - - // FIXME: bandwidth setting unknown - - // Now compensate for the charge pump osc - if(freq <= 506000000) { - buf[2] = 0xb4; - buf[3] = 0x02; - } else if (freq <= 735000000) { - buf[2] = 0xbc; - buf[3] = 0x08; - } else if (freq <= 835000000) { - buf[2] = 0xf4; - buf[3] = 0x08; - } else if (freq <= 896000000) { - buf[2] = 0xfc; - buf[3] = 0x08; - } - - dprintk ("%s: freq == %i, div == 0x%04x\n", __FUNCTION__, (int) freq, (int) div); - - ret= pll_write (i2c, state->pll_addr, state->demod_addr, buf); - if(ret<0) { - dprintk ("%s: first pll_write failed\n",__FUNCTION__); - return ret; - } - - /* Set the AGC to search */ - buf[2]=(buf[2] & 0xdc) | 0x9c; - buf[3]=0xa0; - ret=pll_write (i2c, state->pll_addr, state->demod_addr, buf); - if(ret<0) { - dprintk ("%s: second pll_write failed\n",__FUNCTION__); - return ret; + switch( val&0x03 ) { + case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break; + case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break; } - return ret; - + return 0; } -/* Reset the demod hardware and reset all of the configuration registers - to a default state. */ -static int cx22702_init (struct i2c_adapter *i2c, struct cx22702_state *state) -{ - int i; - - cx22702_writereg (i2c, state->demod_addr, 0x00, 0x02); - msleep(10); - for (i=0; idemod_addr, init_tab[i], init_tab[i+1]); - return 0; -} -static int cx22702_set_inversion (struct i2c_adapter *i2c, struct cx22702_state *state, int inversion) -{ - u8 val; - switch (inversion) { - case INVERSION_AUTO: - return -EOPNOTSUPP; - case INVERSION_ON: - val = cx22702_readreg (i2c, state->demod_addr, 0x0C); - return cx22702_writereg (i2c, state->demod_addr, 0x0C, val | 0x01); - case INVERSION_OFF: - val = cx22702_readreg (i2c, state->demod_addr, 0x0C); - return cx22702_writereg (i2c, state->demod_addr, 0x0C, val & 0xfe); - default: - return -EINVAL; - } -} /* Talk to the demod, set the FEC, GUARD, QAM settings etc */ -static int cx22702_set_tps (struct i2c_adapter *i2c, struct cx22702_state *state, - struct dvb_frontend_parameters *p) +static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { u8 val; + struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; /* set PLL */ - switch(state->pll_type) { - case PLLTYPE_DTT7592: - case PLLTYPE_DTT7595: - pll_dtt759x_set_tv_freq (i2c, state, p->frequency, p->u.ofdm.bandwidth); - break; - - case PLLTYPE_DTT7579: - pll_dtt7579_set_tv_freq (i2c, state, p->frequency, p->u.ofdm.bandwidth); - break; - } + cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe); + state->config->pll_set(fe, p); + cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1); /* set inversion */ - cx22702_set_inversion (i2c, state, p->inversion); + cx22702_set_inversion (state, p->inversion); /* set bandwidth */ switch(p->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: - cx22702_writereg(i2c, state->demod_addr, 0x0C, (cx22702_readreg(i2c, state->demod_addr, 0x0C) & 0xcf) | 0x20 ); + cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x20 ); break; case BANDWIDTH_7_MHZ: - cx22702_writereg(i2c, state->demod_addr, 0x0C, (cx22702_readreg(i2c, state->demod_addr, 0x0C) & 0xcf) | 0x10 ); + cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x10 ); break; case BANDWIDTH_8_MHZ: - cx22702_writereg(i2c, state->demod_addr, 0x0C, cx22702_readreg(i2c, state->demod_addr, 0x0C) &0xcf ); + cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf ); break; default: dprintk ("%s: invalid bandwidth\n",__FUNCTION__); @@ -378,12 +249,12 @@ (p->u.ofdm.transmission_mode==TRANSMISSION_MODE_AUTO) ) { /* TPS Source - use hardware driven values */ - cx22702_writereg(i2c, state->demod_addr, 0x06, 0x10); - cx22702_writereg(i2c, state->demod_addr, 0x07, 0x9); - cx22702_writereg(i2c, state->demod_addr, 0x08, 0xC1); - cx22702_writereg(i2c, state->demod_addr, 0x0B, cx22702_readreg(i2c, state->demod_addr, 0x0B) & 0xfc ); - cx22702_writereg(i2c, state->demod_addr, 0x0C, (cx22702_readreg(i2c, state->demod_addr, 0x0C) & 0xBF) | 0x40 ); - cx22702_writereg(i2c, state->demod_addr, 0x00, 0x01); /* Begin aquisition */ + cx22702_writereg(state, 0x06, 0x10); + cx22702_writereg(state, 0x07, 0x9); + cx22702_writereg(state, 0x08, 0xC1); + cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc ); + cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 ); + cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */ printk("%s: Autodetecting\n",__FUNCTION__); return 0; } @@ -407,7 +278,7 @@ dprintk ("%s: invalid hierarchy\n",__FUNCTION__); return -EINVAL; } - cx22702_writereg (i2c, state->demod_addr, 0x06, val); + cx22702_writereg (state, 0x06, val); val=0; switch(p->u.ofdm.code_rate_HP) { @@ -432,7 +303,7 @@ dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__); return -EINVAL; } - cx22702_writereg (i2c, state->demod_addr, 0x07, val); + cx22702_writereg (state, 0x07, val); val=0; switch(p->u.ofdm.guard_interval) { @@ -451,93 +322,52 @@ dprintk ("%s: invalid transmission_mode\n",__FUNCTION__); return -EINVAL; } - cx22702_writereg (i2c, state->demod_addr, 0x08, val); - cx22702_writereg(i2c, state->demod_addr, 0x0B, (cx22702_readreg(i2c, state->demod_addr, 0x0B) & 0xfc) | 0x02 ); - cx22702_writereg(i2c, state->demod_addr, 0x0C, (cx22702_readreg(i2c, state->demod_addr, 0x0C) & 0xBF) | 0x40 ); + cx22702_writereg(state, 0x08, val); + cx22702_writereg(state, 0x0B, (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02 ); + cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 ); /* Begin channel aquisition */ - cx22702_writereg(i2c, state->demod_addr, 0x00, 0x01); + cx22702_writereg(state, 0x00, 0x01); return 0; } -/* Retrieve the demod settings */ -static int cx22702_get_tps (struct i2c_adapter *i2c, struct cx22702_state *state, - struct dvb_ofdm_parameters *p) -{ - u8 val; - /* Make sure the TPS regs are valid */ - if (!(cx22702_readreg(i2c, state->demod_addr, 0x0A) & 0x20)) - return -EAGAIN; +/* Reset the demod hardware and reset all of the configuration registers + to a default state. */ +static int cx22702_init (struct dvb_frontend* fe) +{ + int i; + struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; - val = cx22702_readreg (i2c, state->demod_addr, 0x01); - switch( (val&0x18)>>3) { - case 0: p->constellation = QPSK; break; - case 1: p->constellation = QAM_16; break; - case 2: p->constellation = QAM_64; break; - } - switch( val&0x07 ) { - case 0: p->hierarchy_information = HIERARCHY_NONE; break; - case 1: p->hierarchy_information = HIERARCHY_1; break; - case 2: p->hierarchy_information = HIERARCHY_2; break; - case 3: p->hierarchy_information = HIERARCHY_4; break; - } + cx22702_writereg (state, 0x00, 0x02); + msleep(10); - val = cx22702_readreg (i2c, state->demod_addr, 0x02); - switch( (val&0x38)>>3 ) { - case 0: p->code_rate_HP = FEC_1_2; break; - case 1: p->code_rate_HP = FEC_2_3; break; - case 2: p->code_rate_HP = FEC_3_4; break; - case 3: p->code_rate_HP = FEC_5_6; break; - case 4: p->code_rate_HP = FEC_7_8; break; - } - switch( val&0x07 ) { - case 0: p->code_rate_LP = FEC_1_2; break; - case 1: p->code_rate_LP = FEC_2_3; break; - case 2: p->code_rate_LP = FEC_3_4; break; - case 3: p->code_rate_LP = FEC_5_6; break; - case 4: p->code_rate_LP = FEC_7_8; break; - } + for (i=0; idemod_addr, 0x03); - switch( (val&0x0c)>>2 ) { - case 0: p->guard_interval = GUARD_INTERVAL_1_32; break; - case 1: p->guard_interval = GUARD_INTERVAL_1_16; break; - case 2: p->guard_interval = GUARD_INTERVAL_1_8; break; - case 3: p->guard_interval = GUARD_INTERVAL_1_4; break; - } - switch( val&0x03 ) { - case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break; - case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break; + /* init PLL */ + if (state->config->pll_init) { + cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe); + state->config->pll_init(fe); + cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1); } return 0; } -static int cx22702_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct cx22702_state *state = fe->data; - struct i2c_adapter *i2c = state->i2c; + struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; u8 reg0A; u8 reg23; - u8 ucblocks; - - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &state->cx22702_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: - { - fe_status_t *status = (fe_status_t *) arg; *status = 0; - reg0A = cx22702_readreg (i2c, state->demod_addr, 0x0A); - reg23 = cx22702_readreg (i2c, state->demod_addr, 0x23); + reg0A = cx22702_readreg (state, 0x0A); + reg23 = cx22702_readreg (state, 0x23); dprintk ("%s: status demod=0x%02x agc=0x%02x\n" ,__FUNCTION__,reg0A,reg23); @@ -554,347 +384,149 @@ if(reg23 < 0xf0) *status |= FE_HAS_SIGNAL; - break; - - } - - case FE_READ_BER: - if(cx22702_readreg (i2c, state->demod_addr, 0xE4) & 0x02) { - /* Realtime statistics */ - *((u32*) arg) = (cx22702_readreg (i2c, state->demod_addr, 0xDE) & 0x7F) << 7 - | (cx22702_readreg (i2c, state->demod_addr, 0xDF)&0x7F); - } else { - /* Averagtine statistics */ - *((u32*) arg) = (cx22702_readreg (i2c, state->demod_addr, 0xDE) & 0x7F) << 7 - | cx22702_readreg (i2c, state->demod_addr, 0xDF); + return 0; } - break; - case FE_READ_SIGNAL_STRENGTH: +static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber) { - u16 ss = cx22702_readreg (i2c, state->demod_addr, 0x23); - *((u16*) arg) = ss; - break; - } + struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; - /* We don't have an register for this */ - /* We'll take the inverse of the BER register */ - case FE_READ_SNR: - { - u16 rs_ber=0; - if(cx22702_readreg (i2c, state->demod_addr, 0xE4) & 0x02) { + if(cx22702_readreg (state, 0xE4) & 0x02) { /* Realtime statistics */ - rs_ber = (cx22702_readreg (i2c, state->demod_addr, 0xDE) & 0x7F) << 7 - | (cx22702_readreg (i2c, state->demod_addr, 0xDF)& 0x7F); + *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7 + | (cx22702_readreg (state, 0xDF)&0x7F); } else { - /* Averagine statistics */ - rs_ber = (cx22702_readreg (i2c, state->demod_addr, 0xDE) & 0x7F) << 8 - | cx22702_readreg (i2c, state->demod_addr, 0xDF); - } - *((u16*) arg) = ~rs_ber; - break; + /* Averagtine statistics */ + *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7 + | cx22702_readreg (state, 0xDF); } - case FE_READ_UNCORRECTED_BLOCKS: - /* RS Uncorrectable Packet Count then reset */ - ucblocks = cx22702_readreg (i2c, state->demod_addr, 0xE3); - if (state->prevUCBlocks < ucblocks) *((u32*) arg) = (ucblocks - state->prevUCBlocks); - else *((u32*) arg) = state->prevUCBlocks - ucblocks; - state->prevUCBlocks = ucblocks; - break; - - case FE_SET_FRONTEND: - { - struct dvb_frontend_parameters *p = arg; - int ret; - - if((ret=cx22702_set_tps (i2c, state, p))<0) { - dprintk ("%s: set_tps failed ret=%d\n",__FUNCTION__,ret); - return ret; - } - break; + return 0; } - case FE_GET_FRONTEND: +static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) { - struct dvb_frontend_parameters *p = arg; - u8 reg0C = cx22702_readreg (i2c, state->demod_addr, 0x0C); - - p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF; - return cx22702_get_tps (i2c, state, &p->u.ofdm); - } - - case FE_INIT: - return cx22702_init (i2c, state); + struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; - default: - return -EOPNOTSUPP; - }; + *signal_strength = cx22702_readreg (state, 0x23); return 0; } -/* Validate the eeprom contents, make sure content look ok. - Get the eeprom data. */ -static int cx22702_validate_eeprom(struct i2c_adapter *i2c, int* minfreq, int* pll_type, int* pll_addr, int* demod_addr) -{ - u8 b0 [] = { 0 }; - u8 b1 [128]; - u32 model=0; - u8 tuner=0; - int i,j; - - struct i2c_msg msg [] = { - { .addr = I2C_EEPROM_SLAVE_ADDR, .flags = 0, .buf = b0, .len = 1 }, - { .addr = I2C_EEPROM_SLAVE_ADDR, .flags = I2C_M_RD, .buf = b1, .len = 128 } - }; - - if (i2c_transfer(i2c, msg, 2) != 2) { - printk ("%s i2c eeprom request failed\n", __FUNCTION__); - return -ENODEV; - } - - if(debug) { - dprintk ("i2c eeprom content:\n"); - j=0; - for(i=0;i<128;i++) { - dprintk("%02x ",b1[i]); - if(j++==16) { - dprintk("\n"); - j=0; - } - } - dprintk("\n"); - } +static int cx22702_read_snr(struct dvb_frontend* fe, u16* snr) +{ + struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; - if( (b1[8]!=0x84) || (b1[10]!=0x00) ) { - printk ("%s eeprom content is not valid\n", __FUNCTION__); - return -ENODEV; - } - - /* Make sure we support the board model */ - model = b1[0x1f] << 24 | b1[0x1e] << 16 | b1[0x1d] << 8 | b1[0x1c]; - switch(model) { - case 90002: - case 90500: - case 90501: - dprintk ("%s: Model #%d\n",__FUNCTION__,model); - break; - default: - printk ("%s: Unknown model #%d not supported\n",__FUNCTION__,model); - return -ENODEV; + u16 rs_ber=0; + if(cx22702_readreg (state, 0xE4) & 0x02) { + /* Realtime statistics */ + rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7 + | (cx22702_readreg (state, 0xDF)& 0x7F); + } else { + /* Averagine statistics */ + rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 8 + | cx22702_readreg (state, 0xDF); } + *snr = ~rs_ber; - /* Make sure we support the tuner */ - tuner = b1[0x2d]; - switch(tuner) { - case 0x4B: - dprintk ("%s: Tuner Thomson DTT 7595\n",__FUNCTION__); - *minfreq = 177000000; - *pll_type = PLLTYPE_DTT7595; - break; - case 0x4C: - dprintk ("%s: Tuner Thomson DTT 7592\n",__FUNCTION__); - *minfreq = 474000000; - *pll_type = PLLTYPE_DTT7592; - break; - default: - printk ("%s: Unknown tuner 0x%02x not supported\n",__FUNCTION__,tuner); - return -ENODEV; - } - *pll_addr = 0x61; - *demod_addr = 0x43; return 0; } - -/* Validate the demod, make sure we understand the hardware */ -static int cx22702_validate_demod(struct i2c_adapter *i2c, int demod_addr) +static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { - u8 b0 [] = { 0x1f }; - u8 b1 [] = { 0 }; + struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; - struct i2c_msg msg [] = { - { .addr = demod_addr, .flags = 0, .buf = b0, .len = 1 }, - { .addr = demod_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } - }; - - if (i2c_transfer(i2c, msg, 2) != 2) { - printk ("%s i2c demod request failed\n", __FUNCTION__); - return -ENODEV; - } + u8 _ucblocks; - if( (b1[0]!=0x3) ) { - printk ("%s i2c demod type 0x(%02x) not known\n", __FUNCTION__,b1[0]); - return -ENODEV; - } + /* RS Uncorrectable Packet Count then reset */ + _ucblocks = cx22702_readreg (state, 0xE3); + if (state->prevUCBlocks < _ucblocks) *ucblocks = (_ucblocks - state->prevUCBlocks); + else *ucblocks = state->prevUCBlocks - _ucblocks; + state->prevUCBlocks = _ucblocks; return 0; } -/* Validate the tuner PLL, make sure we understand the hardware */ -static int cx22702_validate_pll(struct i2c_adapter *i2c, int pll_addr, int demod_addr) +static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - int result=0; + struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; - if( (result=pll_readreg(i2c,pll_addr,demod_addr,0xc2)) < 0) - return result; + u8 reg0C = cx22702_readreg (state, 0x0C); - if( (result >= 0) && (result&0x30) ) - return 0; - - return result; + p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF; + return cx22702_get_tps (state, &p->u.ofdm); } -/* Check we can see the I2c clients */ -static int cx22702_attach_adapter(struct i2c_adapter *adapter) +static void cx22702_release(struct dvb_frontend* fe) { - struct cx22702_state *state; - struct i2c_client *client; - int ret; - int minfreq; - int pll_type; - int pll_addr; - int demod_addr; - - if (0 == (adapter->class & I2C_CLASS_TV_DIGITAL)) { - dprintk("Ignoring adapter 0x%x:%s (no digital tv card).\n", - adapter->id, adapter->name); - return 0; - } - - dprintk("Trying to attach to adapter 0x%x:%s.\n", - adapter->id, adapter->name); - - if (!strcmp(adapter->name, "Conexant DVB-T reference design")) { - printk("cx22702: Detected Conexant DVB-T card - PLL Thomson DTT7579\n"); - pll_type = PLLTYPE_DTT7579; - pll_addr = 0x60; - demod_addr = 0x43; - minfreq = 177000000; // guess - } else { - // default to Hauppauge Nova-T for the moment - printk("cx22702: Detected Hauppauge Nova-T DVB-T - PLL Thomson DTT759x\n"); - ret=cx22702_validate_eeprom(adapter, &minfreq, &pll_type, &pll_addr, &demod_addr); - if(ret < 0) - return ret; - } - - ret=cx22702_validate_demod(adapter, demod_addr); - if(ret < 0) - return ret; - - ret=cx22702_validate_pll(adapter, pll_addr, demod_addr); - if(ret < 0) - return ret; - - if ( !(state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL)) ) - return -ENOMEM; - - memset(state, 0, sizeof(struct cx22702_state)); - state->i2c = adapter; - memcpy(&state->cx22702_info, &cx22702_info, sizeof(struct dvb_frontend_info)); - state->cx22702_info.frequency_min = minfreq; - state->pll_type = pll_type; - state->pll_addr = pll_addr; - state->demod_addr = demod_addr; - - if ( !(client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)) ) { - kfree(state); - return -ENOMEM; - } - - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = state->demod_addr; - i2c_set_clientdata(client, state); - - if ((ret = i2c_attach_client(client))) { - printk("cx22702: attach failed %i\n", ret); - kfree(client); + struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; kfree(state); - return ret; } - return 0; -} -static int cx22702_detach_client(struct i2c_client *client) -{ - struct cx22702_state *state = i2c_get_clientdata(client); - - if (NULL != state->dvb) { - dvb_unregister_frontend (cx22702_ioctl, state->dvb); - state->dvb = NULL; - } - i2c_detach_client(client); - kfree(client); - return 0; -} +static struct dvb_frontend_ops cx22702_ops; -static int command(struct i2c_client *client, unsigned int cmd, void *arg) +struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, + struct i2c_adapter* i2c) { - struct cx22702_state *state = i2c_get_clientdata(client); - int rc; - - switch(cmd) { - case FE_REGISTER: - if (NULL != state->dvb) - break; - state->dvb = arg; - rc = dvb_register_frontend(cx22702_ioctl, state->dvb, state, - &state->cx22702_info, THIS_MODULE); - if (0 != rc) { - printk("cx22702: dvb_register_frontend failed with rc=%d\n",rc); - state->dvb = NULL; - return rc; - } - break; - case FE_UNREGISTER: - if (NULL == state->dvb) - break; - dvb_unregister_frontend (cx22702_ioctl, state->dvb); - state->dvb = NULL; - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} + struct cx22702_state* state = NULL; -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = FRONTEND_NAME, - .id = I2C_DRIVERID_DVBFE_CX22702, - .flags = I2C_DF_NOTIFY, - .attach_adapter = cx22702_attach_adapter, - .detach_client = cx22702_detach_client, - .command = command, + /* allocate memory for the internal state */ + state = (struct cx22702_state*) kmalloc(sizeof(struct cx22702_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &cx22702_ops, sizeof(struct dvb_frontend_ops)); + state->prevUCBlocks = 0; + + /* check if the demod is there */ + if (cx22702_readreg(state, 0x1f) != 0x3) goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; +} + +static struct dvb_frontend_ops cx22702_ops = { + + .info = { + .name = "Conexant CX22702 DVB-T", + .type = FE_OFDM, + .frequency_min = 177000000, + .frequency_max = 858000000, + .frequency_stepsize = 166666, + .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 | FE_CAN_QAM_AUTO | + FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER + }, + + .release = cx22702_release, + + .init = cx22702_init, + + .set_frontend = cx22702_set_tps, + .get_frontend = cx22702_get_frontend, + + .read_status = cx22702_read_status, + .read_ber = cx22702_read_ber, + .read_signal_strength = cx22702_read_signal_strength, + .read_snr = cx22702_read_snr, + .read_ucblocks = cx22702_read_ucblocks, }; -static struct i2c_client client_template = { - .name = FRONTEND_NAME, - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, -}; - -static int __init init_cx22702 (void) -{ - return i2c_add_driver(&driver); -} - -static void __exit exit_cx22702 (void) -{ - if (i2c_del_driver(&driver)) - printk(KERN_ERR "cx22702: driver deregistration failed.\n"); -} - -module_init (init_cx22702); -module_exit (exit_cx22702); - -MODULE_PARM(debug,"i"); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Enable verbose debug messages"); -MODULE_DESCRIPTION("CX22702 / Thomson DTT 759x / Thomson DTT 7579 PLL DVB Frontend driver"); + +MODULE_DESCRIPTION("Conexant CX22702 DVB-T Demodulator driver"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(cx22702_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/cx24110.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/cx24110.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/cx24110.c 2004-12-22 10:04:35.665380890 -0800 @@ -1,6 +1,5 @@ /* cx24110 - Single Chip Satellite Channel Receiver driver module - used on the the Pinnacle PCTV Sat cards Copyright (C) 2002 Peter Hettkamp based on work @@ -23,15 +22,6 @@ */ -/* currently drives the Conexant cx24110 and cx24106 QPSK decoder chips, - connected via i2c to a Conexant Fusion 878 (this uses the standard - linux bttv driver). The tuner chip is supposed to be the Conexant - cx24108 digital satellite tuner, driven through the tuner interface - of the cx24110. SEC is also supplied by the cx24110. - - Oct-2002: Migrate to API V3 (formerly known as NEWSTRUCT) -*/ - #include #include #include @@ -39,44 +29,30 @@ #include #include "dvb_frontend.h" +#include "cx24110.h" -#define FRONTEND_NAME "dvbfe_cx24110" -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG FRONTEND_NAME ": " args); \ - } while (0) +struct cx24110_state { -static int debug; + struct i2c_adapter* i2c; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + struct dvb_frontend_ops ops; + const struct cx24110_config* config; -static struct dvb_frontend_info cx24110_info = { - .name = "Conexant CX24110 with CX24108 tuner, aka HM1221/HM1811", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 1011, /* kHz for QPSK frontends, can be reduced - to 253kHz on the cx24108 tuner */ - .frequency_tolerance = 29500, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, -/* .symbol_rate_tolerance = ???,*/ - .notifier_delay = 50, /* 1/20 s */ - .caps = FE_CAN_INVERSION_AUTO | - 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_RECOVER -}; -/* fixme: are these values correct? especially ..._tolerance and caps */ + struct dvb_frontend frontend; -struct cx24110_state { - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; + u32 lastber; + u32 lastbler; + u32 lastesn0; }; +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "cx24110: " args); \ + } while (0) + static struct {u8 reg; u8 data;} cx24110_regdata[]= /* Comments beginning with @ denote this value should be the default */ @@ -140,15 +116,13 @@ }; -static int cx24110_writereg (struct i2c_adapter *i2c, int reg, int data) +static int cx24110_writereg (struct cx24110_state* state, int reg, int data) { u8 buf [] = { reg, data }; - struct i2c_msg msg = { .addr = 0x55, .flags = 0, .buf = buf, .len = 2 }; -/* fixme (medium): HW allows any i2c address. 0x55 is the default, but the - cx24110 might show up at any address */ + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; int err; - if ((err = i2c_transfer(i2c, &msg, 1)) != 1) { + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { dprintk ("%s: writereg error (err == %i, reg == 0x%02x," " data == 0x%02x)\n", __FUNCTION__, err, reg, data); return -EREMOTEIO; @@ -158,161 +132,46 @@ } -static u8 cx24110_readreg (struct i2c_adapter *i2c, u8 reg) +static int cx24110_readreg (struct cx24110_state* state, u8 reg) { int ret; u8 b0 [] = { reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 }, - { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; -/* fixme (medium): address might be different from 0x55 */ - ret = i2c_transfer(i2c, msg, 2); - - if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - - return b1[0]; -} - - -static int cx24108_write (struct i2c_adapter *i2c, u32 data) -{ -/* tuner data is 21 bits long, must be left-aligned in data */ -/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */ -/* FIXME (low): add error handling, avoid infinite loops if HW fails... */ - -dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data); - - cx24110_writereg(i2c,0x6d,0x30); /* auto mode at 62kHz */ - cx24110_writereg(i2c,0x70,0x15); /* auto mode 21 bits */ - /* if the auto tuner writer is still busy, clear it out */ - while (cx24110_readreg(i2c,0x6d)&0x80) - cx24110_writereg(i2c,0x72,0); - /* write the topmost 8 bits */ - cx24110_writereg(i2c,0x72,(data>>24)&0xff); - /* wait for the send to be completed */ - while ((cx24110_readreg(i2c,0x6d)&0xc0)==0x80) - ; - /* send another 8 bytes */ - cx24110_writereg(i2c,0x72,(data>>16)&0xff); - while ((cx24110_readreg(i2c,0x6d)&0xc0)==0x80) - ; - /* and the topmost 5 bits of this byte */ - cx24110_writereg(i2c,0x72,(data>>8)&0xff); - while ((cx24110_readreg(i2c,0x6d)&0xc0)==0x80) - ; - /* now strobe the enable line once */ - cx24110_writereg(i2c,0x6d,0x32); - cx24110_writereg(i2c,0x6d,0x30); - - return 0; -} - - -static int cx24108_set_tv_freq (struct i2c_adapter *i2c, u32 freq) -{ -/* fixme (low): error handling */ - int i, a, n, pump; - u32 band, pll; + struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + ret = i2c_transfer(state->i2c, msg, 2); - static const u32 osci[]={ 950000,1019000,1075000,1178000, - 1296000,1432000,1576000,1718000, - 1856000,2036000,2150000}; - static const u32 bandsel[]={0,0x00020000,0x00040000,0x00100800, - 0x00101000,0x00102000,0x00104000, - 0x00108000,0x00110000,0x00120000, - 0x00140000}; - -#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */ - dprintk("cx24110 debug: cx24108_set_tv_freq, freq=%d\n",freq); - - if (freq<950000) - freq=950000; /* kHz */ - if (freq>2150000) - freq=2150000; /* satellite IF is 950..2150MHz */ - /* decide which VCO to use for the input frequency */ - for (i=1;(i0) { - cx24110_writereg(i2c,0x05,(cx24110_readreg(i2c,0x05)&0xf0)|rate[fec]); + cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|rate[fec]); /* set nominal Viterbi rate */ - cx24110_writereg(i2c,0x22,(cx24110_readreg(i2c,0x22)&0xf0)|rate[fec]); + cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|rate[fec]); /* set current Viterbi rate */ - cx24110_writereg(i2c,0x1a,g1[fec]); - cx24110_writereg(i2c,0x1b,g2[fec]); + cx24110_writereg(state,0x1a,g1[fec]); + cx24110_writereg(state,0x1b,g2[fec]); /* not sure if this is the right way: I always used AutoAcq mode */ } else return -EOPNOTSUPP; @@ -369,11 +228,11 @@ } -static fe_code_rate_t cx24110_get_fec (struct i2c_adapter *i2c) +static fe_code_rate_t cx24110_get_fec (struct cx24110_state* state) { int i; - i=cx24110_readreg(i2c,0x22)&0x0f; + i=cx24110_readreg(state,0x22)&0x0f; if(!(i&0x08)) { return FEC_1_2 + i - 1; } else { @@ -386,16 +245,13 @@ } -static int cx24110_set_symbolrate (struct i2c_adapter *i2c, u32 srate) +static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate) { /* fixme (low): add error handling */ u32 ratio; u32 tmp, fclk, BDRI; static const u32 bands[]={5000000UL,15000000UL,90999000UL/2}; - static const u32 vca[]={0x80f03800,0x81f0f800,0x83f1f800}; - static const u32 vga[]={0x5f8fc000,0x580f0000,0x500c0000}; - static const u8 filtune[]={0xa2,0xcc,0x66}; int i; dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate); @@ -409,22 +265,22 @@ /* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz, and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult, R06[3:0] PLLphaseDetGain */ - tmp=cx24110_readreg(i2c,0x07)&0xfc; + tmp=cx24110_readreg(state,0x07)&0xfc; if(srate<90999000UL/4) { /* sample rate 45MHz*/ - cx24110_writereg(i2c,0x07,tmp); - cx24110_writereg(i2c,0x06,0x78); + cx24110_writereg(state,0x07,tmp); + cx24110_writereg(state,0x06,0x78); fclk=90999000UL/2; } else if(srate<60666000UL/2) { /* sample rate 60MHz */ - cx24110_writereg(i2c,0x07,tmp|0x1); - cx24110_writereg(i2c,0x06,0xa5); + cx24110_writereg(state,0x07,tmp|0x1); + cx24110_writereg(state,0x06,0xa5); fclk=60666000UL; } else if(srate<80888000UL/2) { /* sample rate 80MHz */ - cx24110_writereg(i2c,0x07,tmp|0x2); - cx24110_writereg(i2c,0x06,0x87); + cx24110_writereg(state,0x07,tmp|0x2); + cx24110_writereg(state,0x06,0x87); fclk=80888000UL; } else { /* sample rate 90MHz */ - cx24110_writereg(i2c,0x07,tmp|0x3); - cx24110_writereg(i2c,0x06,0x78); + cx24110_writereg(state,0x07,tmp|0x3); + cx24110_writereg(state,0x06,0x78); fclk=90999000UL; }; dprintk("cx24110 debug: fclk %d Hz\n",fclk); @@ -453,64 +309,123 @@ dprintk("fclk = %d\n", fclk); dprintk("ratio= %08x\n", ratio); - cx24110_writereg(i2c, 0x1, (ratio>>16)&0xff); - cx24110_writereg(i2c, 0x2, (ratio>>8)&0xff); - cx24110_writereg(i2c, 0x3, (ratio)&0xff); - - /* please see the cx24108 data sheet, this controls tuner gain - and bandwidth settings depending on the symbol rate */ - cx24108_write(i2c,vga[i]); - cx24108_write(i2c,vca[i]); /* gain is set on tuner chip */ - cx24110_writereg(i2c,0x56,filtune[i]); /* bw is contolled by filtune voltage */ + cx24110_writereg(state, 0x1, (ratio>>16)&0xff); + cx24110_writereg(state, 0x2, (ratio>>8)&0xff); + cx24110_writereg(state, 0x3, (ratio)&0xff); return 0; } -static int cx24110_set_voltage (struct i2c_adapter *i2c, fe_sec_voltage_t voltage) + + + + + + + + + + +int cx24110_pll_write (struct dvb_frontend* fe, u32 data) { + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + +/* tuner data is 21 bits long, must be left-aligned in data */ +/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */ +/* FIXME (low): add error handling, avoid infinite loops if HW fails... */ + + dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data); + + cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */ + cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */ + + /* if the auto tuner writer is still busy, clear it out */ + while (cx24110_readreg(state,0x6d)&0x80) + cx24110_writereg(state,0x72,0); + + /* write the topmost 8 bits */ + cx24110_writereg(state,0x72,(data>>24)&0xff); + + /* wait for the send to be completed */ + while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) + ; + + /* send another 8 bytes */ + cx24110_writereg(state,0x72,(data>>16)&0xff); + while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) + ; + + /* and the topmost 5 bits of this byte */ + cx24110_writereg(state,0x72,(data>>8)&0xff); + while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) + ; + + /* now strobe the enable line once */ + cx24110_writereg(state,0x6d,0x32); + cx24110_writereg(state,0x6d,0x30); + + return 0; +} + + + +static int cx24110_initfe(struct dvb_frontend* fe) +{ + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; +/* fixme (low): error handling */ + int i; + + dprintk("%s: init chip\n", __FUNCTION__); + + for(i=0;iconfig->pll_init) state->config->pll_init(fe); + + return 0; +} + + +static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + switch (voltage) { case SEC_VOLTAGE_13: - return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&0x3b)|0xc0); + return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0xc0); case SEC_VOLTAGE_18: - return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&0x3b)|0x40); + return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0x40); default: return -EINVAL; }; } -static void cx24110_send_diseqc_msg(struct i2c_adapter *i2c, +static int cx24110_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) { int i, rv; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; for (i = 0; i < cmd->msg_len; i++) - cx24110_writereg(i2c, 0x79 + i, cmd->msg[i]); + cx24110_writereg(state, 0x79 + i, cmd->msg[i]); - rv = cx24110_readreg(i2c, 0x76); + rv = cx24110_readreg(state, 0x76); - cx24110_writereg(i2c, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3)); - for (i=500; i-- > 0 && !(cx24110_readreg(i2c,0x76)&0x40);) + cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3)); + for (i=500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40);) ; /* wait for LNB ready */ -} + return 0; +} -static int cx24110_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct cx24110_state *state = fe->data; - struct i2c_adapter *i2c = state->i2c; - static int lastber=0, lastbyer=0,lastbler=0, lastesn0=0, sum_bler=0; - - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &cx24110_info, sizeof(struct dvb_frontend_info)); - break; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; - case FE_READ_STATUS: - { - fe_status_t *status = arg; - int sync = cx24110_readreg (i2c, 0x55); + int sync = cx24110_readreg (state, 0x55); *status = 0; @@ -520,7 +435,7 @@ if (sync & 0x08) *status |= FE_HAS_CARRIER; - sync = cx24110_readreg (i2c, 0x08); + sync = cx24110_readreg (state, 0x08); if (sync & 0x40) *status |= FE_HAS_VITERBI; @@ -531,87 +446,97 @@ if ((sync & 0x60) == 0x60) *status |= FE_HAS_LOCK; - if(cx24110_readreg(i2c,0x10)&0x40) { - /* the RS error counter has finished one counting window */ - cx24110_writereg(i2c,0x10,0x60); /* select the byer reg */ - lastbyer=cx24110_readreg(i2c,0x12)| - (cx24110_readreg(i2c,0x13)<<8)| - (cx24110_readreg(i2c,0x14)<<16); - cx24110_writereg(i2c,0x10,0x70); /* select the bler reg */ - lastbler=cx24110_readreg(i2c,0x12)| - (cx24110_readreg(i2c,0x13)<<8)| - (cx24110_readreg(i2c,0x14)<<16); - cx24110_writereg(i2c,0x10,0x20); /* start new count window */ - sum_bler += lastbler; - } - if(cx24110_readreg(i2c,0x24)&0x10) { - /* the Viterbi error counter has finished one counting window */ - cx24110_writereg(i2c,0x24,0x04); /* select the ber reg */ - lastber=cx24110_readreg(i2c,0x25)| - (cx24110_readreg(i2c,0x26)<<8); - cx24110_writereg(i2c,0x24,0x04); /* start new count window */ - cx24110_writereg(i2c,0x24,0x14); - } - if(cx24110_readreg(i2c,0x6a)&0x80) { - /* the Es/N0 error counter has finished one counting window */ - lastesn0=cx24110_readreg(i2c,0x69)| - (cx24110_readreg(i2c,0x68)<<8); - cx24110_writereg(i2c,0x6a,0x84); /* start new count window */ - } - break; + return 0; } - case FE_READ_BER: +static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 *ber = (u32 *) arg; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; - *ber = lastber; /* fixme (maybe): value range is 16 bit. Scale? */ - break; + if(cx24110_readreg(state,0x24)&0x10) { + /* the Viterbi error counter has finished one counting window */ + cx24110_writereg(state,0x24,0x04); /* select the ber reg */ + state->lastber=cx24110_readreg(state,0x25)| + (cx24110_readreg(state,0x26)<<8); + cx24110_writereg(state,0x24,0x04); /* start new count window */ + cx24110_writereg(state,0x24,0x14); } + *ber = state->lastber; - case FE_READ_SIGNAL_STRENGTH: + return 0; + } + +static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) { + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + /* no provision in hardware. Read the frontend AGC accumulator. No idea how to scale this, but I know it is 2s complement */ - u8 signal = cx24110_readreg (i2c, 0x27)+128; - *((u16*) arg) = (signal << 8) | signal; - break; + u8 signal = cx24110_readreg (state, 0x27)+128; + *signal_strength = (signal << 8) | signal; + + return 0; } - case FE_READ_SNR: +static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr) { + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + /* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */ - *(u16*) arg = lastesn0; - break; + if(cx24110_readreg(state,0x6a)&0x80) { + /* the Es/N0 error counter has finished one counting window */ + state->lastesn0=cx24110_readreg(state,0x69)| + (cx24110_readreg(state,0x68)<<8); + cx24110_writereg(state,0x6a,0x84); /* start new count window */ + } + *snr = state->lastesn0; + + return 0; } - case FE_READ_UNCORRECTED_BLOCKS: +static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { - *(u16*) arg = sum_bler&0xffff; - sum_bler=0; - break; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + u32 lastbyer; + + if(cx24110_readreg(state,0x10)&0x40) { + /* the RS error counter has finished one counting window */ + cx24110_writereg(state,0x10,0x60); /* select the byer reg */ + lastbyer=cx24110_readreg(state,0x12)| + (cx24110_readreg(state,0x13)<<8)| + (cx24110_readreg(state,0x14)<<16); + cx24110_writereg(state,0x10,0x70); /* select the bler reg */ + state->lastbler=cx24110_readreg(state,0x12)| + (cx24110_readreg(state,0x13)<<8)| + (cx24110_readreg(state,0x14)<<16); + cx24110_writereg(state,0x10,0x20); /* start new count window */ } + *ucblocks = state->lastbler; - case FE_SET_FRONTEND: + return 0; +} + +static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = arg; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; - cx24108_set_tv_freq (i2c, p->frequency); - cx24110_set_inversion (i2c, p->inversion); - cx24110_set_fec (i2c, p->u.qpsk.fec_inner); - cx24110_set_symbolrate (i2c, p->u.qpsk.symbol_rate); - cx24110_writereg(i2c,0x04,0x05); /* start aquisition */ - break; + state->config->pll_set(fe, p); + cx24110_set_inversion (state, p->inversion); + cx24110_set_fec (state, p->u.qpsk.fec_inner); + cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate); + cx24110_writereg(state,0x04,0x05); /* start aquisition */ + + return 0; } - case FE_GET_FRONTEND: +static int cx24110_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = arg; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; s32 afc; unsigned sclk; /* cannot read back tuner settings (freq). Need to have some private storage */ - sclk = cx24110_readreg (i2c, 0x07) & 0x03; + sclk = cx24110_readreg (state, 0x07) & 0x03; /* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz. * Need 64 bit arithmetic. Is thiss possible in the kernel? */ if (sclk==0) sclk=90999000L/2L; @@ -619,152 +544,104 @@ else if (sclk==2) sclk=80888000L; else sclk=90999000L; sclk>>=8; - afc = sclk*(cx24110_readreg (i2c, 0x44)&0x1f)+ - ((sclk*cx24110_readreg (i2c, 0x45))>>8)+ - ((sclk*cx24110_readreg (i2c, 0x46))>>16); + afc = sclk*(cx24110_readreg (state, 0x44)&0x1f)+ + ((sclk*cx24110_readreg (state, 0x45))>>8)+ + ((sclk*cx24110_readreg (state, 0x46))>>16); p->frequency += afc; - p->inversion = (cx24110_readreg (i2c, 0x22) & 0x10) ? + p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ? INVERSION_ON : INVERSION_OFF; - p->u.qpsk.fec_inner = cx24110_get_fec (i2c); - break; - } - - case FE_SLEEP: -/* cannot do this from the FE end. How to communicate this to the place where it can be done? */ - break; - case FE_INIT: - return cx24110_initfe(i2c); - - case FE_SET_TONE: - return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&~0x10)|((((fe_sec_tone_mode_t) arg)==SEC_TONE_ON)?0x10:0)); - case FE_SET_VOLTAGE: - return cx24110_set_voltage (i2c, (fe_sec_voltage_t) arg); - - case FE_DISEQC_SEND_MASTER_CMD: - // FIXME Status? - cx24110_send_diseqc_msg(i2c, (struct dvb_diseqc_master_cmd*) arg); - return 0; - - default: - return -EOPNOTSUPP; - }; + p->u.qpsk.fec_inner = cx24110_get_fec (state); return 0; } -static struct i2c_client client_template; - -static int attach_adapter (struct i2c_adapter *adapter) +static int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { - struct cx24110_state *state; - struct i2c_client *client; - int ret = 0; - u8 sig; - - dprintk("Trying to attach to adapter 0x%x:%s.\n", - adapter->id, adapter->name); - - sig = cx24110_readreg (adapter, 0x00); - if ( sig != 0x5a && sig != 0x69 ) - return -ENODEV; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; - if ( !(state = kmalloc(sizeof(struct cx24110_state), GFP_KERNEL)) ) - return -ENOMEM; - - memset(state, 0, sizeof(struct cx24110_state)); - state->i2c = adapter; - - if ( !(client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)) ) { - kfree(state); - return -ENOMEM; + return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&~0x10)|(((tone==SEC_TONE_ON))?0x10:0)); } - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = 0x55; - i2c_set_clientdata(client, state); - - if ((ret = i2c_attach_client(client))) { - kfree(client); - kfree(state); - return ret; -} - - BUG_ON(!state->dvb); - - if ((ret = dvb_register_frontend(cx24110_ioctl, state->dvb, state, - &cx24110_info, THIS_MODULE))) { - i2c_detach_client(client); - kfree(client); +static void cx24110_release(struct dvb_frontend* fe) +{ + struct cx24110_state* state = (struct cx24110_state*) fe->demodulator_priv; kfree(state); - return ret; -} - - return 0; } -static int detach_client (struct i2c_client *client) -{ - struct cx24110_state *state = i2c_get_clientdata(client); - - dvb_unregister_frontend(cx24110_ioctl, state->dvb); - i2c_detach_client(client); - BUG_ON(state->dvb); - kfree(client); - kfree(state); - return 0; -} +static struct dvb_frontend_ops cx24110_ops; -static int command(struct i2c_client *client, unsigned int cmd, void *arg) +struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, + struct i2c_adapter* i2c) { - struct cx24110_state *state = i2c_get_clientdata(client); - - switch(cmd) { - case FE_REGISTER: - state->dvb = arg; - break; - case FE_UNREGISTER: - state->dvb = NULL; - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = FRONTEND_NAME, - .id = I2C_DRIVERID_DVBFE_CX24110, - .flags = I2C_DF_NOTIFY, - .attach_adapter = attach_adapter, - .detach_client = detach_client, - .command = command, -}; + struct cx24110_state* state = NULL; + int ret; -static struct i2c_client client_template = { - .name = FRONTEND_NAME, - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, + /* allocate memory for the internal state */ + state = (struct cx24110_state*) kmalloc(sizeof(struct cx24110_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &cx24110_ops, sizeof(struct dvb_frontend_ops)); + state->lastber = 0; + state->lastbler = 0; + state->lastesn0 = 0; + + /* check if the demod is there */ + ret = cx24110_readreg(state, 0x00); + if ((ret != 0x5a) && (ret != 0x69)) goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; +} + +static struct dvb_frontend_ops cx24110_ops = { + + .info = { + .name = "Conexant CX24110 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 1011, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_INVERSION_AUTO | + 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_RECOVER + }, + + .release = cx24110_release, + + .init = cx24110_initfe, + .set_frontend = cx24110_set_frontend, + .get_frontend = cx24110_get_frontend, + .read_status = cx24110_read_status, + .read_ber = cx24110_read_ber, + .read_signal_strength = cx24110_read_signal_strength, + .read_snr = cx24110_read_snr, + .read_ucblocks = cx24110_read_ucblocks, + + .diseqc_send_master_cmd = cx24110_send_diseqc_msg, + .set_tone = cx24110_set_tone, + .set_voltage = cx24110_set_voltage, }; -static int __init cx24110_init(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit cx24110_exit(void) -{ - if (i2c_del_driver(&driver)) - printk(KERN_ERR "cx24110: driver deregistration failed.\n"); -} - -module_init(cx24110_init); -module_exit(cx24110_exit); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("DVB Frontend driver module for the Conexant cx24108/cx24110 chipset"); +MODULE_DESCRIPTION("Conexant CX24110 DVB-S Demodulator driver"); MODULE_AUTHOR("Peter Hettkamp"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(cx24110_attach); +EXPORT_SYMBOL(cx24110_pll_write); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/dib3000mb.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/dib3000mb.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/dib3000mb.c 2004-12-22 10:04:35.685377850 -0800 @@ -17,8 +17,6 @@ * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver * sources, on which this driver (and the dvb-dibusb) are based. * - * - * * see Documentation/dvb/README.dibusb for more information * */ @@ -32,319 +30,42 @@ #include #include "dvb_frontend.h" +#include "dib3000-common.h" +#include "dib3000mb_priv.h" +#include "dib3000.h" -#include "dib3000mb.h" - -/* debug */ +/* Version information */ +#define DRIVER_VERSION "0.1" +#define DRIVER_DESC "DiBcom 3000-MB DVB-T demodulator driver" +#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de" #ifdef CONFIG_DVB_DIBCOM_DEBUG -#define dprintk(level,args...) \ - do { if ((debug & level)) { printk(args); } } while (0) - static int debug; module_param(debug, int, 0x644); -MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=setfe,16=getfe (|-able))."); -#else -#define dprintk(args...) do { } while (0); +MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able))."); #endif - #define deb_info(args...) dprintk(0x01,args) #define deb_xfer(args...) dprintk(0x02,args) -#define deb_alot(args...) dprintk(0x04,args) -#define deb_setf(args...) dprintk(0x08,args) -#define deb_getf(args...) dprintk(0x10,args) - -/* Version information */ -#define DRIVER_VERSION "0.1" -#define DRIVER_DESC "DiBcom 3000-MB DVB-T frontend" -#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de" - -struct dib3000mb_state { - struct i2c_client *i2c; - struct dvb_adapter *dvb; - u16 manufactor_id; - u16 device_id; -}; - -static struct dvb_frontend_info dib3000mb_info = { - .name = "DiBcom 3000-MB DVB-T", - .type = FE_OFDM, - .frequency_min = 44250000, - .frequency_max = 867250000, - .frequency_stepsize = 62500, - .caps = FE_CAN_INVERSION_AUTO | - 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 | FE_CAN_QAM_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; - - -#define rd(reg) dib3000mb_read_reg(state->i2c,reg) -#define wr(reg,val) if (dib3000mb_write_reg(state->i2c,reg,val)) \ - { err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; } -#define wr_foreach(a,v) { int i; \ - deb_alot("sizeof: %d %d\n",sizeof(a),sizeof(v));\ - for (i=0; i < sizeof(a)/sizeof(u16); i++) \ - wr(a[i],v[i]); \ -} - -static u16 dib3000mb_read_reg(struct i2c_client *i2c, u16 reg) -{ - u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff }; - u8 rb[2]; - struct i2c_msg msg[] = { - { .addr = i2c->addr, .flags = 0, .buf = wb, .len = 2 }, - { .addr = i2c->addr, .flags = I2C_M_RD, .buf = rb, .len = 2 }, - }; - deb_alot("reading from i2c bus (reg: %d)\n",reg); - - if (i2c_transfer(i2c->adapter,msg,2) != 2) - deb_alot("i2c read error\n"); - - return (rb[0] << 8) | rb[1]; -} - -static int dib3000mb_write_reg(struct i2c_client *i2c,u16 reg, u16 val) -{ - u8 b[] = { - (reg >> 8) & 0xff, reg & 0xff, - (val >> 8) & 0xff, val & 0xff, - }; - struct i2c_msg msg[] = { { .addr = i2c->addr, .flags = 0, .buf = b, .len = 4 } }; - deb_alot("writing to i2c bus (reg: %d, val: %d)\n",reg,val); - - return i2c_transfer(i2c->adapter,msg,1) != 1 ? -EREMOTEIO : 0 ; -} - -static int dib3000mb_tuner_thomson_cable_eu(struct dib3000mb_state *state, - u32 freq) -{ - u32 tfreq = (freq + 36125000) / 62500; - unsigned int addr; - int vu,p0,p1,p2; - - if (freq > 403250000) - vu = 1, p2 = 1, p1 = 0, p0 = 1; - else if (freq > 115750000) - vu = 0, p2 = 1, p1 = 1, p0 = 0; - else if (freq > 44250000) - vu = 0, p2 = 0, p1 = 1, p0 = 1; - else - return -EINVAL; - /* TODO better solution for i2c->addr handling */ - addr = state->i2c->addr; - state->i2c->addr = DIB3000MB_TUNER_ADDR_DEFAULT; - wr(tfreq & 0x7fff,(0x8e << 8) + ((vu << 7) | (p2 << 2) | (p1 << 1) | p0) ); - state->i2c->addr = addr; - - return 0; -} - -static int dib3000mb_get_frontend(struct dib3000mb_state *state, - struct dvb_frontend_parameters *fep) -{ - struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm; - fe_code_rate_t *cr; - u16 tps_val; - int inv_test1,inv_test2; - u32 dds_val, threshold = 0x800000; - - if (!rd(DIB3000MB_REG_TPS_LOCK)) - return 0; - - dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB); - if (dds_val & threshold) - inv_test1 = 0; - else if (dds_val == threshold) - inv_test1 = 1; - else - inv_test1 = 2; - - dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB); - if (dds_val & threshold) - inv_test2 = 0; - else if (dds_val == threshold) - inv_test2 = 1; - else - inv_test2 = 2; - - fep->inversion = - ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) - || - ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)); - - deb_getf("inversion %d %d, %d\n",inv_test2,inv_test1, fep->inversion); - - switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) { - case DIB3000MB_QAM_QPSK: - deb_getf("QPSK "); - ofdm->constellation = QPSK; - break; - case DIB3000MB_QAM_QAM16: - deb_getf("QAM16 "); - ofdm->constellation = QAM_16; - break; - case DIB3000MB_QAM_QAM64: - deb_getf("QAM64 "); - ofdm->constellation = QAM_64; - break; - default: - err("Unexpected constellation returned by TPS (%d)",tps_val); - break; - } - deb_getf("TPS: %d\n",tps_val); - - if (rd(DIB3000MB_REG_TPS_HRCH)) { - deb_getf("HRCH ON\n"); - tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP); - cr = &ofdm->code_rate_LP; - ofdm->code_rate_HP = FEC_NONE; - - switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) { - case DIB3000MB_VIT_ALPHA_OFF: - deb_getf("HIERARCHY_NONE "); - ofdm->hierarchy_information = HIERARCHY_NONE; - break; - case DIB3000MB_VIT_ALPHA_1: - deb_getf("HIERARCHY_1 "); - ofdm->hierarchy_information = HIERARCHY_1; - break; - case DIB3000MB_VIT_ALPHA_2: - deb_getf("HIERARCHY_2 "); - ofdm->hierarchy_information = HIERARCHY_2; - break; - case DIB3000MB_VIT_ALPHA_4: - deb_getf("HIERARCHY_4 "); - ofdm->hierarchy_information = HIERARCHY_4; - break; - default: - err("Unexpected ALPHA value returned by TPS (%d)",tps_val); - } - deb_getf("TPS: %d\n",tps_val); - } else { - deb_getf("HRCH OFF\n"); - tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP); - cr = &ofdm->code_rate_HP; - ofdm->code_rate_LP = FEC_NONE; - ofdm->hierarchy_information = HIERARCHY_NONE; - } +#define deb_setf(args...) dprintk(0x04,args) +#define deb_getf(args...) dprintk(0x08,args) - switch (tps_val) { - case DIB3000MB_FEC_1_2: - deb_getf("FEC_1_2 "); - *cr = FEC_1_2; - break; - case DIB3000MB_FEC_2_3: - deb_getf("FEC_2_3 "); - *cr = FEC_2_3; - break; - case DIB3000MB_FEC_3_4: - deb_getf("FEC_3_4 "); - *cr = FEC_3_4; - break; - case DIB3000MB_FEC_5_6: - deb_getf("FEC_5_6 "); - *cr = FEC_4_5; - break; - case DIB3000MB_FEC_7_8: - deb_getf("FEC_7_8 "); - *cr = FEC_7_8; - break; - default: - err("Unexpected FEC returned by TPS (%d)",tps_val); - break; - } - deb_getf("TPS: %d\n",tps_val); - - switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) { - case DIB3000MB_GUARD_TIME_1_32: - deb_getf("GUARD_INTERVAL_1_32 "); - ofdm->guard_interval = GUARD_INTERVAL_1_32; - break; - case DIB3000MB_GUARD_TIME_1_16: - deb_getf("GUARD_INTERVAL_1_16 "); - ofdm->guard_interval = GUARD_INTERVAL_1_16; - break; - case DIB3000MB_GUARD_TIME_1_8: - deb_getf("GUARD_INTERVAL_1_8 "); - ofdm->guard_interval = GUARD_INTERVAL_1_8; - break; - case DIB3000MB_GUARD_TIME_1_4: - deb_getf("GUARD_INTERVAL_1_4 "); - ofdm->guard_interval = GUARD_INTERVAL_1_4; - break; - default: - err("Unexpected Guard Time returned by TPS (%d)",tps_val); - break; - } - deb_getf("TPS: %d\n",tps_val); +static int dib3000mb_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep); - switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) { - case DIB3000MB_FFT_2K: - deb_getf("TRANSMISSION_MODE_2K "); - ofdm->transmission_mode = TRANSMISSION_MODE_2K; - break; - case DIB3000MB_FFT_8K: - deb_getf("TRANSMISSION_MODE_8K "); - ofdm->transmission_mode = TRANSMISSION_MODE_8K; - break; - default: - err("unexpected transmission mode return by TPS (%d)",tps_val); - } - deb_getf("TPS: %d\n",tps_val); - return 0; -} - -static int dib3000mb_set_frontend(struct dib3000mb_state *state, - struct dvb_frontend_parameters *fep, int tuner); - -static int dib3000mb_fe_read_search_status(struct dib3000mb_state *state) -{ - u16 irq; - struct dvb_frontend_parameters fep; - - irq = rd(DIB3000MB_REG_AS_IRQ_PENDING); - - if (irq & 0x02) { - if (rd(DIB3000MB_REG_LOCK2_VALUE) & 0x01) { - if (dib3000mb_get_frontend(state,&fep) == 0) { - deb_setf("reading tuning data from frontend succeeded.\n"); - return dib3000mb_set_frontend(state,&fep,0) == 0; - } else { - deb_setf("reading tuning data failed -> tuning failed.\n"); - return 0; - } - } else { - deb_setf("AS IRQ was pending, but LOCK2 was not & 0x01.\n"); - return 0; - } - } else if (irq & 0x01) { - deb_setf("Autosearch failed.\n"); - return 0; - } - - return -1; -} - -static int dib3000mb_set_frontend(struct dib3000mb_state *state, +static int dib3000mb_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep, int tuner) { + struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv; struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm; fe_code_rate_t fe_cr = FEC_NONE; int search_state,seq; if (tuner) { wr(DIB3000MB_REG_TUNER, - DIB3000MB_ACTIVATE_TUNER_XFER( DIB3000MB_TUNER_ADDR_DEFAULT ) ); - dib3000mb_tuner_thomson_cable_eu(state,fep->frequency); - - /* wait for tuner */ - msleep(1); + DIB3000_TUNER_WRITE_ENABLE(state->config.pll_addr)); + state->config.pll_set(fe, fep); wr(DIB3000MB_REG_TUNER, - DIB3000MB_DEACTIVATE_TUNER_XFER( DIB3000MB_TUNER_ADDR_DEFAULT ) ); + DIB3000_TUNER_WRITE_DISABLE(state->config.pll_addr)); deb_setf("bandwidth: "); switch (ofdm->bandwidth) { @@ -376,15 +97,14 @@ switch (ofdm->transmission_mode) { case TRANSMISSION_MODE_2K: deb_setf("2k\n"); - wr(DIB3000MB_REG_FFT,DIB3000MB_FFT_2K); + wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K); break; case TRANSMISSION_MODE_8K: deb_setf("8k\n"); - wr(DIB3000MB_REG_FFT,DIB3000MB_FFT_8K); + wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K); break; case TRANSMISSION_MODE_AUTO: deb_setf("auto\n"); - wr(DIB3000MB_REG_FFT,DIB3000MB_FFT_AUTO); break; default: return -EINVAL; @@ -394,40 +114,39 @@ switch (ofdm->guard_interval) { case GUARD_INTERVAL_1_32: deb_setf("1_32\n"); - wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_1_32); + wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32); break; case GUARD_INTERVAL_1_16: deb_setf("1_16\n"); - wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_1_16); + wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16); break; case GUARD_INTERVAL_1_8: deb_setf("1_8\n"); - wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_1_8); + wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8); break; case GUARD_INTERVAL_1_4: deb_setf("1_4\n"); - wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_1_4); + wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4); break; case GUARD_INTERVAL_AUTO: deb_setf("auto\n"); - wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_AUTO); break; default: return -EINVAL; } - deb_setf("invsersion: "); + deb_setf("inversion: "); switch (fep->inversion) { - case INVERSION_AUTO: - deb_setf("auto\n"); - break; case INVERSION_OFF: - deb_setf("on\n"); - wr(DIB3000MB_REG_DDS_INV,DIB3000MB_DDS_INV_OFF); + deb_setf("off\n"); + wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF); + break; + case INVERSION_AUTO: + deb_setf("auto "); break; case INVERSION_ON: deb_setf("on\n"); - wr(DIB3000MB_REG_DDS_INV,DIB3000MB_DDS_INV_ON); + wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON); break; default: return -EINVAL; @@ -437,15 +156,15 @@ switch (ofdm->constellation) { case QPSK: deb_setf("qpsk\n"); - wr(DIB3000MB_REG_QAM,DIB3000MB_QAM_QPSK); + wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK); break; case QAM_16: deb_setf("qam16\n"); - wr(DIB3000MB_REG_QAM,DIB3000MB_QAM_QAM16); + wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM); break; case QAM_64: deb_setf("qam64\n"); - wr(DIB3000MB_REG_QAM,DIB3000MB_QAM_QAM64); + wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM); break; case QAM_AUTO: break; @@ -456,22 +175,21 @@ switch (ofdm->hierarchy_information) { case HIERARCHY_NONE: deb_setf("none "); - /* fall through alpha is 1, even when HIERARCHY is NONE */ + /* fall through */ case HIERARCHY_1: deb_setf("alpha=1\n"); - wr(DIB3000MB_REG_VIT_ALPHA,DIB3000MB_VIT_ALPHA_1); + wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1); break; case HIERARCHY_2: deb_setf("alpha=2\n"); - wr(DIB3000MB_REG_VIT_ALPHA,DIB3000MB_VIT_ALPHA_2); + wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2); break; case HIERARCHY_4: deb_setf("alpha=4\n"); - wr(DIB3000MB_REG_VIT_ALPHA,DIB3000MB_VIT_ALPHA_4); + wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4); break; case HIERARCHY_AUTO: deb_setf("alpha=auto\n"); - wr(DIB3000MB_REG_VIT_ALPHA,DIB3000MB_VIT_ALPHA_AUTO); break; default: return -EINVAL; @@ -480,39 +198,40 @@ deb_setf("hierarchy: "); if (ofdm->hierarchy_information == HIERARCHY_NONE) { deb_setf("none\n"); - wr(DIB3000MB_REG_VIT_HRCH,DIB3000MB_VIT_HRCH_OFF); - wr(DIB3000MB_REG_VIT_HP,DIB3000MB_VIT_HP); + wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF); + wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP); fe_cr = ofdm->code_rate_HP; } else if (ofdm->hierarchy_information != HIERARCHY_AUTO) { deb_setf("on\n"); - wr(DIB3000MB_REG_VIT_HRCH,DIB3000MB_VIT_HRCH_ON); - wr(DIB3000MB_REG_VIT_HP,DIB3000MB_VIT_LP); + wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON); + wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP); fe_cr = ofdm->code_rate_LP; } deb_setf("fec: "); switch (fe_cr) { case FEC_1_2: deb_setf("1_2\n"); - wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_1_2); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2); break; case FEC_2_3: deb_setf("2_3\n"); - wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_2_3); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3); break; case FEC_3_4: deb_setf("3_4\n"); - wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_3_4); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4); break; case FEC_5_6: deb_setf("5_6\n"); - wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_5_6); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6); break; case FEC_7_8: deb_setf("7_8\n"); - wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_7_8); + wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8); break; case FEC_NONE: deb_setf("none "); + break; case FEC_AUTO: deb_setf("auto\n"); break; @@ -520,7 +239,7 @@ return -EINVAL; } - seq = dib3000mb_seq + seq = dib3000_seq [ofdm->transmission_mode == TRANSMISSION_MODE_AUTO] [ofdm->guard_interval == GUARD_INTERVAL_AUTO] [fep->inversion == INVERSION_AUTO]; @@ -564,6 +283,7 @@ ofdm->hierarchy_information == HIERARCHY_AUTO || fe_cr == FEC_AUTO || fep->inversion == INVERSION_AUTO) { + int as_count=0; deb_setf("autosearch enabled.\n"); @@ -572,20 +292,34 @@ wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_AUTO_SEARCH); wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF); - while ((search_state = dib3000mb_fe_read_search_status(state)) < 0); - deb_info("search_state after autosearch %d\n",search_state); - return search_state ? 0 : -EINVAL; + while ((search_state = + dib3000_search_status( + rd(DIB3000MB_REG_AS_IRQ_PENDING), + rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100) + msleep(1); + + deb_info("search_state after autosearch %d after %d checks\n",search_state,as_count); + + if (search_state == 1) { + struct dvb_frontend_parameters feps; + if (dib3000mb_get_frontend(fe, &feps) == 0) { + deb_setf("reading tuning data from frontend succeeded.\n"); + return dib3000mb_set_frontend(fe, &feps, 0); + } + } + } else { wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_CTRL); wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF); - msleep(70); } + return 0; } - -static int dib3000mb_fe_init(struct dib3000mb_state *state,int mobile_mode) +static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode) { + struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv; + wr(DIB3000MB_REG_POWER_CONTROL,DIB3000MB_POWER_UP); wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC); @@ -597,9 +331,6 @@ wr(DIB3000MB_REG_ELECT_OUT_MODE,DIB3000MB_ELECT_OUT_MODE_ON); - wr(DIB3000MB_REG_QAM,DIB3000MB_QAM_RESERVED); - wr(DIB3000MB_REG_VIT_ALPHA,DIB3000MB_VIT_ALPHA_AUTO); - wr(DIB3000MB_REG_DDS_FREQ_MSB,DIB3000MB_DDS_FREQ_MSB); wr(DIB3000MB_REG_DDS_FREQ_LSB,DIB3000MB_DDS_FREQ_LSB); @@ -621,7 +352,7 @@ wr(DIB3000MB_REG_LOCK0_MASK,DIB3000MB_LOCK0_DEFAULT); wr(DIB3000MB_REG_LOCK1_MASK,DIB3000MB_LOCK1_SEARCH_4); wr(DIB3000MB_REG_LOCK2_MASK,DIB3000MB_LOCK2_DEFAULT); - wr(DIB3000MB_REG_SEQ,dib3000mb_seq[1][1][1]); + wr(DIB3000MB_REG_SEQ, dib3000_seq[1][1][1]); wr_foreach(dib3000mb_reg_bandwidth,dib3000mb_bandwidth_8mhz); @@ -639,8 +370,6 @@ wr(DIB3000MB_REG_UNK_108,DIB3000MB_UNK_108); wr(DIB3000MB_REG_UNK_122,DIB3000MB_UNK_122); wr(DIB3000MB_REG_MOBILE_MODE_QAM,DIB3000MB_MOBILE_MODE_QAM_OFF); - wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_1_2); - wr(DIB3000MB_REG_VIT_HP,DIB3000MB_VIT_HP); wr(DIB3000MB_REG_BERLEN,DIB3000MB_BERLEN_DEFAULT); wr_foreach(dib3000mb_reg_filter_coeffs,dib3000mb_filter_coeffs); @@ -653,17 +382,188 @@ wr(DIB3000MB_REG_FIFO_142,DIB3000MB_FIFO_142); wr(DIB3000MB_REG_MPEG2_OUT_MODE,DIB3000MB_MPEG2_OUT_MODE_188); - wr(DIB3000MB_REG_FIFO_144,DIB3000MB_FIFO_144); + wr(DIB3000MB_REG_PID_PARSE, DIB3000MB_PID_PARSE_ACTIVATE); wr(DIB3000MB_REG_FIFO,DIB3000MB_FIFO_INHIBIT); wr(DIB3000MB_REG_FIFO_146,DIB3000MB_FIFO_146); wr(DIB3000MB_REG_FIFO_147,DIB3000MB_FIFO_147); wr(DIB3000MB_REG_DATA_IN_DIVERSITY,DIB3000MB_DATA_DIVERSITY_IN_OFF); + + if (state->config.pll_init) { + wr(DIB3000MB_REG_TUNER, + DIB3000_TUNER_WRITE_ENABLE(state->config.pll_addr)); + state->config.pll_init(fe); + wr(DIB3000MB_REG_TUNER, + DIB3000_TUNER_WRITE_DISABLE(state->config.pll_addr)); + } + return 0; } -static int dib3000mb_read_status(struct dib3000mb_state *state,fe_status_t *stat) +static int dib3000mb_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) { + struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv; + struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm; + fe_code_rate_t *cr; + u16 tps_val; + int inv_test1,inv_test2; + u32 dds_val, threshold = 0x800000; + + if (!rd(DIB3000MB_REG_TPS_LOCK)) + return 0; + + dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB); + if (dds_val < threshold) + inv_test1 = 0; + else if (dds_val == threshold) + inv_test1 = 1; + else + inv_test1 = 2; + + dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB); + if (dds_val < threshold) + inv_test2 = 0; + else if (dds_val == threshold) + inv_test2 = 1; + else + inv_test2 = 2; + + fep->inversion = + ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) || + ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ? + INVERSION_ON : INVERSION_OFF; + + deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion); + + switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) { + case DIB3000_CONSTELLATION_QPSK: + deb_getf("QPSK "); + ofdm->constellation = QPSK; + break; + case DIB3000_CONSTELLATION_16QAM: + deb_getf("QAM16 "); + ofdm->constellation = QAM_16; + break; + case DIB3000_CONSTELLATION_64QAM: + deb_getf("QAM64 "); + ofdm->constellation = QAM_64; + break; + default: + err("Unexpected constellation returned by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n", tps_val); + + if (rd(DIB3000MB_REG_TPS_HRCH)) { + deb_getf("HRCH ON\n"); + cr = &ofdm->code_rate_LP; + ofdm->code_rate_HP = FEC_NONE; + switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) { + case DIB3000_ALPHA_0: + deb_getf("HIERARCHY_NONE "); + ofdm->hierarchy_information = HIERARCHY_NONE; + break; + case DIB3000_ALPHA_1: + deb_getf("HIERARCHY_1 "); + ofdm->hierarchy_information = HIERARCHY_1; + break; + case DIB3000_ALPHA_2: + deb_getf("HIERARCHY_2 "); + ofdm->hierarchy_information = HIERARCHY_2; + break; + case DIB3000_ALPHA_4: + deb_getf("HIERARCHY_4 "); + ofdm->hierarchy_information = HIERARCHY_4; + break; + default: + err("Unexpected ALPHA value returned by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n", tps_val); + + tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP); + } else { + deb_getf("HRCH OFF\n"); + cr = &ofdm->code_rate_HP; + ofdm->code_rate_LP = FEC_NONE; + ofdm->hierarchy_information = HIERARCHY_NONE; + + tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP); + } + + switch (tps_val) { + case DIB3000_FEC_1_2: + deb_getf("FEC_1_2 "); + *cr = FEC_1_2; + break; + case DIB3000_FEC_2_3: + deb_getf("FEC_2_3 "); + *cr = FEC_2_3; + break; + case DIB3000_FEC_3_4: + deb_getf("FEC_3_4 "); + *cr = FEC_3_4; + break; + case DIB3000_FEC_5_6: + deb_getf("FEC_5_6 "); + *cr = FEC_4_5; + break; + case DIB3000_FEC_7_8: + deb_getf("FEC_7_8 "); + *cr = FEC_7_8; + break; + default: + err("Unexpected FEC returned by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n",tps_val); + + switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) { + case DIB3000_GUARD_TIME_1_32: + deb_getf("GUARD_INTERVAL_1_32 "); + ofdm->guard_interval = GUARD_INTERVAL_1_32; + break; + case DIB3000_GUARD_TIME_1_16: + deb_getf("GUARD_INTERVAL_1_16 "); + ofdm->guard_interval = GUARD_INTERVAL_1_16; + break; + case DIB3000_GUARD_TIME_1_8: + deb_getf("GUARD_INTERVAL_1_8 "); + ofdm->guard_interval = GUARD_INTERVAL_1_8; + break; + case DIB3000_GUARD_TIME_1_4: + deb_getf("GUARD_INTERVAL_1_4 "); + ofdm->guard_interval = GUARD_INTERVAL_1_4; + break; + default: + err("Unexpected Guard Time returned by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n", tps_val); + + switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) { + case DIB3000_TRANSMISSION_MODE_2K: + deb_getf("TRANSMISSION_MODE_2K "); + ofdm->transmission_mode = TRANSMISSION_MODE_2K; + break; + case DIB3000_TRANSMISSION_MODE_8K: + deb_getf("TRANSMISSION_MODE_8K "); + ofdm->transmission_mode = TRANSMISSION_MODE_8K; + break; + default: + err("unexpected transmission mode return by TPS (%d)", tps_val); + break; + } + deb_getf("TPS: %d\n", tps_val); + + return 0; +} + +static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat) +{ + struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv; + *stat = 0; if (rd(DIB3000MB_REG_AGC_LOCK)) @@ -699,8 +599,10 @@ return 0; } -static int dib3000mb_read_ber(struct dib3000mb_state *state,u32 *ber) +static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber) { + struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv; + *ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB) ); return 0; } @@ -714,8 +616,10 @@ #define DIB3000MB_AGC_REF_dBm -14 #define DIB3000MB_GAIN_SLOPE_dBm 100 #define DIB3000MB_GAIN_DELTA_dBm -2 -static int dib3000mb_read_signal_strength(struct dib3000mb_state *state, u16 *strength) +static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength) { + struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv; + /* TODO log10 u16 sigpow = rd(DIB3000MB_REG_SIGNAL_POWER), n_agc_power = rd(DIB3000MB_REG_AGC_POWER), @@ -748,8 +652,9 @@ * If SNR is above 20dB, BER should be always 0. * choose 0dB as the minimum */ -static int dib3000mb_read_snr(struct dib3000mb_state *state,u16 *snr) +static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr) { + struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv; short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER); int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) | rd(DIB3000MB_REG_NOISE_POWER_LSB); @@ -763,24 +668,27 @@ *snr = (u16) ((snr_dBm / 35) * 0xffff); */ - *snr = (sigpow<<8) / (icipow > 0 ? icipow : 1); + *snr = (sigpow << 8) / ((icipow > 0) ? icipow : 1); return 0; } -static int dib3000mb_read_unc_blocks(struct dib3000mb_state *state,u32 *unc) +static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) { + struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv; + *unc = rd(DIB3000MB_REG_UNC); return 0; } -static int dib3000mb_sleep(struct dib3000mb_state *state) +static int dib3000mb_sleep(struct dvb_frontend* fe) { + struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv; + wr(DIB3000MB_REG_POWER_CONTROL,DIB3000MB_POWER_DOWN); return 0; } -static int dib3000mb_fe_get_tune_settings(struct dib3000mb_state *state, - struct dvb_frontend_tune_settings *tune) +static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) { tune->min_delay_ms = 800; tune->step_size = 166667; @@ -789,205 +697,137 @@ return 0; } -static int dib3000mb_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe) { - struct dib3000mb_state *state = fe->data; - switch (cmd) { - case FE_GET_INFO: - deb_info("FE_GET_INFO\n"); - memcpy(arg, &dib3000mb_info, sizeof(struct dvb_frontend_info)); - return 0; - break; - - case FE_READ_STATUS: - deb_info("FE_READ_STATUS\n"); - return dib3000mb_read_status(state,(fe_status_t *)arg); - break; - - case FE_READ_BER: - deb_info("FE_READ_BER\n"); - return dib3000mb_read_ber(state,(u32 *)arg); - break; - - case FE_READ_SIGNAL_STRENGTH: - deb_info("FE_READ_SIG_STRENGTH\n"); - return dib3000mb_read_signal_strength(state,(u16 *) arg); - break; - - case FE_READ_SNR: - deb_info("FE_READ_SNR\n"); - return dib3000mb_read_snr(state,(u16 *) arg); - break; - - case FE_READ_UNCORRECTED_BLOCKS: - deb_info("FE_READ_UNCORRECTED_BLOCKS\n"); - return dib3000mb_read_unc_blocks(state,(u32 *) arg); - break; - - case FE_SET_FRONTEND: - deb_info("FE_SET_FRONTEND\n"); - return dib3000mb_set_frontend(state,(struct dvb_frontend_parameters *) arg,1); - break; - - case FE_GET_FRONTEND: - deb_info("FE_GET_FRONTEND\n"); - return dib3000mb_get_frontend(state,(struct dvb_frontend_parameters *) arg); - break; + return dib3000mb_fe_init(fe, 0); +} - case FE_SLEEP: - deb_info("FE_SLEEP\n"); - return dib3000mb_sleep(state); - break; +static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep) +{ + return dib3000mb_set_frontend(fe, fep, 1); +} - case FE_INIT: - deb_info("FE_INIT\n"); - return dib3000mb_fe_init(state,0); - break; +static void dib3000mb_release(struct dvb_frontend* fe) +{ + struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv; + kfree(state); +} - case FE_GET_TUNE_SETTINGS: - deb_info("GET_TUNE_SETTINGS"); - return dib3000mb_fe_get_tune_settings(state, (struct - dvb_frontend_tune_settings *) arg); +/* pid filter and transfer stuff */ +static int dib3000mb_pid_control(struct dvb_frontend *fe,int pid,int onoff) +{ + struct dib3000_state *state = fe->demodulator_priv; + int index = dib3000_get_pid_index(state->pid_list, DIB3000MB_NUM_PIDS, pid, &state->pid_list_lock,onoff); + pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0); - break; - case FE_SET_TONE: - case FE_SET_VOLTAGE: - default: - return -EOPNOTSUPP; - break; + if (index >= 0) { + wr(index+DIB3000MB_REG_FIRST_PID,pid); + } else { + err("no more pids for filtering."); + return -ENOMEM; } return 0; } -static struct i2c_client client_template; - -static int dib3000mb_attach_adapter(struct i2c_adapter *adapter) +static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff) { - struct i2c_client *client; - struct dib3000mb_state *state; - int ret = -ENOMEM; - - deb_info("i2c probe with adapter '%s'.\n",adapter->name); - - if ((state = kmalloc(sizeof(struct dib3000mb_state),GFP_KERNEL)) == NULL) - return -ENOMEM; + struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv; - - if ((client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)) == NULL) - goto i2c_kmalloc_err; - - memcpy(client, &client_template, sizeof(struct i2c_client)); - - client->adapter = adapter; - client->addr = 0x10; - state->i2c = client; - - i2c_set_clientdata(client,state); - - state->manufactor_id = dib3000mb_read_reg(client, DIB3000MB_REG_MANUFACTOR_ID); - if (state->manufactor_id != 0x01b3) { - ret = -ENODEV; - goto probe_err; + deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling"); + if (onoff) { + wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_ACTIVATE); + } else { + wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT); } - - state->device_id = dib3000mb_read_reg(client,DIB3000MB_REG_DEVICE_ID); - if (state->device_id != 0x3000) { - ret = -ENODEV; - goto probe_err; + return 0; } - info("found a DiBCom (0x%04x) 3000-MB DVB-T frontend (ver: %x).", - state->manufactor_id, state->device_id); - - if ((ret = i2c_attach_client(client))) - goto i2c_attach_err; - - if (state->dvb == NULL) - goto i2c_attach_err; - - if ((ret = dvb_register_frontend(dib3000mb_ioctl, state->dvb, state, - &dib3000mb_info, THIS_MODULE))) - goto dvb_fe_err; - - - goto success; -dvb_fe_err: - i2c_detach_client(client); -i2c_attach_err: -probe_err: - kfree(client); -i2c_kmalloc_err: - kfree(state); - return ret; -success: +static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff) +{ + //struct dib3000_state *state = fe->demodulator_priv; + /* switch it off and on */ return 0; -} + } +static struct dvb_frontend_ops dib3000mb_ops; -static int dib3000mb_detach_client(struct i2c_client *client) +struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, + struct i2c_adapter* i2c, struct dib3000_xfer_ops *xfer_ops) { - struct dib3000mb_state *state = i2c_get_clientdata(client); + struct dib3000_state* state = NULL; - deb_info("i2c detach\n"); + /* allocate memory for the internal state */ + state = (struct dib3000_state*) kmalloc(sizeof(struct dib3000_state), GFP_KERNEL); + if (state == NULL) + goto error; - dvb_unregister_frontend(dib3000mb_ioctl, state->dvb); - i2c_detach_client(client); - kfree(client); - kfree(state); + /* setup the state */ + state->i2c = i2c; + memcpy(&state->config,config,sizeof(struct dib3000_config)); + memcpy(&state->ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops)); - return 0; -} + /* check for the correct demod */ + if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM) + goto error; -static int dib3000mb_command(struct i2c_client *client, - unsigned int cmd, void *arg) -{ - struct dib3000mb_state *state = i2c_get_clientdata(client); - deb_info("i2c command.\n"); - switch(cmd) { - case FE_REGISTER: - state->dvb = arg; - break; - case FE_UNREGISTER: - state->dvb = NULL; - break; - default: - return -EOPNOTSUPP; - } + if (rd(DIB3000_REG_DEVICE_ID) != DIB3000MB_DEVICE_ID) + goto error; - return 0; -} + if (dib3000_init_pid_list(state,DIB3000MB_NUM_PIDS)) + goto error; -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = "dib3000mb", - .id = I2C_DRIVERID_DVBFE_DIB3000MB, - .flags = I2C_DF_NOTIFY, - .attach_adapter = dib3000mb_attach_adapter, - .detach_client = dib3000mb_detach_client, - .command = dib3000mb_command, -}; + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; -static struct i2c_client client_template = { - .name = "dib3000mb", - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, -}; + /* set the xfer operations */ + xfer_ops->pid_parse = dib3000mb_pid_parse; + xfer_ops->fifo_ctrl = dib3000mb_fifo_control; + xfer_ops->pid_ctrl = dib3000mb_pid_control; -/* module stuff */ -static int __init dib3000mb_init(void) -{ - deb_info("debugging level: %d\n",debug); - return i2c_add_driver(&driver); -} + return &state->frontend; -static void __exit dib3000mb_exit(void) -{ - i2c_del_driver(&driver); -} +error: + if (state) + kfree(state); + return NULL; + } -module_init (dib3000mb_init); -module_exit (dib3000mb_exit); +static struct dvb_frontend_ops dib3000mb_ops = { + + .info = { + .name = "DiBcom 3000-MB DVB-T", + .type = FE_OFDM, + .frequency_min = 44250000, + .frequency_max = 867250000, + .frequency_stepsize = 62500, + .caps = FE_CAN_INVERSION_AUTO | + 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 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = dib3000mb_release, + + .init = dib3000mb_fe_init_nonmobile, + .sleep = dib3000mb_sleep, + + .set_frontend = dib3000mb_set_frontend_and_tuner, + .get_frontend = dib3000mb_get_frontend, + .get_tune_settings = dib3000mb_fe_get_tune_settings, + + .read_status = dib3000mb_read_status, + .read_ber = dib3000mb_read_ber, + .read_signal_strength = dib3000mb_read_signal_strength, + .read_snr = dib3000mb_read_snr, + .read_ucblocks = dib3000mb_read_unc_blocks, +}; MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(dib3000mb_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/dst-bt878.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/dst-bt878.h 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/dst-bt878.h 2004-12-22 10:04:35.461411898 -0800 @@ -30,7 +30,7 @@ #define DST_IG_READ 2 #define DST_IG_TS 3 -struct bt878 ; +struct bt878; int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/dst.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/dst.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/dst.c 2004-12-22 10:04:35.459412202 -0800 @@ -1,4 +1,4 @@ -/* +/* Frontend-driver for TwinHan DST Frontend Copyright (C) 2003 Jamie Honan @@ -30,32 +30,23 @@ #include #include "dvb_frontend.h" -#include "dst-bt878.h" +#include "dst_priv.h" +#include "dst.h" -unsigned int dst_verbose = 0; -MODULE_PARM(dst_verbose, "i"); -MODULE_PARM_DESC(dst_verbose, "verbose startup messages, default is 1 (yes)"); -unsigned int dst_debug = 0; -MODULE_PARM(dst_debug, "i"); -MODULE_PARM_DESC(dst_debug, "debug messages, default is 0 (no)"); +struct dst_state { -#define dprintk if (dst_debug) printk + struct i2c_adapter* i2c; -#define DST_I2C_ADDR 0x55 + struct bt878* bt; -#define DST_TYPE_IS_SAT 0 -#define DST_TYPE_IS_TERR 1 -#define DST_TYPE_IS_CABLE 2 + struct dvb_frontend_ops ops; -#define DST_TYPE_HAS_NEWTUNE 1 -#define DST_TYPE_HAS_TS204 2 -#define DST_TYPE_HAS_SYMDIV 4 + /* configuration settings */ + const struct dst_config* config; -#define HAS_LOCK 1 -#define ATTEMPT_TUNE 2 -#define HAS_POWER 4 + struct dvb_frontend frontend; -struct dst_data { + /* private demodulator data */ u8 tx_tuna[10]; u8 rx_tuna[10]; u8 rxbuffer[10]; @@ -75,57 +66,38 @@ unsigned long cur_jiff; u8 k22; fe_bandwidth_t bandwidth; - - struct bt878 *bt; - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; }; -static struct dvb_frontend_info dst_info_sat = { - .name = "DST SAT", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 1000, /* kHz for QPSK frontends */ - .frequency_tolerance = 29500, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, -/* . symbol_rate_tolerance = ???,*/ - .notifier_delay = 50, /* 1/20 s */ - .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK -}; +static unsigned int dst_verbose = 0; +module_param(dst_verbose, int, 0644); +MODULE_PARM_DESC(dst_verbose, "verbose startup messages, default is 1 (yes)"); +static unsigned int dst_debug = 0; +module_param(dst_debug, int, 0644); +MODULE_PARM_DESC(dst_debug, "debug messages, default is 0 (no)"); -static struct dvb_frontend_info dst_info_cable = { - .name = "DST CABLE", - .type = FE_QAM, - .frequency_stepsize = 62500, - .frequency_min = 51000000, - .frequency_max = 858000000, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, -/* . symbol_rate_tolerance = ???,*/ - .notifier_delay = 50, /* 1/20 s */ - .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO -}; +#define dprintk if (dst_debug) printk -static struct dvb_frontend_info dst_info_terr = { - .name = "DST TERR", - .type = FE_OFDM, - .frequency_min = 137000000, - .frequency_max = 858000000, - .frequency_stepsize = 166667, - .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO -}; +#define DST_TYPE_IS_SAT 0 +#define DST_TYPE_IS_TERR 1 +#define DST_TYPE_IS_CABLE 2 + +#define DST_TYPE_HAS_NEWTUNE 1 +#define DST_TYPE_HAS_TS204 2 +#define DST_TYPE_HAS_SYMDIV 4 + +#define HAS_LOCK 1 +#define ATTEMPT_TUNE 2 +#define HAS_POWER 4 -static void dst_packsize(struct dst_data *dst, int psize) +static void dst_packsize(struct dst_state* state, int psize) { union dst_gpio_packet bits; bits.psize = psize; - bt878_device_control(dst->bt, DST_IG_TS, &bits); + bt878_device_control(state->bt, DST_IG_TS, &bits); } -static int dst_gpio_outb(struct dst_data *dst, u32 mask, u32 enbb, u32 outhigh) +static int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh) { union dst_gpio_packet enb; union dst_gpio_packet bits; @@ -133,7 +105,7 @@ enb.enb.mask = mask; enb.enb.enable = enbb; - if ((err = bt878_device_control(dst->bt, DST_IG_ENABLE, &enb)) < 0) { + if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) { dprintk("%s: dst_gpio_enb error (err == %i, mask == 0x%02x, enb == 0x%02x)\n", __FUNCTION__, err, mask, enbb); return -EREMOTEIO; } @@ -145,24 +117,25 @@ bits.outp.mask = enbb; bits.outp.highvals = outhigh; - if ((err = bt878_device_control(dst->bt, DST_IG_WRITE, &bits)) < 0) { + if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) { dprintk("%s: dst_gpio_outb error (err == %i, enbb == 0x%02x, outhigh == 0x%02x)\n", __FUNCTION__, err, enbb, outhigh); return -EREMOTEIO; } return 0; } -static int dst_gpio_inb(struct dst_data *dst, u8 * result) +static int dst_gpio_inb(struct dst_state *state, u8 * result) { union dst_gpio_packet rd_packet; int err; *result = 0; - if ((err = bt878_device_control(dst->bt, DST_IG_READ, &rd_packet)) < 0) { + if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) { dprintk("%s: dst_gpio_inb error (err == %i)\n", __FUNCTION__, err); return -EREMOTEIO; } + *result = (u8) rd_packet.rd.value; return 0; } @@ -170,16 +143,16 @@ #define DST_I2C_ENABLE 1 #define DST_8820 2 -static int dst_reset8820(struct dst_data *dst) +static int dst_reset8820(struct dst_state *state) { int retval; /* pull 8820 gpio pin low, wait, high, wait, then low */ // dprintk ("%s: reset 8820\n", __FUNCTION__); - retval = dst_gpio_outb(dst, DST_8820, DST_8820, 0); + retval = dst_gpio_outb(state, DST_8820, DST_8820, 0); if (retval < 0) return retval; msleep(10); - retval = dst_gpio_outb(dst, DST_8820, DST_8820, DST_8820); + retval = dst_gpio_outb(state, DST_8820, DST_8820, DST_8820); if (retval < 0) return retval; /* wait for more feedback on what works here * @@ -191,12 +164,12 @@ return 0; } -static int dst_i2c_enable(struct dst_data *dst) +static int dst_i2c_enable(struct dst_state *state) { int retval; /* pull I2C enable gpio pin low, wait */ // dprintk ("%s: i2c enable\n", __FUNCTION__); - retval = dst_gpio_outb(dst, ~0, DST_I2C_ENABLE, 0); + retval = dst_gpio_outb(state, ~0, DST_I2C_ENABLE, 0); if (retval < 0) return retval; // dprintk ("%s: i2c enable delay\n", __FUNCTION__); @@ -204,12 +177,12 @@ return 0; } -static int dst_i2c_disable(struct dst_data *dst) +static int dst_i2c_disable(struct dst_state *state) { int retval; /* release I2C enable gpio pin, wait */ // dprintk ("%s: i2c disable\n", __FUNCTION__); - retval = dst_gpio_outb(dst, ~0, 0, 0); + retval = dst_gpio_outb(state, ~0, 0, 0); if (retval < 0) return retval; // dprintk ("%s: i2c disable delay\n", __FUNCTION__); @@ -217,29 +190,29 @@ return 0; } -static int dst_wait_dst_ready(struct dst_data *dst) +static int dst_wait_dst_ready(struct dst_state *state) { u8 reply; int retval; int i; for (i = 0; i < 200; i++) { - retval = dst_gpio_inb(dst, &reply); + retval = dst_gpio_inb(state, &reply); if (retval < 0) return retval; if ((reply & DST_I2C_ENABLE) == 0) { dprintk("%s: dst wait ready after %d\n", __FUNCTION__, i); return 1; } - msleep(5); + msleep(10); } dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i); return 0; } -static int write_dst(struct dst_data *dst, u8 * data, u8 len) +static int write_dst(struct dst_state *state, u8 * data, u8 len) { struct i2c_msg msg = { - .addr = DST_I2C_ADDR,.flags = 0,.buf = data,.len = len + .addr = state->config->demod_address,.flags = 0,.buf = data,.len = len }; int err; int cnt; @@ -254,11 +227,11 @@ } msleep(30); for (cnt = 0; cnt < 4; cnt++) { - if ((err = i2c_transfer(dst->i2c, &msg, 1)) < 0) { + if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) { dprintk("%s: write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]); - dst_i2c_disable(dst); + dst_i2c_disable(state); msleep(500); - dst_i2c_enable(dst); + dst_i2c_enable(state); msleep(500); continue; } else @@ -269,17 +242,17 @@ return 0; } -static int read_dst(struct dst_data *dst, u8 * ret, u8 len) +static int read_dst(struct dst_state *state, u8 * ret, u8 len) { - struct i2c_msg msg = {.addr = DST_I2C_ADDR,.flags = I2C_M_RD,.buf = ret,.len = len }; + struct i2c_msg msg = {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = ret,.len = len }; int err; int cnt; for (cnt = 0; cnt < 4; cnt++) { - if ((err = i2c_transfer(dst->i2c, &msg, 1)) < 0) { + if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) { dprintk("%s: read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]); - dst_i2c_disable(dst); - dst_i2c_enable(dst); + dst_i2c_disable(state); + dst_i2c_enable(state); continue; } else break; @@ -296,34 +269,34 @@ return 0; } -static int dst_set_freq(struct dst_data *dst, u32 freq) +static int dst_set_freq(struct dst_state *state, u32 freq) { u8 *val; - dst->frequency = freq; + state->frequency = freq; // dprintk("%s: set frequency %u\n", __FUNCTION__, freq); - if (dst->dst_type == DST_TYPE_IS_SAT) { + if (state->dst_type == DST_TYPE_IS_SAT) { freq = freq / 1000; if (freq < 950 || freq > 2150) return -EINVAL; - val = &dst->tx_tuna[0]; + val = &state->tx_tuna[0]; val[2] = (freq >> 8) & 0x7f; val[3] = (u8) freq; val[4] = 1; val[8] &= ~4; if (freq < 1531) val[8] |= 4; - } else if (dst->dst_type == DST_TYPE_IS_TERR) { + } else if (state->dst_type == DST_TYPE_IS_TERR) { freq = freq / 1000; if (freq < 137000 || freq > 858000) return -EINVAL; - val = &dst->tx_tuna[0]; + val = &state->tx_tuna[0]; val[2] = (freq >> 16) & 0xff; val[3] = (freq >> 8) & 0xff; val[4] = (u8) freq; val[5] = 0; - switch (dst->bandwidth) { + switch (state->bandwidth) { case BANDWIDTH_6_MHZ: val[6] = 6; break; @@ -340,10 +313,10 @@ val[7] = 0; val[8] = 0; - } else if (dst->dst_type == DST_TYPE_IS_CABLE) { + } else if (state->dst_type == DST_TYPE_IS_CABLE) { /* guess till will get one */ freq = freq / 1000; - val = &dst->tx_tuna[0]; + val = &state->tx_tuna[0]; val[2] = (freq >> 16) & 0xff; val[3] = (freq >> 8) & 0xff; val[4] = (u8) freq; @@ -352,16 +325,16 @@ return 0; } -static int dst_set_bandwidth(struct dst_data *dst, fe_bandwidth_t bandwidth) +static int dst_set_bandwidth(struct dst_state* state, fe_bandwidth_t bandwidth) { u8 *val; - dst->bandwidth = bandwidth; + state->bandwidth = bandwidth; - if (dst->dst_type != DST_TYPE_IS_TERR) + if (state->dst_type != DST_TYPE_IS_TERR) return 0; - val = &dst->tx_tuna[0]; + val = &state->tx_tuna[0]; switch (bandwidth) { case BANDWIDTH_6_MHZ: val[6] = 6; @@ -381,13 +354,13 @@ return 0; } -static int dst_set_inversion(struct dst_data *dst, fe_spectral_inversion_t inversion) +static int dst_set_inversion(struct dst_state* state, fe_spectral_inversion_t inversion) { u8 *val; - dst->inversion = inversion; + state->inversion = inversion; - val = &dst->tx_tuna[0]; + val = &state->tx_tuna[0]; val[8] &= ~0x80; @@ -403,34 +376,33 @@ return 0; } - -static int dst_set_fec(struct dst_data *dst, fe_code_rate_t fec) +static int dst_set_fec(struct dst_state* state, fe_code_rate_t fec) { - dst->fec = fec; + state->fec = fec; return 0; } -static fe_code_rate_t dst_get_fec(struct dst_data *dst) +static fe_code_rate_t dst_get_fec(struct dst_state* state) { - return dst->fec; + return state->fec; } -static int dst_set_symbolrate(struct dst_data *dst, u32 srate) +static int dst_set_symbolrate(struct dst_state* state, u32 srate) { u8 *val; u32 symcalc; u64 sval; - dst->symbol_rate = srate; + state->symbol_rate = srate; - if (dst->dst_type == DST_TYPE_IS_TERR) { + if (state->dst_type == DST_TYPE_IS_TERR) { return 0; } // dprintk("%s: set srate %u\n", __FUNCTION__, srate); srate /= 1000; - val = &dst->tx_tuna[0]; + val = &state->tx_tuna[0]; - if (dst->type_flags & DST_TYPE_HAS_SYMDIV) { + if (state->type_flags & DST_TYPE_HAS_SYMDIV) { sval = srate; sval <<= 20; do_div(sval, 88000); @@ -450,7 +422,6 @@ return 0; } - static u8 dst_check_sum(u8 * buf, u32 len) { u32 i; @@ -463,14 +434,14 @@ return ((~val) + 1); } -typedef struct dst_types { +struct dst_types { char *mstr; int offs; u8 dst_type; u32 type_flags; -} DST_TYPES; +}; -struct dst_types dst_tlist[] = { +static struct dst_types dst_tlist[] = { {"DST-020", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV}, {"DST-030", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE}, {"DST-03T", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204}, @@ -479,7 +450,7 @@ {"DSTMCI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE}, {"DSTFCI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE}, {"DCTNEW", 1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE}, - {"DCT_CI", 1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_TS204}, + {"DCT-CI", 1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_TS204}, {"DTTDIG", 1, DST_TYPE_IS_TERR, 0} }; @@ -505,10 +476,10 @@ otype = "satellite"; break; case DST_TYPE_IS_TERR: - otype = "terrestial TV"; + otype = "terrestrial"; break; case DST_TYPE_IS_CABLE: - otype = "terrestial TV"; + otype = "cable"; break; default: printk("%s: invalid dst type %d\n", __FUNCTION__, type); @@ -518,7 +489,7 @@ return 0; } -static int dst_check_ci(struct dst_data *dst) +static int dst_check_ci(struct dst_state *state) { u8 txbuf[8]; u8 rxbuf[8]; @@ -532,17 +503,17 @@ txbuf[1] = 6; txbuf[7] = dst_check_sum(txbuf, 7); - dst_i2c_enable(dst); - dst_reset8820(dst); - retval = write_dst(dst, txbuf, 8); + dst_i2c_enable(state); + dst_reset8820(state); + retval = write_dst(state, txbuf, 8); if (retval < 0) { - dst_i2c_disable(dst); + dst_i2c_disable(state); dprintk("%s: write not successful, maybe no card?\n", __FUNCTION__); return retval; } msleep(3); - retval = read_dst(dst, rxbuf, 1); - dst_i2c_disable(dst); + retval = read_dst(state, rxbuf, 1); + dst_i2c_disable(state); if (retval < 0) { dprintk("%s: read not successful, maybe no card?\n", __FUNCTION__); return retval; @@ -551,11 +522,11 @@ dprintk("%s: write reply not 0xff, not ci (%02x)\n", __FUNCTION__, rxbuf[0]); return retval; } - if (!dst_wait_dst_ready(dst)) + if (!dst_wait_dst_ready(state)) return 0; // dst_i2c_enable(i2c); Dimitri - retval = read_dst(dst, rxbuf, 8); - dst_i2c_disable(dst); + retval = read_dst(state, rxbuf, 8); + dst_i2c_disable(state); if (retval < 0) { dprintk("%s: read not successful\n", __FUNCTION__); return retval; @@ -581,32 +552,32 @@ } dst_type_print(use_dst_type); - dst->type_flags = use_type_flags; - dst->dst_type = use_dst_type; - dst_type_flags_print(dst->type_flags); + state->type_flags = use_type_flags; + state->dst_type = use_dst_type; + dst_type_flags_print(state->type_flags); - if (dst->type_flags & DST_TYPE_HAS_TS204) { - dst_packsize(dst, 204); + if (state->type_flags & DST_TYPE_HAS_TS204) { + dst_packsize(state, 204); } return 0; } -static int dst_command(struct dst_data *dst, u8 * data, u8 len) +static int dst_command(struct dst_state* state, u8 * data, u8 len) { int retval; u8 reply; - dst_i2c_enable(dst); - dst_reset8820(dst); - retval = write_dst(dst, data, len); + dst_i2c_enable(state); + dst_reset8820(state); + retval = write_dst(state, data, len); if (retval < 0) { - dst_i2c_disable(dst); + dst_i2c_disable(state); dprintk("%s: write not successful\n", __FUNCTION__); return retval; } msleep(33); - retval = read_dst(dst, &reply, 1); - dst_i2c_disable(dst); + retval = read_dst(state, &reply, 1); + dst_i2c_disable(state); if (retval < 0) { dprintk("%s: read verify not successful\n", __FUNCTION__); return retval; @@ -617,201 +588,107 @@ } if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3)) return 0; - if (!dst_wait_dst_ready(dst)) + if (!dst_wait_dst_ready(state)) return 0; // dst_i2c_enable(i2c); Per dimitri - retval = read_dst(dst, dst->rxbuffer, 8); - dst_i2c_disable(dst); + retval = read_dst(state, state->rxbuffer, 8); + dst_i2c_disable(state); if (retval < 0) { dprintk("%s: read not successful\n", __FUNCTION__); return 0; } - if (dst->rxbuffer[7] != dst_check_sum(dst->rxbuffer, 7)) { + if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) { dprintk("%s: checksum failure\n", __FUNCTION__); return 0; } return 0; } -static int dst_get_signal(struct dst_data *dst) +static int dst_get_signal(struct dst_state* state) { int retval; u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb }; - if ((dst->diseq_flags & ATTEMPT_TUNE) == 0) { - dst->decode_lock = dst->decode_strength = dst->decode_snr = 0; + if ((state->diseq_flags & ATTEMPT_TUNE) == 0) { + state->decode_lock = state->decode_strength = state->decode_snr = 0; return 0; } - if (0 == (dst->diseq_flags & HAS_LOCK)) { - dst->decode_lock = dst->decode_strength = dst->decode_snr = 0; + if (0 == (state->diseq_flags & HAS_LOCK)) { + state->decode_lock = state->decode_strength = state->decode_snr = 0; return 0; } - if (time_after_eq(jiffies, dst->cur_jiff + (HZ / 5))) { - retval = dst_command(dst, get_signal, 8); + if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) { + retval = dst_command(state, get_signal, 8); if (retval < 0) return retval; - if (dst->dst_type == DST_TYPE_IS_SAT) { - dst->decode_lock = ((dst->rxbuffer[6] & 0x10) == 0) ? 1 : 0; - dst->decode_strength = dst->rxbuffer[5] << 8; - dst->decode_snr = dst->rxbuffer[2] << 8 | dst->rxbuffer[3]; - } else if ((dst->dst_type == DST_TYPE_IS_TERR) || (dst->dst_type == DST_TYPE_IS_CABLE)) { - dst->decode_lock = (dst->rxbuffer[1]) ? 1 : 0; - dst->decode_strength = dst->rxbuffer[4] << 8; - dst->decode_snr = dst->rxbuffer[3] << 8; + if (state->dst_type == DST_TYPE_IS_SAT) { + state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0; + state->decode_strength = state->rxbuffer[5] << 8; + state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3]; + } else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) { + state->decode_lock = (state->rxbuffer[1]) ? 1 : 0; + state->decode_strength = state->rxbuffer[4] << 8; + state->decode_snr = state->rxbuffer[3] << 8; } - dst->cur_jiff = jiffies; + state->cur_jiff = jiffies; } return 0; } -/* - * line22k0 0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00 - * line22k1 0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00 - * line22k2 0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00 - * tone 0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00 - * data 0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00 - * power_off 0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 - * power_on 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 - * Diseqc 1 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec - * Diseqc 2 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8 - * Diseqc 3 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4 - * Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0 - */ - -static int dst_set_diseqc(struct dst_data *dst, u8 * cmd, u8 len) -{ - u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec }; - - if (dst->dst_type == DST_TYPE_IS_TERR) - return 0; - - if (len == 0 || len > 4) - return -EINVAL; - memcpy(&paket[3], cmd, len); - paket[7] = dst_check_sum(&paket[0], 7); - dst_command(dst, paket, 8); - return 0; -} - -static int dst_tone_power_cmd(struct dst_data *dst) +static int dst_tone_power_cmd(struct dst_state* state) { u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 }; - if (dst->dst_type == DST_TYPE_IS_TERR) + if (state->dst_type == DST_TYPE_IS_TERR) return 0; - if (dst->voltage == SEC_VOLTAGE_OFF) + if (state->voltage == SEC_VOLTAGE_OFF) paket[4] = 0; else paket[4] = 1; - if (dst->tone == SEC_TONE_ON) - paket[2] = dst->k22; + if (state->tone == SEC_TONE_ON) + paket[2] = state->k22; else paket[2] = 0; paket[7] = dst_check_sum(&paket[0], 7); - dst_command(dst, paket, 8); + dst_command(state, paket, 8); return 0; } -static int dst_set_voltage(struct dst_data *dst, fe_sec_voltage_t voltage) -{ - u8 *val; - int need_cmd; - - dst->voltage = voltage; - - if (dst->dst_type == DST_TYPE_IS_TERR) - return 0; - - need_cmd = 0; - val = &dst->tx_tuna[0]; - val[8] &= ~0x40; - switch (voltage) { - case SEC_VOLTAGE_13: - if ((dst->diseq_flags & HAS_POWER) == 0) - need_cmd = 1; - dst->diseq_flags |= HAS_POWER; - break; - case SEC_VOLTAGE_18: - if ((dst->diseq_flags & HAS_POWER) == 0) - need_cmd = 1; - dst->diseq_flags |= HAS_POWER; - val[8] |= 0x40; - break; - case SEC_VOLTAGE_OFF: - need_cmd = 1; - dst->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE); - break; - default: - return -EINVAL; - } - if (need_cmd) { - dst_tone_power_cmd(dst); - } - return 0; -} - - -static int dst_set_tone(struct dst_data *dst, fe_sec_tone_mode_t tone) -{ - u8 *val; - - dst->tone = tone; - - if (dst->dst_type == DST_TYPE_IS_TERR) - return 0; - - val = &dst->tx_tuna[0]; - - val[8] &= ~0x1; - - switch (tone) { - case SEC_TONE_OFF: - break; - case SEC_TONE_ON: - val[8] |= 1; - break; - default: - return -EINVAL; - } - dst_tone_power_cmd(dst); - return 0; -} - -static int dst_get_tuna(struct dst_data *dst) +static int dst_get_tuna(struct dst_state* state) { int retval; - if ((dst->diseq_flags & ATTEMPT_TUNE) == 0) + if ((state->diseq_flags & ATTEMPT_TUNE) == 0) return 0; - dst->diseq_flags &= ~(HAS_LOCK); - if (!dst_wait_dst_ready(dst)) + state->diseq_flags &= ~(HAS_LOCK); + if (!dst_wait_dst_ready(state)) return 0; - if (dst->type_flags & DST_TYPE_HAS_NEWTUNE) { + if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { /* how to get variable length reply ???? */ - retval = read_dst(dst, dst->rx_tuna, 10); + retval = read_dst(state, state->rx_tuna, 10); } else { - retval = read_dst(dst, &dst->rx_tuna[2], 8); + retval = read_dst(state, &state->rx_tuna[2], 8); } if (retval < 0) { dprintk("%s: read not successful\n", __FUNCTION__); return 0; } - if (dst->type_flags & DST_TYPE_HAS_NEWTUNE) { - if (dst->rx_tuna[9] != dst_check_sum(&dst->rx_tuna[0], 9)) { + if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { + if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { dprintk("%s: checksum failure?\n", __FUNCTION__); return 0; } } else { - if (dst->rx_tuna[9] != dst_check_sum(&dst->rx_tuna[2], 7)) { + if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) { dprintk("%s: checksum failure?\n", __FUNCTION__); return 0; } } - if (dst->rx_tuna[2] == 0 && dst->rx_tuna[3] == 0) + if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0) return 0; - dst->decode_freq = ((dst->rx_tuna[2] & 0x7f) << 8) + dst->rx_tuna[3]; + state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3]; - dst->decode_lock = 1; + state->decode_lock = 1; /* dst->decode_n1 = (dst->rx_tuna[4] << 8) + (dst->rx_tuna[5]); @@ -819,41 +696,44 @@ dst->decode_n2 = (dst->rx_tuna[8] << 8) + (dst->rx_tuna[7]); */ - dst->diseq_flags |= HAS_LOCK; + state->diseq_flags |= HAS_LOCK; /* dst->cur_jiff = jiffies; */ return 1; } -static int dst_write_tuna(struct dst_data *dst) +static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage); + +static int dst_write_tuna(struct dvb_frontend* fe) { + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; int retval; u8 reply; - dprintk("%s: type_flags 0x%x \n", __FUNCTION__, dst->type_flags); - dst->decode_freq = 0; - dst->decode_lock = dst->decode_strength = dst->decode_snr = 0; - if (dst->dst_type == DST_TYPE_IS_SAT) { - if (!(dst->diseq_flags & HAS_POWER)) - dst_set_voltage(dst, SEC_VOLTAGE_13); - } - dst->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE); - dst_i2c_enable(dst); - if (dst->type_flags & DST_TYPE_HAS_NEWTUNE) { - dst_reset8820(dst); - dst->tx_tuna[9] = dst_check_sum(&dst->tx_tuna[0], 9); - retval = write_dst(dst, &dst->tx_tuna[0], 10); + dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags); + state->decode_freq = 0; + state->decode_lock = state->decode_strength = state->decode_snr = 0; + if (state->dst_type == DST_TYPE_IS_SAT) { + if (!(state->diseq_flags & HAS_POWER)) + dst_set_voltage(fe, SEC_VOLTAGE_13); + } + state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE); + dst_i2c_enable(state); + if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { + dst_reset8820(state); + state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9); + retval = write_dst(state, &state->tx_tuna[0], 10); } else { - dst->tx_tuna[9] = dst_check_sum(&dst->tx_tuna[2], 7); - retval = write_dst(dst, &dst->tx_tuna[2], 8); + state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7); + retval = write_dst(state, &state->tx_tuna[2], 8); } if (retval < 0) { - dst_i2c_disable(dst); + dst_i2c_disable(state); dprintk("%s: write not successful\n", __FUNCTION__); return retval; } msleep(3); - retval = read_dst(dst, &reply, 1); - dst_i2c_disable(dst); + retval = read_dst(state, &reply, 1); + dst_i2c_disable(state); if (retval < 0) { dprintk("%s: read verify not successful\n", __FUNCTION__); return retval; @@ -862,395 +742,348 @@ dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, reply); return 0; } - dst->diseq_flags |= ATTEMPT_TUNE; - return dst_get_tuna(dst); -} - -static void dst_init(struct dst_data *dst) -{ - static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 }; - static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 }; - static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; - static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; - static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; - static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; - dst->inversion = INVERSION_ON; - dst->voltage = SEC_VOLTAGE_13; - dst->tone = SEC_TONE_OFF; - dst->symbol_rate = 29473000; - dst->fec = FEC_AUTO; - dst->diseq_flags = 0; - dst->k22 = 0x02; - dst->bandwidth = BANDWIDTH_7_MHZ; - dst->cur_jiff = jiffies; - if (dst->dst_type == DST_TYPE_IS_SAT) { - dst->frequency = 950000; - memcpy(dst->tx_tuna, ((dst->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_satci_tuna : ini_satfta_tuna), sizeof(ini_satfta_tuna)); - } else if (dst->dst_type == DST_TYPE_IS_TERR) { - dst->frequency = 137000000; - memcpy(dst->tx_tuna, ((dst->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_tvci_tuna : ini_tvfta_tuna), sizeof(ini_tvfta_tuna)); - } else if (dst->dst_type == DST_TYPE_IS_CABLE) { - dst->frequency = 51000000; - memcpy(dst->tx_tuna, ((dst->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_cabci_tuna : ini_cabfta_tuna), sizeof(ini_cabfta_tuna)); - } + state->diseq_flags |= ATTEMPT_TUNE; + return dst_get_tuna(state); } -struct lkup { - unsigned int cmd; - char *desc; -} looker[] = { - { - FE_GET_INFO, "FE_GET_INFO:"}, { - FE_READ_STATUS, "FE_READ_STATUS:"}, { - FE_READ_BER, "FE_READ_BER:"}, { - FE_READ_SIGNAL_STRENGTH, "FE_READ_SIGNAL_STRENGTH:"}, { - FE_READ_SNR, "FE_READ_SNR:"}, { - FE_READ_UNCORRECTED_BLOCKS, "FE_READ_UNCORRECTED_BLOCKS:"}, { - FE_SET_FRONTEND, "FE_SET_FRONTEND:"}, { - FE_GET_FRONTEND, "FE_GET_FRONTEND:"}, { - FE_SLEEP, "FE_SLEEP:"}, { - FE_INIT, "FE_INIT:"}, { - FE_SET_TONE, "FE_SET_TONE:"}, { -FE_SET_VOLTAGE, "FE_SET_VOLTAGE:"},}; +/* + * line22k0 0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00 + * line22k1 0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00 + * line22k2 0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00 + * tone 0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00 + * data 0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00 + * power_off 0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 + * power_on 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 + * Diseqc 1 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec + * Diseqc 2 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8 + * Diseqc 3 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4 + * Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0 + */ -static int dst_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) { - struct dst_data *dst = fe->data; - int retval; - /* - char *cc; - - cc = "FE_UNSUPP:"; - for(retval = 0; retval < sizeof(looker) / sizeof(looker[0]); retval++) { - if (looker[retval].cmd == cmd) { - cc = looker[retval].desc; - break; - } - } - dprintk("%s cmd %s (0x%x)\n",__FUNCTION__, cc, cmd); - */ - // printk("%s: dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, dst, dst->bt, dst->i2c); - /* should be set by attach, but just in case */ + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec }; - switch (cmd) { - case FE_GET_INFO: - { - struct dvb_frontend_info *info; - info = &dst_info_sat; - if (dst->dst_type == DST_TYPE_IS_TERR) - info = &dst_info_terr; - else if (dst->dst_type == DST_TYPE_IS_CABLE) - info = &dst_info_cable; - memcpy(arg, info, sizeof(struct dvb_frontend_info)); - break; - } - case FE_READ_STATUS: - { - fe_status_t *status = arg; - - *status = 0; - if (dst->diseq_flags & HAS_LOCK) { - dst_get_signal(dst); - if (dst->decode_lock) - *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI; - } - break; - } + if (state->dst_type == DST_TYPE_IS_TERR) + return 0; - case FE_READ_BER: - { - /* guess */ - // *(u32*) arg = dst->decode_n1; - *(u32 *) arg = 0; - return -EOPNOTSUPP; - } + if (cmd->msg_len == 0 || cmd->msg_len > 4) + return -EINVAL; + memcpy(&paket[3], cmd->msg, cmd->msg_len); + paket[7] = dst_check_sum(&paket[0], 7); + dst_command(state, paket, 8); + return 0; +} - case FE_READ_SIGNAL_STRENGTH: - { - dst_get_signal(dst); - *((u16 *) arg) = dst->decode_strength; - break; - } +static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + u8 *val; + int need_cmd; + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; - case FE_READ_SNR: - { - dst_get_signal(dst); - *((u16 *) arg) = dst->decode_snr; - break; - } + state->voltage = voltage; - case FE_READ_UNCORRECTED_BLOCKS: - { - *((u32 *) arg) = 0; /* the stv0299 can't measure BER and */ - return -EOPNOTSUPP; /* errors at the same time.... */ - } + if (state->dst_type == DST_TYPE_IS_TERR) + return 0; - case FE_SET_FRONTEND: - { - struct dvb_frontend_parameters *p = arg; - - dst_set_freq(dst, p->frequency); - dst_set_inversion(dst, p->inversion); - if (dst->dst_type == DST_TYPE_IS_SAT) { - dst_set_fec(dst, p->u.qpsk.fec_inner); - dst_set_symbolrate(dst, p->u.qpsk.symbol_rate); - } else if (dst->dst_type == DST_TYPE_IS_TERR) { - dst_set_bandwidth(dst, p->u.ofdm.bandwidth); - } else if (dst->dst_type == DST_TYPE_IS_CABLE) { - dst_set_fec(dst, p->u.qam.fec_inner); - dst_set_symbolrate(dst, p->u.qam.symbol_rate); - } - dst_write_tuna(dst); + need_cmd = 0; + val = &state->tx_tuna[0]; + val[8] &= ~0x40; + switch (voltage) { + case SEC_VOLTAGE_13: + if ((state->diseq_flags & HAS_POWER) == 0) + need_cmd = 1; + state->diseq_flags |= HAS_POWER; + break; + case SEC_VOLTAGE_18: + if ((state->diseq_flags & HAS_POWER) == 0) + need_cmd = 1; + state->diseq_flags |= HAS_POWER; + val[8] |= 0x40; + break; + case SEC_VOLTAGE_OFF: + need_cmd = 1; + state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE); + break; + default: + return -EINVAL; + } + if (need_cmd) { + dst_tone_power_cmd(state); + } + return 0; +} - break; - } +static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + u8 *val; + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; - case FE_GET_FRONTEND: - { - struct dvb_frontend_parameters *p = arg; - - - p->frequency = dst->decode_freq; - p->inversion = dst->inversion; - if (dst->dst_type == DST_TYPE_IS_SAT) { - p->u.qpsk.symbol_rate = dst->symbol_rate; - p->u.qpsk.fec_inner = dst_get_fec(dst); - } else if (dst->dst_type == DST_TYPE_IS_TERR) { - p->u.ofdm.bandwidth = dst->bandwidth; - } else if (dst->dst_type == DST_TYPE_IS_CABLE) { - p->u.qam.symbol_rate = dst->symbol_rate; - p->u.qam.fec_inner = dst_get_fec(dst); - p->u.qam.modulation = QAM_AUTO; - } - break; - } + state->tone = tone; - case FE_SLEEP: + if (state->dst_type == DST_TYPE_IS_TERR) return 0; - case FE_INIT: - dst_init(dst); - break; + val = &state->tx_tuna[0]; - case FE_DISEQC_SEND_MASTER_CMD: - { - struct dvb_diseqc_master_cmd *cmd = (struct dvb_diseqc_master_cmd *) arg; - retval = dst_set_diseqc(dst, cmd->msg, cmd->msg_len); - if (retval < 0) - return retval; - break; - } - case FE_SET_TONE: - retval = dst_set_tone(dst, (fe_sec_tone_mode_t) arg); - if (retval < 0) - return retval; + val[8] &= ~0x1; + + switch (tone) { + case SEC_TONE_OFF: break; - case FE_SET_VOLTAGE: - retval = dst_set_voltage(dst, (fe_sec_voltage_t) arg); - if (retval < 0) - return retval; + case SEC_TONE_ON: + val[8] |= 1; break; default: - return -EOPNOTSUPP; - }; - + return -EINVAL; + } + dst_tone_power_cmd(state); return 0; } -static ssize_t attr_read_type(struct device *dev, char *buf) +static int dst_init(struct dvb_frontend* fe) { - struct i2c_client *client = to_i2c_client(dev); - struct dst_data *dst = (struct dst_data *) i2c_get_clientdata(client); - return sprintf(buf, "0x%02x\n", dst->dst_type); + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 }; + static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 }; + static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; + static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; + static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; + static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; + state->inversion = INVERSION_ON; + state->voltage = SEC_VOLTAGE_13; + state->tone = SEC_TONE_OFF; + state->symbol_rate = 29473000; + state->fec = FEC_AUTO; + state->diseq_flags = 0; + state->k22 = 0x02; + state->bandwidth = BANDWIDTH_7_MHZ; + state->cur_jiff = jiffies; + if (state->dst_type == DST_TYPE_IS_SAT) { + state->frequency = 950000; + memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_satci_tuna : ini_satfta_tuna), sizeof(ini_satfta_tuna)); + } else if (state->dst_type == DST_TYPE_IS_TERR) { + state->frequency = 137000000; + memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_tvci_tuna : ini_tvfta_tuna), sizeof(ini_tvfta_tuna)); + } else if (state->dst_type == DST_TYPE_IS_CABLE) { + state->frequency = 51000000; + memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_cabci_tuna : ini_cabfta_tuna), sizeof(ini_cabfta_tuna)); + } + + return 0; } -static ssize_t attr_write_type(struct device *dev, const char *buf, size_t count) +static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct i2c_client *client = to_i2c_client(dev); - struct dst_data *dst = (struct dst_data *) i2c_get_clientdata(client); - unsigned long type; - type = simple_strtoul(buf, NULL, 0); - dst->dst_type = type & 0xff; - return strlen(buf) + 1; -} + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; -/* dst_type, "Type of DST card, 0 Satellite, 1 terrestial, 2 Cable, default driver determined"); */ -static struct device_attribute dev_attr_client_type = { - .attr = {.name = "type",.mode = S_IRUGO | S_IWUGO,.owner = THIS_MODULE}, - .show = &attr_read_type, - .store = &attr_write_type, -}; + *status = 0; + if (state->diseq_flags & HAS_LOCK) { + dst_get_signal(state); + if (state->decode_lock) + *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI; + } -static ssize_t attr_read_flags(struct device *dev, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct dst_data *dst = (struct dst_data *) i2c_get_clientdata(client); - return sprintf(buf, "0x%02x\n", dst->type_flags); + return 0; } -static ssize_t attr_write_flags(struct device *dev, const char *buf, size_t count) +static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - struct i2c_client *client = to_i2c_client(dev); - struct dst_data *dst = (struct dst_data *) i2c_get_clientdata(client); - unsigned long flags; - flags = simple_strtoul(buf, NULL, 0); - dst->type_flags = flags & 0xffffffff; - return strlen(buf) + 1; -} + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; -/* dst_type_flags, "Type flags of DST card, bitfield 1=10 byte tuner, 2=TS is 204, 4=symdiv"); */ -static struct device_attribute dev_attr_client_flags = { - .attr = {.name = "flags",.mode = S_IRUGO | S_IWUGO,.owner = THIS_MODULE}, - .show = &attr_read_flags, - .store = &attr_write_flags, -}; + dst_get_signal(state); + *strength = state->decode_strength; -static struct i2c_client client_template; + return 0; +} -static int attach_adapter(struct i2c_adapter *adapter) +static int dst_read_snr(struct dvb_frontend* fe, u16* snr) { - struct i2c_client *client; - struct dst_data *dst; - struct bt878 *bt; - struct dvb_frontend_info *info; - int ret; + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; - bt = bt878_find_by_i2c_adap(adapter); - if (!bt) - return -ENODEV; + dst_get_signal(state); + *snr = state->decode_snr; - dst = kmalloc(sizeof(struct dst_data), GFP_KERNEL); - if (dst == NULL) { - printk(KERN_INFO "%s: Out of memory.\n", __FUNCTION__); - return -ENOMEM; + return 0; +} + +static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + + dst_set_freq(state, p->frequency); + dst_set_inversion(state, p->inversion); + if (state->dst_type == DST_TYPE_IS_SAT) { + dst_set_fec(state, p->u.qpsk.fec_inner); + dst_set_symbolrate(state, p->u.qpsk.symbol_rate); + } else if (state->dst_type == DST_TYPE_IS_TERR) { + dst_set_bandwidth(state, p->u.ofdm.bandwidth); + } else if (state->dst_type == DST_TYPE_IS_CABLE) { + dst_set_fec(state, p->u.qam.fec_inner); + dst_set_symbolrate(state, p->u.qam.symbol_rate); } + dst_write_tuna(fe); + + return 0; +} + +static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; - memset(dst, 0, sizeof(*dst)); - dst->bt = bt; - dst->i2c = adapter; - if (dst_check_ci(dst) < 0) { - kfree(dst); - return -ENODEV; + p->frequency = state->decode_freq; + p->inversion = state->inversion; + if (state->dst_type == DST_TYPE_IS_SAT) { + p->u.qpsk.symbol_rate = state->symbol_rate; + p->u.qpsk.fec_inner = dst_get_fec(state); + } else if (state->dst_type == DST_TYPE_IS_TERR) { + p->u.ofdm.bandwidth = state->bandwidth; + } else if (state->dst_type == DST_TYPE_IS_CABLE) { + p->u.qam.symbol_rate = state->symbol_rate; + p->u.qam.fec_inner = dst_get_fec(state); + p->u.qam.modulation = QAM_AUTO; } - dst_init(dst); - dprintk("%s: register dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, (u32) dst, (u32) (dst->bt), (u32) (dst->i2c)); + return 0; +} + +static void dst_release(struct dvb_frontend* fe) +{ + struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops dst_dvbt_ops; +static struct dvb_frontend_ops dst_dvbs_ops; +static struct dvb_frontend_ops dst_dvbc_ops; + +struct dvb_frontend* dst_attach(const struct dst_config* config, + struct i2c_adapter* i2c, + struct bt878 *bt) +{ + struct dst_state* state = NULL; + + /* allocate memory for the internal state */ + state = (struct dst_state*) kmalloc(sizeof(struct dst_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + state->bt = bt; + + /* check if the demod is there */ + if (dst_check_ci(state) < 0) goto error; - switch (dst->dst_type) { + /* determine settings based on type */ + switch (state->dst_type) { case DST_TYPE_IS_TERR: - info = &dst_info_terr; + memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops)); break; case DST_TYPE_IS_CABLE: - info = &dst_info_cable; + memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops)); break; case DST_TYPE_IS_SAT: - info = &dst_info_sat; + memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops)); break; default: printk("dst: unknown frontend type. please report to the LinuxTV.org DVB mailinglist.\n"); - kfree(dst); - return -ENODEV; + goto error; } - if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { - kfree(dst); - return -ENOMEM; - } - - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = DST_I2C_ADDR; - - i2c_set_clientdata(client, (void *) dst); - - ret = i2c_attach_client(client); - if (ret) { - kfree(client); - kfree(dst); - return -EFAULT; - } - - BUG_ON(!dst->dvb); - - device_create_file(&client->dev, &dev_attr_client_type); - device_create_file(&client->dev, &dev_attr_client_flags); - - ret = dvb_register_frontend(dst_ioctl, dst->dvb, dst, info, THIS_MODULE); - if (ret) { - i2c_detach_client(client); - kfree(client); - kfree(dst); - return -EFAULT; - } + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; - return 0; +error: + if (state) kfree(state); + return NULL; } -static int detach_client(struct i2c_client *client) -{ - struct dst_data *state = (struct dst_data *) i2c_get_clientdata(client); - - dvb_unregister_frontend(dst_ioctl, state->dvb); +static struct dvb_frontend_ops dst_dvbt_ops = { - device_remove_file(&client->dev, &dev_attr_client_type); - device_remove_file(&client->dev, &dev_attr_client_flags); + .info = { + .name = "DST DVB-T", + .type = FE_OFDM, + .frequency_min = 137000000, + .frequency_max = 858000000, + .frequency_stepsize = 166667, + .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO + }, - i2c_detach_client(client); - BUG_ON(state->dvb); - - kfree(client); - kfree(state); - - return 0; -} + .release = dst_release, -static int command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct dst_data *state = (struct dst_data *) i2c_get_clientdata(client); + .init = dst_init, - switch (cmd) { - case FE_REGISTER: - state->dvb = (struct dvb_adapter *) arg; - break; - case FE_UNREGISTER: - state->dvb = NULL; - break; - default: - return -EOPNOTSUPP; - } - return 0; -} + .set_frontend = dst_set_frontend, + .get_frontend = dst_get_frontend, -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = "dst", - .id = I2C_DRIVERID_DVBFE_DST, - .flags = I2C_DF_NOTIFY, - .attach_adapter = attach_adapter, - .detach_client = detach_client, - .command = command, + .read_status = dst_read_status, + .read_signal_strength = dst_read_signal_strength, + .read_snr = dst_read_snr, }; -static struct i2c_client client_template = { - I2C_DEVNAME("dst"), - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, -}; +static struct dvb_frontend_ops dst_dvbs_ops = { -static int __init init_dst(void) -{ - return i2c_add_driver(&driver); -} + .info = { + .name = "DST DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 1000, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + /* . symbol_rate_tolerance = ???,*/ + .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK + }, + + .release = dst_release, + + .init = dst_init, + + .set_frontend = dst_set_frontend, + .get_frontend = dst_get_frontend, + + .read_status = dst_read_status, + .read_signal_strength = dst_read_signal_strength, + .read_snr = dst_read_snr, + + .diseqc_send_master_cmd = dst_set_diseqc, + .set_voltage = dst_set_voltage, + .set_tone = dst_set_tone, +}; -static void __exit exit_dst(void) -{ - if (i2c_del_driver(&driver)) - printk("dst: driver deregistration failed\n"); -} +static struct dvb_frontend_ops dst_dvbc_ops = { -module_init(init_dst); -module_exit(exit_dst); + .info = { + .name = "DST DVB-C", + .type = FE_QAM, + .frequency_stepsize = 62500, + .frequency_min = 51000000, + .frequency_max = 858000000, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + /* . symbol_rate_tolerance = ???,*/ + .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO + }, + + .release = dst_release, + + .init = dst_init, + + .set_frontend = dst_set_frontend, + .get_frontend = dst_get_frontend, + + .read_status = dst_read_status, + .read_signal_strength = dst_read_signal_strength, + .read_snr = dst_read_snr, +}; -MODULE_DESCRIPTION("DST DVB-S Frontend"); +MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver"); MODULE_AUTHOR("Jamie Honan"); MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(dst_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/dvb_dummy_fe.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/dvb_dummy_fe.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/dvb_dummy_fe.c 2004-12-22 10:04:35.692376786 -0800 @@ -24,244 +24,258 @@ #include #include "dvb_frontend.h" +#include "dvb_dummy_fe.h" -#define FRONTEND_NAME "dvbfe_dummy" -static int frontend_type; -module_param(frontend_type, int, 0444); -MODULE_PARM_DESC(frontend_type, "0 == DVB-S, 1 == DVB-C, 2 == DVB-T"); - -/* depending on module parameter sct deliver different infos - */ - -static struct dvb_frontend_info dvb_s_dummyfe_info = { - .name = "DVB-S dummy frontend", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 250, /* kHz for QPSK frontends */ - .frequency_tolerance = 29500, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, -/* .symbol_rate_tolerance = ???,*/ - .notifier_delay = 50, /* 1/20 s */ - .caps = FE_CAN_INVERSION_AUTO | - 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 -}; - -static struct dvb_frontend_info dvb_c_dummyfe_info = { - .name = "DVB-C dummy frontend", - .type = FE_QAM, - .frequency_stepsize = 62500, - .frequency_min = 51000000, - .frequency_max = 858000000, - .symbol_rate_min = (57840000/2)/64, /* SACLK/64 == (XIN/2)/64 */ - .symbol_rate_max = (57840000/2)/4, /* SACLK/4 */ -#if 0 - .frequency_tolerance = ???, - .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */ - .notifier_delay = ?, -#endif - .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | - FE_CAN_QAM_128 | FE_CAN_QAM_256 | - FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO -}; -static struct dvb_frontend_info dvb_t_dummyfe_info = { - .name = "DVB-T dummy frontend", - .type = FE_OFDM, - .frequency_min = 0, - .frequency_max = 863250000, - .frequency_stepsize = 62500, - /*.frequency_tolerance = */ /* FIXME: 12% of SR */ - .symbol_rate_min = 0, /* FIXME */ - .symbol_rate_max = 9360000, /* FIXME */ - .symbol_rate_tolerance = 4000, - .notifier_delay = 0, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; +struct dvb_dummy_fe_state { -struct dvb_frontend_info *frontend_info(void) -{ - switch(frontend_type) { - case 2: - return &dvb_t_dummyfe_info; - case 1: - return &dvb_c_dummyfe_info; - case 0: - default: - return &dvb_s_dummyfe_info; - } -} + struct dvb_frontend_ops ops; + struct dvb_frontend frontend; +}; -static int dvbdummyfe_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, frontend_info(), - sizeof(struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: +static int dvb_dummy_fe_read_status(struct dvb_frontend* fe, fe_status_t* status) { - fe_status_t *status = arg; *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; - break; + + return 0; } - case FE_READ_BER: +static int dvb_dummy_fe_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 *ber = (u32 *) arg; *ber = 0; - break; + return 0; } - case FE_READ_SIGNAL_STRENGTH: +static int dvb_dummy_fe_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - u8 signal = 0xff; - *((u16*) arg) = (signal << 8) | signal; - break; + *strength = 0; + return 0; } - case FE_READ_SNR: +static int dvb_dummy_fe_read_snr(struct dvb_frontend* fe, u16* snr) { - u8 snr = 0xf0; - *(u16*) arg = (snr << 8) | snr; - break; + *snr = 0; + return 0; } - case FE_READ_UNCORRECTED_BLOCKS: - *(u32*) arg = 0; - break; - - case FE_SET_FRONTEND: - break; - - case FE_GET_FRONTEND: - break; - - case FE_SLEEP: +static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + *ucblocks = 0; return 0; +} - case FE_INIT: +static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ return 0; +} - case FE_SET_TONE: - return -EOPNOTSUPP; +static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + return 0; +} - case FE_SET_VOLTAGE: +static int dvb_dummy_fe_sleep(struct dvb_frontend* fe) +{ return 0; +} - default: - return -EOPNOTSUPP; +static int dvb_dummy_fe_init(struct dvb_frontend* fe) +{ + return 0; } + +static int dvb_dummy_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ return 0; } -static struct i2c_client client_template; - -static int dvbdummyfe_attach_adapter(struct i2c_adapter *adapter) +static int dvb_dummy_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { - struct dvb_adapter *dvb; - struct i2c_client *client; - int ret; - - if ((client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)) == NULL) - return -ENOMEM; - - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; + return 0; +} - if ((ret = i2c_attach_client(client))) { - kfree(client); - return ret; +static void dvb_dummy_fe_release(struct dvb_frontend* fe) +{ + struct dvb_dummy_fe_state* state = (struct dvb_dummy_fe_state*) fe->demodulator_priv; + kfree(state); } - dvb = i2c_get_clientdata(client); - BUG_ON(!dvb); +static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops; - if ((ret = dvb_register_frontend(dvbdummyfe_ioctl, dvb, NULL, - frontend_info(), THIS_MODULE))) { - kfree(client); - return ret; - } +struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void) +{ + struct dvb_dummy_fe_state* state = NULL; - return 0; + /* allocate memory for the internal state */ + state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + memcpy(&state->ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops)); + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; } +static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; -static int dvbdummyfe_detach_client(struct i2c_client *client) +struct dvb_frontend* dvb_dummy_fe_qpsk_attach() { - struct dvb_adapter *dvb = i2c_get_clientdata(client); + struct dvb_dummy_fe_state* state = NULL; - dvb_unregister_frontend(dvbdummyfe_ioctl, dvb); - i2c_detach_client(client); - kfree(client); - return 0; + /* allocate memory for the internal state */ + state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + memcpy(&state->ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops)); + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; } -static int dvbdummyfe_command(struct i2c_client *client, - unsigned int cmd, void *arg) +static struct dvb_frontend_ops dvb_dummy_fe_qam_ops; + +struct dvb_frontend* dvb_dummy_fe_qam_attach() { - switch(cmd) { - case FE_REGISTER: - i2c_set_clientdata(client, arg); - break; - case FE_UNREGISTER: - break; - default: - return -EOPNOTSUPP; - } + struct dvb_dummy_fe_state* state = NULL; - return 0; + /* allocate memory for the internal state */ + state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + memcpy(&state->ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops)); + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; } -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = FRONTEND_NAME, - .id = I2C_DRIVERID_DVBFE_DUMMY, - .flags = I2C_DF_NOTIFY, - .attach_adapter = dvbdummyfe_attach_adapter, - .detach_client = dvbdummyfe_detach_client, - .command = dvbdummyfe_command, -}; +static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = { -static struct i2c_client client_template = { - .name = FRONTEND_NAME, - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, + .info = { + .name = "Dummy DVB-T", + .type = FE_OFDM, + .frequency_min = 0, + .frequency_max = 863250000, + .frequency_stepsize = 62500, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = dvb_dummy_fe_release, + + .init = dvb_dummy_fe_init, + .sleep = dvb_dummy_fe_sleep, + + .set_frontend = dvb_dummy_fe_set_frontend, + .get_frontend = dvb_dummy_fe_get_frontend, + + .read_status = dvb_dummy_fe_read_status, + .read_ber = dvb_dummy_fe_read_ber, + .read_signal_strength = dvb_dummy_fe_read_signal_strength, + .read_snr = dvb_dummy_fe_read_snr, + .read_ucblocks = dvb_dummy_fe_read_ucblocks, }; -static int __init init_dvbdummyfe (void) -{ - return i2c_add_driver(&driver); -} +static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = { -static void __exit exit_dvbdummyfe (void) -{ - if (i2c_del_driver(&driver)) - printk(KERN_ERR "dummyfe: driver deregistration failed.\n"); -} + .info = { + .name = "Dummy DVB-C", + .type = FE_QAM, + .frequency_stepsize = 62500, + .frequency_min = 51000000, + .frequency_max = 858000000, + .symbol_rate_min = (57840000/2)/64, /* SACLK/64 == (XIN/2)/64 */ + .symbol_rate_max = (57840000/2)/4, /* SACLK/4 */ + .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | + FE_CAN_QAM_128 | FE_CAN_QAM_256 | + FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO + }, + + .release = dvb_dummy_fe_release, + + .init = dvb_dummy_fe_init, + .sleep = dvb_dummy_fe_sleep, + + .set_frontend = dvb_dummy_fe_set_frontend, + .get_frontend = dvb_dummy_fe_get_frontend, + + .read_status = dvb_dummy_fe_read_status, + .read_ber = dvb_dummy_fe_read_ber, + .read_signal_strength = dvb_dummy_fe_read_signal_strength, + .read_snr = dvb_dummy_fe_read_snr, + .read_ucblocks = dvb_dummy_fe_read_ucblocks, +}; +static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = { -module_init(init_dvbdummyfe); -module_exit(exit_dvbdummyfe); + .info = { + .name = "Dummy DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 250, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_INVERSION_AUTO | + 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 + }, + + .release = dvb_dummy_fe_release, + + .init = dvb_dummy_fe_init, + .sleep = dvb_dummy_fe_sleep, + + .set_frontend = dvb_dummy_fe_set_frontend, + .get_frontend = dvb_dummy_fe_get_frontend, + + .read_status = dvb_dummy_fe_read_status, + .read_ber = dvb_dummy_fe_read_ber, + .read_signal_strength = dvb_dummy_fe_read_signal_strength, + .read_snr = dvb_dummy_fe_read_snr, + .read_ucblocks = dvb_dummy_fe_read_ucblocks, + .set_voltage = dvb_dummy_fe_set_voltage, + .set_tone = dvb_dummy_fe_set_tone, +}; MODULE_DESCRIPTION("DVB DUMMY Frontend"); MODULE_AUTHOR("Emard"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(dvb_dummy_fe_ofdm_attach); +EXPORT_SYMBOL(dvb_dummy_fe_qam_attach); +EXPORT_SYMBOL(dvb_dummy_fe_qpsk_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/mt312.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/mt312.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/mt312.c 2004-12-22 10:04:35.710374050 -0800 @@ -1,5 +1,5 @@ /* - Driver for Zarlink MT312 Satellite Channel Decoder + Driver for Zarlink VP310/MT312 Satellite Channel Decoder Copyright (C) 2003 Andreas Oberritter @@ -31,71 +31,52 @@ #include #include "dvb_frontend.h" +#include "mt312_priv.h" #include "mt312.h" -#define FRONTEND_NAME "dvbfe_mt312" -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG FRONTEND_NAME ": " args); \ - } while (0) +struct mt312_state { -static int debug; + struct i2c_adapter* i2c; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + struct dvb_frontend_ops ops; + + /* configuration settings */ + const struct mt312_config* config; + struct dvb_frontend frontend; -#define I2C_ADDR_MT312 0x0e -#define I2C_ADDR_SL1935 0x61 -#define I2C_ADDR_TSA5059 0x61 + u8 id; + u8 frequency; +}; + +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "mt312: " args); \ + } while (0) #define MT312_SYS_CLK 90000000UL /* 90 MHz */ #define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */ #define MT312_PLL_CLK 10000000UL /* 10 MHz */ -static struct dvb_frontend_info mt312_info = { - .name = "Zarlink MT312", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, - /*.frequency_tolerance = 29500, FIXME: binary compatibility waste? */ - .symbol_rate_min = MT312_SYS_CLK / 128, - .symbol_rate_max = MT312_SYS_CLK / 2, - /*.symbol_rate_tolerance = 500, FIXME: binary compatibility waste? 2% */ - .notifier_delay = 0, - .caps = - FE_CAN_INVERSION_AUTO | 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_MUTE_TS | - FE_CAN_RECOVER -}; - -struct mt312_state { - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; - int id; -}; - -static int mt312_read(struct i2c_adapter *i2c, - const enum mt312_reg_addr reg, void *buf, - const size_t count) +static int mt312_read(struct mt312_state* state, const enum mt312_reg_addr reg, + void *buf, const size_t count) { int ret; struct i2c_msg msg[2]; u8 regbuf[1] = { reg }; - msg[0].addr = I2C_ADDR_MT312; + msg[0].addr = state->config->demod_address; msg[0].flags = 0; msg[0].buf = regbuf; msg[0].len = 1; - msg[1].addr = I2C_ADDR_MT312; + msg[1].addr = state->config->demod_address; msg[1].flags = I2C_M_RD; msg[1].buf = buf; msg[1].len = count; - ret = i2c_transfer(i2c, msg, 2); + ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret); @@ -113,9 +94,8 @@ return 0; } -static int mt312_write(struct i2c_adapter *i2c, - const enum mt312_reg_addr reg, const void *src, - const size_t count) +static int mt312_write(struct mt312_state* state, const enum mt312_reg_addr reg, + const void *src, const size_t count) { int ret; u8 buf[count + 1]; @@ -132,12 +112,12 @@ buf[0] = reg; memcpy(&buf[1], src, count); - msg.addr = I2C_ADDR_MT312; + msg.addr = state->config->demod_address; msg.flags = 0; msg.buf = buf; msg.len = count + 1; - ret = i2c_transfer(i2c, &msg, 1); + ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) { dprintk("%s: ret == %d\n", __FUNCTION__, ret); @@ -147,123 +127,136 @@ return 0; } -static inline int mt312_readreg(struct i2c_adapter *i2c, +static inline int mt312_readreg(struct mt312_state* state, const enum mt312_reg_addr reg, u8 * val) { - return mt312_read(i2c, reg, val, 1); + return mt312_read(state, reg, val, 1); } -static inline int mt312_writereg(struct i2c_adapter *i2c, +static inline int mt312_writereg(struct mt312_state* state, const enum mt312_reg_addr reg, const u8 val) { - return mt312_write(i2c, reg, &val, 1); + return mt312_write(state, reg, &val, 1); } -static int mt312_pll_write(struct i2c_adapter *i2c, const u8 addr, - u8 * buf, const u8 len) +static inline u32 mt312_div(u32 a, u32 b) +{ + return (a + (b / 2)) / b; +} + +static int mt312_reset(struct mt312_state* state, const u8 full) +{ + return mt312_writereg(state, RESET, full ? 0x80 : 0x40); +} + +static int mt312_get_inversion(struct mt312_state* state, + fe_spectral_inversion_t *i) { int ret; - struct i2c_msg msg; + u8 vit_mode; - msg.addr = addr; - msg.flags = 0; - msg.buf = buf; - msg.len = len; + if ((ret = mt312_readreg(state, VIT_MODE, &vit_mode)) < 0) + return ret; + + if (vit_mode & 0x80) /* auto inversion was used */ + *i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF; + + return 0; +} + +static int mt312_get_symbol_rate(struct mt312_state* state, u32 *sr) +{ + int ret; + u8 sym_rate_h; + u8 dec_ratio; + u16 sym_rat_op; + u16 monitor; + u8 buf[2]; - if ((ret = mt312_writereg(i2c, GPP_CTRL, 0x40)) < 0) + if ((ret = mt312_readreg(state, SYM_RATE_H, &sym_rate_h)) < 0) return ret; - if ((ret = i2c_transfer(i2c, &msg, 1)) != 1) - printk(KERN_ERR "%s: i/o error (ret == %d)\n", __FUNCTION__, ret); + if (sym_rate_h & 0x80) { /* symbol rate search was used */ + if ((ret = mt312_writereg(state, MON_CTRL, 0x03)) < 0) + return ret; - if ((ret = mt312_writereg(i2c, GPP_CTRL, 0x00)) < 0) + if ((ret = mt312_read(state, MONITOR_H, buf, sizeof(buf))) < 0) return ret; - return 0; + monitor = (buf[0] << 8) | buf[1]; + + dprintk(KERN_DEBUG "sr(auto) = %u\n", + mt312_div(monitor * 15625, 4)); + } else { + if ((ret = mt312_writereg(state, MON_CTRL, 0x05)) < 0) + return ret; + + if ((ret = mt312_read(state, MONITOR_H, buf, sizeof(buf))) < 0) + return ret; + + dec_ratio = ((buf[0] >> 5) & 0x07) * 32; + + if ((ret = mt312_read(state, SYM_RAT_OP_H, buf, sizeof(buf))) < 0) + return ret; + + sym_rat_op = (buf[0] << 8) | buf[1]; + + dprintk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n", + sym_rat_op, dec_ratio); + dprintk(KERN_DEBUG "*sr(manual) = %lu\n", + (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) * + 2) - dec_ratio); } -static inline u32 mt312_div(u32 a, u32 b) -{ - return (a + (b / 2)) / b; + return 0; } -static int sl1935_set_tv_freq(struct i2c_adapter *i2c, u32 freq, u32 sr) +static int mt312_get_code_rate(struct mt312_state* state, fe_code_rate_t *cr) { - /* 155 uA, Baseband Path B */ - u8 buf[4] = { 0x00, 0x00, 0x80, 0x00 }; + const fe_code_rate_t fec_tab[8] = + { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8, + FEC_AUTO, FEC_AUTO }; - u8 exp; - u32 ref; - u32 div; - - if (sr < 10000000) { /* 1-10 MSym/s: ratio 2 ^ 3 */ - exp = 3; - buf[2] |= 0x40; /* 690 uA */ - } else if (sr < 15000000) { /* 10-15 MSym/s: ratio 2 ^ 4 */ - exp = 4; - buf[2] |= 0x20; /* 330 uA */ - } else { /* 15-45 MSym/s: ratio 2 ^ 7 */ - exp = 7; - buf[3] |= 0x08; /* Baseband Path A */ + int ret; + u8 fec_status; + + if ((ret = mt312_readreg(state, FEC_STATUS, &fec_status)) < 0) + return ret; + + *cr = fec_tab[(fec_status >> 4) & 0x07]; + + return 0; } - div = mt312_div(MT312_PLL_CLK, 1 << exp); - ref = mt312_div(freq * 1000, div); - mt312_info.frequency_stepsize = mt312_div(div, 1000); - buf[0] = (ref >> 8) & 0x7f; - buf[1] = (ref >> 0) & 0xff; - buf[2] |= (exp - 1); - if (freq < 1550000) - buf[3] |= 0x10; - dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0], - buf[1], buf[2], buf[3]); - return mt312_pll_write(i2c, I2C_ADDR_SL1935, buf, sizeof(buf)); -} -static int tsa5059_set_tv_freq(struct i2c_adapter *i2c, u32 freq, u32 sr) -{ - u8 buf[4]; - u32 ref = mt312_div(freq, 125); - buf[0] = (ref >> 8) & 0x7f; - buf[1] = (ref >> 0) & 0xff; - buf[2] = 0x84 | ((ref >> 10) & 0x60); - buf[3] = 0x80; - if (freq < 1550000) - buf[3] |= 0x02; - dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0], - buf[1], buf[2], buf[3]); - return mt312_pll_write(i2c, I2C_ADDR_TSA5059, buf, sizeof(buf)); -} -static int mt312_reset(struct i2c_adapter *i2c, const u8 full) -{ - return mt312_writereg(i2c, RESET, full ? 0x80 : 0x40); -} -static int mt312_initfe(struct mt312_state *state, u8 pll) + + +static int mt312_initfe(struct dvb_frontend* fe) { - struct i2c_adapter *i2c = state->i2c; + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[2]; /* wake up */ - if ((ret = mt312_writereg(i2c, CONFIG, (pll == 60 ? 0x88 : 0x8c))) < 0) + if ((ret = mt312_writereg(state, CONFIG, (state->frequency == 60 ? 0x88 : 0x8c))) < 0) return ret; /* wait at least 150 usec */ udelay(150); /* full reset */ - if ((ret = mt312_reset(i2c, 1)) < 0) + if ((ret = mt312_reset(state, 1)) < 0) return ret; // Per datasheet, write correct values. 09/28/03 ACCJr. @@ -271,56 +264,63 @@ { u8 buf_def[8]={0x14, 0x12, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00}; - if ((ret = mt312_write(i2c, VIT_SETUP, buf_def, sizeof(buf_def))) < 0) + if ((ret = mt312_write(state, VIT_SETUP, buf_def, sizeof(buf_def))) < 0) return ret; } /* SYS_CLK */ - buf[0] = mt312_div((pll == 60 ? MT312_LPOWER_SYS_CLK : MT312_SYS_CLK) * 2, 1000000); + buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK : MT312_SYS_CLK) * 2, 1000000); /* DISEQC_RATIO */ buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4); - if ((ret = mt312_write(i2c, SYS_CLK, buf, sizeof(buf))) < 0) + if ((ret = mt312_write(state, SYS_CLK, buf, sizeof(buf))) < 0) return ret; - if ((ret = mt312_writereg(i2c, SNR_THS_HIGH, 0x32)) < 0) + if ((ret = mt312_writereg(state, SNR_THS_HIGH, 0x32)) < 0) return ret; - if ((ret = mt312_writereg(i2c, OP_CTRL, 0x53)) < 0) + if ((ret = mt312_writereg(state, OP_CTRL, 0x53)) < 0) return ret; /* TS_SW_LIM */ buf[0] = 0x8c; buf[1] = 0x98; - if ((ret = mt312_write(i2c, TS_SW_LIM_L, buf, sizeof(buf))) < 0) + if ((ret = mt312_write(state, TS_SW_LIM_L, buf, sizeof(buf))) < 0) return ret; - if ((ret = mt312_writereg(i2c, CS_SW_LIM, 0x69)) < 0) + if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0) return ret; + if (state->config->pll_init) { + mt312_writereg(state, GPP_CTRL, 0x40); + state->config->pll_init(fe); + mt312_writereg(state, GPP_CTRL, 0x00); + } + return 0; } -static int mt312_send_master_cmd(struct i2c_adapter *i2c, - const struct dvb_diseqc_master_cmd *c) +static int mt312_send_master_cmd(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd *c) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 diseqc_mode; if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg))) return -EINVAL; - if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0) + if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0) return ret; if ((ret = - mt312_write(i2c, (0x80 | DISEQC_INSTR), c->msg, c->msg_len)) < 0) + mt312_write(state, (0x80 | DISEQC_INSTR), c->msg, c->msg_len)) < 0) return ret; if ((ret = - mt312_writereg(i2c, DISEQC_MODE, + mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40) | ((c->msg_len - 1) << 3) | 0x04)) < 0) return ret; @@ -328,21 +328,15 @@ /* set DISEQC_MODE[2:0] to zero if a return message is expected */ if (c->msg[0] & 0x02) if ((ret = - mt312_writereg(i2c, DISEQC_MODE, (diseqc_mode & 0x40))) < 0) + mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40))) < 0) return ret; return 0; } -static int mt312_recv_slave_reply(struct i2c_adapter *i2c, - struct dvb_diseqc_slave_reply *r) -{ - /* TODO */ - return -EOPNOTSUPP; -} - -static int mt312_send_burst(struct i2c_adapter *i2c, const fe_sec_mini_cmd_t c) +static int mt312_send_burst(struct dvb_frontend* fe, const fe_sec_mini_cmd_t c) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; const u8 mini_tab[2] = { 0x02, 0x03 }; int ret; @@ -351,19 +345,20 @@ if (c > SEC_MINI_B) return -EINVAL; - if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0) + if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0) return ret; if ((ret = - mt312_writereg(i2c, DISEQC_MODE, + mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40) | mini_tab[c])) < 0) return ret; return 0; } -static int mt312_set_tone(struct i2c_adapter *i2c, const fe_sec_tone_mode_t t) +static int mt312_set_tone(struct dvb_frontend* fe, const fe_sec_tone_mode_t t) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; const u8 tone_tab[2] = { 0x01, 0x00 }; int ret; @@ -372,36 +367,37 @@ if (t > SEC_TONE_OFF) return -EINVAL; - if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0) + if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0) return ret; if ((ret = - mt312_writereg(i2c, DISEQC_MODE, + mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40) | tone_tab[t])) < 0) return ret; return 0; } -static int mt312_set_voltage(struct i2c_adapter *i2c, const fe_sec_voltage_t v) +static int mt312_set_voltage(struct dvb_frontend* fe, const fe_sec_voltage_t v) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; const u8 volt_tab[3] = { 0x00, 0x40, 0x00 }; if (v > SEC_VOLTAGE_OFF) return -EINVAL; - return mt312_writereg(i2c, DISEQC_MODE, volt_tab[v]); + return mt312_writereg(state, DISEQC_MODE, volt_tab[v]); } -static int mt312_read_status(struct mt312_state *state, fe_status_t *s) +static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s) { - struct i2c_adapter *i2c = state->i2c; + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; - u8 status[3], vit_mode; + u8 status[3]; *s = 0; - if ((ret = mt312_read(i2c, QPSK_STAT_H, status, sizeof(status))) < 0) + if ((ret = mt312_read(state, QPSK_STAT_H, status, sizeof(status))) < 0) return ret; dprintk(KERN_DEBUG "QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]); @@ -417,26 +413,16 @@ if (status[0] & 0x01) *s |= FE_HAS_LOCK; /* qpsk lock */ - // VP310 doesn't have AUTO, so we "implement it here" ACCJr - if ((state->id == ID_VP310) && !(status[0] & 0x01)) { - if ((ret = mt312_readreg(i2c, VIT_MODE, &vit_mode)) < 0) - return ret; - vit_mode ^= 0x40; - if ((ret = mt312_writereg(i2c, VIT_MODE, vit_mode)) < 0) - return ret; - if ((ret = mt312_writereg(i2c, GO, 0x01)) < 0) - return ret; - } - return 0; } -static int mt312_read_bercnt(struct i2c_adapter *i2c, u32 *ber) +static int mt312_read_ber(struct dvb_frontend* fe, u32 *ber) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[3]; - if ((ret = mt312_read(i2c, RS_BERCNT_H, buf, 3)) < 0) + if ((ret = mt312_read(state, RS_BERCNT_H, buf, 3)) < 0) return ret; *ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) * 64; @@ -444,14 +430,15 @@ return 0; } -static int mt312_read_agc(struct i2c_adapter *i2c, u16 *signal_strength) +static int mt312_read_signal_strength(struct dvb_frontend* fe, u16 *signal_strength) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[3]; u16 agc; s16 err_db; - if ((ret = mt312_read(i2c, AGC_H, buf, sizeof(buf))) < 0) + if ((ret = mt312_read(state, AGC_H, buf, sizeof(buf))) < 0) return ret; agc = (buf[0] << 6) | (buf[1] >> 2); @@ -464,12 +451,13 @@ return 0; } -static int mt312_read_snr(struct i2c_adapter *i2c, u16 *snr) +static int mt312_read_snr(struct dvb_frontend* fe, u16 *snr) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[2]; - if ((ret = mt312_read(i2c, M_SNR_H, &buf, sizeof(buf))) < 0) + if ((ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf))) < 0) return ret; *snr = 0xFFFF - ((((buf[0] & 0x7f) << 8) | buf[1]) << 1); @@ -477,12 +465,13 @@ return 0; } -static int mt312_read_ubc(struct i2c_adapter *i2c, u32 *ubc) +static int mt312_read_ucblocks(struct dvb_frontend* fe, u32 *ubc) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[2]; - if ((ret = mt312_read(i2c, RS_UBC_H, &buf, sizeof(buf))) < 0) + if ((ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf))) < 0) return ret; *ubc = (buf[0] << 8) | buf[1]; @@ -490,10 +479,10 @@ return 0; } -static int mt312_set_frontend(struct mt312_state *state, - const struct dvb_frontend_parameters *p) +static int mt312_set_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *p) { - struct i2c_adapter *i2c = state->i2c; + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[5], config_val; u16 sr; @@ -502,20 +491,18 @@ { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f }; const u8 inv_tab[3] = { 0x00, 0x40, 0x80 }; - int (*set_tv_freq)(struct i2c_adapter *i2c, u32 freq, u32 sr); - dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency); - if ((p->frequency < mt312_info.frequency_min) - || (p->frequency > mt312_info.frequency_max)) + if ((p->frequency < fe->ops->info.frequency_min) + || (p->frequency > fe->ops->info.frequency_max)) return -EINVAL; if ((p->inversion < INVERSION_OFF) - || (p->inversion > INVERSION_AUTO)) + || (p->inversion > INVERSION_ON)) return -EINVAL; - if ((p->u.qpsk.symbol_rate < mt312_info.symbol_rate_min) - || (p->u.qpsk.symbol_rate > mt312_info.symbol_rate_max)) + if ((p->u.qpsk.symbol_rate < fe->ops->info.symbol_rate_min) + || (p->u.qpsk.symbol_rate > fe->ops->info.symbol_rate_max)) return -EINVAL; if ((p->u.qpsk.fec_inner < FEC_NONE) @@ -530,31 +517,36 @@ case ID_VP310: // For now we will do this only for the VP310. // It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03 - if ((ret = mt312_readreg(i2c, CONFIG, &config_val) < 0)) + if ((ret = mt312_readreg(state, CONFIG, &config_val) < 0)) return ret; if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz { - if ((config_val & 0x0c) == 0x08) //We are running 60MHz - if ((ret = mt312_initfe(state, (u8) 90)) < 0) + if ((config_val & 0x0c) == 0x08) { //We are running 60MHz + state->frequency = 90; + if ((ret = mt312_initfe(fe)) < 0) return ret; } + } else { - if ((config_val & 0x0c) == 0x0C) //We are running 90MHz - if ((ret = mt312_initfe(state, (u8) 60)) < 0) + if ((config_val & 0x0c) == 0x0C) { //We are running 90MHz + state->frequency = 60; + if ((ret = mt312_initfe(fe)) < 0) return ret; } - set_tv_freq = tsa5059_set_tv_freq; + } break; + case ID_MT312: - set_tv_freq = sl1935_set_tv_freq; break; + default: return -EINVAL; } - if ((ret = set_tv_freq(i2c, p->frequency, p->u.qpsk.symbol_rate)) < 0) - return ret; + mt312_writereg(state, GPP_CTRL, 0x40); + state->config->pll_set(fe, p); + mt312_writereg(state, GPP_CTRL, 0x00); /* sr = (u16)(sr * 256.0 / 1000000.0) */ sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625); @@ -575,333 +567,182 @@ /* GO */ buf[4] = 0x01; - if ((ret = mt312_write(i2c, SYM_RATE_H, buf, sizeof(buf))) < 0) + if ((ret = mt312_write(state, SYM_RATE_H, buf, sizeof(buf))) < 0) return ret; - mt312_reset(i2c, 0); + mt312_reset(state, 0); return 0; } -static int mt312_get_inversion(struct i2c_adapter *i2c, - fe_spectral_inversion_t * i) -{ - int ret; - u8 vit_mode; - - if ((ret = mt312_readreg(i2c, VIT_MODE, &vit_mode)) < 0) - return ret; - - if (vit_mode & 0x80) /* auto inversion was used */ - *i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF; - - return 0; -} - -static int mt312_get_symbol_rate(struct i2c_adapter *i2c, u32 *sr) -{ - int ret; - u8 sym_rate_h; - u8 dec_ratio; - u16 sym_rat_op; - u16 monitor; - u8 buf[2]; - - if ((ret = mt312_readreg(i2c, SYM_RATE_H, &sym_rate_h)) < 0) - return ret; - - if (sym_rate_h & 0x80) { /* symbol rate search was used */ - if ((ret = mt312_writereg(i2c, MON_CTRL, 0x03)) < 0) - return ret; - - if ((ret = mt312_read(i2c, MONITOR_H, buf, sizeof(buf))) < 0) - return ret; - - monitor = (buf[0] << 8) | buf[1]; - - dprintk(KERN_DEBUG "sr(auto) = %u\n", - mt312_div(monitor * 15625, 4)); - } else { - if ((ret = mt312_writereg(i2c, MON_CTRL, 0x05)) < 0) - return ret; - - if ((ret = mt312_read(i2c, MONITOR_H, buf, sizeof(buf))) < 0) - return ret; - - dec_ratio = ((buf[0] >> 5) & 0x07) * 32; - - if ((ret = mt312_read(i2c, SYM_RAT_OP_H, buf, sizeof(buf))) < 0) - return ret; - - sym_rat_op = (buf[0] << 8) | buf[1]; - - dprintk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n", - sym_rat_op, dec_ratio); - dprintk(KERN_DEBUG "*sr(manual) = %lu\n", - (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) * - 2) - dec_ratio); - } - - return 0; -} - -static int mt312_get_code_rate(struct i2c_adapter *i2c, fe_code_rate_t *cr) -{ - const fe_code_rate_t fec_tab[8] = - { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8, - FEC_AUTO, FEC_AUTO }; - - int ret; - u8 fec_status; - - if ((ret = mt312_readreg(i2c, FEC_STATUS, &fec_status)) < 0) - return ret; - - *cr = fec_tab[(fec_status >> 4) & 0x07]; - - return 0; -} - -static int mt312_get_frontend(struct i2c_adapter *i2c, +static int mt312_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; - if ((ret = mt312_get_inversion(i2c, &p->inversion)) < 0) + if ((ret = mt312_get_inversion(state, &p->inversion)) < 0) return ret; - if ((ret = mt312_get_symbol_rate(i2c, &p->u.qpsk.symbol_rate)) < 0) + if ((ret = mt312_get_symbol_rate(state, &p->u.qpsk.symbol_rate)) < 0) return ret; - if ((ret = mt312_get_code_rate(i2c, &p->u.qpsk.fec_inner)) < 0) + if ((ret = mt312_get_code_rate(state, &p->u.qpsk.fec_inner)) < 0) return ret; return 0; } -static int mt312_sleep(struct i2c_adapter *i2c) +static int mt312_sleep(struct dvb_frontend* fe) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 config; /* reset all registers to defaults */ - if ((ret = mt312_reset(i2c, 1)) < 0) + if ((ret = mt312_reset(state, 1)) < 0) return ret; - if ((ret = mt312_readreg(i2c, CONFIG, &config)) < 0) + if ((ret = mt312_readreg(state, CONFIG, &config)) < 0) return ret; /* enter standby */ - if ((ret = mt312_writereg(i2c, CONFIG, config & 0x7f)) < 0) + if ((ret = mt312_writereg(state, CONFIG, config & 0x7f)) < 0) return ret; return 0; } -static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct mt312_state *state = fe->data; - struct i2c_adapter *i2c = state->i2c; - - switch (cmd) { - case FE_GET_INFO: - memcpy(arg, &mt312_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_DISEQC_RESET_OVERLOAD: - return -EOPNOTSUPP; - - case FE_DISEQC_SEND_MASTER_CMD: - return mt312_send_master_cmd(i2c, arg); - - case FE_DISEQC_RECV_SLAVE_REPLY: - if (state->id == ID_MT312) - return mt312_recv_slave_reply(i2c, arg); - else - return -EOPNOTSUPP; - - case FE_DISEQC_SEND_BURST: - return mt312_send_burst(i2c, (fe_sec_mini_cmd_t) arg); - - case FE_SET_TONE: - return mt312_set_tone(i2c, (fe_sec_tone_mode_t) arg); - - case FE_SET_VOLTAGE: - return mt312_set_voltage(i2c, (fe_sec_voltage_t) arg); - - case FE_ENABLE_HIGH_LNB_VOLTAGE: - return -EOPNOTSUPP; - - case FE_READ_STATUS: - return mt312_read_status(state, arg); - - case FE_READ_BER: - return mt312_read_bercnt(i2c, arg); - - case FE_READ_SIGNAL_STRENGTH: - return mt312_read_agc(i2c, arg); - - case FE_READ_SNR: - return mt312_read_snr(i2c, arg); - - case FE_READ_UNCORRECTED_BLOCKS: - return mt312_read_ubc(i2c, arg); - - case FE_SET_FRONTEND: - return mt312_set_frontend(state, arg); - - case FE_GET_FRONTEND: - return mt312_get_frontend(i2c, arg); - - case FE_GET_EVENT: - return -EOPNOTSUPP; - - case FE_SLEEP: - return mt312_sleep(i2c); - - case FE_INIT: - /* For the VP310 we should run at 60MHz when ever possible. - * It should be better to run the mt312 ar lower speed when - * ever possible, but tunning will be slower. ACCJr 09/29/03 - */ - if (state->id == ID_MT312) - return mt312_initfe(state, (u8) 90); - else - return mt312_initfe(state, (u8) 60); - - case FE_GET_TUNE_SETTINGS: +static int mt312_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; fesettings->min_delay_ms = 50; fesettings->step_size = 0; fesettings->max_drift = 0; return 0; } - default: - return -ENOIOCTLCMD; - } - - return 0; +static void mt312_release(struct dvb_frontend* fe) +{ + struct mt312_state* state = (struct mt312_state*) fe->demodulator_priv; + kfree(state); } -static struct i2c_client client_template; +static struct dvb_frontend_ops vp310_mt312_ops; -static int mt312_attach_adapter(struct i2c_adapter *adapter) +struct dvb_frontend* vp310_attach(const struct mt312_config* config, + struct i2c_adapter* i2c) { - struct mt312_state *state; - struct i2c_client *client; - int ret; - u8 id; - - dprintk("Trying to attach to adapter 0x%x:%s.\n", - adapter->id, adapter->name); - - if (mt312_readreg(adapter, ID, &id) < 0) - return -ENODEV; - - if ((id != ID_VP310) && (id != ID_MT312)) - return -ENODEV; - - if ( !(state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL)) ) - return -ENOMEM; - - memset(state, 0, sizeof(struct mt312_state)); - state->i2c = adapter; - state->id = id; - - if ( !(client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)) ) { - kfree(state); - return -ENOMEM; - } + struct mt312_state* state = NULL; - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = I2C_ADDR_MT312; - i2c_set_clientdata(client, state); + /* allocate memory for the internal state */ + state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); + strcpy(state->ops.info.name, "Zarlink VP310 DVB-S"); + + /* check if the demod is there */ + if (mt312_readreg(state, ID, &state->id) < 0) + goto error; + if (state->id != ID_VP310) { + goto error; + } + + /* create dvb_frontend */ + state->frequency = 90; + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; - if ((ret = i2c_attach_client(client))) { - kfree(client); +error: + if (state) kfree(state); - return ret; - } - - BUG_ON(!state->dvb); - - if ((ret = dvb_register_frontend(mt312_ioctl, state->dvb, state, - &mt312_info, THIS_MODULE))) { - i2c_detach_client(client); - kfree(client); - kfree(state); - return ret; - } - - return 0; + return NULL; } -static int mt312_detach_client(struct i2c_client *client) +struct dvb_frontend* mt312_attach(const struct mt312_config* config, + struct i2c_adapter* i2c) { - struct mt312_state *state = i2c_get_clientdata(client); + struct mt312_state* state = NULL; - dprintk ("%s\n", __FUNCTION__); + /* allocate memory for the internal state */ + state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), GFP_KERNEL); + if (state == NULL) + goto error; - dvb_unregister_frontend (mt312_ioctl, state->dvb); - i2c_detach_client(client); - BUG_ON(state->dvb); - kfree(client); - kfree(state); - return 0; -} + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); + strcpy(state->ops.info.name, "Zarlink MT312 DVB-S"); -static int mt312_command (struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct mt312_state *state = i2c_get_clientdata(client); + /* check if the demod is there */ + if (mt312_readreg(state, ID, &state->id) < 0) + goto error; + if (state->id != ID_MT312) { + goto error; +} - dprintk ("%s\n", __FUNCTION__); + /* create dvb_frontend */ + state->frequency = 60; + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; - switch (cmd) { - case FE_REGISTER: - state->dvb = arg; - break; - case FE_UNREGISTER: - state->dvb = NULL; - break; - default: - return -EOPNOTSUPP; - } - return 0; +error: + if (state) + kfree(state); + return NULL; } -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = FRONTEND_NAME, - .id = I2C_DRIVERID_DVBFE_MT312, - .flags = I2C_DF_NOTIFY, - .attach_adapter = mt312_attach_adapter, - .detach_client = mt312_detach_client, - .command = mt312_command, -}; +static struct dvb_frontend_ops vp310_mt312_ops = { -static struct i2c_client client_template = { - .name = FRONTEND_NAME, - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, + .info = { + .name = "Zarlink ???? DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, + .symbol_rate_min = MT312_SYS_CLK / 128, + .symbol_rate_max = MT312_SYS_CLK / 2, + .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_MUTE_TS | + FE_CAN_RECOVER + }, + + .release = mt312_release, + + .init = mt312_initfe, + .sleep = mt312_sleep, + + .set_frontend = mt312_set_frontend, + .get_frontend = mt312_get_frontend, + .get_tune_settings = mt312_get_tune_settings, + + .read_status = mt312_read_status, + .read_ber = mt312_read_ber, + .read_signal_strength = mt312_read_signal_strength, + .read_snr = mt312_read_snr, + .read_ucblocks = mt312_read_ucblocks, + + .diseqc_send_master_cmd = mt312_send_master_cmd, + .diseqc_send_burst = mt312_send_burst, + .set_tone = mt312_set_tone, + .set_voltage = mt312_set_voltage, }; -static int __init mt312_module_init(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit mt312_module_exit(void) -{ - if (i2c_del_driver(&driver)) - printk(KERN_ERR "mt312: driver deregistration failed.\n"); -} - -module_init(mt312_module_init); -module_exit(mt312_module_exit); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("MT312 Satellite Channel Decoder Driver"); +MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver"); MODULE_AUTHOR("Andreas Oberritter "); MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(mt312_attach); +EXPORT_SYMBOL(vp310_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/mt312.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/mt312.h 2004-12-22 09:07:08.886370946 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/mt312.h 2004-12-22 10:04:35.714373442 -0800 @@ -1,5 +1,5 @@ /* - Driver for Zarlink MT312 QPSK Frontend + Driver for Zarlink MT312 Satellite Channel Decoder Copyright (C) 2003 Andreas Oberritter @@ -18,145 +18,30 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + References: + http://products.zarlink.com/product_profiles/MT312.htm + http://products.zarlink.com/product_profiles/SL1935.htm */ -#ifndef _DVB_FRONTENDS_MT312 -#define _DVB_FRONTENDS_MT312 +#ifndef MT312_H +#define MT312_H -enum mt312_reg_addr { - QPSK_INT_H = 0, - QPSK_INT_M = 1, - QPSK_INT_L = 2, - FEC_INT = 3, - QPSK_STAT_H = 4, - QPSK_STAT_L = 5, - FEC_STATUS = 6, - LNB_FREQ_H = 7, - LNB_FREQ_L = 8, - M_SNR_H = 9, - M_SNR_L = 10, - VIT_ERRCNT_H = 11, - VIT_ERRCNT_M = 12, - VIT_ERRCNT_L = 13, - RS_BERCNT_H = 14, - RS_BERCNT_M = 15, - RS_BERCNT_L = 16, - RS_UBC_H = 17, - RS_UBC_L = 18, - SIG_LEVEL = 19, - GPP_CTRL = 20, - RESET = 21, - DISEQC_MODE = 22, - SYM_RATE_H = 23, - SYM_RATE_L = 24, - VIT_MODE = 25, - QPSK_CTRL = 26, - GO = 27, - IE_QPSK_H = 28, - IE_QPSK_M = 29, - IE_QPSK_L = 30, - IE_FEC = 31, - QPSK_STAT_EN = 32, - FEC_STAT_EN = 33, - SYS_CLK = 34, - DISEQC_RATIO = 35, - DISEQC_INSTR = 36, - FR_LIM = 37, - FR_OFF = 38, - AGC_CTRL = 39, - AGC_INIT = 40, - AGC_REF = 41, - AGC_MAX = 42, - AGC_MIN = 43, - AGC_LK_TH = 44, - TS_AGC_LK_TH = 45, - AGC_PWR_SET = 46, - QPSK_MISC = 47, - SNR_THS_LOW = 48, - SNR_THS_HIGH = 49, - TS_SW_RATE = 50, - TS_SW_LIM_L = 51, - TS_SW_LIM_H = 52, - CS_SW_RATE_1 = 53, - CS_SW_RATE_2 = 54, - CS_SW_RATE_3 = 55, - CS_SW_RATE_4 = 56, - CS_SW_LIM = 57, - TS_LPK = 58, - TS_LPK_M = 59, - TS_LPK_L = 60, - CS_KPROP_H = 61, - CS_KPROP_L = 62, - CS_KINT_H = 63, - CS_KINT_L = 64, - QPSK_SCALE = 65, - TLD_OUTCLK_TH = 66, - TLD_INCLK_TH = 67, - FLD_TH = 68, - PLD_OUTLK3 = 69, - PLD_OUTLK2 = 70, - PLD_OUTLK1 = 71, - PLD_OUTLK0 = 72, - PLD_INLK3 = 73, - PLD_INLK2 = 74, - PLD_INLK1 = 75, - PLD_INLK0 = 76, - PLD_ACC_TIME = 77, - SWEEP_PAR = 78, - STARTUP_TIME = 79, - LOSSLOCK_TH = 80, - FEC_LOCK_TM = 81, - LOSSLOCK_TM = 82, - VIT_ERRPER_H = 83, - VIT_ERRPER_M = 84, - VIT_ERRPER_L = 85, - VIT_SETUP = 86, - VIT_REF0 = 87, - VIT_REF1 = 88, - VIT_REF2 = 89, - VIT_REF3 = 90, - VIT_REF4 = 91, - VIT_REF5 = 92, - VIT_REF6 = 93, - VIT_MAXERR = 94, - BA_SETUPT = 95, - OP_CTRL = 96, - FEC_SETUP = 97, - PROG_SYNC = 98, - AFC_SEAR_TH = 99, - CSACC_DIF_TH = 100, - QPSK_LK_CT = 101, - QPSK_ST_CT = 102, - MON_CTRL = 103, - QPSK_RESET = 104, - QPSK_TST_CT = 105, - QPSK_TST_ST = 106, - TEST_R = 107, - AGC_H = 108, - AGC_M = 109, - AGC_L = 110, - FREQ_ERR1_H = 111, - FREQ_ERR1_M = 112, - FREQ_ERR1_L = 113, - FREQ_ERR2_H = 114, - FREQ_ERR2_L = 115, - SYM_RAT_OP_H = 116, - SYM_RAT_OP_L = 117, - DESEQC2_INT = 118, - DISEQC2_STAT = 119, - DISEQC2_FIFO = 120, - DISEQC2_CTRL1 = 121, - DISEQC2_CTRL2 = 122, - MONITOR_H = 123, - MONITOR_L = 124, - TEST_MODE = 125, - ID = 126, - CONFIG = 127 -}; +#include -enum mt312_model_id { - ID_VP310 = 1, - ID_MT312 = 3 +struct mt312_config +{ + /* the demodulator's i2c address */ + u8 demod_address; + + /* PLL maintenance */ + int (*pll_init)(struct dvb_frontend* fe); + int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; -#endif /* DVB_FRONTENDS_MT312 */ +extern struct dvb_frontend* mt312_attach(const struct mt312_config* config, + struct i2c_adapter* i2c); + +extern struct dvb_frontend* vp310_attach(const struct mt312_config* config, + struct i2c_adapter* i2c); + +#endif // MT312_H Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/mt352.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/mt352.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/mt352.c 2004-12-22 10:04:35.730371010 -0800 @@ -37,438 +37,88 @@ #include #include "dvb_frontend.h" +#include "mt352_priv.h" #include "mt352.h" -#define FRONTEND_NAME "dvbfe_mt352" +struct mt352_state { -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG FRONTEND_NAME ": " args); \ - } while (0) + struct i2c_adapter* i2c; -static int debug; -#define MAX_CARDS 4 -static int force_card[MAX_CARDS] = { -1, -1, -1, -1 }; -static int force_card_count = 0; + struct dvb_frontend_ops ops; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -module_param_array(force_card, int, &force_card_count, 0444); -MODULE_PARM_DESC(force_card, "Forces the type of each attached mt352 frontend.\n\t" - "If your card is not autodetected, then you must specify its type here.\n\t" - "Valid card types are: 0 == AVDVBT771, 1 == TUA6034, 2 == TDTC9251DH01C,\n\t" - "3 == DVICO FusionHDTV DVB-T1, 4 == DVICO FusionHDTV DVB-T Lite."); + /* configuration settings */ + const struct mt352_config* config; -struct mt352_state { - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; - struct dvb_frontend_info fe_info; - int card_type; + struct dvb_frontend frontend; }; -#define mt352_write(ibuf, ilen) \ +static int debug; +#define dprintk(args...) \ do { \ - struct i2c_msg msg = { .addr = I2C_MT352_ADDR, .flags = 0, \ - .buf = ibuf, .len = ilen }; \ - int err = i2c_transfer(i2c, &msg, 1); \ - if (err != 1) { \ - printk(KERN_WARNING \ - "mt352_write() failed (err = %d)!\n", err); \ - return err; \ - } \ + if (debug) printk(KERN_DEBUG "mt352: " args); \ } while (0) -static struct _tuner_info tuner_info [] = { - { - .fe_name = "AverMedia DVB-T 771", - .fe_frequency_min = 174000000, - .fe_frequency_max = 862000000, - .fe_frequency_stepsize = 166667, - .pll_i2c_addr = 0xc2, - .mt352_init = mt352_init_AVERMEDIA771, - .mt352_charge_pump = mt352_cp_AVERMEDIA771, - .mt352_band_select = mt352_bs_AVERMEDIA771 - }, - { - .fe_name = "Zarlink MT352 + TUA6034 DVB-T", - .fe_frequency_min = 174000000, - .fe_frequency_max = 862000000, - .fe_frequency_stepsize = 166667, - .pll_i2c_addr = 0xc2, - .mt352_init = mt352_init_TUA6034, - .mt352_charge_pump = mt352_cp_TUA6034, - .mt352_band_select = mt352_bs_TUA6034 - }, - { - .fe_name = "Zarlink MT352 + Samsung TDTC9251DH01C DVB-T", - .fe_frequency_min = 474000000, - .fe_frequency_max = 858000000, - .fe_frequency_stepsize = 166667, - .pll_i2c_addr = 0xc2, - .mt352_init = mt352_init_TDTC9251DH01C, - .mt352_charge_pump = mt352_cp_TDTC9251DH01C, - .mt352_band_select = mt352_bs_TDTC9251DH01C - }, - { - .fe_name = "DVICO FusionHDTV DVB-T1", - .fe_frequency_min = 174000000, - .fe_frequency_max = 862000000, - .fe_frequency_stepsize = 166667, - .pll_i2c_addr = 0xc2, - .mt352_init = mt352_init_DVICODVBT1, - .mt352_charge_pump = mt352_cp_DVICODVBT1, - .mt352_band_select = mt352_bs_DVICODVBT1, - }, - { - .fe_name = "DVICO FusionHDTV DVB-T Lite", - .fe_frequency_min = 174000000, - .fe_frequency_max = 862000000, - .fe_frequency_stepsize = 166667, - .pll_i2c_addr = 0xc0, - .mt352_init = mt352_init_DVICODVBTLITE, - .mt352_charge_pump = mt352_cp_DVICODVBTLITE, - .mt352_band_select = mt352_bs_DVICODVBTLITE, - } -}; - -static struct dvb_frontend_info mt352_info_template = { - .name = "DVB-T Zarlink MT352 demodulator driver", - .type = FE_OFDM, -/* - .frequency_min = 0, - .frequency_max = 0, - .frequency_stepsize = 0, - .frequency_tolerance = 0, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, - .symbol_rate_tolerance = ???, -*/ - .notifier_delay = 0, - .caps = FE_CAN_INVERSION_AUTO | 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 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | - FE_CAN_MUTE_TS -}; - -static u8 mt352_reset [] = { RESET, 0x80 }; -static u8 mt352_adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; -static u8 mt352_capt_range_cfg[] = { CAPT_RANGE, 0x32 }; - -static int mt352_init_TUA6034(struct i2c_adapter *i2c) -{ - static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; - static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x19, 0xa0 }; - - mt352_write(mt352_clock_config, sizeof(mt352_clock_config)); - udelay(2000); - mt352_write(mt352_reset, sizeof(mt352_reset)); - mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - - mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg)); - mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - - return 0; -} - -static int mt352_init_AVERMEDIA771(struct i2c_adapter *i2c) +int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen) { - static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; - static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x10, 0x23, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; - static u8 mt352_av771_extra[] = { 0xB5, 0x7A }; - static u8 mt352_capt_range_cfg[] = { CAPT_RANGE, 0x32 }; - - mt352_write(mt352_clock_config, sizeof(mt352_clock_config)); - udelay(2000); - mt352_write(mt352_reset, sizeof(mt352_reset)); - mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - - mt352_write(mt352_agc_cfg,sizeof(mt352_agc_cfg)); - udelay(2000); - mt352_write(mt352_av771_extra,sizeof(mt352_av771_extra)); - mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - - return 0; + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, + .buf = ibuf, .len = ilen }; + int err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) { + dprintk("mt352_write() failed (err = %d)!\n", err); + return err; } -static int mt352_init_TDTC9251DH01C(struct i2c_adapter *i2c) -{ - static u8 mt352_clock_config [] = { CLOCK_CTL, 0x10, 0x2d }; - static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x28, 0xa1 }; - - mt352_write(mt352_clock_config, sizeof(mt352_clock_config)); - udelay(2000); - mt352_write(mt352_reset, sizeof(mt352_reset)); - mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - - mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg)); - mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - return 0; } -static int mt352_init_DVICODVBT1(struct i2c_adapter *i2c) +static u8 mt352_read_register(struct mt352_state* state, u8 reg) { - static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; - static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; - static u8 mt352_gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; - - mt352_write(mt352_clock_config, sizeof(mt352_clock_config)); - udelay(200); - mt352_write(mt352_reset, sizeof(mt352_reset)); - mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - - mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg)); - mt352_write(mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg)); - mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - - return 0; -} - -static int mt352_init_DVICODVBTLITE(struct i2c_adapter *i2c) -{ - static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; - static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; - static u8 mt352_gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; - - mt352_write(mt352_clock_config, sizeof(mt352_clock_config)); - udelay(200); - mt352_write(mt352_reset, sizeof(mt352_reset)); - mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - - mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg)); - mt352_write(mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg)); - mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - - return 0; -} - -static unsigned char mt352_cp_TUA6034(u32 freq) -{ - unsigned char cp = 0; - - if (freq < 542000000) - cp = 0xbe; - else if (freq < 830000000) - cp = 0xf6; - else - cp = 0xfe; - - return cp; -} - -static unsigned char mt352_cp_AVERMEDIA771(u32 freq) -{ - unsigned char cp = 0; - - if (freq < 150000000) - cp = 0xB4; - else if (freq < 173000000) - cp = 0xBC; - else if (freq < 250000000) - cp = 0xB4; - else if (freq < 400000000) - cp = 0xBC; - else if (freq < 420000000) - cp = 0xF4; - else if (freq < 470000000) - cp = 0xFC; - else if (freq < 600000000) - cp = 0xBC; - else if (freq < 730000000) - cp = 0xF4; - else - cp = 0xFC; - - return cp; -} - -static unsigned char mt352_cp_TDTC9251DH01C(u32 freq) -{ - return(0xcc); -} - -static unsigned char mt352_cp_DVICODVBT1(u32 freq) -{ - unsigned char cp = 0; - - if (freq < 542000000) - cp = 0xbc; - else if (freq < 830000000) - cp = 0xf4; - else - cp = 0xfc; - - return cp; -} - -static unsigned char mt352_cp_DVICODVBTLITE(u32 freq) -{ - unsigned char cp = 0; - - if (freq < 542000000) - cp = 0xb4; - else if (freq < 771000000) - cp = 0xbc; - else - cp = 0xf4; - - return cp; -} - -static unsigned char mt352_bs_TUA6034(u32 freq) -{ - unsigned char bs = 0; - - if (freq < 250000000) - bs = 0x01; - else - bs = 0x08; - - return bs; -} - -static unsigned char mt352_bs_AVERMEDIA771(u32 freq) -{ - unsigned char bs = 0; - - if (freq < 150000000) - bs = 0x01; - else if (freq < 173000000) - bs = 0x01; - else if (freq < 250000000) - bs = 0x02; - else if (freq < 400000000) - bs = 0x02; - else if (freq < 420000000) - bs = 0x02; - else if (freq < 470000000) - bs = 0x02; - else if (freq < 600000000) - bs = 0x08; - else if (freq < 730000000) - bs = 0x08; - else - bs = 0x08; - - return bs; -} - -static unsigned char mt352_bs_TDTC9251DH01C(u32 freq) -{ - unsigned char bs = 0; - - if (freq >= 48000000 && freq <= 154000000) /* low band */ - bs = 0x09; + int ret; + u8 b0 [] = { reg }; + u8 b1 [] = { 0 }; + struct i2c_msg msg [] = { { .addr = state->config->demod_address, + .flags = 0, + .buf = b0, .len = 1 }, + { .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b1, .len = 1 } }; - if (freq >= 161000000 && freq <= 439000000) /* medium band */ - bs = 0x0a; + ret = i2c_transfer(state->i2c, msg, 2); - if (freq >= 447000000 && freq <= 863000000) /* high band */ - bs = 0x08; + if (ret != 2) + dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - return bs; + return b1[0]; } -static unsigned char mt352_bs_DVICODVBT1(u32 freq) -{ - unsigned char bs = 0; - if (freq == 0) /* power down PLL */ - bs = 0x03; - else if (freq < 157500000) /* low band */ - bs = 0x01; - else if (freq < 443250000) /* mid band */ - bs = 0x02; - else /* high band */ - bs = 0x04; - return bs; -} -static unsigned char mt352_bs_DVICODVBTLITE(u32 freq) -{ - unsigned char bs = 0; - if (freq == 0) /* power down PLL */ - bs = 0x03; - else if (freq < 443250000) /* mid band */ - bs = 0x02; - else /* high band */ - bs = 0x08; - return bs; -} -static u32 mt352_read_eeprom_dword(struct i2c_adapter *i2c, int dword_base) - { - int i; - u32 dword = 0; - u8 reg, val; - struct i2c_msg msg[2] = { - { - .addr = 0x50, - .flags = 0, - .buf = ®, - .len = 1 - }, - { - .addr = 0x50, - .flags = I2C_M_RD, - .buf = &val, - .len = 1 - } - }; - for (i = 0; i < 4; i++) { - reg = dword_base + i; - if (i2c_transfer(i2c,msg,2) != 2) - return 0; - dword = (dword << 8) | val; - } - return dword; -} -static int mt352_init(struct i2c_adapter *i2c, int card_type) -{ - /** - * all register write sequence have the register address of the - * first register in the first byte, thenafter the value to write - * into this and the following registers. - * - * - * We only write non-default settings, all default settings are - * restored by the full mt352_reset sequence. - * - * - * The optimal AGC target value and slope might vary from tuner - * type to tuner type, so check whether you need to adjust this one... - **/ - return(MT352_INIT(i2c)); -} -static int mt352_sleep(struct i2c_adapter *i2c) +static int mt352_sleep(struct dvb_frontend* fe) { static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 }; - mt352_write(mt352_softdown, sizeof(mt352_softdown)); + mt352_write(fe, mt352_softdown, sizeof(mt352_softdown)); return 0; } -static int mt352_set_parameters(struct i2c_adapter *i2c, - struct dvb_frontend_parameters *param, - int card_type) +static int mt352_set_parameters(struct dvb_frontend* fe, + struct dvb_frontend_parameters *param) { + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; unsigned char buf[14]; unsigned int tps = 0; struct dvb_ofdm_parameters *op = ¶m->u.ofdm; - uint16_t tmp; int i; switch (op->code_rate_HP) { @@ -600,22 +250,7 @@ buf[6] = 0x31; /* INPUT_FREQ_(1|0), 20.48MHz clock, 36.166667MHz IF */ buf[7] = 0x05; /* see MT352 Design Manual page 32 for details */ - buf[8] = PLL_I2C_ADDR; - - /** - * All the following settings are tuner module dependent, - * check the datasheet... - */ - - /* here we assume 1/6MHz == 166.66kHz stepsize */ - #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ - tmp = (((param->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; - - buf[9] = msb(tmp); /* CHAN_START_(1|0) */ - buf[10] = lsb(tmp); - - buf[11] = MT352_CHARGE_PUMP(param->frequency); - buf[12] = MT352_BAND_SELECT(param->frequency); + state->config->pll_set(fe, param, buf+8); buf[13] = 0x01; /* TUNER_GO!! */ @@ -623,39 +258,18 @@ * parameters already set. Enhances tuning time and prevents stream * breakup when retuning the same transponder. */ for (i = 1; i < 13; i++) - if (buf[i] != mt352_read_register(i2c, i + 0x50)) { - mt352_write(buf, sizeof(buf)); + if (buf[i] != mt352_read_register(state, i + 0x50)) { + mt352_write(fe, buf, sizeof(buf)); break; } return 0; } -static u8 mt352_read_register(struct i2c_adapter *i2c, u8 reg) -{ - int ret; - u8 b0 [] = { reg }; - u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = I2C_MT352_ADDR, - .flags = 0, - .buf = b0, .len = 1 }, - { .addr = I2C_MT352_ADDR, - .flags = I2C_M_RD, - .buf = b1, .len = 1 } }; - - ret = i2c_transfer(i2c, msg, 2); - - if (ret != 2) - printk(KERN_WARNING - "%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - - return b1[0]; -} - - -static int mt352_get_parameters(struct i2c_adapter *i2c, +static int mt352_get_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *param) { + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; u16 tps; u16 div; u8 trl; @@ -672,7 +286,7 @@ FEC_AUTO }; - if ( (mt352_read_register(i2c,0x00) & 0xC0) != 0xC0 ) + if ( (mt352_read_register(state,0x00) & 0xC0) != 0xC0 ) { return -EINVAL; } @@ -680,9 +294,9 @@ /* Use TPS_RECEIVED-registers, not the TPS_CURRENT-registers because * the mt352 sometimes works with the wrong parameters */ - tps = (mt352_read_register(i2c, TPS_RECEIVED_1) << 8) | mt352_read_register(i2c, TPS_RECEIVED_0); - div = (mt352_read_register(i2c, CHAN_START_1) << 8) | mt352_read_register(i2c, CHAN_START_0); - trl = mt352_read_register(i2c, TRL_NOMINAL_RATE_1); + tps = (mt352_read_register(state, TPS_RECEIVED_1) << 8) | mt352_read_register(state, TPS_RECEIVED_0); + div = (mt352_read_register(state, CHAN_START_1) << 8) | mt352_read_register(state, CHAN_START_0); + trl = mt352_read_register(state, TRL_NOMINAL_RATE_1); op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7]; op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7]; @@ -759,7 +373,7 @@ } - if (mt352_read_register(i2c, STATUS_2) & 0x02) + if (mt352_read_register(state, STATUS_2) & 0x02) param->inversion = INVERSION_OFF; else param->inversion = INVERSION_ON; @@ -767,26 +381,13 @@ return 0; } - -static int mt352_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int mt352_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct mt352_state *state = fe->data; - struct i2c_adapter *i2c = state->i2c; - int card_type = state->card_type; - u8 r,snr; - fe_status_t *status; - u16 signal; - struct dvb_frontend_tune_settings *fe_tune_settings; - - switch (cmd) { - case FE_GET_INFO: - memcpy(arg, &state->fe_info, sizeof(struct dvb_frontend_info)); - break; + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; + u8 r; - case FE_READ_STATUS: - status = arg; *status = 0; - r = mt352_read_register (i2c, STATUS_0); + r = mt352_read_register (state, STATUS_0); if (r & (1 << 4)) *status = FE_HAS_CARRIER; if (r & (1 << 1)) @@ -794,243 +395,164 @@ if (r & (1 << 5)) *status |= FE_HAS_LOCK; - r = mt352_read_register (i2c, STATUS_1); + r = mt352_read_register (state, STATUS_1); if (r & (1 << 1)) *status |= FE_HAS_SYNC; - r = mt352_read_register (i2c, STATUS_3); + r = mt352_read_register (state, STATUS_3); if (r & (1 << 6)) *status |= FE_HAS_SIGNAL; - break; + if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != + (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) + *status &= ~FE_HAS_LOCK; - case FE_READ_BER: - *((u32 *) arg) = (mt352_read_register (i2c, RS_ERR_CNT_2) << 16) | - (mt352_read_register (i2c, RS_ERR_CNT_1) << 8) | - (mt352_read_register (i2c, RS_ERR_CNT_0)); - break; - - case FE_READ_SIGNAL_STRENGTH: - signal = (mt352_read_register (i2c, AGC_GAIN_3) << 8) | - (mt352_read_register (i2c, AGC_GAIN_2)); - *((u16*) arg) = ~signal; - break; - - case FE_READ_SNR: - snr = mt352_read_register (i2c, SNR); - *((u16*) arg) = (snr << 8) | snr; - break; - - case FE_READ_UNCORRECTED_BLOCKS: - *(u32*) arg = (mt352_read_register (i2c, RS_UBC_1) << 8) | - (mt352_read_register (i2c, RS_UBC_0)); - break; - - case FE_SET_FRONTEND: - return mt352_set_parameters (i2c, - (struct dvb_frontend_parameters *) arg, - card_type); - - case FE_GET_FRONTEND: - return mt352_get_parameters (i2c, - (struct dvb_frontend_parameters *) arg); - - case FE_GET_TUNE_SETTINGS: - fe_tune_settings = (struct dvb_frontend_tune_settings *) arg; - fe_tune_settings->min_delay_ms = 800; - fe_tune_settings->step_size = 0; - fe_tune_settings->max_drift = 0; - break; - - case FE_SLEEP: - return mt352_sleep(i2c); - - case FE_INIT: - /* Only send the initialisation command if the demodulator - * isn't already enabled. Greatly enhances tuning time. */ - if ((mt352_read_register(i2c, CLOCK_CTL) & 0x10) == 0 || - (mt352_read_register(i2c, CONFIG) & 0x20) == 0) - return mt352_init(i2c, card_type); - else - return 0; + return 0; +} - default: - return -EOPNOTSUPP; +static int mt352_read_ber(struct dvb_frontend* fe, u32* ber) +{ + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; + + *ber = (mt352_read_register (state, RS_ERR_CNT_2) << 16) | + (mt352_read_register (state, RS_ERR_CNT_1) << 8) | + (mt352_read_register (state, RS_ERR_CNT_0)); + + return 0; } +static int mt352_read_signal_strength(struct dvb_frontend* fe, u16* strength) +{ + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; + + u16 signal = (mt352_read_register (state, AGC_GAIN_3) << 8) | + (mt352_read_register (state, AGC_GAIN_2)); + + *strength = ~signal; return 0; } -static struct i2c_client client_template; - -static int mt352_attach_adapter(struct i2c_adapter *i2c) +static int mt352_read_snr(struct dvb_frontend* fe, u16* snr) { - static int num_cards_probed; - struct mt352_state *state; - struct i2c_client *client; - static u8 mt352_reset_attach [] = { RESET, 0xC0 }; - int ret; - int card_type, forced_card = -1; + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; - dprintk("Trying to attach to adapter 0x%x:%s.\n", - i2c->id, i2c->name); + u8 _snr = mt352_read_register (state, SNR); + *snr = (_snr << 8) | _snr; - if (mt352_read_register(i2c, CHIP_ID) != ID_MT352) - return -ENODEV; + return 0; +} - if ( !(state = kmalloc(sizeof(struct mt352_state), GFP_KERNEL)) ) - return -ENOMEM; +static int mt352_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; - memset(state, 0, sizeof(struct mt352_state)); - state->i2c = i2c; - state->card_type = -1; - memcpy(&state->fe_info, &mt352_info_template, sizeof(struct dvb_frontend_info)); + *ucblocks = (mt352_read_register (state, RS_UBC_1) << 8) | + (mt352_read_register (state, RS_UBC_0)); - /* Attempt autodetection of card type based on PCI ID information - * stored in any on-board EEPROM. */ - switch (mt352_read_eeprom_dword(i2c, 0xFC)) { /* BT878A chipset */ - case 0x07711461: - state->card_type = CARD_AVDVBT771; - break; - case 0xdb1018ac: - state->card_type = CARD_DVICODVBTLITE; - break; - default: - break; - } - - switch (mt352_read_eeprom_dword(i2c, 0x04)) { /* CX2388x chipset */ - case 0xac1800db: - state->card_type = CARD_DVICODVBT1; - break; - default: - break; - } - - if (num_cards_probed < force_card_count) - forced_card = force_card[num_cards_probed++]; - - if (state->card_type == -1 && forced_card < 0) { - dprintk("Card type not automatically detected. You " - "must use the 'force_card' module parameter.\n"); - kfree(state); - return -ENODEV; + return 0; } - if (forced_card >= 0) { - if (state->card_type >= 0 && forced_card != state->card_type) - printk(KERN_WARNING FRONTEND_NAME ": Warning, overriding" - " detected card type.\n"); - state->card_type = forced_card; +static int mt352_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings) +{ + fe_tune_settings->min_delay_ms = 800; + fe_tune_settings->step_size = 0; + fe_tune_settings->max_drift = 0; + + return 0; } - card_type = state->card_type; - printk(KERN_INFO FRONTEND_NAME ": Setup for %s\n", FE_NAME); +static int mt352_init(struct dvb_frontend* fe) +{ + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; - /* set the frontend name and card-specific frequency info */ - strlcpy(state->fe_info.name, FE_NAME, sizeof(state->fe_info.name)); - state->fe_info.frequency_min = FE_FREQ_MIN; - state->fe_info.frequency_max = FE_FREQ_MAX; - state->fe_info.frequency_stepsize = FE_FREQ_STEPSIZE; + static u8 mt352_reset_attach [] = { RESET, 0xC0 }; - /* Do a "hard" reset */ - mt352_write(mt352_reset_attach, sizeof(mt352_reset_attach)); + if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 || + (mt352_read_register(state, CONFIG) & 0x20) == 0) { - /* Try to intiialise the device */ - if (mt352_init(i2c, card_type) != 0) { - kfree(state); - return -ENODEV; + /* Do a "hard" reset */ + mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach)); + return state->config->demod_init(fe); } - if ( !(client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)) ) { - kfree(state); - return -ENOMEM; + return 0; } - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = i2c; - client->addr = 0; // XXX - i2c_set_clientdata(client, state); - - if ((ret = i2c_attach_client(client))) { - kfree(client); +static void mt352_release(struct dvb_frontend* fe) +{ + struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; kfree(state); - return ret; } - return 0; -} +static struct dvb_frontend_ops mt352_ops; -static int mt352_detach_client(struct i2c_client *client) +struct dvb_frontend* mt352_attach(const struct mt352_config* config, + struct i2c_adapter* i2c) { - struct mt352_state *state = i2c_get_clientdata(client); + struct mt352_state* state = NULL; - if (state->dvb) - dvb_unregister_frontend (mt352_ioctl, state->dvb); - i2c_detach_client(client); - kfree(client); - kfree(state); - return 0; -} + /* allocate memory for the internal state */ + state = (struct mt352_state*) kmalloc(sizeof(struct mt352_state), GFP_KERNEL); + if (state == NULL) goto error; -static int mt352_command (struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct mt352_state *state = i2c_get_clientdata(client); - int ret; + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &mt352_ops, sizeof(struct dvb_frontend_ops)); - switch (cmd) { - case FE_REGISTER: - if (!state->dvb) { - if ((ret = dvb_register_frontend(mt352_ioctl, arg, - state, &state->fe_info, - THIS_MODULE))) - return ret; - state->dvb = arg; - } - break; - case FE_UNREGISTER: - if (state->dvb == arg) { - dvb_unregister_frontend(mt352_ioctl, state->dvb); - state->dvb = NULL; - } - break; - default: - return -EOPNOTSUPP; - } - return 0; -} + /* check if the demod is there */ + if (mt352_read_register(state, CHIP_ID) != ID_MT352) goto error; -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = FRONTEND_NAME, - .id = I2C_DRIVERID_DVBFE_MT352, - .flags = I2C_DF_NOTIFY, - .attach_adapter = mt352_attach_adapter, - .detach_client = mt352_detach_client, - .command = mt352_command, -}; + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; +} + +static struct dvb_frontend_ops mt352_ops = { + + .info = { + .name = "Zarlink MT352 DVB-T", + .type = FE_OFDM, + .frequency_min = 174000000, + .frequency_max = 862000000, + .frequency_stepsize = 166667, + .frequency_tolerance = 0, + .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 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | + FE_CAN_MUTE_TS + }, -static struct i2c_client client_template = { - .name = FRONTEND_NAME, - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, -}; + .release = mt352_release, -static int __init mt352_module_init(void) -{ - return i2c_add_driver(&driver); -} + .init = mt352_init, + .sleep = mt352_sleep, -static void __exit mt352_module_exit(void) -{ - if (i2c_del_driver(&driver)) - printk(KERN_ERR "mt352: driver deregistration failed.\n"); -} + .set_frontend = mt352_set_parameters, + .get_frontend = mt352_get_parameters, + .get_tune_settings = mt352_get_tune_settings, + + .read_status = mt352_read_status, + .read_ber = mt352_read_ber, + .read_signal_strength = mt352_read_signal_strength, + .read_snr = mt352_read_snr, + .read_ucblocks = mt352_read_ucblocks, +}; -module_init(mt352_module_init); -module_exit(mt352_module_exit); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("DVB-T MT352 Zarlink"); +MODULE_DESCRIPTION("Zarlink MT352 DVB-T Demodulator driver"); MODULE_AUTHOR("Holger Waechtler, Daniel Mack, Antonio Mancuso"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(mt352_attach); +EXPORT_SYMBOL(mt352_write); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/mt352.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/mt352.h 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/mt352.h 2004-12-22 10:04:35.734370402 -0800 @@ -30,145 +30,29 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= */ -#ifndef _MT352_ -#define _MT352_ +#ifndef MT352_H +#define MT352_H -#define I2C_MT352_ADDR 0x0f -#define ID_MT352 0x13 +#include -#define CARD_AVDVBT771 0x00 -#define CARD_TUA6034 0x01 -#define CARD_TDTC9251DH01C 0x02 -#define CARD_DVICODVBT1 0x03 -#define CARD_DVICODVBTLITE 0x04 - -#define msb(x) (((x) >> 8) & 0xff) -#define lsb(x) ((x) & 0xff) - -enum mt352_reg_addr { - STATUS_0 = 0x00, - STATUS_1 = 0x01, - STATUS_2 = 0x02, - STATUS_3 = 0x03, - STATUS_4 = 0x04, - INTERRUPT_0 = 0x05, - INTERRUPT_1 = 0x06, - INTERRUPT_2 = 0x07, - INTERRUPT_3 = 0x08, - SNR = 0x09, - VIT_ERR_CNT_2 = 0x0A, - VIT_ERR_CNT_1 = 0x0B, - VIT_ERR_CNT_0 = 0x0C, - RS_ERR_CNT_2 = 0x0D, - RS_ERR_CNT_1 = 0x0E, - RS_ERR_CNT_0 = 0x0F, - RS_UBC_1 = 0x10, - RS_UBC_0 = 0x11, - AGC_GAIN_3 = 0x12, - AGC_GAIN_2 = 0x13, - AGC_GAIN_1 = 0x14, - AGC_GAIN_0 = 0x15, - FREQ_OFFSET_2 = 0x17, - FREQ_OFFSET_1 = 0x18, - FREQ_OFFSET_0 = 0x19, - TIMING_OFFSET_1 = 0x1A, - TIMING_OFFSET_0 = 0x1B, - CHAN_FREQ_1 = 0x1C, - CHAN_FREQ_0 = 0x1D, - TPS_RECEIVED_1 = 0x1E, - TPS_RECEIVED_0 = 0x1F, - TPS_CURRENT_1 = 0x20, - TPS_CURRENT_0 = 0x21, - TPS_CELL_ID_1 = 0x22, - TPS_CELL_ID_0 = 0x23, - TPS_MISC_DATA_2 = 0x24, - TPS_MISC_DATA_1 = 0x25, - TPS_MISC_DATA_0 = 0x26, - RESET = 0x50, - TPS_GIVEN_1 = 0x51, - TPS_GIVEN_0 = 0x52, - ACQ_CTL = 0x53, - TRL_NOMINAL_RATE_1 = 0x54, - TRL_NOMINAL_RATE_0 = 0x55, - INPUT_FREQ_1 = 0x56, - INPUT_FREQ_0 = 0x57, - TUNER_ADDR = 0x58, - CHAN_START_1 = 0x59, - CHAN_START_0 = 0x5A, - CONT_1 = 0x5B, - CONT_0 = 0x5C, - TUNER_GO = 0x5D, - STATUS_EN_0 = 0x5F, - STATUS_EN_1 = 0x60, - INTERRUPT_EN_0 = 0x61, - INTERRUPT_EN_1 = 0x62, - INTERRUPT_EN_2 = 0x63, - INTERRUPT_EN_3 = 0x64, - AGC_TARGET = 0x67, - AGC_CTL = 0x68, - CAPT_RANGE = 0x75, - SNR_SELECT_1 = 0x79, - SNR_SELECT_0 = 0x7A, - RS_ERR_PER_1 = 0x7C, - RS_ERR_PER_0 = 0x7D, - CHIP_ID = 0x7F, - CHAN_STOP_1 = 0x80, - CHAN_STOP_0 = 0x81, - CHAN_STEP_1 = 0x82, - CHAN_STEP_0 = 0x83, - FEC_LOCK_TIME = 0x85, - OFDM_LOCK_TIME = 0x86, - ACQ_DELAY = 0x87, - SCAN_CTL = 0x88, - CLOCK_CTL = 0x89, - CONFIG = 0x8A, - MCLK_RATIO = 0x8B, - GPP_CTL = 0x8C, - ADC_CTL_1 = 0x8E, - ADC_CTL_0 = 0x8F +struct mt352_config +{ + /* the demodulator's i2c address */ + u8 demod_address; + + /* Initialise the demodulator and PLL. Cannot be NULL */ + int (*demod_init)(struct dvb_frontend* fe); + + /* PLL setup - fill out the supplied 5 byte buffer with your PLL settings. + * byte0: Set to pll i2c address (nonlinux; left shifted by 1) + * byte1-4: PLL configuration. + */ + int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf); }; -struct _tuner_info { - char *fe_name; -#define FE_NAME tuner_info[card_type].fe_name +extern struct dvb_frontend* mt352_attach(const struct mt352_config* config, + struct i2c_adapter* i2c); - __u32 fe_frequency_min; -#define FE_FREQ_MIN tuner_info[card_type].fe_frequency_min +extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen); - __u32 fe_frequency_max; -#define FE_FREQ_MAX tuner_info[card_type].fe_frequency_max - - __u32 fe_frequency_stepsize; //verificare se u32 e' corretto -#define FE_FREQ_STEPSIZE tuner_info[card_type].fe_frequency_stepsize - - u8 pll_i2c_addr; -#define PLL_I2C_ADDR tuner_info[card_type].pll_i2c_addr - - int (* mt352_init) (struct i2c_adapter *i2c); -#define MT352_INIT tuner_info[card_type].mt352_init - - unsigned char (* mt352_charge_pump) (u32 freq); -#define MT352_CHARGE_PUMP tuner_info[card_type].mt352_charge_pump - - unsigned char (* mt352_band_select) (u32 freq); -#define MT352_BAND_SELECT tuner_info[card_type].mt352_band_select -}; - -static int mt352_init_TUA6034(struct i2c_adapter *i2c); -static int mt352_init_AVERMEDIA771(struct i2c_adapter *i2c); -static int mt352_init_TDTC9251DH01C(struct i2c_adapter *i2c); -static int mt352_init_DVICODVBT1(struct i2c_adapter *i2c); -static int mt352_init_DVICODVBTLITE(struct i2c_adapter *i2c); -static unsigned char mt352_cp_TUA6034(u32 freq); -static unsigned char mt352_cp_AVERMEDIA771(u32 freq); -static unsigned char mt352_cp_TDTC9251DH01C(u32 freq); -static unsigned char mt352_cp_DVICODVBT1(u32 freq); -static unsigned char mt352_cp_DVICODVBTLITE(u32 freq); -static unsigned char mt352_bs_TUA6034(u32 freq); -static unsigned char mt352_bs_AVERMEDIA771(u32 freq); -static unsigned char mt352_bs_TDTC9251DH01C(u32 freq); -static unsigned char mt352_bs_DVICODVBT1(u32 freq); -static unsigned char mt352_bs_DVICODVBTLITE(u32 freq); -static u8 mt352_read_register(struct i2c_adapter *i2c, u8 reg); - -#endif /* _MT352_ */ +#endif // MT352_H Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/nxt6000.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/nxt6000.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/nxt6000.c 2004-12-22 10:04:35.754367362 -0800 @@ -1,13 +1,6 @@ /* - NxtWave Communications - NXT6000 demodulator driver - This driver currently supports: - - Alps TDME7 (Tuner: MITEL SP5659) - Alps TDED4 (Tuner: TI ALP510, external Nxt6000) - Comtech DVBT-6k07 (PLL IC: SP5730) - Copyright (C) 2002-2003 Florian Schirmer Copyright (C) 2003 Paul Andreassen @@ -34,217 +27,68 @@ #include #include "dvb_frontend.h" +#include "nxt6000_priv.h" #include "nxt6000.h" -MODULE_DESCRIPTION("NxtWave NXT6000 DVB demodulator driver"); -MODULE_AUTHOR("Florian Schirmer"); -MODULE_LICENSE("GPL"); - -static int debug = 0; -MODULE_PARM(debug, "i"); -static struct dvb_frontend_info nxt6000_info = { - .name = "NxtWave NXT6000", - .type = FE_OFDM, - .frequency_min = 0, - .frequency_max = 863250000, - .frequency_stepsize = 62500, - /*.frequency_tolerance = */ /* FIXME: 12% of SR */ - .symbol_rate_min = 0, /* FIXME */ - .symbol_rate_max = 9360000, /* FIXME */ - .symbol_rate_tolerance = 4000, - .notifier_delay = 0, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; +struct nxt6000_state { -struct nxt6000_config { - u8 demod_addr; - u8 tuner_addr; - u8 tuner_type; - u8 clock_inversion; struct i2c_adapter *i2c; - struct dvb_adapter *dvb; -}; -#define TUNER_TYPE_ALP510 0 -#define TUNER_TYPE_SP5659 1 -#define TUNER_TYPE_SP5730 2 + struct dvb_frontend_ops ops; + + /* configuration settings */ + const struct nxt6000_config* config; -// #define FE2NXT(fe) ((struct nxt6000_config *)((fe)->data)) -#define FREQ2DIV(freq) ((freq + 36166667) / 166667) + struct dvb_frontend frontend; +}; + +static int debug = 0; #define dprintk if (debug) printk -static int nxt6000_write(struct i2c_adapter *i2c, u8 addr, u8 reg, u8 data) +static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data) { u8 buf[] = {reg, data}; - struct i2c_msg msg = {.addr = addr >> 1, .flags = 0, .buf = buf, .len = 2}; + struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 }; int ret; - if ((ret = i2c_transfer(i2c, &msg, 1)) != 1) - dprintk("nxt6000: nxt6000_write error (.addr = 0x%02X, reg: 0x%02X, data: 0x%02X, ret: %d)\n", addr, reg, data, ret); + if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) + dprintk("nxt6000: nxt6000_write error (reg: 0x%02X, data: 0x%02X, ret: %d)\n", reg, data, ret); return (ret != 1) ? -EFAULT : 0; } -static u8 nxt6000_writereg(struct nxt6000_config *nxt, u8 reg, u8 data) -{ - return nxt6000_write(nxt->i2c, nxt->demod_addr, reg, data); -} - -static u8 nxt6000_read(struct i2c_adapter *i2c, u8 addr, u8 reg) +static u8 nxt6000_readreg(struct nxt6000_state* state, u8 reg) { int ret; u8 b0[] = {reg}; u8 b1[] = {0}; struct i2c_msg msgs[] = { - {.addr = addr >> 1,.flags = 0,.buf = b0,.len = 1}, - {.addr = addr >> 1,.flags = I2C_M_RD,.buf = b1,.len = 1} + {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1}, + {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1} }; - ret = i2c_transfer(i2c, msgs, 2); + ret = i2c_transfer(state->i2c, msgs, 2); if (ret != 2) - dprintk("nxt6000: nxt6000_read error (.addr = 0x%02X, reg: 0x%02X, ret: %d)\n", addr, reg, ret); + dprintk("nxt6000: nxt6000_read error (reg: 0x%02X, ret: %d)\n", reg, ret); return b1[0]; } -static u8 nxt6000_readreg(struct nxt6000_config *nxt, u8 reg) -{ - return nxt6000_read(nxt->i2c, nxt->demod_addr, reg); -} - -static int pll_test(struct i2c_adapter *i2c, u8 demod_addr, u8 tuner_addr) -{ - u8 buf [1]; - struct i2c_msg msg = {.addr = tuner_addr >> 1,.flags = I2C_M_RD,.buf = buf,.len = 1 }; - int ret; - - nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ - ret = i2c_transfer(i2c, &msg, 1); - nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ - - return (ret != 1) ? -EFAULT : 0; -} - -static int pll_write(struct i2c_adapter *i2c, u8 demod_addr, u8 tuner_addr, u8 * buf, u8 len) -{ - struct i2c_msg msg = {.addr = tuner_addr >> 1, .flags = 0, .buf = buf, .len = len}; - int ret; - - nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ - ret = i2c_transfer(i2c, &msg, 1); - nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ - - if (ret != 1) - dprintk("nxt6000: pll_write error %d\n", ret); - - return (ret != 1) ? -EFAULT : 0; -} - -static int sp5659_set_tv_freq(struct nxt6000_config *nxt, u32 freq) -{ - u8 buf[4]; - - buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F; - buf[1] = FREQ2DIV(freq) & 0xFF; - buf[2] = (((FREQ2DIV(freq) >> 15) & 0x03) << 5) | 0x85; - - if ((freq >= 174000000) && (freq < 230000000)) - buf[3] = 0x82; - else if ((freq >= 470000000) && (freq < 782000000)) - buf[3] = 0x85; - else if ((freq >= 782000000) && (freq < 863000000)) - buf[3] = 0xC5; - else - return -EINVAL; - - return pll_write(nxt->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4); -} - -static int alp510_set_tv_freq(struct nxt6000_config *nxt, u32 freq) -{ - u8 buf[4]; - - buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F; - buf[1] = FREQ2DIV(freq) & 0xFF; - buf[2] = 0x85; - -#if 0 - if ((freq >= 47000000) && (freq < 153000000)) - buf[3] = 0x01; - else if ((freq >= 153000000) && (freq < 430000000)) - buf[3] = 0x02; - else if ((freq >= 430000000) && (freq < 824000000)) - buf[3] = 0x08; - else if ((freq >= 824000000) && (freq < 863000000)) - buf[3] = 0x88; - else - return -EINVAL; -#else - if ((freq >= 47000000) && (freq < 153000000)) - buf[3] = 0x01; - else if ((freq >= 153000000) && (freq < 430000000)) - buf[3] = 0x02; - else if ((freq >= 430000000) && (freq < 824000000)) - buf[3] = 0x0C; - else if ((freq >= 824000000) && (freq < 863000000)) - buf[3] = 0x8C; - else - return -EINVAL; -#endif - - return pll_write(nxt->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4); -} - -static int sp5730_set_tv_freq(struct nxt6000_config *nxt, u32 freq) -{ - u8 buf[4]; - - buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F; - buf[1] = FREQ2DIV(freq) & 0xFF; - buf[2] = 0x93; - - if ((freq >= 51000000) && (freq < 132100000)) - buf[3] = 0x05; - else if ((freq >= 132100000) && (freq < 143000000)) - buf[3] = 0x45; - else if ((freq >= 146000000) && (freq < 349100000)) - buf[3] = 0x06; - else if ((freq >= 349100000) && (freq < 397100000)) - buf[3] = 0x46; - else if ((freq >= 397100000) && (freq < 426000000)) - buf[3] = 0x86; - else if ((freq >= 430000000) && (freq < 659100000)) - buf[3] = 0x03; - else if ((freq >= 659100000) && (freq < 759100000)) - buf[3] = 0x43; - else if ((freq >= 759100000) && (freq < 858000000)) - buf[3] = 0x83; - else - return -EINVAL; - - return pll_write(nxt->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4); -} - -static void nxt6000_reset(struct nxt6000_config *fe) +static void nxt6000_reset(struct nxt6000_state* state) { u8 val; - val = nxt6000_readreg(fe, OFDM_COR_CTL); + val = nxt6000_readreg(state, OFDM_COR_CTL); - nxt6000_writereg(fe, OFDM_COR_CTL, val & ~COREACT); - nxt6000_writereg(fe, OFDM_COR_CTL, val | COREACT); + nxt6000_writereg(state, OFDM_COR_CTL, val & ~COREACT); + nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT); } -static int nxt6000_set_bandwidth(struct nxt6000_config *fe, fe_bandwidth_t bandwidth) +static int nxt6000_set_bandwidth(struct nxt6000_state* state, fe_bandwidth_t bandwidth) { u16 nominal_rate; int result; @@ -270,119 +114,115 @@ break; default: - return -EINVAL; - } - if ((result = nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0) + if ((result = nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0) return result; - return nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF); + return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF); } -static int nxt6000_set_guard_interval(struct nxt6000_config *fe, fe_guard_interval_t guard_interval) +static int nxt6000_set_guard_interval(struct nxt6000_state* state, fe_guard_interval_t guard_interval) { switch(guard_interval) { case GUARD_INTERVAL_1_32: - - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); case GUARD_INTERVAL_1_16: - - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); case GUARD_INTERVAL_AUTO: case GUARD_INTERVAL_1_8: - - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); case GUARD_INTERVAL_1_4: - - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); default: return -EINVAL; } } -static int nxt6000_set_inversion(struct nxt6000_config *fe, fe_spectral_inversion_t inversion) +static int nxt6000_set_inversion(struct nxt6000_state* state, fe_spectral_inversion_t inversion) { switch(inversion) { case INVERSION_OFF: - - return nxt6000_writereg(fe, OFDM_ITB_CTL, 0x00); + return nxt6000_writereg(state, OFDM_ITB_CTL, 0x00); case INVERSION_ON: - - return nxt6000_writereg(fe, OFDM_ITB_CTL, ITBINV); + return nxt6000_writereg(state, OFDM_ITB_CTL, ITBINV); default: - return -EINVAL; } } -static int nxt6000_set_transmission_mode(struct nxt6000_config *fe, fe_transmit_mode_t transmission_mode) +static int nxt6000_set_transmission_mode(struct nxt6000_state* state, fe_transmit_mode_t transmission_mode) { int result; switch(transmission_mode) { case TRANSMISSION_MODE_2K: - - if ((result = nxt6000_writereg(fe, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(fe, EN_DMD_RACQ) & ~0x03))) < 0) + if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0) return result; - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x04)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04)); case TRANSMISSION_MODE_8K: case TRANSMISSION_MODE_AUTO: - - if ((result = nxt6000_writereg(fe, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(fe, EN_DMD_RACQ) & ~0x03))) < 0) + if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0) return result; - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x04)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04)); default: - return -EINVAL; } } -static void nxt6000_setup(struct nxt6000_config *fe) +static void nxt6000_setup(struct dvb_frontend* fe) { - nxt6000_writereg(fe, RS_COR_SYNC_PARAM, SYNC_PARAM); - nxt6000_writereg(fe, BER_CTRL, /*(1 << 2) |*/ (0x01 << 1) | 0x01); - nxt6000_writereg(fe, VIT_COR_CTL, VIT_COR_RESYNC); - nxt6000_writereg(fe, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(fe, OFDM_COR_CTL) & 0x0F)); - nxt6000_writereg(fe, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02); - nxt6000_writereg(fe, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW); - nxt6000_writereg(fe, OFDM_ITB_FREQ_1, 0x06); - nxt6000_writereg(fe, OFDM_ITB_FREQ_2, 0x31); - nxt6000_writereg(fe, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04); - nxt6000_writereg(fe, CAS_FREQ, 0xBB); /* CHECKME */ - nxt6000_writereg(fe, OFDM_SYR_CTL, 1 << 2); - nxt6000_writereg(fe, OFDM_PPM_CTL_1, PPM256); - nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_1, 0x49); - nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_2, 0x72); - nxt6000_writereg(fe, ANALOG_CONTROL_0, 1 << 5); - nxt6000_writereg(fe, EN_DMD_RACQ, (1 << 7) | (3 << 4) | 2); - nxt6000_writereg(fe, DIAG_CONFIG, TB_SET); + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; - if (fe->clock_inversion) - nxt6000_writereg(fe, SUB_DIAG_MODE_SEL, CLKINVERSION); + nxt6000_writereg(state, RS_COR_SYNC_PARAM, SYNC_PARAM); + nxt6000_writereg(state, BER_CTRL, /*(1 << 2) | */ (0x01 << 1) | 0x01); + nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC); + nxt6000_writereg(state, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(state, OFDM_COR_CTL) & 0x0F)); + nxt6000_writereg(state, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02); + nxt6000_writereg(state, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW); + nxt6000_writereg(state, OFDM_ITB_FREQ_1, 0x06); + nxt6000_writereg(state, OFDM_ITB_FREQ_2, 0x31); + nxt6000_writereg(state, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04); + nxt6000_writereg(state, CAS_FREQ, 0xBB); /* CHECKME */ + nxt6000_writereg(state, OFDM_SYR_CTL, 1 << 2); + nxt6000_writereg(state, OFDM_PPM_CTL_1, PPM256); + nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, 0x49); + nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, 0x72); + nxt6000_writereg(state, ANALOG_CONTROL_0, 1 << 5); + nxt6000_writereg(state, EN_DMD_RACQ, (1 << 7) | (3 << 4) | 2); + nxt6000_writereg(state, DIAG_CONFIG, TB_SET); + + if (state->config->clock_inversion) + nxt6000_writereg(state, SUB_DIAG_MODE_SEL, CLKINVERSION); else - nxt6000_writereg(fe, SUB_DIAG_MODE_SEL, 0); + nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0); + + nxt6000_writereg(state, TS_FORMAT, 0); - nxt6000_writereg(fe, TS_FORMAT, 0); + if (state->config->pll_init) { + nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ + state->config->pll_init(fe); + nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ + } } -static void nxt6000_dump_status(struct nxt6000_config *fe) +static void nxt6000_dump_status(struct nxt6000_state *state) { u8 val; @@ -400,12 +240,12 @@ */ printk("NXT6000 status:"); - val = nxt6000_readreg(fe, RS_COR_STAT); + val = nxt6000_readreg(state, RS_COR_STAT); printk(" DATA DESCR LOCK: %d,", val & 0x01); printk(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01); - val = nxt6000_readreg(fe, VIT_SYNC_STATUS); + val = nxt6000_readreg(state, VIT_SYNC_STATUS); printk(" VITERBI LOCK: %d,", (val >> 7) & 0x01); @@ -443,7 +283,7 @@ } - val = nxt6000_readreg(fe, OFDM_COR_STAT); + val = nxt6000_readreg(state, OFDM_COR_STAT); printk(" CHCTrack: %d,", (val >> 7) & 0x01); printk(" TPSLock: %d,", (val >> 6) & 0x01); @@ -496,7 +336,7 @@ } - val = nxt6000_readreg(fe, OFDM_SYR_STAT); + val = nxt6000_readreg(state, OFDM_SYR_STAT); printk(" SYRLock: %d,", (val >> 4) & 0x01); printk(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K"); @@ -522,14 +362,11 @@ break; case 0x03: - printk(" SYRGuard: 1/4,"); - break; - } - val = nxt6000_readreg(fe, OFDM_TPS_RCVD_3); + val = nxt6000_readreg(state, OFDM_TPS_RCVD_3); switch((val >> 4) & 0x07) { @@ -599,7 +436,7 @@ } - val = nxt6000_readreg(fe, OFDM_TPS_RCVD_4); + val = nxt6000_readreg(state, OFDM_TPS_RCVD_4); printk(" TPSMode: %s,", val & 0x01 ? "8K" : "2K"); @@ -632,299 +469,156 @@ } /* Strange magic required to gain access to RF_AGC_STATUS */ - nxt6000_readreg(fe, RF_AGC_VAL_1); - val = nxt6000_readreg(fe, RF_AGC_STATUS); - val = nxt6000_readreg(fe, RF_AGC_STATUS); + nxt6000_readreg(state, RF_AGC_VAL_1); + val = nxt6000_readreg(state, RF_AGC_STATUS); + val = nxt6000_readreg(state, RF_AGC_STATUS); printk(" RF AGC LOCK: %d,", (val >> 4) & 0x01); printk("\n"); } -static int nxt6000_ioctl(struct dvb_frontend *f, unsigned int cmd, void *arg) -{ - struct nxt6000_config *fe = (struct nxt6000_config *) f->data; - switch (cmd) { - case FE_GET_INFO: - memcpy(arg, &nxt6000_info, sizeof (struct dvb_frontend_info)); - return 0; - case FE_READ_STATUS: - { - fe_status_t *status = (fe_status_t *)arg; + + + + +static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ u8 core_status; + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; *status = 0; - core_status = nxt6000_readreg(fe, OFDM_COR_STAT); + core_status = nxt6000_readreg(state, OFDM_COR_STAT); if (core_status & AGCLOCKED) *status |= FE_HAS_SIGNAL; - if (nxt6000_readreg(fe, OFDM_SYR_STAT) & GI14_SYR_LOCK) + if (nxt6000_readreg(state, OFDM_SYR_STAT) & GI14_SYR_LOCK) *status |= FE_HAS_CARRIER; - if (nxt6000_readreg(fe, VIT_SYNC_STATUS) & VITINSYNC) + if (nxt6000_readreg(state, VIT_SYNC_STATUS) & VITINSYNC) *status |= FE_HAS_VITERBI; - if (nxt6000_readreg(fe, RS_COR_STAT) & RSCORESTATUS) + if (nxt6000_readreg(state, RS_COR_STAT) & RSCORESTATUS) *status |= FE_HAS_SYNC; if ((core_status & TPSLOCKED) && (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))) *status |= FE_HAS_LOCK; if (debug) - nxt6000_dump_status(fe); + nxt6000_dump_status(state); return 0; - } - case FE_READ_BER: +static int nxt6000_init(struct dvb_frontend* fe) { - u32 *ber = (u32 *)arg; - - *ber=0; + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; - return 0; - - } + nxt6000_reset(state); + nxt6000_setup(fe); - case FE_READ_SIGNAL_STRENGTH: - { - s16 *signal = (s16 *) arg; -/* - *signal=(((signed char)readreg(client, 0x16))+128)<<8; -*/ - *signal = 0; return 0; - - } - - case FE_READ_SNR: - { - s16 *snr = (s16 *) arg; -/* - *snr=readreg(client, 0x24)<<8; - *snr|=readreg(client, 0x25); -*/ - *snr = 0; - break; - } - - case FE_READ_UNCORRECTED_BLOCKS: - { - u32 *ublocks = (u32 *)arg; - - *ublocks = 0; - - break; } - case FE_INIT: - nxt6000_reset(fe); - nxt6000_setup(fe); - break; - case FE_SET_FRONTEND: +static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *param) { - struct dvb_frontend_parameters *param = (struct dvb_frontend_parameters *)arg; + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; int result; - switch (fe->tuner_type) { - - case TUNER_TYPE_ALP510: - if ((result = alp510_set_tv_freq(fe, param->frequency)) < 0) - return result; - break; - - case TUNER_TYPE_SP5659: - - if ((result = sp5659_set_tv_freq(fe, param->frequency)) < 0) - return result; - - break; - - case TUNER_TYPE_SP5730: + nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ + state->config->pll_set(fe, param); + nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ - if ((result = sp5730_set_tv_freq(fe, param->frequency)) < 0) + if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0) return result; - - break; - - default: - - return -EFAULT; - - } - - if ((result = nxt6000_set_bandwidth(fe, param->u.ofdm.bandwidth)) < 0) - return result; - if ((result = nxt6000_set_guard_interval(fe, param->u.ofdm.guard_interval)) < 0) + if ((result = nxt6000_set_guard_interval(state, param->u.ofdm.guard_interval)) < 0) return result; - if ((result = nxt6000_set_transmission_mode(fe, param->u.ofdm.transmission_mode)) < 0) + if ((result = nxt6000_set_transmission_mode(state, param->u.ofdm.transmission_mode)) < 0) return result; - if ((result = nxt6000_set_inversion(fe, param->inversion)) < 0) + if ((result = nxt6000_set_inversion(state, param->inversion)) < 0) return result; - - break; - } - - default: - - return -EOPNOTSUPP; - - } return 0; - } -static u8 demod_addr_tbl[] = {0x14, 0x18, 0x24, 0x28}; - -static struct i2c_client client_template; -static int attach_adapter(struct i2c_adapter *adapter) +static void nxt6000_release(struct dvb_frontend* fe) { - struct i2c_client *client; - struct nxt6000_config *nxt; - u8 addr_nr; - int ret; - - if ((nxt = kmalloc(sizeof(struct nxt6000_config), GFP_KERNEL)) == NULL) - return -ENOMEM; - - memset(nxt, 0, sizeof(*nxt)); - nxt->i2c = adapter; - - for (addr_nr = 0; addr_nr < sizeof(demod_addr_tbl); addr_nr++) { - - if (nxt6000_read(adapter, demod_addr_tbl[addr_nr], OFDM_MSC_REV) != NXT6000ASICDEVICE) - continue; - - if (pll_test(adapter, demod_addr_tbl[addr_nr], 0xC0) == 0) { - nxt->tuner_addr = 0xC0; - nxt->tuner_type = TUNER_TYPE_ALP510; - nxt->clock_inversion = 1; - - dprintk("nxt6000: detected TI ALP510 tuner at 0x%02X\n", nxt->tuner_addr); - - } else if (pll_test(adapter, demod_addr_tbl[addr_nr], 0xC2) == 0) { - nxt->tuner_addr = 0xC2; - nxt->tuner_type = TUNER_TYPE_SP5659; - nxt->clock_inversion = 0; - - dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt->tuner_addr); - - } else if (pll_test(adapter, demod_addr_tbl[addr_nr], 0xC0) == 0) { - nxt->tuner_addr = 0xC0; - nxt->tuner_type = TUNER_TYPE_SP5730; - nxt->clock_inversion = 0; - - dprintk("nxt6000: detected SP5730 tuner at 0x%02X\n", nxt->tuner_addr); - - } else { - printk("nxt6000: unable to detect tuner\n"); - continue; - } + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; + kfree(state); } - if (addr_nr == sizeof(demod_addr_tbl)) { - kfree(nxt); - return -ENODEV; - } +static struct dvb_frontend_ops nxt6000_ops; - nxt->demod_addr = demod_addr_tbl[addr_nr]; - - if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { - kfree(nxt); - return -ENOMEM; -} - - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = demod_addr_tbl[addr_nr]; - i2c_set_clientdata(client, (void *) nxt); - - ret = i2c_attach_client(client); - if (ret) - goto out; - - BUG_ON(!nxt->dvb); - - ret = dvb_register_frontend(nxt6000_ioctl, nxt->dvb, nxt, &nxt6000_info, THIS_MODULE); - if (ret) { - i2c_detach_client(client); - goto out; - } - - ret = 0; -out: - kfree(client); - kfree(nxt); - return ret; -} - -static int detach_client(struct i2c_client *client) +struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, + struct i2c_adapter* i2c) { - struct nxt6000_config *state = (struct nxt6000_config *) i2c_get_clientdata(client); - dvb_unregister_frontend(nxt6000_ioctl, state->dvb); - i2c_detach_client(client); - BUG_ON(state->dvb); - kfree(client); - kfree(state); - return 0; -} + struct nxt6000_state* state = NULL; -static int command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct nxt6000_config *state = (struct nxt6000_config *) i2c_get_clientdata(client); + /* allocate memory for the internal state */ + state = (struct nxt6000_state*) kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops)); + + /* check if the demod is there */ + if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; + } + +static struct dvb_frontend_ops nxt6000_ops = { + + .info = { + .name = "NxtWave NXT6000 DVB-T", + .type = FE_OFDM, + .frequency_min = 0, + .frequency_max = 863250000, + .frequency_stepsize = 62500, + /*.frequency_tolerance = *//* FIXME: 12% of SR */ + .symbol_rate_min = 0, /* FIXME */ + .symbol_rate_max = 9360000, /* FIXME */ + .symbol_rate_tolerance = 4000, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO, + }, - switch (cmd) { - case FE_REGISTER:{ - state->dvb = (struct dvb_adapter *) arg; - break; - } - case FE_UNREGISTER:{ - state->dvb = NULL; - break; - } - default: - return -EOPNOTSUPP; - } - return 0; -} + .release = nxt6000_release, + + .init = nxt6000_init, -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = "nxt6000", - .id = I2C_DRIVERID_DVBFE_NXT6000, - .flags = I2C_DF_NOTIFY, - .attach_adapter = attach_adapter, - .detach_client = detach_client, - .command = command, -}; + .set_frontend = nxt6000_set_frontend, -static struct i2c_client client_template = { - I2C_DEVNAME("nxt6000"), - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, + .read_status = nxt6000_read_status, }; -static __init int nxt6000_init(void) -{ - return i2c_add_driver(&driver); -} +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -static __exit void nxt6000_exit(void) -{ - if (i2c_del_driver(&driver)) - printk("nxt6000: driver deregistration failed\n"); -} +MODULE_DESCRIPTION("NxtWave NXT6000 DVB-T demodulator driver"); +MODULE_AUTHOR("Florian Schirmer"); +MODULE_LICENSE("GPL"); -module_init(nxt6000_init); -module_exit(nxt6000_exit); +EXPORT_SYMBOL(nxt6000_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/nxt6000.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/nxt6000.h 2004-12-22 09:07:08.887370794 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/nxt6000.h 2004-12-22 10:04:35.759366602 -0800 @@ -1,266 +1,43 @@ /* - * Public Include File for DRV6000 users - * (ie. NxtWave Communications - NXT6000 demodulator driver) - * - * Copyright (C) 2001 NxtWave Communications, Inc. - * - */ - -/* Nxt6000 Register Addresses and Bit Masks */ - -/* Maximum Register Number */ -#define MAXNXT6000REG (0x9A) - -/* 0x1B A_VIT_BER_0 aka 0x3A */ -#define A_VIT_BER_0 (0x1B) - -/* 0x1D A_VIT_BER_TIMER_0 aka 0x38 */ -#define A_VIT_BER_TIMER_0 (0x1D) - -/* 0x21 RS_COR_STAT */ -#define RS_COR_STAT (0x21) -#define RSCORESTATUS (0x03) - -/* 0x22 RS_COR_INTEN */ -#define RS_COR_INTEN (0x22) - -/* 0x23 RS_COR_INSTAT */ -#define RS_COR_INSTAT (0x23) -#define INSTAT_ERROR (0x04) -#define LOCK_LOSS_BITS (0x03) - -/* 0x24 RS_COR_SYNC_PARAM */ -#define RS_COR_SYNC_PARAM (0x24) -#define SYNC_PARAM (0x03) - -/* 0x25 BER_CTRL */ -#define BER_CTRL (0x25) -#define BER_ENABLE (0x02) -#define BER_RESET (0x01) - -/* 0x26 BER_PAY */ -#define BER_PAY (0x26) - -/* 0x27 BER_PKT_L */ -#define BER_PKT_L (0x27) -#define BER_PKTOVERFLOW (0x80) - -/* 0x30 VIT_COR_CTL */ -#define VIT_COR_CTL (0x30) -#define BER_CONTROL (0x02) -#define VIT_COR_MASK (0x82) -#define VIT_COR_RESYNC (0x80) - - -/* 0x32 VIT_SYNC_STATUS */ -#define VIT_SYNC_STATUS (0x32) -#define VITINSYNC (0x80) - -/* 0x33 VIT_COR_INTEN */ -#define VIT_COR_INTEN (0x33) -#define GLOBAL_ENABLE (0x80) - -/* 0x34 VIT_COR_INTSTAT */ -#define VIT_COR_INTSTAT (0x34) -#define BER_DONE (0x08) -#define BER_OVERFLOW (0x10) - -/* 0x38 OFDM_BERTimer */ /* Use the alias registers */ -#define A_VIT_BER_TIMER_0 (0x1D) - -/* 0x3A VIT_BER_TIMER_0 */ /* Use the alias registers */ -#define A_VIT_BER_0 (0x1B) - -/* 0x40 OFDM_COR_CTL */ -#define OFDM_COR_CTL (0x40) -#define COREACT (0x20) -#define HOLDSM (0x10) -#define WAIT_AGC (0x02) -#define WAIT_SYR (0x03) - -/* 0x41 OFDM_COR_STAT */ -#define OFDM_COR_STAT (0x41) -#define COR_STATUS (0x0F) -#define MONITOR_TPS (0x06) -#define TPSLOCKED (0x40) -#define AGCLOCKED (0x10) - -/* 0x42 OFDM_COR_INTEN */ -#define OFDM_COR_INTEN (0x42) -#define TPSRCVBAD (0x04) -#define TPSRCVCHANGED (0x02) -#define TPSRCVUPDATE (0x01) - -/* 0x43 OFDM_COR_INSTAT */ -#define OFDM_COR_INSTAT (0x43) - -/* 0x44 OFDM_COR_MODEGUARD */ -#define OFDM_COR_MODEGUARD (0x44) -#define FORCEMODE (0x08) -#define FORCEMODE8K (0x04) - -/* 0x45 OFDM_AGC_CTL */ -#define OFDM_AGC_CTL (0x45) -#define INITIAL_AGC_BW (0x08) -#define AGCNEG (0x02) -#define AGCLAST (0x10) - -/* 0x48 OFDM_AGC_TARGET */ -#define OFDM_AGC_TARGET (0x48) -#define OFDM_AGC_TARGET_DEFAULT (0x28) -#define OFDM_AGC_TARGET_IMPULSE (0x38) - -/* 0x49 OFDM_AGC_GAIN_1 */ -#define OFDM_AGC_GAIN_1 (0x49) - -/* 0x4B OFDM_ITB_CTL */ -#define OFDM_ITB_CTL (0x4B) -#define ITBINV (0x01) - -/* 0x4C OFDM_ITB_FREQ_1 */ -#define OFDM_ITB_FREQ_1 (0x4C) - -/* 0x4D OFDM_ITB_FREQ_2 */ -#define OFDM_ITB_FREQ_2 (0x4D) - -/* 0x4E OFDM_CAS_CTL */ -#define OFDM_CAS_CTL (0x4E) -#define ACSDIS (0x40) -#define CCSEN (0x80) - -/* 0x4F CAS_FREQ */ -#define CAS_FREQ (0x4F) - -/* 0x51 OFDM_SYR_CTL */ -#define OFDM_SYR_CTL (0x51) -#define SIXTH_ENABLE (0x80) -#define SYR_TRACKING_DISABLE (0x01) - -/* 0x52 OFDM_SYR_STAT */ -#define OFDM_SYR_STAT (0x52) -#define GI14_2K_SYR_LOCK (0x13) -#define GI14_8K_SYR_LOCK (0x17) -#define GI14_SYR_LOCK (0x10) - -/* 0x55 OFDM_SYR_OFFSET_1 */ -#define OFDM_SYR_OFFSET_1 (0x55) - -/* 0x56 OFDM_SYR_OFFSET_2 */ -#define OFDM_SYR_OFFSET_2 (0x56) - -/* 0x58 OFDM_SCR_CTL */ -#define OFDM_SCR_CTL (0x58) -#define SYR_ADJ_DECAY_MASK (0x70) -#define SYR_ADJ_DECAY (0x30) - -/* 0x59 OFDM_PPM_CTL_1 */ -#define OFDM_PPM_CTL_1 (0x59) -#define PPMMAX_MASK (0x30) -#define PPM256 (0x30) - -/* 0x5B OFDM_TRL_NOMINALRATE_1 */ -#define OFDM_TRL_NOMINALRATE_1 (0x5B) - -/* 0x5C OFDM_TRL_NOMINALRATE_2 */ -#define OFDM_TRL_NOMINALRATE_2 (0x5C) - -/* 0x5D OFDM_TRL_TIME_1 */ -#define OFDM_TRL_TIME_1 (0x5D) - -/* 0x60 OFDM_CRL_FREQ_1 */ -#define OFDM_CRL_FREQ_1 (0x60) - -/* 0x63 OFDM_CHC_CTL_1 */ -#define OFDM_CHC_CTL_1 (0x63) -#define MANMEAN1 (0xF0); -#define CHCFIR (0x01) - -/* 0x64 OFDM_CHC_SNR */ -#define OFDM_CHC_SNR (0x64) - -/* 0x65 OFDM_BDI_CTL */ -#define OFDM_BDI_CTL (0x65) -#define LP_SELECT (0x02) - -/* 0x67 OFDM_TPS_RCVD_1 */ -#define OFDM_TPS_RCVD_1 (0x67) -#define TPSFRAME (0x03) - -/* 0x68 OFDM_TPS_RCVD_2 */ -#define OFDM_TPS_RCVD_2 (0x68) - -/* 0x69 OFDM_TPS_RCVD_3 */ -#define OFDM_TPS_RCVD_3 (0x69) - -/* 0x6A OFDM_TPS_RCVD_4 */ -#define OFDM_TPS_RCVD_4 (0x6A) - -/* 0x6B OFDM_TPS_RESERVED_1 */ -#define OFDM_TPS_RESERVED_1 (0x6B) - -/* 0x6C OFDM_TPS_RESERVED_2 */ -#define OFDM_TPS_RESERVED_2 (0x6C) - -/* 0x73 OFDM_MSC_REV */ -#define OFDM_MSC_REV (0x73) - -/* 0x76 OFDM_SNR_CARRIER_2 */ -#define OFDM_SNR_CARRIER_2 (0x76) -#define MEAN_MASK (0x80) -#define MEANBIT (0x80) - -/* 0x80 ANALOG_CONTROL_0 */ -#define ANALOG_CONTROL_0 (0x80) -#define POWER_DOWN_ADC (0x40) - -/* 0x81 ENABLE_TUNER_IIC */ -#define ENABLE_TUNER_IIC (0x81) -#define ENABLE_TUNER_BIT (0x01) - -/* 0x82 EN_DMD_RACQ */ -#define EN_DMD_RACQ (0x82) -#define EN_DMD_RACQ_REG_VAL (0x81) -#define EN_DMD_RACQ_REG_VAL_14 (0x01) - -/* 0x84 SNR_COMMAND */ -#define SNR_COMMAND (0x84) -#define SNRStat (0x80) - -/* 0x85 SNRCARRIERNUMBER_LSB */ -#define SNRCARRIERNUMBER_LSB (0x85) - -/* 0x87 SNRMINTHRESHOLD_LSB */ -#define SNRMINTHRESHOLD_LSB (0x87) - -/* 0x89 SNR_PER_CARRIER_LSB */ -#define SNR_PER_CARRIER_LSB (0x89) - -/* 0x8B SNRBELOWTHRESHOLD_LSB */ -#define SNRBELOWTHRESHOLD_LSB (0x8B) - -/* 0x91 RF_AGC_VAL_1 */ -#define RF_AGC_VAL_1 (0x91) - -/* 0x92 RF_AGC_STATUS */ -#define RF_AGC_STATUS (0x92) - -/* 0x98 DIAG_CONFIG */ -#define DIAG_CONFIG (0x98) -#define DIAG_MASK (0x70) -#define TB_SET (0x10) -#define TRAN_SELECT (0x07) -#define SERIAL_SELECT (0x01) - -/* 0x99 SUB_DIAG_MODE_SEL */ -#define SUB_DIAG_MODE_SEL (0x99) -#define CLKINVERSION (0x01) - -/* 0x9A TS_FORMAT */ -#define TS_FORMAT (0x9A) -#define ERROR_SENSE (0x08) -#define VALID_SENSE (0x04) -#define SYNC_SENSE (0x02) -#define GATED_CLOCK (0x01) + NxtWave Communications - NXT6000 demodulator driver -#define NXT6000ASICDEVICE (0x0b) + Copyright (C) 2002-2003 Florian Schirmer + Copyright (C) 2003 Paul Andreassen + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef NXT6000_H +#define NXT6000_H + +#include + +struct nxt6000_config +{ + /* the demodulator's i2c address */ + u8 demod_address; + + /* should clock inversion be used? */ + u8 clock_inversion:1; + + /* PLL maintenance */ + int (*pll_init)(struct dvb_frontend* fe); + int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); +}; + +extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, + struct i2c_adapter* i2c); + +#endif // NXT6000_H Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/sp887x.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/sp887x.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/sp887x.c 2004-12-22 10:04:35.773364474 -0800 @@ -1,5 +1,5 @@ /* - Driver for the Microtune 7202D Frontend + Driver for the Spase sp887x demodulator */ /* @@ -16,74 +16,50 @@ #include #include "dvb_frontend.h" +#include "sp887x.h" -#define FRONTEND_NAME "dvbfe_sp887x" -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG FRONTEND_NAME ": " args); \ - } while (0) +struct sp887x_state { -static int debug; + struct i2c_adapter* i2c; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + struct dvb_frontend_ops ops; -#if 0 -#define LOG(dir,addr,buf,len) \ - do { \ - int i; \ - printk("%s (%02x):", dir, addr & 0xff); \ - for (i=0; iconfig->demod_address, .flags = 0, .buf = buf, .len = len }; int err; - LOG("i2c_writebytes", msg.addr, msg.buf, msg.len); - - if ((err = i2c_transfer (i2c, &msg, 1)) != 1) { + if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { printk ("%s: i2c write error (addr %02x, err == %i)\n", - __FUNCTION__, addr, err); + __FUNCTION__, state->config->demod_address, err); return -EREMOTEIO; } return 0; } -static int sp887x_writereg (struct i2c_adapter *i2c, u16 reg, u16 data) +static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data) { u8 b0 [] = { reg >> 8 , reg & 0xff, data >> 8, data & 0xff }; - struct i2c_msg msg = { .addr = 0x70, .flags = 0, .buf = b0, .len = 4 }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 4 }; int ret; - LOG("sp887x_writereg", msg.addr, msg.buf, msg.len); - - if ((ret = i2c_transfer(i2c, &msg, 1)) != 1) { + if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) { /** * in case of soft reset we ignore ACK errors... */ @@ -100,61 +76,60 @@ return 0; } -static u16 sp887x_readreg (struct i2c_adapter *i2c, u16 reg) +static int sp887x_readreg (struct sp887x_state* state, u16 reg) { u8 b0 [] = { reg >> 8 , reg & 0xff }; u8 b1 [2]; int ret; - struct i2c_msg msg[] = {{ .addr = 0x70, .flags = 0, .buf = b0, .len = 2 }, - { .addr = 0x70, .flags = I2C_M_RD, .buf = b1, .len = 2 }}; - - LOG("sp887x_readreg (w)", msg[0].addr, msg[0].buf, msg[0].len); - LOG("sp887x_readreg (r)", msg[1].addr, msg[1].buf, msg[1].len); + struct i2c_msg msg[] = {{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }}; - if ((ret = i2c_transfer(i2c, msg, 2)) != 2) + if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) { printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + return -1; + } return (((b1[0] << 8) | b1[1]) & 0xfff); } -static void sp887x_microcontroller_stop (struct i2c_adapter *fe) +static void sp887x_microcontroller_stop (struct sp887x_state* state) { dprintk("%s\n", __FUNCTION__); - sp887x_writereg(fe, 0xf08, 0x000); - sp887x_writereg(fe, 0xf09, 0x000); + sp887x_writereg(state, 0xf08, 0x000); + sp887x_writereg(state, 0xf09, 0x000); /* microcontroller STOP */ - sp887x_writereg(fe, 0xf00, 0x000); + sp887x_writereg(state, 0xf00, 0x000); } -static void sp887x_microcontroller_start (struct i2c_adapter *fe) +static void sp887x_microcontroller_start (struct sp887x_state* state) { dprintk("%s\n", __FUNCTION__); - sp887x_writereg(fe, 0xf08, 0x000); - sp887x_writereg(fe, 0xf09, 0x000); + sp887x_writereg(state, 0xf08, 0x000); + sp887x_writereg(state, 0xf09, 0x000); /* microcontroller START */ - sp887x_writereg(fe, 0xf00, 0x001); + sp887x_writereg(state, 0xf00, 0x001); } -static void sp887x_setup_agc (struct i2c_adapter *fe) +static void sp887x_setup_agc (struct sp887x_state* state) { /* setup AGC parameters */ dprintk("%s\n", __FUNCTION__); - sp887x_writereg(fe, 0x33c, 0x054); - sp887x_writereg(fe, 0x33b, 0x04c); - sp887x_writereg(fe, 0x328, 0x000); - sp887x_writereg(fe, 0x327, 0x005); - sp887x_writereg(fe, 0x326, 0x001); - sp887x_writereg(fe, 0x325, 0x001); - sp887x_writereg(fe, 0x324, 0x001); - sp887x_writereg(fe, 0x318, 0x050); - sp887x_writereg(fe, 0x317, 0x3fe); - sp887x_writereg(fe, 0x316, 0x001); - sp887x_writereg(fe, 0x313, 0x005); - sp887x_writereg(fe, 0x312, 0x002); - sp887x_writereg(fe, 0x306, 0x000); - sp887x_writereg(fe, 0x303, 0x000); + sp887x_writereg(state, 0x33c, 0x054); + sp887x_writereg(state, 0x33b, 0x04c); + sp887x_writereg(state, 0x328, 0x000); + sp887x_writereg(state, 0x327, 0x005); + sp887x_writereg(state, 0x326, 0x001); + sp887x_writereg(state, 0x325, 0x001); + sp887x_writereg(state, 0x324, 0x001); + sp887x_writereg(state, 0x318, 0x050); + sp887x_writereg(state, 0x317, 0x3fe); + sp887x_writereg(state, 0x316, 0x001); + sp887x_writereg(state, 0x313, 0x005); + sp887x_writereg(state, 0x312, 0x002); + sp887x_writereg(state, 0x306, 0x000); + sp887x_writereg(state, 0x303, 0x000); } #define BLOCKSIZE 30 @@ -162,8 +137,9 @@ /** * load firmware and setup MPEG interface... */ -static int sp887x_initial_setup (struct i2c_adapter *fe, const struct firmware *fw) +static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware *fw) { + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; u8 buf [BLOCKSIZE+2]; int i; int fw_size = fw->size; @@ -178,18 +154,18 @@ mem = fw->data + 10; /* soft reset */ - sp887x_writereg(fe, 0xf1a, 0x000); + sp887x_writereg(state, 0xf1a, 0x000); - sp887x_microcontroller_stop (fe); + sp887x_microcontroller_stop (state); printk ("%s: firmware upload... ", __FUNCTION__); /* setup write pointer to -1 (end of memory) */ /* bit 0x8000 in address is set to enable 13bit mode */ - sp887x_writereg(fe, 0x8f08, 0x1fff); + sp887x_writereg(state, 0x8f08, 0x1fff); /* dummy write (wrap around to start of memory) */ - sp887x_writereg(fe, 0x8f0a, 0x0000); + sp887x_writereg(state, 0x8f0a, 0x0000); for (i = 0; i < FW_SIZE; i += BLOCKSIZE) { int c = BLOCKSIZE; @@ -206,7 +182,7 @@ memcpy(&buf[2], mem + i, c); - if ((err = i2c_writebytes (fe, 0x70, buf, c+2)) < 0) { + if ((err = i2c_writebytes (state, buf, c+2)) < 0) { printk ("failed.\n"); printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err); return err; @@ -214,61 +190,37 @@ } /* don't write RS bytes between packets */ - sp887x_writereg(fe, 0xc13, 0x001); + sp887x_writereg(state, 0xc13, 0x001); /* suppress clock if (!data_valid) */ - sp887x_writereg(fe, 0xc14, 0x000); + sp887x_writereg(state, 0xc14, 0x000); /* setup MPEG interface... */ - sp887x_writereg(fe, 0xc1a, 0x872); - sp887x_writereg(fe, 0xc1b, 0x001); - sp887x_writereg(fe, 0xc1c, 0x000); /* parallel mode (serial mode == 1) */ - sp887x_writereg(fe, 0xc1a, 0x871); + sp887x_writereg(state, 0xc1a, 0x872); + sp887x_writereg(state, 0xc1b, 0x001); + sp887x_writereg(state, 0xc1c, 0x000); /* parallel mode (serial mode == 1) */ + sp887x_writereg(state, 0xc1a, 0x871); /* ADC mode, 2 for MT8872, 3 for SP8870/SP8871 */ - sp887x_writereg(fe, 0x301, 0x002); + sp887x_writereg(state, 0x301, 0x002); - sp887x_setup_agc(fe); + sp887x_setup_agc(state); /* bit 0x010: enable data valid signal */ - sp887x_writereg(fe, 0xd00, 0x010); - sp887x_writereg(fe, 0x0d1, 0x000); + sp887x_writereg(state, 0xd00, 0x010); + sp887x_writereg(state, 0x0d1, 0x000); + + /* setup the PLL */ + if (state->config->pll_init) { + sp887x_writereg(state, 0x206, 0x001); + state->config->pll_init(fe); + sp887x_writereg(state, 0x206, 0x000); + } printk ("done.\n"); return 0; }; -/** - * returns the actual tuned center frequency which can be used - * to initialise the AFC registers - */ -static int tsa5060_setup_pll (struct i2c_adapter *fe, int freq) -{ - u8 cfg, cpump, band_select; - u8 buf [4]; - u32 div; - - div = (36000000 + freq + 83333) / 166666; - cfg = 0x88; - - cpump = freq < 175000000 ? 2 : freq < 390000000 ? 1 : - freq < 470000000 ? 2 : freq < 750000000 ? 2 : 3; - - band_select = freq < 175000000 ? 0x0e : freq < 470000000 ? 0x05 : 0x03; - - buf [0] = (div >> 8) & 0x7f; - buf [1] = div & 0xff; - buf [2] = ((div >> 10) & 0x60) | cfg; - buf [3] = cpump | band_select; - - /* open i2c gate for PLL message transmission... */ - sp887x_writereg(fe, 0x206, 0x001); - i2c_writebytes(fe, 0x60, buf, 4); - sp887x_writereg(fe, 0x206, 0x000); - - return (div * 166666 - 36000000); -} - static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05) { int known_parameters = 1; @@ -362,7 +314,7 @@ } } -static void sp887x_correct_offsets (struct i2c_adapter *fe, +static void sp887x_correct_offsets (struct sp887x_state* state, struct dvb_frontend_parameters *p, int actual_freq) { @@ -385,17 +337,31 @@ frequency_shift = -frequency_shift; /* sample rate correction */ - sp887x_writereg(fe, 0x319, srate_correction[bw_index] >> 12); - sp887x_writereg(fe, 0x31a, srate_correction[bw_index] & 0xfff); + sp887x_writereg(state, 0x319, srate_correction[bw_index] >> 12); + sp887x_writereg(state, 0x31a, srate_correction[bw_index] & 0xfff); /* carrier offset correction */ - sp887x_writereg(fe, 0x309, frequency_shift >> 12); - sp887x_writereg(fe, 0x30a, frequency_shift & 0xfff); + sp887x_writereg(state, 0x309, frequency_shift >> 12); + sp887x_writereg(state, 0x30a, frequency_shift & 0xfff); } -static int sp887x_setup_frontend_parameters (struct i2c_adapter *fe, + + + + + + + + + + + + + +static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; int actual_freq, err; u16 val, reg0xc05; @@ -407,14 +373,17 @@ if ((err = configure_reg0xc05(p, ®0xc05))) return err; - sp887x_microcontroller_stop(fe); + sp887x_microcontroller_stop(state); - actual_freq = tsa5060_setup_pll(fe, p->frequency); + /* setup the PLL */ + sp887x_writereg(state, 0x206, 0x001); + actual_freq = state->config->pll_set(fe, p); + sp887x_writereg(state, 0x206, 0x000); - /* read status reg in order to clear pending irqs */ - sp887x_readreg(fe, 0x200); + /* read status reg in order to clear u.ofdm.bandwidth == BANDWIDTH_6_MHZ) @@ -424,15 +393,15 @@ else val = 0; - sp887x_writereg(fe, 0x311, val); + sp887x_writereg(state, 0x311, val); /* scan order: 2k first = 0, 8k first = 1 */ if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K) - sp887x_writereg(fe, 0x338, 0x000); + sp887x_writereg(state, 0x338, 0x000); else - sp887x_writereg(fe, 0x338, 0x001); + sp887x_writereg(state, 0x338, 0x001); - sp887x_writereg(fe, 0xc05, reg0xc05); + sp887x_writereg(state, 0xc05, reg0xc05); if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ) val = 2 << 3; @@ -444,29 +413,19 @@ /* enable OFDM and SAW bits as lock indicators in sync register 0xf17, * optimize algorithm for given bandwidth... */ - sp887x_writereg(fe, 0xf14, 0x160 | val); - sp887x_writereg(fe, 0xf15, 0x000); + sp887x_writereg(state, 0xf14, 0x160 | val); + sp887x_writereg(state, 0xf15, 0x000); - sp887x_microcontroller_start(fe); + sp887x_microcontroller_start(state); return 0; } -static int sp887x_ioctl(struct dvb_frontend *f, unsigned int cmd, void *arg) -{ - struct sp887x_state *state = (struct sp887x_state *) f->data; - struct i2c_adapter *fe = state->i2c; - - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &sp887x_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: +static int sp887x_read_status(struct dvb_frontend* fe, fe_status_t* status) { - u16 snr12 = sp887x_readreg(fe, 0xf16); - u16 sync0x200 = sp887x_readreg(fe, 0x200); - u16 sync0xf17 = sp887x_readreg(fe, 0xf17); - fe_status_t *status = arg; + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + u16 snr12 = sp887x_readreg(state, 0xf16); + u16 sync0x200 = sp887x_readreg(state, 0x200); + u16 sync0xf17 = sp887x_readreg(state, 0xf17); *status = 0; @@ -492,212 +451,172 @@ steps); } - break; - + return 0; } - case FE_READ_BER: +static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber) { - u32* ber = arg; - *ber = (sp887x_readreg(fe, 0xc08) & 0x3f) | - (sp887x_readreg(fe, 0xc07) << 6); - sp887x_writereg(fe, 0xc08, 0x000); - sp887x_writereg(fe, 0xc07, 0x000); + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + + *ber = (sp887x_readreg(state, 0xc08) & 0x3f) | + (sp887x_readreg(state, 0xc07) << 6); + sp887x_writereg(state, 0xc08, 0x000); + sp887x_writereg(state, 0xc07, 0x000); if (*ber >= 0x3fff0) *ber = ~0; - break; + return 0; } - case FE_READ_SIGNAL_STRENGTH: // FIXME: correct registers ? +static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - u16 snr12 = sp887x_readreg(fe, 0xf16); + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + + u16 snr12 = sp887x_readreg(state, 0xf16); u32 signal = 3 * (snr12 << 4); - *((u16*) arg) = (signal < 0xffff) ? signal : 0xffff; - break; - } + *strength = (signal < 0xffff) ? signal : 0xffff; - case FE_READ_SNR: - { - u16 snr12 = sp887x_readreg(fe, 0xf16); - *(u16*) arg = (snr12 << 4) | (snr12 >> 8); - break; + return 0; } - case FE_READ_UNCORRECTED_BLOCKS: +static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr) { - u32 *ublocks = (u32 *) arg; - *ublocks = sp887x_readreg(fe, 0xc0c); - if (*ublocks == 0xfff) - *ublocks = ~0; - break; - } + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; - case FE_SET_FRONTEND: - return sp887x_setup_frontend_parameters(fe, arg); - - case FE_GET_FRONTEND: // FIXME: read known values back from Hardware... - break; + u16 snr12 = sp887x_readreg(state, 0xf16); + *snr = (snr12 << 4) | (snr12 >> 8); - case FE_SLEEP: - /* tristate TS output and disable interface pins */ - sp887x_writereg(fe, 0xc18, 0x000); - break; - - case FE_INIT: - /* enable TS output and interface pins */ - sp887x_writereg(fe, 0xc18, 0x00d); - break; - - case FE_GET_TUNE_SETTINGS: - { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; - fesettings->min_delay_ms = 350; - fesettings->step_size = 166666*2; - fesettings->max_drift = (166666*2)+1; return 0; } - default: - return -EOPNOTSUPP; - }; +static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + + *ucblocks = sp887x_readreg(state, 0xc0c); + if (*ucblocks == 0xfff) + *ucblocks = ~0; return 0; } -static struct i2c_client client_template; - -static int attach_adapter(struct i2c_adapter *adapter) +static int sp887x_sleep(struct dvb_frontend* fe) { - struct i2c_client *client; - struct sp887x_state *state; - const struct firmware *fw; - int ret; - - struct i2c_msg msg = {.addr = 0x70, .flags = 0, .buf = NULL, .len = 0 }; - - dprintk ("%s\n", __FUNCTION__); - - if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { - return -ENOMEM; - } + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; - if (NULL == (state = kmalloc(sizeof(struct sp887x_state), GFP_KERNEL))) { - kfree(client); - return -ENOMEM; - } - state->i2c = adapter; + /* tristate TS output and disable interface pins */ + sp887x_writereg(state, 0xc18, 0x000); - if (i2c_transfer (adapter, &msg, 1) != 1) { - kfree(state); - kfree(client); - return -ENODEV; + return 0; } - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - i2c_set_clientdata(client, (void*)state); - - ret = i2c_attach_client(client); - if (ret) { - kfree(client); - kfree(state); - return ret; - } +static int sp887x_init(struct dvb_frontend* fe) +{ + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + const struct firmware *fw = NULL; + int ret; + if (!state->initialised) { /* request the firmware, this will block until someone uploads it */ printk("sp887x: waiting for firmware upload...\n"); - ret = request_firmware(&fw, SP887X_DEFAULT_FIRMWARE, &client->dev); + ret = state->config->request_firmware(fe, &fw, SP887X_DEFAULT_FIRMWARE); if (ret) { printk("sp887x: no firmware upload (timeout or file not found?)\n"); - goto out; + return ret; } - ret = sp887x_initial_setup(adapter, fw); + ret = sp887x_initial_setup(fe, fw); if (ret) { printk("sp887x: writing firmware to device failed\n"); - goto out; + release_firmware(fw); + return ret; } - - ret = dvb_register_frontend(sp887x_ioctl, state->dvb, state, - &sp887x_info, THIS_MODULE); - if (ret) { - printk("sp887x: registering frontend to dvb-core failed.\n"); - goto out; + state->initialised = 1; } + /* enable TS output and interface pins */ + sp887x_writereg(state, 0xc18, 0x00d); + return 0; -out: - release_firmware(fw); - i2c_detach_client(client); - kfree(client); - kfree(state); - return ret; } -static int detach_client(struct i2c_client *client) +static int sp887x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - struct sp887x_state *state = (struct sp887x_state*)i2c_get_clientdata(client); - - dprintk ("%s\n", __FUNCTION__); - - dvb_unregister_frontend (sp887x_ioctl, state->dvb); - i2c_detach_client(client); - BUG_ON(state->dvb); - kfree(client); - kfree(state); - return 0; + fesettings->min_delay_ms = 350; + fesettings->step_size = 166666*2; + fesettings->max_drift = (166666*2)+1; + return 0; } -static int command (struct i2c_client *client, unsigned int cmd, void *arg) +static void sp887x_release(struct dvb_frontend* fe) { - struct sp887x_state *state = (struct sp887x_state*)i2c_get_clientdata(client); - - dprintk ("%s\n", __FUNCTION__); - - switch (cmd) { - case FE_REGISTER: - state->dvb = (struct dvb_adapter*)arg; - break; - case FE_UNREGISTER: - state->dvb = NULL; - break; - default: - return -EOPNOTSUPP; - } - return 0; + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + kfree(state); } -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = FRONTEND_NAME, - .id = I2C_DRIVERID_DVBFE_SP887X, - .flags = I2C_DF_NOTIFY, - .attach_adapter = attach_adapter, - .detach_client = detach_client, - .command = command, -}; - -static struct i2c_client client_template = { - .name = FRONTEND_NAME, - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, -}; +static struct dvb_frontend_ops sp887x_ops; -static int __init init_sp887x(void) +struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, + struct i2c_adapter* i2c) { - return i2c_add_driver(&driver); -} + struct sp887x_state* state = NULL; -static void __exit exit_sp887x(void) -{ - if (i2c_del_driver(&driver)) - printk("sp887x: driver deregistration failed\n"); -} + /* allocate memory for the internal state */ + state = (struct sp887x_state*) kmalloc(sizeof(struct sp887x_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &sp887x_ops, sizeof(struct dvb_frontend_ops)); + state->initialised = 0; + + /* check if the demod is there */ + if (sp887x_readreg(state, 0x0200) < 0) goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; +} + +static struct dvb_frontend_ops sp887x_ops = { + + .info = { + .name = "Spase SP887x DVB-T", + .type = FE_OFDM, + .frequency_min = 50500000, + .frequency_max = 858000000, + .frequency_stepsize = 166666, + .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 | + FE_CAN_RECOVER + }, + + .release = sp887x_release, + + .init = sp887x_init, + .sleep = sp887x_sleep, + + .set_frontend = sp887x_setup_frontend_parameters, + .get_tune_settings = sp887x_get_tune_settings, + + .read_status = sp887x_read_status, + .read_ber = sp887x_read_ber, + .read_signal_strength = sp887x_read_signal_strength, + .read_snr = sp887x_read_snr, + .read_ucblocks = sp887x_read_ucblocks, +}; -module_init(init_sp887x); -module_exit(exit_sp887x); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("sp887x DVB-T demodulator driver"); +MODULE_DESCRIPTION("Spase sp887x DVB-T demodulator driver"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(sp887x_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/stv0299.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/stv0299.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/stv0299.c 2004-12-22 10:04:35.800360370 -0800 @@ -1,8 +1,5 @@ /* - Universal driver for STV0299/TDA5059/SL1935 based - DVB QPSK frontends - - Alps BSRU6, LG TDQB-S00x + Driver for ST STV0299 demodulator Copyright (C) 2001-2002 Convergence Integrated Media GmbH , @@ -54,236 +51,42 @@ #include #include "dvb_frontend.h" +#include "stv0299.h" -#define FRONTEND_NAME "dvbfe_stv0299" - -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG FRONTEND_NAME ": " args); \ - } while (0) - -static int debug; -static int stv0299_status; - -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -module_param(stv0299_status, int, 0444); -MODULE_PARM_DESC(stv0299_status, "Which status value to support " - "(0 == BER (default), 1 == UCBLOCKS)"); +struct stv0299_state { -#define STATUS_BER 0 -#define STATUS_UCBLOCKS 1 + struct i2c_adapter* i2c; + struct dvb_frontend_ops ops; -/* frontend types */ -#define UNKNOWN_FRONTEND -1 -#define PHILIPS_SU1278_TSA 0 // SU1278 with TSA5059 synth and datasheet recommended settings -#define ALPS_BSRU6 1 -#define LG_TDQF_S001F 2 -#define PHILIPS_SU1278_TUA 3 // SU1278 with TUA6100 synth -#define SAMSUNG_TBMU24112IMB 4 -#define PHILIPS_SU1278_TSA_TT 5 // SU1278 with TSA5059 synth and TechnoTrend settings -#define PHILIPS_SU1278_TSA_TY 6 // SU1278 with TUA5059 synth and Typhoon wiring -#define PHILIPS_SU1278_TSA_CI 7 // SU1278 with TUA5059 synth and TerraTec Cinergy wiring - -/* Master Clock = 88 MHz */ -#define M_CLK (88000000UL) - -/* Master Clock for TT cards = 64 MHz */ -#define M_CLK_SU1278_TSA_TT (64000000UL) - -static struct dvb_frontend_info uni0299_info = { - .name = "STV0299/TSA5059/SL1935 based", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 125, /* kHz for QPSK frontends */ - .frequency_tolerance = M_CLK/2000, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, - .symbol_rate_tolerance = 500, /* ppm */ - .notifier_delay = 0, - .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_QPSK | - FE_CAN_FEC_AUTO -}; + const struct stv0299_config* config; + struct dvb_frontend frontend; -struct stv0299_state { - u8 tuner_type; u8 initialised:1; u32 tuner_frequency; u32 symbol_rate; fe_code_rate_t fec_inner; - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; -}; - - -static u8 init_tab [] = { - 0x04, 0x7d, /* F22FR = 0x7d */ - /* F22 = f_VCO / 128 / 0x7d = 22 kHz */ - - /* I2C bus repeater */ - 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ - - /* general purpose DAC registers */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ - 0x07, 0x00, /* DAC LSB */ - - /* DiSEqC registers */ - 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ - 0x09, 0x00, /* FIFO */ - - /* Input/Output configuration register */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ - /* OP0 ctl = Normal, OP0 val = 1 (18 V) */ - /* Nyquist filter = 00, QPSK reverse = 0 */ - - /* AGC1 control register */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ - - /* Timing loop register */ - 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - - 0x10, 0x3f, // AGC2 0x3d - - 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on - - 0x15, 0xc9, // lock detector threshold - - 0x16, 0x00, - 0x17, 0x00, - 0x18, 0x00, - 0x19, 0x00, - 0x1a, 0x00, - - 0x1f, 0x50, - - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - - 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 - - 0x29, 0x1e, // 1/2 threshold - 0x2a, 0x14, // 2/3 threshold - 0x2b, 0x0f, // 3/4 threshold - 0x2c, 0x09, // 5/6 threshold - 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, - - 0x31, 0x1f, // test all FECs - - 0x32, 0x19, // viterbi and synchro search - 0x33, 0xfc, // rs control - 0x34, 0x93, // error control -}; - - -static u8 init_tab_samsung [] = { - 0x01, 0x15, - 0x02, 0x00, - 0x03, 0x00, - 0x04, 0x7D, - 0x05, 0x35, - 0x06, 0x02, - 0x07, 0x00, - 0x08, 0xC3, - 0x0C, 0x00, - 0x0D, 0x81, - 0x0E, 0x23, - 0x0F, 0x12, - 0x10, 0x7E, - 0x11, 0x84, - 0x12, 0xB9, - 0x13, 0x88, - 0x14, 0x89, - 0x15, 0xC9, - 0x16, 0x00, - 0x17, 0x5C, - 0x18, 0x00, - 0x19, 0x00, - 0x1A, 0x00, - 0x1C, 0x00, - 0x1D, 0x00, - 0x1E, 0x00, - 0x1F, 0x3A, - 0x20, 0x2E, - 0x21, 0x80, - 0x22, 0xFF, - 0x23, 0xC1, - 0x28, 0x00, - 0x29, 0x1E, - 0x2A, 0x14, - 0x2B, 0x0F, - 0x2C, 0x09, - 0x2D, 0x05, - 0x31, 0x1F, - 0x32, 0x19, - 0x33, 0xFE, - 0x34, 0x93 + int errmode; }; +#define STATUS_BER 0 +#define STATUS_UCBLOCKS 1 -static u8 init_tab_su1278_tsa_tt [] = { - 0x01, 0x0f, - 0x02, 0x30, - 0x03, 0x00, - 0x04, 0x5b, - 0x05, 0x85, - 0x06, 0x02, - 0x07, 0x00, - 0x08, 0x02, - 0x09, 0x00, - 0x0C, 0x01, - 0x0D, 0x81, - 0x0E, 0x44, - 0x0f, 0x14, - 0x10, 0x3c, - 0x11, 0x84, - 0x12, 0xda, - 0x13, 0x97, - 0x14, 0x95, - 0x15, 0xc9, - 0x16, 0x19, - 0x17, 0x8c, - 0x18, 0x59, - 0x19, 0xf8, - 0x1a, 0xfe, - 0x1c, 0x7f, - 0x1d, 0x00, - 0x1e, 0x00, - 0x1f, 0x50, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x28, 0x00, - 0x29, 0x28, - 0x2a, 0x14, - 0x2b, 0x0f, - 0x2c, 0x09, - 0x2d, 0x09, - 0x31, 0x1f, - 0x32, 0x19, - 0x33, 0xfc, - 0x34, 0x13 -}; +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "stv0299: " args); \ + } while (0) -static int stv0299_set_FEC (struct i2c_adapter *i2c, fe_code_rate_t fec); -static int stv0299_set_symbolrate (struct i2c_adapter *i2c, u32 srate, int tuner_type); -static int stv0299_writereg (struct i2c_adapter *i2c, u8 reg, u8 data) +static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data) { int ret; u8 buf [] = { reg, data }; - struct i2c_msg msg = { .addr = 0x68, .flags = 0, .buf = buf, .len = 2 }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; - ret = i2c_transfer (i2c, &msg, 1); + ret = i2c_transfer (state->i2c, &msg, 1); if (ret != 1) dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, " @@ -292,16 +95,23 @@ return (ret != 1) ? -EREMOTEIO : 0; } +int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + return stv0299_writeregI(state, reg, data); +} + -static u8 stv0299_readreg (struct i2c_adapter *i2c, u8 reg) +static u8 stv0299_readreg (struct stv0299_state* state, u8 reg) { int ret; u8 b0 [] = { reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = 0x68, .flags = 0, .buf = b0, .len = 1 }, - { .addr = 0x68, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - ret = i2c_transfer (i2c, msg, 2); + ret = i2c_transfer (state->i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", @@ -311,13 +121,13 @@ } -static int stv0299_readregs (struct i2c_adapter *i2c, u8 reg1, u8 *b, u8 len) +static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len) { int ret; - struct i2c_msg msg [] = { { .addr = 0x68, .flags = 0, .buf = ®1, .len = 1 }, - { .addr = 0x68, .flags = I2C_M_RD, .buf = b, .len = len } }; + struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = ®1, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } }; - ret = i2c_transfer (i2c, msg, 2); + ret = i2c_transfer (state->i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); @@ -326,373 +136,44 @@ } -static int pll_write (struct i2c_adapter *i2c, u8 addr, u8 *data, int len) -{ - int ret; - struct i2c_msg msg = { .addr = addr, .buf = data, .len = len }; - - - stv0299_writereg(i2c, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ - - ret = i2c_transfer (i2c, &msg, 1); - - stv0299_writereg(i2c, 0x05, 0x35); /* disable i2c repeater on stv0299 */ - - if (ret != 1) - dprintk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); - - return (ret != 1) ? -1 : 0; -} - - -static int sl1935_set_tv_freq (struct i2c_adapter *i2c, u32 freq, int ftype) -{ - u8 buf[4]; - u32 div; - - div = freq / 125; - - dprintk("%s : freq = %i, div = %i\n", __FUNCTION__, freq, div); - - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = 0x84; // 0xC4 - buf[3] = 0x08; - - if (freq < 1500000) buf[3] |= 0x10; - - return pll_write (i2c, 0x61, buf, sizeof(buf)); -} - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 125 kHz. - */ -static int tsa5059_set_tv_freq (struct i2c_adapter *i2c, u32 freq, int ftype, int srate) -{ - u8 addr; - u32 div; - u8 buf[4]; - int divisor, regcode; - - dprintk ("%s: freq %i, ftype %i\n", __FUNCTION__, freq, ftype); - - if ((freq < 950000) || (freq > 2150000)) return -EINVAL; - - if (ftype == PHILIPS_SU1278_TSA_TT) { - divisor = 500; - regcode = 2; - } else { - divisor = 125; - regcode = 4; - } - - // setup frequency divisor - div = (freq + (divisor - 1)) / divisor; // round correctly - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = 0x80 | ((div & 0x18000) >> 10) | regcode; - buf[3] = 0; - - // tuner-specific settings - switch(ftype) { - case PHILIPS_SU1278_TSA: - case PHILIPS_SU1278_TSA_TT: - case PHILIPS_SU1278_TSA_TY: - case PHILIPS_SU1278_TSA_CI: - if (ftype == PHILIPS_SU1278_TSA_TY || ftype == PHILIPS_SU1278_TSA_CI) - addr = 0x61; - else - addr = 0x60; - - buf[3] |= 0x20; - - if (srate < 4000000) buf[3] |= 1; - - if (freq < 1250000) buf[3] |= 0; - else if (freq < 1550000) buf[3] |= 0x40; - else if (freq < 2050000) buf[3] |= 0x80; - else if (freq < 2150000) buf[3] |= 0xC0; - break; - - case ALPS_BSRU6: - addr = 0x61; - buf[3] = 0xC4; - if (freq > 1530000) buf[3] = 0xc0; - break; - - default: - return -EINVAL; - } - - return pll_write (i2c, addr, buf, sizeof(buf)); -} - - -#define MIN2(a,b) ((a) < (b) ? (a) : (b)) -#define MIN3(a,b,c) MIN2(MIN2(a,b),c) - -static int tua6100_set_tv_freq (struct i2c_adapter *i2c, u32 freq, - int ftype, int srate) -{ - u8 reg0 [2] = { 0x00, 0x00 }; - u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 }; - u8 reg2 [3] = { 0x02, 0x00, 0x00 }; - int _fband; - int first_ZF; - int R, A, N, P, M; - int err; - - first_ZF = (freq) / 1000; - - if (abs(MIN2(abs(first_ZF-1190),abs(first_ZF-1790))) < - abs(MIN3(abs(first_ZF-1202),abs(first_ZF-1542),abs(first_ZF-1890)))) - _fband = 2; - else - _fband = 3; - - if (_fband == 2) { - if (((first_ZF >= 950) && (first_ZF < 1350)) || - ((first_ZF >= 1430) && (first_ZF < 1950))) - reg0[1] = 0x07; - else if (((first_ZF >= 1350) && (first_ZF < 1430)) || - ((first_ZF >= 1950) && (first_ZF < 2150))) - reg0[1] = 0x0B; - } - - if(_fband == 3) { - if (((first_ZF >= 950) && (first_ZF < 1350)) || - ((first_ZF >= 1455) && (first_ZF < 1950))) - reg0[1] = 0x07; - else if (((first_ZF >= 1350) && (first_ZF < 1420)) || - ((first_ZF >= 1950) && (first_ZF < 2150))) - reg0[1] = 0x0B; - else if ((first_ZF >= 1420) && (first_ZF < 1455)) - reg0[1] = 0x0F; -} - - if (first_ZF > 1525) - reg1[1] |= 0x80; - else - reg1[1] &= 0x7F; - - if (_fband == 2) { - if (first_ZF > 1430) { /* 1430MHZ */ - reg1[1] &= 0xCF; /* N2 */ - reg2[1] &= 0xCF; /* R2 */ - reg2[1] |= 0x10; - } else { - reg1[1] &= 0xCF; /* N2 */ - reg1[1] |= 0x20; - reg2[1] &= 0xCF; /* R2 */ - reg2[1] |= 0x10; - } -} - - if (_fband == 3) { - if ((first_ZF >= 1455) && - (first_ZF < 1630)) { - reg1[1] &= 0xCF; /* N2 */ - reg1[1] |= 0x20; - reg2[1] &= 0xCF; /* R2 */ - } else { - if (first_ZF < 1455) { - reg1[1] &= 0xCF; /* N2 */ - reg1[1] |= 0x20; - reg2[1] &= 0xCF; /* R2 */ - reg2[1] |= 0x10; - } else { - if (first_ZF >= 1630) { - reg1[1] &= 0xCF; /* N2 */ - reg2[1] &= 0xCF; /* R2 */ - reg2[1] |= 0x10; - } - } - } - } - - /* set ports, enable P0 for symbol rates > 4Ms/s */ - if (srate >= 4000000) - reg1[1] |= 0x0c; - else - reg1[1] |= 0x04; - - reg2[1] |= 0x0c; - - R = 64; - A = 64; - P = 64; //32 - - M = (freq * R) / 4; /* in Mhz */ - N = (M - A * 1000) / (P * 1000); - - reg1[1] |= (N >> 9) & 0x03; - reg1[2] = (N >> 1) & 0xff; - reg1[3] = (N << 7) & 0x80; - - reg2[1] |= (R >> 8) & 0x03; - reg2[2] = R & 0xFF; /* R */ - - reg1[3] |= A & 0x7f; /* A */ - - if (P == 64) - reg1[1] |= 0x40; /* Prescaler 64/65 */ - - reg0[1] |= 0x03; - - if ((err = pll_write(i2c, 0x60, reg0, sizeof(reg0)))) - return err; - - if ((err = pll_write(i2c, 0x60, reg1, sizeof(reg1)))) - return err; - - if ((err = pll_write(i2c, 0x60, reg2, sizeof(reg2)))) - return err; - - return 0; -} - - -static int pll_set_tv_freq (struct i2c_adapter *i2c, u32 freq, int ftype, int srate) -{ - switch(ftype) { - case SAMSUNG_TBMU24112IMB: - return sl1935_set_tv_freq(i2c, freq, ftype); - - case LG_TDQF_S001F: - return sl1935_set_tv_freq(i2c, freq, ftype); - - case PHILIPS_SU1278_TUA: - return tua6100_set_tv_freq(i2c, freq, ftype, srate); - - default: - return tsa5059_set_tv_freq(i2c, freq, ftype, srate); -} -} - -#if 0 -static int tsa5059_read_status (struct i2c_adapter *i2c) -{ - int ret; - u8 rpt1 [] = { 0x05, 0xb5 }; - u8 stat [] = { 0 }; - - struct i2c_msg msg [] = {{ .addr = 0x68, .flags = 0, .buf = rpt1, .len = 2 }, - { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; - - dprintk ("%s\n", __FUNCTION__); - - ret = i2c_transfer (i2c, msg, 2); - - if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - - return stat[0]; -} -#endif - - -static int stv0299_init (struct i2c_adapter *i2c, int ftype) -{ - int i; - - dprintk("stv0299: init chip\n"); - - switch(ftype) { - case SAMSUNG_TBMU24112IMB: - dprintk("%s: init stv0299 chip for Samsung TBMU24112IMB\n", __FUNCTION__); - - for (i=0; i 4) @@ -710,13 +191,13 @@ } -static int stv0299_wait_diseqc_fifo (struct i2c_adapter *i2c, int timeout) +static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout) { unsigned long start = jiffies; dprintk ("%s\n", __FUNCTION__); - while (stv0299_readreg(i2c, 0x0a) & 1) { + while (stv0299_readreg(state, 0x0a) & 1) { if (jiffies - start > timeout) { dprintk ("%s: timeout!!\n", __FUNCTION__); return -ETIMEDOUT; @@ -728,13 +209,13 @@ } -static int stv0299_wait_diseqc_idle (struct i2c_adapter *i2c, int timeout) +static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout) { unsigned long start = jiffies; dprintk ("%s\n", __FUNCTION__); - while ((stv0299_readreg(i2c, 0x0a) & 3) != 2 ) { + while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) { if (jiffies - start > timeout) { dprintk ("%s: timeout!!\n", __FUNCTION__); return -ETIMEDOUT; @@ -745,101 +226,156 @@ return 0; } +static int stv0299_set_symbolrate (struct dvb_frontend* fe, u32 srate) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + u64 big = srate; + u32 ratio; + + // check rate is within limits + if ((srate < 1000000) || (srate > 45000000)) return -EINVAL; + + // calculate value to program + big = big << 20; + big += (state->config->mclk-1); // round correctly + do_div(big, state->config->mclk); + ratio = big << 4; + + return state->config->set_symbol_rate(fe, srate, ratio); +} + + +static int stv0299_get_symbolrate (struct stv0299_state* state) +{ + u32 Mclk = state->config->mclk / 4096L; + u32 srate; + s32 offset; + u8 sfr[3]; + s8 rtf; + + dprintk ("%s\n", __FUNCTION__); + + stv0299_readregs (state, 0x1f, sfr, 3); + stv0299_readregs (state, 0x1a, &rtf, 1); + + srate = (sfr[0] << 8) | sfr[1]; + srate *= Mclk; + srate /= 16; + srate += (sfr[2] >> 4) * Mclk / 256; + offset = (s32) rtf * (srate / 4096L); + offset /= 128; + + dprintk ("%s : srate = %i\n", __FUNCTION__, srate); + dprintk ("%s : ofset = %i\n", __FUNCTION__, offset); + + srate += offset; + + srate += 1000; + srate /= 2000; + srate *= 2000; + + return srate; +} + + + + + + + + + + -static int stv0299_send_diseqc_msg (struct i2c_adapter *i2c, + + + +static int stv0299_send_diseqc_msg (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *m) { + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; u8 val; int i; dprintk ("%s\n", __FUNCTION__); - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; - val = stv0299_readreg (i2c, 0x08); + val = stv0299_readreg (state, 0x08); - if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x6)) /* DiSEqC mode */ + if (stv0299_writeregI (state, 0x08, (val & ~0x7) | 0x6)) /* DiSEqC mode */ return -EREMOTEIO; for (i=0; imsg_len; i++) { - if (stv0299_wait_diseqc_fifo (i2c, 100) < 0) + if (stv0299_wait_diseqc_fifo (state, 100) < 0) return -ETIMEDOUT; - if (stv0299_writereg (i2c, 0x09, m->msg[i])) + if (stv0299_writeregI (state, 0x09, m->msg[i])) return -EREMOTEIO; } - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; return 0; } -static int stv0299_send_diseqc_burst (struct i2c_adapter *i2c, fe_sec_mini_cmd_t burst) +static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) { + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; u8 val; dprintk ("%s\n", __FUNCTION__); - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; - val = stv0299_readreg (i2c, 0x08); + val = stv0299_readreg (state, 0x08); - if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x2)) /* burst mode */ + if (stv0299_writeregI (state, 0x08, (val & ~0x7) | 0x2)) /* burst mode */ return -EREMOTEIO; - if (stv0299_writereg (i2c, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff)) + if (stv0299_writeregI (state, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff)) return -EREMOTEIO; - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; - if (stv0299_writereg (i2c, 0x08, val)) + if (stv0299_writeregI (state, 0x08, val)) return -EREMOTEIO; return 0; } -static int stv0299_set_tone (struct i2c_adapter *i2c, fe_sec_tone_mode_t tone) +static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; u8 val; - dprintk("%s: %s\n", __FUNCTION__, - tone == SEC_TONE_ON ? "SEC_TONE_ON" : - tone == SEC_TONE_OFF ? "SEC_TONE_OFF" : "??"); - - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; - val = stv0299_readreg (i2c, 0x08); + val = stv0299_readreg (state, 0x08); switch (tone) { case SEC_TONE_ON: - { - dprintk("%s: TONE_ON\n", __FUNCTION__); - return stv0299_writereg (i2c, 0x08, val | 0x3); - } + return stv0299_writeregI (state, 0x08, val | 0x3); + case SEC_TONE_OFF: - { - dprintk("%s: TONE_OFF\n", __FUNCTION__); - return stv0299_writereg (i2c, 0x08, (val & ~0x3) | 0x02); - } + return stv0299_writeregI (state, 0x08, (val & ~0x3) | 0x02); + default: - { - dprintk("%s: TONE INVALID\n", __FUNCTION__); return -EINVAL; } - }; } -static int stv0299_set_voltage (struct i2c_adapter *i2c, fe_sec_voltage_t voltage, - int tuner_type) +static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) { + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; u8 reg0x08; u8 reg0x0c; @@ -847,8 +383,8 @@ voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); - reg0x08 = stv0299_readreg (i2c, 0x08); - reg0x0c = stv0299_readreg (i2c, 0x0c); + reg0x08 = stv0299_readreg (state, 0x08); + reg0x0c = stv0299_readreg (state, 0x0c); /** * H/V switching over OP0, OP1 and OP2 are LNB power enable bits @@ -856,37 +392,28 @@ reg0x0c &= 0x0f; if (voltage == SEC_VOLTAGE_OFF) { - stv0299_writereg (i2c, 0x0c, 0x00); /* LNB power off! */ - return stv0299_writereg (i2c, 0x08, 0x00); /* LNB power off! */ + stv0299_writeregI (state, 0x0c, 0x00); /* LNB power off! */ + return stv0299_writeregI (state, 0x08, 0x00); /* LNB power off! */ } - if (tuner_type == PHILIPS_SU1278_TSA_CI) - { - stv0299_writereg (i2c, 0x08, reg0x08 & 0xBF); // switch LNB power on OP2/LOCK pin off - } - else - { - stv0299_writereg (i2c, 0x08, reg0x08 | 0x40); - } + stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6)); switch (voltage) { case SEC_VOLTAGE_13: - if (tuner_type == PHILIPS_SU1278_TSA_TY || tuner_type == PHILIPS_SU1278_TSA_CI) - return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x10); - else - return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x40); + if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) reg0x0c |= 0x10; + else reg0x0c |= 0x40; - case SEC_VOLTAGE_18: - return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x50); + return stv0299_writeregI(state, 0x0c, reg0x0c); + case SEC_VOLTAGE_18: + return stv0299_writeregI(state, 0x0c, reg0x0c | 0x50); default: return -EINVAL; }; } -static int stv0299_send_legacy_dish_cmd(struct i2c_adapter *i2c, u32 cmd, - int tuner_type) +static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd) { u8 last = 1; int i; @@ -901,15 +428,14 @@ cmd = cmd << 1; dprintk("%s switch command: 0x%04x\n",__FUNCTION__, cmd); - stv0299_set_voltage(i2c,SEC_VOLTAGE_18,tuner_type); + stv0299_set_voltage(fe,SEC_VOLTAGE_18); msleep(32); for (i=0; i<9; i++) { if((cmd & 0x01) != last) { - stv0299_set_voltage(i2c, + stv0299_set_voltage(fe, last ? SEC_VOLTAGE_13 : - SEC_VOLTAGE_18, - tuner_type); + SEC_VOLTAGE_18); last = (last) ? 0 : 1; } @@ -922,160 +448,35 @@ return 0; } -static int stv0299_set_symbolrate (struct i2c_adapter *i2c, u32 srate, int tuner_type) + +static int stv0299_init (struct dvb_frontend* fe) { - u64 big = srate; - u32 ratio; - u8 aclk = 0; - u8 bclk = 0; - u8 m1; - int Mclk = M_CLK; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + int i; - // check rate is within limits - if ((srate < 1000000) || (srate > 45000000)) return -EINVAL; + dprintk("stv0299: init chip\n"); - // calculate value to program - if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT; - big = big << 20; - big += (Mclk-1); // round correctly - do_div(big, Mclk); - ratio = big << 4; - - // program registers - switch(tuner_type) { - case PHILIPS_SU1278_TSA_TT: - stv0299_writereg (i2c, 0x0e, 0x44); - if (srate >= 10000000) { - stv0299_writereg (i2c, 0x13, 0x97); - stv0299_writereg (i2c, 0x14, 0x95); - stv0299_writereg (i2c, 0x15, 0xc9); - stv0299_writereg (i2c, 0x17, 0x8c); - stv0299_writereg (i2c, 0x1a, 0xfe); - stv0299_writereg (i2c, 0x1c, 0x7f); - stv0299_writereg (i2c, 0x2d, 0x09); - } else { - stv0299_writereg (i2c, 0x13, 0x99); - stv0299_writereg (i2c, 0x14, 0x8d); - stv0299_writereg (i2c, 0x15, 0xce); - stv0299_writereg (i2c, 0x17, 0x43); - stv0299_writereg (i2c, 0x1a, 0x1d); - stv0299_writereg (i2c, 0x1c, 0x12); - stv0299_writereg (i2c, 0x2d, 0x05); - } - stv0299_writereg (i2c, 0x0e, 0x23); - stv0299_writereg (i2c, 0x0f, 0x94); - stv0299_writereg (i2c, 0x10, 0x39); - stv0299_writereg (i2c, 0x15, 0xc9); - - stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); - break; - - case PHILIPS_SU1278_TSA_TY: - case PHILIPS_SU1278_TSA_CI: - case PHILIPS_SU1278_TSA: - aclk = 0xb5; - if (srate < 2000000) bclk = 0x86; - else if (srate < 5000000) bclk = 0x89; - else if (srate < 15000000) bclk = 0x8f; - else if (srate < 45000000) bclk = 0x95; - - m1 = 0x14; - if (srate < 4000000) m1 = 0x10; - - stv0299_writereg (i2c, 0x13, aclk); - stv0299_writereg (i2c, 0x14, bclk); - stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); - stv0299_writereg (i2c, 0x0f, (stv0299_readreg(i2c, 0x0f) & 0xc0) | m1); - break; + for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2) + stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]); - case ALPS_BSRU6: - default: - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg (i2c, 0x13, aclk); - stv0299_writereg (i2c, 0x14, bclk); - stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); - break; + if (state->config->pll_init) { + stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ + state->config->pll_init(fe); + stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ } - return 0; } -static int stv0299_get_symbolrate (struct i2c_adapter *i2c, int tuner_type) -{ - u32 Mclk = M_CLK / 4096L; - u32 srate; - s32 offset; - u8 sfr[3]; - s8 rtf; - - dprintk ("%s\n", __FUNCTION__); - - if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT / 4096L; - - stv0299_readregs (i2c, 0x1f, sfr, 3); - stv0299_readregs (i2c, 0x1a, &rtf, 1); - - srate = (sfr[0] << 8) | sfr[1]; - srate *= Mclk; - srate /= 16; - srate += (sfr[2] >> 4) * Mclk / 256; - - offset = (s32) rtf * (srate / 4096L); - offset /= 128; - - dprintk ("%s : srate = %i\n", __FUNCTION__, srate); - dprintk ("%s : ofset = %i\n", __FUNCTION__, offset); - - srate += offset; - - srate += 1000; - srate /= 2000; - srate *= 2000; - - return srate; -} - -static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct stv0299_state *state = (struct stv0299_state *) fe->data; - struct i2c_adapter *i2c = state->i2c; - - dprintk ("%s\n", __FUNCTION__); - - switch (cmd) { - case FE_GET_INFO: +static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) arg; - memcpy (arg, &uni0299_info, sizeof(struct dvb_frontend_info)); - - if (state->tuner_type == PHILIPS_SU1278_TSA_TT) { - tmp->frequency_tolerance = M_CLK_SU1278_TSA_TT / 2000; - } - break; - } + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; - case FE_READ_STATUS: - { - fe_status_t *status = (fe_status_t *) arg; - u8 signal = 0xff - stv0299_readreg (i2c, 0x18); - u8 sync = stv0299_readreg (i2c, 0x1b); + u8 signal = 0xff - stv0299_readreg (state, 0x18); + u8 sync = stv0299_readreg (state, 0x1b); dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync); - *status = 0; if (signal > 10) @@ -1093,53 +494,61 @@ if ((sync & 0x98) == 0x98) *status |= FE_HAS_LOCK; - break; + return 0; } - case FE_READ_BER: - if (stv0299_status == STATUS_BER) { - *((u32*) arg) = (stv0299_readreg (i2c, 0x1d) << 8) - | stv0299_readreg (i2c, 0x1e); - } else { - *((u32*) arg) = 0; +static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + if (state->errmode != STATUS_BER) return 0; + *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); + + return 0; } - break; - case FE_READ_SIGNAL_STRENGTH: +static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - s32 signal = 0xffff - ((stv0299_readreg (i2c, 0x18) << 8) - | stv0299_readreg (i2c, 0x19)); + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8) + | stv0299_readreg (state, 0x19)); dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__, - stv0299_readreg (i2c, 0x18), - stv0299_readreg (i2c, 0x19), (int) signal); + stv0299_readreg (state, 0x18), + stv0299_readreg (state, 0x19), (int) signal); signal = signal * 5 / 4; - *((u16*) arg) = (signal > 0xffff) ? 0xffff : - (signal < 0) ? 0 : signal; - break; - } - case FE_READ_SNR: - { - s32 snr = 0xffff - ((stv0299_readreg (i2c, 0x24) << 8) - | stv0299_readreg (i2c, 0x25)); - snr = 3 * (snr - 0xa100); - *((u16*) arg) = (snr > 0xffff) ? 0xffff : - (snr < 0) ? 0 : snr; - break; - } - case FE_READ_UNCORRECTED_BLOCKS: - if (stv0299_status == STATUS_UCBLOCKS) { - *((u32*) arg) = (stv0299_readreg (i2c, 0x1d) << 8) - | stv0299_readreg (i2c, 0x1e); - } else { - *((u32*) arg) = 0; + *strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal; + + return 0; } - break; - case FE_SET_FRONTEND: +static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr) { - struct dvb_frontend_parameters *p = arg; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + s32 xsnr = 0xffff - ((stv0299_readreg (state, 0x24) << 8) + | stv0299_readreg (state, 0x25)); + xsnr = 3 * (xsnr - 0xa100); + *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr; + + return 0; +} + +static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0; + else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); + + return 0; +} + +static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; int invval = 0; dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__); @@ -1151,12 +560,10 @@ printk("stv0299 does not support auto-inversion\n"); return -EINVAL; } - if (state->tuner_type == ALPS_BSRU6) invval = (~invval) & 1; - stv0299_writereg(i2c, 0x0c, (stv0299_readreg(i2c, 0x0c) & 0xfe) | invval); + if (state->config->invert) invval = (~invval) & 1; + stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval); - switch(state->tuner_type) { - case PHILIPS_SU1278_TSA_TT: - { + if (state->config->enhanced_tuning) { /* check if we should do a finetune */ int frequency_delta = p->frequency - state->tuner_frequency; int minmax = p->u.qpsk.symbol_rate / 2000; @@ -1165,130 +572,88 @@ if ((frequency_delta > -minmax) && (frequency_delta < minmax) && (frequency_delta != 0) && (state->fec_inner == p->u.qpsk.fec_inner) && (state->symbol_rate == p->u.qpsk.symbol_rate)) { - int Drot_freq = (frequency_delta << 16) / (M_CLK_SU1278_TSA_TT / 1000); + int Drot_freq = (frequency_delta << 16) / (state->config->mclk / 1000); // zap the derotator registers first - stv0299_writereg (i2c, 0x22, 0x00); - stv0299_writereg (i2c, 0x23, 0x00); + stv0299_writeregI(state, 0x22, 0x00); + stv0299_writeregI(state, 0x23, 0x00); // now set them as we want - stv0299_writereg (i2c, 0x22, Drot_freq >> 8); - stv0299_writereg (i2c, 0x23, Drot_freq); + stv0299_writeregI(state, 0x22, Drot_freq >> 8); + stv0299_writeregI(state, 0x23, Drot_freq); } else { /* A "normal" tune is requested */ - pll_set_tv_freq (i2c, p->frequency, state->tuner_type, p->u.qpsk.symbol_rate); - stv0299_writereg (i2c, 0x32, 0x80); - stv0299_writereg (i2c, 0x22, 0x00); - stv0299_writereg (i2c, 0x23, 0x00); - stv0299_writereg (i2c, 0x32, 0x19); - stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, state->tuner_type); - stv0299_set_FEC (i2c, p->u.qpsk.fec_inner); - } - break; + stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ + state->config->pll_set(fe, p); + stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ + + stv0299_writeregI(state, 0x32, 0x80); + stv0299_writeregI(state, 0x22, 0x00); + stv0299_writeregI(state, 0x23, 0x00); + stv0299_writeregI(state, 0x32, 0x19); + stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); + stv0299_set_FEC (state, p->u.qpsk.fec_inner); } - - default: - pll_set_tv_freq (i2c, p->frequency, state->tuner_type, p->u.qpsk.symbol_rate); - stv0299_set_FEC (i2c, p->u.qpsk.fec_inner); - stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, state->tuner_type); - stv0299_writereg (i2c, 0x22, 0x00); - stv0299_writereg (i2c, 0x23, 0x00); - stv0299_readreg (i2c, 0x23); - stv0299_writereg (i2c, 0x12, 0xb9); - break; + } else { + stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ + state->config->pll_set(fe, p); + stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ + + stv0299_set_FEC (state, p->u.qpsk.fec_inner); + stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); + stv0299_writeregI(state, 0x22, 0x00); + stv0299_writeregI(state, 0x23, 0x00); + stv0299_readreg (state, 0x23); + stv0299_writeregI(state, 0x12, 0xb9); } state->tuner_frequency = p->frequency; state->fec_inner = p->u.qpsk.fec_inner; state->symbol_rate = p->u.qpsk.symbol_rate; - break; + + return 0; } - case FE_GET_FRONTEND: +static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) { - struct dvb_frontend_parameters *p = arg; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; s32 derot_freq; - int Mclk = M_CLK; int invval; - if (state->tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT; + derot_freq = (s32)(s16) ((stv0299_readreg (state, 0x22) << 8) + | stv0299_readreg (state, 0x23)); - derot_freq = (s32)(s16) ((stv0299_readreg (i2c, 0x22) << 8) - | stv0299_readreg (i2c, 0x23)); - - derot_freq *= (Mclk >> 16); + derot_freq *= (state->config->mclk >> 16); derot_freq += 500; derot_freq /= 1000; p->frequency += derot_freq; - invval = stv0299_readreg (i2c, 0x0c) & 1; - if (state->tuner_type == ALPS_BSRU6) invval = (~invval) & 1; + invval = stv0299_readreg (state, 0x0c) & 1; + if (state->config->invert) invval = (~invval) & 1; p->inversion = invval ? INVERSION_ON : INVERSION_OFF; - p->u.qpsk.fec_inner = stv0299_get_fec (i2c); - p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c, state->tuner_type); - break; - } - - case FE_SLEEP: - stv0299_writereg (i2c, 0x0c, 0x00); /* LNB power off! */ - stv0299_writereg (i2c, 0x08, 0x00); /* LNB power off! */ - stv0299_writereg (i2c, 0x02, 0x80); - state->initialised = 0; - break; - - case FE_INIT: - switch(state->tuner_type) { - case PHILIPS_SU1278_TSA_TT: - state->tuner_frequency = 0; - if (!state->initialised) { - state->initialised = 1; - return stv0299_init (i2c, state->tuner_type); - } - break; + p->u.qpsk.fec_inner = stv0299_get_fec (state); + p->u.qpsk.symbol_rate = stv0299_get_symbolrate (state); - default: - return stv0299_init (i2c, state->tuner_type); + return 0; } - break; - - case FE_DISEQC_SEND_MASTER_CMD: - return stv0299_send_diseqc_msg (i2c, arg); - case FE_DISEQC_SEND_BURST: - return stv0299_send_diseqc_burst (i2c, (fe_sec_mini_cmd_t) arg); - - case FE_SET_TONE: - return stv0299_set_tone (i2c, (fe_sec_tone_mode_t) arg); +static int stv0299_sleep(struct dvb_frontend* fe) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; - case FE_SET_VOLTAGE: - return stv0299_set_voltage (i2c, (fe_sec_voltage_t) arg, - state->tuner_type); + stv0299_writeregI(state, 0x02, 0x80); + state->initialised = 0; - case FE_DISHNETWORK_SEND_LEGACY_CMD: - return stv0299_send_legacy_dish_cmd (i2c, - (u32)(unsigned long)arg, - state->tuner_type); + return 0; +} - case FE_GET_TUNE_SETTINGS: +static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; - - switch(state->tuner_type) { - case PHILIPS_SU1278_TSA_TT: - fesettings->min_delay_ms = 50; - if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) { - fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000; - fesettings->max_drift = 5000; - } else { - fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000; - fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000; - } - break; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; - default: - fesettings->min_delay_ms = 100; + fesettings->min_delay_ms = state->config->min_delay_ms; if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) { fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000; fesettings->max_drift = 5000; @@ -1296,225 +661,103 @@ fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000; fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000; } - break; - } - - return 0; - } - - default: - return -EOPNOTSUPP; - }; - return 0; } -static long probe_tuner (struct i2c_adapter *adapter) -{ - struct i2c_adapter *i2c = adapter; /* superfluous */ - - /* read the status register of TSA5059 */ - u8 rpt[] = { 0x05, 0xb5 }; - u8 stat [] = { 0 }; - u8 tda6100_buf [] = { 0, 0 }; - int ret; - struct i2c_msg msg1 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, .len = 2 }, - { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; - struct i2c_msg msg2 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, .len = 2 }, - { .addr = 0x61, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; - struct i2c_msg msg3 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, .len = 2 }, - { .addr = 0x60, .flags = 0, .buf = tda6100_buf, .len = 2 }}; - - stv0299_writereg (i2c, 0x01, 0x15); - stv0299_writereg (i2c, 0x02, 0x30); - stv0299_writereg (i2c, 0x03, 0x00); - - - printk("stv0299: try to attach to %s\n", adapter->name); - - if (!strcmp(adapter->name, "SkyStar2")) { - printk ("stv0299: setup for tuner Samsung TBMU24112IMB\n"); - return SAMSUNG_TBMU24112IMB; - } - - if ((ret = i2c_transfer(i2c, msg1, 2)) == 2) { - if ( strcmp(adapter->name, "TT-Budget/WinTV-NOVA-CI PCI") == 0 ) { - // technotrend cards require non-datasheet settings - printk ("stv0299: setup for tuner SU1278 (TSA5059 synth) on TechnoTrend hardware\n"); - return PHILIPS_SU1278_TSA_TT; - } else { - // fall back to datasheet-recommended settings - printk ("stv0299: setup for tuner SU1278 (TSA5059 synth)\n"); - return PHILIPS_SU1278_TSA; - } - } - - if ((ret = i2c_transfer(i2c, msg2, 2)) == 2) { - if ( strcmp(adapter->name, "KNC1 DVB-S") == 0 ) +static void stv0299_release(struct dvb_frontend* fe) { - // Typhoon cards have unusual wiring. - printk ("stv0299: setup for tuner SU1278 (TSA5059 synth) on Typhoon hardware\n"); - return PHILIPS_SU1278_TSA_TY; - } - else if ( strcmp(adapter->name, "TerraTec Cinergy 1200 DVB-S") == 0 ) - { - // Cinergy cards have unusual wiring. - printk ("%s: setup for tuner SU1278 (TSA5059 synth) on" - " TerraTec hardware\n", __FILE__); - return PHILIPS_SU1278_TSA_CI; - } - //else if ((stat[0] & 0x3f) == 0) { - else if (0) { - printk ("stv0299: setup for tuner TDQF-S001F\n"); - return LG_TDQF_S001F; - } else { - printk ("stv0299: setup for tuner BSRU6, TDQB-S00x\n"); - return ALPS_BSRU6; - } - } - - /** - * setup i2c timing for SU1278... - */ - stv0299_writereg (i2c, 0x02, 0x00); - - if ((ret = i2c_transfer(i2c, msg3, 2)) == 2) { - printk ("stv0299: setup for tuner Philips SU1278 (TUA6100 synth)\n"); - return PHILIPS_SU1278_TUA; - } - - printk ("stv0299: unknown PLL synthesizer (ret == %i), please report to !!\n", ret); - - return UNKNOWN_FRONTEND; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + kfree(state); } -static struct i2c_client client_template; +static struct dvb_frontend_ops stv0299_ops; -static int attach_adapter(struct i2c_adapter *adapter) +struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, + struct i2c_adapter* i2c) { - struct i2c_client *client; - struct stv0299_state* state; - int tuner_type; - int ret; - u8 id; + struct stv0299_state* state = NULL; + int id; - stv0299_writereg(adapter, 0x02, 0x34); /* standby off */ - msleep(200); - id = stv0299_readreg(adapter, 0x00); + /* allocate memory for the internal state */ + state = (struct stv0299_state*) kmalloc(sizeof(struct stv0299_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &stv0299_ops, sizeof(struct dvb_frontend_ops)); + state->initialised = 0; + state->tuner_frequency = 0; + state->symbol_rate = 0; + state->fec_inner = 0; + state->errmode = STATUS_BER; - dprintk ("%s: id == 0x%02x\n", __FUNCTION__, id); + /* check if the demod is there */ + stv0299_writeregI(state, 0x02, 0x34); /* standby off */ + msleep(200); + id = stv0299_readreg(state, 0x00); /* register 0x00 contains 0xa1 for STV0299 and STV0299B */ /* register 0x00 might contain 0x80 when returning from standby */ - if (id != 0xa1 && id != 0x80) - return -ENODEV; - - if ((tuner_type = probe_tuner(adapter)) < 0) - return -ENODEV; - - if ((state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL)) == NULL) { - return -ENOMEM; - } - - if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { - kfree(state); - return -ENOMEM; - } - - state->tuner_type = tuner_type; - state->tuner_frequency = 0; - state->initialised = 0; - state->i2c = adapter; - - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = (0x68>>1); - i2c_set_clientdata(client, (void*)state); - - ret = i2c_attach_client(client); - if (ret) { - kfree(client); - kfree(state); - return -EFAULT; - } - - BUG_ON(!state->dvb); - - ret = dvb_register_frontend(uni0299_ioctl, state->dvb, state, - &uni0299_info, THIS_MODULE); - if (ret) { - i2c_detach_client(client); - kfree(client); - kfree(state); - return -EFAULT; -} + if (id != 0xa1 && id != 0x80) goto error; - return 0; -} - -static int detach_client(struct i2c_client *client) -{ - struct stv0299_state *state = (struct stv0299_state*)i2c_get_clientdata(client); - - dvb_unregister_frontend (uni0299_ioctl, state->dvb); - i2c_detach_client(client); - kfree(client); - kfree(state); - return 0; -} - -static int command (struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct stv0299_state *data = (struct stv0299_state*)i2c_get_clientdata(client); - dprintk ("%s\n", __FUNCTION__); - - switch (cmd) { - case FE_REGISTER: { - data->dvb = (struct dvb_adapter*)arg; - break; - } - case FE_UNREGISTER: { - data->dvb = NULL; - break; - } - default: - return -EOPNOTSUPP; - } - return 0; -} - -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = FRONTEND_NAME, - .id = I2C_DRIVERID_DVBFE_STV0299, - .flags = I2C_DF_NOTIFY, - .attach_adapter = attach_adapter, - .detach_client = detach_client, - .command = command, -}; - -static struct i2c_client client_template = { - .name = FRONTEND_NAME, - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; +} + +static struct dvb_frontend_ops stv0299_ops = { + + .info = { + .name = "ST STV0299 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 125, /* kHz for QPSK frontends */ + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, /* ppm */ + .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_QPSK | + FE_CAN_FEC_AUTO + }, + + .release = stv0299_release, + + .init = stv0299_init, + .sleep = stv0299_sleep, + + .set_frontend = stv0299_set_frontend, + .get_frontend = stv0299_get_frontend, + .get_tune_settings = stv0299_get_tune_settings, + + .read_status = stv0299_read_status, + .read_ber = stv0299_read_ber, + .read_signal_strength = stv0299_read_signal_strength, + .read_snr = stv0299_read_snr, + .read_ucblocks = stv0299_read_ucblocks, + + .diseqc_send_master_cmd = stv0299_send_diseqc_msg, + .diseqc_send_burst = stv0299_send_diseqc_burst, + .set_tone = stv0299_set_tone, + .set_voltage = stv0299_set_voltage, + .dishnetwork_send_legacy_command = stv0299_send_legacy_dish_cmd, }; -static int __init init_uni0299 (void) -{ - return i2c_add_driver(&driver); -} - -static void __exit exit_uni0299 (void) -{ - if (i2c_del_driver(&driver)) - printk("stv0299: driver deregistration failed\n"); -} - -module_init (init_uni0299); -module_exit (exit_uni0299); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("Universal STV0299/TSA5059/SL1935 DVB Frontend driver"); +MODULE_DESCRIPTION("ST STV0299 DVB Demodulator driver"); MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, " "Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(stv0299_writereg); +EXPORT_SYMBOL(stv0299_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/tda1004x.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/tda1004x.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/tda1004x.c 2004-12-22 10:04:35.833355354 -0800 @@ -1,5 +1,5 @@ /* - Driver for Philips tda1004xh OFDM Frontend + Driver for Philips tda1004xh OFDM Demodulator (c) 2003, 2004 Andrew de Quincey & Robert Schlabbach @@ -32,23 +32,35 @@ #include #include #include -#include - #include "dvb_frontend.h" +#include "tda1004x.h" -#define FRONTEND_NAME "dvbfe_tda1004x" +#define TDA1004X_DEMOD_TDA10045 0 +#define TDA1004X_DEMOD_TDA10046 1 -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG FRONTEND_NAME ": " args); \ - } while (0) -static int debug; +struct tda1004x_state +{ + struct i2c_adapter* i2c; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + struct dvb_frontend_ops ops; -#define MC44BC374_ADDRESS 0x65 + const struct tda1004x_config* config; + + struct dvb_frontend frontend; + + /* private demod data */ + u8 initialised:1; + + u8 demod_type; +}; + + +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "tda1004x: " args); \ + } while (0) #define TDA1004X_CHIPID 0x00 #define TDA1004X_AUTO 0x01 @@ -128,53 +140,7 @@ #define TDA10046H_CODE_IN 0x58 -#define FE_TYPE_TDA10045H 0 -#define FE_TYPE_TDA10046H 1 - -#define TUNER_TYPE_TD1344 0 -#define TUNER_TYPE_TD1316 1 - -static struct dvb_frontend_info tda10045h_info = { - .name = "Philips TDA10045H", - .type = FE_OFDM, - .frequency_min = 51000000, - .frequency_max = 858000000, - .frequency_stepsize = 166667, - .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 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO -}; - -static struct dvb_frontend_info tda10046h_info = { - .name = "Philips TDA10046H", - .type = FE_OFDM, - .frequency_min = 51000000, - .frequency_max = 858000000, - .frequency_stepsize = 166667, - .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 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO -}; - -struct tda1004x_state { - u8 tda1004x_address; - u8 tuner_address; - u8 initialised; - u8 tuner_type; - u8 fe_type; - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; - - int dspCodeCounterReg; - int dspCodeInReg; - int dspVersion; -}; - -static int tda1004x_write_byte(struct i2c_adapter *i2c, struct tda1004x_state *tda_state, int reg, int data) +static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data) { int ret; u8 buf[] = { reg, data }; @@ -182,8 +148,8 @@ dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data); - msg.addr = tda_state->tda1004x_address; - ret = i2c_transfer(i2c, &msg, 1); + msg.addr = state->config->demod_address; + ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", @@ -194,7 +160,7 @@ return (ret != 1) ? -1 : 0; } -static int tda1004x_read_byte(struct i2c_adapter *i2c, struct tda1004x_state *tda_state, int reg) +static int tda1004x_read_byte(struct tda1004x_state *state, int reg) { int ret; u8 b0[] = { reg }; @@ -204,9 +170,9 @@ dprintk("%s: reg=0x%x\n", __FUNCTION__, reg); - msg[0].addr = tda_state->tda1004x_address; - msg[1].addr = tda_state->tda1004x_address; - ret = i2c_transfer(i2c, msg, 2); + msg[0].addr = state->config->demod_address; + msg[1].addr = state->config->demod_address; + ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg, @@ -219,14 +185,14 @@ return b1[0]; } -static int tda1004x_write_mask(struct i2c_adapter *i2c, struct tda1004x_state *tda_state, int reg, int mask, int data) +static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data) { int val; dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg, mask, data); // read a byte and check - val = tda1004x_read_byte(i2c, tda_state, reg); + val = tda1004x_read_byte(state, reg); if (val < 0) return val; @@ -235,10 +201,10 @@ val |= data & 0xff; // write it out again - return tda1004x_write_byte(i2c, tda_state, reg, val); + return tda1004x_write_byteI(state, reg, val); } -static int tda1004x_write_buf(struct i2c_adapter *i2c, struct tda1004x_state *tda_state, int reg, unsigned char *buf, int len) +static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned char *buf, int len) { int i; int result; @@ -247,7 +213,7 @@ result = 0; for (i = 0; i < len; i++) { - result = tda1004x_write_byte(i2c, tda_state, reg + i, buf[i]); + result = tda1004x_write_byteI(state, reg + i, buf[i]); if (result != 0) break; } @@ -255,25 +221,24 @@ return result; } -static int tda1004x_enable_tuner_i2c(struct i2c_adapter *i2c, struct tda1004x_state *tda_state) +static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state) { int result; dprintk("%s\n", __FUNCTION__); - result = tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 2); + result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2); msleep(1); return result; } -static int tda1004x_disable_tuner_i2c(struct i2c_adapter *i2c, struct tda1004x_state *tda_state) +static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state) { dprintk("%s\n", __FUNCTION__); - return tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 0); + return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0); } -static int tda10045h_set_bandwidth(struct i2c_adapter *i2c, - struct tda1004x_state *tda_state, +static int tda10045h_set_bandwidth(struct tda1004x_state *state, fe_bandwidth_t bandwidth) { static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f }; @@ -282,31 +247,27 @@ switch (bandwidth) { case BANDWIDTH_6_MHZ: - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14); - tda1004x_write_buf(i2c, tda_state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz)); + tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz)); break; case BANDWIDTH_7_MHZ: - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x80); - tda1004x_write_buf(i2c, tda_state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz)); + tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz)); break; case BANDWIDTH_8_MHZ: - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14); - tda1004x_write_buf(i2c, tda_state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz)); + tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz)); break; default: return -EINVAL; } - tda1004x_write_byte(i2c, tda_state, TDA10045H_IOFFSET, 0); + tda1004x_write_byteI(state, TDA10045H_IOFFSET, 0); return 0; } -static int tda10046h_set_bandwidth(struct i2c_adapter *i2c, - struct tda1004x_state *tda_state, +static int tda10046h_set_bandwidth(struct tda1004x_state *state, fe_bandwidth_t bandwidth) { static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e }; @@ -315,18 +276,15 @@ switch (bandwidth) { case BANDWIDTH_6_MHZ: - tda1004x_write_buf(i2c, tda_state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz)); - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0); + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz)); break; case BANDWIDTH_7_MHZ: - tda1004x_write_buf(i2c, tda_state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz)); - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0); + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz)); break; case BANDWIDTH_8_MHZ: - tda1004x_write_buf(i2c, tda_state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz)); - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0xFF); + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz)); break; default: @@ -336,7 +294,9 @@ return 0; } -static int tda1004x_do_upload(struct i2c_adapter *i2c, struct tda1004x_state *state, unsigned char *mem, unsigned int len) +static int tda1004x_do_upload(struct tda1004x_state *state, + unsigned char *mem, unsigned int len, + u8 dspCodeCounterReg, u8 dspCodeInReg) { u8 buf[65]; struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = buf,.len = 0 }; @@ -344,10 +304,10 @@ int pos = 0; /* clear code counter */ - tda1004x_write_byte(i2c, state, state->dspCodeCounterReg, 0); - fw_msg.addr = state->tda1004x_address; + tda1004x_write_byteI(state, dspCodeCounterReg, 0); + fw_msg.addr = state->config->demod_address; - buf[0] = state->dspCodeInReg; + buf[0] = dspCodeInReg; while (pos != len) { // work out how much to send this time @@ -359,7 +319,7 @@ // send the chunk memcpy(buf + 1, mem + pos, tx_size); fw_msg.len = tx_size + 1; - if (i2c_transfer(i2c, &fw_msg, 1) != 1) { + if (i2c_transfer(state->i2c, &fw_msg, 1) != 1) { printk("tda1004x: Error during firmware upload\n"); return -EIO; } @@ -370,18 +330,17 @@ return 0; } -static int tda1004x_check_upload_ok(struct i2c_adapter *i2c, struct tda1004x_state *state) +static int tda1004x_check_upload_ok(struct tda1004x_state *state, u8 dspVersion) { u8 data1, data2; // check upload was OK - tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP - tda1004x_write_byte(i2c, state, TDA1004X_DSP_CMD, 0x67); + tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP + tda1004x_write_byteI(state, TDA1004X_DSP_CMD, 0x67); - data1 = tda1004x_read_byte(i2c, state, TDA1004X_DSP_DATA1); - data2 = tda1004x_read_byte(i2c, state, TDA1004X_DSP_DATA2); - if (data1 != 0x67 || data2 != state->dspVersion) { - printk("tda1004x: firmware upload failed!\n"); + data1 = tda1004x_read_byte(state, TDA1004X_DSP_DATA1); + data2 = tda1004x_read_byte(state, TDA1004X_DSP_DATA2); + if (data1 != 0x67 || data2 != dspVersion) { return -EIO; } @@ -389,31 +348,34 @@ } -static int tda10045_fwupload(struct i2c_adapter *i2c, struct tda1004x_state *state, struct i2c_client *client) +static int tda10045_fwupload(struct dvb_frontend* fe) { + struct tda1004x_state* state = fe->demodulator_priv; int ret; const struct firmware *fw; + + /* don't re-upload unless necessary */ + if (tda1004x_check_upload_ok(state, 0x2c) == 0) return 0; + /* request the firmware, this will block until someone uploads it */ printk("tda1004x: waiting for firmware upload...\n"); - ret = request_firmware(&fw, TDA10045_DEFAULT_FIRMWARE, &client->dev); + ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); if (ret) { printk("tda1004x: no firmware upload (timeout or file not found?)\n"); return ret; } - /* set some valid bandwith parameters before uploading */ - /* reset chip */ - tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 0x10, 0); - tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 8, 8); - tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 8, 0); + tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0); msleep(10); /* set parameters */ - tda10045h_set_bandwidth(i2c, state, BANDWIDTH_8_MHZ); + tda10045h_set_bandwidth(state, BANDWIDTH_8_MHZ); - ret = tda1004x_do_upload(i2c, state, fw->data, fw->size); + ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN); if (ret) return ret; @@ -421,49 +383,47 @@ /* DSPREADY doesn't seem to work on the TDA10045H */ msleep(100); - ret = tda1004x_check_upload_ok(i2c, state); - if (ret) - return ret; - - return 0; + return tda1004x_check_upload_ok(state, 0x2c); } -static int tda10046_fwupload(struct i2c_adapter *i2c, struct tda1004x_state *state, struct i2c_client *client) +static int tda10046_fwupload(struct dvb_frontend* fe) { + struct tda1004x_state* state = fe->demodulator_priv; unsigned long timeout; int ret; const struct firmware *fw; + /* reset + wake up chip */ + tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 0); + tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); + msleep(100); + + /* don't re-upload unless necessary */ + if (tda1004x_check_upload_ok(state, 0x20) == 0) return 0; + /* request the firmware, this will block until someone uploads it */ printk("tda1004x: waiting for firmware upload...\n"); - ret = request_firmware(&fw, TDA10046_DEFAULT_FIRMWARE, &client->dev); + ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); if (ret) { printk("tda1004x: no firmware upload (timeout or file not found?)\n"); return ret; } - /* set some valid bandwith parameters before uploading */ - - /* reset chip */ - tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 1, 0); - tda1004x_write_mask(i2c, state, TDA10046H_CONF_TRISTATE1, 1, 0); - msleep(10); - /* set parameters */ - tda1004x_write_byte(i2c, state, TDA10046H_CONFPLL2, 10); - tda1004x_write_byte(i2c, state, TDA10046H_CONFPLL3, 0); - tda1004x_write_byte(i2c, state, TDA10046H_FREQ_OFFSET, 99); - tda1004x_write_byte(i2c, state, TDA10046H_FREQ_PHY2_MSB, 0xd4); - tda1004x_write_byte(i2c, state, TDA10046H_FREQ_PHY2_LSB, 0x2c); - tda1004x_write_mask(i2c, state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST + tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); + tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); + tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c); + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST - ret = tda1004x_do_upload(i2c, state, fw->data, fw->size); + ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN); if (ret) return ret; /* wait for DSP to initialise */ timeout = jiffies + HZ; - while(!(tda1004x_read_byte(i2c, state, TDA1004X_STATUS_CD) & 0x20)) { + while(!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) { if (time_after(jiffies, timeout)) { printk("tda1004x: DSP failed to initialised.\n"); return -EIO; @@ -471,95 +431,7 @@ msleep(1); } - ret = tda1004x_check_upload_ok(i2c, state); - if (ret) - return ret; - - return 0; -} - -static int tda10045h_init(struct i2c_adapter *i2c, struct tda1004x_state *tda_state) -{ - struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = NULL,.len = 0 }; - static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; - - dprintk("%s\n", __FUNCTION__); - - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC - - // Disable the MC44BC374C - tda1004x_enable_tuner_i2c(i2c, tda_state); - tuner_msg.addr = MC44BC374_ADDRESS; - tuner_msg.buf = disable_mc44BC374c; - tuner_msg.len = sizeof(disable_mc44BC374c); - if (i2c_transfer(i2c, &tuner_msg, 1) != 1) { - i2c_transfer(i2c, &tuner_msg, 1); - } - tda1004x_disable_tuner_i2c(i2c, tda_state); - - // tda setup - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // select HP stream - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0); // no frequency inversion - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset - tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface - tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface - tda1004x_write_mask(i2c, tda_state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity - tda1004x_write_byte(i2c, tda_state, TDA1004X_CONFADC1, 0x2e); - - return 0; -} - -static int tda10046h_init(struct i2c_adapter *i2c, struct tda1004x_state *tda_state) -{ - struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = NULL,.len = 0 }; - static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; - - dprintk("%s\n", __FUNCTION__); - - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 0); // wake up the chip - - // Disable the MC44BC374C - tda1004x_enable_tuner_i2c(i2c, tda_state); - tuner_msg.addr = MC44BC374_ADDRESS; - tuner_msg.buf = disable_mc44BC374c; - tuner_msg.len = sizeof(disable_mc44BC374c); - if (i2c_transfer(i2c, &tuner_msg, 1) != 1) { - i2c_transfer(i2c, &tuner_msg, 1); - } - tda1004x_disable_tuner_i2c(i2c, tda_state); - - // tda setup - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0x40); // TT TDA10046H needs inversion ON - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // select HP stream - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0); // disable pulse killer - tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL2, 10); // PLL M = 10 - tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 - tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_OFFSET, 99); // FREQOFFS = 99 - tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_MSB, 0xd4); // } PHY2 = -11221 - tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_LSB, 0x2c); // } - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_CONF, 0); // AGC setup - tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_POLARITY, 0x60, 0x60); // set AGC polarities - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_TUN_MIN, 0); // } - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_IF_MIN, 0); // } - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_IF_MAX, 0xff); // } - tda1004x_write_mask(i2c, tda_state, TDA10046H_CVBER_CTRL, 0x30, 0x10); // 10^6 VBER measurement bits - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1 - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x80, 0); // crystal is 50ppm - tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONF_TS2, 0x31, 0); // MPEG2 interface config - tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 0x9e, 0); // disable AGC_TUN - tda1004x_write_byte(i2c, tda_state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup - tda1004x_write_byte(i2c, tda_state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config - tda1004x_write_mask(i2c, tda_state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select - tda10046h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz - - return 0; + return tda1004x_check_upload_ok(state, 0x20); } static int tda1004x_encode_fec(int fec) @@ -602,216 +474,194 @@ return -1; } -static int tda1004x_set_frequency(struct i2c_adapter *i2c, - struct tda1004x_state *tda_state, - struct dvb_frontend_parameters *fe_params) -{ - u8 tuner_buf[4]; - struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) }; - int tuner_frequency = 0; - u8 band, cp, filter; - int counter, counter2; - dprintk("%s\n", __FUNCTION__); - // setup the frequency buffer - switch (tda_state->tuner_type) { - case TUNER_TYPE_TD1344: - - // setup tuner buffer - // ((Fif+((1000000/6)/2)) + Finput)/(1000000/6) - tuner_frequency = - (((fe_params->frequency / 1000) * 6) + 217502) / 1000; - tuner_buf[0] = tuner_frequency >> 8; - tuner_buf[1] = tuner_frequency & 0xff; - tuner_buf[2] = 0x88; - if (fe_params->frequency < 550000000) { - tuner_buf[3] = 0xab; - } else { - tuner_buf[3] = 0xeb; - } - // tune it - tda1004x_enable_tuner_i2c(i2c, tda_state); - tuner_msg.addr = tda_state->tuner_address; - tuner_msg.len = 4; - i2c_transfer(i2c, &tuner_msg, 1); - - // wait for it to finish - tuner_msg.len = 1; - tuner_msg.flags = I2C_M_RD; - counter = 0; - counter2 = 0; - while (counter++ < 100) { - if (i2c_transfer(i2c, &tuner_msg, 1) == 1) { - if (tuner_buf[0] & 0x40) { - counter2++; - } else { - counter2 = 0; - } - } - - if (counter2 > 10) { - break; - } - } - tda1004x_disable_tuner_i2c(i2c, tda_state); - break; - case TUNER_TYPE_TD1316: - // determine charge pump - tuner_frequency = fe_params->frequency + 36130000; - if (tuner_frequency < 87000000) { - return -EINVAL; - } else if (tuner_frequency < 130000000) { - cp = 3; - } else if (tuner_frequency < 160000000) { - cp = 5; - } else if (tuner_frequency < 200000000) { - cp = 6; - } else if (tuner_frequency < 290000000) { - cp = 3; - } else if (tuner_frequency < 420000000) { - cp = 5; - } else if (tuner_frequency < 480000000) { - cp = 6; - } else if (tuner_frequency < 620000000) { - cp = 3; - } else if (tuner_frequency < 830000000) { - cp = 5; - } else if (tuner_frequency < 895000000) { - cp = 7; - } else { - return -EINVAL; - } - // determine band - if (fe_params->frequency < 49000000) { - return -EINVAL; - } else if (fe_params->frequency < 159000000) { - band = 1; - } else if (fe_params->frequency < 444000000) { - band = 2; - } else if (fe_params->frequency < 861000000) { - band = 4; - } else { - return -EINVAL; + + + + + + + + + + + + +int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data) +{ + struct tda1004x_state* state = fe->demodulator_priv; + + return tda1004x_write_byteI(state, reg, data); } - // work out filter - switch (fe_params->u.ofdm.bandwidth) { - case BANDWIDTH_6_MHZ: - filter = 0; - break; +static int tda10045_init(struct dvb_frontend* fe) +{ + struct tda1004x_state* state = fe->demodulator_priv; - case BANDWIDTH_7_MHZ: - filter = 0; - break; + dprintk("%s\n", __FUNCTION__); - case BANDWIDTH_8_MHZ: - filter = 1; - break; + if (state->initialised) return 0; - default: - return -EINVAL; + if (tda10045_fwupload(fe)) { + printk("tda1004x: firmware upload failed\n"); + return -EIO; } - // calculate divisor - // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6) - tuner_frequency = - (((fe_params->frequency / 1000) * 6) + 217280) / 1000; - - // setup tuner buffer - tuner_buf[0] = tuner_frequency >> 8; - tuner_buf[1] = tuner_frequency & 0xff; - tuner_buf[2] = 0xca; - tuner_buf[3] = (cp << 5) | (filter << 3) | band; - - // tune it - if (tda_state->fe_type == FE_TYPE_TDA10046H) { - // setup auto offset - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x80, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0); + tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC + + // Init the PLL + if (state->config->pll_init) { + tda1004x_enable_tuner_i2c(state); + state->config->pll_init(fe); + tda1004x_disable_tuner_i2c(state); + } + + // tda setup + tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer + tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x40, 0); // set polarity of VAGC signal + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer + tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset + tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface + tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface + tda1004x_write_mask(state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity + tda1004x_write_byteI(state, TDA1004X_CONFADC1, 0x2e); + + tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk); - // disable agc_conf[2] - tda1004x_write_mask(i2c, tda_state, TDA10046H_AGC_CONF, 4, 0); + state->initialised = 1; + return 0; } - tda1004x_enable_tuner_i2c(i2c, tda_state); - tuner_msg.addr = tda_state->tuner_address; - tuner_msg.len = 4; - if (i2c_transfer(i2c, &tuner_msg, 1) != 1) { + +static int tda10046_init(struct dvb_frontend* fe) +{ + struct tda1004x_state* state = fe->demodulator_priv; + dprintk("%s\n", __FUNCTION__); + + if (state->initialised) return 0; + + if (tda10046_fwupload(fe)) { + printk("tda1004x: firmware upload failed\n"); return -EIO; } - msleep(1); - tda1004x_disable_tuner_i2c(i2c, tda_state); - if (tda_state->fe_type == FE_TYPE_TDA10046H) - tda1004x_write_mask(i2c, tda_state, TDA10046H_AGC_CONF, 4, 4); - break; - default: - return -EINVAL; + tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 0); // wake up the chip + + // Init the PLL + if (state->config->pll_init) { + tda1004x_enable_tuner_i2c(state); + state->config->pll_init(fe); + tda1004x_disable_tuner_i2c(state); } - dprintk("%s: success\n", __FUNCTION__); + // tda setup + tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x40, 0x40); + tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0); // disable pulse killer + tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); // PLL M = 10 + tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 + tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99); // FREQOFFS = 99 + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4); // } PHY2 = -11221 + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c); // } + tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0); // AGC setup + tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x60, 0x60); // set AGC polarities + tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // } + tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values + tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // } + tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // } + tda1004x_write_mask(state, TDA10046H_CVBER_CTRL, 0x30, 0x10); // 10^6 VBER measurement bits + tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1 + tda1004x_write_mask(state, TDA1004X_AUTO, 0x80, 0); // crystal is 50ppm + tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config + tda1004x_write_mask(state, TDA1004X_CONF_TS2, 0x31, 0); // MPEG2 interface config + tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0x9e, 0); // disable AGC_TUN + tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup + tda1004x_write_byteI(state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config + tda1004x_write_mask(state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select + tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz + + tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); + state->initialised = 1; return 0; } -static int tda1004x_set_fe(struct i2c_adapter *i2c, - struct tda1004x_state *tda_state, +static int tda1004x_set_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params) { + struct tda1004x_state* state = fe->demodulator_priv; int tmp; int inversion; dprintk("%s\n", __FUNCTION__); - // set frequency - if ((tmp = tda1004x_set_frequency(i2c, tda_state, fe_params)) < 0) - return tmp; + if (state->demod_type == TDA1004X_DEMOD_TDA10046) { + // setup auto offset + tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x80, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0); - // Hardcoded to use auto as much as possible - // The TDA10045 is very unreliable if AUTO mode is _not_ used. I have not - // yet tested the TDA10046 to see if this issue has been fixed + // disable agc_conf[2] + tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 0); + } + + // set frequency + tda1004x_enable_tuner_i2c(state); + state->config->pll_set(fe, fe_params); + tda1004x_disable_tuner_i2c(state); + + if (state->demod_type == TDA1004X_DEMOD_TDA10046) + tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 4); + + // Hardcoded to use auto as much as possible on the TDA10045 as it + // is very unreliable if AUTO mode is _not_ used. + if (state->demod_type == TDA1004X_DEMOD_TDA10045) { fe_params->u.ofdm.code_rate_HP = FEC_AUTO; fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + } // Set standard params.. or put them to auto if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) || (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) || (fe_params->u.ofdm.constellation == QAM_AUTO) || (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) { - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 1); // enable auto - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits + tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits } else { - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 0); // disable auto + tda1004x_write_mask(state, TDA1004X_AUTO, 1, 0); // disable auto // set HP FEC tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP); if (tmp < 0) return tmp; - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 7, tmp); + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp); // set LP FEC tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP); if (tmp < 0) return tmp; - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x38, tmp << 3); + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3); // set constellation switch (fe_params->u.ofdm.constellation) { case QPSK: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 0); break; case QAM_16: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 1); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 1); break; case QAM_64: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 2); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 2); break; default: @@ -821,19 +671,19 @@ // set hierarchy switch (fe_params->u.ofdm.hierarchy_information) { case HIERARCHY_NONE: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0 << 5); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0 << 5); break; case HIERARCHY_1: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 1 << 5); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 1 << 5); break; case HIERARCHY_2: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 2 << 5); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 2 << 5); break; case HIERARCHY_4: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 3 << 5); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 3 << 5); break; default: @@ -842,30 +692,26 @@ } // set bandwidth - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - tda10045h_set_bandwidth(i2c, tda_state, fe_params->u.ofdm.bandwidth); + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + tda10045h_set_bandwidth(state, fe_params->u.ofdm.bandwidth); break; - case FE_TYPE_TDA10046H: - tda10046h_set_bandwidth(i2c, tda_state, fe_params->u.ofdm.bandwidth); + case TDA1004X_DEMOD_TDA10046: + tda10046h_set_bandwidth(state, fe_params->u.ofdm.bandwidth); break; } - // need to invert the inversion for TT TDA10046H - inversion = fe_params->inversion; - if (tda_state->fe_type == FE_TYPE_TDA10046H) { - inversion = inversion ? INVERSION_OFF : INVERSION_ON; - } - // set inversion + inversion = fe_params->inversion; + if (state->config->invert) inversion = inversion ? INVERSION_OFF : INVERSION_ON; switch (inversion) { case INVERSION_OFF: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0); + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0); break; case INVERSION_ON: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0x20); + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0x20); break; default: @@ -875,28 +721,28 @@ // set guard interval switch (fe_params->u.ofdm.guard_interval) { case GUARD_INTERVAL_1_32: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); break; case GUARD_INTERVAL_1_16: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 1 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 1 << 2); break; case GUARD_INTERVAL_1_8: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 2 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 2 << 2); break; case GUARD_INTERVAL_1_4: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 3 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 3 << 2); break; case GUARD_INTERVAL_AUTO: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 2); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 2); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); break; default: @@ -906,18 +752,18 @@ // set transmission mode switch (fe_params->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0 << 4); + tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0 << 4); break; case TRANSMISSION_MODE_8K: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 1 << 4); + tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 1 << 4); break; case TRANSMISSION_MODE_AUTO: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 4); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0); + tda1004x_write_mask(state, TDA1004X_AUTO, 4, 4); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0); break; default: @@ -925,15 +771,15 @@ } // start the lock - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0); msleep(10); break; - case FE_TYPE_TDA10046H: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x40, 0x40); + case TDA1004X_DEMOD_TDA10046: + tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40); msleep(10); break; } @@ -941,25 +787,22 @@ return 0; } -static int tda1004x_get_fe(struct i2c_adapter *i2c, struct tda1004x_state* tda_state, struct dvb_frontend_parameters *fe_params) +static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params) { + struct tda1004x_state* state = fe->demodulator_priv; dprintk("%s\n", __FUNCTION__); // inversion status fe_params->inversion = INVERSION_OFF; - if (tda1004x_read_byte(i2c, tda_state, TDA1004X_CONFC1) & 0x20) { + if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20) { fe_params->inversion = INVERSION_ON; } - - // need to invert the inversion for TT TDA10046H - if (tda_state->fe_type == FE_TYPE_TDA10046H) { - fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON; - } + if (state->config->invert) fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON; // bandwidth - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - switch (tda1004x_read_byte(i2c, tda_state, TDA10045H_WREF_LSB)) { + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) { case 0x14: fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; break; @@ -972,8 +815,8 @@ } break; - case FE_TYPE_TDA10046H: - switch (tda1004x_read_byte(i2c, tda_state, TDA10046H_TIME_WREF1)) { + case TDA1004X_DEMOD_TDA10046: + switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) { case 0x60: fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; break; @@ -989,12 +832,12 @@ // FEC fe_params->u.ofdm.code_rate_HP = - tda1004x_decode_fec(tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) & 7); + tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7); fe_params->u.ofdm.code_rate_LP = - tda1004x_decode_fec((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) >> 3) & 7); + tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7); // constellation - switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 3) { + switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) { case 0: fe_params->u.ofdm.constellation = QPSK; break; @@ -1008,12 +851,12 @@ // transmission mode fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; - if (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x10) { + if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10) { fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; } // guard interval - switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) { + switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) { case 0: fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; @@ -1029,7 +872,7 @@ } // hierarchy - switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x60) >> 5) { + switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) { case 0: fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE; break; @@ -1047,8 +890,9 @@ return 0; } -static int tda1004x_read_status(struct i2c_adapter *i2c, struct tda1004x_state* tda_state, fe_status_t * fe_status) +static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status) { + struct tda1004x_state* state = fe->demodulator_priv; int status; int cber; int vber; @@ -1056,7 +900,7 @@ dprintk("%s\n", __FUNCTION__); // read status - status = tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD); + status = tda1004x_read_byte(state, TDA1004X_STATUS_CD); if (status == -1) { return -EIO; } @@ -1071,12 +915,12 @@ // is getting anything valid if (!(*fe_status & FE_HAS_VITERBI)) { // read the CBER - cber = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); + cber = tda1004x_read_byte(state, TDA1004X_CBER_LSB); if (cber == -1) return -EIO; - status = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); + status = tda1004x_read_byte(state, TDA1004X_CBER_MSB); if (status == -1) return -EIO; cber |= (status << 8); - tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); + tda1004x_read_byte(state, TDA1004X_CBER_RESET); if (cber != 65535) { *fe_status |= FE_HAS_VITERBI; @@ -1087,15 +931,15 @@ // bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid. if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) { // read the VBER - vber = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_LSB); + vber = tda1004x_read_byte(state, TDA1004X_VBER_LSB); if (vber == -1) return -EIO; - status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MID); + status = tda1004x_read_byte(state, TDA1004X_VBER_MID); if (status == -1) return -EIO; vber |= (status << 8); - status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MSB); + status = tda1004x_read_byte(state, TDA1004X_VBER_MSB); if (status == -1) return -EIO; vber |= ((status << 16) & 0x0f); - tda1004x_read_byte(i2c, tda_state, TDA1004X_CVBER_LUT); + tda1004x_read_byte(state, TDA1004X_CVBER_LUT); // if RS has passed some valid TS packets, then we must be // getting some SYNC bytes @@ -1109,26 +953,27 @@ return 0; } -static int tda1004x_read_signal_strength(struct i2c_adapter *i2c, struct tda1004x_state* tda_state, u16 * signal) +static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal) { + struct tda1004x_state* state = fe->demodulator_priv; int tmp; int reg = 0; dprintk("%s\n", __FUNCTION__); // determine the register to use - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: reg = TDA10045H_S_AGC; break; - case FE_TYPE_TDA10046H: + case TDA1004X_DEMOD_TDA10046: reg = TDA10046H_AGC_IF_LEVEL; break; } // read it - tmp = tda1004x_read_byte(i2c, tda_state, reg); + tmp = tda1004x_read_byte(state, reg); if (tmp < 0) return -EIO; @@ -1137,14 +982,15 @@ return 0; } -static int tda1004x_read_snr(struct i2c_adapter *i2c, struct tda1004x_state* tda_state, u16 * snr) +static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr) { + struct tda1004x_state* state = fe->demodulator_priv; int tmp; dprintk("%s\n", __FUNCTION__); // read it - tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SNR); + tmp = tda1004x_read_byte(state, TDA1004X_SNR); if (tmp < 0) return -EIO; if (tmp) { @@ -1156,8 +1002,9 @@ return 0; } -static int tda1004x_read_ucblocks(struct i2c_adapter *i2c, struct tda1004x_state* tda_state, u32* ucblocks) +static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { + struct tda1004x_state* state = fe->demodulator_priv; int tmp; int tmp2; int counter; @@ -1166,16 +1013,16 @@ // read the UCBLOCKS and reset counter = 0; - tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); + tmp = tda1004x_read_byte(state, TDA1004X_UNCOR); if (tmp < 0) return -EIO; tmp &= 0x7f; while (counter++ < 5) { - tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0); - tmp2 = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); + tmp2 = tda1004x_read_byte(state, TDA1004X_UNCOR); if (tmp2 < 0) return -EIO; tmp2 &= 0x7f; @@ -1192,373 +1039,189 @@ return 0; } -static int tda1004x_read_ber(struct i2c_adapter *i2c, struct tda1004x_state* tda_state, u32* ber) +static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber) { + struct tda1004x_state* state = fe->demodulator_priv; int tmp; dprintk("%s\n", __FUNCTION__); // read it in - tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); + tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB); if (tmp < 0) return -EIO; *ber = tmp << 1; - tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); + tmp = tda1004x_read_byte(state, TDA1004X_CBER_MSB); if (tmp < 0) return -EIO; *ber |= (tmp << 9); - tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); + tda1004x_read_byte(state, TDA1004X_CBER_RESET); dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); return 0; } -static int tda1004x_sleep(struct i2c_adapter *i2c, struct tda1004x_state* tda_state) +static int tda1004x_sleep(struct dvb_frontend* fe) { - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFADC1, 0x10, 0x10); - break; + struct tda1004x_state* state = fe->demodulator_priv; - case FE_TYPE_TDA10046H: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 1); - break; - } - - return 0; -} - -static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct tda1004x_state *tda_state = (struct tda1004x_state *) fe->data; - struct i2c_adapter *i2c = tda_state->i2c; - int status = 0; - - dprintk("%s: cmd=0x%x\n", __FUNCTION__, cmd); - - switch (cmd) { - case FE_GET_INFO: - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - memcpy(arg, &tda10045h_info, sizeof(struct dvb_frontend_info)); + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10); break; - case FE_TYPE_TDA10046H: - memcpy(arg, &tda10046h_info, sizeof(struct dvb_frontend_info)); + case TDA1004X_DEMOD_TDA10046: + tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); break; } - break; - - case FE_READ_STATUS: - return tda1004x_read_status(i2c, tda_state, (fe_status_t *) arg); - - case FE_READ_BER: - return tda1004x_read_ber(i2c, tda_state, (u32 *) arg); - - case FE_READ_SIGNAL_STRENGTH: - return tda1004x_read_signal_strength(i2c, tda_state, (u16 *) arg); - - case FE_READ_SNR: - return tda1004x_read_snr(i2c, tda_state, (u16 *) arg); - - case FE_READ_UNCORRECTED_BLOCKS: - return tda1004x_read_ucblocks(i2c, tda_state, (u32 *) arg); - - case FE_SET_FRONTEND: - return tda1004x_set_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); - - case FE_GET_FRONTEND: - return tda1004x_get_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); - - case FE_SLEEP: - tda_state->initialised = 0; - return tda1004x_sleep(i2c, tda_state); - - case FE_INIT: + state->initialised = 0; - // don't bother reinitialising - if (tda_state->initialised) return 0; - - // OK, perform initialisation - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - status = tda10045h_init(i2c, tda_state); - break; - - case FE_TYPE_TDA10046H: - status = tda10046h_init(i2c, tda_state); - break; } - if (status == 0) - tda_state->initialised = 1; - return status; - case FE_GET_TUNE_SETTINGS: +static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; fesettings->min_delay_ms = 800; fesettings->step_size = 166667; fesettings->max_drift = 166667*2; return 0; } - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static int tda1004x_attach(struct i2c_adapter *i2c, struct tda1004x_state* state) +static void tda1004x_release(struct dvb_frontend* fe) { - int tda1004x_address = -1; - int tuner_address = -1; - int fe_type = -1; - int tuner_type = -1; - struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=NULL, .len=0 }; - static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab }; - static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; - static u8 td1316_init_tda10046h[] = { 0x0b, 0xf5, 0x80, 0xab }; - - dprintk("%s\n", __FUNCTION__); - - // probe for tda10045h - if (tda1004x_address == -1) { - state->tda1004x_address = 0x08; - if (tda1004x_read_byte(i2c, state, TDA1004X_CHIPID) == 0x25) { - tda1004x_address = 0x08; - fe_type = FE_TYPE_TDA10045H; - printk("tda1004x: Detected Philips TDA10045H.\n"); - } - } - - // probe for tda10046h - if (tda1004x_address == -1) { - state->tda1004x_address = 0x08; - if (tda1004x_read_byte(i2c, state, TDA1004X_CHIPID) == 0x46) { - tda1004x_address = 0x08; - fe_type = FE_TYPE_TDA10046H; - printk("tda1004x: Detected Philips TDA10046H.\n"); - } - } - - // did we find a frontend? - if (tda1004x_address == -1) { - return -ENODEV; - } - - // enable access to the tuner - tda1004x_enable_tuner_i2c(i2c, state); - - // check for a TD1344 first - if (tuner_address == -1) { - tuner_msg.addr = 0x61; - tuner_msg.buf = td1344_init; - tuner_msg.len = sizeof(td1344_init); - if (i2c_transfer(i2c, &tuner_msg, 1) == 1) { - msleep(1); - tuner_address = 0x61; - tuner_type = TUNER_TYPE_TD1344; - printk("tda1004x: Detected Philips TD1344 tuner.\n"); - } - } - - // OK, try a TD1316 on address 0x63 - if (tuner_address == -1) { - tuner_msg.addr = 0x63; - tuner_msg.buf = td1316_init; - tuner_msg.len = sizeof(td1316_init); - if (i2c_transfer(i2c, &tuner_msg, 1) == 1) { - msleep(1); - tuner_address = 0x63; - tuner_type = TUNER_TYPE_TD1316; - printk("tda1004x: Detected Philips TD1316 tuner.\n"); - } - } - - // OK, TD1316 again, on address 0x60 (TDA10046H) - if (tuner_address == -1) { - tuner_msg.addr = 0x60; - tuner_msg.buf = td1316_init_tda10046h; - tuner_msg.len = sizeof(td1316_init_tda10046h); - if (i2c_transfer(i2c, &tuner_msg, 1) == 1) { - msleep(1); - tuner_address = 0x60; - tuner_type = TUNER_TYPE_TD1316; - printk("tda1004x: Detected Philips TD1316 tuner.\n"); - } - } - tda1004x_disable_tuner_i2c(i2c, state); - - // did we find a tuner? - if (tuner_address == -1) { - printk("tda1004x: Detected, but with unknown tuner.\n"); - return -ENODEV; + struct tda1004x_state* state = (struct tda1004x_state*) fe->demodulator_priv; + kfree(state); } - // create state - state->tda1004x_address = tda1004x_address; - state->fe_type = fe_type; - state->tuner_address = tuner_address; - state->tuner_type = tuner_type; - state->initialised = 0; - - return 0; -} +static struct dvb_frontend_ops tda10045_ops; -static struct i2c_client client_template; - -static int attach_adapter(struct i2c_adapter *adapter) +struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, + struct i2c_adapter* i2c) { - struct i2c_client *client; - struct tda1004x_state *state; - int ret; - - dprintk ("%s\n", __FUNCTION__); - - if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { - return -ENOMEM; - } + struct tda1004x_state* state = NULL; - if (NULL == (state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL))) { - kfree(client); - return -ENOMEM; - } - state->i2c = adapter; - - ret = tda1004x_attach(adapter, state); - if (ret) { - kfree(state); - kfree(client); - return -ENODEV; - } - - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = state->tda1004x_address; - i2c_set_clientdata(client, (void*)state); - - ret = i2c_attach_client(client); - if (ret) { - kfree(client); - kfree(state); - return ret; - } + /* allocate memory for the internal state */ + state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + if (state == NULL) goto error; - // upload firmware - BUG_ON(!state->dvb); - - switch(state->fe_type) { - case FE_TYPE_TDA10045H: - state->dspCodeCounterReg = TDA10045H_FWPAGE; - state->dspCodeInReg = TDA10045H_CODE_IN; - state->dspVersion = 0x2c; - - ret = tda10045_fwupload(adapter, state, client); - if (ret) { - printk("tda1004x: firmware upload failed\n"); - goto out; - } + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops)); + state->initialised = 0; + state->demod_type = TDA1004X_DEMOD_TDA10045; - ret = dvb_register_frontend(tda1004x_ioctl, state->dvb, - state, &tda10045h_info, - THIS_MODULE); - break; - case FE_TYPE_TDA10046H: - state->dspCodeCounterReg = TDA10046H_CODE_CPT; - state->dspCodeInReg = TDA10046H_CODE_IN; - state->dspVersion = 0x20; - - ret = tda10046_fwupload(adapter, state, client); - if (ret) { - printk("tda1004x: firmware upload failed\n"); - goto out; - } + /* check if the demod is there */ + if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) goto error; - ret = dvb_register_frontend(tda1004x_ioctl, state->dvb, - state, &tda10046h_info, - THIS_MODULE); - break; - default: - BUG_ON(1); - } + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; - if (ret) { - printk("tda1004x: registering frontend failed\n"); - goto out; +error: + if (state) kfree(state); + return NULL; } - return 0; -out: - i2c_detach_client(client); - kfree(client); - kfree(state); - return ret; -} - -static int detach_client(struct i2c_client *client) -{ - struct tda1004x_state *state = (struct tda1004x_state*)i2c_get_clientdata(client); - - dprintk ("%s\n", __FUNCTION__); +static struct dvb_frontend_ops tda10046_ops; - dvb_unregister_frontend (tda1004x_ioctl, state->dvb); - i2c_detach_client(client); - BUG_ON(state->dvb); - kfree(client); - kfree(state); - return 0; -} - -static int command (struct i2c_client *client, unsigned int cmd, void *arg) +struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, + struct i2c_adapter* i2c) { - struct tda1004x_state *state = (struct tda1004x_state*)i2c_get_clientdata(client); + struct tda1004x_state* state = NULL; - dprintk ("%s\n", __FUNCTION__); + /* allocate memory for the internal state */ + state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + if (state == NULL) goto error; - switch (cmd) { - case FE_REGISTER: - state->dvb = (struct dvb_adapter*)arg; - break; - case FE_UNREGISTER: - state->dvb = NULL; - break; - default: - return -EOPNOTSUPP; - } - return 0; -} + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops)); + state->initialised = 0; + state->demod_type = TDA1004X_DEMOD_TDA10046; -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = FRONTEND_NAME, - .id = I2C_DRIVERID_DVBFE_TDA1004X, - .flags = I2C_DF_NOTIFY, - .attach_adapter = attach_adapter, - .detach_client = detach_client, - .command = command, -}; + /* check if the demod is there */ + if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) goto error; -static struct i2c_client client_template = { - .name = FRONTEND_NAME, - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; + } + +static struct dvb_frontend_ops tda10045_ops = { + + .info = { + .name = "Philips TDA10045H DVB-T", + .type = FE_OFDM, + .frequency_min = 51000000, + .frequency_max = 858000000, + .frequency_stepsize = 166667, + .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 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO + }, + + .release = tda1004x_release, + + .init = tda10045_init, + .sleep = tda1004x_sleep, + + .set_frontend = tda1004x_set_fe, + .get_frontend = tda1004x_get_fe, + .get_tune_settings = tda1004x_get_tune_settings, + + .read_status = tda1004x_read_status, + .read_ber = tda1004x_read_ber, + .read_signal_strength = tda1004x_read_signal_strength, + .read_snr = tda1004x_read_snr, + .read_ucblocks = tda1004x_read_ucblocks, }; -static int __init init_tda1004x(void) -{ - return i2c_add_driver(&driver); -} +static struct dvb_frontend_ops tda10046_ops = { -static void __exit exit_tda1004x(void) -{ - if (i2c_del_driver(&driver)) - printk("tda1004x: driver deregistration failed\n"); -} + .info = { + .name = "Philips TDA10046H DVB-T", + .type = FE_OFDM, + .frequency_min = 51000000, + .frequency_max = 858000000, + .frequency_stepsize = 166667, + .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 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO + }, + + .release = tda1004x_release, + + .init = tda10046_init, + .sleep = tda1004x_sleep, + + .set_frontend = tda1004x_set_fe, + .get_frontend = tda1004x_get_fe, + .get_tune_settings = tda1004x_get_tune_settings, + + .read_status = tda1004x_read_status, + .read_ber = tda1004x_read_ber, + .read_signal_strength = tda1004x_read_signal_strength, + .read_snr = tda1004x_read_snr, + .read_ucblocks = tda1004x_read_ucblocks, +}; -module_init(init_tda1004x); -module_exit(exit_tda1004x); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Frontend"); +MODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Demodulator"); MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(tda10045_attach); +EXPORT_SYMBOL(tda10046_attach); +EXPORT_SYMBOL(tda1004x_write_byte); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/ves1820.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/ves1820.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/ves1820.c 2004-12-22 10:04:35.846353378 -0800 @@ -1,6 +1,5 @@ /* VES1820 - Single Chip Cable Channel Receiver driver module - used on the the Siemens DVB-C cards Copyright (C) 1999 Convergence Integrated Media GmbH @@ -27,70 +26,34 @@ #include #include #include +#include #include "dvb_frontend.h" +#include "ves1820.h" -/* I2C_DRIVERID_VES1820 is already defined in i2c-id.h */ -#if 0 -static int debug = 0; -#define dprintk if (debug) printk -#endif - -static int verbose; struct ves1820_state { - int pwm; - u8 reg0; - int tuner; - u8 demod_addr; - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; -}; -/* possible ves1820 adresses */ -static u8 addr[] = { 0x61, 0x62 }; + struct i2c_adapter *i2c; -#if defined(CONFIG_DBOX2) -#define XIN 69600000UL -#define DISABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0) -#define ENABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0) -#define HAS_INVERSION(reg0) (reg0 & 0x20) -#else /* PCI cards */ -#define XIN 57840000UL -#define DISABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0) -#define ENABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0) -#define HAS_INVERSION(reg0) (!(reg0 & 0x20)) -#endif - -#define FIN (XIN >> 4) + struct dvb_frontend_ops ops; + /* configuration settings */ + const struct ves1820_config* config; + struct dvb_frontend frontend; -static struct dvb_frontend_info ves1820_info = { - .name = "VES1820 based DVB-C frontend", - .type = FE_QAM, - .frequency_stepsize = 62500, - .frequency_min = 51000000, - .frequency_max = 858000000, - .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */ - .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */ -#if 0 - .frequency_tolerance = ???, - .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */ - .notifier_delay = ?, -#endif - .caps = FE_CAN_QAM_16 | - FE_CAN_QAM_32 | - FE_CAN_QAM_64 | - FE_CAN_QAM_128 | - FE_CAN_QAM_256 | - FE_CAN_FEC_AUTO | - FE_CAN_INVERSION_AUTO, + /* private demodulator data */ + u8 reg0; + u8 pwm; }; + +static int verbose; + static u8 ves1820_inittab[] = { - 0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A, + 0x69, 0x6A, 0x93, 0x12, 0x12, 0x46, 0x26, 0x1A, 0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20, 0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, @@ -102,7 +65,7 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data) { u8 buf[] = { 0x00, reg, data }; - struct i2c_msg msg = {.addr = state->demod_addr,.flags = 0,.buf = buf,.len = 3 }; + struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 3 }; int ret; ret = i2c_transfer(state->i2c, &msg, 1); @@ -120,8 +83,8 @@ u8 b0 [] = { 0x00, reg }; u8 b1 [] = { 0 }; struct i2c_msg msg[] = { - {.addr = state->demod_addr,.flags = 0,.buf = b0,.len = 2}, - {.addr = state->demod_addr,.flags = I2C_M_RD,.buf = b1,.len = 1} + {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 2}, + {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1} }; int ret; @@ -134,148 +97,88 @@ return b1[0]; } -static int tuner_write(struct ves1820_state *state, u8 addr, u8 data[4]) -{ - int ret; - struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; - - ret = i2c_transfer(state->i2c, &msg, 1); - - if (ret != 1) - printk("ves1820: %s(): i/o error (ret == %i)\n", __FUNCTION__, ret); - - return (ret != 1) ? -EREMOTEIO : 0; -} - - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 62.5 kHz. - */ -static int tuner_set_tv_freq(struct ves1820_state *state, u32 freq) -{ - u32 div, ifreq; - static u8 byte3 [] = { 0x8e, 0x85 }; - int tuner_type = state->tuner; - u8 buf [4]; - - if (tuner_type == 0xff) /* PLL not reachable over i2c ... */ - return 0; - - if (strstr(state->i2c->name, "Technotrend") - || strstr(state->i2c->name, "TT-Budget")) - ifreq = 35937500; - else - ifreq = 36125000; - - div = (freq + ifreq + 31250) / 62500; - - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = byte3[tuner_type]; - - if (tuner_type == 1) { - buf[2] |= (div >> 10) & 0x60; - buf[3] = (freq < 174000000 ? 0x88 : freq < 470000000 ? 0x84 : 0x81); - } else { - buf[3] = (freq < 174000000 ? 0xa1 : freq < 454000000 ? 0x92 : 0x34); - } - - return tuner_write(state, addr[tuner_type], buf); -} static int ves1820_setup_reg0(struct ves1820_state *state, u8 reg0, fe_spectral_inversion_t inversion) { reg0 |= state->reg0 & 0x62; - if (INVERSION_ON == inversion) - ENABLE_INVERSION(reg0); - else if (INVERSION_OFF == inversion) - DISABLE_INVERSION(reg0); + if (INVERSION_ON == inversion) { + if (!state->config->invert) reg0 |= 0x20; + else reg0 &= ~0x20; - ves1820_writereg(state, 0x00, reg0 & 0xfe); - ves1820_writereg(state, 0x00, reg0 | 0x01); + } else if (INVERSION_OFF == inversion) { + + if (!state->config->invert) reg0 &= ~0x20; + else reg0 |= 0x20; + } - /** - * check lock and toggle inversion bit if required... - */ - if (INVERSION_AUTO == inversion && !(ves1820_readreg(state, 0x11) & 0x08)) { - mdelay(50); - if (!(ves1820_readreg(state, 0x11) & 0x08)) { - reg0 ^= 0x20; ves1820_writereg(state, 0x00, reg0 & 0xfe); ves1820_writereg(state, 0x00, reg0 | 0x01); - } - } state->reg0 = reg0; return 0; } -static int ves1820_init(struct ves1820_state *state) -{ - int i; - - ves1820_writereg(state, 0, 0); - -#if defined(CONFIG_DBOX2) - ves1820_inittab[2] &= ~0x08; -#endif - - for (i=0; i<53; i++) - ves1820_writereg(state, i, ves1820_inittab[i]); - - ves1820_writereg(state, 0x34, state->pwm); - - return 0; -} - static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate) { s32 BDR; s32 BDRI; s16 SFIL=0; u16 NDEC = 0; - u32 tmp, ratio; + u32 ratio; + u32 fin; + u32 tmp; + u64 fptmp; + u64 fpxin; - if (symbolrate > XIN/2) - symbolrate = XIN/2; + if (symbolrate > state->config->xin / 2) + symbolrate = state->config->xin / 2; if (symbolrate < 500000) symbolrate = 500000; - if (symbolrate < XIN / 16) + if (symbolrate < state->config->xin / 16) NDEC = 1; - if (symbolrate < XIN / 32) + if (symbolrate < state->config->xin / 32) NDEC = 2; - if (symbolrate < XIN / 64) + if (symbolrate < state->config->xin / 64) NDEC = 3; - if (symbolrate < (u32) (XIN / 12.3)) + /* yeuch! */ + fpxin = state->config->xin * 10; + fptmp = fpxin; do_div(fptmp, 123); + if (symbolrate < fptmp); SFIL = 1; - if (symbolrate < (u32) (XIN / 16)) + fptmp = fpxin; do_div(fptmp, 160); + if (symbolrate < fptmp); SFIL = 0; - if (symbolrate < (u32) (XIN / 24.6)) + fptmp = fpxin; do_div(fptmp, 246); + if (symbolrate < fptmp); SFIL = 1; - if (symbolrate < (u32) (XIN / 32)) + fptmp = fpxin; do_div(fptmp, 320); + if (symbolrate < fptmp); SFIL = 0; - if (symbolrate < (u32) (XIN / 49.2)) + fptmp = fpxin; do_div(fptmp, 492); + if (symbolrate < fptmp); SFIL = 1; - if (symbolrate < (u32) (XIN / 64)) + fptmp = fpxin; do_div(fptmp, 640); + if (symbolrate < fptmp); SFIL = 0; - if (symbolrate < (u32) (XIN / 98.4)) + fptmp = fpxin; do_div(fptmp, 984); + if (symbolrate < fptmp); SFIL = 1; + fin = state->config->xin >> 4; symbolrate <<= NDEC; - ratio = (symbolrate << 4) / FIN; - tmp = ((symbolrate << 4) % FIN) << 8; - ratio = (ratio << 8) + tmp / FIN; - tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + (tmp + FIN/2) / FIN; + ratio = (symbolrate << 4) / fin; + tmp = ((symbolrate << 4) % fin) << 8; + ratio = (ratio << 8) + tmp / fin; + tmp = (tmp % fin) << 8; + ratio = (ratio << 8) + (tmp + fin / 2) / fin; BDR = ratio; - BDRI = (((XIN << 5) / symbolrate) + 1) / 2; + BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2; if (BDRI > 0xFF) BDRI = 0xFF; @@ -295,8 +198,42 @@ return 0; } -static int ves1820_set_parameters(struct ves1820_state *state, struct dvb_frontend_parameters *p) + + + + + + + + + + + + +static int ves1820_init(struct dvb_frontend* fe) { + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + int i; + int val; + + ves1820_writereg(state, 0, 0); + + for (i = 0; i < 53; i++) { + val = ves1820_inittab[i]; + if ((i == 2) && (state->config->selagc)) val |= 0x08; + ves1820_writereg(state, i, val); + } + + ves1820_writereg(state, 0x34, state->pwm); + + if (state->config->pll_init) state->config->pll_init(fe); + + return 0; +} + +static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; static const u8 reg0x00 [] = { 0x00, 0x04, 0x08, 0x0c, 0x10 }; static const u8 reg0x01 [] = { 140, 140, 106, 100, 92 }; static const u8 reg0x05 [] = { 135, 100, 70, 54, 38 }; @@ -307,7 +244,7 @@ if (real_qam < 0 || real_qam > 4) return -EINVAL; - tuner_set_tv_freq(state, p->frequency); + state->config->pll_set(fe, p); ves1820_set_symbolrate(state, p->u.qam.symbol_rate); ves1820_writereg(state, 0x34, state->pwm); @@ -318,25 +255,12 @@ ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion); - /* yes, this speeds things up: userspace reports lock in about 8 ms - instead of 500 to 1200 ms after calling FE_SET_FRONTEND. */ - mdelay(50); - return 0; } -static int ves1820_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct ves1820_state *state = (struct ves1820_state *) fe->data; - - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &ves1820_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: - { - fe_status_t *status = (fe_status_t *) arg; + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; int sync; *status = 0; @@ -358,46 +282,59 @@ if (sync & 8) *status |= FE_HAS_LOCK; - break; + return 0; } - case FE_READ_BER: +static int ves1820_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 ber = ves1820_readreg(state, 0x14) | + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + + u32 _ber = ves1820_readreg(state, 0x14) | (ves1820_readreg(state, 0x15) << 8) | ((ves1820_readreg(state, 0x16) & 0x0f) << 16); - *((u32*) arg) = 10 * ber; - break; + *ber = 10 * _ber; + + return 0; } - case FE_READ_SIGNAL_STRENGTH: + +static int ves1820_read_signal_strength(struct dvb_frontend* fe, u16* strength) { + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + u8 gain = ves1820_readreg(state, 0x17); - *((u16*) arg) = (gain << 8) | gain; - break; + *strength = (gain << 8) | gain; + + return 0; } - case FE_READ_SNR: +static int ves1820_read_snr(struct dvb_frontend* fe, u16* snr) { + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + u8 quality = ~ves1820_readreg(state, 0x18); - *((u16*) arg) = (quality << 8) | quality; - break; + *snr = (quality << 8) | quality; + + return 0; } - case FE_READ_UNCORRECTED_BLOCKS: - *((u32 *) arg) = ves1820_readreg(state, 0x13) & 0x7f; - if (*((u32*) arg) == 0x7f) - *((u32*) arg) = 0xffffffff; +static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + + *ucblocks = ves1820_readreg(state, 0x13) & 0x7f; + if (*ucblocks == 0x7f) + *ucblocks = 0xffffffff; + /* reset uncorrected block counter */ ves1820_writereg(state, 0x10, ves1820_inittab[0x10] & 0xdf); ves1820_writereg(state, 0x10, ves1820_inittab[0x10]); - break; - case FE_SET_FRONTEND: - return ves1820_set_parameters(state, arg); + return 0; +} - case FE_GET_FRONTEND: +static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = (struct dvb_frontend_parameters *)arg; + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; int sync; s8 afc = 0; @@ -409,7 +346,12 @@ "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->u.qam.symbol_rate * afc) >> 10); } - p->inversion = HAS_INVERSION(state->reg0) ? INVERSION_ON : INVERSION_OFF; + if (!state->config->invert) { + p->inversion = (state->reg0 & 0x20) ? INVERSION_ON : INVERSION_OFF; + } else { + p->inversion = (!(state->reg0 & 0x20)) ? INVERSION_ON : INVERSION_OFF; + } + p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16; p->u.qam.fec_inner = FEC_NONE; @@ -417,229 +359,112 @@ p->frequency = ((p->frequency + 31250) / 62500) * 62500; if (sync & 2) p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10; - break; - } - case FE_SLEEP: - ves1820_writereg(state, 0x1b, 0x02); /* pdown ADC */ - ves1820_writereg(state, 0x00, 0x80); /* standby */ - break; - - case FE_INIT: - return ves1820_init(state); - - default: - return -EINVAL; - } return 0; } -static long probe_tuner(struct i2c_adapter *i2c) +static int ves1820_sleep(struct dvb_frontend* fe) { - struct i2c_msg msg1 = {.addr = 0x61,.flags = 0,.buf = NULL,.len = 0 }; - struct i2c_msg msg2 = {.addr = 0x62,.flags = 0,.buf = NULL,.len = 0 }; - int type; - - if (i2c_transfer(i2c, &msg1, 1) == 1) { - type = 0; - printk("ves1820: setup for tuner spXXXX\n"); - } else if (i2c_transfer(i2c, &msg2, 1) == 1) { - type = 1; - printk("ves1820: setup for tuner sp5659c\n"); - } else { - type = -1; - } - - return type; -} + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; -static u8 read_pwm(struct i2c_adapter *i2c) -{ - u8 b = 0xff; - u8 pwm; - struct i2c_msg msg [] = { { .addr = 0x50, .flags = 0, .buf = &b, .len = 1 }, - {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} - }; - - if ((i2c_transfer(i2c, msg, 2) != 2) || (pwm == 0xff)) - pwm = 0x48; - - printk("ves1820: pwm=0x%02x\n", pwm); - - return pwm; -} - -static long probe_demod_addr(struct i2c_adapter *i2c) -{ - u8 b [] = { 0x00, 0x1a }; - u8 id; - struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b, .len = 2 }, - {.addr = 0x08,.flags = I2C_M_RD,.buf = &id,.len = 1} - }; - - if (i2c_transfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70) - return msg[0].addr; - - msg[0].addr = msg[1].addr = 0x09; - - if (i2c_transfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70) - return msg[0].addr; - - return -1; -} - -static ssize_t attr_read_pwm(struct device *dev, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ves1820_state *state = (struct ves1820_state *) i2c_get_clientdata(client); - return sprintf(buf, "0x%02x\n", state->pwm); -} + ves1820_writereg(state, 0x1b, 0x02); /* pdown ADC */ + ves1820_writereg(state, 0x00, 0x80); /* standby */ -static ssize_t attr_write_pwm(struct device *dev, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ves1820_state *state = (struct ves1820_state *) i2c_get_clientdata(client); - unsigned long pwm; - pwm = simple_strtoul(buf, NULL, 0); - state->pwm = pwm & 0xff; - return strlen(buf)+1; + return 0; } -static struct device_attribute dev_attr_client_name = { - .attr = { .name = "pwm", .mode = S_IRUGO|S_IWUGO, .owner = THIS_MODULE }, - .show = &attr_read_pwm, - .store = &attr_write_pwm, -}; - -static struct i2c_client client_template; - -static int attach_adapter(struct i2c_adapter *adapter) +static int ves1820_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - struct i2c_client *client; - struct ves1820_state *state; - long demod_addr; - int tuner_type; - int ret; - - demod_addr = probe_demod_addr(adapter); - if (demod_addr < 0) - return -ENODEV; - - tuner_type = probe_tuner(adapter); - if (tuner_type < 0) { - printk("ves1820: demod found, but unknown tuner type.\n"); - return -ENODEV; - } - - if ((state = kmalloc(sizeof(struct ves1820_state), GFP_KERNEL)) == NULL) { - return -ENOMEM; - } - - if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { - kfree(state); - return -ENOMEM; - } - - memset(state, 0, sizeof(*state)); - state->i2c = adapter; - state->tuner = tuner_type; - state->pwm = read_pwm(adapter); - state->reg0 = ves1820_inittab[0]; - state->demod_addr = demod_addr; - - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = addr[tuner_type]; - - i2c_set_clientdata(client, (void *) state); - - ret = i2c_attach_client(client); - if (ret) { - kfree(client); - kfree(state); - return ret; -} - - BUG_ON(!state->dvb); - - device_create_file(&client->dev, &dev_attr_client_name); - - ret = dvb_register_frontend(ves1820_ioctl, state->dvb, state, &ves1820_info, THIS_MODULE); - if (ret) { - i2c_detach_client(client); - kfree(client); - kfree(state); - return ret; - } + fesettings->min_delay_ms = 200; + fesettings->step_size = 0; + fesettings->max_drift = 0; return 0; } -static int detach_client(struct i2c_client *client) +static void ves1820_release(struct dvb_frontend* fe) { - struct ves1820_state *state = (struct ves1820_state *) i2c_get_clientdata(client); - dvb_unregister_frontend(ves1820_ioctl, state->dvb); - device_remove_file(&client->dev, &dev_attr_client_name); - i2c_detach_client(client); - BUG_ON(state->dvb); - kfree(client); + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; kfree(state); - return 0; -} - -static int command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct ves1820_state *state = (struct ves1820_state *) i2c_get_clientdata(client); - - switch (cmd) { - case FE_REGISTER:{ - state->dvb = (struct dvb_adapter *) arg; - break; - } - case FE_UNREGISTER:{ - state->dvb = NULL; - break; - } - default: - return -EOPNOTSUPP; - } - return 0; } -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = "ves1820", - .id = I2C_DRIVERID_VES1820, - .flags = I2C_DF_NOTIFY, - .attach_adapter = attach_adapter, - .detach_client = detach_client, - .command = command, -}; +static struct dvb_frontend_ops ves1820_ops; -static struct i2c_client client_template = { - I2C_DEVNAME("ves1820"), - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, -}; - -static int __init init_ves1820 (void) +struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, + struct i2c_adapter* i2c, + u8 pwm) { - return i2c_add_driver(&driver); -} + struct ves1820_state* state = NULL; -static void __exit exit_ves1820 (void) -{ - if (i2c_del_driver(&driver)) - printk("ves1820: driver deregistration failed\n"); -} + /* allocate memory for the internal state */ + state = (struct ves1820_state*) kmalloc(sizeof(struct ves1820_state), GFP_KERNEL); + if (state == NULL) + goto error; -module_init(init_ves1820); -module_exit(exit_ves1820); + /* setup the state */ + memcpy(&state->ops, &ves1820_ops, sizeof(struct dvb_frontend_ops)); + state->reg0 = ves1820_inittab[0]; + state->config = config; + state->i2c = i2c; + state->pwm = pwm; + + /* check if the demod is there */ + if ((ves1820_readreg(state, 0x1a) & 0xf0) != 0x70) + goto error; + + if (verbose) + printk("ves1820: pwm=0x%02x\n", state->pwm); + + state->ops.info.symbol_rate_min = (state->config->xin / 2) / 64; /* SACLK/64 == (XIN/2)/64 */ + state->ops.info.symbol_rate_max = (state->config->xin / 2) / 4; /* SACLK/4 */ + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; + } + +static struct dvb_frontend_ops ves1820_ops = { + + .info = { + .name = "VLSI VES1820 DVB-C", + .type = FE_QAM, + .frequency_stepsize = 62500, + .frequency_min = 51000000, + .frequency_max = 858000000, + .caps = FE_CAN_QAM_16 | + FE_CAN_QAM_32 | + FE_CAN_QAM_64 | + FE_CAN_QAM_128 | + FE_CAN_QAM_256 | + FE_CAN_FEC_AUTO + }, + + .release = ves1820_release, + + .init = ves1820_init, + .sleep = ves1820_sleep, + + .set_frontend = ves1820_set_parameters, + .get_frontend = ves1820_get_frontend, + .get_tune_settings = ves1820_get_tune_settings, + + .read_status = ves1820_read_status, + .read_ber = ves1820_read_ber, + .read_signal_strength = ves1820_read_signal_strength, + .read_snr = ves1820_read_snr, + .read_ucblocks = ves1820_read_ucblocks, +}; -MODULE_PARM(verbose, "i"); +module_param(verbose, int, 0644); MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting"); -MODULE_DESCRIPTION("VES1820 DVB-C frontend driver"); +MODULE_DESCRIPTION("VLSI VES1820 DVB-C Demodulator driver"); MODULE_AUTHOR("Ralph Metzler, Holger Waechtler"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(ves1820_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/frontends/ves1x93.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/frontends/ves1x93.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/frontends/ves1x93.c 2004-12-22 10:04:35.860351250 -0800 @@ -1,5 +1,5 @@ /* - Driver for VES1893 and VES1993 QPSK Frontends + Driver for VES1893 and VES1993 QPSK Demodulators Copyright (C) 1999 Convergence Integrated Media GmbH Copyright (C) 2001 Ronny Strutz <3des@elitedvb.de> @@ -31,41 +31,33 @@ #include #include "dvb_frontend.h" +#include "ves1x93.h" -static int debug = 0; -#define dprintk if (debug) printk -static int board_type = 0; -#define BOARD_SIEMENS_PCI 0 -#define BOARD_NOKIA_DBOX2 1 -#define BOARD_SAGEM_DBOX2 2 +struct ves1x93_state { -static int demod_type = 0; -#define DEMOD_VES1893 0 -#define DEMOD_VES1993 1 + struct i2c_adapter* i2c; + + struct dvb_frontend_ops ops; + + /* configuration settings */ + const struct ves1x93_config* config; -static struct dvb_frontend_info ves1x93_info = { - .name = "VES1x93", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 125, /* kHz for QPSK frontends */ - .frequency_tolerance = 29500, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, -/* .symbol_rate_tolerance = ???,*/ - .notifier_delay = 50, /* 1/20 s */ - .caps = FE_CAN_INVERSION_AUTO | - 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 + struct dvb_frontend frontend; + + /* previous uncorrected block counter */ + fe_spectral_inversion_t inversion; + u8 *init_1x93_tab; + u8 *init_1x93_wtab; + u8 tab_size; + u8 demod_type; }; +static int debug = 0; +#define dprintk if (debug) printk -/** - * nokia dbox2 (ves1893) and sagem dbox2 (ves1993) - * need bit AGCR[PWMS] set to 1 - */ +#define DEMOD_VES1893 0 +#define DEMOD_VES1993 1 static u8 init_1893_tab [] = { 0x01, 0xa4, 0x35, 0x80, 0x2a, 0x0b, 0x55, 0xc4, @@ -89,10 +81,6 @@ 0x00, 0x00, 0x0e, 0x80, 0x00 }; - -static u8 * init_1x93_tab; - - static u8 init_1893_wtab[] = { 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0, @@ -110,21 +98,13 @@ 1,1,1,0,1,1,1,1, 1,1,1,1,1 }; -struct ves1x93_state { - fe_spectral_inversion_t inversion; - struct i2c_adapter *i2c; - struct dvb_adapter *dvb; -}; - - - -static int ves1x93_writereg (struct i2c_adapter *i2c, u8 reg, u8 data) +static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data) { u8 buf [] = { 0x00, reg, data }; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 3 }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 3 }; int err; - if ((err = i2c_transfer (i2c, &msg, 1)) != 1) { + if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); return -EREMOTEIO; } @@ -133,151 +113,31 @@ } -static u8 ves1x93_readreg (struct i2c_adapter *i2c, u8 reg) +static u8 ves1x93_readreg (struct ves1x93_state* state, u8 reg) { int ret; u8 b0 [] = { 0x00, reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b0, .len = 2 }, - { .addr = 0x08, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - ret = i2c_transfer (i2c, msg, 2); + ret = i2c_transfer (state->i2c, msg, 2); - if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + if (ret != 2) return ret; return b1[0]; } - -static int tuner_write (struct i2c_adapter *i2c, u8 *data, u8 len) -{ - int ret; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = len }; - - ves1x93_writereg(i2c, 0x00, 0x11); - ret = i2c_transfer (i2c, &msg, 1); - ves1x93_writereg(i2c, 0x00, 0x01); - - if (ret != 1) - printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); - - return (ret != 1) ? -1 : 0; -} - - - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 125 kHz. - */ -static int sp5659_set_tv_freq (struct i2c_adapter *i2c, u32 freq) -{ - u8 pwr = 0; - u8 buf[4]; - u32 div = (freq + 479500) / 125; - - if (freq > 2000000) pwr = 3; - else if (freq > 1800000) pwr = 2; - else if (freq > 1600000) pwr = 1; - else if (freq > 1200000) pwr = 0; - else if (freq >= 1100000) pwr = 1; - else pwr = 2; - - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = ((div & 0x18000) >> 10) | 0x95; - buf[3] = (pwr << 6) | 0x30; - - // NOTE: since we're using a prescaler of 2, we set the - // divisor frequency to 62.5kHz and divide by 125 above - - return tuner_write (i2c, buf, sizeof(buf)); -} - - -static int tsa5059_set_tv_freq (struct i2c_adapter *i2c, u32 freq) -{ - int ret; - u8 buf [2]; - - freq /= 1000; - - buf[0] = (freq >> 8) & 0x7F; - buf[1] = freq & 0xFF; - - ret = tuner_write(i2c, buf, sizeof(buf)); - - return ret; -} - - -static int tuner_set_tv_freq (struct i2c_adapter *i2c, u32 freq) -{ - if ((demod_type == DEMOD_VES1893) && (board_type == BOARD_SIEMENS_PCI)) - return sp5659_set_tv_freq (i2c, freq); - else if (demod_type == DEMOD_VES1993) - return tsa5059_set_tv_freq (i2c, freq); - - return -EINVAL; -} - - -static int ves1x93_init (struct i2c_adapter *i2c) -{ - int i; - int size; - u8 *init_1x93_wtab; - - dprintk("%s: init chip\n", __FUNCTION__); - - switch (demod_type) { - case DEMOD_VES1893: - init_1x93_tab = init_1893_tab; - init_1x93_wtab = init_1893_wtab; - size = sizeof(init_1893_tab); - if (board_type == BOARD_NOKIA_DBOX2) - init_1x93_tab[0x05] |= 0x20; /* invert PWM */ - break; - - case DEMOD_VES1993: - init_1x93_tab = init_1993_tab; - init_1x93_wtab = init_1993_wtab; - size = sizeof(init_1993_tab); - if (board_type == BOARD_SAGEM_DBOX2) - init_1x93_tab[0x05] |= 0x20; /* invert PWM */ - break; - - default: - return -EINVAL; - } - - for (i = 0; i < size; i++) - if (init_1x93_wtab[i]) - ves1x93_writereg (i2c, i, init_1x93_tab[i]); - - if (demod_type == DEMOD_VES1993) { - if (board_type == BOARD_NOKIA_DBOX2) - tuner_write(i2c, "\x06\x5c\x83\x60", 4); - else if (board_type == BOARD_SAGEM_DBOX2) - tuner_write(i2c, "\x25\x70\x92\x40", 4); - } - - return 0; -} - - -static int ves1x93_clr_bit (struct i2c_adapter *i2c) +static int ves1x93_clr_bit (struct ves1x93_state* state) { msleep(10); - ves1x93_writereg (i2c, 0, init_1x93_tab[0] & 0xfe); - ves1x93_writereg (i2c, 0, init_1x93_tab[0]); + ves1x93_writereg (state, 0, state->init_1x93_tab[0] & 0xfe); + ves1x93_writereg (state, 0, state->init_1x93_tab[0]); msleep(50); return 0; } - -static int ves1x93_set_inversion (struct i2c_adapter *i2c, fe_spectral_inversion_t inversion) +static int ves1x93_set_inversion (struct ves1x93_state* state, fe_spectral_inversion_t inversion) { u8 val; @@ -300,66 +160,47 @@ return -EINVAL; } - return ves1x93_writereg (i2c, 0x0c, (init_1x93_tab[0x0c] & 0x3f) | val); + return ves1x93_writereg (state, 0x0c, (state->init_1x93_tab[0x0c] & 0x3f) | val); } -static int ves1x93_set_fec (struct i2c_adapter *i2c, fe_code_rate_t fec) +static int ves1x93_set_fec (struct ves1x93_state* state, fe_code_rate_t fec) { if (fec == FEC_AUTO) - return ves1x93_writereg (i2c, 0x0d, 0x08); + return ves1x93_writereg (state, 0x0d, 0x08); else if (fec < FEC_1_2 || fec > FEC_8_9) return -EINVAL; else - return ves1x93_writereg (i2c, 0x0d, fec - FEC_1_2); + return ves1x93_writereg (state, 0x0d, fec - FEC_1_2); } -static fe_code_rate_t ves1x93_get_fec (struct i2c_adapter *i2c) +static fe_code_rate_t ves1x93_get_fec (struct ves1x93_state* state) { - return FEC_1_2 + ((ves1x93_readreg (i2c, 0x0d) >> 4) & 0x7); + return FEC_1_2 + ((ves1x93_readreg (state, 0x0d) >> 4) & 0x7); } -static int ves1x93_set_symbolrate (struct i2c_adapter *i2c, u32 srate) +static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate) { u32 BDR; u32 ratio; u8 ADCONF, FCONF, FNR; u32 BDRI; u32 tmp; - u32 XIN, FIN; + u32 FIN; dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate); - switch (board_type) { - case BOARD_SIEMENS_PCI: - XIN = 90100000UL; - break; - case BOARD_NOKIA_DBOX2: - if (demod_type == DEMOD_VES1893) - XIN = 91000000UL; - else if (demod_type == DEMOD_VES1993) - XIN = 96000000UL; - else - return -EINVAL; - break; - case BOARD_SAGEM_DBOX2: - XIN = 92160000UL; - break; - default: - return -EINVAL; - } - - if (srate > XIN/2) - srate = XIN/2; + if (srate > state->config->xin/2) + srate = state->config->xin/2; if (srate < 500000) srate = 500000; #define MUL (1UL<<26) - FIN = (XIN + 6000) >> 4; + FIN = (state->config->xin + 6000) >> 4; tmp = srate << 6; ratio = tmp / FIN; @@ -404,55 +245,87 @@ if (BDRI > 0xff) BDRI = 0xff; - ves1x93_writereg (i2c, 0x06, 0xff & BDR); - ves1x93_writereg (i2c, 0x07, 0xff & (BDR >> 8)); - ves1x93_writereg (i2c, 0x08, 0x0f & (BDR >> 16)); - - ves1x93_writereg (i2c, 0x09, BDRI); - ves1x93_writereg (i2c, 0x20, ADCONF); - ves1x93_writereg (i2c, 0x21, FCONF); + ves1x93_writereg (state, 0x06, 0xff & BDR); + ves1x93_writereg (state, 0x07, 0xff & (BDR >> 8)); + ves1x93_writereg (state, 0x08, 0x0f & (BDR >> 16)); + + ves1x93_writereg (state, 0x09, BDRI); + ves1x93_writereg (state, 0x20, ADCONF); + ves1x93_writereg (state, 0x21, FCONF); if (srate < 6000000) - ves1x93_writereg (i2c, 0x05, init_1x93_tab[0x05] | 0x80); + ves1x93_writereg (state, 0x05, state->init_1x93_tab[0x05] | 0x80); else - ves1x93_writereg (i2c, 0x05, init_1x93_tab[0x05] & 0x7f); + ves1x93_writereg (state, 0x05, state->init_1x93_tab[0x05] & 0x7f); /* ves1993 hates this, will lose lock */ - if (demod_type != DEMOD_VES1993) - ves1x93_clr_bit (i2c); + if (state->demod_type != DEMOD_VES1993) + ves1x93_clr_bit (state); return 0; } -static int ves1x93_set_voltage (struct i2c_adapter *i2c, fe_sec_voltage_t voltage) + + + + + + + + + + + + + + +static int ves1x93_init (struct dvb_frontend* fe) { + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + int i; + int val; + + dprintk("%s: init chip\n", __FUNCTION__); + + for (i = 0; i < state->tab_size; i++) { + if (state->init_1x93_wtab[i]) { + val = state->init_1x93_tab[i]; + + if (state->config->invert_pwm && (i == 0x05)) val |= 0x20; /* invert PWM */ + ves1x93_writereg (state, i, val); + } + } + + if (state->config->pll_init) { + ves1x93_writereg(state, 0x00, 0x11); + state->config->pll_init(fe); + ves1x93_writereg(state, 0x00, 0x01); + } + + return 0; +} + +static int ves1x93_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + switch (voltage) { case SEC_VOLTAGE_13: - return ves1x93_writereg (i2c, 0x1f, 0x20); + return ves1x93_writereg (state, 0x1f, 0x20); case SEC_VOLTAGE_18: - return ves1x93_writereg (i2c, 0x1f, 0x30); + return ves1x93_writereg (state, 0x1f, 0x30); case SEC_VOLTAGE_OFF: - return ves1x93_writereg (i2c, 0x1f, 0x00); + return ves1x93_writereg (state, 0x1f, 0x00); default: return -EINVAL; } } - -static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct ves1x93_state *state = (struct ves1x93_state*) fe->data; - struct i2c_adapter *i2c = state->i2c; - - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &ves1x93_info, sizeof(struct dvb_frontend_info)); - break; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; - case FE_READ_STATUS: - { - fe_status_t *status = arg; - u8 sync = ves1x93_readreg (i2c, 0x0e); + u8 sync = ves1x93_readreg (state, 0x0e); /* * The ves1893 sometimes returns sync values that make no sense, @@ -466,7 +339,7 @@ int maxtry = 10; /* just for safety - let's not get stuck here */ while ((sync & 0x03) != 0x03 && (sync & 0x0c) && maxtry--) { msleep(10); - sync = ves1x93_readreg (i2c, 0x0e); + sync = ves1x93_readreg (state, 0x0e); } *status = 0; @@ -486,64 +359,78 @@ if ((sync & 0x1f) == 0x1f) *status |= FE_HAS_LOCK; - break; + return 0; } - case FE_READ_BER: + +static int ves1x93_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 *ber = (u32 *) arg; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; - *ber = ves1x93_readreg (i2c, 0x15); - *ber |= (ves1x93_readreg (i2c, 0x16) << 8); - *ber |= ((ves1x93_readreg (i2c, 0x17) & 0x0F) << 16); + *ber = ves1x93_readreg (state, 0x15); + *ber |= (ves1x93_readreg (state, 0x16) << 8); + *ber |= ((ves1x93_readreg (state, 0x17) & 0x0F) << 16); *ber *= 10; - break; + + return 0; } - case FE_READ_SIGNAL_STRENGTH: +static int ves1x93_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - u8 signal = ~ves1x93_readreg (i2c, 0x0b); - *((u16*) arg) = (signal << 8) | signal; - break; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + + u8 signal = ~ves1x93_readreg (state, 0x0b); + *strength = (signal << 8) | signal; + + return 0; } - case FE_READ_SNR: +static int ves1x93_read_snr(struct dvb_frontend* fe, u16* snr) { - u8 snr = ~ves1x93_readreg (i2c, 0x1c); - *(u16*) arg = (snr << 8) | snr; - break; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + + u8 _snr = ~ves1x93_readreg (state, 0x1c); + *snr = (_snr << 8) | _snr; + + return 0; } - case FE_READ_UNCORRECTED_BLOCKS: +static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { - *(u32*) arg = ves1x93_readreg (i2c, 0x18) & 0x7f; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; - if (*(u32*) arg == 0x7f) - *(u32*) arg = 0xffffffff; /* counter overflow... */ + *ucblocks = ves1x93_readreg (state, 0x18) & 0x7f; - ves1x93_writereg (i2c, 0x18, 0x00); /* reset the counter */ - ves1x93_writereg (i2c, 0x18, 0x80); /* dto. */ - break; + if (*ucblocks == 0x7f) + *ucblocks = 0xffffffff; /* counter overflow... */ + + ves1x93_writereg (state, 0x18, 0x00); /* reset the counter */ + ves1x93_writereg (state, 0x18, 0x80); /* dto. */ + + return 0; } - case FE_SET_FRONTEND: +static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = arg; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; - tuner_set_tv_freq (i2c, p->frequency); - ves1x93_set_inversion (i2c, p->inversion); - ves1x93_set_fec (i2c, p->u.qpsk.fec_inner); - ves1x93_set_symbolrate (i2c, p->u.qpsk.symbol_rate); + ves1x93_writereg(state, 0x00, 0x11); + state->config->pll_set(fe, p); + ves1x93_writereg(state, 0x00, 0x01); + ves1x93_set_inversion (state, p->inversion); + ves1x93_set_fec (state, p->u.qpsk.fec_inner); + ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate); state->inversion = p->inversion; - break; + + return 0; } - case FE_GET_FRONTEND: +static int ves1x93_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = arg; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; int afc; - afc = ((int)((char)(ves1x93_readreg (i2c, 0x0a) << 1)))/2; + afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1)))/2; afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16; p->frequency -= afc; @@ -553,185 +440,125 @@ * if auto inversion was used */ if (state->inversion == INVERSION_AUTO) - p->inversion = (ves1x93_readreg (i2c, 0x0f) & 2) ? + p->inversion = (ves1x93_readreg (state, 0x0f) & 2) ? INVERSION_OFF : INVERSION_ON; - p->u.qpsk.fec_inner = ves1x93_get_fec (i2c); + p->u.qpsk.fec_inner = ves1x93_get_fec (state); /* XXX FIXME: timing offset !! */ - break; - } - case FE_SLEEP: - if (board_type == BOARD_SIEMENS_PCI) - ves1x93_writereg (i2c, 0x1f, 0x00); /* LNB power off */ - return ves1x93_writereg (i2c, 0x00, 0x08); - - case FE_INIT: - return ves1x93_init (i2c); - - case FE_SET_TONE: - return -EOPNOTSUPP; /* the ves1893 can generate the 22k */ - /* let's implement this when we have */ - /* a box that uses the 22K_0 pin... */ + return 0; +} - case FE_SET_VOLTAGE: - return ves1x93_set_voltage (i2c, (fe_sec_voltage_t) arg); +static int ves1x93_sleep(struct dvb_frontend* fe) +{ + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; - default: - return -EOPNOTSUPP; - }; + return ves1x93_writereg (state, 0x00, 0x08); +} - return 0; +static void ves1x93_release(struct dvb_frontend* fe) +{ + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + kfree(state); } -static struct i2c_client client_template; +static struct dvb_frontend_ops ves1x93_ops; -static int attach_adapter(struct i2c_adapter *adapter) +struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, + struct i2c_adapter* i2c) { - struct i2c_client *client; - struct ves1x93_state* state; - u8 identity = ves1x93_readreg(adapter, 0x1e); - int ret; + struct ves1x93_state* state = NULL; + u8 identity; + /* allocate memory for the internal state */ + state = (struct ves1x93_state*) kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops)); + state->inversion = INVERSION_OFF; + + /* check if the demod is there + identify it */ + identity = ves1x93_readreg(state, 0x1e); switch (identity) { case 0xdc: /* VES1893A rev1 */ printk("ves1x93: Detected ves1893a rev1\n"); - demod_type = DEMOD_VES1893; - ves1x93_info.name[4] = '8'; + state->demod_type = DEMOD_VES1893; + state->init_1x93_tab = init_1893_tab; + state->init_1x93_wtab = init_1893_wtab; + state->tab_size = sizeof(init_1893_tab); break; + case 0xdd: /* VES1893A rev2 */ printk("ves1x93: Detected ves1893a rev2\n"); - demod_type = DEMOD_VES1893; - ves1x93_info.name[4] = '8'; + state->demod_type = DEMOD_VES1893; + state->init_1x93_tab = init_1893_tab; + state->init_1x93_wtab = init_1893_wtab; + state->tab_size = sizeof(init_1893_tab); break; + case 0xde: /* VES1993 */ printk("ves1x93: Detected ves1993\n"); - demod_type = DEMOD_VES1993; - ves1x93_info.name[4] = '9'; - break; - default: - dprintk("VES1x93 not found (identity %02x)\n", identity); - return -ENODEV; - } - - if ((state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL)) == NULL) { - return -ENOMEM; - } - - if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { - kfree(state); - return -ENOMEM; - } - - state->inversion = INVERSION_OFF; - state->i2c = adapter; - - memcpy(client, &client_template, sizeof(struct i2c_client)); - client->adapter = adapter; - client->addr = (0x08>>1); - i2c_set_clientdata(client, (void*)state); - - ret = i2c_attach_client(client); - if (ret) { - kfree(client); - kfree(state); - return -EFAULT; - } - - BUG_ON(!state->dvb); - - ret = dvb_register_frontend(ves1x93_ioctl, state->dvb, state, - &ves1x93_info, THIS_MODULE); - if (ret) { - i2c_detach_client(client); - kfree(client); - kfree(state); - return -EFAULT; -} - - return 0; -} - -static int detach_client(struct i2c_client *client) -{ - struct ves1x93_state *state = (struct ves1x93_state*)i2c_get_clientdata(client); - dvb_unregister_frontend(ves1x93_ioctl, state->dvb); - i2c_detach_client(client); - BUG_ON(state->dvb); - kfree(client); - kfree(state); - return 0; -} - -static int command (struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct ves1x93_state *state = (struct ves1x93_state*)i2c_get_clientdata(client); - - dprintk ("%s\n", __FUNCTION__); - - switch (cmd) { - case FE_REGISTER: { - state->dvb = (struct dvb_adapter*)arg; + state->demod_type = DEMOD_VES1993; + state->init_1x93_tab = init_1993_tab; + state->init_1x93_wtab = init_1993_wtab; + state->tab_size = sizeof(init_1993_tab); break; - } - case FE_UNREGISTER: { - state->dvb = NULL; - break; - } - default: - return -EOPNOTSUPP; -} - return 0; -} - -static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = "ves1x93", - .id = I2C_DRIVERID_DVBFE_VES1X93, - .flags = I2C_DF_NOTIFY, - .attach_adapter = attach_adapter, - .detach_client = detach_client, - .command = command, -}; -static struct i2c_client client_template = { - I2C_DEVNAME("ves1x93"), - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, -}; - -static int __init init_ves1x93 (void) -{ - switch (board_type) { - case BOARD_NOKIA_DBOX2: - dprintk("%s: NOKIA_DBOX2\n", __FILE__); - break; - case BOARD_SAGEM_DBOX2: - dprintk("%s: SAGEM_DBOX2\n", __FILE__); - break; - case BOARD_SIEMENS_PCI: - dprintk("%s: SIEMENS_PCI\n", __FILE__); - break; default: - return -EIO; + goto error; } - return i2c_add_driver(&driver); -} - - -static void __exit exit_ves1x93 (void) -{ - if (i2c_del_driver(&driver)) - printk("vex1x93: driver deregistration failed\n"); -} + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; + } + +static struct dvb_frontend_ops ves1x93_ops = { + + .info = { + .name = "VLSI VES1x93 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 125, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + /* .symbol_rate_tolerance = ???,*/ + .caps = FE_CAN_INVERSION_AUTO | + 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 + }, + + .release = ves1x93_release, + + .init = ves1x93_init, + .sleep = ves1x93_sleep, + + .set_frontend = ves1x93_set_frontend, + .get_frontend = ves1x93_get_frontend, + + .read_status = ves1x93_read_status, + .read_ber = ves1x93_read_ber, + .read_signal_strength = ves1x93_read_signal_strength, + .read_snr = ves1x93_read_snr, + .read_ucblocks = ves1x93_read_ucblocks, -module_init(init_ves1x93); -module_exit(exit_ves1x93); + .set_voltage = ves1x93_set_voltage, +}; +module_param(debug, int, 0644); -MODULE_DESCRIPTION("VES1x93 DVB-S Frontend"); +MODULE_DESCRIPTION("VLSI VES1x93 DVB-S Demodulator driver"); MODULE_AUTHOR("Ralph Metzler"); MODULE_LICENSE("GPL"); -MODULE_PARM(debug,"i"); -MODULE_PARM(board_type,"i"); +EXPORT_SYMBOL(ves1x93_attach); Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/Kconfig 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/Kconfig 2004-12-22 10:04:35.863350794 -0800 @@ -4,6 +4,12 @@ select FW_LOADER select VIDEO_DEV select VIDEO_SAA7146_VV + select DVB_VES1820 + select DVB_VES1X93 + select DVB_STV0299 + select DVB_TDA8083 + select DVB_SP8870 + select DVB_STV0297 help Support for SAA7146 and AV7110 based DVB cards as produced by Fujitsu-Siemens, Technotrend, Hauppauge and others. @@ -53,6 +59,12 @@ tristate "Budget cards" depends on DVB_CORE && PCI select VIDEO_SAA7146 + select DVB_STV0299 + select DVB_VES1X93 + select DVB_VES1820 + select DVB_L64781 + select DVB_TDA8083 + select DVB_TDA10021 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -67,6 +79,8 @@ tristate "Budget cards with onboard CI connector" depends on DVB_CORE && PCI select VIDEO_SAA7146 + select DVB_STV0299 + select DVB_TDA1004X help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -85,6 +99,7 @@ depends on DVB_CORE && PCI select VIDEO_DEV select VIDEO_SAA7146_VV + select DVB_STV0299 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -99,6 +114,9 @@ tristate "AV7110 cards with Budget Patch" depends on DVB_CORE && DVB_BUDGET select DVB_AV7110 + select DVB_STV0299 + select DVB_VES1X93 + select DVB_TDA8083 help Support for Budget Patch (full TS) modification on SAA7146+AV7110 based cards (DVB-S cards). This Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/Makefile 2004-12-22 09:07:08.899368970 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/Makefile 2004-12-22 10:04:35.865350490 -0800 @@ -11,7 +11,7 @@ obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ hostprogs-y := fdump Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/av7110.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110.c 2004-12-22 10:04:35.889346842 -0800 @@ -77,7 +77,7 @@ static int volume = 255; module_param_named(debug, av7110_debug, int, 0644); -MODULE_PARM_DESC(av7110_debug, "Turn on/off debugging (default:off)."); +MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); module_param(vidmode, int, 0444); MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC"); module_param(pids_off, int, 0444); @@ -94,7 +94,16 @@ static void restart_feeds(struct av7110 *av7110); -int av7110_num = 0; +static int av7110_num = 0; + +#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \ +{\ + if (fe_func != NULL) { \ + av7110_copy = fe_func; \ + fe_func = av7110_func; \ + } \ +} + static void init_av7110_av(struct av7110 *av7110) { @@ -108,7 +117,7 @@ /* handle different card types */ /* remaining inits according to card and frontend type */ - av7110->has_analog_tuner = 0; + av7110->analog_tuner_flags = 0; av7110->current_input = 0; if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) { printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n", @@ -140,10 +149,12 @@ // switch DVB SCART on av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1); - if (rgb_on) + if (rgb_on && + (av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) { saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8 } + } av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right); av7110_setup_irc_config(av7110, 0); @@ -183,9 +194,10 @@ av7110->arm_thread = current; - while (1) { - timeout = wait_event_interruptible_timeout(av7110->arm_wait,0 != av7110->arm_rmmod, 5*HZ); - if (-ERESTARTSYS == timeout || 0 != av7110->arm_rmmod) { + for (;;) { + timeout = wait_event_interruptible_timeout(av7110->arm_wait, + av7110->arm_rmmod, 5 * HZ); + if (-ERESTARTSYS == timeout || av7110->arm_rmmod) { /* got signal or told to quit*/ break; } @@ -259,15 +271,15 @@ irc_handler = NULL; } -void run_handlers(unsigned long ircom) +static void run_handlers(unsigned long ircom) { if (irc_handler != NULL) (*irc_handler)((u32) ircom); } -DECLARE_TASKLET(irtask,run_handlers,0); +static DECLARE_TASKLET(irtask, run_handlers, 0); -void IR_handle(struct av7110 *av7110, u32 ircom) +static void IR_handle(struct av7110 *av7110, u32 ircom) { dprintk(4, "ircommand = %08x\n", ircom); irtask.data = (unsigned long) ircom; @@ -278,7 +290,7 @@ * IRQ handling ****************************************************************************/ -static inline int DvbDmxFilterCallback(u8 * buffer1, size_t buffer1_len, +static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len, u8 * buffer2, size_t buffer2_len, struct dvb_demux_filter *dvbdmxfilter, enum dmx_success success, @@ -346,9 +358,8 @@ // dprintk(4, "%p\n",av7110); print_time("debi"); - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER) & ~MASK_19 ); - saa7146_write(av7110->dev, ISR, MASK_19 ); + SAA7146_IER_DISABLE(av7110->dev, MASK_19); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19); if (type==-1) { printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n", @@ -484,9 +495,8 @@ ARM_ClearIrq(av7110); - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER) & ~MASK_19 ); - saa7146_write(av7110->dev, ISR, MASK_19 ); + SAA7146_IER_DISABLE(av7110->dev, MASK_19); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19); av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2); av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); @@ -572,7 +582,7 @@ wake_up(&cibuf->queue); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); saa7146_write(av7110->dev, IER, saa7146_read(av7110->dev, IER) | MASK_19 ); if (len < 5) @@ -610,7 +620,7 @@ dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); saa7146_write(av7110->dev, IER, saa7146_read(av7110->dev, IER) | MASK_19 ); @@ -637,7 +647,7 @@ memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len); av7110->bmpp+=len; av7110->bmplen-=len; - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); saa7146_write(av7110->dev, IER, saa7146_read(av7110->dev, IER) | MASK_19 ); if (len < 5) @@ -659,7 +669,7 @@ case DATA_TS_RECORD: case DATA_PES_RECORD: - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); saa7146_write(av7110->dev, IER, saa7146_read(av7110->dev, IER) | MASK_19); irdebi(av7110, DEBISWAB, DPRAM_BASE+rxbuf, 0, len); @@ -667,7 +677,7 @@ return; case DATA_DEBUG_MESSAGE: - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); if (!len || len>0xff) { iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); break; @@ -813,9 +823,13 @@ buf[3] = mode; ret = av7110_fw_request(av7110, buf, 20, &handle, 1); - if (ret < 0) { - dprintk(1, "StartHWFilter error\n"); - return ret; + if (ret != 0 || handle >= 32) { + printk("dvb-ttpci: %s error buf %04x %04x %04x %04x " + "ret %x handle %04x\n", + __FUNCTION__, buf[0], buf[1], buf[2], buf[3], + ret, handle); + dvbdmxfilter->hw_handle = 0xffff; + return -1; } av7110->handle2filter[handle] = dvbdmxfilter; @@ -835,8 +849,9 @@ dprintk(4, "%p\n", av7110); handle = dvbdmxfilter->hw_handle; - if (handle > 32) { - dprintk(1, "StopHWFilter tried to stop invalid filter %d, filter type = %d\n", handle, dvbdmxfilter->type); + if (handle >= 32) { + printk("%s tried to stop invalid filter %04x, filter type = %x\n", + __FUNCTION__, handle, dvbdmxfilter->type); return 0; } @@ -846,11 +861,11 @@ buf[1] = 1; buf[2] = handle; ret = av7110_fw_request(av7110, buf, 3, answ, 2); - if (ret) - dprintk(1, "StopHWFilter error\n"); - - if (answ[1] != handle) { - dprintk(2, "filter %d shutdown error :%d\n", handle, answ[1]); + if (ret != 0 || answ[1] != handle) { + printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x " + "resp %04x %04x pid %d\n", + __FUNCTION__, buf[0], buf[1], buf[2], ret, + answ[0], answ[1], dvbdmxfilter->feed->pid); ret = -1; } return ret; @@ -928,7 +943,7 @@ static int av7110_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct av7110 *av7110 = (struct av7110 *) demux->priv; + struct av7110 *av7110 = demux->priv; dprintk(4, "%p\n", av7110); @@ -986,7 +1001,7 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct av7110 *av7110 = (struct av7110 *) demux->priv; + struct av7110 *av7110 = demux->priv; dprintk(4, "%p\n", av7110); @@ -1090,71 +1105,44 @@ * SEC device file operations ******************************************************************************/ -static int av7110_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct av7110 *av7110 = fe->before_after_data; - dprintk(4, "%p\n", av7110); +static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct av7110* av7110 = (struct av7110*) fe->dvb->priv; - switch (cmd) { - case FE_SET_TONE: - switch ((fe_sec_tone_mode_t) arg) { + switch (tone) { case SEC_TONE_ON: Set22K(av7110, 1); break; case SEC_TONE_OFF: Set22K(av7110, 0); break; + default: return -EINVAL; -}; - break; - - case FE_DISEQC_SEND_MASTER_CMD: - { - struct dvb_diseqc_master_cmd *cmd = arg; - av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1); - break; } - case FE_DISEQC_SEND_BURST: - av7110_diseqc_send(av7110, 0, NULL, (unsigned long) arg); - break; - - default: - return -EOPNOTSUPP; -}; - return 0; } - -static void av7110_before_after_tune (fe_status_t s, void *data) +static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd* cmd) { - struct av7110 *av7110 = data; - - dprintk(4, "%p\n", av7110); + struct av7110* av7110 = fe->dvb->priv; - av7110->fe_synced = (s & FE_HAS_LOCK) ? 1 : 0; + av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1); - if (av7110->playing) - return; + return 0; +} - if (down_interruptible(&av7110->pid_mutex)) - return; +static int av7110_diseqc_send_burst(struct dvb_frontend* fe, + fe_sec_mini_cmd_t minicmd) +{ + struct av7110* av7110 = fe->dvb->priv; - if (av7110->fe_synced) { - SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO], - av7110->pids[DMX_PES_AUDIO], - av7110->pids[DMX_PES_TELETEXT], 0, - av7110->pids[DMX_PES_PCR]); - av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0); - } else { - SetPIDs(av7110, 0, 0, 0, 0, 0); - av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, FlushTSQueue, 0); - } + av7110_diseqc_send(av7110, 0, NULL, minicmd); - up(&av7110->pid_mutex); + return 0; } @@ -1170,15 +1158,6 @@ av7110->registered=1; - dvb_add_frontend_notifier (av7110->dvb_adapter, - av7110_before_after_tune, av7110); - - /** - * init DiSEqC stuff - */ - dvb_add_frontend_ioctls (av7110->dvb_adapter, - av7110_diseqc_ioctl, NULL, av7110); - dvbdemux->priv = (void *) av7110; for (i=0; i<32; i++) @@ -1252,12 +1231,8 @@ dvb_dmxdev_release(&av7110->dmxdev); dvb_dmx_release(&av7110->demux); - dvb_remove_frontend_notifier (av7110->dvb_adapter, - av7110_before_after_tune); - - dvb_remove_frontend_ioctls (av7110->dvb_adapter, - av7110_diseqc_ioctl, NULL); - + if (av7110->fe != NULL) + dvb_unregister_frontend(av7110->fe); dvb_unregister_device(av7110->osd_dev); av7110_av_unregister(av7110); av7110_ca_unregister(av7110); @@ -1280,6 +1255,7 @@ return i2c_transfer(&av7110->i2c_adap, &msgs, 1); } +#if 0 u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) { u8 mm1[] = {0x00}; @@ -1296,6 +1272,7 @@ return mm2[0]; } +#endif /**************************************************************************** * INITIALIZATION @@ -1408,28 +1385,561 @@ #endif -static int client_register(struct i2c_client *client) +static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter); - struct av7110 *av7110 = (struct av7110*)dev->ext_priv; + struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + u8 pwr = 0; + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + u32 div = (params->frequency + 479500) / 125; + + if (params->frequency > 2000000) pwr = 3; + else if (params->frequency > 1800000) pwr = 2; + else if (params->frequency > 1600000) pwr = 1; + else if (params->frequency > 1200000) pwr = 0; + else if (params->frequency >= 1100000) pwr = 1; + else pwr = 2; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = ((div & 0x18000) >> 10) | 0x95; + buf[3] = (pwr << 6) | 0x30; + + // NOTE: since we're using a prescaler of 2, we set the + // divisor frequency to 62.5kHz and divide by 125 above - /* fixme: check for "type" (ie. frontend type) */ - if (client->driver->command) - return client->driver->command(client, FE_REGISTER, av7110->dvb_adapter); + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; return 0; } -static int client_unregister(struct i2c_client *client) +static struct ves1x93_config alps_bsrv2_config = { + .demod_address = 0x08, + .xin = 90100000UL, + .invert_pwm = 0, + .pll_set = alps_bsrv2_pll_set, +}; + + +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) { - struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter); - struct av7110 *av7110 = (struct av7110*)dev->ext_priv; + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } + + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); - /* fixme: check for "type" (ie. frontend type) */ - if (client->driver->command) - return client->driver->command(client, FE_UNREGISTER, av7110->dvb_adapter); return 0; } +static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + int ret; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + data[3] = 0xC4; + + if (params->frequency > 1530000) data[3] = 0xc0; + + ret = i2c_transfer (&av7110->i2c_adap, &msg, 1); + if (ret != 1) + return -EIO; + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + + + +static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (params->frequency + 35937500 + 31250) / 62500; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x85 | ((div >> 10) & 0x60); + data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); + + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct ves1820_config alps_tdbe2_config = { + .demod_address = 0x09, + .xin = 57840000UL, + .invert = 1, + .selagc = VES1820_SELAGC_SIGNAMPERR, + .pll_set = alps_tdbe2_pll_set, +}; + + + + +static int grundig_29504_451_pll_set(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = params->frequency / 125; + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x8e; + data[3] = 0x00; + + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct tda8083_config grundig_29504_451_config = { + .demod_address = 0x68, + .pll_set = grundig_29504_451_pll_set, +}; + + + +static int philips_cd1516_pll_set(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div; + u32 f = params->frequency; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (f + 36125000 + 31250) / 62500; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x8e; + data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34); + + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct ves1820_config philips_cd1516_config = { + .demod_address = 0x09, + .xin = 57840000UL, + .invert = 1, + .selagc = VES1820_SELAGC_SIGNAMPERR, + .pll_set = philips_cd1516_pll_set, +}; + + + +static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div, pwr; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (params->frequency + 36200000) / 166666; + + if (params->frequency <= 782000000) + pwr = 1; + else + pwr = 2; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x85; + data[3] = pwr << 6; + + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) +{ + struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + + return request_firmware(fw, name, &av7110->dev->pci->dev); +} + +static struct sp8870_config alps_tdlb7_config = { + + .demod_address = 0x71, + .pll_set = alps_tdlb7_pll_set, + .request_firmware = alps_tdlb7_request_firmware, +}; + + + +static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) }; + struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 }; + int i; + + div = (params->frequency + 36150000 + 31250) / 62500; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0xce; + + if (params->frequency < 45000000) + return -EINVAL; + else if (params->frequency < 137000000) + data[3] = 0x01; + else if (params->frequency < 403000000) + data[3] = 0x02; + else if (params->frequency < 860000000) + data[3] = 0x04; + else + return -EINVAL; + + stv0297_enable_plli2c(fe); + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) { + printk("nexusca: pll transfer failed!\n"); + return -EIO; + } + + // wait for PLL lock + for(i=0; i< 20; i++) { + + stv0297_enable_plli2c(fe); + if (i2c_transfer (&av7110->i2c_adap, &readmsg, 1) == 1) + if (data[0] & 0x40) break; + msleep(10); + } + + return 0; +} + +static struct stv0297_config nexusca_stv0297_config = { + + .demod_address = 0x1C, + .pll_set = nexusca_stv0297_pll_set, +}; + + +static void av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status) +{ + int synced = (status & FE_HAS_LOCK) ? 1 : 0; + + av7110->fe_status = status; + + if (av7110->fe_synced == synced) + return; + + av7110->fe_synced = synced; + + if (av7110->playing) + return; + + if (down_interruptible(&av7110->pid_mutex)) + return; + + if (av7110->fe_synced) { + SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO], + av7110->pids[DMX_PES_AUDIO], + av7110->pids[DMX_PES_TELETEXT], 0, + av7110->pids[DMX_PES_PCR]); + av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0); + } else { + SetPIDs(av7110, 0, 0, 0, 0, 0); + av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0); + av7110_wait_msgstate(av7110, GPMQBusy); + } + + up(&av7110->pid_mutex); +} + +static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_set_frontend(fe, params); +} + +static int av7110_fe_init(struct dvb_frontend* fe) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_init(fe); +} + +static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + struct av7110* av7110 = fe->dvb->priv; + int ret; + + /* call the real implementation */ + ret = av7110->fe_read_status(fe, status); + if (ret) + return ret; + + if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK)) { + av7110_fe_lock_fix(av7110, *status); + } + + return 0; +} + +static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_diseqc_reset_overload(fe); +} + +static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd* cmd) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_diseqc_send_master_cmd(fe, cmd); +} + +static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_diseqc_send_burst(fe, minicmd); +} + +static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_set_tone(fe, tone); +} + +static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_set_voltage(fe, voltage); +} + +static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_dishnetwork_send_legacy_command(fe, cmd); +} + +static u8 read_pwm(struct av7110* av7110) +{ + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 }, + { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} }; + + if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff)) + pwm = 0x48; + + return pwm; +} + +static void frontend_init(struct av7110 *av7110) +{ + if (av7110->dev->pci->subsystem_vendor == 0x110a) { + switch(av7110->dev->pci->subsystem_device) { + case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??)) + av7110->fe = ves1820_attach(&philips_cd1516_config, + &av7110->i2c_adap, read_pwm(av7110)); + break; + } + + } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) { + switch(av7110->dev->pci->subsystem_device) { + case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X + case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X + case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE + + // try the ALPS BSRV2 first of all + av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops->set_tone = av7110_set_tone; + break; + } + + // try the ALPS BSRU6 now + av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops->set_tone = av7110_set_tone; + break; + } + + // Try the grundig 29504-451 + av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops->set_tone = av7110_set_tone; + break; + } + + /* Try DVB-C cards */ + switch(av7110->dev->pci->subsystem_device) { + case 0x0000: + /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */ + av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap, + read_pwm(av7110)); + break; + case 0x0003: + /* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */ + av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, + read_pwm(av7110)); + break; + } + break; + + case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X + + // ALPS TDLB7 + av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap); + break; + + case 0x0002: // Hauppauge/TT DVB-C premium rev2.X + + av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); + break; + + case 0x000A: // Hauppauge/TT Nexus-CA rev1.X + + av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap, 0x7b); + if (av7110->fe) { + /* set TDA9819 into DVB mode */ + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + + /* tuner on this needs a slower i2c bus speed */ + av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; + break; + } + } + } + + if (av7110->fe == NULL) { + printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + av7110->dev->pci->vendor, + av7110->dev->pci->device, + av7110->dev->pci->subsystem_vendor, + av7110->dev->pci->subsystem_device); + } else { + FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init); + FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status); + FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload); + FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd); + FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst); + FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone); + FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;) + FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command); + FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend); + + if (dvb_register_frontend(av7110->dvb_adapter, av7110->fe)) { + printk("av7110: Frontend registration failed!\n"); + if (av7110->fe->ops->release) + av7110->fe->ops->release(av7110->fe); + av7110->fe = NULL; + } + } +} + static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext) { struct av7110 *av7110 = NULL; @@ -1446,7 +1956,7 @@ memset(av7110, 0, sizeof(struct av7110)); av7110->card_name = (char*)pci_ext->ext_priv; - av7110->dev=(struct saa7146_dev *)dev; + av7110->dev = dev; dev->ext_priv = av7110; if ((ret = get_firmware(av7110))) { @@ -1460,15 +1970,11 @@ get recognized before the main driver is fully loaded */ saa7146_write(dev, GPIO_CTRL, 0x500000); - av7110->i2c_adap = (struct i2c_adapter) { - .client_register = client_register, - .client_unregister = client_unregister, #ifdef I2C_ADAP_CLASS_TV_DIGITAL - .class = I2C_ADAP_CLASS_TV_DIGITAL, + av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL; #else - .class = I2C_CLASS_TV_DIGITAL, + av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL; #endif - }; strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name)); saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */ @@ -1501,7 +2007,6 @@ /* locks for data transfers from/to AV7110 */ spin_lock_init (&av7110->debilock); sema_init(&av7110->dcomlock, 1); - av7110->debilock=SPIN_LOCK_UNLOCKED; av7110->debitype=-1; /* default OSD window */ @@ -1567,6 +2072,9 @@ if (ret) goto err3; + av7110->dvb_adapter->priv = av7110; + frontend_init(av7110); + printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num); av7110->device_initialized = 1; av7110_num++; @@ -1615,11 +2123,8 @@ dvb_unregister(av7110); - IER_DISABLE(saa, (MASK_19 | MASK_03)); -// saa7146_write (av7110->dev, IER, -// saa7146_read(av7110->dev, IER) & ~(MASK_19 | MASK_03)); - - saa7146_write(av7110->dev, ISR,(MASK_19 | MASK_03)); + SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03); + SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03); av7110_ca_exit(av7110); av7110_av_exit(av7110); @@ -1646,7 +2151,7 @@ static void av7110_irq(struct saa7146_dev* dev, u32 *isr) { - struct av7110 *av7110 = (struct av7110*)dev->ext_priv; + struct av7110 *av7110 = dev->ext_priv; if (*isr & MASK_19) tasklet_schedule (&av7110->debi_tasklet); @@ -1663,33 +2168,29 @@ .ext_priv = x_name, \ .ext = &av7110_extension } -MAKE_AV7110_INFO(fs_1_5, "Siemens cable card PCI rev1.5"); -MAKE_AV7110_INFO(fs_1_3, "Siemens/Technotrend/Hauppauge PCI rev1.3"); -MAKE_AV7110_INFO(tt_1_6, "Technotrend/Hauppauge PCI rev1.3 or 1.6"); -MAKE_AV7110_INFO(tt_2_1, "Technotrend/Hauppauge PCI rev2.1 or 2.2"); -MAKE_AV7110_INFO(tt_t, "Technotrend/Hauppauge PCI DVB-T"); -MAKE_AV7110_INFO(unkwn0, "Technotrend/Hauppauge PCI rev?(unknown0)?"); -MAKE_AV7110_INFO(unkwn1, "Technotrend/Hauppauge PCI rev?(unknown1)?"); -MAKE_AV7110_INFO(unkwn2, "Technotrend/Hauppauge PCI rev?(unknown2)?"); -MAKE_AV7110_INFO(nexus, "Technotrend/Hauppauge Nexus PCI DVB-S"); -MAKE_AV7110_INFO(dvboc11,"Octal/Technotrend DVB-C for iTV"); +MAKE_AV7110_INFO(tts_1_X, "Technotrend/Hauppauge WinTV DVB-S rev1.X"); +MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X"); +MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X"); +MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X"); +MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X"); +MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV Nexus-S rev1.3"); +MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C"); static struct pci_device_id pci_tbl[] = { - MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0xffff), - MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0x0000), - MAKE_EXTENSION_PCI(fs_1_3, 0x13c2, 0x0000), - MAKE_EXTENSION_PCI(unkwn0, 0x13c2, 0x1002), - MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0001), - MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0002), - MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0003), - MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0004), - MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0006), - MAKE_EXTENSION_PCI(tt_t, 0x13c2, 0x0008), - MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x1102), - MAKE_EXTENSION_PCI(unkwn1, 0xffc2, 0x0000), - MAKE_EXTENSION_PCI(unkwn2, 0x00a1, 0x00a1), - MAKE_EXTENSION_PCI(nexus, 0x00a1, 0xa1a0), - MAKE_EXTENSION_PCI(dvboc11,0x13c2, 0x000a), + MAKE_EXTENSION_PCI(tts_1_X, 0x13c2, 0x0000), + MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001), + MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002), + MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003), + MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002), + MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000), + MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a), + +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1 +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0006), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-S v???? +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0008), UNDEFINED CARD */ // TT/Hauppauge WinTV DVB-T v???? +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v???? + { .vendor = 0, } Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/av7110.h 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110.h 2004-12-22 10:04:35.892346386 -0800 @@ -24,9 +24,21 @@ #include "dvb_filter.h" #include "dvb_net.h" #include "dvb_ringbuffer.h" +#include "dvb_frontend.h" +#include "ves1820.h" +#include "ves1x93.h" +#include "stv0299.h" +#include "tda8083.h" +#include "sp8870.h" +#include "stv0297.h" #include + +#define ANALOG_TUNER_VES1820 1 +#define ANALOG_TUNER_STV0297 2 +#define ANALOG_TUNER_VBI 0x100 + extern int av7110_debug; #define dprintk(level,args...) \ @@ -75,7 +87,7 @@ char *card_name; /* support for analog module of dvb-c */ - int has_analog_tuner; + int analog_tuner_flags; int current_input; u32 current_freq; @@ -115,8 +127,8 @@ spinlock_t debilock; struct semaphore dcomlock; - int debitype; - int debilen; + volatile int debitype; + volatile int debilen; /* Recording and playback flags */ @@ -217,6 +229,18 @@ unsigned char *bin_root; unsigned long size_root; + + struct dvb_frontend* fe; + fe_status_t fe_status; + int (*fe_init)(struct dvb_frontend* fe); + int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status); + int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe); + int (*fe_diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd); + int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd); + int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); + int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); + int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd); + int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110_av.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/av7110_av.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110_av.c 2004-12-22 10:04:35.897345626 -0800 @@ -674,7 +674,7 @@ } -int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length) +static int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length) { int i; int c = 0; @@ -936,7 +936,7 @@ return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); } -u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 }; +static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 }; #define MIN_IFRAME 400000 Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110_ca.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/av7110_ca.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110_ca.c 2004-12-22 10:04:35.900345170 -0800 @@ -89,20 +89,20 @@ * CI link layer file ops ******************************************************************************/ -int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size) +static int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size) { dvb_ringbuffer_init(cirbuf, vmalloc(size), size); dvb_ringbuffer_init(ciwbuf, vmalloc(size), size); return 0; } -void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) +static void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) { dvb_ringbuffer_flush_spinlock_wakeup(cirbuf); dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf); } -void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) +static void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) { vfree(cirbuf->data); cirbuf->data = NULL; @@ -110,7 +110,7 @@ ciwbuf->data = NULL; } -int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, +static int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, int slots, ca_slot_info_t *slot) { int i; Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110_hw.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/av7110_hw.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110_hw.c 2004-12-22 10:04:35.908343954 -0800 @@ -53,10 +53,14 @@ { struct saa7146_dev *dev = av7110->dev; - if (count <= 0 || count > 32764) + if (count <= 0 || count > 32764) { + printk("%s: invalid count %d\n", __FUNCTION__, count); return -1; - if (saa7146_wait_for_debi_done(av7110->dev) < 0) + } + if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { + printk("%s: wait_for_debi_done failed\n", __FUNCTION__); return -1; + } saa7146_write(dev, DEBI_CONFIG, config); if (count <= 4) /* immediate transfer */ saa7146_write(dev, DEBI_AD, val); @@ -72,10 +76,14 @@ struct saa7146_dev *dev = av7110->dev; u32 result = 0; - if (count > 32764 || count <= 0) + if (count > 32764 || count <= 0) { + printk("%s: invalid count %d\n", __FUNCTION__, count); return 0; - if (saa7146_wait_for_debi_done(av7110->dev) < 0) + } + if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { + printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__); return 0; + } saa7146_write(dev, DEBI_AD, av7110->debi_bus); saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff)); @@ -83,7 +91,11 @@ saa7146_write(dev, MC2, (2 << 16) | 2); if (count > 4) return count; - saa7146_wait_for_debi_done(av7110->dev); + if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { + printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__); + return 0; + } + result = saa7146_read(dev, DEBI_AD); result &= (0xffffffffUL >> ((4 - count) * 8)); return result; @@ -98,16 +110,16 @@ saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ - IER_DISABLE(av7110->dev, (MASK_19 | MASK_03)); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); + SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI); msleep(30); /* the firmware needs some time to initialize */ ARM_ResetMailBox(av7110); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); - IER_ENABLE(av7110->dev, MASK_03); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); + SAA7146_IER_ENABLE(av7110->dev, MASK_03); av7110->arm_ready = 1; dprintk(1, "reset ARM\n"); @@ -211,8 +223,8 @@ saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ - IER_DISABLE(av7110->dev, MASK_03 | MASK_19); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); + SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); /* enable DEBI */ saa7146_write(av7110->dev, MC1, 0x08800880); @@ -240,7 +252,7 @@ mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode)); iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); - if (saa7146_wait_for_debi_done(av7110->dev)) { + if (saa7146_wait_for_debi_done(av7110->dev, 1)) { printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " "saa7146_wait_for_debi_done() timed out\n"); return -1; @@ -258,7 +270,7 @@ dprintk(1, "load dpram code\n"); mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram); - if (saa7146_wait_for_debi_done(av7110->dev)) { + if (saa7146_wait_for_debi_done(av7110->dev, 1)) { printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " "saa7146_wait_for_debi_done() timed out after loading DRAM\n"); return -1; @@ -268,8 +280,8 @@ //ARM_ClearIrq(av7110); ARM_ResetMailBox(av7110); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); - IER_ENABLE(av7110->dev, MASK_03); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); + SAA7146_IER_ENABLE(av7110->dev, MASK_03); av7110->arm_errors = 0; av7110->arm_ready = 1; @@ -281,13 +293,44 @@ * DEBI command polling ****************************************************************************/ +int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) +{ + unsigned long start; + u32 stat; + + if (FW_VERSION(av7110->arm_app) <= 0x261c) { + /* not supported by old firmware */ + msleep(50); + return 0; + } + + /* new firmware */ + start = jiffies; + for (;;) { + if (down_interruptible(&av7110->dcomlock)) + return -ERESTARTSYS; + stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); + up(&av7110->dcomlock); + if ((stat & flags) == 0) { + break; + } + if (time_after(jiffies, start + ARM_WAIT_FREE)) { + printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", + __FUNCTION__, stat & flags); + return -1; + } + msleep(1); + } + return 0; +} + int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) { int i; unsigned long start; -#ifdef COM_DEBUG + char *type = NULL; + u16 flags[2] = {0, 0}; u32 stat; -#endif // dprintk(4, "%p\n", av7110); @@ -305,6 +348,8 @@ } } + wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2); + #ifndef _NOHANDSHAKE start = jiffies; while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { @@ -316,14 +361,45 @@ } #endif + switch ((buf[0] >> 8) & 0xff) { + case COMTYPE_PIDFILTER: + case COMTYPE_ENCODER: + case COMTYPE_REC_PLAY: + case COMTYPE_MPEGDECODER: + type = "MSG"; + flags[0] = GPMQOver; + flags[1] = GPMQFull; + break; + case COMTYPE_OSD: + type = "OSD"; + flags[0] = OSDQOver; + flags[1] = OSDQFull; + break; + default: + break; + } + + if (type != NULL) { + /* non-immediate COMMAND type */ start = jiffies; - while (rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2) & OSDQFull) { - msleep(1); - if (time_after(jiffies, start + ARM_WAIT_OSD)) { - printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for !OSDQFull\n", __FUNCTION__); + for (;;) { + stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); + if (stat & flags[0]) { + printk(KERN_ERR "%s: %s QUEUE overflow\n", + __FUNCTION__, type); + return -1; + } + if ((stat & flags[1]) == 0) + break; + if (time_after(jiffies, start + ARM_WAIT_FREE)) { + printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", + __FUNCTION__, type); return -1; } + msleep(1); + } } + for (i = 2; i < length; i++) wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2); @@ -334,6 +410,8 @@ wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2); + wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2); + #ifdef COM_DEBUG start = jiffies; while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { @@ -956,7 +1034,7 @@ goto out; } else { int i, len = dc->x0-dc->color+1; - u8 __user *colors = dc->data; + u8 __user *colors = (u8 *)dc->data; u8 r, g, b, blend; for (i = 0; i= 261d */ +#define HPQBusy 0x0080 +#define OSDQBusy 0x0100 /* hw section filter flags */ #define SECTION_EIT 0x01 @@ -368,6 +371,7 @@ #define FW_4M_SDRAM(arm_app) ((arm_app) & 0x40000000) #define FW_VERSION(arm_app) ((arm_app) & 0x0000FFFF) +extern int av7110_wait_msgstate(struct av7110 *av7110, u16 flags); extern int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...); extern int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length); extern int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length); Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110_v4l.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/av7110_v4l.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/av7110_v4l.c 2004-12-22 10:04:35.920342130 -0800 @@ -92,10 +92,8 @@ } }; -/* for Siemens DVB-C analog module: (taken from ves1820.c) */ -static int ves1820_writereg(struct saa7146_dev *dev, u8 reg, u8 data) +static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) { - u8 addr = 0x09; u8 buf[] = { 0x00, reg, data }; struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 }; @@ -106,6 +104,17 @@ return 0; } +static int stv0297_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) +{ + u8 buf [] = { reg, data }; + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 2 }; + + if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) + return -1; + return 0; +} + + static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4]) { struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; @@ -117,12 +126,7 @@ return 0; } - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 62.5 kHz. - */ -static int tuner_set_tv_freq(struct saa7146_dev *dev, u32 freq) +static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq) { u32 div; u8 config; @@ -151,6 +155,34 @@ return tuner_write(dev, 0x61, buf); } +static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq) +{ + u32 div; + u8 data[4]; + + div = (freq + 38900000 + 31250) / 62500; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0xce; + + if (freq < 45000000) + return -EINVAL; + else if (freq < 137000000) + data[3] = 0x01; + else if (freq < 403000000) + data[3] = 0x02; + else if (freq < 860000000) + data[3] = 0x04; + else + return -EINVAL; + + stv0297_writereg(dev, 0x1C, 0x87, 0x78); + stv0297_writereg(dev, 0x1C, 0x86, 0xc8); + return tuner_write(dev, 0x63, data); +} + + static struct saa7146_standard analog_standard[]; static struct saa7146_standard dvb_standard[]; @@ -162,13 +194,12 @@ .capability = V4L2_AUDCAP_STEREO }; -int av7110_dvb_c_switch(struct saa7146_fh *fh) +static int av7110_dvb_c_switch(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; struct av7110 *av7110 = (struct av7110*)dev->ext_priv; u16 adswitch; - u8 band = 0; int source, sync, err; dprintk(4, "%p\n", av7110); @@ -184,7 +215,6 @@ if (0 != av7110->current_input) { adswitch = 1; - band = 0x60; /* analog band */ source = SAA7146_HPS_SOURCE_PORT_B; sync = SAA7146_HPS_SYNC_PORT_B; memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2); @@ -195,9 +225,16 @@ msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume + + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + if (ves1820_writereg(dev, 0x09, 0x0f, 0x60)) + dprintk(1, "setting band in demodulator failed.\n"); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF) + } } else { adswitch = 0; - band = 0x20; /* digital band */ source = SAA7146_HPS_SOURCE_PORT_A; sync = SAA7146_HPS_SYNC_PORT_A; memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2); @@ -208,15 +245,20 @@ msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume + + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + if (ves1820_writereg(dev, 0x09, 0x0f, 0x20)) + dprintk(1, "setting band in demodulator failed.\n"); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + } } /* hmm, this does not do anything!? */ if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch)) dprintk(1, "ADSwitch error\n"); - if (ves1820_writereg(dev, 0x0f, band)) - dprintk(1, "setting band in demodulator failed.\n"); - saa7146_set_hps_source_and_sync(dev, source, sync); if (vv->ov_suspend != NULL) { @@ -227,7 +269,7 @@ return 0; } -int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct av7110 *av7110 = (struct av7110*) dev->ext_priv; @@ -242,7 +284,7 @@ dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index); - if (!av7110->has_analog_tuner || t->index != 0) + if (!av7110->analog_tuner_flags || t->index != 0) return -EINVAL; memset(t, 0, sizeof(*t)); @@ -285,7 +327,7 @@ u16 fm_matrix, src; dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index); - if (!av7110->has_analog_tuner || av7110->current_input != 1) + if (!av7110->analog_tuner_flags || av7110->current_input != 1) return -EINVAL; switch (t->audmode) { @@ -322,7 +364,7 @@ dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency); - if (!av7110->has_analog_tuner || av7110->current_input != 1) + if (!av7110->analog_tuner_flags || av7110->current_input != 1) return -EINVAL; memset(f, 0, sizeof(*f)); @@ -336,7 +378,7 @@ dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency); - if (!av7110->has_analog_tuner || av7110->current_input != 1) + if (!av7110->analog_tuner_flags || av7110->current_input != 1) return -EINVAL; if (V4L2_TUNER_ANALOG_TV != f->type) @@ -346,7 +388,11 @@ msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0); /* tune in desired frequency */ - tuner_set_tv_freq(dev, f->frequency); + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + ves1820_set_tv_freq(dev, f->frequency); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + stv0297_set_tv_freq(dev, f->frequency); + } av7110->current_freq = f->frequency; msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection @@ -361,7 +407,7 @@ dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index); - if (av7110->has_analog_tuner ) { + if (av7110->analog_tuner_flags) { if (i->index < 0 || i->index >= 2) return -EINVAL; } else { @@ -386,7 +432,7 @@ dprintk(2, "VIDIOC_S_INPUT: %d\n", input); - if (!av7110->has_analog_tuner ) + if (!av7110->analog_tuner_flags) return 0; if (input < 0 || input >= 2) @@ -424,7 +470,7 @@ * INITIALIZATION ****************************************************************************/ -struct saa7146_extension_ioctls ioctls[] = { +static struct saa7146_extension_ioctls ioctls[] = { { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, @@ -528,7 +574,27 @@ INFO(("saa7113 not accessible.\n")); } else { u8 *i = saa7113_init_regs; - av7110->has_analog_tuner = 1; + + if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) { + /* Fujitsu/Siemens DVB-Cable */ + av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820; + } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) { + /* Hauppauge/TT DVB-C premium */ + av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820; + } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) { + /* Hauppauge/TT DVB-C premium */ + av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297; + } + + /* setup for DVB by default */ + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20)) + dprintk(1, "setting band in demodulator failed.\n"); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + } + /* init the saa7113 */ while (*i != 0xff) { if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) { @@ -579,7 +645,7 @@ /* special case DVB-C: these cards have an analog tuner plus need some special handling, so we have separate saa7146_ext_vv data for these... */ - if (av7110->has_analog_tuner) + if (av7110->analog_tuner_flags) ret = saa7146_vv_init(dev, &av7110_vv_data_c); else ret = saa7146_vv_init(dev, &av7110_vv_data_st); @@ -594,12 +660,12 @@ saa7146_vv_release(dev); return -ENODEV; } - if (av7110->has_analog_tuner) { + if (av7110->analog_tuner_flags) { if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) { ERR(("cannot register vbi v4l2 device. skipping.\n")); - } else - /* we use this to remember that this dvb-c card can do vbi */ - av7110->has_analog_tuner = 2; + } else { + av7110->analog_tuner_flags |= ANALOG_TUNER_VBI; + } } return 0; } @@ -607,7 +673,7 @@ int av7110_exit_v4l(struct av7110 *av7110) { saa7146_unregister_device(&av7110->v4l_dev, av7110->dev); - if (2 == av7110->has_analog_tuner) + if (av7110->analog_tuner_flags & ANALOG_TUNER_VBI) saa7146_unregister_device(&av7110->vbi_dev, av7110->dev); return 0; } @@ -684,7 +750,7 @@ .flags = 0, .stds = &standard[0], - .num_stds = sizeof(standard) / sizeof(struct saa7146_standard), + .num_stds = ARRAY_SIZE(standard), .std_callback = &std_callback, .ioctls = &ioctls[0], @@ -698,7 +764,7 @@ .flags = SAA7146_USE_PORT_B_FOR_VBI, .stds = &standard[0], - .num_stds = sizeof(standard) / sizeof(struct saa7146_standard), + .num_stds = ARRAY_SIZE(standard), .std_callback = &std_callback, .ioctls = &ioctls[0], Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget-av.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/budget-av.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget-av.c 2004-12-22 10:04:35.934340002 -0800 @@ -4,6 +4,9 @@ * * Compiled from various sources by Michael Hunold * + * CI interface support (c) 2004 Olivier Gournet & + * Andrew de Quincey + * * Copyright (C) 2002 Ralph Metzler * * Copyright (C) 1999-2002 Ralph Metzler @@ -31,15 +34,34 @@ */ #include "budget.h" +#include "stv0299.h" +#include "tda10021.h" +#include "tda1004x.h" #include +#include +#include +#include +#include +#include +#include + +#include "dvb_ca_en50221.h" + +#define DEBICICAM 0x02420000 struct budget_av { struct budget budget; struct video_device *vd; int cur_input; int has_saa7113; + struct tasklet_struct ciintf_irq_tasklet; + int slot_status; + struct dvb_ca_en50221 ca; }; +int enable_ci = 0; + + /**************************************************************************** * INITIALIZATION ****************************************************************************/ @@ -55,8 +77,10 @@ msgs[1].flags = I2C_M_RD; msgs[0].addr = msgs[1].addr=id/2; mm1[0] = reg; - msgs[0].len = 1; msgs[1].len = 1; - msgs[0].buf = mm1; msgs[1].buf = mm2; + msgs[0].len = 1; + msgs[1].len = 1; + msgs[0].buf = mm1; + msgs[1].buf = mm2; i2c_transfer(i2c, msgs, 2); @@ -90,6 +114,211 @@ return i2c_transfer(i2c, &msgs, 1); } +static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + if (slot != 0) + return -EINVAL; + + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI); + result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0); + + if (result == -ETIMEDOUT) + budget_av->slot_status = 0; + return result; +} + +static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + if (slot != 0) + return -EINVAL; + + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI); + result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0); + + if (result == -ETIMEDOUT) + budget_av->slot_status = 0; + return result; +} + +static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + if (slot != 0) + return -EINVAL; + + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); + result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0); + + if (result == -ETIMEDOUT) + budget_av->slot_status = 0; + return result; +} + +static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + if (slot != 0) + return -EINVAL; + + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); + result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0); + + if (result == -ETIMEDOUT) + budget_av->slot_status = 0; + return result; +} + +static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + struct saa7146_dev *saa = budget_av->budget.dev; + + if (slot != 0) + return -EINVAL; + + dprintk(1, "ciintf_slot_reset\n"); + + /* reset the card */ + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); + msleep(100); + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); + msleep(2000); /* horrendous I know, but its the only way to be absolutely sure without an IRQ line! */ + + ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); + return 0; +} + +static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + struct saa7146_dev *saa = budget_av->budget.dev; + + if (slot != 0) + return -EINVAL; + + dprintk(1, "ciintf_slot_shutdown\n"); + + ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); + budget_av->slot_status = 0; + return 0; +} + +static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + struct saa7146_dev *saa = budget_av->budget.dev; + + if (slot != 0) + return -EINVAL; + + dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status); + + ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); + return 0; +} + +static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + struct saa7146_dev *saa = budget_av->budget.dev; + int cam = 0; + + if (slot != 0) + return -EINVAL; + + if (!budget_av->slot_status) { + saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); + udelay(1); + cam = saa7146_read(saa, PSR) & MASK_06; + saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); + + if (cam) + budget_av->slot_status = 1; + } else if (!open) { + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); + if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT) + budget_av->slot_status = 0; + } + + if (budget_av->slot_status == 1) + return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + + return 0; +} + +static int ciintf_init(struct budget_av *budget_av) +{ + struct saa7146_dev *saa = budget_av->budget.dev; + int result; + + memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221)); + + /* setup GPIOs */ + saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); + saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); + saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); + + /* Reset the card */ + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); + msleep(50); + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); + msleep(100); + + /* Enable DEBI pins */ + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); + + /* register CI interface */ + budget_av->ca.owner = THIS_MODULE; + budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem; + budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem; + budget_av->ca.read_cam_control = ciintf_read_cam_control; + budget_av->ca.write_cam_control = ciintf_write_cam_control; + budget_av->ca.slot_reset = ciintf_slot_reset; + budget_av->ca.slot_shutdown = ciintf_slot_shutdown; + budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; + budget_av->ca.poll_slot_status = ciintf_poll_slot_status; + budget_av->ca.data = budget_av; + if ((result = dvb_ca_en50221_init(budget_av->budget.dvb_adapter, + &budget_av->ca, 0, 1)) != 0) { + printk("budget_av: CI interface detected, but initialisation failed.\n"); + goto error; + } + // success! + printk("ciintf_init: CI interface initialised\n"); + budget_av->budget.ci_present = 1; + return 0; + +error: + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); + return result; +} + +static void ciintf_deinit(struct budget_av *budget_av) +{ + struct saa7146_dev *saa = budget_av->budget.dev; + + saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); + saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT); + saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); + saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); + + /* release the CA device */ + dvb_ca_en50221_release(&budget_av->ca); + + /* disable DEBI pins */ + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); +} + static const u8 saa7113_tab[] = { 0x01, 0x08, @@ -165,6 +394,385 @@ } +static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + u8 m1; + + aclk = 0xb5; + if (srate < 2000000) + bclk = 0x86; + else if (srate < 5000000) + bclk = 0x89; + else if (srate < 15000000) + bclk = 0x8f; + else if (srate < 45000000) + bclk = 0x95; + + m1 = 0x14; + if (srate < 4000000) + m1 = 0x10; + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio) & 0xf0); + stv0299_writereg(fe, 0x0f, 0x80 | m1); + + return 0; +} + +static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct budget_av *budget_av = (struct budget_av *) fe->dvb->priv; + u32 div; + u8 buf[4]; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0x20; + + if (params->u.qpsk.symbol_rate < 4000000) + buf[3] |= 1; + + if (params->frequency < 1250000) + buf[3] |= 0; + else if (params->frequency < 1550000) + buf[3] |= 0x40; + else if (params->frequency < 2050000) + buf[3] |= 0x80; + else if (params->frequency < 2150000) + buf[3] |= 0xC0; + + if (i2c_transfer(&budget_av->budget.i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static u8 typhoon_cinergy1200s_inittab[] = { + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x92, + 0xff, 0xff +}; + +static struct stv0299_config typhoon_config = { + .demod_address = 0x68, + .inittab = typhoon_cinergy1200s_inittab, + .mclk = 88000000UL, + .invert = 0, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, + .pll_set = philips_su1278_ty_ci_pll_set, +}; + + +static struct stv0299_config cinergy_1200s_config = { + .demod_address = 0x68, + .inittab = typhoon_cinergy1200s_inittab, + .mclk = 88000000UL, + .invert = 0, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_0, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, + .pll_set = philips_su1278_ty_ci_pll_set, +}; + + +static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + u8 buf[4]; + struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; + +#define TUNER_MUL 62500 + + u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x8e; + buf[3] = (params->frequency < 174500000 ? 0xa1 : + params->frequency < 454000000 ? 0x92 : 0x34); + + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct tda10021_config philips_cu1216_config = { + .demod_address = 0x0c, + .pll_set = philips_cu1216_pll_set, +}; + + + + +static int philips_tu1216_pll_init(struct dvb_frontend *fe) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; + + // setup PLL configuration + if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + msleep(1); + + return 0; +} + +static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + u8 tuner_buf[4]; + struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len = + sizeof(tuner_buf) }; + int tuner_frequency = 0; + u8 band, cp, filter; + + // determine charge pump + tuner_frequency = params->frequency + 36166000; + if (tuner_frequency < 87000000) + return -EINVAL; + else if (tuner_frequency < 130000000) + cp = 3; + else if (tuner_frequency < 160000000) + cp = 5; + else if (tuner_frequency < 200000000) + cp = 6; + else if (tuner_frequency < 290000000) + cp = 3; + else if (tuner_frequency < 420000000) + cp = 5; + else if (tuner_frequency < 480000000) + cp = 6; + else if (tuner_frequency < 620000000) + cp = 3; + else if (tuner_frequency < 830000000) + cp = 5; + else if (tuner_frequency < 895000000) + cp = 7; + else + return -EINVAL; + + // determine band + if (params->frequency < 49000000) + return -EINVAL; + else if (params->frequency < 161000000) + band = 1; + else if (params->frequency < 444000000) + band = 2; + else if (params->frequency < 861000000) + band = 4; + else + return -EINVAL; + + // setup PLL filter + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + filter = 0; + break; + + case BANDWIDTH_7_MHZ: + filter = 0; + break; + + case BANDWIDTH_8_MHZ: + filter = 1; + break; + + default: + return -EINVAL; + } + + // calculate divisor + // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6) + tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000; + + // setup tuner buffer + tuner_buf[0] = (tuner_frequency >> 8) & 0x7f; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0xca; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; + + if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + + msleep(1); + return 0; +} + +static int philips_tu1216_request_firmware(struct dvb_frontend *fe, + const struct firmware **fw, char *name) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + + return request_firmware(fw, name, &budget->dev->pci->dev); +} + +struct tda1004x_config philips_tu1216_config = { + + .demod_address = 0x8, + .invert = 1, + .invert_oclk = 1, + .pll_init = philips_tu1216_pll_init, + .pll_set = philips_tu1216_pll_set, + .request_firmware = philips_tu1216_request_firmware, +}; + + + + +static u8 read_pwm(struct budget_av *budget_av) +{ + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1}, + {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} + }; + + if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2) + || (pwm == 0xff)) + pwm = 0x48; + + return pwm; +} + + +static void frontend_init(struct budget_av *budget_av) +{ + switch (budget_av->budget.dev->pci->subsystem_device) { + case 0x4f56: // Typhoon/KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059)) + budget_av->budget.dvb_frontend = + stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap); + if (budget_av->budget.dvb_frontend != NULL) { + break; + } + break; + + case 0x0020: // KNC1 DVB-C budget (tda10021/Philips CU1216(tua6034)) + budget_av->budget.dvb_frontend = + tda10021_attach(&philips_cu1216_config, + &budget_av->budget.i2c_adap, read_pwm(budget_av)); + if (budget_av->budget.dvb_frontend != NULL) { + break; + } + break; + + case 0x0030: // KNC1 DVB-T budget (tda10046/Philips TU1216(tda6651tt)) + budget_av->budget.dvb_frontend = + tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); + if (budget_av->budget.dvb_frontend != NULL) { + break; + } + break; + + case 0x1154: // TerraTec Cinergy 1200 DVB-S (stv0299/Philips SU1278(tsa5059)) + budget_av->budget.dvb_frontend = + stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap); + if (budget_av->budget.dvb_frontend != NULL) { + break; + } + break; + + case 0x1156: // Terratec Cinergy 1200 DVB-C (tda10021/Philips CU1216(tua6034)) + budget_av->budget.dvb_frontend = + tda10021_attach(&philips_cu1216_config, + &budget_av->budget.i2c_adap, read_pwm(budget_av)); + if (budget_av->budget.dvb_frontend) { + break; + } + break; + + case 0x1157: // Terratec Cinergy 1200 DVB-T (tda10046/Philips TU1216(tda6651tt)) + budget_av->budget.dvb_frontend = + tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); + if (budget_av->budget.dvb_frontend) { + break; + } + break; + } + + if (budget_av->budget.dvb_frontend == NULL) { + printk("budget_av: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + budget_av->budget.dev->pci->vendor, + budget_av->budget.dev->pci->device, + budget_av->budget.dev->pci->subsystem_vendor, + budget_av->budget.dev->pci->subsystem_device); + } else { + if (dvb_register_frontend + (budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) { + printk("budget-av: Frontend registration failed!\n"); + if (budget_av->budget.dvb_frontend->ops->release) + budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend); + budget_av->budget.dvb_frontend = NULL; + } + } +} + + +static void budget_av_irq(struct saa7146_dev *dev, u32 * isr) +{ + struct budget_av *budget_av = (struct budget_av *) dev->ext_priv; + + dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av); + + if (*isr & MASK_10) + ttpci_budget_irq10_handler(dev, isr); +} + static int budget_av_detach (struct saa7146_dev *dev) { struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; @@ -180,6 +788,11 @@ saa7146_unregister_device (&budget_av->vd, dev); } + if (budget_av->budget.ci_present) + ciintf_deinit(budget_av); + + if (budget_av->budget.dvb_frontend != NULL) + dvb_unregister_frontend(budget_av->budget.dvb_frontend); err = ttpci_budget_deinit (&budget_av->budget); kfree (budget_av); @@ -189,28 +802,24 @@ static struct saa7146_ext_vv vv_data; -static int budget_av_attach (struct saa7146_dev* dev, - struct saa7146_pci_extension_data *info) +static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { struct budget_av *budget_av; - struct budget_info *bi = info->ext_priv; u8 *mac; int err; dprintk(2, "dev: %p\n", dev); - if (bi->type != BUDGET_KNC1 && bi->type != BUDGET_CIN1200) { - return -ENODEV; - } - if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL))) return -ENOMEM; memset(budget_av, 0, sizeof(struct budget_av)); + budget_av->budget.ci_present = 0; + dev->ext_priv = budget_av; - if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) { + if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) { kfree(budget_av); return err; } @@ -220,8 +829,6 @@ saa7146_write(dev, DD1_INIT, 0x07000600); saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26); - //test_knc_ci(av7110); - saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); msleep(500); @@ -234,9 +841,7 @@ return err; } - if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", - VFL_TYPE_GRABBER))) - { + if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) { /* fixme: proper cleanup here */ ERR(("cannot register capture v4l2 device.\n")); return err; @@ -261,15 +866,20 @@ printk("KNC1-%d: Could not read MAC from KNC1 card\n", budget_av->budget.dvb_adapter->num); memset(mac, 0, 6); - } - else + } else { printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", budget_av->budget.dvb_adapter->num, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return 0; } + budget_av->budget.dvb_adapter->priv = budget_av; + frontend_init(budget_av); + + if (enable_ci) + ciintf_init(budget_av); + return 0; +} #define KNC1_INPUTS 2 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { @@ -290,12 +900,9 @@ { struct saa7146_dev *dev = fh->dev; struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; -/* - struct saa7146_vv *vv = dev->vv_data; -*/ + switch(cmd) { - case VIDIOC_ENUMINPUT: - { + case VIDIOC_ENUMINPUT:{ struct v4l2_input *i = arg; dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index); @@ -305,8 +912,7 @@ memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); return 0; } - case VIDIOC_G_INPUT: - { + case VIDIOC_G_INPUT:{ int *input = (int *)arg; *input = budget_av->cur_input; @@ -314,8 +920,7 @@ dprintk(1, "VIDIOC_G_INPUT %d.\n", *input); return 0; } - case VIDIOC_S_INPUT: - { + case VIDIOC_S_INPUT:{ int input = *(int *)arg; dprintk(1, "VIDIOC_S_INPUT %d.\n", input); return saa7113_setinput (budget_av, input); @@ -327,17 +932,15 @@ } static struct saa7146_standard standard[] = { - { - .name = "PAL", .id = V4L2_STD_PAL, + {.name = "PAL",.id = V4L2_STD_PAL, .v_offset = 0x17, .v_field = 288, .h_offset = 0x14, .h_pixels = 680, - .v_max_out = 576, .h_max_out = 768 - }, { - .name = "NTSC", .id = V4L2_STD_NTSC, + .v_max_out = 576,.h_max_out = 768 }, + + {.name = "NTSC",.id = V4L2_STD_NTSC, .v_offset = 0x16, .v_field = 240, .h_offset = 0x06, .h_pixels = 708, - .v_max_out = 480, .h_max_out = 640, - } + .v_max_out = 480,.h_max_out = 640, }, }; static struct saa7146_ext_vv vv_data = { @@ -350,17 +953,22 @@ .ioctl = av_ioctl, }; - - static struct saa7146_extension budget_extension; - -MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1); -MAKE_BUDGET_INFO(cin1200, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200); +MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S); +MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C); +MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T); +MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S); +MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C); +MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T); static struct pci_device_id pci_tbl [] = { - MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56), - MAKE_EXTENSION_PCI(cin1200, 0x153b, 0x1154), + MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56), + MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), + MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), + MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154), + MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156), + MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157), { .vendor = 0, } @@ -377,7 +985,7 @@ .detach = budget_av_detach, .irq_mask = MASK_10, - .irq_func = ttpci_budget_irq10_handler, + .irq_func = budget_av_irq, }; static int __init budget_av_init(void) @@ -396,5 +1004,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); MODULE_DESCRIPTION("driver for the SAA7146 based so-called " - "budget PCI DVB w/ analog input (e.g. the KNC cards)"); - + "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)"); +module_param_named(enable_ci, enable_ci, int, 0644); +MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off)."); Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget-ci.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/budget-ci.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget-ci.c 2004-12-22 10:04:35.950337570 -0800 @@ -39,6 +39,8 @@ #include #include "dvb_ca_en50221.h" +#include "stv0299.h" +#include "tda1004x.h" #define DEBIADDR_IR 0x1234 #define DEBIADDR_CICONTROL 0x0000 @@ -64,72 +66,11 @@ struct input_dev input_dev; struct tasklet_struct msp430_irq_tasklet; struct tasklet_struct ciintf_irq_tasklet; - spinlock_t debilock; int slot_status; struct dvb_ca_en50221 ca; char ir_dev_name[50]; }; -static u32 budget_debiread (struct budget_ci* budget_ci, u32 config, int addr, int count) -{ - struct saa7146_dev *saa = budget_ci->budget.dev; - u32 result = 0; - unsigned long flags; - - if (count > 4 || count <= 0) - return 0; - - spin_lock_irqsave(&budget_ci->debilock, flags); - - if (saa7146_wait_for_debi_done(saa) < 0) { - spin_unlock_irqrestore(&budget_ci->debilock, flags); - return 0; - } - - saa7146_write (saa, DEBI_COMMAND, - (count << 17) | 0x10000 | (addr & 0xffff)); - saa7146_write(saa, DEBI_CONFIG, config); - saa7146_write(saa, DEBI_PAGE, 0); - saa7146_write(saa, MC2, (2 << 16) | 2); - - saa7146_wait_for_debi_done(saa); - - result = saa7146_read(saa, 0x88); - result &= (0xffffffffUL >> ((4 - count) * 8)); - - spin_unlock_irqrestore(&budget_ci->debilock, flags); - return result; -} - -static u8 budget_debiwrite (struct budget_ci* budget_ci, u32 config, int addr, int count, u32 value) -{ - struct saa7146_dev *saa = budget_ci->budget.dev; - unsigned long flags; - - if (count > 4 || count <= 0) - return 0; - - spin_lock_irqsave(&budget_ci->debilock, flags); - - if (saa7146_wait_for_debi_done(saa) < 0) { - spin_unlock_irqrestore(&budget_ci->debilock, flags); - return 0; - } - - saa7146_write (saa, DEBI_COMMAND, - (count << 17) | 0x00000 | (addr & 0xffff)); - saa7146_write(saa, DEBI_CONFIG, config); - saa7146_write(saa, DEBI_PAGE, 0); - saa7146_write(saa, DEBI_AD, value); - saa7146_write(saa, MC2, (2 << 16) | 2); - - saa7146_wait_for_debi_done(saa); - - spin_unlock_irqrestore(&budget_ci->debilock, flags); - return 0; -} - - /* from reading the following remotes: Zenith Universal 7 / TV Mode 807 / VCR Mode 837 Hauppauge (from NOVA-CI-s box product) @@ -206,7 +147,8 @@ { struct budget_ci *budget_ci = (struct budget_ci*) data; struct input_dev *dev = &budget_ci->input_dev; - unsigned int code = budget_debiread(budget_ci, DEBINOSWAP, DEBIADDR_IR, 2) >> 8; + unsigned int code = + ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; if (code & 0x40) { code &= 0x3f; @@ -221,8 +163,7 @@ } if (!key_map[code]) { - printk ("DVB (%s): no key for %02x!\n", - __FUNCTION__, code); + printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code); return; } @@ -281,79 +222,98 @@ input_unregister_device(dev); } -static int ciintf_read_attribute_mem(struct dvb_ca_en50221* ca, int slot, int address) { +static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; - return budget_debiread(budget_ci, DEBICICAM, DEBIADDR_ATTR | (address & 0xfff), 1); + return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM, + DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0); } -static int ciintf_write_attribute_mem(struct dvb_ca_en50221* ca, int slot, int address, u8 value) { +static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; - return budget_debiwrite(budget_ci, DEBICICAM, DEBIADDR_ATTR | (address & 0xfff), 1, value); + return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM, + DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0); } -static int ciintf_read_cam_control(struct dvb_ca_en50221* ca, int slot, u8 address) { +static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; - return budget_debiread(budget_ci, DEBICICAM, DEBIADDR_IO | (address & 3), 1); + return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM, + DEBIADDR_IO | (address & 3), 1, 1, 0); } -static int ciintf_write_cam_control(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value) { +static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; - return budget_debiwrite(budget_ci, DEBICICAM, DEBIADDR_IO | (address & 3), 1, value); + return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM, + DEBIADDR_IO | (address & 3), 1, value, 1, 0); } -static int ciintf_slot_reset(struct dvb_ca_en50221* ca, int slot) { +static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; struct saa7146_dev *saa = budget_ci->budget.dev; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; // trigger on RISING edge during reset so we know when READY is re-asserted saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); budget_ci->slot_status = SLOTSTATUS_RESET; - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); msleep(1); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, + CICONTROL_RESET, 1, 0); saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); return 0; } -static int ciintf_slot_shutdown(struct dvb_ca_en50221* ca, int slot) { +static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; struct saa7146_dev *saa = budget_ci->budget.dev; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); return 0; } -static int ciintf_slot_ts_enable(struct dvb_ca_en50221* ca, int slot) { +static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; struct saa7146_dev *saa = budget_ci->budget.dev; int tmp; - if (slot != 0) return -EINVAL; - + if (slot != 0) + return -EINVAL; saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO); - tmp = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, tmp | CICONTROL_ENABLETS); + tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, + tmp | CICONTROL_ENABLETS, 1, 0); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); return 0; @@ -367,10 +327,11 @@ unsigned int flags; // ensure we don't get spurious IRQs during initialisation - if (!budget_ci->budget.ci_present) return; + if (!budget_ci->budget.ci_present) + return; // read the CAM status - flags = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); + flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); if (flags & CICONTROL_CAMDETECT) { // GPIO should be set to trigger on falling edge if a CAM is present @@ -379,7 +340,8 @@ if (budget_ci->slot_status & SLOTSTATUS_NONE) { // CAM insertion IRQ budget_ci->slot_status = SLOTSTATUS_PRESENT; - dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, DVB_CA_EN50221_CAMCHANGE_INSERTED); + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, + DVB_CA_EN50221_CAMCHANGE_INSERTED); } else if (budget_ci->slot_status & SLOTSTATUS_RESET) { // CAM ready (reset completed) @@ -401,7 +363,8 @@ if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) { // CAM removal IRQ budget_ci->slot_status = SLOTSTATUS_NONE; - dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, DVB_CA_EN50221_CAMCHANGE_REMOVED); + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, + DVB_CA_EN50221_CAMCHANGE_REMOVED); } } } @@ -418,18 +381,18 @@ saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); // test if it is there - if ((budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CIVERSION, 1) & 0xa0) != 0xa0) { + if ((ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0) & 0xa0) != 0xa0) { result = -ENODEV; goto error; } - // determine whether a CAM is present or not - flags = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); + flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); budget_ci->slot_status = SLOTSTATUS_NONE; - if (flags & CICONTROL_CAMDETECT) budget_ci->slot_status = SLOTSTATUS_PRESENT; - + if (flags & CICONTROL_CAMDETECT) + budget_ci->slot_status = SLOTSTATUS_PRESENT; // register CI interface + budget_ci->ca.owner = THIS_MODULE; budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem; budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem; budget_ci->ca.read_cam_control = ciintf_read_cam_control; @@ -442,8 +405,7 @@ &budget_ci->ca, DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | DVB_CA_EN50221_FLAG_IRQ_FR | - DVB_CA_EN50221_FLAG_IRQ_DA, - 1)) != 0) { + DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) { printk("budget_ci: CI interface detected, but initialisation failed.\n"); goto error; } @@ -456,7 +418,8 @@ saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); } saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, + CICONTROL_RESET, 1, 0); // success! printk("budget_ci: CI interface initialised\n"); @@ -464,7 +427,8 @@ // forge a fake CI IRQ so the CAM state is setup correctly flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; - if (budget_ci->slot_status != SLOTSTATUS_NONE) flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; + if (budget_ci->slot_status != SLOTSTATUS_NONE) + flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags); return 0; @@ -482,9 +446,10 @@ saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); tasklet_kill(&budget_ci->ciintf_irq_tasklet); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); msleep(1); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, + CICONTROL_RESET, 1, 0); // disable TS data stream to CI interface saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT); @@ -513,9 +478,426 @@ } +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio) & 0xf0); + + return 0; +} + +static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0xC4; + + if (params->frequency > 1530000) + buf[3] = 0xc0; + + if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + + + + +static u8 philips_su1278_tt_inittab[] = { + 0x01, 0x0f, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x5b, + 0x05, 0x85, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0x02, + 0x09, 0x00, + 0x0C, 0x01, + 0x0D, 0x81, + 0x0E, 0x44, + 0x0f, 0x14, + 0x10, 0x3c, + 0x11, 0x84, + 0x12, 0xda, + 0x13, 0x97, + 0x14, 0x95, + 0x15, 0xc9, + 0x16, 0x19, + 0x17, 0x8c, + 0x18, 0x59, + 0x19, 0xf8, + 0x1a, 0xfe, + 0x1c, 0x7f, + 0x1d, 0x00, + 0x1e, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, + 0x29, 0x28, + 0x2a, 0x14, + 0x2b, 0x0f, + 0x2c, 0x09, + 0x2d, 0x09, + 0x31, 0x1f, + 0x32, 0x19, + 0x33, 0xfc, + 0x34, 0x93, + 0xff, 0xff +}; -static int budget_ci_attach (struct saa7146_dev* dev, - struct saa7146_pci_extension_data *info) +static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + stv0299_writereg(fe, 0x0e, 0x44); + if (srate >= 10000000) { + stv0299_writereg(fe, 0x13, 0x97); + stv0299_writereg(fe, 0x14, 0x95); + stv0299_writereg(fe, 0x15, 0xc9); + stv0299_writereg(fe, 0x17, 0x8c); + stv0299_writereg(fe, 0x1a, 0xfe); + stv0299_writereg(fe, 0x1c, 0x7f); + stv0299_writereg(fe, 0x2d, 0x09); + } else { + stv0299_writereg(fe, 0x13, 0x99); + stv0299_writereg(fe, 0x14, 0x8d); + stv0299_writereg(fe, 0x15, 0xce); + stv0299_writereg(fe, 0x17, 0x43); + stv0299_writereg(fe, 0x1a, 0x1d); + stv0299_writereg(fe, 0x1c, 0x12); + stv0299_writereg(fe, 0x2d, 0x05); + } + stv0299_writereg(fe, 0x0e, 0x23); + stv0299_writereg(fe, 0x0f, 0x94); + stv0299_writereg(fe, 0x10, 0x39); + stv0299_writereg(fe, 0x15, 0xc9); + + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio) & 0xf0); + + return 0; +} + +static int philips_su1278_tt_pll_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + u32 div; + u8 buf[4]; + struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (500 - 1)) / 500; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2; + buf[3] = 0x20; + + if (params->u.qpsk.symbol_rate < 4000000) + buf[3] |= 1; + + if (params->frequency < 1250000) + buf[3] |= 0; + else if (params->frequency < 1550000) + buf[3] |= 0x40; + else if (params->frequency < 2050000) + buf[3] |= 0x80; + else if (params->frequency < 2150000) + buf[3] |= 0xC0; + + if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct stv0299_config philips_su1278_tt_config = { + + .demod_address = 0x68, + .inittab = philips_su1278_tt_inittab, + .mclk = 64000000UL, + .invert = 0, + .enhanced_tuning = 1, + .skip_reinit = 1, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 50, + .set_symbol_rate = philips_su1278_tt_set_symbol_rate, + .pll_set = philips_su1278_tt_pll_set, +}; + + + +static int philips_tdm1316l_pll_init(struct dvb_frontend *fe) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; + struct i2c_msg tuner_msg = {.addr = 0x63,.flags = 0,.buf = td1316_init,.len = + sizeof(td1316_init) }; + + // setup PLL configuration + if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + msleep(1); + + // disable the mc44BC374c (do not check for errors) + tuner_msg.addr = 0x65; + tuner_msg.buf = disable_mc44BC374c; + tuner_msg.len = sizeof(disable_mc44BC374c); + if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) { + i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1); + } + + return 0; +} + +static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + u8 tuner_buf[4]; + struct i2c_msg tuner_msg = {.addr = 0x63,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) }; + int tuner_frequency = 0; + u8 band, cp, filter; + + // determine charge pump + tuner_frequency = params->frequency + 36130000; + if (tuner_frequency < 87000000) + return -EINVAL; + else if (tuner_frequency < 130000000) + cp = 3; + else if (tuner_frequency < 160000000) + cp = 5; + else if (tuner_frequency < 200000000) + cp = 6; + else if (tuner_frequency < 290000000) + cp = 3; + else if (tuner_frequency < 420000000) + cp = 5; + else if (tuner_frequency < 480000000) + cp = 6; + else if (tuner_frequency < 620000000) + cp = 3; + else if (tuner_frequency < 830000000) + cp = 5; + else if (tuner_frequency < 895000000) + cp = 7; + else + return -EINVAL; + + // determine band + if (params->frequency < 49000000) + return -EINVAL; + else if (params->frequency < 159000000) + band = 1; + else if (params->frequency < 444000000) + band = 2; + else if (params->frequency < 861000000) + band = 4; + else + return -EINVAL; + + // setup PLL filter and TDA9889 + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + tda1004x_write_byte(fe, 0x0C, 0x14); + filter = 0; + break; + + case BANDWIDTH_7_MHZ: + tda1004x_write_byte(fe, 0x0C, 0x80); + filter = 0; + break; + + case BANDWIDTH_8_MHZ: + tda1004x_write_byte(fe, 0x0C, 0x14); + filter = 1; + break; + + default: + return -EINVAL; + } + + // calculate divisor + // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6) + tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000; + + // setup tuner buffer + tuner_buf[0] = tuner_frequency >> 8; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0xca; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; + + if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + + msleep(1); + return 0; +} + +static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe, + const struct firmware **fw, char *name) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + + return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev); +} + +static struct tda1004x_config philips_tdm1316l_config = { + + .demod_address = 0x8, + .invert = 0, + .invert_oclk = 0, + .pll_init = philips_tdm1316l_pll_init, + .pll_set = philips_tdm1316l_pll_set, + .request_firmware = philips_tdm1316l_request_firmware, +}; + + + +static void frontend_init(struct budget_ci *budget_ci) +{ + switch (budget_ci->budget.dev->pci->subsystem_device) { + case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059)) + budget_ci->budget.dvb_frontend = + stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap); + if (budget_ci->budget.dvb_frontend) { + break; + } + break; + + case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059)) + budget_ci->budget.dvb_frontend = + stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap); + if (budget_ci->budget.dvb_frontend) { + break; + } + break; + + case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889) + budget_ci->budget.dvb_frontend = + tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); + if (budget_ci->budget.dvb_frontend) { + break; + } + break; + } + + if (budget_ci->budget.dvb_frontend == NULL) { + printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + budget_ci->budget.dev->pci->vendor, + budget_ci->budget.dev->pci->device, + budget_ci->budget.dev->pci->subsystem_vendor, + budget_ci->budget.dev->pci->subsystem_device); + } else { + if (dvb_register_frontend + (budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) { + printk("budget-ci: Frontend registration failed!\n"); + if (budget_ci->budget.dvb_frontend->ops->release) + budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend); + budget_ci->budget.dvb_frontend = NULL; + } + } +} + +static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { struct budget_ci *budget_ci; int err; @@ -525,12 +907,11 @@ dprintk(2, "budget_ci: %p\n", budget_ci); - spin_lock_init(&budget_ci->debilock); budget_ci->budget.ci_present = 0; dev->ext_priv = budget_ci; - if ((err = ttpci_budget_init (&budget_ci->budget, dev, info))) { + if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) { kfree (budget_ci); return err; } @@ -542,6 +923,9 @@ ciintf_init(budget_ci); + budget_ci->budget.dvb_adapter->priv = budget_ci; + frontend_init(budget_ci); + return 0; } @@ -553,8 +937,10 @@ struct saa7146_dev *saa = budget_ci->budget.dev; int err; - if (budget_ci->budget.ci_present) ciintf_deinit(budget_ci); - + if (budget_ci->budget.ci_present) + ciintf_deinit(budget_ci); + if (budget_ci->budget.dvb_frontend) + dvb_unregister_frontend(budget_ci->budget.dvb_frontend); err = ttpci_budget_deinit (&budget_ci->budget); tasklet_kill (&budget_ci->msp430_irq_tasklet); Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget-core.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/budget-core.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget-core.c 2004-12-22 10:04:35.956336658 -0800 @@ -56,7 +56,7 @@ return budget->feeding; saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off - IER_DISABLE(budget->dev, MASK_10); + SAA7146_IER_DISABLE(budget->dev, MASK_10); return 0; } @@ -74,8 +74,7 @@ memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH); - saa7146_write(dev, PCI_BT_V1, 0x001c0000 | - (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000)); + saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000)); budget->tsf=0xff; budget->ttbp=0; @@ -125,7 +124,7 @@ saa7146_write(dev, MC2, (MASK_04 | MASK_20)); saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on - IER_ENABLE(budget->dev, MASK_10); // VPE + SAA7146_IER_ENABLE(budget->dev, MASK_10); // VPE return ++budget->feeding; } @@ -150,14 +149,87 @@ return; if (newdma > olddma) { /* no wraparound, dump olddma..newdma */ - dvb_dmx_swfilter_packets(&budget->demux, - mem+olddma, (newdma-olddma) / 188); + dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (newdma - olddma) / 188); } else { /* wraparound, dump olddma..buflen and 0..newdma */ - dvb_dmx_swfilter_packets(&budget->demux, - mem+olddma, (TS_BUFLEN-olddma) / 188); - dvb_dmx_swfilter_packets(&budget->demux, - mem, newdma / 188); + dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (TS_BUFLEN - olddma) / 188); + dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188); + } } + + +int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count, + int uselocks, int nobusyloop) +{ + struct saa7146_dev *saa = budget->dev; + int result = 0; + unsigned long flags = 0; + + if (count > 4 || count <= 0) + return 0; + + if (uselocks) + spin_lock_irqsave(&budget->debilock, flags); + + if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return result; + } + + saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff)); + saa7146_write(saa, DEBI_CONFIG, config); + saa7146_write(saa, DEBI_PAGE, 0); + saa7146_write(saa, MC2, (2 << 16) | 2); + + if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return result; + } + + result = saa7146_read(saa, DEBI_AD); + result &= (0xffffffffUL >> ((4 - count) * 8)); + + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + + return result; +} + +int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, + int count, u32 value, int uselocks, int nobusyloop) +{ + struct saa7146_dev *saa = budget->dev; + unsigned long flags = 0; + int result; + + if (count > 4 || count <= 0) + return 0; + + if (uselocks) + spin_lock_irqsave(&budget->debilock, flags); + + if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return result; + } + + saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff)); + saa7146_write(saa, DEBI_CONFIG, config); + saa7146_write(saa, DEBI_PAGE, 0); + saa7146_write(saa, DEBI_AD, value); + saa7146_write(saa, MC2, (2 << 16) | 2); + + if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return result; + } + + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return 0; } @@ -231,13 +303,11 @@ return ret; budget->mem_frontend.source = DMX_MEMORY_FE; - ret=dvbdemux->dmx.add_frontend (&dvbdemux->dmx, - &budget->mem_frontend); + ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend); if (ret<0) return ret; - ret=dvbdemux->dmx.connect_frontend (&dvbdemux->dmx, - &budget->hw_frontend); + ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend); if (ret < 0) return ret; @@ -263,30 +333,9 @@ dvb_dmx_release(&budget->demux); } -/* fixme: can this be unified among all saa7146 based dvb cards? */ -static int client_register(struct i2c_client *client) -{ - struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter); - struct budget *budget = (struct budget*)dev->ext_priv; - - if (client->driver->command) - return client->driver->command(client, FE_REGISTER, budget->dvb_adapter); - return 0; -} - -static int client_unregister(struct i2c_client *client) -{ - struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter); - struct budget *budget = (struct budget*)dev->ext_priv; - - if (client->driver->command) - return client->driver->command(client, FE_UNREGISTER, budget->dvb_adapter); - return 0; -} - -int ttpci_budget_init (struct budget *budget, - struct saa7146_dev* dev, - struct saa7146_pci_extension_data *info) +int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, + struct saa7146_pci_extension_data *info, + struct module *owner) { int length = TS_WIDTH*TS_HEIGHT; int ret = 0; @@ -299,7 +348,7 @@ budget->card = bi; budget->dev = (struct saa7146_dev *) dev; - dvb_register_adapter(&budget->dvb_adapter, budget->card->name, THIS_MODULE); + dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner); /* set dd1 stream a & b */ saa7146_write(dev, DD1_STREAM_B, 0x00000000); @@ -313,21 +362,18 @@ else budget->video_port = BUDGET_VIDEO_PORTA; spin_lock_init(&budget->feedlock); + spin_lock_init(&budget->debilock); /* the Siemens DVB needs this if you want to have the i2c chips get recognized before the main driver is loaded */ if (bi->type != BUDGET_FS_ACTIVY) saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */ - budget->i2c_adap = (struct i2c_adapter) { - .client_register = client_register, - .client_unregister = client_unregister, #ifdef I2C_ADAP_CLASS_TV_DIGITAL - .class = I2C_ADAP_CLASS_TV_DIGITAL, + budget->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL; #else - .class = I2C_CLASS_TV_DIGITAL, + budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL; #endif - }; strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name)); @@ -341,7 +387,8 @@ ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter->proposed_mac); - if( NULL == (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci,length,&budget->pt))) { + if (NULL == + (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, &budget->pt))) { ret = -ENOMEM; goto err; } @@ -420,8 +467,8 @@ spin_unlock(&budget->feedlock); } - - +EXPORT_SYMBOL_GPL(ttpci_budget_debiread); +EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite); EXPORT_SYMBOL_GPL(ttpci_budget_init); EXPORT_SYMBOL_GPL(ttpci_budget_deinit); EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget-patch.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/budget-patch.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget-patch.c 2004-12-22 10:04:35.963335594 -0800 @@ -33,6 +33,9 @@ #include "av7110.h" #include "av7110_hw.h" #include "budget.h" +#include "stv0299.h" +#include "ves1x93.h" +#include "tda8083.h" #define budget_patch budget @@ -121,16 +124,11 @@ return 0; } - -int budget_patch_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int budget_patch_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { - struct budget_patch *budget = fe->before_after_data; - - dprintk(2, "budget: %p\n", budget); + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; - switch (cmd) { - case FE_SET_TONE: - switch ((fe_sec_tone_mode_t) arg) { + switch (tone) { case SEC_TONE_ON: av7110_set22k (budget, 1); break; @@ -140,27 +138,232 @@ default: return -EINVAL; } - break; - case FE_DISEQC_SEND_MASTER_CMD: + return 0; +} + +static int budget_patch_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) { - struct dvb_diseqc_master_cmd *cmd = arg; + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0); - break; + + return 0; } - case FE_DISEQC_SEND_BURST: - av7110_send_diseqc_msg (budget, 0, NULL, (int) (long) arg); - break; +static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +{ + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; + + av7110_send_diseqc_msg (budget, 0, NULL, minicmd); - default: - return -EOPNOTSUPP; + return 0; } +static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; + u8 pwr = 0; + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + u32 div = (params->frequency + 479500) / 125; + + if (params->frequency > 2000000) pwr = 3; + else if (params->frequency > 1800000) pwr = 2; + else if (params->frequency > 1600000) pwr = 1; + else if (params->frequency > 1200000) pwr = 0; + else if (params->frequency >= 1100000) pwr = 1; + else pwr = 2; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = ((div & 0x18000) >> 10) | 0x95; + buf[3] = (pwr << 6) | 0x30; + + // NOTE: since we're using a prescaler of 2, we set the + // divisor frequency to 62.5kHz and divide by 125 above + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +static struct ves1x93_config alps_bsrv2_config = { + .demod_address = 0x08, + .xin = 90100000UL, + .invert_pwm = 0, + .pll_set = alps_bsrv2_pll_set, +}; + +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } + + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + return 0; } +static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + data[3] = 0xC4; + + if (params->frequency > 1530000) data[3] = 0xc0; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + +static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = params->frequency / 125; + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x8e; + data[3] = 0x00; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +struct tda8083_config grundig_29504_451_config = { + .demod_address = 0x68, + .pll_set = grundig_29504_451_pll_set, +}; + +static void frontend_init(struct budget_patch* budget) +{ + switch(budget->dev->pci->subsystem_device) { + case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X + + // try the ALPS BSRV2 first of all + budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_patch_set_tone; + break; + } + + // try the ALPS BSRU6 now + budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_patch_set_tone; + break; + } + + // Try the grundig 29504-451 + budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_patch_set_tone; + break; + } + break; + } + + if (budget->dvb_frontend == NULL) { + printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + budget->dev->pci->vendor, + budget->dev->pci->device, + budget->dev->pci->subsystem_vendor, + budget->dev->pci->subsystem_device); + } else { + if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) { + printk("budget-av: Frontend registration failed!\n"); + if (budget->dvb_frontend->ops->release) + budget->dvb_frontend->ops->release(budget->dvb_frontend); + budget->dvb_frontend = NULL; + } + } +} static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { @@ -173,7 +376,7 @@ dprintk(2, "budget: %p\n", budget); - if ((err = ttpci_budget_init (budget, dev, info))) { + if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { kfree (budget); return err; } @@ -221,11 +424,11 @@ // Enable RPS1 (rFC p33) saa7146_write(dev, MC1, (MASK_13 | MASK_29)); - dvb_add_frontend_ioctls (budget->dvb_adapter, - budget_patch_diseqc_ioctl, NULL, budget); - dev->ext_priv = budget; + budget->dvb_adapter->priv = budget; + frontend_init(budget); + return 0; } @@ -235,8 +438,7 @@ struct budget_patch *budget = (struct budget_patch*) dev->ext_priv; int err; - dvb_remove_frontend_ioctls (budget->dvb_adapter, - budget_patch_diseqc_ioctl, NULL); + if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend); err = ttpci_budget_deinit (budget); Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/budget.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget.c 2004-12-22 10:04:35.972334226 -0800 @@ -35,6 +35,11 @@ */ #include "budget.h" +#include "stv0299.h" +#include "ves1x93.h" +#include "ves1820.h" +#include "l64781.h" +#include "tda8083.h" static void Set22K (struct budget *budget, int state) { @@ -105,89 +110,368 @@ return 0; } - -int budget_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +/* + * Routines for the Fujitsu Siemens Activy budget card + * 22 kHz tone and DiSEqC are handled by the frontend. + * Voltage must be set here. + */ +static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage) { - struct budget *budget = fe->before_after_data; + struct saa7146_dev *dev=budget->dev; dprintk(2, "budget: %p\n", budget); - switch (cmd) { - case FE_SET_TONE: - switch ((fe_sec_tone_mode_t) arg) { + switch (voltage) { + case SEC_VOLTAGE_13: + saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO); + break; + case SEC_VOLTAGE_18: + saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + + return SetVoltage_Activy (budget, voltage); +} + +static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + + switch (tone) { case SEC_TONE_ON: Set22K (budget, 1); break; case SEC_TONE_OFF: Set22K (budget, 0); break; + default: return -EINVAL; - }; - break; + } + + return 0; +} - case FE_DISEQC_SEND_MASTER_CMD: +static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) { - struct dvb_diseqc_master_cmd *cmd = arg; + struct budget* budget = (struct budget*) fe->dvb->priv; SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0); - break; + + return 0; } - case FE_DISEQC_SEND_BURST: - SendDiSEqCMsg (budget, 0, NULL, (unsigned long)arg); - break; - - default: - return -EOPNOTSUPP; - }; +static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + + SendDiSEqCMsg (budget, 0, NULL, minicmd); return 0; } +static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + u8 pwr = 0; + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + u32 div = (params->frequency + 479500) / 125; + + if (params->frequency > 2000000) pwr = 3; + else if (params->frequency > 1800000) pwr = 2; + else if (params->frequency > 1600000) pwr = 1; + else if (params->frequency > 1200000) pwr = 0; + else if (params->frequency >= 1100000) pwr = 1; + else pwr = 2; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = ((div & 0x18000) >> 10) | 0x95; + buf[3] = (pwr << 6) | 0x30; -/* - * Routines for the Fujitsu Siemens Activy budget card - * 22 kHz tone and DiSEqC are handled by the frontend. - * Voltage must be set here. - */ -static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage) + // NOTE: since we're using a prescaler of 2, we set the + // divisor frequency to 62.5kHz and divide by 125 above + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +static struct ves1x93_config alps_bsrv2_config = { - struct saa7146_dev *dev=budget->dev; + .demod_address = 0x08, + .xin = 90100000UL, + .invert_pwm = 0, + .pll_set = alps_bsrv2_pll_set, +}; - dprintk(2, "budget: %p\n", budget); +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; - switch (voltage) { - case SEC_VOLTAGE_13: - saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO); - break; - case SEC_VOLTAGE_18: - saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); - break; - default: - return -EINVAL; +static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } + + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + + return 0; } +static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + data[3] = 0xC4; + + if (params->frequency > 1530000) data[3] = 0xc0; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; -static int budget_ioctl_activy (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - struct budget *budget = fe->before_after_data; + struct budget* budget = (struct budget*) fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) }; - dprintk(2, "budget: %p\n", budget); + div = (params->frequency + 35937500 + 31250) / 62500; - switch (cmd) { - case FE_SET_VOLTAGE: - return SetVoltage_Activy (budget, (fe_sec_voltage_t) arg); - default: - return -EOPNOTSUPP; + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x85 | ((div >> 10) & 0x60); + data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +static struct ves1820_config alps_tdbe2_config = { + .demod_address = 0x09, + .xin = 57840000UL, + .invert = 1, + .selagc = VES1820_SELAGC_SIGNAMPERR, + .pll_set = alps_tdbe2_pll_set, +}; + +static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + u32 div; + u8 cfg, cpump, band_select; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (36125000 + params->frequency) / 166666; + + cfg = 0x88; + + if (params->frequency < 175000000) cpump = 2; + else if (params->frequency < 390000000) cpump = 1; + else if (params->frequency < 470000000) cpump = 2; + else if (params->frequency < 750000000) cpump = 1; + else cpump = 3; + + if (params->frequency < 175000000) band_select = 0x0e; + else if (params->frequency < 470000000) band_select = 0x05; + else band_select = 0x03; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = ((div >> 10) & 0x60) | cfg; + data[3] = (cpump << 6) | band_select; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; } +static struct l64781_config grundig_29504_401_config = { + .demod_address = 0x55, + .pll_set = grundig_29504_401_pll_set, +}; + +static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = params->frequency / 125; + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x8e; + data[3] = 0x00; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } +static struct tda8083_config grundig_29504_451_config = { + .demod_address = 0x68, + .pll_set = grundig_29504_451_pll_set, +}; + +static u8 read_pwm(struct budget* budget) +{ + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 }, + { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} }; + + if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff)) + pwm = 0x48; + + return pwm; +} + +static void frontend_init(struct budget *budget) +{ + switch(budget->dev->pci->subsystem_device) { + case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659)) + + // try the ALPS BSRV2 first of all + budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_set_tone; + break; + } + + // try the ALPS BSRU6 now + budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_set_tone; + break; + } + break; + + case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) + + budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget)); + if (budget->dvb_frontend) break; + break; + + case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060)) + + budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap); + if (budget->dvb_frontend) break; + break; + + case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI (tda8083/Grundig 29504-451(tsa5522)) + + // grundig 29504-451 + budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage; + break; + } + break; + } + + if (budget->dvb_frontend == NULL) { + printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + budget->dev->pci->vendor, + budget->dev->pci->device, + budget->dev->pci->subsystem_vendor, + budget->dev->pci->subsystem_device); + } else { + if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) { + printk("budget: Frontend registration failed!\n"); + if (budget->dvb_frontend->ops->release) + budget->dvb_frontend->ops->release(budget->dvb_frontend); + budget->dvb_frontend = NULL; + } + } +} static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { @@ -203,18 +487,14 @@ dev->ext_priv = budget; - if ((err = ttpci_budget_init (budget, dev, info))) { + if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { printk("==> failed\n"); kfree (budget); return err; } - if (budget->card->type == BUDGET_FS_ACTIVY) - dvb_add_frontend_ioctls (budget->dvb_adapter, - budget_ioctl_activy, NULL, budget); - else - dvb_add_frontend_ioctls (budget->dvb_adapter, - budget_diseqc_ioctl, NULL, budget); + budget->dvb_adapter->priv = budget; + frontend_init(budget); return 0; } @@ -225,12 +505,7 @@ struct budget *budget = (struct budget*) dev->ext_priv; int err; - if (budget->card->type == BUDGET_FS_ACTIVY) - dvb_remove_frontend_ioctls (budget->dvb_adapter, - budget_ioctl_activy, NULL); - else - dvb_remove_frontend_ioctls (budget->dvb_adapter, - budget_diseqc_ioctl, NULL); + if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend); err = ttpci_budget_deinit (budget); @@ -247,18 +522,14 @@ MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); -MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); +/* MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); UNDEFINED HARDWARE - mail linuxtv.org list */ MAKE_BUDGET_INFO(fsacs, "Fujitsu Siemens Activy Budget-S PCI", BUDGET_FS_ACTIVY); -/* Uncomment for Budget Patch */ -/*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/ static struct pci_device_id pci_tbl[] = { - /* Uncomment for Budget Patch */ - /*MAKE_EXTENSION_PCI(fs_1_3,0x13c2, 0x0000),*/ MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), - MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), +/* MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), UNDEFINED HARDWARE */ MAKE_EXTENSION_PCI(fsacs, 0x1131, 0x4f61), { .vendor = 0, Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttpci/budget.h 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttpci/budget.h 2004-12-22 10:04:35.975333770 -0800 @@ -9,6 +9,7 @@ #include "dvb_filter.h" #include "dvb_net.h" +#include #include extern int budget_debug; @@ -61,7 +62,10 @@ spinlock_t feedlock; + spinlock_t debilock; + struct dvb_adapter *dvb_adapter; + struct dvb_frontend *dvb_frontend; void *priv; }; @@ -82,20 +86,27 @@ #define BUDGET_TT 0 #define BUDGET_TT_HW_DISEQC 1 -#define BUDGET_KNC1 2 #define BUDGET_PATCH 3 #define BUDGET_FS_ACTIVY 4 -#define BUDGET_CIN1200 5 +#define BUDGET_CIN1200S 5 +#define BUDGET_CIN1200C 6 +#define BUDGET_CIN1200T 7 +#define BUDGET_KNC1S 8 +#define BUDGET_KNC1C 9 +#define BUDGET_KNC1T 10 #define BUDGET_VIDEO_PORTA 0 #define BUDGET_VIDEO_PORTB 1 -extern int ttpci_budget_init (struct budget *budget, - struct saa7146_dev* dev, - struct saa7146_pci_extension_data *info); +extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, + struct saa7146_pci_extension_data *info, + struct module *owner); extern int ttpci_budget_deinit (struct budget *budget); extern void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr); extern void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port); +extern int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count, + int uselocks, int nobusyloop); +extern int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, int count, u32 value, + int uselocks, int nobusyloop); #endif - Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-budget/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttusb-budget/Kconfig 2004-12-22 09:07:08.910367298 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-budget/Kconfig 2004-12-22 10:04:35.977333466 -0800 @@ -1,6 +1,10 @@ config DVB_TTUSB_BUDGET tristate "Technotrend/Hauppauge Nova-USB devices" depends on DVB_CORE && USB + select DVB_CX22700 + select DVB_TDA1004X + select DVB_TDA8083 + select DVB_STV0299 help Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'Nova-USB'. Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-budget/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttusb-budget/Makefile 2004-12-22 09:07:08.911367146 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-budget/Makefile 2004-12-22 10:04:35.978333314 -0800 @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c 2004-12-22 10:04:35.990331490 -0800 @@ -24,6 +24,10 @@ #include "dmxdev.h" #include "dvb_demux.h" #include "dvb_net.h" +#include "cx22700.h" +#include "tda1004x.h" +#include "stv0299.h" +#include "tda8083.h" #include #include @@ -132,6 +136,8 @@ #if 0 devfs_handle_t stc_devfs_handle; #endif + + struct dvb_frontend* fe; }; /* ugly workaround ... don't know why it's neccessary to read */ @@ -461,9 +467,10 @@ } #ifdef TTUSB_DISEQC -static int ttusb_send_diseqc(struct ttusb *ttusb, +static int ttusb_send_diseqc(struct dvb_frontend* fe, const struct dvb_diseqc_master_cmd *cmd) { + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; u8 b[12] = { 0xaa, ++ttusb->c, 0x18 }; int err; @@ -501,41 +508,24 @@ return err; } -static int ttusb_set_voltage(struct ttusb *ttusb, fe_sec_voltage_t voltage) +static int ttusb_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + ttusb->voltage = voltage; return ttusb_update_lnb(ttusb); } #ifdef TTUSB_TONE -static int ttusb_set_tone(struct ttusb *ttusb, fe_sec_tone_mode_t tone) +static int ttusb_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + ttusb->tone = tone; return ttusb_update_lnb(ttusb); } #endif -static int ttusb_lnb_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct ttusb *ttusb = fe->before_after_data; - - switch (cmd) { - case FE_SET_VOLTAGE: - return ttusb_set_voltage(ttusb, (fe_sec_voltage_t) arg); -#ifdef TTUSB_TONE - case FE_SET_TONE: - return ttusb_set_tone(ttusb, (fe_sec_tone_mode_t) arg); -#endif -#ifdef TTUSB_DISEQC - case FE_DISEQC_SEND_MASTER_CMD: - return ttusb_send_diseqc(ttusb, - (struct dvb_diseqc_master_cmd *) - arg); -#endif - default: - return -EOPNOTSUPP; - }; -} #if 0 static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq) @@ -560,7 +550,7 @@ const u8 * data, int len); #endif -int numpkt = 0, lastj, numts, numstuff, numsec, numinvalid; +static int numpkt = 0, lastj, numts, numstuff, numsec, numinvalid; static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack, int len) @@ -1071,38 +1061,347 @@ }; #endif -u32 functionality(struct i2c_adapter *adapter) +static u32 functionality(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; } -static struct i2c_algorithm ttusb_dec_algo = { - .name = "ttusb dec i2c algorithm", - .id = I2C_ALGO_BIT, - .master_xfer = master_xfer, - .functionality = functionality, + + +static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 data[4]; + struct i2c_msg msg = {.addr=0x61, .flags=0, .buf=data, .len=sizeof(data) }; + u32 div; + + div = (params->frequency + 36166667) / 166667; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = ((div >> 10) & 0x60) | 0x85; + data[3] = params->frequency < 592000000 ? 0x40 : 0x80; + + if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +struct cx22700_config alps_tdmb7_config = { + .demod_address = 0x43, + .pll_set = alps_tdmb7_pll_set, }; -static int client_register(struct i2c_client *client) + + + + +static int philips_tdm1316l_pll_init(struct dvb_frontend* fe) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; + struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) }; + + // setup PLL configuration + if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO; + msleep(1); + + // disable the mc44BC374c (do not check for errors) + tuner_msg.addr = 0x65; + tuner_msg.buf = disable_mc44BC374c; + tuner_msg.len = sizeof(disable_mc44BC374c); + if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) { + i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1); + } + + return 0; +} + +static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - struct ttusb *ttusb = (struct ttusb*)i2c_get_adapdata(client->adapter); + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 tuner_buf[4]; + struct i2c_msg tuner_msg = {.addr=0x60, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) }; + int tuner_frequency = 0; + u8 band, cp, filter; + + // determine charge pump + tuner_frequency = params->frequency + 36130000; + if (tuner_frequency < 87000000) return -EINVAL; + else if (tuner_frequency < 130000000) cp = 3; + else if (tuner_frequency < 160000000) cp = 5; + else if (tuner_frequency < 200000000) cp = 6; + else if (tuner_frequency < 290000000) cp = 3; + else if (tuner_frequency < 420000000) cp = 5; + else if (tuner_frequency < 480000000) cp = 6; + else if (tuner_frequency < 620000000) cp = 3; + else if (tuner_frequency < 830000000) cp = 5; + else if (tuner_frequency < 895000000) cp = 7; + else return -EINVAL; + + // determine band + if (params->frequency < 49000000) return -EINVAL; + else if (params->frequency < 159000000) band = 1; + else if (params->frequency < 444000000) band = 2; + else if (params->frequency < 861000000) band = 4; + else return -EINVAL; + + // setup PLL filter + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + tda1004x_write_byte(fe, 0x0C, 0); + filter = 0; + break; + + case BANDWIDTH_7_MHZ: + tda1004x_write_byte(fe, 0x0C, 0); + filter = 0; + break; + + case BANDWIDTH_8_MHZ: + tda1004x_write_byte(fe, 0x0C, 0xFF); + filter = 1; + break; + + default: + return -EINVAL; + } - if (client->driver->command) - return client->driver->command(client, FE_REGISTER, ttusb->adapter); + // calculate divisor + // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6) + tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000; + + // setup tuner buffer + tuner_buf[0] = tuner_frequency >> 8; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0xca; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; + if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + + msleep(1); return 0; } -static int client_unregister(struct i2c_client *client) +static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + + return request_firmware(fw, name, &ttusb->dev->dev); +} + +static struct tda1004x_config philips_tdm1316l_config = { + + .demod_address = 0x8, + .invert = 1, + .invert_oclk = 0, + .pll_init = philips_tdm1316l_pll_init, + .pll_set = philips_tdm1316l_pll_set, + .request_firmware = philips_tdm1316l_request_firmware, +}; + + +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) { - struct ttusb *ttusb = (struct ttusb*)i2c_get_adapdata(client->adapter); + u8 aclk = 0; + u8 bclk = 0; - if (client->driver->command) - return client->driver->command(client, FE_UNREGISTER, ttusb->adapter); + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio) & 0xf0); return 0; } +static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0xC4; + + if (params->frequency > 1530000) + buf[3] = 0xc0; + + if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) + return -EIO; + + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + +static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + div = params->frequency / 125; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x8e; + buf[3] = 0x00; + + if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) + return -EIO; + + return 0; +} + +static struct tda8083_config ttusb_novas_grundig_29504_491_config = { + + .demod_address = 0x68, + .pll_set = ttusb_novas_grundig_29504_491_pll_set, +}; + + + +static void frontend_init(struct ttusb* ttusb) +{ + switch(ttusb->dev->descriptor.idProduct) { + case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6(tsa5059) + // try the ALPS BSRU6 first + ttusb->fe = stv0299_attach(&alps_bsru6_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) { + ttusb->fe->ops->set_voltage = ttusb_set_voltage; + break; + } + + // Grundig 29504-491 + ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) { + ttusb->fe->ops->set_voltage = ttusb_set_voltage; + break; + } + + break; + + case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??)) + // try the ALPS TDMB7 first + ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) + break; + + // Philips td1316 + ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) + break; + break; + } + + if (ttusb->fe == NULL) { + printk("dvb-ttusb-budget: A frontend driver was not found for device %04x/%04x\n", + ttusb->dev->descriptor.idVendor, + ttusb->dev->descriptor.idProduct); + } else { + if (dvb_register_frontend(ttusb->adapter, ttusb->fe)) { + printk("dvb-ttusb-budget: Frontend registration failed!\n"); + if (ttusb->fe->ops->release) + ttusb->fe->ops->release(ttusb->fe); + ttusb->fe = NULL; + } + } +} + + + +static struct i2c_algorithm ttusb_dec_algo = { + .name = "ttusb dec i2c algorithm", + .id = I2C_ALGO_BIT, + .master_xfer = master_xfer, + .functionality = functionality, +}; + static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev; @@ -1140,6 +1439,7 @@ up(&ttusb->sem); dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE); + ttusb->adapter->priv = ttusb; /* i2c */ memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter)); @@ -1155,8 +1455,6 @@ ttusb->i2c_adap.algo = &ttusb_dec_algo; ttusb->i2c_adap.algo_data = NULL; ttusb->i2c_adap.id = I2C_ALGO_BIT; - ttusb->i2c_adap.client_register = client_register; - ttusb->i2c_adap.client_unregister = client_unregister; result = i2c_add_adapter(&ttusb->i2c_adap); if (result) { @@ -1164,9 +1462,6 @@ return result; } - dvb_add_frontend_ioctls(ttusb->adapter, ttusb_lnb_ioctl, NULL, - ttusb); - memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux)); ttusb->dvb_demux.dmx.capabilities = @@ -1218,9 +1513,10 @@ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &stc_fops, ttusb); #endif - usb_set_intfdata(intf, (void *) ttusb); + frontend_init(ttusb); + return 0; } @@ -1238,7 +1534,7 @@ dvb_net_release(&ttusb->dvbnet); dvb_dmxdev_release(&ttusb->dmxdev); dvb_dmx_release(&ttusb->dvb_demux); - + if (ttusb->fe != NULL) dvb_unregister_frontend(ttusb->fe); i2c_del_adapter(&ttusb->i2c_adap); dvb_unregister_adapter(ttusb->adapter); @@ -1251,7 +1547,7 @@ static struct usb_device_id ttusb_table[] = { {USB_DEVICE(0xb48, 0x1003)}, - {USB_DEVICE(0xb48, 0x1004)}, /* to be confirmed ???? */ +/* {USB_DEVICE(0xb48, 0x1004)},UNDEFINED HARDWARE - mail linuxtv.org list*/ /* to be confirmed ???? */ {USB_DEVICE(0xb48, 0x1005)}, {} }; Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h 2004-12-22 09:07:08.913366842 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h 2004-12-22 10:04:35.998330274 -0800 @@ -1,7 +1,7 @@ #include -u8 dsp_bootcode [] = { +static u8 dsp_bootcode [] = { 0x08, 0xaa, 0x00, 0x18, 0x00, 0x03, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x80, 0x18, 0x5f, 0x00, 0x00, 0x01, 0x80, 0x77, 0x18, 0x2a, 0xeb, Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-dec/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttusb-dec/Makefile 2004-12-22 09:07:08.914366690 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-dec/Makefile 2004-12-22 10:04:35.999330122 -0800 @@ -1,3 +1,3 @@ -obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o +obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ Index: wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-dec/ttusb_dec.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/dvb/ttusb-dec/ttusb_dec.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/dvb/ttusb-dec/ttusb_dec.c 2004-12-22 10:04:36.011328298 -0800 @@ -30,11 +30,7 @@ #include #include #include -#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE) #include -#else -#warning "CRC checking of firmware not available" -#endif #include #include "dmxdev.h" @@ -42,6 +38,7 @@ #include "dvb_filter.h" #include "dvb_frontend.h" #include "dvb_net.h" +#include "ttusbdecfe.h" static int debug; static int output_pva; @@ -69,9 +66,6 @@ #define MAX_PVA_LENGTH 6144 -#define LOF_HI 10600000 -#define LOF_LO 9750000 - enum ttusb_dec_model { TTUSB_DEC2000T, TTUSB_DEC2540T, @@ -102,12 +96,9 @@ struct dvb_demux demux; struct dmx_frontend frontend; struct dvb_net dvb_net; - struct dvb_frontend_info *frontend_info; - int (*frontend_ioctl) (struct dvb_frontend *, unsigned int, void *); + struct dvb_frontend* fe; u16 pid[DMX_PES_OTHER]; - int hi_band; - int voltage; /* USB bits */ struct usb_device *udev; @@ -166,32 +157,6 @@ struct list_head filter_info_list; }; -static struct dvb_frontend_info dec2000t_frontend_info = { - .name = "TechnoTrend/Hauppauge DEC2000-t Frontend", - .type = FE_OFDM, - .frequency_min = 51000000, - .frequency_max = 858000000, - .frequency_stepsize = 62500, - .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_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; - -static struct dvb_frontend_info dec3000s_frontend_info = { - .name = "TechnoTrend/Hauppauge DEC3000-s Frontend", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 125, - .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_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; - static void ttusb_dec_set_model(struct ttusb_dec *dec, enum ttusb_dec_model model); @@ -1170,10 +1135,9 @@ u16 firmware_csum = 0; u16 firmware_csum_ns; u32 firmware_size_nl; -#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE) u32 crc32_csum, crc32_check, tmp; -#endif const struct firmware *fw_entry = NULL; + dprintk("%s\n", __FUNCTION__); if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) { @@ -1194,7 +1158,6 @@ /* a 32 bit checksum over the first 56 bytes of the DSP Code is stored at offset 56 of file, so use it to check if the firmware file is valid. */ -#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE) crc32_csum = crc32(~0L, firmware, 56) ^ ~0L; memcpy(&tmp, &firmware[56], 4); crc32_check = htonl(tmp); @@ -1204,7 +1167,6 @@ __FUNCTION__, crc32_csum, crc32_check); return -1; } -#endif memcpy(idstring, &firmware[36], 20); idstring[20] = '\0'; printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring); @@ -1404,6 +1366,7 @@ dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); dvb_dmxdev_release(&dec->dmxdev); dvb_dmx_release(&dec->demux); + if (dec->fe) dvb_unregister_frontend(dec->fe); dvb_unregister_adapter(dec->adapter); } @@ -1435,264 +1398,6 @@ } } -static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd, - void *arg) -{ - struct ttusb_dec *dec = fe->data; - - dprintk("%s\n", __FUNCTION__); - - switch (cmd) { - - case FE_GET_INFO: - dprintk("%s: FE_GET_INFO\n", __FUNCTION__); - memcpy(arg, dec->frontend_info, - sizeof (struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: { - fe_status_t *status = (fe_status_t *)arg; - dprintk("%s: FE_READ_STATUS\n", __FUNCTION__); - *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | - FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; - break; - } - - case FE_READ_BER: { - u32 *ber = (u32 *)arg; - dprintk("%s: FE_READ_BER\n", __FUNCTION__); - *ber = 0; - return -ENOSYS; - break; - } - - case FE_READ_SIGNAL_STRENGTH: { - dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__); - *(s32 *)arg = 0xFF; - return -ENOSYS; - break; - } - - case FE_READ_SNR: - dprintk("%s: FE_READ_SNR\n", __FUNCTION__); - *(s32 *)arg = 0; - return -ENOSYS; - break; - - case FE_READ_UNCORRECTED_BLOCKS: - dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__); - *(u32 *)arg = 0; - return -ENOSYS; - break; - - case FE_SET_FRONTEND: { - struct dvb_frontend_parameters *p = - (struct dvb_frontend_parameters *)arg; - u8 b[] = { 0x00, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff }; - u32 freq; - - dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__); - - dprintk(" frequency->%d\n", p->frequency); - dprintk(" symbol_rate->%d\n", - p->u.qam.symbol_rate); - dprintk(" inversion->%d\n", p->inversion); - - freq = htonl(p->frequency / 1000); - memcpy(&b[4], &freq, sizeof (u32)); - ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL); - - break; - } - - case FE_GET_FRONTEND: - dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__); - break; - - case FE_SLEEP: - dprintk("%s: FE_SLEEP\n", __FUNCTION__); - return -ENOSYS; - break; - - case FE_INIT: - dprintk("%s: FE_INIT\n", __FUNCTION__); - break; - - default: - dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd); - return -EINVAL; - - } - - return 0; -} - -static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, - unsigned int cmd, void *arg) -{ - struct ttusb_dec *dec = fe->data; - - dprintk("%s\n", __FUNCTION__); - - switch (cmd) { - - case FE_GET_INFO: - dprintk("%s: FE_GET_INFO\n", __FUNCTION__); - memcpy(arg, dec->frontend_info, - sizeof (struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: { - fe_status_t *status = (fe_status_t *)arg; - dprintk("%s: FE_READ_STATUS\n", __FUNCTION__); - *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | - FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; - break; - } - - case FE_READ_BER: { - u32 *ber = (u32 *)arg; - dprintk("%s: FE_READ_BER\n", __FUNCTION__); - *ber = 0; - return -ENOSYS; - break; - } - - case FE_READ_SIGNAL_STRENGTH: { - dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__); - *(s32 *)arg = 0xFF; - return -ENOSYS; - break; - } - - case FE_READ_SNR: - dprintk("%s: FE_READ_SNR\n", __FUNCTION__); - *(s32 *)arg = 0; - return -ENOSYS; - break; - - case FE_READ_UNCORRECTED_BLOCKS: - dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__); - *(u32 *)arg = 0; - return -ENOSYS; - break; - - case FE_SET_FRONTEND: { - struct dvb_frontend_parameters *p = - (struct dvb_frontend_parameters *)arg; - u8 b[] = { 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }; - u32 freq; - u32 sym_rate; - u32 band; - u32 lnb_voltage; - - dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__); - - dprintk(" frequency->%d\n", p->frequency); - dprintk(" symbol_rate->%d\n", - p->u.qam.symbol_rate); - dprintk(" inversion->%d\n", p->inversion); - - freq = htonl(p->frequency + - (dec->hi_band ? LOF_HI : LOF_LO)); - memcpy(&b[4], &freq, sizeof(u32)); - sym_rate = htonl(p->u.qam.symbol_rate); - memcpy(&b[12], &sym_rate, sizeof(u32)); - band = htonl(dec->hi_band ? LOF_HI : LOF_LO); - memcpy(&b[24], &band, sizeof(u32)); - lnb_voltage = htonl(dec->voltage); - memcpy(&b[28], &lnb_voltage, sizeof(u32)); - - ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL); - - break; - } - - case FE_GET_FRONTEND: - dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__); - break; - - case FE_SLEEP: - dprintk("%s: FE_SLEEP\n", __FUNCTION__); - return -ENOSYS; - break; - - case FE_INIT: - dprintk("%s: FE_INIT\n", __FUNCTION__); - break; - - case FE_DISEQC_SEND_MASTER_CMD: { - u8 b[] = { 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 }; - struct dvb_diseqc_master_cmd *cmd = arg; - memcpy(&b[4], cmd->msg, cmd->msg_len); - dprintk("%s: FE_DISEQC_SEND_MASTER_CMD\n", __FUNCTION__); - ttusb_dec_send_command(dec, 0x72, - sizeof(b) - (6 - cmd->msg_len), b, - NULL, NULL); - break; - } - - case FE_DISEQC_SEND_BURST: - dprintk("%s: FE_DISEQC_SEND_BURST\n", __FUNCTION__); - break; - - case FE_SET_TONE: { - fe_sec_tone_mode_t tone = (fe_sec_tone_mode_t)arg; - dprintk("%s: FE_SET_TONE\n", __FUNCTION__); - dec->hi_band = (SEC_TONE_ON == tone); - break; - } - - case FE_SET_VOLTAGE: - dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__); - switch ((fe_sec_voltage_t) arg) { - case SEC_VOLTAGE_13: - dec->voltage = 13; - break; - case SEC_VOLTAGE_18: - dec->voltage = 18; - break; - default: - return -EINVAL; - break; - } - break; - - default: - dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd); - return -EINVAL; - - } - - return 0; -} - -static void ttusb_dec_init_frontend(struct ttusb_dec *dec) -{ - int ret; - ret = dvb_register_frontend(dec->frontend_ioctl, dec->adapter, dec, dec->frontend_info, THIS_MODULE); -} - -static void ttusb_dec_exit_frontend(struct ttusb_dec *dec) -{ - dvb_unregister_frontend(dec->frontend_ioctl, dec->adapter); -} - static void ttusb_dec_init_filters(struct ttusb_dec *dec) { INIT_LIST_HEAD(&dec->filter_info_list); @@ -1711,6 +1416,18 @@ } } +int fe_send_command(struct dvb_frontend* fe, const u8 command, + int param_length, const u8 params[], + int *result_length, u8 cmd_result[]) +{ + struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv; + return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result); +} + +struct ttusbdecfe_config fe_config = { + .send_command = fe_send_command +}; + static int ttusb_dec_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -1752,7 +1469,32 @@ return 0; } ttusb_dec_init_dvb(dec); - ttusb_dec_init_frontend(dec); + + dec->adapter->priv = dec; + switch (id->idProduct) { + case 0x1006: + dec->fe = ttusbdecfe_dvbs_attach(&fe_config); + break; + + case 0x1008: + case 0x1009: + dec->fe = ttusbdecfe_dvbt_attach(&fe_config); + break; + } + + if (dec->fe == NULL) { + printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n", + dec->udev->descriptor.idVendor, + dec->udev->descriptor.idProduct); + } else { + if (dvb_register_frontend(dec->adapter, dec->fe)) { + printk("budget-ci: Frontend registration failed!\n"); + if (dec->fe->ops->release) + dec->fe->ops->release(dec->fe); + dec->fe = NULL; + } + } + ttusb_dec_init_v_pes(dec); ttusb_dec_init_filters(dec); ttusb_dec_init_tasklet(dec); @@ -1776,7 +1518,6 @@ ttusb_dec_exit_tasklet(dec); ttusb_dec_exit_filters(dec); ttusb_dec_exit_usb(dec); - ttusb_dec_exit_frontend(dec); ttusb_dec_exit_dvb(dec); } @@ -1792,22 +1533,16 @@ case TTUSB_DEC2000T: dec->model_name = "DEC2000-t"; dec->firmware_name = "dvb-ttusb-dec-2000t.fw"; - dec->frontend_info = &dec2000t_frontend_info; - dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl; break; case TTUSB_DEC2540T: dec->model_name = "DEC2540-t"; dec->firmware_name = "dvb-ttusb-dec-2540t.fw"; - dec->frontend_info = &dec2000t_frontend_info; - dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl; break; case TTUSB_DEC3000S: dec->model_name = "DEC3000-s"; dec->firmware_name = "dvb-ttusb-dec-3000s.fw"; - dec->frontend_info = &dec3000s_frontend_info; - dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl; break; } } Index: wli-2.6.10-rc3-1/drivers/media/video/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/video/Kconfig 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/video/Kconfig 2004-12-22 10:04:36.014327842 -0800 @@ -220,7 +220,7 @@ config VIDEO_MEYE tristate "Sony Vaio Picturebook Motion Eye Video For Linux" - depends on VIDEO_DEV && PCI && SONYPI && !HIGHMEM64G + depends on VIDEO_DEV && PCI && SONYPI ---help--- This is the video4linux driver for the Motion Eye camera found in the Vaio Picturebook laptops. Please read the material in Index: wli-2.6.10-rc3-1/drivers/media/video/meye.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/video/meye.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/video/meye.c 2004-12-22 10:04:36.022326626 -0800 @@ -110,19 +110,20 @@ /* * return a page table pointing to N pages of locked memory * - * NOTE: The meye device expects dma_addr_t size to be 32 bits - * (the toc must be exactly 1024 entries each of them being 4 bytes - * in size, the whole result being 4096 bytes). We're using here - * dma_addr_t for correctness but the compilation of this driver is - * disabled for HIGHMEM64G=y, where sizeof(dma_addr_t) != 4 + * NOTE: The meye device expects DMA addresses on 32 bits, we build + * a table of 1024 entries = 4 bytes * 1024 = 4096 bytes. */ static int ptable_alloc(void) { - dma_addr_t *pt; + u32 *pt; int i; memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable)); + /* give only 32 bit DMA addresses */ + if (dma_set_mask(&meye.mchip_dev->dev, 0xffffffff)) + return -1; + meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev, PAGE_SIZE, &meye.mchip_dmahandle, @@ -134,17 +135,19 @@ pt = meye.mchip_ptable_toc; for (i = 0; i < MCHIP_NB_PAGES; i++) { + dma_addr_t dma; meye.mchip_ptable[i] = dma_alloc_coherent(&meye.mchip_dev->dev, PAGE_SIZE, - pt, + &dma, GFP_KERNEL); if (!meye.mchip_ptable[i]) { int j; pt = meye.mchip_ptable_toc; for (j = 0; j < i; ++j) { + dma = (dma_addr_t) *pt; dma_free_coherent(&meye.mchip_dev->dev, PAGE_SIZE, - meye.mchip_ptable[j], *pt); + meye.mchip_ptable[j], dma); pt++; } dma_free_coherent(&meye.mchip_dev->dev, @@ -155,6 +158,7 @@ meye.mchip_dmahandle = 0; return -1; } + *pt = (u32) dma; pt++; } return 0; @@ -162,15 +166,16 @@ static void ptable_free(void) { - dma_addr_t *pt; + u32 *pt; int i; pt = meye.mchip_ptable_toc; for (i = 0; i < MCHIP_NB_PAGES; i++) { + dma_addr_t dma = (dma_addr_t) *pt; if (meye.mchip_ptable[i]) dma_free_coherent(&meye.mchip_dev->dev, PAGE_SIZE, - meye.mchip_ptable[i], *pt); + meye.mchip_ptable[i], dma); pt++; } @@ -520,11 +525,11 @@ } /* sets the DMA parameters into the chip */ -static void mchip_dma_setup(u32 dma_addr) +static void mchip_dma_setup(dma_addr_t dma_addr) { int i; - mchip_set(MCHIP_MM_PT_ADDR, dma_addr); + mchip_set(MCHIP_MM_PT_ADDR, (u32)dma_addr); for (i = 0; i < 4; i++) mchip_set(MCHIP_MM_FIR(i), 0); meye.mchip_fnum = 0; Index: wli-2.6.10-rc3-1/drivers/media/video/meye.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/video/meye.h 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/video/meye.h 2004-12-22 10:04:36.025326170 -0800 @@ -31,7 +31,7 @@ #define _MEYE_PRIV_H_ #define MEYE_DRIVER_MAJORVERSION 1 -#define MEYE_DRIVER_MINORVERSION 12 +#define MEYE_DRIVER_MINORVERSION 13 #define MEYE_DRIVER_VERSION __stringify(MEYE_DRIVER_MAJORVERSION) "." \ __stringify(MEYE_DRIVER_MINORVERSION) @@ -294,7 +294,7 @@ u8 mchip_fnum; /* current mchip frame number */ unsigned char __iomem *mchip_mmregs;/* mchip: memory mapped registers */ u8 *mchip_ptable[MCHIP_NB_PAGES];/* mchip: ptable */ - dma_addr_t *mchip_ptable_toc; /* mchip: ptable toc */ + void *mchip_ptable_toc; /* mchip: ptable toc */ dma_addr_t mchip_dmahandle; /* mchip: dma handle to ptable toc */ unsigned char *grab_fbuffer; /* capture framebuffer */ unsigned char *grab_temp; /* temporary buffer */ Index: wli-2.6.10-rc3-1/drivers/media/video/msp3400.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/video/msp3400.c 2004-12-16 06:19:35.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/video/msp3400.c 2004-12-22 10:04:36.031325258 -0800 @@ -1511,9 +1511,12 @@ msp->opmode = opmode; if (OPMODE_AUTO == msp->opmode) { +#if 0 /* seems to work for ivtv only, disable by default for now ... */ if (HAVE_SIMPLER(msp)) msp->opmode = OPMODE_SIMPLER; - else if (HAVE_SIMPLE(msp)) + else +#endif + if (HAVE_SIMPLE(msp)) msp->opmode = OPMODE_SIMPLE; else msp->opmode = OPMODE_MANUAL; Index: wli-2.6.10-rc3-1/drivers/media/video/saa7134/saa7134-core.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/media/video/saa7134/saa7134-core.c 2004-12-16 06:19:36.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/media/video/saa7134/saa7134-core.c 2004-12-22 10:04:36.037324346 -0800 @@ -87,7 +87,7 @@ static DECLARE_MUTEX(devlist_lock); LIST_HEAD(saa7134_devlist); static LIST_HEAD(mops_list); -static unsigned int saa7134_devcount; +unsigned int saa7134_devcount; #define dprintk(fmt, arg...) if (core_debug) \ printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) Index: wli-2.6.10-rc3-1/drivers/message/fusion/mptbase.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/message/fusion/mptbase.c 2004-12-16 06:19:36.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/message/fusion/mptbase.c 2004-12-22 10:04:36.060320850 -0800 @@ -155,7 +155,6 @@ static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]; -static int FusionInitCalled = 0; static int mpt_base_index = -1; static int last_drv_idx = -1; @@ -337,15 +336,13 @@ ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); - if ((int)ioc->chip_type <= (int)FC929) + if (ioc->bus_type == FC) mpt_fc_log_info(ioc, log_info); - else + else if (ioc->bus_type == SCSI) mpt_sp_log_info(ioc, log_info); } if (ioc_stat & MPI_IOCSTATUS_MASK) { - if ((int)ioc->chip_type <= (int)FC929) - ; - else + if (ioc->bus_type == SCSI) mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); } } else { @@ -392,7 +389,7 @@ } #ifdef MPT_DEBUG_IRQ - if ((int)ioc->chip_type > (int)FC929) { + if (ioc->bus_type == SCSI) { /* Verify mf, mr are reasonable. */ if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth)) @@ -603,22 +600,6 @@ last_drv_idx = -1; -#ifndef MODULE - /* - * Handle possibility of the mptscsih_detect() routine getting - * called *before* fusion_init! - */ - if (!FusionInitCalled) { - dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n")); - /* - * NOTE! We'll get recursion here, as fusion_init() - * calls mpt_register()! - */ - fusion_init(); - FusionInitCalled++; - } -#endif - /* * Search for empty callback slot in this order: {N,...,7,6,5,...,1} * (slot/handle 0 is reserved!) @@ -1220,22 +1201,21 @@ ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; } - ioc->chip_type = FCUNK; if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) { - ioc->chip_type = FC909; ioc->prod_name = "LSIFC909"; + ioc->bus_type = FC; } if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { - ioc->chip_type = FC929; ioc->prod_name = "LSIFC929"; + ioc->bus_type = FC; } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) { - ioc->chip_type = FC919; ioc->prod_name = "LSIFC919"; + ioc->bus_type = FC; } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) { - ioc->chip_type = FC929X; pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + ioc->bus_type = FC; if (revision < XL_929) { ioc->prod_name = "LSIFC929X"; /* 929X Chip Fix. Set Split transactions level @@ -1254,8 +1234,8 @@ } } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) { - ioc->chip_type = FC919X; ioc->prod_name = "LSIFC919X"; + ioc->bus_type = FC; /* 919X Chip Fix. Set Split transactions level * for PCIX. Set MOST bits to zero. */ @@ -1264,8 +1244,8 @@ pci_write_config_byte(pdev, 0x6a, pcixcmd); } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { - ioc->chip_type = C1030; ioc->prod_name = "LSI53C1030"; + ioc->bus_type = SCSI; /* 1030 Chip Fix. Disable Split transactions * for PCIX. Set MOST bits to zero if Rev < C0( = 8). */ @@ -1277,8 +1257,8 @@ } } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { - ioc->chip_type = C1035; ioc->prod_name = "LSI53C1035"; + ioc->bus_type = SCSI; } sprintf(ioc->name, "ioc%d", ioc->id); @@ -1326,9 +1306,7 @@ /* NEW! 20010220 -sralston * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. */ - if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) - || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X)) - mpt_detect_bound_ports(ioc, pdev); + mpt_detect_bound_ports(ioc, pdev); if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { @@ -1760,7 +1738,7 @@ * and we try GetLanConfigPages again... */ if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { - if ((int)ioc->chip_type <= (int)FC929) { + if (ioc->bus_type == FC) { /* * Pre-fetch FC port WWN and stuff... * (FCPortPage0_t stuff) @@ -2103,20 +2081,8 @@ } /* Is it already READY? */ - if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) { - if ((int)ioc->chip_type <= (int)FC929) - return 0; - else { - return 0; - /* Workaround from broken 1030 FW. - * Force a diagnostic reset if fails. - */ -/* if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) - return 0; - else - statefault = 4; */ - } - } + if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) + return 0; /* * Check to see if IOC is in FAULT state. @@ -2513,11 +2479,11 @@ ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", ioc->name, ioc->upload_fw, ioc->facts.Flags)); - if ((int)ioc->chip_type <= (int)FC929) { + if (ioc->bus_type == FC) ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; - } else { + else ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; - } + ioc_init.MaxBuses = MPT_MAX_BUS; ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ @@ -2622,7 +2588,7 @@ /* RAID FW may take a long time to enable */ - if ((int)ioc->chip_type <= (int)FC929) { + if (ioc->bus_type == FC) { ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag); } else { @@ -2992,7 +2958,7 @@ int cnt,cntdn; dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); - if ((int)ioc->chip_type > (int)FC929) { + if (ioc->bus_type == SCSI) { /* Always issue a Msg Unit Reset first. This will clear some * SCSI bus hang conditions. */ @@ -3420,7 +3386,7 @@ dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n", ioc->name, numSGE, num_sge, num_chain)); - if ((int) ioc->chip_type > (int) FC929) + if (ioc->bus_type == SCSI) num_chain *= MPT_SCSI_CAN_QUEUE; else num_chain *= MPT_FC_CAN_QUEUE; @@ -5277,7 +5243,7 @@ len += sprintf(buf+len, " PortNumber = %d (of %d)\n", p+1, ioc->facts.NumberOfPorts); - if ((int)ioc->chip_type <= (int)FC929) { + if (ioc->bus_type == FC) { if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", @@ -5921,11 +5887,6 @@ int i; int r; - if (FusionInitCalled++) { - dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n")); - return 0; - } - show_mptmod_ver(my_NAME, my_VERSION); printk(KERN_INFO COPYRIGHT "\n"); Index: wli-2.6.10-rc3-1/drivers/message/fusion/mptbase.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/message/fusion/mptbase.h 2004-12-16 06:19:36.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/message/fusion/mptbase.h 2004-12-22 10:04:36.065320090 -0800 @@ -83,8 +83,8 @@ #define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.01.17" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.17" +#define MPT_LINUX_VERSION_COMMON "3.01.18" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.18" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -296,23 +296,6 @@ SGESimple64_t sge[1]; } MPT_SGL64_HDR; - -/* - * Chip-specific stuff... FC929 delineates break between - * FC and Parallel SCSI parts. Do NOT re-order. - */ - -typedef enum { - FC919X = 0x0819, - FC929X = 0x0829, - FC909 = 0x0909, - FC919 = 0x0919, - FC929 = 0x0929, - C1030 = 0x1030, - C1035 = 0x1035, - FCUNK = 0xFBAD -} CHIP_TYPE; - /* * System interface register set */ @@ -517,6 +500,7 @@ char *prod_name; /* "LSIFC9x9" */ SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */ SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */ + u8 bus_type; u32 mem_phys; /* == f4020000 (mmap) */ u32 pio_mem_phys; /* Programmed IO (downloadboot) */ int mem_size; /* mmap memory size */ @@ -543,7 +527,6 @@ dma_addr_t ChainBufferDMA; struct list_head FreeChainQ; spinlock_t FreeChainQlock; - CHIP_TYPE chip_type; /* We (host driver) get to manage our own RequestQueue! */ dma_addr_t req_frames_dma; MPT_FRAME_HDR *req_frames; /* Request msg frames - rounded up! */ @@ -573,12 +556,6 @@ int eventTypes; /* Event logging parameters */ int eventContext; /* Next event context */ int eventLogSize; /* Max number of cached events */ -#ifdef MPTSCSIH_DBG_TIMEOUT - int timeout_hard; - int timeout_delta; - int timeout_cnt; - int timeout_maxcnt; -#endif struct _mpt_ioctl_events *events; /* pointer to event log */ u8 *cached_fw; /* Pointer to FW */ dma_addr_t cached_fw_dma; @@ -894,6 +871,12 @@ #define TM_STATE_IN_PROGRESS (1) #define TM_STATE_ERROR (2) +typedef enum { + FC, + SCSI, + SAS +} BUS_TYPE; + typedef struct _MPT_SCSI_HOST { MPT_ADAPTER *ioc; int port; @@ -909,7 +892,6 @@ */ u8 tmPending; u8 resetPending; - u8 is_spi; /* Parallel SCSI i/f */ u8 negoNvram; /* DV disabled, nego NVRAM */ u8 pad1; u8 tmState; Index: wli-2.6.10-rc3-1/drivers/message/fusion/mptctl.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/message/fusion/mptctl.c 2004-12-22 09:07:08.966358786 -0800 +++ wli-2.6.10-rc3-1/drivers/message/fusion/mptctl.c 2004-12-22 10:04:36.076318418 -0800 @@ -1218,7 +1218,7 @@ /* Fill in the data and return the structure to the calling * program */ - if ((int)ioc->chip_type <= (int) FC929) + if (ioc->bus_type == FC) karg->adapterType = MPT_IOCTL_INTERFACE_FC; else karg->adapterType = MPT_IOCTL_INTERFACE_SCSI; @@ -1518,7 +1518,7 @@ #ifdef MFCNT karg.chip_type = ioc->mfcnt; #else - karg.chip_type = ioc->chip_type; + karg.chip_type = ioc->pcidev->device; #endif strncpy (karg.name, ioc->name, MPT_MAX_NAME); karg.name[MPT_MAX_NAME-1]='\0'; @@ -2470,7 +2470,7 @@ karg.base_io_addr = pci_resource_start(pdev, 0); - if ((int)ioc->chip_type <= (int) FC929) + if (ioc->bus_type == FC) karg.bus_phys_width = HP_BUS_WIDTH_UNK; else karg.bus_phys_width = HP_BUS_WIDTH_16; @@ -2559,7 +2559,7 @@ /* There is nothing to do for FCP parts. */ - if ((int) ioc->chip_type <= (int) FC929) + if (ioc->bus_type == FC) return 0; if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL)) Index: wli-2.6.10-rc3-1/drivers/message/fusion/mptscsih.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/message/fusion/mptscsih.c 2004-12-16 06:19:36.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/message/fusion/mptscsih.c 2004-12-22 10:04:36.108313554 -0800 @@ -96,10 +96,22 @@ MODULE_DESCRIPTION(my_NAME); MODULE_LICENSE("GPL"); -/* Set string for command line args from insmod */ #ifdef MODULE -char *mptscsih = NULL; -module_param(mptscsih, charp, 0); +static int dv = MPTSCSIH_DOMAIN_VALIDATION; +module_param(dv, int, 0); +MODULE_PARM_DESC(dv, "DV Algorithm: enhanced = 1, basic = 0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)"); + +static int width = MPTSCSIH_MAX_WIDTH; +module_param(width, int, 0); +MODULE_PARM_DESC(width, "Max Bus Width: wide = 1, narrow = 0 (default=MPTSCSIH_MAX_WIDTH=1)"); + +static ushort factor = MPTSCSIH_MIN_SYNC; +module_param(factor, ushort, 0); +MODULE_PARM_DESC(factor, "Min Sync Factor: (default=MPTSCSIH_MIN_SYNC=0x08)"); + +static int saf_te = MPTSCSIH_SAF_TE; +module_param(saf_te, int, 0); +MODULE_PARM_DESC(saf_te, "Force enabling SEP Processor: (default=MPTSCSIH_SAF_TE=0)"); #endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -200,9 +212,6 @@ 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); #endif -#ifdef MODULE -static int mptscsih_setup(char *str); -#endif /* module entry point */ static int __init mptscsih_init (void); static void __exit mptscsih_exit (void); @@ -245,15 +254,9 @@ static int scandv_wait_done = 1; -/* Driver default setup +/* Driver command line structure */ -static struct mptscsih_driver_setup - driver_setup = MPTSCSIH_DRIVER_SETUP; - -#ifdef MPTSCSIH_DBG_TIMEOUT -static struct scsi_cmnd *foo_to[8]; -#endif - +static struct mptscsih_driver_setup driver_setup; static struct scsi_host_template driver_template; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -653,27 +656,6 @@ pScsiReq = (SCSIIORequest_t *) mf; pScsiReply = (SCSIIOReply_t *) mr; -#ifdef MPTSCSIH_DBG_TIMEOUT - if (ioc->timeout_cnt > 0) { - int ii, left = 0; - - for (ii=0; ii < 8; ii++) { - if (sc == foo_to[ii]) { - printk(MYIOC_s_INFO_FMT "complete (%p, %ld)\n", - ioc->name, sc, jiffies); - foo_to[ii] = NULL; - } - if (foo_to[ii] != NULL) - left++; - } - - if (left == 0) { - ioc->timeout_maxcnt = 0; - ioc->timeout_cnt = 0; - } - } -#endif - if (pScsiReply == NULL) { /* special context reply handling */ ; @@ -686,13 +668,14 @@ scsi_state = pScsiReply->SCSIState; scsi_status = pScsiReply->SCSIStatus; xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); + sc->resid = sc->request_bufflen - xfer_cnt; - dreplyprintk((KERN_NOTICE " Reply (%d:%d:%d) mf=%p, mr=%p, sc=%p\n", - ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], - mf, mr, sc)); - dreplyprintk((KERN_NOTICE "IOCStatus=%04xh SCSIState=%02xh" - " SCSIStatus=%02xh xfer_cnt=%08xh\n", - status, scsi_state, scsi_status, xfer_cnt)); + dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" + "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n" + "resid=%d bufflen=%d xfer_cnt=%d\n", + ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], + status, scsi_state, scsi_status, sc->resid, + sc->request_bufflen, xfer_cnt)); if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) copy_sense_data(sc, hd, mf, pScsiReply); @@ -737,12 +720,11 @@ sc->result = DID_RESET << 16; /* GEM Workaround. */ - if (hd->is_spi) + if (ioc->bus_type == SCSI) mptscsih_no_negotiate(hd, sc->device->id); break; case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ - sc->resid = sc->request_bufflen - xfer_cnt; if ( xfer_cnt >= sc->underflow ) { /* Sufficient data transfer occurred */ sc->result = (DID_OK << 16) | scsi_status; @@ -771,7 +753,7 @@ */ ; } else { - if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) { + if (xfer_cnt < sc->underflow) { sc->result = DID_SOFT_ERROR << 16; } if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { @@ -785,15 +767,9 @@ } } - /* Give report and update residual count. - */ dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", sc->underflow)); dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt)); - - sc->resid = sc->request_bufflen - xfer_cnt; - dreplyprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid)); - /* Report Queue Full */ if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL) @@ -848,7 +824,7 @@ break; case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ - sc->result = DID_SOFT_ERROR << 16; + sc->result = DID_SOFT_ERROR << 16; break; case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ @@ -1132,7 +1108,7 @@ * max_lun = 1 + actual last lun, * see hosts.h :o( */ - if ((int)ioc->chip_type > (int)FC929) { + if (ioc->bus_type == SCSI) { sh->max_id = MPT_MAX_SCSI_DEVICES; } else { /* For FC, increase the queue depth @@ -1191,9 +1167,6 @@ hd = (MPT_SCSI_HOST *) sh->hostdata; hd->ioc = ioc; - if ((int)ioc->chip_type > (int)FC929) - hd->is_spi = 1; - /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ @@ -1259,15 +1232,7 @@ /* Moved Earlier Pam D */ /* ioc->sh = sh; */ -#ifdef MPTSCSIH_DBG_TIMEOUT - ioc->timeout_hard = 0; - ioc->timeout_delta = 30 * HZ; - ioc->timeout_maxcnt = 0; - ioc->timeout_cnt = 0; - for (ii=0; ii < 8; ii++) - foo_to[ii] = NULL; -#endif - if (hd->is_spi) { + if (ioc->bus_type == SCSI) { /* Update with the driver setup * values. */ @@ -1278,9 +1243,9 @@ } if (ioc->spi_data.minSyncFactor < - driver_setup.min_sync_fac) { + driver_setup.min_sync_factor) { ioc->spi_data.minSyncFactor = - driver_setup.min_sync_fac; + driver_setup.min_sync_factor; } if (ioc->spi_data.minSyncFactor == MPT_ASYNC) { @@ -1307,7 +1272,7 @@ "dv %x width %x factor %x saf_te %x\n", ioc->name, driver_setup.dv, driver_setup.max_width, - driver_setup.min_sync_fac, + driver_setup.min_sync_factor, driver_setup.saf_te)); } @@ -1374,11 +1339,11 @@ hd = (MPT_SCSI_HOST *)host->hostdata; if (hd != NULL) { - int sz1, sz3, sztarget=0; + int sz1; mptscsih_shutdown(&pdev->dev); - sz1 = sz3 = 0; + sz1=0; if (hd->ScsiLookup != NULL) { sz1 = hd->ioc->req_depth * sizeof(void *); @@ -1387,36 +1352,16 @@ } if (hd->Targets != NULL) { - int max, ii; - - /* - * Free any target structures that were allocated. - */ - 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++) { - if (hd->Targets[ii]) { - kfree(hd->Targets[ii]); - hd->Targets[ii] = NULL; - sztarget += sizeof(VirtDevice); - } - } - /* * Free pointer array. */ - sz3 = max * sizeof(void *); kfree(hd->Targets); hd->Targets = NULL; } dprintk((MYIOC_s_INFO_FMT - "Free'd ScsiLookup (%d) Target (%d+%d) memory\n", - hd->ioc->name, sz1, sz3, sztarget)); - dprintk(("Free'd done and free Q (%d) memory\n", szQ)); + "Free'd ScsiLookup (%d) memory\n", + hd->ioc->name, sz1)); /* NULL the Scsi_Host pointer */ @@ -1545,9 +1490,15 @@ } #ifdef MODULE - /* Evaluate the command line arguments, if any */ - if (mptscsih) - mptscsih_setup(mptscsih); + dinitprintk((KERN_INFO MYNAM + ": Command Line Args: dv=%d max_width=%d " + "factor=0x%x saf_te=%d\n", + dv, width, factor, saf_te)); + + driver_setup.dv = (dv) ? 1 : 0; + driver_setup.max_width = (width) ? 1 : 0; + driver_setup.min_sync_factor = factor; + driver_setup.saf_te = (saf_te) ? 1 : 0;; #endif if(mpt_device_driver_register(&mptscsih_driver, @@ -1676,129 +1627,6 @@ return ((info.pos > info.offset) ? info.pos - info.offset : 0); } -#ifndef MPTSCSIH_DBG_TIMEOUT -static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len) -{ - /* Not yet implemented */ - return len; -} -#else -#define is_digit(c) ((c) >= '0' && (c) <= '9') -#define digit_to_bin(c) ((c) - '0') -#define is_space(c) ((c) == ' ' || (c) == '\t') - -#define UC_DBG_TIMEOUT 0x01 -#define UC_DBG_HARDRESET 0x02 - -static int skip_spaces(char *ptr, int len) -{ - int cnt, c; - - for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --); - - return (len - cnt); -} - -static int get_int_arg(char *ptr, int len, ulong *pv) -{ - int cnt, c; - ulong v; - for (v = 0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) { - v = (v * 10) + digit_to_bin(c); - } - - if (pv) - *pv = v; - - return (len - cnt); -} - - -static int is_keyword(char *ptr, int len, char *verb) -{ - int verb_len = strlen(verb); - - if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len)) - return verb_len; - else - return 0; -} - -#define SKIP_SPACES(min_spaces) \ - if ((arg_len = skip_spaces(ptr,len)) < (min_spaces)) \ - return -EINVAL; \ - ptr += arg_len; \ - len -= arg_len; - -#define GET_INT_ARG(v) \ - if (!(arg_len = get_int_arg(ptr,len, &(v)))) \ - return -EINVAL; \ - ptr += arg_len; \ - len -= arg_len; - -static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length) -{ - char *ptr = buffer; - char btmp[24]; /* REMOVE */ - int arg_len; - int len = length; - int cmd; - ulong number = 1; - ulong delta = 10; - - if ((len > 0) && (ptr[len -1] == '\n')) - --len; - - if (len < 22) { - strncpy(btmp, buffer, len); - btmp[len+1]='\0'; - } else { - strncpy(btmp, buffer, 22); - btmp[23]='\0'; - } - printk("user_command: ioc %d, buffer %s, length %d\n", - ioc->id, btmp, length); - - if ((arg_len = is_keyword(ptr, len, "timeout")) != 0) - cmd = UC_DBG_TIMEOUT; - else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0) - cmd = UC_DBG_HARDRESET; - else - return -EINVAL; - - ptr += arg_len; - len -= arg_len; - - switch(cmd) { - case UC_DBG_TIMEOUT: - SKIP_SPACES(1); - GET_INT_ARG(number); - SKIP_SPACES(1); - GET_INT_ARG(delta); - break; - } - - printk("user_command: cnt=%ld delta=%ld\n", number, delta); - - if (len) - return -EINVAL; - else { - if (cmd == UC_DBG_HARDRESET) { - ioc->timeout_hard = 1; - } else if (cmd == UC_DBG_TIMEOUT) { - /* process this command ... - */ - ioc->timeout_maxcnt = 0; - ioc->timeout_delta = delta < 2 ? 2 : delta; - ioc->timeout_cnt = 0; - ioc->timeout_maxcnt = number < 8 ? number: 8; - } - } - /* Not yet implemented */ - return length; -} -#endif - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_proc_info - Return information about MPT adapter @@ -1812,7 +1640,7 @@ * hostno: scsi host number * func: if write = 1; if read = 0 */ -static int +static int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func) { @@ -1821,7 +1649,9 @@ int size = 0; if (func) { - size = mptscsih_user_command(ioc, buffer, length); + /* + * write is not supported + */ } else { if (start) *start = buffer; @@ -1832,7 +1662,6 @@ return size; } - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #define ADD_INDEX_LOG(req_ent) do { } while(0) @@ -1863,11 +1692,7 @@ u32 cmd_len; int my_idx; int ii; - int rc; - int did_errcode; - int issueCmd; - did_errcode = 0; hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; target = SCpnt->device->id; lun = SCpnt->device->lun; @@ -1966,84 +1791,66 @@ /* Now add the SG list * Always have a SGE even if null length. */ - rc = SUCCESS; if (datalen == 0) { /* Add a NULL SGE */ mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); } else { /* Add a 32 or 64 bit SGE */ - rc = mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx); + if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) + goto fail; } - - if (rc == SUCCESS) { - hd->ScsiLookup[my_idx] = SCpnt; - SCpnt->host_scribble = NULL; - - /* SCSI specific processing */ - issueCmd = 1; - if (hd->is_spi) { - int dvStatus = hd->ioc->spi_data.dvStatus[target]; - - if (dvStatus || hd->ioc->spi_data.forceDv) { + hd->ScsiLookup[my_idx] = SCpnt; + SCpnt->host_scribble = NULL; #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - if ((dvStatus & MPT_SCSICFG_NEED_DV) || - (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { - unsigned long lflags; - /* Schedule DV if necessary */ - spin_lock_irqsave(&dvtaskQ_lock, lflags); - if (!dvtaskQ_active) { - dvtaskQ_active = 1; - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); - - schedule_work(&mptscsih_dvTask); - } else { - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - } - hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV; - } + if (hd->ioc->bus_type == SCSI) { + int dvStatus = hd->ioc->spi_data.dvStatus[target]; + int issueCmd = 1; + + if (dvStatus || hd->ioc->spi_data.forceDv) { + + if ((dvStatus & MPT_SCSICFG_NEED_DV) || + (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { + unsigned long lflags; + /* Schedule DV if necessary */ + spin_lock_irqsave(&dvtaskQ_lock, lflags); + if (!dvtaskQ_active) { + dvtaskQ_active = 1; + spin_unlock_irqrestore(&dvtaskQ_lock, lflags); + INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); - /* Trying to do DV to this target, extend timeout. - * Wait to issue until flag is clear - */ - if (dvStatus & MPT_SCSICFG_DV_PENDING) { - mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); - issueCmd = 0; + schedule_work(&mptscsih_dvTask); + } else { + spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } + hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV; + } - /* Set the DV flags. - */ - if (dvStatus & MPT_SCSICFG_DV_NOT_DONE) - mptscsih_set_dvflags(hd, pScsiReq); -#endif + /* Trying to do DV to this target, extend timeout. + * Wait to issue until flag is clear + */ + if (dvStatus & MPT_SCSICFG_DV_PENDING) { + mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); + issueCmd = 0; } - } -#ifdef MPTSCSIH_DBG_TIMEOUT - if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) { - foo_to[hd->ioc->timeout_cnt] = SCpnt; - hd->ioc->timeout_cnt++; - //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta); - issueCmd = 0; - printk(MYIOC_s_WARN_FMT - "to pendingQ: (sc=%p, mf=%p, time=%ld)\n", - hd->ioc->name, SCpnt, mf, jiffies); + /* Set the DV flags. + */ + if (dvStatus & MPT_SCSICFG_DV_NOT_DONE) + mptscsih_set_dvflags(hd, pScsiReq); + + if (!issueCmd) + goto fail; } + } #endif - if (issueCmd) { - mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf); - dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", - hd->ioc->name, SCpnt, mf, my_idx)); - DBG_DUMP_REQUEST_FRAME(mf) - } else - goto fail; - } else - goto fail; - + mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf); + dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", + hd->ioc->name, SCpnt, mf, my_idx)); + DBG_DUMP_REQUEST_FRAME(mf) return 0; fail: @@ -2216,11 +2023,6 @@ } } -#ifdef MPTSCSIH_DBG_TIMEOUT - if (hd->ioc->timeout_hard) - rc = 1; -#endif - /* Only fall through to the HRH if this is a bus reset */ if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || @@ -2457,9 +2259,9 @@ printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", hd->ioc->name, SCpnt); - /* Unsupported for SCSI. Supported for FCP + /* Supported for FC only. */ - if (hd->is_spi) + if (hd->ioc->bus_type == SCSI) return FAILED; spin_unlock_irq(host_lock); @@ -2767,39 +2569,56 @@ mptscsih_slave_alloc(struct scsi_device *device) { struct Scsi_Host *host = device->host; - MPT_SCSI_HOST *hd; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; VirtDevice *vdev; - - hd = (MPT_SCSI_HOST *)host->hostdata; + uint target = device->id; if (hd == NULL) return -ENODEV; - if ((vdev = hd->Targets[device->id]) == NULL) { - if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) { - printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%d) FAILED!\n", - hd->ioc->name, (int)sizeof(VirtDevice)); - return -ENOMEM; - } else { - memset(vdev, 0, sizeof(VirtDevice)); - vdev->tflags = MPT_TARGET_FLAGS_Q_YES; - vdev->ioc_id = hd->ioc->id; - vdev->target_id = device->id; - vdev->bus_id = device->channel; - vdev->raidVolume = 0; - hd->Targets[device->id] = vdev; - if (hd->is_spi) { - if (hd->ioc->spi_data.isRaid & (1 << device->id)) { - vdev->raidVolume = 1; - ddvtprintk((KERN_INFO - "RAID Volume @ id %d\n", device->id)); - } - } else { - vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; - } + if ((vdev = hd->Targets[target]) != NULL) + goto out; + + vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { + printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", + hd->ioc->name, sizeof(VirtDevice)); + return -ENOMEM; + } + + memset(vdev, 0, sizeof(VirtDevice)); + vdev->tflags = MPT_TARGET_FLAGS_Q_YES; + vdev->ioc_id = hd->ioc->id; + vdev->target_id = device->id; + vdev->bus_id = device->channel; + vdev->raidVolume = 0; + hd->Targets[device->id] = vdev; + if (hd->ioc->bus_type == SCSI) { + if (hd->ioc->spi_data.isRaid & (1 << device->id)) { + vdev->raidVolume = 1; + ddvtprintk((KERN_INFO + "RAID Volume @ id %d\n", device->id)); } + } else { + vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; } + + out: vdev->num_luns++; + return 0; +} + +static int mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id) +{ + int i; + + if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3) + return 0; + + for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) { + if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) + return 1; + } return 0; } @@ -2812,59 +2631,37 @@ mptscsih_slave_destroy(struct scsi_device *device) { struct Scsi_Host *host = device->host; - MPT_SCSI_HOST *hd; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; VirtDevice *vdev; - int raid_volume=0; - - hd = (MPT_SCSI_HOST *)host->hostdata; + uint target = device->id; + uint lun = device->lun; if (hd == NULL) return; - mptscsih_search_running_cmds(hd, device->id, device->lun); - - /* Free memory and reset all flags for this target - */ - if ((vdev = hd->Targets[device->id]) != NULL) { - vdev->num_luns--; - - if (vdev->luns[0] & (1 << device->lun)) - vdev->luns[0] &= ~(1 << device->lun); - - /* Free device structure only if number of luns is 0. - */ - if (vdev->num_luns == 0) { - kfree(hd->Targets[device->id]); - hd->Targets[device->id] = NULL; - - if (!hd->is_spi) - return; + mptscsih_search_running_cmds(hd, target, lun); - if((hd->ioc->spi_data.isRaid) && (hd->ioc->spi_data.pIocPg3)) { - int i; - for(i=0;iioc->spi_data.pIocPg3->NumPhysDisks && - raid_volume==0;i++) - - if(device->id == - hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) { - raid_volume=1; - hd->ioc->spi_data.forceDv |= - MPT_SCSICFG_RELOAD_IOC_PG3; - } - } + vdev = hd->Targets[target]; + vdev->luns[0] &= ~(1 << lun); + if (--vdev->num_luns) + return; - if(!raid_volume){ - hd->ioc->spi_data.dvStatus[device->id] = + kfree(hd->Targets[target]); + hd->Targets[target] = NULL; + + if (hd->ioc->bus_type == SCSI) { + if (mptscsih_is_raid_volume(hd, target)) { + hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; + } else { + hd->ioc->spi_data.dvStatus[target] = MPT_SCSICFG_NEGOTIATE; - if (hd->negoNvram == 0) - hd->ioc->spi_data.dvStatus[device->id] - |= MPT_SCSICFG_DV_NOT_DONE; + if (!hd->negoNvram) { + hd->ioc->spi_data.dvStatus[target] |= + MPT_SCSICFG_DV_NOT_DONE; } } } - - return; } static void @@ -2874,7 +2671,7 @@ int max_depth; int tagged; - if ( hd->is_spi ) { + if (hd->ioc->bus_type == SCSI) { if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) max_depth = 1; @@ -2989,7 +2786,6 @@ return count; } - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Private routines... @@ -3125,10 +2921,6 @@ mpt_free_msg_frame(ioc, hd->tmPtr); } -#ifdef MPTSCSIH_DBG_TIMEOUT - ioc->timeout_hard = 0; -#endif - dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name)); } else { @@ -3158,7 +2950,7 @@ /* 4. Renegotiate to all devices, if SCSI */ - if (hd->is_spi) { + if (ioc->bus_type == SCSI) { dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n")); mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM); } @@ -3187,7 +2979,7 @@ /* 7. Set flag to force DV and re-read IOC Page 3 */ - if (hd->is_spi) { + if (ioc->bus_type == SCSI) { ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; ddvtprintk(("Set reload IOC Pg3 Flag\n")); } @@ -3218,7 +3010,7 @@ hd = NULL; if (ioc->sh) { hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd && (hd->is_spi) && (hd->soft_resets < -1)) + if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1)) hd->soft_resets++; } break; @@ -3247,7 +3039,7 @@ if (ioc->sh) hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd && (hd->is_spi) && (hd->negoNvram == 0)) { + if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) { ScsiCfgData *pSpi; Ioc3PhysDisk_t *pPDisk; int numPDisk; @@ -3394,7 +3186,7 @@ indexed_lun = (lun % 32); vdev->luns[lun_index] |= (1 << indexed_lun); - if (hd->is_spi) { + if (hd->ioc->bus_type == SCSI) { if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { /* Treat all Processors as SAF-TE if * command line option is set */ @@ -4675,7 +4467,7 @@ /* Write SDP1 for all SCSI devices * Alloc memory and set up config buffer */ - if (hd->is_spi) { + if (ioc->bus_type == SCSI) { if (ioc->spi_data.sdp1length > 0) { pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev, ioc->spi_data.sdp1length * 4, &cfg1_dma_addr); @@ -4818,7 +4610,7 @@ msleep(250); /* DV only to SCSI adapters */ - if ((int)ioc->chip_type <= (int)FC929) + if (ioc->bus_type != SCSI) continue; /* Make sure everything looks ok */ @@ -6289,107 +6081,6 @@ #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Commandline Parsing routines and defines. - * - * insmod format: - * insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1" - * boot format: - * mptscsih=width:1,dv:n,factor:0x8,saf-te:1 - * - */ -#ifdef MODULE -#define ARG_SEP ' ' -#else -#define ARG_SEP ',' -#endif - -#ifdef MODULE -static char setup_token[] __initdata = - "dv:" - "width:" - "factor:" - "saf-te:" - ; /* DO NOT REMOVE THIS ';' */ -#endif - -#define OPT_DV 1 -#define OPT_MAX_WIDTH 2 -#define OPT_MIN_SYNC_FACTOR 3 -#define OPT_SAF_TE 4 - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#ifdef MODULE -static int -get_setup_token(char *p) -{ - char *cur = setup_token; - char *pc; - int i = 0; - - while (cur != NULL && (pc = strchr(cur, ':')) != NULL) { - ++pc; - ++i; - if (!strncmp(p, cur, pc - cur)) - return i; - cur = pc; - } - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mptscsih_setup(char *str) -{ - char *cur = str; - char *pc, *pv; - unsigned long val; - int c; - - while (cur != NULL && (pc = strchr(cur, ':')) != NULL) { - char *pe; - - val = 0; - pv = pc; - c = *++pv; - - if (c == 'n') - val = 0; - else if (c == 'y') - val = 1; - else - val = (int) simple_strtoul(pv, &pe, 0); - - printk("Found Token: %s, value %x\n", cur, (int)val); - switch (get_setup_token(cur)) { - case OPT_DV: - driver_setup.dv = val; - break; - - case OPT_MAX_WIDTH: - driver_setup.max_width = val; - break; - - case OPT_MIN_SYNC_FACTOR: - driver_setup.min_sync_fac = val; - break; - - case OPT_SAF_TE: - driver_setup.saf_te = val; - break; - - default: - printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur); - break; - } - - if ((cur = strchr(cur, ARG_SEP)) != NULL) - ++cur; - } - return 1; -} -#endif -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - module_init(mptscsih_init); module_exit(mptscsih_exit); Index: wli-2.6.10-rc3-1/drivers/message/fusion/mptscsih.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/message/fusion/mptscsih.h 2004-12-22 09:07:08.967358634 -0800 +++ wli-2.6.10-rc3-1/drivers/message/fusion/mptscsih.h 2004-12-22 10:04:36.110313250 -0800 @@ -95,17 +95,8 @@ { u8 dv; u8 max_width; - u8 min_sync_fac; + u8 min_sync_factor; u8 saf_te; }; - -#define MPTSCSIH_DRIVER_SETUP \ -{ \ - MPTSCSIH_DOMAIN_VALIDATION, \ - MPTSCSIH_MAX_WIDTH, \ - MPTSCSIH_MIN_SYNC, \ - MPTSCSIH_SAF_TE, \ -} - #endif Index: wli-2.6.10-rc3-1/drivers/mmc/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/mmc/Kconfig 2004-12-22 09:07:08.978356962 -0800 +++ wli-2.6.10-rc3-1/drivers/mmc/Kconfig 2004-12-22 10:04:36.112312946 -0800 @@ -49,4 +49,15 @@ If unsure, say N. +config MMC_WBSD + tristate "Winbond W83L51xD SD/MMC Card Interface support" + depends on MMC + help + This selects the Winbond(R) W83L51xD Secure digital and + Multimedia card Interface. + If you have a machine with a integrated W83L518D or W83L519D + SD/MMC card reader, say Y or M here. + + If unsure, say N. + endmenu Index: wli-2.6.10-rc3-1/drivers/mmc/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/mmc/Makefile 2004-12-22 09:07:08.979356810 -0800 +++ wli-2.6.10-rc3-1/drivers/mmc/Makefile 2004-12-22 10:04:36.113312794 -0800 @@ -17,5 +17,6 @@ # obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_PXA) += pxamci.o +obj-$(CONFIG_MMC_WBSD) += wbsd.o mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o Index: wli-2.6.10-rc3-1/drivers/mmc/pxamci.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/mmc/pxamci.c 2004-12-16 06:19:36.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/mmc/pxamci.c 2004-12-22 10:04:36.117312186 -0800 @@ -122,7 +122,7 @@ unsigned int nob = data->blocks; unsigned int timeout; u32 dcmd; - int i, len; + int i; host->data = data; @@ -375,15 +375,14 @@ if (CLOCKRATE / clk > ios->clock) clk <<= 1; host->clkrt = fls(clk) - 1; + pxa_set_cken(CKEN12_MMC, 1); /* * we write clkrt on the next command */ - } else if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { - /* - * Ensure that the clock is off. - */ - writel(STOP_CLOCK, host->base + MMC_STRPCL); + } else { + pxamci_stop_clock(host); + pxa_set_cken(CKEN12_MMC, 0); } if (host->power_mode != ios->power_mode) { @@ -505,8 +504,6 @@ if (host->pdata && host->pdata->init) host->pdata->init(dev, pxamci_detect_irq, mmc); - pxa_set_cken(CKEN12_MMC, 1); - mmc_add_host(mmc); return 0; @@ -545,8 +542,6 @@ END_CMD_RES|PRG_DONE|DATA_TRAN_DONE, host->base + MMC_I_MASK); - pxa_set_cken(CKEN12_MMC, 0); - DRCMRRXMMC = 0; DRCMRTXMMC = 0; @@ -555,8 +550,6 @@ iounmap(host->base); dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); - pxa_set_cken(CKEN12_MMC, 0); - release_resource(host->res); mmc_free_host(mmc); Index: wli-2.6.10-rc3-1/drivers/net/acenic.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/acenic.c 2004-12-16 06:19:38.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/net/acenic.c 2004-12-22 10:04:36.128310514 -0800 @@ -457,6 +457,8 @@ .get_drvinfo = ace_get_drvinfo, }; +static void ace_watchdog(struct net_device *dev); + static int __devinit acenic_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -485,7 +487,6 @@ dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid; #endif if (1) { - static void ace_watchdog(struct net_device *dev); dev->tx_timeout = &ace_watchdog; dev->watchdog_timeo = 5*HZ; } Index: wli-2.6.10-rc3-1/drivers/net/eepro100.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/eepro100.c 2004-12-16 06:19:38.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/net/eepro100.c 2004-12-22 10:04:36.136309298 -0800 @@ -2328,6 +2328,8 @@ outl(PortPartialReset, ioaddr + SCBPort); /* XXX call pci_set_power_state ()? */ + pci_disable_device(pdev); + pci_set_power_state (pdev, 3); return 0; } @@ -2337,7 +2339,10 @@ struct speedo_private *sp = netdev_priv(dev); long ioaddr = dev->base_addr; + pci_set_power_state(pdev, 0); pci_restore_state(pdev); + pci_enable_device(pdev); + pci_set_master(pdev); if (!netif_running(dev)) return 0; Index: wli-2.6.10-rc3-1/drivers/net/ibmveth.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/ibmveth.c 2004-12-16 06:19:39.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/net/ibmveth.c 2004-12-22 10:04:36.141308538 -0800 @@ -96,6 +96,7 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter); static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter*); #ifdef CONFIG_PROC_FS #define IBMVETH_PROC_DIR "ibmveth" @@ -104,7 +105,7 @@ static const char ibmveth_driver_name[] = "ibmveth"; static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver"; -#define ibmveth_driver_version "1.02" +#define ibmveth_driver_version "1.03" MODULE_AUTHOR("Santiago Leon "); MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver"); @@ -271,6 +272,8 @@ adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); atomic_inc(&adapter->not_replenishing); + + ibmveth_schedule_replenishing(adapter); } /* kick the replenish tasklet if we need replenishing and it isn't already running */ Index: wli-2.6.10-rc3-1/drivers/net/irda/irda-usb.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/irda/irda-usb.c 2004-12-22 09:07:09.152330514 -0800 +++ wli-2.6.10-rc3-1/drivers/net/irda/irda-usb.c 2004-12-22 10:04:36.168304434 -0800 @@ -52,7 +52,7 @@ /*------------------------------------------------------------------*/ #include - +#include #include #include #include @@ -88,10 +88,10 @@ /* * Important note : - * Devices based on the SigmaTel chipset (0x66f, 0x4200) are not compliant - * with the USB-IrDA specification (and actually very very different), and - * there is no way this driver can support those devices, apart from - * a complete rewrite... + * Devices based on the SigmaTel chipset (0x66f, 0x4200) are not designed + * using the "USB-IrDA specification" (yes, there exist such a thing), and + * therefore not supported by this driver (don't add them above). + * There is a Linux driver, stir4200, that support those USB devices. * Jean II */ @@ -1007,9 +1007,9 @@ } /* Cancel Tx and speed URB - need to be synchronous to avoid races */ self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK; - usb_unlink_urb(self->tx_urb); + usb_kill_urb(self->tx_urb); self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK; - usb_unlink_urb(self->speed_urb); + usb_kill_urb(self->speed_urb); /* Stop and remove instance of IrLAP */ if (self->irlap) @@ -1520,9 +1520,9 @@ /* Cancel Tx and speed URB. * Toggle flags to make sure it's synchronous. */ self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK; - usb_unlink_urb(self->tx_urb); + usb_kill_urb(self->tx_urb); self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK; - usb_unlink_urb(self->speed_urb); + usb_kill_urb(self->speed_urb); } /* Cleanup the device stuff */ @@ -1593,7 +1593,7 @@ /* * Module parameters */ -MODULE_PARM(qos_mtt_bits, "i"); +module_param(qos_mtt_bits, int, 0); MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); MODULE_AUTHOR("Roman Weissgaerber , Dag Brattli and Jean Tourrilhes "); MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); Index: wli-2.6.10-rc3-1/drivers/net/irda/sa1100_ir.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/irda/sa1100_ir.c 2004-12-22 09:07:09.155330058 -0800 +++ wli-2.6.10-rc3-1/drivers/net/irda/sa1100_ir.c 2004-12-22 10:04:36.175303370 -0800 @@ -39,19 +39,7 @@ #include #include #include -#include - -#include -#include -#include - -#ifndef GPIO_IRDA_FIR -#define GPIO_IRDA_FIR (0) -#endif - -#ifndef GPIO_IRDA_POWER -#define GPIO_IRDA_POWER (0) -#endif +#include static int power_level = 3; static int tx_lpm; @@ -75,6 +63,7 @@ struct net_device_stats stats; struct device *dev; + struct irda_platform_data *pdata; struct irlap_cb *irlap; struct qos_info qos; @@ -170,12 +159,8 @@ Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID; Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE; - if (machine_is_assabet()) - ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL); - if (machine_is_h3xxx()) - clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL); - if (machine_is_yopy()) - PPSR &= ~GPIO_IRDA_FIR; + if (si->pdata->set_speed) + si->pdata->set_speed(si->dev, speed); si->speed = speed; @@ -194,12 +179,8 @@ si->speed = speed; - if (machine_is_assabet()) - ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL); - if (machine_is_h3xxx()) - set_h3600_egpio(IPAQ_EGPIO_IR_FSEL); - if (machine_is_yopy()) - PPSR |= GPIO_IRDA_FIR; + if (si->pdata->set_speed) + si->pdata->set_speed(si->dev, speed); sa1100_irda_rx_alloc(si); sa1100_irda_rx_dma_start(si); @@ -216,51 +197,6 @@ } /* - * This sets the IRDA power level on the Assabet. - */ -static inline int -sa1100_irda_set_power_assabet(struct sa1100_irda *si, unsigned int state) -{ - static unsigned int bcr_state[4] = { - ASSABET_BCR_IRDA_MD0, - ASSABET_BCR_IRDA_MD1|ASSABET_BCR_IRDA_MD0, - ASSABET_BCR_IRDA_MD1, - 0 - }; - - if (state < 4) { - state = bcr_state[state]; - ASSABET_BCR_clear(state ^ (ASSABET_BCR_IRDA_MD1| - ASSABET_BCR_IRDA_MD0)); - ASSABET_BCR_set(state); - } - return 0; -} - -/* - * This turns the IRDA power on or off on the Compaq H3600 - */ -static inline int -sa1100_irda_set_power_h3600(struct sa1100_irda *si, unsigned int state) -{ - assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state ); - return 0; -} - -/* - * This turns the IRDA power on or off on the Yopy - */ -static inline int -sa1100_irda_set_power_yopy(struct sa1100_irda *si, unsigned int state) -{ - if (state) - PPSR &= ~GPIO_IRDA_POWER; - else - PPSR |= GPIO_IRDA_POWER; - return 0; -} - -/* * Control the power state of the IrDA transmitter. * State: * 0 - off @@ -274,14 +210,8 @@ __sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state) { int ret = 0; - - if (machine_is_assabet()) - ret = sa1100_irda_set_power_assabet(si, state); - if (machine_is_h3xxx()) - ret = sa1100_irda_set_power_h3600(si, state); - if (machine_is_yopy()) - ret = sa1100_irda_set_power_yopy(si, state); - + if (si->pdata->set_power) + ret = si->pdata->set_power(si->dev, state); return ret; } @@ -304,11 +234,8 @@ /* * Ensure that the ports for this device are setup correctly. */ - if (machine_is_yopy()) { - PPDR |= GPIO_IRDA_POWER | GPIO_IRDA_FIR; - PPSR |= GPIO_IRDA_POWER | GPIO_IRDA_FIR; - PSDR |= GPIO_IRDA_POWER | GPIO_IRDA_FIR; - } + if (si->pdata->startup) + si->pdata->startup(si->dev); /* * Configure PPC for IRDA - we want to drive TXD2 low. @@ -333,10 +260,15 @@ Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID; ret = sa1100_irda_set_speed(si, si->speed = 9600); - if (ret) - return ret; + if (ret) { + Ser2UTCR3 = 0; + Ser2HSCR0 = 0; - return 0; + if (si->pdata->shutdown) + si->pdata->shutdown(si->dev); + } + + return ret; } static void sa1100_irda_shutdown(struct sa1100_irda *si) @@ -350,6 +282,9 @@ /* Disable the port. */ Ser2UTCR3 = 0; Ser2HSCR0 = 0; + + if (si->pdata->shutdown) + si->pdata->shutdown(si->dev); } #ifdef CONFIG_PM @@ -959,6 +894,9 @@ unsigned int baudrate_mask; int err; + if (!pdev->dev.platform_data) + return -EINVAL; + err = request_mem_region(__PREG(Ser2UTCR0), 0x24, "IrDA") ? 0 : -EBUSY; if (err) goto err_mem_1; @@ -975,6 +913,7 @@ si = dev->priv; si->dev = &pdev->dev; + si->pdata = pdev->dev.platform_data; /* * Initialise the HP-SIR buffers @@ -1028,7 +967,7 @@ err = register_netdev(dev); if (err == 0) - dev_set_drvdata(&pdev->dev, si); + dev_set_drvdata(&pdev->dev, dev); if (err) { err_mem_5: @@ -1074,15 +1013,8 @@ .resume = sa1100_irda_resume, }; -static struct platform_device sa1100ir_device = { - .name = "sa11x0-ir", - .id = 0, -}; - static int __init sa1100_irda_init(void) { - int ret; - /* * Limit power level a sensible range. */ @@ -1091,19 +1023,12 @@ if (power_level > 3) power_level = 3; - ret = driver_register(&sa1100ir_driver); - if (ret == 0) { - ret = platform_device_register(&sa1100ir_device); - if (ret) - driver_unregister(&sa1100ir_driver); - } - return ret; + return driver_register(&sa1100ir_driver); } static void __exit sa1100_irda_exit(void) { driver_unregister(&sa1100ir_driver); - platform_device_unregister(&sa1100ir_device); } module_init(sa1100_irda_init); Index: wli-2.6.10-rc3-1/drivers/net/irda/stir4200.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/irda/stir4200.c 2004-12-16 06:19:39.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/net/irda/stir4200.c 2004-12-22 10:04:36.179302762 -0800 @@ -705,7 +705,7 @@ static void receive_stop(struct stir_cb *stir) { stir->receiving = 0; - usb_unlink_urb(stir->rx_urb); + usb_kill_urb(stir->rx_urb); if (stir->rx_buff.in_frame) stir->stats.collisions++; @@ -974,7 +974,7 @@ kfree(stir->fifo_status); /* Mop up receive urb's */ - usb_unlink_urb(stir->rx_urb); + usb_kill_urb(stir->rx_urb); kfree(stir->io_buf); usb_free_urb(stir->rx_urb); Index: wli-2.6.10-rc3-1/drivers/net/irda/via-ircc.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/irda/via-ircc.c 2004-12-16 06:19:39.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/net/irda/via-ircc.c 2004-12-22 10:04:36.186301698 -0800 @@ -75,6 +75,9 @@ /* We can't guess the type of connected dongle, user *must* supply it. */ MODULE_PARM(dongle_id, "i"); +/* FIXME : we should not need this, because instances should be automatically + * managed by the PCI layer. Especially that we seem to only be using the + * first entry. Jean II */ /* Max 4 instances for now */ static struct via_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; @@ -153,11 +156,9 @@ IRDA_DEBUG(3, "%s()\n", __FUNCTION__); rc = pci_register_driver(&via_driver); - if (rc < 1) { + if (rc < 0) { IRDA_DEBUG(0, "%s(): error rc = %d, returning -ENODEV...\n", __FUNCTION__, rc); - if (rc == 0) - pci_unregister_driver (&via_driver); return -ENODEV; } return 0; @@ -288,15 +289,27 @@ { IRDA_DEBUG(3, "%s()\n", __FUNCTION__); + /* FIXME : This is ugly. We should use pci_get_drvdata(pdev); + * to get our driver instance and call directly via_ircc_close(). + * See vlsi_ir for details... + * Jean II */ via_ircc_clean(); + /* FIXME : This should be in via_ircc_close(), because here we may + * theoritically disable still configured devices :-( - Jean II */ + pci_disable_device(pdev); } static void __exit via_ircc_cleanup(void) { IRDA_DEBUG(3, "%s()\n", __FUNCTION__); + /* FIXME : This should be redundant, as pci_unregister_driver() + * should call via_remove_one() on each device. + * Jean II */ via_ircc_clean(); + + /* Cleanup all instances of the driver */ pci_unregister_driver (&via_driver); } @@ -323,6 +336,10 @@ self->netdev = dev; spin_lock_init(&self->lock); + /* FIXME : We should store our driver instance in the PCI layer, + * using pci_set_drvdata(), not in this array. + * See vlsi_ir for details... - Jean II */ + /* FIXME : 'i' is always 0 (see via_init_one()) :-( - Jean II */ /* Need to store self somewhere */ dev_self[i] = self; self->index = i; Index: wli-2.6.10-rc3-1/drivers/net/r8169.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/r8169.c 2004-12-22 09:07:09.106337506 -0800 +++ wli-2.6.10-rc3-1/drivers/net/r8169.c 2004-12-22 10:04:36.148307474 -0800 @@ -150,6 +150,7 @@ static struct pci_device_id rtl8169_pci_tbl[] = { {0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x1186, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0,}, }; Index: wli-2.6.10-rc3-1/drivers/net/smc91x.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/smc91x.c 2004-12-16 06:19:39.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/net/smc91x.c 2004-12-22 10:04:36.155306410 -0800 @@ -1244,6 +1244,11 @@ spin_lock(&lp->lock); + /* A preamble may be used when there is a potential race + * between the interruptible transmit functions and this + * ISR. */ + SMC_INTERRUPT_PREAMBLE; + saved_pointer = SMC_GET_PTR(); mask = SMC_GET_INT_MASK(); SMC_SET_INT_MASK(0); Index: wli-2.6.10-rc3-1/drivers/net/smc91x.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/net/smc91x.h 2004-12-16 06:19:39.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/net/smc91x.h 2004-12-22 10:04:36.160305650 -0800 @@ -193,6 +193,53 @@ #define RPC_LSA_DEFAULT RPC_LED_TX_RX #define RPC_LSB_DEFAULT RPC_LED_100_10 +#elif defined(CONFIG_MACH_LPD7A400) || defined(CONFIG_MACH_LPD7A404) + +/* The LPD7A40X_IOBARRIER is necessary to overcome a mismatch between + * the way that the CPU handles chip selects and the way that the SMC + * chip expects the chip select to operate. Refer to + * Documentation/arm/Sharp-LH/IOBarrier for details. The read from + * IOBARRIER is a byte as a least-common denominator of possible + * regions to use as the barrier. It would be wasteful to read 32 + * bits from a byte oriented region. + * + * There is no explicit protection against interrupts intervening + * between the writew and the IOBARRIER. In SMC ISR there is a + * preamble that performs an IOBARRIER in the extremely unlikely event + * that the driver interrupts itself between a writew to the chip an + * the IOBARRIER that follows *and* the cache is large enough that the + * first off-chip access while handing the interrupt is to the SMC + * chip. Other devices in the same address space as the SMC chip must + * be aware of the potential for trouble and perform a similar + * IOBARRIER on entry to their ISR. + */ + +#include /* IOBARRIER_VIRT */ + +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 0 +#define LPD7A40X_IOBARRIER readb (IOBARRIER_VIRT) + +#define SMC_inw(a,r) readw ((void*) ((a) + (r))) +#define SMC_insw(a,r,p,l) readsw ((void*) ((a) + (r)), p, l) +#define SMC_outw(v,a,r) ({ writew ((v), (a) + (r)); LPD7A40X_IOBARRIER; }) + +static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) +{ + unsigned short* ps = (unsigned short*) p; + while (l-- > 0) { + writew (*ps++, a + r); + LPD7A40X_IOBARRIER; + } +} + +#define SMC_INTERRUPT_PREAMBLE LPD7A40X_IOBARRIER + +#define RPC_LSA_DEFAULT RPC_LED_TX_RX +#define RPC_LSB_DEFAULT RPC_LED_100_10 + #else #define SMC_CAN_USE_8BIT 1 @@ -894,5 +941,8 @@ }) #endif +#if !defined (SMC_INTERRUPT_PREAMBLE) +# define SMC_INTERRUPT_PREAMBLE +#endif #endif /* _SMC91X_H_ */ Index: wli-2.6.10-rc3-1/drivers/pcmcia/pxa2xx_base.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/pcmcia/pxa2xx_base.c 2004-12-22 09:07:09.269312730 -0800 +++ wli-2.6.10-rc3-1/drivers/pcmcia/pxa2xx_base.c 2004-12-22 10:04:36.188301394 -0800 @@ -217,7 +217,13 @@ { int ret = 0; if (level == RESUME_RESTORE_STATE) + { + struct pcmcia_low_level *ops = dev->platform_data; + int nr = ops ? ops->nr : 0; + + MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0); ret = pcmcia_socket_dev_resume(dev); + } return ret; } Index: wli-2.6.10-rc3-1/drivers/s390/char/monreader.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/s390/char/monreader.c 2004-12-16 06:19:43.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/s390/char/monreader.c 2004-12-22 10:04:36.191300938 -0800 @@ -450,7 +450,7 @@ } P_INFO("open, established connection to *MONITOR service\n\n"); filp->private_data = monpriv; - return 0; + return nonseekable_open(inode, filp); out_unregister: iucv_unregister_program(monpriv->iucv_handle); Index: wli-2.6.10-rc3-1/drivers/s390/char/vmwatchdog.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/s390/char/vmwatchdog.c 2004-12-16 06:19:43.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/s390/char/vmwatchdog.c 2004-12-22 10:04:36.194300482 -0800 @@ -168,7 +168,7 @@ ret = vmwdt_keepalive(); if (ret) clear_bit(0, &vmwdt_is_open); - return ret; + return ret ? ret : nonseekable_open(i, f); } static int vmwdt_close(struct inode *i, struct file *f) @@ -238,10 +238,6 @@ static ssize_t vmwdt_write(struct file *f, const char __user *buf, size_t count, loff_t *ppos) { - /* We can't seek */ - if(ppos != &f->f_pos) - return -ESPIPE; - if(count) { if (!vmwdt_nowayout) { size_t i; Index: wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_def.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/s390/scsi/zfcp_def.h 2004-12-16 06:19:43.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_def.h 2004-12-22 10:04:36.199299722 -0800 @@ -34,8 +34,7 @@ #ifndef ZFCP_DEF_H #define ZFCP_DEF_H -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_DEF_REVISION "$Revision: 1.110 $" +#define ZFCP_DEF_REVISION "$Revision: 1.111 $" /*************************** INCLUDES *****************************************/ @@ -70,6 +69,7 @@ /********************* GENERAL DEFINES *********************************/ +/* zfcp version number, it consists of major, minor, and patch-level number */ #define ZFCP_VERSION "4.2.0" /** Index: wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_erp.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/s390/scsi/zfcp_erp.c 2004-12-16 06:19:43.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_erp.c 2004-12-22 10:04:36.211297898 -0800 @@ -31,8 +31,7 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_ERP_REVISION "$Revision: 1.83 $" +#define ZFCP_ERP_REVISION "$Revision: 1.85 $" #include "zfcp_ext.h" @@ -3482,9 +3481,8 @@ debug_text_event(adapter->erp_dbf, 3, "p_access_block"); debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); read_lock_irqsave(&zfcp_data.config_lock, flags); - zfcp_erp_modify_port_status(port, - ZFCP_STATUS_COMMON_ERP_FAILED | ZFCP_STATUS_COMMON_ACCESS_DENIED, - ZFCP_SET); + zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED | + ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); read_unlock_irqrestore(&zfcp_data.config_lock, flags); } @@ -3500,9 +3498,8 @@ debug_text_event(adapter->erp_dbf, 3, "u_access_block"); debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t)); - zfcp_erp_modify_unit_status(unit, - ZFCP_STATUS_COMMON_ERP_FAILED | ZFCP_STATUS_COMMON_ACCESS_DENIED, - ZFCP_SET); + zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_ERP_FAILED | + ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); } /* @@ -3541,19 +3538,21 @@ debug_text_event(adapter->erp_dbf, 3, "p_access_unblock"); debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); - if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status)) { + if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, + &port->status)) { if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) list_for_each_entry(unit, &port->unit_list_head, list) zfcp_erp_unit_access_changed(unit); return; } - ZFCP_LOG_NORMAL("Trying to reopen port 0x%016Lx on adapter %s " - "due to update to access control table\n", + ZFCP_LOG_NORMAL("reopen of port 0x%016Lx on adapter %s " + "(due to ACT update)\n", port->wwpn, zfcp_get_busid_by_adapter(adapter)); if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED) != 0) - ZFCP_LOG_NORMAL("Reopen of port 0x%016Lx on adapter %s failed\n", - port->wwpn, zfcp_get_busid_by_adapter(adapter)); + ZFCP_LOG_NORMAL("failed reopen of port" + "(adapter %s, wwpn=0x%016Lx)\n", + zfcp_get_busid_by_adapter(adapter), port->wwpn); } /* @@ -3572,16 +3571,15 @@ if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status)) return; - ZFCP_LOG_NORMAL("Trying to reopen unit 0x%016Lx " - "on port 0x%016Lx on adapter %s " - "due to update to access control table\n", + ZFCP_LOG_NORMAL("reopen of unit 0x%016Lx on port 0x%016Lx " + " on adapter %s (due to ACT update)\n", unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_adapter(adapter)); if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED) != 0) - ZFCP_LOG_NORMAL("Reopen of unit 0x%016Lx " - "on port 0x%016Lx on adapter %s failed\n", - unit->fcp_lun, unit->port->wwpn, - zfcp_get_busid_by_adapter(adapter)); + ZFCP_LOG_NORMAL("failed reopen of unit (adapter %s, " + "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n", + zfcp_get_busid_by_adapter(adapter), + unit->port->wwpn, unit->fcp_lun); } #undef ZFCP_LOG_AREA Index: wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_ext.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/s390/scsi/zfcp_ext.h 2004-12-16 06:19:43.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_ext.h 2004-12-22 10:04:36.213297594 -0800 @@ -31,8 +31,8 @@ #ifndef ZFCP_EXT_H #define ZFCP_EXT_H -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_EXT_REVISION "$Revision: 1.61 $" + +#define ZFCP_EXT_REVISION "$Revision: 1.62 $" #include "zfcp_def.h" Index: wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_fsf.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/s390/scsi/zfcp_fsf.c 2004-12-16 06:19:43.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_fsf.c 2004-12-22 10:04:36.232294706 -0800 @@ -30,8 +30,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_FSF_C_REVISION "$Revision: 1.86 $" +#define ZFCP_FSF_C_REVISION "$Revision: 1.88 $" #include "zfcp_ext.h" @@ -1737,7 +1736,7 @@ adapter = els->adapter; ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, - ZFCP_WAIT_FOR_SBAL|ZFCP_REQ_AUTO_CLEANUP, + ZFCP_REQ_AUTO_CLEANUP, NULL, &lock_flags, &fsf_req); if (ret < 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " @@ -3094,57 +3093,11 @@ exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE; readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER; - if (!adapter->supported_features & FSF_FEATURE_CFDC) - goto no_cfdc; - atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_UNIT_SHARED | ZFCP_STATUS_UNIT_READONLY, &unit->status); - if (!allowed) - atomic_set_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status); - - if (!adapter->supported_features & FSF_FEATURE_LUN_SHARING) - goto no_lun_sharing; - - if (!exclusive) - atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); - - if (!readwrite) { - atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); - ZFCP_LOG_NORMAL("Unit 0x%016Lx on port 0x%016Lx on adapter %s " - "accessed read-only\n", unit->fcp_lun, - unit->port->wwpn, zfcp_get_busid_by_unit(unit)); - } - - if (exclusive && !readwrite) { - ZFCP_LOG_NORMAL("Exclusive access of read-only unit not " - "supported\n"); - zfcp_erp_unit_failed(unit); - fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; - goto skip_fsfstatus; - } - if (!exclusive && readwrite) { - ZFCP_LOG_NORMAL("Shared access of read-write unit is not " - "supported\n"); - zfcp_erp_unit_failed(unit); - fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; - goto skip_fsfstatus; - } - - no_lun_sharing: - no_cfdc: - if (!(adapter->supported_features & FSF_FEATURE_CFDC) && - (adapter->supported_features & FSF_FEATURE_LUN_SHARING)) { - ZFCP_LOG_NORMAL("LUN sharing without access control is not " - "supported.\n"); - zfcp_erp_unit_failed(unit); - fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; - goto skip_fsfstatus; - } - - /* evaluate FSF status in QTCB */ switch (header->fsf_status) { @@ -3196,6 +3149,8 @@ } debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); zfcp_erp_unit_access_denied(unit); + atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); + atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; Index: wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_scsi.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/s390/scsi/zfcp_scsi.c 2004-12-16 06:19:43.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/s390/scsi/zfcp_scsi.c 2004-12-22 10:04:36.236294098 -0800 @@ -31,8 +31,7 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_SCSI_REVISION "$Revision: 1.73 $" +#define ZFCP_SCSI_REVISION "$Revision: 1.74 $" #include "zfcp_ext.h" Index: wli-2.6.10-rc3-1/drivers/sbus/char/rtc.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/sbus/char/rtc.c 2004-12-22 10:13:56.619102962 -0800 +++ wli-2.6.10-rc3-1/drivers/sbus/char/rtc.c 2004-12-22 10:52:10.213423626 -0800 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +31,7 @@ /* Retrieve the current date and time from the real time clock. */ static void get_rtc_time(struct rtc_time *t) { - unsigned long regs = mstk48t02_regs; + void * __iomem regs = mstk48t02_regs; u8 tmp; spin_lock_irq(&mostek_lock); @@ -57,7 +58,7 @@ /* Set the current date and time inthe real time clock. */ void set_rtc_time(struct rtc_time *t) { - unsigned long regs = mstk48t02_regs; + void * __iomem regs = mstk48t02_regs; u8 tmp; spin_lock_irq(&mostek_lock); Index: wli-2.6.10-rc3-1/drivers/sbus/sbus.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/sbus/sbus.c 2004-12-22 10:14:01.799315450 -0800 +++ wli-2.6.10-rc3-1/drivers/sbus/sbus.c 2004-12-22 10:28:47.118726442 -0800 @@ -217,6 +217,8 @@ * prom_sbus_ranges_init(), with all sun4d stuff cut away. * Ask DaveM what is going on here, how is sun4d supposed to work... XXX */ +/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ + static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus) { int len; @@ -229,6 +231,18 @@ return; } sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges); + if (sparc_cpu_model == sun4d) { + struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; + int num_iounit_ranges; + + len = prom_getproperty(parent_node, "ranges", + (char *) iounit_ranges, + sizeof (iounit_ranges)); + if (len != -1) { + num_iounit_ranges = (len/sizeof(struct linux_prom_ranges)); + prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges); + } + } } static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, Index: wli-2.6.10-rc3-1/drivers/scsi/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/Kconfig 2004-12-16 06:19:43.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/Kconfig 2004-12-22 10:04:36.243293034 -0800 @@ -1767,7 +1767,7 @@ config ZFCP tristate "FCP host bus adapter driver for IBM eServer zSeries" - depends on ARCH_S390 && SCSI + depends on ARCH_S390 && QDIO && SCSI select SCSI_FC_ATTRS help If you want to access SCSI devices attached to your IBM eServer Index: wli-2.6.10-rc3-1/drivers/scsi/aacraid/aachba.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/aacraid/aachba.c 2004-12-16 06:19:44.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/aacraid/aachba.c 2004-12-22 10:04:36.300284370 -0800 @@ -645,9 +645,31 @@ dev->adapter_info.serial[1]); dev->nondasd_support = 0; + dev->raid_scsi_mode = 0; if(dev->adapter_info.options & AAC_OPT_NONDASD){ dev->nondasd_support = 1; } + + /* + * If the firmware supports ROMB RAID/SCSI mode and we are currently + * in RAID/SCSI mode, set the flag. For now if in this mode we will + * force nondasd support on. If we decide to allow the non-dasd flag + * additional changes changes will have to be made to support + * RAID/SCSI. the function aac_scsi_cmd in this module will have to be + * changed to support the new dev->raid_scsi_mode flag instead of + * leaching off of the dev->nondasd_support flag. Also in linit.c the + * function aac_detect will have to be modified where it sets up the + * max number of channels based on the aac->nondasd_support flag only. + */ + if ((dev->adapter_info.options & AAC_OPT_SCSI_MANAGED) && + (dev->adapter_info.options & AAC_OPT_RAID_SCSI_MODE)) { + dev->nondasd_support = 1; + dev->raid_scsi_mode = 1; + } + if (dev->raid_scsi_mode != 0) + printk(KERN_INFO "%s%d: ROMB RAID/SCSI mode enabled\n", + dev->name, dev->id); + if(nondasd != -1) { dev->nondasd_support = (nondasd!=0); } @@ -1137,7 +1159,7 @@ char *cp; dprintk((KERN_DEBUG "READ CAPACITY command.\n")); - if (fsa_dev_ptr[cid].size <= 0x100000000) + if (fsa_dev_ptr[cid].size <= 0x100000000LL) capacity = fsa_dev_ptr[cid].size - 1; else capacity = (u32)-1; @@ -1446,8 +1468,17 @@ if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER || (b==TYPE_DISK && (b1&0x80)) ){ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + /* + * We will allow disk devices if in RAID/SCSI mode and + * the channel is 2 + */ + } else if ((dev->raid_scsi_mode) && + (scsicmd->device->channel == 2)) { + scsicmd->result = DID_OK << 16 | + COMMAND_COMPLETE << 8; } else { - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + scsicmd->result = DID_NO_CONNECT << 16 | + COMMAND_COMPLETE << 8; } } else { scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; @@ -1479,8 +1510,17 @@ if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER || (b==TYPE_DISK && (b1&0x80)) ){ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + /* + * We will allow disk devices if in RAID/SCSI mode and + * the channel is 2 + */ + } else if ((dev->raid_scsi_mode) && + (scsicmd->device->channel == 2)) { + scsicmd->result = DID_OK << 16 | + COMMAND_COMPLETE << 8; } else { - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + scsicmd->result = DID_NO_CONNECT << 16 | + COMMAND_COMPLETE << 8; } break; } Index: wli-2.6.10-rc3-1/drivers/scsi/aacraid/aacraid.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/aacraid/aacraid.h 2004-12-16 06:19:44.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/aacraid/aacraid.h 2004-12-22 10:04:36.305283610 -0800 @@ -805,6 +805,8 @@ #define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) #define AAC_OPT_ALARM cpu_to_le32(1<<11) #define AAC_OPT_NONDASD cpu_to_le32(1<<12) +#define AAC_OPT_SCSI_MANAGED cpu_to_le32(1<<13) +#define AAC_OPT_RAID_SCSI_MODE cpu_to_le32(1<<14) struct aac_dev { @@ -877,6 +879,7 @@ */ u8 nondasd_support; u8 dac_support; + u8 raid_scsi_mode; }; #define aac_adapter_interrupt(dev) \ Index: wli-2.6.10-rc3-1/drivers/scsi/aacraid/linit.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/aacraid/linit.c 2004-12-16 06:19:44.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/aacraid/linit.c 2004-12-22 10:04:36.309283002 -0800 @@ -663,10 +663,9 @@ kfree(aac->fibs); + list_del(&aac->entry); scsi_host_put(shost); pci_disable_device(pdev); - - list_del(&aac->entry); } static struct pci_driver aac_pci_driver = { Index: wli-2.6.10-rc3-1/drivers/scsi/ahci.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/ahci.c 2004-12-16 06:19:44.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/ahci.c 2004-12-22 10:04:36.247292426 -0800 @@ -229,7 +229,8 @@ { .sht = &ahci_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO, + ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_PIO_DMA, .pio_mask = 0x03, /* pio3-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, Index: wli-2.6.10-rc3-1/drivers/scsi/aic7xxx/aic79xx_osm.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/aic7xxx/aic79xx_osm.h 2004-12-16 06:19:44.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/aic7xxx/aic79xx_osm.h 2004-12-22 10:04:36.313282394 -0800 @@ -540,7 +540,7 @@ uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ - dma_addr_t hw_dma_mask; + uint64_t hw_dma_mask; ahd_linux_softc_flags flags; }; Index: wli-2.6.10-rc3-1/drivers/scsi/aic7xxx/aic79xx_osm_pci.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/aic7xxx/aic79xx_osm_pci.c 2004-12-16 06:19:44.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/aic7xxx/aic79xx_osm_pci.c 2004-12-22 10:04:36.316281938 -0800 @@ -170,24 +170,22 @@ if (sizeof(dma_addr_t) > 4) { uint64_t memsize; - dma_addr_t mask_64bit; - dma_addr_t mask_39bit; + const uint64_t mask_39bit = 0x7FFFFFFFFFULL; memsize = ahd_linux_get_memsize(); - mask_64bit = (dma_addr_t)0xFFFFFFFFFFFFFFFFULL; - mask_39bit = (dma_addr_t)0x7FFFFFFFFFULL; + if (memsize >= 0x8000000000ULL - && pci_set_dma_mask(pdev, mask_64bit) == 0) { + && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { ahd->flags |= AHD_64BIT_ADDRESSING; - ahd->platform_data->hw_dma_mask = mask_64bit; + ahd->platform_data->hw_dma_mask = DMA_64BIT_MASK; } else if (memsize > 0x80000000 && pci_set_dma_mask(pdev, mask_39bit) == 0) { ahd->flags |= AHD_39BIT_ADDRESSING; ahd->platform_data->hw_dma_mask = mask_39bit; } } else { - pci_set_dma_mask(pdev, 0xFFFFFFFF); - ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; + pci_set_dma_mask(pdev, DMA_32BIT_MASK); + ahd->platform_data->hw_dma_mask = DMA_32BIT_MASK; } ahd->dev_softc = pci; error = ahd_pci_config(ahd, entry); Index: wli-2.6.10-rc3-1/drivers/scsi/aic7xxx/aic7xxx_osm.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-12-16 06:19:44.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-12-22 10:04:36.320281330 -0800 @@ -545,7 +545,7 @@ uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ - dma_addr_t hw_dma_mask; + uint64_t hw_dma_mask; ahc_linux_softc_flags flags; }; Index: wli-2.6.10-rc3-1/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c 2004-12-16 06:19:44.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c 2004-12-22 10:04:36.323280874 -0800 @@ -175,7 +175,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { char buf[80]; - dma_addr_t mask_39bit; + const uint64_t mask_39bit = 0x7FFFFFFFFFULL; struct ahc_softc *ahc; ahc_dev_softc_t pci; struct ahc_pci_identity *entry; @@ -226,18 +226,17 @@ } pci_set_master(pdev); - mask_39bit = 0x7FFFFFFFFFULL; if (sizeof(dma_addr_t) > 4 && ahc_linux_get_memsize() > 0x80000000 && pci_set_dma_mask(pdev, mask_39bit) == 0) { ahc->flags |= AHC_39BIT_ADDRESSING; ahc->platform_data->hw_dma_mask = mask_39bit; } else { - if (pci_set_dma_mask(pdev, 0xFFFFFFFF)) { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); return (-ENODEV); } - ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; + ahc->platform_data->hw_dma_mask = DMA_32BIT_MASK; } #endif ahc->dev_softc = pci; Index: wli-2.6.10-rc3-1/drivers/scsi/imm.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/imm.c 2004-12-22 09:07:09.350300418 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/imm.c 2004-12-22 10:04:36.252291666 -0800 @@ -1140,6 +1140,10 @@ .use_clustering = ENABLE_CLUSTERING, .can_queue = 1, .slave_alloc = imm_adjust_queue, + .unchecked_isa_dma = 1, /* imm cannot deal with highmem, so + * this is an easy trick to ensure + * all io pages for this host reside + * in low memory */ }; /*************************************************************************** Index: wli-2.6.10-rc3-1/drivers/scsi/libata-core.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/libata-core.c 2004-12-16 06:19:45.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/libata-core.c 2004-12-22 10:04:36.263289994 -0800 @@ -1950,8 +1950,6 @@ sg->page = virt_to_page(buf); sg->offset = (unsigned long) buf & ~PAGE_MASK; sg_dma_len(sg) = buflen; - - WARN_ON(buflen > PAGE_SIZE); } void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, @@ -2693,6 +2691,30 @@ VPRINTK("EXIT\n"); } +static inline int ata_should_dma_map(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + case ATA_PROT_ATAPI_DMA: + return 1; + + case ATA_PROT_ATAPI: + case ATA_PROT_PIO: + case ATA_PROT_PIO_MULT: + if (ap->flags & ATA_FLAG_PIO_DMA) + return 1; + + /* fall through */ + + default: + return 0; + } + + /* never reached */ +} + /** * ata_qc_issue - issue taskfile to device * @qc: command to issue to device @@ -2713,12 +2735,16 @@ { struct ata_port *ap = qc->ap; - if (qc->flags & ATA_QCFLAG_SG) { - if (ata_sg_setup(qc)) - goto err_out; - } else if (qc->flags & ATA_QCFLAG_SINGLE) { - if (ata_sg_setup_one(qc)) - goto err_out; + if (ata_should_dma_map(qc)) { + if (qc->flags & ATA_QCFLAG_SG) { + if (ata_sg_setup(qc)) + goto err_out; + } else if (qc->flags & ATA_QCFLAG_SINGLE) { + if (ata_sg_setup_one(qc)) + goto err_out; + } + } else { + qc->flags &= ~ATA_QCFLAG_DMAMAP; } ap->ops->qc_prep(qc); Index: wli-2.6.10-rc3-1/drivers/scsi/libata-scsi.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/libata-scsi.c 2004-12-16 06:19:45.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/libata-scsi.c 2004-12-22 10:04:36.268289234 -0800 @@ -898,7 +898,7 @@ }; memcpy(rbuf, hdr, sizeof(hdr)); - if (buflen > (ATA_SERNO_LEN + 4)) + if (buflen > (ATA_SERNO_LEN + 4 - 1)) ata_dev_id_string(args->id, (unsigned char *) &rbuf[4], ATA_ID_SERNO_OFS, ATA_SERNO_LEN); @@ -927,7 +927,7 @@ rbuf[3] = 4 + strlen(inq_83_str); /* page len */ /* our one and only identification descriptor (vendor-specific) */ - if (buflen > (strlen(inq_83_str) + 4 + 4)) { + if (buflen > (strlen(inq_83_str) + 4 + 4 - 1)) { rbuf[4 + 0] = 2; /* code set: ASCII */ rbuf[4 + 3] = strlen(inq_83_str); memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str)); Index: wli-2.6.10-rc3-1/drivers/scsi/megaraid/megaraid_ioctl.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/megaraid/megaraid_ioctl.h 2004-12-16 06:19:45.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/megaraid/megaraid_ioctl.h 2004-12-22 10:04:36.326280418 -0800 @@ -142,7 +142,7 @@ caddr_t buf_vaddr; dma_addr_t buf_paddr; - uint8_t pool_index; + int8_t pool_index; uint8_t free_buf; uint8_t timedout; Index: wli-2.6.10-rc3-1/drivers/scsi/megaraid/megaraid_mm.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/megaraid/megaraid_mm.c 2004-12-16 06:19:45.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/megaraid/megaraid_mm.c 2004-12-22 10:04:36.331279658 -0800 @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_mm.c - * Version : v2.20.2.2 (Nov 04 2004) + * Version : v2.20.2.3 (Dec 09 2004) * * Common management module */ @@ -614,23 +614,27 @@ mm_dmapool_t *pool; unsigned long flags; - pool = &adp->dma_pool_list[kioc->pool_index]; + if (kioc->pool_index != -1) { + pool = &adp->dma_pool_list[kioc->pool_index]; - /* This routine may be called in non-isr context also */ - spin_lock_irqsave(&pool->lock, flags); + /* This routine may be called in non-isr context also */ + spin_lock_irqsave(&pool->lock, flags); - /* - * While attaching the dma buffer, if we didn't get the required - * buffer from the pool, we would have allocated it at the run time - * and set the free_buf flag. We must free that buffer. Otherwise, - * just mark that the buffer is not in use - */ - if (kioc->free_buf == 1) - pci_pool_free(pool->handle, kioc->buf_vaddr, kioc->buf_paddr); - else - pool->in_use = 0; + /* + * While attaching the dma buffer, if we didn't get the + * required buffer from the pool, we would have allocated + * it at the run time and set the free_buf flag. We must + * free that buffer. Otherwise, just mark that the buffer is + * not in use + */ + if (kioc->free_buf == 1) + pci_pool_free(pool->handle, kioc->buf_vaddr, + kioc->buf_paddr); + else + pool->in_use = 0; - spin_unlock_irqrestore(&pool->lock, flags); + spin_unlock_irqrestore(&pool->lock, flags); + } /* Return the kioc to the free pool */ spin_lock_irqsave(&adp->kioc_pool_lock, flags); Index: wli-2.6.10-rc3-1/drivers/scsi/megaraid/megaraid_mm.h =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/megaraid/megaraid_mm.h 2004-12-16 06:19:45.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/megaraid/megaraid_mm.h 2004-12-22 10:04:36.332279506 -0800 @@ -29,10 +29,9 @@ #include "megaraid_ioctl.h" -#define LSI_COMMON_MOD_VERSION "2.20.2.2" +#define LSI_COMMON_MOD_VERSION "2.20.2.3" #define LSI_COMMON_MOD_EXT_VERSION \ - "(Release Date: Thu Nov 4 17:46:29 EST 2004)" - + "(Release Date: Thu Dec 9 19:02:14 EST 2004)" #define LSI_DBGLVL dbglevel Index: wli-2.6.10-rc3-1/drivers/scsi/qla2xxx/qla_rscn.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/qla2xxx/qla_rscn.c 2004-12-16 06:19:48.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/qla2xxx/qla_rscn.c 2004-12-22 10:04:36.339278442 -0800 @@ -47,8 +47,6 @@ /* Local Prototypes. */ static inline uint32_t qla2x00_to_handle(uint16_t, uint16_t, uint16_t); static inline uint16_t qla2x00_handle_to_idx(uint32_t); -static inline uint16_t qla2x00_handle_to_iter(uint32_t); -static inline uint16_t qla2x00_handle_to_type(uint32_t); static inline uint32_t qla2x00_iodesc_to_handle(struct io_descriptor *); static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *, uint32_t); @@ -130,30 +128,6 @@ } /** - * qla2x00_handle_to_type() - Retrive the descriptor type for a given handle. - * @handle: descriptor handle - * - * Returns the descriptor type specified by the @handle. - */ -static inline uint16_t -qla2x00_handle_to_type(uint32_t handle) -{ - return ((uint16_t)(((handle) >> HDL_TYPE_SHIFT) & HDL_TYPE_MASK)); -} - -/** - * qla2x00_handle_to_iter() - Retrive the rolling signature for a given handle. - * @handle: descriptor handle - * - * Returns the signature specified by the @handle. - */ -static inline uint16_t -qla2x00_handle_to_iter(uint32_t handle) -{ - return ((uint16_t)(((handle) >> HDL_ITER_SHIFT) & HDL_ITER_MASK)); -} - -/** * qla2x00_iodesc_to_handle() - Convert an IO descriptor to a unique handle. * @iodesc: io descriptor * Index: wli-2.6.10-rc3-1/drivers/scsi/scsi_devinfo.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/scsi_devinfo.c 2004-12-16 06:19:48.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/scsi_devinfo.c 2004-12-22 10:04:36.272288626 -0800 @@ -118,6 +118,7 @@ * Other types of devices that have special flags. * Note that all USB devices should have the BLIST_INQUIRY_36 flag. */ + {"3PARdata", "VV", NULL, BLIST_REPORTLUN2}, {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN}, {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN}, {"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN}, Index: wli-2.6.10-rc3-1/drivers/scsi/scsi_lib.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/scsi_lib.c 2004-12-16 06:19:48.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/scsi_lib.c 2004-12-22 10:04:36.278287714 -0800 @@ -728,7 +728,7 @@ req->sense_len = len; } } else - req->data_len -= cmd->bufflen; + req->data_len = cmd->resid; } /* Index: wli-2.6.10-rc3-1/drivers/scsi/scsi_transport_spi.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/scsi_transport_spi.c 2004-12-16 06:19:48.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/scsi_transport_spi.c 2004-12-22 10:04:36.282287106 -0800 @@ -361,9 +361,8 @@ enum spi_signal_type type = spi_signal_to_value(buf); if (type != SPI_SIGNAL_UNKNOWN) - return count; + i->f->set_signalling(shost, type); - i->f->set_signalling(shost, type); return count; } static CLASS_DEVICE_ATTR(signalling, S_IRUGO | S_IWUSR, @@ -635,7 +634,11 @@ /* OK, now we have our initial speed set by the read only inquiry * test, now try an echo buffer test (if the device allows it) */ - if ((len = spi_dv_device_get_echo_buffer(sreq, buffer)) == 0) { + len = 0; + if (sdev->ppr) + len = spi_dv_device_get_echo_buffer(sreq, buffer); + + if (len == 0) { SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n"); return; } Index: wli-2.6.10-rc3-1/drivers/scsi/sd.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/sd.c 2004-12-16 06:19:48.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/sd.c 2004-12-22 10:04:36.287286346 -0800 @@ -198,8 +198,8 @@ static void scsi_disk_put(struct scsi_disk *sdkp) { down(&sd_ref_sem); - scsi_device_put(sdkp->device); kref_put(&sdkp->kref, scsi_disk_release); + scsi_device_put(sdkp->device); up(&sd_ref_sem); } Index: wli-2.6.10-rc3-1/drivers/scsi/sr.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/scsi/sr.c 2004-12-16 06:19:48.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/scsi/sr.c 2004-12-22 10:04:36.291285738 -0800 @@ -156,8 +156,8 @@ static inline void scsi_cd_put(struct scsi_cd *cd) { down(&sr_ref_sem); - scsi_device_put(cd->device); kref_put(&cd->kref, sr_kref_release); + scsi_device_put(cd->device); up(&sr_ref_sem); } Index: wli-2.6.10-rc3-1/drivers/serial/amba-pl010.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/serial/amba-pl010.c 2004-12-16 06:19:49.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/serial/amba-pl010.c 2004-12-22 10:04:36.343277834 -0800 @@ -710,6 +710,24 @@ .data = &amba_reg, }; +static int __init amba_console_init(void) +{ + /* + * All port initializations are done statically + */ + register_console(&amba_console); + return 0; +} +console_initcall(amba_console_init); + +static int __init amba_late_console_init(void) +{ + if (!(amba_console.flags & CON_ENABLED)) + register_console(&amba_console); + return 0; +} +late_initcall(amba_late_console_init); + #define AMBA_CONSOLE &amba_console #else #define AMBA_CONSOLE NULL Index: wli-2.6.10-rc3-1/drivers/serial/serial_core.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/serial/serial_core.c 2004-12-16 06:19:49.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/serial/serial_core.c 2004-12-22 10:04:36.352276466 -0800 @@ -584,8 +584,10 @@ tmp.flags = port->flags; tmp.xmit_fifo_size = port->fifosize; tmp.baud_base = port->uartclk / 16; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; + tmp.close_delay = state->close_delay / 10; + tmp.closing_wait = state->closing_wait == USF_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + state->closing_wait / 10; tmp.custom_divisor = port->custom_divisor; tmp.hub6 = port->hub6; tmp.io_type = port->iotype; @@ -603,8 +605,8 @@ struct serial_struct new_serial; struct uart_port *port = state->port; unsigned long new_port; - unsigned int change_irq, change_port, old_flags; - unsigned int old_custom_divisor; + unsigned int change_irq, change_port, old_flags, closing_wait; + unsigned int old_custom_divisor, close_delay; int retval = 0; if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) @@ -615,6 +617,9 @@ new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; new_serial.irq = irq_canonicalize(new_serial.irq); + close_delay = new_serial.close_delay * 10; + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + USF_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; /* * This semaphore protects state->count. It is also @@ -646,8 +651,8 @@ retval = -EPERM; if (change_irq || change_port || (new_serial.baud_base != port->uartclk / 16) || - (new_serial.close_delay != state->close_delay) || - (new_serial.closing_wait != state->closing_wait) || + (close_delay != state->close_delay) || + (closing_wait != state->closing_wait) || (new_serial.xmit_fifo_size != port->fifosize) || (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0)) goto exit; @@ -751,8 +756,8 @@ port->flags = (port->flags & ~UPF_CHANGE_MASK) | (new_serial.flags & UPF_CHANGE_MASK); port->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ / 100; - state->closing_wait = new_serial.closing_wait * HZ / 100; + state->close_delay = close_delay; + state->closing_wait = closing_wait; port->fifosize = new_serial.xmit_fifo_size; if (state->info->tty) state->info->tty->low_latency = @@ -1191,7 +1196,7 @@ tty->closing = 1; if (state->closing_wait != USF_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, state->closing_wait); + tty_wait_until_sent(tty, msecs_to_jiffies(state->closing_wait)); /* * At this point, we stop accepting input. To do this, we @@ -1219,9 +1224,8 @@ state->info->tty = NULL; if (state->info->blocked_open) { - if (state->close_delay) { - msleep_interruptible(jiffies_to_msecs(state->close_delay)); - } + if (state->close_delay) + msleep_interruptible(state->close_delay); } else if (!uart_console(port)) { uart_change_pm(state, 3); } @@ -2082,8 +2086,8 @@ for (i = 0; i < drv->nr; i++) { struct uart_state *state = drv->state + i; - state->close_delay = 5 * HZ / 10; - state->closing_wait = 30 * HZ; + state->close_delay = 500; /* .5 seconds */ + state->closing_wait = 30000; /* 30 seconds */ init_MUTEX(&state->sem); } Index: wli-2.6.10-rc3-1/drivers/serial/sunsab.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/serial/sunsab.c 2004-12-16 06:19:49.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/serial/sunsab.c 2004-12-22 10:04:36.357275706 -0800 @@ -143,6 +143,11 @@ writeb(SAB82532_CMDR_RMC, &up->regs->w.cmdr); } + /* Count may be zero for BRK, so we check for it here */ + if ((stat->sreg.isr1 & SAB82532_ISR1_BRK) && + (up->port.line == up->port.cons->index)) + saw_console_brk = 1; + for (i = 0; i < count; i++) { unsigned char ch = buf[i]; @@ -172,8 +177,6 @@ stat->sreg.isr0 &= ~(SAB82532_ISR0_PERR | SAB82532_ISR0_FERR); up->port.icount.brk++; - if (up->port.line == up->port.cons->index) - saw_console_brk = 1; /* * We do the SysRQ and SAK checking * here because otherwise the break @@ -325,8 +328,9 @@ tty = NULL; if (status.stat) { - if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | - SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) + if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | + SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) || + (status.sreg.isr1 & SAB82532_ISR1_BRK)) tty = receive_chars(up, &status, regs); if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) || (status.sreg.isr1 & SAB82532_ISR1_CSC)) @@ -352,8 +356,10 @@ tty = NULL; if (status.stat) { - if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | - SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) + if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | + SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) || + (status.sreg.isr1 & SAB82532_ISR1_BRK)) + tty = receive_chars(up, &status, regs); if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) || (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC))) Index: wli-2.6.10-rc3-1/drivers/serial/sunsu.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/serial/sunsu.c 2004-12-22 10:13:56.860066330 -0800 +++ wli-2.6.10-rc3-1/drivers/serial/sunsu.c 2004-12-22 10:48:34.355239058 -0800 @@ -1285,7 +1285,9 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel) { +#ifdef CONFIG_SERIO struct serio *serio; +#endif up->port.line = channel; up->port.type = PORT_UNKNOWN; Index: wli-2.6.10-rc3-1/drivers/usb/core/devio.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/core/devio.c 2004-12-16 06:19:49.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/core/devio.c 2004-12-22 10:04:36.363274794 -0800 @@ -523,13 +523,12 @@ usb_lock_device(dev); list_del_init(&ps->list); - - if (connected(dev)) { - for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); ifnum++) - if (test_bit(ifnum, &ps->ifclaimed)) - releaseintf(ps, ifnum); - destroy_all_async(ps); + for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); + ifnum++) { + if (test_bit(ifnum, &ps->ifclaimed)) + releaseintf(ps, ifnum); } + destroy_all_async(ps); usb_unlock_device(dev); usb_put_dev(dev); ps->dev = NULL; @@ -1023,7 +1022,7 @@ int ret; add_wait_queue(&ps->wait, &wait); - while (connected(dev)) { + for (;;) { __set_current_state(TASK_INTERRUPTIBLE); if ((as = async_getcompleted(ps))) break; Index: wli-2.6.10-rc3-1/drivers/usb/core/inode.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/core/inode.c 2004-12-16 06:19:49.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/core/inode.c 2004-12-22 10:04:36.366274338 -0800 @@ -695,7 +695,7 @@ for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) { struct usb_config_descriptor *config = (struct usb_config_descriptor *)dev->rawdescriptors[i]; - i_size += le16_to_cpu (config->wTotalLength); + i_size += le16_to_cpu ((__force __le16)config->wTotalLength); } if (dev->usbfs_dentry->d_inode) dev->usbfs_dentry->d_inode->i_size = i_size; @@ -715,6 +715,7 @@ } while (!list_empty(&dev->filelist)) { ds = list_entry(dev->filelist.next, struct dev_state, list); + wake_up_all(&ds->wait); list_del_init(&ds->list); if (ds->discsignr) { sinfo.si_signo = SIGPIPE; Index: wli-2.6.10-rc3-1/drivers/usb/host/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/Kconfig 2004-12-16 06:19:50.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/Kconfig 2004-12-22 10:04:36.368274034 -0800 @@ -100,14 +100,16 @@ To compile this driver as a module, choose M here: the module will be called uhci-hcd. -config USB_SL811HS - tristate "SL811HS support" - depends on ARM && USB +config USB_SL811_HCD + tristate "SL811HS HCD support" + depends on USB + default N help - Say Y here if you have a SL811HS USB host controller in your system. - - If you do not know what this is, please say N. + The SL811HS is a single-port USB controller that supports either + host side or peripheral side roles. Enable this option if your + board has this chip, and you want to use it as a host controller. + If unsure, say N. To compile this driver as a module, choose M here: the - module will be called hc_sl811. + module will be called sl811-hcd. Index: wli-2.6.10-rc3-1/drivers/usb/host/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/Makefile 2004-12-16 06:19:50.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/Makefile 2004-12-22 10:04:36.370273730 -0800 @@ -6,6 +6,5 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o - -obj-$(CONFIG_USB_SL811HS) += hc_sl811.o +obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o Index: wli-2.6.10-rc3-1/drivers/usb/host/ehci-hub.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/ehci-hub.c 2004-12-16 06:19:50.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/ehci-hub.c 2004-12-22 10:04:36.373273274 -0800 @@ -122,7 +122,7 @@ writel (temp, &ehci->regs->port_status [i]); } i = HCS_N_PORTS (ehci->hcs_params); - msleep (20); + mdelay (20); while (i--) { temp = readl (&ehci->regs->port_status [i]); if ((temp & PORT_SUSPEND) == 0) @@ -286,7 +286,7 @@ if (HCS_INDICATOR (ehci->hcs_params)) temp |= 0x0080; /* per-port indicators (LEDs) */ #endif - desc->wHubCharacteristics = cpu_to_le16 (temp); + desc->wHubCharacteristics = (__force __u16)cpu_to_le16 (temp); } /*-------------------------------------------------------------------------*/ Index: wli-2.6.10-rc3-1/drivers/usb/host/ehci-q.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/ehci-q.c 2004-12-16 06:19:50.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/ehci-q.c 2004-12-22 10:04:36.380272210 -0800 @@ -83,19 +83,59 @@ /*-------------------------------------------------------------------------*/ -/* update halted (but potentially linked) qh */ - static inline void qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) { + /* writes to an active overlay are unsafe */ + BUG_ON(qh->qh_state != QH_STATE_IDLE); + qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma); qh->hw_alt_next = EHCI_LIST_END; + /* Except for control endpoints, we make hardware maintain data + * toggle (like OHCI) ... here (re)initialize the toggle in the QH, + * and set the pseudo-toggle in udev. Only usb_clear_halt() will + * ever clear it. + */ + if (!(qh->hw_info1 & cpu_to_le32(1 << 14))) { + unsigned is_out, epnum; + + is_out = !(qtd->hw_token & cpu_to_le32(1 << 8)); + epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f; + if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { + qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE); + usb_settoggle (qh->dev, epnum, is_out, 1); + } + } + /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ wmb (); qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING); } +/* if it weren't for a common silicon quirk (writing the dummy into the qh + * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault + * recovery (including urb dequeue) would need software changes to a QH... + */ +static void +qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + struct ehci_qtd *qtd; + + if (list_empty (&qh->qtd_list)) + qtd = qh->dummy; + else { + qtd = list_entry (qh->qtd_list.next, + struct ehci_qtd, qtd_list); + /* first qtd may already be partially processed */ + if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current) + qtd = NULL; + } + + if (qtd) + qh_update (ehci, qh, qtd); +} + /*-------------------------------------------------------------------------*/ static void qtd_copy_status ( @@ -226,6 +266,11 @@ spin_lock (&ehci->lock); } +static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); + +static void intr_deschedule (struct ehci_hcd *ehci, + struct ehci_qh *qh, int wait); +static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); /* * Process and free completed qtds for a qh, returning URBs to drivers. @@ -369,21 +414,27 @@ /* restore original state; caller must unlink or relink */ qh->qh_state = state; - /* update qh after fault cleanup */ - if (unlikely (stopped != 0) - /* some EHCI 0.95 impls will overlay dummy qtds */ - || qh->hw_qtd_next == EHCI_LIST_END) { - if (list_empty (&qh->qtd_list)) - end = qh->dummy; - else { - end = list_entry (qh->qtd_list.next, - struct ehci_qtd, qtd_list); - /* first qtd may already be partially processed */ - if (cpu_to_le32 (end->qtd_dma) == qh->hw_current) - end = NULL; + /* be sure the hardware's done with the qh before refreshing + * it after fault cleanup, or recovering from silicon wrongly + * overlaying the dummy qtd (which reduces DMA chatter). + */ + if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END) { + switch (state) { + case QH_STATE_IDLE: + qh_refresh(ehci, qh); + break; + case QH_STATE_LINKED: + /* should be rare for periodic transfers, + * except maybe high bandwidth ... + */ + if (qh->period) { + intr_deschedule (ehci, qh, 1); + (void) qh_schedule (ehci, qh); + } else + start_unlink_async (ehci, qh); + break; + /* otherwise, unlink already started */ } - if (end) - qh_update (ehci, qh, end); } return count; @@ -557,21 +608,6 @@ /*-------------------------------------------------------------------------*/ -/* - * Hardware maintains data toggle (like OHCI) ... here we (re)initialize - * the hardware data toggle in the QH, and set the pseudo-toggle in udev - * so we can see if usb_clear_halt() was called. NOP for control, since - * we set up qh->hw_info1 to always use the QTD toggle bits. - */ -static inline void -clear_toggle (struct usb_device *udev, int ep, int is_out, struct ehci_qh *qh) -{ - vdbg ("clear toggle, dev %d ep 0x%x-%s", - udev->devnum, ep, is_out ? "out" : "in"); - qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE); - usb_settoggle (udev, ep, is_out, 1); -} - // Would be best to create all qh's from config descriptors, // when each interface/altsetting is established. Unlink // any previous qh and cancel its urbs first; endpoints are @@ -651,11 +687,11 @@ qh->period = urb->interval; } - - /* support for tt scheduling */ - qh->dev = usb_get_dev (urb->dev); } + /* support for tt scheduling, and access to toggles */ + qh->dev = usb_get_dev (urb->dev); + /* using TT? */ switch (urb->dev->speed) { case USB_SPEED_LOW: @@ -715,8 +751,8 @@ qh->qh_state = QH_STATE_IDLE; qh->hw_info1 = cpu_to_le32 (info1); qh->hw_info2 = cpu_to_le32 (info2); - qh_update (ehci, qh, qh->dummy); usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); + qh_refresh (ehci, qh); return qh; } @@ -745,7 +781,9 @@ } } - qh->hw_token &= ~HALT_BIT; + /* clear halt and/or toggle; and maybe recover from silicon quirk */ + if (qh->qh_state == QH_STATE_IDLE) + qh_refresh (ehci, qh); /* splice right after start */ qh->qh_next = head->qh_next; @@ -820,27 +858,8 @@ qh->hw_info1 &= ~QH_ADDR_MASK; } - /* usb_clear_halt() means qh data toggle gets reset */ - if (unlikely (!usb_gettoggle (urb->dev, - (epnum & 0x0f), !(epnum & 0x10))) - && !usb_pipecontrol (urb->pipe)) { - /* "never happens": drivers do stall cleanup right */ - if (qh->qh_state != QH_STATE_IDLE - && !list_empty (&qh->qtd_list) - && qh->qh_state != QH_STATE_COMPLETING) - ehci_warn (ehci, "clear toggle dev%d " - "ep%d%s: not idle\n", - usb_pipedevice (urb->pipe), - epnum & 0x0f, - usb_pipein (urb->pipe) - ? "in" : "out"); - /* else we know this overlay write is safe */ - clear_toggle (urb->dev, - epnum & 0x0f, !(epnum & 0x10), qh); - } - /* just one way to queue requests: swap with the dummy qtd. - * only hc or qh_completions() usually modify the overlay. + * only hc or qh_refresh() ever modify the overlay. */ if (likely (qtd != 0)) { struct ehci_qtd *dummy; @@ -936,8 +955,6 @@ /* the async qh for the qtds being reclaimed are now unlinked from the HC */ -static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); - static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs) { struct ehci_qh *qh = ehci->reclaim; Index: wli-2.6.10-rc3-1/drivers/usb/host/ehci-sched.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/ehci-sched.c 2004-12-16 06:19:50.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/ehci-sched.c 2004-12-22 10:04:36.387271146 -0800 @@ -325,7 +325,7 @@ status = disable_periodic (ehci); else { status = 0; - vdbg ("periodic schedule still enabled"); + ehci_vdbg (ehci, "periodic schedule still enabled\n"); } /* @@ -342,7 +342,7 @@ * the race is very short. then if qh also isn't * rescheduled soon, it won't matter. otherwise... */ - vdbg ("intr_deschedule..."); + ehci_vdbg (ehci, "intr_deschedule...\n"); } } else qh->hw_next = EHCI_LIST_END; @@ -450,6 +450,7 @@ __le32 c_mask; unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ + qh_refresh(ehci, qh); qh->hw_next = EHCI_LIST_END; frame = qh->start; Index: wli-2.6.10-rc3-1/drivers/usb/host/hc_crisv10.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/hc_crisv10.c 2004-12-16 06:19:50.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/hc_crisv10.c 2004-12-22 10:04:36.402268866 -0800 @@ -30,7 +30,7 @@ #include <../drivers/usb/core/hcd.h> #include <../drivers/usb/core/usb.h> -#include "usb-host.h" +#include "hc_crisv10.h" #define ETRAX_USB_HC_IRQ USB_HC_IRQ_NBR #define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR Index: wli-2.6.10-rc3-1/drivers/usb/host/ohci-hub.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/ohci-hub.c 2004-12-16 06:19:50.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/ohci-hub.c 2004-12-22 10:04:36.406268258 -0800 @@ -305,18 +305,26 @@ { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ports, i, changed = 0, length = 1; - int can_suspend = 1; + int can_suspend = hcd->can_wakeup; + unsigned long flags; - /* if !USB_SUSPEND, root hub timers won't get shut down ... */ - if (!HCD_IS_RUNNING(ohci->hcd.state)) - return 0; + spin_lock_irqsave (&ohci->lock, flags); + + /* handle autosuspended root: finish resuming before + * letting khubd or root hub timer see state changes. + */ + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER + || !HCD_IS_RUNNING(ohci->hcd.state)) { + can_suspend = 0; + goto done; + } ports = roothub_a (ohci) & RH_A_NDP; if (ports > MAX_ROOT_PORTS) { ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ - return 0; + goto done; } /* init status */ @@ -352,6 +360,8 @@ continue; can_suspend = 0; } +done: + spin_unlock_irqrestore (&ohci->lock, flags); #ifdef CONFIG_PM /* save power by suspending idle root hubs; Index: wli-2.6.10-rc3-1/drivers/usb/host/ohci-pci.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/ohci-pci.c 2004-12-16 06:19:50.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/ohci-pci.c 2004-12-22 10:04:36.409267802 -0800 @@ -121,10 +121,7 @@ msleep (100); #ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - disable_irq ((to_pci_dev(hcd->self.controller))->irq); - - { + if (_machine == _MACH_Pmac) { struct device_node *of_node; /* Disable USB PAD & cell clock */ @@ -132,7 +129,7 @@ if (of_node) pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); } -#endif +#endif /* CONFIG_PMAC_PBOOK */ return 0; } @@ -143,7 +140,7 @@ int retval = 0; #ifdef CONFIG_PMAC_PBOOK - { + if (_machine == _MACH_Pmac) { struct device_node *of_node; /* Re-enable USB PAD & cell clock */ @@ -151,7 +148,7 @@ if (of_node) pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); } -#endif +#endif /* CONFIG_PMAC_PBOOK */ /* resume root hub */ if (time_before (jiffies, ohci->next_statechange)) @@ -165,12 +162,6 @@ usb_unlock_device (hcd->self.root_hub); #endif - if (retval == 0) { -#ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - enable_irq (to_pci_dev(hcd->self.controller)->irq); -#endif - } return retval; } Index: wli-2.6.10-rc3-1/drivers/usb/host/uhci-debug.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/uhci-debug.c 2004-12-22 09:07:09.526273666 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/uhci-debug.c 2004-12-22 10:04:36.411267498 -0800 @@ -34,17 +34,6 @@ } } -static inline int uhci_is_skeleton_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) -{ - int i; - - for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (qh == uhci->skelqh[i]) - return 1; - - return 0; -} - static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space) { char *out = buf; Index: wli-2.6.10-rc3-1/drivers/usb/host/uhci-hub.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/usb/host/uhci-hub.c 2004-12-16 06:19:50.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/usb/host/uhci-hub.c 2004-12-22 10:04:36.414267042 -0800 @@ -69,7 +69,7 @@ * FIXME: Synchronize access to these fields by a spinlock. */ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, - unsigned int port_addr) + unsigned long port_addr) { int status; @@ -78,13 +78,19 @@ clear_bit(port, &uhci->suspended_ports); clear_bit(port, &uhci->resuming_ports); set_bit(port, &uhci->port_c_suspend); + + /* The controller won't actually turn off the RD bit until + * it has had a chance to send a low-speed EOP sequence, + * which takes 3 bit times (= 2 microseconds). We'll delay + * slightly longer for good luck. */ + udelay(4); } } static void uhci_check_resume(struct uhci_hcd *uhci) { unsigned int port; - unsigned int port_addr; + unsigned long port_addr; for (port = 0; port < uhci->rh_numports; ++port) { port_addr = uhci->io_addr + USBPORTSC1 + 2 * port; Index: wli-2.6.10-rc3-1/drivers/video/aty/aty128fb.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/video/aty/aty128fb.c 2004-12-16 06:19:51.000000000 -0800 +++ wli-2.6.10-rc3-1/drivers/video/aty/aty128fb.c 2004-12-22 10:04:36.422265826 -0800 @@ -2016,8 +2016,6 @@ release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); release_mem_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); framebuffer_release(info); Index: wli-2.6.10-rc3-1/drivers/video/cg6.c =================================================================== --- wli-2.6.10-rc3-1.orig/drivers/video/cg6.c 2004-12-22 19:31:09.073597338 -0800 +++ wli-2.6.10-rc3-1/drivers/video/cg6.c 2004-12-22 19:57:01.633572346 -0800 @@ -689,6 +689,9 @@ all->par.physbase = sdev->reg_addrs[0].phys_addr; sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); + all->info.var.red.length = 8; + all->info.var.green.length = 8; + all->info.var.blue.length = 8; linebytes = prom_getintdefault(sdev->prom_node, "linebytes", all->info.var.xres); @@ -732,6 +735,7 @@ return; } + fb_set_cmap(&all->info.cmap, &all->info); cg6_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { Index: wli-2.6.10-rc3-1/fs/Kconfig =================================================================== --- wli-2.6.10-rc3-1.orig/fs/Kconfig 2004-12-16 06:19:53.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/Kconfig 2004-12-22 10:04:36.430264610 -0800 @@ -1718,12 +1718,22 @@ config CIFS_POSIX bool "CIFS POSIX Extensions (EXPERIMENTAL)" - depends on CIFS + depends on CIFS_XATTR help Enabling this option will cause the cifs client to attempt to negotiate a newer dialect with servers, such as Samba 3.0.5 or later, that optionally can handle more POSIX like (rather - than Windows like) file behavior. If unsure, say N. + than Windows like) file behavior. It also enables + support for POSIX ACLs (getfacl and setfacl) to servers + (such as Samba 3.10 and later) which can negotiate + CIFS POSIX ACL support. If unsure, say N. + +config CIFS_EXPERIMENTAL + bool "CIFS Experimental Features (EXPERIMENTAL)" + depends on CIFS + help + Enables cifs features under testing. These features + are highly experimental. If unsure, say N. config NCP_FS tristate "NCP file system support (to mount NetWare volumes)" Index: wli-2.6.10-rc3-1/fs/cifs/CHANGES =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/CHANGES 2004-12-16 06:19:53.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/CHANGES 2004-12-22 10:04:36.451261418 -0800 @@ -1,3 +1,53 @@ +Version 1.28 +------------ +Add module init parm for large SMB buffer size (to allow it to be changed +from its default of 16K) which is especially useful for large file copy +when mounting with the directio mount option. Fix oops after +returning from mount when experimental ExtendedSecurity enabled and +SpnegoNegotiated returning invalid error. Fix case to retry better when +peek returns from 1 to 3 bytes on socket which should have more data. +Fixed path based calls (such as cifs lookup) to handle path names +longer than 530 (now can handle PATH_MAX). + +Version 1.27 +------------ +Turn off DNOTIFY (directory change notification support) by default +(unless built with the experimental flag) to fix hang with KDE +file browser. Fix DNOTIFY flag mappings. Fix hang (in wait_event +waiting on an SMB response) in SendReceive when session dies but +reconnects quickly from another task. Add module init parms for +minimum number of large and small network buffers in the buffer pools, +and for the maximum number of simultaneous requests. + +Version 1.26 +------------ +Add setfacl support to allow setting of ACLs remotely to Samba 3.10 and later +and other POSIX CIFS compliant servers. Fix error mapping for getfacl +to EOPNOTSUPP when server does not support posix acls on the wire. Fix +improperly zeroed buffer in CIFS Unix extensions set times call. + +Version 1.25 +------------ +Fix internationlization problem in cifs readdir with filenames that map to +longer UTF8 strings than the string on the wire was in Unicode. Add workaround +for readdir to netapp servers. Fix search rewind (seek into readdir to return +non-consecutive entries). Do not do readdir when server negotiates +buffer size to small to fit filename. Add support for reading POSIX ACLs from +the server (add also acl and noacl mount options). + +Version 1.24 +------------ +Optionally allow using server side inode numbers, rather than client generated +ones by specifying mount option "serverino" - this is required for some apps +to work which double check hardlinked files and have persistent inode numbers. + +Version 1.23 +------------ +Multiple bigendian fixes. On little endian systems (for reconnect after +network failure) fix tcp session reconnect code so we do not try first +to reconnect on reverse of port 445. Treat reparse points (NTFS junctions) +as directories rather than symlinks because we can do follow link on them. + Version 1.22 ------------ Add config option to enable XATTR (extended attribute) support, mapping Index: wli-2.6.10-rc3-1/fs/cifs/Makefile =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/Makefile 2004-12-22 09:07:09.679250410 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/Makefile 2004-12-22 10:04:36.452261266 -0800 @@ -3,4 +3,4 @@ # obj-$(CONFIG_CIFS) += cifs.o -cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o +cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o Index: wli-2.6.10-rc3-1/fs/cifs/README =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/README 2004-12-22 09:07:09.679250410 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/README 2004-12-22 10:04:36.458260354 -0800 @@ -64,6 +64,13 @@ gcc samba/source/client/mount.cifs.c -o mount.cifs +If cifs is built as a module, then the size and number of network buffers +and maximum number of simultaneous requests to one server can be configured. +Changing these from their defaults is not recommended. By executing modinfo + modinfo kernel/fs/cifs/cifs.ko +on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made +at module initialization time (by running insmod cifs.ko) can be seen. + Allowing User Mounts ==================== To permit users to mount and unmount over directories they own is possible @@ -115,11 +122,20 @@ 3.0.6 and later (also EA support works in all versions of Windows, at least to shares on NTFS filesystems). Extended Attribute (xattr) support is an optional feature of most Linux filesystems which may require enabling via -make menuconfig +make menuconfig. + +The CIFS client can get and set POSIX ACLs (getfacl, setfacl) to Samba servers +version 3.10 and later. Setting POSIX ACLs requires enabling both XATTR and +then POSIX support in the CIFS configuration options when building the cifs +module. Some administrators may want to change Samba's smb.conf "map archive" and -"create mask" parameters from the default. Creating special devices (mknod) -remotely may require specifying a mkdev function to Samba if you are not using +"create mask" parameters from the default. Unless the create mask is changed +newly created files can end up with an unnecessarily restrictive default mode, +which may not be what you want, although if the CIFS Unix extensions are +enabled on the server and client, subsequent setattr calls (e.g. chmod) can +fix the mode. Note that creating special devices (mknod) remotely +may require specifying a mkdev function to Samba if you are not using Samba 3.0.6 or later. For more information on these see the manual pages ("man smb.conf") on the Samba server system. Note that the cifs vfs, unlike the smbfs vfs, does not read the smb.conf on the client system @@ -191,7 +207,20 @@ by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers) Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC 1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a -problem as most servers support this. IPv6 support is planned for the future. +problem as most servers support this. IPv6 support is planned for the future, +and is almost complete. + +Valid filenames differ between Windows and Linux. Windows typically restricts +filenames which contain certain reserved characters (e.g.the character : +which is used to delimit the beginning of a stream name by Windows), while +Linux allows a slightly wider set of valid characters in filenames. Windows +servers can remap such characters when an explicit mapping is specified in +the Server's registry. Samba starting with version 3.10 will allow such +filenames (ie those which contain valid Linux characters, which normally +would be forbidden for Windows/CIFS semantics) as long as the server is +configured for Unix Extensions (and the client has not disabled +/proc/fs/cifs/LinuxExtensionsEnabled). + CIFS VFS Mount Options ====================== @@ -266,6 +295,10 @@ If you do not trust the servers in your network (your mount targets) it is recommended that you specify this option for greater security. + exec Permit execution of binaries on the mount. + noexec Do not permit execution of binaries on the mount. + dev Recognize block devices on the remote mount. + nodev Do not recognize devices on the remote mount. suid Allow remote files on this mountpoint with suid enabled to be executed (default for mounts when executed as root, nosuid is default for user mounts). @@ -292,6 +325,22 @@ Note that this does not affect the normal ACL check on the target machine done by the server software (of the server ACL against the user name provided at mount time). + serverino Use servers inode numbers instead of generating automatically + incrementing inode numbers on the client. Although this will + make it easier to spot hardlinked files (as they will have + the same inode numbers) and inode numbers may be persistent, + note that the server does not guarantee that the inode numbers + are unique if multiple server side mounts are exported under a + single share (since inode numbers on the servers might not + be unique if multiple filesystems are mounted under the same + shared higher level directory). Note that this requires that + the server support the CIFS Unix Extensions as other servers + do not return a unique IndexNumber on SMB FindFirst (most + servers return zero as the IndexNumber). Parameter has no + effect to Windows servers and others which do not support the + CIFS Unix Extensions. + noserverino Client generates inode numbers (rather than using the actual one + from the server) by default. setuids If the CIFS Unix extensions are negotiated with the server the client will attempt to set the effective uid and gid of the local process on newly created files, directories, and @@ -304,6 +353,23 @@ the client) set the uid and gid is the default. This parameter has no effect if the CIFS Unix Extensions are not negotiated. + netbiosname When mounting to servers via port 139, specifies the RFC1001 + source name to use to represent the client netbios machine + name when doing the RFC1001 netbios session initialize. + direct Do not do inode data caching on files opened on this mount. + This precludes mmaping files on this mount. In some cases + with fast networks and little or no caching benefits on the + client (e.g. when the application is doing large sequential + reads bigger than page size without rereading the same data) + this can provide better performance than the default + behavior which caches reads (reaadahead) and writes + (writebehind) through the local Linux client pagecache + if oplock (caching token) is granted and held. Note that + direct allows write operations larger than page size + to be sent to the server. + acl Allow setfacl and getfacl to manage posix ACLs if server + supports them. (default) + noacl Do not allow setfacl and getfacl calls on this mount The mount.cifs mount helper also accepts a few mount options before -o including: @@ -375,14 +441,14 @@ echo 1 > /proc/fs/cifs/traceSMB Two other experimental features are under development and to test -require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h) +require enabling CONFIG_CIFS_EXPERIMENTAL - CONFIG_CIFS_QUOTA + More efficient write operations and SMB buffer handling - CONFIG_CIFS_FCNTL (fcntl needed for support of directory change + DNOTIFY fcntl: needed for support of directory change notification and perhaps later for file leases) -Per share (per client mount) statistics are available in /proc/fs/cifs/DebugData +Per share (per client mount) statistics are available in /proc/fs/cifs/Stats if the kernel was configured with cifs statistics enabled. The statistics represent the number of successful (ie non-zero return code from the server) SMB responses to some of the more common commands (open, delete, mkdir etc.). Index: wli-2.6.10-rc3-1/fs/cifs/TODO =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/TODO 2004-12-22 09:07:09.680250258 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/TODO 2004-12-22 10:04:36.461259898 -0800 @@ -14,7 +14,7 @@ better) c) multi-user mounts - multiplexed sessionsetups over single vc -(ie tcp session) - prettying up needed +(ie tcp session) - prettying up needed, and more testing needed d) Kerberos/SPNEGO session setup support - (started) @@ -40,8 +40,8 @@ extra copy in/out of the socket buffers in some cases. l) finish support for IPv6. This is mostly complete but -needs a simple inet_pton like function to convert ipv6 -addresses in string representation. +needs a simple conversion of ipv6 to sin6_addr from the +address in string representation. m) Better optimize open (and pathbased setfilesize) to reduce the oplock breaks coming from windows srv. Piggyback identical file @@ -50,23 +50,24 @@ spurious oplock breaks). o) Improve performance of readpages by sending more than one read -at a time when 8 pages or more are requested. Evaluate whether -reads larger than 16K would be helpful. +at a time when 8 pages or more are requested. In conjuntion +add support for async_cifs_readpages. -p) For support of Windows9x/98 we need to retry failed mounts -to *SMBSERVER (default server name) with the uppercase hostname -in the RFC1001 session_init request. - -q) Add support for storing symlink and fifo info to Windows servers +p) Add support for storing symlink and fifo info to Windows servers in the Extended Attribute format their SFU clients would recognize. -r) Finish fcntl D_NOTIFY support so kde and gnome file list windows -will autorefresh +q) Finish fcntl D_NOTIFY support so kde and gnome file list windows +will autorefresh (started) + +r) Add GUI tool to configure /proc/fs/cifs settings and for display of +the CIFS statistics (started) + +q) implement support for security and trusted categories of xattrs +(requires minor protocol extension) to enable better support for SELINUX -s) Add GUI tool to configure /proc/fs/cifs settings and for display of -the CIFS statistics +r) Implement O_DIRECT flag on open (already supported on mount) -KNOWN BUGS (updated May 27, 2004) +KNOWN BUGS (updated December 10, 2004) ==================================== 1) existing symbolic links (Windows reparse points) are recognized but can not be created remotely. They are implemented for Samba and those that @@ -83,9 +84,6 @@ differences but worth investigating). Also debug Samba to see why lock test case 7 takes longer to complete to Samba than to Windows. -5) implement search rewind (seeking backward in a readdir), which is -necessary for one of the "special" subsection of posix file API -tests in the Connectathon nfs test suite. Misc testing to do ================== Index: wli-2.6.10-rc3-1/fs/cifs/cifs_debug.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/cifs_debug.c 2004-12-22 09:07:09.681250106 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/cifs_debug.c 2004-12-22 10:04:36.465259290 -0800 @@ -201,7 +201,12 @@ sprintf(buf,"SMB Request/Response Buffer: %d\n", bufAllocCount.counter); length += item_length; - buf += item_length; + buf += item_length; + item_length = + sprintf(buf,"SMB Small Req/Resp Buffer: %d\n", + smBufAllocCount.counter); + length += item_length; + buf += item_length; item_length = sprintf(buf,"Operations (MIDs): %d\n", midCount.counter); @@ -337,7 +342,7 @@ if (pde) pde->write_proc = oplockEnabled_write; - pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs, + pde = create_proc_read_entry("ReenableOldCifsReaddirCode", 0, proc_fs_cifs, quotaEnabled_read, NULL); if (pde) pde->write_proc = quotaEnabled_write; @@ -396,7 +401,7 @@ remove_proc_entry("ExtendedSecurity",proc_fs_cifs); remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); - remove_proc_entry("QuotaEnabled",proc_fs_cifs); + remove_proc_entry("ReenableOldCifsReaddirCode",proc_fs_cifs); remove_proc_entry("LookupCacheEnabled",proc_fs_cifs); remove_proc_entry("cifs", proc_root_fs); } @@ -485,7 +490,7 @@ { int len; - len = sprintf(page, "%d\n", quotaEnabled); + len = sprintf(page, "%d\n", experimEnabled); /* could also check if quotas are enabled in kernel as a whole first */ len -= off; @@ -512,9 +517,9 @@ if (rc) return rc; if (c == '0' || c == 'n' || c == 'N') - quotaEnabled = 0; + experimEnabled = 0; else if (c == '1' || c == 'y' || c == 'Y') - quotaEnabled = 1; + experimEnabled = 1; return count; } Index: wli-2.6.10-rc3-1/fs/cifs/cifs_fs_sb.h =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/cifs_fs_sb.h 2004-12-22 09:07:09.681250106 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/cifs_fs_sb.h 2004-12-22 10:04:36.467258986 -0800 @@ -1,7 +1,7 @@ /* * fs/cifs/cifs_fs_sb.h * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002,2004 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -18,8 +18,10 @@ #ifndef _CIFS_FS_SB_H #define _CIFS_FS_SB_H -#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */ +#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */ #define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */ +#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ +#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ Index: wli-2.6.10-rc3-1/fs/cifs/cifsfs.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/cifsfs.c 2004-12-16 06:19:53.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/cifsfs.c 2004-12-22 10:04:36.474257922 -0800 @@ -50,15 +50,27 @@ int cifsERROR = 1; int traceSMB = 0; unsigned int oplockEnabled = 1; -unsigned int quotaEnabled = 0; +unsigned int experimEnabled = 0; unsigned int linuxExtEnabled = 1; unsigned int lookupCacheEnabled = 1; unsigned int multiuser_mount = 0; unsigned int extended_security = 0; unsigned int ntlmv2_support = 0; unsigned int sign_CIFS_PDUs = 1; -unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE; struct task_struct * oplockThread = NULL; +unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; +module_param(CIFSMaxBufSize, int, CIFS_MAX_MSGSIZE); +MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); +unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; +module_param(cifs_min_rcv, int, CIFS_MIN_RCV_POOL); +MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64"); +unsigned int cifs_min_small = 30; +module_param(cifs_min_small, int, 30); +MODULE_PARM_DESC(cifs_small_rcv,"Small network buffers in pool. Default: 30 Range: 2 to 256"); +unsigned int cifs_max_pending = CIFS_MAX_REQ; +module_param(cifs_max_pending, int, CIFS_MAX_REQ); +MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256"); + extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, const char *); @@ -207,6 +219,8 @@ static kmem_cache_t *cifs_req_cachep; static kmem_cache_t *cifs_mid_cachep; kmem_cache_t *cifs_oplock_cachep; +static kmem_cache_t *cifs_sm_req_cachep; +mempool_t *cifs_sm_req_poolp; mempool_t *cifs_req_poolp; mempool_t *cifs_mid_poolp; @@ -431,6 +445,20 @@ return -EIO; cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset)); + +#ifdef CONFIG_CIFS_EXPERIMENTAL + /* check whether we can cache writes locally */ + if(file->f_dentry->d_sb) { + struct cifs_sb_info *cifs_sb; + cifs_sb = CIFS_SB(file->f_dentry->d_sb); + if(cifs_sb != NULL) { + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) + return cifs_user_read(file,read_data, + read_size,poffset); + } + } +#endif /* CIFS_EXPERIMENTAL */ + if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) { return generic_file_read(file,read_data,read_size,poffset); } else { @@ -463,7 +491,19 @@ cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset)); +#ifdef CONFIG_CIFS_EXPERIMENTAL /* BB fixme - fix user char * to kernel char * mapping here BB */ /* check whether we can cache writes locally */ + if(file->f_dentry->d_sb) { + struct cifs_sb_info *cifs_sb; + cifs_sb = CIFS_SB(file->f_dentry->d_sb); + if(cifs_sb != NULL) { + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { + return cifs_user_write(file,write_data, + write_size,poffset); + } + } + } +#endif /* CIFS_EXPERIMENTAL */ written = generic_file_write(file,write_data,write_size,poffset); if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) { if(file->f_dentry->d_inode->i_mapping) { @@ -495,6 +535,12 @@ .setattr = cifs_setattr, .symlink = cifs_symlink, .mknod = cifs_mknod, +#ifdef CONFIG_CIFS_XATTR + .setxattr = cifs_setxattr, + .getxattr = cifs_getxattr, + .listxattr = cifs_listxattr, + .removexattr = cifs_removexattr, +#endif }; struct inode_operations cifs_file_inode_ops = { @@ -537,14 +583,18 @@ .flush = cifs_flush, .mmap = cifs_file_mmap, .sendfile = generic_file_sendfile, +#ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, +#endif /* CONFIG_CIFS_EXPERIMENTAL */ }; struct file_operations cifs_dir_ops = { .readdir = cifs_readdir, .release = cifs_closedir, .read = generic_read_dir, +#ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, +#endif /* CONFIG_CIFS_EXPERIMENTAL */ }; static void @@ -582,14 +632,31 @@ static int cifs_init_request_bufs(void) { + if(CIFSMaxBufSize < 8192) { + /* Buffer size can not be smaller than 2 * PATH_MAX since maximum + Unicode path name has to fit in any SMB/CIFS path based frames */ + CIFSMaxBufSize = 8192; + } else if (CIFSMaxBufSize > 1024*127) { + CIFSMaxBufSize = 1024 * 127; + } else { + CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/ + } +/* cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */ cifs_req_cachep = kmem_cache_create("cifs_request", - CIFS_MAX_MSGSIZE + + CIFSMaxBufSize + MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (cifs_req_cachep == NULL) return -ENOMEM; - cifs_req_poolp = mempool_create(CIFS_MIN_RCV_POOL, + if(cifs_min_rcv < 1) + cifs_min_rcv = 1; + else if (cifs_min_rcv > 64) { + cifs_min_rcv = 64; + cFYI(1,("cifs_min_rcv set to maximum (64)")); + } + + cifs_req_poolp = mempool_create(cifs_min_rcv, mempool_alloc_slab, mempool_free_slab, cifs_req_cachep); @@ -598,6 +665,40 @@ kmem_cache_destroy(cifs_req_cachep); return -ENOMEM; } + /* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and + almost all handle based requests (but not write response, nor is it + sufficient for path based requests). A smaller size would have + been more efficient (compacting multiple slab items on one 4k page) + for the case in which debug was on, but this larger size allows + more SMBs to use small buffer alloc and is still much more + efficient to alloc 1 per page off the slab compared to 17K (5page) + alloc of large cifs buffers even when page debugging is on */ + cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", + MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + if (cifs_sm_req_cachep == NULL) { + mempool_destroy(cifs_req_poolp); + kmem_cache_destroy(cifs_req_cachep); + return -ENOMEM; + } + + if(cifs_min_small < 2) + cifs_min_small = 2; + else if (cifs_min_small > 256) { + cifs_min_small = 256; + cFYI(1,("cifs_min_small set to maximum (256)")); + } + + cifs_sm_req_poolp = mempool_create(cifs_min_small, + mempool_alloc_slab, + mempool_free_slab, + cifs_sm_req_cachep); + + if(cifs_sm_req_poolp == NULL) { + mempool_destroy(cifs_req_poolp); + kmem_cache_destroy(cifs_req_cachep); + kmem_cache_destroy(cifs_sm_req_cachep); + return -ENOMEM; + } return 0; } @@ -609,6 +710,10 @@ if (kmem_cache_destroy(cifs_req_cachep)) printk(KERN_WARNING "cifs_destroy_request_cache: error not all structures were freed\n"); + mempool_destroy(cifs_sm_req_poolp); + if (kmem_cache_destroy(cifs_sm_req_cachep)) + printk(KERN_WARNING + "cifs_destroy_request_cache: cifs_small_rq free error\n"); } static int @@ -751,6 +856,14 @@ GlobalSMBSeslock = RW_LOCK_UNLOCKED; GlobalMid_Lock = SPIN_LOCK_UNLOCKED; + if(cifs_max_pending < 2) { + cifs_max_pending = 2; + cFYI(1,("cifs_max_pending set to min of 2")); + } else if(cifs_max_pending > 256) { + cifs_max_pending = 256; + cFYI(1,("cifs_max_pending set to max of 256")); + } + rc = cifs_init_inodecache(); if (!rc) { rc = cifs_init_mids(); Index: wli-2.6.10-rc3-1/fs/cifs/cifsfs.h =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/cifsfs.h 2004-12-22 09:07:09.682249954 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/cifsfs.h 2004-12-22 10:04:36.476257618 -0800 @@ -63,10 +63,10 @@ extern int cifs_open(struct inode *inode, struct file *file); extern int cifs_close(struct inode *inode, struct file *file); extern int cifs_closedir(struct inode *inode, struct file *file); -extern ssize_t cifs_read(struct file *file, char *read_data, +extern ssize_t cifs_user_read(struct file *file, char __user *read_data, size_t read_size, loff_t * poffset); -extern ssize_t cifs_write(struct file *file, const char *write_data, - size_t write_size, loff_t * poffset); +extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, + size_t write_size, loff_t * poffset); extern int cifs_lock(struct file *, int, struct file_lock *); extern int cifs_fsync(struct file *, struct dentry *, int); extern int cifs_flush(struct file *); @@ -90,5 +90,5 @@ size_t, int); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); -#define CIFS_VERSION "1.20" +#define CIFS_VERSION "1.28" #endif /* _CIFSFS_H */ Index: wli-2.6.10-rc3-1/fs/cifs/cifsglob.h =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/cifsglob.h 2004-12-22 09:07:09.683249802 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/cifsglob.h 2004-12-22 10:04:36.480257010 -0800 @@ -240,6 +240,20 @@ /* * One of these for each open instance of a file */ +struct cifs_search_info { + loff_t index_of_last_entry; + __u16 entries_in_buffer; + __u16 info_level; + __u32 resume_key; + char * ntwrk_buf_start; + char * srch_entries_start; + char * presume_name; + unsigned int resume_name_len; + unsigned endOfSearch:1; + unsigned emptyDir:1; + unsigned unicode:1; +}; + struct cifsFileInfo { struct list_head tlist; /* pointer to next fid owned by tcon */ struct list_head flist; /* next fid (file instance) for this inode */ @@ -250,14 +264,12 @@ /* lock scope id (0 if none) */ struct file * pfile; /* needed for writepage */ struct inode * pInode; /* needed for oplock break */ - unsigned endOfSearch:1; /* we have reached end of search */ unsigned closePend:1; /* file is marked to close */ - unsigned emptyDir:1; unsigned invalidHandle:1; /* file closed via session abend */ struct semaphore fh_sem; /* prevents reopen race after dead ses*/ - char * search_resume_name; - unsigned int resume_name_length; - __u32 resume_key; + char * search_resume_name; /* BB removeme BB */ + unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */ + struct cifs_search_info srch_inf; }; /* @@ -317,6 +329,8 @@ #define MID_REQUEST_SUBMITTED 2 #define MID_RESPONSE_RECEIVED 4 #define MID_RETRY_NEEDED 8 /* session closed while this request out */ +#define MID_NO_RESP_NEEDED 0x10 +#define MID_SMALL_BUFFER 0x20 /* 112 byte response buffer instead of 4K */ /* ***************************************************************** @@ -399,6 +413,7 @@ /* Various Debug counters to remove someday (BB) */ GLOBAL_EXTERN atomic_t bufAllocCount; +GLOBAL_EXTERN atomic_t smBufAllocCount; GLOBAL_EXTERN atomic_t midCount; /* Misc globals */ @@ -407,11 +422,15 @@ have the uid/password or Kerberos credential or equivalent for current user */ GLOBAL_EXTERN unsigned int oplockEnabled; -GLOBAL_EXTERN unsigned int quotaEnabled; +GLOBAL_EXTERN unsigned int experimEnabled; GLOBAL_EXTERN unsigned int lookupCacheEnabled; GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent with more secure ntlmssp2 challenge/resp */ GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */ GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ -GLOBAL_EXTERN unsigned int linuxExtEnabled; /* enable Linux/Unix CIFS extensions */ +GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ +GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ +GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ +GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ +GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ Index: wli-2.6.10-rc3-1/fs/cifs/cifspdu.h =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/cifspdu.h 2004-12-22 09:07:09.684249650 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/cifspdu.h 2004-12-22 10:04:36.497254426 -0800 @@ -28,27 +28,30 @@ #define BAD_PROT CIFS_PROT+1 /* SMB command codes */ -#define SMB_COM_CREATE_DIRECTORY 0x00 -#define SMB_COM_DELETE_DIRECTORY 0x01 -#define SMB_COM_CLOSE 0x04 -#define SMB_COM_DELETE 0x06 -#define SMB_COM_RENAME 0x07 -#define SMB_COM_LOCKING_ANDX 0x24 -#define SMB_COM_COPY 0x29 +/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses + (ie which include no useful data other than the SMB error code itself). + Knowing this helps avoid response buffer allocations and copy in some cases */ +#define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ +#define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ +#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ +#define SMB_COM_DELETE 0x06 /* trivial response */ +#define SMB_COM_RENAME 0x07 /* trivial response */ +#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ +#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ #define SMB_COM_READ_ANDX 0x2E #define SMB_COM_WRITE_ANDX 0x2F #define SMB_COM_TRANSACTION2 0x32 #define SMB_COM_TRANSACTION2_SECONDARY 0x33 -#define SMB_COM_FIND_CLOSE2 0x34 -#define SMB_COM_TREE_DISCONNECT 0x71 +#define SMB_COM_FIND_CLOSE2 0x34 /* trivial response */ +#define SMB_COM_TREE_DISCONNECT 0x71 /* trivial response */ #define SMB_COM_NEGOTIATE 0x72 #define SMB_COM_SESSION_SETUP_ANDX 0x73 -#define SMB_COM_LOGOFF_ANDX 0x74 +#define SMB_COM_LOGOFF_ANDX 0x74 /* trivial response */ #define SMB_COM_TREE_CONNECT_ANDX 0x75 #define SMB_COM_NT_TRANSACT 0xA0 #define SMB_COM_NT_TRANSACT_SECONDARY 0xA1 #define SMB_COM_NT_CREATE_ANDX 0xA2 -#define SMB_COM_NT_RENAME 0xA5 +#define SMB_COM_NT_RENAME 0xA5 /* trivial response */ /* Transact2 subcommand codes */ #define TRANS2_OPEN 0x00 @@ -141,7 +144,7 @@ #define SMBFLG2_KNOWS_EAS cpu_to_le16(2) #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4) #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40) -#define SMBFLG2_EXT_SEC cpu_to_le16(0x80) +#define SMBFLG2_EXT_SEC cpu_to_le16(0x800) #define SMBFLG2_DFS cpu_to_le16(0x1000) #define SMBFLG2_PAGING_IO cpu_to_le16(0x2000) #define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000) @@ -682,7 +685,7 @@ __le32 OffsetHigh; __le16 ByteCount; __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */ - char Data[1]; + char Data[0]; } WRITE_REQ; typedef struct smb_com_write_rsp { @@ -972,10 +975,10 @@ /* response contains array of the following structures */ struct file_notify_information { - __u32 NextEntryOffset; - __u32 Action; - __u32 FileNameLength; - __u8 FileName[1]; + __le32 NextEntryOffset; + __le32 Action; + __le32 FileNameLength; + __u8 FileName[0]; }; struct reparse_data { @@ -1004,45 +1007,55 @@ #define QUOTA_LIST_START 0x100 #define QUOTA_FOR_SID 0x101 -typedef union smb_com_transaction2 { - struct { - struct smb_hdr hdr; /* wct = 14+ */ - __u16 TotalParameterCount; - __u16 TotalDataCount; - __u16 MaxParameterCount; - __u16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __u16 Flags; - __u32 Timeout; - __u16 Reserved2; - __u16 ParameterCount; - __u16 ParameterOffset; - __u16 DataCount; - __u16 DataOffset; - __u8 SetupCount; - __u8 Reserved3; - __u16 SubCommand; /* 1st setup word - can be followed by SetupCount words */ - __u16 ByteCount; /* careful - setupcount is not always one */ - } req; - struct { - struct smb_hdr hdr; /* wct = 0 */ - __u16 TotalParameterCount; - __u16 TotalDataCount; - __u16 Reserved; - __u16 ParameterCount; - __u16 ParamterOffset; - __u16 ParameterDisplacement; - __u16 DataCount; - __u16 DataOffset; - __u16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ - __u16 ByteCount; - __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ - /* data area follows */ - } resp; -} TRANSACTION2; +struct trans2_req { + /* struct smb_hdr hdr precedes. Set wct = 14+ */ + __le16 TotalParameterCount; + __le16 TotalDataCount; + __le16 MaxParameterCount; + __le16 MaxDataCount; + __u8 MaxSetupCount; + __u8 Reserved; + __le16 Flags; + __le32 Timeout; + __u16 Reserved2; + __le16 ParameterCount; + __le16 ParameterOffset; + __le16 DataCount; + __le16 DataOffset; + __u8 SetupCount; + __u8 Reserved3; + __le16 SubCommand; /* 1st setup word - SetupCount words follow */ + __le16 ByteCount; +}; + +struct smb_t2_req { + struct smb_hdr hdr; + struct trans2_req t2_req; +}; + +struct trans2_resp { + /* struct smb_hdr hdr precedes. Note wct = 10 + setup count */ + __le16 TotalParameterCount; + __le16 TotalDataCount; + __u16 Reserved; + __le16 ParameterCount; + __le16 ParameterOffset; + __le16 ParameterDisplacement; + __le16 DataCount; + __le16 DataOffset; + __le16 DataDisplacement; + __u8 SetupCount; + __u8 Reserved1; + /* SetupWords[SetupCount]; + __u16 ByteCount; + __u16 Reserved2;*/ + /* data area follows */ +}; + +struct smb_t2_rsp { + struct smb_hdr hdr; + struct trans2_resp t2_rsp; +}; /* PathInfo/FileInfo infolevels */ #define SMB_INFO_STANDARD 1 @@ -1063,6 +1076,15 @@ #define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B #define SMB_QUERY_FILE_UNIX_BASIC 0x200 #define SMB_QUERY_FILE_UNIX_LINK 0x201 +#define SMB_QUERY_POSIX_ACL 0x204 +#define SMB_QUERY_XATTR 0x205 +#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee +#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 +#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ +#define SMB_QUERY_FILE_POSITION_INFO 0x3f6 +#define SMB_QUERY_FILE_MODE_INFO 0x3f8 +#define SMB_QUERY_FILE_ALGN_INFO 0x3f9 + #define SMB_SET_FILE_BASIC_INFO 0x101 #define SMB_SET_FILE_DISPOSITION_INFO 0x102 @@ -1071,8 +1093,10 @@ #define SMB_SET_FILE_UNIX_BASIC 0x200 #define SMB_SET_FILE_UNIX_LINK 0x201 #define SMB_SET_FILE_UNIX_HLINK 0x203 +#define SMB_SET_POSIX_ACL 0x204 +#define SMB_SET_XATTR 0x205 #define SMB_SET_FILE_BASIC_INFO2 0x3ec -#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 +#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ #define SMB_FILE_ALL_INFO2 0x3fa #define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb #define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc @@ -1086,6 +1110,8 @@ #define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 #define SMB_FIND_FILE_NAMES_INFO 0x103 #define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104 +#define SMB_FIND_FILE_ID_FULL_DIR_INFO 0x105 +#define SMB_FIND_FILE_ID_BOTH_DIR_INFO 0x106 #define SMB_FIND_FILE_UNIX 0x202 typedef struct smb_com_transaction2_qpi_req { @@ -1115,17 +1141,7 @@ typedef struct smb_com_transaction2_qpi_rsp { struct smb_hdr hdr; /* wct = 10 + SetupCount */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ } TRANSACTION2_QPI_RSP; @@ -1158,17 +1174,7 @@ typedef struct smb_com_transaction2_spi_rsp { struct smb_hdr hdr; /* wct = 10 + SetupCount */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ } TRANSACTION2_SPI_RSP; @@ -1208,17 +1214,7 @@ struct smb_com_transaction2_sfi_rsp { struct smb_hdr hdr; /* wct = 10 + SetupCount */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ }; @@ -1268,17 +1264,7 @@ typedef struct smb_com_transaction2_ffirst_rsp { struct smb_hdr hdr; /* wct = 10 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; } TRANSACTION2_FFIRST_RSP; @@ -1320,17 +1306,7 @@ typedef struct smb_com_transaction2_fnext_rsp { struct smb_hdr hdr; /* wct = 10 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; } TRANSACTION2_FNEXT_RSP; @@ -1351,6 +1327,8 @@ #define SMB_QUERY_CIFS_UNIX_INFO 0x200 #define SMB_QUERY_LABEL_INFO 0x3ea #define SMB_QUERY_FS_QUOTA_INFO 0x3ee +#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef +#define SMB_QUERY_OBJECTID_INFO 0x3f0 typedef struct smb_com_transaction2_qfsi_req { struct smb_hdr hdr; /* wct = 14+ */ @@ -1377,17 +1355,7 @@ typedef struct smb_com_transaction_qfsi_rsp { struct smb_hdr hdr; /* wct = 10 + SetupCount */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u8 Pad; /* may be three bytes *//* followed by data area */ } TRANSACTION2_QFSI_RSP; @@ -1430,17 +1398,7 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp { struct smb_hdr hdr; /* wct = 10 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u8 Pad; __le16 PathConsumed; @@ -1545,6 +1503,7 @@ /* Linux/Unix extensions capability flags */ #define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ #define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 +#define CIFS_UNIX_XATTR_CAP 0x00000004 /*support for new namespace*/ /* DeviceType Flags */ #define FILE_DEVICE_CD_ROM 0x00000002 @@ -1575,10 +1534,13 @@ __le32 Attributes; __le32 MaxPathNameComponentLength; __le32 FileSystemNameLen; - char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */ + char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */ } FILE_SYSTEM_ATTRIBUTE_INFO; -typedef struct { /* data block encoding of response to level 263 QPathInfo */ +/******************************************************************************/ +/* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */ +/******************************************************************************/ +typedef struct { /* data block encoding of response to level 263 QPathInfo */ __le64 CreationTime; __le64 LastAccessTime; __le64 LastWriteTime; @@ -1600,12 +1562,20 @@ __le32 AlignmentRequirement; __le32 FileNameLength; char FileName[1]; -} FILE_ALL_INFO; /* level 263 QPathInfo */ +} FILE_ALL_INFO; /* level 0x107 QPathInfo */ +/* defines for enumerating possible values of the Unix type field below */ +#define UNIX_FILE 0 +#define UNIX_DIR 1 +#define UNIX_SYMLINK 2 +#define UNIX_CHARDEV 3 +#define UNIX_BLOCKDEV 4 +#define UNIX_FIFO 5 +#define UNIX_SOCKET 6 typedef struct { __le64 EndOfFile; __le64 NumOfBytes; - __le64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */ + __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ __le64 LastAccessTime; __le64 LastModificationTime; __le64 Uid; @@ -1616,11 +1586,11 @@ __u64 UniqueId; __le64 Permissions; __le64 Nlinks; -} FILE_UNIX_BASIC_INFO; /* level 512 QPathInfo */ +} FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */ typedef struct { char LinkDest[1]; -} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */ +} FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */ typedef struct { __u16 CreationDate; @@ -1635,21 +1605,99 @@ __u32 EASize; } FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */ -/* defines for enumerating possible values of the Unix type field below */ -#define UNIX_FILE 0 -#define UNIX_DIR 1 -#define UNIX_SYMLINK 2 -#define UNIX_CHARDEV 3 -#define UNIX_BLOCKDEV 4 -#define UNIX_FIFO 5 -#define UNIX_SOCKET 6 +typedef struct { + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le32 Attributes; + __u32 Pad; +} FILE_BASIC_INFO; /* size info, level 0x101 */ + +struct file_allocation_info { + __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */ +}; /* size used on disk, level 0x103 for set, 0x105 for query */ + +struct file_end_of_file_info { + __le64 FileSize; /* offset to end of file */ +}; /* size info, level 0x104 for set, 0x106 for query */ + +struct file_alt_name_info { + __u8 alt_name[1]; +}; /* level 0x0108 */ + +struct file_stream_info { + __le32 number_of_streams; /* BB check sizes and verify location */ + /* followed by info on streams themselves + u64 size; + u64 allocation_size + stream info */ +}; /* level 0x109 */ + +struct file_compression_info { + __le64 compressed_size; + __le16 format; + __u8 unit_shift; + __u8 ch_shift; + __u8 cl_shift; + __u8 pad[3]; +}; /* level 0x10b */ + +/* POSIX ACL set/query path info structures */ +#define CIFS_ACL_VERSION 1 +struct cifs_posix_ace { /* access control entry (ACE) */ + __u8 cifs_e_tag; + __u8 cifs_e_perm; + __le64 cifs_uid; /* or gid */ +}; + +struct cifs_posix_acl { /* access conrol list (ACL) */ + __le16 version; + __le16 access_entry_count; /* access ACL - count of entries */ + __le16 default_entry_count; /* default ACL - count of entries */ + struct cifs_posix_ace ace_array[0]; + /* followed by + struct cifs_posix_ace default_ace_arraay[] */ +}; /* level 0x204 */ + +/* types of access control entries already defined in posix_acl.h */ +/* #define CIFS_POSIX_ACL_USER_OBJ 0x01 +#define CIFS_POSIX_ACL_USER 0x02 +#define CIFS_POSIX_ACL_GROUP_OBJ 0x04 +#define CIFS_POSIX_ACL_GROUP 0x08 +#define CIFS_POSIX_ACL_MASK 0x10 +#define CIFS_POSIX_ACL_OTHER 0x20 */ + +/* types of perms */ +/* #define CIFS_POSIX_ACL_EXECUTE 0x01 +#define CIFS_POSIX_ACL_WRITE 0x02 +#define CIFS_POSIX_ACL_READ 0x04 */ + +/* end of POSIX ACL definitions */ + +struct file_internal_info { + __u64 UniqueId; /* inode number */ +}; /* level 0x3ee */ +struct file_mode_info { + __le32 Mode; +}; /* level 0x3f8 */ + +struct file_attrib_tag { + __le32 Attribute; + __le32 ReparseTag; +}; /* level 0x40b */ + + +/********************************************************/ +/* FindFirst/FindNext transact2 data buffer formats */ +/********************************************************/ typedef struct { __le32 NextEntryOffset; - __le32 ResumeKey; + __u32 ResumeKey; /* as with FileIndex - no need to convert */ __le64 EndOfFile; __le64 NumOfBytes; - __le64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */ + __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ __le64 LastAccessTime; __le64 LastModificationTime; __le64 Uid; @@ -1657,28 +1705,40 @@ __le32 Type; __le64 DevMajor; __le64 DevMinor; - __le64 UniqueId; + __u64 UniqueId; __le64 Permissions; __le64 Nlinks; char FileName[1]; -} FILE_UNIX_INFO; +} FILE_UNIX_INFO; /* level 0x202 */ typedef struct { + __le32 NextEntryOffset; + __u32 FileIndex; __le64 CreationTime; __le64 LastAccessTime; __le64 LastWriteTime; __le64 ChangeTime; - __le32 Attributes; - __u32 Pad; -} FILE_BASIC_INFO; /* size info, level 0x101 */ - -struct file_allocation_info { + __le64 EndOfFile; __le64 AllocationSize; -}; /* size info, level 0x103 */ + __le32 ExtFileAttributes; + __le32 FileNameLength; + char FileName[1]; +} FILE_DIRECTORY_INFO; /* level 0x101 FF response data area */ -struct file_end_of_file_info { - __le64 FileSize; /* offset to end of file */ -}; /* size info, level 0x104 */ +typedef struct { + __le32 NextEntryOffset; + __u32 FileIndex; + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le64 EndOfFile; + __le64 AllocationSize; + __le32 ExtFileAttributes; + __le32 FileNameLength; + __le32 EaSize; /* length of the xattrs */ + char FileName[1]; +} FILE_FULL_DIRECTORY_INFO; /* level 0x102 FF response data area */ typedef struct { __le32 NextEntryOffset; @@ -1691,8 +1751,30 @@ __le64 AllocationSize; __le32 ExtFileAttributes; __le32 FileNameLength; + __le32 EaSize; /* EA size */ + __le32 Reserved; + __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/ char FileName[1]; -} FILE_DIRECTORY_INFO; /* level 257 FF response data area */ +} SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF response data area */ + +typedef struct { + __le32 NextEntryOffset; + __u32 FileIndex; + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le64 EndOfFile; + __le64 AllocationSize; + __le32 ExtFileAttributes; + __le32 FileNameLength; + __le32 EaSize; /* length of the xattrs */ + __u8 ShortNameLength; + __u8 Reserved; + __u8 ShortName[12]; + char FileName[1]; +} FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */ + struct gea { unsigned char name_len; @@ -1830,6 +1912,15 @@ char path[1024]; }; +typedef struct { + /* BB do we need another field for flags? BB */ + __u32 xattr_name_len; + __u32 xattr_value_len; + char xattr_name[0]; + /* followed by xattr_value[xattr_value_len], no pad */ +} FILE_XATTR_INFO; /* extended attribute, info level 205 */ + + #endif #pragma pack() /* resume default structure packing */ Index: wli-2.6.10-rc3-1/fs/cifs/cifsproto.h =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/cifsproto.h 2004-12-22 09:07:09.684249650 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/cifsproto.h 2004-12-22 10:04:36.500253970 -0800 @@ -1,7 +1,7 @@ /* * fs/cifs/cifsproto.h * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002,2004 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -32,6 +32,8 @@ extern struct smb_hdr *cifs_buf_get(void); extern void cifs_buf_release(void *); +extern struct smb_hdr *cifs_small_buf_get(void); +extern void cifs_small_buf_release(void *); extern int smb_send(struct socket *, struct smb_hdr *, unsigned int /* length */ , struct sockaddr *); extern unsigned int _GetXid(void); @@ -190,7 +192,8 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, const int netfid, const unsigned int count, const __u64 lseek, unsigned int *nbytes, - const char *buf, const int long_op); + const char *buf, const char __user *ubuf, + const int long_op); extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, const __u16 netfid, const __u64 len, const __u64 offset, const __u32 numUnlock, @@ -233,4 +236,12 @@ const char *fileName, const char * ea_name, const void * ea_value, const __u16 ea_value_len, const struct nls_table *nls_codepage); +extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, + const unsigned char *searchName, + char *acl_inf, const int buflen,const int acl_type, + const struct nls_table *nls_codepage); +extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, + const unsigned char *fileName, + const char *local_acl, const int buflen, const int acl_type, + const struct nls_table *nls_codepage); #endif /* _CIFSPROTO_H */ Index: wli-2.6.10-rc3-1/fs/cifs/cifssmb.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/cifssmb.c 2004-12-22 09:07:09.685249498 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/cifssmb.c 2004-12-22 10:04:36.545247130 -0800 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "cifspdu.h" #include "cifsglob.h" @@ -78,6 +79,97 @@ } static int +small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, + void **request_buf /* returned */) +{ + int rc = 0; + + /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so + check for tcp and smb session status done differently + for those three - in the calling routine */ + if(tcon) { + if((tcon->ses) && (tcon->ses->server)){ + struct nls_table *nls_codepage; + /* Give Demultiplex thread up to 10 seconds to + reconnect, should be greater than cifs socket + timeout which is 7 seconds */ + while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { + wait_event_interruptible_timeout(tcon->ses->server->response_q, + (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); + if(tcon->ses->server->tcpStatus == CifsNeedReconnect) { + /* on "soft" mounts we wait once */ + if((tcon->retry == FALSE) || + (tcon->ses->status == CifsExiting)) { + cFYI(1,("gave up waiting on reconnect in smb_init")); + return -EHOSTDOWN; + } /* else "hard" mount - keep retrying until + process is killed or server comes back up */ + } else /* TCP session is reestablished now */ + break; + + } + + nls_codepage = load_nls_default(); + /* need to prevent multiple threads trying to + simultaneously reconnect the same SMB session */ + down(&tcon->ses->sesSem); + if(tcon->ses->status == CifsNeedReconnect) + rc = cifs_setup_session(0, tcon->ses, nls_codepage); + if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { + mark_open_files_invalid(tcon); + rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, + nls_codepage); + up(&tcon->ses->sesSem); + if(rc == 0) + atomic_inc(&tconInfoReconnectCount); + + cFYI(1, ("reconnect tcon rc = %d", rc)); + /* Removed call to reopen open files here - + it is safer (and faster) to reopen files + one at a time as needed in read and write */ + + /* Check if handle based operation so we + know whether we can continue or not without + returning to caller to reset file handle */ + switch(smb_command) { + case SMB_COM_READ_ANDX: + case SMB_COM_WRITE_ANDX: + case SMB_COM_CLOSE: + case SMB_COM_FIND_CLOSE2: + case SMB_COM_LOCKING_ANDX: { + unload_nls(nls_codepage); + return -EAGAIN; + } + } + } else { + up(&tcon->ses->sesSem); + } + unload_nls(nls_codepage); + + } else { + return -EIO; + } + } + if(rc) + return rc; + + *request_buf = cifs_small_buf_get(); + if (*request_buf == 0) { + /* BB should we add a retry in here if not a writepage? */ + return -ENOMEM; + } + + header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct); + +#ifdef CONFIG_CIFS_STATS + if(tcon != NULL) { + atomic_inc(&tcon->num_smbs_sent); + } +#endif /* CONFIG_CIFS_STATS */ + return rc; +} + +static int smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, void **request_buf /* returned */ , void **response_buf /* returned */ ) @@ -171,10 +263,42 @@ if(tcon != NULL) { atomic_inc(&tcon->num_smbs_sent); } -#endif +#endif /* CONFIG_CIFS_STATS */ return rc; } +static int validate_t2(struct smb_t2_rsp * pSMB) +{ + int rc = -EINVAL; + int total_size; + char * pBCC; + + /* check for plausible wct, bcc and t2 data and parm sizes */ + /* check for parm and data offset going beyond end of smb */ + if(pSMB->hdr.WordCount >= 10) { + if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) && + (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) { + /* check that bcc is at least as big as parms + data */ + /* check that bcc is less than negotiated smb buffer */ + total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount); + if(total_size < 512) { + total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount); + /* BCC le converted in SendReceive */ + pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + + (char *)pSMB; + if((total_size <= (*(u16 *)pBCC)) && + (total_size < + CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) { + return 0; + } + + } + } + } + cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB, + sizeof(struct smb_t2_rsp) + 16); + return rc; +} int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) { @@ -217,7 +341,7 @@ /* probably no need to store and check maxvcs */ server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), - (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE); + (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); cFYI(0, ("Max buf = %d ", ses->server->maxBuf)); GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); @@ -265,6 +389,12 @@ SecurityBlob, count - 16, &server->secType); + if(rc == 1) { + /* BB Need to fill struct for sessetup here */ + rc = -EOPNOTSUPP; + } else { + rc = -EINVAL; + } } } else server->capabilities &= ~CAP_EXTENDED_SECURITY; @@ -288,7 +418,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) { struct smb_hdr *smb_buffer; - struct smb_hdr *smb_buffer_response; + struct smb_hdr *smb_buffer_response; /* BB removeme BB */ int rc = 0; int length; @@ -322,20 +452,20 @@ up(&tcon->tconSem); return -EIO; } - - rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, - (void **) &smb_buffer, (void **) &smb_buffer_response); + rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer); if (rc) { up(&tcon->tconSem); return rc; - } + } else { + smb_buffer_response = smb_buffer; /* BB removeme BB */ + } rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, &length, 0); if (rc) cFYI(1, (" Tree disconnect failed %d", rc)); if (smb_buffer) - cifs_buf_release(smb_buffer); + cifs_small_buf_release(smb_buffer); up(&tcon->tconSem); /* No need to return error on this operation if tid invalidated and @@ -365,9 +495,8 @@ up(&ses->sesSem); return -EBUSY; } - - rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */, - (void **) &pSMB, (void **) &smb_buffer_response); + rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB); + smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ if(ses->server) { if(ses->server->secMode & @@ -395,7 +524,7 @@ } } if (pSMB) - cifs_buf_release(pSMB); + cifs_small_buf_release(pSMB); up(&ses->sesSem); /* if session dead then we do not need to do ulogoff, @@ -424,13 +553,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530 + cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); + name_len = strnlen(fileName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->fileName, fileName, name_len); } @@ -476,13 +605,13 @@ return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530 + name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(dirName, 530); + name_len = strnlen(dirName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->DirName, dirName, name_len); } @@ -526,13 +655,13 @@ return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530 + name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(name, 530); + name_len = strnlen(name, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->DirName, name, name_len); } @@ -583,7 +712,7 @@ count = 1; /* account for one byte pad to word boundary */ name_len = cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1), - fileName, 530 + fileName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ @@ -591,7 +720,7 @@ pSMB->NameLength = cpu_to_le16(name_len); } else { /* BB improve the check for buffer overruns BB */ count = 0; /* no pad */ - name_len = strnlen(fileName, 530); + name_len = strnlen(fileName, PATH_MAX); name_len++; /* trailing null */ pSMB->NameLength = cpu_to_le16(name_len); strncpy(pSMB->fileName, fileName, name_len); @@ -700,7 +829,7 @@ __u16 data_length = le16_to_cpu(pSMBr->DataLength); *nbytes = data_length; /*check that DataLength would not go beyond end of SMB */ - if ((data_length > CIFS_MAX_MSGSIZE) + if ((data_length > CIFSMaxBufSize) || (data_length > count)) { cFYI(1,("bad length %d for count %d",data_length,count)); rc = -EIO; @@ -733,7 +862,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, const int netfid, const unsigned int count, const __u64 offset, unsigned int *nbytes, const char *buf, - const int long_op) + const char __user * ubuf, const int long_op) { int rc = -EACCES; WRITE_REQ *pSMB = NULL; @@ -754,15 +883,29 @@ pSMB->Fid = netfid; pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); pSMB->OffsetHigh = cpu_to_le32(offset >> 32); + pSMB->Reserved = 0xFFFFFFFF; + pSMB->WriteMode = 0; pSMB->Remaining = 0; + /* BB can relax this if buffer is big enough in some cases - ie we can + send more if LARGE_WRITE_X capability returned by the server and if + our buffer is big enough or if we convert to iovecs on socket writes + and eliminate the copy to the CIFS buffer */ bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; if (bytes_sent > count) bytes_sent = count; pSMB->DataLengthHigh = 0; pSMB->DataOffset = cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); - - memcpy(pSMB->Data,buf,bytes_sent); + if(buf) + memcpy(pSMB->Data,buf,bytes_sent); + else if(ubuf) + copy_from_user(pSMB->Data,ubuf,bytes_sent); + else { + /* No buffer */ + if(pSMB) + cifs_buf_release(pSMB); + return -EINVAL; + } byte_count = bytes_sent + 1 /* pad */ ; pSMB->DataLengthLow = cpu_to_le16(bytes_sent); @@ -787,6 +930,66 @@ return rc; } +#ifdef CONFIG_CIFS_EXPERIMENTAL +int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, + const int netfid, const unsigned int count, + const __u64 offset, unsigned int *nbytes, const char __user *buf, + const int long_op) +{ + int rc = -EACCES; + WRITE_REQ *pSMB = NULL; + WRITE_RSP *pSMBr = NULL; + /*int bytes_returned;*/ + unsigned bytes_sent; + __u16 byte_count; + + rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); + pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */ + + if (rc) + return rc; + /* tcon and ses pointer are checked in smb_init */ + if (tcon->ses->server == NULL) + return -ECONNABORTED; + + pSMB->AndXCommand = 0xFF; /* none */ + pSMB->Fid = netfid; + pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); + pSMB->OffsetHigh = cpu_to_le32(offset >> 32); + pSMB->Reserved = 0xFFFFFFFF; + pSMB->WriteMode = 0; + pSMB->Remaining = 0; + bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; + if (bytes_sent > count) + bytes_sent = count; + pSMB->DataLengthHigh = 0; + pSMB->DataOffset = + cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); + + byte_count = bytes_sent + 1 /* pad */ ; + pSMB->DataLengthLow = cpu_to_le16(bytes_sent); + pSMB->DataLengthHigh = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + +/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */ + if (rc) { + cFYI(1, ("Send error in write2 (large write) = %d", rc)); + *nbytes = 0; + } else + *nbytes = le16_to_cpu(pSMBr->Count); + + if (pSMB) + cifs_small_buf_release(pSMB); + + /* Note: On -EAGAIN error only caller can retry on handle based calls + since file handle passed in no longer valid */ + + return rc; +} +#endif /* CIFS_EXPERIMENTAL */ + int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, const __u16 smb_file_id, const __u64 len, @@ -861,8 +1064,8 @@ cFYI(1, ("In CIFSSMBClose")); /* do not retry on dead session on close */ - rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB); + pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ if(rc == -EAGAIN) return 0; if (rc) @@ -879,8 +1082,9 @@ cERROR(1, ("Send error in Close = %d", rc)); } } + if (pSMB) - cifs_buf_release(pSMB); + cifs_small_buf_release(pSMB); /* Since session is dead, file will be closed on server already */ if(rc == -EAGAIN) @@ -915,7 +1119,7 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530 + cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ @@ -925,15 +1129,15 @@ pSMB->OldFileName[name_len + 1] = 0x00; name_len2 = cifs_strtoUCS((wchar_t *) & pSMB-> - OldFileName[name_len + 2], toName, 530, + OldFileName[name_len + 2], toName, PATH_MAX, nls_codepage); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, 530); + name_len = strnlen(fromName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->OldFileName, fromName, name_len); - name_len2 = strnlen(toName, 530); + name_len2 = strnlen(toName, PATH_MAX); name_len2++; /* trailing null */ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); @@ -1014,7 +1218,7 @@ sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid); len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage); } else { - len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage); + len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage); } rename_info->target_name_len = cpu_to_le32(2 * len_of_str); count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2; @@ -1073,7 +1277,7 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, - 530 /* find define for this maxpathcomponent */, + PATH_MAX /* find define for this maxpathcomponent */, nls_codepage); name_len++; /* trailing null */ name_len *= 2; @@ -1081,15 +1285,15 @@ /* protocol requires ASCII signature byte on Unicode string */ pSMB->OldFileName[name_len + 1] = 0x00; name_len2 = cifs_strtoUCS((wchar_t *) & pSMB-> - OldFileName[name_len + 2], toName, 530, + OldFileName[name_len + 2], toName, PATH_MAX, nls_codepage); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, 530); + name_len = strnlen(fromName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->OldFileName, fromName, name_len); - name_len2 = strnlen(toName, 530); + name_len2 = strnlen(toName, PATH_MAX); name_len2++; /* trailing null */ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); @@ -1139,14 +1343,14 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, 530); + name_len = strnlen(fromName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, fromName, name_len); } @@ -1163,13 +1367,13 @@ data_offset = (char *) (&pSMB->hdr.Protocol) + offset; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len_target = - cifs_strtoUCS((wchar_t *) data_offset, toName, 530 + cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len_target++; /* trailing null */ name_len_target *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len_target = strnlen(toName, 530); + name_len_target = strnlen(toName, PATH_MAX); name_len_target++; /* trailing null */ strncpy(data_offset, toName, name_len_target); } @@ -1230,14 +1434,14 @@ return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530 + name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(toName, 530); + name_len = strnlen(toName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, toName, name_len); } @@ -1254,13 +1458,13 @@ data_offset = (char *) (&pSMB->hdr.Protocol) + offset; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len_target = - cifs_strtoUCS((wchar_t *) data_offset, fromName, 530 + cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len_target++; /* trailing null */ name_len_target *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len_target = strnlen(fromName, 530); + name_len_target = strnlen(fromName, PATH_MAX); name_len_target++; /* trailing null */ strncpy(data_offset, fromName, name_len_target); } @@ -1326,7 +1530,7 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530 + cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ @@ -1335,15 +1539,15 @@ pSMB->OldFileName[name_len + 1] = 0x04; name_len2 = cifs_strtoUCS((wchar_t *) & pSMB-> - OldFileName[name_len + 2], toName, 530, + OldFileName[name_len + 2], toName, PATH_MAX, nls_codepage); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, 530); + name_len = strnlen(fromName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->OldFileName, fromName, name_len); - name_len2 = strnlen(toName, 530); + name_len2 = strnlen(toName, PATH_MAX); name_len2++; /* trailing null */ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); @@ -1392,13 +1596,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); + name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } @@ -1432,13 +1636,17 @@ (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc)); - } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - __u16 count = le16_to_cpu(pSMBr->DataCount); - if ((pSMBr->ByteCount < 2) || (data_offset > 512)) + } else { + /* decode response */ + + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + if (rc || (pSMBr->ByteCount < 2)) /* BB also check enough total bytes returned */ rc = -EIO; /* bad smb */ else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + __u16 count = le16_to_cpu(pSMBr->t2.DataCount); + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = UniStrnlen((wchar_t *) ((char *) &pSMBr->hdr.Protocol +data_offset), @@ -1550,6 +1758,306 @@ return rc; } +#ifdef CONFIG_CIFS_POSIX + +/*Convert an Access Control Entry from wire format to local POSIX xattr format*/ +static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace) +{ + /* u8 cifs fields do not need le conversion */ + ace->e_perm = (__u16)cifs_ace->cifs_e_perm; + ace->e_tag = (__u16)cifs_ace->cifs_e_tag; + ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid); + /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */ + + return; +} + +/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */ +static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area) +{ + int size = 0; + int i; + __u16 count; + struct cifs_posix_ace * pACE; + struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src; + posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt; + + if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION) + return -EOPNOTSUPP; + + if(acl_type & ACL_TYPE_ACCESS) { + count = le16_to_cpu(cifs_acl->access_entry_count); + pACE = &cifs_acl->ace_array[0]; + size = sizeof(struct cifs_posix_acl); + size += sizeof(struct cifs_posix_ace) * count; + /* check if we would go beyond end of SMB */ + if(size_of_data_area < size) { + cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size)); + return -EINVAL; + } + } else if(acl_type & ACL_TYPE_DEFAULT) { + count = le16_to_cpu(cifs_acl->access_entry_count); + size = sizeof(struct cifs_posix_acl); + size += sizeof(struct cifs_posix_ace) * count; +/* skip past access ACEs to get to default ACEs */ + pACE = &cifs_acl->ace_array[count]; + count = le16_to_cpu(cifs_acl->default_entry_count); + size += sizeof(struct cifs_posix_ace) * count; + /* check if we would go beyond end of SMB */ + if(size_of_data_area < size) + return -EINVAL; + } else { + /* illegal type */ + return -EINVAL; + } + + size = posix_acl_xattr_size(count); + if((buflen == 0) || (local_acl == NULL)) { + /* used to query ACL EA size */ + } else if(size > buflen) { + return -ERANGE; + } else /* buffer big enough */ { + local_acl->a_version = POSIX_ACL_XATTR_VERSION; + for(i = 0;i < count ;i++) { + cifs_convert_ace(&local_acl->a_entries[i],pACE); + pACE ++; + } + } + return size; +} + +__u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace, + const posix_acl_xattr_entry * local_ace) +{ + __u16 rc = 0; /* 0 = ACL converted ok */ + + cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm); + cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag); + /* BB is there a better way to handle the large uid? */ + if(local_ace->e_id == -1) { + /* Probably no need to le convert -1 on any arch but can not hurt */ + cifs_ace->cifs_uid = cpu_to_le64(-1); + } else + cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id); + /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/ + return rc; +} + +/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */ +__u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen, + const int acl_type) +{ + __u16 rc = 0; + struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data; + posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL; + int count; + int i; + + if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL)) + return 0; + + count = posix_acl_xattr_count((size_t)buflen); + cFYI(1,("setting acl with %d entries from buf of length %d and version of %d", + count,buflen,local_acl->a_version)); + if(local_acl->a_version != 2) { + cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version)); + return 0; + } + cifs_acl->version = cpu_to_le16(1); + if(acl_type == ACL_TYPE_ACCESS) + cifs_acl->access_entry_count = count; + else if(acl_type == ACL_TYPE_DEFAULT) + cifs_acl->default_entry_count = count; + else { + cFYI(1,("unknown ACL type %d",acl_type)); + return 0; + } + for(i=0;iace_array[i], + &local_acl->a_entries[i]); + if(rc != 0) { + /* ACE not converted */ + break; + } + } + if(rc == 0) { + rc = (__u16)(count * sizeof(struct cifs_posix_ace)); + rc += sizeof(struct cifs_posix_acl); + /* BB add check to make sure ACL does not overflow SMB */ + } + return rc; +} + +int +CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, + const unsigned char *searchName, + char *acl_inf, const int buflen, const int acl_type, + const struct nls_table *nls_codepage) +{ +/* SMB_QUERY_POSIX_ACL */ + TRANSACTION2_QPI_REQ *pSMB = NULL; + TRANSACTION2_QPI_RSP *pSMBr = NULL; + int rc = 0; + int bytes_returned; + int name_len; + __u16 params, byte_count; + + cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName)); + +queryAclRetry: + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { + name_len = + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX + /* BB fixme find define for this maxpathcomponent */ + , nls_codepage); + name_len++; /* trailing null */ + name_len *= 2; + pSMB->FileName[name_len] = 0; + pSMB->FileName[name_len+1] = 0; + } else { /* BB improve the check for buffer overruns BB */ + name_len = strnlen(searchName, PATH_MAX /* BB fixme */); + name_len++; /* trailing null */ + strncpy(pSMB->FileName, searchName, name_len); + } + + params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; + pSMB->TotalDataCount = 0; + pSMB->MaxParameterCount = cpu_to_le16(2); + /* BB find exact max data count below from sess structure BB */ + pSMB->MaxDataCount = cpu_to_le16(4000); + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + pSMB->ParameterOffset = cpu_to_le16( + offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4); + pSMB->DataCount = 0; + pSMB->DataOffset = 0; + pSMB->SetupCount = 1; + pSMB->Reserved3 = 0; + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); + byte_count = params + 1 /* pad */ ; + pSMB->TotalParameterCount = cpu_to_le16(params); + pSMB->ParameterCount = pSMB->TotalParameterCount; + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); + pSMB->Reserved4 = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + if (rc) { + cFYI(1, ("Send error in Query POSIX ACL = %d", rc)); + } else { + /* decode response */ + + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + if (rc || (pSMBr->ByteCount < 2)) + /* BB also check enough total bytes returned */ + rc = -EIO; /* bad smb */ + else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + __u16 count = le16_to_cpu(pSMBr->t2.DataCount); + rc = cifs_copy_posix_acl(acl_inf, + (char *)&pSMBr->hdr.Protocol+data_offset, + buflen,acl_type,count); + } + } + if (pSMB) + cifs_buf_release(pSMB); + if (rc == -EAGAIN) + goto queryAclRetry; + return rc; +} + +int +CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, + const unsigned char *fileName, + const char *local_acl, const int buflen, const int acl_type, + const struct nls_table *nls_codepage) +{ + struct smb_com_transaction2_spi_req *pSMB = NULL; + struct smb_com_transaction2_spi_rsp *pSMBr = NULL; + char *parm_data; + int name_len; + int rc = 0; + int bytes_returned = 0; + __u16 params, byte_count, data_count, param_offset, offset; + + cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName)); +setAclRetry: + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { + name_len = + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX + /* BB fixme find define for this maxpathcomponent */ + , nls_codepage); + name_len++; /* trailing null */ + name_len *= 2; + } else { /* BB improve the check for buffer overruns BB */ + name_len = strnlen(fileName, PATH_MAX); + name_len++; /* trailing null */ + strncpy(pSMB->FileName, fileName, name_len); + } + params = 6 + name_len; + pSMB->MaxParameterCount = cpu_to_le16(2); + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + param_offset = offsetof(struct smb_com_transaction2_spi_req, + InformationLevel) - 4; + offset = param_offset + params; + parm_data = ((char *) &pSMB->hdr.Protocol) + offset; + pSMB->ParameterOffset = cpu_to_le16(param_offset); + + /* convert to on the wire format for POSIX ACL */ + data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type); + + if(data_count == 0) { + rc = -EOPNOTSUPP; + goto setACLerrorExit; + } + pSMB->DataOffset = cpu_to_le16(offset); + pSMB->SetupCount = 1; + pSMB->Reserved3 = 0; + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); + pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL); + byte_count = 3 /* pad */ + params + data_count; + pSMB->DataCount = cpu_to_le16(data_count); + pSMB->TotalDataCount = pSMB->DataCount; + pSMB->ParameterCount = cpu_to_le16(params); + pSMB->TotalParameterCount = pSMB->ParameterCount; + pSMB->Reserved4 = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + if (rc) { + cFYI(1, ("Set POSIX ACL returned %d", rc)); + } + +setACLerrorExit: + if (pSMB) + cifs_buf_release(pSMB); + if (rc == -EAGAIN) + goto setAclRetry; + return rc; +} + +#endif + int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, @@ -1564,7 +2072,7 @@ int name_len; __u16 params, byte_count; - cFYI(1, ("In QPathInfo path %s", searchName)); +/* cFYI(1, ("In QPathInfo path %s", searchName)); */ /* BB fixme BB */ QPathInfoRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -1573,13 +2081,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); + name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } @@ -1613,13 +2121,12 @@ if (rc) { cFYI(1, ("Send error in QPathInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - /* BB also check enough total bytes returned */ - /* BB we need to improve the validity checking - of these trans2 responses */ - if ((pSMBr->ByteCount < 40) || (data_offset > 512)) + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 40)) rc = -EIO; /* bad smb */ else if (pFindData){ + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); memcpy((char *) pFindData, (char *) &pSMBr->hdr.Protocol + data_offset, sizeof (FILE_ALL_INFO)); @@ -1657,13 +2164,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); + name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } @@ -1698,15 +2205,12 @@ if (rc) { cFYI(1, ("Send error in QPathInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - /* BB also check if enough total bytes returned */ - if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) || - (data_offset > 512) || - (data_offset < sizeof(struct smb_hdr))) { - cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d", - (int)data_offset,bytes_returned)); + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { rc = -EIO; /* bad smb */ } else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); memcpy((char *) pFindData, (char *) &pSMBr->hdr.Protocol + data_offset, @@ -1721,6 +2225,7 @@ return rc; } +#ifdef CONFIG_CIFS_EXPERIMENTAL /* function unused at present */ int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon, const char *searchName, FILE_ALL_INFO * findData, @@ -1743,13 +2248,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); + name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } @@ -1764,7 +2269,7 @@ pSMB->Timeout = 0; pSMB->Reserved2 = 0; pSMB->ParameterOffset = cpu_to_le16( - offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4); + offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4); pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->SetupCount = 1; /* one byte, no need to le convert */ @@ -1799,6 +2304,7 @@ return rc; } +#endif /* CIFS_EXPERIMENTAL */ int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, @@ -1825,13 +2331,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); + name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } @@ -1849,8 +2355,8 @@ byte_count = params + 1 /* pad */ ; pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->ParameterOffset = cpu_to_le16(offsetof(struct - smb_com_transaction2_ffirst_req, SearchAttributes) - 4); + pSMB->ParameterOffset = cpu_to_le16( + offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4); pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->SetupCount = 1; /* one byte no need to make endian neutral */ @@ -1859,7 +2365,7 @@ pSMB->SearchAttributes = cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); - pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */ + pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */ pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); /* test for Unix extensions */ @@ -1880,20 +2386,25 @@ if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ cFYI(1, ("Error in FindFirst = %d", rc)); - } else { /* decode response */ + } else { + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + if(!rc) { + /* decode response */ /* BB add safety checks for these memcpys */ - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - *pUnicodeFlag = TRUE; - else - *pUnicodeFlag = FALSE; - memcpy(findParms, - (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->ParameterOffset), - sizeof (T2_FFIRST_RSP_PARMS)); - response_data = - (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->DataOffset); - memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount)); + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) + *pUnicodeFlag = TRUE; + else + *pUnicodeFlag = FALSE; + memcpy(findParms, + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.ParameterOffset), + sizeof (T2_FFIRST_RSP_PARMS)); + response_data = + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.DataOffset); + memcpy(findData, response_data, + le16_to_cpu(pSMBr->t2.DataCount)); + } } if (pSMB) cifs_buf_release(pSMB); @@ -1904,6 +2415,256 @@ return rc; } +/* xid, tcon, searchName and codepage are input parms, rest are returned */ +int +CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon, + const char *searchName, + const struct nls_table *nls_codepage, + __u16 * pnetfid, + struct cifs_search_info * psrch_inf) +{ +/* level 257 SMB_ */ + TRANSACTION2_FFIRST_REQ *pSMB = NULL; + TRANSACTION2_FFIRST_RSP *pSMBr = NULL; + T2_FFIRST_RSP_PARMS * parms; + int rc = 0; + int bytes_returned = 0; + int name_len; + __u16 params, byte_count; + + cFYI(1, ("In FindFirst2")); + +findFirst2Retry: + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { + name_len = + cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName, + PATH_MAX, nls_codepage); + name_len++; /* trailing null */ + name_len *= 2; + pSMB->FileName[name_len] = 0; /* null terminate just in case */ + pSMB->FileName[name_len+1] = 0; + } else { /* BB add check for overrun of SMB buf BB */ + name_len = strnlen(searchName, PATH_MAX); + name_len++; /* trailing null */ +/* BB fix here and in unicode clause above ie + if(name_len > buffersize-header) + free buffer exit; BB */ + strncpy(pSMB->FileName, searchName, name_len); + pSMB->FileName[name_len] = 0; /* just in case */ + } + + params = 12 + name_len /* includes null */ ; + pSMB->TotalDataCount = 0; /* no EAs */ + pSMB->MaxParameterCount = cpu_to_le16(10); + pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + byte_count = params + 1 /* pad */ ; + pSMB->TotalParameterCount = cpu_to_le16(params); + pSMB->ParameterCount = pSMB->TotalParameterCount; + pSMB->ParameterOffset = cpu_to_le16( + offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4); + pSMB->DataCount = 0; + pSMB->DataOffset = 0; + pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */ + pSMB->Reserved3 = 0; + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST); + pSMB->SearchAttributes = + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | + ATTR_DIRECTORY); + pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO)); + pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | + CIFS_SEARCH_RETURN_RESUME); + pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); + + /* BB what should we set StorageType to? Does it matter? BB */ + pSMB->SearchStorageType = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + + if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ + /* BB Add code to handle unsupported level rc */ + cFYI(1, ("Error in FindFirst = %d", rc)); + + if (pSMB) + cifs_buf_release(pSMB); + + /* BB eventually could optimize out free and realloc of buf */ + /* for this case */ + if (rc == -EAGAIN) + goto findFirst2Retry; + } else { /* decode response */ + /* BB remember to free buffer if error BB */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + if(rc == 0) { + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) + psrch_inf->unicode = TRUE; + else + psrch_inf->unicode = FALSE; + + psrch_inf->ntwrk_buf_start = (char *)pSMBr; + psrch_inf->srch_entries_start = + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.DataOffset); + + parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.ParameterOffset)); + + if(parms->EndofSearch) + psrch_inf->endOfSearch = TRUE; + else + psrch_inf->endOfSearch = FALSE; + + psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); + psrch_inf->index_of_last_entry = + psrch_inf->entries_in_buffer; +/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */ + *pnetfid = parms->SearchHandle; + } else { + if(pSMB) + cifs_buf_release(pSMB); + } + } + + return rc; +} + +int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon, + __u16 searchHandle, struct cifs_search_info * psrch_inf) +{ + TRANSACTION2_FNEXT_REQ *pSMB = NULL; + TRANSACTION2_FNEXT_RSP *pSMBr = NULL; + T2_FNEXT_RSP_PARMS * parms; + char *response_data; + int rc = 0; + int bytes_returned, name_len; + __u16 params, byte_count; + + cFYI(1, ("In FindNext2")); + + if(psrch_inf->endOfSearch == TRUE) + return -ENOENT; + + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + + params = 14; /* includes 2 bytes of null string, converted to LE below */ + byte_count = 0; + pSMB->TotalDataCount = 0; /* no EAs */ + pSMB->MaxParameterCount = cpu_to_le16(8); + pSMB->MaxDataCount = + cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + pSMB->ParameterOffset = cpu_to_le16( + offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4); + pSMB->DataCount = 0; + pSMB->DataOffset = 0; + pSMB->SetupCount = 1; + pSMB->Reserved3 = 0; + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); + pSMB->SearchHandle = searchHandle; /* always kept as le */ + pSMB->SearchCount = + cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO)); + /* test for Unix extensions */ +/* if (tcon->ses->capabilities & CAP_UNIX) { + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX); + psrch_inf->info_level = SMB_FIND_FILE_UNIX; + } else { + pSMB->InformationLevel = + cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO); + psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO; + } */ + pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); + pSMB->ResumeKey = psrch_inf->resume_key; + pSMB->SearchFlags = + cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); + + name_len = psrch_inf->resume_name_len; + params += name_len; + if(name_len < PATH_MAX) { + memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len); + byte_count += name_len; + } else { + rc = -EINVAL; + goto FNext2_err_exit; + } + byte_count = params + 1 /* pad */ ; + pSMB->TotalParameterCount = cpu_to_le16(params); + pSMB->ParameterCount = pSMB->TotalParameterCount; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + + if (rc) { + if (rc == -EBADF) { + psrch_inf->endOfSearch = TRUE; + rc = 0; /* search probably was closed at end of search above */ + } else + cFYI(1, ("FindNext returned = %d", rc)); + } else { /* decode response */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if(rc == 0) { + /* BB fixme add lock for file (srch_info) struct here */ + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) + psrch_inf->unicode = TRUE; + else + psrch_inf->unicode = FALSE; + response_data = (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.ParameterOffset); + parms = (T2_FNEXT_RSP_PARMS *)response_data; + response_data = (char *)&pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.DataOffset); + cifs_buf_release(psrch_inf->ntwrk_buf_start); + psrch_inf->srch_entries_start = response_data; + psrch_inf->ntwrk_buf_start = (char *)pSMB; + if(parms->EndofSearch) + psrch_inf->endOfSearch = TRUE; + else + psrch_inf->endOfSearch = FALSE; + + psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); + psrch_inf->index_of_last_entry += + psrch_inf->entries_in_buffer; +/* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */ + + /* BB fixme add unlock here */ + } + + } + + /* BB On error, should we leave previous search buf (and count and + last entry fields) intact or free the previous one? */ + + /* Note: On -EAGAIN error only caller can retry on handle based calls + since file handle passed in no longer valid */ +FNext2_err_exit: + if ((rc != 0) && pSMB) + cifs_buf_release(pSMB); + + return rc; +} + int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms, @@ -1939,8 +2700,8 @@ pSMB->Flags = 0; pSMB->Timeout = 0; pSMB->Reserved2 = 0; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_fnext_req,SearchHandle) - 4); + pSMB->ParameterOffset = cpu_to_le16( + offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4); pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->SetupCount = 1; @@ -1949,7 +2710,7 @@ pSMB->SearchHandle = searchHandle; /* always kept as le */ findParms->SearchCount = 0; /* set to zero in case of error */ pSMB->SearchCount = - cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); + cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO)); /* test for Unix extensions */ if (tcon->ses->capabilities & CAP_UNIX) { pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX); @@ -1963,7 +2724,7 @@ pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); /* BB add check to make sure we do not cross end of smb */ - if(name_len < CIFS_MAX_MSGSIZE) { + if(name_len < PATH_MAX) { memcpy(pSMB->ResumeFileName, resume_file_name, name_len); byte_count += name_len; } @@ -1984,19 +2745,23 @@ else cFYI(1, ("FindNext returned = %d", rc)); } else { /* decode response */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + /* BB add safety checks for these memcpys */ - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - *pUnicodeFlag = TRUE; - else - *pUnicodeFlag = FALSE; - memcpy(findParms, - (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->ParameterOffset), - sizeof (T2_FNEXT_RSP_PARMS)); - response_data = - (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->DataOffset); - memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount)); + if(rc == 0) { + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) + *pUnicodeFlag = TRUE; + else + *pUnicodeFlag = FALSE; + memcpy(findParms, + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.ParameterOffset), + sizeof (T2_FNEXT_RSP_PARMS)); + response_data = + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.DataOffset); + memcpy(findData,response_data,le16_to_cpu(pSMBr->t2.DataCount)); + } } if (pSMB) cifs_buf_release(pSMB); @@ -2012,12 +2777,12 @@ { int rc = 0; FINDCLOSE_REQ *pSMB = NULL; - CLOSE_RSP *pSMBr = NULL; + CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */ int bytes_returned; cFYI(1, ("In CIFSSMBFindClose")); - rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); + pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ /* no sense returning error if session restarted file handle has been closed */ if(rc == -EAGAIN) @@ -2033,7 +2798,7 @@ cERROR(1, ("Send error in FindClose = %d", rc)); } if (pSMB) - cifs_buf_release(pSMB); + cifs_small_buf_release(pSMB); /* Since session is dead, search handle closed on server already */ if (rc == -EAGAIN) @@ -2042,6 +2807,39 @@ return rc; } +#ifdef CONFIG_CIFS_EXPERIMENTAL +int +CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, + const unsigned char *searchName, + __u64 * inode_number, + const struct nls_table *nls_codepage) +{ + int rc = 0; + TRANSACTION2_QPI_REQ *pSMB = NULL; + TRANSACTION2_QPI_RSP *pSMBr = NULL; + + cFYI(1,("In GetSrvInodeNumber for %s",searchName)); + if(tcon == NULL) + return -ENODEV; + + cFYI(1, ("In QPathInfo path %s", searchName)); +GetInodeNumberRetry: + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + +/* BB add missing code here */ + + if (pSMB) + cifs_buf_release(pSMB); + + if (rc == -EAGAIN) + goto GetInodeNumberRetry; + return rc; +} +#endif /* CIFS_EXPERIMENTAL */ + int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, const unsigned char *searchName, @@ -2084,13 +2882,13 @@ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; name_len = cifs_strtoUCS((wchar_t *) pSMB->RequestFileName, - searchName, 530 + searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); + name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->RequestFileName, searchName, name_len); } @@ -2124,14 +2922,17 @@ cFYI(1, ("Send error in GetDFSRefer = %d", rc)); } else { /* decode response */ /* BB Add logic to parse referrals here */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - __u16 data_count = le16_to_cpu(pSMBr->DataCount); - cFYI(1, - ("Decoding GetDFSRefer response. BCC: %d Offset %d", - pSMBr->ByteCount, data_offset)); - if ((pSMBr->ByteCount < 17) || (data_offset > 512)) /* BB also check enough total bytes returned */ - rc = -EIO; /* bad smb */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */ + rc = -EIO; /* bad smb */ else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount); + + cFYI(1, + ("Decoding GetDFSRefer response. BCC: %d Offset %d", + pSMBr->ByteCount, data_offset)); referrals = (struct dfs_referral_level_3 *) (8 /* sizeof start of data block */ + @@ -2257,13 +3058,16 @@ if (rc) { cERROR(1, ("Send error in QFSInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - cFYI(1, - ("Decoding qfsinfo response. BCC: %d Offset %d", - pSMBr->ByteCount, data_offset)); - if ((pSMBr->ByteCount < 24) || (data_offset > 512)) /* BB also check enough total bytes returned */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */ rc = -EIO; /* bad smb */ else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + cFYI(1, + ("Decoding qfsinfo response. BCC: %d Offset %d", + pSMBr->ByteCount, data_offset)); + response_data = (FILE_SYSTEM_INFO *) (((char *) &pSMBr->hdr.Protocol) + @@ -2339,10 +3143,12 @@ if (rc) { cERROR(1, ("Send error in QFSAttributeInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - if ((pSMBr->ByteCount < 13) || (data_offset > 512)) { /* BB also check enough bytes returned */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */ rc = -EIO; /* bad smb */ } else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); response_data = (FILE_SYSTEM_ATTRIBUTE_INFO *) (((char *) &pSMBr->hdr.Protocol) + @@ -2408,11 +3214,12 @@ if (rc) { cFYI(1, ("Send error in QFSDeviceInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)) - || (data_offset > 512)) + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))) rc = -EIO; /* bad smb */ else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); response_data = (FILE_SYSTEM_DEVICE_INFO *) (((char *) &pSMBr->hdr.Protocol) + @@ -2477,10 +3284,12 @@ if (rc) { cERROR(1, ("Send error in QFSUnixInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - if ((pSMBr->ByteCount < 13) || (data_offset > 512)) { + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 13)) { rc = -EIO; /* bad smb */ } else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); response_data = (FILE_SYSTEM_UNIX_INFO *) (((char *) &pSMBr->hdr.Protocol) + @@ -2526,13 +3335,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); + name_len = strnlen(fileName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, fileName, name_len); } @@ -2705,13 +3514,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); + name_len = strnlen(fileName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, fileName, name_len); } @@ -2785,13 +3594,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); + name_len = strnlen(fileName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, fileName, name_len); } @@ -2821,12 +3630,7 @@ pSMB->ParameterCount = cpu_to_le16(params); pSMB->TotalDataCount = pSMB->DataCount; pSMB->TotalParameterCount = pSMB->ParameterCount; - /* I doubt that passthrough levels apply to this old - preNT info level */ -/* if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2); - else*/ - pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD); + pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD); pSMB->Reserved4 = 0; pSMB->hdr.smb_buf_length += byte_count; memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD)); @@ -2868,13 +3672,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); + name_len = strnlen(fileName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, fileName, name_len); } @@ -2894,6 +3698,7 @@ data_offset = (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol + offset); + memset(data_offset, 0, count); pSMB->DataOffset = cpu_to_le16(offset); pSMB->ParameterOffset = cpu_to_le16(param_offset); pSMB->SetupCount = 1; @@ -2980,7 +3785,7 @@ pSMB->ByteCount = 0; rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); + (struct smb_hdr *) pSMBr, &bytes_returned, -1); if (rc) { cFYI(1, ("Error in Notify = %d", rc)); } @@ -3016,13 +3821,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); + name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } @@ -3056,11 +3861,12 @@ if (rc) { cFYI(1, ("Send error in QueryAllEAs = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + /* BB also check enough total bytes returned */ /* BB we need to improve the validity checking of these trans2 responses */ - if ((pSMBr->ByteCount < 4) || (data_offset > 512)) + if (rc || (pSMBr->ByteCount < 4)) rc = -EIO; /* bad smb */ /* else if (pFindData){ memcpy((char *) pFindData, @@ -3072,6 +3878,7 @@ of list */ /* check that each element of each entry does not go beyond end of list */ + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); struct fealist * ea_response_data; rc = 0; /* validate_trans2_offsets() */ @@ -3158,13 +3965,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, 530); + name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } @@ -3198,11 +4005,12 @@ if (rc) { cFYI(1, ("Send error in Query EA = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + /* BB also check enough total bytes returned */ /* BB we need to improve the validity checking of these trans2 responses */ - if ((pSMBr->ByteCount < 4) || (data_offset > 512)) + if (rc || (pSMBr->ByteCount < 4)) rc = -EIO; /* bad smb */ /* else if (pFindData){ memcpy((char *) pFindData, @@ -3214,8 +4022,9 @@ of list */ /* check that each element of each entry does not go beyond end of list */ + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); struct fealist * ea_response_data; - rc = -ENOENT; + rc = -ENODATA; /* validate_trans2_offsets() */ /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/ ea_response_data = (struct fealist *) @@ -3303,13 +4112,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530 + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, 530); + name_len = strnlen(fileName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, fileName, name_len); } Index: wli-2.6.10-rc3-1/fs/cifs/connect.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/connect.c 2004-12-22 09:07:09.686249346 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/connect.c 2004-12-22 10:04:36.559245002 -0800 @@ -58,6 +58,7 @@ char *domainname; char *UNC; char *UNCip; + char *in6_addr; /* ipv6 address as human readable form of in6_addr */ char *iocharset; /* local code page for mapping to and from Unicode */ char source_rfc1001_name[16]; /* netbios name of client */ uid_t linux_uid; @@ -69,6 +70,9 @@ unsigned intr:1; unsigned setuids:1; unsigned noperm:1; + unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ + unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ + unsigned direct_io:1; unsigned int rsize; unsigned int wsize; unsigned int sockopt; @@ -213,7 +217,7 @@ write_unlock(&GlobalSMBSeslock); if(length > 1) { mempool_resize(cifs_req_poolp, - length + CIFS_MIN_RCV_POOL, + length + cifs_min_rcv, GFP_KERNEL); } @@ -250,7 +254,8 @@ cFYI(1,("call to reconnect done")); csocket = server->ssocket; continue; - } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { + } else if ((length == -ERESTARTSYS) || (length == -EAGAIN) + || ((length > 0) && (length <= 3)) ) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); /* minimum sleep to prevent looping allowing socket to clear and app threads to set @@ -276,7 +281,7 @@ } pdu_length = 4 + ntohl(smb_buffer->smb_buf_length); - /* Ony read pdu_length after below checks for too short (due + /* Only read pdu_length after below checks for too short (due to e.g. int overflow) and too long ie beyond end of buf */ cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length)); @@ -326,18 +331,24 @@ csocket = server->ssocket; continue; } else { - if ((length != sizeof (struct smb_hdr) - 1) - || (pdu_length > - CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) + if (length < 16) { + /* We can not validate the SMB unless + at least this much of SMB available + so give the socket time to copy + a few more bytes and retry */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(10); + continue; + } else if( (pdu_length > + CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) || (pdu_length < sizeof (struct smb_hdr) - 1) - || - (checkSMBhdr + || (checkSMBhdr (smb_buffer, smb_buffer->Mid))) { cERROR(1, - ("Invalid size or format for SMB found with length %d and pdu_lenght %d", + ("Invalid size or format for SMB found with length %d and pdu_length %d", length, pdu_length)); - cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); + cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)+3); /* could we fix this network corruption by finding next smb header (instead of killing the session) and restart reading from next valid SMB found? */ @@ -485,7 +496,7 @@ write_unlock(&GlobalSMBSeslock); if(length > 0) { mempool_resize(cifs_req_poolp, - length + CIFS_MIN_RCV_POOL, + length + cifs_min_rcv, GFP_KERNEL); } @@ -505,7 +516,7 @@ } static int -cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol) +cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) { char *value; char *data; @@ -692,7 +703,12 @@ vol->file_mode = simple_strtoul(value, &value, 0); } - } else if (strnicmp(data, "dir_mode", 3) == 0) { + } else if (strnicmp(data, "dir_mode", 4) == 0) { + if (value && *value) { + vol->dir_mode = + simple_strtoul(value, &value, 0); + } + } else if (strnicmp(data, "dirmode", 4) == 0) { if (value && *value) { vol->dir_mode = simple_strtoul(value, &value, 0); @@ -742,6 +758,8 @@ /* ignore */ } else if (strnicmp(data, "version", 3) == 0) { /* ignore */ + } else if (strnicmp(data, "guest",5) == 0) { + /* ignore */ } else if (strnicmp(data, "rw", 2) == 0) { vol->rw = TRUE; } else if ((strnicmp(data, "suid", 4) == 0) || @@ -780,6 +798,27 @@ vol->intr = 0; } else if (strnicmp(data, "intr", 4) == 0) { vol->intr = 1; + } else if (strnicmp(data, "serverino",7) == 0) { + vol->server_ino = 1; + } else if (strnicmp(data, "noserverino",9) == 0) { + vol->server_ino = 0; + } else if (strnicmp(data, "acl",3) == 0) { + vol->no_psx_acl = 0; + } else if (strnicmp(data, "noacl",5) == 0) { + vol->no_psx_acl = 1; + } else if (strnicmp(data, "direct",6) == 0) { + vol->direct_io = 1; + } else if (strnicmp(data, "forcedirectio",13) == 0) { + vol->direct_io = 1; + } else if (strnicmp(data, "in6_addr",8) == 0) { + if (!value || !*value) { + vol->in6_addr = NULL; + } else if (strnlen(value, 49) == 48) { + vol->in6_addr = value; + } else { + printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n"); + return 1; + } } else if (strnicmp(data, "noac", 4) == 0) { printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n"); } else @@ -1393,6 +1432,12 @@ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; if(volume_info.setuids) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; + if(volume_info.server_ino) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; + if(volume_info.direct_io) { + cERROR(1,("mounting share using direct i/o")); + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; + } tcon = find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, @@ -1482,8 +1527,16 @@ /* do not care if following two calls succeed - informational only */ CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls); CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls); - if (tcon->ses->capabilities & CAP_UNIX) - CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls); + if (tcon->ses->capabilities & CAP_UNIX) { + if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) { + if(!volume_info.no_psx_acl) { + if(CIFS_UNIX_POSIX_ACL_CAP & + le64_to_cpu(tcon->fsUnixInfo.Capability)) + cFYI(1,("server negotiated posix acl support")); + sb->s_flags |= MS_POSIXACL; + } + } + } } /* volume_info.password is freed above when existing session found @@ -1552,14 +1605,15 @@ capabilities |= CAP_DFS; } pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); - /* pSMB->req_no_secext.CaseInsensitivePasswordLength = - CIFS_SESSION_KEY_SIZE; */ - pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; + + pSMB->req_no_secext.CaseInsensitivePasswordLength = + cpu_to_le16(CIFS_SESSION_KEY_SIZE); + pSMB->req_no_secext.CaseSensitivePasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); bcc_ptr = pByteArea(smb_buffer); - /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE); - bcc_ptr += CIFS_SESSION_KEY_SIZE; */ + memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); + bcc_ptr += CIFS_SESSION_KEY_SIZE; memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); bcc_ptr += CIFS_SESSION_KEY_SIZE; Index: wli-2.6.10-rc3-1/fs/cifs/dir.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/dir.c 2004-12-22 09:07:09.686249346 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/dir.c 2004-12-22 10:04:36.562244546 -0800 @@ -399,9 +399,6 @@ (" parent inode = 0x%p name is: %s and dentry = 0x%p", parent_dir_inode, direntry->d_name.name, direntry)); - if(nd) { /* BB removeme */ - cFYI(1,("In lookup nd flags 0x%x open intent flags 0x%x",nd->flags,nd->intent.open.flags)); - } /* BB removeme BB */ /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */ /* check whether path exists */ Index: wli-2.6.10-rc3-1/fs/cifs/fcntl.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/fcntl.c 2004-12-22 09:07:09.687249194 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/fcntl.c 2004-12-22 10:04:36.565244090 -0800 @@ -28,6 +28,44 @@ #include "cifs_unicode.h" #include "cifs_debug.h" +__u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags) +{ + __u32 cifs_ntfy_flags = 0; + + /* No way on Linux VFS to ask to monitor xattr + changes (and no stream support either */ + if(fcntl_notify_flags & DN_ACCESS) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS; + } + if(fcntl_notify_flags & DN_MODIFY) { + /* What does this mean on directories? */ + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_SIZE; + } + if(fcntl_notify_flags & DN_CREATE) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_LAST_WRITE; + } + if(fcntl_notify_flags & DN_DELETE) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE; + } + if(fcntl_notify_flags & DN_RENAME) { + /* BB review this - checking various server behaviors */ + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_FILE_NAME; + } + if(fcntl_notify_flags & DN_ATTRIB) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY | + FILE_NOTIFY_CHANGE_ATTRIBUTES; + } +/* if(fcntl_notify_flags & DN_MULTISHOT) { + cifs_ntfy_flags |= ; + } */ /* BB fixme - not sure how to handle this with CIFS yet */ + + + return cifs_ntfy_flags; +} + int cifs_dir_notify(struct file * file, unsigned long arg) { int xid; @@ -37,7 +75,7 @@ struct cifsTconInfo *pTcon; char *full_path = NULL; __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; - __u16 netfid; + __u16 netfid; xid = GetXid(); cifs_sb = CIFS_SB(file->f_dentry->d_sb); @@ -50,20 +88,26 @@ if(full_path == NULL) { rc = -ENOMEM; } else { - cFYI(1,("cifs dir notify on file %s",full_path)); + cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ | SYNCHRONIZE, 0 /* create options */, &netfid, &oplock,NULL, cifs_sb->local_nls); /* BB fixme - add this handle to a notify handle list */ if(rc) { - cFYI(1,("Could not open directory for notify")); + cERROR(1,("Could not open directory for notify")); /* BB remove BB */ } else { - rc = CIFSSMBNotify(xid, pTcon, 1 /* subdirs */, netfid, - filter, cifs_sb->local_nls); + filter = convert_to_cifs_notify_flags(arg); + if(filter != 0) { + rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, + filter, cifs_sb->local_nls); + } else { + rc = -EINVAL; + } /* BB add code to close file eventually (at unmount it would close automatically but may be a way to do it easily when inode freed or when notify info is cleared/changed */ + cERROR(1,("notify rc %d",rc)); } } Index: wli-2.6.10-rc3-1/fs/cifs/file.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/file.c 2004-12-22 09:07:09.688249042 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/file.c 2004-12-22 10:04:36.582241506 -0800 @@ -35,6 +35,8 @@ #include "cifs_debug.h" #include "cifs_fs_sb.h" +extern int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir); /* BB removeme BB */ + int cifs_open(struct inode *inode, struct file *file) { @@ -62,7 +64,7 @@ read_lock(&GlobalSMBSeslock); list_for_each(tmp, &pCifsInode->openFileList) { pCifsFile = list_entry(tmp,struct cifsFileInfo, flist); - if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){ + if((pCifsFile->pfile == NULL)&& (pCifsFile->pid == current->tgid)){ /* mode set in cifs_create */ pCifsFile->pfile = file; /* needed for writepage */ file->private_data = pCifsFile; @@ -166,7 +168,7 @@ memset(file->private_data, 0, sizeof(struct cifsFileInfo)); pCifsFile = (struct cifsFileInfo *) file->private_data; pCifsFile->netfid = netfid; - pCifsFile->pid = current->pid; + pCifsFile->pid = current->tgid; init_MUTEX(&pCifsFile->fh_sem); pCifsFile->pfile = file; /* needed for writepage */ pCifsFile->pInode = inode; @@ -452,18 +454,44 @@ { int rc = 0; int xid; - struct cifsFileInfo *pSMBFileStruct = + struct cifsFileInfo *pCFileStruct = (struct cifsFileInfo *) file->private_data; + char * ptmp; cFYI(1, ("Closedir inode = 0x%p with ", inode)); xid = GetXid(); - if (pSMBFileStruct) { + if (pCFileStruct) { + struct cifsTconInfo *pTcon; + struct cifs_sb_info * cifs_sb = CIFS_SB(file->f_dentry->d_sb); + + pTcon = cifs_sb->tcon; + cFYI(1, ("Freeing private data in close dir")); + if(pCFileStruct->srch_inf.endOfSearch == FALSE) { + pCFileStruct->invalidHandle = TRUE; + rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); + cFYI(1,("Closing uncompleted readdir with rc %d",rc)); + /* not much we can do if it fails anywway, ignore rc */ + rc = 0; + } + ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; + if(ptmp) { + cFYI(1,("freeing smb buf in srch struct in closedir")); /* BB removeme BB */ + pCFileStruct->srch_inf.ntwrk_buf_start = NULL; + cifs_buf_release(ptmp); + } + ptmp = pCFileStruct->search_resume_name; + if(ptmp) { + cFYI(1,("freeing resume name in closedir")); /* BB removeme BB */ + pCFileStruct->search_resume_name = NULL; + kfree(ptmp); + } kfree(file->private_data); file->private_data = NULL; } + /* BB can we lock the filestruct while this is going on? */ FreeXid(xid); return rc; } @@ -570,12 +598,131 @@ pfLock->fl_start, numUnlock, numLock, lockType, wait_flag); if (rc == 0 && (pfLock->fl_flags & FL_POSIX)) - posix_lock_file(file, pfLock); + posix_lock_file_wait(file, pfLock); FreeXid(xid); return rc; } ssize_t +cifs_user_write(struct file * file, const char __user * write_data, + size_t write_size, loff_t * poffset) +{ + int rc = 0; + unsigned int bytes_written = 0; + unsigned int total_written; + struct cifs_sb_info *cifs_sb; + struct cifsTconInfo *pTcon; + int xid, long_op; + struct cifsFileInfo * open_file; + + if(file->f_dentry == NULL) + return -EBADF; + + cifs_sb = CIFS_SB(file->f_dentry->d_sb); + if(cifs_sb == NULL) { + return -EBADF; + } + pTcon = cifs_sb->tcon; + + /*cFYI(1, + (" write %d bytes to offset %lld of %s", write_size, + *poffset, file->f_dentry->d_name.name)); */ + + if (file->private_data == NULL) { + return -EBADF; + } else { + open_file = (struct cifsFileInfo *) file->private_data; + } + + xid = GetXid(); + if(file->f_dentry->d_inode == NULL) { + FreeXid(xid); + return -EBADF; + } + + if (*poffset > file->f_dentry->d_inode->i_size) + long_op = 2; /* writes past end of file can take a long time */ + else + long_op = 1; + + for (total_written = 0; write_size > total_written; + total_written += bytes_written) { + rc = -EAGAIN; + while(rc == -EAGAIN) { + if(file->private_data == NULL) { + /* file has been closed on us */ + FreeXid(xid); + /* if we have gotten here we have written some data + and blocked, and the file has been freed on us + while we blocked so return what we managed to write */ + return total_written; + } + if(open_file->closePend) { + FreeXid(xid); + if(total_written) + return total_written; + else + return -EBADF; + } + if (open_file->invalidHandle) { + if((file->f_dentry == NULL) || + (file->f_dentry->d_inode == NULL)) { + FreeXid(xid); + return total_written; + } + /* we could deadlock if we called + filemap_fdatawait from here so tell + reopen_file not to flush data to server now */ + rc = cifs_reopen_file(file->f_dentry->d_inode, + file,FALSE); + if(rc != 0) + break; + } + + rc = CIFSSMBWrite(xid, pTcon, + open_file->netfid, + write_size - total_written, *poffset, + &bytes_written, + NULL, write_data + total_written, long_op); + } + if (rc || (bytes_written == 0)) { + if (total_written) + break; + else { + FreeXid(xid); + return rc; + } + } else + *poffset += bytes_written; + long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */ + } + +#ifdef CONFIG_CIFS_STATS + if(total_written > 0) { + atomic_inc(&pTcon->num_writes); + spin_lock(&pTcon->stat_lock); + pTcon->bytes_written += total_written; + spin_unlock(&pTcon->stat_lock); + } +#endif + + /* since the write may have blocked check these pointers again */ + if(file->f_dentry) { + if(file->f_dentry->d_inode) { + file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime = + CURRENT_TIME; + if (total_written > 0) { + if (*poffset > file->f_dentry->d_inode->i_size) + i_size_write(file->f_dentry->d_inode, *poffset); + } + mark_inode_dirty_sync(file->f_dentry->d_inode); + } + } + FreeXid(xid); + return total_written; +} + +static ssize_t cifs_write(struct file * file, const char *write_data, size_t write_size, loff_t * poffset) { @@ -652,10 +799,10 @@ } rc = CIFSSMBWrite(xid, pTcon, - open_file->netfid, + open_file->netfid, write_size - total_written, *poffset, &bytes_written, - write_data + total_written, long_op); + write_data + total_written, NULL, long_op); } if (rc || (bytes_written == 0)) { if (total_written) @@ -969,6 +1116,83 @@ ssize_t +cifs_user_read(struct file * file, char __user *read_data, size_t read_size, + loff_t * poffset) +{ + int rc = -EACCES; + unsigned int bytes_read = 0; + unsigned int total_read = 0; + unsigned int current_read_size; + struct cifs_sb_info *cifs_sb; + struct cifsTconInfo *pTcon; + int xid; + struct cifsFileInfo * open_file; + char * smb_read_data; + char __user * current_offset; + struct smb_com_read_rsp * pSMBr; + + xid = GetXid(); + cifs_sb = CIFS_SB(file->f_dentry->d_sb); + pTcon = cifs_sb->tcon; + + if (file->private_data == NULL) { + FreeXid(xid); + return -EBADF; + } + open_file = (struct cifsFileInfo *)file->private_data; + + if((file->f_flags & O_ACCMODE) == O_WRONLY) { + cFYI(1,("attempting read on write only file instance")); + } + + for (total_read = 0,current_offset=read_data; read_size > total_read; + total_read += bytes_read,current_offset+=bytes_read) { + current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize); + rc = -EAGAIN; + smb_read_data = NULL; + while(rc == -EAGAIN) { + if ((open_file->invalidHandle) && (!open_file->closePend)) { + rc = cifs_reopen_file(file->f_dentry->d_inode, + file,TRUE); + if(rc != 0) + break; + } + + rc = CIFSSMBRead(xid, pTcon, + open_file->netfid, + current_read_size, *poffset, + &bytes_read, &smb_read_data); + + pSMBr = (struct smb_com_read_rsp *)smb_read_data; + copy_to_user(current_offset,smb_read_data + 4/* RFC1001 hdr*/ + + le16_to_cpu(pSMBr->DataOffset), bytes_read); + if(smb_read_data) { + cifs_buf_release(smb_read_data); + smb_read_data = NULL; + } + } + if (rc || (bytes_read == 0)) { + if (total_read) { + break; + } else { + FreeXid(xid); + return rc; + } + } else { +#ifdef CONFIG_CIFS_STATS + atomic_inc(&pTcon->num_reads); + spin_lock(&pTcon->stat_lock); + pTcon->bytes_read += total_read; + spin_unlock(&pTcon->stat_lock); +#endif + *poffset += bytes_read; + } + } + FreeXid(xid); + return total_read; +} + +static ssize_t cifs_read(struct file * file, char *read_data, size_t read_size, loff_t * poffset) { @@ -1039,6 +1263,17 @@ struct dentry * dentry = file->f_dentry; int rc, xid; +#ifdef CIFS_EXPERIMENTAL /* BB fixme reenable when cifs_read_wrapper fixed */ + if(dentry->d_sb) { + struct cifs_sb_info *cifs_sb; + cifs_sb = CIFS_SB(sb); + if(cifs_sb != NULL) { + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) + return -ENODEV + } + } +#endif /* CIFS_EXPERIMENTAL */ + xid = GetXid(); rc = cifs_revalidate(dentry); if (rc) { @@ -1199,8 +1434,6 @@ spin_unlock(&pTcon->stat_lock); #endif if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { - cFYI(1,("Partial page %d of %d read to cache",i++,num_pages)); - i++; /* account for partial page */ /* server copy of file can have smaller size than client */ @@ -1376,23 +1609,22 @@ cFYI(0, ("CIFS FFIRST: Attributes came in as 0x%x", attr)); - if (attr & ATTR_REPARSE) { - *pobject_type = DT_LNK; - /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */ - tmp_inode->i_mode |= S_IFLNK; - } else if (attr & ATTR_DIRECTORY) { + if (attr & ATTR_DIRECTORY) { *pobject_type = DT_DIR; /* override default perms since we do not lock dirs */ if(atomic_read(&cifsInfo->inUse) == 0) { tmp_inode->i_mode = cifs_sb->mnt_dir_mode; } tmp_inode->i_mode |= S_IFDIR; +/* we no longer mark these because we could not follow them */ +/* } else if (attr & ATTR_REPARSE) { + *pobject_type = DT_LNK; + tmp_inode->i_mode |= S_IFLNK;*/ } else { *pobject_type = DT_REG; tmp_inode->i_mode |= S_IFREG; if(attr & ATTR_READONLY) tmp_inode->i_mode &= ~(S_IWUGO); - }/* could add code here - to validate if device or weird share type? */ /* can not fill in nlink here as in qpathinfo version and Unx search */ @@ -1516,13 +1748,16 @@ } } -static void +/* Returns one if new inode created (which therefore needs to be hashed) */ +/* Might check in the future if inode number changed so we can rehash inode */ +int construct_dentry(struct qstr *qstring, struct file *file, struct inode **ptmp_inode, struct dentry **pnew_dentry) { struct dentry *tmp_dentry; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; + int rc = 0; cFYI(1, ("For %s ", qstring->name)); cifs_sb = CIFS_SB(file->f_dentry->d_sb); @@ -1537,29 +1772,30 @@ if(*ptmp_inode == NULL) { *ptmp_inode = new_inode(file->f_dentry->d_sb); if(*ptmp_inode == NULL) - return; + return rc; + rc = 1; d_instantiate(tmp_dentry, *ptmp_inode); - insert_inode_hash(*ptmp_inode); } } else { tmp_dentry = d_alloc(file->f_dentry, qstring); if(tmp_dentry == NULL) { cERROR(1,("Failed allocating dentry")); *ptmp_inode = NULL; - return; + return rc; } *ptmp_inode = new_inode(file->f_dentry->d_sb); tmp_dentry->d_op = &cifs_dentry_ops; if(*ptmp_inode == NULL) - return; + return rc; + rc = 1; d_instantiate(tmp_dentry, *ptmp_inode); d_rehash(tmp_dentry); - insert_inode_hash(*ptmp_inode); } tmp_dentry->d_time = jiffies; *pnew_dentry = tmp_dentry; + return rc; } static void reset_resume_key(struct file * dir_file, @@ -1609,11 +1845,19 @@ pqstring->name = pfindData->FileName; /* pqstring->len is already set by caller */ - construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); + rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); if((tmp_inode == NULL) || (tmp_dentry == NULL)) { return -ENOMEM; } fill_in_inode(tmp_inode, pfindData, &object_type); + if(rc) { + /* We have no reliable way to get inode numbers + from servers w/o Unix extensions yet so we can not set + i_ino from pfindData yet */ + + /* new inode created, let us hash it */ + insert_inode_hash(tmp_inode); + } /* else if inode number changed do we rehash it? */ rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos, tmp_inode->i_ino, object_type); if(rc) { @@ -1637,11 +1881,19 @@ pqstring->name = pUnixFindData->FileName; pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF); - construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); + rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); if((tmp_inode == NULL) || (tmp_dentry == NULL)) { return -ENOMEM; - } + } + if(rc) { + struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { + tmp_inode->i_ino = + (unsigned long)pUnixFindData->UniqueId; + } + insert_inode_hash(tmp_inode); + } /* else if i_ino has changed should we rehash it? */ unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type); rc = filldir(direntry, pUnixFindData->FileName, pqstring->len, file->f_pos, tmp_inode->i_ino, object_type); @@ -1675,25 +1927,34 @@ FILE_DIRECTORY_INFO *lastFindData; FILE_UNIX_INFO *pfindDataUnix; + + /* BB removeme begin */ + if(!experimEnabled) + return cifs_readdir2(file,direntry,filldir); + /* BB removeme end */ + + xid = GetXid(); + if(file->f_dentry == NULL) { + rc = -EIO; + FreeXid(xid); + return rc; + } cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; - if(bufsize > CIFS_MAX_MSGSIZE) { + if(bufsize > CIFSMaxBufSize) { + rc = -EIO; FreeXid(xid); - return -EIO; + return rc; } data = kmalloc(bufsize, GFP_KERNEL); pfindData = (FILE_DIRECTORY_INFO *) data; if(data == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; - } - if(file->f_dentry == NULL) { - kfree(data); - FreeXid(xid); - return -EIO; + return rc; } down(&file->f_dentry->d_sb->s_vfs_rename_sem); full_path = build_wildcard_path_from_dentry(file->f_dentry); @@ -1727,8 +1988,8 @@ if (file->private_data != NULL) { cifsFile = (struct cifsFileInfo *) file->private_data; - if (cifsFile->endOfSearch) { - if(cifsFile->emptyDir) { + if (cifsFile->srch_inf.endOfSearch) { + if(cifsFile->srch_inf.emptyDir) { cFYI(1, ("End of search, empty dir")); rc = 0; break; @@ -1778,7 +2039,7 @@ break; } /* Offset of resume key same for levels 257 and 514 */ - cifsFile->resume_key = lastFindData->FileIndex; + cifsFile->srch_inf.resume_key = lastFindData->FileIndex; if(UnixSearch == FALSE) { cifsFile->resume_name_length = le32_to_cpu(lastFindData->FileNameLength); @@ -1915,13 +2176,13 @@ /* if(pfindData > lastFindData) rc = -EIO; break; */ } /* end for loop */ if ((findParms.EndofSearch != 0) && cifsFile) { - cifsFile->endOfSearch = TRUE; + cifsFile->srch_inf.endOfSearch = TRUE; if(findParms.SearchCount == cpu_to_le16(2)) - cifsFile->emptyDir = TRUE; + cifsFile->srch_inf.emptyDir = TRUE; } } else { if (cifsFile) - cifsFile->endOfSearch = TRUE; + cifsFile->srch_inf.endOfSearch = TRUE; /* unless parent directory gone do not return error */ rc = 0; } @@ -1934,7 +2195,7 @@ file->f_pos)); } else { cifsFile = (struct cifsFileInfo *) file->private_data; - if (cifsFile->endOfSearch) { + if (cifsFile->srch_inf.endOfSearch) { rc = 0; cFYI(1, ("End of search ")); break; @@ -1944,7 +2205,7 @@ &findNextParms, searchHandle, cifsFile->search_resume_name, cifsFile->resume_name_length, - cifsFile->resume_key, + cifsFile->srch_inf.resume_key, &Unicode, &UnixSearch); cFYI(1,("Count: %d End: %d ", le16_to_cpu(findNextParms.SearchCount), @@ -1961,7 +2222,7 @@ break; } /* Offset of resume key same for levels 257 and 514 */ - cifsFile->resume_key = lastFindData->FileIndex; + cifsFile->srch_inf.resume_key = lastFindData->FileIndex; if(UnixSearch == FALSE) { cifsFile->resume_name_length = @@ -2114,10 +2375,10 @@ /* BB also should check to ensure pointer not beyond end of SMB */ } /* end for loop */ if (findNextParms.EndofSearch != 0) { - cifsFile->endOfSearch = TRUE; + cifsFile->srch_inf.endOfSearch = TRUE; } } else { - cifsFile->endOfSearch = TRUE; + cifsFile->srch_inf.endOfSearch = TRUE; rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */ } Index: wli-2.6.10-rc3-1/fs/cifs/inode.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/inode.c 2004-12-22 09:07:09.688249042 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/inode.c 2004-12-22 10:04:36.587240746 -0800 @@ -85,6 +85,13 @@ *pinode = new_inode(sb); if(*pinode == NULL) return -ENOMEM; + /* Is an i_ino of zero legal? */ + /* Are there sanity checks we can use to ensure that + the server is really filling in that field? */ + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { + (*pinode)->i_ino = + (unsigned long)findData.UniqueId; + } /* note ino incremented to unique num in new_inode */ insert_inode_hash(*pinode); } @@ -244,6 +251,21 @@ *pinode = new_inode(sb); if(*pinode == NULL) return -ENOMEM; + /* Is an i_ino of zero legal? */ + /* Are there sanity checks we can use to ensure that + the server is really filling in that field? */ + + /* We can not use the IndexNumber from either + Windows or Samba as it is frequently set to zero */ + /* There may be higher info levels that work but + Are there Windows server or network appliances + for which IndexNumber field is not guaranteed unique? */ + + /* if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { + (*pinode)->i_ino = + (unsigned long)pfindData->IndexNumber; + } */ /*NB: ino incremented to unique num in new_inode*/ + insert_inode_hash(*pinode); } inode = *pinode; @@ -273,10 +295,10 @@ /* new inode, can safely set these fields */ inode->i_mode = cifs_sb->mnt_file_mode; - if (attr & ATTR_REPARSE) { - /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */ - inode->i_mode |= S_IFLNK; - } else if (attr & ATTR_DIRECTORY) { +/* if (attr & ATTR_REPARSE) */ +/* We no longer handle these as symlinks because we could not */ +/* follow them due to the absolute path with drive letter */ + if (attr & ATTR_DIRECTORY) { /* override default perms since we do not do byte range locking on dirs */ inode->i_mode = cifs_sb->mnt_dir_mode; inode->i_mode |= S_IFDIR; @@ -958,6 +980,16 @@ via Handle (SetFileInfo) instead of by path */ rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf, cifs_sb->local_nls); + if(rc == -EOPNOTSUPP) { + cFYI(1,("OS2 level of SetPathInfo not implemented")); + /* Need to convert time_buf into old format, + but probably better to do that inside the function + below rather than here */ + /* Better to return EOPNOTSUPP until function + below is ready */ + /* CIFSSMBSetTimesLegacy(xid, pTcon, full_path, + FILE_INFO_STANDARD * data, cifs_sb->local_nls); */ + } } /* do not need local check to inode_check_ok since the server does that */ Index: wli-2.6.10-rc3-1/fs/cifs/misc.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/misc.c 2004-12-22 09:07:09.689248890 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/misc.c 2004-12-22 10:04:36.592239986 -0800 @@ -1,7 +1,7 @@ /* * fs/cifs/misc.c * - * Copyright (C) International Business Machines Corp., 2002,2003 + * Copyright (C) International Business Machines Corp., 2002,2004 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -29,6 +29,7 @@ #include "smberr.h" #include "nterr.h" +extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; extern struct task_struct * oplockThread; @@ -160,8 +161,9 @@ (struct smb_hdr *) mempool_alloc(cifs_req_poolp, SLAB_KERNEL | SLAB_NOFS); /* clear the first few header bytes */ + /* for most paths, more is cleared in header_assemble */ if (ret_buf) { - memset(ret_buf, 0, sizeof (struct smb_hdr)); + memset(ret_buf, 0, sizeof(struct smb_hdr) + 3); atomic_inc(&bufAllocCount); } @@ -173,7 +175,7 @@ { if (buf_to_free == NULL) { - cFYI(1, ("Null buffer passed to cifs_buf_release")); + /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/ return; } mempool_free(buf_to_free,cifs_req_poolp); @@ -182,20 +184,49 @@ return; } +struct smb_hdr * +cifs_small_buf_get(void) +{ + struct smb_hdr *ret_buf = NULL; + +/* We could use negotiated size instead of max_msgsize - + but it may be more efficient to always alloc same size + albeit slightly larger than necessary and maxbuffersize + defaults to this and can not be bigger */ + ret_buf = + (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, SLAB_KERNEL | SLAB_NOFS); + if (ret_buf) { + /* No need to clear memory here, cleared in header assemble */ + /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ + atomic_inc(&smBufAllocCount); + } + return ret_buf; +} + +void +cifs_small_buf_release(void *buf_to_free) +{ + + if (buf_to_free == NULL) { + cFYI(1, ("Null buffer passed to cifs_small_buf_release")); + return; + } + mempool_free(buf_to_free,cifs_sm_req_poolp); + + atomic_dec(&smBufAllocCount); + return; +} + void header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , const struct cifsTconInfo *treeCon, int word_count - /* length of fixed section (word count) in two byte units */ - ) + /* length of fixed section (word count) in two byte units */) { - int i; struct list_head* temp_item; struct cifsSesInfo * ses; char *temp = (char *) buffer; - for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) { - temp[i] = 0; /* BB is this needed ?? */ - } + memset(temp,0,MAX_CIFS_HDR_SIZE); buffer->smb_buf_length = (2 * word_count) + sizeof (struct smb_hdr) - @@ -320,7 +351,7 @@ ("Entering checkSMB with Length: %x, smb_buf_length: %x ", length, len)); if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || - (len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) { + (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { cERROR(1, ("Length less than 2 + sizeof smb_hdr ")); if (((unsigned int)length >= sizeof (struct smb_hdr) - 1) @@ -328,9 +359,9 @@ return 0; /* some error cases do not return wct and bcc */ } - if (len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) + if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) cERROR(1, - ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... ")); + ("smb_buf_length greater than MaxBufSize")); cERROR(1, ("bad smb detected. Illegal length. The mid=%d", smb->Mid)); @@ -359,8 +390,29 @@ struct cifsTconInfo *tcon; struct cifsFileInfo *netfile; - /* could add check for smb response flag 0x80 */ - cFYI(1,("Checking for oplock break")); + cFYI(1,("Checking for oplock break or dnotify response")); + if((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && + (pSMB->hdr.Flags & SMBFLG_RESPONSE)) { + struct smb_com_transaction_change_notify_rsp * pSMBr = + (struct smb_com_transaction_change_notify_rsp *)buf; + struct file_notify_information * pnotify; + __u32 data_offset = 0; + if(pSMBr->ByteCount > sizeof(struct file_notify_information)) { + data_offset = le32_to_cpu(pSMBr->DataOffset); + + pnotify = (struct file_notify_information *)((char *)&pSMBr->hdr.Protocol + + data_offset); + cFYI(1,("dnotify on %s with action: 0x%x",pnotify->FileName, + pnotify->Action)); /* BB removeme BB */ + /* cifs_dump_mem("Received notify Data is: ",buf,sizeof(struct smb_hdr)+60); */ + return TRUE; + } + if(pSMBr->hdr.Status.CifsError) { + cFYI(1,("notify err 0x%d",pSMBr->hdr.Status.CifsError)); + return TRUE; + } + return FALSE; + } if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) return FALSE; if(pSMB->hdr.Flags & SMBFLG_RESPONSE) { Index: wli-2.6.10-rc3-1/fs/cifs/netmisc.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/netmisc.c 2004-12-22 09:07:09.689248890 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/netmisc.c 2004-12-22 10:04:36.597239226 -0800 @@ -69,10 +69,12 @@ {ERRinvparm, -EINVAL}, {ERRdiskfull, -ENOSPC}, {ERRinvname, -ENOENT}, + {ERRinvlevel,-EOPNOTSUPP}, {ERRdirnotempty, -ENOTEMPTY}, {ERRnotlocked, -ENOLCK}, {ERRalreadyexists, -EEXIST}, {ERRmoredata, -EOVERFLOW}, + {ERReasnotsupported,-EOPNOTSUPP}, {ErrQuota, -EDQUOT}, {ErrNotALink, -ENOLINK}, {ERRnetlogonNotStarted,-ENOPROTOOPT}, @@ -287,7 +289,7 @@ ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, { ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, { ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, { - ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED}, { + ERRDOS, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED}, { ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, { ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, { ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, { @@ -752,7 +754,8 @@ ERRDOS, ERRnoaccess, 0xc000028e}, { ERRDOS, ERRnoaccess, 0xc000028f}, { ERRDOS, ERRnoaccess, 0xc0000290}, { -ERRDOS, ERRbadfunc, 0xc000029c},}; + ERRDOS, ERRbadfunc, 0xc000029c}, { + ERRDOS, ERRinvlevel, 0x007c0001}, }; /***************************************************************************** Print an error message from the status code Index: wli-2.6.10-rc3-1/fs/cifs/smberr.h =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/smberr.h 2004-12-22 09:07:09.690248738 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/smberr.h 2004-12-22 10:04:36.599238922 -0800 @@ -69,6 +69,7 @@ #define ERRpipeclosing 232 #define ERRnotconnected 233 #define ERRmoredata 234 +#define ERReasnotsupported 282 #define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */ #define ErrNotALink 0x201 /* A link operation was performed on a pathname that was not a link. */ Index: wli-2.6.10-rc3-1/fs/cifs/transport.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/transport.c 2004-12-22 09:07:09.690248738 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/transport.c 2004-12-22 10:04:36.604238162 -0800 @@ -176,6 +176,143 @@ return rc; } +#ifdef CIFS_EXPERIMENTAL +/* BB finish off this function, adding support for writing set of pages as iovec */ +/* and also adding support for operations that need to parse the response smb */ +int +CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, + struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op) +{ + int rc = 0; + unsigned long timeout = 15 * HZ; + struct mid_q_entry *midQ = NULL; + + if (ses == NULL) { + cERROR(1,("Null smb session")); + return -EIO; + } + if(ses->server == NULL) { + cERROR(1,("Null tcp session")); + return -EIO; + } + if(pbytes_returned == NULL) + return -EIO; + else + *pbytes_returned = 0; + + + + /* Ensure that we do not send more than 50 overlapping requests + to the same server. We may make this configurable later or + use ses->maxReq */ + if(long_op == -1) { + /* oplock breaks must not be held up */ + atomic_inc(&ses->server->inFlight); + } else { + spin_lock(&GlobalMid_Lock); + while(1) { + if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){ + spin_unlock(&GlobalMid_Lock); + wait_event(ses->server->request_q, + atomic_read(&ses->server->inFlight) + < cifs_max_pending); + spin_lock(&GlobalMid_Lock); + } else { + if(ses->server->tcpStatus == CifsExiting) { + spin_unlock(&GlobalMid_Lock); + return -ENOENT; + } + + /* can not count locking commands against total since + they are allowed to block on server */ + + if(long_op < 3) { + /* update # of requests on the wire to server */ + atomic_inc(&ses->server->inFlight); + } + spin_unlock(&GlobalMid_Lock); + break; + } + } + } + /* make sure that we sign in the same order that we send on this socket + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ + + down(&ses->server->tcpSem); + + if (ses->server->tcpStatus == CifsExiting) { + rc = -ENOENT; + goto cifs_out_label; + } else if (ses->server->tcpStatus == CifsNeedReconnect) { + cFYI(1,("tcp session dead - return to caller to retry")); + rc = -EAGAIN; + goto cifs_out_label; + } else if (ses->status != CifsGood) { + /* check if SMB session is bad because we are setting it up */ + if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && + (in_buf->Command != SMB_COM_NEGOTIATE)) { + rc = -EAGAIN; + goto cifs_out_label; + } /* else ok - we are setting up session */ + } + midQ = AllocMidQEntry(in_buf, ses); + if (midQ == NULL) { + up(&ses->server->tcpSem); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return -ENOMEM; + } + + if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { + up(&ses->server->tcpSem); + cERROR(1, + ("Illegal length, greater than maximum frame, %d ", + in_buf->smb_buf_length)); + DeleteMidQEntry(midQ); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return -EIO; + } + + /* BB can we sign efficiently in this path? */ + rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); + + midQ->midState = MID_REQUEST_SUBMITTED; +/* rc = smb_send2(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec, + (struct sockaddr *) &(ses->server->addr.sockAddr));*/ + if(rc < 0) { + DeleteMidQEntry(midQ); + up(&ses->server->tcpSem); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return rc; + } else + up(&ses->server->tcpSem); +cifs_out_label: + if(midQ) + DeleteMidQEntry(midQ); + + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + + return rc; +} + + +#endif /* CIFS_EXPERIMENTAL */ + int SendReceive(const unsigned int xid, struct cifsSesInfo *ses, struct smb_hdr *in_buf, struct smb_hdr *out_buf, @@ -204,11 +341,11 @@ } else { spin_lock(&GlobalMid_Lock); while(1) { - if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){ + if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){ spin_unlock(&GlobalMid_Lock); wait_event(ses->server->request_q, atomic_read(&ses->server->inFlight) - < CIFS_MAX_REQ); + < cifs_max_pending); spin_lock(&GlobalMid_Lock); } else { if(ses->server->tcpStatus == CifsExiting) { @@ -260,7 +397,7 @@ return -ENOMEM; } - if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) { + if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { up(&ses->server->tcpSem); cERROR(1, ("Illegal length, greater than maximum frame, %d ", @@ -307,20 +444,19 @@ /* if signal pending do not hold up user for full smb timeout but we still give response a change to complete */ timeout = 2 * HZ; - } /* No user interrupts in wait - wreaks havoc with performance */ if(timeout != MAX_SCHEDULE_TIMEOUT) { timeout += jiffies; wait_event(ses->server->response_q, - (midQ->midState & MID_RESPONSE_RECEIVED) || + (!(midQ->midState & MID_REQUEST_SUBMITTED)) || time_after(jiffies, timeout) || ((ses->server->tcpStatus != CifsGood) && (ses->server->tcpStatus != CifsNew))); } else { wait_event(ses->server->response_q, - (midQ->midState & MID_RESPONSE_RECEIVED) || + (!(midQ->midState & MID_REQUEST_SUBMITTED)) || ((ses->server->tcpStatus != CifsGood) && (ses->server->tcpStatus != CifsNew))); } @@ -358,7 +494,7 @@ return rc; } - if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) { + if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { cERROR(1, ("Frame too large received. Length: %d Xid: %d", receive_len, xid)); Index: wli-2.6.10-rc3-1/fs/cifs/xattr.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/cifs/xattr.c 2004-12-22 09:07:09.691248586 -0800 +++ wli-2.6.10-rc3-1/fs/cifs/xattr.c 2004-12-22 10:04:36.609237402 -0800 @@ -20,6 +20,7 @@ */ #include +#include #include "cifsfs.h" #include "cifspdu.h" #include "cifsglob.h" @@ -27,11 +28,16 @@ #include "cifs_debug.h" #define MAX_EA_VALUE_SIZE 65535 -#define CIFS_XATTR_DOS_ATTRIB "user.DOSATTRIB" +#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" #define CIFS_XATTR_USER_PREFIX "user." #define CIFS_XATTR_SYSTEM_PREFIX "system." -#define CIFS_XATTR_OS2_PREFIX "OS2." /* BB should check for this someday */ -/* also note could add check for security prefix XATTR_SECURITY_PREFIX */ +#define CIFS_XATTR_OS2_PREFIX "os2." +#define CIFS_XATTR_SECURITY_PREFIX ".security" +#define CIFS_XATTR_TRUSTED_PREFIX "trusted." +#define XATTR_TRUSTED_PREFIX_LEN 8 +#define XATTR_SECURITY_PREFIX_LEN 9 +/* BB need to add server (Samba e.g) support for security and trusted prefix */ + int cifs_removexattr(struct dentry * direntry, const char * ea_name) @@ -128,16 +134,47 @@ if(ea_name == NULL) { cFYI(1,("Null xattr names not supported")); - } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) { - cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name)); + } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) { + if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) { + cFYI(1,("attempt to set cifs inode metadata")); + } + ea_name += 5; /* skip past user. prefix */ + rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, + (__u16)value_size, cifs_sb->local_nls); + } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { + ea_name += 4; /* skip past os2. prefix */ + rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, + (__u16)value_size, cifs_sb->local_nls); + } else { + int temp; + temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, + strlen(POSIX_ACL_XATTR_ACCESS)); + if (temp == 0) { +#ifdef CONFIG_CIFS_POSIX + rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value, + (const int)value_size, ACL_TYPE_ACCESS, + cifs_sb->local_nls); + cFYI(1,("set POSIX ACL rc %d",rc)); +#else + cFYI(1,("set POSIX ACL not supported")); +#endif + } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { +#ifdef CONFIG_CIFS_POSIX + rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value, + (const int)value_size, ACL_TYPE_DEFAULT, + cifs_sb->local_nls); + cFYI(1,("set POSIX default ACL rc %d",rc)); +#else + cFYI(1,("set default POSIX ACL not supported")); +#endif + } else { + cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name)); /* BB what if no namespace prefix? */ /* Should we just pass them to server, except for system and perhaps security prefixes? */ - } else { - ea_name+=5; /* skip past user. prefix */ - rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, - (__u16)value_size, cifs_sb->local_nls); + } } + if (full_path) kfree(full_path); FreeXid(xid); @@ -163,6 +200,7 @@ sb = direntry->d_inode->i_sb; if(sb == NULL) return -EIO; + xid = GetXid(); cifs_sb = CIFS_SB(sb); @@ -177,19 +215,54 @@ } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ - if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) { - cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name)); - /* BB what if no namespace prefix? */ - /* Should we just pass them to server, except for system? */ + if(ea_name == NULL) { + cFYI(1,("Null xattr names not supported")); + } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) { + if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) { + cFYI(1,("attempt to query cifs inode metadata")); + /* revalidate/getattr then populate from inode */ + } /* BB add else when above is implemented */ + ea_name += 5; /* skip past user. prefix */ + rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, + buf_size, cifs_sb->local_nls); + } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { + ea_name += 4; /* skip past os2. prefix */ + rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, + buf_size, cifs_sb->local_nls); + } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { +#ifdef CONFIG_CIFS_POSIX + rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, + ea_value, buf_size, ACL_TYPE_ACCESS, + cifs_sb->local_nls); +#else + cFYI(1,("query POSIX ACL not supported yet")); +#endif /* CONFIG_CIFS_POSIX */ + } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { +#ifdef CONFIG_CIFS_POSIX + rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, + ea_value, buf_size, ACL_TYPE_DEFAULT, + cifs_sb->local_nls); +#else + cFYI(1,("query POSIX default ACL not supported yet")); +#endif + } else if(strncmp(ea_name, + CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) { + cFYI(1,("Trusted xattr namespace not supported yet")); + } else if(strncmp(ea_name, + CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) { + cFYI(1,("Security xattr namespace not supported yet")); } else { - /* We could add a check here + cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name)); + } + + /* We could add an additional check for streams ie if proc/fs/cifs/streamstoxattr is set then search server for EAs or streams to returns as xattrs */ - ea_name+=5; /* skip past user. */ - rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, - buf_size, cifs_sb->local_nls); - } + + if(rc == -EINVAL) + rc = -EOPNOTSUPP; + if (full_path) kfree(full_path); FreeXid(xid); Index: wli-2.6.10-rc3-1/fs/compat.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/compat.c 2004-12-16 06:19:53.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/compat.c 2004-12-22 10:04:36.436263698 -0800 @@ -1387,25 +1387,25 @@ int retval; int i; - file = open_exec(filename); - - retval = PTR_ERR(file); - if (IS_ERR(file)) - return retval; - - sched_exec(); - retval = -ENOMEM; bprm = kmalloc(sizeof(*bprm), GFP_KERNEL); if (!bprm) goto out_ret; memset(bprm, 0, sizeof(*bprm)); + file = open_exec(filename); + retval = PTR_ERR(file); + if (IS_ERR(file)) + goto out_kfree; + + sched_exec(); + bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); bprm->file = file; bprm->filename = filename; bprm->interp = filename; bprm->mm = mm_alloc(); + retval = -ENOMEM; if (!bprm->mm) goto out_file; @@ -1472,6 +1472,8 @@ allow_write_access(bprm->file); fput(bprm->file); } + +out_kfree: kfree(bprm); out_ret: Index: wli-2.6.10-rc3-1/fs/direct-io.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/direct-io.c 2004-12-16 06:19:54.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/direct-io.c 2004-12-22 10:04:36.441262938 -0800 @@ -1161,6 +1161,9 @@ struct dio *dio; int reader_with_isem = (rw == READ && dio_lock_type == DIO_OWN_LOCKING); + if (rw & WRITE) + current->flags |= PF_SYNCWRITE; + if (bdev) bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev)); @@ -1244,6 +1247,8 @@ out: if (reader_with_isem) up(&inode->i_sem); + if (rw & WRITE) + current->flags &= ~PF_SYNCWRITE; return retval; } EXPORT_SYMBOL(__blockdev_direct_IO); Index: wli-2.6.10-rc3-1/fs/exec.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/exec.c 2004-12-16 06:19:54.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/exec.c 2004-12-22 10:04:36.446262178 -0800 @@ -1094,26 +1094,26 @@ int retval; int i; - file = open_exec(filename); - - retval = PTR_ERR(file); - if (IS_ERR(file)) - return retval; - - sched_exec(); - retval = -ENOMEM; bprm = kmalloc(sizeof(*bprm), GFP_KERNEL); if (!bprm) goto out_ret; memset(bprm, 0, sizeof(*bprm)); + file = open_exec(filename); + retval = PTR_ERR(file); + if (IS_ERR(file)) + goto out_kfree; + + sched_exec(); + bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); bprm->file = file; bprm->filename = filename; bprm->interp = filename; bprm->mm = mm_alloc(); + retval = -ENOMEM; if (!bprm->mm) goto out_file; @@ -1180,6 +1180,8 @@ allow_write_access(bprm->file); fput(bprm->file); } + +out_kfree: kfree(bprm); out_ret: Index: wli-2.6.10-rc3-1/fs/ext2/super.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/ext2/super.c 2004-12-16 06:19:54.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/ext2/super.c 2004-12-22 10:04:36.614236642 -0800 @@ -122,6 +122,9 @@ brelse (sbi->s_group_desc[i]); kfree(sbi->s_group_desc); kfree(sbi->s_debts); + percpu_counter_destroy(&sbi->s_freeblocks_counter); + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); brelse (sbi->s_sbh); sb->s_fs_info = NULL; kfree(sbi); Index: wli-2.6.10-rc3-1/fs/ext3/dir.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/ext3/dir.c 2004-12-16 06:19:54.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/ext3/dir.c 2004-12-22 10:04:36.617236186 -0800 @@ -418,7 +418,7 @@ get_dtype(sb, fname->file_type)); if (error) { filp->f_pos = curr_pos; - info->extra_fname = fname; + info->extra_fname = fname->next; return error; } fname = fname->next; @@ -457,12 +457,9 @@ * If there are any leftover names on the hash collision * chain, return them first. */ - if (info->extra_fname) { - if(call_filldir(filp, dirent, filldir, info->extra_fname)) - goto finished; - else - goto next_entry; - } + if (info->extra_fname && + call_filldir(filp, dirent, filldir, info->extra_fname)) + goto finished; if (!info->curr_node) info->curr_node = rb_first(&info->root); @@ -495,7 +492,7 @@ info->curr_minor_hash = fname->minor_hash; if (call_filldir(filp, dirent, filldir, fname)) break; -next_entry: + info->curr_node = rb_next(info->curr_node); if (!info->curr_node) { if (info->next_hash == ~0) { Index: wli-2.6.10-rc3-1/fs/ext3/namei.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/ext3/namei.c 2004-12-16 06:19:54.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/ext3/namei.c 2004-12-22 10:04:36.625234970 -0800 @@ -872,7 +872,7 @@ if (!buffer_uptodate(bh)) { /* read error, skip block & hope for the best */ ext3_error(sb, __FUNCTION__, "reading directory #%lu " - "offset %lu\n", dir->i_ino, block); + "offset %lu", dir->i_ino, block); brelse(bh); goto next; } Index: wli-2.6.10-rc3-1/fs/ext3/super.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/ext3/super.c 2004-12-16 06:19:54.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/ext3/super.c 2004-12-22 10:04:36.633233754 -0800 @@ -400,6 +400,9 @@ for (i = 0; i < sbi->s_gdb_count; i++) brelse(sbi->s_group_desc[i]); kfree(sbi->s_group_desc); + percpu_counter_destroy(&sbi->s_freeblocks_counter); + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); brelse(sbi->s_sbh); #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) { Index: wli-2.6.10-rc3-1/fs/partitions/check.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/partitions/check.c 2004-12-16 06:19:55.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/partitions/check.c 2004-12-22 10:04:36.635233450 -0800 @@ -378,7 +378,7 @@ if (disk->fops->revalidate_disk) disk->fops->revalidate_disk(disk); if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) - return -EIO; + return 0; for (p = 1; p < state->limit; p++) { sector_t size = state->parts[p].size; sector_t from = state->parts[p].from; Index: wli-2.6.10-rc3-1/fs/proc/array.c =================================================================== --- wli-2.6.10-rc3-1.orig/fs/proc/array.c 2004-12-16 06:19:55.000000000 -0800 +++ wli-2.6.10-rc3-1/fs/proc/array.c 2004-12-22 10:04:36.638232994 -0800 @@ -370,7 +370,7 @@ stime += task->signal->stime; } } - ppid = task->pid ? task->group_leader->real_parent->tgid : 0; + ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0; read_unlock(&tasklist_lock); if (!whole || num_threads<2) Index: wli-2.6.10-rc3-1/include/asm-arm/arch-ixp4xx/io.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-arm/arch-ixp4xx/io.h 2004-12-16 06:19:56.000000000 -0800 +++ wli-2.6.10-rc3-1/include/asm-arm/arch-ixp4xx/io.h 2004-12-22 10:04:36.649231322 -0800 @@ -292,7 +292,7 @@ } static inline void -__ixp4xx_outsb(u32 io_addr, u8 *vaddr, u32 count) +__ixp4xx_outsb(u32 io_addr, const u8 *vaddr, u32 count) { while (count--) outb(*vaddr++, io_addr); @@ -309,7 +309,7 @@ } static inline void -__ixp4xx_outsw(u32 io_addr, u16 *vaddr, u32 count) +__ixp4xx_outsw(u32 io_addr, const u16 *vaddr, u32 count) { while (count--) outw(cpu_to_le16(*vaddr++), io_addr); @@ -322,7 +322,7 @@ } static inline void -__ixp4xx_outsl(u32 io_addr, u32 *vaddr, u32 count) +__ixp4xx_outsl(u32 io_addr, const u32 *vaddr, u32 count) { while (count--) outl(*vaddr++, io_addr); Index: wli-2.6.10-rc3-1/include/asm-arm/arch-pxa/pxa-regs.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-arm/arch-pxa/pxa-regs.h 2004-12-16 06:19:56.000000000 -0800 +++ wli-2.6.10-rc3-1/include/asm-arm/arch-pxa/pxa-regs.h 2004-12-22 10:04:36.659229802 -0800 @@ -1494,7 +1494,7 @@ #define PVCR_CommandDelay (0xf80) #define PCFR_PI2C_EN (0x1 << 6) -#define PSSR_OTGPH (1 << 7) /* OTG Peripheral control Hold */ +#define PSSR_OTGPH (1 << 6) /* OTG Peripheral control Hold */ #define PSSR_RDH (1 << 5) /* Read Disable Hold */ #define PSSR_PH (1 << 4) /* Peripheral Control Hold */ #define PSSR_VFS (1 << 2) /* VDD Fault Status */ Index: wli-2.6.10-rc3-1/include/asm-arm/arch-sa1100/ide.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-arm/arch-sa1100/ide.h 2004-12-16 06:19:56.000000000 -0800 +++ wli-2.6.10-rc3-1/include/asm-arm/arch-sa1100/ide.h 2004-12-22 10:04:36.661229498 -0800 @@ -14,6 +14,8 @@ #include #include +#error "This code is broken and needs update to match with current ide support" + /* * Set up a hw structure for a specified data port, control port and IRQ. Index: wli-2.6.10-rc3-1/include/asm-arm/arch-versatile/platform.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-arm/arch-versatile/platform.h 2004-12-16 06:19:57.000000000 -0800 +++ wli-2.6.10-rc3-1/include/asm-arm/arch-versatile/platform.h 2004-12-22 10:04:36.665228890 -0800 @@ -61,7 +61,7 @@ #define VERSATILE_SYS_OSC2_OFFSET 0x14 #define VERSATILE_SYS_OSC3_OFFSET 0x18 #define VERSATILE_SYS_OSC4_OFFSET 0x1C -#elif defined(CONFIG_ARCH_VERSATILE_AB) +#elif defined(CONFIG_MACH_VERSATILE_AB) #define VERSATILE_SYS_OSC1_OFFSET 0x1C #endif @@ -494,7 +494,7 @@ #define VERSATILE_CSR_BASE 0x10000000 #define VERSATILE_CSR_SIZE 0x10000000 -#ifdef CONFIG_ARCH_VERSATILE_AB +#ifdef CONFIG_MACH_VERSATILE_AB /* * IB2 Versatile/AB expansion board definitions */ Index: wli-2.6.10-rc3-1/include/asm-arm/ide.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-arm/ide.h 2004-12-22 09:07:09.838226242 -0800 +++ wli-2.6.10-rc3-1/include/asm-arm/ide.h 2004-12-22 10:04:36.640232690 -0800 @@ -17,10 +17,6 @@ #define MAX_HWIFS 4 #endif -#if defined(CONFIG_ARCH_SA1100) -# include /* obsolete + broken */ -#endif - #if !defined(CONFIG_ARCH_L7200) # define IDE_ARCH_OBSOLETE_INIT # ifdef CONFIG_ARCH_CLPS7500 Index: wli-2.6.10-rc3-1/include/asm-arm/mach/map.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-arm/mach/map.h 2004-12-16 06:19:57.000000000 -0800 +++ wli-2.6.10-rc3-1/include/asm-arm/mach/map.h 2004-12-22 10:04:36.667228586 -0800 @@ -21,9 +21,10 @@ #define MT_DEVICE 0 #define MT_CACHECLEAN 1 #define MT_MINICLEAN 2 -#define MT_VECTORS 3 -#define MT_MEMORY 4 -#define MT_ROM 5 +#define MT_LOW_VECTORS 3 +#define MT_HIGH_VECTORS 4 +#define MT_MEMORY 5 +#define MT_ROM 6 extern void create_memmap_holes(struct meminfo *); extern void memtable_init(struct meminfo *); Index: wli-2.6.10-rc3-1/include/asm-arm/system.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-arm/system.h 2004-12-16 06:19:57.000000000 -0800 +++ wli-2.6.10-rc3-1/include/asm-arm/system.h 2004-12-22 10:04:36.642232386 -0800 @@ -128,9 +128,9 @@ extern unsigned int user_debug; #if __LINUX_ARM_ARCH__ >= 4 -#define vectors_base() ((cr_alignment & CR_V) ? 0xffff0000 : 0) +#define vectors_high() (cr_alignment & CR_V) #else -#define vectors_base() (0) +#define vectors_high() (0) #endif #define mb() __asm__ __volatile__ ("" : : : "memory") Index: wli-2.6.10-rc3-1/include/asm-arm/uaccess.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-arm/uaccess.h 2004-12-22 09:07:09.846225026 -0800 +++ wli-2.6.10-rc3-1/include/asm-arm/uaccess.h 2004-12-22 10:04:36.646231778 -0800 @@ -108,35 +108,35 @@ extern int __get_user_8(void *); extern int __get_user_bad(void); -#define __get_user_x(__r1,__p,__e,__s,__i...) \ +#define __get_user_x(__r2,__p,__e,__s,__i...) \ __asm__ __volatile__ ( \ - __asmeq("%0", "r0") __asmeq("%1", "r1") \ + __asmeq("%0", "r0") __asmeq("%1", "r2") \ "bl __get_user_" #__s \ - : "=&r" (__e), "=r" (__r1) \ + : "=&r" (__e), "=r" (__r2) \ : "0" (__p) \ : __i, "cc") #define get_user(x,p) \ ({ \ const register typeof(*(p)) __user *__p asm("r0") = (p);\ - register typeof(*(p)) __r1 asm("r1"); \ + register typeof(*(p)) __r2 asm("r2"); \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __get_user_x(__r1, __p, __e, 1, "lr"); \ + __get_user_x(__r2, __p, __e, 1, "lr"); \ break; \ case 2: \ - __get_user_x(__r1, __p, __e, 2, "r2", "lr"); \ + __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \ break; \ case 4: \ - __get_user_x(__r1, __p, __e, 4, "lr"); \ + __get_user_x(__r2, __p, __e, 4, "lr"); \ break; \ case 8: \ - __get_user_x(__r1, __p, __e, 8, "lr"); \ + __get_user_x(__r2, __p, __e, 8, "lr"); \ break; \ default: __e = __get_user_bad(); break; \ } \ - x = __r1; \ + x = __r2; \ __e; \ }) @@ -227,31 +227,31 @@ extern int __put_user_8(void *, unsigned long long); extern int __put_user_bad(void); -#define __put_user_x(__r1,__p,__e,__s) \ +#define __put_user_x(__r2,__p,__e,__s) \ __asm__ __volatile__ ( \ - __asmeq("%0", "r0") __asmeq("%2", "r1") \ + __asmeq("%0", "r0") __asmeq("%2", "r2") \ "bl __put_user_" #__s \ : "=&r" (__e) \ - : "0" (__p), "r" (__r1) \ + : "0" (__p), "r" (__r2) \ : "ip", "lr", "cc") #define put_user(x,p) \ ({ \ - const register typeof(*(p)) __r1 asm("r1") = (x); \ + const register typeof(*(p)) __r2 asm("r2") = (x); \ const register typeof(*(p)) __user *__p asm("r0") = (p);\ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __put_user_x(__r1, __p, __e, 1); \ + __put_user_x(__r2, __p, __e, 1); \ break; \ case 2: \ - __put_user_x(__r1, __p, __e, 2); \ + __put_user_x(__r2, __p, __e, 2); \ break; \ case 4: \ - __put_user_x(__r1, __p, __e, 4); \ + __put_user_x(__r2, __p, __e, 4); \ break; \ case 8: \ - __put_user_x(__r1, __p, __e, 8); \ + __put_user_x(__r2, __p, __e, 8); \ break; \ default: __e = __put_user_bad(); break; \ } \ Index: wli-2.6.10-rc3-1/include/asm-i386/io.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-i386/io.h 2004-12-16 06:19:57.000000000 -0800 +++ wli-2.6.10-rc3-1/include/asm-i386/io.h 2004-12-22 10:04:36.669228282 -0800 @@ -184,7 +184,7 @@ { memset((void __force *) addr, val, count); } -static inline void memcpy_fromio(void *dst, volatile void __iomem *src, int count) +static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, int count) { __memcpy(dst, (void __force *) src, count); } Index: wli-2.6.10-rc3-1/include/asm-ia64/delay.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-ia64/delay.h 2004-12-22 09:07:09.926212866 -0800 +++ wli-2.6.10-rc3-1/include/asm-ia64/delay.h 2004-12-22 10:04:36.671227978 -0800 @@ -91,7 +91,7 @@ unsigned long cycles = usecs*local_cpu_data->cyc_per_usec; while (ia64_get_itc() - start < cycles) - /* skip */; + cpu_relax(); } #endif /* _ASM_IA64_DELAY_H */ Index: wli-2.6.10-rc3-1/include/asm-ppc64/paca.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-ppc64/paca.h 2004-12-22 09:07:10.043195082 -0800 +++ wli-2.6.10-rc3-1/include/asm-ppc64/paca.h 2004-12-22 10:04:36.674227522 -0800 @@ -99,11 +99,17 @@ u64 exdsi[8]; /* used for linear mapping hash table misses */ /* - * iSeries structues which the hypervisor knows about - Not - * sure if these particularly need to be cacheline aligned. + * iSeries structure which the hypervisor knows about - + * this structure should not cross a page boundary. + * The vpa_init/register_vpa call is now known to fail if the + * lppaca structure crosses a page boundary. * The lppaca is also used on POWER5 pSeries boxes. + * The lppaca is 640 bytes long, and cannot readily change + * since the hypervisor knows its layout, so a 1kB + * alignment will suffice to ensure that it doesn't + * cross a page boundary. */ - struct ItLpPaca lppaca __attribute__((aligned(0x80))); + struct ItLpPaca lppaca __attribute__((__aligned__(0x400))); #ifdef CONFIG_PPC_ISERIES struct ItLpRegSave reg_save; #endif Index: wli-2.6.10-rc3-1/include/asm-ppc64/plpar_wrappers.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-ppc64/plpar_wrappers.h 2004-12-22 09:07:10.046194626 -0800 +++ wli-2.6.10-rc3-1/include/asm-ppc64/plpar_wrappers.h 2004-12-22 10:04:36.675227370 -0800 @@ -22,12 +22,14 @@ return(0); } -static inline long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa) +static inline long register_vpa(unsigned long flags, unsigned long proc, + unsigned long vpa) { - plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa); - return(0); + return plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa); } +void vpa_init(int cpu); + static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex, unsigned long avpn, Index: wli-2.6.10-rc3-1/include/asm-ppc64/ptrace-common.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-ppc64/ptrace-common.h 2004-12-22 09:07:10.047194474 -0800 +++ wli-2.6.10-rc3-1/include/asm-ppc64/ptrace-common.h 2004-12-22 10:04:36.677227066 -0800 @@ -58,6 +58,7 @@ struct pt_regs *regs = task->thread.regs; if (regs != NULL) regs->msr |= MSR_SE; + set_ti_thread_flag(task->thread_info, TIF_SINGLESTEP); } static inline void clear_single_step(struct task_struct *task) @@ -65,6 +66,7 @@ struct pt_regs *regs = task->thread.regs; if (regs != NULL) regs->msr &= ~MSR_SE; + clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP); } #endif /* _PPC64_PTRACE_COMMON_H */ Index: wli-2.6.10-rc3-1/include/asm-ppc64/thread_info.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-ppc64/thread_info.h 2004-12-16 06:20:00.000000000 -0800 +++ wli-2.6.10-rc3-1/include/asm-ppc64/thread_info.h 2004-12-22 10:04:36.679226762 -0800 @@ -97,6 +97,7 @@ #define TIF_RUN_LIGHT 6 /* iSeries run light */ #define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */ #define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */ +#define TIF_SINGLESTEP 9 /* singlestepping active */ /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1< #include +#include /* M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ) * Index: wli-2.6.10-rc3-1/include/asm-sparc/pcic.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-sparc/pcic.h 2004-12-22 10:13:57.128025594 -0800 +++ wli-2.6.10-rc3-1/include/asm-sparc/pcic.h 2004-12-22 10:44:30.965239962 -0800 @@ -16,10 +16,10 @@ #include struct linux_pcic { - unsigned long pcic_regs; + void * __iomem pcic_regs; unsigned long pcic_io; - unsigned long pcic_config_space_addr; - unsigned long pcic_config_space_data; + void * __iomem pcic_config_space_addr; + void * __iomem pcic_config_space_data; struct resource pcic_res_regs; struct resource pcic_res_io; struct resource pcic_res_cfg_addr; Index: wli-2.6.10-rc3-1/include/asm-sparc/processor.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-sparc/processor.h 2004-12-22 09:07:10.083189002 -0800 +++ wli-2.6.10-rc3-1/include/asm-sparc/processor.h 2004-12-22 10:04:36.685225850 -0800 @@ -43,10 +43,12 @@ struct task_struct; +#ifdef __KERNEL__ struct fpq { unsigned long *insn_addr; unsigned long insn; }; +#endif typedef struct { int seg; Index: wli-2.6.10-rc3-1/include/asm-sparc/sbus.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-sparc/sbus.h 2004-12-22 10:14:01.804314690 -0800 +++ wli-2.6.10-rc3-1/include/asm-sparc/sbus.h 2004-12-22 10:28:47.135723858 -0800 @@ -106,6 +106,8 @@ /* These yield IOMMU mappings in consistent mode. */ extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp); extern void sbus_free_consistent(struct sbus_dev *, long, void *, u32); +void prom_adjust_ranges(struct linux_prom_ranges *, int, + struct linux_prom_ranges *, int); #define SBUS_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL #define SBUS_DMA_TODEVICE DMA_TO_DEVICE Index: wli-2.6.10-rc3-1/include/asm-sparc/sigcontext.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-sparc/sigcontext.h 2004-12-22 09:07:10.083189002 -0800 +++ wli-2.6.10-rc3-1/include/asm-sparc/sigcontext.h 2004-12-22 10:04:36.686225698 -0800 @@ -4,7 +4,6 @@ #ifdef __KERNEL__ #include -#endif #ifndef __ASSEMBLY__ @@ -59,4 +58,6 @@ #endif /* !(__ASSEMBLY__) */ +#endif /* (__KERNEL__) */ + #endif /* !(__SPARC_SIGCONTEXT_H) */ Index: wli-2.6.10-rc3-1/include/asm-sparc/signal.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-sparc/signal.h 2004-12-22 09:07:10.084188850 -0800 +++ wli-2.6.10-rc3-1/include/asm-sparc/signal.h 2004-12-22 10:04:36.689225242 -0800 @@ -3,6 +3,7 @@ #define _ASMSPARC_SIGNAL_H #include +#include #ifdef __KERNEL__ #ifndef __ASSEMBLY__ @@ -111,11 +112,14 @@ unsigned long sig[_NSIG_WORDS]; } __new_sigset_t; + +#ifdef __KERNEL__ /* A SunOS sigstack */ struct sigstack { char *the_stack; int cur_status; }; +#endif /* Sigvec flags */ #define _SV_SSTACK 1u /* This signal handler should use sig-stack */ @@ -189,6 +193,7 @@ #define SIG_IGN ((__sighandler_t)1) /* ignore signal */ #define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ +#ifdef __KERNEL__ struct __new_sigaction { __sighandler_t sa_handler; unsigned long sa_flags; @@ -196,12 +201,10 @@ __new_sigset_t sa_mask; }; -#ifdef __KERNEL__ struct k_sigaction { struct __new_sigaction sa; void __user *ka_restorer; }; -#endif struct __old_sigaction { __sighandler_t sa_handler; @@ -216,7 +219,6 @@ size_t ss_size; } stack_t; -#ifdef __KERNEL__ struct sparc_deliver_cookie { int restart_syscall; unsigned long orig_i0; Index: wli-2.6.10-rc3-1/include/asm-sparc/string.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-sparc/string.h 2004-12-22 10:13:57.611952026 -0800 +++ wli-2.6.10-rc3-1/include/asm-sparc/string.h 2004-12-22 10:31:32.031655866 -0800 @@ -40,6 +40,9 @@ if(n <= 32) { __builtin_memcpy(to, from, n); + } else if (((unsigned int) to & 7) != 0) { + /* Destination is not aligned on the double-word boundary */ + __memcpy(to, from, n); } else { switch(n) { case PAGE_SIZE: Index: wli-2.6.10-rc3-1/include/asm-sparc/unistd.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-sparc/unistd.h 2004-12-22 10:13:19.650723010 -0800 +++ wli-2.6.10-rc3-1/include/asm-sparc/unistd.h 2004-12-22 11:01:22.342487250 -0800 @@ -486,7 +486,6 @@ static __inline__ _syscall3(int,execve,__const__ char *,file,char **,argv,char **,envp) static __inline__ _syscall3(int,open,__const__ char *,file,int,flag,int,mode) static __inline__ _syscall1(int,close,int,fd) -static __inline__ _syscall1(int,_exit,int,exitcode) static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) #include Index: wli-2.6.10-rc3-1/include/asm-sparc/winmacro.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/asm-sparc/winmacro.h 2004-12-22 10:14:01.803314842 -0800 +++ wli-2.6.10-rc3-1/include/asm-sparc/winmacro.h 2004-12-22 10:28:47.129724770 -0800 @@ -112,9 +112,12 @@ and %idreg, 0xc, %idreg; \ ld [%idreg + %dest_reg], %dest_reg; -/* Sliiick. We have a Linux current register :) -jj */ -#define LOAD_CURRENT4D(dest_reg) \ - lda [%g0] ASI_M_VIKING_TMP2, %dest_reg; +#define LOAD_CURRENT4D(dest_reg, idreg) \ + lda [%g0] ASI_M_VIKING_TMP1, %idreg; \ + sethi %hi(C_LABEL(current_set)), %dest_reg; \ + sll %idreg, 2, %idreg; \ + or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \ + ld [%idreg + %dest_reg], %dest_reg; /* Blackbox - take care with this... - check smp4m and smp4d before changing this. */ #define LOAD_CURRENT(dest_reg, idreg) \ Index: wli-2.6.10-rc3-1/include/linux/dvb/frontend.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/dvb/frontend.h 2004-12-16 06:20:01.000000000 -0800 +++ wli-2.6.10-rc3-1/include/linux/dvb/frontend.h 2004-12-22 10:04:36.724219922 -0800 @@ -62,7 +62,7 @@ FE_CAN_HIERARCHY_AUTO = 0x100000, FE_CAN_8VSB = 0x200000, FE_CAN_16VSB = 0x400000, - FE_NEEDS_BENDING = 0x20000000, // frontend requires frequency bending + FE_NEEDS_BENDING = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending) FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output } fe_caps_t; @@ -78,7 +78,7 @@ __u32 symbol_rate_min; __u32 symbol_rate_max; __u32 symbol_rate_tolerance; /* ppm */ - __u32 notifier_delay; /* ms */ + __u32 notifier_delay; /* DEPRECATED */ fe_caps_t caps; }; Index: wli-2.6.10-rc3-1/include/linux/filter.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/filter.h 2004-12-16 06:20:01.000000000 -0800 +++ wli-2.6.10-rc3-1/include/linux/filter.h 2004-12-22 10:04:36.691224938 -0800 @@ -8,7 +8,9 @@ #include #include +#ifdef __KERNEL__ #include +#endif /* * Current version of the filter code architecture. Index: wli-2.6.10-rc3-1/include/linux/hdreg.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/hdreg.h 2004-12-16 06:20:01.000000000 -0800 +++ wli-2.6.10-rc3-1/include/linux/hdreg.h 2004-12-22 10:04:36.695224330 -0800 @@ -1,6 +1,7 @@ #ifndef _LINUX_HDREG_H #define _LINUX_HDREG_H +#ifdef __KERNEL__ #include /* @@ -57,7 +58,7 @@ #define IO 0x02 #define REL 0x04 #define TAG_MASK 0xf8 - +#endif /* __KERNEL__ */ /* * Command Header sizes for IOCTL commands Index: wli-2.6.10-rc3-1/include/linux/i2o.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/i2o.h 2004-12-16 06:20:01.000000000 -0800 +++ wli-2.6.10-rc3-1/include/linux/i2o.h 2004-12-22 10:04:36.699223722 -0800 @@ -976,7 +976,7 @@ #define I2O_TIMEOUT_MESSAGE_GET 5 #define I2O_TIMEOUT_RESET 30 #define I2O_TIMEOUT_STATUS_GET 5 -#define I2O_TIMEOUT_LCT_GET 20 +#define I2O_TIMEOUT_LCT_GET 360 #define I2O_TIMEOUT_SCSI_SCB_ABORT 240 /* retries */ Index: wli-2.6.10-rc3-1/include/linux/libata.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/libata.h 2004-12-16 06:20:01.000000000 -0800 +++ wli-2.6.10-rc3-1/include/linux/libata.h 2004-12-22 10:04:36.702223266 -0800 @@ -112,6 +112,7 @@ ATA_FLAG_SRST = (1 << 5), /* use ATA SRST, not E.D.D. */ ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ + ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ Index: wli-2.6.10-rc3-1/include/linux/netfilter_ipv4/ip_conntrack_tcp.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/netfilter_ipv4/ip_conntrack_tcp.h 2004-12-22 09:07:10.227167114 -0800 +++ wli-2.6.10-rc3-1/include/linux/netfilter_ipv4/ip_conntrack_tcp.h 2004-12-22 10:04:36.726219618 -0800 @@ -18,7 +18,7 @@ }; /* Window scaling is advertised by the sender */ -#define IP_CT_TCP_STATE_FLAG_WINDOW_SCALE 0x01 +#define IP_CT_TCP_FLAG_WINDOW_SCALE 0x01 /* SACK is permitted by the sender */ #define IP_CT_TCP_FLAG_SACK_PERM 0x02 Index: wli-2.6.10-rc3-1/include/linux/pci_ids.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/pci_ids.h 2004-12-16 06:20:02.000000000 -0800 +++ wli-2.6.10-rc3-1/include/linux/pci_ids.h 2004-12-22 10:04:36.712221746 -0800 @@ -344,6 +344,7 @@ #define PCI_DEVICE_ID_ATI_RS300_200 0x5833 /* ATI IXP Chipset */ #define PCI_DEVICE_ID_ATI_IXP_IDE 0x4349 +#define PCI_DEVICE_ID_ATI_IXP2_IDE 0x4369 /* True name not yet sure */ #define PCI_VENDOR_ID_VLSI 0x1004 #define PCI_DEVICE_ID_VLSI_82C592 0x0005 @@ -1029,6 +1030,7 @@ #define PCI_DEVICE_ID_AL_M3307 0x3307 #define PCI_DEVICE_ID_AL_M4803 0x5215 #define PCI_DEVICE_ID_AL_M5219 0x5219 +#define PCI_DEVICE_ID_AL_M5228 0x5228 #define PCI_DEVICE_ID_AL_M5229 0x5229 #define PCI_DEVICE_ID_AL_M5237 0x5237 #define PCI_DEVICE_ID_AL_M5243 0x5243 Index: wli-2.6.10-rc3-1/include/linux/serial_core.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/serial_core.h 2004-12-16 06:20:02.000000000 -0800 +++ wli-2.6.10-rc3-1/include/linux/serial_core.h 2004-12-22 10:04:36.715221290 -0800 @@ -91,12 +91,15 @@ /* MPC52xx type numbers */ #define PORT_MPC52xx 59 -/*IBM icom*/ -#define PORT_ICOM 60 +/* IBM icom */ +#define PORT_ICOM 60 /* Samsung S3C2440 SoC */ #define PORT_S3C2440 61 +/* Motorola i.MX SoC */ +#define PORT_IMX 62 + #ifdef __KERNEL__ #include @@ -241,11 +244,11 @@ * within. */ struct uart_state { - unsigned int close_delay; - unsigned int closing_wait; + unsigned int close_delay; /* msec */ + unsigned int closing_wait; /* msec */ #define USF_CLOSING_WAIT_INF (0) -#define USF_CLOSING_WAIT_NONE (65535) +#define USF_CLOSING_WAIT_NONE (~0U) int count; int pm_state; Index: wli-2.6.10-rc3-1/include/linux/socket.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/socket.h 2004-12-22 09:07:10.200171218 -0800 +++ wli-2.6.10-rc3-1/include/linux/socket.h 2004-12-22 10:04:36.717220986 -0800 @@ -90,6 +90,10 @@ (struct cmsghdr *)(ctl) : \ (struct cmsghdr *)NULL) #define CMSG_FIRSTHDR(msg) __CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) +#define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) && \ + (cmsg)->cmsg_len <= (unsigned long) \ + ((mhdr)->msg_controllen - \ + ((char *)(cmsg) - (char *)(mhdr)->msg_control))) /* * This mess will go away with glibc Index: wli-2.6.10-rc3-1/include/linux/types.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/types.h 2004-12-16 06:20:02.000000000 -0800 +++ wli-2.6.10-rc3-1/include/linux/types.h 2004-12-22 10:04:36.719220682 -0800 @@ -157,8 +157,10 @@ typedef __u16 __bitwise __be16; typedef __u32 __bitwise __le32; typedef __u32 __bitwise __be32; +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) typedef __u64 __bitwise __le64; typedef __u64 __bitwise __be64; +#endif struct ustat { __kernel_daddr_t f_tfree; Index: wli-2.6.10-rc3-1/include/linux/wait.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/linux/wait.h 2004-12-16 06:20:02.000000000 -0800 +++ wli-2.6.10-rc3-1/include/linux/wait.h 2004-12-22 10:04:36.722220226 -0800 @@ -326,8 +326,8 @@ wait_queue_t name = { \ .task = current, \ .func = autoremove_wake_function, \ - .task_list = { .next = &name.task_list, \ - .prev = &name.task_list, \ + .task_list = { .next = &(name).task_list, \ + .prev = &(name).task_list, \ }, \ } @@ -338,15 +338,15 @@ .task = current, \ .func = wake_bit_function, \ .task_list = \ - LIST_HEAD_INIT(name.wait.task_list), \ + LIST_HEAD_INIT((name).wait.task_list), \ }, \ } #define init_wait(wait) \ do { \ - wait->task = current; \ - wait->func = autoremove_wake_function; \ - INIT_LIST_HEAD(&wait->task_list); \ + (wait)->task = current; \ + (wait)->func = autoremove_wake_function; \ + INIT_LIST_HEAD(&(wait)->task_list); \ } while (0) /** Index: wli-2.6.10-rc3-1/include/media/saa7146.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/media/saa7146.h 2004-12-16 06:20:02.000000000 -0800 +++ wli-2.6.10-rc3-1/include/media/saa7146.h 2004-12-22 10:04:36.730219010 -0800 @@ -51,10 +51,12 @@ #define DEB_INT(x) if (0!=(DEBUG_VARIABLE&0x20)) { DEBUG_PROLOG; printk x; } /* interrupt debug messages */ #define DEB_CAP(x) if (0!=(DEBUG_VARIABLE&0x40)) { DEBUG_PROLOG; printk x; } /* capture debug messages */ -#define IER_DISABLE(x,y) \ +#define SAA7146_IER_DISABLE(x,y) \ saa7146_write(x, IER, saa7146_read(x, IER) & ~(y)); -#define IER_ENABLE(x,y) \ +#define SAA7146_IER_ENABLE(x,y) \ saa7146_write(x, IER, saa7146_read(x, IER) | (y)); +#define SAA7146_ISR_CLEAR(x,y) \ + saa7146_write(x, ISR, (y)); struct saa7146_dev; struct saa7146_extension; @@ -168,7 +170,7 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length ); char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt); void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data); -int saa7146_wait_for_debi_done(struct saa7146_dev *dev); +int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop); /* some memory sizes */ #define SAA7146_I2C_MEM ( 1*PAGE_SIZE) Index: wli-2.6.10-rc3-1/include/media/saa7146_vv.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/media/saa7146_vv.h 2004-12-16 06:20:02.000000000 -0800 +++ wli-2.6.10-rc3-1/include/media/saa7146_vv.h 2004-12-22 10:04:36.732218706 -0800 @@ -219,8 +219,6 @@ /* resource management functions */ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit); -int saa7146_res_check(struct saa7146_fh *fh, unsigned int bit); -int saa7146_res_locked(struct saa7146_dev *dev, unsigned int bit); void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits); #define RESOURCE_DMA1_HPS 0x1 Index: wli-2.6.10-rc3-1/include/net/act_api.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/net/act_api.h 2004-12-16 06:20:02.000000000 -0800 +++ wli-2.6.10-rc3-1/include/net/act_api.h 2004-12-22 10:04:36.734218402 -0800 @@ -8,15 +8,23 @@ #include #include +#define tca_gen(name) \ +struct tcf_##name *next; \ + u32 index; \ + int refcnt; \ + int bindcnt; \ + u32 capab; \ + int action; \ + struct tcf_t tm; \ + struct gnet_stats_basic bstats; \ + struct gnet_stats_queue qstats; \ + struct gnet_stats_rate_est rate_est; \ + spinlock_t *stats_lock; \ + spinlock_t lock + struct tcf_police { - struct tcf_police *next; - int refcnt; -#ifdef CONFIG_NET_CLS_ACT - int bindcnt; -#endif - u32 index; - int action; + tca_gen(police); int result; u32 ewma_rate; u32 burst; @@ -24,33 +32,14 @@ u32 toks; u32 ptoks; psched_time_t t_c; - spinlock_t lock; struct qdisc_rate_table *R_tab; struct qdisc_rate_table *P_tab; - - struct gnet_stats_basic bstats; - struct gnet_stats_queue qstats; - struct gnet_stats_rate_est rate_est; - spinlock_t *stats_lock; }; #ifdef CONFIG_NET_CLS_ACT #define ACT_P_CREATED 1 #define ACT_P_DELETED 1 -#define tca_gen(name) \ -struct tcf_##name *next; \ - u32 index; \ - int refcnt; \ - int bindcnt; \ - u32 capab; \ - int action; \ - struct tcf_t tm; \ - struct gnet_stats_basic bstats; \ - struct gnet_stats_queue qstats; \ - struct gnet_stats_rate_est rate_est; \ - spinlock_t *stats_lock; \ - spinlock_t lock struct tcf_act_hdr { Index: wli-2.6.10-rc3-1/include/net/bluetooth/hci_core.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/net/bluetooth/hci_core.h 2004-12-16 06:20:02.000000000 -0800 +++ wli-2.6.10-rc3-1/include/net/bluetooth/hci_core.h 2004-12-22 10:04:36.744216882 -0800 @@ -38,10 +38,20 @@ /* HCI Core structures */ +struct inquiry_data { + bdaddr_t bdaddr; + __u8 pscan_rep_mode; + __u8 pscan_period_mode; + __u8 pscan_mode; + __u8 dev_class[3]; + __u16 clock_offset; + __s8 rssi; +}; + struct inquiry_entry { struct inquiry_entry *next; __u32 timestamp; - struct inquiry_info info; + struct inquiry_data data; }; struct inquiry_cache { @@ -142,6 +152,7 @@ __u16 state; __u8 type; __u8 out; + __u8 dev_class[3]; __u32 link_mode; unsigned long pend; @@ -199,7 +210,7 @@ } struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr); -void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_info *info); +void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data); /* ----- HCI Connections ----- */ enum { Index: wli-2.6.10-rc3-1/include/net/ip_vs.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/net/ip_vs.h 2004-12-16 06:20:02.000000000 -0800 +++ wli-2.6.10-rc3-1/include/net/ip_vs.h 2004-12-22 10:04:36.738217794 -0800 @@ -358,6 +358,7 @@ NET_IPV4_VS_EXPIRE_NODEST_CONN=23, NET_IPV4_VS_SYNC_THRESHOLD=24, NET_IPV4_VS_NAT_ICMP_SEND=25, + NET_IPV4_VS_EXPIRE_QUIESCENT_TEMPLATE=26, NET_IPV4_VS_LAST }; @@ -879,6 +880,7 @@ */ extern int sysctl_ip_vs_cache_bypass; extern int sysctl_ip_vs_expire_nodest_conn; +extern int sysctl_ip_vs_expire_quiescent_template; extern int sysctl_ip_vs_sync_threshold[2]; extern int sysctl_ip_vs_nat_icmp_send; extern struct ip_vs_stats ip_vs_stats; Index: wli-2.6.10-rc3-1/include/net/pkt_sched.h =================================================================== --- wli-2.6.10-rc3-1.orig/include/net/pkt_sched.h 2004-12-16 06:20:03.000000000 -0800 +++ wli-2.6.10-rc3-1/include/net/pkt_sched.h 2004-12-22 10:04:36.741217338 -0800 @@ -228,6 +228,12 @@ extern int qdisc_restart(struct net_device *dev); +static inline void qdisc_run(struct net_device *dev) +{ + while (!netif_queue_stopped(dev) && qdisc_restart(dev) < 0) + /* NOTHING */; +} + extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res); Index: wli-2.6.10-rc3-1/ipc/shm.c =================================================================== --- wli-2.6.10-rc3-1.orig/ipc/shm.c 2004-12-16 06:20:03.000000000 -0800 +++ wli-2.6.10-rc3-1/ipc/shm.c 2004-12-22 10:04:36.748216274 -0800 @@ -511,11 +511,6 @@ case SHM_LOCK: case SHM_UNLOCK: { - /* Allow superuser to lock segment in memory */ - if (!can_do_mlock() && cmd == SHM_LOCK) { - err = -EPERM; - goto out; - } shp = shm_lock(shmid); if(shp==NULL) { err = -EINVAL; @@ -525,6 +520,16 @@ if(err) goto out_unlock; + if (!capable(CAP_IPC_LOCK)) { + err = -EPERM; + if (current->euid != shp->shm_perm.uid && + current->euid != shp->shm_perm.cuid) + goto out_unlock; + if (cmd == SHM_LOCK && + !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur) + goto out_unlock; + } + err = security_shm_shmctl(shp, cmd); if (err) goto out_unlock; Index: wli-2.6.10-rc3-1/kernel/exit.c =================================================================== --- wli-2.6.10-rc3-1.orig/kernel/exit.c 2004-12-16 06:20:03.000000000 -0800 +++ wli-2.6.10-rc3-1/kernel/exit.c 2004-12-22 10:04:36.754215362 -0800 @@ -1319,6 +1319,10 @@ add_wait_queue(¤t->wait_chldexit,&wait); repeat: + /* + * We will set this flag if we see any child that might later + * match our criteria, even if we are not able to reap it yet. + */ flag = 0; current->state = TASK_INTERRUPTIBLE; read_lock(&tasklist_lock); @@ -1337,11 +1341,14 @@ switch (p->state) { case TASK_TRACED: - flag = 1; if (!my_ptrace_child(p)) continue; /*FALLTHROUGH*/ case TASK_STOPPED: + /* + * It's stopped now, so it might later + * continue, exit, or stop again. + */ flag = 1; if (!(options & WUNTRACED) && !my_ptrace_child(p)) @@ -1377,8 +1384,12 @@ goto end; break; } - flag = 1; check_continued: + /* + * It's running now, so it might later + * exit, stop, or stop and then continue. + */ + flag = 1; if (!unlikely(options & WCONTINUED)) continue; retval = wait_task_continued( Index: wli-2.6.10-rc3-1/kernel/posix-timers.c =================================================================== --- wli-2.6.10-rc3-1.orig/kernel/posix-timers.c 2004-12-16 06:20:03.000000000 -0800 +++ wli-2.6.10-rc3-1/kernel/posix-timers.c 2004-12-22 10:04:36.763213994 -0800 @@ -10,10 +10,6 @@ * 2004-06-01 Fix CLOCK_REALTIME clock/timer TIMER_ABSTIME bug. * Copyright (C) 2004 Boris Hu * - * 2004-07-27 Provide POSIX compliant clocks - * CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID. - * by Christoph Lameter - * * 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 @@ -193,8 +189,6 @@ static u64 do_posix_clock_monotonic_gettime_parts( struct timespec *tp, struct timespec *mo); int do_posix_clock_monotonic_gettime(struct timespec *tp); -static int do_posix_clock_process_gettime(struct timespec *tp); -static int do_posix_clock_thread_gettime(struct timespec *tp); static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags); static inline void unlock_timer(struct k_itimer *timr, unsigned long flags) @@ -215,25 +209,9 @@ .clock_get = do_posix_clock_monotonic_gettime, .clock_set = do_posix_clock_nosettime }; - struct k_clock clock_thread = {.res = CLOCK_REALTIME_RES, - .abs_struct = NULL, - .clock_get = do_posix_clock_thread_gettime, - .clock_set = do_posix_clock_nosettime, - .timer_create = do_posix_clock_notimer_create, - .nsleep = do_posix_clock_nonanosleep - }; - struct k_clock clock_process = {.res = CLOCK_REALTIME_RES, - .abs_struct = NULL, - .clock_get = do_posix_clock_process_gettime, - .clock_set = do_posix_clock_nosettime, - .timer_create = do_posix_clock_notimer_create, - .nsleep = do_posix_clock_nonanosleep - }; register_posix_clock(CLOCK_REALTIME, &clock_realtime); register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic); - register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &clock_process); - register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &clock_thread); posix_timers_cache = kmem_cache_create("posix_timers_cache", sizeof (struct k_itimer), 0, 0, NULL, NULL); @@ -1220,69 +1198,18 @@ return -EINVAL; } -int do_posix_clock_notimer_create(struct k_itimer *timer) { - return -EINVAL; -} - -int do_posix_clock_nonanosleep(int which_lock, int flags,struct timespec * t) { -/* Single Unix specficiation says to return ENOTSUP but we do not have that */ - return -EINVAL; -} - -static unsigned long process_ticks(task_t *p) { - unsigned long ticks; - task_t *t; - - spin_lock(&p->sighand->siglock); - /* The signal structure is shared between all threads */ - ticks = p->signal->utime + p->signal->stime; - - /* Add up the cpu time for all the still running threads of this process */ - t = p; - do { - ticks += t->utime + t->stime; - t = next_thread(t); - } while (t != p); - - spin_unlock(&p->sighand->siglock); - return ticks; -} - -static inline unsigned long thread_ticks(task_t *p) { - return p->utime + current->stime; -} - -/* - * Single Unix Specification V3: - * - * Implementations shall also support the special clockid_t value - * CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the calling - * thread when invoking one of the clock_*() or timer_*() functions. For these - * clock IDs, the values returned by clock_gettime() and specified by - * clock_settime() shall represent the amount of execution time of the thread - * associated with the clock. - */ -static int do_posix_clock_thread_gettime(struct timespec *tp) +int do_posix_clock_notimer_create(struct k_itimer *timer) { - jiffies_to_timespec(thread_ticks(current), tp); - return 0; + return -EINVAL; } -/* - * Single Unix Specification V3: - * - * Implementations shall also support the special clockid_t value - * CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the - * calling process when invoking one of the clock_*() or timer_*() functions. - * For these clock IDs, the values returned by clock_gettime() and specified - * by clock_settime() represent the amount of execution time of the process - * associated with the clock. - */ - -static int do_posix_clock_process_gettime(struct timespec *tp) +int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec *t) { - jiffies_to_timespec(process_ticks(current), tp); - return 0; +#ifndef ENOTSUP + return -EOPNOTSUPP; /* aka ENOTSUP in userland for POSIX */ +#else /* parisc does define it separately. */ + return -ENOTSUP; +#endif } asmlinkage long @@ -1290,10 +1217,6 @@ { struct timespec new_tp; - /* Cannot set process specific clocks */ - if (which_clock<0) - return -EINVAL; - if ((unsigned) which_clock >= MAX_CLOCKS || !posix_clocks[which_clock].res) return -EINVAL; @@ -1307,29 +1230,6 @@ static int do_clock_gettime(clockid_t which_clock, struct timespec *tp) { - /* Process process specific clocks */ - if (which_clock < 0) { - task_t *t; - int pid = -which_clock; - - if (pid < PID_MAX_LIMIT) { - if ((t = find_task_by_pid(pid))) { - jiffies_to_timespec(process_ticks(t), tp); - return 0; - } - return -EINVAL; - } - if (pid < 2*PID_MAX_LIMIT) { - if ((t = find_task_by_pid(pid - PID_MAX_LIMIT))) { - jiffies_to_timespec(thread_ticks(t), tp); - return 0; - } - return -EINVAL; - } - /* More process specific clocks could follow here */ - return -EINVAL; - } - if ((unsigned) which_clock >= MAX_CLOCKS || !posix_clocks[which_clock].res) return -EINVAL; @@ -1356,9 +1256,6 @@ { struct timespec rtn_tp; - /* All process clocks have the resolution of CLOCK_PROCESS_CPUTIME_ID */ - if (which_clock < 0 ) which_clock = CLOCK_PROCESS_CPUTIME_ID; - if ((unsigned) which_clock >= MAX_CLOCKS || !posix_clocks[which_clock].res) return -EINVAL; Index: wli-2.6.10-rc3-1/kernel/power/disk.c =================================================================== --- wli-2.6.10-rc3-1.orig/kernel/power/disk.c 2004-12-16 06:20:03.000000000 -0800 +++ wli-2.6.10-rc3-1/kernel/power/disk.c 2004-12-22 10:04:36.779211562 -0800 @@ -43,7 +43,7 @@ * there ain't no turning back. */ -static void power_down(u32 mode) +static void power_down(suspend_disk_method_t mode) { unsigned long flags; int error = 0; Index: wli-2.6.10-rc3-1/kernel/power/main.c =================================================================== --- wli-2.6.10-rc3-1.orig/kernel/power/main.c 2004-12-16 06:20:03.000000000 -0800 +++ wli-2.6.10-rc3-1/kernel/power/main.c 2004-12-22 10:04:36.780211410 -0800 @@ -4,7 +4,7 @@ * Copyright (c) 2003 Patrick Mochel * Copyright (c) 2003 Open Source Development Lab * - * This file is release under the GPLv2 + * This file is released under the GPLv2 * */ Index: wli-2.6.10-rc3-1/kernel/power/swsusp.c =================================================================== --- wli-2.6.10-rc3-1.orig/kernel/power/swsusp.c 2004-12-16 06:20:03.000000000 -0800 +++ wli-2.6.10-rc3-1/kernel/power/swsusp.c 2004-12-22 10:04:36.785210650 -0800 @@ -786,12 +786,13 @@ int suspend_prepare_image(void) { - unsigned int nr_needed_pages = 0; + unsigned int nr_needed_pages; int error; pr_debug("swsusp: critical section: \n"); if (save_highmem()) { printk(KERN_CRIT "Suspend machine: Not enough free pages for highmem\n"); + restore_highmem(); return -ENOMEM; } @@ -985,6 +986,8 @@ c = *c; free_pages((unsigned long)f, pagedir_order); } + if (ret) + return ret; printk("|\n"); return check_pagedir(); } @@ -1128,7 +1131,7 @@ */ error = bio_write_page(0, &swsusp_header); } else { - pr_debug(KERN_ERR "swsusp: Invalid partition type.\n"); + pr_debug(KERN_ERR "swsusp: Suspend partition has wrong signature?\n"); return -EINVAL; } if (!error) Index: wli-2.6.10-rc3-1/kernel/sched.c =================================================================== --- wli-2.6.10-rc3-1.orig/kernel/sched.c 2004-12-16 06:20:03.000000000 -0800 +++ wli-2.6.10-rc3-1/kernel/sched.c 2004-12-22 10:04:36.776212018 -0800 @@ -4446,6 +4446,7 @@ if (sd->parent) printk(" ERROR !SD_LOAD_BALANCE domain has parent"); printk("\n"); + break; } printk("span %s\n", str); @@ -4454,8 +4455,6 @@ printk(KERN_DEBUG "ERROR domain->span does not contain CPU%d\n", i); if (!cpu_isset(i, group->cpumask)) printk(KERN_DEBUG "ERROR domain->groups does not contain CPU%d\n", i); - if (!group->cpu_power) - printk(KERN_DEBUG "ERROR domain->cpu_power not set\n"); printk(KERN_DEBUG); for (j = 0; j < level + 2; j++) @@ -4466,6 +4465,9 @@ printk(" ERROR: NULL"); break; } + + if (!group->cpu_power) + printk(KERN_DEBUG "ERROR group->cpu_power not set\n"); if (!cpus_weight(group->cpumask)) printk(" ERROR empty group:"); Index: wli-2.6.10-rc3-1/mm/highmem.c =================================================================== --- wli-2.6.10-rc3-1.orig/mm/highmem.c 2004-12-22 09:07:10.312154194 -0800 +++ wli-2.6.10-rc3-1/mm/highmem.c 2004-12-22 10:04:36.789210042 -0800 @@ -305,14 +305,14 @@ } } -static void bounce_end_io(struct bio *bio, mempool_t *pool) +static void bounce_end_io(struct bio *bio, mempool_t *pool, int err) { struct bio *bio_orig = bio->bi_private; struct bio_vec *bvec, *org_vec; - int i, err = 0; + int i; - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) - err = -EIO; + if (test_bit(BIO_EOPNOTSUPP, &bio->bi_flags)) + set_bit(BIO_EOPNOTSUPP, &bio_orig->bi_flags); /* * free up bounce indirect pages used @@ -334,7 +334,7 @@ if (bio->bi_size) return 1; - bounce_end_io(bio, page_pool); + bounce_end_io(bio, page_pool, err); return 0; } @@ -343,18 +343,18 @@ if (bio->bi_size) return 1; - bounce_end_io(bio, isa_page_pool); + bounce_end_io(bio, isa_page_pool, err); return 0; } -static void __bounce_end_io_read(struct bio *bio, mempool_t *pool) +static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err) { struct bio *bio_orig = bio->bi_private; if (test_bit(BIO_UPTODATE, &bio->bi_flags)) copy_to_high_bio_irq(bio_orig, bio); - bounce_end_io(bio, pool); + bounce_end_io(bio, pool, err); } static int bounce_end_io_read(struct bio *bio, unsigned int bytes_done, int err) @@ -362,7 +362,7 @@ if (bio->bi_size) return 1; - __bounce_end_io_read(bio, page_pool); + __bounce_end_io_read(bio, page_pool, err); return 0; } @@ -371,7 +371,7 @@ if (bio->bi_size) return 1; - __bounce_end_io_read(bio, isa_page_pool); + __bounce_end_io_read(bio, isa_page_pool, err); return 0; } Index: wli-2.6.10-rc3-1/mm/mmap.c =================================================================== --- wli-2.6.10-rc3-1.orig/mm/mmap.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/mm/mmap.c 2004-12-22 10:04:36.796208978 -0800 @@ -744,12 +744,12 @@ } #endif /* CONFIG_HUGETLB */ - if (file) + if (file) { mm->shared_vm += pages; - else if (flags & stack_flags) + if ((flags & (VM_EXEC|VM_WRITE)) == VM_EXEC) + mm->exec_vm += pages; + } else if (flags & stack_flags) mm->stack_vm += pages; - if (flags & VM_EXEC) - mm->exec_vm += pages; if (flags & (VM_RESERVED|VM_IO)) mm->reserved_vm += pages; } Index: wli-2.6.10-rc3-1/mm/mprotect.c =================================================================== --- wli-2.6.10-rc3-1.orig/mm/mprotect.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/mm/mprotect.c 2004-12-22 10:04:36.798208674 -0800 @@ -111,15 +111,17 @@ static int mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, - unsigned long start, unsigned long end, unsigned int newflags) + unsigned long start, unsigned long end, unsigned long newflags) { struct mm_struct * mm = vma->vm_mm; + unsigned long oldflags = vma->vm_flags; + long nrpages = (end - start) >> PAGE_SHIFT; unsigned long charged = 0; pgprot_t newprot; pgoff_t pgoff; int error; - if (newflags == vma->vm_flags) { + if (newflags == oldflags) { *pprev = vma; return 0; } @@ -133,8 +135,8 @@ * a MAP_NORESERVE private mapping to writable will now reserve. */ if (newflags & VM_WRITE) { - if (!(vma->vm_flags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) { - charged = (end - start) >> PAGE_SHIFT; + if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) { + charged = nrpages; if (security_vm_enough_memory(charged)) return -ENOMEM; newflags |= VM_ACCOUNT; @@ -176,11 +178,11 @@ * vm_flags and vm_page_prot are protected by the mmap_sem * held in write mode. */ - vm_stat_unaccount(vma); vma->vm_flags = newflags; vma->vm_page_prot = newprot; change_protection(vma, start, end, newprot); - vm_stat_account(vma); + __vm_stat_account(mm, oldflags, vma->vm_file, -nrpages); + __vm_stat_account(mm, newflags, vma->vm_file, nrpages); return 0; fail: @@ -246,7 +248,7 @@ prev = vma; for (nstart = start ; ; ) { - unsigned int newflags; + unsigned long newflags; /* Here we know that vma->vm_start <= nstart < vma->vm_end. */ Index: wli-2.6.10-rc3-1/mm/rmap.c =================================================================== --- wli-2.6.10-rc3-1.orig/mm/rmap.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/mm/rmap.c 2004-12-22 10:04:36.802208066 -0800 @@ -395,6 +395,9 @@ { int referenced = 0; + if (!swap_token_default_timeout) + ignore_token = 1; + if (page_test_and_clear_young(page)) referenced++; Index: wli-2.6.10-rc3-1/mm/slab.c =================================================================== --- wli-2.6.10-rc3-1.orig/mm/slab.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/mm/slab.c 2004-12-22 10:04:36.811206698 -0800 @@ -2573,6 +2573,7 @@ continue; kfree(p->ptrs[i]); } + kfree(p); } EXPORT_SYMBOL(free_percpu); Index: wli-2.6.10-rc3-1/mm/thrash.c =================================================================== --- wli-2.6.10-rc3-1.orig/mm/thrash.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/mm/thrash.c 2004-12-22 10:04:36.813206394 -0800 @@ -19,7 +19,10 @@ struct mm_struct * swap_token_mm = &init_mm; #define SWAP_TOKEN_CHECK_INTERVAL (HZ * 2) -#define SWAP_TOKEN_TIMEOUT (HZ * 300) +#define SWAP_TOKEN_TIMEOUT 0 +/* + * Currently disabled; Needs further code to work at HZ * 300. + */ unsigned long swap_token_default_timeout = SWAP_TOKEN_TIMEOUT; /* Index: wli-2.6.10-rc3-1/net/bluetooth/hci_conn.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/bluetooth/hci_conn.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/bluetooth/hci_conn.c 2004-12-22 10:04:36.819205482 -0800 @@ -71,9 +71,10 @@ if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)) && inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) { - cp.pscan_rep_mode = ie->info.pscan_rep_mode; - cp.pscan_mode = ie->info.pscan_mode; - cp.clock_offset = ie->info.clock_offset | __cpu_to_le16(0x8000); + cp.pscan_rep_mode = ie->data.pscan_rep_mode; + cp.pscan_mode = ie->data.pscan_mode; + cp.clock_offset = ie->data.clock_offset | __cpu_to_le16(0x8000); + memcpy(conn->dev_class, ie->data.dev_class, 3); } cp.pkt_type = __cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK); Index: wli-2.6.10-rc3-1/net/bluetooth/hci_core.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/bluetooth/hci_core.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/bluetooth/hci_core.c 2004-12-22 10:04:36.825204570 -0800 @@ -313,19 +313,19 @@ BT_DBG("cache %p, %s", cache, batostr(bdaddr)); for (e = cache->list; e; e = e->next) - if (!bacmp(&e->info.bdaddr, bdaddr)) + if (!bacmp(&e->data.bdaddr, bdaddr)) break; return e; } -void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_info *info) +void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data) { struct inquiry_cache *cache = &hdev->inq_cache; struct inquiry_entry *e; - BT_DBG("cache %p, %s", cache, batostr(&info->bdaddr)); + BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr)); - if (!(e = hci_inquiry_cache_lookup(hdev, &info->bdaddr))) { + if (!(e = hci_inquiry_cache_lookup(hdev, &data->bdaddr))) { /* Entry not in the cache. Add new one. */ if (!(e = kmalloc(sizeof(struct inquiry_entry), GFP_ATOMIC))) return; @@ -334,7 +334,7 @@ cache->list = e; } - memcpy(&e->info, info, sizeof(*info)); + memcpy(&e->data, data, sizeof(*data)); e->timestamp = jiffies; cache->timestamp = jiffies; } @@ -346,8 +346,16 @@ struct inquiry_entry *e; int copied = 0; - for (e = cache->list; e && copied < num; e = e->next, copied++) - memcpy(info++, &e->info, sizeof(*info)); + for (e = cache->list; e && copied < num; e = e->next, copied++) { + struct inquiry_data *data = &e->data; + bacpy(&info->bdaddr, &data->bdaddr); + info->pscan_rep_mode = data->pscan_rep_mode; + info->pscan_period_mode = data->pscan_period_mode; + info->pscan_mode = data->pscan_mode; + memcpy(info->dev_class, data->dev_class, 3); + info->clock_offset = data->clock_offset; + info++; + } BT_DBG("cache %p, copied %d", cache, copied); return copied; Index: wli-2.6.10-rc3-1/net/bluetooth/hci_event.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/bluetooth/hci_event.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/bluetooth/hci_event.c 2004-12-22 10:04:36.829203962 -0800 @@ -491,8 +491,18 @@ BT_DBG("%s num_rsp %d", hdev->name, num_rsp); hci_dev_lock(hdev); - for (; num_rsp; num_rsp--) - hci_inquiry_cache_update(hdev, info++); + for (; num_rsp; num_rsp--) { + struct inquiry_data data; + bacpy(&data.bdaddr, &info->bdaddr); + data.pscan_rep_mode = info->pscan_rep_mode; + data.pscan_period_mode = info->pscan_period_mode; + data.pscan_mode = info->pscan_mode; + memcpy(data.dev_class, info->dev_class, 3); + data.clock_offset = info->clock_offset; + data.rssi = 0x00; + info++; + hci_inquiry_cache_update(hdev, &data); + } hci_dev_unlock(hdev); } @@ -506,15 +516,16 @@ hci_dev_lock(hdev); for (; num_rsp; num_rsp--) { - struct inquiry_info tmp; - bacpy(&tmp.bdaddr, &info->bdaddr); - tmp.pscan_rep_mode = info->pscan_rep_mode; - tmp.pscan_period_mode = info->pscan_period_mode; - tmp.pscan_mode = 0x00; - memcpy(tmp.dev_class, &info->dev_class, 3); - tmp.clock_offset = info->clock_offset; + struct inquiry_data data; + bacpy(&data.bdaddr, &info->bdaddr); + data.pscan_rep_mode = info->pscan_rep_mode; + data.pscan_period_mode = info->pscan_period_mode; + data.pscan_mode = 0x00; + memcpy(data.dev_class, info->dev_class, 3); + data.clock_offset = info->clock_offset; + data.rssi = info->rssi; info++; - hci_inquiry_cache_update(hdev, &tmp); + hci_inquiry_cache_update(hdev, &data); } hci_dev_unlock(hdev); } @@ -544,6 +555,7 @@ return; } } + memcpy(conn->dev_class, ev->dev_class, 3); conn->state = BT_CONNECT; hci_dev_unlock(hdev); Index: wli-2.6.10-rc3-1/net/bluetooth/hci_sysfs.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/bluetooth/hci_sysfs.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/bluetooth/hci_sysfs.c 2004-12-22 10:04:36.831203658 -0800 @@ -48,14 +48,14 @@ hci_dev_lock_bh(hdev); for (e = cache->list; e; e = e->next) { - struct inquiry_info *info = &e->info; + struct inquiry_data *data = &e->data; bdaddr_t bdaddr; - baswap(&bdaddr, &info->bdaddr); - n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x 0x%.2x %u\n", + baswap(&bdaddr, &data->bdaddr); + n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %u\n", batostr(&bdaddr), - info->pscan_rep_mode, info->pscan_period_mode, info->pscan_mode, - info->dev_class[2], info->dev_class[1], info->dev_class[0], - info->clock_offset, 0, e->timestamp); + data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode, + data->dev_class[2], data->dev_class[1], data->dev_class[0], + data->clock_offset, data->rssi, e->timestamp); } hci_dev_unlock_bh(hdev); Index: wli-2.6.10-rc3-1/net/compat.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/compat.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/compat.c 2004-12-22 10:04:36.817205786 -0800 @@ -124,6 +124,12 @@ (struct compat_cmsghdr __user *)((msg)->msg_control) : \ (struct compat_cmsghdr __user *)NULL) +#define CMSG_COMPAT_OK(ucmlen, ucmsg, mhdr) \ + ((ucmlen) >= sizeof(struct cmsghdr) && \ + (ucmlen) <= (unsigned long) \ + ((mhdr)->msg_controllen - \ + ((char *)(ucmsg) - (char *)(mhdr)->msg_control))) + static inline struct compat_cmsghdr __user *cmsg_compat_nxthdr(struct msghdr *msg, struct compat_cmsghdr __user *cmsg, int cmsg_len) { @@ -154,11 +160,7 @@ return -EFAULT; /* Catch bogons. */ - if(CMSG_COMPAT_ALIGN(ucmlen) < - CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))) - return -EINVAL; - if((unsigned long)(((char __user *)ucmsg - (char __user *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) + if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg)) return -EINVAL; tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) + Index: wli-2.6.10-rc3-1/net/core/dev.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/core/dev.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/core/dev.c 2004-12-22 10:04:36.841202138 -0800 @@ -1202,13 +1202,6 @@ } \ } -static inline void qdisc_run(struct net_device *dev) -{ - while (!netif_queue_stopped(dev) && - qdisc_restart(dev)<0) - /* NOTHING */; -} - /** * dev_queue_xmit - transmit a buffer * @skb: buffer to transmit Index: wli-2.6.10-rc3-1/net/core/scm.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/core/scm.c 2004-12-22 09:07:10.352148114 -0800 +++ wli-2.6.10-rc3-1/net/core/scm.c 2004-12-22 10:04:36.843201834 -0800 @@ -127,9 +127,7 @@ for too short ancillary data object at all! Oops. OK, let's add it... */ - if (cmsg->cmsg_len < sizeof(struct cmsghdr) || - (unsigned long)(((char*)cmsg - (char*)msg->msg_control) - + cmsg->cmsg_len) > msg->msg_controllen) + if (!CMSG_OK(msg, cmsg)) goto error; if (cmsg->cmsg_level != SOL_SOCKET) Index: wli-2.6.10-rc3-1/net/ipv4/af_inet.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/af_inet.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/af_inet.c 2004-12-22 10:04:36.848201074 -0800 @@ -821,6 +821,31 @@ .sendpage = inet_sendpage, }; +/* + * For SOCK_RAW sockets; should be the same as inet_dgram_ops but without + * udp_poll + */ +static struct proto_ops inet_sockraw_ops = { + .family = PF_INET, + .owner = THIS_MODULE, + .release = inet_release, + .bind = inet_bind, + .connect = inet_dgram_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = inet_getname, + .poll = datagram_poll, + .ioctl = inet_ioctl, + .listen = sock_no_listen, + .shutdown = inet_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = inet_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = inet_sendpage, +}; + static struct net_proto_family inet_family_ops = { .family = PF_INET, .create = inet_create, @@ -861,7 +886,7 @@ .type = SOCK_RAW, .protocol = IPPROTO_IP, /* wild card */ .prot = &raw_prot, - .ops = &inet_dgram_ops, + .ops = &inet_sockraw_ops, .capability = CAP_NET_RAW, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_REUSE, Index: wli-2.6.10-rc3-1/net/ipv4/igmp.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/igmp.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/igmp.c 2004-12-22 10:04:36.857199706 -0800 @@ -1778,12 +1778,12 @@ goto done; rv = !0; for (i=0; isl_count; i++) { - rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr, + rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr, sizeof(__u32)); - if (rv >= 0) + if (rv == 0) break; } - if (!rv) /* source not found */ + if (rv) /* source not found */ goto done; /* update the interface filter */ @@ -1825,9 +1825,9 @@ } rv = 1; /* > 0 for insert logic below if sl_count is 0 */ for (i=0; isl_count; i++) { - rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr, + rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr, sizeof(__u32)); - if (rv >= 0) + if (rv == 0) break; } if (rv == 0) /* address already there is an error */ Index: wli-2.6.10-rc3-1/net/ipv4/ip_options.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/ip_options.c 2004-12-22 09:07:10.367145834 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/ip_options.c 2004-12-22 10:04:36.859199402 -0800 @@ -515,6 +515,8 @@ kfree(opt); return -EINVAL; } + if (*optp) + kfree(*optp); *optp = opt; return 0; } Index: wli-2.6.10-rc3-1/net/ipv4/ip_sockglue.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/ip_sockglue.c 2004-12-22 09:07:10.368145682 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/ip_sockglue.c 2004-12-22 10:04:36.863198794 -0800 @@ -146,11 +146,8 @@ struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { - if (cmsg->cmsg_len < sizeof(struct cmsghdr) || - (unsigned long)(((char*)cmsg - (char*)msg->msg_control) - + cmsg->cmsg_len) > msg->msg_controllen) { + if (!CMSG_OK(msg, cmsg)) return -EINVAL; - } if (cmsg->cmsg_level != SOL_IP) continue; switch (cmsg->cmsg_type) { Index: wli-2.6.10-rc3-1/net/ipv4/ipvs/ip_vs_conn.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/ipvs/ip_vs_conn.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/ipvs/ip_vs_conn.c 2004-12-22 10:04:36.883195754 -0800 @@ -453,7 +453,9 @@ * Checking the dest server status. */ if ((dest == NULL) || - !(dest->flags & IP_VS_DEST_F_AVAILABLE)) { + !(dest->flags & IP_VS_DEST_F_AVAILABLE) || + (sysctl_ip_vs_expire_quiescent_template && + (atomic_read(&dest->weight) == 0))) { IP_VS_DBG(9, "check_template: dest not available for " "protocol %s s:%u.%u.%u.%u:%d v:%u.%u.%u.%u:%d " "-> d:%u.%u.%u.%u:%d\n", Index: wli-2.6.10-rc3-1/net/ipv4/ipvs/ip_vs_ctl.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/ipvs/ip_vs_ctl.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/ipvs/ip_vs_ctl.c 2004-12-22 10:04:36.893194234 -0800 @@ -75,6 +75,7 @@ static int sysctl_ip_vs_am_droprate = 10; int sysctl_ip_vs_cache_bypass = 0; int sysctl_ip_vs_expire_nodest_conn = 0; +int sysctl_ip_vs_expire_quiescent_template = 0; int sysctl_ip_vs_sync_threshold[2] = { 3, 50 }; int sysctl_ip_vs_nat_icmp_send = 0; @@ -1447,9 +1448,9 @@ { .ctl_name = NET_IPV4_VS_TO_ES, .procname = "timeout_established", - .data = &vs_timeout_table_dos.timeout[IP_VS_S_ESTABLISHED], + .data = &vs_timeout_table_dos.timeout[IP_VS_S_ESTABLISHED], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1457,7 +1458,7 @@ .procname = "timeout_synsent", .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYN_SENT], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1465,7 +1466,7 @@ .procname = "timeout_synrecv", .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYN_RECV], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1473,7 +1474,7 @@ .procname = "timeout_finwait", .data = &vs_timeout_table_dos.timeout[IP_VS_S_FIN_WAIT], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1489,7 +1490,7 @@ .procname = "timeout_close", .data = &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1497,7 +1498,7 @@ .procname = "timeout_closewait", .data = &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE_WAIT], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1505,7 +1506,7 @@ .procname = "timeout_lastack", .data = &vs_timeout_table_dos.timeout[IP_VS_S_LAST_ACK], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1513,7 +1514,7 @@ .procname = "timeout_listen", .data = &vs_timeout_table_dos.timeout[IP_VS_S_LISTEN], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1521,7 +1522,7 @@ .procname = "timeout_synack", .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYNACK], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1529,7 +1530,7 @@ .procname = "timeout_udp", .data = &vs_timeout_table_dos.timeout[IP_VS_S_UDP], .maxlen = sizeof(int), - .mode = 0644, + .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { @@ -1558,6 +1559,14 @@ .proc_handler = &proc_dointvec, }, { + .ctl_name = NET_IPV4_VS_EXPIRE_QUIESCENT_TEMPLATE, + .procname = "expire_quiescent_template", + .data = &sysctl_ip_vs_expire_quiescent_template, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { .ctl_name = NET_IPV4_VS_SYNC_THRESHOLD, .procname = "sync_threshold", .data = &sysctl_ip_vs_sync_threshold, Index: wli-2.6.10-rc3-1/net/ipv4/netfilter/ip_conntrack_ftp.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-12-22 10:04:36.896193778 -0800 @@ -381,6 +381,7 @@ problem (DMZ machines opening holes to internal networks, or the packet filter itself). */ if (!loose) { + ip_conntrack_expect_put(exp); ret = NF_ACCEPT; goto out; } Index: wli-2.6.10-rc3-1/net/ipv4/netfilter/ip_conntrack_irc.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/netfilter/ip_conntrack_irc.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/netfilter/ip_conntrack_irc.c 2004-12-22 10:04:36.898193474 -0800 @@ -65,8 +65,8 @@ #define DEBUGP(format, args...) #endif -int parse_dcc(char *data, char *data_end, u_int32_t * ip, u_int16_t * port, - char **ad_beg_p, char **ad_end_p) +static int parse_dcc(char *data, char *data_end, u_int32_t *ip, + u_int16_t *port, char **ad_beg_p, char **ad_end_p) /* tries to get the ip_addr and port out of a dcc command return value: -1 on failure, 0 on success data pointer to first byte of DCC command data Index: wli-2.6.10-rc3-1/net/ipv4/netfilter/ip_conntrack_proto_tcp.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-12-22 10:04:36.904192562 -0800 @@ -273,9 +273,9 @@ * sCL -> sCL */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ -/*ack*/ { sIV, sIV, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV }, +/*ack*/ { sIV, sIG, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV }, /* - * sSS -> sIV ACK is invalid: we haven't seen a SYN/ACK yet. + * sSS -> sIG Might be a half-open connection. * sSR -> sIV Simultaneous open. * sES -> sES :-) * sFW -> sCW Normal close request answered by ACK. @@ -436,7 +436,7 @@ state->td_scale = 14; } state->flags |= - IP_CT_TCP_STATE_FLAG_WINDOW_SCALE; + IP_CT_TCP_FLAG_WINDOW_SCALE; } ptr += opsize - 2; length -= opsize; @@ -552,8 +552,8 @@ * Both sides must send the Window Scale option * to enable window scaling in either direction. */ - if (!(sender->flags & IP_CT_TCP_STATE_FLAG_WINDOW_SCALE - && receiver->flags & IP_CT_TCP_STATE_FLAG_WINDOW_SCALE)) + if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE + && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE)) sender->td_scale = receiver->td_scale = 0; } else { @@ -566,9 +566,11 @@ sender->td_maxwin = (win == 0 ? 1 : win); sender->td_maxend = end + sender->td_maxwin; } - } else if (state->state == TCP_CONNTRACK_SYN_SENT - && dir == IP_CT_DIR_ORIGINAL - && after(end, sender->td_end)) { + } else if (((state->state == TCP_CONNTRACK_SYN_SENT + && dir == IP_CT_DIR_ORIGINAL) + || (state->state == TCP_CONNTRACK_SYN_RECV + && dir == IP_CT_DIR_REPLY)) + && after(end, sender->td_end)) { /* * RFC 793: "if a TCP is reinitialized ... then it need * not wait at all; it must only be sure to use sequence @@ -685,7 +687,7 @@ "ip_ct_tcp: %s ", before(end, sender->td_maxend + 1) ? after(seq, sender->td_end - receiver->td_maxwin - 1) ? - before(ack, receiver->td_end + 1) ? + before(sack, receiver->td_end + 1) ? after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG" : "ACK is under the lower bound (possibly overly delayed ACK)" : "ACK is over the upper bound (ACKed data has never seen yet)" @@ -846,7 +848,9 @@ switch (new_state) { case TCP_CONNTRACK_IGNORE: - /* Either SYN in ORIGINAL, or SYN/ACK in REPLY direction. */ + /* Either SYN in ORIGINAL + * or SYN/ACK in REPLY + * or ACK in REPLY direction (half-open connection). */ if (index == TCP_SYNACK_SET && conntrack->proto.tcp.last_index == TCP_SYN_SET && conntrack->proto.tcp.last_dir != dir @@ -875,7 +879,7 @@ WRITE_UNLOCK(&tcp_lock); if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(PF_INET, 0, skb, NULL, NULL, - "ip_ct_tcp: invalid SYN (ignored) "); + "ip_ct_tcp: invalid packet ignored "); return NF_ACCEPT; case TCP_CONNTRACK_MAX: /* Invalid packet */ @@ -900,11 +904,12 @@ break; case TCP_CONNTRACK_CLOSE: if (index == TCP_RST_SET - && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) - && conntrack->proto.tcp.last_index <= TCP_SYNACK_SET + && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) + && conntrack->proto.tcp.last_index <= TCP_SYNACK_SET) + || conntrack->proto.tcp.last_index == TCP_ACK_SET) && after(ntohl(th->ack_seq), conntrack->proto.tcp.last_seq)) { - /* Ignore RST closing down invalid SYN + /* Ignore RST closing down invalid SYN or ACK we had let trough. */ WRITE_UNLOCK(&tcp_lock); if (LOG_INVALID(IPPROTO_TCP)) Index: wli-2.6.10-rc3-1/net/ipv4/netfilter/ip_conntrack_standalone.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-16 06:20:04.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-22 10:04:36.908191954 -0800 @@ -741,6 +741,7 @@ goto cleanup_nothing; #ifdef CONFIG_PROC_FS + ret = -ENOMEM; proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops); if (!proc) goto cleanup_init; Index: wli-2.6.10-rc3-1/net/ipv4/tcp_input.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv4/tcp_input.c 2004-12-16 06:20:05.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv4/tcp_input.c 2004-12-22 10:04:36.879196362 -0800 @@ -3028,8 +3028,8 @@ tp->snd_wscale = *(__u8 *)ptr; if(tp->snd_wscale > 14) { if(net_ratelimit()) - printk("tcp_parse_options: Illegal window " - "scaling value %d >14 received.", + printk(KERN_INFO "tcp_parse_options: Illegal window " + "scaling value %d >14 received.\n", tp->snd_wscale); tp->snd_wscale = 14; } Index: wli-2.6.10-rc3-1/net/ipv6/af_inet6.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv6/af_inet6.c 2004-12-16 06:20:05.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv6/af_inet6.c 2004-12-22 10:04:36.912191346 -0800 @@ -524,11 +524,33 @@ extern void ipv6_sysctl_unregister(void); #endif +/* Same as inet6_dgram_ops, sans udp_poll. */ +static struct proto_ops inet6_sockraw_ops = { + .family = PF_INET6, + .owner = THIS_MODULE, + .release = inet6_release, + .bind = inet6_bind, + .connect = inet_dgram_connect, /* ok */ + .socketpair = sock_no_socketpair, /* a do nothing */ + .accept = sock_no_accept, /* a do nothing */ + .getname = inet6_getname, + .poll = datagram_poll, /* ok */ + .ioctl = inet6_ioctl, /* must change */ + .listen = sock_no_listen, /* ok */ + .shutdown = inet_shutdown, /* ok */ + .setsockopt = sock_common_setsockopt, /* ok */ + .getsockopt = sock_common_getsockopt, /* ok */ + .sendmsg = inet_sendmsg, /* ok */ + .recvmsg = sock_common_recvmsg, /* ok */ + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +}; + static struct inet_protosw rawv6_protosw = { .type = SOCK_RAW, .protocol = IPPROTO_IP, /* wild card */ .prot = &rawv6_prot, - .ops = &inet6_dgram_ops, + .ops = &inet6_sockraw_ops, .capability = CAP_NET_RAW, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_REUSE, Index: wli-2.6.10-rc3-1/net/ipv6/datagram.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv6/datagram.c 2004-12-16 06:20:05.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv6/datagram.c 2004-12-22 10:04:36.915190890 -0800 @@ -427,9 +427,7 @@ int addr_type; struct net_device *dev = NULL; - if (cmsg->cmsg_len < sizeof(struct cmsghdr) || - (unsigned long)(((char*)cmsg - (char*)msg->msg_control) - + cmsg->cmsg_len) > msg->msg_controllen) { + if (!CMSG_OK(msg, cmsg)) { err = -EINVAL; goto exit_f; } Index: wli-2.6.10-rc3-1/net/ipv6/mcast.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv6/mcast.c 2004-12-16 06:20:05.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv6/mcast.c 2004-12-22 10:04:36.922189826 -0800 @@ -391,12 +391,12 @@ goto done; rv = !0; for (i=0; isl_count; i++) { - rv = memcmp(&psl->sl_addr, group, + rv = memcmp(&psl->sl_addr[i], source, sizeof(struct in6_addr)); - if (rv >= 0) + if (rv == 0) break; } - if (!rv) /* source not found */ + if (rv) /* source not found */ goto done; /* update the interface filter */ @@ -437,8 +437,8 @@ } rv = 1; /* > 0 for insert logic below if sl_count is 0 */ for (i=0; isl_count; i++) { - rv = memcmp(&psl->sl_addr, group, sizeof(struct in6_addr)); - if (rv >= 0) + rv = memcmp(&psl->sl_addr[i], source, sizeof(struct in6_addr)); + if (rv == 0) break; } if (rv == 0) /* address already there is an error */ Index: wli-2.6.10-rc3-1/net/ipv6/ndisc.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/ipv6/ndisc.c 2004-12-16 06:20:05.000000000 -0800 +++ wli-2.6.10-rc3-1/net/ipv6/ndisc.c 2004-12-22 10:04:36.928188914 -0800 @@ -943,7 +943,7 @@ } /* Don't accept RS if we're not in router mode */ - if (!idev->cnf.forwarding || idev->cnf.accept_ra) + if (!idev->cnf.forwarding) goto out; /* Index: wli-2.6.10-rc3-1/net/sched/act_api.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/sched/act_api.c 2004-12-16 06:20:05.000000000 -0800 +++ wli-2.6.10-rc3-1/net/sched/act_api.c 2004-12-22 10:04:36.932188306 -0800 @@ -418,6 +418,7 @@ int tcf_action_copy_stats (struct sk_buff *skb,struct tc_action *a) { + int err; struct gnet_dump d; struct tcf_act_hdr *h = a->priv; @@ -428,7 +429,14 @@ if (NULL == h) goto errout; - if (gnet_stats_start_copy(skb, TCA_ACT_STATS, h->stats_lock, &d) < 0) + if (a->type == TCA_OLD_COMPAT) + err = gnet_stats_start_copy_compat(skb, TCA_ACT_STATS, + TCA_STATS, TCA_XSTATS, h->stats_lock, &d); + else + err = gnet_stats_start_copy(skb, TCA_ACT_STATS, + h->stats_lock, &d); + + if (err < 0) goto errout; if (NULL != a->ops && NULL != a->ops->get_stats) Index: wli-2.6.10-rc3-1/net/sched/cls_tcindex.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/sched/cls_tcindex.c 2004-12-16 06:20:05.000000000 -0800 +++ wli-2.6.10-rc3-1/net/sched/cls_tcindex.c 2004-12-22 10:04:36.935187850 -0800 @@ -160,7 +160,8 @@ } -static int tcindex_delete(struct tcf_proto *tp, unsigned long arg) +static int +__tcindex_delete(struct tcf_proto *tp, unsigned long arg, int lock) { struct tcindex_data *p = PRIV(tp); struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg; @@ -182,9 +183,11 @@ found: f = *walk; - tcf_tree_lock(tp); + if (lock) + tcf_tree_lock(tp); *walk = f->next; - tcf_tree_unlock(tp); + if (lock) + tcf_tree_unlock(tp); } tcf_unbind_filter(tp, &r->res); #ifdef CONFIG_NET_CLS_POLICE @@ -195,6 +198,10 @@ return 0; } +static int tcindex_delete(struct tcf_proto *tp, unsigned long arg) +{ + return __tcindex_delete(tp, arg, 1); +} /* * There are no parameters for tcindex_init, so we overload tcindex_change @@ -384,7 +391,7 @@ static int tcindex_destroy_element(struct tcf_proto *tp, unsigned long arg, struct tcf_walker *walker) { - return tcindex_delete(tp,arg); + return __tcindex_delete(tp, arg, 0); } Index: wli-2.6.10-rc3-1/net/sched/ipt.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/sched/ipt.c 2004-12-16 06:20:05.000000000 -0800 +++ wli-2.6.10-rc3-1/net/sched/ipt.c 2004-12-22 10:04:36.937187546 -0800 @@ -63,8 +63,7 @@ target = __ipt_find_target_lock(t->u.user.name, &ret); if (!target) { - printk("init_targ: Failed to find %s\n", - t->u.kernel.target->name); + printk("init_targ: Failed to find %s\n", t->u.user.name); return -1; } Index: wli-2.6.10-rc3-1/net/sched/sch_netem.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/sched/sch_netem.c 2004-12-16 06:20:05.000000000 -0800 +++ wli-2.6.10-rc3-1/net/sched/sch_netem.c 2004-12-22 10:04:36.940187090 -0800 @@ -258,12 +258,13 @@ { struct Qdisc *sch = (struct Qdisc *)arg; struct netem_sched_data *q = qdisc_priv(sch); + struct net_device *dev = sch->dev; struct sk_buff *skb; psched_time_t now; pr_debug("netem_watchdog: fired @%lu\n", jiffies); - spin_lock_bh(&sch->dev->queue_lock); + spin_lock_bh(&dev->queue_lock); PSCHED_GET_TIME(now); while ((skb = skb_peek(&q->delayed)) != NULL) { @@ -286,7 +287,8 @@ else sch->q.qlen++; } - spin_unlock_bh(&sch->dev->queue_lock); + qdisc_run(dev); + spin_unlock_bh(&dev->queue_lock); } static void netem_reset(struct Qdisc *sch) Index: wli-2.6.10-rc3-1/net/sctp/socket.c =================================================================== --- wli-2.6.10-rc3-1.orig/net/sctp/socket.c 2004-12-16 06:20:06.000000000 -0800 +++ wli-2.6.10-rc3-1/net/sctp/socket.c 2004-12-22 10:04:36.954184962 -0800 @@ -4098,12 +4098,8 @@ for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR((struct msghdr*)msg, cmsg)) { - /* Check for minimum length. The SCM code has this check. */ - if (cmsg->cmsg_len < sizeof(struct cmsghdr) || - (unsigned long)(((char*)cmsg - (char*)msg->msg_control) - + cmsg->cmsg_len) > msg->msg_controllen) { + if (!CMSG_OK(msg, cmsg)) return -EINVAL; - } /* Should we parse this header or ignore? */ if (cmsg->cmsg_level != IPPROTO_SCTP) Index: wli-2.6.10-rc3-1/sound/core/init.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/core/init.c 2004-12-16 06:20:06.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/core/init.c 2004-12-22 10:04:36.958184354 -0800 @@ -785,12 +785,15 @@ int snd_card_pci_suspend(struct pci_dev *dev, u32 state) { snd_card_t *card = pci_get_drvdata(dev); + int err; if (! card || ! card->pm_suspend) return 0; if (card->power_state == SNDRV_CTL_POWER_D3hot) return 0; /* FIXME: correct state value? */ - return card->pm_suspend(card, 0); + err = card->pm_suspend(card, 0); + pci_save_state(dev); + return err; } int snd_card_pci_resume(struct pci_dev *dev) Index: wli-2.6.10-rc3-1/sound/core/pcm_native.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/core/pcm_native.c 2004-12-16 06:20:06.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/core/pcm_native.c 2004-12-22 10:04:36.969182682 -0800 @@ -3099,6 +3099,7 @@ area->vm_page_prot = pgprot_noncached(area->vm_page_prot); #endif area->vm_ops = &snd_pcm_vm_ops_data_mmio; + area->vm_private_data = substream; area->vm_flags |= VM_IO; size = area->vm_end - area->vm_start; offset = area->vm_pgoff << PAGE_SHIFT; Index: wli-2.6.10-rc3-1/sound/pci/ali5451/ali5451.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/ali5451/ali5451.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/ali5451/ali5451.c 2004-12-22 10:04:37.106161858 -0800 @@ -1932,6 +1932,7 @@ outl(0xffffffff, ALI_REG(chip, ALI_STOP)); spin_unlock_irq(&chip->reg_lock); + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -1986,6 +1987,7 @@ } if (codec->port) pci_release_regions(codec->pci); + pci_disable_device(codec->pci); #ifdef CONFIG_PM if (codec->image) kfree(codec->image); @@ -2093,11 +2095,14 @@ if (pci_set_dma_mask(pci, 0x7fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x7fffffff) < 0) { snd_printk("architecture does not support 31bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } - if ((codec = kcalloc(1, sizeof(*codec), GFP_KERNEL)) == NULL) + if ((codec = kcalloc(1, sizeof(*codec), GFP_KERNEL)) == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&codec->reg_lock); spin_lock_init(&codec->voice_alloc); Index: wli-2.6.10-rc3-1/sound/pci/als4000.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/als4000.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/als4000.c 2004-12-22 10:04:36.973182074 -0800 @@ -582,6 +582,7 @@ } #endif pci_release_regions(acard->pci); + pci_disable_device(acard->pci); } static int __devinit snd_card_als4000_probe(struct pci_dev *pci, @@ -612,11 +613,14 @@ if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { snd_printk("architecture does not support 24bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } - if ((err = pci_request_regions(pci, "ALS4000")) < 0) + if ((err = pci_request_regions(pci, "ALS4000")) < 0) { + pci_disable_device(pci); return err; + } gcr = pci_resource_start(pci, 0); pci_read_config_word(pci, PCI_COMMAND, &word); @@ -627,6 +631,7 @@ sizeof( snd_card_als4000_t ) ); if (card == NULL) { pci_release_regions(pci); + pci_disable_device(pci); return -ENOMEM; } Index: wli-2.6.10-rc3-1/sound/pci/atiixp.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/atiixp.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/atiixp.c 2004-12-22 10:04:36.979181162 -0800 @@ -1420,6 +1420,7 @@ pci_enable_device(chip->pci); pci_set_power_state(chip->pci, 0); + pci_set_master(chip->pci); snd_atiixp_aclink_reset(chip); snd_atiixp_chip_start(chip); @@ -1473,6 +1474,7 @@ if (chip->remap_addr) iounmap(chip->remap_addr); pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -1500,8 +1502,10 @@ return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); spin_lock_init(&chip->ac97_lock); @@ -1510,6 +1514,7 @@ chip->pci = pci; chip->irq = -1; if ((err = pci_request_regions(pci, "ATI IXP AC97")) < 0) { + pci_disable_device(pci); kfree(chip); return err; } Index: wli-2.6.10-rc3-1/sound/pci/atiixp_modem.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/atiixp_modem.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/atiixp_modem.c 2004-12-22 10:04:36.984180402 -0800 @@ -1142,6 +1142,7 @@ pci_enable_device(chip->pci); pci_set_power_state(chip->pci, 0); + pci_set_master(chip->pci); snd_atiixp_aclink_reset(chip); snd_atiixp_chip_start(chip); @@ -1195,6 +1196,7 @@ if (chip->remap_addr) iounmap(chip->remap_addr); pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -1222,8 +1224,10 @@ return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); spin_lock_init(&chip->ac97_lock); @@ -1233,6 +1237,7 @@ chip->irq = -1; if ((err = pci_request_regions(pci, "ATI IXP MC97")) < 0) { kfree(chip); + pci_disable_device(pci); return err; } chip->addr = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/azt3328.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/azt3328.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/azt3328.c 2004-12-22 10:04:36.990179490 -0800 @@ -1268,6 +1268,7 @@ if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; @@ -1317,8 +1318,10 @@ return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); chip->card = card; chip->pci = pci; @@ -1328,11 +1331,13 @@ if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { snd_printk("architecture does not support 24bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } if ((err = pci_request_regions(pci, "Aztech AZF3328")) < 0) { kfree(chip); + pci_disable_device(pci); return err; } Index: wli-2.6.10-rc3-1/sound/pci/bt87x.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/bt87x.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/bt87x.c 2004-12-22 10:04:36.994178882 -0800 @@ -648,6 +648,7 @@ if (chip->irq >= 0) free_irq(chip->irq, chip); pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -693,8 +694,10 @@ return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (!chip) + if (!chip) { + pci_disable_device(pci); return -ENOMEM; + } chip->card = card; chip->pci = pci; chip->irq = -1; @@ -702,6 +705,7 @@ if ((err = pci_request_regions(pci, "Bt87x audio")) < 0) { kfree(chip); + pci_disable_device(pci); return err; } chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), Index: wli-2.6.10-rc3-1/sound/pci/cmipci.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/cmipci.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/cmipci.c 2004-12-22 10:04:37.004177362 -0800 @@ -2550,6 +2550,7 @@ } #endif pci_release_regions(cm->pci); + pci_disable_device(cm->pci); kfree(cm); return 0; } @@ -2583,8 +2584,10 @@ return err; cm = kcalloc(1, sizeof(*cm), GFP_KERNEL); - if (cm == NULL) + if (cm == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&cm->reg_lock); init_MUTEX(&cm->open_mutex); @@ -2598,6 +2601,7 @@ if ((err = pci_request_regions(pci, card->driver)) < 0) { kfree(cm); + pci_disable_device(pci); return err; } cm->iobase = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/cs4281.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/cs4281.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/cs4281.c 2004-12-22 10:04:37.012176146 -0800 @@ -1362,6 +1362,7 @@ if (chip->ba1) iounmap(chip->ba1); pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; @@ -1395,8 +1396,10 @@ if ((err = pci_enable_device(pci)) < 0) return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); chip->card = card; chip->pci = pci; @@ -1410,6 +1413,7 @@ if ((err = pci_request_regions(pci, "CS4281")) < 0) { kfree(chip); + pci_disable_device(pci); return err; } chip->ba0_addr = pci_resource_start(pci, 0); @@ -2074,6 +2078,7 @@ ulCLK &= ~CLKCR1_CKRA; snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -2085,6 +2090,7 @@ u32 ulCLK; pci_enable_device(chip->pci); + pci_set_master(chip->pci); ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); ulCLK |= CLKCR1_CKRA; Index: wli-2.6.10-rc3-1/sound/pci/cs46xx/cs46xx_lib.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/cs46xx/cs46xx_lib.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/cs46xx/cs46xx_lib.c 2004-12-22 10:04:37.118160034 -0800 @@ -2885,6 +2885,7 @@ } #endif + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -3678,6 +3679,7 @@ /* disable CLKRUN */ chip->active_ctrl(chip, -chip->amplifier); chip->amplifier = amp_saved; /* restore the status */ + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -3688,6 +3690,7 @@ int amp_saved; pci_enable_device(chip->pci); + pci_set_master(chip->pci); amp_saved = chip->amplifier; chip->amplifier = 0; chip->active_ctrl(chip, 1); /* force to on */ @@ -3744,8 +3747,10 @@ return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); #ifdef CONFIG_SND_CS46XX_NEW_DSP init_MUTEX(&chip->spos_mutex); Index: wli-2.6.10-rc3-1/sound/pci/emu10k1/emu10k1_main.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/emu10k1/emu10k1_main.c 2004-12-22 09:07:10.578113762 -0800 +++ wli-2.6.10-rc3-1/sound/pci/emu10k1/emu10k1_main.c 2004-12-22 10:04:37.122159426 -0800 @@ -561,6 +561,7 @@ free_irq(emu->irq, (void *)emu); if (emu->port) pci_release_regions(emu->pci); + pci_disable_device(emu->pci); kfree(emu); return 0; } @@ -596,14 +597,17 @@ return err; emu = kcalloc(1, sizeof(*emu), GFP_KERNEL); - if (emu == NULL) + if (emu == NULL) { + pci_disable_device(pci); return -ENOMEM; + } /* set the DMA transfer mask */ emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK; if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask); kfree(emu); + pci_disable_device(pci); return -ENXIO; } emu->card = card; @@ -629,6 +633,7 @@ if ((err = pci_request_regions(pci, "EMU10K1")) < 0) { kfree(emu); + pci_disable_device(pci); return err; } emu->port = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/ens1370.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/ens1370.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/ens1370.c 2004-12-22 10:04:37.021174778 -0800 @@ -1839,6 +1839,7 @@ if (ensoniq->irq >= 0) free_irq(ensoniq->irq, (void *)ensoniq); pci_release_regions(ensoniq->pci); + pci_disable_device(ensoniq->pci); kfree(ensoniq); return 0; } @@ -1893,8 +1894,10 @@ if ((err = pci_enable_device(pci)) < 0) return err; ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL); - if (ensoniq == NULL) + if (ensoniq == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&ensoniq->reg_lock); init_MUTEX(&ensoniq->src_mutex); ensoniq->card = card; @@ -1902,6 +1905,7 @@ ensoniq->irq = -1; if ((err = pci_request_regions(pci, "Ensoniq AudioPCI")) < 0) { kfree(ensoniq); + pci_disable_device(pci); return err; } ensoniq->port = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/es1938.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/es1938.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/es1938.c 2004-12-22 10:04:37.028173714 -0800 @@ -1394,6 +1394,7 @@ outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */ + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -1432,6 +1433,7 @@ if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -1461,18 +1463,22 @@ if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { snd_printk("architecture does not support 24bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); spin_lock_init(&chip->mixer_lock); chip->card = card; chip->pci = pci; if ((err = pci_request_regions(pci, "ESS Solo-1")) < 0) { kfree(chip); + pci_disable_device(pci); return err; } chip->io_port = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/es1968.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/es1968.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/es1968.c 2004-12-22 10:04:37.037172346 -0800 @@ -2411,6 +2411,7 @@ snd_ac97_suspend(chip->ac97); snd_es1968_bob_stop(chip); snd_es1968_set_acpi(chip, ACPI_D3); + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -2424,6 +2425,7 @@ /* restore all our config */ pci_enable_device(chip->pci); + pci_set_master(chip->pci); snd_es1968_chip_init(chip); /* need to restore the base pointers.. */ @@ -2467,6 +2469,7 @@ chip->master_switch = NULL; chip->master_volume = NULL; pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -2518,12 +2521,15 @@ if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { snd_printk("architecture does not support 28bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (! chip) + if (! chip) { + pci_disable_device(pci); return -ENOMEM; + } /* Set Vars */ chip->type = chip_type; @@ -2543,6 +2549,7 @@ if ((err = pci_request_regions(pci, "ESS Maestro")) < 0) { kfree(chip); + pci_disable_device(pci); return err; } chip->io_port = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/fm801.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/fm801.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/fm801.c 2004-12-22 10:04:37.043171434 -0800 @@ -1234,6 +1234,7 @@ if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; @@ -1263,14 +1264,17 @@ if ((err = pci_enable_device(pci)) < 0) return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); chip->card = card; chip->pci = pci; chip->irq = -1; if ((err = pci_request_regions(pci, "FM801")) < 0) { kfree(chip); + pci_disable_device(pci); return err; } chip->port = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/ice1712/ice1712.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/ice1712/ice1712.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/ice1712/ice1712.c 2004-12-22 10:04:37.131158058 -0800 @@ -2495,6 +2495,7 @@ if (ice->port) pci_release_regions(ice->pci); snd_ice1712_akm4xxx_free(ice); + pci_disable_device(ice->pci); kfree(ice); return 0; } @@ -2527,12 +2528,15 @@ if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { snd_printk("architecture does not support 28bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } ice = kcalloc(1, sizeof(*ice), GFP_KERNEL); - if (ice == NULL) + if (ice == NULL) { + pci_disable_device(pci); return -ENOMEM; + } ice->omni = omni ? 1 : 0; if (cs8427_timeout < 1) cs8427_timeout = 1; @@ -2562,6 +2566,7 @@ if ((err = pci_request_regions(pci, "ICE1712")) < 0) { kfree(ice); + pci_disable_device(pci); return err; } ice->port = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/ice1712/ice1724.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/ice1712/ice1724.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/ice1712/ice1724.c 2004-12-22 10:04:37.140156690 -0800 @@ -2076,6 +2076,7 @@ } pci_release_regions(ice->pci); snd_ice1712_akm4xxx_free(ice); + pci_disable_device(ice->pci); kfree(ice); return 0; } @@ -2105,8 +2106,10 @@ return err; ice = kcalloc(1, sizeof(*ice), GFP_KERNEL); - if (ice == NULL) + if (ice == NULL) { + pci_disable_device(pci); return -ENOMEM; + } ice->vt1724 = 1; spin_lock_init(&ice->reg_lock); init_MUTEX(&ice->gpio_mutex); @@ -2124,6 +2127,7 @@ if ((err = pci_request_regions(pci, "ICE1724")) < 0) { kfree(ice); + pci_disable_device(pci); return err; } ice->port = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/intel8x0.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/intel8x0.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/intel8x0.c 2004-12-22 10:04:37.052170066 -0800 @@ -1020,7 +1020,9 @@ */ if (cnt & ICH_PCM_246_MASK) { iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_PCM_246_MASK); + spin_unlock_irq(&chip->reg_lock); msleep(50); /* grrr... */ + spin_lock_irq(&chip->reg_lock); } } else if (chip->device_type == DEVICE_INTEL_ICH4) { if (runtime->sample_bits > 16) @@ -2261,6 +2263,7 @@ if (chip->remap_bmaddr) iounmap(chip->remap_bmaddr); pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -2279,6 +2282,7 @@ for (i = 0; i < 3; i++) if (chip->ac97[i]) snd_ac97_suspend(chip->ac97[i]); + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -2496,8 +2500,10 @@ return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); spin_lock_init(&chip->ac97_lock); chip->device_type = device_type; @@ -2517,6 +2523,7 @@ if ((err = pci_request_regions(pci, card->shortname)) < 0) { kfree(chip); + pci_disable_device(pci); return err; } Index: wli-2.6.10-rc3-1/sound/pci/intel8x0m.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/intel8x0m.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/intel8x0m.c 2004-12-22 10:04:37.058169154 -0800 @@ -1074,6 +1074,7 @@ if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -1091,6 +1092,7 @@ snd_pcm_suspend_all(chip->pcm[i]); if (chip->ac97) snd_ac97_suspend(chip->ac97); + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -1172,8 +1174,10 @@ return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); spin_lock_init(&chip->ac97_lock); chip->device_type = device_type; @@ -1183,6 +1187,7 @@ if ((err = pci_request_regions(pci, card->shortname)) < 0) { kfree(chip); + pci_disable_device(pci); return err; } Index: wli-2.6.10-rc3-1/sound/pci/korg1212/korg1212.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/korg1212/korg1212.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/korg1212/korg1212.c 2004-12-22 10:04:37.152154866 -0800 @@ -2179,6 +2179,7 @@ korg1212->dma_shared.area = NULL; } + pci_disable_device(korg1212->pci); kfree(korg1212); return 0; } @@ -2210,8 +2211,10 @@ return err; korg1212 = kcalloc(1, sizeof(*korg1212), GFP_KERNEL); - if (korg1212 == NULL) + if (korg1212 == NULL) { + pci_disable_device(pci); return -ENOMEM; + } korg1212->card = card; korg1212->pci = pci; @@ -2244,6 +2247,7 @@ if ((err = pci_request_regions(pci, "korg1212")) < 0) { kfree(korg1212); + pci_disable_device(pci); return err; } @@ -2270,6 +2274,7 @@ if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) { snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem, korg1212->iomem + iomem_size - 1); + snd_korg1212_free(korg1212); return -EBUSY; } @@ -2279,6 +2284,7 @@ if (err) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + snd_korg1212_free(korg1212); return -EBUSY; } @@ -2326,6 +2332,7 @@ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) { snd_printk(KERN_ERR "can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer)); + snd_korg1212_free(korg1212); return -ENOMEM; } korg1212->sharedBufferPtr = (KorgSharedBuffer *)korg1212->dma_shared.area; @@ -2342,6 +2349,7 @@ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), korg1212->DataBufsSize, &korg1212->dma_play) < 0) { snd_printk(KERN_ERR "can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize); + snd_korg1212_free(korg1212); return -ENOMEM; } korg1212->playDataBufsPtr = (KorgAudioBuffer *)korg1212->dma_play.area; @@ -2355,6 +2363,7 @@ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), korg1212->DataBufsSize, &korg1212->dma_rec) < 0) { snd_printk(KERN_ERR "can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize); + snd_korg1212_free(korg1212); return -ENOMEM; } korg1212->recordDataBufsPtr = (KorgAudioBuffer *)korg1212->dma_rec.area; @@ -2386,6 +2395,7 @@ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) { snd_printk(KERN_ERR "can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize); + snd_korg1212_free(korg1212); return -ENOMEM; } @@ -2405,8 +2415,10 @@ mdelay(CARD_BOOT_DELAY_IN_MS); - if (snd_korg1212_downloadDSPCode(korg1212)) + if (snd_korg1212_downloadDSPCode(korg1212)) { + snd_korg1212_free(korg1212); return -EBUSY; + } printk(KERN_INFO "dspMemPhy = %08x U[%08x]\n" "PlayDataPhy = %08x L[%08x]\n" @@ -2421,8 +2433,10 @@ korg1212->RoutingTablePhy, LowerWordSwap(korg1212->RoutingTablePhy), korg1212->AdatTimeCodePhy, LowerWordSwap(korg1212->AdatTimeCodePhy)); - if ((err = snd_pcm_new(korg1212->card, "korg1212", 0, 1, 1, &korg1212->pcm)) < 0) + if ((err = snd_pcm_new(korg1212->card, "korg1212", 0, 1, 1, &korg1212->pcm)) < 0) { + snd_korg1212_free(korg1212); return err; + } korg1212->pcm->private_data = korg1212; korg1212->pcm->private_free = snd_korg1212_free_pcm; @@ -2439,8 +2453,10 @@ for (i = 0; i < ARRAY_SIZE(snd_korg1212_controls); i++) { err = snd_ctl_add(korg1212->card, snd_ctl_new1(&snd_korg1212_controls[i], korg1212)); - if (err < 0) + if (err < 0) { + snd_korg1212_free(korg1212); return err; + } } snd_korg1212_proc_init(korg1212); Index: wli-2.6.10-rc3-1/sound/pci/maestro3.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/maestro3.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/maestro3.c 2004-12-22 10:04:37.068167634 -0800 @@ -2386,6 +2386,7 @@ if (chip->iobase) pci_release_regions(chip->pci); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -2422,6 +2423,8 @@ /* power down apci registers */ snd_m3_outw(chip, 0xffff, 0x54); snd_m3_outw(chip, 0xffff, 0x56); + + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -2434,6 +2437,7 @@ if (chip->suspend_mem == NULL) return 0; + pci_enable_device(chip->pci); pci_set_master(chip->pci); /* first lets just bring everything back. .*/ @@ -2502,12 +2506,15 @@ if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { snd_printk("architecture does not support 28bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&chip->reg_lock); switch (pci->device) { @@ -2549,6 +2556,7 @@ chip->substreams = kmalloc(sizeof(m3_dma_t) * chip->num_substreams, GFP_KERNEL); if (chip->substreams == NULL) { kfree(chip); + pci_disable_device(pci); return -ENOMEM; } memset(chip->substreams, 0, sizeof(m3_dma_t) * chip->num_substreams); Index: wli-2.6.10-rc3-1/sound/pci/mixart/mixart.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/mixart/mixart.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/mixart/mixart.c 2004-12-22 10:04:37.158153954 -0800 @@ -1092,6 +1092,7 @@ mgr->bufferinfo.area = NULL; } + pci_disable_device(mgr->pci); kfree(mgr); return 0; } @@ -1292,14 +1293,17 @@ /* check if we can restrict PCI DMA transfers to 32 bits */ if (pci_set_dma_mask(pci, 0xffffffff) < 0) { snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } /* */ mgr = kcalloc(1, sizeof(*mgr), GFP_KERNEL); - if (! mgr) + if (! mgr) { + pci_disable_device(pci); return -ENOMEM; + } mgr->pci = pci; mgr->irq = -1; @@ -1307,6 +1311,7 @@ /* resource assignment */ if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { kfree(mgr); + pci_disable_device(pci); return err; } for (i = 0; i < 2; i++) { Index: wli-2.6.10-rc3-1/sound/pci/nm256/nm256.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/nm256/nm256.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/nm256/nm256.c 2004-12-22 10:04:37.164153042 -0800 @@ -1274,6 +1274,7 @@ snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); chip->coeffs_current = 0; + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -1319,6 +1320,7 @@ if (chip->irq >= 0) free_irq(chip->irq, (void*)chip); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -1346,9 +1348,14 @@ *chip_ret = NULL; + if ((err = pci_enable_device(pci)) < 0) + return err; + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } chip->card = card; chip->pci = pci; @@ -1535,9 +1542,6 @@ struct nm256_quirk *q; u16 subsystem_vendor, subsystem_device; - if ((err = pci_enable_device(pci)) < 0) - return err; - if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { Index: wli-2.6.10-rc3-1/sound/pci/rme32.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/rme32.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/rme32.c 2004-12-22 10:04:37.075166570 -0800 @@ -1350,6 +1350,7 @@ pci_release_regions(rme32->pci); rme32->port = 0; } + pci_disable_device(rme32->pci); } static void snd_rme32_free_spdif_pcm(snd_pcm_t * pcm) Index: wli-2.6.10-rc3-1/sound/pci/rme96.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/rme96.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/rme96.c 2004-12-22 10:04:37.083165354 -0800 @@ -1553,6 +1553,7 @@ pci_release_regions(rme96->pci); rme96->port = 0; } + pci_disable_device(rme96->pci); } static void Index: wli-2.6.10-rc3-1/sound/pci/rme9652/hdsp.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/rme9652/hdsp.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/rme9652/hdsp.c 2004-12-22 10:04:37.180150610 -0800 @@ -5060,6 +5060,7 @@ if (hdsp->port) pci_release_regions(hdsp->pci); + pci_disable_device(hdsp->pci); return 0; } Index: wli-2.6.10-rc3-1/sound/pci/rme9652/rme9652.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/rme9652/rme9652.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/rme9652/rme9652.c 2004-12-22 10:04:37.189149242 -0800 @@ -1812,6 +1812,7 @@ if (rme9652->port) pci_release_regions(rme9652->pci); + pci_disable_device(rme9652->pci); return 0; } Index: wli-2.6.10-rc3-1/sound/pci/sonicvibes.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/sonicvibes.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/sonicvibes.c 2004-12-22 10:04:37.089164442 -0800 @@ -1185,6 +1185,7 @@ kfree_nocheck(sonic->res_dmac); } pci_release_regions(sonic->pci); + pci_disable_device(sonic->pci); kfree(sonic); return 0; } @@ -1216,12 +1217,15 @@ if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { snd_printk("architecture does not support 24bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } sonic = kcalloc(1, sizeof(*sonic), GFP_KERNEL); - if (sonic == NULL) + if (sonic == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&sonic->reg_lock); sonic->card = card; sonic->pci = pci; @@ -1229,6 +1233,7 @@ if ((err = pci_request_regions(pci, "S3 SonicVibes")) < 0) { kfree(sonic); + pci_disable_device(pci); return err; } Index: wli-2.6.10-rc3-1/sound/pci/trident/trident_main.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/trident/trident_main.c 2004-12-22 09:07:10.594111330 -0800 +++ wli-2.6.10-rc3-1/sound/pci/trident/trident_main.c 2004-12-22 10:04:37.202147266 -0800 @@ -3537,12 +3537,15 @@ if (pci_set_dma_mask(pci, 0x3fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x3fffffff) < 0) { snd_printk("architecture does not support 30bit PCI busmaster DMA\n"); + pci_disable_device(pci); return -ENXIO; } trident = kcalloc(1, sizeof(*trident), GFP_KERNEL); - if (trident == NULL) + if (trident == NULL) { + pci_disable_device(pci); return -ENOMEM; + } trident->device = (pci->vendor << 16) | pci->device; trident->card = card; trident->pci = pci; @@ -3564,6 +3567,7 @@ if ((err = pci_request_regions(pci, "Trident Audio")) < 0) { kfree(trident); + pci_disable_device(pci); return err; } trident->port = pci_resource_start(pci, 0); @@ -3682,6 +3686,7 @@ if (trident->irq >= 0) free_irq(trident->irq, (void *)trident); pci_release_regions(trident->pci); + pci_disable_device(trident->pci); kfree(trident); return 0; } @@ -3949,6 +3954,7 @@ case TRIDENT_DEVICE_ID_SI7018: break; } + pci_disable_device(trident->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } Index: wli-2.6.10-rc3-1/sound/pci/via82xx.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/via82xx.c 2004-12-16 06:20:08.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/via82xx.c 2004-12-22 10:04:37.098163074 -0800 @@ -1980,6 +1980,7 @@ pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy); pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg); } + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -2006,8 +2007,10 @@ if ((err = pci_enable_device(pci)) < 0) return err; - if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL) + if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL) { + pci_disable_device(pci); return -ENOMEM; + } chip->chip_type = chip_type; chip->revision = revision; @@ -2025,6 +2028,7 @@ if ((err = pci_request_regions(pci, card->driver)) < 0) { kfree(chip); + pci_disable_device(pci); return err; } chip->port = pci_resource_start(pci, 0); Index: wli-2.6.10-rc3-1/sound/pci/vx222/vx222.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/vx222/vx222.c 2004-12-16 06:20:09.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/vx222/vx222.c 2004-12-22 10:04:37.205146810 -0800 @@ -116,6 +116,7 @@ free_irq(chip->irq, (void*)chip); if (vx->port[0]) pci_release_regions(vx->pci); + pci_disable_device(vx->pci); kfree(chip); return 0; } @@ -147,8 +148,10 @@ vx_ops = hw->type == VX_TYPE_BOARD ? &vx222_old_ops : &vx222_ops; chip = snd_vx_create(card, hw, vx_ops, sizeof(struct snd_vx222) - sizeof(vx_core_t)); - if (! chip) + if (! chip) { + pci_disable_device(pci); return -ENOMEM; + } vx = (struct snd_vx222 *)chip; vx->pci = pci; Index: wli-2.6.10-rc3-1/sound/pci/ymfpci/ymfpci_main.c =================================================================== --- wli-2.6.10-rc3-1.orig/sound/pci/ymfpci/ymfpci_main.c 2004-12-16 06:20:09.000000000 -0800 +++ wli-2.6.10-rc3-1/sound/pci/ymfpci/ymfpci_main.c 2004-12-22 10:04:37.213145594 -0800 @@ -2098,6 +2098,7 @@ pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -2153,6 +2154,7 @@ chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE); snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); snd_ymfpci_disable_dsp(chip); + pci_disable_device(chip->pci); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -2204,8 +2206,10 @@ return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } chip->old_legacy_ctrl = old_legacy_ctrl; spin_lock_init(&chip->reg_lock); spin_lock_init(&chip->voice_lock);