S: USA
N: Patrick Mochel
-E: mochel@transmeta.com
+E: pat@osdl.org
+E: mochelp@infinity.powertie.org
D: PCI Power Management, ACPI work
-S: 3940 Freedom Circle
-S: Santa Clara, CA 95054
+S: 15275 SW Koll Parkway, Suite H
+S: Beaverton, OR 97006
S: USA
N: Eberhard Moenkeberg
The module will be called se401.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
-USB ADMtek Pegasus-based ethernet device support
+Pegasus/Pegasus II based USB-Ethernet device support
CONFIG_USB_PEGASUS
- Say Y if you want to use your USB ethernet device. Supported
- cards until now are:
- ADMtek AN986 Pegasus (eval. board)
- ADMtek ADM8511 Pegasus II (eval. board)
- Accton 10/100
- Billington USB-100
- Corega FEter USB-TX
- MELCO/BUFFALO LUA-TX
- D-Link DSB-650TX, DSB-650TX-PNA, DSB-650, DU-E10, DU-E100
- Linksys USB100TX, USB10TX
- LANEED Ethernet LD-USB/TX
- SMC 202
- SOHOware NUB Ethernet
-
- Any Pegasus II based board also are supported.
- If you have devices with vendor IDs other than noted above
- you should add them in the driver code and send a message
- to me (petkan@dce.bg) for update.
+ Say Y here if you know you have Pegasus or Pegasus II based adapter.
+ If in doubt then look at linux/drivers/usb/pegasus.h for the complete
+ list of supported devices.
+ If your particular adapter is not in the list and you are _sure_ it
+ is Pegasus or Pegasus II based then send me (pmanolov@lnxw.com) vendor
+ and device IDs.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
- Version 2.2.9 for Linux 2.2.17
- Version 2.4.9 for Linux 2.4.0
+ Version 2.2.11 for Linux 2.2.19
+ Version 2.4.11 for Linux 2.4.12
PRODUCTION RELEASE
- 7 September 2000
+ 11 October 2001
Leonard N. Zubkoff
Dandelion Digital
lnz@dandelion.com
- Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com>
+ Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
INTRODUCTION
controllers. Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont,
California 94555, USA and can be reached at 510.796.6100 or on the World Wide
Web at http://www.mylex.com. Mylex Technical Support can be reached by
-electronic mail at support@mylex.com, by voice at 510.608.2400, or by FAX at
+electronic mail at mylexsup@us.ibm.com, by voice at 510.608.2400, or by FAX at
510.745.7715. Contact information for offices in Europe and Japan is available
on their Web site.
100MHz Intel i960RM RISC Processor
16MB/32MB/64MB ECC SDRAM Memory
-AcceleRAID 160
+AcceleRAID 160 (AcceleRAID 170LP)
1 Wide Ultra-160 LVD SCSI channel
100MHz Intel i960RS RISC Processor
Built in 16M ECC SDRAM Memory
Intel i960 RISC Processor
2MB/4MB/8MB/16MB/32MB DRAM Memory
+DAC960P 1/2/3 Wide Fast SCSI-2 Channels
+ Intel i960 RISC Processor
+ 2MB/4MB/8MB/16MB/32MB DRAM Memory
+
For the eXtremeRAID 2000/3000 and AcceleRAID 352/170/160, firmware version
6.00-01 or above is required.
For the DAC960PJ and DAC960PG, firmware version 4.06-0-00 or above is required.
-For the DAC960PU, DAC960PD, and DAC960PL, firmware version 3.51-0-04 or above
-is required.
-
-Note that earlier revisions of the DAC960PU, DAC960PD, and DAC960PL controllers
-were delivered with version 2.xx firmware. Version 2.xx firmware is not
-supported by this driver and no support is envisioned. Contact Mylex RAID
-Technical Support to inquire about upgrading controllers with version 2.xx
-firmware to version 3.51-0-04. Upgrading to version 3.xx firmware requires
-installation of higher capacity Flash ROM chips, and not all DAC960PD and
-DAC960PL controllers can be upgraded.
+For the DAC960PU, DAC960PD, DAC960PL, and DAC960P, either firmware version
+3.51-0-04 or above is required (for dual Flash ROM controllers), or firmware
+version 2.73-0-00 or above is required (for single Flash ROM controllers)
Please note that not all SCSI disk drives are suitable for use with DAC960
controllers, and only particular firmware versions of any given model may
actually function correctly. Similarly, not all motherboards have a BIOS that
properly initializes the AcceleRAID 250, AcceleRAID 200, AcceleRAID 150,
DAC960PJ, and DAC960PG because the Intel i960RD/RP is a multi-function device.
-If in doubt, contact Mylex RAID Technical Support (support@mylex.com) to verify
-compatibility. Mylex makes available a hard disk compatibility list by FTP at
-ftp://ftp.mylex.com/pub/dac960/diskcomp.html.
+If in doubt, contact Mylex RAID Technical Support (mylexsup@us.ibm.com) to
+verify compatibility. Mylex makes available a hard disk compatibility list at
+http://www.mylex.com/support/hdcomp/hd-lists.html.
DRIVER INSTALLATION
-This distribution was prepared for Linux kernel version 2.2.17 or 2.4.0.
+This distribution was prepared for Linux kernel version 2.2.19 or 2.4.12.
To install the DAC960 RAID driver, you may use the following commands,
replacing "/usr/src" with wherever you keep your Linux kernel source tree:
cd /usr/src
- tar -xvzf DAC960-2.2.9.tar.gz (or DAC960-2.4.9.tar.gz)
+ tar -xvzf DAC960-2.2.11.tar.gz (or DAC960-2.4.11.tar.gz)
mv README.DAC960 linux/Documentation
mv DAC960.[ch] linux/drivers/block
patch -p0 < DAC960.patch (if DAC960.patch is included)
The "make-online" command changes the physical drive <channel>:<target-id>
from status DEAD to status ONLINE. In cases where multiple physical drives
- have been killed simultaneously, this command may be used to bring them
- back online, after which a consistency check is advisable.
+ have been killed simultaneously, this command may be used to bring all but
+ one of them back online, after which a rebuild to the final drive is
+ necessary.
Warning: make-online should only be used on a dead physical drive that is
- an active part of a drive group, never on a standby drive.
+ an active part of a drive group, never on a standby drive. The command
+ should never be used on a dead drive that is part of a critical logical
+ drive; rebuild should be used if only a single drive is dead.
make-standby <channel>:<target-id>
-EILSEQ CRC mismatch
USB_ST_STALL
--EPIPE a) babble detect
- b) endpoint stalled
+-EPIPE endpoint stalled
USB_ST_BUFFEROVERRUN
-ECOMM During an IN transfer, the host controller
USB_ST_DATAOVERRUN
-EOVERFLOW The amount of data returned by the endpoint was
greater than either the max packet size of the
- endpoint or the remaining buffer size
+ endpoint or the remaining buffer size. "Babble".
USB_ST_DATAUNDERRUN
-EREMOTEIO The endpoint returned less than max packet size
size
Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
'vga', for an image size of resp. 128x96, 160x120, 176x144,
- 320x240, 352x288 and 640x480 (of course, only for those cameras that support these resolutions).
+ 320x240, 352x288 and 640x480 (of course, only for those cameras that
+ support these resolutions).
fps
Specifies the desired framerate. Is an integer in the range of 4-30.
-palette
- Specifies the desired colour order that should be delivered by read() and
- mmap(). The string can be one of yuv420 or yuv420p; however, yuv420 will
- be phased out, leaving only yuv420p, so this option will disappear
- entirely.
-
- Only the native yuv420/yuv420p format is supported by the in kernel driver.
- If you want to use other formats with in-kernel conversion download the
- driver from the URL given. [Alan]
-
fbufs
This paramter specifies the number of internal buffers to use for storing
frames from the cam. This will help if the process that reads images from
The compression parameter only applies to the Vesta & ToUCam cameras.
The 645 and 646 have fixed compression parameters.
+leds
+ This settings takes 2 integers, that define the on/off time for the LED
+ (in milliseconds). One of the interesting things that you can do with
+ this is let the LED blink while the camera is in use. This:
+
+ leds=500,500
+
+ will blink the LED once every second. But with:
+
+ leds=0,0
+
+ the LED never goes on, making it suitable for silent survaillance.
+
+ By default the camera's LED is on solid while in use, and turned off
+ when the camera is not used anymore.
+
+ This parameter works only with the ToUCam range of cameras (730, 740,
+ 750). For other cameras this command is silently ignored, and the LED
+ cannot be controlled.
+
trace
In order to better detect problems, it is now possible to turn on a
'trace' of some of the calls the module makes; it logs all items in your
bttv.o
- card=0 - *** UNKNOWN ***
+ card=0 - *** UNKNOWN/GENERIC ***
card=1 - MIRO PCTV
- card=2 - Hauppauge old
+ card=2 - Hauppauge (bt848)
card=3 - STB
card=4 - Intel
card=5 - Diamond DTV2000
card=6 - AVerMedia TVPhone
card=7 - MATRIX-Vision MV-Delta
- card=8 - Fly Video II
+ card=8 - Fly Video II (Bt848)
card=9 - TurboTV
- card=10 - Hauppauge new (bt878)
+ card=10 - Hauppauge (bt878)
card=11 - MIRO PCTV pro
card=12 - ADS Technologies Channel Surfer TV
card=13 - AVerMedia TVCapture 98
card=21 - Lucky Star Image World ConferenceTV
card=22 - Phoebe Tv Master + FM
card=23 - Modular Technology MM205 PCTV, bt878
- card=24 - Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)
+ card=24 - [many vendors] CPH05X/06X (bt878)
card=25 - Terratec/Vobis TV-Boostar
card=26 - Newer Hauppauge WinCam (bt878)
card=27 - MAXI TV Video PCI2
card=32 - Intel Create and Share PCI
card=33 - Terratec TerraTValue
card=34 - Leadtek WinFast 2000
- card=35 - Chronos Video Shuttle II
- card=36 - Typhoon TView TV/FM Tuner
+ card=35 - Flyvideo 98 (LR50Q) / Chronos Video Shuttle II
+ card=36 - Flyvideo 98FM (LR50Q) / Typhoon TView TV/FM Tuner
card=37 - PixelView PlayTV pro
- card=38 - TView99 CPH063
+ card=38 - TView99 CPH06X
card=39 - Pinnacle PCTV Studio/Rave
card=40 - STB2
card=41 - AVerMedia TVPhone 98
card=47 - Terratec TV/Radio+
card=48 - Dynalink Magic TView
card=49 - GV-BCTV3
- card=50 - Prolink PV-BT878P+4E (PixelView PlayTV PAK)
+ card=50 - Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP
card=51 - Eagle Wireless Capricorn2 (bt878A)
card=52 - Pinnacle PCTV Studio Pro
- card=53 - Typhoon TView RDS / FM Stereo
- card=54 - Lifetec LT 9415 TV
+ card=53 - Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS
+ card=54 - Lifetec LT 9415 TV (LR90 Rev.F)
card=55 - BESTBUY Easy TV
card=56 - FlyVideo '98/FM
card=57 - GrandTec 'Grand Video Capture'
card=64 - ATI TV-Wonder VE
card=65 - FlyVideo 2000S
card=66 - Terratec TValueRadio
+ card=67 - GV-BCTV4/PCI
+ card=68 - 3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)
+ card=69 - Active Imaging AIMMS
+ card=70 - PV-BT878P+
+ card=71 - Flyvideo 98EZ (capture only)
+ card=72 - Prolink PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)
tuner.o
type=0 - Temic PAL (4002 FH5)
type=11 - Alps TSBB5
type=12 - Alps TSBE5
type=13 - Alps TSBC5
- type=14 - Temic PAL_I (4006FH5)
+ type=14 - Temic PAL_BG (4006FH5)
type=15 - Alps TSCH6
type=16 - Temic PAL_DK (4016 FY5)
type=17 - Philips NTSC_M (MK2)
type=28 - LG PAL_BG+FM (TPI8PSB01D)
type=29 - LG PAL_BG (TPI8PSB11D)
type=30 - Temic PAL* auto + FM (4009 FN5)
+ type=31 - SHARP NTSC_JP (2U5JF5540)
+ type=32 - Samsung PAL TCPM9091PD27
+ type=33 - MT2032 universal
+ type=34 - Temic PAL_BG (4106 FH5)
+ type=35 - Temic PAL_DK/SECAM_L (4012 FY5)
+ type=36 - Temic NTSC (4136 FY5)
+ type=37 - LG PAL (newer TAPC series)
--- /dev/null
+Suppported cards:
+
+
+Bt848/Bt848a/Bt849/Bt878/Bt879 cards
+------------------------------------
+
+All cards with Bt848/Bt848a/Bt849/Bt878/Bt879 and normal Composite/S-VHS inputs
+are supported.
+Teletext and Intercast support (PAL only) for ALL cards via VBI sample decoding
+in software.
+
+Some cards with additional multiplexing of inputs are only partially
+supported (unless specifications by the card manufacturer are given).
+
+All other cards only differ by additional components as tuners, sound decoders,
+EEPROMs, teletext decoders ...
+
+
+MATRIX Vision
+-------------
+
+MV-Delta
+- Bt848A
+- 4 Composite inputs, 1 S-VHS input (shared with 4th composite)
+- EEPROM
+
+http://www.matrix-vision.de/
+
+This card has no tuner but supports all 4 composite (1 shared with an
+S-VHS input) of the Bt848A.
+Very nice card if you only have satellite TV but several tuners connected
+to the card via composite.
+
+Many thanks to Matrix-Vision for giving us 2 cards for free which made
+Bt848a/Bt849 single crytal operation support possible!!!
+
+
+
+Miro/Pinnacle PCTV
+------------------
+
+- Bt848
+ some (all??) come with 2 crystals for PAL/SECAM and NTSC
+- PAL, SECAM or NTSC TV tuner (Philips or TEMIC)
+- MSP34xx sound decoder on add on board
+ decoder is supported but AFAIK does not yet work
+ (other sound MUX setting in GPIO port needed??? somebody who fixed this???)
+- 1 tuner, 1 composite and 1 S-VHS input
+- tuner type is autodetected
+
+http://www.miro.de/
+http://www.miro.com/
+
+
+Many thanks for the free card which made first NTSC support possible back
+in 1997!
+
+
+Hauppauge Win/TV pci
+--------------------
+
+There are many different versions of the Hauppauge cards with different
+tuners (TV+Radio ...), teletext decoders.
+Note that even cards with same model numbers have (depending on the revision)
+different chips on it.
+
+- Bt848 (and others but always in 2 crystal operation???)
+ newer cards have a Bt878
+- PAL, SECAM, NTSC or tuner with or without Radio support
+
+e.g.:
+ PAL:
+ TDA5737: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
+ TSA5522: 1.4 GHz I2C-bus controlled synthesizer, I2C 0xc2-0xc3
+
+ NTSC:
+ TDA5731: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
+ TSA5518: no datasheet available on Philips site
+- Philips SAA5246 or SAA5284 ( or no) Teletext decoder chip
+ with buffer RAM (e.g. Winbond W24257AS-35: 32Kx8 CMOS static RAM)
+ SAA5246 (I2C 0x22) is supported
+- 256 bytes EEPROM: Microchip 24LC02B or Philips 8582E2Y
+ with configuration information
+ I2C address 0xa0 (24LC02B also responds to 0xa2-0xaf)
+- 1 tuner, 1 composite and (depending on model) 1 S-VHS input
+- 14052B: mux for selection of sound source
+- sound decoder: TDA9800, MSP34xx (stereo cards)
+
+
+CPH-Series (CPH050, ...)
+------------------------
+Developed by TelSignal(?), OEMed by many vendors (Askey, Typhoon,
+ Anubis, Dynalink)
+
+ Card series:
+ CPH01x: BT848 capture only
+ CPH03x: BT848
+ CPH05x: BT878 with FM
+ CPH06x: BT878 (w/o FM)
+ CPH07x: BT878 capture only
+
+ TV standards:
+ CPH0x0: NTSC-M/M
+ CPH0x1: PAL-B/G
+ CPH0x2: PAL-I/I
+ CPH0x3: PAL-D/K
+ CPH0x4: SECAM-L/L
+ CPH0x5: SECAM-B/G
+ CPH0x6: SECAM-D/K
+ CPH0x7: PAL-N/N
+ CPH0x8: PAL-B/H
+ CPH0x9: PAL-M/M
+
+ CPH03x was often sold as "TV capturer".
+
+ Identifying:
+ 1) 878 cards can be identified by PCI Subsystem-ID:
+ 144f:3000 = CPH06x
+ 144F:3002 = CPH05x w/ FM
+ 144F:3005 = CPH06x_LC (w/o remote control)
+ 1) The cards have a sticker with "CPH"-model on the back.
+ 2) These cards have a number printed on the PCB just above the tuner metal box:
+ "80-CP2000300-x" = CPH03X
+ "80-CP2000500-x" = CPH05X
+ "80-CP2000600-x" = CPH06X / CPH06x_LC
+
+ Askey sells these cards as "Magic TView series", Brand "MagicXpress".
+ Other OEM often call these "Tview", "TView99" or else.
+
+Lifeview Flyvideo Series:
+-------------------------
+ The naming of these series differs in time and space.
+
+ Identifying:
+ 1) Some models can be identified by PCI subsystem ID:
+ 1852:1852 = Flyvideo 98 FM
+ 1851:1850 = Flyvideo 98
+ 1851:1851 = Flyvideo 98 EZ (capture only)
+ 2) There is a print on the PCB:
+ LR25 = Flyvideo (Zoran)
+ LR37 Rev.C = Capture only (ZR36120 + SAA7110)
+ LR50 Rev.Q = Flyvideo 98 (w/eeprom and PCI subsystem ID)
+ LR50 Rev.W = Flyvideo 98 (no eeprom)
+ LR51 Rev.E = Flyvideo 98 EZ (capture only)
+ LR90 = Flyvideo 2000 series
+ LR90 Rev.F = Lifetec/Medion LT 9815
+ LR97 = Flyvideo DVBS
+
+ "Flyvideo II" had been the name for the 848 cards, nowadays (in Germany)
+ this name is re-used for LR50 Rev.W.
+ The Lifeview website has even more names: Flyvideo III,2100,3000,3100.
+ These cards are sold by many OEMs too.
+
+
+Typhoon TV card series:
+-----------------------
+ These can be CPH, Flyvideo, Pixelview or KNC1 series.
+ Typhoon is the brand of Anubis.
+ Model 50680 got re-used, some model no. had different contents over time.
+
+ Models:
+ 50680 "TV Tuner PCI Pal BG"(old,red package)=can be CPH03x(bt848) or CPH06x(bt878)
+ 50680 "TV Tuner Pal BG" (blue package)= Pixelview PV-BT878P+ (Rev 9B)
+ 50681 "TV Tuner PCI Pal I" (variant of 50680)
+ 50682 "TView TV/FM Tuner Pal BG" = Flyvideo 98FM (LR50 Rev.Q)
+ Note: The package has a picture of CPH05x (which would be a real TView)
+ 50683 "TV Tuner PCI SECAM" (variant of 50680)
+ 50684 "TV Tuner Pal BG" = Pixelview 878TV(Rev.3D)
+ 50686 "TV Tuner" = KNC1 TV Station
+ 50687 "TV Tuner stereo" = KNC1 TV Station pro
+ 50688 "TV Tuner RDS" (black package) = KNC1 TV Station RDS
+ 50692 "TV/FM Tuner" (small PCB)
+ 50868 "TV/FM Tuner Pal I" (variant of 50682)
+ 50999 "TV/FM Tuner Secam" (variant of 50682)
+
+
+Guillemot
+---------
+ Maxi TV Video 2 = LR50 Rev.Q (FI1216MF, PAL BG+SECAM)
+ Maxi TV Video 3 = CPH064 (PAL BG + SECAM)
+
+Mentor
+------
+ Mentor TV card ("55-878TV-U1") = Pixelview 878TV(Rev.3F) (w/FM w/Remote)
+
+Prolink
+-------
+ Pixelview Play TV Pro:
+ PV-BT878P+rev.9B (Play TV Pro w/FM w/NICAM)
+ PV-BT878P+rev.8X
+ PV-BT878P+rev.4C (Play TV Pro)
+ PV-BT878P+rev.4E (Play TV Pak)
+ PV-BT878P+rev.2F
+ PV-BT878TV
+
+ PixelView Play TV
+ PV-BT848P+
+
+Dynalink
+--------
+ These are CPH series.
+
+Phoebemicro
+-----------
+ TV Master = CPH030 or CPH060
+ TV Master FM = CPH050
+
+Genius/Kye
+----------
+ Video Wonder/Genius Internet Video Kit = LR37 Rev.C
bttv.o
- the bt848 (grabber chip) driver
+ the bt848/878 (grabber chip) driver
insmod args:
card=n card type, see CARDLIST for a list.
0: don't use PLL
1: 28 MHz crystal installed
2: 35 MHz crystal installed
- triton1=0/1 for Triton1 compatibility
- Triton1 is automatically recognized
- but this might also help with other chipsets
- vsfx=0/1 yet another chipset bug compatibility flag
- (bt878 docs mentiones via+sis, but no
- specific chipsets with that problem).
+
+ triton1=0/1 for Triton1 (+others) compatibility
+ vsfx=0/1 yet another chipset bug compatibility bit
+ see README.quirks for details on these two.
+
bigendian=n Set the endianness of the gfx framebuffer.
Default is native endian.
fieldnr=0/1 Count fields. Some TV descrambling software
50 useless IRQs/sec. default is 0 (off).
autoload=0/1 autoload helper modules (tuner, audio).
default is 1 (on).
- bttv_verbose=0/1/2 verbose level (at insmod time, while looking
- at the hardware). default is 1.
+ bttv_verbose=0/1/2 verbose level (at insmod time, while
+ looking at the hardware). default is 1.
bttv_debug=0/1 debug messages (for capture).
default is 0 (off).
irq_debug=0/1 irq handler debug messages.
tda9850 = 1 The tea6300 can't be autodetected and is
tda9855 = 1 therefore off by default, if you have
tda9873 = 1 this one on your card (STB uses these)
- tea6300 = 0 you have to enable it explicitly.
- tea6420 = 1 The two tda985x chips use the same i2c
- pic16c54 = 1 address and can't be disturgished from
- each other, you might have to disable
+ tda9874a = 1 you have to enable it explicitly.
+ tea6300 = 0 The two tda985x chips use the same i2c
+ tea6420 = 1 address and can't be disturgished from
+ pic16c54 = 1 each other, you might have to disable
the wrong one.
debug = 1 print debug messages
+ insmod args for tda9874a:
+ tda9874a_SIF=1/2 select sound IF input pin (1 or 2)
+ (default is pin 1)
+ tda9874a_STD=n select TV sound standard (0..8):
+ 0 - A2, B/G
+ 1 - A2, M (Korea)
+ 2 - A2, D/K (1)
+ 3 - A2, D/K (2)
+ 4 - A2, D/K (3)
+ 5 - NICAM, I
+ 6 - NICAM, B/G
+ 7 - NICAM, D/K (default)
+ 8 - NICAM, L
+
+ Note: tda9874a is very similar to tda9874 (without 'A'-suffix), but
+ this driver will not work for the latter device (will not load).
+ Note: tda9874a and tda9875 (which is supported separately by
+ tda9875.o) use the same i2c address so both modules should not be
+ used at the same time.
+
msp3400.o
The driver for the msp34xx sound processor chips. If you have a
stereo card, you probably want to insmod this one.
--- /dev/null
+
+Below is what the bt878 data book says about the PCI bug compatibility
+modes of the bt878 chip.
+
+The triton1 insmod option sets the EN_TBFX bit in the control register.
+The vsfx insmod option does the same for EN_VSFX bit. If you have
+stability problems you can try if one of these options makes your box
+work solid.
+
+drivers/pci/quirks.c knows about these issues, this way these bits are
+enabled automagically for known-buggy chipsets (look at the kernel
+messages, bttv tells you).
+
+HTH,
+
+ Gerd
+
+---------------------------- cut here --------------------------
+
+Normal PCI Mode
+---------------
+
+The PCI REQ signal is the logical-or of the incoming function requests.
+The inter-nal GNT[0:1] signals are gated asynchronously with GNT and
+demultiplexed by the audio request signal. Thus the arbiter defaults to
+the video function at power-up and parks there during no requests for
+bus access. This is desirable since the video will request the bus more
+often. However, the audio will have highest bus access priority. Thus
+the audio will have first access to the bus even when issuing a request
+after the video request but before the PCI external arbiter has granted
+access to the Bt879. Neither function can preempt the other once on the
+bus. The duration to empty the entire video PCI FIFO onto the PCI bus is
+very short compared to the bus access latency the audio PCI FIFO can
+tolerate.
+
+
+430FX Compatibility Mode
+------------------------
+
+When using the 430FX PCI, the following rules will ensure
+compatibility:
+
+ (1) Deassert REQ at the same time as asserting FRAME.
+ (2) Do not reassert REQ to request another bus transaction until after
+ finish-ing the previous transaction.
+
+Since the individual bus masters do not have direct control of REQ, a
+simple logical-or of video and audio requests would violate the rules.
+Thus, both the arbiter and the initiator contain 430FX compatibility
+mode logic. To enable 430FX mode, set the EN_TBFX bit as indicated in
+Device Control Register on page 104.
+
+When EN_TBFX is enabled, the arbiter ensures that the two compatibility
+rules are satisfied. Before GNT is asserted by the PCI arbiter, this
+internal arbiter may still logical-or the two requests. However, once
+the GNT is issued, this arbiter must lock in its decision and now route
+only the granted request to the REQ pin. The arbiter decision lock
+happens regardless of the state of FRAME because it does not know when
+FRAME will be asserted (typically - each initiator will assert FRAME on
+the cycle following GNT). When FRAME is asserted, it is the initiator s
+responsibility to remove its request at the same time. It is the
+arbiters responsibility to allow this request to flow through to REQ and
+not allow the other request to hold REQ asserted. The decision lock may
+be removed at the end of the transaction: for example, when the bus is
+idle (FRAME and IRDY). The arbiter decision may then continue
+asynchronously until GNT is again asserted.
+
+
+Interfacing with Non-PCI 2.1 Compliant Core Logic
+-------------------------------------------------
+
+A small percentage of core logic devices may start a bus transaction
+during the same cycle that GNT is de-asserted. This is non PCI 2.1
+compliant. To ensure compatibility when using PCs with these PCI
+controllers, the EN_VSFX bit must be enabled (refer to Device Control
+Register on page 104). When in this mode, the arbiter does not pass GNT
+to the internal functions unless REQ is asserted. This prevents a bus
+transaction from starting the same cycle as GNT is de-asserted. This
+also has the side effect of not being able to take advantage of bus
+parking, thus lowering arbitration performance. The Bt879 drivers must
+query for these non-compliant devices, and set the EN_VSFX bit only if
+required.
+
tuner_type - same as tuner= insmod option
*_modulename - hint whenever some card needs this or that audio
module loaded to work properly.
+has_radio - whenever this TV card has a radio tuner.
If some config item is specified both from the tvcards array and as
insmod option, the insmod option takes precedence.
--- /dev/null
+
+SAMSUNG Tuner identification: (e.g. TCPM9091PD27)
+ TCP [ABCJLMNQ] 90[89][125] [DP] [ACD] 27 [ABCD]
+ [ABCJLMNQ]:
+ A= BG+DK
+ B= BG
+ C= I+DK
+ J= NTSC-Japan
+ L= Secam LL
+ M= BG+I+DK
+ N= NTSC
+ Q= BG+I+DK+LL
+ [125]:
+ 2: No FM
+ 5: With FM
+ [DP]:
+ D= NTSC
+ P= PAL
+ [ACD]:
+ A= F-connector
+ C= Phono connector
+ D= Din Jack
+ [ABCD]:
+ 3-wire/I2C tuning, 2-band/3-band
+
+Philips Tuner identification: (e.g. FM1216MF)
+ F[IRMQ]12[1345]{MF|ME|MP}
+ [IRMQ]:
+ I: Tuner Series
+ R: Tuner + Radio IF
+ M: Tuner + FM
+ Q,MR: specials
+ TD15xx: Digital Tuner ATSC
+ [1345]
+ 1: PAL BG
+ 3: NTSC
+ 4: PAL I
+ 5: Pal DK
+ {MF|ME|MP}
+ MF: w/ Secam
+ ME: BD DK I LL
+ MP: BG DK I
+ MR: BG DK M (?)
+ MG: BG DKI M (?)
+
+Temic Tuner identification: (.e.g 4006FH5)
+ 4[01][0136][269]F[HYNR]5
+ 40x2: Tuner (5V/33V), different I2C programming from Philips !
+ 40x6: Tuner 5V
+ 41xx: Tuner compact
+ 40x9: Tuner+FM compact
+ [0136]
+ 0: PAL BG
+ 1: Pal DK, Secam LL
+ 3: NTSC
+ 6: PAL I
+ F[HYNR]5
+ FH5: Pal BG
+ FY5: others
+ FN5: multistandard
+ FR5: w/ FM radio
+ 3X xxxx: order number with specific connector
+
+LG Innotek Tuner:
+ TPI8NSR11 : NTSC J/M (TPI8NSR01 w/FM) (P,210/497)
+ TPI8PSB11 : PAL B/G (TPI8PSB01 w/FM) (P,170/450)
+ TAPC-I701 : PAL I (TAPC-I001 w/FM) (P,170/450)
+ TPI8PSB12 : PAL D/K+B/G (TPI8PSB02 w/FM) (P,170/450)
+ TAPC-H701P: NTSC_JP (TAPC-H001P w/FM) (L,170/450)
+ TAPC-G701P: PAL B/G (TAPC-G001P w/FM) (L,170/450)
+ TAPC-W701P: PAL I (TAPC-W001P w/FM) (L,170/450)
+ TAPC-Q703P: PAL D/K (TAPC-Q001P w/FM) (L,170/450)
+ TAPC-Q704P: PAL D/K+I (L,170/450)
+ TAPC-G702P: PAL D/K+B/G (L,170/450)
+
+ TADC-H002F: NTSC (L,175/410?; 2-B, C-W+11, W+12-69)
+ TADC-M201D: PAL D/K+B/G+I (L,143/425) (sound control at I2C address 0xc8)
+ TADC-T003F: NTSC Taiwan (L,175/410?; 2-B, C-W+11, W+12-69)
+
+ (API,Lo-Hi-takeover/Hi-UHF-takeover)
+ I2C APIs:
+ L= LG programming (VHF_LO=0x01, VHF_HI=0x02, UHF=0x08, radio=0x04)
+ P= Philips progr. (VHF_LO=0xA0, VHF_HI=0x90, UHF=0x30, radio=0x04)
+ T= Temic progr. (VHF_LO=0x02, VHF_HI=0x04, UHF=0x01)
+ Suffix:
+ P= Standard phono female socket
+ D= IEC female socket
+ F= F-connector
W: http://www.torque.net/linux-pp.html
S: Maintained
+PERSONALITY HANDLING
+P: Christoph Hellwig
+M: hch@caldera.de
+L: linux-abi-devel@lists.sourceforge.net
+S: Supported
+
PCI ID DATABASE
P: Jens Maurer
M: jmaurer@cck.uni-kl.de
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 13
-EXTRAVERSION =-pre3
+EXTRAVERSION =-pre4
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
#
# CONFIG_USB_DEVICEFS is not set
# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_LONG_TIMEOUT is not set
+# CONFIG_USB_LARGE_CONFIG is not set
#
# USB Controllers
# CONFIG_USB_BLUETOOTH is not set
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
#
# USB Multimedia devices
#
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_PWC is not set
-# CONFIG_USB_SE401 is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
#
# USB Network adaptors
#
# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
# CONFIG_USB_CATC is not set
# CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_KAWETH is not set
# CONFIG_USB_USBNET is not set
#
# USB Serial Converter support
#
# CONFIG_USB_SERIAL is not set
-
-#
-# USB misc drivers
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
#
# CONFIG_USB_RIO500 is not set
.long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */
.long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */
.long SYMBOL_NAME(sys_gettid)
+ .long SYMBOL_NAME(sys_readahead) /* 225 */
.rept NR_syscalls-(.-sys_call_table)/4
.long SYMBOL_NAME(sys_ni_syscall)
return err;
}
+static int read_default_ldt(void * ptr, unsigned long bytecount)
+{
+ int err;
+ unsigned long size;
+ void *address;
+
+ err = 0;
+ address = &default_ldt[0];
+ size = sizeof(struct desc_struct);
+ if (size > bytecount)
+ size = bytecount;
+
+ err = size;
+ if (copy_to_user(ptr, address, size))
+ err = -EFAULT;
+
+ return err;
+}
+
static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
{
struct mm_struct * mm = current->mm;
case 1:
ret = write_ldt(ptr, bytecount, 1);
break;
+ case 2:
+ ret = read_default_ldt(ptr, bytecount);
+ break;
case 0x11:
ret = write_ldt(ptr, bytecount, 0);
break;
{ "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set },
{ "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4,
pirq_serverworks_get, pirq_serverworks_set },
+ { "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5,
+ pirq_serverworks_get, pirq_serverworks_set },
{ "AMD756 VIPER", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B,
pirq_amd756_get, pirq_amd756_set },
/*
- * BK Id: SCCS/s.enet.c 1.15 09/14/01 18:01:16 trini
+ * BK Id: SCCS/s.enet.c 1.17 10/11/01 11:55:47 trini
*/
/*
* Ethernet driver for Motorola MPC8xx.
static int scc_enet_open(struct net_device *dev);
static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
static int scc_enet_rx(struct net_device *dev);
-static void scc_enet_interrupt(void *dev_id);
+static void scc_enet_interrupt(void *dev_id, struct pt_regs *regs);
static int scc_enet_close(struct net_device *dev);
static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
* This is called from the CPM handler, not the MPC core interrupt.
*/
static void
-scc_enet_interrupt(void *dev_id)
+scc_enet_interrupt(void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
volatile struct scc_enet_private *cep;
ep->sen_iaddr4 = 0;
/* Set Ethernet station address.
- *
- * If we performed a MBX diskless boot, the Ethernet controller
- * has been initialized and we copy the address out into our
- * own structure.
- *
- * All other types of boards supply the address in the board
- * information structure, so we copy that into the controller.
*/
eap = (unsigned char *)&(ep->sen_paddrh);
-#ifndef CONFIG_MBX
for (i=5; i>=0; i--)
*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
-#else
- for (i=5; i>=0; i--)
- dev->dev_addr[i] = *eap++;
-#endif
ep->sen_pper = 0; /* 'cause the book says so */
ep->sen_taddrl = 0; /* temp address (LSB) */
immap->im_ioport.iop_pcdat &= ~PC_BSE_LOOPBACK;
#endif
+#ifdef CONFIG_FADS
+ cp->cp_pbpar |= PB_ENET_TENA;
+ cp->cp_pbdir |= PB_ENET_TENA;
+
+ /* Enable the EEST PHY.
+ */
+ *((volatile uint *)BCSR1) &= ~BCSR1_ETHEN;
+#endif
dev->base_addr = (unsigned long)ep;
dev->priv = cep;
return 0;
}
-
-
/*
- * BK Id: SCCS/s.fec.c 1.18 09/22/01 09:12:32 trini
+ * BK Id: SCCS/s.fec.c 1.20 10/11/01 11:55:47 trini
*/
/*
* Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
*s |= PHY_STAT_FAULT;
if (mii_reg & 0x0020)
*s |= PHY_STAT_ANC;
+
+ fep->link = (*s & PHY_STAT_LINK) ? 1 : 0;
}
static void mii_parse_cr(uint mii_reg, struct net_device *dev)
#endif
#ifdef PHY_INTERRUPT
- if (request_8xxirq(PHY_INTERRUPT, mii_link_interrupt, 0, "mii", dev) != 0)
- panic("Could not allocate MII IRQ!");
-
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |=
(0x80000000 >> PHY_INTERRUPT);
+
+ if (request_8xxirq(PHY_INTERRUPT, mii_link_interrupt, 0, "mii", dev) != 0)
+ panic("Could not allocate MII IRQ!");
#endif
dev->base_addr = (unsigned long)fecp;
/*
- * BK Id: SCCS/s.m8xx_setup.c 1.32 09/27/01 09:01:12 trini
+ * BK Id: SCCS/s.m8xx_setup.c 1.35 10/11/01 11:55:47 trini
*
* linux/arch/ppc/kernel/setup.c
*
unsigned char __res[sizeof(bd_t)];
-extern void m8xx_ide_init();
+extern void m8xx_ide_init(void);
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = ~KAPWR_KEY;
((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = ~KAPWR_KEY;
((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = ~KAPWR_KEY;
- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = KAPWR_KEY;
/* Disable the RTC one second and alarm interrupts. */
((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &=
-# $Id: Makefile,v 1.47 2001/07/27 09:42:22 davem Exp $
+# $Id: Makefile,v 1.48 2001/10/15 09:24:51 davem Exp $
# sparc64/Makefile
#
# Makefile for the architecture dependent flags and dependencies on the
CC := $(shell if gcc -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo gcc; else echo sparc64-linux-gcc; fi )
NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
-NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
+NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; )
export NEW_GCC
-/* $Id: dtlb_base.S,v 1.16 2001/10/09 04:02:11 davem Exp $
+/* $Id: dtlb_base.S,v 1.17 2001/10/11 22:33:52 davem Exp $
* dtlb_base.S: Front end to DTLB miss replacement strategy.
* This is included directly into the trap table.
*
be,pn %xcc, 3f ! Yep, special processing
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
cmp %g5, 3 ! Last trap level?
- be,a,pn %xcc, 1f ! Yep, use non-faulting load
- ldxa [%g3 + %g6] ASI_SNF, %g5 ! Load VPTE (no-VPTE-fault)
+ be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
+ nop ! delay slot
/* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */
ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE
-/* $Id: entry.S,v 1.134 2001/08/27 18:42:07 kanoj Exp $
+/* $Id: entry.S,v 1.135 2001/10/13 23:04:09 kanoj Exp $
* arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
__do_data_access_exception_tl1:
rdpr %pstate, %g4
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
- rdpr %tl, %g3
- cmp %g3, 1
mov TLB_SFSR, %g3
mov DMMU_SFAR, %g5
ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
membar #Sync
- bgu,pn %icc, winfix_dax
+ ba,pt %xcc, winfix_dax
rdpr %tpc, %g3
- sethi %hi(109f), %g7
- ba,pt %xcc, etraptl1
- or %g7, %lo(109f), %g7 ! Merge in below
__do_data_access_exception:
rdpr %pstate, %g4
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
ldxa [%g3] ASI_DMMU, %g5
stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit
membar #Sync
- bgu,pn %icc, winfix_dax
+ bgu,pn %icc, winfix_mna
rdpr %tpc, %g3
1: sethi %hi(109f), %g7
-/* $Id: rtrap.S,v 1.55 2001/06/05 09:56:06 davem Exp $
+/* $Id: rtrap.S,v 1.56 2001/10/13 00:14:34 kanoj Exp $
* rtrap.S: Preparing for return from trap on Sparc V9.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
andn %l1, %l4, %l1
.align 64
- .globl rtrap_clr_l6, rtrap
+ .globl rtrap_clr_l6, rtrap, irqsz_patchme
rtrap_clr_l6: clr %l6
rtrap: lduw [%g6 + AOFF_task_processor], %l0
sethi %hi(irq_stat), %l2 ! &softirq_active
or %l2, %lo(irq_stat), %l2 ! &softirq_active
- sllx %l0, 6, %l0
+irqsz_patchme: sllx %l0, 0, %l0
lduw [%l2 + %l0], %l1 ! softirq_pending
cmp %l1, 0
-/* $Id: setup.c,v 1.67 2001/09/21 03:17:06 kanoj Exp $
+/* $Id: setup.c,v 1.68 2001/10/13 00:14:34 kanoj Exp $
* linux/arch/sparc64/kernel/setup.c
*
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
conswitchp = &prom_con;
#endif
+#ifdef CONFIG_SMP
+ i = (unsigned long)&irq_stat[1] - (unsigned long)&irq_stat[0];
+ if ((i == SMP_CACHE_BYTES) || (i == (2 * SMP_CACHE_BYTES))) {
+ extern unsigned int irqsz_patchme[1];
+ irqsz_patchme[0] |= ((i == SMP_CACHE_BYTES) ? SMP_CACHE_BYTES_SHIFT : \
+ SMP_CACHE_BYTES_SHIFT + 1);
+ flushi((long)&irqsz_patchme[1]);
+ } else {
+ prom_printf("Unexpected size of irq_stat[] elements\n");
+ prom_halt();
+ }
+#endif
/* Work out if we are starfire early on */
check_if_starfire();
#define BREAKPOINT3
#define disable() __cli()
#define enable() __sti()
-#define wbinvd()
/*! [Begin] no source code translation */
*/
-#define DAC960_DriverVersion "2.4.10"
-#define DAC960_DriverDate "23 July 2001"
+#define DAC960_DriverVersion "2.4.11"
+#define DAC960_DriverDate "11 October 2001"
#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/pci.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
*/
static NotifierBlock_T
- DAC960_NotifierBlock = { DAC960_Finalize, NULL, 0 };
+ DAC960_NotifierBlock = { DAC960_Notifier, NULL, 0 };
/*
/*
DAC960_AllocateCommand allocates a Command structure from Controller's
- free list.
+ free list. During driver initialization, a special initialization command
+ has been placed on the free list to guarantee that command allocation can
+ never fail.
*/
static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T
}
+/*
+ DAC960_P_QueueCommand queues Command for DAC960 P Series Controllers.
+*/
+
+static void DAC960_P_QueueCommand(DAC960_Command_T *Command)
+{
+ DAC960_Controller_T *Controller = Command->Controller;
+ void *ControllerBaseAddress = Controller->BaseAddress;
+ DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
+ CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
+ switch (CommandMailbox->Common.CommandOpcode)
+ {
+ case DAC960_V1_Enquiry:
+ CommandMailbox->Common.CommandOpcode = DAC960_V1_Enquiry_Old;
+ break;
+ case DAC960_V1_GetDeviceState:
+ CommandMailbox->Common.CommandOpcode = DAC960_V1_GetDeviceState_Old;
+ break;
+ case DAC960_V1_Read:
+ CommandMailbox->Common.CommandOpcode = DAC960_V1_Read_Old;
+ DAC960_PD_To_P_TranslateReadWriteCommand(CommandMailbox);
+ break;
+ case DAC960_V1_Write:
+ CommandMailbox->Common.CommandOpcode = DAC960_V1_Write_Old;
+ DAC960_PD_To_P_TranslateReadWriteCommand(CommandMailbox);
+ break;
+ case DAC960_V1_ReadWithScatterGather:
+ CommandMailbox->Common.CommandOpcode =
+ DAC960_V1_ReadWithScatterGather_Old;
+ DAC960_PD_To_P_TranslateReadWriteCommand(CommandMailbox);
+ break;
+ case DAC960_V1_WriteWithScatterGather:
+ CommandMailbox->Common.CommandOpcode =
+ DAC960_V1_WriteWithScatterGather_Old;
+ DAC960_PD_To_P_TranslateReadWriteCommand(CommandMailbox);
+ break;
+ default:
+ break;
+ }
+ while (DAC960_PD_MailboxFullP(ControllerBaseAddress))
+ udelay(1);
+ DAC960_PD_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox);
+ DAC960_PD_NewCommand(ControllerBaseAddress);
+}
+
+
/*
DAC960_ExecuteCommand executes Command and waits for completion.
*/
}
+/*
+ DAC960_V1_ExecuteTypeB executes a DAC960 V1 Firmware Controller Type 3B
+ Command and waits for completion. It returns true on success and false
+ on failure.
+*/
+
+static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
+ DAC960_V1_CommandOpcode_T CommandOpcode,
+ unsigned char CommandOpcode2,
+ void *DataPointer)
+{
+ DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
+ DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
+ DAC960_V1_CommandStatus_T CommandStatus;
+ DAC960_V1_ClearCommand(Command);
+ Command->CommandType = DAC960_ImmediateCommand;
+ CommandMailbox->Type3B.CommandOpcode = CommandOpcode;
+ CommandMailbox->Type3B.CommandOpcode2 = CommandOpcode2;
+ CommandMailbox->Type3B.BusAddress = Virtual_to_Bus32(DataPointer);
+ DAC960_ExecuteCommand(Command);
+ CommandStatus = Command->V1.CommandStatus;
+ DAC960_DeallocateCommand(Command);
+ return (CommandStatus == DAC960_V1_NormalCompletion);
+}
+
+
/*
DAC960_V1_ExecuteType3D executes a DAC960 V1 Firmware Controller Type 3D
Command and waits for completion. It returns true on success and false
DAC1164P 5.06 and above
DAC960PTL/PRL/PJ/PG 4.06 and above
DAC960PU/PD/PL 3.51 and above
+ DAC960PU/PD/PL/P 2.73 and above
*/
+ if (Enquiry2.FirmwareID.MajorVersion == 0)
+ {
+ Enquiry2.FirmwareID.MajorVersion =
+ Controller->V1.Enquiry.MajorFirmwareVersion;
+ Enquiry2.FirmwareID.MinorVersion =
+ Controller->V1.Enquiry.MinorFirmwareVersion;
+ Enquiry2.FirmwareID.FirmwareType = '0';
+ Enquiry2.FirmwareID.TurnID = 0;
+ }
sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d",
Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion,
Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID);
(Controller->FirmwareVersion[0] == '4' &&
strcmp(Controller->FirmwareVersion, "4.06") >= 0) ||
(Controller->FirmwareVersion[0] == '3' &&
- strcmp(Controller->FirmwareVersion, "3.51") >= 0)))
+ strcmp(Controller->FirmwareVersion, "3.51") >= 0) ||
+ (Controller->FirmwareVersion[0] == '2' &&
+ strcmp(Controller->FirmwareVersion, "2.73") >= 0)))
{
DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
DAC960_Error("Firmware Version = '%s'\n", Controller,
default:
return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY");
}
+ /*
+ Initialize the Background Initialization Status.
+ */
+ if ((Controller->FirmwareVersion[0] == '4' &&
+ strcmp(Controller->FirmwareVersion, "4.08") >= 0) ||
+ (Controller->FirmwareVersion[0] == '5' &&
+ strcmp(Controller->FirmwareVersion, "5.08") >= 0))
+ {
+ Controller->V1.BackgroundInitializationStatusSupported = true;
+ DAC960_V1_ExecuteType3B(Controller,
+ DAC960_V1_BackgroundInitializationControl, 0x20,
+ &Controller->
+ V1.LastBackgroundInitializationStatus);
+ }
/*
Initialize the Logical Drive Initially Accessible flag.
*/
DeviceState->DeviceType == DAC960_V1_DiskType)
{
if (Controller->V1.DeviceResetCount[Channel][TargetID] > 0)
- DAC960_Info(" Disk Status: %s, %d blocks, %d resets\n",
+ DAC960_Info(" Disk Status: %s, %u blocks, %d resets\n",
Controller,
(DeviceState->DeviceState == DAC960_V1_Device_Dead
? "Dead"
DeviceState->DiskSize,
Controller->V1.DeviceResetCount[Channel][TargetID]);
else
- DAC960_Info(" Disk Status: %s, %d blocks\n", Controller,
+ DAC960_Info(" Disk Status: %s, %u blocks\n", Controller,
(DeviceState->DeviceState == DAC960_V1_Device_Dead
? "Dead"
: DeviceState->DeviceState
{
DAC960_V1_LogicalDriveInformation_T *LogicalDriveInformation =
&Controller->V1.LogicalDriveInformation[LogicalDriveNumber];
- DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n",
+ DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %u blocks, %s\n",
Controller, Controller->ControllerNumber, LogicalDriveNumber,
LogicalDriveInformation->RAIDLevel,
(LogicalDriveInformation->LogicalDriveState
if (PhysicalDeviceInfo->PhysicalDeviceState ==
DAC960_V2_Device_Unconfigured)
continue;
- DAC960_Info(" Disk Status: %s, %d blocks\n", Controller,
+ DAC960_Info(" Disk Status: %s, %u blocks\n", Controller,
(PhysicalDeviceInfo->PhysicalDeviceState
== DAC960_V2_Device_Online
? "Online"
: PhysicalDeviceInfo->PhysicalDeviceState
- == DAC960_V2_Device_WriteOnly
- ? "Write-Only"
+ == DAC960_V2_Device_Rebuild
+ ? "Rebuild"
: PhysicalDeviceInfo->PhysicalDeviceState
- == DAC960_V2_Device_Dead
- ? "Dead" : "Standby"),
- PhysicalDeviceInfo
- ->ConfigurableDeviceSizeIn512ByteBlocksOrMB);
+ == DAC960_V2_Device_Missing
+ ? "Missing"
+ : PhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_Critical
+ ? "Critical"
+ : PhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_Dead
+ ? "Dead"
+ : PhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_SuspectedDead
+ ? "Suspected-Dead"
+ : PhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_CommandedOffline
+ ? "Commanded-Offline"
+ : PhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_Standby
+ ? "Standby" : "Unknown"),
+ PhysicalDeviceInfo->ConfigurableDeviceSize);
if (PhysicalDeviceInfo->ParityErrors == 0 &&
PhysicalDeviceInfo->SoftErrors == 0 &&
PhysicalDeviceInfo->HardErrors == 0 &&
"-", "-", "-", "-" };
unsigned char *GeometryTranslation;
if (LogicalDeviceInfo == NULL) continue;
- switch(LogicalDeviceInfo->DriveGeometry)
+ switch (LogicalDeviceInfo->DriveGeometry)
{
case DAC960_V2_Geometry_128_32:
GeometryTranslation = "128/32";
Controller, LogicalDeviceInfo->DriveGeometry);
break;
}
- DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks\n",
+ DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %u blocks\n",
Controller, Controller->ControllerNumber, LogicalDriveNumber,
LogicalDeviceInfo->RAIDLevel,
(LogicalDeviceInfo->LogicalDeviceState
: LogicalDeviceInfo->LogicalDeviceState
== DAC960_V2_LogicalDevice_Critical
? "Critical" : "Offline"),
- LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB);
+ LogicalDeviceInfo->ConfigurableDeviceSize);
DAC960_Info(" Logical Device %s, BIOS Geometry: %s\n",
Controller,
(LogicalDeviceInfo->LogicalDeviceControl
RequestQueue->queuedata = Controller;
Controller->RequestQueue = RequestQueue;
/*
- Initialize the Disk Partitions array, Partition Sizes array, Block Sizes
- array, and Max Sectors per Request array.
+ Initialize the Max Sectors per Request array.
*/
for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++)
- {
- Controller->BlockSizes[MinorNumber] = BLOCK_SIZE;
- Controller->MaxSectorsPerRequest[MinorNumber] =
- Controller->MaxBlocksPerCommand;
- }
+ Controller->MaxSectorsPerRequest[MinorNumber] =
+ Controller->MaxBlocksPerCommand;
Controller->GenericDiskInfo.part = Controller->DiskPartitions;
Controller->GenericDiskInfo.sizes = Controller->PartitionSizes;
blksize_size[MajorNumber] = Controller->BlockSizes;
Controller->GenericDiskInfo.major_name = "rd";
Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits;
Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions;
- Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount;
+ Controller->GenericDiskInfo.nr_real = DAC960_MaxLogicalDrives;
+ Controller->GenericDiskInfo.real_devices = Controller;
Controller->GenericDiskInfo.next = NULL;
Controller->GenericDiskInfo.fops = &DAC960_BlockDeviceOperations;
/*
}
+/*
+ DAC960_ComputeGenericDiskInfo computes the values for the Generic Disk
+ Information Partition Sector Counts and Block Sizes.
+*/
+
+static void DAC960_ComputeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo)
+{
+ DAC960_Controller_T *Controller =
+ (DAC960_Controller_T *) GenericDiskInfo->real_devices;
+ int LogicalDriveNumber, i;
+ for (LogicalDriveNumber = 0;
+ LogicalDriveNumber < DAC960_MaxLogicalDrives;
+ LogicalDriveNumber++)
+ {
+ int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber, 0);
+ if (Controller->FirmwareType == DAC960_V1_Controller)
+ {
+ if (LogicalDriveNumber < Controller->LogicalDriveCount)
+ GenericDiskInfo->part[MinorNumber].nr_sects =
+ Controller->V1.LogicalDriveInformation
+ [LogicalDriveNumber].LogicalDriveSize;
+ else GenericDiskInfo->part[MinorNumber].nr_sects = 0;
+ }
+ else
+ {
+ DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo =
+ Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
+ if (LogicalDeviceInfo != NULL)
+ GenericDiskInfo->part[MinorNumber].nr_sects =
+ LogicalDeviceInfo->ConfigurableDeviceSize;
+ else GenericDiskInfo->part[MinorNumber].nr_sects = 0;
+ }
+ for (i = 0; i < DAC960_MaxPartitions; i++)
+ if (GenericDiskInfo->part[MinorNumber].nr_sects > 0)
+ Controller->BlockSizes[MinorNumber + i] = BLOCK_SIZE;
+ else Controller->BlockSizes[MinorNumber + i] = 0;
+ }
+}
+
+
/*
DAC960_RegisterDisk registers the DAC960 Logical Disk Device for Logical
Drive Number if it exists.
register_disk(&Controller->GenericDiskInfo,
DAC960_KernelDevice(Controller->ControllerNumber,
LogicalDriveNumber, 0),
- DAC960_MaxPartitions, &DAC960_BlockDeviceOperations,
+ DAC960_MaxPartitions,
+ &DAC960_BlockDeviceOperations,
Controller->V1.LogicalDriveInformation
[LogicalDriveNumber].LogicalDriveSize);
}
register_disk(&Controller->GenericDiskInfo,
DAC960_KernelDevice(Controller->ControllerNumber,
LogicalDriveNumber, 0),
- DAC960_MaxPartitions, &DAC960_BlockDeviceOperations,
- LogicalDeviceInfo
- ->ConfigurableDeviceSizeIn512ByteBlocksOrMB);
+ DAC960_MaxPartitions,
+ &DAC960_BlockDeviceOperations,
+ LogicalDeviceInfo->ConfigurableDeviceSize);
}
}
InterruptHandler = DAC960_PD_InterruptHandler;
MemoryWindowSize = DAC960_PD_RegisterWindowSize;
break;
+ case DAC960_P_Controller:
+ VendorID = PCI_VENDOR_ID_MYLEX;
+ DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_P;
+ FirmwareType = DAC960_V1_Controller;
+ InterruptHandler = DAC960_P_InterruptHandler;
+ MemoryWindowSize = DAC960_PD_RegisterWindowSize;
+ break;
}
while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL)
{
IO_Address = pci_resource_start(PCI_Device, 0);
PCI_Address = pci_resource_start(PCI_Device, 1);
break;
+ case DAC960_P_Controller:
+ IO_Address = pci_resource_start(PCI_Device, 0);
+ PCI_Address = pci_resource_start(PCI_Device, 1);
+ break;
}
if (DAC960_ControllerCount == DAC960_MaxControllers)
{
Controller->QueueReadWriteCommand =
DAC960_V1_QueueReadWriteCommand;
break;
+ case DAC960_P_Controller:
+ request_region(Controller->IO_Address, 0x80,
+ Controller->FullModelName);
+ DAC960_PD_DisableInterrupts(BaseAddress);
+ DAC960_PD_AcknowledgeStatus(BaseAddress);
+ udelay(1000);
+ while (DAC960_PD_InitializationInProgressP(BaseAddress))
+ {
+ if (DAC960_PD_ReadErrorStatus(BaseAddress, &ErrorStatus,
+ &Parameter0, &Parameter1) &&
+ DAC960_ReportErrorStatus(Controller, ErrorStatus,
+ Parameter0, Parameter1))
+ goto Failure;
+ udelay(10);
+ }
+ DAC960_PD_EnableInterrupts(Controller->BaseAddress);
+ Controller->QueueCommand = DAC960_P_QueueCommand;
+ Controller->ReadControllerConfiguration =
+ DAC960_V1_ReadControllerConfiguration;
+ Controller->ReadDeviceConfiguration =
+ DAC960_V1_ReadDeviceConfiguration;
+ Controller->ReportDeviceConfiguration =
+ DAC960_V1_ReportDeviceConfiguration;
+ Controller->QueueReadWriteCommand =
+ DAC960_V1_QueueReadWriteCommand;
+ break;
}
/*
Acquire shared access to the IRQ Channel.
DAC960_Initialize initializes the DAC960 Driver.
*/
-void DAC960_Initialize(void)
+static int DAC960_Initialize(void)
{
int ControllerNumber;
DAC960_DetectControllers(DAC960_BA_Controller);
DAC960_DetectControllers(DAC960_LA_Controller);
DAC960_DetectControllers(DAC960_PG_Controller);
DAC960_DetectControllers(DAC960_PD_Controller);
+ DAC960_DetectControllers(DAC960_P_Controller);
DAC960_SortControllers();
- if (DAC960_ActiveControllerCount == 0) return;
+ if (DAC960_ActiveControllerCount == 0) return -ENODEV;
for (ControllerNumber = 0;
ControllerNumber < DAC960_ControllerCount;
ControllerNumber++)
int LogicalDriveNumber;
if (Controller == NULL) continue;
DAC960_InitializeController(Controller);
+ DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
for (LogicalDriveNumber = 0;
LogicalDriveNumber < DAC960_MaxLogicalDrives;
LogicalDriveNumber++)
}
DAC960_CreateProcEntries();
register_reboot_notifier(&DAC960_NotifierBlock);
+ return 0;
}
DAC960_Finalize finalizes the DAC960 Driver.
*/
-static int DAC960_Finalize(NotifierBlock_T *NotifierBlock,
- unsigned long Event,
- void *Buffer)
+static void DAC960_Finalize(void)
{
int ControllerNumber;
- if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF))
- return NOTIFY_DONE;
- if (DAC960_ActiveControllerCount == 0) return NOTIFY_OK;
+ if (DAC960_ActiveControllerCount == 0) return;
for (ControllerNumber = 0;
ControllerNumber < DAC960_ControllerCount;
ControllerNumber++)
DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]);
DAC960_DestroyProcEntries();
unregister_reboot_notifier(&DAC960_NotifierBlock);
+}
+
+
+/*
+ DAC960_Notifier is the notifier for the DAC960 Driver.
+*/
+
+static int DAC960_Notifier(NotifierBlock_T *NotifierBlock,
+ unsigned long Event,
+ void *Buffer)
+{
+ if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF))
+ return NOTIFY_DONE;
+ DAC960_Finalize();
return NOTIFY_OK;
}
char *LastDataEndPointer = NULL;
int SegmentNumber = 0;
if (Command->CommandType == DAC960_ReadCommand)
- CommandMailbox->Type5.CommandOpcode =
- DAC960_V1_ReadWithOldScatterGather;
+ CommandMailbox->Type5.CommandOpcode = DAC960_V1_ReadWithScatterGather;
else
- CommandMailbox->Type5.CommandOpcode =
- DAC960_V1_WriteWithOldScatterGather;
+ CommandMailbox->Type5.CommandOpcode = DAC960_V1_WriteWithScatterGather;
CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
Controller, Command->V1.CommandStatus, CommandName);
break;
}
- DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n",
+ DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %u..%u\n",
Controller, Controller->ControllerNumber,
Command->LogicalDriveNumber, Command->BlockNumber,
Command->BlockNumber + Command->BlockCount - 1);
if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
- DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %d..%d\n",
+ DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
Controller, Controller->ControllerNumber,
Command->LogicalDriveNumber,
DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
LogicalDriveNumber,
Controller->ControllerNumber,
LogicalDriveNumber);
+ Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
+ DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
}
if (NewEnquiry->NumberOfLogicalDrives < Controller->LogicalDriveCount)
{
LogicalDriveNumber,
Controller->ControllerNumber,
LogicalDriveNumber);
+ Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
+ DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
}
- Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
if (NewEnquiry->StatusFlags.DeferredWriteError !=
OldEnquiry->StatusFlags.DeferredWriteError)
DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller,
Controller->V1.NeedErrorTableInformation = true;
Controller->V1.NeedDeviceStateInformation = true;
Controller->V1.StartDeviceStateScan = true;
+ Controller->V1.NeedBackgroundInitializationStatus =
+ Controller->V1.BackgroundInitializationStatusSupported;
Controller->SecondaryMonitoringTime = jiffies;
}
if (NewEnquiry->RebuildFlag == DAC960_V1_StandbyRebuildInProgress ||
AdditionalSenseCodeQualifier == 0x02))))
{
DAC960_Critical("Physical Device %d:%d Error Log: "
- "Sense Key = %d, ASC = %02X, ASCQ = %02X\n",
+ "Sense Key = %X, ASC = %02X, ASCQ = %02X\n",
Controller,
EventLogEntry->Channel,
EventLogEntry->TargetID,
Controller->EphemeralProgressMessage = false;
}
}
+ else if (CommandOpcode == DAC960_V1_BackgroundInitializationControl)
+ {
+ unsigned int LogicalDriveNumber =
+ Controller->V1.BackgroundInitializationStatus.LogicalDriveNumber;
+ unsigned int LogicalDriveSize =
+ Controller->V1.BackgroundInitializationStatus.LogicalDriveSize;
+ unsigned int BlocksCompleted =
+ Controller->V1.BackgroundInitializationStatus.BlocksCompleted;
+ switch (CommandStatus)
+ {
+ case DAC960_V1_NormalCompletion:
+ switch (Controller->V1.BackgroundInitializationStatus.Status)
+ {
+ case DAC960_V1_BackgroundInitializationInvalid:
+ break;
+ case DAC960_V1_BackgroundInitializationStarted:
+ DAC960_Progress("Background Initialization Started\n",
+ Controller);
+ break;
+ case DAC960_V1_BackgroundInitializationInProgress:
+ if (BlocksCompleted ==
+ Controller->V1.LastBackgroundInitializationStatus
+ .BlocksCompleted &&
+ LogicalDriveNumber ==
+ Controller->V1.LastBackgroundInitializationStatus
+ .LogicalDriveNumber)
+ break;
+ Controller->EphemeralProgressMessage = true;
+ DAC960_Progress("Background Initialization in Progress: "
+ "Logical Drive %d (/dev/rd/c%dd%d) "
+ "%d%% completed\n",
+ Controller, LogicalDriveNumber,
+ Controller->ControllerNumber,
+ LogicalDriveNumber,
+ (100 * (BlocksCompleted >> 7))
+ / (LogicalDriveSize >> 7));
+ Controller->EphemeralProgressMessage = false;
+ break;
+ case DAC960_V1_BackgroundInitializationSuspended:
+ DAC960_Progress("Background Initialization Suspended\n",
+ Controller);
+ break;
+ case DAC960_V1_BackgroundInitializationCancelled:
+ DAC960_Progress("Background Initialization Cancelled\n",
+ Controller);
+ break;
+ }
+ memcpy(&Controller->V1.LastBackgroundInitializationStatus,
+ &Controller->V1.BackgroundInitializationStatus,
+ sizeof(DAC960_V1_BackgroundInitializationStatus_T));
+ break;
+ case DAC960_V1_BackgroundInitSuccessful:
+ if (Controller->V1.BackgroundInitializationStatus.Status ==
+ DAC960_V1_BackgroundInitializationInProgress)
+ DAC960_Progress("Background Initialization "
+ "Completed Successfully\n", Controller);
+ Controller->V1.BackgroundInitializationStatus.Status =
+ DAC960_V1_BackgroundInitializationInvalid;
+ break;
+ case DAC960_V1_BackgroundInitAborted:
+ if (Controller->V1.BackgroundInitializationStatus.Status ==
+ DAC960_V1_BackgroundInitializationInProgress)
+ DAC960_Progress("Background Initialization Aborted\n",
+ Controller);
+ Controller->V1.BackgroundInitializationStatus.Status =
+ DAC960_V1_BackgroundInitializationInvalid;
+ break;
+ case DAC960_V1_NoBackgroundInitInProgress:
+ break;
+ }
+ }
}
if (CommandType == DAC960_MonitoringCommand)
{
DAC960_QueueCommand(Command);
return;
}
+ if (Controller->V1.NeedBackgroundInitializationStatus)
+ {
+ Controller->V1.NeedBackgroundInitializationStatus = false;
+ Command->V1.CommandMailbox.Type3B.CommandOpcode =
+ DAC960_V1_BackgroundInitializationControl;
+ Command->V1.CommandMailbox.Type3B.CommandOpcode2 = 0x20;
+ Command->V1.CommandMailbox.Type3B.BusAddress =
+ Virtual_to_Bus32(&Controller->V1.BackgroundInitializationStatus);
+ DAC960_QueueCommand(Command);
+ return;
+ }
Controller->MonitoringTimerCount++;
Controller->MonitoringTimer.expires =
jiffies + DAC960_MonitoringTimerInterval;
}
DAC960_Error("Error Condition %s on %s:\n", Controller,
SenseErrors[Command->V2.RequestSense.SenseKey], CommandName);
- DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n",
+ DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %u..%u\n",
Controller, Controller->ControllerNumber,
Command->LogicalDriveNumber, Command->BlockNumber,
Command->BlockNumber + Command->BlockCount - 1);
if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
- DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %d..%d\n",
+ DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
Controller, Controller->ControllerNumber,
Command->LogicalDriveNumber,
DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
{ 0x000B, "P Rebuild Failed due to Logical Drive Failure" },
{ 0x000C, "S Offline" },
{ 0x000D, "P Found" },
- { 0x000E, "P Gone" },
+ { 0x000E, "P Removed" },
{ 0x000F, "P Unconfigured" },
{ 0x0010, "P Expand Capacity Started" },
{ 0x0011, "P Expand Capacity Completed" },
{ 0x0012, "P Expand Capacity Failed" },
+ { 0x0013, "P Command Timed Out" },
+ { 0x0014, "P Command Aborted" },
+ { 0x0015, "P Command Retried" },
{ 0x0016, "P Parity Error" },
{ 0x0017, "P Soft Error" },
{ 0x0018, "P Miscellaneous Error" },
{ 0x0031, "P Failed because BDT Write Operation Failed" },
{ 0x0039, "P Missing at Startup" },
{ 0x003A, "P Start Rebuild Failed due to Physical Drive Too Small" },
+ { 0x003C, "P Temporarily Offline Device Automatically Made Online" },
+ { 0x003D, "P Standby Rebuild Started" },
/* Logical Device Events (0x0080 - 0x00FF) */
{ 0x0080, "M Consistency Check Started" },
{ 0x0081, "M Consistency Check Completed" },
{ 0x0092, "M Initialization Cancelled" },
{ 0x0093, "M Initialization Failed" },
{ 0x0094, "L Found" },
- { 0x0095, "L Gone" },
+ { 0x0095, "L Deleted" },
{ 0x0096, "M Expand Capacity Started" },
{ 0x0097, "M Expand Capacity Completed" },
{ 0x0098, "M Expand Capacity Failed" },
{ 0x009C, "L Bad Data Block Found" },
{ 0x009E, "L Read of Data Block in BDT" },
{ 0x009F, "L Write Back Data for Disk Block Lost" },
+ { 0x00A0, "L Temporarily Offline RAID-5/3 Drive Made Online" },
+ { 0x00A1, "L Temporarily Offline RAID-6/1/0/7 Drive Made Online" },
+ { 0x00A2, "L Standby Rebuild Started" },
/* Fault Management Events (0x0100 - 0x017F) */
{ 0x0140, "E Fan %d Failed" },
{ 0x0141, "E Fan %d OK" },
{ 0x0143, "E Power Supply %d Failed" },
{ 0x0144, "E Power Supply %d OK" },
{ 0x0145, "E Power Supply %d Not Present" },
- { 0x0146, "E Temperature Sensor %d Failed" },
- { 0x0147, "E Temperature Sensor %d Critical" },
- { 0x0148, "E Temperature Sensor %d OK" },
+ { 0x0146, "E Temperature Sensor %d Temperature Exceeds Safe Limit" },
+ { 0x0147, "E Temperature Sensor %d Temperature Exceeds Working Limit" },
+ { 0x0148, "E Temperature Sensor %d Temperature Normal" },
{ 0x0149, "E Temperature Sensor %d Not Present" },
- { 0x014A, "E Unit %d Access Critical" },
- { 0x014B, "E Unit %d Access OK" },
- { 0x014C, "E Unit %d Access Offline" },
+ { 0x014A, "E Enclosure Management Unit %d Access Critical" },
+ { 0x014B, "E Enclosure Management Unit %d Access OK" },
+ { 0x014C, "E Enclosure Management Unit %d Access Offline" },
/* Controller Events (0x0180 - 0x01FF) */
{ 0x0181, "C Cache Write Back Error" },
{ 0x0188, "C Battery Backup Unit Found" },
{ 0x0189, "C Battery Backup Unit Charge Level Low" },
{ 0x018A, "C Battery Backup Unit Charge Level OK" },
{ 0x0193, "C Installation Aborted" },
- { 0x0195, "C Mirror Race Recovery In Progress" },
- { 0x0196, "C Mirror Race on Critical Drive" },
- { 0x019E, "C Memory Soft ECC Error" },
- { 0x019F, "C Memory Hard ECC Error" },
+ { 0x0195, "C Battery Backup Unit Physically Removed" },
+ { 0x0196, "C Memory Error During Warm Boot" },
+ { 0x019E, "C Memory Soft ECC Error Corrected" },
+ { 0x019F, "C Memory Hard ECC Error Corrected" },
{ 0x01A2, "C Battery Backup Unit Failed" },
+ { 0x01AB, "C Mirror Race Recovery Failed" },
+ { 0x01AC, "C Mirror Race on Critical Drive" },
+ /* Controller Internal Processor Events */
+ { 0x0380, "C Internal Controller Hung" },
+ { 0x0381, "C Internal Controller Firmware Breakpoint" },
+ { 0x0390, "C Internal Controller i960 Processor Specific Error" },
+ { 0x03A0, "C Internal Controller StrongARM Processor Specific Error" },
{ 0, "" } };
int EventListIndex = 0, EventCode;
unsigned char EventType, *EventMessage;
DAC960_Critical("Physical Device %d:%d %s\n", Controller,
Event->Channel, Event->TargetID, EventMessage);
DAC960_Critical("Physical Device %d:%d Request Sense: "
- "Sense Key = %d, ASC = %02X, ASCQ = %02X\n",
+ "Sense Key = %X, ASC = %02X, ASCQ = %02X\n",
Controller,
Event->Channel,
Event->TargetID,
{
if (NewPhysicalDeviceInfo->PhysicalDeviceState !=
PhysicalDeviceInfo->PhysicalDeviceState)
- DAC960_Critical("Physical Device %d:%d is now %s\n", Controller,
- NewPhysicalDeviceInfo->Channel,
- NewPhysicalDeviceInfo->TargetID,
- (NewPhysicalDeviceInfo->PhysicalDeviceState
- == DAC960_V2_Device_Unconfigured
- ? "UNCONFIGURED"
- : NewPhysicalDeviceInfo->PhysicalDeviceState
- == DAC960_V2_Device_Online
- ? "ONLINE"
- : NewPhysicalDeviceInfo->PhysicalDeviceState
- == DAC960_V2_Device_WriteOnly
- ? "WRITE-ONLY"
- : NewPhysicalDeviceInfo
- ->PhysicalDeviceState
- == DAC960_V2_Device_Dead
- ? "DEAD" : "STANDBY"));
+ DAC960_Critical(
+ "Physical Device %d:%d is now %s\n", Controller,
+ NewPhysicalDeviceInfo->Channel,
+ NewPhysicalDeviceInfo->TargetID,
+ (NewPhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_Online
+ ? "ONLINE"
+ : NewPhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_Rebuild
+ ? "REBUILD"
+ : NewPhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_Missing
+ ? "MISSING"
+ : NewPhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_Critical
+ ? "CRITICAL"
+ : NewPhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_Dead
+ ? "DEAD"
+ : NewPhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_SuspectedDead
+ ? "SUSPECTED-DEAD"
+ : NewPhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_CommandedOffline
+ ? "COMMANDED-OFFLINE"
+ : NewPhysicalDeviceInfo->PhysicalDeviceState
+ == DAC960_V2_Device_Standby
+ ? "STANDBY" : "UNKNOWN"));
if ((NewPhysicalDeviceInfo->ParityErrors !=
PhysicalDeviceInfo->ParityErrors) ||
(NewPhysicalDeviceInfo->SoftErrors !=
(LogicalDeviceInfo != NULL
? "" : " - Allocation Failed"));
if (LogicalDeviceInfo != NULL)
- memset(LogicalDeviceInfo, 0,
- sizeof(DAC960_V2_LogicalDeviceInfo_T));
+ {
+ memset(LogicalDeviceInfo, 0,
+ sizeof(DAC960_V2_LogicalDeviceInfo_T));
+ DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
+ }
}
if (LogicalDeviceInfo != NULL)
{
unsigned long LogicalDeviceSize =
- NewLogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB;
+ NewLogicalDeviceInfo->ConfigurableDeviceSize;
if (NewLogicalDeviceInfo->LogicalDeviceState !=
LogicalDeviceInfo->LogicalDeviceState)
DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
kfree(LogicalDeviceInfo);
Controller->LogicalDriveInitiallyAccessible
[LogicalDriveNumber] = false;
+ DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
}
Controller->V2.NeedLogicalDeviceInformation = false;
}
}
+/*
+ DAC960_P_InterruptHandler handles hardware interrupts from DAC960 P Series
+ Controllers.
+*/
+
+static void DAC960_P_InterruptHandler(int IRQ_Channel,
+ void *DeviceIdentifier,
+ Registers_T *InterruptRegisters)
+{
+ DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+ void *ControllerBaseAddress = Controller->BaseAddress;
+ ProcessorFlags_T ProcessorFlags;
+ /*
+ Acquire exclusive access to Controller.
+ */
+ DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags);
+ /*
+ Process Hardware Interrupts for Controller.
+ */
+ while (DAC960_PD_StatusAvailableP(ControllerBaseAddress))
+ {
+ DAC960_V1_CommandIdentifier_T CommandIdentifier =
+ DAC960_PD_ReadStatusCommandIdentifier(ControllerBaseAddress);
+ DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1];
+ DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
+ DAC960_V1_CommandOpcode_T CommandOpcode =
+ CommandMailbox->Common.CommandOpcode;
+ Command->V1.CommandStatus =
+ DAC960_PD_ReadStatusRegister(ControllerBaseAddress);
+ DAC960_PD_AcknowledgeInterrupt(ControllerBaseAddress);
+ DAC960_PD_AcknowledgeStatus(ControllerBaseAddress);
+ switch (CommandOpcode)
+ {
+ case DAC960_V1_Enquiry_Old:
+ Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Enquiry;
+ DAC960_P_To_PD_TranslateEnquiry(
+ Bus32_to_Virtual(CommandMailbox->Type3.BusAddress));
+ break;
+ case DAC960_V1_GetDeviceState_Old:
+ Command->V1.CommandMailbox.Common.CommandOpcode =
+ DAC960_V1_GetDeviceState;
+ DAC960_P_To_PD_TranslateDeviceState(
+ Bus32_to_Virtual(CommandMailbox->Type3.BusAddress));
+ break;
+ case DAC960_V1_Read_Old:
+ Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Read;
+ DAC960_P_To_PD_TranslateReadWriteCommand(CommandMailbox);
+ break;
+ case DAC960_V1_Write_Old:
+ Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Write;
+ DAC960_P_To_PD_TranslateReadWriteCommand(CommandMailbox);
+ break;
+ case DAC960_V1_ReadWithScatterGather_Old:
+ Command->V1.CommandMailbox.Common.CommandOpcode =
+ DAC960_V1_ReadWithScatterGather;
+ DAC960_P_To_PD_TranslateReadWriteCommand(CommandMailbox);
+ break;
+ case DAC960_V1_WriteWithScatterGather_Old:
+ Command->V1.CommandMailbox.Common.CommandOpcode =
+ DAC960_V1_WriteWithScatterGather;
+ DAC960_P_To_PD_TranslateReadWriteCommand(CommandMailbox);
+ break;
+ default:
+ break;
+ }
+ DAC960_V1_ProcessCompletedCommand(Command);
+ }
+ /*
+ Attempt to remove additional I/O Requests from the Controller's
+ I/O Request Queue and queue them to the Controller.
+ */
+ while (DAC960_ProcessRequest(Controller, false)) ;
+ /*
+ Release exclusive access to Controller.
+ */
+ DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags);
+}
+
+
/*
DAC960_V1_QueueMonitoringCommand queues a Monitoring Command to DAC960 V1
Firmware Controllers.
Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
if (LogicalDeviceInfo == NULL) continue;
if (!LogicalDeviceInfo->LogicalDeviceControl
- .LogicalDeviceInitialized &&
- Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 0)
+ .LogicalDeviceInitialized)
{
ForceMonitoringCommand = true;
break;
if (!Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber])
{
Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true;
+ DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
DAC960_RegisterDisk(Controller, LogicalDriveNumber);
}
if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
if (LogicalDeviceInfo == NULL)
return -EINVAL;
- switch(LogicalDeviceInfo->DriveGeometry)
+ switch (LogicalDeviceInfo->DriveGeometry)
{
case DAC960_V2_Geometry_128_32:
Geometry.heads = 128;
return -EINVAL;
}
Geometry.cylinders =
- LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB
+ LogicalDeviceInfo->ConfigurableDeviceSize
/ (Geometry.heads * Geometry.sectors);
}
Geometry.start =
sizeof(DiskGeometry_T)) ? -EFAULT : 0);
case BLKGETSIZE:
/* Get Device Size. */
+ if ((unsigned long *) Argument == NULL) return -EINVAL;
return put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
.nr_sects,
- (long *) Argument);
+ (unsigned long *) Argument);
case BLKGETSIZE64:
- return put_user((u64)Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].nr_sects << 9,
+ if ((u64 *) Argument == NULL) return -EINVAL;
+ return put_user((u64) Controller->GenericDiskInfo
+ .part[MINOR(Inode->i_rdev)]
+ .nr_sects << 9,
(u64 *) Argument);
case BLKRAGET:
case BLKRASET:
case BLKFLSBUF:
case BLKBSZGET:
case BLKBSZSET:
- return blk_ioctl (Inode->i_rdev, Request, Argument);
-
+ return blk_ioctl(Inode->i_rdev, Request, Argument);
case BLKRRPART:
/* Re-Read Partition Table. */
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
*/
set_blocksize(Device, BLOCK_SIZE);
}
- if (Controller->FirmwareType == DAC960_V1_Controller)
- grok_partitions(&Controller->GenericDiskInfo,
- LogicalDriveNumber,
- DAC960_MaxPartitions,
- Controller->V1.LogicalDriveInformation
- [LogicalDriveNumber]
- .LogicalDriveSize);
- else
- grok_partitions(
- &Controller->GenericDiskInfo,
- LogicalDriveNumber,
- DAC960_MaxPartitions,
- Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]
- ->ConfigurableDeviceSizeIn512ByteBlocksOrMB);
+ DAC960_RegisterDisk(Controller, LogicalDriveNumber);
return 0;
}
return -EINVAL;
== DAC960_V2_NormalCompletion
? "Cancelled" : "Not Cancelled"));
}
+ else if (strcmp(UserCommand, "perform-discovery") == 0)
+ {
+ CommandMailbox->Common.IOCTL_Opcode = DAC960_V2_StartDiscovery;
+ DAC960_ExecuteCommand(Command);
+ DAC960_UserCritical("Discovery %s\n", Controller,
+ (Command->V2.CommandStatus
+ == DAC960_V2_NormalCompletion
+ ? "Initiated" : "Not Initiated"));
+ if (Command->V2.CommandStatus == DAC960_V2_NormalCompletion)
+ {
+ CommandMailbox->ControllerInfo.CommandOpcode = DAC960_V2_IOCTL;
+ CommandMailbox->ControllerInfo.CommandControlBits
+ .DataTransferControllerToHost = true;
+ CommandMailbox->ControllerInfo.CommandControlBits
+ .NoAutoRequestSense = true;
+ CommandMailbox->ControllerInfo.DataTransferSize =
+ sizeof(DAC960_V2_ControllerInfo_T);
+ CommandMailbox->ControllerInfo.ControllerNumber = 0;
+ CommandMailbox->ControllerInfo.IOCTL_Opcode =
+ DAC960_V2_GetControllerInfo;
+ CommandMailbox->ControllerInfo.DataTransferMemoryAddress
+ .ScatterGatherSegments[0]
+ .SegmentDataPointer =
+ Virtual_to_Bus64(&Controller->V2.NewControllerInformation);
+ CommandMailbox->ControllerInfo.DataTransferMemoryAddress
+ .ScatterGatherSegments[0]
+ .SegmentByteCount =
+ CommandMailbox->ControllerInfo.DataTransferSize;
+ DAC960_ExecuteCommand(Command);
+ while (Controller->V2.NewControllerInformation.PhysicalScanActive)
+ {
+ DAC960_ExecuteCommand(Command);
+ sleep_on_timeout(&Controller->CommandWaitQueue, HZ);
+ }
+ DAC960_UserCritical("Discovery Completed\n", Controller);
+ }
+ }
else if (strcmp(UserCommand, "suppress-enclosure-messages") == 0)
Controller->SuppressEnclosureMessages = true;
else DAC960_UserCritical("Illegal User Command: '%s'\n",
}
-/*
- Include Module support if requested.
-*/
-
-#ifdef MODULE
-
-
-int init_module(void)
-{
- DAC960_Initialize();
- return (DAC960_ActiveControllerCount > 0 ? 0 : -1);
-}
-
-
-void cleanup_module(void)
-{
- DAC960_Finalize(&DAC960_NotifierBlock, SYS_RESTART, NULL);
-}
-
-
-#endif
+module_init(DAC960_Initialize);
+module_exit(DAC960_Finalize);
DAC960_V1_ReadExtendedWithScatterGather = 0xB3,
DAC960_V1_WriteExtendedWithScatterGather = 0xB4,
DAC960_V1_Read = 0x36,
- DAC960_V1_ReadWithOldScatterGather = 0xB6,
+ DAC960_V1_ReadWithScatterGather = 0xB6,
DAC960_V1_Write = 0x37,
- DAC960_V1_WriteWithOldScatterGather = 0xB7,
+ DAC960_V1_WriteWithScatterGather = 0xB7,
DAC960_V1_DCDB = 0x04,
DAC960_V1_DCDBWithScatterGather = 0x84,
DAC960_V1_Flush = 0x0A,
DAC960_V1_RunDiagnostic = 0x32,
/* Subsystem Service Commands */
DAC960_V1_GetSubsystemData = 0x70,
- DAC960_V1_SetSubsystemParameters = 0x71
+ DAC960_V1_SetSubsystemParameters = 0x71,
+ /* Version 2.xx Firmware Commands */
+ DAC960_V1_Enquiry_Old = 0x05,
+ DAC960_V1_GetDeviceState_Old = 0x14,
+ DAC960_V1_Read_Old = 0x02,
+ DAC960_V1_Write_Old = 0x03,
+ DAC960_V1_ReadWithScatterGather_Old = 0x82,
+ DAC960_V1_WriteWithScatterGather_Old = 0x83
}
__attribute__ ((packed))
DAC960_V1_CommandOpcode_T;
#define DAC960_V1_RebuildFailed_NewDriveFailed 0x0004 /* Consistency */
#define DAC960_V1_RebuildSuccessful 0x0100 /* Consistency */
#define DAC960_V1_RebuildSuccessfullyTerminated 0x0107 /* Consistency */
+#define DAC960_V1_BackgroundInitSuccessful 0x0100 /* Consistency */
+#define DAC960_V1_BackgroundInitAborted 0x0005 /* Consistency */
+#define DAC960_V1_NoBackgroundInitInProgress 0x0105 /* Consistency */
#define DAC960_V1_AddCapacityInProgress 0x0004 /* Consistency */
#define DAC960_V1_AddCapacityFailedOrSuspended 0x00F4 /* Consistency */
#define DAC960_V1_Config2ChecksumError 0x0002 /* Configuration */
/*
Define the DAC960 V1 Firmware Get Device State Command reply structure.
+ The structure is padded by 2 bytes for compatibility with Version 2.xx
+ Firmware.
*/
typedef struct DAC960_V1_DeviceState
unsigned char SynchronousOffset:5; /* Byte 5 Bits 0-4 */
unsigned char :3; /* Byte 5 Bits 5-7 */
unsigned int DiskSize __attribute__ ((packed)); /* Bytes 6-9 */
+ unsigned short :16; /* Bytes 10-11 */
}
DAC960_V1_DeviceState_T;
DAC960_V1_RebuildProgress_T;
+/*
+ Define the DAC960 V1 Firmware Background Initialization Status Command
+ reply structure.
+*/
+
+typedef struct DAC960_V1_BackgroundInitializationStatus
+{
+ unsigned int LogicalDriveSize; /* Bytes 0-3 */
+ unsigned int BlocksCompleted; /* Bytes 4-7 */
+ unsigned char Reserved1[12]; /* Bytes 8-19 */
+ unsigned int LogicalDriveNumber; /* Bytes 20-23 */
+ unsigned char RAIDLevel; /* Byte 24 */
+ enum {
+ DAC960_V1_BackgroundInitializationInvalid = 0x00,
+ DAC960_V1_BackgroundInitializationStarted = 0x02,
+ DAC960_V1_BackgroundInitializationInProgress = 0x04,
+ DAC960_V1_BackgroundInitializationSuspended = 0x05,
+ DAC960_V1_BackgroundInitializationCancelled = 0x06
+ } __attribute__ ((packed)) Status; /* Byte 25 */
+ unsigned char Reserved2[6]; /* Bytes 26-31 */
+}
+DAC960_V1_BackgroundInitializationStatus_T;
+
+
/*
Define the DAC960 V1 Firmware Error Table Entry structure.
*/
DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */
unsigned char Dummy2[4]; /* Bytes 12-15 */
} __attribute__ ((packed)) Type3;
+ struct {
+ DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */
+ DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
+ unsigned char CommandOpcode2; /* Byte 2 */
+ unsigned char Dummy1[5]; /* Bytes 3-7 */
+ DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */
+ unsigned char Dummy2[4]; /* Bytes 12-15 */
+ } __attribute__ ((packed)) Type3B;
struct {
DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */
DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */
DAC960_V2_GetPhysicalDeviceInfoValid = 0x05,
DAC960_V2_GetHealthStatus = 0x11,
DAC960_V2_GetEvent = 0x15,
+ DAC960_V2_StartDiscovery = 0x81,
DAC960_V2_SetDeviceState = 0x82,
DAC960_V2_RebuildDeviceStart = 0x88,
DAC960_V2_RebuildDeviceStop = 0x89,
#define DAC960_V2_NormalCompletion 0x00
#define DAC960_V2_AbormalCompletion 0x02
+#define DAC960_V2_DeviceBusy 0x08
#define DAC960_V2_DeviceNonresponsive 0x0E
+#define DAC960_V2_DeviceNonresponsive2 0x0F
+#define DAC960_V2_DeviceRevervationConflict 0x18
typedef unsigned char DAC960_V2_CommandStatus_T;
DAC960_V2_EXR2000P = 0x1C,
DAC960_V2_EXR3000P = 0x1D,
DAC960_V2_AcceleRAID352 = 0x1E,
- DAC960_V2_AcceleRAID351 = 0x1F,
+ DAC960_V2_AcceleRAID170 = 0x1F,
+ DAC960_V2_AcceleRAID160 = 0x20,
DAC960_V2_DAC960S = 0x60,
DAC960_V2_DAC960SU = 0x61,
DAC960_V2_DAC960SX = 0x62,
unsigned char :8; /* Byte 3 */
unsigned short BusInterfaceSpeedMHz; /* Bytes 4-5 */
unsigned char BusWidthBits; /* Byte 6 */
- unsigned char Reserved1[9]; /* Bytes 7-15 */
+ unsigned char FlashCodeTypeOrProductID; /* Byte 7 */
+ unsigned char NumberOfHostPortsPresent; /* Byte 8 */
+ unsigned char Reserved1[7]; /* Bytes 9-15 */
unsigned char BusInterfaceName[16]; /* Bytes 16-31 */
unsigned char ControllerName[16]; /* Bytes 32-47 */
unsigned char Reserved2[16]; /* Bytes 48-63 */
unsigned char HardwareManufacturingMonth; /* Byte 85 */
unsigned char HardwareManufacturingYearHigh2Digits; /* Byte 86 */
unsigned char HardwareManufacturingYearLow2Digits; /* Byte 87 */
- unsigned char MaximumNumberOfPDDperXLDD; /* Byte 88 */
- unsigned char MaximumNumberOfILDDperXLDD; /* Byte 89 */
+ unsigned char MaximumNumberOfPDDperXLD; /* Byte 88 */
+ unsigned char MaximumNumberOfILDperXLD; /* Byte 89 */
unsigned short NonvolatileMemorySizeKB; /* Bytes 90-91 */
- unsigned char MaximumNumberOfXLDD; /* Byte 92 */
+ unsigned char MaximumNumberOfXLD; /* Byte 92 */
unsigned int :24; /* Bytes 93-95 */
/* Unique Information per Controller */
unsigned char ControllerSerialNumber[16]; /* Bytes 96-111 */
unsigned char Reserved3[16]; /* Bytes 112-127 */
/* Vendor Information */
unsigned int :24; /* Bytes 128-130 */
- unsigned char OEM_Information; /* Byte 131 */
+ unsigned char OEM_Code; /* Byte 131 */
unsigned char VendorName[16]; /* Bytes 132-147 */
/* Other Physical/Controller/Operation Information */
boolean BBU_Present:1; /* Byte 148 Bit 0 */
unsigned short PhysicalDeviceHostCommandAbortsDone; /* Bytes 370-371 */
unsigned short PhysicalDevicePredictedFailuresDetected; /* Bytes 372-373 */
unsigned short PhysicalDeviceHostCommandsFailed; /* Bytes 374-375 */
- unsigned char Reserved9[8]; /* Bytes 376-383 */
+ unsigned short PhysicalDeviceHardErrors; /* Bytes 376-377 */
+ unsigned char Reserved9[6]; /* Bytes 378-383 */
/* Error Counters on Logical Devices */
unsigned short LogicalDeviceSoftErrors; /* Bytes 384-385 */
unsigned short LogicalDeviceCommandsFailed; /* Bytes 386-387 */
unsigned short LogicalDeviceHostCommandAbortsDone; /* Bytes 388-389 */
unsigned short :16; /* Bytes 390-391 */
+ /* Error Counters on Controller */
unsigned short ControllerMemoryErrors; /* Bytes 392-393 */
unsigned short ControllerHostCommandAbortsDone; /* Bytes 394-395 */
unsigned int :32; /* Bytes 396-399 */
unsigned short RebuildsActive; /* Bytes 408-409 */
unsigned short OnlineExpansionsActive; /* Bytes 410-411 */
unsigned short PatrolActivitiesActive; /* Bytes 412-413 */
- unsigned char LongOperationStatus; /* Byte 414 */
- unsigned char :8; /* Byte 415 */
+ unsigned short :16; /* Bytes 414-415 */
/* Flash ROM Information */
unsigned char FlashType; /* Byte 416 */
unsigned char :8; /* Byte 417 */
unsigned short NumberOfConfigurationGroups; /* Bytes 474-475 */
boolean InstallationAbortStatus:1; /* Byte 476 Bit 0 */
boolean MaintenanceModeStatus:1; /* Byte 476 Bit 1 */
- unsigned int :6; /* Byte 476 Bits 2-7 */
- unsigned int :24; /* Bytes 477-479 */
+ unsigned int :24; /* Bytes 476-479 */
unsigned char Reserved10[32]; /* Bytes 480-511 */
unsigned char Reserved11[512]; /* Bytes 512-1023 */
}
DAC960_V2_Geometry_Reserved1 = 0x2,
DAC960_V2_Geometry_Reserved2 = 0x3
} __attribute__ ((packed)) DriveGeometry:2; /* Byte 14 Bits 5-6 */
- unsigned char :1; /* Byte 14 Bit 7 */
+ boolean SuperReadAheadEnabled:1; /* Byte 14 Bit 7 */
unsigned char :8; /* Byte 15 */
/* Error Counters */
unsigned short SoftErrors; /* Bytes 16-17 */
/* Device Size Information */
unsigned short :16; /* Bytes 32-33 */
unsigned short DeviceBlockSizeInBytes; /* Bytes 34-35 */
- unsigned int OriginalDeviceSizeIn512ByteBlocksOrMB; /* Bytes 36-39 */
- unsigned int ConfigurableDeviceSizeIn512ByteBlocksOrMB; /* Bytes 40-43 */
+ unsigned int OriginalDeviceSize; /* Bytes 36-39 */
+ unsigned int ConfigurableDeviceSize; /* Bytes 40-43 */
unsigned int :32; /* Bytes 44-47 */
unsigned char LogicalDeviceName[32]; /* Bytes 48-79 */
unsigned char SCSI_InquiryData[36]; /* Bytes 80-115 */
{
DAC960_V2_Device_Unconfigured = 0x00,
DAC960_V2_Device_Online = 0x01,
- DAC960_V2_Device_WriteOnly = 0x03,
+ DAC960_V2_Device_Rebuild = 0x03,
+ DAC960_V2_Device_Missing = 0x04,
+ DAC960_V2_Device_Critical = 0x05,
DAC960_V2_Device_Dead = 0x08,
+ DAC960_V2_Device_SuspectedDead = 0x0C,
+ DAC960_V2_Device_CommandedOffline = 0x10,
DAC960_V2_Device_Standby = 0x21,
DAC960_V2_Device_InvalidState = 0xFF
}
unsigned char LogicalUnit; /* Byte 3 */
/* Configuration Status Bits */
boolean PhysicalDeviceFaultTolerant:1; /* Byte 4 Bit 0 */
- boolean :1; /* Byte 4 Bit 1 */
+ boolean PhysicalDeviceConnected:1; /* Byte 4 Bit 1 */
boolean PhysicalDeviceLocalToController:1; /* Byte 4 Bit 2 */
unsigned char :5; /* Byte 4 Bits 3-7 */
/* Multiple Host/Controller Status Bits */
unsigned int :32; /* Bytes 44-47 */
unsigned short :16; /* Bytes 48-49 */
unsigned short DeviceBlockSizeInBytes; /* Bytes 50-51 */
- unsigned int OriginalDeviceSizeIn512ByteBlocksOrMB; /* Bytes 52-55 */
- unsigned int ConfigurableDeviceSizeIn512ByteBlocksOrMB; /* Bytes 56-59 */
+ unsigned int OriginalDeviceSize; /* Bytes 52-55 */
+ unsigned int ConfigurableDeviceSize; /* Bytes 56-59 */
unsigned int :32; /* Bytes 60-63 */
unsigned char PhysicalDeviceName[16]; /* Bytes 64-79 */
unsigned char Reserved1[16]; /* Bytes 80-95 */
unsigned char Reserved2[32]; /* Bytes 96-127 */
unsigned char SCSI_InquiryData[36]; /* Bytes 128-163 */
- unsigned char Reserved3[12]; /* Bytes 164-175 */
- unsigned char Reserved4[16]; /* Bytes 176-191 */
+ unsigned char Reserved3[20]; /* Bytes 164-183 */
+ unsigned char Reserved4[8]; /* Bytes 184-191 */
DAC960_ByteCount64_T LastReadBlockNumber; /* Bytes 192-199 */
DAC960_ByteCount64_T LastWrittenBlockNumber; /* Bytes 200-207 */
DAC960_ByteCount64_T ConsistencyCheckBlockNumber; /* Bytes 208-215 */
DAC960_V2_RAID_Channel = 0x03,
DAC960_V2_Physical_Controller = 0x04,
DAC960_V2_RAID_Controller = 0x05,
- DAC960_V2_Configuration_Group = 0x10
+ DAC960_V2_Configuration_Group = 0x10,
+ DAC960_V2_Enclosure = 0x11
}
__attribute__ ((packed))
DAC960_V2_OperationDevice_T;
DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */
DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */
DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */
- DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */
- unsigned char DataTransferPageNumber; /* Byte 7 */
+ DAC960_ByteCount32_T DataTransferSize; /* Bytes 4-7 */
DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */
DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */
DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */
DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */
DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */
DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */
- DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */
- unsigned char DataTransferPageNumber; /* Byte 7 */
+ DAC960_ByteCount32_T DataTransferSize; /* Bytes 4-7 */
DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */
DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */
DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */
DataTransferMemoryAddress; /* Bytes 32-63 */
} DeviceOperation;
}
-__attribute__ ((packed))
DAC960_V2_CommandMailbox_T;
DAC960_LP_Controller = 2, /* AcceleRAID 352 */
DAC960_LA_Controller = 3, /* DAC1164P */
DAC960_PG_Controller = 4, /* DAC960PTL/PJ/PG */
- DAC960_PD_Controller = 5 /* DAC960PU/PD/PL */
+ DAC960_PD_Controller = 5, /* DAC960PU/PD/PL/P */
+ DAC960_P_Controller = 6 /* DAC960PU/PD/PL/P */
}
DAC960_HardwareType_T;
unsigned short DeviceStateChannel;
unsigned short DeviceStateTargetID;
boolean DualModeMemoryMailboxInterface;
+ boolean BackgroundInitializationStatusSupported;
boolean SAFTE_EnclosureManagementEnabled;
boolean NeedLogicalDriveInformation;
boolean NeedErrorTableInformation;
boolean NeedDeviceSerialNumberInformation;
boolean NeedRebuildProgress;
boolean NeedConsistencyCheckProgress;
+ boolean NeedBackgroundInitializationStatus;
boolean StartDeviceStateScan;
boolean RebuildProgressFirst;
boolean RebuildFlagPending;
DAC960_V1_CommandStatus_T PendingRebuildStatus;
DAC960_V1_LogicalDriveInformationArray_T LogicalDriveInformation;
DAC960_V1_LogicalDriveInformationArray_T NewLogicalDriveInformation;
+ DAC960_V1_BackgroundInitializationStatus_T
+ BackgroundInitializationStatus;
+ DAC960_V1_BackgroundInitializationStatus_T
+ LastBackgroundInitializationStatus;
DAC960_V1_DeviceState_T
DeviceState[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
DAC960_V1_DeviceState_T NewDeviceState;
return true;
}
+static inline void DAC960_P_To_PD_TranslateEnquiry(void *Enquiry)
+{
+ memcpy(Enquiry + 132, Enquiry + 36, 64);
+ memset(Enquiry + 36, 0, 96);
+}
+
+static inline void DAC960_P_To_PD_TranslateDeviceState(void *DeviceState)
+{
+ memcpy(DeviceState + 2, DeviceState + 3, 1);
+ memcpy(DeviceState + 4, DeviceState + 5, 2);
+ memcpy(DeviceState + 6, DeviceState + 8, 4);
+}
+
+static inline
+void DAC960_PD_To_P_TranslateReadWriteCommand(DAC960_V1_CommandMailbox_T
+ *CommandMailbox)
+{
+ int LogicalDriveNumber = CommandMailbox->Type5.LD.LogicalDriveNumber;
+ CommandMailbox->Bytes[3] &= 0x7;
+ CommandMailbox->Bytes[3] |= CommandMailbox->Bytes[7] << 6;
+ CommandMailbox->Bytes[7] = LogicalDriveNumber;
+}
+
+static inline
+void DAC960_P_To_PD_TranslateReadWriteCommand(DAC960_V1_CommandMailbox_T
+ *CommandMailbox)
+{
+ int LogicalDriveNumber = CommandMailbox->Bytes[7];
+ CommandMailbox->Bytes[7] = CommandMailbox->Bytes[3] >> 6;
+ CommandMailbox->Bytes[3] &= 0x7;
+ CommandMailbox->Bytes[3] |= LogicalDriveNumber << 3;
+}
+
/*
Define prototypes for the forward referenced DAC960 Driver Internal Functions.
*/
static void DAC960_FinalizeController(DAC960_Controller_T *);
-static int DAC960_Finalize(NotifierBlock_T *, unsigned long, void *);
+static int DAC960_Notifier(NotifierBlock_T *, unsigned long, void *);
static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *);
static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *);
static void DAC960_RequestFunction(RequestQueue_T *);
static void DAC960_LA_InterruptHandler(int, void *, Registers_T *);
static void DAC960_PG_InterruptHandler(int, void *, Registers_T *);
static void DAC960_PD_InterruptHandler(int, void *, Registers_T *);
+static void DAC960_P_InterruptHandler(int, void *, Registers_T *);
static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *);
static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *);
static void DAC960_MonitoringTimerFunction(unsigned long);
extern int blk_dev_init(void);
-#ifdef CONFIG_BLK_DEV_DAC960
-extern void DAC960_Initialize(void);
-#endif
#ifdef CONFIG_FUSION_BOOT
extern int fusion_init(void);
#endif
#ifdef CONFIG_I2O
i2o_init();
#endif
-#ifdef CONFIG_BLK_DEV_DAC960
- DAC960_Initialize();
-#endif
#ifdef CONFIG_FUSION_BOOT
fusion_init();
#endif
static int max_loop = 8;
static struct loop_device *loop_dev;
-static unsigned long *loop_sizes;
+static int *loop_sizes;
static int *loop_blksizes;
static devfs_handle_t devfs_handle; /* For the directory */
err = -ENXIO;
break;
}
- err = put_user(loop_sizes[lo->lo_number] << 1, (unsigned long *) arg);
+ err = put_user((unsigned long)loop_sizes[lo->lo_number] << 1, (unsigned long *) arg);
break;
case BLKGETSIZE64:
if (lo->lo_state != Lo_bound) {
if (!loop_dev)
return -ENOMEM;
- loop_sizes = kmalloc(max_loop * sizeof(unsigned long), GFP_KERNEL);
+ loop_sizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL);
if (!loop_sizes)
goto out_sizes;
spin_lock_init(&lo->lo_lock);
}
- memset(loop_sizes, 0, max_loop * sizeof(unsigned long));
+ memset(loop_sizes, 0, max_loop * sizeof(int));
memset(loop_blksizes, 0, max_loop * sizeof(int));
blk_size[MAJOR_NR] = loop_sizes;
blksize_size[MAJOR_NR] = loop_blksizes;
page = pte_page(*pte);
get_page(page);
- DRM_DEBUG("0x%08lx => 0x%08x\n", address, page_to_bus(page));
+ DRM_DEBUG("shm_nopage 0x%lx\n", address);
#if LINUX_VERSION_CODE < 0x020317
return page_address(page);
#else
get_page(page);
- DRM_DEBUG("0x%08lx (page %lu) => 0x%08x\n", address, page_nr,
- page_to_bus(page));
+ DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr);
#if LINUX_VERSION_CODE < 0x020317
return page_address(page);
#else
O_TARGET := ieee1394drv.o
-export-objs := ieee1394_syms.o ohci1394.o
+export-objs := ieee1394_core.o ohci1394.o
list-multi := ieee1394.o
ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
- highlevel.o csr.o nodemgr.o ieee1394_syms.o
+ highlevel.o csr.o nodemgr.o
obj-$(CONFIG_IEEE1394) += ieee1394.o
obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
#define SPEED_100 0x0
#define SPEED_200 0x1
-#define SPEED_400 0x2
+#define SPEED_400 0x2
+
+/* Maps speed values above to a string representation */
+extern const char *hpsb_speedto_str[];
#define SELFID_PWRCL_NO_POWER 0x0
#define SELFID_PWRCL_PROVIDE_15W 0x1
#include "ieee1394_transactions.h"
#include "csr.h"
#include "nodemgr.h"
+#include "ieee1394_hotplug.h"
/*
* Disable the nodemgr detection and config rom reading functionality.
MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
static int disable_nodemgr = 0;
+/* We are GPL, so treat us special */
+MODULE_LICENSE("GPL");
+
static kmem_cache_t *hpsb_packet_cache;
+/* Some globals used */
+const char *hpsb_speedto_str[] = { "S100", "S200", "S400" };
static void dump_packet(const char *text, quadlet_t *data, int size)
{
module_init(ieee1394_init);
module_exit(ieee1394_cleanup);
+
+/* Exported symbols */
+EXPORT_SYMBOL(hpsb_register_lowlevel);
+EXPORT_SYMBOL(hpsb_unregister_lowlevel);
+EXPORT_SYMBOL(hpsb_get_host);
+EXPORT_SYMBOL(hpsb_inc_host_usage);
+EXPORT_SYMBOL(hpsb_dec_host_usage);
+EXPORT_SYMBOL(hpsb_speedto_str);
+
+EXPORT_SYMBOL(alloc_hpsb_packet);
+EXPORT_SYMBOL(free_hpsb_packet);
+EXPORT_SYMBOL(hpsb_send_packet);
+EXPORT_SYMBOL(hpsb_reset_bus);
+EXPORT_SYMBOL(hpsb_bus_reset);
+EXPORT_SYMBOL(hpsb_selfid_received);
+EXPORT_SYMBOL(hpsb_selfid_complete);
+EXPORT_SYMBOL(hpsb_packet_sent);
+EXPORT_SYMBOL(hpsb_packet_received);
+
+EXPORT_SYMBOL(get_tlabel);
+EXPORT_SYMBOL(free_tlabel);
+EXPORT_SYMBOL(fill_async_readquad);
+EXPORT_SYMBOL(fill_async_readquad_resp);
+EXPORT_SYMBOL(fill_async_readblock);
+EXPORT_SYMBOL(fill_async_readblock_resp);
+EXPORT_SYMBOL(fill_async_writequad);
+EXPORT_SYMBOL(fill_async_writeblock);
+EXPORT_SYMBOL(fill_async_write_resp);
+EXPORT_SYMBOL(fill_async_lock);
+EXPORT_SYMBOL(fill_async_lock_resp);
+EXPORT_SYMBOL(fill_iso_packet);
+EXPORT_SYMBOL(fill_phy_packet);
+EXPORT_SYMBOL(hpsb_make_readqpacket);
+EXPORT_SYMBOL(hpsb_make_readbpacket);
+EXPORT_SYMBOL(hpsb_make_writeqpacket);
+EXPORT_SYMBOL(hpsb_make_writebpacket);
+EXPORT_SYMBOL(hpsb_make_lockpacket);
+EXPORT_SYMBOL(hpsb_make_phypacket);
+EXPORT_SYMBOL(hpsb_packet_success);
+EXPORT_SYMBOL(hpsb_make_packet);
+EXPORT_SYMBOL(hpsb_read);
+EXPORT_SYMBOL(hpsb_write);
+EXPORT_SYMBOL(hpsb_lock);
+
+EXPORT_SYMBOL(hpsb_register_highlevel);
+EXPORT_SYMBOL(hpsb_unregister_highlevel);
+EXPORT_SYMBOL(hpsb_register_addrspace);
+EXPORT_SYMBOL(hpsb_listen_channel);
+EXPORT_SYMBOL(hpsb_unlisten_channel);
+EXPORT_SYMBOL(highlevel_read);
+EXPORT_SYMBOL(highlevel_write);
+EXPORT_SYMBOL(highlevel_lock);
+EXPORT_SYMBOL(highlevel_lock64);
+EXPORT_SYMBOL(highlevel_add_host);
+EXPORT_SYMBOL(highlevel_remove_host);
+EXPORT_SYMBOL(highlevel_host_reset);
+EXPORT_SYMBOL(highlevel_add_one_host);
+
+EXPORT_SYMBOL(hpsb_guid_get_entry);
+EXPORT_SYMBOL(hpsb_nodeid_get_entry);
+EXPORT_SYMBOL(hpsb_get_host_by_ne);
+EXPORT_SYMBOL(hpsb_guid_fill_packet);
+EXPORT_SYMBOL(hpsb_register_protocol);
+EXPORT_SYMBOL(hpsb_unregister_protocol);
+EXPORT_SYMBOL(hpsb_release_unit_directory);
#define INIT_TQ_HEAD(tq) INIT_LIST_HEAD(&(tq))
#endif
+/* This showed up around this time */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,12)
+
+# ifndef MODULE_LICENSE
+# define MODULE_LICENSE(x)
+# endif
+
+# ifndef min
+# define min(x,y) ({ \
+ const typeof(x) _x = (x); \
+ const typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x < _y ? _x : _y; })
+# endif
+
+#endif /* Linux version < 2.4.12 */
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
#include <asm/spinlock.h>
#else
#define LOCAL_BUS 0xffc0
#define ALL_NODES 0x003f
+#define NODE_BUS_FMT "%d:%d"
+#define NODE_BUS_ARGS(nodeid) \
+ (nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
+
#define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args)
#define HPSB_DEBUG(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args)
#include "nodemgr.h"
-#define NODE_BUS_FMT "%d:%d"
-#define NODE_BUS_ARGS(nodeid) \
- (nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
-
-/* Basically what we do here is start off retrieving the bus_info block.
+/*
+ * Basically what we do here is start off retrieving the bus_info block.
* From there will fill in some info about the node, verify it is of IEEE
* 1394 type, and that the crc checks out ok. After that we start off with
* the root directory, and subdirectories. To do this, we retrieve the
* We verify CRC's along the way for each directory/block/leaf. The
* entire node structure is generic, and simply stores the information in
* a way that's easy to parse by the protocol interface.
- *
- * XXX: Most of this isn't done yet :) */
-
+ */
static LIST_HEAD(node_list);
static rwlock_t node_lock = RW_LOCK_UNLOCKED;
* add some init code to the kernel to support this... and modules are much
* more flexible anyway. ;-)
*
+ * - The scsi stack in recent kernels pass down the data transfer
+ * direction as scsicmd->sc_data_direction, which we should use
+ * instead of the sbp2scsi_direction_table.
+ *
*
* History:
*
#if CONFIG_IEEE1394_SBP2_DEBUG >= 2
-#define SBP2_DEBUG(fmt, args...) HPSB_ERR(fmt, ## args)
-#define SBP2_INFO(fmt, args...) HPSB_ERR(fmt, ## args)
-#define SBP2_NOTICE(fmt, args...) HPSB_ERR(fmt, ## args)
-#define SBP2_WARN(fmt, args...) HPSB_ERR(fmt, ## args)
+#define SBP2_DEBUG(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
+#define SBP2_INFO(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
+#define SBP2_NOTICE(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
+#define SBP2_WARN(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
#elif CONFIG_IEEE1394_SBP2_DEBUG == 1
-#define SBP2_DEBUG(fmt, args...) HPSB_DEBUG(fmt, ## args)
-#define SBP2_INFO(fmt, args...) HPSB_INFO(fmt, ## args)
-#define SBP2_NOTICE(fmt, args...) HPSB_NOTICE(fmt, ## args)
-#define SBP2_WARN(fmt, args...) HPSB_WARN(fmt, ## args)
+#define SBP2_DEBUG(fmt, args...) HPSB_DEBUG("sbp2: "fmt, ## args)
+#define SBP2_INFO(fmt, args...) HPSB_INFO("sbp2: "fmt, ## args)
+#define SBP2_NOTICE(fmt, args...) HPSB_NOTICE("sbp2: "fmt, ## args)
+#define SBP2_WARN(fmt, args...) HPSB_WARN("sbp2: "fmt, ## args)
#else
-#define SBP2_DEBUG(fmt, args...)
-#define SBP2_INFO(fmt, args...)
-#define SBP2_NOTICE(fmt, args...)
-#define SBP2_WARN(fmt, args...)
+#define SBP2_DEBUG(fmt, args...)
+#define SBP2_INFO(fmt, args...)
+#define SBP2_NOTICE(fmt, args...)
+#define SBP2_WARN(fmt, args...)
#endif
-#define SBP2_ERR(fmt, args...) HPSB_ERR(fmt, ## args)
+#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
/*
* Spinlock debugging stuff. I'm playing it safe until the driver has been
Scsi_Host_Template *global_scsi_tpnt = NULL;
+static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 };
+
static LIST_HEAD(sbp2_host_info_list);
static int sbp2_host_count = 0;
packet = alloc_hpsb_packet(8);
if (!packet) {
- SBP2_ERR("sbp2: sbp2util_create_request_packet_pool - packet allocation failed!");
+ SBP2_ERR("sbp2util_create_request_packet_pool - packet allocation failed!");
return(-ENOMEM);
}
list_add_tail(&request_packet->list, &hi->sbp2_req_inuse);
} else {
- SBP2_ERR("sbp2: sbp2util_allocate_request_packet - no packets available!");
+ SBP2_ERR("sbp2util_allocate_request_packet - no packets available!");
}
sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);
command->linked = 0;
list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);
} else {
- SBP2_ERR("sbp2: sbp2util_allocate_command_orb - No orbs available!");
+ SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
}
sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
return (command);
*/
int sbp2_init(void)
{
- SBP2_DEBUG("sbp2: sbp2_init");
+ SBP2_DEBUG("sbp2_init");
/*
* Register our high level driver with 1394 stack
sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME, &sbp2_hl_ops);
if (sbp2_hl_handle == NULL) {
- SBP2_ERR("sbp2: sbp2 failed to register with ieee1394 highlevel");
+ SBP2_ERR("sbp2 failed to register with ieee1394 highlevel");
return(-ENOMEM);
}
*/
void sbp2_cleanup(void)
{
- SBP2_DEBUG("sbp2: sbp2_cleanup");
+ SBP2_DEBUG("sbp2_cleanup");
hpsb_unregister_protocol(&sbp2_driver);
{
struct sbp2scsi_host_info *hi;
- SBP2_DEBUG("sbp2: sbp2_probe");
+ SBP2_DEBUG("sbp2_probe");
hi = sbp2_find_host_info(ud->ne->host);
return sbp2_start_device(hi, ud);
struct sbp2scsi_host_info *hi;
struct scsi_id_instance_data *scsi_id = ud->driver_data;
- SBP2_DEBUG("sbp2: sbp2_disconnect");
+ SBP2_DEBUG("sbp2_disconnect");
hi = sbp2_find_host_info(ud->ne->host);
if (hi != NULL)
struct scsi_id_instance_data *scsi_id = ud->driver_data;
unsigned long flags;
- SBP2_DEBUG("sbp2: sbp2_update");
+ SBP2_DEBUG("sbp2_update");
hi = sbp2_find_host_info(ud->ne->host);
if (sbp2_reconnect_device(hi, scsi_id)) {
* unvalidated, so that he gets cleaned up
* later.
*/
- SBP2_ERR("sbp2: sbp2_reconnect_device failed!");
+ SBP2_ERR("sbp2_reconnect_device failed!");
sbp2_remove_device(hi, scsi_id);
return;
}
struct sbp2scsi_host_info *hi;
unsigned long flags;
- SBP2_DEBUG("sbp2: sbp2_add_host");
+ SBP2_DEBUG("sbp2_add_host");
/* Allocate some memory for our host info structure */
hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info),
GFP_KERNEL);
if (hi == NULL) {
- SBP2_ERR("sbp2: out of memory in sbp2_add_host");
+ SBP2_ERR("out of memory in sbp2_add_host");
return;
}
/* Create our request packet pool (pool of packets for use in I/O) */
if (sbp2util_create_request_packet_pool(hi)) {
- SBP2_ERR("sbp2: sbp2util_create_request_packet_pool failed!");
+ SBP2_ERR("sbp2util_create_request_packet_pool failed!");
return;
}
unsigned long flags;
int i;
- SBP2_DEBUG("sbp2: sbp2_remove_host");
+ SBP2_DEBUG("sbp2_remove_host");
sbp2_spin_lock(&sbp2_host_info_lock, flags);
kfree(hi);
}
else
- SBP2_ERR("sbp2: attempt to remove unknown host %p", host);
+ SBP2_ERR("attempt to remove unknown host %p", host);
sbp2_spin_unlock(&sbp2_host_info_lock, flags);
}
struct node_entry *ne;
int i;
- SBP2_DEBUG("sbp2: sbp2_start_device");
+ SBP2_DEBUG("sbp2_start_device");
ne = ud->ne;
/*
kfree(scsi_id);
alloc_fail_first:
- SBP2_ERR ("sbp2: Could not allocate memory for scsi_id");
+ SBP2_ERR ("Could not allocate memory for scsi_id");
return(-ENOMEM);
}
SBP2_DMA_ALLOC("consistent DMA region for login ORB");
scsi_id->ne = ne;
scsi_id->ud = ud;
scsi_id->speed_code = SPEED_100;
- scsi_id->max_payload_size = MAX_PAYLOAD_S100;
+ scsi_id->max_payload_size = sbp2_speedto_maxrec[SPEED_100];
ud->driver_data = scsi_id;
init_waitqueue_head(&scsi_id->sbp2_login_wait);
if (!hi->scsi_id[i]) {
hi->scsi_id[i] = scsi_id;
scsi_id->id = i;
- SBP2_DEBUG("sbp2: New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i);
+ SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i);
break;
}
}
* Create our command orb pool
*/
if (sbp2util_create_command_orb_pool(scsi_id, hi)) {
- SBP2_ERR("sbp2: sbp2util_create_command_orb_pool failed!");
+ SBP2_ERR("sbp2util_create_command_orb_pool failed!");
sbp2_remove_device(hi, scsi_id);
return -ENOMEM;
}
* Make sure we are not out of space
*/
if (i == SBP2SCSI_MAX_SCSI_IDS) {
- SBP2_ERR("sbp2: No slots left for SBP-2 device");
+ SBP2_ERR("No slots left for SBP-2 device");
sbp2_remove_device(hi, scsi_id);
return -EBUSY;
}
* Login failed... so, just mark him as unvalidated, so
* that he gets cleaned up later.
*/
- SBP2_ERR("sbp2: sbp2_login_device failed");
+ SBP2_ERR("sbp2_login_device failed");
sbp2_remove_device(hi, scsi_id);
return -EBUSY;
}
SBP2_DMA_FREE("single logout orb");
}
- SBP2_DEBUG("sbp2: Unvalidated SBP-2 device removed, SCSI ID = %d",
+ SBP2_DEBUG("Unvalidated SBP-2 device removed, SCSI ID = %d",
scsi_id->id);
hi->scsi_id[scsi_id->id] = NULL;
kfree(scsi_id);
quadlet_t data[2];
unsigned long flags;
- SBP2_DEBUG("sbp2: sbp2_login_device");
+ SBP2_DEBUG("sbp2_login_device");
if (!scsi_id->login_orb) {
- SBP2_DEBUG("sbp2: sbp2_login_device: login_orb not alloc'd!");
+ SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");
return(-EIO);
}
/* Set-up login ORB, assume no password */
scsi_id->login_orb->password_hi = 0;
scsi_id->login_orb->password_lo = 0;
- SBP2_DEBUG("sbp2: sbp2_login_device: password_hi/lo initialized");
+ SBP2_DEBUG("sbp2_login_device: password_hi/lo initialized");
scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma;
scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
- SBP2_DEBUG("sbp2: sbp2_login_device: login_response_hi/lo initialized");
+ SBP2_DEBUG("sbp2_login_device: login_response_hi/lo initialized");
scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(LOGIN_REQUEST);
scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */
scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(1); /* Exclusive access to device */
scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */
- SBP2_DEBUG("sbp2: sbp2_login_device: lun_misc initialized");
+ SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
scsi_id->login_orb->passwd_resp_lengths =
ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
- SBP2_DEBUG("sbp2: sbp2_login_device: passwd_resp_lengths initialized");
+ SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
SBP2_STATUS_FIFO_ADDRESS_HI);
- SBP2_DEBUG("sbp2: sbp2_login_device: status FIFO initialized");
+ SBP2_DEBUG("sbp2_login_device: status FIFO initialized");
/*
* Byte swap ORB if necessary
*/
sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb));
- SBP2_DEBUG("sbp2: sbp2_login_device: orb byte-swapped");
+ SBP2_DEBUG("sbp2_login_device: orb byte-swapped");
/*
* Initialize login response and status fifo
memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));
memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
- SBP2_DEBUG("sbp2: sbp2_login_device: login_response/status FIFO memset");
+ SBP2_DEBUG("sbp2_login_device: login_response/status FIFO memset");
/*
* Ok, let's write to the target's management agent register
data[1] = scsi_id->login_orb_dma;
sbp2util_cpu_to_be32_buffer(data, 8);
- SBP2_DEBUG("sbp2: sbp2_login_device: prepared to write");
+ SBP2_DEBUG("sbp2_login_device: prepared to write");
hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
- SBP2_DEBUG("sbp2: sbp2_login_device: written");
+ SBP2_DEBUG("sbp2_login_device: written");
/*
* Wait for login status... but, only if the device has not
sleep_on_timeout(&scsi_id->sbp2_login_wait, 10*HZ);
restore_flags(flags);
- SBP2_DEBUG("sbp2: sbp2_login_device: initial check");
+ SBP2_DEBUG("sbp2_login_device: initial check");
/*
* Match status to the login orb. If they do not match, it's
* probably because the login timed-out.
*/
if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
- SBP2_ERR("sbp2: Error logging into SBP-2 device - login timed-out");
+ SBP2_ERR("Error logging into SBP-2 device - login timed-out");
return(-EIO);
}
- SBP2_DEBUG("sbp2: sbp2_login_device: second check");
+ SBP2_DEBUG("sbp2_login_device: second check");
/*
* Check status
STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
- SBP2_ERR("sbp2: Error logging into SBP-2 device - login failed");
+ SBP2_ERR("Error logging into SBP-2 device - login failed");
return(-EIO);
}
/*
* Grab our command block agent address from the login response.
*/
- SBP2_DEBUG("sbp2: command_block_agent_hi = %x",
+ SBP2_DEBUG("command_block_agent_hi = %x",
(unsigned int)scsi_id->login_response->command_block_agent_hi);
- SBP2_DEBUG("sbp2: command_block_agent_lo = %x",
+ SBP2_DEBUG("command_block_agent_lo = %x",
(unsigned int)scsi_id->login_response->command_block_agent_lo);
scsi_id->sbp2_command_block_agent_addr =
scsi_id->sbp2_command_block_agent_addr |= ((u64)scsi_id->login_response->command_block_agent_lo);
scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL;
- SBP2_INFO("sbp2: Logged into SBP-2 device");
+ SBP2_INFO("Logged into SBP-2 device");
return(0);
{
quadlet_t data[2];
- SBP2_DEBUG("sbp2: sbp2_logout_device");
+ SBP2_DEBUG("sbp2_logout_device");
/*
* Set-up logout ORB
/* Wait for device to logout...1 second. */
sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);
- SBP2_INFO("sbp2: Logged out of SBP-2 device");
+ SBP2_INFO("Logged out of SBP-2 device");
return(0);
quadlet_t data[2];
unsigned long flags;
- SBP2_DEBUG("sbp2: sbp2_reconnect_device");
+ SBP2_DEBUG("sbp2_reconnect_device");
/*
* Set-up reconnect ORB
* probably because the reconnect timed-out.
*/
if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
- SBP2_ERR("sbp2: Error reconnecting to SBP-2 device - reconnect timed-out");
+ SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
return(-EIO);
}
STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
- SBP2_ERR("sbp2: Error reconnecting to SBP-2 device - reconnect failed");
+ SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed");
return(-EIO);
}
- SBP2_INFO("sbp2: Reconnected to SBP-2 device");
+ SBP2_INFO("Reconnected to SBP-2 device");
return(0);
{
quadlet_t data;
- SBP2_DEBUG("sbp2: sbp2_set_busy_timeout");
+ SBP2_DEBUG("sbp2_set_busy_timeout");
/*
* Ok, let's write to the target's busy timeout register
data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
if (hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
- SBP2_ERR("sbp2: sbp2_set_busy_timeout error");
+ SBP2_ERR("sbp2_set_busy_timeout error");
}
return(0);
struct unit_directory *ud;
int i;
- SBP2_DEBUG("sbp2: sbp2_parse_unit_directory");
+ SBP2_DEBUG("sbp2_parse_unit_directory");
ud = scsi_id->ud;
CONFIG_ROM_INITIAL_MEMORY_SPACE +
(ud->arb_values[i] << 2);
- SBP2_DEBUG("sbp2: sbp2_management_agent_addr = %x",
+ SBP2_DEBUG("sbp2_management_agent_addr = %x",
(unsigned int) scsi_id->sbp2_management_agent_addr);
break;
case SBP2_COMMAND_SET_SPEC_ID_KEY:
/* Command spec organization */
scsi_id->sbp2_command_set_spec_id = ud->arb_values[i];
- SBP2_DEBUG("sbp2: sbp2_command_set_spec_id = %x",
+ SBP2_DEBUG("sbp2_command_set_spec_id = %x",
(unsigned int) scsi_id->sbp2_command_set_spec_id);
break;
case SBP2_COMMAND_SET_KEY:
/* Command set used by sbp2 device */
scsi_id->sbp2_command_set = ud->arb_values[i];
- SBP2_DEBUG("sbp2: sbp2_command_set = %x",
+ SBP2_DEBUG("sbp2_command_set = %x",
(unsigned int) scsi_id->sbp2_command_set);
break;
* that I'm not yet paying attention to)
*/
scsi_id->sbp2_unit_characteristics = ud->arb_values[i];
- SBP2_DEBUG("sbp2: sbp2_unit_characteristics = %x",
+ SBP2_DEBUG("sbp2_unit_characteristics = %x",
(unsigned int) scsi_id->sbp2_unit_characteristics);
break;
* detemining type of sbp2 device)
*/
scsi_id->sbp2_device_type_and_lun = ud->arb_values[i];
- SBP2_DEBUG("sbp2: sbp2_device_type_and_lun = %x",
+ SBP2_DEBUG("sbp2_device_type_and_lun = %x",
(unsigned int) scsi_id->sbp2_device_type_and_lun);
break;
scsi_id->sbp2_firmware_revision = ud->arb_values[i];
if (scsi_id->sbp2_firmware_revision ==
SBP2_128KB_BROKEN_FIRMWARE) {
- SBP2_WARN("sbp2: warning: Bridge chipset supports 128KB max transfer size");
+ SBP2_WARN("warning: Bridge chipset supports 128KB max transfer size");
}
break;
/*
* This function is called in order to determine the max speed and packet
- * size we can use in our ORBs.
+ * size we can use in our ORBs. Note, that we (the driver and host) only
+ * initiate the transaction. The SBP-2 device actually transfers the data
+ * (by reading from the DMA area we tell it). This means that the SBP-2
+ * device decides the actual maximum data it can transfer. We just tell it
+ * the speed that it needs to use, and the max_rec the host supports, and
+ * it takes care of the rest.
*/
static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
{
- u8 speed_code;
- unsigned int max_rec;
-
- SBP2_DEBUG("sbp2: sbp2_max_speed_and_size");
-
- speed_code = scsi_id->ne->busopt.lnkspd;
- max_rec = scsi_id->ne->busopt.max_rec;
-
- /* Bump down our speed if there is a module parameter forcing us slower */
- if (speed_code > max_speed) {
- speed_code = max_speed;
- SBP2_ERR("sbp2: Reducing SBP-2 max speed allowed (%x)", max_speed);
- }
-
- /* Support the devices max_rec and max speed. We choose a setting
- * that fits both values, since they may differ. */
- if (speed_code >= SPEED_400 && max_rec >= MAX_REC_S400) {
- HPSB_INFO("sbp2: SBP-2 device max speed S400 and payload 2KB");
- scsi_id->speed_code = SPEED_400;
- scsi_id->max_payload_size = MAX_PAYLOAD_S400;
- } else if (speed_code >= SPEED_200 && max_rec >= MAX_REC_S200) {
- HPSB_INFO("sbp2: SBP-2 device max speed S200 and payload 1KB");
- scsi_id->speed_code = SPEED_200;
- scsi_id->max_payload_size = MAX_PAYLOAD_S200;
- } else {
- HPSB_INFO("sbp2: SBP-2 device max speed S100 and payload 512 bytes");
- scsi_id->speed_code = SPEED_100;
- scsi_id->max_payload_size = MAX_PAYLOAD_S100;
+ SBP2_DEBUG("sbp2_max_speed_and_size");
+
+ /* Initial setting comes from the hosts speed map */
+ scsi_id->speed_code = hi->host->speed_map[(hi->host->node_id & NODE_MASK) * 64
+ + (scsi_id->ne->nodeid & NODE_MASK)];
+
+ /* Bump down our speed if the user requested it */
+ if (scsi_id->speed_code > max_speed) {
+ scsi_id->speed_code = max_speed;
+ SBP2_ERR("Forcing SBP-2 max speed down to %s",
+ hpsb_speedto_str[scsi_id->speed_code]);
}
+ /* Payload size is the lesser of what our speed supports and what
+ * our host supports. */
+ scsi_id->max_payload_size = min(sbp2_speedto_maxrec[scsi_id->speed_code],
+ (u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1));
+
+ SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [0x%02x/%u]",
+ NODE_BUS_ARGS(scsi_id->ne->nodeid), hpsb_speedto_str[scsi_id->speed_code],
+ scsi_id->max_payload_size, 1 << ((u32)scsi_id->max_payload_size + 2));
+
return(0);
}
{
struct sbp2_request_packet *agent_reset_request_packet;
- SBP2_DEBUG("sbp2: sbp2_agent_reset");
+ SBP2_DEBUG("sbp2_agent_reset");
/*
* Ok, let's write to the target's management agent register
0, ntohl(SBP2_AGENT_RESET_DATA));
if (!agent_reset_request_packet) {
- SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
+ SBP2_ERR("sbp2util_allocate_write_request_packet failed");
return(-EIO);
}
if (!hpsb_send_packet(agent_reset_request_packet->packet)) {
- SBP2_ERR("sbp2: hpsb_send_packet failed");
+ SBP2_ERR("hpsb_send_packet failed");
sbp2util_free_request_packet(agent_reset_request_packet);
return(-EIO);
}
*/
if (sbp2scsi_direction_table[*scsi_cmd] == ORB_DIRECTION_NO_DATA_TRANSFER) {
- SBP2_DEBUG("sbp2: No data transfer");
+ SBP2_DEBUG("No data transfer");
/*
* Handle no data transfer
} else if (scsi_use_sg) {
- SBP2_DEBUG("sbp2: Use scatter/gather");
+ SBP2_DEBUG("Use scatter/gather");
/*
* Special case if only one element (and less than 64KB in size)
*/
if ((scsi_use_sg == 1) && (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
- SBP2_DEBUG("sbp2: Only one s/g element");
+ SBP2_DEBUG("Only one s/g element");
command->dma_dir = dma_dir;
command->dma_size = sgpnt[0].length;
command->cmd_dma = pci_map_single (hi->host->pdev, sgpnt[0].address,
} else {
- SBP2_DEBUG("sbp2: No scatter/gather");
+ SBP2_DEBUG("No scatter/gather");
command->dma_dir = dma_dir;
command->dma_size = scsi_request_bufflen;
SBP2_ORB_POINTER_OFFSET, 8, 0);
if (!command_request_packet) {
- SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
+ SBP2_ERR("sbp2util_allocate_write_request_packet failed");
return(-EIO);
}
SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb);
if (!hpsb_send_packet(command_request_packet->packet)) {
- SBP2_ERR("sbp2: hpsb_send_packet failed");
+ SBP2_ERR("hpsb_send_packet failed");
sbp2util_free_request_packet(command_request_packet);
return(-EIO);
}
0, cpu_to_be32(command->command_orb_dma));
if (!command_request_packet) {
- SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
+ SBP2_ERR("sbp2util_allocate_write_request_packet failed");
return(-EIO);
}
SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb);
if (!hpsb_send_packet(command_request_packet->packet)) {
- SBP2_ERR("sbp2: hpsb_send_packet failed");
+ SBP2_ERR("hpsb_send_packet failed");
sbp2util_free_request_packet(command_request_packet);
return(-EIO);
}
u32 device_type = (scsi_id->sbp2_device_type_and_lun & 0x00ff0000) >> 16;
struct sbp2_command_info *command;
- SBP2_DEBUG("sbp2: sbp2_send_command");
- SBP2_DEBUG("sbp2: SCSI command = %02x", *cmd);
- SBP2_DEBUG("sbp2: SCSI transfer size = %x", SCpnt->request_bufflen);
- SBP2_DEBUG("sbp2: SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
+ SBP2_DEBUG("sbp2_send_command");
+ SBP2_DEBUG("SCSI command = %02x", *cmd);
+ SBP2_DEBUG("SCSI transfer size = %x", SCpnt->request_bufflen);
+ SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
/*
* Check for broken devices that can't handle greater than 128K
{
unchar new_cmd[16];
- SBP2_DEBUG("sbp2: sbp2_check_sbp2_command");
+ SBP2_DEBUG("sbp2_check_sbp2_command");
switch (*cmd) {
case READ_6:
- SBP2_DEBUG("sbp2: Convert READ_6 to READ_10");
+ SBP2_DEBUG("Convert READ_6 to READ_10");
/*
* Need to turn read_6 into read_10
case WRITE_6:
- SBP2_DEBUG("sbp2: Convert WRITE_6 to WRITE_10");
+ SBP2_DEBUG("Convert WRITE_6 to WRITE_10");
/*
* Need to turn write_6 into write_10
case MODE_SENSE:
- SBP2_DEBUG("sbp2: Convert MODE_SENSE_6 to MOSE_SENSE_10");
+ SBP2_DEBUG("Convert MODE_SENSE_6 to MOSE_SENSE_10");
/*
* Need to turn mode_sense_6 into mode_sense_10
*/
static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data)
{
- SBP2_DEBUG("sbp2: sbp2_status_to_sense_data");
+ SBP2_DEBUG("sbp2_status_to_sense_data");
/*
* Ok, it's pretty ugly... ;-)
u8 *scsi_buf = SCpnt->request_buffer;
u32 device_type = (scsi_id->sbp2_device_type_and_lun & 0x00ff0000) >> 16;
- SBP2_DEBUG("sbp2: sbp2_check_sbp2_response");
+ SBP2_DEBUG("sbp2_check_sbp2_response");
switch (SCpnt->cmnd[0]) {
case INQUIRY:
- SBP2_DEBUG("sbp2: Check Inquiry data");
+ SBP2_DEBUG("Check Inquiry data");
/*
* Check for Simple Direct Access Device and change it to TYPE_DISK
*/
if ((scsi_buf[0] & 0x1f) == TYPE_SDAD) {
- SBP2_DEBUG("sbp2: Changing TYPE_SDAD to TYPE_DISK");
+ SBP2_DEBUG("Changing TYPE_SDAD to TYPE_DISK");
scsi_buf[0] &= 0xe0;
}
(device_type == TYPE_SDAD) ||
(device_type == TYPE_ROM)) {
- SBP2_DEBUG("sbp2: Modify mode sense response (10 byte version)");
+ SBP2_DEBUG("Modify mode sense response (10 byte version)");
scsi_buf[0] = scsi_buf[1]; /* Mode data length */
scsi_buf[1] = scsi_buf[2]; /* Medium type */
u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
struct sbp2_command_info *command;
- SBP2_DEBUG("sbp2: sbp2_handle_status_write");
+ SBP2_DEBUG("sbp2_handle_status_write");
if (!host) {
- SBP2_ERR("sbp2: host is NULL - this is bad!");
+ SBP2_ERR("host is NULL - this is bad!");
return(RCODE_ADDRESS_ERROR);
}
sbp2_spin_unlock(&sbp2_host_info_lock, flags);
if (!hi) {
- SBP2_ERR("sbp2: host info is NULL - this is bad!");
+ SBP2_ERR("host info is NULL - this is bad!");
return(RCODE_ADDRESS_ERROR);
}
if (hi->scsi_id[i]) {
if ((hi->scsi_id[i]->ne->nodeid & NODE_MASK) == (nodeid & NODE_MASK)) {
scsi_id = hi->scsi_id[i];
- SBP2_DEBUG("sbp2: SBP-2 status write from node %x", scsi_id->ne->nodeid);
+ SBP2_DEBUG("SBP-2 status write from node %x", scsi_id->ne->nodeid);
break;
}
}
}
if (!scsi_id) {
- SBP2_ERR("sbp2: scsi_id is NULL - device is gone?");
+ SBP2_ERR("scsi_id is NULL - device is gone?");
sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
return(RCODE_ADDRESS_ERROR);
}
command = sbp2util_find_command_for_orb(scsi_id, scsi_id->status_block.ORB_offset_lo);
if (command) {
- SBP2_DEBUG("sbp2: Found status for command ORB");
+ SBP2_DEBUG("Found status for command ORB");
SBP2_ORB_DEBUG("matched command orb %p", &command->command_orb);
outstanding_orb_decr;
*/
if (STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
- SBP2_DEBUG("sbp2: CHECK CONDITION");
+ SBP2_DEBUG("CHECK CONDITION");
/*
* Translate SBP-2 status to SCSI sense data
/*
* Complete the SCSI command
*/
- SBP2_DEBUG("sbp2: Completing SCSI command");
+ SBP2_DEBUG("Completing SCSI command");
sbp2scsi_complete_command(hi, scsi_id, scsi_status, SCpnt, command->Current_done);
SBP2_ORB_DEBUG("command orb completed");
}
struct scsi_id_instance_data *scsi_id = NULL;
unsigned long flags;
- SBP2_DEBUG("sbp2: sbp2scsi_queuecommand");
+ SBP2_DEBUG("sbp2scsi_queuecommand");
/*
* Pull our host info and scsi id instance data from the scsi command
hi = (struct sbp2scsi_host_info *) SCpnt->host->hostdata[0];
if (!hi) {
- SBP2_ERR("sbp2: sbp2scsi_host_info is NULL - this is bad!");
+ SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
SCpnt->result = DID_NO_CONNECT << 16;
done (SCpnt);
return(0);
* (autorequest sense)
*/
if (SCpnt->cmnd[0] == REQUEST_SENSE) {
- SBP2_DEBUG("sbp2: REQUEST_SENSE");
+ SBP2_DEBUG("REQUEST_SENSE");
memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen);
memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done);
* busy (to be queued later)
*/
if (!hpsb_node_entry_valid(scsi_id->ne)) {
- SBP2_ERR("sbp2: Bus reset in progress - rejecting command");
+ SBP2_ERR("Bus reset in progress - rejecting command");
SCpnt->result = DID_BUS_BUSY << 16;
done (SCpnt);
return(0);
*/
sbp2_spin_lock(&hi->sbp2_command_lock, flags);
if (sbp2_send_command(hi, scsi_id, SCpnt, done)) {
- SBP2_ERR("sbp2: Error sending SCSI command");
+ SBP2_ERR("Error sending SCSI command");
sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, SCpnt, done);
}
sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
struct list_head *lh;
struct sbp2_command_info *command;
- SBP2_DEBUG("sbp2: sbp2_complete_all_commands");
+ SBP2_DEBUG("sbp2_complete_all_commands");
while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
- SBP2_DEBUG("sbp2: Found pending command to complete");
+ SBP2_DEBUG("Found pending command to complete");
lh = scsi_id->sbp2_command_orb_inuse.next;
command = list_entry(lh, struct sbp2_command_info, list);
sbp2util_mark_command_completed(scsi_id, command);
static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status,
Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{
- SBP2_DEBUG("sbp2: sbp2scsi_complete_command");
+ SBP2_DEBUG("sbp2scsi_complete_command");
/*
* Sanity
*/
if (!SCpnt) {
- SBP2_ERR("sbp2: SCpnt is NULL");
+ SBP2_ERR("SCpnt is NULL");
return;
}
* bus reset.
*/
if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
- SBP2_ERR("sbp2: Bus reset in progress - retry command later");
+ SBP2_ERR("Bus reset in progress - retry command later");
return;
}
break;
case SBP2_SCSI_STATUS_BUSY:
- SBP2_ERR("sbp2: SBP2_SCSI_STATUS_BUSY");
+ SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
SCpnt->result = DID_BUS_BUSY << 16;
break;
case SBP2_SCSI_STATUS_CHECK_CONDITION:
- SBP2_DEBUG("sbp2: SBP2_SCSI_STATUS_CHECK_CONDITION");
+ SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
SCpnt->result = CHECK_CONDITION << 1;
/*
break;
case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
- SBP2_ERR("sbp2: SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
+ SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
SCpnt->result = DID_NO_CONNECT << 16;
break;
case SBP2_SCSI_STATUS_CONDITION_MET:
case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
- SBP2_ERR("sbp2: Bad SCSI status = %x", scsi_status);
+ SBP2_ERR("Bad SCSI status = %x", scsi_status);
SCpnt->result = DID_ERROR << 16;
break;
default:
- SBP2_ERR("sbp2: Unsupported SCSI status = %x", scsi_status);
+ SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
SCpnt->result = DID_ERROR << 16;
}
* can mount the device rw).
*/
if (mode_sense_hack && SCpnt->result != DID_OK && SCpnt->cmnd[0] == MODE_SENSE) {
- SBP2_INFO("sbp2: Returning success to mode sense command");
+ SBP2_INFO("Returning success to mode sense command");
SCpnt->result = DID_OK;
SCpnt->sense_buffer[0] = 0;
memset (SCpnt->request_buffer, 0, 8);
* the command as busy so that it will get retried.
*/
if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
- SBP2_ERR("sbp2: Completing command with busy (bus reset)");
+ SBP2_ERR("Completing command with busy (bus reset)");
SCpnt->result = DID_BUS_BUSY << 16;
}
* or hot-plug...
*/
if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) && (SCpnt->sense_buffer[2] == UNIT_ATTENTION)) {
- SBP2_INFO("sbp2: UNIT ATTENTION - return busy");
+ SBP2_INFO("UNIT ATTENTION - return busy");
SCpnt->result = DID_BUS_BUSY << 16;
}
struct sbp2_command_info *command;
unsigned long flags;
- SBP2_ERR("sbp2: aborting sbp2 command");
+ SBP2_ERR("aborting sbp2 command");
if (scsi_id) {
do {
command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
if (command) {
- SBP2_DEBUG("sbp2: Found command to abort");
+ SBP2_DEBUG("Found command to abort");
sbp2util_mark_command_completed(scsi_id, command);
if (command->Current_SCpnt && !command->linked) {
void (*done)(Scsi_Cmnd *) = command->Current_done;
{
struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->host->hostdata[0];
- SBP2_ERR("sbp2: reset requested");
+ SBP2_ERR("reset requested");
if (hi) {
- SBP2_ERR("sbp2: generating IEEE-1394 bus reset");
+ SBP2_ERR("Generating IEEE-1394 bus reset");
hpsb_reset_bus(hi->host, LONG_RESET);
}
{
int heads, sectors, cylinders;
- SBP2_DEBUG("sbp2: request for bios parameters");
+ SBP2_DEBUG("Request for bios parameters");
heads = 64;
sectors = 32;
*/
void sbp2scsi_setup( char *str, int *ints)
{
- SBP2_DEBUG("sbp2: sbp2scsi_setup");
+ SBP2_DEBUG("sbp2scsi_setup");
return;
}
*/
static int sbp2scsi_detect (Scsi_Host_Template *tpnt)
{
- SBP2_DEBUG("sbp2: sbp2scsi_detect");
+ SBP2_DEBUG("sbp2scsi_detect");
global_scsi_tpnt = tpnt;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,26)
* Module load option for force one command at a time
*/
if (serialize_io) {
- SBP2_ERR("sbp2: Driver forced to serialize I/O (serialize_io = 1)");
+ SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)");
global_scsi_tpnt->can_queue = 1;
global_scsi_tpnt->cmd_per_lun = 1;
}
* Module load option to limit max size of requests from the scsi drivers
*/
if (no_large_packets) {
- SBP2_ERR("sbp2: Driver forced to limit max transfer size (no_large_packets = 1)");
+ SBP2_ERR("Driver forced to limit max transfer size (no_large_packets = 1)");
global_scsi_tpnt->sg_tablesize = 0x1f;
global_scsi_tpnt->use_clustering = DISABLE_CLUSTERING;
}
if (mode_sense_hack) {
- SBP2_ERR("sbp2: Mode sense emulation enabled (mode_sense_hack = 1)");
+ SBP2_ERR("Mode sense emulation enabled (mode_sense_hack = 1)");
}
sbp2_init();
if (!sbp2_host_count) {
- SBP2_ERR("sbp2: Please load the lower level IEEE-1394 driver (e.g. ohci1394) before sbp2...");
+ SBP2_ERR("Please load the lower level IEEE-1394 driver (e.g. ohci1394) before sbp2...");
sbp2_cleanup();
}
{
struct Scsi_Host *shpnt = NULL;
- SBP2_DEBUG("sbp2: sbp2scsi_register_scsi_host");
- SBP2_DEBUG("sbp2: sbp2scsi_host_info = %p", hi);
+ SBP2_DEBUG("sbp2scsi_register_scsi_host");
+ SBP2_DEBUG("sbp2scsi_host_info = %p", hi);
/*
* Let's register with the scsi stack
/* Called when our module is released */
static int sbp2scsi_release(struct Scsi_Host *host)
{
- SBP2_DEBUG("sbp2: sbp2scsi_release");
+ SBP2_DEBUG("sbp2scsi_release");
sbp2_cleanup();
return(0);
}
MODULE_AUTHOR("James Goodwin <jamesg@filanet.com>");
MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
+MODULE_LICENSE("GPL");
/* SCSI host template */
static Scsi_Host_Template driver_template = {
#define ORB_DIRECTION_READ_FROM_MEDIA 0x1
#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
-/* 2^(MAX_PAYLOAD+1) = Maximum data transfer length */
-#define MAX_PAYLOAD_S100 0x7
-#define MAX_PAYLOAD_S200 0x8
-#define MAX_PAYLOAD_S400 0x9
-
-/* Max rec matches node_entry values */
-#define MAX_REC_S100 512
-#define MAX_REC_S200 1024
-#define MAX_REC_S400 2048
-
#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31)
#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29)
#define ORB_SET_NODE_ID(value) ((value & 0xffff) << 16)
* DOU = OUT data direction
* DNO = No data transfer
* DUN = Unknown data direction
+ *
+ * Opcode 0xec (Teac specific "opc execute") possibly should be DNO,
+ * but we'll change it when somebody reports a problem with this.
*/
#define DIN ORB_DIRECTION_READ_FROM_MEDIA
#define DOU ORB_DIRECTION_WRITE_TO_MEDIA
DIN,DUN,DIN,DIN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
DOU,DOU,DIN,DIN,DIN,DNO,DIN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DNO,DUN,
- DUN,DIN,DIN,DNO,DOU,DOU,DUN,DUN,DNO,DIN,DIN,DNO,DIN,DOU,DUN,DUN,
+ DUN,DIN,DIN,DNO,DNO,DOU,DUN,DUN,DNO,DIN,DIN,DNO,DIN,DOU,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
goto abort;
}
- if (calc_sb_csum(sb) != sb->sb_csum)
+ if (calc_sb_csum(sb) != sb->sb_csum) {
printk(BAD_CSUM, partition_name(rdev->dev));
+ goto abort;
+ }
ret = 0;
abort:
return ret;
}
}
- if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN))) {
+ if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN)) &&
+ (conf->working_disks > 1)) {
const char * name = "raid1syncd";
conf->resync_thread = md_register_thread(raid1syncd, conf,name);
PRINTK("raid5_error called\n");
for (i = 0, disk = conf->disks; i < conf->raid_disks; i++, disk++) {
- if (disk->dev == dev && disk->operational) {
- disk->operational = 0;
- mark_disk_faulty(sb->disks+disk->number);
- mark_disk_nonsync(sb->disks+disk->number);
- mark_disk_inactive(sb->disks+disk->number);
- sb->active_disks--;
- sb->working_disks--;
- sb->failed_disks++;
- mddev->sb_dirty = 1;
- conf->working_disks--;
- conf->failed_disks++;
- md_wakeup_thread(conf->thread);
- printk (KERN_ALERT
- "raid5: Disk failure on %s, disabling device."
- " Operation continuing on %d devices\n",
- partition_name (dev), conf->working_disks);
+ if (disk->dev == dev) {
+ if (disk->operational) {
+ disk->operational = 0;
+ mark_disk_faulty(sb->disks+disk->number);
+ mark_disk_nonsync(sb->disks+disk->number);
+ mark_disk_inactive(sb->disks+disk->number);
+ sb->active_disks--;
+ sb->working_disks--;
+ sb->failed_disks++;
+ mddev->sb_dirty = 1;
+ conf->working_disks--;
+ conf->failed_disks++;
+ md_wakeup_thread(conf->thread);
+ printk (KERN_ALERT
+ "raid5: Disk failure on %s, disabling device."
+ " Operation continuing on %d devices\n",
+ partition_name (dev), conf->working_disks);
+ }
return 0;
}
}
/* fwd decl */
static void hauppauge_eeprom(struct bttv *btv);
+static void avermedia_eeprom(struct bttv *btv);
+
static void init_PXC200(struct bttv *btv);
#if 0
static void init_tea5757(struct bttv *btv);
static void terratv_audio(struct bttv *btv, struct video_audio *v, int set);
static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set);
static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set);
+static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set);
/* config variables */
static int triton1=0;
/* insmod options */
MODULE_PARM(triton1,"i");
+MODULE_PARM_DESC(triton1,"set ETBF pci config bit "
+ "[enable bug compatibility for triton1 + others]");
+MODULE_PARM(vsfx,"i");
+MODULE_PARM_DESC(vsfx,"set VSFX pci config bit [yet another chipset flaw workaround]");
MODULE_PARM(no_overlay,"i");
MODULE_PARM(card,"1-4i");
MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list");
MODULE_PARM(gpiomask,"i");
MODULE_PARM(audioall,"i");
MODULE_PARM(audiomux,"1-5i");
-MODULE_LICENSE("GPL");
/* kernel args */
#ifndef MODULE
{ 0x6606107d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" },
{ 0x263610b4, BTTV_STB2, "STB TV PCI FM, P/N 6000704" },
{ 0x402010fc, BTTV_GVBCTV3PCI, "I-O Data Co. GV-BCV3/PCI" },
- { 0x405010fc, BTTV_GVBCTV3PCI, "I-O Data Co. GV-BCV4/PCI" },
- { 0x001211bd, BTTV_PINNACLE, "Pinnacle PCTV" },
- { 0x3000121a, 0/* no entry yet */,"VoodooTV 200" },
+ { 0x405010fc, BTTV_GVBCTV4PCI, "I-O Data Co. GV-BCV4/PCI" },
- { 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" },
- { 0x3002144f, BTTV_MAGICTVIEW061, "Askey Magic TView" },
+ { 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV" },
+ { 0x001211bd, BTTV_PINNACLE, "Pinnacle PCTV" },
+ { 0x001c11bd, BTTV_PINNACLE, "Pinnacle PCTV Sat" },
+ { 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
+
+ { 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
+ { 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
+ { 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
+
{ 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" },
{ 0x00021461, BTTV_AVERMEDIA98, "AVermedia TVCapture 98" },
{ 0x00031461, BTTV_AVPHONE98, "AVerMedia TVPhone98" },
{ 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
{ 0x400d15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
{ 0x401015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
+ { 0x401615b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
{ 0x010115cb, BTTV_GMV1, "AG GMV1" },
- { 0x010114c7, 16 /* FIXME */, "Modular Technology PCTV" },
- { 0x18501851, BTTV_CHRONOS_VS2, "Chronos Video Shuttle II" },
- { 0x18511851, 0 /* FIXME */, "CyberMail AV" },
- { 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" },
+ { 0x010114c7, BTTV_MODTEC_205, "Modular Technology PCTV" },
+ { 0x18501851, BTTV_CHRONOS_VS2, "Flyvideo 98 (LR50)/ Chronos Video Shuttle II" },
+ { 0x18511851, BTTV_FLYVIDEO98EZ, "Flyvideo 98EZ (LR51)/ CyberMail AV" },
+ { 0x18521852, BTTV_TYPHOON_TVIEW, "Flyvideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
{ 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" },
{ 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" },
- { 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV" },
{ 0, -1, NULL }
};
struct tvcard bttv_tvcards[] = {
{
/* ---- card 0x00 ---------------------------------- */
- name: " *** UNKNOWN *** ",
+ name: " *** UNKNOWN/GENERIC *** ",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
needs_tvaudio: 1,
tuner_type: -1,
},{
- name: "Hauppauge old",
+ name: "Hauppauge (bt848)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
},{
/* ---- card 0x08 ---------------------------------- */
- name: "Fly Video II",
+ name: "Fly Video II (Bt848)",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
needs_tvaudio: 1,
tuner_type: -1,
},{
- name: "Hauppauge new (bt878)",
+ name: "Hauppauge (bt878)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
- gpiomask: 7,
+ gpiomask: 0x0f, /* old: 7 */
muxsel: { 2, 0, 1, 1},
audiomux: { 0, 1, 2, 3, 4},
needs_tvaudio: 1,
audiomux: { 13, 14, 11, 7, 0, 0},
needs_tvaudio: 1,
pll: PLL_28,
- tuner_type: 5,
+ tuner_type: -1,
},{
name: "Aimslab VHX",
video_inputs: 3,
},{
/* ---- card 0x18 ---------------------------------- */
- name: "Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)",
+ name: "[many vendors] CPH05X/06X (bt878)",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xe00,
muxsel: { 2, 3, 1, 1},
- audiomux: {0x400, 0x400, 0x400, 0x400, 0},
+ audiomux: {0x400, 0x400, 0x400, 0x400, 0xc00},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
audio_inputs: 1,
tuner: 0,
svhs: 2,
- gpiomask: 0x8dfe00,
+ gpiomask: 0x1800, //0x8dfe00
muxsel: {2, 3, 1, 1},
- audiomux: { 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 },
+ audiomux: { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 },
needs_tvaudio: 1,
tuner_type: -1,
},{
tuner_type: -1,
audio_hook: winfast2000_audio,
},{
- name: "Chronos Video Shuttle II",
+ name: "Flyvideo 98 (LR50Q) / Chronos Video Shuttle II",
video_inputs: 3,
audio_inputs: 3,
tuner: 0,
svhs: 2,
gpiomask: 0x1800,
muxsel: { 2, 3, 1, 1},
- audiomux: { 0, 0, 0x1000, 0x1000, 0x0800},
+ audiomux: { 0, 0x800, 0x1000, 0x1000, 0x1800},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
/* ---- card 0x24 ---------------------------------- */
- name: "Typhoon TView TV/FM Tuner",
+ name: "Flyvideo 98FM (LR50Q) / Typhoon TView TV/FM Tuner",
video_inputs: 3,
audio_inputs: 3,
tuner: 0,
svhs: 2,
gpiomask: 0x1800,
muxsel: { 2, 3, 1, 1},
- audiomux: { 0, 0x800, 0, 0, 0x1800, 0 },
+ audiomux: { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
+ has_radio: 1,
},{
name: "PixelView PlayTV pro",
video_inputs: 3,
pll: PLL_28,
tuner_type: -1,
},{
- name: "TView99 CPH063",
+ name: "TView99 CPH06X",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x551e00,
muxsel: { 2, 3, 1, 0},
- audiomux: { 0x551400, 0x551200, 0, 0, 0, 0x551200 },
+ audiomux: { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 },
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
audiomux: { 13, 4, 11, 7, 0, 0},
needs_tvaudio: 1,
pll: PLL_28,
- tuner_type: 5,
+ tuner_type: -1,
+ has_radio: 1,
},{
name: "ProVideo PV951", /* pic16c54 */
video_inputs: 3,
no_msp34xx: 1,
pll: PLL_35,
tuner_type: 1,
+ has_radio: 1,
},{
/* ---- card 0x30 ---------------------------------- */
tuner_type: TUNER_ALPS_TSHC6_NTSC,
audio_hook: gvbctv3pci_audio,
},{
- name: "Prolink PV-BT878P+4E (PixelView PlayTV PAK)",
+ name: "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
},{
/* Claas Langbehn <claas@bigfoot.com>,
Sven Grothklags <sven@upb.de> */
- name: "Typhoon TView RDS / FM Stereo",
+ name: "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS",
video_inputs: 3,
audio_inputs: 3,
tuner: 0,
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL_I,
+ has_radio: 1,
},{
/* Tim Röstermundt <rosterm@uni-muenster.de>
in de.comp.os.unix.linux.hardware:
options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
options tuner type=5 */
- name: "Lifetec LT 9415 TV",
+ name: "Lifetec LT 9415 TV (LR90 Rev.F)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL,
audio_hook: lt9415_audio,
+ has_radio: 1,
},{
/* Miguel Angel Alvarez <maacruz@navegalia.com>
old Easy TV BT848 version (model CPH031) */
svhs: 2,
gpiomask: 0x1800,
muxsel: { 2, 3, 0, 1},
- audiomux: { 0, 0x800, 0, 0, 0x1800, 0 },
+ audiomux: { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: 5,
audio_inputs: 1,
tuner: 0,
svhs: 2,
- gpiomask: 0x0e00,
+ gpiomask: 0xe00,
muxsel: { 2, 3, 1, 1},
audiomux: { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
needs_tvaudio: 1,
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL,
-}};
+ has_radio: 1,
+},{
+ /* TANAKA Kei <peg00625@nifty.com> */
+ name: "GV-BCTV4/PCI",
+ video_inputs: 3,
+ audio_inputs: 1,
+ tuner: 0,
+ svhs: 2,
+ gpiomask: 0x010f00,
+ muxsel: {2, 3, 0, 0},
+ audiomux: {0x10000, 0, 0x10000, 0, 0, 0},
+ no_msp34xx: 1,
+ pll: PLL_28,
+ tuner_type: TUNER_SHARP_2U5JF5540_NTSC,
+ audio_hook: gvbctv3pci_audio,
+},{
+
+/* ---- card 0x44 ---------------------------------- */
+ name: "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
+ // try "insmod msp3400 simple=0" if you have
+ // sound problems with this card.
+ video_inputs: 4,
+ audio_inputs: 1,
+ tuner: 0,
+ svhs: -1,
+ gpiomask: 0x4f8a00,
+ // 0x100000: 1=MSP enabled (0=disable again)
+ // 0x010000: somehow influences tuner picture quality (?)
+ audiomux: {0x947fff, 0x987fff,0x947fff,0x947fff},
+ //tvtuner, radio, external,internal,mute,stereo
+ muxsel: { 2, 3 ,0 ,1}, /* tuner, Composit, SVid, Composit-on-Svid-adapter*/
+ tuner_type: TUNER_MT2032,
+ pll: PLL_28,
+ has_radio: 1,
+},{
+ /* Philip Blundell <pb@nexus.co.uk> */
+ name: "Active Imaging AIMMS",
+ video_inputs: 1,
+ audio_inputs: 0,
+ tuner: -1,
+ tuner_type: -1,
+ pll: PLL_28,
+ muxsel: { 2 },
+ gpiomask: 0
+},{
+ /* Tomasz Pyra <hellfire@sedez.iq.pl> */
+ name: "PV-BT878P+",
+ video_inputs: 3,
+ audio_inputs: 4,
+ tuner: 0,
+ svhs: 2,
+ gpiomask: 15,
+ muxsel: { 2, 3, 1, 1},
+ audiomux: { 0, 0, 11, 7, 13, 0},
+ needs_tvaudio: 1,
+ pll: PLL_28,
+ tuner_type: 25,
+},{
+ name: "Flyvideo 98EZ (capture only)",
+ video_inputs: 4,
+ audio_inputs: 0,
+ tuner: -1,
+ svhs: 2,
+ muxsel: { 2, 3, 1, 1}, // AV1, AV2, SVHS, CVid adapter on SVHS
+ pll: PLL_28,
+ no_msp34xx: 1,
+},{
+
+/* ---- card 0x48 ---------------------------------- */
+ /* Dariusz Kowalewski <darekk@automex.pl> */
+ name: "Prolink PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)",
+ video_inputs: 3,
+ audio_inputs: 1,
+ tuner: 0,
+ svhs: 2,
+ gpiomask: 0x3f,
+ muxsel: { 2, 3, 0, 1 },
+ audiomux: { 0x01, 0x00, 0x03, 0x03, 0x09, 0x02 },
+ needs_tvaudio: 1,
+ no_msp34xx: 1,
+ no_tda9875: 1,
+ pll: PLL_28,
+ tuner_type: -1,
+ audio_hook: pvbt878p9b_audio,
+ has_radio: 1,
+}
+};
const int bttv_num_tvcards = (sizeof(bttv_tvcards)/sizeof(struct tvcard));
if (type != -1) {
/* found it */
- printk(KERN_INFO "bttv%d: subsystem: %04x:%04x => %s => card=%d\n",
- btv->nr, btv->cardid & 0xffff, btv->cardid >> 16,
- cards[type].name,cards[type].cardnr);
+ printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
+ "PCI subsystem ID is %04x:%04x\n",
+ btv->nr,cards[type].name,cards[type].cardnr,
+ btv->cardid & 0xffff, btv->cardid >> 16);
btv->type = cards[type].cardnr;
} else {
/* 404 */
printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n",
btv->nr, btv->cardid&0xffff, btv->cardid>>16);
printk(KERN_DEBUG "please mail id, board name and "
- "the correct card= insmod option to "
- "kraxel@goldbach.in-berlin.de\n");
+ "the correct card= insmod option to kraxel@bytesex.org\n");
}
}
btv->id,
(btv->id==848 && btv->revision==0x12) ? "A" : "",
bttv_tvcards[btv->type].name);
- printk(KERN_INFO "bttv%d: model: %s [%s]\n",btv->nr,btv->video_dev.name,
+ printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->nr,
+ btv->video_dev.name,btv->type,
(card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) ?
"insmod option" : "autodetected");
btv->type = BTTV_PINNACLEPRO;
}
if (bttv_verbose)
- printk("bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+ printk(KERN_INFO "bttv%d: miro: id=%d tuner=%d "
+ "radio=%s stereo=%s\n",
btv->nr, id+1, btv->tuner_type,
!btv->has_radio ? "no" :
(btv->has_matchbox ? "matchbox" : "fmtuner"),
hauppauge_eeprom(btv);
}
+ if (btv->type == BTTV_AVERMEDIA98 || btv->type == BTTV_AVPHONE98) {
+ bttv_readee(btv,eeprom_data,0xa0);
+ avermedia_eeprom(btv);
+ }
+
if (btv->type == BTTV_PXC200)
init_PXC200(btv);
printk("bttv%d: lifetec: tv mono/fm stereo card\n", btv->nr);
else
printk("bttv%d: lifetec: stereo(TDA9821) card\n",btv->nr);
- btv->has_radio=1;
+ }
+
+ if (btv->type == BTTV_MAGICTVIEW061) {
+ if(btv->cardid == 0x4002144f) {
+ btv->has_radio=1;
+ printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->nr);
+ }
}
/* pll configuration */
if (btv->tuner_type != -1)
bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
+ if (bttv_tvcards[btv->type].has_radio)
+ btv->has_radio=1;
+
/* try to detect audio/fader chips */
if (!bttv_tvcards[btv->type].no_msp34xx &&
bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) {
request_module("msp3400");
}
- if (bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) {
+ if (!bttv_tvcards[btv->type].no_tda9875 &&
+ bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) {
if (autoload)
request_module("tda9875");
}
int blk2,tuner,radio,model;
if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0)
- printk("bttv%d: Hauppauge eeprom: invalid\n",btv->nr);
+ printk(KERN_WARNING "bttv%d: Hauppauge eeprom: invalid\n",
+ btv->nr);
/* Block 2 starts after len+3 bytes header */
blk2 = eeprom_data[1] + 3;
btv->has_radio = 1;
if (bttv_verbose)
- printk("bttv%d: Hauppauge eeprom: model=%d, tuner=%s (%d), radio=%s\n",
+ printk(KERN_INFO "bttv%d: Hauppauge eeprom: model=%d, "
+ "tuner=%s (%d), radio=%s\n",
btv->nr, model, hauppauge_tuner[tuner].name,
btv->tuner_type, radio ? "yes" : "no");
}
-void __devinit bttv_hauppauge_boot_msp34xx(struct bttv *btv)
+// AVermedia specific stuff...
+// from bktr_card.c
+int tuner_0_table[] = {
+ TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL,
+ TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL,
+ TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL,
+ TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM,
+ TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL};
+/*
+int tuner_0_fm_table[] = {
+ PHILIPS_FR1236_NTSC, PHILIPS_FR1216_PAL,
+ PHILIPS_FR1216_PAL, PHILIPS_FR1216_PAL,
+ PHILIPS_FR1216_PAL, PHILIPS_FR1216_PAL,
+ PHILIPS_FR1236_SECAM, PHILIPS_FR1236_SECAM,
+ PHILIPS_FR1236_SECAM, PHILIPS_FR1216_PAL};
+*/
+
+int tuner_1_table[] = {
+ TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL,
+ TUNER_TEMIC_PAL, TUNER_TEMIC_PAL,
+ TUNER_TEMIC_PAL, TUNER_TEMIC_PAL,
+ TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, //TUNER_TEMIC_SECAM
+ TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
+
+static void __devinit avermedia_eeprom(struct bttv *btv)
+{
+ int tuner_make,tuner_tv_fm,tuner_format,tuner=0;
+
+ tuner_make = (eeprom_data[0x41] & 0x7);
+ tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3;
+ tuner_format = (eeprom_data[0x42] & 0xf0) >> 4;
+
+ if (tuner_make == 0 || tuner_make == 2)
+ if(tuner_format <=9)
+ tuner = tuner_0_table[tuner_format];
+ if (tuner_make == 1)
+ if(tuner_format <=9)
+ tuner = tuner_1_table[tuner_format];
+
+ printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
+ btv->nr,eeprom_data[0x41],eeprom_data[0x42]);
+ if(tuner) {
+ btv->tuner_type=tuner;
+ printk("%d\n",tuner);
+ } else
+ printk("Unknown type\n");
+}
+
+
+
+/*
+ * reset/enable the MSP on some Hauppauge cards
+ * Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)!
+ *
+ * Hauppauge: pin 5
+ * Voodoo: pin 20
+ */
+void __devinit bttv_boot_msp34xx(struct bttv *btv, int pin)
{
- /* reset/enable the MSP on some Hauppauge cards */
- /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */
- btaor(32, ~32, BT848_GPIO_OUT_EN);
- btaor(0, ~32, BT848_GPIO_DATA);
+ int mask = (1 << pin);
+
+ btaor(mask, ~mask, BT848_GPIO_OUT_EN);
+ btaor(0, ~mask, BT848_GPIO_DATA);
udelay(2500);
- btaor(32, ~32, BT848_GPIO_DATA);
+ btaor(mask, ~mask, BT848_GPIO_DATA);
if (bttv_gpio)
bttv_gpio_tracking(btv,"msp34xx");
if (bttv_verbose)
- printk("bttv%d: Hauppauge msp34xx: reset line init\n",btv->nr);
+ printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line "
+ "init [%d]\n", btv->nr, pin);
}
static void __devinit init_PXC200(struct bttv *btv)
{
- static const int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x00 };
+ static int vals[] __devinitdata = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x00 };
int i,tmp;
/* Initialise GPIO-connevted stuff */
BUS_IN(btv->mbox_data) && time_before(jiffies, timeout);
schedule()); /* 10 s */
if (BUS_IN(btv->mbox_data)) {
- printk("bttv%d: tea5757: read timeout\n",btv->nr);
+ printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->nr);
return -1;
}
for(timeout = jiffies + HZ/5;
}
}
+/*
+ * Dariusz Kowalewski <darekk@automex.pl>
+ * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
+ * revision 9B has on-board TDA9874A sound decoder).
+ */
+static void
+pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ unsigned int val = 0;
+
+#if BTTV_VERSION_CODE > KERNEL_VERSION(0,8,0)
+ if (btv->radio_user)
+ return;
+#else
+ if (btv->radio)
+ return;
+#endif
+
+ if (set) {
+ if (v->mode & VIDEO_SOUND_MONO) {
+ val = 0x01;
+ }
+ if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
+ || (v->mode & VIDEO_SOUND_STEREO)) {
+ val = 0x02;
+ }
+ if (val) {
+ btaor(val, ~0x03, BT848_GPIO_DATA);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv,"pvbt878p9b");
+ }
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+}
+
/* ----------------------------------------------------------------------- */
/* motherboard chipset specific stuff */
/* for 2.4.x we'll use the pci quirks (drivers/pci/quirks.c) */
if (pci_pci_problems & PCIPCI_FAIL)
pcipci_fail = 1;
-
if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF))
triton1 = 1;
- while ((dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, dev)))
+ if (pci_pci_problems & PCIPCI_VSFX)
vsfx = 1;
- /* print warnings about quirks found */
+ /* print which chipset we have */
+ while ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8,dev)))
+ printk(KERN_INFO "bttv: Host bridge is %s\n",dev->name);
+
+ /* print warnings about any quirks found */
if (triton1)
printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n");
if (vsfx)
MODULE_PARM(vbi_nr,"i");
MODULE_DESCRIPTION("bttv - v4l driver module for bt848/878 based cards");
-MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
+MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
MODULE_LICENSE("GPL");
/* kernel args */
unsigned long adr, page;
mem=vmalloc_32(size);
- if (mem)
- {
- memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+ if (NULL == mem)
+ printk(KERN_INFO "bttv: vmalloc_32(%ld) failed\n",size);
+ else {
+ /* Clear the ram out, no junk to the user */
+ memset(mem, 0, size);
adr=(unsigned long) mem;
while (size > 0)
{
/* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
{ 35468950,
924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
- 1135, 186, 924, 0x20, 255},
+ 1135, 186, 924,
+#ifdef VIDEODAT_HACK
+ VBI_MAXLINES*2,
+#else
+ 0x20,
+#endif
+ 255},
/* NTSC */
{ 28636363,
btv->nr,virt_to_bus(po), virt_to_bus(pe));
*(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0;
- for (i=0; i<16; i++)
+ for (i=0; i<VBI_MAXLINES; i++)
{
*(po++)=cpu_to_le32(VBI_RISC);
*(po++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048));
*(po++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+4));
*(pe++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(pe++)=0;
- for (i=16; i<32; i++)
+ for (i=VBI_MAXLINES; i<VBI_MAXLINES*2; i++)
{
*(pe++)=cpu_to_le32(VBI_RISC);
*(pe++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048));
};
static int palette2fmt[] = {
- 0,
- BT848_COLOR_FMT_Y8,
- BT848_COLOR_FMT_RGB8,
- BT848_COLOR_FMT_RGB16,
- BT848_COLOR_FMT_RGB24,
- BT848_COLOR_FMT_RGB32,
- BT848_COLOR_FMT_RGB15,
- BT848_COLOR_FMT_YUY2,
- BT848_COLOR_FMT_BtYUV,
- -1,
- -1,
- -1,
- BT848_COLOR_FMT_RAW,
- BT848_COLOR_FMT_YCrCb422,
- BT848_COLOR_FMT_YCrCb411,
- BT848_COLOR_FMT_YCrCb422,
- BT848_COLOR_FMT_YCrCb411,
+ 0,
+ BT848_COLOR_FMT_Y8,
+ BT848_COLOR_FMT_RGB8,
+ BT848_COLOR_FMT_RGB16,
+ BT848_COLOR_FMT_RGB24,
+ BT848_COLOR_FMT_RGB32,
+ BT848_COLOR_FMT_RGB15,
+ BT848_COLOR_FMT_YUY2,
+ BT848_COLOR_FMT_YUY2,
+ -1,
+ -1,
+ -1,
+ BT848_COLOR_FMT_RAW,
+ BT848_COLOR_FMT_YCrCb422,
+ BT848_COLOR_FMT_YCrCb411,
+ BT848_COLOR_FMT_YCrCb422,
+ BT848_COLOR_FMT_YCrCb411,
};
#define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(int))
/* needs to be done before i2c is registered */
if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878)
- bttv_hauppauge_boot_msp34xx(btv);
+ bttv_boot_msp34xx(btv,5);
+ if (btv->type == BTTV_VOODOOTV_FM)
+ bttv_boot_msp34xx(btv,20);
/* register i2c */
btv->tuner_type=-1;
if (btv->tuner_type != -1)
bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
if (bttv_verbose)
- printk("bttv%d: i2c attach [%s]\n",btv->nr,client->name);
+ printk("bttv%d: i2c attach [client=%s,%s]\n",btv->nr,
+ client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
return 0;
}
struct bttv *btv = (struct bttv*)client->adapter->data;
int i;
- if (bttv_verbose)
- printk("bttv%d: i2c detach [%s]\n",btv->nr,client->name);
for (i = 0; i < I2C_CLIENTS_MAX; i++) {
if (btv->i2c_clients[i] == client) {
btv->i2c_clients[i] = NULL;
break;
}
}
+ if (bttv_verbose)
+ printk("bttv%d: i2c detach [client=%s,%s]\n",btv->nr,
+ client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
return 0;
}
btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap);
return btv->i2c_rc;
}
-MODULE_LICENSE("GPL");
/*
* Local variables:
#define BTTV_ATI_TVWONDERVE 0x40
#define BTTV_FLYVIDEO2000 0x41
#define BTTV_TERRATVALUER 0x42
+#define BTTV_GVBCTV4PCI 0x43
+#define BTTV_VOODOOTV_FM 0x44
+#define BTTV_AIMMS 0x45
+#define BTTV_PV_BT878P_PLUS 0x46
+#define BTTV_FLYVIDEO98EZ 0x47
+#define BTTV_PV_BT878P_9B 0x48
+
/* i2c address list */
#define I2C_TSA5522 0xc2
#define I2C_TDA8425 0x82
#define I2C_TDA9840 0x84
#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */
+#define I2C_TDA9874A 0xb0 /* also used by 9875 */
#define I2C_TDA9875 0xb0
#define I2C_HAUPEE 0xa0
#define I2C_STBEE 0xae
/* i2c audio flags */
int no_msp34xx:1;
+ int no_tda9875:1;
int needs_tvaudio:1;
/* other settings */
#define PLL_35 2
int tuner_type;
+ int has_radio;
void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
};
/* card-specific funtions */
extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
-extern void bttv_hauppauge_boot_msp34xx(struct bttv *btv);
+extern void bttv_boot_msp34xx(struct bttv *btv, int pin);
/* kernel cmd line parse helper */
extern int bttv_parse(char *str, int max, int *vals);
extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card);
/* i2c */
-#define I2C_CLIENTS_MAX 8
+#define I2C_CLIENTS_MAX 16
extern void bttv_bit_setscl(void *data, int state);
extern void bttv_bit_setsda(void *data, int state);
extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg);
extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
#endif /* _BTTV_H_ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
#ifndef _BTTVP_H_
#define _BTTVP_H_
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,72)
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,83)
#include <linux/types.h>
#define O_NONCAP O_TRUNC
#endif
+#ifdef VIDEODAT_HACK
+# define VBI_MAXLINES 19
+#else
+# define VBI_MAXLINES 16
+#endif
+#define VBIBUF_SIZE (2048*VBI_MAXLINES*2)
#define MAX_GBUFFERS 64
#define RISCMEM_LEN (32744*2)
-#define VBI_MAXLINES 16
-#define VBIBUF_SIZE (2048*VBI_MAXLINES*2)
#define BTTV_MAX_FBUF 0x208000
#ifndef I2C_DRIVERID_TDA7432
# define I2C_DRIVERID_TDA7432 I2C_DRIVERID_EXP0+6
#endif
+#ifndef I2C_DRIVERID_TDA9874A
+# define I2C_DRIVERID_TDA9874A I2C_DRIVERID_EXP0+7
+#endif
/*
* programming the msp34* sound processor family
*
- * (c) 1997-2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
*
* what works and what doesn't:
*
int nicam_on;
int acb;
int main, second; /* sound carrier */
- int scart; /* input is scart (extern) */
int muted;
int left, right; /* volume */
MODULE_PARM(simple,"i");
MODULE_PARM(amsound,"i");
MODULE_PARM(dolby,"i");
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
/* ---------------------------------------------------------------------- */
#define MSP_MODE_FM_NICAM2 6
#define MSP_MODE_AM_NICAM 7
#define MSP_MODE_BTSC 8
+#define MSP_MODE_EXTERN 9
static struct MSP_INIT_DATA_DEM {
int fir1[6];
msp_init_data[type].dfp_src);
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,
msp_init_data[type].dfp_src);
+ msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,
+ msp_init_data[type].dfp_src);
}
msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,
msp_init_data[type].dfp_src);
dprintk("msp3400: BTSC setstereo: %d\n",mode);
nicam=0x0300;
break;
+ case MSP_MODE_EXTERN:
+ dprintk("msp3400: extern setstereo: %d\n", mode);
+ nicam = 0x0200;
+ break;
+ case MSP_MODE_FM_RADIO:
+ dprintk("msp3400: FM-Radio setstereo: %d\n", mode);
+ break;
default:
dprintk("msp3400: mono setstereo\n");
return;
src = 0x0010 | nicam;
break;
}
- if (msp->scart)
- src |= 0x0200;
+ dprintk("msp3400: setstereo final source/matrix = 0x%x\n", src);
+
if (dolby) {
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,0x0520);
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,0x0620);
{
struct i2c_client *client = data;
struct msp3400c *msp = client->data;
-
+
struct CARRIER_DETECT *cd;
- int count, max1,max2,val1,val2, val,this;
-
+ int count, max1,max2,val1,val2, val,this;
+
#ifdef CONFIG_SMP
lock_kernel();
#endif
-
+
daemonize();
sigfillset(¤t->blocked);
strcpy(current->comm,"msp3400");
printk("msp3400: daemon started\n");
if(msp->notify != NULL)
up(msp->notify);
-
+
for (;;) {
if (msp->rmmod)
goto done;
if (msp->rmmod || signal_pending(current))
goto done;
- if (VIDEO_MODE_RADIO == msp->norm)
- continue; /* nothing to do */
- if (msp->scart)
+ if (VIDEO_MODE_RADIO == msp->norm ||
+ MSP_MODE_EXTERN == msp->mode)
continue; /* nothing to do */
msp->active = 1;
goto done;
restart:
- if (msp->scart)
- continue;
- if (VIDEO_MODE_RADIO == msp->norm)
- continue;
+ if (VIDEO_MODE_RADIO == msp->norm ||
+ MSP_MODE_EXTERN == msp->mode)
+ continue; /* nothing to do */
msp->restart = 0;
msp3400c_setvolume(client, msp->muted, 0, 0);
msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
if (msp->rmmod || signal_pending(current))
goto done;
- if (msp->scart)
+ if (msp->mode == MSP_MODE_EXTERN)
continue;
msp->active = 1;
goto done;
restart:
- if (msp->scart)
+ if (msp->mode == MSP_MODE_EXTERN)
continue;
msp->restart = 0;
del_timer(&msp->wake_stereo);
/* scart routing */
msp3400c_set_scart(client,SCART_IN2,0);
msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0220);
+ msp3400c_write(client,I2C_MSP3400C_DFP, 0x09, 0x0220);
+ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0b, 0x0220);
break;
case 0x0003:
msp->mode = MSP_MODE_FM_TERRA;
return 0;
}
-static int msp_command(struct i2c_client *client,unsigned int cmd, void *arg)
+static void msp_wake_thread(struct i2c_client *client)
+{
+ struct msp3400c *msp = (struct msp3400c*)client->data;
+
+ msp3400c_setvolume(client,msp->muted,0,0);
+ msp->watch_stereo=0;
+ del_timer(&msp->wake_stereo);
+ if (msp->active)
+ msp->restart = 1;
+ wake_up_interruptible(&msp->wq);
+}
+
+static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct msp3400c *msp = (struct msp3400c*)client->data;
__u16 *sarg = arg;
- IN1 is often used for external input
- Hauppauge uses IN2 for the radio */
dprintk(KERN_DEBUG "msp34xx: AUDC_SET_INPUT(%d)\n",*sarg);
- msp->scart = 0;
switch (*sarg) {
case AUDIO_RADIO:
+ msp->mode = MSP_MODE_FM_RADIO;
+ msp->stereo = VIDEO_SOUND_STEREO;
msp3400c_set_scart(client,SCART_IN2,0);
msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
msp3400c_setstereo(client,msp->stereo);
break;
case AUDIO_EXTERN:
- msp->scart = 1;
+ msp->mode = MSP_MODE_EXTERN;
+ msp->stereo = VIDEO_SOUND_STEREO;
msp3400c_set_scart(client,SCART_IN1,0);
msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
msp3400c_setstereo(client,msp->stereo);
break;
case AUDIO_TUNER:
- msp3400c_setstereo(client,msp->stereo);
+ msp->mode = -1;
+ msp_wake_thread(client);
break;
default:
if (*sarg & AUDIO_MUTE)
dprintk("msp34xx: switching to radio mode\n");
if (msp->simple) {
/* the thread will do for us */
- msp3400c_setvolume(client,msp->muted,0,0);
- wake_up_interruptible(&msp->wq);
+ msp_wake_thread(client);
} else {
/* set msp3400 to FM radio mode */
msp3400c_setmode(client,MSP_MODE_FM_RADIO);
(va->volume ? va->volume : 1);
va->balance=(msp->left<msp->right)?
(65535-va->balance) : va->balance;
+ if (0 == va->volume)
+ va->balance = 32768;
va->bass = msp->bass;
va->treble = msp->treble;
case VIDIOCSFREQ:
{
/* new channel -- kick audio carrier scan */
- msp3400c_setvolume(client,msp->muted,0,0);
- msp->watch_stereo=0;
- del_timer(&msp->wake_stereo);
- if (msp->active)
- msp->restart = 1;
- wake_up_interruptible(&msp->wq);
+ msp_wake_thread(client);
break;
}
MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip");
MODULE_LICENSE("GPL");
-
MODULE_PARM(debug,"i");
MODULE_PARM(loudness,"i");
static int loudness = 0; /* disable loudness by default */
MODULE_PARM(debug,"i");
MODULE_LICENSE("GPL");
-
static int debug = 0; /* insmod parameter */
/* Addresses to scan */
force
};
-static int debug = 0; /* insmod parameter */
-static int type = -1; /* insmod parameter */
-
+/* insmod options */
+static int debug = 0;
+static int type = -1;
static int addr = 0;
static char *pal = "b";
-static int this_adap;
static int tv_range[2] = { 44, 958 };
static int radio_range[2] = { 65, 108 };
-
-#define dprintk if (debug) printk
-
MODULE_PARM(debug,"i");
MODULE_PARM(type,"i");
MODULE_PARM(addr,"i");
MODULE_PARM(tv_range,"2i");
MODULE_PARM(radio_range,"2i");
MODULE_PARM(pal,"s");
+
+#define optimize_vco 1
+
+MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
MODULE_LICENSE("GPL");
+static int this_adap;
+#define dprintk if (debug) printk
+
struct tuner
{
int type; /* chip type */
int std;
int radio;
- int mode; /* PAL(0)/SECAM(1) mode (PHILIPS_SECAM only) */
+ int mode; /* current norm for multi-norm tuners */
+ int xogc; // only for MT2032
};
static struct i2c_driver driver;
static struct i2c_client client_template;
+/* ---------------------------------------------------------------------- */
+
/* tv standard selection for Temic 4046 FM5
this value takes the low bits of control byte 2
from datasheet Rev.01, Feb.00
16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
{ "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
- { "Temic PAL_I (4006FH5)", TEMIC, PAL_I,
+ { "Temic PAL_BG (4006FH5)", TEMIC, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
{ "Alps TSCH6",Alps,NTSC,
16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
{ "Temic PAL_DK (4016 FY5)",TEMIC,PAL,
- 16*136.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
+ 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
{ "Philips NTSC_M (MK2)",Philips,NTSC,
16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
{ "Temic PAL_I (4066 FY5)", TEMIC, PAL_I,
{ "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL,
16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
{ "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
- 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}
+ 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
+ { "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */
+ 16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940},
+
+ { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */
+ 16*169,16*464,0xA0,0x90,0x30,0x8e,623},
+ { "MT2032 universal", Microtune,PAL|NTSC,
+ 0,0,0,0,0,0,0},
+ { "Temic PAL_BG (4106 FH5)", TEMIC, PAL,
+ 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
+ { "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL,
+ 16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623},
+
+ { "Temic NTSC (4136 FY5)", TEMIC, NTSC,
+ 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
+ { "LG PAL (newer TAPC series)", LGINNOTEK, PAL,
+ 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623},
+
};
#define TUNERS (sizeof(tuners)/sizeof(struct tunertype))
{
unsigned char byte;
+ struct tuner *t = (struct tuner*)c->data;
+
+ if (t->type == TUNER_MT2032)
+ return 0;
+
if (1 != i2c_master_recv(c,&byte,1))
return 0;
return byte;
return (tuner_getstatus (c) & TUNER_MODE) >> 3;
}
#endif
+// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
+int mt2032_init(struct i2c_client *c)
+{
+ unsigned char buf[21];
+ int ret,xogc,xok=0;
+ struct tuner *t = (struct tuner*)c->data;
+
+ buf[0]=0;
+ ret=i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,21);
+
+ printk("MT2032: Companycode=%02x%02x Part=%02x Revision=%02x\n",
+ buf[0x11],buf[0x12],buf[0x13],buf[0x14]);
+
+ if(debug) {
+ int i;
+ printk("MT2032 hexdump:\n");
+ for(i=0;i<21;i++) {
+ printk(" %02x",buf[i]);
+ if(((i+1)%8)==0) printk(" ");
+ if(((i+1)%16)==0) printk("\n ");
+ }
+ printk("\n ");
+ }
+
+ // Initialize Registers per spec.
+ buf[1]=2; // Index to register 2
+ buf[2]=0xff;
+ buf[3]=0x0f;
+ buf[4]=0x1f;
+ ret=i2c_master_send(c,buf+1,4);
+
+ buf[5]=6; // Index register 6
+ buf[6]=0xe4;
+ buf[7]=0x8f;
+ buf[8]=0xc3;
+ buf[9]=0x4e;
+ buf[10]=0xec;
+ ret=i2c_master_send(c,buf+5,6);
+
+ buf[12]=13; // Index register 13
+ buf[13]=0x32;
+ ret=i2c_master_send(c,buf+12,2);
+
+ // Adjust XOGC (register 7), wait for XOK
+ xogc=7;
+ do {
+ dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07);
+ mdelay(10);
+ buf[0]=0x0e;
+ i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,1);
+ xok=buf[0]&0x01;
+ dprintk("mt2032: xok = 0x%02x\n",xok);
+ if (xok == 1) break;
+
+ xogc--;
+ dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07);
+ if (xogc == 3) {
+ xogc=4; // min. 4 per spec
+ break;
+ }
+ buf[0]=0x07;
+ buf[1]=0x88 + xogc;
+ ret=i2c_master_send(c,buf,2);
+ if (ret!=2)
+ printk("mt2032_init failed with %d\n",ret);
+ } while (xok != 1 );
+ t->xogc=xogc;
+
+ return(1);
+}
+
+
+// IsSpurInBand()?
+int mt2032_spurcheck(int f1, int f2, int spectrum_from,int spectrum_to)
+{
+ int n1=1,n2,f;
+
+ f1=f1/1000; //scale to kHz to avoid 32bit overflows
+ f2=f2/1000;
+ spectrum_from/=1000;
+ spectrum_to/=1000;
+
+ dprintk("spurcheck f1=%d f2=%d from=%d to=%d\n",f1,f2,spectrum_from,spectrum_to);
+
+ do {
+ n2=-n1;
+ f=n1*(f1-f2);
+ do {
+ n2--;
+ f=f-f2;
+ dprintk(" spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
+
+ if( (f>spectrum_from) && (f<spectrum_to))
+ printk("mt2032 spurcheck triggered: %d\n",n1);
+ } while ( (f>(f2-spectrum_to)) || (n2>-5));
+ n1++;
+ } while (n1<5);
+
+ return 1;
+}
+
+int mt2032_compute_freq(int rfin, int if1, int if2, int spectrum_from,
+ int spectrum_to, unsigned char *buf, int *ret_sel, int xogc) //all in Hz
+{
+ int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
+ desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
+
+ fref= 5250 *1000; //5.25MHz
+ desired_lo1=rfin+if1;
+
+ lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
+ lo1n=lo1/8;
+ lo1a=lo1-(lo1n*8);
+
+ s=rfin/1000/1000+1090;
+
+ if(optimize_vco) {
+ if(s>1890) sel=0;
+ else if(s>1720) sel=1;
+ else if(s>1530) sel=2;
+ else if(s>1370) sel=3;
+ else sel=4; // >1090
+ }
+ else {
+ if(s>1790) sel=0; // <1958
+ else if(s>1617) sel=1;
+ else if(s>1449) sel=2;
+ else if(s>1291) sel=3;
+ else sel=4; // >1090
+ }
+ *ret_sel=sel;
+
+ lo1freq=(lo1a+8*lo1n)*fref;
+
+ dprintk("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
+ rfin,lo1,lo1n,lo1a,sel,lo1freq);
+
+ desired_lo2=lo1freq-rfin-if2;
+ lo2=(desired_lo2)/fref;
+ lo2n=lo2/8;
+ lo2a=lo2-(lo2n*8);
+ lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
+ lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
+
+ dprintk("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
+ rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
+
+ if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
+ printk("mt2032: frequency parameters out of range: %d %d %d %d\n",
+ lo1a, lo1n, lo2a,lo2n);
+ return(-1);
+ }
+
+ mt2032_spurcheck(lo1freq, desired_lo2, spectrum_from, spectrum_to);
+ // should recalculate lo1 (one step up/down)
+
+ // set up MT2032 register map for transfer over i2c
+ buf[0]=lo1n-1;
+ buf[1]=lo1a | (sel<<4);
+ buf[2]=0x86; // LOGC
+ buf[3]=0x0f; //reserved
+ buf[4]=0x1f;
+ buf[5]=(lo2n-1) | (lo2a<<5);
+ if(rfin >400*1000*1000)
+ buf[6]=0xe4;
+ else
+ buf[6]=0xf4; // set PKEN per rev 1.2
+ buf[7]=8+xogc;
+ buf[8]=0xc3; //reserved
+ buf[9]=0x4e; //reserved
+ buf[10]=0xec; //reserved
+ buf[11]=(lo2num&0xff);
+ buf[12]=(lo2num>>8) |0x80; // Lo2RST
+
+ return 0;
+}
+
+int mt2032_check_lo_lock(struct i2c_client *c)
+{
+ int try,lock=0;
+ unsigned char buf[2];
+ for(try=0;try<10;try++) {
+ buf[0]=0x0e;
+ i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,1);
+ dprintk("mt2032 Reg.E=0x%02x\n",buf[0]);
+ lock=buf[0] &0x06;
+
+ if (lock==6)
+ break;
+
+ dprintk("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
+ udelay(1000);
+ }
+ return lock;
+}
+
+int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
+{
+ unsigned char buf[2];
+ int tad1;
+
+ buf[0]=0x0f;
+ i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,1);
+ dprintk("mt2032 Reg.F=0x%02x\n",buf[0]);
+ tad1=buf[0]&0x07;
+
+ if(tad1 ==0) return lock;
+ if(tad1 ==1) return lock;
+
+ if(tad1==2) {
+ if(sel==0)
+ return lock;
+ else sel--;
+ }
+ else {
+ if(sel<4)
+ sel++;
+ else
+ return lock;
+ }
+
+ dprintk("mt2032 optimize_vco: sel=%d\n",sel);
+
+ buf[0]=0x0f;
+ buf[1]=sel;
+ i2c_master_send(c,buf,2);
+ lock=mt2032_check_lo_lock(c);
+ return lock;
+}
+
+
+void mt2032_set_if_freq(struct i2c_client *c,int rfin, int if1, int if2, int from, int to)
+{
+ unsigned char buf[21];
+ int lint_try,ret,sel,lock=0;
+ struct tuner *t = (struct tuner*)c->data;
+
+ dprintk("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",rfin,if1,if2,from,to);
+
+ buf[0]=0;
+ ret=i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,21);
+
+ buf[0]=0;
+ ret=mt2032_compute_freq(rfin,if1,if2,from,to,&buf[1],&sel,t->xogc);
+ if (ret<0)
+ return;
+
+ // send only the relevant registers per Rev. 1.2
+ buf[0]=0;
+ ret=i2c_master_send(c,buf,4);
+ buf[5]=5;
+ ret=i2c_master_send(c,buf+5,4);
+ buf[11]=11;
+ ret=i2c_master_send(c,buf+11,3);
+ if(ret!=3)
+ printk("mt2032_set_if_freq failed with %d\n",ret);
+
+ // wait for PLLs to lock (per manual), retry LINT if not.
+ for(lint_try=0; lint_try<2; lint_try++) {
+ lock=mt2032_check_lo_lock(c);
+
+ if(optimize_vco)
+ lock=mt2032_optimize_vco(c,sel,lock);
+ if(lock==6) break;
+
+ printk("mt2032: re-init PLLs by LINT\n");
+ buf[0]=7;
+ buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs
+ i2c_master_send(c,buf,2);
+ mdelay(10);
+ buf[1]=8+t->xogc;
+ i2c_master_send(c,buf,2);
+ }
+
+ if (lock!=6)
+ printk("MT2032 Fatal Error: PLLs didn't lock.\n");
+
+ buf[0]=2;
+ buf[1]=0x20; // LOGC for optimal phase noise
+ ret=i2c_master_send(c,buf,2);
+ if (ret!=2)
+ printk("mt2032_set_if_freq2 failed with %d\n",ret);
+}
+
+
+void mt2032_set_tv_freq(struct i2c_client *c, int freq, int norm)
+{
+ int if2,from,to;
+
+ // signal bandwidth and picture carrier
+ if(norm==VIDEO_MODE_NTSC) {
+ from=40750*1000;
+ to=46750*1000;
+ if2=45750*1000;
+ }
+ else { // Pal
+ from=32900*1000;
+ to=39900*1000;
+ if2=38900*1000;
+ }
+
+ mt2032_set_if_freq(c,freq* 1000*1000/16, 1090*1000*1000, if2, from, to);
+}
+
// Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz
static void set_tv_freq(struct i2c_client *c, int freq)
unsigned char buffer[4];
int rc;
+ if (t->type == -1) {
+ printk("tuner: tuner type not set\n");
+ return;
+ }
+ if (t->type == TUNER_MT2032) {
+ mt2032_set_tv_freq(c,freq,t->mode);
+ return;
+ }
+
if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
/* FIXME: better do that chip-specific, but
right now we don't have that in the config
check at all */
printk("tuner: TV freq (%d.%02d) out of range (%d-%d)\n",
freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
- }
-
- if (t->type == -1) {
- printk("tuner: tuner type not set\n");
return;
}
/* 0x02 -> PAL BDGHI / SECAM L */
/* 0x04 -> ??? PAL others / SECAM others ??? */
config &= ~0x02;
- if (t->mode)
+ if (t->mode == VIDEO_MODE_SECAM)
config |= 0x02;
break;
}
+static void mt2032_set_radio_freq(struct i2c_client *c,int freq)
+{
+ int if2;
+
+ if2=10700*1000; // 10.7MHz FM intermediate frequency
+
+ mt2032_set_if_freq(c,freq* 1000*1000/16, 1085*1000*1000,if2,if2,if2);
+}
+
static void set_radio_freq(struct i2c_client *c, int freq)
{
u8 config;
return;
}
+ if (t->type == TUNER_MT2032) {
+ mt2032_set_radio_freq(c,freq);
+ return;
+ }
+
tun=&tuners[t->type];
config = 0xa4 /* 0xa5 */; /* bit 0 is AFC (set) vs. RF-Signal (clear) */
div=freq + (int)(16*10.7);
t->type = -1;
}
i2c_attach_client(client);
+ if (t->type == TUNER_MT2032)
+ mt2032_init(client);
+
MOD_INC_USE_COUNT;
return 0;
dprintk("tuner: type set to %d (%s)\n",
t->type,tuners[t->type].name);
strncpy(client->name, tuners[t->type].name, sizeof(client->name));
+ if (t->type == TUNER_MT2032)
+ mt2032_init(client);
break;
case AUDC_SET_RADIO:
t->radio = 1;
case VIDIOCSCHAN:
{
struct video_channel *vc = arg;
-
+
t->radio = 0;
- if (t->type == TUNER_PHILIPS_SECAM) {
- t->mode = (vc->norm == VIDEO_MODE_SECAM) ? 1 : 0;
+ t->mode = vc->norm;
+ if (t->freq)
set_tv_freq(client,t->freq);
- }
return 0;
}
case VIDIOCSFREQ:
#ifndef _TUNER_H
#define _TUNER_H
-#define TUNER_TEMIC_PAL 0 /* 4002 FH5_9483 */
+#define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */
#define TUNER_PHILIPS_PAL_I 1
#define TUNER_PHILIPS_NTSC 2
#define TUNER_PHILIPS_SECAM 3 /* you must actively select B/G, L, L` */
#define TUNER_ABSENT 4
#define TUNER_PHILIPS_PAL 5
-#define TUNER_TEMIC_NTSC 6 /* 4032 FY5_7004 */
-#define TUNER_TEMIC_PAL_I 7 /* 4062 FY5_9957 */
-#define TUNER_TEMIC_4036FY5_NTSC 8 /* 4036 FY5 */
+#define TUNER_TEMIC_NTSC 6 /* 4032 FY5 (3X 7004, 9498, 9789) */
+#define TUNER_TEMIC_PAL_I 7 /* 4062 FY5 (3X 8501, 9957) */
+#define TUNER_TEMIC_4036FY5_NTSC 8 /* 4036 FY5 (3X 1223, 1981, 7686) */
#define TUNER_ALPS_TSBH1_NTSC 9
#define TUNER_ALPS_TSBE1_PAL 10
#define TUNER_ALPS_TSBB5_PAL_I 11
#define TUNER_ALPS_TSBE5_PAL 12
#define TUNER_ALPS_TSBC5_PAL 13
-#define TUNER_TEMIC_4006FH5_PAL 14 /* 4006 FH5 */
+#define TUNER_TEMIC_4006FH5_PAL 14 /* 4006 FH5 (3X 9500, 9501, 7291) */
#define TUNER_ALPS_TSHC6_NTSC 15
-#define TUNER_TEMIC_PAL_DK 16 /* 4016 FY5 */
+#define TUNER_TEMIC_PAL_DK 16 /* 4016 FY5 (3X 1392, 1393) */
#define TUNER_PHILIPS_NTSC_M 17
-#define TUNER_TEMIC_4066FY5_PAL_I 18
-#define TUNER_TEMIC_4006FN5_MULTI_PAL 19 /* B/G, I and D/K autodetected */
-#define TUNER_TEMIC_4009FR5_PAL 20 /* incl. FM radio */
-#define TUNER_TEMIC_4039FR5_NTSC 21 /* incl. FM radio */
-#define TUNER_TEMIC_4046FM5 22 /* you must actively select B/G, D/K, I, L, L` ! */
+#define TUNER_TEMIC_4066FY5_PAL_I 18 /* 4066 FY5 (3X 7032, 7035) */
+#define TUNER_TEMIC_4006FN5_MULTI_PAL 19 /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/
+#define TUNER_TEMIC_4009FR5_PAL 20 /* incl. FM radio (3X 7607, 7488, 7711)*/
+#define TUNER_TEMIC_4039FR5_NTSC 21 /* incl. FM radio (3X 7246, 7578, 7732)*/
+#define TUNER_TEMIC_4046FM5 22 /* you must actively select B/G, D/K, I, L, L` ! (3X 7804, 7806, 8103, 8104)*/
#define TUNER_PHILIPS_PAL_DK 23
#define TUNER_PHILIPS_FQ1216ME 24 /* you must actively select B/G/D/K, I, L, L` */
#define TUNER_LG_PAL_I_FM 25
#define TUNER_LG_NTSC_FM 27
#define TUNER_LG_PAL_FM 28
#define TUNER_LG_PAL 29
-#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30 /* B/G, I and D/K autodetected */
+#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30 /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/
+#define TUNER_SHARP_2U5JF5540_NTSC 31
+#define TUNER_Samsung_PAL_TCPM9091PD27 32
+#define TUNER_MT2032 33
+#define TUNER_TEMIC_4106FH5 34 /* 4106 FH5 (3X 7808, 7865)*/
+#define TUNER_TEMIC_4012FY5 35 /* 4012 FY5 (3X 0971, 1099)*/
+#define TUNER_TEMIC_4136FY5 36 /* 4136 FY5 (3X 7708, 7746)*/
+#define TUNER_LG_PAL_NEW_TAPC 37
+
#define NOTUNER 0
#define Sony 3
#define Alps 4
#define LGINNOTEK 5
+#define SHARP 6
+#define Samsung 7
+#define Microtune 8
#define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */
#define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */
#define dprintk if (debug) printk
+MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
+MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr");
+MODULE_LICENSE("GPL");
/* ---------------------------------------------------------------------- */
/* our structs */
struct CHIPSTATE;
typedef int (*getvalue)(int);
typedef int (*checkit)(struct CHIPSTATE*);
+typedef int (*initialize)(struct CHIPSTATE*);
typedef int (*getmode)(struct CHIPSTATE*);
typedef void (*setmode)(struct CHIPSTATE*, int mode);
typedef void (*checkmode)(struct CHIPSTATE*);
int *insmodopt;
checkit checkit;
+ initialize initialize;
int flags;
#define CHIP_HAS_VOLUME 1
#define CHIP_HAS_BASSTREBLE 2
I2C_TDA9840 >> 1,
I2C_TDA985x_L >> 1,
I2C_TDA985x_H >> 1,
+ I2C_TDA9874A >> 1,
I2C_PIC16C54 >> 1,
I2C_CLIENT_END };
static unsigned short normal_i2c_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
{ chip->c.addr, 0, 1, write },
{ chip->c.addr, I2C_M_RD, 1, read }
};
- write[1] = subaddr;
+ write[0] = subaddr;
if (2 != i2c_transfer(chip->c.adapter,msgs,2)) {
printk(KERN_WARNING "%s: I/O error (read2)\n",
if (mode & VIDEO_SOUND_LANG1)
desc->setmode(chip,VIDEO_SOUND_LANG1);
+ else if (mode & VIDEO_SOUND_LANG2)
+ desc->setmode(chip,VIDEO_SOUND_LANG2);
else if (mode & VIDEO_SOUND_STEREO)
desc->setmode(chip,VIDEO_SOUND_STEREO);
else
return;
}
+ chip_write(chip, TDA9873_SW, sw_data);
dprintk("tda9873_setmode(): req. mode %d; chip_write: %d\n",
mode, sw_data);
}
}
+/* ---------------------------------------------------------------------- */
+/* audio chip description - defines+functions for tda9874a */
+/* Dariusz Kowalewski <darekk@automex.pl> */
+
+/* Subaddresses for TDA9874A (slave rx) */
+#define TDA9874A_AGCGR 0x00 /* AGC gain */
+#define TDA9874A_GCONR 0x01 /* general config */
+#define TDA9874A_MSR 0x02 /* monitor select */
+#define TDA9874A_C1FRA 0x03 /* carrier 1 freq. */
+#define TDA9874A_C1FRB 0x04 /* carrier 1 freq. */
+#define TDA9874A_C1FRC 0x05 /* carrier 1 freq. */
+#define TDA9874A_C2FRA 0x06 /* carrier 2 freq. */
+#define TDA9874A_C2FRB 0x07 /* carrier 2 freq. */
+#define TDA9874A_C2FRC 0x08 /* carrier 2 freq. */
+#define TDA9874A_DCR 0x09 /* demodulator config */
+#define TDA9874A_FMER 0x0a /* FM de-emphasis */
+#define TDA9874A_FMMR 0x0b /* FM dematrix */
+#define TDA9874A_C1OLAR 0x0c /* ch.1 output level adj. */
+#define TDA9874A_C2OLAR 0x0d /* ch.2 output level adj. */
+#define TDA9874A_NCONR 0x0e /* NICAM config */
+#define TDA9874A_NOLAR 0x0f /* NICAM output level adj. */
+#define TDA9874A_NLELR 0x10 /* NICAM lower error limit */
+#define TDA9874A_NUELR 0x11 /* NICAM upper error limit */
+#define TDA9874A_AMCONR 0x12 /* audio mute control */
+#define TDA9874A_SDACOSR 0x13 /* stereo DAC output select */
+#define TDA9874A_AOSR 0x14 /* analog output select */
+#define TDA9874A_DAICONR 0x15 /* digital audio interface config */
+#define TDA9874A_I2SOSR 0x16 /* I2S-bus output select */
+#define TDA9874A_I2SOLAR 0x17 /* I2S-bus output level adj. */
+#define TDA9874A_MDACOSR 0x18 /* mono DAC output select */
+#define TDA9874A_ESP 0xFF /* easy standard progr. */
+
+/* Subaddresses for TDA9874A (slave tx) */
+#define TDA9874A_DSR 0x00 /* device status */
+#define TDA9874A_NSR 0x01 /* NICAM status */
+#define TDA9874A_NECR 0x02 /* NICAM error count */
+#define TDA9874A_DR1 0x03 /* add. data LSB */
+#define TDA9874A_DR2 0x04 /* add. data MSB */
+#define TDA9874A_LLRA 0x05 /* monitor level read-out LSB */
+#define TDA9874A_LLRB 0x06 /* monitor level read-out MSB */
+#define TDA9874A_SIFLR 0x07 /* SIF level */
+#define TDA9874A_TR2 252 /* test reg. 2 */
+#define TDA9874A_TR1 253 /* test reg. 1 */
+#define TDA9874A_DIC 254 /* device id. code */
+#define TDA9874A_SIC 255 /* software id. code */
+
+
+static int tda9874a_mode = 1; /* 0: A2, 1: NICAM */
+static int tda9874a_GCONR = 0xc0; /* default config. input pin: SIFSEL=0 */
+static int tda9874a_ESP = 0x07; /* default standard: NICAM D/K */
+
+/* insmod options for tda9874a */
+static int tda9874a_SIF = -1;
+static int tda9874a_STD = -1;
+MODULE_PARM(tda9874a_SIF,"i");
+MODULE_PARM(tda9874a_STD,"i");
+
+
+static int tda9874a_setup(struct CHIPSTATE *chip)
+{
+ chip_write(chip, TDA9874A_AGCGR, 0x00); /* 0 dB */
+ chip_write(chip, TDA9874A_GCONR, tda9874a_GCONR);
+ chip_write(chip, TDA9874A_MSR, (tda9874a_mode) ? 0x03:0x02);
+ chip_write(chip, TDA9874A_FMMR, 0x80);
+ chip_write(chip, TDA9874A_C1OLAR, 0x00); /* 0 dB */
+ chip_write(chip, TDA9874A_C2OLAR, 0x00); /* 0 dB */
+ chip_write(chip, TDA9874A_NCONR, 0x00); /* not 0x04 as doc. table 10 says! */
+ chip_write(chip, TDA9874A_NOLAR, 0x00); /* 0 dB */
+ chip_write(chip, TDA9874A_AMCONR, 0xf9);
+ chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80); /* 0x81 */
+ chip_write(chip, TDA9874A_AOSR, 0x80);
+ chip_write(chip, TDA9874A_MDACOSR, (tda9874a_mode) ? 0x82:0x80);
+ chip_write(chip, TDA9874A_ESP, tda9874a_ESP);
+
+ return 1;
+}
+
+int tda9874a_getmode(struct CHIPSTATE *chip)
+{
+ int dsr,nsr,mode;
+
+ mode = VIDEO_SOUND_MONO;
+
+ if(-1 == (dsr = chip_read2(chip,TDA9874A_DSR)))
+ return mode;
+ if(-1 == (nsr = chip_read2(chip,TDA9874A_NSR)))
+ return mode;
+
+ if(tda9874a_mode) {
+ /* check also DSR.RSSF and DSR.AMSTAT bits? */
+ if(nsr & 0x02) /* NSR.S/MB */
+ mode |= VIDEO_SOUND_STEREO;
+ if(nsr & 0x01) /* NSR.D/SB */
+ mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ } else {
+ if(dsr & 0x02) /* DSR.IDSTE */
+ mode |= VIDEO_SOUND_STEREO;
+ if(dsr & 0x04) /* DSR.IDDUA */
+ mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+
+ dprintk("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, return: %d.\n",
+ dsr, nsr, mode);
+ return mode;
+}
+
+void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
+{
+ int aosr=0x80,mdacosr=0x82;
+
+ /* note: TDA9874A has auto-select function for audio output */
+ switch(mode) {
+ case VIDEO_SOUND_MONO:
+ case VIDEO_SOUND_STEREO:
+ break;
+ case VIDEO_SOUND_LANG1:
+ aosr = 0x80; /* dual A/A */
+ mdacosr = (tda9874a_mode) ? 0x82:0x80;
+ break;
+ case VIDEO_SOUND_LANG2:
+ aosr = 0xa0; /* dual B/B */
+ mdacosr = (tda9874a_mode) ? 0x83:0x81;
+ break;
+ default:
+ chip->mode = 0;
+ return;
+ }
+
+ chip_write(chip, TDA9874A_AOSR, aosr);
+ chip_write(chip, TDA9874A_MDACOSR, mdacosr);
+
+ dprintk("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
+ mode, aosr, mdacosr);
+}
+
+int tda9874a_checkit(struct CHIPSTATE *chip)
+{
+ int dic,sic; /* device id. and software id. codes */
+
+ if(-1 == (dic = chip_read2(chip,TDA9874A_DIC)))
+ return 0;
+ if(-1 == (sic = chip_read2(chip,TDA9874A_SIC)))
+ return 0;
+
+ dprintk("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
+
+ return((dic & 0xff) == 0x11);
+}
+
+int tda9874a_initialize(struct CHIPSTATE *chip)
+{
+ if(tda9874a_SIF != -1) {
+ if(tda9874a_SIF == 1)
+ tda9874a_GCONR = 0xc0; /* sound IF input 1 */
+ else if(tda9874a_SIF == 2)
+ tda9874a_GCONR = 0xc1; /* sound IF input 2 */
+ else
+ printk(KERN_WARNING "tda9874a: SIF parameter must be 1 or 2.\n");
+ }
+
+ if(tda9874a_STD != -1) {
+ if((tda9874a_STD >= 0)&&(tda9874a_STD <= 8)) {
+ tda9874a_ESP = tda9874a_STD;
+ tda9874a_mode = (tda9874a_STD < 5) ? 0 : 1;
+ } else {
+ printk(KERN_WARNING "tda9874a: STD parameter must be between 0 and 8.\n");
+ }
+ }
+
+ tda9874a_setup(chip);
+
+ return 0;
+}
+
+
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for tea6420 */
int tda9850 = 1;
int tda9855 = 1;
int tda9873 = 1;
+int tda9874a = 1;
int tea6300 = 0;
int tea6420 = 1;
int pic16c54 = 1;
MODULE_PARM(tda9850,"i");
MODULE_PARM(tda9855,"i");
MODULE_PARM(tda9873,"i");
+MODULE_PARM(tda9874a,"i");
MODULE_PARM(tea6300,"i");
MODULE_PARM(tea6420,"i");
MODULE_PARM(pic16c54,"i");
inputmask: TDA9873_INP_MASK | TDA9873_MUTE | TDA9873_AUTOMUTE
},
+ {
+ name: "tda9874a",
+ id: I2C_DRIVERID_TDA9874A,
+ checkit: tda9874a_checkit,
+ initialize: tda9874a_initialize,
+ insmodopt: &tda9874a,
+ addr_lo: I2C_TDA9874A >> 1,
+ addr_hi: I2C_TDA9874A >> 1,
+
+ getmode: tda9874a_getmode,
+ setmode: tda9874a_setmode,
+ checkmode: generic_checkmode,
+ },
{
name: "tda9850",
id: I2C_DRIVERID_TDA9850,
i2c_attach_client(&chip->c);
/* initialization */
- chip_cmd(chip,"init",&desc->init);
+ if (desc->initialize != NULL)
+ desc->initialize(chip);
+ else
+ chip_cmd(chip,"init",&desc->init);
+
if (desc->flags & CHIP_HAS_VOLUME) {
chip->left = desc->leftinit ? desc->leftinit : 65536;
chip->right = desc->rightinit ? desc->rightinit : 65536;
module_init(audiochip_init_module);
module_exit(audiochip_cleanup_module);
-MODULE_LICENSE("GPL");
/*
* Local variables:
#define I2C_TDA9840 0x84
#define I2C_TDA985x_L 0xb4 /* also used by 9873 */
#define I2C_TDA985x_H 0xb6
+#define I2C_TDA9874A 0xb0 /* also used by 9875 */
#define I2C_TEA6300 0x80
#define I2C_TEA6420 0x98
MODULE_PARM(debug,"i");
MODULE_PARM(devnr,"i");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
/* ----------------------------------------------------------------------- */
struct TVMIXER {
static int tvmixer_adapters(struct i2c_adapter *adap);
static int tvmixer_clients(struct i2c_client *client);
-static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int tvmixer_open(struct inode *inode, struct file *file);
-static int tvmixer_release(struct inode *inode, struct file *file);
-
-
-static struct i2c_driver driver = {
- name: "tv card mixer driver",
- id: I2C_DRIVERID_TVMIXER,
- flags: I2C_DF_DUMMY,
- attach_adapter: tvmixer_adapters,
- detach_client: tvmixer_clients,
-};
-
-static struct file_operations tvmixer_fops = {
- owner: THIS_MODULE,
- llseek: no_llseek,
- ioctl: tvmixer_ioctl,
- open: tvmixer_open,
- release: tvmixer_release,
-};
-
/* ----------------------------------------------------------------------- */
static int mix_to_v4l(int i)
return 0;
}
+
+static struct i2c_driver driver = {
+ name: "tv card mixer driver",
+ id: I2C_DRIVERID_TVMIXER,
+ flags: I2C_DF_DUMMY,
+ attach_adapter: tvmixer_adapters,
+ detach_client: tvmixer_clients,
+};
+
+static struct file_operations tvmixer_fops = {
+ owner: THIS_MODULE,
+ llseek: no_llseek,
+ ioctl: tvmixer_ioctl,
+ open: tvmixer_open,
+ release: tvmixer_release,
+};
+
/* ----------------------------------------------------------------------- */
static int tvmixer_adapters(struct i2c_adapter *adap)
* c-basic-offset: 8
* End:
*/
-MODULE_LICENSE("GPL");
module_init(a2065_probe);
module_exit(a2065_cleanup);
+MODULE_LICENSE("GPL");
unsigned int bionet_debug = NET_DEBUG;
MODULE_PARM(bionet_debug, "i");
MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)");
+MODULE_LICENSE("GPL");
static unsigned int bionet_min_poll_time = 2;
unsigned int pamsnet_debug = NET_DEBUG;
MODULE_PARM(pamsnet_debug, "i");
MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)");
+MODULE_LICENSE("GPL");
static unsigned int pamsnet_min_poll_time = 2;
#endif
MODULE_PARM(lance_debug, "i");
MODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)");
+MODULE_LICENSE("GPL");
/* Print debug messages on probing? */
#undef LANCE_DEBUG_PROBE
#endif
MODULE_PARM(lance_debug, "i");
MODULE_PARM_DESC(lance_debug, "Lance debug level (0-3)");
+MODULE_LICENSE("GPL");
/* Print debug messages on probing? */
#undef LANCE_DEBUG_PROBE
MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
+MODULE_LICENSE("GPL");
static void __exit bmac_cleanup (void)
MODULE_AUTHOR("Myson or whoever");
MODULE_DESCRIPTION("Myson MTD-8xx 100/10M Ethernet PCI Adapter Driver");
+MODULE_LICENSE("GPL");
MODULE_PARM(max_interrupt_work, "i");
//MODULE_PARM(min_pci_latency, "i");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(io, "FMV-18X I/O address");
MODULE_PARM_DESC(irq, "FMV-18X IRQ number");
MODULE_PARM_DESC(net_debug, "FMV-18X debug level (0-1,5-6)");
+MODULE_LICENSE("GPL");
int init_module(void)
{
MODULE_AUTHOR("Paul Mackerras/Ben Herrenschmidt");
MODULE_DESCRIPTION("PowerMac GMAC driver.");
+MODULE_LICENSE("GPL");
static void __exit gmac_cleanup_module(void)
{
}
module_init(gt96100_probe);
+MODULE_LICENSE("GPL");
}
#ifdef MODULE
+MODULE_LICENSE("GPL");
int init_module(void)
{
root_lance_dev = NULL;
module_init(hydra_probe);
module_exit(hydra_cleanup);
+MODULE_LICENSE("GPL");
MODULE_PARM(io, "i");
MODULE_PARM_DESC(irq, "IBM LAN/A IRQ number");
MODULE_PARM_DESC(io, "IBM LAN/A I/O base address");
+MODULE_LICENSE("GPL");
int init_module(void)
{
MODULE_AUTHOR("Ralf Baechle <ralf@oss.sgi.com>");
MODULE_DESCRIPTION("SGI IOC3 Ethernet driver");
+MODULE_LICENSE("GPL");
module_init(ioc3_init_module);
module_exit(ioc3_cleanup_module);
static int irq;
static int dma;
static int mem;
+MODULE_LICENSE("GPL");
int init_module(void)
{
MODULE_AUTHOR("Richard Hirst");
MODULE_DESCRIPTION("i82596 driver");
+MODULE_LICENSE("GPL");
MODULE_PARM(i596_debug, "i");
MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)");
+MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Paul Mackerras");
MODULE_DESCRIPTION("PowerMac MACE driver.");
+MODULE_LICENSE("GPL");
static void __exit mace_cleanup (void)
{
MODULE_PARM(sonic_debug, "i");
MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
+MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
}
#ifdef MODULE
+MODULE_LICENSE("GPL");
+
int init_module(void)
{
root_lance_dev = NULL;
static int io[MAX_NE_CARDS];
static int irq[MAX_NE_CARDS];
static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
+MODULE_LICENSE("GPL");
#ifdef MODULE_PARM
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
module_init(oaknet_init_module);
module_exit(oaknet_cleanup_module);
+MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
MODULE_DESCRIPTION ("Skeleton for a PCI Fast Ethernet driver");
+MODULE_LICENSE("GPL");
MODULE_PARM (multicast_filter_limit, "i");
MODULE_PARM (max_interrupt_work, "i");
MODULE_PARM (debug, "i");
Scyld Computing Corporation
410 Severn Ave., Suite 210
Annapolis MD 21403
+
+ -----------------------------------------------------------
+
+ Linux kernel-specific changes:
+
+ LK1.0 (Ion Badulescu)
+ - Major cleanup
+ - Use 2.4 PCI API
+ - Support ethtool
+ - Rewrite perfect filter/hash code
+ - Use interrupts for media changes
+
+ LK1.1 (Ion Badulescu)
+ - Disallow negotiation of unsupported full-duplex modes
*/
#define DRV_NAME "xircom_tulip_cb"
-#define DRV_VERSION "0.91+LK"
-#define DRV_RELDATE "July 19, 2001"
+#define DRV_VERSION "0.91+LK1.1"
+#define DRV_RELDATE "October 11, 2001"
#define CARDBUS 1
/* These identify the driver base version and may not be removed. */
static char version[] __devinitdata =
KERN_INFO DRV_NAME ".c derived from tulip.c:v0.91 4/14/99 becker@scyld.com\n"
-KERN_INFO " modified by danilo@cs.uni-magdeburg.de for XIRCOM CBE, fixed by Doug Ledford\n"
KERN_INFO " unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE "\n";
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
int valid_intrs; /* CSR7 interrupt enable settings */
int flags;
} xircom_tbl[] = {
- { "Xircom Cardbus Adapter (DEC 21143 compatible mode)",
+ { "Xircom Cardbus Adapter",
LinkChange | NormalIntr | AbnormalIntr | BusErrorIntr |
RxDied | RxNoBuf | RxIntr | TxFIFOUnderflow | TxNoBuf | TxDied | TxIntr,
HAS_MII | HAS_ACPI, },
/*
* locate the MII interfaces and initialize them.
+ * we disable full-duplex modes here,
+ * because we don't know how to handle them.
*/
static void find_mii_transceivers(struct net_device *dev)
{
struct xircom_private *tp = dev->priv;
int phy, phy_idx;
+ if (media_cap[tp->default_port] & MediaIsMII) {
+ u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
+ tp->to_advertise = media2advert[tp->default_port - 9];
+ } else
+ tp->to_advertise =
+ /*ADVERTISE_100BASE4 | ADVERTISE_100FULL |*/ ADVERTISE_100HALF |
+ /*ADVERTISE_10FULL |*/ ADVERTISE_10HALF | ADVERTISE_CSMA;
+
/* Find the connected MII xcvrs.
Doing this in open() would allow detecting external xcvrs later,
but takes much time. */
printk(KERN_INFO "%s: MII transceiver #%d "
"config %4.4x status %4.4x advertising %4.4x.\n",
dev->name, phy, mii_reg0, mii_status, mii_advert);
- /* Fixup for DLink with miswired PHY. */
- if (mii_advert != reg4) {
- printk(KERN_DEBUG "%s: Advertising %4.4x on PHY %d,"
- " previously advertising %4.4x.\n",
- dev->name, reg4, phy, mii_advert);
- mdio_write(dev, phy, MII_ADVERTISE, reg4);
- }
- /* Enable autonegotiation: some boards default to off. */
- mdio_write(dev, phy, MII_BMCR, mii_reg0 | BMCR_ANENABLE |
- (tp->full_duplex ? BMCR_FULLDPLX : 0) |
- (media_cap[tp->default_port]&MediaIs100 ? BMCR_SPEED100 : 0));
}
}
tp->mii_cnt = phy_idx;
printk(version);
#endif
- printk(KERN_INFO "xircom_init_one(%s)\n", pdev->slot_name);
+ //printk(KERN_INFO "xircom_init_one(%s)\n", pdev->slot_name);
board_idx++;
}
-/* XXX: resume isn't able to power up the MII/PHY! */
static int xircom_resume(struct pci_dev *pdev)
{
struct net_device *dev = pdev->driver_data;
}
module_init(saa9730_probe);
+MODULE_LICENSE("GPL");
static struct net_device dev_seeq = { init: seeq8005_probe };
static int io = 0x320;
static int irq = 10;
+MODULE_LICENSE("GPL");
MODULE_PARM(io, "i");
MODULE_PARM(irq, "i");
MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address");
MODULE_AUTHOR("Patrick J.D. Weichmann");
MODULE_DESCRIPTION("Schneider & Koch G16 Ethernet Device Driver");
+MODULE_LICENSE("GPL");
MODULE_PARM(io, "i");
MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the board");
* ------------------------------------------------------------------------ */
#ifdef MODULE
+MODULE_LICENSE("GPL");
#define DEVMAX 5
static struct net_device dev_ultra[MAX_ULTRAMCA_CARDS];
static int io[MAX_ULTRAMCA_CARDS];
static int irq[MAX_ULTRAMCA_CARDS];
+MODULE_LICENSE("GPL");
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
static int io;
static int irq;
static int ifport;
+MODULE_LICENSE("GPL");
MODULE_PARM(io, "i");
MODULE_PARM(irq, "i");
module_init(stnic_probe);
/* No cleanup routine. */
+MODULE_LICENSE("GPL");
#endif
MODULE_PARM(lance_debug, "i");
MODULE_PARM_DESC(lance_debug, "SUN3 Lance debug level (0-3)");
+MODULE_LICENSE("GPL");
#define DPRINTK(n,a) \
do { \
module_init(qec_probe);
module_exit(qec_cleanup);
+MODULE_LICENSE("GPL");
long ioaddr = dev->base_addr;
int csr5;
int entry;
- int csr8;
+ int missed;
int rx = 0;
int tx = 0;
int oi = 0;
}
}
if (csr5 & RxDied) { /* Missed a Rx frame. */
+ tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
#ifdef CONFIG_NET_HW_FLOWCONTROL
if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) {
tp->stats.rx_errors++;
}
}
- csr8 = inl(ioaddr + CSR8);
- tp->stats.rx_dropped += (csr8 & 0x1ffff) + ((csr8 >> 17) & 0xfff);
+ if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) {
+ tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
+ }
if (tulip_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
*/
#define DRV_NAME "tulip"
-#define DRV_VERSION "0.9.15-pre7"
-#define DRV_RELDATE "Oct 2, 2001"
+#define DRV_VERSION "0.9.15-pre8"
+#define DRV_RELDATE "Oct 11, 2001"
#include <linux/config.h>
#include <linux/module.h>
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
MODULE_LICENSE("Dual MPL/GPL");
+EXPORT_NO_SYMBOLS;
typedef struct dldwd_card {
struct device_node* node;
-/* $Id: amd7930.c,v 1.27 2001/05/21 01:25:22 davem Exp $
+/* $Id: amd7930.c,v 1.28 2001/10/13 01:47:29 davem Exp $
* drivers/sbus/audio/amd7930.c
*
* Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
-/* $Id: aurora.c,v 1.16 2001/10/08 22:19:51 davem Exp $
+/* $Id: aurora.c,v 1.17 2001/10/13 08:27:50 davem Exp $
* linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
*
* Copyright (c) 1999 by Oliver Aldulea (oli at bv dot ro)
* read that file before reading this one.
*
* Several parts of the code do not have comments yet.
+ *
+ * n.b. The board can support 115.2 bit rates, but only on a few
+ * ports. The total badwidth of one chip (ports 0-7 or 8-15) is equal
+ * to OSC_FREQ div 16. In case of my board, each chip can take 6
+ * channels of 115.2 kbaud. This information is not well-tested.
+ *
+ * Fixed to use tty_get_baud_rate().
+ * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*/
#include <linux/module.h>
DECLARE_TASK_QUEUE(tq_aurora);
-/* Yes, the board can support 115.2 bit rates, but only on a few ports. The
- * total badwidth of one chip (ports 0-7 or 8-15) is equal to OSC_FREQ div
- * 16. In case of my board, each chip can take 6 channels of 115.2 kbaud.
- * This information is not well-tested.
- */
-static unsigned long baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 0,
-};
-
static inline int aurora_paranoia_check(struct Aurora_port const * port,
kdev_t device, const char *routine)
{
port->COR2 = 0;
port->MSVR = MSVR_RTS|MSVR_DTR;
- baud = C_BAUD(tty);
-
- if (baud & CBAUDEX) {
- baud &= ~CBAUDEX;
- if (baud < 1 || baud > 2)
- port->tty->termios->c_cflag &= ~CBAUDEX;
- else
- baud += 15;
- }
- if (baud == 15) {
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- baud ++;
- if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- baud += 2;
- }
+ baud = tty_get_baud_rate(tty);
/* Select port on the board */
sbus_writeb(port_No(port) & 7,
&bp->r[chip]->r[CD180_CAR]);
udelay(1);
- if (!baud_table[baud]) {
+ if (!baud) {
/* Drop DTR & exit */
port->MSVR &= ~(bp->DTR|bp->RTS);
sbus_writeb(port->MSVR,
/* Now we must calculate some speed dependant things. */
/* Set baud rate for port. */
- tmp = (((bp->oscfreq + baud_table[baud]/2) / baud_table[baud] +
+ tmp = (((bp->oscfreq + baud/2) / baud +
CD180_TPC/2) / CD180_TPC);
-/* tmp = (bp->oscfreq/7)/baud_table[baud];
+/* tmp = (bp->oscfreq/7)/baud;
if((tmp%10)>4)tmp=tmp/10+1;else tmp=tmp/10;*/
/* printk("Prescaler period: %d\n",tmp);*/
sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_RBPRL]);
sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_TBPRL]);
- baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */
+ baud = (baud + 5) / 10; /* Estimated CPS */
/* Two timer ticks seems enough to wakeup something like SLIP driver */
tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
-/* $Id: sab82532.c,v 1.64 2001/10/08 22:19:51 davem Exp $
+/* $Id: sab82532.c,v 1.65 2001/10/13 08:27:50 davem Exp $
* sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
* Rewrote buffer handling to use CIRC(Circular Buffer) macros.
* Maxim Krasnyanskiy <maxk@qualcomm.com>
*
+ * Fixed to use tty_get_baud_rate, and to allow for arbitrary baud
+ * rates to be programmed into the UART. Also eliminated a lot of
+ * duplicated code in the console setup.
+ * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*/
#include <linux/config.h>
* The formula is: Baud = BASE_BAUD / ((N + 1) * (1 << M)),
*
* with 0 <= N < 64 and 0 <= M < 16
- *
- * XXX: Speeds with M = 0 might not work properly for XTAL frequencies
- * above 10 MHz.
+ *
+ * 12-Oct-2001 - Replaced table driven approach with code written by
+ * Theodore Ts'o <tytso@alum.mit.edu> which exactly replicates the
+ * table. (Modulo bugs for the 307200 and 61440 baud rates, which
+ * were clearly incorrectly calculated in the original table. This is
+ * why tables filled with magic constants are evil.)
*/
-struct ebrg_struct {
- int baud;
- int n;
- int m;
-};
-static struct ebrg_struct ebrg_table[] = {
- { 0, 0, 0 },
- { 50, 35, 10 },
- { 75, 47, 9 },
- { 110, 32, 9 },
- { 134, 53, 8 },
- { 150, 47, 8 },
- { 200, 35, 8 },
- { 300, 47, 7 },
- { 600, 47, 6 },
- { 1200, 47, 5 },
- { 1800, 31, 5 },
- { 2400, 47, 4 },
- { 4800, 47, 3 },
- { 9600, 47, 2 },
- { 19200, 47, 1 },
- { 38400, 23, 1 },
- { 57600, 15, 1 },
- { 115200, 7, 1 },
- { 230400, 3, 1 },
- { 460800, 1, 1 },
- { 76800, 11, 1 },
- { 153600, 5, 1 },
- { 307200, 3, 1 },
- { 614400, 3, 0 },
- { 921600, 0, 1 },
-};
+static void calc_ebrg(int baud, int *n_ret, int *m_ret)
+{
+ int n, m;
-#define NR_EBRG_VALUES (sizeof(ebrg_table)/sizeof(struct ebrg_struct))
+ if (baud == 0) {
+ *n_ret = 0;
+ *m_ret = 0;
+ return;
+ }
+
+ /*
+ * We scale numbers by 10 so that we get better accuracy
+ * without having to use floating point. Here we increment m
+ * until n is within the valid range.
+ */
+ n = (BASE_BAUD*10) / baud;
+ m = 0;
+ while (n >= 640) {
+ n = n / 2;
+ m++;
+ }
+ n = (n+5) / 10;
+ /*
+ * We try very hard to avoid speeds with M == 0 since they may
+ * not work correctly for XTAL frequences above 10 MHz.
+ */
+ if ((m == 0) && ((n & 1) == 0)) {
+ n = n / 2;
+ m++;
+ }
+ *n_ret = n - 1;
+ *m_ret = m;
+}
#define SAB82532_MAX_TEC_TIMEOUT 200000 /* 1 character time (at 50 baud) */
#define SAB82532_MAX_CEC_TIMEOUT 50000 /* 2.5 TX CLKs (at 50 baud) */
unsigned int ebrg;
tcflag_t cflag;
unsigned char dafo;
- int i, bits;
+ int bits, n, m;
if (!info->tty || !info->tty->termios)
return;
}
/* Determine EBRG values based on baud rate */
- i = cflag & CBAUD;
- if (i & CBAUDEX) {
- i &= ~(CBAUDEX);
- if ((i < 1) || ((i + 15) >= NR_EBRG_VALUES))
- info->tty->termios->c_cflag &= ~CBAUDEX;
- else
- i += 15;
- }
- ebrg = ebrg_table[i].n;
- ebrg |= (ebrg_table[i].m << 6);
+ info->baud = tty_get_baud_rate(info->tty);
+ calc_ebrg(info->baud, &n, &m);
+
+ ebrg = n | (m << 6);
- info->baud = ebrg_table[i].baud;
if (info->baud) {
info->timeout = (info->xmit_fifo_size * HZ * bits) / info->baud;
info->tec_timeout = (10 * 1000000) / info->baud;
static inline void __init show_serial_version(void)
{
- char *revision = "$Revision: 1.64 $";
+ char *revision = "$Revision: 1.65 $";
char *version, *p;
version = strchr(revision, ' ');
static int
sab82532_console_setup(struct console *con, char *options)
{
+ static struct tty_struct c_tty;
+ static struct termios c_termios;
struct sab82532 *info;
- unsigned int ebrg;
tcflag_t cflag;
- unsigned char dafo;
- int i, bits;
- unsigned long flags;
+ int i;
info = sab82532_chain;
for (i = con->index; i; i--) {
sunserial_console_termios(con);
cflag = con->cflag;
- /* Byte size and parity */
- switch (cflag & CSIZE) {
- case CS5: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
- case CS6: dafo = SAB82532_DAFO_CHL6; bits = 8; break;
- case CS7: dafo = SAB82532_DAFO_CHL7; bits = 9; break;
- case CS8: dafo = SAB82532_DAFO_CHL8; bits = 10; break;
- /* Never happens, but GCC is too dumb to figure it out */
- default: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
- }
-
- if (cflag & CSTOPB) {
- dafo |= SAB82532_DAFO_STOP;
- bits++;
- }
-
- if (cflag & PARENB) {
- dafo |= SAB82532_DAFO_PARE;
- bits++;
- }
-
- if (cflag & PARODD) {
-#ifdef CMSPAR
- if (cflag & CMSPAR)
- dafo |= SAB82532_DAFO_PAR_MARK;
- else
-#endif
- dafo |= SAB82532_DAFO_PAR_ODD;
- } else {
-#ifdef CMSPAR
- if (cflag & CMSPAR)
- dafo |= SAB82532_DAFO_PAR_SPACE;
- else
-#endif
- dafo |= SAB82532_DAFO_PAR_EVEN;
+ /*
+ * Fake up the tty and tty->termios structures so we can use
+ * change_speed (and eliminate a lot of duplicate code).
+ */
+ if (!info->tty) {
+ memset(&c_tty, 0, sizeof(c_tty));
+ info->tty = &c_tty;
}
-
- /* Determine EBRG values based on baud rate */
- i = cflag & CBAUD;
- if (i & CBAUDEX) {
- i &= ~(CBAUDEX);
- if ((i < 1) || ((i + 15) >= NR_EBRG_VALUES))
- cflag &= ~CBAUDEX;
- else
- i += 15;
+ if (!info->tty->termios) {
+ memset(&c_termios, 0, sizeof(c_termios));
+ info->tty->termios = &c_termios;
}
- ebrg = ebrg_table[i].n;
- ebrg |= (ebrg_table[i].m << 6);
-
- info->baud = ebrg_table[i].baud;
- if (info->baud)
- info->timeout = (info->xmit_fifo_size * HZ * bits) / info->baud;
- else
- info->timeout = 0;
- info->timeout += HZ / 50; /* Add .02 seconds of slop */
-
- /* CTS flow control flags */
- if (cflag & CRTSCTS)
- info->flags |= ASYNC_CTS_FLOW;
- else
- info->flags &= ~(ASYNC_CTS_FLOW);
-
- if (cflag & CLOCAL)
- info->flags &= ~(ASYNC_CHECK_CD);
- else
- info->flags |= ASYNC_CHECK_CD;
+ info->tty->termios->c_cflag = con->cflag;
- save_flags(flags); cli();
- sab82532_cec_wait(info);
- sab82532_tec_wait(info);
- writeb(dafo, &info->regs->w.dafo);
- writeb(ebrg & 0xff, &info->regs->w.bgr);
- writeb(readb(&info->regs->rw.ccr2) & ~(0xc0), &info->regs->rw.ccr2);
- writeb(readb(&info->regs->rw.ccr2) | ((ebrg >> 2) & 0xc0), &info->regs->rw.ccr2);
- if (info->flags & ASYNC_CTS_FLOW) {
- writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);
- writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
- writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FCTS), &info->regs->rw.mode);
- } else {
- writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
- writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);
- writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FCTS, &info->regs->rw.mode);
- }
- writeb(~(info->pvr_dtr_bit), &info->regs->rw.pvr);
- writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RAC, &info->regs->rw.mode);
- restore_flags(flags);
+ change_speed(info);
+ /* Now take out the pointers to static structures if necessary */
+ if (info->tty->termios == &c_termios)
+ info->tty->termios = 0;
+ if (info->tty == &c_tty)
+ info->tty = 0;
+
return 0;
}
-/* $Id: su.c,v 1.52 2001/06/29 21:54:32 davem Exp $
+/* $Id: su.c,v 1.53 2001/10/13 08:27:50 davem Exp $
* su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
*
* This is mainly a variation of drivers/char/serial.c,
* credits go to authors mentioned therein.
+ *
+ * Fixed to use tty_get_baud_rate().
+ * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*/
/*
static int
su_get_baud_rate(struct su_struct *info)
{
- static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0
- };
- int i;
+ static struct tty_struct c_tty;
+ static struct termios c_termios;
if (info->tty)
return tty_get_baud_rate(info->tty);
- i = info->cflag & CBAUD;
- if (i & CBAUDEX) {
- i &= ~(CBAUDEX);
- if (i < 1 || i > 4)
- info->cflag &= ~(CBAUDEX);
- else
- i += 15;
- }
- return baud_table[i];
+ memset(&c_tty, 0, sizeof(c_tty));
+ memset(&c_termios, 0, sizeof(c_termios));
+ c_tty.termios = &c_termios;
+ c_termios.c_cflag = info->cflag;
+
+ return tty_get_baud_rate(&c_tty);
}
/*
if (info->port_type != SU_PORT_MS)
return;
- info->cflag &= ~(CBAUDEX | CBAUD);
+ info->cflag &= ~CBAUD;
switch (baud) {
case 1200:
info->cflag |= B1200;
*/
static __inline__ void __init show_su_version(void)
{
- char *revision = "$Revision: 1.52 $";
+ char *revision = "$Revision: 1.53 $";
char *version, *p;
version = strchr(revision, ' ');
-/* $Id: zs.c,v 1.66 2001/06/29 21:33:22 davem Exp $
+/* $Id: zs.c,v 1.67 2001/10/13 08:27:50 davem Exp $
* zs.c: Zilog serial port driver for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
* Fixes by Pete A. Zaitcev <zaitcev@yahoo.com>.
+ *
+ * Fixed to use tty_get_baud_rate().
+ * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*/
#include <linux/errno.h>
return 0;
}
-/* This is used to figure out the divisor speeds and the timeouts. */
-static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 76800, 0
-};
-
/* Reading and writing Zilog8530 registers. The delays are to make this
* driver work on the Sun4 which needs a settling delay after each chip
* register access, other machines handle this in hardware via auxiliary
static void change_speed(struct sun_serial *info)
{
unsigned cflag;
- int quot = 0;
- int i;
+ int baud, quot = 0;
int brg;
if (!info->tty || !info->tty->termios)
cflag = info->tty->termios->c_cflag;
if (!info->port)
return;
- i = cflag & CBAUD;
- if (cflag & CBAUDEX) {
- i &= ~CBAUDEX;
- if (i != 5)
- info->tty->termios->c_cflag &= ~CBAUDEX;
- else
- i = 16;
- }
- if (i == 15) {
- if ((info->flags & ZILOG_SPD_MASK) == ZILOG_SPD_HI)
- i += 1;
- if ((info->flags & ZILOG_SPD_MASK) == ZILOG_SPD_CUST)
- quot = info->custom_divisor;
- }
+ baud = tty_get_baud_rate(info->tty);
+
+ if ((baud == 38400) &&
+ ((info->flags & ZILOG_SPD_MASK) == ZILOG_SPD_CUST))
+ quot = info->custom_divisor;
+
if (quot) {
info->zs_baud = info->baud_base / quot;
info->clk_divisor = 16;
info->curregs[13] = ((brg >> 8) & 255);
info->curregs[14] = BRSRC | BRENAB;
zs_rtsdtr(info, 1);
- } else if (baud_table[i]) {
- info->zs_baud = baud_table[i];
+ } else if (baud) {
+ info->zs_baud = baud;
info->clk_divisor = 16;
info->curregs[4] = X16CLK;
static void show_serial_version(void)
{
- char *revision = "$Revision: 1.66 $";
+ char *revision = "$Revision: 1.67 $";
char *version, *p;
version = strchr(revision, ' ');
static int __init zs_console_setup(struct console *con, char *options)
{
+ static struct tty_struct c_tty;
+ static struct termios c_termios;
struct sun_serial *info;
- int i, brg, baud;
+ int brg, baud;
info = zs_soft + con->index;
info->is_cons = 1;
printk("Console: ttyS%d (Zilog8530)\n", info->line);
-
+
sunserial_console_termios(con);
+ memset(&c_tty, 0, sizeof(c_tty));
+ memset(&c_termios, 0, sizeof(c_termios));
+ c_tty.termios = &c_termios;
+ c_termios.c_cflag = con->cflag;
+ baud = tty_get_baud_rate(&c_tty);
- i = con->cflag & CBAUD;
- if (con->cflag & CBAUDEX) {
- i &= ~CBAUDEX;
- con->cflag &= ~CBAUDEX;
- }
- baud = baud_table[i];
info->zs_baud = baud;
switch (con->cflag & CSIZE) {
pcount = next_scsi_host;
+ MOD_INC_USE_COUNT;
+
/* The detect routine must carefully spinunlock/spinlock if
it enables interrupts, since all interrupt handlers do
spinlock as well.
(scsi_memory_upper_value - scsi_init_memory_start) / 1024);
#endif
- MOD_INC_USE_COUNT;
-
if (out_of_space) {
scsi_unregister_host(tpnt); /* easiest way to clean up?? */
return 1;
int diskinfo[4];
SDev = rscsi_disks[DEVICE_NR(dev)].device;
+ if (!SDev)
+ return -ENODEV;
+
/*
* If we are in the middle of error recovery, don't let anyone
* else try and use this device. Also, if error recovery fails, it
target = DEVICE_NR(inode->i_rdev);
SDev = rscsi_disks[target].device;
+ if (!SDev)
+ return -ENODEV;
SDev->access_count--;
** in the size field. We use normal 32-bit PCI addresses for
** descriptors.
*/
- if (chip->features & FE_DAC) {
+ if (chip && (chip->features & FE_DAC)) {
if (pci_set_dma_mask(pdev, (u64) 0xffffffffff))
chip->features &= ~FE_DAC_IN_USE;
else
chip->features |= FE_DAC_IN_USE;
}
- if (!(chip->features & FE_DAC_IN_USE)) {
+ if (chip && !(chip->features & FE_DAC_IN_USE)) {
if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
printk(KERN_WARNING NAME53C8XX
"32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
case SNDCTL_DSP_SYNC:
/* NOP */
return 0;
+ case SNDCTL_DSP_GETISPACE:
+ {
+ audio_buf_info info;
+ if (!bta->recording)
+ return -EINVAL;
+ info.fragsize = bta->block_bytes>>bta->sampleshift;
+ info.fragstotal = bta->block_count;
+ info.bytes = bta->read_count;
+ info.fragments = info.bytes / info.fragsize;
+ if (debug)
+ printk(KERN_DEBUG "btaudio: SNDCTL_DSP_GETISPACE "
+ "returns %d/%d/%d/%d\n",
+ info.fragsize, info.fragstotal,
+ info.bytes, info.fragments);
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
#if 0 /* TODO */
case SNDCTL_DSP_GETTRIGGER:
case SNDCTL_DSP_SETTRIGGER:
mainmenu_option next_comment
comment 'USB support'
-tristate 'Support for USB' CONFIG_USB
-if [ ! "$CONFIG_USB" = "n" ]; then
+dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
+if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
bool ' USB verbose debug messages' CONFIG_USB_DEBUG
comment 'Miscellaneous USB options'
else
define_bool CONFIG_USB_BANDWIDTH n
fi
+ bool ' Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
+ bool ' Large report fetching for "broken" devices (some APC UPSes)' CONFIG_USB_LARGE_CONFIG
+fi
comment 'USB Controllers'
- if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
- dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
- fi
- if [ "$CONFIG_USB_UHCI" != "y" ]; then
- dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
- fi
- dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
+if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
+ dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
+fi
+if [ "$CONFIG_USB_UHCI" != "y" ]; then
+ dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
+else
+ define_bool CONFIG_USB_UHCI_ALT n
+fi
+dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
- comment 'USB Device Class drivers'
- dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
- dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
- if [ "$CONFIG_USB_STORAGE" != "n" ]; then
- bool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG
- bool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM
- bool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200
- bool ' Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e
- bool ' SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09
- fi
- fi
- dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
- dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
+comment 'USB Device Class drivers'
+dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
+dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
+ dep_mbool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE
+ dep_mbool ' Datafab MDCFE-B Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+ dep_mbool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM $CONFIG_USB_STORAGE
+ dep_mbool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE
+ dep_mbool ' Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE
+ dep_mbool ' HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+ dep_mbool ' SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+ dep_mbool ' Lexar Jumpshot Compact Flash Reader' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
+dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
- comment 'USB Human Interface Devices (HID)'
- if [ "$CONFIG_INPUT" = "n" ]; then
- comment ' Input core support is needed for USB HID'
- else
- dep_tristate ' USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB $CONFIG_INPUT
- if [ "$CONFIG_USB_HID" != "y" ]; then
- dep_tristate ' USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
- dep_tristate ' USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
- fi
- dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
+comment 'USB Human Interface Devices (HID)'
+if [ "$CONFIG_INPUT" = "n" ]; then
+ comment ' Input core support is needed for USB HID'
+else
+ dep_tristate ' USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB $CONFIG_INPUT
+ dep_mbool ' /dev/hiddev raw HID device support (EXPERIMENTAL)' CONFIG_USB_HIDDEV $CONFIG_USB_HID
+ if [ "$CONFIG_USB_HID" != "y" ]; then
+ dep_tristate ' USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
+ dep_tristate ' USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
fi
+ dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
+fi
- comment 'USB Imaging devices'
- dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
- dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
- dep_tristate ' Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
- dep_tristate ' HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL
+comment 'USB Imaging devices'
+dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
+dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
+dep_tristate ' Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
+dep_tristate ' HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL
- comment 'USB Multimedia devices'
+comment 'USB Multimedia devices'
+if [ "$CONFIG_VIDEO_DEV" = "n" ]; then
+ comment ' Video4Linux support is needed for USB Multimedia device support'
+else
dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
dep_tristate ' USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
dep_tristate ' USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV
dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
+fi
- comment 'USB Network adaptors'
+comment 'USB Network adaptors'
+if [ "$CONFIG_NET" = "n" ]; then
+ comment ' Networking support is needed for USB Networking device support'
+else
dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
- dep_tristate ' USB CATC NetMate-based Ethernet driver (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
- dep_tristate ' USB CDC Ethernet class (USB cable modem) support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
dep_tristate ' USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
- dep_tristate ' USB-to-USB Networking (NetChip, Prolific, ...) (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Communication Class Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB-to-USB Networking cable device support (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+fi
- comment 'USB port drivers'
- dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
- source drivers/usb/serial/Config.in
+comment 'USB port drivers'
+dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
+source drivers/usb/serial/Config.in
- comment 'USB misc drivers'
- dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
-fi
+comment 'USB Miscellaneous drivers'
+dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
endmenu
#define VENDOR_ABOCOM 0x07b8
#define VENDOR_ACCTON 0x083a
#define VENDOR_ADMTEK 0x07a6
+#define VENDOR_ALLIEDTEL 0x07c9
+#define VENDOR_BELKIN 0x050d
#define VENDOR_BILLIONTON 0x08dd
#define VENDOR_COREGA 0x07aa
#define VENDOR_DLINK 0x2001
#define VENDOR_SMARTBRIDGES 0x08d1
#define VENDOR_SMC 0x0707
#define VENDOR_SOHOWARE 0x15e8
-#define VENDOR_BELKIN 0x050d
+
#else /* PEGASUS_DEV */
PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)",
VENDOR_ADMTEK, 0x0986,
DEFAULT_GPIO_RESET | HAS_HOME_PNA )
+PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
+ DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121,
+ DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "Belkin F5D5050 USB Ethernet",
- VENDOR_BELKIN, 0x0121,
- DEFAULT_GPIO_RESET | PEGASUS_II )
+
#endif /* PEGASUS_DEV */
}
-#ifdef __KERNEL__
+
/* BRIGHTNESS */
int pwc_get_brightness(struct pwc_device *pdev)
return (buf << 8);
}
+
static inline int pwc_read_blue_gain(struct pwc_device *pdev)
{
unsigned char buf;
return (buf << 8);
}
-/* still unused (it doesn't work yet...) */
-static inline int pwc_set_led(struct pwc_device *pdev, int value)
+int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
{
- unsigned char buf;
-
- if (value < 0)
- value = 0;
- if (value > 0xffff)
- value = 0xffff;
-
- buf = (value >> 8);
+ unsigned char buf[2];
+
+ if (pdev->type < 730)
+ return 0;
+ if (on_value < 0)
+ on_value = 0;
+ if (on_value > 0xff)
+ on_value = 0xff;
+ if (off_value < 0)
+ off_value = 0;
+ if (off_value > 0xff)
+ off_value = 0xff;
+
+ buf[0] = on_value;
+ buf[1] = off_value;
return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
SET_STATUS_CTL,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
LED_FORMATTER,
pdev->vcinterface,
- &buf, 1, HZ / 2);
+ &buf, 2, HZ / 2);
}
-/* still unused (it doesn't work yet...) */
-static inline int pwc_get_led(struct pwc_device *pdev)
+int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
{
- unsigned char buf;
+ unsigned char buf[2];
int ret;
+ if (pdev->type < 730) {
+ *on_value = -1;
+ *off_value = -1;
+ return 0;
+ }
+
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
GET_STATUS_CTL,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
LED_FORMATTER,
pdev->vcinterface,
- &buf, 1, HZ / 2);
+ &buf, 2, HZ / 2);
if (ret < 0)
- return ret;
-
- return (buf << 8);
+ return ret;
+ *on_value = buf[0];
+ *off_value = buf[1];
+ return 0;
}
/* End of Add-Ons */
case VIDIOCPWCSLED:
{
- int led, ret;
- if (copy_from_user(&led,arg,sizeof(led)))
- return -EFAULT;
- else {
- /* ret = pwc_set_led(pdev, led); */
- ret = 0;
+ int ret;
+ struct pwc_leds leds;
+
+ if (copy_from_user(&leds, arg, sizeof(leds)))
+ return -EFAULT;
+
+ ret = pwc_set_leds(pdev, leds.led_on, leds.led_off);
if (ret<0)
return ret;
- }
break;
}
case VIDIOCPWCGLED:
{
int led;
+ struct pwc_leds leds;
- led = pwc_get_led(pdev);
+ led = pwc_get_leds(pdev, &leds.led_on, &leds.led_off);
if (led < 0)
return -EINVAL;
- if (copy_to_user(arg, &led, sizeof(led)))
+ if (copy_to_user(arg, &leds, sizeof(leds)))
return -EFAULT;
break;
}
return 0;
}
-#endif
-
-
{ USB_DEVICE(0x0471, 0x0311) },
{ USB_DEVICE(0x0471, 0x0312) },
{ USB_DEVICE(0x069A, 0x0001) },
- { USB_DEVICE(0x046D, 0x0b80) },
+ { USB_DEVICE(0x046D, 0x08b0) },
+ { USB_DEVICE(0x055D, 0x9000) },
+ { USB_DEVICE(0x055D, 0x9001) },
{ }
};
MODULE_DEVICE_TABLE(usb, pwc_device_table);
static int default_mbufs = 2; /* Default number of mmap() buffers */
int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
static int power_save = 0;
+static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */
int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
static struct semaphore mem_lock;
pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
}
-/* XXX: 2001-06-17: The YUV420 palette will be phased out soon */
+/* 2001-10-14: The YUV420 is still there, but you can only set it from within
+ a program (YUV420P being the default) */
static int pwc_set_palette(struct pwc_device *pdev, int pal)
{
if ( pal == VIDEO_PALETTE_YUV420
Info("Failed to set alternate interface to 0.\n");
pdev->usb_init = 1;
}
- else {
- /* Turn on camera */
- if (power_save) {
- i = pwc_camera_power(pdev, 1);
- if (i < 0)
- Info("Failed to restore power to the camera! (%d)\n", i);
- }
+
+ /* Turn on camera */
+ if (power_save) {
+ i = pwc_camera_power(pdev, 1);
+ if (i < 0)
+ Info("Failed to restore power to the camera! (%d)\n", i);
}
+ /* Set LED on/off time */
+ if (pwc_set_leds(pdev, led_on, led_off) < 0)
+ Info("Failed to set LED on/off time.\n");
/* Find our decompressor, if any */
pdev->decompressor = pwc_find_decompressor(pdev->type);
up(&pdev->modlock);
return i;
}
+
i = usb_set_interface(pdev->udev, 0, pdev->valternate);
if (i) {
Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i);
Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n");
usb_set_interface(pdev->udev, 0, 0);
- /* Turn off LED by powering down camera */
+ /* Turn LEDs off */
+ if (pwc_set_leds(pdev, 0, 0) < 0)
+ Info("Failed to set LED on/off time..\n");
+ /* Power down camere to save energy */
if (power_save) {
i = pwc_camera_power(pdev, 0);
if (i < 0)
while (pdev->full_frames == NULL) {
if (noblock) {
remove_wait_queue(&pdev->frameq, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
return -EWOULDBLOCK;
}
if (signal_pending(current)) {
remove_wait_queue(&pdev->frameq, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
return -ERESTARTSYS;
}
schedule();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
}
remove_wait_queue(&pdev->frameq, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
/* Decompress [, convert] and release frame */
if (pwc_handle_frame(pdev))
while (pdev->full_frames == NULL) {
if (signal_pending(current)) {
remove_wait_queue(&pdev->frameq, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
return -ERESTARTSYS;
}
schedule();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
}
remove_wait_queue(&pdev->frameq, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
/* The frame is ready. Expand in the image buffer
requested by the user. I don't care if you
break;
}
}
- else if (vendor_id == 0x046d) {
- switch(product_id) {
- case 0x08b0:
- Info("Logitech QuickCam 3000 Pro detected.\n");
- type_id = 730;
+ else if (vendor_id == 0x046d) {
+ switch(product_id) {
+ case 0x08b0:
+ Info("Logitech QuickCam 3000 Pro detected.\n");
+ type_id = 730;
break;
default:
return NULL;
break;
}
}
- else return NULL; /* Not Philips or Askey, for sure. */
+ else if (vendor_id == 0x055d) {
+ /* I don't know the difference between the C10 and the C30;
+ I suppose the difference is the sensor, but both cameras
+ work equally well with a type_id of 675
+ */
+ switch(product_id) {
+ case 0x9000:
+ Info("Samsung MPC-C10 USB webcam detected.\n");
+ type_id = 675;
+ break;
+ case 0x9001:
+ Info("Samsung MPC-C30 USB webcam detected.\n");
+ type_id = 675;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ }
+ else return NULL; /* Not Philips, Askey, Logitech or Samsung, for sure. */
if (udev->descriptor.bNumConfigurations > 1)
Info("Warning: more than 1 configuration available.\n");
static char *size = NULL;
static int fps = 0;
-static char *palette = NULL;
static int fbufs = 0;
static int mbufs = 0;
static int trace = -1;
static int compression = -1;
+static int leds[2] = { -1, -1 };
MODULE_PARM(video_nr, "i");
MODULE_PARM(size, "s");
MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
MODULE_PARM(fps, "i");
MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
-MODULE_PARM(palette, "s");
-MODULE_PARM_DESC(palette, "Initial colour format of images. One of yuv420, yuv420p");
MODULE_PARM(fbufs, "i");
MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
MODULE_PARM(mbufs, "i");
MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
MODULE_PARM(compression, "i");
MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
-
+MODULE_PARM(leds, "2i");
+MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
MODULE_DESCRIPTION("Philips USB webcam driver");
MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
MODULE_LICENSE("GPL");
char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
- Info("Also supports Askey VC010 cam.\n");
+ Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro and the Samsung MPC-C10 and MPC-C30.\n");
if (fps) {
if (fps < 5 || fps > 30) {
}
Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
}
- if (palette) {
- /* Determine default palette */
- if (!strcmp(palette, "yuv420"))
- default_palette = VIDEO_PALETTE_YUV420;
- else if (!strcmp(palette, "yuv420p"))
- default_palette = VIDEO_PALETTE_YUV420P;
- else {
- Err("Palette not recognized: try palette=yuv420 or yuv420p.\n");
- return -EINVAL;
- }
- Info("Default palette set to %d.\n", default_palette);
- }
if (mbufs) {
if (mbufs < 1 || mbufs > MAX_IMAGES) {
Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
}
if (power_save)
Info("Enabling power save on open/close.\n");
+ if (leds[0] >= 0)
+ led_on = leds[0] / 100;
+ if (leds[1] >= 0)
+ led_off = leds[1] / 100;
init_MUTEX(&mem_lock);
Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
};
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+ int led_on; /* Led on-time; range = 0..255 */
+ int led_off; /* */
+};
+
+
+
/* Restore user settings */
#define VIDIOCPWCRUSER _IO('v', 192)
/* Save user settings */
#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
/* Turn LED on/off ; int range 0..65535 */
-#define VIDIOCPWCSLED _IOW('v', 205, int)
-
+#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
/* Get state of LED; int range 0..65535 */
-#define VIDIOCPWCGLED _IOR('v', 205, int)
+#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
#endif
/* Version block */
#define PWC_MAJOR 8
-#define PWC_MINOR 2
-#define PWC_VERSION "8.2"
+#define PWC_MINOR 3
+#define PWC_VERSION "8.3"
#define PWC_NAME "pwc"
/* Turn certain features on/off */
extern int pwc_set_gamma(struct pwc_device *pdev, int value);
extern int pwc_get_saturation(struct pwc_device *pdev);
extern int pwc_set_saturation(struct pwc_device *pdev, int value);
+extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
+extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
/* Power down or up the camera; not supported by all models */
extern int pwc_camera_power(struct pwc_device *pdev, int power);
comment 'USB Serial Converter support'
dep_tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
-if [ "$CONFIG_USB_SERIAL" != "n" ]; then
- if [ "$CONFIG_USB_SERIAL" = "y" ]; then
- bool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG
- fi
- bool ' USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC
- dep_tristate ' USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL
- dep_tristate ' USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
- dep_tristate ' USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- if [ "$CONFIG_USB_SERIAL_KEYSPAN" != "n" ]; then
- bool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28
- bool ' USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X
- bool ' USB Keyspan USA-28XA Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XA
- bool ' USB Keyspan USA-28XB Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XB
- bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19
- bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X
- bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W
- bool ' USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W
- fi
- dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
- dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+if [ "$CONFIG_USB_SERIAL" = "y" ]; then
+ dep_mbool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG $CONFIG_USB_SERIAL
fi
+dep_mbool ' USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC $CONFIG_USB_SERIAL
+dep_tristate ' USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL
+dep_tristate ' USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
+dep_tristate ' USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_mbool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28 $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-28XA Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XA $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-28XB Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XB $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19 $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W $CONFIG_USB_SERIAL_KEYSPAN
+ dep_mbool ' USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W $CONFIG_USB_SERIAL_KEYSPAN
+dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
endmenu
unsigned long flags;
spin_lock_irqsave(&uhci->frame_list_lock, flags);
- uhci->skel_term_td->status |= TD_CTRL_IOC;
+ set_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
}
unsigned long flags;
spin_lock_irqsave(&uhci->frame_list_lock, flags);
- uhci->skel_term_td->status &= ~TD_CTRL_IOC;
+ clear_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
}
if (status & TD_CTRL_NAK) /* NAK */
return -ETIMEDOUT;
if (status & TD_CTRL_BABBLE) /* Babble */
- return -EPIPE;
+ return -EOVERFLOW;
if (status & TD_CTRL_DBUFERR) /* Buffer error */
return -ENOSR;
if (status & TD_CTRL_STALLED) /* Stalled */
!(td->status & TD_CTRL_ACTIVE)) {
uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
urbp->fsbr_timeout = 0;
- td->status &= ~TD_CTRL_IOC;
+ clear_bit(TD_CTRL_IOC_BIT, &td->status);
}
status = uhci_status_bits(td->status);
!(td->status & TD_CTRL_ACTIVE)) {
uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
urbp->fsbr_timeout = 0;
- td->status &= ~TD_CTRL_IOC;
+ clear_bit(TD_CTRL_IOC_BIT, &td->status);
}
status = uhci_status_bits(td->status);
tmp = tmp->next;
if (td->status & TD_CTRL_ACTIVE) {
- td->status |= TD_CTRL_IOC;
+ set_bit(TD_CTRL_IOC_BIT, &td->status);
break;
}
}
#define TD_CTRL_C_ERR_SHIFT 27
#define TD_CTRL_LS (1 << 26) /* Low Speed Device */
#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */
+#define TD_CTRL_IOC_BIT 24
#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */
#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */
#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */
* 12-Nov-2000 Reworked to comply with new probe() signature.
* 23-Jan-2001 Added compatibility with 2.2.x kernels.
*/
-static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum
-#if defined(usb_device_id_ver)
- ,const struct usb_device_id *devid
-#endif
- )
+static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum ,const struct usb_device_id *devid)
{
uvd_t *uvd = NULL;
int i, nas;
if (status & TD_CTRL_NAK) /* NAK */
return -ETIMEDOUT;
if (status & TD_CTRL_BABBLE) /* Babble */
- return -EPIPE;
+ return -EOVERFLOW;
if (status & TD_CTRL_DBUFERR) /* Buffer error */
return -ENOSR;
if (status & TD_CTRL_STALLED) /* Stalled */
-/* $Id: cgsixfb.c,v 1.25 2001/09/19 00:04:33 davem Exp $
+/* $Id: cgsixfb.c,v 1.26 2001/10/16 05:44:44 davem Exp $
* cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
-/* $Id: creatorfb.c,v 1.36 2001/09/19 00:04:33 davem Exp $
+/* $Id: creatorfb.c,v 1.37 2001/10/16 05:44:44 davem Exp $
* creatorfb.c: Creator/Creator3D frame buffer driver
*
* Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
-/* $Id: leofb.c,v 1.13 2001/09/19 00:04:33 davem Exp $
+/* $Id: leofb.c,v 1.14 2001/10/16 05:44:44 davem Exp $
* leofb.c: Leo (ZX) 24/8bit frame buffer driver
*
* Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
size_buffers_type[blist] += bh->b_size;
}
-static void __remove_from_lru_list(struct buffer_head * bh, int blist)
+static void __remove_from_lru_list(struct buffer_head * bh)
{
struct buffer_head *next = bh->b_next_free;
if (next) {
struct buffer_head *prev = bh->b_prev_free;
+ int blist = bh->b_list;
+
prev->b_next_free = next;
next->b_prev_free = prev;
if (lru_list[blist] == bh) {
static void __remove_from_queues(struct buffer_head *bh)
{
__hash_unlink(bh);
- __remove_from_lru_list(bh, bh->b_list);
+ __remove_from_lru_list(bh);
}
struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
if (buffer_dirty(bh))
dispose = BUF_DIRTY;
if (dispose != bh->b_list) {
- __remove_from_lru_list(bh, bh->b_list);
+ __remove_from_lru_list(bh);
bh->b_list = dispose;
if (dispose == BUF_CLEAN)
remove_inode_queue(bh);
*/
void __bforget(struct buffer_head * buf)
{
- /* mark_buffer_clean(bh); */
- __brelse(buf);
+ /* grab the lru lock here so that "b_count" is stable */
+ spin_lock(&lru_list_lock);
+ write_lock(&hash_table_lock);
+ if (!atomic_dec_and_test(&buf->b_count) || buffer_locked(buf))
+ goto in_use;
+
+ /* Mark it clean */
+ clear_bit(BH_Dirty, &buf->b_state);
+ write_unlock(&hash_table_lock);
+
+ /* After which we can remove it from all queues */
+ remove_inode_queue(buf);
+ __remove_from_lru_list(buf);
+ buf->b_list = BUF_CLEAN;
+ spin_unlock(&lru_list_lock);
+ return;
+
+in_use:
+ write_unlock(&hash_table_lock);
+ spin_unlock(&lru_list_lock);
}
/**
static LIST_HEAD(entry_unused);
static struct list_head hash_table[C_HASHSIZE];
-spinlock_t entry_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t entry_lock = SPIN_LOCK_UNLOCKED;
static struct {
int nr_entries;
static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
{
if (path_walk(name, nd))
- return 0;
+ return 0; /* something went wrong... */
- if (!nd->dentry->d_inode) {
+ if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) {
struct nameidata nd_root;
+ /*
+ * NAME was not found in alternate root or it's a directory. Try to find
+ * it in the normal root:
+ */
nd_root.last_type = LAST_ROOT;
nd_root.flags = nd->flags;
read_lock(¤t->fs->lock);
atomic_inc(&sb->s_active);
mnt->mnt_sb = sb;
mnt->mnt_root = dget(root);
+ mnt->mnt_mountpoint = mnt->mnt_root;
+ mnt->mnt_parent = mnt;
}
return mnt;
}
printk(KERN_NOTICE "Trying to unmount old root ... ");
if (!blivet) {
spin_lock(&dcache_lock);
- list_del(&old_rootmnt->mnt_list);
+ list_del_init(&old_rootmnt->mnt_list);
spin_unlock(&dcache_lock);
mntput(old_rootmnt);
mntput(old_rootmnt);
{
int nfserr;
- dprintk("nfsd: LOOKUP %s %s\n",
- SVCFH_fmt(&argp->fh), argp->name);
+ dprintk("nfsd: LOOKUP %s %.*s\n",
+ SVCFH_fmt(&argp->fh), argp->len, argp->name);
fh_init(&resp->fh, NFS_FHSIZE);
nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
int nfserr, type, mode;
dev_t rdev = NODEV;
- dprintk("nfsd: CREATE %s %s\n",
- SVCFH_fmt(dirfhp), argp->name);
+ dprintk("nfsd: CREATE %s %*.s\n",
+ SVCFH_fmt(dirfhp), argp->len, argp->name);
/* First verify the parent file handle */
nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC);
{
int nfserr;
- dprintk("nfsd: REMOVE %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
+ dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh),
+ argp->len, argp->name);
/* Unlink. -SIFDIR means file must not be a directory */
nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
{
int nfserr;
- dprintk("nfsd: RENAME %s %s -> \n",
- SVCFH_fmt(&argp->ffh), argp->fname);
- dprintk("nfsd: -> %s %s\n",
- SVCFH_fmt(&argp->tfh), argp->tname);
+ dprintk("nfsd: RENAME %s %.*s -> \n",
+ SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
+ dprintk("nfsd: -> %s %.*s\n",
+ SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
&argp->tfh, argp->tname, argp->tlen);
dprintk("nfsd: LINK %s ->\n",
SVCFH_fmt(&argp->ffh));
- dprintk("nfsd: %s %s\n",
+ dprintk("nfsd: %s %.*s\n",
SVCFH_fmt(&argp->tfh),
+ argp->tlen,
argp->tname);
nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
struct svc_fh newfh;
int nfserr;
- dprintk("nfsd: SYMLINK %s %s -> %s\n",
- SVCFH_fmt(&argp->ffh), argp->fname, argp->tname);
+ dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n",
+ SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
+ argp->tlen, argp->tname);
fh_init(&newfh, NFS_FHSIZE);
/*
{
int nfserr;
- dprintk("nfsd: MKDIR %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
+ dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
if (resp->fh.fh_dentry) {
printk(KERN_WARNING
{
int nfserr;
- dprintk("nfsd: RMDIR %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
+ dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
fh_put(&argp->fh);
lock_kernel();
daemonize();
sprintf(current->comm, "nfsd");
- current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
+ current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
nfsdstats.th_cnt++;
/* Let svc_process check client's authentication. */
if (*name == '\0')
return NULL;
}
- *name = '\0';
}
return p;
/* lowlevel.c */
extern unsigned int udf_get_last_session(struct super_block *);
-extern unsigned int udf_get_last_block(struct super_block *);
+extern unsigned long udf_get_last_block(struct super_block *);
/* partition.c */
extern Uint32 udf_get_pblock(struct super_block *, Uint32, Uint16, Uint32);
void disable_hlt(void);
void enable_hlt(void);
+extern int is_sony_vaio_laptop;
+
#endif
#define __NR_fcntl64 221
#define __NR_security 223 /* syscall for security modules */
#define __NR_gettid 224
+#define __NR_readahead 225
/* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
static inline void kunmap_atomic(void *kvaddr, enum km_type type)
{
-#if HIGHMEM_DEBUG
unsigned long vaddr = (unsigned long) kvaddr;
unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
-#if 0
- if (vaddr < FIXADDR_START) // FIXME
+ if (vaddr < FIX_KMAP_BEGIN) // FIXME
return;
-#endif
if (vaddr != FIX_KMAP_BEGIN + idx * PAGE_SIZE)
BUG();
flush_cache_all();
#endif
+#ifdef HIGHMEM_DEBUG
/*
* force other mappings to Oops if they'll try to access
* this pte without first remap it
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
-#define SMP_CACHE_BYTES 64 /* L2 cache line size. */
+#define SMP_CACHE_BYTES_SHIFT 6
+#define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT) /* L2 cache line size. */
#ifdef MODULE
#define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
#include <linux/spinlock.h>
/* entry.S is sensitive to the offsets of these fields */
+/* rtrap.S is sensitive to the size of this structure */
typedef struct {
unsigned int __softirq_pending;
unsigned int __unused_1;
#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */
#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers, privileged. */
#define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */
-#define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options. */
+#define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options, priv. */
+#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */
+#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */
+#define ETHTOOL_NWAY_RST 0X00000009 /* Restart autonegotiation, priv. */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
#define SUPPORTED_AUI (1 << 8)
#define SUPPORTED_MII (1 << 9)
#define SUPPORTED_FIBRE (1 << 10)
+#define SUPPORTED_10base2 (1 << 11)
/* Indicates what features are advertised by the interface. */
#define ADVERTISED_10baseT_Half (1 << 0)
#define ADVERTISED_AUI (1 << 8)
#define ADVERTISED_MII (1 << 9)
#define ADVERTISED_FIBRE (1 << 10)
+#define ADVERTISED_10base2 (1 << 11)
/* The following are all involved in forcing a particular link
* mode for the device for setting things. When getting the
#define PCI_DEVICE_ID_INTEL_82801CA_10 0x248a
#define PCI_DEVICE_ID_INTEL_82801CA_11 0x248b
#define PCI_DEVICE_ID_INTEL_82801CA_12 0x248c
+#define PCI_DEVICE_ID_INTEL_80310 0x530d
#define PCI_DEVICE_ID_INTEL_82810_MC1 0x7120
#define PCI_DEVICE_ID_INTEL_82810_IG1 0x7121
#define PCI_DEVICE_ID_INTEL_82810_MC3 0x7122
/* linux/mm/vmscan.c */
extern wait_queue_head_t kswapd_wait;
-extern int FASTCALL(try_to_free_pages(zone_t *, unsigned int, unsigned int));
+extern int FASTCALL(try_to_free_pages(unsigned int, unsigned int));
/* linux/mm/page_io.c */
extern void rw_swap_page(int, struct page *);
#endif
#define RTO_ONLINK 0x01
-#define RTO_TPROXY 0x80000000
#define RTO_CONN 0
+/* RTO_CONN is not used (being alias for 0), but preserved not to break
+ * some modules referring to it. */
+
+#define RT_CONN_FLAGS(sk) (RT_TOS(sk->protinfo.af_inet.tos) | sk->localroute)
struct rt_key
{
static void shm_get_stat (unsigned long *rss, unsigned long *swp)
{
+ struct shmem_inode_info *info;
int i;
*rss = 0;
if(shp == NULL)
continue;
inode = shp->shm_file->f_dentry->d_inode;
- spin_lock (&inode->u.shmem_i.lock);
+ info = SHMEM_I(inode);
+ spin_lock (&info->lock);
*rss += inode->i_mapping->nrpages;
- *swp += inode->u.shmem_i.swapped;
- spin_unlock (&inode->u.shmem_i.lock);
+ *swp += info->swapped;
+ spin_unlock (&info->lock);
}
}
extern void *sys_call_table;
-extern int sys_tz;
+extern struct timezone sys_tz;
extern int request_dma(unsigned int dmanr, char * deviceID);
extern void free_dma(unsigned int dmanr);
extern spinlock_t dma_spin_lock;
current->session = 1;
current->pgrp = 1;
+ current->tty = NULL;
/* Become as one with the init task */
return retval;
}
+static ssize_t do_readahead(struct file *file, unsigned long index, unsigned long nr)
+{
+ struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+ unsigned long max;
+
+ if (!mapping || !mapping->a_ops || !mapping->a_ops->readpage)
+ return -EINVAL;
+
+ /* Limit it to the size of the file.. */
+ max = (mapping->host->i_size + ~PAGE_CACHE_MASK) >> PAGE_CACHE_SHIFT;
+ if (index > max)
+ return 0;
+ max -= index;
+ if (nr > max)
+ nr = max;
+
+ /* And limit it to a sane percentage of the inactive list.. */
+ max = nr_inactive_pages / 2;
+ if (nr > max)
+ nr = max;
+
+ while (nr) {
+ page_cache_read(file, index);
+ index++;
+ nr--;
+ }
+ return 0;
+}
+
+asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count)
+{
+ ssize_t ret;
+ struct file *file;
+
+ ret = -EBADF;
+ file = fget(fd);
+ if (file) {
+ if (file->f_mode & FMODE_READ) {
+ unsigned long start = offset >> PAGE_CACHE_SHIFT;
+ unsigned long len = (count + ((long)offset & ~PAGE_CACHE_MASK)) >> PAGE_CACHE_SHIFT;
+ ret = do_readahead(file, start, len);
+ }
+ fput(file);
+ }
+ return ret;
+}
+
/*
* Read-ahead and flush behind for MADV_SEQUENTIAL areas. Since we are
* sure this is sequential access, we don't need a flexible read-ahead
unsigned long pgoff)
{
unsigned char present = 0;
- struct address_space * as = &vma->vm_file->f_dentry->d_inode->i_mapping;
+ struct address_space * as = vma->vm_file->f_dentry->d_inode->i_mapping;
struct page * page, ** hash = page_hash(as, pgoff);
spin_lock(&pagecache_lock);
current->allocation_order = order;
current->flags |= PF_MEMALLOC | PF_FREE_PAGES;
- __freed = try_to_free_pages(classzone, gfp_mask, order);
+ __freed = try_to_free_pages(gfp_mask, order);
current->flags &= ~(PF_MEMALLOC | PF_FREE_PAGES);
static int shmem_parse_options(char *options, int *mode, unsigned long * blocks, unsigned long *inodes)
{
- char *this_char, *value;
+ char *this_char, *value, *rest;
this_char = NULL;
if ( options )
this_char = strtok(options,",");
for ( ; this_char; this_char = strtok(NULL,",")) {
- if ((value = strchr(this_char,'=')) != NULL)
+ if ((value = strchr(this_char,'=')) != NULL) {
*value++ = 0;
+ } else {
+ printk(KERN_ERR
+ "shmem_parse_options: No value for option '%s'\n",
+ this_char);
+ return 1;
+ }
+
if (!strcmp(this_char,"size")) {
unsigned long long size;
- if (!value || !*value || !blocks)
- return 1;
- size = memparse(value,&value);
- if (*value)
- return 1;
+ size = memparse(value,&rest);
+ if (*rest)
+ goto bad_val;
*blocks = size >> PAGE_CACHE_SHIFT;
} else if (!strcmp(this_char,"nr_blocks")) {
- if (!value || !*value || !blocks)
- return 1;
- *blocks = memparse(value,&value);
- if (*value)
- return 1;
+ *blocks = memparse(value,&rest);
+ if (*rest)
+ goto bad_val;
} else if (!strcmp(this_char,"nr_inodes")) {
- if (!value || !*value || !inodes)
- return 1;
- *inodes = memparse(value,&value);
- if (*value)
- return 1;
+ *inodes = memparse(value,&rest);
+ if (*rest)
+ goto bad_val;
} else if (!strcmp(this_char,"mode")) {
- if (!value || !*value || !mode)
- return 1;
- *mode = simple_strtoul(value,&value,8);
- if (*value)
- return 1;
- }
- else
+ if (!mode)
+ continue;
+ *mode = simple_strtoul(value,&rest,8);
+ if (*rest)
+ goto bad_val;
+ } else {
+ printk(KERN_ERR "shmem_parse_options: Bad option %s\n",
+ this_char);
return 1;
+ }
}
return 0;
+
+bad_val:
+ printk(KERN_ERR "shmem_parse_options: Bad value '%s' for option '%s'\n",
+ value, this_char);
+ return 1;
+
}
static int shmem_remount_fs (struct super_block *sb, int *flags, char *data)
/* Use a smaller cluster for small-memory machines */
if (megs < 16)
page_cluster = 2;
- else if (megs < 32)
- page_cluster = 3;
- else if (megs < 64)
- page_cluster = 4;
- else if (megs < 128)
- page_cluster = 5;
else
- page_cluster = 6;
+ page_cluster = 3;
+ /*
+ * Right now other parts of the system means that we
+ * _really_ don't want to cluster much more
+ */
}
*/
#define DEF_PRIORITY (6)
+#define page_zone_plenty(page) ((page)->zone->free_pages > (page)->zone->pages_high)
+
/*
* The swap-out function returns 1 if it successfully
* scanned all the pages it was asked to (`count').
*/
/* mm->page_table_lock is held. mmap_sem is not held */
-static inline int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, unsigned long address, pte_t * page_table, struct page *page, zone_t * classzone)
+static inline int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, unsigned long address, pte_t * page_table, struct page *page)
{
pte_t pte;
swp_entry_t entry;
- int right_classzone;
/* Don't look at this pte if it's been accessed recently. */
if (ptep_test_and_clear_young(page_table)) {
return 0;
}
- if (TryLockPage(page))
+ /* Don't bother replenishing zones that have tons of memory */
+ if (page_zone_plenty(page))
return 0;
- right_classzone = 1;
- if (!memclass(page->zone, classzone))
- right_classzone = 0;
+ if (TryLockPage(page))
+ return 0;
/* From this point on, the odds are that we're going to
* nuke this pte, so read and clear the pte. This hook
{
int freeable = page_count(page) - !!page->buffers <= 2;
page_cache_release(page);
- return freeable & right_classzone;
+ return freeable;
}
}
}
/* mm->page_table_lock is held. mmap_sem is not held */
-static inline int swap_out_pmd(struct mm_struct * mm, struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int count, zone_t * classzone)
+static inline int swap_out_pmd(struct mm_struct * mm, struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int count)
{
pte_t * pte;
unsigned long pmd_end;
struct page *page = pte_page(*pte);
if (VALID_PAGE(page) && !PageReserved(page)) {
- count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
+ count -= try_to_swap_out(mm, vma, address, pte, page);
if (!count) {
address += PAGE_SIZE;
break;
}
/* mm->page_table_lock is held. mmap_sem is not held */
-static inline int swap_out_pgd(struct mm_struct * mm, struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int count, zone_t * classzone)
+static inline int swap_out_pgd(struct mm_struct * mm, struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int count)
{
pmd_t * pmd;
unsigned long pgd_end;
end = pgd_end;
do {
- count = swap_out_pmd(mm, vma, pmd, address, end, count, classzone);
+ count = swap_out_pmd(mm, vma, pmd, address, end, count);
if (!count)
break;
address = (address + PMD_SIZE) & PMD_MASK;
}
/* mm->page_table_lock is held. mmap_sem is not held */
-static inline int swap_out_vma(struct mm_struct * mm, struct vm_area_struct * vma, unsigned long address, int count, zone_t * classzone)
+static inline int swap_out_vma(struct mm_struct * mm, struct vm_area_struct * vma, unsigned long address, int count)
{
pgd_t *pgdir;
unsigned long end;
if (address >= end)
BUG();
do {
- count = swap_out_pgd(mm, vma, pgdir, address, end, count, classzone);
+ count = swap_out_pgd(mm, vma, pgdir, address, end, count);
if (!count)
break;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
/*
* Returns remaining count of pages to be swapped out by followup call.
*/
-static inline int swap_out_mm(struct mm_struct * mm, int count, int * mmcounter, zone_t * classzone)
+static inline int swap_out_mm(struct mm_struct * mm, int count, int * mmcounter)
{
unsigned long address;
struct vm_area_struct* vma;
address = vma->vm_start;
for (;;) {
- count = swap_out_vma(mm, vma, address, count, classzone);
+ count = swap_out_vma(mm, vma, address, count);
vma = vma->vm_next;
if (!vma)
break;
return count;
}
-static int FASTCALL(swap_out(unsigned int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages));
-static int swap_out(unsigned int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages)
+static int FASTCALL(swap_out(unsigned int priority, unsigned int gfp_mask, int nr_pages));
+static int swap_out(unsigned int priority, unsigned int gfp_mask, int nr_pages)
{
int counter;
struct mm_struct *mm;
atomic_inc(&mm->mm_users);
spin_unlock(&mmlist_lock);
- nr_pages = swap_out_mm(mm, nr_pages, &counter, classzone);
+ nr_pages = swap_out_mm(mm, nr_pages, &counter);
mmput(mm);
return 0;
}
-static int FASTCALL(shrink_cache(int nr_pages, int max_scan, zone_t * classzone, unsigned int gfp_mask));
-static int shrink_cache(int nr_pages, int max_scan, zone_t * classzone, unsigned int gfp_mask)
+static int FASTCALL(shrink_cache(int nr_pages, int max_scan, unsigned int gfp_mask));
+static int shrink_cache(int nr_pages, int max_scan, unsigned int gfp_mask)
{
struct list_head * entry;
if (unlikely(!PageInactive(page) && !PageActive(page)))
BUG();
+ /* Mapping-less page on LRU-list? */
+ if (unlikely(!page->mapping))
+ BUG();
+
list_del(entry);
list_add(entry, &inactive_list);
if (PageTestandClearReferenced(page))
continue;
max_scan--;
-
- if (unlikely(!memclass(page->zone, classzone)))
+ if (unlikely(page_zone_plenty(page)))
continue;
/* Racy check to avoid trylocking when not worthwhile */
- if (!page->buffers && page_count(page) != 1)
+ if (!is_page_cache_freeable(page))
+ continue;
+
+ if (unlikely(TryLockPage(page))) {
+ if (gfp_mask & __GFP_FS) {
+ page_cache_get(page);
+ spin_unlock(&pagemap_lru_lock);
+ wait_on_page(page);
+ page_cache_release(page);
+ spin_lock(&pagemap_lru_lock);
+ }
continue;
+ }
/*
- * The page is locked. IO in progress?
- * Move it to the back of the list.
+ * Still strictly racy - we don't own the pagecache lock,
+ * so somebody might look up the page while we do this.
+ * It's just a heuristic, though.
*/
- if (unlikely(TryLockPage(page)))
+ if (!is_page_cache_freeable(page)) {
+ UnlockPage(page);
continue;
+ }
- if (PageDirty(page) && is_page_cache_freeable(page)) {
+ if (PageDirty(page)) {
/*
* It is not critical here to write it only if
* the page is unmapped beause any direct writer
}
}
- if (unlikely(!page->mapping))
- BUG();
-
if (unlikely(!spin_trylock(&pagecache_lock))) {
/* we hold the page lock so the page cannot go away from under us */
spin_unlock(&pagemap_lru_lock);
spin_unlock(&pagemap_lru_lock);
}
-static int FASTCALL(shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages));
-static int shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages)
+static int FASTCALL(shrink_caches(int priority, unsigned int gfp_mask, int nr_pages));
+static int shrink_caches(int priority, unsigned int gfp_mask, int nr_pages)
{
int max_scan;
int chunk_size = nr_pages;
/* try to keep the active list 2/3 of the size of the cache */
ratio = (unsigned long) nr_pages * nr_active_pages / ((nr_inactive_pages + 1) * 2);
refill_inactive(ratio);
-
+
max_scan = nr_inactive_pages / priority;
- nr_pages = shrink_cache(nr_pages, max_scan, classzone, gfp_mask);
+ nr_pages = shrink_cache(nr_pages, max_scan, gfp_mask);
if (nr_pages <= 0)
return 0;
return nr_pages;
}
-int try_to_free_pages(zone_t * classzone, unsigned int gfp_mask, unsigned int order)
+int try_to_free_pages(unsigned int gfp_mask, unsigned int order)
{
int ret = 0;
int priority = DEF_PRIORITY;
int nr_pages = SWAP_CLUSTER_MAX;
do {
- nr_pages = shrink_caches(priority, classzone, gfp_mask, nr_pages);
+ nr_pages = shrink_caches(priority, gfp_mask, nr_pages);
if (nr_pages <= 0)
return 1;
- ret |= swap_out(priority, classzone, gfp_mask, SWAP_CLUSTER_MAX << 2);
+ ret |= swap_out(priority, gfp_mask, SWAP_CLUSTER_MAX << 2);
} while (--priority);
return ret;
schedule();
if (!zone->need_balance)
continue;
- if (!try_to_free_pages(zone, GFP_KSWAPD, 0)) {
+ if (!try_to_free_pages(GFP_KSWAPD, 0)) {
zone->need_balance = 0;
__set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br.c,v 1.45 2000/10/22 18:26:07 davem Exp $
+ * $Id: br.c,v 1.46 2001/10/02 02:22:36 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
*
* The Internet Protocol (IP) output module.
*
- * Version: $Id: ip_output.c,v 1.98 2001/09/01 00:31:50 davem Exp $
+ * Version: $Id: ip_output.c,v 1.99 2001/10/15 12:34:50 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* out.
*/
if (ip_route_output(&rt, daddr, sk->saddr,
- RT_TOS(sk->protinfo.af_inet.tos) | RTO_CONN | sk->localroute,
+ RT_CONN_FLAGS(sk),
sk->bound_dev_if))
goto no_route;
__sk_dst_set(sk, &rt->u.dst);
/*
- * $Id: ipconfig.c,v 1.38 2001/09/25 23:23:07 davem Exp $
+ * $Id: ipconfig.c,v 1.39 2001/10/13 01:47:31 davem Exp $
*
* Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or
* user-supplied information to configure own IP address and routes.
/*
* Linux NET3: IP/IP protocol decoder.
*
- * Version: $Id: ipip.c,v 1.49 2001/09/25 22:35:47 davem Exp $
+ * Version: $Id: ipip.c,v 1.50 2001/10/02 02:22:36 davem Exp $
*
* Authors:
* Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
*
* ROUTE - implementation of the IP router.
*
- * Version: $Id: route.c,v 1.99 2001/09/18 22:29:09 davem Exp $
+ * Version: $Id: route.c,v 1.100 2001/10/15 12:34:50 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
rth->key.fwmark == key->fwmark &&
#endif
!((rth->key.tos ^ key->tos) &
- (IPTOS_RT_MASK | RTO_ONLINK)) &&
- ((key->tos & RTO_TPROXY) ||
- !(rth->rt_flags & RTCF_TPROXY))) {
+ (IPTOS_RT_MASK | RTO_ONLINK))) {
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
rth->u.dst.__use++;
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * $Id: syncookies.c,v 1.14 2001/05/05 01:01:55 davem Exp $
+ * $Id: syncookies.c,v 1.15 2001/10/15 12:34:50 davem Exp $
*
* Missing: IPv6 support.
*/
opt &&
opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
req->af.v4_req.loc_addr,
- sk->protinfo.af_inet.tos | RTO_CONN,
+ RT_CONN_FLAGS(sk),
0)) {
tcp_openreq_free(req);
goto out;
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_ipv4.c,v 1.231 2001/09/26 23:38:47 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.232 2001/10/15 12:34:50 davem Exp $
*
* IPv4 specific functions
*
}
tmp = ip_route_connect(&rt, nexthop, sk->saddr,
- RT_TOS(sk->protinfo.af_inet.tos)|RTO_CONN|sk->localroute, sk->bound_dev_if);
+ RT_CONN_FLAGS(sk), sk->bound_dev_if);
if (tmp < 0)
return tmp;
daddr = rt->rt_dst;
err = -ENOBUFS;
- buff = alloc_skb(MAX_TCP_HEADER + 15, GFP_KERNEL);
+ buff = alloc_skb(MAX_TCP_HEADER + 15, sk->allocation);
if (buff == NULL)
goto failure;
opt->faddr :
req->af.v4_req.rmt_addr),
req->af.v4_req.loc_addr,
- RT_TOS(sk->protinfo.af_inet.tos) | RTO_CONN | sk->localroute,
- sk->bound_dev_if)) {
+ RT_CONN_FLAGS(sk), sk->bound_dev_if)) {
IP_INC_STATS_BH(IpOutNoRoutes);
return NULL;
}
daddr = sk->protinfo.af_inet.opt->faddr;
err = ip_route_output(&rt, daddr, sk->saddr,
- RT_TOS(sk->protinfo.af_inet.tos) | RTO_CONN | sk->localroute,
- sk->bound_dev_if);
+ RT_CONN_FLAGS(sk), sk->bound_dev_if);
if (!err) {
__sk_dst_set(sk, &rt->u.dst);
sk->route_caps = rt->u.dst.dev->features;
*
* The User Datagram Protocol (UDP).
*
- * Version: $Id: udp.c,v 1.99 2001/09/01 00:31:50 davem Exp $
+ * Version: $Id: udp.c,v 1.100 2001/10/15 12:34:50 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
sk_dst_reset(sk);
err = ip_route_connect(&rt, usin->sin_addr.s_addr, sk->saddr,
- sk->protinfo.af_inet.tos|sk->localroute, sk->bound_dev_if);
+ RT_CONN_FLAGS(sk), sk->bound_dev_if);
if (err)
return err;
if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) {
*
* Adapted from linux/net/ipv4/af_inet.c
*
- * $Id: af_inet6.c,v 1.64 2001/06/13 16:25:03 davem Exp $
+ * $Id: af_inet6.c,v 1.65 2001/10/02 02:22:36 davem Exp $
*
* Fixes:
* piggy, Karl Knutson : Socket protocol table
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: tcp_ipv6.c,v 1.139 2001/09/26 23:38:47 davem Exp $
+ * $Id: tcp_ipv6.c,v 1.140 2001/10/15 12:34:50 davem Exp $
*
* Based on:
* linux/net/ipv4/tcp.c
return tcp_v6_lookup_listener(daddr, hnum, dif);
}
-#define tcp_v6_lookup(sa, sp, da, dp, dif) \
-({ struct sock *___sk; \
- local_bh_disable(); \
- ___sk = __tcp_v6_lookup((sa),(sp),(da),ntohs(dp),(dif)); \
- local_bh_enable(); \
- ___sk; \
-})
+__inline__ struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
+ struct in6_addr *daddr, u16 dport,
+ int dif)
+{
+ struct sock *sk;
+
+ local_bh_disable();
+ sk = __tcp_v6_lookup(saddr, sport, daddr, ntohs(dport), dif);
+ local_bh_enable();
+
+ return sk;
+}
/*
tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
err = -ENOBUFS;
- buff = alloc_skb(MAX_TCP_HEADER + 15, GFP_KERNEL);
+ buff = alloc_skb(MAX_TCP_HEADER + 15, sk->allocation);
if (buff == NULL)
goto failure;
struct inode * inode;
struct socket * sock;
- inode = new_inode(sock_mnt->mnt_sb);
+ inode = get_empty_inode();
if (!inode)
return NULL;
+ inode->i_sb = sock_mnt->mnt_sb;
sock = socki_lookup(inode);
inode->i_mode = S_IFSOCK|S_IRWXUGO;