From 792ee2cdb7c09660e8c47bc0d4c8961dd15b4426 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:16:25 -0500 Subject: [PATCH] Import 2.1.118 --- CREDITS | 20 +- Documentation/video4linux/API.html | 354 +++++++ Documentation/video4linux/bttv/CARDS | 104 +++ Documentation/video4linux/bttv/CONTRIBUTORS | 20 + Documentation/video4linux/bttv/ICs | 37 + Documentation/video4linux/bttv/INSTALL | 73 ++ Documentation/video4linux/bttv/PROBLEMS | 62 ++ Documentation/video4linux/bttv/README | 41 + Documentation/video4linux/bttv/README.FIRST | 4 + Documentation/video4linux/bttv/README.Hauppauge | 29 + Documentation/video4linux/bttv/README.MIRO | 3 + Documentation/video4linux/bttv/README.PCI | 36 + Documentation/video4linux/bttv/README.RADIO | 15 + Documentation/video4linux/bttv/THANKS | 24 + Documentation/{ => video4linux}/radiotrack.txt | 0 MAINTAINERS | 38 +- Makefile | 4 +- arch/i386/kernel/bios32.c | 66 +- arch/i386/kernel/mca.c | 2 +- arch/i386/kernel/mtrr.c | 1 + arch/i386/kernel/process.c | 27 +- arch/i386/kernel/signal.c | 43 +- arch/i386/lib/usercopy.c | 6 +- arch/i386/mm/init.c | 8 +- arch/m68k/atari/stram.c | 57 +- arch/m68k/bvme6000/rtc.c | 1 + arch/m68k/mac/adb-bus.c | 2 + arch/m68k/mvme16x/rtc.c | 1 + arch/ppc/kernel/ppc_htab.c | 1 + arch/sparc64/solaris/socksys.c | 2 + drivers/Makefile | 2 +- drivers/acorn/block/fd1772.c | 1 + drivers/acorn/block/mfmhd.c | 1 + drivers/ap1000/ap.c | 27 +- drivers/ap1000/ddv.c | 1 + drivers/ap1000/ringbuf.c | 1 + drivers/block/Makefile | 4 +- drivers/block/acsi.c | 3 +- drivers/block/acsi_slm.c | 3 +- drivers/block/amiflop.c | 1 + drivers/block/ataflop.c | 1 + drivers/block/floppy.c | 1 + drivers/block/genhd.c | 20 +- drivers/block/ide.c | 1 + drivers/block/loop.c | 1 + drivers/block/md.c | 1 + drivers/block/nbd.c | 1 + drivers/block/paride/Makefile | 37 +- drivers/block/paride/bpck.c | 5 +- drivers/block/paride/paride.c | 5 +- drivers/block/paride/pcd.c | 609 +++++++++---- drivers/block/paride/pd.c | 15 +- drivers/block/paride/pf.c | 17 +- drivers/block/paride/pg.c | 349 +++---- drivers/block/paride/pt.c | 22 +- drivers/block/ps2esdi.c | 1 + drivers/block/rd.c | 8 +- drivers/block/swim3.c | 3 +- drivers/block/xd.c | 1 + drivers/block/z2ram.c | 347 +++---- drivers/cdrom/Makefile | 1 + drivers/cdrom/aztcd.c | 1 + drivers/cdrom/cdrom.c | 3 + drivers/cdrom/gscd.c | 1 + drivers/cdrom/optcd.c | 1 + drivers/cdrom/sbpcd.c | 6 +- drivers/cdrom/sjcd.c | 1 + drivers/cdrom/sonycd535.c | 7 +- drivers/char/Config.in | 5 + drivers/char/Makefile | 8 + drivers/char/acquirewdt.c | 1 + drivers/char/adbmouse.c | 1 + drivers/char/amigamouse.c | 1 + drivers/char/apm_bios.c | 1 + drivers/char/atarimouse.c | 1 + drivers/char/atixlmouse.c | 1 + drivers/char/bt848.h | 17 +- drivers/char/bttv.c | 1113 ++++++++++++----------- drivers/char/bttv.h | 40 +- drivers/char/busmouse.c | 1 + drivers/char/cyclades.c | 13 +- drivers/char/dn_keyb.c | 1 + drivers/char/dsp56k.c | 1 + drivers/char/fbmem.c | 1 + drivers/char/ftape/lowlevel/ftape-proc.c | 1 + drivers/char/ftape/zftape/zftape-init.c | 1 + drivers/char/h8.c | 1 + drivers/char/hfmodem/main.c | 1 + drivers/char/lp.c | 1 + drivers/char/lp_m68k.c | 1 + drivers/char/macmouse.c | 1 + drivers/char/mem.c | 7 + drivers/char/misc.c | 1 + drivers/char/msbusmouse.c | 1 + drivers/char/n_tty.c | 31 +- drivers/char/nvram.c | 1 + drivers/char/pc110pad.c | 1 + drivers/char/pcwd.c | 1 + drivers/char/psaux.c | 1 + drivers/char/radio-aimslab.c | 1 + drivers/char/radio-aztech.c | 1 + drivers/char/radio-miropcm20.c | 245 +++++ drivers/char/radio-rtrack2.c | 1 + drivers/char/radio-sf16fmi.c | 84 +- drivers/char/radio-zoltrix.c | 1 + drivers/char/random.c | 2 + drivers/char/rtc.c | 1 + drivers/char/softdog.c | 1 + drivers/char/stallion.c | 1 + drivers/char/tpqic02.c | 1 + drivers/char/tty_io.c | 4 +- drivers/char/tuner.c | 2 +- drivers/char/vc_screen.c | 1 + drivers/char/videodev.c | 7 + drivers/char/wdt.c | 1 + drivers/isdn/avmb1/capi.c | 1 + drivers/macintosh/adb.c | 1 + drivers/macintosh/nvram.c | 1 + drivers/macintosh/via-pmu.c | 1 + drivers/pci/oldproc.c | 4 +- drivers/pci/pci.c | 11 +- drivers/pci/proc.c | 1 + drivers/sbus/audio/audio.c | 1 + drivers/sbus/char/bpp.c | 1 + drivers/sbus/char/envctrl.c | 1 + drivers/sbus/char/flash.c | 1 + drivers/sbus/char/openprom.c | 1 + drivers/sbus/char/pcikbd.c | 1 + drivers/sbus/char/rtc.c | 1 + drivers/sbus/char/sunkbd.c | 1 + drivers/sbus/char/sunmouse.c | 1 + drivers/sbus/char/vfc_dev.c | 1 + drivers/scsi/Makefile | 2 +- drivers/scsi/sd.c | 1 + drivers/scsi/seagate.c | 657 +++++-------- drivers/scsi/seagate.h | 4 - drivers/scsi/sg.c | 1 + drivers/scsi/st.c | 1 + drivers/sgi/char/graphics.c | 1 + drivers/sgi/char/shmiq.c | 1 + drivers/sgi/char/streamable.c | 3 + drivers/sgi/char/usema.c | 1 + drivers/sound/Config.in | 2 +- drivers/sound/dmasound.c | 3 + drivers/sound/es1370.c | 4 + drivers/sound/es1371.c | 4 + drivers/sound/lowlevel/README | 7 +- drivers/sound/lowlevel/README.aedsp16 | 137 --- drivers/sound/lowlevel/aci.c | 104 ++- drivers/sound/lowlevel/aedsp16.c | 149 +-- drivers/sound/lowlevel/miroaci.h | 6 + drivers/sound/lowlevel/soundlow.c | 5 +- drivers/sound/msnd_pinnacle.c | 1 + drivers/sound/sb_common.c | 2 +- drivers/sound/sonicvibes.c | 4 + drivers/sound/sound_core.c | 1 + drivers/sound/soundcard.c | 1 + drivers/zorro/proc.c | 1 + fs/adfs/dir.c | 1 + fs/adfs/file.c | 1 + fs/affs/dir.c | 1 + fs/affs/file.c | 2 + fs/autofs/dir.c | 1 + fs/autofs/root.c | 1 + fs/bad_inode.c | 1 + fs/binfmt_aout.c | 5 +- fs/binfmt_elf.c | 2 +- fs/binfmt_em86.c | 2 +- fs/binfmt_java.c | 2 +- fs/binfmt_misc.c | 2 +- fs/binfmt_script.c | 2 +- fs/buffer.c | 2 +- fs/coda/dir.c | 1 + fs/coda/file.c | 1 + fs/coda/pioctl.c | 1 + fs/coda/psdev.c | 1 + fs/dcache.c | 2 +- fs/devices.c | 2 + fs/devpts/inode.c | 8 +- fs/devpts/root.c | 1 + fs/dquot.c | 2 +- fs/exec.c | 2 +- fs/ext2/balloc.c | 2 +- fs/ext2/dir.c | 1 + fs/ext2/file.c | 1 + fs/ext2/ialloc.c | 3 +- fs/fat/dir.c | 1 + fs/fat/file.c | 3 + fs/fifo.c | 2 + fs/file_table.c | 4 +- fs/filesystems.c | 2 +- fs/hfs/dir_cap.c | 1 + fs/hfs/dir_dbl.c | 1 + fs/hfs/dir_nat.c | 1 + fs/hfs/file.c | 1 + fs/hfs/file_cap.c | 1 + fs/hfs/file_hdr.c | 1 + fs/isofs/dir.c | 1 + fs/isofs/file.c | 1 + fs/lockd/clntproc.c | 45 +- fs/lockd/svclock.c | 8 +- fs/minix/dir.c | 1 + fs/minix/file.c | 1 + fs/ncpfs/dir.c | 1 + fs/ncpfs/file.c | 1 + fs/nfs/dir.c | 32 +- fs/nfs/file.c | 26 +- fs/nfs/inode.c | 15 + fs/nfs/mount_clnt.c | 1 - fs/nfs/nfs2xdr.c | 8 - fs/nfs/write.c | 16 +- fs/ntfs/fs.c | 3 + fs/open.c | 13 +- fs/pipe.c | 7 + fs/proc/array.c | 2 + fs/proc/base.c | 1 + fs/proc/fd.c | 1 + fs/proc/generic.c | 1 + fs/proc/kmsg.c | 1 + fs/proc/link.c | 1 + fs/proc/mem.c | 1 + fs/proc/net.c | 1 + fs/proc/omirr.c | 1 + fs/proc/openpromfs.c | 3 + fs/proc/root.c | 14 +- fs/proc/scsi.c | 1 + fs/smbfs/dir.c | 1 + fs/smbfs/file.c | 1 + fs/super.c | 6 +- fs/sysv/dir.c | 1 + fs/sysv/file.c | 1 + fs/ufs/dir.c | 1 + fs/ufs/file.c | 1 + fs/umsdos/dir.c | 1 + fs/umsdos/file.c | 3 + fs/umsdos/rdir.c | 1 + fs/umsdos/symlink.c | 1 + include/asm-alpha/fcntl.h | 1 + include/asm-alpha/posix_types.h | 2 +- include/asm-arm/uaccess.h | 5 +- include/asm-i386/fcntl.h | 26 +- include/asm-i386/fixmap.h | 13 +- include/asm-i386/uaccess.h | 166 +++- include/asm-i386/unistd.h | 4 +- include/asm-m68k/uaccess.h | 9 +- include/asm-ppc/uaccess.h | 11 +- include/asm-sparc/uaccess.h | 5 +- include/linux/file.h | 8 +- include/linux/fs.h | 2 +- include/linux/pci.h | 7 +- include/linux/shm.h | 1 + include/linux/videodev.h | 2 +- init/main.c | 26 +- ipc/sem.c | 2 +- ipc/shm.c | 38 +- ipc/util.c | 2 +- kernel/capability.c | 1 - kernel/fork.c | 4 +- kernel/kmod.c | 2 +- kernel/panic.c | 2 +- kernel/printk.c | 2 +- kernel/resource.c | 2 +- kernel/sched.c | 2 +- kernel/signal.c | 4 +- kernel/sysctl.c | 3 +- mm/mmap.c | 2 +- mm/page_alloc.c | 2 +- mm/slab.c | 4 +- mm/swapfile.c | 2 + mm/vmscan.c | 3 +- net/netlink/netlink_dev.c | 1 + net/socket.c | 5 +- net/sunrpc/clnt.c | 2 +- net/sunrpc/sched.c | 60 +- net/sunrpc/xprt.c | 6 +- net/wanrouter/wanproc.c | 2 + 276 files changed, 3821 insertions(+), 2252 deletions(-) create mode 100644 Documentation/video4linux/API.html create mode 100644 Documentation/video4linux/bttv/CARDS create mode 100644 Documentation/video4linux/bttv/CONTRIBUTORS create mode 100644 Documentation/video4linux/bttv/ICs create mode 100644 Documentation/video4linux/bttv/INSTALL create mode 100644 Documentation/video4linux/bttv/PROBLEMS create mode 100644 Documentation/video4linux/bttv/README create mode 100644 Documentation/video4linux/bttv/README.FIRST create mode 100644 Documentation/video4linux/bttv/README.Hauppauge create mode 100644 Documentation/video4linux/bttv/README.MIRO create mode 100644 Documentation/video4linux/bttv/README.PCI create mode 100644 Documentation/video4linux/bttv/README.RADIO create mode 100644 Documentation/video4linux/bttv/THANKS rename Documentation/{ => video4linux}/radiotrack.txt (100%) create mode 100644 drivers/char/radio-miropcm20.c delete mode 100644 drivers/sound/lowlevel/README.aedsp16 create mode 100644 drivers/sound/lowlevel/miroaci.h diff --git a/CREDITS b/CREDITS index d7ee29257..c563579b7 100644 --- a/CREDITS +++ b/CREDITS @@ -67,6 +67,7 @@ P: 1024/CB4660B9 CC A0 71 81 F4 A0 63 AC C0 4B 81 1D 8C 15 C8 E5 D: Parport hacker D: Implemented a workaround for some interrupt buggy printers D: Author of pscan that helps to fix lp/parport bug +D: Author of lil (Linux Interrupt Latency benchmark) D: Various other kernel hacks S: Via Ciaclini 26 S: Imola 40026 @@ -333,18 +334,19 @@ S: East Malvern, Victoria, 3145 S: Australia N: Alan Cox -E: alan@lxorguk.ukuu.org.uk (linux related - except big patches) -E: iialan@www.uk.linux.org (linux.org.uk/big patches) -E: alan@cymru.net (commercial CymruNET stuff) +W: http://roadrunner.swansea.linux.org.uk/alan.shtml +E: alan@lxorguk.ukuu.org.uk +E: alan@www.linux.org.uk (linux.org.uk stuff) E: Alan.Cox@linux.org (if others fail) -D: NET2Debugged/NET3 author -D: Network layer debugging -D: Initial AX.25 & IPX releases -D: Original Linux netatalk patches. +D: Linux Networking (0.99.10->2.0.29) +D: Original Appletalk, AX.25, and IPX code D: Current 3c501 hacker. >>More 3c501 info/tricks wanted<<. D: Watchdog timer drivers -D: Linux/SMP -S: CymruNet Limited +D: Linux/SMP x86 (up to 2.0 only) +D: Initial Mac68K port +D: Video4Linux design, bw-qcam and PMS driver ports. +D: 2.1.x modular sound +S: c/o I2IT Limited S: The Innovation Centre S: Singleton Park S: Swansea, SA2 8PP diff --git a/Documentation/video4linux/API.html b/Documentation/video4linux/API.html new file mode 100644 index 000000000..5b3780cc3 --- /dev/null +++ b/Documentation/video4linux/API.html @@ -0,0 +1,354 @@ + +Video4Linux Kernel API Reference v0.1:19980516 + + +

Devices

+Video4Linux provides the following sets of device files. These live on the +character device formerly known as "/dev/bttv". /dev/bttv should be a +symlink to /dev/video0 for most people. +

+ + + + + + +
Device NameMinor RangeFunction
/dev/video0-63Video Capture Interface
/dev/radio64-127AM/FM Radio Devices
/dev/vtx192-223Teletext Interface Chips
/dev/vbi224-239Raw VBI Data (Intercast/teletext)
+

+Video4Linux programs open and scan the devices to find what they are looking +for. Capability queries define what each interface supports. The +described API is only defined for video capture cards. The relevant subset +applies to radio cards. Teletext interfaces talk the existing VTX API. +

+

Capability Query Ioctl

+The VIDIOCGCAP ioctl call is used to obtain the capability +information for a video device. The struct video_capability object +passed to the ioctl is completed and returned. It contains the following +information +

+ + + + + + + + + +
name[32]Cannonical name for this interface
typeType of interface
channelsNumber of radio/tv channels if appropriate
audiosNumber of audio devices if appropriate
maxwidthMaximum capture width in pixels
maxheightMaximum capture height in pixels
minwidthMinimum capture width in pixels
minheightMinimum capture height in pixels
+

+The type field lists the capability flags for the device. These are +as follows +

+ + + + + + + + + + + + +
NameDescription
VID_TYPE_CAPTURECan capture to memory
VID_TYPE_TUNERHas a tuner of some form
VID_TYPE_TELETEXTHas teletext capability
VID_TYPE_OVERLAYCan overlay its image onto the frame buffer
VID_TYPE_CHROMAKEYOverlay is Chromakeyed
VID_TYPE_CLIPPINGOverlay clipping is supported
VID_TYPE_FRAMERAMOverlay overwrites frame buffer memory
VID_TYPE_SCALESThe hardware supports image scaling
VID_TYPE_MONOCHROMEImage capture is grey scale only
VID_TYPE_SUBCAPTURECapture can be of only part of the image
+

+The minimum and maximum sizes listed for a capture device do not imply all +that all height/width ratios or sizes within the range are possible. A +request to set a size will be honoured by the largest available capture +size whose capture is no large than the requested rectangle in either +direction. For example the quickcam has 3 fixed settings. +

+

Frame Buffer

+Capture cards that drop data directly onto the frame buffer must be told the +base address of the frame buffer, its size and organisation. This is a +privileged ioctl and one that eventually X itself should set. +

+The VIDIOCSFBUF ioctl sets the frame buffer parameters for a capture +card. If the card does not do direct writes to the frame buffer then this +ioctl will be unsupported. The VIDIOCGFBUF ioctl returns the +currently used parameters. The structure used in both cases is a +struct video_buffer. +

+ + + + + + +
void *baseBase physical address of the buffer
int heightHeight of the frame buffer
int widthWidth of the frame buffer
int depthDepth of the frame buffer
int bytesperlineNumber of bytes of memory between the start of two adjacent lines
+

+Note that these values reflect the physical layout of the frame buffer. +The visible area may be smaller. In fact under XFree86 this is commonly the +case. XFree86 DGA can provide the parameters required to set up this ioctl. +Setting the base address to NULL indicates there is no physical frame buffer +access. +

+

Capture Windows

+The capture area is described by a struct video_window. This defines +a capture area and the clipping information if relevant. The +VIDIOCGWIN ioctl recovers the current settings and the +VIDIOCSWIN sets new values. A successful call to VIDIOCSWIN +indicates that a suitable set of parameters have been chosen. They do not +indicate that exactly what was requested was granted. The program should +call VIDIOCGWIN to check if the nearest match was suitable. The +struct video_window contains the following fields. +

+ + + + + + + + +
xThe X co-ordinate specified in X windows format.
yThe Y co-ordinate specified in X windows format.
widthThe width of the image capture.
heightThe height of the image capture.
chromakeyA host order RGB32 value for the chroma key.
flagsAdditional capture flags.
clipsA list of clipping rectangles. (Set only) +
clipcountThe number of clipping rectangles. (Set only)
+

+Clipping rectangles are passed as an array. Each clip consists of the following +fields available to the user. +

+ + + + + +
xX co-ordinate of rectangle to skip
yY co-ordinate of rectangle to skip
widthWidth of rectangle to skip
heightHeight of rectangle to skip
+

+Merely setting the window does not enable capturing. Overlay capturing +is activatied by passing the VIDIOCCAPTURE ioctl a value of 1, and +disabled by passing it a value of 0. +

+Some capture devices can capture a subfield of the image they actually see. +This is indicated when VIDEO_TYPE_SUBCAPTURE is defined. +The video_capture describes the time and spacial subfields to capture. +The video_capture structure contains the following fields. +

+ + + + + + + +
xX co-ordinate of source rectangle to grab
yY co-ordinate of source rectangle to grab
widthWidth of source rectangle to grab
heightHeight of source rectangle to grab
decimationDecimation to apply
flagsFlag settings for grabbing
+The available flags are +

+ + + + +
NameDescription
VIDEO_CAPTURE_ODDCapture only odd frames
VIDEO_CAPTURE_EVENCapture only even frames
+

+

Video Sources

+Each video4linux video or audio device captures from one or more +source channels. Each channel can be queries with the +VDIOCGCHAN ioctl call. Before invoking this function the caller +must set the channel field to the channel that is being queried. On return +the struct video_channel is filled in with information about the +nature of the channel itself. +

+The VIDIOCSCHAN ioctl takes an integer argument and switches the +capture to this input. It is not defined whether paramters such as colour +settings or tuning are maintained across a channel switch. The caller should +maintain settings as desired for each channel. (This is reasonable as +different video inputs may have different properties). +

+The struct video_channel consists of the following +

+ + + + + + + +
channelThe channel number
nameThe input name - preferably reflecting the label +on the card input itself
tunersNumber of tuners for this input
flagsProperties the tuner has
typeInput type (if known)
normThe norm for this channel
+

+The flags defined are +

+ + + + +
VIDEO_VC_TUNERChannel has tuners.
VIDEO_VC_AUDIOChannel has audio.
VIDEO_VC_NORMChannel has norm setting.
+

+The types defined are +

+ + + +
VIDEO_TYPE_TVThe input is a TV input.
VIDEO_TYPE_CAMERAThe input is a camera.
+

+

Image Properties

+The image properties of the picture can be queried with the VIDIOCGPICT +ioctl which fills in a struct video_picture. The VIDIOCSPICT +ioctl allows values to be changed. All values except for the palette type +are scaled between 0-65535. +

+The struct video_picture consists of the following fields +

+ + + + + + + + +
brightnessPicture brightness
huePicture hue (colour only)
colourPicture colour (colour only)
contrastPicture contrast
whitenessThe whiteness (greyscale only)
depthThe capture depth (may need to match the frame buffer depth)
paletteReports the palette that should be used for this image
+

+The following palettes are defined +

+ + + + + + + + + + + + + + + +
VIDEO_PALETTE_GREYLinear intensity grey scale (255 is brightest).
VIDEO_PALETTE_HI240The BT848 8bit colour cube.
VIDEO_PALETTE_RGB565RGB565 packed into 16 bit words.
VIDEO_PALETTE_RGB555RGV555 packed into 16 bit words, top bit undefined.
VIDEO_PALETTE_RGB24RGB888 packed into 24bit words.
VIDEO_PALETTE_RGB32RGB888 packed into the low 3 bytes of 32bit words. The top 8bits are undefined.
VIDEO_PALETTE_YUV422Video style YUV422 - 8bits packed 4bits Y 2bits U 2bits V
VIDEO_PALETTE_YUYVDescribe me
VIDEO_PALETTE_UYVYDescribe me
VIDEO_PALETTE_YUV420YUV420 capture
VIDEO_PALETTE_YUV411YUV411 capture
VIDEO_PALETTE_RAWRAW capture (BT848)
VIDEO_PALETTE_YUV422PYUV 4:2:2 Planar
VIDEO_PALETTE_YUV411PYUV 4:1:1 Planar
+

+

Tuning

+Each video input channel can have one or more tuners associated with it. Many +devices will not have tuners. TV cards and radio cards will have one or more +tuners attached. +

+Tuners are described by a struct video_tuner which can be obtained by +the VIDIOCGTUNER ioctl. Fill in the tuner number in the structure +then pass the structure to the ioctl to have the data filled in. The +tuner can be switched using VIDIOCSTUNER which takes an integer argument +giving the tuner to use. A struct tuner has the following fields +

+ + + + + + + + +
tunerNumber of the tuner
nameCannonical name for this tuner (eg FM/AM/TV)
rangelowLowest tunable frequency
rangehighHighest tunable frequency
flagsFlags describing the tuner
modeThe video signal mode if relevant
signalSignal strength if known - between 0-65535
+

+The following flags exist +

+ + + + + + + +
VIDEO_TUNER_PALPAL tuning is supported
VIDEO_TUNER_NTSCNTSC tuning is supported
VIDEO_TUNER_SECAMSECAM tuning is supported
VIDEO_TUNER_LOWFrequency is in a lower range
VIDEO_TUNER_NORMThe norm for this tuner is settable
VIDEO_TUNER_STEREO_ONThe tuner is seeing stereo audio
+

+The following modes are defined +

+ + + + + +
VIDEO_MODE_PALThe tuner is in PAL mode
VIDEO_MODE_NTSCThe tuner is in NTSC mode
VIDEO_MODE_SECAMThe tuner is in SECAM mode
VIDEO_MODE_AUTOThe tuner auto switches, or mode does not apply
+

+Tuning frequencies are an unsigned 32bit value in 1/16th MHz or if the +VIDEO_TUNER_LOW flag is set they are in 1/16th KHz. The current +frequency is obtained as an unsigned long via the VIDIOCGFREQ ioctl and +set by the VIDIOCSFREQ ioctl. +

+

Audio

+TV and Radio devices have one or more audio inputs that may be selected. +The audio properties are queried by passing a struct video_audio to VIDIOCGAUDIO ioctl. The +VIDIOCSAUDIO ioctl sets audio properties. +

+The structure contains the following fields +

+ + + + + + + + + + +
audioThe channel number
volumeThe voume level
bassThe bass level
trebleThe treble level
flagsFlags describing the audio channel
nameCanonical name for the audio input
modeThe mode the audio input is in
balanceThe left/right balance
stepActual step used by the hardware
+

+The following flags are defined +

+ + + + + + + +
VIDEO_AUDIO_MUTEThe audio is muted
VIDEO_AUDIO_MUTABLEAudio muting is supported
VIDEO_AUDIO_VOLUMEThe volume is controllable
VIDEO_AUDIO_BASSThe bass is controllable
VIDEO_AUDIO_TREBLEThe treble is controllable
VIDEO_AUDIO_BALANCEThe balance is controllable
+

+The following decoding modes are defined +

+ + + + + +
VIDEO_SOUND_MONOMono signal
VIDEO_SOUND_STEREOStereo signal (NICAM for TV)
VIDEO_SOUND_LANG1European TV alternate language 1
VIDEO_SOUND_LANG2European TV alternate language 2
+

+

Reading Images

+Each call to the read syscall returns the next available image from +the device. It is up to the caller to set the format and then to pass a +suitable size buffer and length to the function. Not all devices will support +read operations. +

+A second way to handle image capture is via the mmap interface if supported. +To use the mmap interface a user first sets the desired image size and depth +properties. Next the VIDIOCGMBUF ioctl is issued. This reports the size +of buffer to mmap and the offset within the buffer for each frame. The +number of frames supported is device dependant and may only be one. +

+The video_mbuf structure contains the following fields +

+ + + + +
sizeThe number of bytes to map
framesThe number of frames
offsetsThe offset of each frame
+

+Once the mmap has been made the VIDIOCMCAPTURE ioctl sets the image size +you wish to use (which should match or be below the initial query size). +Having done so it will begin capturing to the memory mapped buffer. Whenever +a buffer is "used" by the program it should called VIDIOCSYNC to free this +frame up and continue. to add:VIDIOCSYNC takes the frame number +you are freeing as its argument. When the buffer is unmapped or all the +buffers are full capture ceases. While capturing to memory the driver will +make a "best effort" attempt to capture to screen as well if requested. This +normally means all frames that "miss" memory mapped capture will go to the +display. +

+A final ioctl exists to allow a device to obtain related devices if a +driver has multiple components (for example video0 may not be associated +with vbi0 which would cause an intercast display program to make a bad +mistake). The VIDIOCGUNIT ioctl reports the unit numbers of the associated +devices if any exist. The video_unit structure has the following fields. +

+ + + + + + +
videoVideo capture device
vbiVBI capture device
radioRadio device
audioAudio mixer
teletextTeletext device
+

+ + + diff --git a/Documentation/video4linux/bttv/CARDS b/Documentation/video4linux/bttv/CARDS new file mode 100644 index 000000000..0cfd4d72e --- /dev/null +++ b/Documentation/video4linux/bttv/CARDS @@ -0,0 +1,104 @@ +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) via VBI samples 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 ... + +Tuner and sound decoder support for Bt878/879 is not fully working yet. + + +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, I2C support for it is still experimental +- 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) + + +AverMedia +--------- + +... + + + + + + + + + + diff --git a/Documentation/video4linux/bttv/CONTRIBUTORS b/Documentation/video4linux/bttv/CONTRIBUTORS new file mode 100644 index 000000000..cf7d2300a --- /dev/null +++ b/Documentation/video4linux/bttv/CONTRIBUTORS @@ -0,0 +1,20 @@ +Contributors to bttv: + +Michael Chu + AverMedia fix and more flexible card recognition + +Alan Cox + Video4Linux interface and 2.1.x kernel adaptation + +Chris Kleitsch + Hardware I2C + +Gerd Knorr + Radio card (ITT sound processor) + ++ many more (please mail me if you are missing in this list and would + like to be mentioned) + + + + diff --git a/Documentation/video4linux/bttv/ICs b/Documentation/video4linux/bttv/ICs new file mode 100644 index 000000000..6b7491336 --- /dev/null +++ b/Documentation/video4linux/bttv/ICs @@ -0,0 +1,37 @@ +all boards: + +Brooktree Bt848/848A/849/878/879: video capture chip + + + +Miro PCTV: + +Philips or Temic Tuner + + + +Hauppauge Win/TV pci (version 405): + +Microchip 24LC02B or +Philips 8582E2Y: 256 Byte EEPROM with configuration information + I2C 0xa0-0xa1, (24LC02B also responds to 0xa2-0xaf) +Philips SAA5246AGP/E: Videotext decoder chip, I2C 0x22-0x23 +TDA9800: sound decoder +Winbond W24257AS-35: 32Kx8 CMOS static RAM (Videotext buffer mem) +14052B: analog switch for selection of sound source + +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 + + + +STB TV pci: + +??? +if you want better support for STB cards send me info! +Look at the board! What chips are on it? diff --git a/Documentation/video4linux/bttv/INSTALL b/Documentation/video4linux/bttv/INSTALL new file mode 100644 index 000000000..52cac1e6c --- /dev/null +++ b/Documentation/video4linux/bttv/INSTALL @@ -0,0 +1,73 @@ +- Make sure you have a recent 2.0.x kernel (I recommend AT LEAST 2.0.33!) + or a recent 2.1.x kernel. + Older kernels might lead to problems. + +- Do NOT compile videodev into your kernel! + Use the module supplied with bttv. + +- Edit "driver/Makefile": + + - If you do NOT have a Miro card: + Adjust TUNER to a number between 0 and 7. + + This number has the following meaning: + + 0: Temic PAL tuner + 1: Philips PAL_I tuner + 2: Philips NTSC tuner + 3: Philips SECAM tuner + 4: no tuner + 5: Philips PAL tuner + 6: Temic NTSC tuner + 7: Temic PAL tuner + + The number corresponds to the number (-1) given at the GPIO port of the + Bt848 on Miro cards. + + + - Adjust CARD to one of the numbers below: + + 0: Auto-Detect + 1: Miro + 2: Hauppauge + 3: STB + 4: Intel + 5: Diamond + 6: AVerMedia + + + - You may have to adjust BTTV_MAJOR to a different number depending on your + kernel version. The official number 81 does not work on some setups. + But instead of changing it, better update to a newer kernel. + + - If you have a Bt848a or Bt849 on your board you might have to + uncomment: -DUSE_PLL + +- do a "make" in the main directory. + +If you have Hauppauge card read "README.HAUPPAUGE" before proceeding. + +- type "make ins" + + This creates the bttv devices in /dev and installs the bttv module + + Look in the kernel log file (/var/adm/syslog or /var/log/kernel or something + else depending on your /etc/syslogd.conf or just call "dmesg") + and see what bttv reported (lines starting with "bttv:") + If the installation failed and you send e-mail to me always include those + lines! Dumps of the insmod output alone do not help at all. + +- Start X11 in hi or true color mode + 8 bit color is also supported but really ugly! + (If you have an S3 card you might have to start X11 before installing + the module!) + + If you have Motif or LessTif, "xtvscreen" in the "XTV" directory should + have been compiled with the "make" above. + Otherwise use the statically linked version which should be available + on the web site you got bttv from. + Read the documentation in "XTV" and start xtvscreen. + +- make applications by typing "make" in "apps" + + diff --git a/Documentation/video4linux/bttv/PROBLEMS b/Documentation/video4linux/bttv/PROBLEMS new file mode 100644 index 000000000..6148f859c --- /dev/null +++ b/Documentation/video4linux/bttv/PROBLEMS @@ -0,0 +1,62 @@ +- Start capturing by pressing "c" or by selecting it via a menu! + +- Start capturing by pressing "c" or by selecting it via a menu!!! + +- The memory of some S3 cards is not recognized right: + + First of all, if you are not using Xfree-3.2 or newer, upgrade AT LEAST to + XFree-3.2A! This solved the problem for most people. + + Start up X11 like this: "XF86_S3 -probeonly" and write down where the + linear frame buffer is. + If it is different to the address found by bttv install bttv like this: + "insmod bttv vidmem=0xfb0" + if the linear frame buffer is at 0xfb000000 (i.e. omit the last 5 zeros!) + + Some S3 cards even take up 64MB of memory but only report 32MB to the BIOS. + If this 64MB area overlaps the IO memory of the Bt848 you also have to + remap this. E.g.: insmod bttv vidmem=0xfb0 remap=0xfa0 + + If the videomemory is found at the right place and there are no address + conflicts but still no picture (or the computer even crashes.), + try disabling features of your PCI chipset in the BIOS Setup. + + Frank Kapahnke also reported that problems + with his S3 868 went away when he upgraded to XFree 3.2. + + +- I still only get a black picture with my S3 card! + + Even with XFree-3.2A some people have problems with their S3 cards + (mostly with Trio 64 but also with some others) + Get the free demo version of Accelerated X from www.xinside.com and try + bttv with it. bttv seems to work with most S3 cards with Accelerated X. + + Since I do not know much (better make that almost nothing) about VGA card + programming I do not know the reason for this. + Looks like XFree does something different when setting up the video memory? + Maybe somebody can enlighten me? + Would be nice if somebody could get this to work with XFree since + Accelerated X costs more than some of the grabber cards ... + + Better linear frame buffer support for S3 cards will probably be in + XFree 4.0. + +- Grabbing is not switched off when changing consoles with XFree. + That's because XFree and some AcceleratedX versions do not send unmap + events. + +- Some popup windows (e.g. of the window manager) are not refreshed. + + Disable backing store by starting X with the option "-bs" + +- When using 32bpp in XFree or 24+8bpp mode in AccelX 3.1 the system + can sometimes lock up if you use more than 1 bt848 card at the same time. + You will always get pixel errors when e.g. using more than 1 card in full + screen mode. Maybe we need something faster than the PCI bus ... + + +- Some S3 cards and the Matrox Mystique will produce pixel erros with + full resolution in 32bit mode. + +- Some video cards have problems with Accelerated X 4.1 \ No newline at end of file diff --git a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README new file mode 100644 index 000000000..72f4f4b73 --- /dev/null +++ b/Documentation/video4linux/bttv/README @@ -0,0 +1,41 @@ +bttv - BT848 frame grabber driver + +Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) + according to GNU GPL in file COPYING. + + +Bttv is a device driver for frame grabber cards using the Bt848 family +of video decoder chips. +Among those are the Bt848, Bt848A, Bt849, Bt878 and Bt879. +The only major differences between the cards by different manufacturers +are the types of tuners and extra components on the boards. +E.g., some cards by Hauppauge have an additional Videotext decoder +and/or sound decoder chip. +Also type (Composite or S-VHS) and number of inputs differ. +Other Brooktree chips (e.g. the Bt829) or chips by other manufacturers +(Philips, Zoran, ...) are NOT supported by bttv. + +You can use several cards at the same time. +Interrupts can be shared with other Bt848 cards or any other drivers +which allow it. +The (arbitrary) maximum number of cards is 4 but can be adjusted by +changing BTTV_MAX at the beginning of bttv.c if you need more. +(But which board has more than 4 PCI slots plus 1 for the VGA card?) + +Bttv is a standard component of all newer 2.1.x kernels. +This distribution additionally supports 2.0.x kernels and all other +changes and improvements which did not make it into the kernel version +yet. +It also includes versions of videodev.c, i2.c, tuner.c and others +which are the same as in the latest 2.1.x kernel but with 2.0.x support. +A kernel version >2.0.30 is recommended. + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +Although bttv is now used and tested by many people it still might crash your +computer! Take all precautions to avoid data loss until you are certain +bttv runs on your setup without problems. +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The latest version of bttv can be found at: +http://www.thp.uni-koeln.de/~rjkm/linux/bttv.html diff --git a/Documentation/video4linux/bttv/README.FIRST b/Documentation/video4linux/bttv/README.FIRST new file mode 100644 index 000000000..ea68726a6 --- /dev/null +++ b/Documentation/video4linux/bttv/README.FIRST @@ -0,0 +1,4 @@ +o Please direct queries about the in kernel version of this driver to + Alan Cox first not to Ralph, or better yet join the video4linux mailing + list (mail majordomo@phunk.org with "subscribe video4linux") + diff --git a/Documentation/video4linux/bttv/README.Hauppauge b/Documentation/video4linux/bttv/README.Hauppauge new file mode 100644 index 000000000..0076ed8d8 --- /dev/null +++ b/Documentation/video4linux/bttv/README.Hauppauge @@ -0,0 +1,29 @@ +The current I2C-Code could by accident overwrite the configuration EEPROM on +Hauppauge boards!!! +(E.g. the videotext driver and the bt848 driver do not know about each other. +This might cause unwanted states on the I2C bus which overwrite the EEPROM) + +Back up this EEPROM before doing anything else by typing: +(do this AFTER installing bttv.o with "make ins" but BEFORE starting the +X application) + +make readee +readee > tvee.h + +If you encounter any problems in Windows95 (like "PNP component not found" ...) +go back into linux, load bttv and type: + +make writeee +writeee + +to write the backed up contents. +If you backed up your EEPROM as described above, this will restore it to its +original state. +A detailed description of the meaning of the EEPROM bytes by +Hauppauge would of course be even more helpful! + +If you have board type 405 and you did not make a backup, my tvee.h file in +mytvee.h might be of help. + +Forget about all of the above if you do not have a Hauppauge board. + diff --git a/Documentation/video4linux/bttv/README.MIRO b/Documentation/video4linux/bttv/README.MIRO new file mode 100644 index 000000000..e74fc4ab6 --- /dev/null +++ b/Documentation/video4linux/bttv/README.MIRO @@ -0,0 +1,3 @@ +The right tuner type should automatically be detected. +Look in your kernel log files to see which one bttv thinks it is. + diff --git a/Documentation/video4linux/bttv/README.PCI b/Documentation/video4linux/bttv/README.PCI new file mode 100644 index 000000000..1ae8276f1 --- /dev/null +++ b/Documentation/video4linux/bttv/README.PCI @@ -0,0 +1,36 @@ +Because some people were asking about the bandwidth the Bt848 might use up +on the PCI bus I did a little benchmark. + +"bonnie -s 200" with a Fireball TM 3.8 Gb using Busmaster DMA on an ASUS P6NP5 + +without capturing: + + -------Sequential Output-------- ---Sequential Input-- --Random-- + -Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks--- +Machine MB K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU /sec %CPU + 200 5353 76.6 5898 16.9 2363 12.1 5889 51.3 6416 10.2 37.8 0.9 + + +while capturing full screen PAL (786x576) with 24bpp: + + -------Sequential Output-------- ---Sequential Input-- --Random-- + -Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks--- +Machine MB K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU /sec %CPU + 200 5619 69.3 5939 16.9 2334 12.0 5859 50.9 6441 10.5 37.9 0.9 + +The differences are small and probably within the normal error margin of +bonnie. +So, one bt848 card does not have much(any?) impact on the normal operation +of a Linux system. +If you have several cards running this will look very differently! +The same is probably true if your Linux box is used as a file server +with 15 (or 30) SCSI drives. + +I tested having 2 Bt848 cards grabbing in 32 bit mode (That's almost 100MB/s!) +while running bonnie. +The xtvscreen windows showed severe pixel errors. +After a while the ide driver failed to use DMA and switched DMA off. +It continued running but the results where bad. + + + diff --git a/Documentation/video4linux/bttv/README.RADIO b/Documentation/video4linux/bttv/README.RADIO new file mode 100644 index 000000000..53d04f59b --- /dev/null +++ b/Documentation/video4linux/bttv/README.RADIO @@ -0,0 +1,15 @@ +Support is in now: + - Turn on the "big red switch" of the sound processor. + - two ioctls to access (some) registers of the sound processor. + - a function in the TV-Widget which monitors the signal quality + and does the mono/stereo switching. + +So you should have TV with (stereo) sound now. Radio does _not_ work. +It probably does not work with sat receivers. I can't test this and +therefore hav'nt added support for it yet. If someone needs this and +can help testing the sat stuff, drop me a note. + + Gerd + +-- +Gerd Knorr diff --git a/Documentation/video4linux/bttv/THANKS b/Documentation/video4linux/bttv/THANKS new file mode 100644 index 000000000..0da6d9f8e --- /dev/null +++ b/Documentation/video4linux/bttv/THANKS @@ -0,0 +1,24 @@ +Many thanks to: + +- Markus Schroeder for information on the Bt848 + and tuner programming and his control program xtvc. + +- Martin Buck for his great Videotext + package. + +- Gerd Knorr for the MSP3400 support and the modular + I2C, tuner, ... support. + + +- MATRIX Vision for giving us 2 cards for free, which made support of + single crystal operation possible. + +- MIRO for providing a free PCTV card and detailed information about the + components on their cards. (E.g. how the tuner type is detected) + Without their card I could not have debugged the NTSC mode. + +- Hauppauge for telling how the sound input is selected and what compenents + they do and will use on their radio cards. + Also many thanks for faxing me the FM1216 data sheet. + + diff --git a/Documentation/radiotrack.txt b/Documentation/video4linux/radiotrack.txt similarity index 100% rename from Documentation/radiotrack.txt rename to Documentation/video4linux/radiotrack.txt diff --git a/MAINTAINERS b/MAINTAINERS index 9fbebebbd..dd0e825e1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -47,6 +47,10 @@ trivial patch so apply some common sense. Maintainers List (try to look for most precise areas first) +Note: For the hard of thinking, this list is meant to remain in Alphabetical +order. If you could add yourselves to it in Alphabetical order that would +so much easier [Ed] + P: Person M: Mail patches to L: Mailing list that is relevant to this area @@ -66,7 +70,7 @@ S: Status, one of the following: 3C501 NETWORK DRIVER P: Alan Cox -M: net-patches@lxorguk.ukuu.org.uk +M: alan@the.3c501.cabal.tm L: linux-net@vger.rutgers.edu S: Maintained @@ -124,6 +128,19 @@ M: layes@loran.com L: linux-net@vger.rutgers.edu S: Maintained +ARM MFM AND FLOPPY DRIVERS +P: Dave Gilbert +M: linux@treblig.org +S: Maintained + +ARM PORT +P: Russell King +M: linux@arm.uk.linux.org +L: linux-arm@vger.rutgers.edu +L: arm-linux@tardis.ed.ac.uk +W: http://www.arm.uk.linux.org/~rmk/armlinux.html +S: Maintained + AX.25 NETWORK LAYER P: Jon Naylor M: jsn@cs.nott.ac.uk @@ -365,7 +382,7 @@ P: Alan Cox M: Alan.Cox@linux.org W: http://www.mac.linux-m68k.org/home.html L: linux-mac68k@wave.lm.com -S: Maintained +S: As time permits [Michael confess, you are the mac68k maintainer 8)] MENUCONFIG: P: Michael Elizabeth Chastain @@ -548,8 +565,8 @@ S: Maintained SOUND P: Alan Cox -M: Alan.Cox@linux.org -S: Maintained +M: alan@redhat.com +S: Supported SPARC: P: Eddie C. Dost @@ -641,6 +658,7 @@ S: Maintained VIDEO FOR LINUX P: Alan Cox M: Alan.Cox@linux.org +W: http://roadrunner.swansea.linux.org.uk/v4l.shtml S: Maintained WAN ROUTER AND SANGOMA WANPIPE DRIVERS (X.25, FRAME RELAY, PPP) @@ -669,18 +687,6 @@ W: http://qsl.net/dl1bke/ L: linux-hams@vger.rutgers.edu S: Maintained -ARM PORT -P: Russell King -M: linux@arm.uk.linux.org -L: linux-arm@vger.rutgers.edu -L: arm-linux@tardis.ed.ac.uk -W: http://www.arm.uk.linux.org/~rmk/armlinux.html -S: Maintained - -ARM MFM AND FLOPPY DRIVERS -P: Dave Gilbert -M: linux@treblig.org -S: Maintained REST: P: Linus Torvalds diff --git a/Makefile b/Makefile index 1b52ea5b6..4fa20439d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 117 +SUBLEVEL = 118 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -125,7 +125,7 @@ ifeq ($(CONFIG_SCSI),y) DRIVERS := $(DRIVERS) drivers/scsi/scsi.a endif -ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR),) +ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),) DRIVERS := $(DRIVERS) drivers/cdrom/cdrom.a endif diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c index 1752ff2c0..0aa1f4553 100644 --- a/arch/i386/kernel/bios32.c +++ b/arch/i386/kernel/bios32.c @@ -1,7 +1,7 @@ /* * bios32.c - Low-Level PCI Access * - * $Id: bios32.c,v 1.44 1998/08/04 14:54:56 mj Exp $ + * $Id: bios32.c,v 1.45 1998/08/15 10:41:04 mj Exp $ * * Copyright 1993, 1994 Drew Eckhardt * Visionary Computing @@ -945,7 +945,8 @@ __initfunc(void pcibios_fixup_ghosts(struct pci_bus *b)) __initfunc(void pcibios_fixup_peer_bridges(void)) { struct pci_bus *b = &pci_root; - int i; + int i, cnt=-1; + struct pci_dev *d; #ifdef CONFIG_PCI_DIRECT /* @@ -956,23 +957,34 @@ __initfunc(void pcibios_fixup_peer_bridges(void)) if (access_pci == &pci_direct_conf2) return; #endif + for(d=b->devices; d; d=d->sibling) + if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST) + cnt++; do { int n = b->subordinate+1; + int found = 0; u16 l; for(i=0; i<256; i += 8) if (!pcibios_read_config_word(n, i, PCI_VENDOR_ID, &l) && l != 0x0000 && l != 0xffff) { DBG("Found device at %02x:%02x\n", n, i); - printk("PCI: Discovered primary peer bus %02x\n", n); - b = kmalloc(sizeof(*b), GFP_KERNEL); - memset(b, 0, sizeof(*b)); - b->next = pci_root.next; - pci_root.next = b; - b->number = b->secondary = n; - b->subordinate = 0xff; - b->subordinate = pci_scan_bus(b); - break; + found++; + if (!pcibios_read_config_word(n, i, PCI_CLASS_DEVICE, &l) && + l == PCI_CLASS_BRIDGE_HOST) + cnt++; } + if (found && cnt > 0) { + cnt--; + printk("PCI: Discovered primary peer bus %02x\n", n); + b = kmalloc(sizeof(*b), GFP_KERNEL); + memset(b, 0, sizeof(*b)); + b->next = pci_root.next; + pci_root.next = b; + b->number = b->secondary = n; + b->subordinate = 0xff; + b->subordinate = pci_scan_bus(b); + break; + } } while (i < 256); } @@ -1032,21 +1044,25 @@ __initfunc(void pcibios_fixup_devices(void)) #ifdef __SMP__ /* * Recalculate IRQ numbers if we use the I/O APIC + * + * NOTE! If the "original" interrupt is marked as an old-fashioned + * irq, we have to keep it old-fashioned even if it's a PCI device + * and we could have found it in the MP-table transform. */ - { - int irq; - unsigned char pin; - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (pin) { - pin--; /* interrupt pins are numbered starting from 1 */ - irq = IO_APIC_get_PCI_irq_vector (dev->bus->number, PCI_SLOT(dev->devfn), pin); - if (irq >= 0) { - printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n", - dev->bus->number, PCI_SLOT(dev->devfn), pin, irq); - dev->irq = irq; - } - } + if (IO_APIC_IRQ(dev->irq)) { + int irq; + unsigned char pin; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin) { + pin--; /* interrupt pins are numbered starting from 1 */ + irq = IO_APIC_get_PCI_irq_vector (dev->bus->number, PCI_SLOT(dev->devfn), pin); + if (irq >= 0) { + printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n", + dev->bus->number, PCI_SLOT(dev->devfn), pin, irq); + dev->irq = irq; + } + } } #endif /* diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c index ae67822bc..de6efd1e2 100644 --- a/arch/i386/kernel/mca.c +++ b/arch/i386/kernel/mca.c @@ -68,7 +68,7 @@ static int mca_default_procfn( char* buf, int slot ); static ssize_t proc_mca_read( struct file*, char*, size_t, loff_t *); static struct file_operations proc_mca_operations = { NULL, proc_mca_read, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static struct inode_operations proc_mca_inode_operations = { &proc_mca_operations, diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c index 02d5b61a0..f56bcdfa1 100644 --- a/arch/i386/kernel/mtrr.c +++ b/arch/i386/kernel/mtrr.c @@ -1086,6 +1086,7 @@ static struct file_operations mtrr_fops = mtrr_ioctl, /* IOctl */ NULL, /* MMAP */ mtrr_open, /* Open */ + NULL, /* Flush */ mtrr_close, /* Release */ NULL, /* Fsync */ NULL, /* Fasync */ diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 3bcd0f9bc..731797f6b 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -727,6 +727,13 @@ void __switch_to(struct task_struct *prev, struct task_struct *next) gdt_table[next->tss.tr >> 3].b &= 0xfffffdff; asm volatile("ltr %0": :"g" (*(unsigned short *)&next->tss.tr)); + /* + * Save away %fs and %gs. No need to save %es and %ds, as + * those are always kernel segments while inside the kernel. + */ + asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->tss.fs)); + asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->tss.gs)); + /* Re-load LDT if necessary */ if (next->mm->segments != prev->mm->segments) asm volatile("lldt %0": :"g" (*(unsigned short *)&next->tss.ldt)); @@ -736,13 +743,8 @@ void __switch_to(struct task_struct *prev, struct task_struct *next) asm volatile("movl %0,%%cr3": :"r" (next->tss.cr3)); /* - * Save away %fs and %gs. No need to save %es and %ds, as - * those are always kernel segments while inside the kernel. - * Restore the new values. + * Restore %fs and %gs. */ - asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->tss.fs)); - asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->tss.gs)); - loadsegment(fs,next->tss.fs); loadsegment(gs,next->tss.gs); @@ -761,28 +763,19 @@ void __switch_to(struct task_struct *prev, struct task_struct *next) asmlinkage int sys_fork(struct pt_regs regs) { - int ret; - - lock_kernel(); - ret = do_fork(SIGCHLD, regs.esp, ®s); - unlock_kernel(); - return ret; + return do_fork(SIGCHLD, regs.esp, ®s); } asmlinkage int sys_clone(struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; - int ret; - lock_kernel(); clone_flags = regs.ebx; newsp = regs.ecx; if (!newsp) newsp = regs.esp; - ret = do_fork(clone_flags, newsp, ®s); - unlock_kernel(); - return ret; + return do_fork(clone_flags, newsp, ®s); } /* diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index 05e53287a..231356d90 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -184,26 +184,17 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *peax) #define COPY_SEG(seg) \ { unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ - if ((tmp & 0xfffc) /* not a NULL selectors */ \ - && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ - && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ - goto badframe; \ + err |= __get_user(tmp, &sc->seg); \ regs->x##seg = tmp; } #define COPY_SEG_STRICT(seg) \ { unsigned short tmp; \ err |= __get_user(tmp, &sc->seg); \ - if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \ - regs->x##seg = tmp; } + regs->x##seg = tmp|3; } #define GET_SEG(seg) \ { unsigned short tmp; \ err |= __get_user(tmp, &sc->seg); \ - if ((tmp & 0xfffc) /* not a NULL selectors */ \ - && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ - && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ - goto badframe; \ loadsegment(seg,tmp); } GET_SEG(gs); @@ -459,15 +450,12 @@ static void setup_frame(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->esp = (unsigned long) frame; regs->eip = (unsigned long) ka->sa.sa_handler; - { - unsigned long seg = __USER_DS; - __asm__("movl %w0,%%fs ; movl %w0,%%gs": "=r"(seg) : "0"(seg)); - set_fs(USER_DS); - regs->xds = seg; - regs->xes = seg; - regs->xss = seg; - regs->xcs = __USER_CS; - } + + set_fs(USER_DS); + regs->xds = __USER_DS; + regs->xes = __USER_DS; + regs->xss = __USER_DS; + regs->xcs = __USER_CS; regs->eflags &= ~TF_MASK; #if DEBUG_SIG @@ -533,15 +521,12 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->esp = (unsigned long) frame; regs->eip = (unsigned long) ka->sa.sa_handler; - { - unsigned long seg = __USER_DS; - __asm__("movl %w0,%%fs ; movl %w0,%%gs": "=r"(seg) : "0"(seg)); - set_fs(USER_DS); - regs->xds = seg; - regs->xes = seg; - regs->xss = seg; - regs->xcs = __USER_CS; - } + + set_fs(USER_DS); + regs->xds = __USER_DS; + regs->xes = __USER_DS; + regs->xss = __USER_DS; + regs->xcs = __USER_CS; regs->eflags &= ~TF_MASK; #if DEBUG_SIG diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c index 6b313d99c..d5b052c20 100644 --- a/arch/i386/lib/usercopy.c +++ b/arch/i386/lib/usercopy.c @@ -7,7 +7,7 @@ */ #include -inline unsigned long +unsigned long __generic_copy_to_user(void *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) @@ -15,11 +15,11 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n) return n; } -inline unsigned long +unsigned long __generic_copy_from_user(void *to, const void *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) - __copy_user(to,from,n); + __copy_user_zeroing(to,from,n); return n; } diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index b4cba8730..b5febaf59 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -220,7 +220,7 @@ static unsigned long __init fixmap_init(unsigned long start_mem) for (idx=1; idx <= __end_of_fixed_addresses; idx += PTRS_PER_PTE) { - address = fix_to_virt(__end_of_fixed_addresses-idx); + address = __fix_to_virt(__end_of_fixed_addresses-idx); pg_dir = swapper_pg_dir + (address >> PGDIR_SHIFT); memset((void *)start_mem, 0, PAGE_SIZE); pgd_val(*pg_dir) = _PAGE_TABLE | __pa(start_mem); @@ -246,8 +246,12 @@ static void set_pte_phys (unsigned long vaddr, unsigned long phys) void set_fixmap (enum fixed_addresses idx, unsigned long phys) { - unsigned long address = fix_to_virt(idx); + unsigned long address = __fix_to_virt(idx); + if (idx >= __end_of_fixed_addresses) { + printk("Invalid set_fixmap\n"); + return; + } set_pte_phys (address,phys); } diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index 02821ebaf..d11011c5e 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -218,31 +218,31 @@ static unsigned stat_swap_force = 0; #ifdef CONFIG_STRAM_SWAP static int swap_init( unsigned long start_mem, unsigned long swap_data ); static inline int unswap_pte( struct vm_area_struct * vma, unsigned long - address, pte_t *dir, unsigned long entry, - unsigned long page, int isswap ); + address, pte_t *dir, unsigned long entry, + unsigned long page, int isswap ); static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir, - unsigned long address, unsigned long size, - unsigned long offset, unsigned long entry, - unsigned long page, int isswap ); + unsigned long address, unsigned long size, + unsigned long offset, unsigned long entry, + unsigned long page, int isswap ); static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir, - unsigned long address, unsigned long size, - unsigned long entry, unsigned long page, int - isswap ); + unsigned long address, unsigned long size, + unsigned long entry, unsigned long page, int + isswap ); static int unswap_vma( struct vm_area_struct * vma, pgd_t *pgdir, unsigned - long entry, unsigned long page, int isswap ); + long entry, unsigned long page, int isswap ); static int unswap_process( struct mm_struct * mm, unsigned long entry, - unsigned long page, int isswap ); + unsigned long page, int isswap ); static int unswap_by_move( unsigned char *map, unsigned long max, unsigned - long start, unsigned long n_pages ); + long start, unsigned long n_pages ); static int unswap_by_read( unsigned char *map, unsigned long max, unsigned - long start, unsigned long n_pages ); + long start, unsigned long n_pages ); static void *get_stram_region( unsigned long n_pages ); static void free_stram_region( unsigned long offset, unsigned long n_pages - ); + ); static int in_some_region( unsigned long addr ); static unsigned long find_free_region( unsigned long n_pages, unsigned long - *total_free, unsigned long - *region_free ); + *total_free, unsigned long + *region_free ); static void do_stram_request( void ); static int stram_open( struct inode *inode, struct file *filp ); static int stram_release( struct inode *inode, struct file *filp ); @@ -1249,16 +1249,17 @@ static int stram_release( struct inode *inode, struct file *filp ) static struct file_operations stram_fops = { - NULL, /* lseek - default */ - block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ - NULL, /* readdir - bad */ - NULL, /* select */ - NULL, /* ioctl */ - NULL, /* mmap */ - stram_open, /* open */ - stram_release, /* release */ - block_fsync /* fsync */ + NULL, /* lseek - default */ + block_read, /* read - general block-dev read */ + block_write, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* select */ + NULL, /* ioctl */ + NULL, /* mmap */ + stram_open, /* open */ + NULL, /* flush */ + stram_release, /* release */ + block_fsync /* fsync */ }; __initfunc(int stram_device_init(void)) @@ -1269,12 +1270,12 @@ __initfunc(int stram_device_init(void)) return( -ENXIO ); if (!max_swap_size) - /* swapping not enabled */ + /* swapping not enabled */ return( -ENXIO ); if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) { - printk( KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR ); - return( -ENXIO ); + printk( KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR ); + return( -ENXIO ); } blk_dev[STRAM_MAJOR].request_fn = do_stram_request; diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c index ca9f677f8..cf05ab9aa 100644 --- a/arch/m68k/bvme6000/rtc.c +++ b/arch/m68k/bvme6000/rtc.c @@ -153,6 +153,7 @@ static struct file_operations rtc_fops = { rtc_ioctl, NULL, /* No mmap */ rtc_open, + NULL, /* flush */ rtc_release }; diff --git a/arch/m68k/mac/adb-bus.c b/arch/m68k/mac/adb-bus.c index 0f41bc6aa..642164314 100644 --- a/arch/m68k/mac/adb-bus.c +++ b/arch/m68k/mac/adb-bus.c @@ -2504,6 +2504,7 @@ static struct file_operations adb_fops = { NULL, /* no ioctl yet */ NULL, /* no mmap */ adb_open, + NULL, /* flush */ adb_release }; @@ -2688,6 +2689,7 @@ static struct file_operations adb_fops = { NULL, /* no ioctl */ NULL, /* no mmap */ adb_open, + NULL, /* flush */ adb_release }; diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c index 6b7c0c011..b9485e54d 100644 --- a/arch/m68k/mvme16x/rtc.c +++ b/arch/m68k/mvme16x/rtc.c @@ -144,6 +144,7 @@ static struct file_operations rtc_fops = { rtc_ioctl, NULL, /* No mmap */ rtc_open, + NULL, /* flush */ rtc_release }; diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index 074e15a9d..c1445d393 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -49,6 +49,7 @@ static struct file_operations ppc_htab_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c index 523073a6d..dce7927d8 100644 --- a/arch/sparc64/solaris/socksys.c +++ b/arch/sparc64/solaris/socksys.c @@ -57,6 +57,7 @@ static struct file_operations socksys_file_ops = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* open */ + NULL, /* flush */ NULL, /* release */ }; @@ -170,6 +171,7 @@ static struct file_operations socksys_fops = { NULL, /* ioctl */ NULL, /* mmap */ socksys_open, /* open */ + NULL, /* flush */ socksys_release,/* release */ }; diff --git a/drivers/Makefile b/drivers/Makefile index d661fcd4b..f6b73e35f 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -63,7 +63,7 @@ else endif endif -ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR),) +ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),) SUB_DIRS += cdrom MOD_SUB_DIRS += cdrom endif diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c index d9afbea9b..a92320305 100644 --- a/drivers/acorn/block/fd1772.c +++ b/drivers/acorn/block/fd1772.c @@ -1589,6 +1589,7 @@ static struct file_operations floppy_fops = fd_ioctl, /* ioctl */ NULL, /* mmap */ floppy_open, /* open */ + NULL, /* flush */ floppy_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c index 614d8403c..bec74c62b 100644 --- a/drivers/acorn/block/mfmhd.c +++ b/drivers/acorn/block/mfmhd.c @@ -1372,6 +1372,7 @@ static struct file_operations mfm_fops = mfm_ioctl, /* ioctl */ NULL, /* mmap */ mfm_open, /* open */ + NULL, /* flush */ mfm_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ diff --git a/drivers/ap1000/ap.c b/drivers/ap1000/ap.c index ae2071cf9..ce50c5edb 100644 --- a/drivers/ap1000/ap.c +++ b/drivers/ap1000/ap.c @@ -48,12 +48,10 @@ static int ap_fds[NUM_APDEVS]; static volatile int request_count = 0; -#ifdef MODULE static void ap_release(struct inode * inode, struct file * filp) { MOD_DEC_USE_COUNT; } -#endif static void ap_request(void) { @@ -247,20 +245,17 @@ void ap_open_reply(struct cap_request *creq) } static struct file_operations ap_fops = { - NULL, /* lseek - default */ - block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ - NULL, /* readdir - bad */ - NULL, /* poll */ - ap_ioctl, /* ioctl */ - NULL, /* mmap */ - ap_open, /* open */ -#ifndef MODULE - NULL, /* no special release code... */ -#else - ap_release, /* module needs to decrement use count */ -#endif - block_fsync, /* fsync */ + NULL, /* lseek - default */ + block_read, /* read - general block-dev read */ + block_write, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* poll */ + ap_ioctl, /* ioctl */ + NULL, /* mmap */ + ap_open, /* open */ + NULL, /* flush */ + ap_release, /* module needs to decrement use count */ + block_fsync, /* fsync */ }; diff --git a/drivers/ap1000/ddv.c b/drivers/ap1000/ddv.c index 2e7f492a5..4a21a5882 100644 --- a/drivers/ap1000/ddv.c +++ b/drivers/ap1000/ddv.c @@ -884,6 +884,7 @@ static struct file_operations ddv_fops = { ddv_ioctl, /* ioctl */ NULL, /* mmap */ ddv_open, /* open */ + NULL, /* flush */ ddv_release, block_fsync /* fsync */ }; diff --git a/drivers/ap1000/ringbuf.c b/drivers/ap1000/ringbuf.c index 905b8f069..d8f9b02c3 100644 --- a/drivers/ap1000/ringbuf.c +++ b/drivers/ap1000/ringbuf.c @@ -302,6 +302,7 @@ static struct file_operations proc_ringbuf_operations = { ringbuf_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/drivers/block/Makefile b/drivers/block/Makefile index f3543db2e..eff9baf43 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -269,10 +269,10 @@ endif ifeq ($(CONFIG_PARIDE),y) SUB_DIRS += paride -MOD_SUB_DIRS += paride +MOD_IN_SUB_DIRS += paride else ifeq ($(CONFIG_PARIDE),m) - MOD_SUB_DIRS += paride + MOD_IN_SUB_DIRS += paride endif endif diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c index 3594eb189..f49f186a8 100644 --- a/drivers/block/acsi.c +++ b/drivers/block/acsi.c @@ -1788,7 +1788,8 @@ static struct file_operations acsi_fops = { acsi_ioctl, /* ioctl */ NULL, /* mmap */ acsi_open, /* open */ - acsi_release, /* release */ + NULL, /* flush */ + acsi_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ acsi_media_change, /* media_change */ diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c index 4b301cb2a..66121340f 100644 --- a/drivers/block/acsi_slm.c +++ b/drivers/block/acsi_slm.c @@ -288,7 +288,8 @@ static struct file_operations slm_fops = { slm_ioctl, /* ioctl */ NULL, /* mmap */ slm_open, /* open */ - slm_release, /* release */ + NULL, /* flush */ + slm_release, /* release */ NULL /* fsync */ }; diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index afee4899e..a7631741e 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1747,6 +1747,7 @@ static struct file_operations floppy_fops = { fd_ioctl, /* ioctl */ NULL, /* mmap */ floppy_open, /* open */ + NULL, /* flush */ floppy_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 640ddfd3a..5c55700a7 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -2008,6 +2008,7 @@ static struct file_operations floppy_fops = { fd_ioctl, /* ioctl */ NULL, /* mmap */ floppy_open, /* open */ + NULL, /* flush */ floppy_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 9fb5c8e7e..b8ef97922 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3836,6 +3836,7 @@ static struct file_operations floppy_fops = { fd_ioctl, /* ioctl */ NULL, /* mmap */ floppy_open, /* open */ + NULL, /* flush */ floppy_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index e739090f1..0246d15bf 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -411,29 +411,23 @@ check_table: } else { /* * Examine the partition table for common translations. - * This is necessary for drives for situations where - * the translated geometry is unavailable from the BIOS. + * This is useful for drives in situations where the + * translated geometry is unavailable from the BIOS. */ - int xlate_done = 0; - for (i = 0; i < 4 && !xlate_done; i++) { + for (i = 0; i < 4; i++) { struct partition *q = &p[i]; if (NR_SECTS(q) && (q->sector & 63) == 1 && (q->end_sector & 63) == 63) { unsigned int heads = q->end_head + 1; - if (heads == 32 || heads == 64 || heads == 128 || heads == 255) { - + if (heads == 32 || heads == 64 || + heads == 128 || heads == 255 || + heads == 240) { (void) ide_xlate_1024(dev, heads, " [PTBL]"); - xlate_done = 1; + break; } } } - if (!xlate_done) { - /* - * Default translation is equivalent of "BIOS LBA": - */ - ide_xlate_1024(dev, -2, " [LBA]"); - } } } #endif /* CONFIG_BLK_DEV_IDE */ diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 01a4e18e4..07463389a 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -2869,6 +2869,7 @@ struct file_operations ide_fops[] = {{ ide_ioctl, /* ioctl */ NULL, /* mmap */ ide_open, /* open */ + NULL, /* flush */ ide_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 268c9187a..5a936899f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -670,6 +670,7 @@ static struct file_operations lo_fops = { lo_ioctl, /* ioctl */ NULL, /* mmap */ lo_open, /* open */ + NULL, /* flush */ lo_release /* release */ }; diff --git a/drivers/block/md.c b/drivers/block/md.c index d0eae5a29..b6cf3d34e 100644 --- a/drivers/block/md.c +++ b/drivers/block/md.c @@ -754,6 +754,7 @@ static struct file_operations md_fops= md_ioctl, NULL, md_open, + NULL, md_release, block_fsync }; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index ddec2b425..944647096 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -415,6 +415,7 @@ static struct file_operations nbd_fops = nbd_ioctl, /* ioctl */ NULL, /* mmap */ nbd_open, /* open */ + NULL, /* flush */ nbd_release /* release */ }; diff --git a/drivers/block/paride/Makefile b/drivers/block/paride/Makefile index abb45d2fc..ae2d54dd9 100644 --- a/drivers/block/paride/Makefile +++ b/drivers/block/paride/Makefile @@ -12,6 +12,7 @@ SUB_DIRS := MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) +MOD_LIST_NAME := PARIDE_MODULES L_TARGET := paride.a MX_OBJS := LX_OBJS := @@ -30,7 +31,7 @@ ifeq ($(CONFIG_PARIDE_PD),y) LX_OBJS += pd.o else ifeq ($(CONFIG_PARIDE_PD),m) - MX_OBJS += pd.o + M_OBJS += pd.o endif endif @@ -38,7 +39,7 @@ ifeq ($(CONFIG_PARIDE_PCD),y) LX_OBJS += pcd.o else ifeq ($(CONFIG_PARIDE_PCD),m) - MX_OBJS += pcd.o + M_OBJS += pcd.o endif endif @@ -46,7 +47,7 @@ ifeq ($(CONFIG_PARIDE_PF),y) LX_OBJS += pf.o else ifeq ($(CONFIG_PARIDE_PF),m) - MX_OBJS += pf.o + M_OBJS += pf.o endif endif @@ -54,7 +55,7 @@ ifeq ($(CONFIG_PARIDE_PT),y) LX_OBJS += pt.o else ifeq ($(CONFIG_PARIDE_PT),m) - MX_OBJS += pt.o + M_OBJS += pt.o endif endif @@ -62,7 +63,7 @@ ifeq ($(CONFIG_PARIDE_PG),y) LX_OBJS += pg.o else ifeq ($(CONFIG_PARIDE_PG),m) - MX_OBJS += pg.o + M_OBJS += pg.o endif endif @@ -70,7 +71,7 @@ ifeq ($(CONFIG_PARIDE_ATEN),y) LX_OBJS += aten.o else ifeq ($(CONFIG_PARIDE_ATEN),m) - MX_OBJS += aten.o + M_OBJS += aten.o endif endif @@ -78,7 +79,7 @@ ifeq ($(CONFIG_PARIDE_BPCK),y) LX_OBJS += bpck.o else ifeq ($(CONFIG_PARIDE_BPCK),m) - MX_OBJS += bpck.o + M_OBJS += bpck.o endif endif @@ -86,7 +87,7 @@ ifeq ($(CONFIG_PARIDE_COMM),y) LX_OBJS += comm.o else ifeq ($(CONFIG_PARIDE_COMM),m) - MX_OBJS += comm.o + M_OBJS += comm.o endif endif @@ -94,7 +95,7 @@ ifeq ($(CONFIG_PARIDE_DSTR),y) LX_OBJS += dstr.o else ifeq ($(CONFIG_PARIDE_DSTR),m) - MX_OBJS += dstr.o + M_OBJS += dstr.o endif endif @@ -102,7 +103,7 @@ ifeq ($(CONFIG_PARIDE_KBIC),y) LX_OBJS += kbic.o else ifeq ($(CONFIG_PARIDE_KBIC),m) - MX_OBJS += kbic.o + M_OBJS += kbic.o endif endif @@ -110,7 +111,7 @@ ifeq ($(CONFIG_PARIDE_EPAT),y) LX_OBJS += epat.o else ifeq ($(CONFIG_PARIDE_EPAT),m) - MX_OBJS += epat.o + M_OBJS += epat.o endif endif @@ -118,7 +119,7 @@ ifeq ($(CONFIG_PARIDE_EPIA),y) LX_OBJS += epia.o else ifeq ($(CONFIG_PARIDE_EPIA),m) - MX_OBJS += epia.o + M_OBJS += epia.o endif endif @@ -126,7 +127,7 @@ ifeq ($(CONFIG_PARIDE_FIT2),y) LX_OBJS += fit2.o else ifeq ($(CONFIG_PARIDE_FIT2),m) - MX_OBJS += fit2.o + M_OBJS += fit2.o endif endif @@ -134,7 +135,7 @@ ifeq ($(CONFIG_PARIDE_FIT3),y) LX_OBJS += fit3.o else ifeq ($(CONFIG_PARIDE_FIT3),m) - MX_OBJS += fit3.o + M_OBJS += fit3.o endif endif @@ -142,7 +143,7 @@ ifeq ($(CONFIG_PARIDE_FRPW),y) LX_OBJS += frpw.o else ifeq ($(CONFIG_PARIDE_FRPW),m) - MX_OBJS += frpw.o + M_OBJS += frpw.o endif endif @@ -150,7 +151,7 @@ ifeq ($(CONFIG_PARIDE_ON20),y) LX_OBJS += on20.o else ifeq ($(CONFIG_PARIDE_ON20),m) - MX_OBJS += on20.o + M_OBJS += on20.o endif endif @@ -158,7 +159,7 @@ ifeq ($(CONFIG_PARIDE_ON26),y) LX_OBJS += on26.o else ifeq ($(CONFIG_PARIDE_ON26),m) - MX_OBJS += on26.o + M_OBJS += on26.o endif endif @@ -166,7 +167,7 @@ ifeq ($(CONFIG_PARIDE_KTTI),y) LX_OBJS += ktti.o else ifeq ($(CONFIG_PARIDE_KTTI),m) - MX_OBJS += ktti.o + M_OBJS += ktti.o endif endif diff --git a/drivers/block/paride/bpck.c b/drivers/block/paride/bpck.c index 4b241c737..05e2de2da 100644 --- a/drivers/block/paride/bpck.c +++ b/drivers/block/paride/bpck.c @@ -10,10 +10,11 @@ /* Changes: 1.01 GRG 1998.05.05 init_proto, release_proto, pi->delay + 1.02 GRG 1998.08.15 default pi->delay returned to 4 */ -#define BPCK_VERSION "1.01" +#define BPCK_VERSION "1.02" #include #include @@ -450,7 +451,7 @@ static void bpck_release_proto( PIA *pi) { MOD_DEC_USE_COUNT; } -struct pi_protocol bpck = { "bpck",0,5,2,1,256, +struct pi_protocol bpck = { "bpck",0,5,2,4,256, bpck_write_regr, bpck_read_regr, bpck_write_block, diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c index 805b69e19..068deffd6 100644 --- a/drivers/block/paride/paride.c +++ b/drivers/block/paride/paride.c @@ -11,10 +11,11 @@ 1.01 GRG 1998.05.03 Use spinlocks 1.02 GRG 1998.05.05 init_proto, release_proto, ktti + 1.03 GRG 1998.08.15 eliminate compiler warning */ -#define PI_VERSION "1.02" +#define PI_VERSION "1.03" #include #include @@ -249,7 +250,7 @@ static void pi_register_parport( PIA *pi, int verbose) if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port,pp->name); - pi->parname = pp->name; + pi->parname = (char *)pp->name; #endif } diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index ecacacb3b..4a083abbf 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -2,11 +2,11 @@ pcd.c (c) 1997-8 Grant R. Guenther Under the terms of the GNU public license. - This is a high-level driver for parallel port ATAPI CDROM + This is a high-level driver for parallel port ATAPI CD-ROM drives based on chips supported by the paride module. By default, the driver will autoprobe for a single parallel - port ATAPI CDROM drive, but if their individual parameters are + port ATAPI CD-ROM drive, but if their individual parameters are specified, the driver can handle up to 4 drives. The behaviour of the pcd driver can be altered by setting @@ -38,7 +38,7 @@ of the mode numbers supported by the adapter. (-1 if not given) - ATAPI CDROMs can be jumpered to master or slave. + ATAPI CD-ROMs can be jumpered to master or slave. Set this to 0 to choose the master drive, 1 to choose the slave, -1 (the default) to choose the first drive found. @@ -61,10 +61,11 @@ (default "pcd") verbose This parameter controls the amount of logging - that is done while the driver probes for - devices. Set it to 0 for a quiet load, or 1 to - see all the progress messages. (default 0) - + that the driver will do. Set it to 0 for + normal operation, 1 to see autoprobe progress + messages, or 2 to see additional debugging + output. (default 0) + nice This parameter controls the driver's use of idle CPU time, at the expense of some speed. @@ -85,16 +86,20 @@ /* Changes: - 1.01 GRG 1997.01.24 Added test unit ready support + 1.01 GRG 1998.01.24 Added test unit ready support 1.02 GRG 1998.05.06 Changes to pcd_completion, ready_wait, and loosen interpretation of ATAPI standard for clearing error status. Use spinlocks. Eliminate sti(). 1.03 GRG 1998.06.16 Eliminated an Ugh + 1.04 GRG 1998.08.15 Added extra debugging, improvements to + pcd_completion, use HZ in loop timing + 1.05 GRG 1998.08.16 Conformed to "Uniform CD-ROM" standard + 1.06 GRG 1998.08.19 Added audio ioctl support */ -#define PCD_VERSION "1.03" +#define PCD_VERSION "1.06" #define PCD_MAJOR 46 #define PCD_NAME "pcd" #define PCD_UNITS 4 @@ -185,9 +190,10 @@ MODULE_PARM(drive3,"1-6i"); #define PCD_RETRIES 5 #define PCD_TMO 800 /* timeout in jiffies */ #define PCD_DELAY 50 /* spin delay in uS */ -#define PCD_READY_TMO 20 +#define PCD_READY_TMO 20 /* in seconds */ +#define PCD_RESET_TMO 30 /* in tenths of a second */ -#define PCD_SPIN (10000/PCD_DELAY)*PCD_TMO +#define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY) #define IDE_ERR 0x01 #define IDE_DRQ 0x08 @@ -197,33 +203,33 @@ MODULE_PARM(drive3,"1-6i"); int pcd_init(void); void cleanup_module( void ); -static int pcd_open(struct inode *inode, struct file *file); -static void do_pcd_request(void); -static void do_pcd_read(void); -static int pcd_ioctl(struct inode *inode,struct file *file, - unsigned int cmd, unsigned long arg); - -static int pcd_release (struct inode *inode, struct file *file); +static int pcd_open(struct cdrom_device_info *cdi, int purpose); +static void pcd_release(struct cdrom_device_info *cdi); +static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr); +static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr); +static int pcd_tray_move(struct cdrom_device_info *cdi, int position); +static int pcd_lock_door(struct cdrom_device_info *cdi, int lock); +static int pcd_drive_reset(struct cdrom_device_info *cdi); +static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn); +static int pcd_audio_ioctl(struct cdrom_device_info *cdi, + unsigned int cmd, void *arg); static int pcd_detect(void); -static void pcd_lock(int unit); -static void pcd_unlock(int unit); -static void pcd_eject(int unit); -static int pcd_check_media(int unit); static void do_pcd_read_drq(void); +static void do_pcd_request(void); +static void do_pcd_read(void); static int pcd_blocksizes[PCD_UNITS]; -#define PCD_NAMELEN 8 - struct pcd_unit { - struct pi_adapter pia; /* interface to paride layer */ + struct pi_adapter pia; /* interface to paride layer */ struct pi_adapter *pi; - int drive; /* master/slave */ - int last_sense; /* result of last request sense */ - int access; /* count of active opens */ - int present; /* does this unit exist ? */ - char name[PCD_NAMELEN]; /* pcd0, pcd1, etc */ + int drive; /* master/slave */ + int last_sense; /* result of last request sense */ + int changed; /* media change seen */ + int present; /* does this unit exist ? */ + char *name; /* pcd0, pcd1, etc */ + struct cdrom_device_info info; /* uniform cdrom interface */ }; struct pcd_unit pcd[PCD_UNITS]; @@ -251,22 +257,32 @@ static int pcd_sector; /* address of next requested sector */ static int pcd_count; /* number of blocks still to do */ static char * pcd_buf; /* buffer for request in progress */ +static int pcd_warned = 0; /* Have we logged a phase warning ? */ + /* kernel glue structures */ -static struct file_operations pcd_fops = { - NULL, /* lseek - default */ - block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ - NULL, /* readdir - bad */ - NULL, /* select */ - pcd_ioctl, /* ioctl */ - NULL, /* mmap */ - pcd_open, /* open */ - pcd_release, /* release */ - block_fsync, /* fsync */ - NULL, /* fasync */ - NULL, /* media change ? */ - NULL /* revalidate new media */ +static struct cdrom_device_ops pcd_dops = { + pcd_open, + pcd_release, + pcd_drive_status, + pcd_media_changed, + pcd_tray_move, + pcd_lock_door, + 0, /* select speed */ + 0, /* select disk */ + 0, /* get last session */ + pcd_get_mcn, + pcd_drive_reset, + pcd_audio_ioctl, + 0, /* dev_ioctl */ + CDC_CLOSE_TRAY | + CDC_OPEN_TRAY | + CDC_LOCK | + CDC_MCN | + CDC_MEDIA_CHANGED | + CDC_RESET | + CDC_PLAY_AUDIO, + 0 }; static void pcd_init_units( void ) @@ -276,21 +292,31 @@ static void pcd_init_units( void ) pcd_drive_count = 0; for (unit=0;uniti_rdev); +{ int unit = DEVICE_NR(cdi->dev); if ((unit >= PCD_UNITS) || (!PCD.present)) return -ENODEV; - if (file->f_mode & 2) return -EROFS; /* wants to write ? */ - MOD_INC_USE_COUNT; - if (pcd_check_media(unit)) { - MOD_DEC_USE_COUNT; - return -ENXIO; - } - - pcd_lock(unit); - - PCD.access++; return 0; } -static void do_pcd_request (void) - -{ int unit; - - if (pcd_busy) return; - while (1) { - if ((!CURRENT) || (CURRENT->rq_status == RQ_INACTIVE)) return; - INIT_REQUEST; - if (CURRENT->cmd == READ) { - unit = MINOR(CURRENT->rq_dev); - if (unit != pcd_unit) { - pcd_bufblk = -1; - pcd_unit = unit; - } - pcd_sector = CURRENT->sector; - pcd_count = CURRENT->nr_sectors; - pcd_buf = CURRENT->buffer; - pcd_busy = 1; - ps_set_intr(do_pcd_read,0,0,nice); - return; - } - else end_request(0); - } -} - -static int pcd_ioctl(struct inode *inode,struct file *file, - unsigned int cmd, unsigned long arg) - -/* we currently support only the EJECT ioctl. */ - -{ int unit = DEVICE_NR(inode->i_rdev); - if ((unit >= PCD_UNITS) || (!PCD.present)) return -ENODEV; - - switch (cmd) { - case CDROMEJECT: if (PCD.access == 1) { - pcd_eject(unit); - return 0; - } - default: - return -EINVAL; - } -} - -static int pcd_release (struct inode *inode, struct file *file) - -{ kdev_t devp; - int unit; - - struct super_block *sb; - - devp = inode->i_rdev; - unit = DEVICE_NR(devp); - - if ((unit >= PCD_UNITS) || (PCD.access <= 0)) - return -EINVAL; - - PCD.access--; - - if (!PCD.access) { - fsync_dev(devp); - - sb = get_super(devp); - if (sb) invalidate_inodes(sb); - - invalidate_buffers(devp); - pcd_unlock(unit); - - } - - MOD_DEC_USE_COUNT; - - return 0; +static void pcd_release(struct cdrom_device_info *cdi) +{ MOD_DEC_USE_COUNT; } #ifdef MODULE @@ -423,11 +373,14 @@ int init_module(void) void cleanup_module(void) { int unit; - - unregister_blkdev(MAJOR_NR,name); for (unit=0;unit 0) && (j == 0)) { + pi_read_block(PI,buf,n); + if (verbose > 1) + printk("%s: %s: Read %d bytes\n",PCD.name,fun,n); + r = 0; j++; + } else { + if (verbose > 1) + printk("%s: %s: Unexpected phase %d, d=%d, k=%d\n", + PCD.name,fun,p,d,k); + if ((verbose < 2) && !pcd_warned) { + pcd_warned = 1; + printk("%s: WARNING: ATAPI phase errors\n",PCD.name); + } + mdelay(1); + } + if (k++ > PCD_TMO) { + printk("%s: Stuck DRQ\n",PCD.name); + break; + } + if (pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR, + fun,"completion")) { + r = -1; + break; + } + } } - - s = pcd_wait(unit,IDE_BUSY,IDE_READY|IDE_ERR,fun,"data done"); - + pi_disconnect(PI); - return (r?r:s); + return r; } -static void pcd_req_sense( int unit, int quiet ) +static void pcd_req_sense( int unit, char *fun ) { char rs_cmd[12] = { 0x03,0,0,0,16,0,0,0,0,0,0,0 }; char buf[16]; - int r; + int r, c; r = pcd_command(unit,rs_cmd,16,"Request sense"); mdelay(1); if (!r) pcd_completion(unit,buf,"Request sense"); - PCD.last_sense = -1; + PCD.last_sense = -1; c = 2; if (!r) { - if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n", - PCD.name,buf[2]&0xf,buf[12],buf[13]); - PCD.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8) - | ((buf[13]&0xff)<<16) ; + if (fun) printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n", + PCD.name,fun,buf[2]&0xf,buf[12],buf[13]); + c = buf[2]&0xf; + PCD.last_sense = c | ((buf[12]&0xff)<<8) | ((buf[13]&0xff)<<16); } + if ((c == 2) || (c == 6)) PCD.changed = 1; } static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) @@ -531,45 +513,42 @@ static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) r = pcd_command(unit,cmd,dlen,fun); mdelay(1); if (!r) r = pcd_completion(unit,buf,fun); - if (r) pcd_req_sense(unit,!fun); + if (r) pcd_req_sense(unit,fun); return r; } -#define DBMSG(msg) NULL +#define DBMSG(msg) ((verbose>1)?(msg):NULL) -static void pcd_lock(int unit) +static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr) -{ char lo_cmd[12] = { 0x1e,0,0,0,1,0,0,0,0,0,0,0 }; - char cl_cmd[12] = { 0x1b,0,0,0,3,0,0,0,0,0,0,0 }; +{ int r; + int unit = DEVICE_NR(cdi->dev); - pcd_atapi(unit,cl_cmd,0,pcd_scratch,DBMSG("cd1")); - pcd_atapi(unit,cl_cmd,0,pcd_scratch,DBMSG("cd2")); - pcd_atapi(unit,cl_cmd,0,pcd_scratch,DBMSG("cd3")); - pcd_atapi(unit,cl_cmd,0,pcd_scratch,DBMSG("cd4")); - pcd_atapi(unit,cl_cmd,0,pcd_scratch,"close door"); + r = PCD.changed; + PCD.changed = 0; - pcd_atapi(unit,lo_cmd,0,pcd_scratch,DBMSG("ld")); - pcd_atapi(unit,lo_cmd,0,pcd_scratch,"lock door"); + return r; } -static void pcd_unlock( int unit ) +static int pcd_lock_door(struct cdrom_device_info *cdi, int lock) -{ char un_cmd[12] = { 0x1e,0,0,0,0,0,0,0,0,0,0,0 }; +{ char un_cmd[12] = { 0x1e,0,0,0,lock,0,0,0,0,0,0,0 }; + int unit = DEVICE_NR(cdi->dev); - pcd_atapi(unit,un_cmd,0,pcd_scratch,"unlock door"); + return pcd_atapi(unit,un_cmd,0,pcd_scratch, + lock?"lock door":"unlock door"); } -static void pcd_eject( int unit) +static int pcd_tray_move(struct cdrom_device_info *cdi, int position) -{ char ej_cmd[12] = { 0x1b,0,0,0,2,0,0,0,0,0,0,0 }; +{ char ej_cmd[12] = { 0x1b,0,0,0,3-position,0,0,0,0,0,0,0 }; + int unit = DEVICE_NR(cdi->dev); - pcd_unlock(unit); - pcd_atapi(unit,ej_cmd,0,pcd_scratch,"eject"); + return pcd_atapi(unit,ej_cmd,0,pcd_scratch, + position?"eject":"close tray"); } -#define PCD_RESET_TMO 30 /* in tenths of a second */ - static void pcd_sleep( int cs ) { current->state = TASK_INTERRUPTIBLE; @@ -579,11 +558,6 @@ static void pcd_sleep( int cs ) static int pcd_reset( int unit ) -/* the ATAPI standard actually specifies the contents of all 7 registers - after a reset, but the specification is ambiguous concerning the last - two bytes, and different drives interpret the standard differently. -*/ - { int i, k, flg; int expect[5] = {1,1,1,0x14,0xeb}; @@ -591,11 +565,11 @@ static int pcd_reset( int unit ) WR(0,6,0xa0 + 0x10*PCD.drive); WR(0,7,8); - pcd_sleep(2); /* delay a bit*/ + pcd_sleep(2); /* delay a bit */ k = 0; while ((k++ < PCD_RESET_TMO) && (RR(1,6)&IDE_BUSY)) - pcd_sleep(10); + pcd_sleep(HZ/10); flg = 1; for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]); @@ -611,6 +585,11 @@ static int pcd_reset( int unit ) return flg-1; } +static int pcd_drive_reset(struct cdrom_device_info *cdi) + +{ return pcd_reset(DEVICE_NR(cdi->dev)); +} + static int pcd_ready_wait( int unit, int tmo ) { char tr_cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; @@ -629,12 +608,16 @@ static int pcd_ready_wait( int unit, int tmo ) return 0x000020; /* timeout */ } -static int pcd_check_media( int unit ) +static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) { char rc_cmd[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0}; + int unit = DEVICE_NR(cdi->dev); - pcd_ready_wait(unit,PCD_READY_TMO); - return (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media"))); + if (pcd_ready_wait(unit,PCD_READY_TMO)) + return CDS_DRIVE_NOT_READY; + if (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media"))) + return CDS_NO_DISC; + return CDS_DISC_OK; } static int pcd_identify( int unit, char * id ) @@ -648,7 +631,7 @@ static int pcd_identify( int unit, char * id ) if (s) return -1; if ((pcd_buffer[0] & 0x1f) != 5) { - if (verbose) printk("%s: %s is not a CDROM\n", + if (verbose) printk("%s: %s is not a CD-ROM\n", PCD.name,PCD.drive?"Slave":"Master"); return -1; } @@ -709,12 +692,37 @@ static int pcd_detect( void ) if (k) return 0; - printk("%s: No CDROM drive found\n",name); + printk("%s: No CD-ROM drive found\n",name); return -1; } /* I/O request processing */ +static void do_pcd_request (void) + +{ int unit; + + if (pcd_busy) return; + while (1) { + if ((!CURRENT) || (CURRENT->rq_status == RQ_INACTIVE)) return; + INIT_REQUEST; + if (CURRENT->cmd == READ) { + unit = MINOR(CURRENT->rq_dev); + if (unit != pcd_unit) { + pcd_bufblk = -1; + pcd_unit = unit; + } + pcd_sector = CURRENT->sector; + pcd_count = CURRENT->nr_sectors; + pcd_buf = CURRENT->buffer; + pcd_busy = 1; + ps_set_intr(do_pcd_read,0,0,nice); + return; + } + else end_request(0); + } +} + static int pcd_ready( void ) { int unit = pcd_unit; @@ -793,7 +801,7 @@ static void do_pcd_read_drq( void ) if (pcd_completion(unit,pcd_buffer,"read block")) { if (pcd_retries < PCD_RETRIES) { - mdelay(1); + mdelay(1); pcd_retries++; pi_do_claimed(PI,pcd_start); return; @@ -812,6 +820,227 @@ static void do_pcd_read_drq( void ) do_pcd_request(); spin_unlock_irqrestore(&io_request_lock,saved_flags); } + +/* the audio_ioctl stuff is adapted from sr_ioctl.c */ + +static int pcd_audio_ioctl(struct cdrom_device_info *cdi, + unsigned int cmd, void *arg) + +{ int unit = DEVICE_NR(cdi->dev); + + switch (cmd) { + + case CDROMPAUSE: + + { char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0}; + + return (pcd_atapi(unit,cmd,0,NULL,"pause")) * EIO; + } + + case CDROMRESUME: + + { char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0}; + + return (pcd_atapi(unit,cmd,0,NULL,"resume")) * EIO; + } + + case CDROMPLAYMSF: + + { char cmd[12]={SCMD_PLAYAUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0}; + struct cdrom_msf* msf = (struct cdrom_msf*)arg; + + cmd[3] = msf->cdmsf_min0; + cmd[4] = msf->cdmsf_sec0; + cmd[5] = msf->cdmsf_frame0; + cmd[6] = msf->cdmsf_min1; + cmd[7] = msf->cdmsf_sec1; + cmd[8] = msf->cdmsf_frame1; + + return (pcd_atapi(unit,cmd,0,NULL,"play msf")) * EIO; + } + + case CDROMPLAYBLK: + + { char cmd[12]={SCMD_PLAYAUDIO10,0,0,0,0,0,0,0,0,0,0,0}; + struct cdrom_blk* blk = (struct cdrom_blk*)arg; + + cmd[2] = blk->from >> 24; + cmd[3] = blk->from >> 16; + cmd[4] = blk->from >> 8; + cmd[5] = blk->from; + cmd[7] = blk->len >> 8; + cmd[8] = blk->len; + + return (pcd_atapi(unit,cmd,0,NULL,"play block")) * EIO; + } + + case CDROMPLAYTRKIND: + + { char cmd[12]={SCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0}; + struct cdrom_ti* ti = (struct cdrom_ti*)arg; + + cmd[4] = ti->cdti_trk0; + cmd[5] = ti->cdti_ind0; + cmd[7] = ti->cdti_trk1; + cmd[8] = ti->cdti_ind1; + + return (pcd_atapi(unit,cmd,0,NULL,"play track")) * EIO; + } + + case CDROMREADTOCHDR: + + { char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0}; + struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg; + char buffer[32]; + int r; + + r = pcd_atapi(unit,cmd,12,buffer,"read toc header"); + + tochdr->cdth_trk0 = buffer[2]; + tochdr->cdth_trk1 = buffer[3]; + + return r * EIO; + } + + case CDROMREADTOCENTRY: + + { char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0}; + + struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg; + unsigned char buffer[32]; + int r; + + cmd[1] = (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0); + cmd[6] = tocentry->cdte_track; + + r = pcd_atapi(unit,cmd,12,buffer,"read toc entry"); + + tocentry->cdte_ctrl = buffer[5] & 0xf; + tocentry->cdte_adr = buffer[5] >> 4; + tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04)?1:0; + if (tocentry->cdte_format == CDROM_MSF) { + tocentry->cdte_addr.msf.minute = buffer[9]; + tocentry->cdte_addr.msf.second = buffer[10]; + tocentry->cdte_addr.msf.frame = buffer[11]; + } else + tocentry->cdte_addr.lba = + (((((buffer[8] << 8) + buffer[9]) << 8) + + buffer[10]) << 8) + buffer[11]; + + return r * EIO; + } + + case CDROMSTOP: + + { char cmd[12]={0x1b,1,0,0,0,0,0,0,0,0,0,0}; + + return (pcd_atapi(unit,cmd,0,NULL,"stop")) * EIO; + } + + case CDROMSTART: + + { char cmd[12]={0x1b,1,0,0,1,0,0,0,0,0,0,0}; + + return (pcd_atapi(unit,cmd,0,NULL,"start")) * EIO; + } + + case CDROMVOLCTRL: + + { char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0}; + char buffer[32]; + char mask[32]; + struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; + + cmd[2] = 0xe; + cmd[4] = 28; + + if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol")) + return -EIO; + + cmd[2] = 0x4e; + + if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol mask")) + return -EIO; + + buffer[0] = 0; + + buffer[21] = volctrl->channel0 & mask[21]; + buffer[23] = volctrl->channel1 & mask[23]; + buffer[25] = volctrl->channel2 & mask[25]; + buffer[27] = volctrl->channel3 & mask[27]; + + cmd[0] = 0x55; + cmd[1] = 0x10; + + return pcd_atapi(unit,cmd,28,buffer,"mode select vol") * EIO; + } + + case CDROMVOLREAD: + + { char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0}; + char buffer[32]; + struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; + int r; + + cmd[2] = 0xe; + cmd[4] = 28; + + r = pcd_atapi(unit,cmd,28,buffer,"mode sense vol read"); + + volctrl->channel0 = buffer[21]; + volctrl->channel1 = buffer[23]; + volctrl->channel2 = buffer[25]; + volctrl->channel3 = buffer[27]; + + return r * EIO; + } + + + case CDROMSUBCHNL: + + { char cmd[12]={SCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0}; + struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg; + char buffer[32]; + + if (pcd_atapi(unit,cmd,16,buffer,"read subchannel")) + return -EIO; + + subchnl->cdsc_audiostatus = buffer[1]; + subchnl->cdsc_format = CDROM_MSF; + subchnl->cdsc_ctrl = buffer[5] & 0xf; + subchnl->cdsc_trk = buffer[6]; + subchnl->cdsc_ind = buffer[7]; + + subchnl->cdsc_reladdr.msf.minute = buffer[13]; + subchnl->cdsc_reladdr.msf.second = buffer[14]; + subchnl->cdsc_reladdr.msf.frame = buffer[15]; + subchnl->cdsc_absaddr.msf.minute = buffer[9]; + subchnl->cdsc_absaddr.msf.second = buffer[10]; + subchnl->cdsc_absaddr.msf.frame = buffer[11]; + + return 0; + } + + default: + + return -ENOSYS; + } +} +static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) + +{ char cmd[12]={SCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0}; + char buffer[32]; + int k; + int unit = DEVICE_NR(cdi->dev); + + if (pcd_atapi(unit,cmd,24,buffer,"get mcn")) return -EIO; + + for (k=0;k<13;k++) mcn->medium_catalog_number[k] = buffer[k+9]; + mcn->medium_catalog_number[13] = 0; + + return 0; +} + /* end of pcd.c */ diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 3be1de32c..69274fe48 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -78,9 +78,10 @@ (default 64) verbose This parameter controls the amount of logging - that is done while the driver probes for - devices. Set it to 0 for a quiet load, or to 1 - see all the progress messages. (default 0) + that the driver will do. Set it to 0 for + normal operation, 1 to see autoprobe progress + messages, or 2 to see additional debugging + output. (default 0) nice This parameter controls the driver's use of idle CPU time, at the expense of some speed. @@ -108,10 +109,11 @@ 1.02 GRG 1998.05.06 SMP spinlock changes, Added slave support 1.03 GRG 1998.06.16 Eliminate an Ugh. + 1.04 GRG 1998.08.15 Extra debugging, use HZ in loop timing */ -#define PD_VERSION "1.03" +#define PD_VERSION "1.04" #define PD_MAJOR 45 #define PD_NAME "pd" #define PD_UNITS 4 @@ -223,7 +225,7 @@ MODULE_PARM(drive3,"1-8i"); #define PD_TMO 800 /* interrupt timeout in jiffies */ #define PD_SPIN_DEL 50 /* spin delay in micro-seconds */ -#define PD_SPIN (10000/PD_SPIN_DEL)*PD_TMO +#define PD_SPIN (1000000*PD_TMO)/(HZ*PD_SPIN_DEL) #define STAT_ERR 0x00001 #define STAT_INDEX 0x00002 @@ -359,6 +361,7 @@ static struct file_operations pd_fops = { pd_ioctl, /* ioctl */ NULL, /* mmap */ pd_open, /* open */ + NULL, /* flush */ pd_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ @@ -666,7 +669,7 @@ static void pd_reset( int unit ) /* called only for MASTER drive */ udelay(250); } -#define DBMSG(msg) NULL +#define DBMSG(msg) ((verbose>1)?(msg):NULL) static int pd_wait_for( int unit, int w, char * msg ) /* polled wait */ diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index a176c45d3..a2f1f1da9 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -76,10 +76,11 @@ (default 64) verbose This parameter controls the amount of logging - that is done while the driver probes for - devices. Set it to 0 for a quiet load, or 1 to - see all the progress messages. (default 0) - + that the driver will do. Set it to 0 for + normal operation, 1 to see autoprobe progress + messages, or 2 to see additional debugging + output. (default 0) + nice This parameter controls the driver's use of idle CPU time, at the expense of some speed. @@ -107,10 +108,11 @@ Small change in pf_completion to round up transfer size. 1.02 GRG 1998.06.16 Eliminated an Ugh + 1.03 GRG 1998.08.16 Use HZ in loop timings, extra debugging */ -#define PF_VERSION "1.02" +#define PF_VERSION "1.03" #define PF_MAJOR 47 #define PF_NAME "pf" #define PF_UNITS 4 @@ -217,7 +219,7 @@ MODULE_PARM(drive3,"1-7i"); #define PF_TMO 800 /* interrupt timeout in jiffies */ #define PF_SPIN_DEL 50 /* spin delay in micro-seconds */ -#define PF_SPIN (10000/PF_SPIN_DEL)*PF_TMO +#define PF_SPIN (1000000*PF_TMO)/(HZ*PF_SPIN_DEL) #define STAT_ERR 0x00001 #define STAT_INDEX 0x00002 @@ -316,6 +318,7 @@ static struct file_operations pf_fops = { pf_ioctl, /* ioctl */ NULL, /* mmap */ pf_open, /* open */ + NULL, /* flush */ pf_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ @@ -627,7 +630,7 @@ static int pf_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) return r; } -#define DBMSG(msg) NULL +#define DBMSG(msg) ((verbose>1)?(msg):NULL) static void pf_lock(int unit, int func) diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index 816b44ede..fd001008d 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -1,35 +1,35 @@ /* - pg.c (c) 1998 Grant R. Guenther - Under the terms of the GNU public license. + pg.c (c) 1998 Grant R. Guenther + Under the terms of the GNU public license. The pg driver provides a simple character device interface for - sending ATAPI commands to a device. With the exception of the + sending ATAPI commands to a device. With the exception of the ATAPI reset operation, all operations are performed by a pair - of read and write operations to the appropriate /dev/pgN device. + of read and write operations to the appropriate /dev/pgN device. A write operation delivers a command and any outbound data in - a single buffer. Normally, the write will succeed unless the - device is offline or malfunctioning, or there is already another + a single buffer. Normally, the write will succeed unless the + device is offline or malfunctioning, or there is already another command pending. If the write succeeds, it should be followed - immediately by a read operation, to obtain any returned data and - status information. A read will fail if there is no operation - in progress. + immediately by a read operation, to obtain any returned data and + status information. A read will fail if there is no operation + in progress. As a special case, the device can be reset with a write operation, - and in this case, no following read is expected, or permitted. + and in this case, no following read is expected, or permitted. There are no ioctl() operations. Any single operation may transfer at most PG_MAX_DATA bytes. Note that the driver must - copy the data through an internal buffer. In keeping with all + copy the data through an internal buffer. In keeping with all current ATAPI devices, command packets are assumed to be exactly 12 bytes in length. To permit future changes to this interface, the headers in the read and write buffers contain a single character "magic" flag. - Currently this flag must be the character "P". + Currently this flag must be the character "P". - By default, the driver will autoprobe for a single parallel - port ATAPI device, but if their individual parameters are - specified, the driver can handle up to 4 devices. + By default, the driver will autoprobe for a single parallel + port ATAPI device, but if their individual parameters are + specified, the driver can handle up to 4 devices. To use this device, you must have the following device special files defined: @@ -41,48 +41,48 @@ (You'll need to change the 97 to something else if you use the 'major' parameter to install the driver on a different - major number.) + major number.) - The behaviour of the pg driver can be altered by setting - some parameters from the insmod command line. The following - parameters are adjustable: + The behaviour of the pg driver can be altered by setting + some parameters from the insmod command line. The following + parameters are adjustable: - drive0 These four arguments can be arrays of - drive1 1-6 integers as follows: - drive2 - drive3 ,,,,, + drive0 These four arguments can be arrays of + drive1 1-6 integers as follows: + drive2 + drive3 ,,,,, - Where, + Where, - is the base of the parallel port address for - the corresponding drive. (required) + is the base of the parallel port address for + the corresponding drive. (required) - is the protocol number for the adapter that - supports this drive. These numbers are - logged by 'paride' when the protocol modules - are initialised. (0 if not given) + is the protocol number for the adapter that + supports this drive. These numbers are + logged by 'paride' when the protocol modules + are initialised. (0 if not given) - for those adapters that support chained - devices, this is the unit selector for the - chain of devices on the given port. It should - be zero for devices that don't support chaining. - (0 if not given) + for those adapters that support chained + devices, this is the unit selector for the + chain of devices on the given port. It should + be zero for devices that don't support chaining. + (0 if not given) - this can be -1 to choose the best mode, or one - of the mode numbers supported by the adapter. - (-1 if not given) + this can be -1 to choose the best mode, or one + of the mode numbers supported by the adapter. + (-1 if not given) - ATAPI devices can be jumpered to master or slave. - Set this to 0 to choose the master drive, 1 to - choose the slave, -1 (the default) to choose the - first drive found. + ATAPI devices can be jumpered to master or slave. + Set this to 0 to choose the master drive, 1 to + choose the slave, -1 (the default) to choose the + first drive found. - some parallel ports require the driver to - go more slowly. -1 sets a default value that - should work with the chosen protocol. Otherwise, - set this to a small integer, the larger it is - the slower the port i/o. In some cases, setting - this to zero will speed up the device. (default -1) + some parallel ports require the driver to + go more slowly. -1 sets a default value that + should work with the chosen protocol. Otherwise, + set this to a small integer, the larger it is + the slower the port i/o. In some cases, setting + this to zero will speed up the device. (default -1) major You may use this parameter to overide the default major number (97) that this driver @@ -94,23 +94,23 @@ device (in /proc output, for instance). (default "pg"). - verbose This parameter controls the amount of logging - that is done by the driver. Set it to 0 for + verbose This parameter controls the amount of logging + that is done by the driver. Set it to 0 for quiet operation, to 1 to enable progress messages while the driver probes for devices, or to 2 for full debug logging. (default 0) - If this driver is built into the kernel, you can use - the following command line parameters, with the same values - as the corresponding module parameters listed above: + If this driver is built into the kernel, you can use + the following command line parameters, with the same values + as the corresponding module parameters listed above: - pg.drive0 - pg.drive1 - pg.drive2 - pg.drive3 + pg.drive0 + pg.drive1 + pg.drive2 + pg.drive3 - In addition, you can use the parameter pg.disable to disable - the driver entirely. + In addition, you can use the parameter pg.disable to disable + the driver entirely. */ @@ -175,9 +175,9 @@ static int pg_drive_count; #include "setup.h" static STT pg_stt[5] = {{"drive0",6,drive0}, - {"drive1",6,drive1}, - {"drive2",6,drive2}, - {"drive3",6,drive3}, + {"drive1",6,drive1}, + {"drive2",6,drive2}, + {"drive3",6,drive3}, {"disable",1,&disable}}; void pg_setup( char *str, int *ints) @@ -221,9 +221,9 @@ void cleanup_module( void ); static int pg_open(struct inode *inode, struct file *file); static int pg_release (struct inode *inode, struct file *file); static ssize_t pg_read(struct file * filp, char * buf, - size_t count, loff_t *ppos); + size_t count, loff_t *ppos); static ssize_t pg_write(struct file * filp, const char * buf, - size_t count, loff_t *ppos); + size_t count, loff_t *ppos); static int pg_detect(void); static int pg_identify (int unit, int log); @@ -257,39 +257,40 @@ static char pg_scratch[512]; /* scratch block buffer */ /* kernel glue structures */ static struct file_operations pg_fops = { - NULL, /* lseek - default */ - pg_read, /* read */ - pg_write, /* write */ - NULL, /* readdir - bad */ - NULL, /* select */ - NULL, /* ioctl */ - NULL, /* mmap */ - pg_open, /* open */ - pg_release, /* release */ - NULL, /* fsync */ - NULL, /* fasync */ - NULL, /* media change ? */ - NULL /* revalidate new media */ + NULL, /* lseek - default */ + pg_read, /* read */ + pg_write, /* write */ + NULL, /* readdir - bad */ + NULL, /* select */ + NULL, /* ioctl */ + NULL, /* mmap */ + pg_open, /* open */ + NULL, /* flush */ + pg_release, /* release */ + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* media change ? */ + NULL /* revalidate new media */ }; void pg_init_units( void ) { int unit, j; - pg_drive_count = 0; - for (unit=0;unitstate = TASK_INTERRUPTIBLE; - current->timeout = jiffies + cs; - schedule(); + current->timeout = jiffies + cs; + schedule(); } static int pg_wait( int unit, int go, int stop, int tmo, char * msg ) @@ -358,26 +359,26 @@ static int pg_wait( int unit, int go, int stop, int tmo, char * msg ) PG.status = 0; - j = 0; - while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(jiffies=tmo)) { - s = RR(0,7); - e = RR(0,1); - p = RR(0,2); - if (verbose > 1) + if ((r&(STAT_ERR&stop))||(jiffies>=tmo)) { + s = RR(0,7); + e = RR(0,1); + p = RR(0,2); + if (verbose > 1) printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n", - PG.name,msg,s,e,p,(jiffies>=tmo)?" timeout":""); + PG.name,msg,s,e,p,(jiffies>=tmo)?" timeout":""); - if (jiffies>=tmo) e |= 0x100; + if (jiffies>=tmo) e |= 0x100; PG.status = (e >> 4) & 0xff; - return -1; - } - return 0; + return -1; + } + return 0; } static int pg_command( int unit, char * cmd, int dlen, int tmo ) @@ -386,64 +387,64 @@ static int pg_command( int unit, char * cmd, int dlen, int tmo ) pi_connect(PI); - WR(0,6,DRIVE); + WR(0,6,DRIVE); - if (pg_wait(unit,STAT_BUSY|STAT_DRQ,0,tmo,"before command")) { - pi_disconnect(PI); - return -1; - } + if (pg_wait(unit,STAT_BUSY|STAT_DRQ,0,tmo,"before command")) { + pi_disconnect(PI); + return -1; + } - WR(0,4,dlen % 256); - WR(0,5,dlen / 256); - WR(0,7,0xa0); /* ATAPI packet command */ + WR(0,4,dlen % 256); + WR(0,5,dlen / 256); + WR(0,7,0xa0); /* ATAPI packet command */ - if (pg_wait(unit,STAT_BUSY,STAT_DRQ,tmo,"command DRQ")) { - pi_disconnect(PI); - return -1; - } + if (pg_wait(unit,STAT_BUSY,STAT_DRQ,tmo,"command DRQ")) { + pi_disconnect(PI); + return -1; + } - if (RR(0,2) != 1) { - printk("%s: command phase error\n",PG.name); - pi_disconnect(PI); - return -1; - } + if (RR(0,2) != 1) { + printk("%s: command phase error\n",PG.name); + pi_disconnect(PI); + return -1; + } - pi_write_block(PI,cmd,12); + pi_write_block(PI,cmd,12); if (verbose > 1) { printk("%s: Command sent, dlen=%d packet= ", PG.name,dlen); for (k=0;k<12;k++) printk("%02x ",cmd[k]&0xff); printk("\n"); } - return 0; + return 0; } static int pg_completion( int unit, char * buf, int tmo) { int r, d, n, p; - r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR, + r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR, tmo,"completion"); PG.dlen = 0; - while (RR(0,7)&STAT_DRQ) { - d = (RR(0,4)+256*RR(0,5)); - n = ((d+3)&0xfffc); + while (RR(0,7)&STAT_DRQ) { + d = (RR(0,4)+256*RR(0,5)); + n = ((d+3)&0xfffc); p = RR(0,2)&3; if (p == 0) pi_write_block(PI,buf,n); if (p == 2) pi_read_block(PI,buf,n); if (verbose > 1) printk("%s: %s %d bytes\n",PG.name, p?"Read":"Write",n); - PG.dlen += (1-p)*d; - buf += d; - r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR, - tmo,"completion"); - } + PG.dlen += (1-p)*d; + buf += d; + r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR, + tmo,"completion"); + } - pi_disconnect(PI); + pi_disconnect(PI); - return r; + return r; } static int pg_reset( int unit ) @@ -457,9 +458,9 @@ static int pg_reset( int unit ) pg_sleep(2); - k = 0; - while ((k++ < PG_RESET_TMO) && (RR(1,6)&STAT_BUSY)) - pg_sleep(1); + k = 0; + while ((k++ < PG_RESET_TMO) && (RR(1,6)&STAT_BUSY)) + pg_sleep(1); flg = 1; for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]); @@ -494,7 +495,7 @@ static int pg_identify( int unit, int log ) char id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0}; char buf[36]; - s = pg_command(unit,id_cmd,36,jiffies+PG_TMO); + s = pg_command(unit,id_cmd,36,jiffies+PG_TMO); if (s) return -1; s = pg_completion(unit,buf,jiffies+PG_TMO); if (s) return -1; @@ -502,7 +503,7 @@ static int pg_identify( int unit, int log ) if (log) { xs(buf,mf,8,8); xs(buf,id,16,16); - printk("%s: %s %s, %s\n",PG.name,mf,id,ms[PG.drive]); + printk("%s: %s %s, %s\n",PG.name,mf,id,ms[PG.drive]); } return 0; @@ -511,7 +512,7 @@ static int pg_identify( int unit, int log ) static int pg_probe( int unit ) /* returns 0, with id set if drive is detected - -1, if drive detection failed + -1, if drive detection failed */ { if (PG.drive == -1) { @@ -520,7 +521,7 @@ static int pg_probe( int unit ) } else { if (!pg_reset(unit)) return pg_identify(unit,1); } - return -1; + return -1; } static int pg_detect( void ) @@ -534,22 +535,22 @@ static int pg_detect( void ) if (pg_drive_count == 0) { unit = 0; if (pi_init(PI,1,-1,-1,-1,-1,-1,pg_scratch, - PI_PG,verbose,PG.name)) { - if (!pg_probe(unit)) { + PI_PG,verbose,PG.name)) { + if (!pg_probe(unit)) { PG.present = 1; k++; - } else pi_release(PI); + } else pi_release(PI); } } else for (unit=0;uniti_rdev); - if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV; + if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV; - PG.access++; + PG.access++; if (PG.access > 1) { PG.access--; return -EBUSY; } - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; if (PG.busy) { pg_reset(unit); @@ -590,34 +591,34 @@ static int pg_open (struct inode *inode, struct file *file) return -ENOMEM; } - return 0; + return 0; } static int pg_release (struct inode *inode, struct file *file) { - int unit = DEVICE_NR(inode->i_rdev); + int unit = DEVICE_NR(inode->i_rdev); - if ((unit >= PG_UNITS) || (PG.access <= 0)) - return -EINVAL; + if ((unit >= PG_UNITS) || (PG.access <= 0)) + return -EINVAL; PG.access--; kfree(PG.bufptr); PG.bufptr = NULL; - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; return 0; } static ssize_t pg_write(struct file * filp, const char * buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { struct inode *ino = filp->f_dentry->d_inode; - int unit = DEVICE_NR(ino->i_rdev); - struct pg_write_hdr hdr; - int hs = sizeof(hdr); + int unit = DEVICE_NR(ino->i_rdev); + struct pg_write_hdr hdr; + int hs = sizeof(hdr); if (PG.busy) return -EBUSY; if (count < hs) return -EINVAL; @@ -652,7 +653,7 @@ static ssize_t pg_write(struct file * filp, const char * buf, } static ssize_t pg_read(struct file * filp, char * buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { struct inode *ino = filp->f_dentry->d_inode; int unit = DEVICE_NR(ino->i_rdev); @@ -673,7 +674,7 @@ static ssize_t pg_read(struct file * filp, char * buf, copy = 0; if (hdr.dlen < 0) { - hdr.dlen = -1 * hdr.dlen; + hdr.dlen = -1 * hdr.dlen; copy = hdr.dlen; if (copy > (count - hs)) copy = count - hs; } diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index de77c1b5a..44c4dadfb 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -72,10 +72,11 @@ (default "pt"). verbose This parameter controls the amount of logging - that is done while the driver probes for - devices. Set it to 0 for a quiet load, or 1 to - see all the progress messages. (default 0) - + that the driver will do. Set it to 0 for + normal operation, 1 to see autoprobe progress + messages, or 2 to see additional debugging + output. (default 0) + If this driver is built into the kernel, you can use the following command line parameters, with the same values as the corresponding module parameters listed above: @@ -97,10 +98,12 @@ for clearing error status. Eliminate sti(); 1.02 GRG 1998.06.16 Eliminate an Ugh. + 1.03 GRG 1998.08.15 Adjusted PT_TMO, use HZ in loop timing, + extra debugging */ -#define PT_VERSION "1.02" +#define PT_VERSION "1.03" #define PT_MAJOR 96 #define PT_NAME "pt" #define PT_UNITS 4 @@ -174,13 +177,13 @@ MODULE_PARM(drive3,"1-6i"); #include "paride.h" #define PT_MAX_RETRIES 5 -#define PT_TMO 800 /* interrupt timeout in jiffies */ +#define PT_TMO 3000 /* interrupt timeout in jiffies */ #define PT_SPIN_DEL 50 /* spin delay in micro-seconds */ -#define PT_RESET_TMO 30 /* 3 seconds */ +#define PT_RESET_TMO 30 /* 30 seconds */ #define PT_READY_TMO 60 /* 60 seconds */ #define PT_REWIND_TMO 1200 /* 20 minutes */ -#define PT_SPIN (10000/PT_SPIN_DEL)*PT_TMO +#define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO) #define STAT_ERR 0x00001 #define STAT_INDEX 0x00002 @@ -265,6 +268,7 @@ static struct file_operations pt_fops = { pt_ioctl, /* ioctl */ NULL, /* mmap */ pt_open, /* open */ + NULL, /* flush */ pt_release, /* release */ NULL, /* fsync */ NULL, /* fasync */ @@ -505,7 +509,7 @@ static void pt_write_fm( int unit ) pt_media_access_cmd(unit,PT_TMO,wm_cmd,"write filemark"); } -#define DBMSG(msg) NULL +#define DBMSG(msg) ((verbose>1)?(msg):NULL) static int pt_reset( int unit ) diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c index bef50bd36..e56616a77 100644 --- a/drivers/block/ps2esdi.c +++ b/drivers/block/ps2esdi.c @@ -157,6 +157,7 @@ static struct file_operations ps2esdi_fops = ps2esdi_ioctl, /* ioctl */ NULL, /* mmap */ ps2esdi_open, /* open */ + NULL, /* flush */ ps2esdi_release, /* release */ block_fsync /* fsync */ }; diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 822e3ec18..dd1933a47 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -223,6 +223,7 @@ static struct file_operations initrd_fops = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* open */ + NULL, /* flush */ initrd_release, /* release */ NULL /* fsync */ }; @@ -249,13 +250,11 @@ static int rd_open(struct inode * inode, struct file * filp) return 0; } -#ifdef MODULE static int rd_release(struct inode * inode, struct file * filp) { MOD_DEC_USE_COUNT; return 0; } -#endif static struct file_operations fd_fops = { NULL, /* lseek - default */ @@ -266,11 +265,8 @@ static struct file_operations fd_fops = { rd_ioctl, /* ioctl */ NULL, /* mmap */ rd_open, /* open */ -#ifndef MODULE - NULL, /* no special release code... */ -#else + NULL, /* flush */ rd_release, /* module needs to decrement use count */ -#endif block_fsync /* fsync */ }; diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 5598ad0a7..eb2b38e95 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -968,7 +968,8 @@ static struct file_operations floppy_fops = { floppy_ioctl, /* ioctl */ NULL, /* mmap */ floppy_open, /* open */ - floppy_release, /* release */ + NULL, /* flush */ + floppy_release, /* release * block_fsync, /* fsync */ NULL, /* fasync */ floppy_check_change, /* check_media_change */ diff --git a/drivers/block/xd.c b/drivers/block/xd.c index ffb1645ac..ccbcc0a97 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -157,6 +157,7 @@ static struct file_operations xd_fops = { xd_ioctl, /* ioctl */ NULL, /* mmap */ xd_open, /* open */ + NULL, /* flush */ xd_release, /* release */ block_fsync /* fsync */ }; diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index ac13bcff2..193208d0d 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -63,46 +63,46 @@ do_z2_request( void ) while ( TRUE ) { - INIT_REQUEST; - - start = CURRENT->sector << 9; - len = CURRENT->current_nr_sectors << 9; - - if ( ( start + len ) > z2ram_size ) - { - printk( KERN_ERR DEVICE_NAME ": bad access: block=%ld, count=%ld\n", - CURRENT->sector, - CURRENT->current_nr_sectors); - end_request( FALSE ); - continue; - } - - if ( ( CURRENT->cmd != READ ) && ( CURRENT->cmd != WRITE ) ) - { - printk( KERN_ERR DEVICE_NAME ": bad command: %d\n", CURRENT->cmd ); - end_request( FALSE ); - continue; - } - - while ( len ) - { - addr = start & Z2RAM_CHUNKMASK; - size = Z2RAM_CHUNKSIZE - addr; - if ( len < size ) - size = len; - - addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ]; - - if ( CURRENT->cmd == READ ) - memcpy( CURRENT->buffer, (char *)addr, size ); - else - memcpy( (char *)addr, CURRENT->buffer, size ); - - start += size; - len -= size; - } - - end_request( TRUE ); + INIT_REQUEST; + + start = CURRENT->sector << 9; + len = CURRENT->current_nr_sectors << 9; + + if ( ( start + len ) > z2ram_size ) + { + printk( KERN_ERR DEVICE_NAME ": bad access: block=%ld, count=%ld\n", + CURRENT->sector, + CURRENT->current_nr_sectors); + end_request( FALSE ); + continue; + } + + if ( ( CURRENT->cmd != READ ) && ( CURRENT->cmd != WRITE ) ) + { + printk( KERN_ERR DEVICE_NAME ": bad command: %d\n", CURRENT->cmd ); + end_request( FALSE ); + continue; + } + + while ( len ) + { + addr = start & Z2RAM_CHUNKMASK; + size = Z2RAM_CHUNKSIZE - addr; + if ( len < size ) + size = len; + + addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ]; + + if ( CURRENT->cmd == READ ) + memcpy( CURRENT->buffer, (char *)addr, size ); + else + memcpy( (char *)addr, CURRENT->buffer, size ); + + start += size; + len -= size; + } + + end_request( TRUE ); } } @@ -113,13 +113,13 @@ get_z2ram( void ) for ( i = 0; i < Z2RAM_SIZE / Z2RAM_CHUNKSIZE; i++ ) { - if ( test_bit( i, zorro_unused_z2ram ) ) - { - z2_count++; - z2ram_map[ z2ram_size++ ] = - ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT ); - clear_bit( i, zorro_unused_z2ram ); - } + if ( test_bit( i, zorro_unused_z2ram ) ) + { + z2_count++; + z2ram_map[ z2ram_size++ ] = + ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT ); + clear_bit( i, zorro_unused_z2ram ); + } } return; @@ -131,18 +131,18 @@ get_chipram( void ) while ( amiga_chip_avail() > ( Z2RAM_CHUNKSIZE * 4 ) ) { - chip_count++; - z2ram_map[ z2ram_size ] = - (u_long)amiga_chip_alloc( Z2RAM_CHUNKSIZE ); + chip_count++; + z2ram_map[ z2ram_size ] = + (u_long)amiga_chip_alloc( Z2RAM_CHUNKSIZE ); - if ( z2ram_map[ z2ram_size ] == 0 ) - { - break; - } + if ( z2ram_map[ z2ram_size ] == 0 ) + { + break; + } - z2ram_size++; + z2ram_size++; } - + return; } @@ -151,99 +151,99 @@ z2_open( struct inode *inode, struct file *filp ) { int device; int max_z2_map = ( Z2RAM_SIZE / Z2RAM_CHUNKSIZE ) * - sizeof( z2ram_map[0] ); + sizeof( z2ram_map[0] ); int max_chip_map = ( amiga_chip_size / Z2RAM_CHUNKSIZE ) * - sizeof( z2ram_map[0] ); + sizeof( z2ram_map[0] ); device = DEVICE_NR( inode->i_rdev ); if ( current_device != -1 && current_device != device ) { - return -EBUSY; + return -EBUSY; } if ( current_device == -1 ) { - z2_count = 0; - chip_count = 0; - z2ram_size = 0; - - switch ( device ) - { - case Z2MINOR_COMBINED: - - z2ram_map = kmalloc( max_z2_map + max_chip_map, GFP_KERNEL ); - if ( z2ram_map == NULL ) - { - printk( KERN_ERR DEVICE_NAME - ": cannot get mem for z2ram_map\n" ); - return -ENOMEM; - } - - get_z2ram(); - get_chipram(); - - if ( z2ram_size != 0 ) - printk( KERN_INFO DEVICE_NAME - ": using %iK Zorro II RAM and %iK Chip RAM (Total %dK)\n", - z2_count * Z2RAM_CHUNK1024, - chip_count * Z2RAM_CHUNK1024, - ( z2_count + chip_count ) * Z2RAM_CHUNK1024 ); - - break; + z2_count = 0; + chip_count = 0; + z2ram_size = 0; + + switch ( device ) + { + case Z2MINOR_COMBINED: + + z2ram_map = kmalloc( max_z2_map + max_chip_map, GFP_KERNEL ); + if ( z2ram_map == NULL ) + { + printk( KERN_ERR DEVICE_NAME + ": cannot get mem for z2ram_map\n" ); + return -ENOMEM; + } + + get_z2ram(); + get_chipram(); + + if ( z2ram_size != 0 ) + printk( KERN_INFO DEVICE_NAME + ": using %iK Zorro II RAM and %iK Chip RAM (Total %dK)\n", + z2_count * Z2RAM_CHUNK1024, + chip_count * Z2RAM_CHUNK1024, + ( z2_count + chip_count ) * Z2RAM_CHUNK1024 ); + + break; case Z2MINOR_Z2ONLY: - z2ram_map = kmalloc( max_z2_map, GFP_KERNEL ); - if ( z2ram_map == NULL ) - { - printk( KERN_ERR DEVICE_NAME - ": cannot get mem for z2ram_map\n" ); - return -ENOMEM; - } - - get_z2ram(); - - if ( z2ram_size != 0 ) - printk( KERN_INFO DEVICE_NAME - ": using %iK of Zorro II RAM\n", - z2_count * Z2RAM_CHUNK1024 ); - - break; - - case Z2MINOR_CHIPONLY: - z2ram_map = kmalloc( max_chip_map, GFP_KERNEL ); - if ( z2ram_map == NULL ) - { - printk( KERN_ERR DEVICE_NAME - ": cannot get mem for z2ram_map\n" ); - return -ENOMEM; - } - - get_chipram(); - - if ( z2ram_size != 0 ) - printk( KERN_INFO DEVICE_NAME - ": using %iK Chip RAM\n", - chip_count * Z2RAM_CHUNK1024 ); - - break; - - default: - return -ENODEV; - } - - if ( z2ram_size == 0 ) - { - kfree( z2ram_map ); - printk( KERN_NOTICE DEVICE_NAME - ": no unused ZII/Chip RAM found\n" ); - return -ENOMEM; - } - - current_device = device; - z2ram_size <<= Z2RAM_CHUNKSHIFT; - z2_sizes[ device ] = z2ram_size >> 10; - blk_size[ MAJOR_NR ] = z2_sizes; + z2ram_map = kmalloc( max_z2_map, GFP_KERNEL ); + if ( z2ram_map == NULL ) + { + printk( KERN_ERR DEVICE_NAME + ": cannot get mem for z2ram_map\n" ); + return -ENOMEM; + } + + get_z2ram(); + + if ( z2ram_size != 0 ) + printk( KERN_INFO DEVICE_NAME + ": using %iK of Zorro II RAM\n", + z2_count * Z2RAM_CHUNK1024 ); + + break; + + case Z2MINOR_CHIPONLY: + z2ram_map = kmalloc( max_chip_map, GFP_KERNEL ); + if ( z2ram_map == NULL ) + { + printk( KERN_ERR DEVICE_NAME + ": cannot get mem for z2ram_map\n" ); + return -ENOMEM; + } + + get_chipram(); + + if ( z2ram_size != 0 ) + printk( KERN_INFO DEVICE_NAME + ": using %iK Chip RAM\n", + chip_count * Z2RAM_CHUNK1024 ); + + break; + + default: + return -ENODEV; + } + + if ( z2ram_size == 0 ) + { + kfree( z2ram_map ); + printk( KERN_NOTICE DEVICE_NAME + ": no unused ZII/Chip RAM found\n" ); + return -ENOMEM; + } + + current_device = device; + z2ram_size <<= Z2RAM_CHUNKSHIFT; + z2_sizes[ device ] = z2ram_size >> 10; + blk_size[ MAJOR_NR ] = z2_sizes; } #if defined(MODULE) @@ -258,7 +258,7 @@ z2_release( struct inode *inode, struct file *filp ) { if ( current_device == -1 ) - return; + return; sync_dev( inode->i_rdev ); @@ -271,16 +271,17 @@ z2_release( struct inode *inode, struct file *filp ) static struct file_operations z2_fops = { - NULL, /* lseek - default */ - block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ - NULL, /* readdir - bad */ - NULL, /* poll */ - NULL, /* ioctl */ - NULL, /* mmap */ - z2_open, /* open */ - z2_release, /* release */ - block_fsync /* fsync */ + NULL, /* lseek - default */ + block_read, /* read - general block-dev read */ + block_write, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + z2_open, /* open */ + NULL, /* flush */ + z2_release, /* release */ + block_fsync /* fsync */ }; __initfunc(int @@ -288,13 +289,13 @@ z2_init( void )) { if ( !MACH_IS_AMIGA ) - return -ENXIO; + return -ENXIO; if ( register_blkdev( MAJOR_NR, DEVICE_NAME, &z2_fops ) ) { - printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n", - MAJOR_NR ); - return -EBUSY; + printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n", + MAJOR_NR ); + return -EBUSY; } blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST; @@ -313,7 +314,7 @@ init_module( void ) error = z2_init(); if ( error == 0 ) { - printk( KERN_INFO DEVICE_NAME ": loaded as module\n" ); + printk( KERN_INFO DEVICE_NAME ": loaded as module\n" ); } return error; @@ -325,29 +326,29 @@ cleanup_module( void ) int i, j; if ( unregister_blkdev( MAJOR_NR, DEVICE_NAME ) != 0 ) - printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n"); + printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n"); if ( current_device != -1 ) { - i = 0; - - for ( j = 0 ; j < z2_count; j++ ) - { - set_bit( i++, zorro_unused_z2ram ); - } - - for ( j = 0 ; j < chip_count; j++ ) - { - if ( z2ram_map[ i ] ) - { - amiga_chip_free( (void *) z2ram_map[ i++ ] ); - } - } - - if ( z2ram_map != NULL ) - { - kfree( z2ram_map ); - } + i = 0; + + for ( j = 0 ; j < z2_count; j++ ) + { + set_bit( i++, zorro_unused_z2ram ); + } + + for ( j = 0 ; j < chip_count; j++ ) + { + if ( z2ram_map[ i ] ) + { + amiga_chip_free( (void *) z2ram_map[ i++ ] ); + } + } + + if ( z2ram_map != NULL ) + { + kfree( z2ram_map ); + } } return; diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile index 00cb2cda2..025b25a7a 100644 --- a/drivers/cdrom/Makefile +++ b/drivers/cdrom/Makefile @@ -25,6 +25,7 @@ obj- := obj-$(CONFIG_BLK_DEV_IDECD) += cdrom.o obj-$(CONFIG_BLK_DEV_SR) += cdrom.o +obj-$(CONFIG_PARIDE_PCD) += cdrom.o obj-$(CONFIG_AZTCD) += aztcd.o obj-$(CONFIG_CDU31A) += cdu31a.o cdrom.o diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c index 0d8848fdc..0342a5381 100644 --- a/drivers/cdrom/aztcd.c +++ b/drivers/cdrom/aztcd.c @@ -379,6 +379,7 @@ static struct file_operations azt_fops = { aztcd_ioctl, /* ioctl */ NULL, /* mmap */ aztcd_open, /* open */ + NULL, /* flush */ aztcd_release, /* release */ NULL, /* fsync */ NULL, /* fasync*/ diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index a2806b858..af5fb7021 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -184,6 +184,7 @@ struct file_operations cdrom_fops = cdrom_ioctl, /* ioctl */ NULL, /* mmap */ cdrom_open, /* open */ + NULL, /* flush */ cdrom_release, /* release */ NULL, /* fsync */ NULL, /* fasync */ @@ -1081,10 +1082,12 @@ static void cdrom_sysctl_register(void) initialized = 1; } +#ifdef MODULE static void cdrom_sysctl_unregister(void) { unregister_sysctl_table(cdrom_sysctl_header); } +#endif /* endif MODULE */ #endif /* endif CONFIG_SYSCTL */ #ifdef MODULE diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c index 3fad59c73..ea3f9093c 100644 --- a/drivers/cdrom/gscd.c +++ b/drivers/cdrom/gscd.c @@ -160,6 +160,7 @@ static struct file_operations gscd_fops = { gscd_ioctl, /* ioctl */ NULL, /* mmap */ gscd_open, /* open */ + NULL, /* flush */ gscd_release, /* release */ NULL, /* fsync */ NULL, /* fasync*/ diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c index eae60ad3c..76103945b 100644 --- a/drivers/cdrom/optcd.c +++ b/drivers/cdrom/optcd.c @@ -2008,6 +2008,7 @@ static struct file_operations opt_fops = { opt_ioctl, /* ioctl */ NULL, /* mmap */ opt_open, /* open */ + NULL, /* flush */ opt_release, /* release */ NULL, /* fsync */ NULL, /* fasync */ diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 428964d8f..11b99e645 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -4540,7 +4540,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, /* resume playing audio tracks when a previous PLAY AUDIO call has */ /* been paused with a PAUSE command. */ /* It will resume playing from the location saved in SubQ_run_tot. */ - if (D_S[d].audio_state!=audio_pausing) return -EINVAL; + if (D_S[d].audio_state!=audio_pausing) RETURN_UP(-EINVAL); if (famL_drive) i=cc_PlayAudio(D_S[d].pos_audio_start, D_S[d].pos_audio_end); @@ -4654,7 +4654,9 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, #endif SAFE_MIXED i=cc_Pause_Resume(1); D_S[d].audio_state=0; +#if 0 cc_DriveReset(); +#endif RETURN_UP(i); case CDROMSTART: /* Spin up the drive */ @@ -4676,7 +4678,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, case CDROMVOLREAD: /* read Volume settings from drive */ msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); st=cc_GetVolume(); - if (st<0) return (st); + if (st<0) RETURN_UP(st); volctrl.channel0=D_S[d].vol_ctrl0; volctrl.channel1=D_S[d].vol_ctrl1; volctrl.channel2=0; diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c index dc6e243f1..6681f2a19 100644 --- a/drivers/cdrom/sjcd.c +++ b/drivers/cdrom/sjcd.c @@ -1429,6 +1429,7 @@ static struct file_operations sjcd_fops = { sjcd_ioctl, /* ioctl */ NULL, /* mmap */ sjcd_open, /* open */ + NULL, /* flush */ sjcd_release, /* release */ NULL, /* fsync */ NULL, /* fasync */ diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c index 52e64890e..aaad43c96 100644 --- a/drivers/cdrom/sonycd535.c +++ b/drivers/cdrom/sonycd535.c @@ -1469,16 +1469,17 @@ static struct file_operations cdu_fops = { NULL, /* lseek - default */ block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ + block_write, /* write - general block-dev write */ NULL, /* readdir - bad */ NULL, /* poll */ cdu_ioctl, /* ioctl */ NULL, /* mmap */ cdu_open, /* open */ - cdu_release, /* release */ + NULL, /* flush */ + cdu_release, /* release */ NULL, /* fsync */ NULL, /* fasync */ - cdu535_check_media_change, /* check media change */ + cdu535_check_media_change, /* check media change */ NULL /* revalidate */ }; diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 407238f40..8ee33b612 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -113,10 +113,15 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then hex ' RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f fi + dep_tristate 'AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV + if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then + hex ' RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c + fi dep_tristate 'Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then hex ' Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350 fi + dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV if [ "$CONFIG_PARPORT" != "n" ]; then dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV diff --git a/drivers/char/Makefile b/drivers/char/Makefile index baa7c859a..e8424737f 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -407,6 +407,14 @@ else endif endif +ifeq ($(CONFIG_RADIO_MIROPCM20),y) +L_OBJS += radio-miropcm20.o +else + ifeq ($(CONFIG_RADIO_MIROPCM20),m) + M_OBJS += radio-miropcm20.o + endif +endif + ifeq ($(CONFIG_QIC02_TAPE),y) L_OBJS += tpqic02.o else diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c index 153cb9ad7..a9aa76714 100644 --- a/drivers/char/acquirewdt.c +++ b/drivers/char/acquirewdt.c @@ -174,6 +174,7 @@ static struct file_operations acq_fops = { acq_ioctl, NULL, /* No mmap */ acq_open, + NULL, /* flush */ acq_close }; diff --git a/drivers/char/adbmouse.c b/drivers/char/adbmouse.c index 2703baac0..43930ff1b 100644 --- a/drivers/char/adbmouse.c +++ b/drivers/char/adbmouse.c @@ -236,6 +236,7 @@ struct file_operations adb_mouse_fops = { NULL, /* mouse_ioctl */ NULL, /* mouse_mmap */ open_mouse, + NULL, /* flush */ release_mouse, NULL, fasync_mouse, diff --git a/drivers/char/amigamouse.c b/drivers/char/amigamouse.c index 45eaa0a73..e62ea5753 100644 --- a/drivers/char/amigamouse.c +++ b/drivers/char/amigamouse.c @@ -299,6 +299,7 @@ struct file_operations amiga_mouse_fops = { NULL, /* mouse_ioctl */ NULL, /* mouse_mmap */ open_mouse, + NULL, /* flush */ release_mouse, NULL, fasync_mouse, diff --git a/drivers/char/apm_bios.c b/drivers/char/apm_bios.c index e9e964c43..32f109be3 100644 --- a/drivers/char/apm_bios.c +++ b/drivers/char/apm_bios.c @@ -401,6 +401,7 @@ static struct file_operations apm_bios_fops = { do_ioctl, NULL, /* mmap */ do_open, + NULL, /* flush */ do_release, NULL, /* fsync */ NULL /* fasync */ diff --git a/drivers/char/atarimouse.c b/drivers/char/atarimouse.c index 683d6de80..33d71d376 100644 --- a/drivers/char/atarimouse.c +++ b/drivers/char/atarimouse.c @@ -149,6 +149,7 @@ struct file_operations atari_mouse_fops = { NULL, /* mouse_ioctl */ NULL, /* mouse_mmap */ open_mouse, + NULL, /* flush */ release_mouse, NULL, fasync_mouse, diff --git a/drivers/char/atixlmouse.c b/drivers/char/atixlmouse.c index 4a25dc4b1..52ce4bf67 100644 --- a/drivers/char/atixlmouse.c +++ b/drivers/char/atixlmouse.c @@ -191,6 +191,7 @@ struct file_operations atixl_busmouse_fops = { NULL, /* mouse_ioctl */ NULL, /* mouse_mmap */ open_mouse, + NULL, /* flush */ release_mouse, NULL, fasync_mouse, diff --git a/drivers/char/bt848.h b/drivers/char/bt848.h index 79ea691c2..5227ef712 100644 --- a/drivers/char/bt848.h +++ b/drivers/char/bt848.h @@ -30,6 +30,12 @@ #ifndef PCI_DEVICE_ID_BT849 #define PCI_DEVICE_ID_BT849 0x351 #endif +#ifndef PCI_DEVICE_ID_BT878 +#define PCI_DEVICE_ID_BT878 0x36e +#endif +#ifndef PCI_DEVICE_ID_BT879 +#define PCI_DEVICE_ID_BT879 0x36f +#endif /* Brooktree 848 registers */ @@ -286,10 +292,6 @@ #define BT848_RISC_COUNT 0x120 #define BT848_GPIO_DATA 0x200 -/* Bt878 register */ - -#define BT878_DEVCTRL 0x40 -#define BT878_NTBF 0x02 /* Bt848 RISC commands */ @@ -340,7 +342,14 @@ #define BT848_FCAP 0x0E8 #define BT848_PLL_F_LO 0x0F0 #define BT848_PLL_F_HI 0x0F4 + #define BT848_PLL_XCI 0x0F8 +#define BT848_PLL_X (1<<7) +#define BT848_PLL_C (1<<6) + +/* Bt878 register */ +#define BT878_DEVCTRL 0x40 +#define BT878_EN_TBFX 0x02 #endif diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index 58d8fadc1..9f7975439 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -65,18 +65,12 @@ #define DEBUG(x) /* Debug driver */ #define IDEBUG(x) /* Debug interrupt handler */ -static unsigned int remap=0; /* remap Bt848 */ -static unsigned int vidmem=0; /* manually set video mem address */ -static int triton1=0; -static int radio=0; - -static unsigned int card=0; - -MODULE_PARM(remap,"i"); MODULE_PARM(vidmem,"i"); MODULE_PARM(triton1,"i"); -MODULE_PARM(radio,"i"); -MODULE_PARM(card,"i"); +MODULE_PARM(remap,"1-4i"); +MODULE_PARM(radio,"1-4i"); +MODULE_PARM(card,"1-4i"); +MODULE_PARM(pll,"1-4i"); static int find_vga(void); static void bt848_set_risc_jmps(struct bttv *btv); @@ -84,12 +78,19 @@ static void bt848_set_risc_jmps(struct bttv *btv); /* Anybody who uses more than four? */ #define BTTV_MAX 4 +static unsigned int vidmem=0; /* manually set video mem address */ +static int triton1=0; + +static unsigned int remap[BTTV_MAX]; /* remap Bt848 */ +static unsigned int radio[BTTV_MAX]; +static unsigned int card[BTTV_MAX] = { 0, 0, + 0, 0 }; +static unsigned int pll[BTTV_MAX] = { 0, 0, 0, 0 }; + static int bttv_num; /* number of Bt848s in use */ static struct bttv bttvs[BTTV_MAX]; #define I2C_TIMING (0x7<<4) -#define I2C_COMMAND (I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA) - #define I2C_DELAY 10 #define I2C_SET(CTRL,DATA) \ { btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); } @@ -128,10 +129,6 @@ static inline unsigned long uvirt_to_phys(unsigned long adr) static inline unsigned long uvirt_to_bus(unsigned long adr) { - /* printk("adr: 0x%8x, ",adr); - printk("phys: 0x%8x, ",(uvirt_to_phys(adr))); - printk("bus: 0x%8x\n",virt_to_bus(phys_to_virt(uvirt_to_phys(adr)))); - */ return virt_to_bus(phys_to_virt(uvirt_to_phys(adr))); } @@ -199,7 +196,8 @@ static int fbuffer_alloc(struct bttv *btv) if(!btv->fbuffer) btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF); else - printk(KERN_ERR "bttv: Double alloc of fbuffer!\n"); + printk(KERN_ERR "bttv%d: Double alloc of fbuffer!\n", + btv->nr); if(!btv->fbuffer) return -ENOBUFS; return 0; @@ -236,7 +234,7 @@ static int I2CRead(struct i2c_bus *bus, unsigned char addr) /* clear status bit ; BT848_INT_RACK is ro */ btwrite(BT848_INT_I2CDONE, BT848_INT_STAT); - btwrite(((addr & 0xff) << 24) | I2C_COMMAND, BT848_I2C); + btwrite(((addr & 0xff) << 24) | btv->i2c_command, BT848_I2C); /* * Timeout for I2CRead is 1 second (this should be enough, really!) @@ -251,7 +249,8 @@ static int I2CRead(struct i2c_bus *bus, unsigned char addr) if (!i) { - printk(KERN_DEBUG "bttv: I2CRead timeout\n"); + printk(KERN_DEBUG "bttv%d: I2CRead timeout\n", + btv->nr); return -1; } if (!(stat & BT848_INT_RACK)) @@ -274,7 +273,7 @@ static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1, /* clear status bit; BT848_INT_RACK is ro */ btwrite(BT848_INT_I2CDONE, BT848_INT_STAT); - data=((addr & 0xff) << 24) | ((b1 & 0xff) << 16) | I2C_COMMAND; + data=((addr & 0xff) << 24) | ((b1 & 0xff) << 16) | btv->i2c_command; if (both) { data|=((b2 & 0xff) << 8); @@ -293,7 +292,8 @@ static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1, if (!i) { - printk(KERN_DEBUG "bttv: I2CWrite timeout\n"); + printk(KERN_DEBUG "bttv%d: I2CWrite timeout\n", + btv->nr); return -1; } if (!(stat & BT848_INT_RACK)) @@ -356,9 +356,10 @@ void attach_inform(struct i2c_bus *bus, int id) if (btv->tuner_type != -1) { tunertype=btv->tuner_type; - i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER, - TUNER_SET_TYPE,&tunertype); - } + i2c_control_device(&(btv->i2c), + I2C_DRIVERID_TUNER, + TUNER_SET_TYPE,&tunertype); + } break; } } @@ -406,6 +407,7 @@ struct tvcard u32 gpiomask; u32 muxsel[8]; u32 audiomux[6]; /* Tuner, Radio, internal, external, mute, stereo */ + u32 gpiomask2; /* GPIO MUX mask */ }; static struct tvcard tvcards[] = @@ -423,12 +425,14 @@ static struct tvcard tvcards[] = /* Diamond DTV2000 */ { 3, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}}, /* AVerMedia TVPhone */ - { 3, 0, 2,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}}, + { 3, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}}, /* Matrix Vision MV-Delta */ - { 5,-1, 4, 0, { 2, 3, 1, 0, 0}}, + { 5,-1, 3, 0, { 2, 3, 1, 0, 0}}, /* Fly Video II */ { 3, 0, 2, 0xc00, { 2, 3, 1, 1}, {0, 0xc00, 0x800, 0x400, 0xc00, 0}}, + /* TurboTV */ + { 3, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}}, }; #define TVCARDS (sizeof(tvcards)/sizeof(tvcard)) @@ -503,12 +507,46 @@ static void bt848_cap(struct bttv *btv, uint state) /* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC*/ +/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C + PLL_X = Reference pre-divider (0=1, 1=2) + PLL_C = Post divider (0=6, 1=4) + PLL_I = Integer input + PLL_F = Fractional input + + F_input = 28.636363 MHz: + PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0 +*/ + +static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout) +{ + unsigned char fl, fh, fi; + + /* prevent overflows */ + fin/=4; + fout/=4; + + fout*=12; + fi=fout/fin; + + fout=(fout-fin*fi)*256; + fh=fout/fin; + + fout=(fout-fin*fh)*256; + fl=fout/fin; + + /*printk("0x%02x 0x%02x 0x%02x\n", fi, fh, fl);*/ + btwrite(fl,BT848_PLL_F_LO); + btwrite(fh,BT848_PLL_F_HI); + btwrite(fi|BT848_PLL_X,BT848_PLL_XCI); +} + static int set_pll(struct bttv *btv) { int i; + unsigned long tv; - if (!btv->pll) - return 0; + if (!btv->pll) + return 0; if ((btread(BT848_IFORM)&BT848_IFORM_XT0)) { /* printk ("switching PLL off\n");*/ @@ -524,13 +562,24 @@ static int set_pll(struct bttv *btv) /* printk ("setting PLL for PAL/SECAM\n");*/ + set_pll_freq(btv, 28636363, 35468950); +/* btwrite(0x00,BT848_TGCTRL); btwrite(0xf9,BT848_PLL_F_LO); btwrite(0xdc,BT848_PLL_F_HI); - btwrite(0x8e,BT848_PLL_XCI); + btwrite(14|BT848_PLL_X,BT848_PLL_XCI); +*/ + /* + * Let other people run while the PLL stabilizes + */ + + tv=jiffies+HZ/10; /* .1 seconds */ + do + { + schedule(); + } + while(time_before(jiffies,tv)); - /* Ugh ugh ugh .. schedule ? */ - udelay(100000); for (i=0; i<100; i++) { if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK)) @@ -548,7 +597,8 @@ static int set_pll(struct bttv *btv) static void bt848_muxsel(struct bttv *btv, unsigned int input) { - btwrite(tvcards[btv->type].gpiomask, BT848_GPIO_OUT_EN); + btaor(tvcards[btv->type].gpiomask2,~tvcards[btv->type].gpiomask2, + BT848_GPIO_OUT_EN); /* This seems to get rid of some synchronization problems */ btand(~(3<<5), BT848_IFORM); @@ -569,23 +619,7 @@ static void bt848_muxsel(struct bttv *btv, unsigned int input) audio(btv, (input!=tvcards[btv->type].tuner) ? AUDIO_EXTERN : AUDIO_TUNER); btaor(tvcards[btv->type].muxsel[input]>>4, - ~tvcards[btv->type].gpiomask, BT848_GPIO_DATA); -#if 0 - if (input==3) - { - btor(BT848_CONTROL_COMP, BT848_E_CONTROL); - btor(BT848_CONTROL_COMP, BT848_O_CONTROL); - } - else - { - btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); - btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); - } - if (input==2) - input=3; - btaor(((input+2)&3)<<5, ~(3<<5), BT848_IFORM); - audio(btv, input ? AUDIO_EXTERN : AUDIO_TUNER); -#endif + ~tvcards[btv->type].gpiomask2, BT848_GPIO_DATA); } @@ -645,27 +679,28 @@ int palette2fmt[] = { BT848_COLOR_FMT_RGB15, BT848_COLOR_FMT_YUY2, BT848_COLOR_FMT_BtYUV, - -1, - -1, - -1, + 0, + 0, + 0, BT848_COLOR_FMT_RAW, BT848_COLOR_FMT_YCrCb422, BT848_COLOR_FMT_YCrCb411, }; #define PALETTEFMT_MAX 11 -static int make_rawrisctab(struct bttv *btv, unsigned int *ro, +static int make_rawrisctab(struct bttv *btv, unsigned int *ro, unsigned int *re, unsigned int *vbuf) { unsigned long line; - unsigned long bpl=1024; + unsigned long bpl=1024; /* bytes per line */ unsigned long vadr=(unsigned long) vbuf; *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0; *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0; /* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY - is 2. We'll have to handle this inside the IRQ handler ... */ + is 2 and without separate VBI grabbing. + We'll have to handle this inside the IRQ handler ... */ for (line=0; line < 640; line++) { @@ -802,6 +837,152 @@ static inline void write_risc_segment(unsigned int **rp, unsigned long line_adr, *x+=dx; } +static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr) +{ + int i,t; + int yy, y, x, dx; + struct video_clip first, *cur, *cur2, *nx, first2, *prev, *nx2; + int bpp, bpl, width, height, inter; + unsigned int **rp,*ro,*re; + unsigned long adr; + int cx,cx2,cy,cy2; + + inter=(btv->win.interlace&1)^1; + bpp=btv->win.bpp; + bpl=btv->win.bpl; + ro=btv->risc_odd; + re=btv->risc_even; + width=btv->win.width; + height=btv->win.height; + adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl; + + /* clip clipping rects against viewing window AND screen + so we do not have to rely on the user program + */ + cx=(btv->win.x<0) ? (-btv->win.x) : 0; + cy=(btv->win.y<0) ? (-btv->win.y) : 0; + cx2=(btv->win.x+width>btv->win.swidth) ? + (btv->win.swidth-btv->win.x) : width; + cy2=(btv->win.y+height>btv->win.sheight) ? + (btv->win.sheight-btv->win.y) : height; + first.next=NULL; + for (i=0; i0) + { + if (cr[i].height<=t) + continue; + cr[i].height-=t; + cr[i].y=cy; + } + if ((t=cy2-cr[i].y)0) + { + if (cr[i].width<=t) + continue; + cr[i].width-=t; + cr[i].x=cx; + } + if ((t=cx2-cr[i].x)next) && (cr[i].y > cur->next->y)) + cur=nx; + cur->next=&(cr[i]); + cr[i].next=nx; + } + first2.next=NULL; + + *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0; + *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0; + + /* loop through all lines */ + for (yy=0; yy<(height<>inter; + rp= (yy&1) ? &re : &ro; + + /* remove rects with y2 > y */ + if ((cur=first2.next)) + { + prev=&first2; + do + { + if (cur->y+cur->height <= y) + prev->next=cur->next; + else + prev=cur; + } + while ((cur=cur->next)); + } + + /* add rect to second (x-sorted) list if rect.y == y */ + if ((cur=first.next)) + { + while ((cur) && (cur->y == y)) + { + first.next=cur->next; + cur2=&first2; + while ((nx2=cur2->next) && (cur->x > cur2->next->x)) + cur2=nx2; + cur2->next=cur; + cur->next=nx2; + cur=first.next; + } + } + x=0; + if ((btv->win.y+y<=0)||(btv->win.y+y>=btv->win.sheight)) + write_risc_segment(rp, adr, BT848_RISC_SKIP, &x, + width, bpp, width); + else + { + dx=cx; + for (cur2=first2.next; cur2; cur2=cur2->next) + { + if (x+dx < cur2->x) + { + write_risc_segment(rp, adr, BT848_RISC_SKIP, + &x, dx, bpp, width); + dx=cur2->x-x; + write_risc_segment(rp, adr, BT848_RISC_WRITEC, + &x, dx, bpp, width); + dx=cur2->width; + } + else if (x+dx < cur2->x+cur2->width) + dx=cur2->x+cur2->width-x; + } + if (cx2bus_vbi_even; + *(re++)=BT848_RISC_JUMP; + *(re++)=btv->bus_vbi_odd; +} + /* * Set the registers for the size we have specified. Don't bother @@ -814,36 +995,50 @@ static inline void write_risc_segment(unsigned int **rp, unsigned long line_adr, struct tvnorm { - u16 cropwidth, cropheight; + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ u16 totalwidth; u8 adelay, bdelay, iform; u32 scaledtwidth; u16 hdelayx1, hactivex1; - u16 vdelay; + u16 vdelay, fporch; }; static struct tvnorm tvnorms[] = { /* PAL-BDGHI */ - { 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), - 944, 186, 922, 0x20}, + /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ + { 35468950, + 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), + 1135, 186, 924, 0x20}, +/* + { 35468950, + 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), + 944, 186, 922, 0x20}, +*/ /* NTSC */ - { 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0), - 780, 135, 754, 0x16}, + { 28636363, + 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0), + 780, 135, 754, 0x1a}, /* SECAM */ - { 768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1), - 944, 186, 922, 0x20}, + { 28636363, + 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0), + 780, 135, 754, 0x16}, /* PAL-M */ - { 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0), - 780, 135, 754, 0x16}, + { 28636363, + 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0), + 780, 135, 754, 0x16}, /* PAL-N */ - { 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1), - 944, 186, 922, 0x20}, + { 35468950, + 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1), + 944, 186, 922, 0x20}, /* PAL-NC */ - { 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0), - 944, 186, 922, 0x20}, + { 35468950, + 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0), + 944, 186, 922, 0x20}, /* NTSC-Japan */ - { 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0), - 780, 135, 754, 0x16}, + { 28636363, + 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0), + 780, 135, 754, 0x16}, }; #define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) @@ -891,6 +1086,10 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt) tvn=&tvnorms[btv->win.norm]; + btv->win.cropheight=tvn->sheight; + btv->win.cropwidth=tvn->swidth; + +/* if (btv->win.cropwidth>tvn->cropwidth) btv->win.cropwidth=tvn->cropwidth; if (btv->win.cropheight>tvn->cropheight) @@ -900,7 +1099,7 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt) width=btv->win.cropwidth; if (height>btv->win.cropheight) height=btv->win.cropheight; - +*/ btwrite(tvn->adelay, BT848_ADELAY); btwrite(tvn->bdelay, BT848_BDELAY); btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM); @@ -916,12 +1115,13 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt) btv->win.interlace = (height>btv->win.cropheight/2) ? 1 : 0; inter=(btv->win.interlace&1)^1; + vdelay=btv->win.cropy+tvn->vdelay; + xsf = (hactive*tvn->scaledtwidth)/btv->win.cropwidth; hscale = ((tvn->totalwidth*4096UL)/xsf-4096); - vdelay=btv->win.cropy+tvn->vdelay; - hdelay=(tvn->hdelayx1*tvn->scaledtwidth)/tvn->totalwidth; - hdelay=((hdelay+btv->win.cropx)*hactive)/btv->win.cropwidth; + hdelay=tvn->hdelayx1+btv->win.cropx; + hdelay=(hdelay*hactive)/btv->win.cropwidth; hdelay&=0x3fe; sr=((btv->win.cropheight>>inter)*512)/height-512; @@ -948,22 +1148,23 @@ static void bt848_set_winsize(struct bttv *btv) { unsigned short format; - btv->win.color_fmt=format= (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 : - bpp2fmt[(btv->win.bpp-1)&3]; - + btv->win.color_fmt = format = + (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 : + bpp2fmt[(btv->win.bpp-1)&3]; + /* RGB8 seems to be a 9x5x5 GRB color cube starting at * color 16. Why the h... can't they even mention this in the * data sheet? [AC - because it's a standard format so I guess * it never occurred to them] * Enable dithering in this mode. */ -#if 0 + if (format==BT848_COLOR_FMT_RGB8) - btand(~0x10, BT848_CAP_CTL); + btand(~BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); else - btor(0x10, BT848_CAP_CTL); -#endif - bt848_set_geo(btv,btv->win.width, btv->win.height, format); + btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); + + bt848_set_geo(btv, btv->win.width, btv->win.height, format); } /* @@ -978,7 +1179,7 @@ static void set_freq(struct bttv *btv, unsigned short freq) audio(btv, AUDIO_MUTE); udelay(AUDIO_MUTE_DELAY); - if (btv->radio) + if (radio[btv->nr]) { if (btv->have_tuner) i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER, @@ -1027,7 +1228,7 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) if(fbuffer_alloc(btv)) return -ENOBUFS; } - if(btv->grabbing>1) + if(btv->grabbing >= MAX_GBUFFERS) return -ENOBUFS; /* @@ -1040,9 +1241,16 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) if(mp->height <0 || mp->width <0) return -EINVAL; +/* This doesn´t work like this for NTSC anyway. + So, better check the total image size ... +*/ +/* if(mp->height>576 || mp->width>768) return -EINVAL; - +*/ + if (mp->height*mp->width*fmtbppx2[mp->format&0x0f]/2>BTTV_MAX_FBUF) + return -EINVAL; + /* * FIXME: Check the format of the grab here. This is probably * also less restrictive than the normal overlay grabs. Stuff @@ -1055,27 +1263,31 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) vbuf=(unsigned int *)(btv->fbuffer+BTTV_MAX_FBUF*mp->frame); /* if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)) - return -EAGAIN; */ + return -EAGAIN;*/ ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0); re=ro+2048; btv->gwidth=mp->width; btv->gheight=mp->height; + if (mp->format > PALETTEFMT_MAX) return -EINVAL; btv->gfmt=palette2fmt[mp->format]; - if(btv->gfmt==-1) + if(btv->gfmt==0) return -EINVAL; make_vrisctab(btv, ro, re, vbuf, btv->gwidth, btv->gheight, btv->gfmt); /* bt848_set_risc_jmps(btv); */ btor(3, BT848_CAP_CTL); btor(3, BT848_GPIO_DMA_CTL); + btv->frame_stat[mp->frame] = GBUFFER_GRABBING; if (btv->grabbing) { btv->gro_next=virt_to_bus(ro); btv->gre_next=virt_to_bus(re); + btv->grf_next=mp->frame; } else { btv->gro=virt_to_bus(ro); btv->gre=virt_to_bus(re); + btv->grf=mp->frame; } if (!(btv->grabbing++)) btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ; @@ -1159,7 +1371,12 @@ static int bttv_open(struct video_device *dev, int flags) btv->user--; return -EINVAL; } - break; + btv->grabbing = 0; + btv->grab = 0; + btv->lastgrab = 0; + for (i = 0; i < MAX_GBUFFERS; i++) + btv->frame_stat[i] = GBUFFER_UNUSED; + break; case 1: break; } @@ -1227,265 +1444,6 @@ static inline void bt848_sat_v(struct bttv *btv, unsigned long data) btaor(datahi, ~1, BT848_O_CONTROL); } - -/* - * Cliprect -> risc table. - * - * FIXME: This is generating wrong code when we have some kinds of - * rectangle lists. If you generate overlapped rectangles then it - * gets a bit confused. Since we add the frame buffer clip rectangles - * we need to fix this. Better yet to rewrite this function. - */ - -static void write_risc_data(struct bttv *btv, struct video_clip *vp, int count) -{ - int i; - u32 yy, y, x, dx, ox; - u32 *rmem, *rmem2; - struct video_clip first, *cur, *cur2, *nx, first2, *prev, *nx2; - u32 *rp, rpo=0, rpe=0, p, bpsl; - u32 *rpp; - u32 mask; - int interlace; - int depth; - - rmem=(u32 *)btv->risc_odd; - rmem2=(u32 *)btv->risc_even; - depth=btv->win.bpp; - - /* create y-sorted list */ - - first.next=NULL; - for (i=0; inext) && (vp[i].y > cur->next->y)) - cur=nx; - cur->next=&(vp[i]); - vp[i].next=nx; - } - first2.next=NULL; - - rmem[rpo++]=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1|(0xf<<20); - rmem[rpo++]=0; - - rmem2[rpe++]=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; - rmem2[rpe++]=0; - - - /* - * 32bit depth frame buffers need extra flags setting - */ - - if (depth==4) - mask=BT848_RISC_BYTE3; - else - mask=0; - - bpsl=btv->win.width*btv->win.bpp; - p=btv->win.vidadr+btv->win.x*btv->win.bpp+ - btv->win.y*btv->win.bpl; - - interlace=btv->win.interlace; - - /* - * Loop through all lines - */ - - for (yy=0; yy<(btv->win.height<<(1^interlace)); yy++) - { - y=yy>>(1^interlace); - - /* - * Even or odd frame generation. We have to - * write the RISC instructions to the right stream. - */ - - if(!(y&1)) - { - rp=&rpo; - rpp=rmem; - } - else - { - rp=&rpe; - rpp=rmem2; - } - - - /* - * first2 is the header of a list of "active" rectangles. We add - * rectangles as we hit their top and remove them as they fall off - * the bottom - */ - - /* remove rects with y2 > y */ - if ((cur=first2.next)) - { - prev=&first2; - do - { - if (cur->y+cur->height < y) - prev->next=cur->next; - else - prev=cur; - } - while ((cur=cur->next)); - } - - /* - * Fixme - we have to handle overlapped rectangles - * here, but the overlap might be partial - */ - - /* add rect to second (x-sorted) list if rect.y == y */ - if ((cur=first.next)) - { - while ((cur) && (cur->y == y)) - { - first.next=cur->next; - cur2=&first2; - while ((nx2=cur2->next) && (cur->x > cur2->next->x)) - cur2=nx2; - cur2->next=cur; - cur->next=nx2; - cur=first.next; - } - } - - - /* - * Begin writing the RISC script - */ - - dx=x=0; - - /* - * Starting at x position 0 on a new scan line - * write to location p, don't yet write the number - * of pixels for the instruction - */ - - rpp[(*rp)++]=BT848_RISC_WRITE|BT848_RISC_SOL; - rpp[(*rp)++]=p; - - /* - * For each rectangle we have in the "active" list - sorted left to - * right.. - */ - - for (cur2=first2.next; cur2; cur2=cur2->next) - { - /* - * If we are to the left of the first drawing area - */ - - if (x+dx < cur2->x) - { - /* Bytes pending ? */ - if (dx) - { - /* For a delta away from the start we need to write a SKIP */ - if (x) - rpp[(*rp)++]=BT848_RISC_SKIP|(dx*depth); - else - /* Rewrite the start of line WRITE to a SKIP */ - rpp[(*rp)-2]|=BT848_RISC_BYTE_ALL|(dx*depth); - /* Move X to the next point (drawing start) */ - x=x+dx; - } - /* Ok how far are we from the start of the next rectangle ? */ - dx=cur2->x-x; - /* dx is now the size of data to write */ - - /* If this isnt the left edge generate a "write continue" */ - if (x) - rpp[(*rp)++]=BT848_RISC_WRITEC|(dx*depth)|mask; - else - /* Fill in the byte count on the initial WRITE */ - rpp[(*rp)-2]|=(dx*depth)|mask; - /* Move to the start of the rectangle */ - x=cur2->x; - /* x is our left dx is byte size of hole */ - dx=cur2->width+1; - } - else - /* Already in a clip zone.. set dx */ - if (x+dx < cur2->x+cur2->width) - dx=cur2->x+cur2->width-x+1; - } - /* now treat the rest of the line */ - ox=x; - if (dx) - { - /* Complete the SKIP to eat to the end of the gap */ - if (x) - rpp[(*rp)++]=BT848_RISC_SKIP|(dx*depth); - else - /* Rewrite to SKIP start to this point */ - rpp[(*rp)-2]|=BT848_RISC_BYTE_ALL|(dx*depth); - x=x+dx; - } - - /* - * Not at the right hand edge ? - */ - - if ((dx=btv->win.width-x)!=0) - { - /* Write to edge of display */ - if (x) - rpp[(*rp)++]=BT848_RISC_WRITEC|(dx*depth)|BT848_RISC_EOL|mask; - else - /* Entire frame is a write - patch first order */ - rpp[(*rp)-2]|=(dx*depth)|BT848_RISC_EOL|mask; - } - else - { - /* End of line if needed */ - if (ox) - rpp[(*rp)-1]|=BT848_RISC_EOL|mask; - else - { - /* Skip the line : write a SKIP + start/end of line marks */ - (*rp)--; - rpp[(*rp)-1]=BT848_RISC_SKIP| - (btv->win.width*depth)| - BT848_RISC_EOL|BT848_RISC_SOL; - } - } - /* - * Move the video render pointer on a line - */ - if (interlace||(y&1)) - p+=btv->win.bpl; - } - - /* - * Attach the interframe jumps - */ - - rmem[rpo++]=BT848_RISC_JUMP; - rmem[rpo++]=btv->bus_vbi_even; - - rmem2[rpe++]=BT848_RISC_JUMP; - rmem2[rpe++]=btv->bus_vbi_odd; -} - -/* - * Helper for adding clips. - */ - -static void new_risc_clip(struct video_window *vw, struct video_clip *vcp, int x, int y, int w, int h) -{ - vcp[vw->clipcount].x=x; - vcp[vw->clipcount].y=y; - vcp[vw->clipcount].width=w; - vcp[vw->clipcount].height=h; - vw->clipcount++; -} - - /* * ioctl routine */ @@ -1495,7 +1453,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) { unsigned char eedata[256]; struct bttv *btv=(struct bttv *)dev; - static int lastchan=0; + int i; switch (cmd) { @@ -1510,8 +1468,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) VID_TYPE_CLIPPING| VID_TYPE_FRAMERAM| VID_TYPE_SCALES; - b.channels = 4; /* tv , input, svhs */ - b.audios = 4; /* tv, input, svhs */ + b.channels = tvcards[btv->type].inputs; + b.audios = tvcards[btv->type].inputs; b.maxwidth = 768; b.maxheight = 576; b.minwidth = 32; @@ -1528,26 +1486,21 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.flags=VIDEO_VC_AUDIO; v.tuners=0; v.type=VIDEO_TYPE_CAMERA; - switch(v.channel) - { - case 0: - strcpy(v.name,"Television"); - v.flags|=VIDEO_VC_TUNER; - v.type=VIDEO_TYPE_TV; - v.tuners=1; - break; - case 1: - strcpy(v.name,"Composite1"); - break; - case 2: - strcpy(v.name,"Composite2"); - break; - case 3: - strcpy(v.name,"SVHS"); - break; - default: - return -EINVAL; - } + v.norm = btv->win.norm; + if (v.channel>=tvcards[btv->type].inputs) + return -EINVAL; + if(v.channel==tvcards[btv->type].tuner) + { + strcpy(v.name,"Television"); + v.flags|=VIDEO_VC_TUNER; + v.type=VIDEO_TYPE_TV; + v.tuners=1; + } + else if(v.channel==tvcards[btv->type].svhs) + strcpy(v.name,"SVHS"); + else + sprintf(v.name,"Composite%d",v.channel); + if(copy_to_user(arg,&v,sizeof(v))) return -EFAULT; return 0; @@ -1557,11 +1510,19 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) */ case VIDIOCSCHAN: { - int v; - if(copy_from_user(&v, arg, sizeof(v))) + struct video_channel v; + if(copy_from_user(&v, arg,sizeof(v))) return -EFAULT; - bt848_muxsel(btv, v); - lastchan=v; + + if (v.channel>tvcards[btv->type].inputs) + return -EINVAL; + bt848_muxsel(btv, v.channel); + if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC + &&v.norm!=VIDEO_MODE_SECAM) + return -EOPNOTSUPP; + btv->win.norm = v.norm; + bt848_set_winsize(btv); + btv->channel=v.channel; return 0; } case VIDIOCGTUNER: @@ -1569,7 +1530,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) struct video_tuner v; if(copy_from_user(&v,arg,sizeof(v))!=0) return -EFAULT; - if(v.tuner||lastchan) /* Only tuner 0 */ + if(v.tuner||btv->channel) /* Only tuner 0 */ return -EINVAL; strcpy(v.name, "Television"); v.rangelow=0; @@ -1581,23 +1542,22 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EFAULT; return 0; } - /* We have but tuner 0 */ + /* We have but one tuner */ case VIDIOCSTUNER: { struct video_tuner v; if(copy_from_user(&v, arg, sizeof(v))) return -EFAULT; - /* Only channel 0 has a tuner */ - if(v.tuner!=0 || lastchan) - return -EINVAL; + + /* Only one channel has a tuner */ + if(v.tuner!=tvcards[btv->type].tuner) + return -EINVAL; + if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC &&v.mode!=VIDEO_MODE_SECAM) return -EOPNOTSUPP; - /* FIXME: norm should be in video_channel struct - composite source can have different norms too - */ - btv->win.norm = v.mode; - bt848_set_winsize(btv); + btv->win.norm = v.mode; + bt848_set_winsize(btv); return 0; } case VIDIOCGPICT: @@ -1682,24 +1642,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -ENOMEM; if(vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) return -EFAULT; - /* - * Impose display clips - */ - if(btv->win.x<0) - new_risc_clip(&vw, vcp, 0, 0, -btv->win.x, btv->win.height-1); - if(btv->win.y<0) - new_risc_clip(&vw, vcp, 0, 0, btv->win.width-1,-btv->win.y); - if(btv->win.x+btv->win.width> btv->win.swidth) - new_risc_clip(&vw, vcp, btv->win.swidth-btv->win.x, 0, btv->win.width-1, btv->win.height-1); - if(btv->win.y+btv->win.height > btv->win.sheight) - new_risc_clip(&vw, vcp, 0, btv->win.sheight-btv->win.y, btv->win.width-1, btv->win.height-1); - /* - * Question: Do we need to walk the clip list - * and saw off any clips outside the window - * frame or will write_risc_tab do the right - * thing ? - */ - write_risc_data(btv,vcp, vw.clipcount); + make_clip_tab(btv,vcp, vw.clipcount); vfree(vcp); if(on && btv->win.vidadr!=0) bt848_cap(btv,1); @@ -1764,7 +1707,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) btv->win.vidadr=(unsigned long)v.base; btv->win.sheight=v.height; btv->win.swidth=v.width; - btv->win.bpp=((v.depth+1)&0x38)/8; + btv->win.bpp=((v.depth+7)&0x38)/8; btv->win.depth=v.depth; btv->win.bpl=v.bytesperline; @@ -1832,8 +1775,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EFAULT; if(v.flags&VIDEO_AUDIO_MUTE) audio(btv, AUDIO_MUTE); - /* One audio source per tuner */ - if(v.audio!=0) + /* One audio source per tuner */ + if(v.audio!=0) return -EINVAL; bt848_muxsel(btv,v.audio); if(!(v.flags&VIDEO_AUDIO_MUTE)) @@ -1858,12 +1801,19 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) } case VIDIOCSYNC: - if (!btv->grabbing) - return -EAGAIN; - if (btv->grab==btv->lastgrab) - interruptible_sleep_on(&btv->capq); - btv->lastgrab++; - return 0; + if(copy_from_user((void *)&i,arg,sizeof(int))) + return -EFAULT; + switch (btv->frame_stat[i]) { + case GBUFFER_UNUSED: + return -EINVAL; + case GBUFFER_GRABBING: + interruptible_sleep_on(&btv->capq); + /* fall */ + case GBUFFER_DONE: + btv->frame_stat[i] = GBUFFER_UNUSED; + break; + } + return 0; case BTTV_WRITEE: if(!capable(CAP_SYS_ADMIN)) @@ -1881,11 +1831,19 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EFAULT; break; + case BTTV_FIELDNR: + if(copy_to_user((void *) arg, (void *) &btv->last_field, + sizeof(btv->last_field))) + return -EFAULT; + break; + case VIDIOCMCAPTURE: { struct video_mmap vm; if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm))) return -EFAULT; + if (btv->frame_stat[vm.frame] == GBUFFER_GRABBING) + return -EBUSY; return vgrab(btv, &vm); } @@ -2127,21 +2085,34 @@ static long radio_read(struct video_device *v, char *buf, unsigned long count, i static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg) { struct bttv *btv=(struct bttv *)(dev-1); - static int lastchan=0; switch (cmd) { case VIDIOCGCAP: - /* XXX */ + { + struct video_capability v; + strcpy(v.name,btv->video_dev.name); + v.type = VID_TYPE_TUNER; + v.channels = 1; + v.audios = 1; + /* No we don't do pictures */ + v.maxwidth = 0; + v.maxheight = 0; + v.minwidth = 0; + v.minheight = 0; + if (copy_to_user(arg, &v, sizeof(v))) + return -EFAULT; + return 0; break; + } case VIDIOCGTUNER: { struct video_tuner v; if(copy_from_user(&v,arg,sizeof(v))!=0) return -EFAULT; - if(v.tuner||lastchan) /* Only tuner 0 */ + if(v.tuner||btv->channel) /* Only tuner 0 */ return -EINVAL; strcpy(v.name, "Radio"); v.rangelow=(int)(87.5*16); - v.rangehigh=(int)(108.0*16); + v.rangehigh=(int)(108*16); v.flags= 0; /* XXX */ v.mode = 0; /* XXX */ if(copy_to_user(arg,&v,sizeof(v))) @@ -2154,7 +2125,7 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg) if(copy_from_user(&v, arg, sizeof(v))) return -EFAULT; /* Only channel 0 has a tuner */ - if(v.tuner!=0 || lastchan) + if(v.tuner!=0 || btv->channel) return -EINVAL; /* XXX anything to do ??? */ return 0; @@ -2198,6 +2169,8 @@ struct vidbases }; static struct vidbases vbs[] = { + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215CT222, + "ATI MACH64 CT", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_210888GX, "ATI MACH64 Winturbo", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215GT, @@ -2214,8 +2187,12 @@ static struct vidbases vbs[] = { { PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1}, { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128, "Number Nine Imagine 128", PCI_BASE_ADDRESS_0}, + { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128_2, + "Number Nine Imagine 128 Series 2", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_S3, 0, "S3", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_TSENG, 0, "TSENG", PCI_BASE_ADDRESS_0}, + { PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128, + "Riva128", PCI_BASE_ADDRESS_1}, }; @@ -2409,13 +2386,16 @@ static void init_tda9850(struct i2c_bus *bus) /* Figure out card and tuner type */ -static void idcard(struct bttv *btv) +static void idcard(int i) { + struct bttv *btv = &bttvs[i]; + + int tunertype; btwrite(0, BT848_GPIO_OUT_EN); - DEBUG(printk(KERN_DEBUG "bttv: GPIO: 0x%08x\n", btread(BT848_GPIO_DATA))); + DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA))); /* Default the card to the user-selected one. */ - btv->type=card; + btv->type=card[i]; btv->tuner_type=-1; /* use default tuner type */ /* If we were asked to auto-detect, then do so! @@ -2440,13 +2420,13 @@ static void idcard(struct bttv *btv) if (I2CRead(&(btv->i2c), I2C_TDA9850) >=0) { btv->audio_chip = TDA9850; - printk(KERN_INFO "bttv: audio chip: TDA9850\n"); + printk(KERN_INFO "bttv%d: audio chip: TDA9850\n", i); } if (I2CRead(&(btv->i2c), I2C_TDA8425) >=0) { btv->audio_chip = TDA8425; - printk("bttv: audio chip: TDA8425\n"); + printk("bttv%d: audio chip: TDA8425\n", i); } switch(btv->audio_chip) @@ -2460,11 +2440,18 @@ static void idcard(struct bttv *btv) } /* How do I detect the tuner type for other cards but Miro ??? */ - printk(KERN_INFO "bttv: model: "); + printk(KERN_INFO "bttv%d: model: ", btv->nr); switch (btv->type) { case BTTV_MIRO: printk("MIRO\n"); + if (btv->have_tuner) + { + tunertype=((btread(BT848_GPIO_DATA)>>10)-1)&7; + i2c_control_device(&(btv->i2c), + I2C_DRIVERID_TUNER, + TUNER_SET_TYPE,&tunertype); + } strcpy(btv->video_dev.name,"BT848(Miro)"); break; case BTTV_HAUPPAUGE: @@ -2558,8 +2545,18 @@ static int init_bt848(int i) /* reset the bt848 */ btwrite(0, BT848_SRESET); - - DEBUG(printk(KERN_DEBUG "bttv: bt848_mem: 0x%08x\n",(unsigned int) btv->bt848_mem)); + DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%08x\n",i,(unsigned int) btv->bt848_mem)); + +#ifdef RESET_MSP_HAUPPAUGE + /* Reset the MSP on some Hauppauge cards */ + /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */ + /* Can this hurt cards without one? What about Miros with MSP? */ + btaor(32, ~32, BT848_GPIO_OUT_EN); + btaor(0, ~32, BT848_GPIO_DATA); + udelay(2500); + btaor(32, ~32, BT848_GPIO_DATA); + btaor(0, ~32, BT848_GPIO_OUT_EN); +#endif /* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */ @@ -2591,6 +2588,7 @@ static int init_bt848(int i) btv->grabcount=0; btv->grab=0; btv->lastgrab=0; + btv->field=btv->last_field=0; /* i2c */ memcpy(&(btv->i2c),&bttv_i2c_bus_template,sizeof(struct i2c_bus)); @@ -2642,8 +2640,8 @@ static int init_bt848(int i) btwrite(0xd8, BT848_CONTRAST_LO); bt848_bright(btv, 0x10); - btwrite(0x60, BT848_E_VSCALE_HI); - btwrite(0x60, BT848_O_VSCALE_HI); + btwrite(0x20, BT848_E_VSCALE_HI); + btwrite(0x20, BT848_O_VSCALE_HI); btwrite(/*BT848_ADC_SYNC_T|*/ BT848_ADC_RESERVED|BT848_ADC_CRUSH, BT848_ADC); @@ -2662,9 +2660,10 @@ static int init_bt848(int i) btwrite(0xfffffUL, BT848_INT_STAT); /* set interrupt mask */ - btwrite(triton1| -/* BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR| - BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/ + btwrite(btv->triton1| + /*BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR| + BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/ + BT848_INT_VSYNC| BT848_INT_SCERR| BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| BT848_INT_FMTCHG|BT848_INT_HLOCK, @@ -2680,7 +2679,7 @@ static int init_bt848(int i) memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template)); memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template)); memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template)); - idcard(btv); + idcard(i); if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0) return -1; @@ -2689,7 +2688,7 @@ static int init_bt848(int i) video_unregister_device(&btv->video_dev); return -1; } - if (radio) + if (radio[i]) { if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0) { @@ -2720,28 +2719,28 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) if (!astat) return; btwrite(astat,BT848_INT_STAT); - IDEBUG(printk ("bttv: astat %08x\n",astat)); - IDEBUG(printk ("bttv: stat %08x\n",stat)); + IDEBUG(printk ("bttv%d: astat %08x\n", btv->nr, astat)); + IDEBUG(printk ("bttv%d: stat %08x\n", btv->nr, stat)); /* get device status bits */ dstat=btread(BT848_DSTATUS); if (astat&BT848_INT_FMTCHG) { - IDEBUG(printk ("bttv: IRQ_FMTCHG\n")); + IDEBUG(printk ("bttv%d: IRQ_FMTCHG\n", btv->nr)); /*btv->win.norm&= (dstat&BT848_DSTATUS_NUML) ? (~1) : (~0); */ } if (astat&BT848_INT_VPRES) { - IDEBUG(printk ("bttv: IRQ_VPRES\n")); + IDEBUG(printk ("bttv%d: IRQ_VPRES\n", btv->nr)); } if (astat&BT848_INT_VSYNC) { - IDEBUG(printk ("bttv: IRQ_VSYNC\n")); + IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr)); } if (astat&BT848_INT_SCERR) { - IDEBUG(printk ("bttv: IRQ_SCERR\n")); + IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr)); bt848_dma(btv, 0); bt848_dma(btv, 1); wake_up_interruptible(&btv->vbiq); @@ -2750,7 +2749,7 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) } if (astat&BT848_INT_RISCI) { - IDEBUG(printk ("bttv: IRQ_RISCI\n")); + IDEBUG(printk ("bttv%d: IRQ_RISCI\n", btv->nr)); /* captured VBI frame */ if (stat&(1<<28)) @@ -2763,10 +2762,14 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) if (stat&(2<<28)) { wake_up_interruptible(&btv->capq); + btv->last_field=btv->field; + btv->grab++; + btv->frame_stat[btv->grf] = GBUFFER_DONE; if ((--btv->grabbing)) { btv->gro = btv->gro_next; btv->gre = btv->gre_next; + btv->grf = btv->grf_next; btv->risc_jmp[5]=btv->gro; btv->risc_jmp[11]=btv->gre; bt848_set_geo(btv, btv->gwidth, @@ -2792,31 +2795,31 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) } if (astat&BT848_INT_OCERR) { - IDEBUG(printk ("bttv: IRQ_OCERR\n")); + IDEBUG(printk ("bttv%d: IRQ_OCERR\n", btv->nr)); } if (astat&BT848_INT_PABORT) { - IDEBUG(printk ("bttv: IRQ_PABORT\n")); + IDEBUG(printk ("bttv%d: IRQ_PABORT\n", btv->nr)); } if (astat&BT848_INT_RIPERR) { - IDEBUG(printk ("bttv: IRQ_RIPERR\n")); + IDEBUG(printk ("bttv%d: IRQ_RIPERR\n", btv->nr)); } if (astat&BT848_INT_PPERR) { - IDEBUG(printk ("bttv: IRQ_PPERR\n")); + IDEBUG(printk ("bttv%d: IRQ_PPERR\n", btv->nr)); } if (astat&BT848_INT_FDSR) { - IDEBUG(printk ("bttv: IRQ_FDSR\n")); + IDEBUG(printk ("bttv%d: IRQ_FDSR\n", btv->nr)); } if (astat&BT848_INT_FTRGT) { - IDEBUG(printk ("bttv: IRQ_FTRGT\n")); + IDEBUG(printk ("bttv%d: IRQ_FTRGT\n", btv->nr)); } if (astat&BT848_INT_FBUS) { - IDEBUG(printk ("bttv: IRQ_FBUS\n")); + IDEBUG(printk ("bttv%d: IRQ_FBUS\n", btv->nr)); } if (astat&BT848_INT_HLOCK) { @@ -2832,12 +2835,12 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) count++; if (count > 10) - printk (KERN_WARNING "bttv: irq loop %d\n", count); + printk (KERN_WARNING "bttv%d: irq loop %d\n", btv->nr, count); if (count > 20) { btwrite(0, BT848_INT_MASK); printk(KERN_ERR - "bttv: IRQ lockup, cleared int mask\n"); + "bttv%d: IRQ lockup, cleared int mask\n", btv->nr); } } } @@ -2847,120 +2850,132 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) /* * Scan for a Bt848 card, request the irq and map the io memory */ - -static int find_bt848(void) + +int configure_bt848(struct pci_dev *dev, int bttv_num) { - unsigned char command, latency; int result; + unsigned char bus, devfn, command; struct bttv *btv; - struct pci_dev *dev; - bttv_num=0; + btv=&bttvs[bttv_num]; + btv->dev=dev; + btv->nr = bttv_num; + btv->bus=bus=dev->bus->number; + btv->devfn=devfn=dev->devfn; + btv->bt848_mem=NULL; + btv->vbibuf=NULL; + btv->risc_jmp=NULL; + btv->vbi_odd=NULL; + btv->vbi_even=NULL; + btv->vbiq=NULL; + btv->capq=NULL; + btv->capqo=NULL; + btv->capqe=NULL; + btv->vbip=VBIBUF_SIZE; + + btv->id=dev->device; + btv->irq=dev->irq; + btv->bt848_adr=dev->base_address[0]; + if (btv->id >= 878) + btv->i2c_command = 0x83; + else + btv->i2c_command=(I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA); + + if (remap[bttv_num]) + { + if (remap[bttv_num] < 0x1000) + remap[bttv_num]<<=20; + remap[bttv_num]&=PCI_BASE_ADDRESS_MEM_MASK; + printk(KERN_INFO "bttv%d: remapping to : 0x%08x.\n", + bttv_num,remap[bttv_num]); + remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, remap[bttv_num]); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &btv->bt848_adr); + btv->dev->base_address[0] = btv->bt848_adr; + } + btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK; + pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); + printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ", + bttv_num,btv->id, btv->revision); + printk("bus: %d, devfn: %d, ", + btv->bus, btv->devfn); + printk("irq: %d, ",btv->irq); + printk("memory: 0x%08x.\n", btv->bt848_adr); + + btv->pll=0; + if(pll[btv->nr]) + if (!(btv->id==848 && btv->revision==0x11)) + { + printk(KERN_INFO "bttv%d: internal PLL, single crystal operation enabled\n",bttv_num); + btv->pll=1; + } + + btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000); + + /* clear interrupt mask */ + btwrite(0, BT848_INT_MASK); - if (!pcibios_present()) - { - DEBUG(printk(KERN_DEBUG "bttv: PCI-BIOS not present or not accessible!\n")); - return 0; - } - for (dev = pci_devices; dev != NULL; dev = dev->next) - { - if (dev->vendor != PCI_VENDOR_ID_BROOKTREE) - continue; - if (dev->device != PCI_DEVICE_ID_BT849 && - dev->device != PCI_DEVICE_ID_BT848) - continue; + result = request_irq(btv->irq, bttv_irq, + SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv); + if (result==-EINVAL) + { + printk(KERN_ERR "bttv%d: Bad irq number or handler\n", + bttv_num); + return -EINVAL; + } + if (result==-EBUSY) + { + printk(KERN_ERR "bttv%d: IRQ %d busy, change your PnP config in BIOS\n",bttv_num,btv->irq); + return result; + } + if (result < 0) + return result; + + pci_set_master(dev); - /* Ok, Bt848 or Bt849 found! */ - btv=&bttvs[bttv_num]; - btv->dev=dev; - btv->bt848_mem=NULL; - btv->vbibuf=NULL; - btv->risc_jmp=NULL; - btv->vbi_odd=NULL; - btv->vbi_even=NULL; - btv->vbiq=NULL; - btv->capq=NULL; - btv->capqo=NULL; - btv->capqe=NULL; - - btv->vbip=VBIBUF_SIZE; - - pci_read_config_word (btv->dev, PCI_DEVICE_ID, &btv->id); - - /* pci_read_config_dword(btv->dev, PCI_BASE_ADDRESS_0, &btv->bt848_adr); */ - btv->bt848_adr = btv->dev->base_address[0]; - - if (remap&&(!bttv_num)) - { - remap<<=20; - remap&=PCI_BASE_ADDRESS_MEM_MASK; - printk(KERN_INFO "Remapping to : 0x%08x.\n", remap); - remap|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK); - pci_write_config_dword(btv->dev, PCI_BASE_ADDRESS_0, remap); - pci_read_config_dword(btv->dev, PCI_BASE_ADDRESS_0, &btv->bt848_adr); - btv->dev->base_address[0] = btv->bt848_adr; - } - - btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK; - pci_read_config_byte(btv->dev, PCI_CLASS_REVISION, - &btv->revision); - printk(KERN_INFO "bttv: Brooktree Bt%d (rev %d) ", - btv->id, btv->revision); - printk("bus: %d, devfn: %d, ", - btv->dev->bus->number, btv->dev->devfn); - printk("irq: %d, ",btv->dev->irq); - printk("memory: 0x%08x.\n", btv->bt848_adr); - - btv->pll = 0; -#ifdef USE_PLL - if (btv->id==849 || (btv->id==848 && btv->revision==0x12)) + btv->triton1=triton1 ? BT848_INT_ETBF : 0; + if (triton1 && btv->id >= 878) + { + btv->triton1 = 0; + printk("bttv: Enabling 430FX compatibilty for bt878\n"); + pci_read_config_byte(dev, BT878_DEVCTRL, &command); + command|=BT878_EN_TBFX; + pci_write_config_byte(dev, BT878_DEVCTRL, command); + pci_read_config_byte(dev, BT878_DEVCTRL, &command); + if (!(command&BT878_EN_TBFX)) { - printk(KERN_INFO "bttv: internal PLL, single crystal operation enabled.\n"); - btv->pll=1; + printk("bttv: 430FX compatibility could not be enabled\n"); + return -1; } -#endif - - btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000); + } + + return 0; +} - result = request_irq(btv->dev->irq, bttv_irq, - SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv); - if (result==-EINVAL) - { - printk(KERN_ERR "bttv: Bad irq number or handler\n"); - return -EINVAL; - } - if (result==-EBUSY) - { - printk(KERN_ERR "bttv: IRQ %d busy, change your PnP config in BIOS\n",btv->dev->irq); - return result; - } - if (result < 0) - return result; +static int find_bt848(void) +{ + struct pci_dev *dev = pci_devices; + int result=0; - /* Enable bus-mastering */ - pci_read_config_byte(btv->dev, PCI_COMMAND, &command); - command|=PCI_COMMAND_MASTER; - pci_write_config_byte(btv->dev, PCI_COMMAND, command); - pci_read_config_byte(btv->dev, PCI_COMMAND, &command); - if (!(command&PCI_COMMAND_MASTER)) - { - printk(KERN_ERR "bttv: PCI bus-mastering could not be enabled\n"); - return -1; - } - pci_read_config_byte(btv->dev, PCI_LATENCY_TIMER, &latency); - if (!latency) - { - latency=32; - pci_write_config_byte(btv->dev, PCI_LATENCY_TIMER, latency); - } - DEBUG(printk(KERN_DEBUG "bttv: latency: %02x\n", latency)); - bttv_num++; - } + bttv_num=0; + + while (dev) + { + if (dev->vendor == PCI_VENDOR_ID_BROOKTREE) + if ((dev->device == PCI_DEVICE_ID_BT848)|| + (dev->device == PCI_DEVICE_ID_BT849)|| + (dev->device == PCI_DEVICE_ID_BT878)|| + (dev->device == PCI_DEVICE_ID_BT879)) + result=configure_bt848(dev,bttv_num++); + if (result) + return result; + dev = dev->next; + } if(bttv_num) printk(KERN_INFO "bttv: %d Bt848 card(s) found.\n", bttv_num); return bttv_num; } - + static void release_bttv(void) { @@ -3009,7 +3024,7 @@ static void release_bttv(void) vfree((void *) btv->vbibuf); - free_irq(btv->dev->irq,btv); + free_irq(btv->irq,btv); DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%08x.\n", btv->bt848_mem)); if (btv->bt848_mem) iounmap(btv->bt848_mem); diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h index e1e21f595..83a0cecb6 100644 --- a/drivers/char/bttv.h +++ b/drivers/char/bttv.h @@ -32,17 +32,11 @@ #include #define MAX_CLIPRECS 100 +#define MAX_GBUFFERS 2 #define RISCMEM_LEN (32744*2) -#define BTTV_MAX_FBUF 0x144000 - - -/* clipping rectangle */ -struct cliprec -{ - int x, y, x2, y2; - struct cliprec *next; -}; +/* maximum needed buffer size for extended VBI frame mode capturing */ +#define BTTV_MAX_FBUF 0x151000 #ifdef __KERNEL__ @@ -75,9 +69,14 @@ struct bttv int have_msp3400; int have_tuner; int tuner_type; - + int channel; + + unsigned int nr; unsigned short id; + unsigned char bus; /* PCI bus the Bt848 is on */ + unsigned char devfn; struct pci_dev *dev; + unsigned char irq; /* IRQ used by Bt848 card */ unsigned char revision; unsigned int bt848_adr; /* bus address of IO mem returned by PCI BIOS */ unsigned char *bt848_mem; /* pointer to mapped IO memory */ @@ -106,24 +105,37 @@ struct bttv u32 *risc_odd; u32 *risc_even; int cap; - struct cliprec *cliprecs; - int ncr; /* number of clipping rectangles */ + struct video_clip *cliprecs; struct gbuffer *ogbuffers; struct gbuffer *egbuffers; u16 gwidth, gheight, gfmt; u32 *grisc; + unsigned long gro; unsigned long gre; unsigned long gro_next; unsigned long gre_next; - char *fbuffer; + + int grf,grf_next; /* frame numbers in grab queue */ + int frame_stat[MAX_GBUFFERS]; +#define GBUFFER_UNUSED 0 +#define GBUFFER_GRABBING 1 +#define GBUFFER_DONE 2 + + char *fbuffer; int gmode; int grabbing; int lastgrab; int grab; int grabcount; + int pll; + unsigned int Fsc; + unsigned int field; + unsigned int last_field; /* number of last grabbed field */ + int i2c_command; + int triton1; }; #endif @@ -148,6 +160,7 @@ struct bttv #define BTTV_READEE _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]) #define BTTV_WRITEE _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]) #define BTTV_GRAB _IOR('v' , BASE_VIDIOCPRIVATE+2, struct gbuf) +#define BTTV_FIELDNR _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int) #define BTTV_UNKNOWN 0x00 @@ -186,7 +199,6 @@ struct bttv #define TDA9850_ALI2 0x09 #define TDA9850_ALI3 0x0a - #define TDA8425_VL 0x00 #define TDA8425_VR 0x01 #define TDA8425_BA 0x02 diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c index f86a73e9e..34651f9e9 100644 --- a/drivers/char/busmouse.c +++ b/drivers/char/busmouse.c @@ -238,6 +238,7 @@ struct file_operations bus_mouse_fops = { NULL, /* mouse_ioctl */ NULL, /* mouse_mmap */ open_mouse, + NULL, /* flush */ close_mouse, NULL, fasync_mouse, diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 976219825..efd4854ce 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -1,7 +1,7 @@ #define BLOCKMOVE #define Z_WAKE static char rcsid[] = -"$Revision: 2.2.1.5 $$Date: 1998/08/10 18:10:28 $"; +"$Revision: 2.2.1.6 $$Date: 1998/08/20 17:15:39 $"; /* * linux/drivers/char/cyclades.c @@ -31,6 +31,11 @@ static char rcsid[] = * void cleanup_module(void); * * $Log: cyclades.c,v $ + * Revision 2.2.1.6 1998/08/20 17:15:39 ivan + * Fixed bug in cy_close function, which causes malfunction + * of one of the first 4 ports when a higher port is closed + * (Cyclom-Y only). + * * Revision 2.2.1.5 1998/08/10 18:10:28 ivan * Fixed Cyclom-4Yo hardware detection bug. * @@ -2679,9 +2684,11 @@ cy_close(struct tty_struct * tty, struct file * filp) } if (!IS_CYC_Z(cy_card[info->card])) { - unsigned char *base_addr = (unsigned char *) - cy_card[info->card].base_addr; + int channel = info->line - cy_card[info->card].first_line; int index = cy_card[info->card].bus_index; + unsigned char *base_addr = (unsigned char *) + (cy_card[info->card].base_addr + + (cy_chip_offset[channel>>2] <read_cnt, N_TTY_BUF_SIZE - tty->read_tail)); - if (!n) - return; - /* N.B. copy_to_user may work only partially */ - n -= copy_to_user(*b, &tty->read_buf[tty->read_tail], n); - tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); - tty->read_cnt -= n; - *b += n; - *nr -= n; + if (n) { + retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n); + n -= retval; + tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); + tty->read_cnt -= n; + *b += n; + *nr -= n; + } + return retval; } static ssize_t read_chan(struct tty_struct *tty, struct file *file, @@ -996,9 +999,13 @@ do_it_again: } } } else { - /* N.B. check for errors writing to user space? */ - copy_from_read_buf(tty, &b, &nr); - copy_from_read_buf(tty, &b, &nr); + int uncopied; + uncopied = copy_from_read_buf(tty, &b, &nr); + uncopied += copy_from_read_buf(tty, &b, &nr); + if (uncopied) { + retval = -EFAULT; + break; + } } /* If there is enough space in the read buffer now, let the diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index a3353f4af..11e7eadcf 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -402,6 +402,7 @@ static struct file_operations nvram_fops = { nvram_ioctl, NULL, /* No mmap */ nvram_open, + NULL, /* flush */ nvram_release }; diff --git a/drivers/char/pc110pad.c b/drivers/char/pc110pad.c index 3921235e2..ea6d706cb 100644 --- a/drivers/char/pc110pad.c +++ b/drivers/char/pc110pad.c @@ -626,6 +626,7 @@ static struct file_operations pad_fops = { pad_ioctl, NULL, /* pad_mmap */ open_pad, + NULL, /* flush */ close_pad, NULL, /* fsync */ fasync_pad, diff --git a/drivers/char/pcwd.c b/drivers/char/pcwd.c index 4bd0f0f29..ded35916c 100644 --- a/drivers/char/pcwd.c +++ b/drivers/char/pcwd.c @@ -515,6 +515,7 @@ static struct file_operations pcwd_fops = { pcwd_ioctl, /* IOctl */ NULL, /* MMAP */ pcwd_open, /* Open */ + NULL, /* flush */ pcwd_close, /* Release */ NULL, /* Fsync */ NULL, /* Fasync */ diff --git a/drivers/char/psaux.c b/drivers/char/psaux.c index 50c0b63c4..e4a54097b 100644 --- a/drivers/char/psaux.c +++ b/drivers/char/psaux.c @@ -582,6 +582,7 @@ struct file_operations psaux_fops = { NULL, /* ioctl */ NULL, /* mmap */ open_aux, + NULL, /* flush */ release_aux, NULL, fasync_aux, diff --git a/drivers/char/radio-aimslab.c b/drivers/char/radio-aimslab.c index 08fc6116d..59d95042e 100644 --- a/drivers/char/radio-aimslab.c +++ b/drivers/char/radio-aimslab.c @@ -216,6 +216,7 @@ static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.maxheight=0; v.minwidth=0; v.minheight=0; + strcpy(v.name, "RadioTrack"); if(copy_to_user(arg,&v,sizeof(v))) return -EFAULT; return 0; diff --git a/drivers/char/radio-aztech.c b/drivers/char/radio-aztech.c index caaa60c7c..39d56a86f 100644 --- a/drivers/char/radio-aztech.c +++ b/drivers/char/radio-aztech.c @@ -167,6 +167,7 @@ static int az_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.maxheight=0; v.minwidth=0; v.minheight=0; + strcpy(v.name, "Aztech Radio"); if(copy_to_user(arg,&v,sizeof(v))) return -EFAULT; return 0; diff --git a/drivers/char/radio-miropcm20.c b/drivers/char/radio-miropcm20.c new file mode 100644 index 000000000..ffc1d1908 --- /dev/null +++ b/drivers/char/radio-miropcm20.c @@ -0,0 +1,245 @@ +/* Miro PCM20 radio driver for Linux radio support + * (c) 1998 Ruurd Reitsma + * Thanks to Norberto Pellici for the ACI device interface specification + * The API part is based on the radiotrack driver by M. Kirkwood + * This driver relies on the aci mixer (drivers/sound/lowlevel/aci.c) + * Look there for further info... + */ + +#include /* Modules */ +#include /* Initdata */ +#include /* copy to/from user */ +#include /* kernel radio structs */ +#include /* CONFIG_RADIO_MIROPCM20 */ +#include "../sound/lowlevel/miroaci.h" /* ACI Control by acimixer */ + +static int users = 0; + +struct pcm20_device +{ + int port; + int curvol; + unsigned long curfreq; + int muted; +}; + + +/* local things */ + + +static void pcm20_mute(struct pcm20_device *dev) +{ + + dev->muted = 1; + aci_write_cmd(0xa3,0x01); + +} + +static int pcm20_setvol(struct pcm20_device *dev, int vol) +{ + + if(vol == dev->curvol) { /* requested volume = current */ + if (dev->muted) { /* user is unmuting the card */ + dev->muted = 0; + aci_write_cmd(0xa3,0x00); /* enable card */ + } + + return 0; + } + + if(vol == 0) { /* volume = 0 means mute the card */ + aci_write_cmd(0x3d, 0x20); + aci_write_cmd(0x35, 0x20); + return 0; + } + + dev->muted = 0; + aci_write_cmd(0x3d, 32-vol); /* Right Channel */ + aci_write_cmd(0x35, 32-vol); /* Left Channel */ + dev->curvol = vol; + + return 0; +} + +static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq) +{ + unsigned char freql; + unsigned char freqh; + + freq = (freq * 10) / 16; + freql = freq & 0xff; + freqh = freq >> 8; + + + aci_write_cmd_d(0xa7, freql, freqh); /* Tune to frequency */ + + return 0; +} + +int pcm20_getsigstr(struct pcm20_device *dev) +{ + unsigned char buf; + aci_indexed_cmd(0xf0, 0x32, &buf); + if ((buf & 0x80) == 0x80) + return 0; + return 1; /* signal present */ +} + +static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + struct pcm20_device *pcm20=dev->priv; + + switch(cmd) + { + case VIDIOCGCAP: + { + struct video_capability v; + v.type=VID_TYPE_TUNER; + strcpy(v.name, "Miro PCM20"); + v.channels=1; + v.audios=1; + /* No we don't do pictures */ + v.maxwidth=0; + v.maxheight=0; + v.minwidth=0; + v.minheight=0; + if(copy_to_user(arg,&v,sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCGTUNER: + { + struct video_tuner v; + if(copy_from_user(&v, arg,sizeof(v))!=0) + return -EFAULT; + if(v.tuner) /* Only 1 tuner */ + return -EINVAL; + v.rangelow=(int)(87.5*16); + v.rangehigh=(int)(108.0*16); + v.flags=0; + v.mode=VIDEO_MODE_AUTO; + v.signal=0xFFFF*pcm20_getsigstr(pcm20); + if(copy_to_user(arg,&v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSTUNER: + { + struct video_tuner v; + if(copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if(v.tuner!=0) + return -EINVAL; + /* Only 1 tuner so no setting needed ! */ + return 0; + } + case VIDIOCGFREQ: + if(copy_to_user(arg, &pcm20->curfreq, sizeof(pcm20->curfreq))) + return -EFAULT; + return 0; + case VIDIOCSFREQ: + if(copy_from_user(&pcm20->curfreq, arg,sizeof(pcm20->curfreq))) + return -EFAULT; + pcm20_setfreq(pcm20, pcm20->curfreq); + return 0; + case VIDIOCGAUDIO: + { + struct video_audio v; + memset(&v,0, sizeof(v)); + v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; + v.volume=pcm20->curvol * 2048; + strcpy(v.name, "Radio"); + if(copy_to_user(arg,&v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSAUDIO: + { + struct video_audio v; + if(copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if(v.audio) + return -EINVAL; + + if(v.flags&VIDEO_AUDIO_MUTE) + pcm20_mute(pcm20); + else + pcm20_setvol(pcm20,v.volume/2048); + + return 0; + } + default: + return -ENOIOCTLCMD; + } +} + +static int pcm20_open(struct video_device *dev, int flags) +{ + if(users) + return -EBUSY; + users++; + MOD_INC_USE_COUNT; + return 0; +} + +static void pcm20_close(struct video_device *dev) +{ + users--; + MOD_DEC_USE_COUNT; +} + +static struct pcm20_device pcm20_unit; + +static struct video_device pcm20_radio= +{ + "Miro PCM 20 radio", + VID_TYPE_TUNER, + VID_HARDWARE_RTRACK, + pcm20_open, + pcm20_close, + NULL, /* Can't read (no capture ability) */ + NULL, /* Can't write */ + NULL, /* Can't poll */ + pcm20_ioctl, + NULL, + NULL +}; + +__initfunc(int pcm20_init(struct video_init *v)) +{ + + pcm20_radio.priv=&pcm20_unit; + + if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO)==-1) + return -EINVAL; + + printk(KERN_INFO "Miro PCM20 radio card driver.\n"); + + /* mute card - prevents noisy bootups */ + + /* this ensures that the volume is all the way down */ + + pcm20_unit.curvol = 0; + + return 0; +} + +#ifdef MODULE + +MODULE_AUTHOR("Ruurd Reitsma"); +MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card."); + +EXPORT_NO_SYMBOLS; + +int init_module(void) +{ + + return pcm20_init(NULL); +} + +void cleanup_module(void) +{ + video_unregister_device(&pcm20_radio); +} + +#endif diff --git a/drivers/char/radio-rtrack2.c b/drivers/char/radio-rtrack2.c index c035efe29..175c665f7 100644 --- a/drivers/char/radio-rtrack2.c +++ b/drivers/char/radio-rtrack2.c @@ -113,6 +113,7 @@ static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.maxheight=0; v.minwidth=0; v.minheight=0; + strcpy(v.name, "RadioTrack II"); if(copy_to_user(arg,&v,sizeof(v))) return -EFAULT; return 0; diff --git a/drivers/char/radio-sf16fmi.c b/drivers/char/radio-sf16fmi.c index d8dee777d..192fa5236 100644 --- a/drivers/char/radio-sf16fmi.c +++ b/drivers/char/radio-sf16fmi.c @@ -22,14 +22,12 @@ #include /* kernel radio structs */ #include /* CONFIG_RADIO_SF16MI_PORT */ -#include "rsf16fmi.h" - struct fmi_device { int port; - int curvol; - unsigned long curfreq; - int flags; + int curvol; /* 1 or 0 */ + unsigned long curfreq; /* RSF16_PREC * freq in MHz */ + __u32 flags; }; #ifndef CONFIG_RADIO_SF16FMI_PORT @@ -39,11 +37,16 @@ struct fmi_device static int io = CONFIG_RADIO_SF16FMI_PORT; static int users = 0; -/* local things */ -/* freq in 1/16kHz to internal number */ -#define RSF16_ENCODE(x) ((x/16+10700)/50) +/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ +/* It is only usefull to give freq in intervall of 800 (=0.05Mhz), + * other bits will be truncated, e.g 92.7400016 -> 92.7, but + * 92.7400017 -> 92.75 + */ +#define RSF16_ENCODE(x) ((x)/800+214) +#define RSF16_MINFREQ 88*16000 +#define RSF16_MAXFREQ 108*16000 -static void outbits(int bits, int data, int port) +static void outbits(int bits, unsigned int data, int port) { while(bits--) { if(data & 1) { @@ -73,7 +76,7 @@ static void fmi_unmute(int port) static int fmi_setfreq(struct fmi_device *dev, unsigned long freq) { - int myport = dev->port; + int myport = dev->port; outbits(16, RSF16_ENCODE(freq), myport); outbits(8, 0xC0, myport); @@ -105,6 +108,7 @@ static int fmi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) case VIDIOCGCAP: { struct video_capability v; + strcpy(v.name, "SF16-FMx radio"); v.type=VID_TYPE_TUNER; v.channels=1; v.audios=1; @@ -120,17 +124,16 @@ static int fmi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) case VIDIOCGTUNER: { struct video_tuner v; + int mult; + if(copy_from_user(&v, arg,sizeof(v))!=0) return -EFAULT; if(v.tuner) /* Only 1 tuner */ return -EINVAL; - if (fmi->flags & VIDEO_TUNER_LOW) { - v.rangelow = 87500 * 16; - v.rangehigh = 108000 * 16; - } else { - v.rangelow=(int)(175*8 /* 87.5 *16 */); - v.rangehigh=(int)(108*16); - } + strcpy(v.name, "FM"); + mult = (fmi->flags & VIDEO_TUNER_LOW) ? 1 : 1000; + v.rangelow = RSF16_MINFREQ/mult; + v.rangehigh = RSF16_MAXFREQ/mult; v.flags=fmi->flags; v.mode=VIDEO_MODE_AUTO; v.signal=0xFFFF*fmi_getsigstr(fmi); @@ -165,6 +168,8 @@ static int fmi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EFAULT; if (!(fmi->flags & VIDEO_TUNER_LOW)) tmp *= 1000; + if ( tmpRSF16_MAXFREQ ) + return -EINVAL; fmi->curfreq = tmp; fmi_setfreq(fmi, fmi->curfreq); return 0; @@ -172,12 +177,15 @@ static int fmi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) case VIDIOCGAUDIO: { struct video_audio v; - memset(&v,0, sizeof(v)); - v.flags|=VIDEO_AUDIO_MUTABLE; - v.mode=VIDEO_SOUND_MONO; - v.volume=fmi->curvol; - v.step=65535; + v.audio=0; + v.volume=0; + v.bass=0; + v.treble=0; + v.flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); strcpy(v.name, "Radio"); + v.mode=VIDEO_SOUND_MONO; + v.balance=0; + v.step=0; /* No volume, just (un)mute */ if(copy_to_user(arg,&v, sizeof(v))) return -EFAULT; return 0; @@ -189,15 +197,23 @@ static int fmi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EFAULT; if(v.audio) return -EINVAL; - fmi->curvol=v.volume; - if(v.flags&VIDEO_AUDIO_MUTE) - fmi_mute(fmi->port); - else if(fmi->curvol) - fmi_unmute(fmi->port); - else - fmi_mute(fmi->port); + fmi->curvol= v.flags&VIDEO_AUDIO_MUTE ? 0 : 1; + fmi->curvol ? + fmi_unmute(fmi->port) : fmi_mute(fmi->port); return 0; } + case VIDIOCGUNIT: + { + struct video_unit v; + v.video=VIDEO_NO_UNIT; + v.vbi=VIDEO_NO_UNIT; + v.radio=dev->minor; + v.audio=0; /* How do we find out this??? */ + v.teletext=VIDEO_NO_UNIT; + if(copy_to_user(arg, &v, sizeof(v))) + return -EFAULT; + return 0; + } default: return -ENOIOCTLCMD; } @@ -222,7 +238,7 @@ static struct fmi_device fmi_unit; static struct video_device fmi_radio= { - "SF16FMI radio", + "SF16FMx radio", VID_TYPE_TUNER, VID_HARDWARE_SF16MI, fmi_open, @@ -243,15 +259,17 @@ __initfunc(int fmi_init(struct video_init *v)) return -EBUSY; } - fmi_unit.port=io; + fmi_unit.port = io; + fmi_unit.curvol = 0; + fmi_unit.curfreq = 0; fmi_unit.flags = VIDEO_TUNER_LOW; - fmi_radio.priv=&fmi_unit; + fmi_radio.priv = &fmi_unit; if(video_register_device(&fmi_radio, VFL_TYPE_RADIO)==-1) return -EINVAL; request_region(io, 2, "fmi"); - printk(KERN_INFO "SF16FMI radio card driver.\n"); + printk(KERN_INFO "SF16FMx radio card driver at 0x%x.\n", io); printk(KERN_INFO "(c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz.\n"); /* mute card - prevents noisy bootups */ fmi_mute(io); diff --git a/drivers/char/radio-zoltrix.c b/drivers/char/radio-zoltrix.c index 8c28247b9..115606ac3 100644 --- a/drivers/char/radio-zoltrix.c +++ b/drivers/char/radio-zoltrix.c @@ -176,6 +176,7 @@ static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.maxheight = 0; v.minwidth = 0; v.minheight = 0; + strcpy(v.name, "Zoltrix Radio"); if (copy_to_user(arg, &v, sizeof(v))) return -EFAULT; return 0; diff --git a/drivers/char/random.c b/drivers/char/random.c index b7ed4e10b..5db97f906 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1526,6 +1526,7 @@ struct file_operations random_fops = { random_ioctl, NULL, /* random_mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL /* no special release code */ }; @@ -1538,6 +1539,7 @@ struct file_operations urandom_fops = { random_ioctl, NULL, /* urandom_mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL /* no special release code */ }; diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 1a0079531..c5b326083 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -506,6 +506,7 @@ static struct file_operations rtc_fops = { rtc_ioctl, NULL, /* No mmap */ rtc_open, + NULL, /* flush */ rtc_release }; diff --git a/drivers/char/softdog.c b/drivers/char/softdog.c index 60e1dccdf..c611b5344 100644 --- a/drivers/char/softdog.c +++ b/drivers/char/softdog.c @@ -168,6 +168,7 @@ static struct file_operations softdog_fops= softdog_ioctl, /* Ioctl */ NULL, /* MMap */ softdog_open, + NULL, /* flush */ softdog_release, NULL, NULL /* Fasync */ diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 7239923ec..81d389cad 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -672,6 +672,7 @@ static struct file_operations stl_fsiomem = { stl_memioctl, NULL, stl_memopen, + NULL, /* flush */ stl_memclose, NULL }; diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c index 461e58165..56e2099ba 100644 --- a/drivers/char/tpqic02.c +++ b/drivers/char/tpqic02.c @@ -2756,6 +2756,7 @@ static struct file_operations qic02_tape_fops = { qic02_tape_ioctl, /* ioctl */ NULL, /* mmap not allowed */ qic02_tape_open, /* open */ + NULL, /* flush */ qic02_tape_release, /* release */ NULL, /* fsync */ NULL, /* fasync */ diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index ff5fe5d5a..091cd26dc 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -358,6 +358,7 @@ static struct file_operations tty_fops = { tty_ioctl, NULL, /* tty_mmap */ tty_open, + NULL, /* flush */ tty_release, NULL, /* tty_fsync */ tty_fasync @@ -372,6 +373,7 @@ static struct file_operations hung_up_tty_fops = { hung_up_tty_ioctl, NULL, /* hung_up_tty_mmap */ NULL, /* hung_up_tty_open */ + NULL, /* flush */ tty_release, /* hung_up_tty_release */ NULL, /* hung_up_tty_fsync */ NULL /* hung_up_tty_fasync */ @@ -1976,7 +1978,7 @@ int tty_unregister_driver(struct tty_driver *driver) * Just do some early initializations, and do the complex setup * later. */ -long console_init(long kmem_start, long kmem_end) +long __init console_init(long kmem_start, long kmem_end) { /* Setup the default TTY line discipline. */ memset(ldiscs, 0, sizeof(ldiscs)); diff --git a/drivers/char/tuner.c b/drivers/char/tuner.c index 9eb3d3944..c640ff321 100644 --- a/drivers/char/tuner.c +++ b/drivers/char/tuner.c @@ -108,7 +108,7 @@ static void set_tv_freq(struct tuner *t, int freq) else config = tun->UHF; - div=freq + (int)(16*38.9); + div=freq + tun->IFPCoff; div&=0x7fff; LOCK_I2C_BUS(t->bus); diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index 30de4d39b..bbdf7e4d5 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -258,6 +258,7 @@ static struct file_operations vcs_fops = { NULL, /* ioctl */ NULL, /* mmap */ vcs_open, /* open */ + NULL, /* flush */ NULL, /* release */ NULL /* fsync */ }; diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c index 868ba4eb9..2ba0bd030 100644 --- a/drivers/char/videodev.c +++ b/drivers/char/videodev.c @@ -62,6 +62,9 @@ extern int rtrack_init(struct video_init *); #ifdef CONFIG_RADIO_SF16FMI extern int fmi_init(struct video_init *); #endif +#ifdef CONFIG_RADIO_MIROPCM20 +extern int pcm20_init(struct video_init *); +#endif static struct video_init video_init_list[]={ #ifdef CONFIG_VIDEO_BT848 @@ -88,6 +91,9 @@ static struct video_init video_init_list[]={ #endif #ifdef CONFIG_RADIO_SF16FMI {"SF16FMI", fmi_init}, +#endif +#ifdef CONFIG_RADIO_MIROPCM20 + {"PCM20", pcm20_init}, #endif {"end", NULL} }; @@ -315,6 +321,7 @@ static struct file_operations video_fops= video_ioctl, video_mmap, video_open, + NULL, /* flush */ video_release }; diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c index 86ce29744..a42c35fe3 100644 --- a/drivers/char/wdt.c +++ b/drivers/char/wdt.c @@ -327,6 +327,7 @@ static struct file_operations wdt_fops = { wdt_ioctl, NULL, /* No mmap */ wdt_open, + NULL, /* flush */ wdt_release }; diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c index d94a8a771..f4f5c7039 100644 --- a/drivers/isdn/avmb1/capi.c +++ b/drivers/isdn/avmb1/capi.c @@ -464,6 +464,7 @@ static struct file_operations capi_fops = capi_ioctl, NULL, /* capi_mmap */ capi_open, + NULL, /* flush */ capi_release, NULL, /* capi_fsync */ NULL, /* capi_fasync */ diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index f8a7d46e5..4c9a67cc0 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -442,6 +442,7 @@ static struct file_operations adb_fops = { NULL, /* no ioctl yet */ NULL, /* no mmap */ adb_open, + NULL, /* flush */ adb_release }; diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c index ad06d3f85..33297e3f2 100644 --- a/drivers/macintosh/nvram.c +++ b/drivers/macintosh/nvram.c @@ -82,6 +82,7 @@ struct file_operations nvram_fops = { NULL, /* nvram_ioctl */ NULL, /* nvram_mmap */ nvram_open, + NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ }; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index ee6b014bd..407a93002 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -903,6 +903,7 @@ static struct file_operations pmu_device_fops = { pmu_ioctl, NULL, /* no mmap */ pmu_open, + NULL, /* flush */ NULL /* no release */ }; diff --git a/drivers/pci/oldproc.c b/drivers/pci/oldproc.c index a71f26bbe..95e904a40 100644 --- a/drivers/pci/oldproc.c +++ b/drivers/pci/oldproc.c @@ -1,5 +1,5 @@ /* - * $Id: oldproc.c,v 1.16 1998/07/19 17:50:18 davem Exp $ + * $Id: oldproc.c,v 1.20 1998/08/23 12:12:01 mj Exp $ * * Backward-compatible procfs interface for PCI. * @@ -122,7 +122,9 @@ struct pci_dev_info dev_info[] = { DEVICE( IBM, IBM_82351, "82351"), DEVICE( IBM, IBM_SERVERAID, "ServeRAID"), DEVICE( IBM, IBM_TR_WAKE, "Wake On LAN Token Ring"), + DEVICE( IBM, IBM_MPIC, "MPIC-2 Interrupt Controller"), DEVICE( IBM, IBM_3780IDSP, "MWave DSP"), + DEVICE( IBM, IBM_MPIC_2, "MPIC-2 ASIC Interrupt Controller"), DEVICE( WD, WD_7197, "WD 7197"), DEVICE( AMD, AMD_LANCE, "79C970"), DEVICE( AMD, AMD_SCSI, "53C974"), diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b70b879ab..8b1f6011b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1,5 +1,5 @@ /* - * $Id: pci.c,v 1.86 1998/07/15 20:34:47 mj Exp $ + * $Id: pci.c,v 1.88 1998/08/15 10:37:12 mj Exp $ * * PCI Bus Services, see include/linux/pci.h for further explanation. * @@ -170,13 +170,14 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus)) /* not a multi-function device */ continue; } - pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type); + if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type)) + continue; if (!PCI_FUNC(devfn)) is_multi = hdr_type & 0x80; - pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l); - /* some broken boards return 0 if a slot is empty: */ - if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) { + if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) || + /* some broken boards return 0 if a slot is empty: */ + l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) { is_multi = 0; continue; } diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index b9362798f..d1a78fe53 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -204,6 +204,7 @@ static struct file_operations proc_bus_pci_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c index ab14e2767..c98923da4 100644 --- a/drivers/sbus/audio/audio.c +++ b/drivers/sbus/audio/audio.c @@ -881,6 +881,7 @@ static struct file_operations sparcaudioctl_fops = { sparcaudio_ioctl, NULL, /* sparcaudio_mmap */ NULL, + NULL, /* flush */ sparcaudioctl_release }; diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c index 983e3893f..846f7cd7b 100644 --- a/drivers/sbus/char/bpp.c +++ b/drivers/sbus/char/bpp.c @@ -866,6 +866,7 @@ static struct file_operations bpp_fops = { bpp_ioctl, NULL, /* bpp_mmap */ bpp_open, + NULL, /* flush */ bpp_release, }; diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index b957ce81c..af8f6ce78 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -298,6 +298,7 @@ static struct file_operations envctrl_fops = { envctrl_ioctl, NULL, /* mmap */ envctrl_open, + NULL, /* flush */ envctrl_release }; diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 0a09e07e2..fd91eeefd 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -143,6 +143,7 @@ static struct file_operations flash_fops = { NULL, /* ioctl */ flash_mmap, flash_open, + NULL, /* flush */ flash_release }; diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 6d09bfca4..7d17e08ea 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -564,6 +564,7 @@ static struct file_operations openprom_fops = { openprom_ioctl, NULL, /* openprom_mmap */ openprom_open, + NULL, /* flush */ openprom_release }; diff --git a/drivers/sbus/char/pcikbd.c b/drivers/sbus/char/pcikbd.c index 06140fa68..d6be1fca0 100644 --- a/drivers/sbus/char/pcikbd.c +++ b/drivers/sbus/char/pcikbd.c @@ -869,6 +869,7 @@ struct file_operations psaux_fops = { NULL, /* ioctl */ NULL, /* mmap */ aux_open, + NULL, /* flush */ aux_release, NULL, aux_fasync, diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c index f506a7c90..8e001c0bd 100644 --- a/drivers/sbus/char/rtc.c +++ b/drivers/sbus/char/rtc.c @@ -133,6 +133,7 @@ static struct file_operations rtc_fops = { rtc_ioctl, NULL, /* rtc_mmap */ rtc_open, + NULL, /* flush */ rtc_release }; diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c index 63586750e..59b77a5e4 100644 --- a/drivers/sbus/char/sunkbd.c +++ b/drivers/sbus/char/sunkbd.c @@ -1494,6 +1494,7 @@ file_operations kbd_fops = kbd_ioctl, /* ioctl */ NULL, /* mmap */ kbd_open, /* open */ + NULL, /* flush */ kbd_close, /* close */ NULL, /* fsync */ kbd_fasync, /* fasync */ diff --git a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c index 70edaab36..3a6d672fb 100644 --- a/drivers/sbus/char/sunmouse.c +++ b/drivers/sbus/char/sunmouse.c @@ -474,6 +474,7 @@ struct file_operations sun_mouse_fops = { sun_mouse_ioctl, NULL, sun_mouse_open, + NULL, /* flush */ sun_mouse_close, NULL, sun_mouse_fasync, diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 81a8b7477..b16581679 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -603,6 +603,7 @@ static struct file_operations vfc_fops = { vfc_ioctl, vfc_mmap, vfc_open, + NULL, /* flush */ vfc_release, }; diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 158215961..6441113ac 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -15,7 +15,7 @@ SCSI_SRCS = $(wildcard $(L_OBJS:%.o=%.c)) CFLAGS_aha152x.o = -DDEBUG_AHA152X -DAUTOCONF CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS -CFLAGS_seagate.o = -DARBITRATE -DSLOW_HANDSHAKE -DFAST32 -DPARITY +CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM .SUFFIXES: .SUFFIXES: .c .o .h .a diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index cd4ca8f4d..a7d86efba 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -222,6 +222,7 @@ static struct file_operations sd_fops = { sd_ioctl, /* ioctl */ NULL, /* mmap */ sd_open, /* open code */ + NULL, /* flush */ sd_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index 130e6a233..f5a316d31 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -1,30 +1,23 @@ /* * seagate.c Copyright (C) 1992, 1993 Drew Eckhardt * low level scsi driver for ST01/ST02, Future Domain TMC-885, - * TMC-950 by - * - * Drew Eckhardt - * - * + * TMC-950 by Drew Eckhardt * * Note : TMC-880 boards don't work because they have two bits in * the status register flipped, I'll fix this "RSN" + * [why do I have strong feeling that above message is from 1993? :-) pavel@ucw.cz] * * This card does all the I/O via memory mapped I/O, so there is no need * to check or allocate a region of the I/O address space. */ -/* Modified 1996 to use new read{b,w,l}, write{b,w,l}, and phys_to_virt - macros. This meant redefining st0x_cr_sr and st0x_dr, as well as - replacing the "DATA = foo;" and "CONTROL = foo;" structures with - WRITE_DATA(foo) and WRITE_CONTROL(foo) macros. - - Replaced assembler routines with C. There's probably a performance hit, - but I only have a cdrom and can't tell. Define SEAGATE_USE_ASM if you - want the old assembler code. - - Look for the string "SJT" for details. - +/* 1996 - to use new read{b,w,l}, write{b,w,l}, and phys_to_virt + * macros, replaced assembler routines with C. There's probably a + * performance hit, but I only have a cdrom and can't tell. Define + * SEAGATE_USE_ASM if you want the old assembler code -- SJT + * + * 1998-jul-29 - created DPRINTK macros and made it work under + * linux 2.1.112, simplified some #defines etc. */ /* @@ -50,7 +43,7 @@ * let us do one command per Lun when I integrate my * reorganization changes into the distribution sources. * - * -DDEBUG + * -DDEBUG=65535 * Will activate debug code. * * -DFAST or -DFAST32 @@ -63,13 +56,12 @@ * Will use older seagate assembly code. should be (very small amount) * Faster. * - * -DSLOW_HANDSHAKE + * -DSLOW_RATE=50 * Will allow compatibility with broken devices that don't * handshake fast enough (ie, some CD ROM's) for the Seagate * code. * - * -DSLOW_RATE=x - * x is some number, It will let you specify a default + * 50 is some number, It will let you specify a default * transfer rate if handshaking isn't working correctly. * * -DOLDCNTDATASCEME There is a new sceme to set the CONTROL @@ -97,16 +89,25 @@ #include #include #include +#include #include #include "scsi.h" #include "hosts.h" #include "seagate.h" #include "constants.h" -#include +#include #include #include "sd.h" #include +#include + +#ifdef DEBUG +#define DPRINTK( when, msg... ) do { if ( (DEBUG & (when)) == (when) ) printk( msg ); } while (0) +#else +#define DPRINTK( when, msg... ) do { } while (0) +#endif +#define DANY( msg... ) DPRINTK( 0xffff, msg ); static struct proc_dir_entry proc_scsi_seagate = { @@ -118,24 +119,16 @@ static struct proc_dir_entry proc_scsi_seagate = #define IRQ 5 #endif -#if (defined(FAST32) && !defined(FAST)) +#ifdef FAST32 #define FAST #endif -#if defined(SLOW_RATE) && !defined(SLOW_HANDSHAKE) -#define SLOW_HANDSHAKE -#endif - -#if defined(SLOW_HANDSHAKE) && !defined(SLOW_RATE) -#define SLOW_RATE 50 -#endif +#undef LINKED /* Linked commands are currently broken! */ -#if defined(LINKED) -#undef LINKED /* Linked commands are currently - broken! */ +#if defined(OVERRIDE) && !defined(CONTROLLER) +#error Please use -DCONTROLLER=SEAGATE or -DCONTROLLER=FD to override controller type #endif - /* Thanks to Brian Antoine for the example code in his Messy-Loss ST-01 driver, and Mitsugu Suzuki for information on the ST-01 @@ -206,7 +199,7 @@ extern volatile int seagate_st0x_timeout; #define PHASE_MSGIN 0x40 #define PHASE_MSGOUT 0x80 #define PHASE_STATUSIN 0x100 -#define PHASE_ETC (PHASE_DATAIN | PHASE_DATA_OUT | PHASE_CMDOUT | PHASE_MSGIN | PHASE_MSGOUT | PHASE_STATUSIN) +#define PHASE_ETC (PHASE_DATAIN | PHASE_DATAOUT | PHASE_CMDOUT | PHASE_MSGIN | PHASE_MSGOUT | PHASE_STATUSIN) #define PRINT_COMMAND 0x200 #define PHASE_EXIT 0x400 #define PHASE_RESELECT 0x800 @@ -223,8 +216,6 @@ extern volatile int seagate_st0x_timeout; #define ST0X_BUS_FREE_DELAY 25 #define ST0X_SELECTION_DELAY 25 -#define eoi() __asm__("push %%eax\nmovb $0x20, %%al\noutb %%al, $0x20\npop %%eax"::) - #define SEAGATE 1 /* these determine the type of the controller */ #define FD 2 @@ -242,10 +233,6 @@ static int incommand; /* set if arbitration has finished static unsigned int base_address = 0; /* Where the card ROM starts, used to calculate memory mapped register location. */ -#ifdef notyet -static volatile int abort_confirm = 0; - -#endif static unsigned long st0x_cr_sr; /* control register write, status register read. 256 bytes in @@ -262,15 +249,13 @@ static volatile int st0x_aborted = 0; /* set when we are aborted, ie by a static unsigned char controller_type = 0; /* set to SEAGATE for ST0x boards or FD for TMC-8xx boards */ -static unsigned char irq = IRQ; +static int irq = IRQ; #define retcode(result) (((result) << 16) | (message << 8) | status) -#define STATUS (readb(st0x_cr_sr)) -#define DATA (readb(st0x_dr)) -/* SJT: Start. */ -#define WRITE_CONTROL(d) writeb((d), st0x_cr_sr) -#define WRITE_DATA(d) writeb((d), st0x_dr) -/* SJT: End. */ +#define STATUS ((u8) readb(st0x_cr_sr)) +#define DATA ((u8) readb(st0x_dr)) +#define WRITE_CONTROL(d) { writeb((d), st0x_cr_sr); } +#define WRITE_DATA(d) { writeb((d), st0x_dr); } void st0x_setup (char *str, int *ints) { @@ -302,9 +287,8 @@ typedef struct } Signature; -static const Signature signatures[] = +static const Signature __initdata signatures[] = { -#ifdef CONFIG_SCSI_SEAGATE {"ST01 v1.7 (C) Copyright 1987 Seagate", 15, 37, SEAGATE}, {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40, SEAGATE}, @@ -331,9 +315,7 @@ static const Signature signatures[] = {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FD}, {"IBM F1 BIOS V1.1004/30/92", 5, 25, FD}, {"FUTURE DOMAIN TMC-950", 5, 21, FD}, -#endif /* CONFIG_SCSI_SEAGATE */ -} -; +}; #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature)) #endif /* n OVERRIDE */ @@ -348,10 +330,11 @@ static void do_seagate_reconnect_intr (int, void *, struct pt_regs *); #ifdef FAST static int fast = 1; - +#else +#define fast 0 #endif -#ifdef SLOW_HANDSHAKE +#ifdef SLOW_RATE /* * Support for broken devices : * The Seagate board has a handshaking problem. Namely, a lack @@ -387,10 +370,13 @@ static int fast = 1; * the best thing for us to do will be to calibrate a timing * loop in the initialization code using the timer chip before * gettimeofday() can screw with it. + * + * FIXME: this is broken (not borken :-). Empty loop costs less than + * loop with ISA access in it! -- pavel@ucw.cz */ static int borken_calibration = 0; -static void borken_init (void) +static void __init borken_init (void) { register int count = 0, start = jiffies + 1, stop = start + 25; @@ -399,53 +385,47 @@ static void borken_init (void) /* * Ok, we now have a count for .25 seconds. Convert to a - * count per second and divide by transfer rate in K. - */ + * count per second and divide by transfer rate in K. */ borken_calibration = (count * 4) / (SLOW_RATE * 1024); if (borken_calibration < 1) borken_calibration = 1; -#if (DEBUG & DEBUG_BORKEN) - printk ("scsi%d : borken calibrated to %dK/sec, %d cycles per transfer\n", - hostno, BORKEN_RATE, borken_calibration); -#endif } static inline void borken_wait (void) { register int count; - for (count = borken_calibration; count && (STATUS & STAT_REQ); - --count) ; + for (count = borken_calibration; count && (STATUS & STAT_REQ); --count) ; #if (DEBUG & DEBUG_BORKEN) if (count) printk ("scsi%d : borken timeout\n", hostno); #endif } -#endif /* def SLOW_HANDSHAKE */ +#endif /* def SLOW_RATE */ + +/* These beasts only live on ISA, and ISA means 8MHz. Each ULOOP() + * contains at least one ISA access, which takes more than 0.125 + * usec. So if we loop 8 times time in usec, we are safe. + */ + +#define ULOOP( i ) for (clock = i*8;;) +#define TIMEOUT (!(clock--)) -int seagate_st0x_detect (Scsi_Host_Template * tpnt) +int __init seagate_st0x_detect (Scsi_Host_Template * tpnt) { struct Scsi_Host *instance; - -#ifndef OVERRIDE int i, j; -#endif - tpnt->proc_dir = &proc_scsi_seagate; /* - * First, we try for the manual override. - */ -#ifdef DEBUG - printk ("Autodetecting ST0x / TMC-8xx\n"); -#endif + * First, we try for the manual override. */ + DANY ("Autodetecting ST0x / TMC-8xx\n"); - if (hostno != -1) - { - printk ("ERROR : seagate_st0x_detect() called twice.\n"); + if (hostno != -1) { + printk (KERN_ERR "seagate_st0x_detect() called twice?!\n"); return 0; } @@ -456,17 +436,10 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt) { #ifdef OVERRIDE base_address = OVERRIDE; - -/* CONTROLLER is used to override controller (SEAGATE or FD). PM: 07/01/93 */ -#ifdef CONTROLLER controller_type = CONTROLLER; -#else -#error Please use -DCONTROLLER=SEAGATE or -DCONTROLLER=FD to override controller type -#endif /* CONTROLLER */ -#ifdef DEBUG - printk ("Base address overridden to %x, controller type is %s\n", + + DANY("Base address overridden to %x, controller type is %s\n", base_address, controller_type == SEAGATE ? "SEAGATE" : "FD"); -#endif #else /* OVERRIDE */ /* * To detect this card, we simply look for the signature @@ -493,33 +466,46 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt) tpnt->this_id = (controller_type == SEAGATE) ? 7 : 6; tpnt->name = (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR; - if (base_address) - { - st0x_cr_sr = base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00); - st0x_dr = st0x_cr_sr + 0x200; -#ifdef DEBUG - printk ("%s detected. Base address = %x, cr = %x, dr = %x\n", - tpnt->name, base_address, st0x_cr_sr, st0x_dr); -#endif + if (!base_address) { + DANY ("ST0x / TMC-8xx not detected.\n"); + return 0; + } + + st0x_cr_sr = base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00); + st0x_dr = st0x_cr_sr + 0x200; + + DANY ("%s detected. Base address = %x, cr = %x, dr = %x\n", + tpnt->name, base_address, st0x_cr_sr, st0x_dr); + /* * At all times, we will use IRQ 5. Should also check for IRQ3 if we * loose our first interrupt. */ - instance = scsi_register (tpnt, 0); - hostno = instance->host_no; - if (request_irq ((int) irq, do_seagate_reconnect_intr, SA_INTERRUPT, - (controller_type == SEAGATE) ? "seagate" : "tmc-8xx", NULL)) - { - printk ("scsi%d : unable to allocate IRQ%d\n", hostno, (int) irq); - return 0; - } - instance->irq = irq; - instance->io_port = base_address; -#ifdef SLOW_HANDSHAKE - borken_init (); + instance = scsi_register (tpnt, 0); + hostno = instance->host_no; + if (request_irq (irq, do_seagate_reconnect_intr, SA_INTERRUPT, + (controller_type == SEAGATE) ? "seagate" : "tmc-8xx", NULL)) { + printk ("scsi%d : unable to allocate IRQ%d\n", hostno, irq); + return 0; + } + instance->irq = irq; + instance->io_port = base_address; +#ifdef SLOW_RATE + printk( "Calibrating borken timer... " ); + borken_init (); + printk( " %d cycles per transfer\n", borken_calibration ); #endif - printk ("%s options:" + printk( "This is one second... " ); + { + int clock; + ULOOP( 1*1000*1000 ) { + volatile int x = STATUS; + if (TIMEOUT) break; + } + } + + printk ("done, %s options:" #ifdef ARBITRATE " ARBITRATE" #endif @@ -527,10 +513,9 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt) " DEBUG" #endif #ifdef FAST -#ifdef FAST32 - " FAST32" -#else " FAST" +#ifdef FAST32 + "32" #endif #endif #ifdef LINKED @@ -542,8 +527,8 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt) #ifdef SEAGATE_USE_ASM " SEAGATE_USE_ASM" #endif -#ifdef SLOW_HANDSHAKE - " SLOW_HANDSHAKE" +#ifdef SLOW_RATE + " SLOW_RATE" #endif #ifdef SWAPSTAT " SWAPSTAT" @@ -551,16 +536,8 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt) #ifdef SWAPCNTDATA " SWAPCNTDATA" #endif - "\n", tpnt->name); - return 1; - } - else - { -#ifdef DEBUG - printk ("ST0x / TMC-8xx not detected.\n"); -#endif - return 0; - } + "\n", tpnt->name); + return 1; } const char *seagate_st0x_info (struct Scsi_Host *shpnt) @@ -585,7 +562,6 @@ static struct scatterlist *current_buffer; static int current_bufflen; #ifdef LINKED - /* * linked_connected indicates whether or not we are currently connected to * linked_target, linked_lun and in an INFORMATION TRANSFER phase, @@ -594,7 +570,6 @@ static int current_bufflen; static int linked_connected = 0; static unsigned char linked_target, linked_lun; - #endif static void (*done_fn) (Scsi_Cmnd *) = NULL; @@ -609,17 +584,14 @@ static Scsi_Cmnd *SCint = NULL; #define RECONNECT_NOW 1 #define CAN_RECONNECT 2 -#ifdef LINKED - /* * LINKED_RIGHT indicates that we are currently connected to the correct target * for this command, LINKED_WRONG indicates that we are connected to the wrong - * target. Note that these imply CAN_RECONNECT. + * target. Note that these imply CAN_RECONNECT and require defined(LINKED). */ #define LINKED_RIGHT 3 #define LINKED_WRONG 4 -#endif /* * This determines if we are expecting to reconnect or not. @@ -633,8 +605,7 @@ static int should_reconnect = 0; * asserting SEL. */ -static void do_seagate_reconnect_intr (int irq, void *dev_id, - struct pt_regs *regs) +static void do_seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs) { unsigned long flags; @@ -643,15 +614,12 @@ static void do_seagate_reconnect_intr (int irq, void *dev_id, spin_unlock_irqrestore(&io_request_lock, flags); } -static void seagate_reconnect_intr (int irq, void *dev_id, - struct pt_regs *regs) +static void seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs) { int temp; Scsi_Cmnd *SCtmp; -#if (DEBUG & PHASE_RESELECT) - printk ("scsi%d : seagate_reconnect_intr() called\n", hostno); -#endif + DPRINTK (PHASE_RESELECT, "scsi%d : seagate_reconnect_intr() called\n", hostno); if (!should_reconnect) printk ("scsi%d: unexpected interrupt.\n", hostno); @@ -659,11 +627,9 @@ static void seagate_reconnect_intr (int irq, void *dev_id, { should_reconnect = 0; -#if (DEBUG & PHASE_RESELECT) - printk ("scsi%d : internal_command(" - "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno, + DPRINTK (PHASE_RESELECT, "scsi%d : internal_command(" + "%d, %08x, %08x, RECONNECT_NOW\n", hostno, current_target, current_data, current_bufflen); -#endif temp = internal_command (current_target, current_lun, current_cmnd, current_data, current_bufflen, RECONNECT_NOW); @@ -672,10 +638,8 @@ static void seagate_reconnect_intr (int irq, void *dev_id, { if (done_fn) { -#if (DEBUG & PHASE_RESELECT) - printk ("scsi%d : done_fn(%d,%08x)", hostno, + DPRINTK (PHASE_RESELECT, "scsi%d : done_fn(%d,%08x)", hostno, hostno, temp); -#endif if (!SCint) panic ("SCint == NULL in seagate"); SCtmp = SCint; @@ -707,6 +671,7 @@ int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) int result, reconnect; Scsi_Cmnd *SCtmp; + DANY( "seagate: que_command" ); done_fn = done; current_target = SCpnt->target; current_lun = SCpnt->lun; @@ -714,10 +679,7 @@ int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) current_data = (unsigned char *) SCpnt->request_buffer; current_bufflen = SCpnt->request_bufflen; SCint = SCpnt; - if (recursion_depth) - { - return 0; - }; + if (recursion_depth) return 0; recursion_depth++; do { @@ -729,22 +691,16 @@ int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) current_cmnd[SCpnt->cmd_len] |= 0x01; if (linked_connected) { -#if (DEBUG & DEBUG_LINKED) - printk ("scsi%d : using linked commands, current I_T_L nexus is ", - hostno); -#endif + DPRINTK (DEBUG_LINKED, + "scsi%d : using linked commands, current I_T_L nexus is ", hostno); if ((linked_target == current_target) && (linked_lun == current_lun)) { -#if (DEBUG & DEBUG_LINKED) - printk ("correct\n"); -#endif + DPRINTK (DEBUG_LINKED, "correct\n"); reconnect = LINKED_RIGHT; } else { -#if (DEBUG & DEBUG_LINKED) - printk ("incorrect\n"); -#endif + DPRINTK (DEBUG_LINKED, "incorrect\n"); reconnect = LINKED_WRONG; } } @@ -753,10 +709,8 @@ int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) reconnect = CAN_RECONNECT; result = internal_command (SCint->target, SCint->lun, SCint->cmnd, - SCint->request_buffer, SCint->request_bufflen, - reconnect); - if (msg_byte (result) == DISCONNECT) - break; + SCint->request_buffer, SCint->request_bufflen, reconnect); + if (msg_byte (result) == DISCONNECT) break; SCtmp = SCint; SCint = NULL; SCtmp->result = result; @@ -775,59 +729,33 @@ int seagate_st0x_command (Scsi_Cmnd * SCpnt) } static int internal_command (unsigned char target, unsigned char lun, - const void *cmnd, void *buff, int bufflen, - int reselect) + const void *cmnd, void *buff, int bufflen, int reselect) { - int len = 0; unsigned char *data = NULL; struct scatterlist *buffer = NULL; - int nobuffs = 0; - int clock; - int temp; - -#ifdef SLOW_HANDSHAKE - int borken; /* Does the current target require - Very Slow I/O ? */ -#endif - -#if (DEBUG & PHASE_DATAIN) || (DEBUG & PHASE_DATOUT) - int transfered = 0; - -#endif - -#if (((DEBUG & PHASE_ETC) == PHASE_ETC) || (DEBUG & PRINT_COMMAND) || \ - (DEBUG & PHASE_EXIT)) - int i; - -#endif - -#if ((DEBUG & PHASE_ETC) == PHASE_ETC) - int phase = 0, newphase; + int clock, temp, nobuffs = 0, done = 0, len = 0; + unsigned long flags; +#ifdef DEBUG + int transfered = 0, phase = 0, newphase; #endif - int done = 0; - unsigned char status = 0; - unsigned char message = 0; register unsigned char status_read; + unsigned char tmp_data, tmp_control, status = 0, message = 0; -#ifndef OLDCNTDATASCEME - volatile unsigned char tmp_data; - volatile unsigned char tmp_control; -#endif unsigned transfersize = 0, underflow = 0; +#ifdef SLOW_RATE + int borken = (int) SCint->device->borken; /* Does the current target require + Very Slow I/O ? */ +#endif + incommand = 0; st0x_aborted = 0; -#ifdef SLOW_HANDSHAKE - borken = (int) SCint->device->borken; -#endif - #if (DEBUG & PRINT_COMMAND) printk ("scsi%d : target = %d, command = ", hostno, target); print_command ((unsigned char *) cmnd); - printk ("\n"); #endif #if (DEBUG & PHASE_RESELECT) @@ -864,9 +792,7 @@ static int internal_command (unsigned char target, unsigned char lun, switch (reselect) { case RECONNECT_NOW: -#if (DEBUG & PHASE_RESELECT) - printk ("scsi%d : phase RESELECT \n", hostno); -#endif + DPRINTK ( PHASE_RESELECT, "scsi%d : phase RESELECT \n", hostno); /* * At this point, we should find the logical or of our ID and the original @@ -876,19 +802,14 @@ static int internal_command (unsigned char target, unsigned char lun, * target ID are asserted. A valid initiator ID is not on the bus * until IO is asserted, so we must wait for that. */ - clock = jiffies + 10; - for (;;) - { + ULOOP( 100*1000 ) { temp = STATUS; if ((temp & STAT_IO) && !(temp & STAT_BSY)) break; - if (jiffies > clock) - { -#if (DEBUG & PHASE_RESELECT) - printk ("scsi%d : RESELECT timed out while waiting for IO .\n", - hostno); -#endif + if (TIMEOUT) { + DPRINTK (PHASE_RESELECT, + "scsi%d : RESELECT timed out while waiting for IO .\n", hostno); return (DID_BAD_INTR << 16); } } @@ -900,10 +821,9 @@ static int internal_command (unsigned char target, unsigned char lun, if (!((temp = DATA) & (controller_type == SEAGATE ? 0x80 : 0x40))) { -#if (DEBUG & PHASE_RESELECT) - printk ("scsi%d : detected reconnect request to different target.\n" - "\tData bus = %d\n", hostno, temp); -#endif + DPRINTK (PHASE_RESELECT, + "scsi%d : detected reconnect request to different target.\n" + "\tData bus = %d\n", hostno, temp); return (DID_BAD_INTR << 16); } @@ -936,16 +856,14 @@ static int internal_command (unsigned char target, unsigned char lun, * BSY. */ - for (clock = jiffies + 10; (jiffies < clock) && (STATUS & STAT_SEL);) ; - - if (jiffies >= clock) - { - WRITE_CONTROL (BASE_CMD | CMD_INTR); -#if (DEBUG & PHASE_RESELECT) - printk ("scsi%d : RESELECT timed out while waiting for SEL.\n", - hostno); -#endif - return (DID_BAD_INTR << 16); + ULOOP( 100*1000 ) { + if (!(STATUS & STAT_SEL)) break; + if (TIMEOUT) { + WRITE_CONTROL (BASE_CMD | CMD_INTR); + DPRINTK (PHASE_RESELECT, + "scsi%d : RESELECT timed out while waiting for SEL.\n", hostno); + return (DID_BAD_INTR << 16); + } } WRITE_CONTROL (BASE_CMD); @@ -969,9 +887,7 @@ static int internal_command (unsigned char target, unsigned char lun, #endif -#if (DEBUG & PHASE_BUS_FREE) - printk ("scsi%d : phase = BUS FREE \n", hostno); -#endif + DPRINTK (PHASE_BUS_FREE, "scsi%d : phase = BUS FREE \n", hostno); /* * BUS FREE PHASE @@ -982,12 +898,13 @@ static int internal_command (unsigned char target, unsigned char lun, * eliminate wire glitch. */ +#ifndef ARBITRATE +#error FIXME: this is broken: we may not use jiffies here - we are under cli(). It will hardlock. clock = jiffies + ST0X_BUS_FREE_DELAY; -#if !defined (ARBITRATE) while (((STATUS | STATUS | STATUS) & (STAT_BSY | STAT_SEL)) && - (!st0x_aborted) && (jiffies < clock)) ; + (!st0x_aborted) && (jiffies < clock)); if (jiffies > clock) return retcode (DID_BUS_BUSY); @@ -995,9 +912,7 @@ static int internal_command (unsigned char target, unsigned char lun, return retcode (st0x_aborted); #endif -#if (DEBUG & PHASE_SELECTION) - printk ("scsi%d : phase = SELECTION\n", hostno); -#endif + DPRINTK (PHASE_SELECTION, "scsi%d : phase = SELECTION\n", hostno); clock = jiffies + ST0X_SELECTION_DELAY; @@ -1012,33 +927,27 @@ static int internal_command (unsigned char target, unsigned char lun, * 6. Enable SCSI drivers and asserted SEL and ATTN */ -#if defined(ARBITRATE) - { unsigned long flags; +#ifdef ARBITRATE save_flags (flags); cli (); WRITE_CONTROL (0); WRITE_DATA ((controller_type == SEAGATE) ? 0x80 : 0x40); WRITE_CONTROL (CMD_START_ARB); restore_flags (flags); - } - while (!((status_read = STATUS) & (STAT_ARB_CMPL | STAT_SEL)) && - (jiffies < clock) && !st0x_aborted) ; - if (!(status_read & STAT_ARB_CMPL)) - { -#if (DEBUG & PHASE_SELECTION) - if (status_read & STAT_SEL) - printk ("scsi%d : arbitration lost\n", hostno); - else - printk ("scsi%d : arbitration timeout.\n", hostno); -#endif - WRITE_CONTROL (BASE_CMD); - return retcode (DID_NO_CONNECT); - }; + ULOOP( ST0X_SELECTION_DELAY * 10000 ) { + status_read = STATUS; + if (status_read & STAT_ARB_CMPL) break; + if (st0x_aborted) /* FIXME: What? We are going to do something even after abort? */ + break; + if (TIMEOUT || (status_read & STAT_SEL)) { + printk( "scsi%d : arbitration lost or timeout.\n", hostno ); + WRITE_CONTROL (BASE_CMD); + return retcode (DID_NO_CONNECT); + } + } -#if (DEBUG & PHASE_SELECTION) - printk ("scsi%d : arbitration complete\n", hostno); -#endif + DPRINTK (PHASE_SELECTION, "scsi%d : arbitration complete\n", hostno); #endif /* @@ -1053,81 +962,53 @@ static int internal_command (unsigned char target, unsigned char lun, * try this with a SCSI protocol or logic analyzer to see what is * going on. */ + tmp_data = (unsigned char) ((1 << target) | (controller_type == SEAGATE ? 0x80 : 0x40)); + tmp_control = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | (reselect ? CMD_ATTN : 0); + + save_flags(flags); + cli(); #ifdef OLDCNTDATASCEME #ifdef SWAPCNTDATA - { unsigned long flags; - save_flags(flags); - cli(); - WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | - (reselect ? CMD_ATTN : 0)); - WRITE_DATA ((unsigned char) ((1 << target) | - (controller_type == SEAGATE ? 0x80 : 0x40))); - restore_flags(flags); - } + WRITE_CONTROL (tmp_control); + WRITE_DATA (tmp_data); #else - { unsigned long flags; - save_flags(flags); - cli (); - WRITE_DATA ((unsigned char) ((1 << target) | - (controller_type == SEAGATE ? 0x80 : 0x40))); - WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | - (reselect ? CMD_ATTN : 0)); - restore_flags (flags); - } + WRITE_DATA (tmp_data); + WRITE_CONTROL (tmp_control); #endif #else - tmp_data = (unsigned char) ((1 << target) | (controller_type == SEAGATE -? 0x80 : 0x40)); - tmp_control = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | - (reselect ? CMD_ATTN : 0) | CMD_BSY; - WRITE_CONTROL(tmp_data); - WRITE_DATA(tmp_control); - tmp_control ^= CMD_BSY; - WRITE_CONTROL(tmp_control); -#endif /* OLDCNTDATASCEME */ - while (!((status_read = STATUS) & STAT_BSY) && (jiffies < clock) - && !st0x_aborted) -#if 0 && (DEBUG & PHASE_SELECTION) - { - temp = clock - jiffies; + tmp_control ^= CMD_BSY; /* This is guesswork. What used to be in driver */ + WRITE_CONTROL (tmp_control); /* could never work: it sent data into control */ + WRITE_DATA (tmp_data); /* register and control info into data. Hopefully */ + tmp_control ^= CMD_BSY; /* fixed, but order of first two may be wrong. */ + WRITE_CONTROL (tmp_control); /* -- pavel@ucw.cz */ +#endif - if (!(jiffies % 5)) - printk ("seagate_st0x_timeout : %d \r", temp); - } - printk ("Done. \n"); - printk ("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n", - hostno, status_read, temp, st0x_aborted); -#else - ; -#endif - if ((jiffies >= clock) && !(status_read & STAT_BSY)) - { -#if (DEBUG & PHASE_SELECTION) - printk ("scsi%d : NO CONNECT with target %d, status = %x \n", - hostno, target, STATUS); -#endif - return retcode (DID_NO_CONNECT); - } + restore_flags (flags); + ULOOP( 250*1000 ) { + if (st0x_aborted) { /* * If we have been aborted, and we have a command in progress, IE the * target still has BSY asserted, then we will reset the bus, and * notify the midlevel driver to expect sense. */ - if (st0x_aborted) - { - WRITE_CONTROL (BASE_CMD); - if (STATUS & STAT_BSY) - { - printk ("scsi%d : BST asserted after we've been aborted.\n", - hostno); - seagate_st0x_reset (NULL, 0); - return retcode (DID_RESET); - } - return retcode (st0x_aborted); - } + WRITE_CONTROL (BASE_CMD); + if (STATUS & STAT_BSY) { + printk ("scsi%d : BST asserted after we've been aborted.\n", hostno); + seagate_st0x_reset (NULL, 0); + return retcode (DID_RESET); + } + return retcode (st0x_aborted); + } + if (STATUS & STAT_BSY) break; + if (TIMEOUT) { + DPRINTK (PHASE_SELECTION, "scsi%d : NO CONNECT with target %d, stat = %x \n", + hostno, target, STATUS); + return retcode (DID_NO_CONNECT); + } + } /* Establish current pointers. Take into account scatter / gather */ @@ -1151,17 +1032,13 @@ static int internal_command (unsigned char target, unsigned char lun, } else { -#if (DEBUG & DEBUG_SG) - printk ("scsi%d : scatter gather not requested.\n", hostno); -#endif + DPRINTK (DEBUG_SG, "scsi%d : scatter gather not requested.\n", hostno); buffer = NULL; len = SCint->request_bufflen; data = (unsigned char *) SCint->request_buffer; } -#if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT)) - printk ("scsi%d : len = %d\n", hostno, len); -#endif + DPRINTK (PHASE_DATAIN | PHASE_DATAOUT, "scsi%d : len = %d\n", hostno, len); break; #ifdef LINKED @@ -1205,9 +1082,7 @@ static int internal_command (unsigned char target, unsigned char lun, * */ -#if ((DEBUG & PHASE_ETC) == PHASE_ETC) - printk ("scsi%d : phase = INFORMATION TRANSFER\n", hostno); -#endif + DPRINTK (PHASE_ETC, "scsi%d : phase = INFORMATION TRANSFER\n", hostno); incommand = 1; transfersize = SCint->transfersize; @@ -1271,12 +1146,10 @@ static int internal_command (unsigned char target, unsigned char lun, * in word-sized chunks as fast as we can. */ -#ifdef FAST if (!len) { #if 0 - printk ("scsi%d: underflow to target %d lun %d \n", hostno, - target, lun); + printk ("scsi%d: underflow to target %d lun %d \n", hostno, target, lun); st0x_aborted = DID_ERROR; fast = 0; #endif @@ -1290,11 +1163,10 @@ static int internal_command (unsigned char target, unsigned char lun, #endif ) { -#if (DEBUG & DEBUG_FAST) - printk ("scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" + DPRINTK (DEBUG_FAST, + "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" " len = %d, data = %08x\n", hostno, SCint->underflow, SCint->transfersize, len, data); -#endif /* SJT: Start. Fast Write */ #ifdef SEAGATE_USE_ASM @@ -1332,13 +1204,11 @@ static int internal_command (unsigned char target, unsigned char lun, /* SJT: End */ len -= transfersize; data += transfersize; -#if (DEBUG & DEBUG_FAST) - printk ("scsi%d : FAST transfer complete len = %d data = %08x\n", + DPRINTK (DEBUG_FAST, + "scsi%d : FAST transfer complete len = %d data = %08x\n", hostno, len, data); -#endif } else -#endif /* ifdef FAST */ { /* * We loop as long as we are in a data out phase, there is data to send, @@ -1404,15 +1274,14 @@ static int internal_command (unsigned char target, unsigned char lun, ++buffer; len = buffer->length; data = (unsigned char *) buffer->address; -#if (DEBUG & DEBUG_SG) - printk ("scsi%d : next scatter-gather buffer len = %d address = %08x\n", + DPRINTK (DEBUG_SG, + "scsi%d : next scatter-gather buffer len = %d address = %08x\n", hostno, len, data); -#endif } break; case REQ_DATAIN: -#ifdef SLOW_HANDSHAKE +#ifdef SLOW_RATE if (borken) { #if (DEBUG & (PHASE_DATAIN)) @@ -1432,7 +1301,7 @@ static int internal_command (unsigned char target, unsigned char lun, } else #endif -#ifdef FAST + if (fast && transfersize && !(len % transfersize) && (len >= transfersize) #ifdef FAST32 @@ -1440,11 +1309,11 @@ static int internal_command (unsigned char target, unsigned char lun, #endif ) { -#if (DEBUG & DEBUG_FAST) - printk ("scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" + DPRINTK (DEBUG_FAST, + "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" " len = %d, data = %08x\n", hostno, SCint->underflow, SCint->transfersize, len, data); -#endif + /* SJT: Start. Fast Read */ #ifdef SEAGATE_USE_ASM __asm__( @@ -1486,13 +1355,11 @@ static int internal_command (unsigned char target, unsigned char lun, transfered += transfersize; #endif -#if (DEBUG & DEBUG_FAST) - printk ("scsi%d : FAST transfer complete len = %d data = %08x\n", + DPRINTK (DEBUG_FAST, + "scsi%d : FAST transfer complete len = %d data = %08x\n", hostno, len, data); -#endif } else -#endif { #if (DEBUG & PHASE_DATAIN) @@ -1571,10 +1438,9 @@ static int internal_command (unsigned char target, unsigned char lun, ++buffer; len = buffer->length; data = (unsigned char *) buffer->address; -#if (DEBUG & DEBUG_SG) - printk ("scsi%d : next scatter-gather buffer len = %d address = %08x\n", + DPRINTK (DEBUG_SG, + "scsi%d : next scatter-gather buffer len = %d address = %08x\n", hostno, len, data); -#endif } break; @@ -1586,7 +1452,7 @@ static int internal_command (unsigned char target, unsigned char lun, { WRITE_DATA (*(const unsigned char *) cmnd); cmnd = 1 + (const unsigned char *) cmnd; -#ifdef SLOW_HANDSHAKE +#ifdef SLOW_RATE if (borken) borken_wait (); #endif @@ -1613,9 +1479,7 @@ static int internal_command (unsigned char target, unsigned char lun, case CAN_RECONNECT: WRITE_DATA (IDENTIFY (1, lun)); -#if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT)) - printk ("scsi%d : sent IDENTIFY message.\n", hostno); -#endif + DPRINTK (PHASE_RESELECT | PHASE_MSGOUT, "scsi%d : sent IDENTIFY message.\n", hostno); break; #ifdef LINKED case LINKED_WRONG: @@ -1623,13 +1487,10 @@ static int internal_command (unsigned char target, unsigned char lun, linked_connected = 0; reselect = CAN_RECONNECT; goto connect_loop; -#if (DEBUG & (PHASE_MSGOUT | DEBUG_LINKED)) - printk ("scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.\n", hostno); -#endif + DPRINTK (PHASE_MSGOUT | DEBUG_LINKED, + "scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.\n", hostno); #endif /* LINKED */ -#if (DEBUG & DEBUG_LINKED) - printk ("correct\n"); -#endif + DPRINTK (DEBUG_LINKED, "correct\n"); default: WRITE_DATA (NOP); printk ("scsi%d : target %d requested MSGOUT, sent NOP message.\n", hostno, target); @@ -1640,6 +1501,7 @@ static int internal_command (unsigned char target, unsigned char lun, switch (message = DATA) { case DISCONNECT: + DANY ("seagate: deciding to disconnect\n"); should_reconnect = 1; current_data = data; /* WDE add */ current_buffer = buffer; @@ -1649,9 +1511,7 @@ static int internal_command (unsigned char target, unsigned char lun, linked_connected = 0; #endif done = 1; -#if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN)) - printk ("scsi%d : disconnected.\n", hostno); -#endif + DPRINTK ((PHASE_RESELECT | PHASE_MSGIN), "scsi%d : disconnected.\n", hostno); break; #ifdef LINKED @@ -1662,15 +1522,11 @@ static int internal_command (unsigned char target, unsigned char lun, /* * Note : we should check for underflow here. */ -#if (DEBUG & PHASE_MSGIN) - printk ("scsi%d : command complete.\n", hostno); -#endif + DPRINTK (PHASE_MSGIN, "scsi%d : command complete.\n", hostno); done = 1; break; case ABORT: -#if (DEBUG & PHASE_MSGIN) - printk ("scsi%d : abort message.\n", hostno); -#endif + DPRINTK (PHASE_MSGIN, "scsi%d : abort message.\n", hostno); done = 1; break; case SAVE_POINTERS: @@ -1678,9 +1534,7 @@ static int internal_command (unsigned char target, unsigned char lun, current_bufflen = len; /* WDE add */ current_data = data; /* WDE mod */ current_nobuffs = nobuffs; -#if (DEBUG & PHASE_MSGIN) - printk ("scsi%d : pointers saved.\n", hostno); -#endif + DPRINTK (PHASE_MSGIN, "scsi%d : pointers saved.\n", hostno); break; case RESTORE_POINTERS: buffer = current_buffer; @@ -1688,15 +1542,13 @@ static int internal_command (unsigned char target, unsigned char lun, data = current_data; /* WDE mod */ len = current_bufflen; nobuffs = current_nobuffs; -#if (DEBUG & PHASE_MSGIN) - printk ("scsi%d : pointers restored.\n", hostno); -#endif + DPRINTK (PHASE_MSGIN, "scsi%d : pointers restored.\n", hostno); break; default: /* * IDENTIFY distinguishes itself from the other messages by setting the - * high byte. + * high byte. [FIXME: should not this read "the high bit"? - pavel@ucw.cz] * * Note : we need to handle at least one outstanding command per LUN, * and need to hash the SCSI command for that I_T_L nexus based on the @@ -1705,10 +1557,8 @@ static int internal_command (unsigned char target, unsigned char lun, if (message & 0x80) { -#if (DEBUG & PHASE_MSGIN) - printk ("scsi%d : IDENTIFY message received from id %d, lun %d.\n", + DPRINTK (PHASE_MSGIN, "scsi%d : IDENTIFY message received from id %d, lun %d.\n", hostno, target, message & 7); -#endif } else { @@ -1719,10 +1569,8 @@ static int internal_command (unsigned char target, unsigned char lun, * needs some serious restructuring first though. */ -#if (DEBUG & PHASE_MSGIN) - printk ("scsi%d : unknown message %d from target %d.\n", - hostno, message, target); -#endif + DPRINTK (PHASE_MSGIN, + "scsi%d : unknown message %d from target %d.\n", hostno, message, target); } } break; @@ -1733,7 +1581,7 @@ static int internal_command (unsigned char target, unsigned char lun, } /* end of switch (status_read & REQ_MASK) */ -#ifdef SLOW_HANDSHAKE +#ifdef SLOW_RATE /* * I really don't care to deal with borken devices in each single * byte transfer case (ie, message in, message out, status), so @@ -1747,9 +1595,8 @@ static int internal_command (unsigned char target, unsigned char lun, } /* while(((status_read = STATUS)...) ends */ -#if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT)) - printk ("scsi%d : Transfered %d bytes\n", hostno, transfered); -#endif + DPRINTK (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT, + "scsi%d : Transfered %d bytes\n", hostno, transfered); #if (DEBUG & PHASE_EXIT) #if 0 /* Doesn't work for scatter/gather */ @@ -1764,17 +1611,6 @@ static int internal_command (unsigned char target, unsigned char lun, #endif /* We shouldn't reach this until *after* BSY has been deasserted */ -#ifdef notyet - if (st0x_aborted) - { - if (STATUS & STAT_BSY) - { - seagate_st0x_reset (NULL); - st0x_aborted = DID_RESET; - } - abort_confirm = 1; - } -#endif #ifdef LINKED else @@ -1797,10 +1633,8 @@ static int internal_command (unsigned char target, unsigned char lun, linked_target = current_target; linked_lun = current_lun; linked_connected = 1; -#if (DEBUG & DEBUG_LINKED) - printk ("scsi%d : keeping I_T_L nexus established for linked command.\n", - hostno); -#endif + DPRINTK (DEBUG_LINKED, "scsi%d : keeping I_T_L nexus established" + "for linked command.\n", hostno); /* We also will need to adjust status to accommodate intermediate conditions. */ if ((status == INTERMEDIATE_GOOD) || @@ -1814,9 +1648,7 @@ static int internal_command (unsigned char target, unsigned char lun, * and flake if things aren't right. */ default: -#if (DEBUG & DEBUG_LINKED) - printk ("scsi%d : closing I_T_L nexus.\n", hostno); -#endif + DPRINTK (DEBUG_LINKED, "scsi%d : closing I_T_L nexus.\n", hostno); linked_connected = 0; } } @@ -1824,10 +1656,8 @@ static int internal_command (unsigned char target, unsigned char lun, if (should_reconnect) { -#if (DEBUG & PHASE_RESELECT) - printk ("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n", - hostno); -#endif + DPRINTK (PHASE_RESELECT, "scsi%d : exiting seagate_st0x_queue_command()" + "with reconnect enabled.\n", hostno); WRITE_CONTROL (BASE_CMD | CMD_INTR); } else @@ -1841,32 +1671,27 @@ int seagate_st0x_abort (Scsi_Cmnd * SCpnt) st0x_aborted = DID_ABORT; return SCSI_ABORT_PENDING; } +#undef ULOOP +#undef TIMEOUT /* - the seagate_st0x_reset function resets the SCSI bus */ + * the seagate_st0x_reset function resets the SCSI bus + */ int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags) { - unsigned clock; - /* No timeouts - this command is going to fail because it was reset. */ -#ifdef DEBUG - printk ("In seagate_st0x_reset()\n"); -#endif + DANY ("scsi%d: Reseting bus... ", hostno ); /* assert RESET signal on SCSI bus. */ WRITE_CONTROL (BASE_CMD | CMD_RST); - clock = jiffies + 2; -/* Wait. */ - while (jiffies < clock) ; + udelay( 20*1000 ); WRITE_CONTROL (BASE_CMD); st0x_aborted = DID_RESET; -#ifdef DEBUG - printk ("SCSI bus reset.\n"); -#endif + DANY ("done.\n"); return SCSI_RESET_WAKEUP; } diff --git a/drivers/scsi/seagate.h b/drivers/scsi/seagate.h index 2d07fd9a7..c8ead00c4 100644 --- a/drivers/scsi/seagate.h +++ b/drivers/scsi/seagate.h @@ -20,10 +20,6 @@ int seagate_st0x_abort(Scsi_Cmnd *); const char *seagate_st0x_info(struct Scsi_Host *); int seagate_st0x_reset(Scsi_Cmnd *, unsigned int); -#ifndef NULL - #define NULL 0 -#endif - #include int seagate_st0x_biosparam(Disk *, kdev_t, int*); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 4232a56a5..8eb3894cd 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -574,6 +574,7 @@ static struct file_operations sg_fops = { sg_ioctl, /* ioctl */ NULL, /* mmap */ sg_open, /* open */ + NULL, /* flush */ sg_close, /* release */ NULL /* fsync */ }; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index a0adf83b3..38b05c29a 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3162,6 +3162,7 @@ static struct file_operations st_fops = { st_ioctl, /* ioctl */ NULL, /* mmap */ scsi_tape_open, /* open */ + NULL, /* flush */ scsi_tape_close, /* release */ NULL /* fsync */ }; diff --git a/drivers/sgi/char/graphics.c b/drivers/sgi/char/graphics.c index b7e69b243..80803da81 100644 --- a/drivers/sgi/char/graphics.c +++ b/drivers/sgi/char/graphics.c @@ -274,6 +274,7 @@ struct file_operations sgi_graphics_fops = { sgi_graphics_ioctl, /* ioctl */ sgi_graphics_mmap, /* mmap */ sgi_graphics_open, /* open */ + NULL, /* flush */ sgi_graphics_close, /* release */ NULL, /* fsync */ NULL, /* check_media_change */ diff --git a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c index 81d43617a..6a41d0ae0 100644 --- a/drivers/sgi/char/shmiq.c +++ b/drivers/sgi/char/shmiq.c @@ -445,6 +445,7 @@ file_operations shmiq_fops = shmiq_qcntl_ioctl, /* ioctl */ shmiq_qcntl_mmap, /* mmap */ shmiq_qcntl_open, /* open */ + NULL, /* flush */ shmiq_qcntl_close, /* close */ NULL, /* fsync */ shmiq_qcntl_fasync, /* fasync */ diff --git a/drivers/sgi/char/streamable.c b/drivers/sgi/char/streamable.c index f26aad0e2..a1f4b07b2 100644 --- a/drivers/sgi/char/streamable.c +++ b/drivers/sgi/char/streamable.c @@ -79,6 +79,7 @@ struct file_operations sgi_gfx_fops = { sgi_gfx_ioctl, /* ioctl */ NULL, /* mmap */ sgi_gfx_open, /* open */ + NULL, /* flush */ sgi_gfx_close, /* release */ NULL, /* fsync */ NULL, /* check_media_change */ @@ -199,6 +200,7 @@ struct file_operations sgi_keyb_fops = { sgi_keyb_ioctl, /* ioctl */ NULL, /* mmap */ sgi_keyb_open, /* open */ + NULL, /* flush */ NULL, /* release */ NULL, /* fsync */ NULL, /* check_media_change */ @@ -339,6 +341,7 @@ struct file_operations sgi_mouse_fops = { sgi_mouse_ioctl, /* ioctl */ NULL, /* mmap */ sgi_mouse_open, /* open */ + NULL, /* flush */ sgi_mouse_close, /* release */ NULL, /* fsync */ NULL, /* check_media_change */ diff --git a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c index 4ca11db51..5bf0e4ee7 100644 --- a/drivers/sgi/char/usema.c +++ b/drivers/sgi/char/usema.c @@ -172,6 +172,7 @@ struct file_operations sgi_usemaclone_fops = { sgi_usemaclone_ioctl, /* ioctl */ NULL, /* mmap */ sgi_usemaclone_open, /* open */ + NULL, /* flush */ sgi_usemaclone_release, /* release */ NULL, /* fsync */ NULL, /* check_media_change */ diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index 95a89cdb6..ae125308d 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -156,7 +156,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then dep_tristate 'Support for Crystal CS4232 based (PnP) cards' CONFIG_SOUND_CS4232 $CONFIG_SOUND_OSS if [ "$CONFIG_SOUND_CS4232" = "y" ]; then - hex 'CS4232 audio I/O base 530, 604, E80 or F40' CONFIG_CS4232_BASE 530 + hex 'CS4232 audio I/O base (normally 530, 604, E80 or F40)' CONFIG_CS4232_BASE 530 int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_IRQ 11 int 'CS4232 audio DMA 0, 1 or 3' CONFIG_CS4232_DMA 0 int 'CS4232 second (duplex) DMA 0, 1 or 3' CONFIG_CS4232_DMA2 3 diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c index f944252bf..b351c73db 100644 --- a/drivers/sound/dmasound.c +++ b/drivers/sound/dmasound.c @@ -3808,6 +3808,7 @@ static struct file_operations mixer_fops = mixer_ioctl, NULL, /* mixer_mmap */ mixer_open, + NULL, /* flush */ mixer_release, }; @@ -4169,6 +4170,7 @@ static struct file_operations sq_fops = sq_ioctl, NULL, /* sq_mmap */ sq_open, + NULL, /* flush */ sq_release, }; @@ -4363,6 +4365,7 @@ static struct file_operations state_fops = NULL, /* state_ioctl */ NULL, /* state_mmap */ state_open, + NULL, /* flush */ state_release, }; diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c index 2e6abb3d6..90d12d84b 100644 --- a/drivers/sound/es1370.c +++ b/drivers/sound/es1370.c @@ -977,6 +977,7 @@ static /*const*/ struct file_operations es1370_mixer_fops = { &es1370_ioctl_mixdev, NULL, /* mmap */ &es1370_open_mixdev, + NULL, /* flush */ &es1370_release_mixdev, NULL, /* fsync */ NULL, /* fasync */ @@ -1626,6 +1627,7 @@ static /*const*/ struct file_operations es1370_audio_fops = { &es1370_ioctl, &es1370_mmap, &es1370_open, + NULL, /* flush */ &es1370_release, NULL, /* fsync */ NULL, /* fasync */ @@ -1992,6 +1994,7 @@ static /*const*/ struct file_operations es1370_dac_fops = { &es1370_ioctl_dac, &es1370_mmap_dac, &es1370_open_dac, + NULL, /* flush */ &es1370_release_dac, NULL, /* fsync */ NULL, /* fasync */ @@ -2228,6 +2231,7 @@ static /*const*/ struct file_operations es1370_midi_fops = { NULL, /* ioctl */ NULL, /* mmap */ &es1370_midi_open, + NULL, /* flush */ &es1370_midi_release, NULL, /* fsync */ NULL, /* fasync */ diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index 6a510d9d4..4963d1271 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -1425,6 +1425,7 @@ static /*const*/ struct file_operations es1371_mixer_fops = { &es1371_ioctl_mixdev, NULL, /* mmap */ &es1371_open_mixdev, + NULL, /* flush */ &es1371_release_mixdev, NULL, /* fsync */ NULL, /* fasync */ @@ -2072,6 +2073,7 @@ static /*const*/ struct file_operations es1371_audio_fops = { &es1371_ioctl, &es1371_mmap, &es1371_open, + NULL, /* flush */ &es1371_release, NULL, /* fsync */ NULL, /* fasync */ @@ -2428,6 +2430,7 @@ static /*const*/ struct file_operations es1371_dac_fops = { &es1371_ioctl_dac, &es1371_mmap_dac, &es1371_open_dac, + NULL, /* flush */ &es1371_release_dac, NULL, /* fsync */ NULL, /* fasync */ @@ -2663,6 +2666,7 @@ static /*const*/ struct file_operations es1371_midi_fops = { NULL, /* ioctl */ NULL, /* mmap */ &es1371_midi_open, + NULL, /* flush */ &es1371_midi_release, NULL, /* fsync */ NULL, /* fasync */ diff --git a/drivers/sound/lowlevel/README b/drivers/sound/lowlevel/README index 86c93b55b..76fba8dee 100644 --- a/drivers/sound/lowlevel/README +++ b/drivers/sound/lowlevel/README @@ -11,7 +11,8 @@ Hannu Savolainen (hannu@voxware.pp.fi) for more info. The following low level drivers are included: - ACI MIXER for miroPCM12 by Markus Kuhn -(mskuhn@cip.informatik.uni-erlangen.de). + (mskuhn@cip.informatik.uni-erlangen.de). +- Audio Excel DSP 16 initialization driver by Riccardo Facchetti + (fizban@tin.it) - SB32/AWE synthesizer driver (Emu8000) by Takashi Iwai -(iwai@dragon.mm.t.u-tokyo.ac.jp). See README.awe for more -info. + (iwai@dragon.mm.t.u-tokyo.ac.jp). See README.awe for more info. diff --git a/drivers/sound/lowlevel/README.aedsp16 b/drivers/sound/lowlevel/README.aedsp16 deleted file mode 100644 index 8f5b05afd..000000000 --- a/drivers/sound/lowlevel/README.aedsp16 +++ /dev/null @@ -1,137 +0,0 @@ -Driver ------- - -Informations about Audio Excel DSP 16 driver can be found in the source -file lowlevel/aedsp16.c -Please, read the head of the source before using it. It contain useful -informations. - -Configuration -------------- - -The Audio Excel configuration, is now done with the standard Linux setup. -You have to configure the sound card (Sound Blaster or Microsoft Sound System) -and, if you want it, the Roland MPU-401 (do not use the Sound Blaster MPU-401, -SB-MPU401) in the main driver menu. Activate the lowlevel drivers then select -the Audio Excel hardware that you want to initialize. Check the IRQ/DMA/MIRQ -of the Audio Excel initialization: it must be the same as the SBPRO (or MSS) -setup. If the parameters are different, correct it. -I you own a Gallant's audio card based on SC-6600, activate the SC-6600 support. -If you want to change the configuration of the sound board, be sure to -check off all the configuration items before re-configure it. - -Module parameters ------------------ -To use this driver as a module, you must configure some module parameters, to -set up I/O addresses, IRQ lines and DMA channels. Some parameters are -mandatory while some others are optional. Here a list of parameters you can -use with this module: - -Name Description -==== =========== -MANDATORY -io I/O base address (0x220 or 0x240) -irq irq line (5, 7, 9, 10 or 11) -dma dma channel (0, 1 or 3) - -OPTIONAL -mss_base I/O base address for activate MSS mode (default SBPRO) - (0x530 or 0xE80) -mpu_base I/O base address for activate MPU-401 mode - (0x300, 0x310, 0x320 or 0x330) -mpu_irq MPU-401 irq line (5, 7, 9, 10 or 0) - -The /etc/conf.modules will have a line like this: - -options aedsp16 io=0x220 irq=10 dma=3 mss_base=0x530 - -Of course, you must write the 'options' for all other subsequent modules, -opl3, ad1848, adlib_card, sb - -Then you must load the sound modules stack in this order: -sound -> aedsp16 -> [ ad1848, opl3 ] - -Sound cards supported ---------------------- -This driver supports the SC-6000 and SC-6600 based Gallant's sound card. -It don't support the Audio Excel DSP 16 III (try the SC-6600 code). -I'm working on the III version of the card: if someone have useful -informations about it, please let me know. -For all the non-supported audio cards, you have to boot MS-DOS (or WIN95) -activating the audio card with the MS-DOS device driver, then you have to --- and boot Linux. -Follow these steps: - -1) Compile Linux kernel with standard sound driver, using the emulation - you want, with the parameters of your audio card, - e.g. Microsoft Sound System irq10 dma3 -2) Install your new kernel as the default boot kernel. -3) Boot MS-DOS and configure the audio card with the boot time device - driver, for MSS irq10 dma3 in our example. -4) -- and boot Linux. This will mantain the DOS configuration - and will boot the new kernel with sound driver. The sound driver will find - the audio card and will recognize and attach it. - -Reports on User successes -------------------------- - -[--------------------------------------------------------------------------] - -From POPmail Mon Jul 29 18:23:12 1996 -Received: from cdc8g5.cdc.polimi.it by mbox.vol.it with SMTP - (1.39.111.2/16.2) id AA257995686; Mon, 29 Jul 1996 09:34:46 +0200 -Return-Path: -Received: from [130.246.12.16] by cdc8g5.cdc.polimi.it with SMTP - (1.38.193.4/15.6) id AA27426; Mon, 29 Jul 1996 09:42:49 +0200 -Posted-Date: Mon, 29 Jul 1996 08:35:40 +0100 -Received-Date: Mon, 29 Jul 1996 09:42:49 +0200 -Received: (from sjg95@localhost) by unixfe.rl.ac.uk (8.7.3/8.7.3) - id IAA58788 for riccardo@cdc8g5.cdc.polimi.it; Mon, 29 Jul 1996 08:35:40 +0100 -Date: Mon, 29 Jul 1996 08:35:40 +0100 -From: Mr S J Greenaway -Message-Id: <199607290735.IAA58788@unixfe.rl.ac.uk> -To: riccardo@cdc8g5.cdc.polimi.it (Riccardo Facchetti) -Subject: Re: Audio Excel DSP 16 initialization code -Newsgroups: comp.os.linux.announce -X-Newsreader: TIN [version 1.2 PL2] -Status: RO -X-Status: A - -Just to let you know got my Audio Excel (emulating a MSS) working -with my original SB16, thanks for the driver! - -/dev/sndstat: - -Linux huey 2.0.9 #10 Sat Jul 27 11:41:42 BST 1996 i586) -Kernel: Linux huey 2.0.9 #14 Sun Jul 28 12:50:43 BST 1996 i586 -Config options: c0202 - -Installed drivers: -Type 10: MS Sound System -Type 24: MS Sound System (AXP) -Type 27: Compaq Deskpro XL -Type 2: Sound Blaster - -Card config: -MS Sound System at 0x530 irq 11 drq 3 -Sound Blaster at 0x240 irq 5 drq 1,5 - -Audio devices: -0: MSS audio codec (CS4231A) -1: Sound Blaster 16 (4.12) - -Synth devices: - -Midi devices: NOT ENABLED IN CONFIG - -Timers: -0: System clock -1: MSS audio codec (CS4231A) - -Mixers: -0: MSS audio codec (CS4231A) -1: Sound Blaster - -[--------------------------------------------------------------------------] - - Riccardo diff --git a/drivers/sound/lowlevel/aci.c b/drivers/sound/lowlevel/aci.c index b98c02ea6..fc71be47d 100644 --- a/drivers/sound/lowlevel/aci.c +++ b/drivers/sound/lowlevel/aci.c @@ -4,17 +4,21 @@ * ACI is a protocol used to communicate with the microcontroller on * some sound cards produced by miro, e.g. the miroSOUND PCM12 and * PCM20. The ACI has been developed for miro by Norberto Pellicci - * . Special thanks to both him and miro for + * . Special thanks to both him and miro for * providing the ACI specification. * * The main function of the ACI is to control the mixer and to get a * product identification. On the PCM20, ACI also controls the radio - * tuner on this card, however this is not yet supported in this - * software. + * tuner on this card, this is supported in the Video for Linux + * radio-miropcm20 driver. * * This Voxware ACI driver currently only supports the ACI functions - * on the miroSOUND PCM12 card. Support for miro sound cards with - * additional ACI functions can easily be added later. + * on the miroSOUND PCM12 and PCM20 card. Support for miro sound cards + * with additional ACI functions can easily be added later. + * + * / NOTE / When compiling as a module, make sure to load the module + * after loading the mad16 module. The initialisation code expects the + * MAD16 default mixer to be already available. * * / NOTE / When compiling as a module, make sure to load the module * after loading the mad16 module. The initialisation code expects the @@ -31,8 +35,9 @@ * 1996-05-28 Markus Kuhn * Initialize CS4231A mixer, make ACI first mixer, * use new private mixer API for solo mode. - * 1998-08-04 Ruurd Reitsma - * Small modification to complete modularisation. + * 1998-08-18 Ruurd Reitsma + * Small modification to export ACI functions and + * complete modularisation. */ /* @@ -84,7 +89,7 @@ static int aci_present = 0; #ifdef MODULE /* Whether the aci mixer is to be reset. */ int aci_reset = 0; /* Default: don't reset if the driver is a */ MODULE_PARM(aci_reset,"i"); -#else /* module; use "insmod sound.o aci_reset=1" */ +#else /* module; use "insmod aci.o aci_reset=1" */ int aci_reset = 1; /* to override. */ #endif @@ -150,12 +155,12 @@ static int read_general_status(void) * If a problem occurred, they return -1. */ -static int implied_cmd(unsigned char opcode) +int aci_implied_cmd(unsigned char opcode) { unsigned long flags; #ifdef DEBUG - printk("ACI: implied_cmd(0x%02x)\n", opcode); + printk("ACI: aci_implied_cmd(0x%02x)\n", opcode); #endif save_flags(flags); @@ -172,13 +177,13 @@ static int implied_cmd(unsigned char opcode) } -static int write_cmd(unsigned char opcode, unsigned char parameter) +int aci_write_cmd(unsigned char opcode, unsigned char parameter) { unsigned long flags; int status; #ifdef DEBUG - printk("ACI: write_cmd(0x%02x, 0x%02x)\n", opcode, parameter); + printk("ACI: aci_write_cmd(0x%02x, 0x%02x)\n", opcode, parameter); #endif save_flags(flags); @@ -209,8 +214,53 @@ static int write_cmd(unsigned char opcode, unsigned char parameter) return 0; } +/* + * This write command send 2 parameters instead of one. + * Only used in PCM20 radio frequency tuning control + */ + +int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2) +{ + unsigned long flags; + int status; + +#ifdef DEBUG + printk("ACI: aci_write_cmd_d(0x%02x, 0x%02x)\n", opcode, parameter, parameter2); +#endif + + save_flags(flags); + cli(); + + if (read_general_status() < 0 || busy_wait()) { + restore_flags(flags); + return -1; + } + outb_p(opcode, COMMAND_REGISTER); + if (busy_wait()) { restore_flags(flags); return -1; } + outb_p(parameter, COMMAND_REGISTER); + if (busy_wait()) { restore_flags(flags); return -1; } + outb_p(parameter2, COMMAND_REGISTER); + + if ((status = read_general_status()) < 0) { + restore_flags(flags); + return -1; + } + /* polarity of the INVALID flag depends on ACI version */ + if ((aci_version < 0xb0 && (status & 0x40) != 0) || + (aci_version >= 0xb0 && (status & 0x40) == 0)) { + restore_flags(flags); +#if 0 /* Frequency tuning works, but the INVALID flag is set ??? */ + printk("ACI: invalid write (double) command 0x%02x, 0x%02x, 0x%02x.\n", + opcode, parameter, parameter2); +#endif + return -1; + } + + restore_flags(flags); + return 0; +} -static int read_cmd(unsigned char opcode, int length, unsigned char *parameter) +int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter) { unsigned long flags; int i = 0; @@ -226,10 +276,10 @@ static int read_cmd(unsigned char opcode, int length, unsigned char *parameter) parameter[i++] = inb_p(STATUS_REGISTER); #ifdef DEBUG if (i == 1) - printk("ACI: read_cmd(0x%02x, %d) = 0x%02x\n", opcode, length, + printk("ACI: aci_read_cmd(0x%02x, %d) = 0x%02x\n", opcode, length, parameter[i-1]); else - printk("ACI: read_cmd cont.: 0x%02x\n", parameter[i-1]); + printk("ACI: aci_read_cmd cont.: 0x%02x\n", parameter[i-1]); #endif } @@ -238,7 +288,7 @@ static int read_cmd(unsigned char opcode, int length, unsigned char *parameter) } -static int indexed_cmd(unsigned char opcode, unsigned char index, +int aci_indexed_cmd(unsigned char opcode, unsigned char index, unsigned char *parameter) { unsigned long flags; @@ -256,7 +306,7 @@ static int indexed_cmd(unsigned char opcode, unsigned char index, if (busy_wait()) { restore_flags(flags); return -1; } *parameter = inb_p(STATUS_REGISTER); #ifdef DEBUG - printk("ACI: indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index, + printk("ACI: aci_indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index, *parameter); #endif @@ -292,10 +342,10 @@ static int getvolume(caddr_t arg, unsigned char buf; /* left channel */ - if (indexed_cmd(0xf0, left_index, &buf)) return -EIO; + if (aci_indexed_cmd(0xf0, left_index, &buf)) return -EIO; vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0); /* right channel */ - if (indexed_cmd(0xf0, right_index, &buf)) return -EIO; + if (aci_indexed_cmd(0xf0, right_index, &buf)) return -EIO; vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8; return (*(int *) arg = vol); @@ -311,13 +361,13 @@ static int setvolume(caddr_t arg, vol = *(int *)arg & 0xff; if (vol > 100) vol = 100; vol = SCALE(100, 0x20, vol); - if (write_cmd(left_index, 0x20 - vol)) return -EIO; + if (aci_write_cmd(left_index, 0x20 - vol)) return -EIO; ret = SCALE(0x20, 100, vol); /* right channel */ vol = (*(int *)arg >> 8) & 0xff; if (vol > 100) vol = 100; vol = SCALE(100, 0x20, vol); - if (write_cmd(right_index, 0x20 - vol)) return -EIO; + if (aci_write_cmd(right_index, 0x20 - vol)) return -EIO; ret |= SCALE(0x20, 100, vol) << 8; return (*(int *) arg = ret); @@ -334,7 +384,7 @@ aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) if (cmd == SOUND_MIXER_PRIVATE1) { if (*(int *) arg >= 0) { aci_solo = !!*(int *) arg; - if (write_cmd(0xd2, aci_solo)) return -EIO; + if (aci_write_cmd(0xd2, aci_solo)) return -EIO; } else if (aci_version >= 0xb0) { if ((status = read_general_status()) < 0) return -EIO; return (*(int *) arg = (status & 0x20) == 0); @@ -366,7 +416,7 @@ aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) vol = *(int *) arg & 0xff; if (vol > 100) vol = 100; vol = SCALE(100, 3, vol); - if (write_cmd(0x03, vol)) return -EIO; + if (aci_write_cmd(0x03, vol)) return -EIO; vol = SCALE(3, 100, vol); return (*(int *) arg = vol | (vol << 8)); case SOUND_MIXER_RECSRC: @@ -421,7 +471,7 @@ aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) case SOUND_MIXER_LINE2: /* AUX2 */ return getvolume(arg, 0x13, 0x12); case SOUND_MIXER_IGAIN: /* MIC pre-amp */ - if (indexed_cmd(0xf0, 0x21, &buf)) return -EIO; + if (aci_indexed_cmd(0xf0, 0x21, &buf)) return -EIO; vol = SCALE(3, 100, buf <= 3 ? buf : 3); vol |= vol << 8; return (*(int *) arg = vol); @@ -485,13 +535,13 @@ int attach_aci(void) return 0; } - if (read_cmd(0xf2, 2, aci_idcode)) { + if (aci_read_cmd(0xf2, 2, aci_idcode)) { #ifdef DEBUG printk("ACI: Failed to read idcode.\n"); #endif return 0; } - if (read_cmd(0xf1, 1, &aci_version)) { + if (aci_read_cmd(0xf1, 1, &aci_version)) { #ifdef DEBUG printk("ACI: Failed to read version.\n"); #endif @@ -523,7 +573,7 @@ int attach_aci(void) if (aci_reset) { /* initialize ACI mixer */ - implied_cmd(0xff); + aci_implied_cmd(0xff); aci_solo = 0; } diff --git a/drivers/sound/lowlevel/aedsp16.c b/drivers/sound/lowlevel/aedsp16.c index cb919507e..48ef93f19 100644 --- a/drivers/sound/lowlevel/aedsp16.c +++ b/drivers/sound/lowlevel/aedsp16.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "../sound_config.h" #include "../soundmodule.h" @@ -248,6 +249,10 @@ the flexibility of modular version, I have removed all the conditional compilation for SBPRO, MPU and MSS code. Now it is all managed with the ae_config structure. + v1.2 + - Module informations added. + - Removed aedsp16_delay_10msec(), now using mdelay(10) + - All data and funcs moved to .*.init section. Known Problems: - Audio Excel DSP 16 III don't work with this driver. @@ -259,7 +264,7 @@ */ -#define VERSION "1.1" /* Version of Audio Excel DSP 16 driver */ +#define VERSION "1.2" /* Version of Audio Excel DSP 16 driver */ #undef AEDSP16_DEBUG 1 /* Define this to enable debug code */ #undef AEDSP16_DEBUG_MORE 1 /* Define this to enable more debug */ @@ -421,14 +426,14 @@ #define INIT_MSS (1<<1) #define INIT_MPU401 (1<<2) -static int soft_cfg = 0; /* Will contain or'ed values of soft cf */ -static int soft_cfg_1 = 0; /* Will contain or'ed values of some cf */ -static int gc = 0; /* generic counter (utility counter) */ -static int ver[3]; /* DSP Version, hi<-ver[0], lo<-ver[1] */ +static int soft_cfg __initdata = 0; /* bitmapped config */ +static int soft_cfg_mss __initdata = 0; /* bitmapped mss config */ +static int ver[CARDVERLEN] __initdata = {0, 0}; /* DSP Ver: + hi->ver[0] lo->ver[1] */ #if defined(CONFIG_SC6600) static int hard_cfg[2] /* lo<-hard_cfg[0] hi<-hard_cfg[1] */ - = { 0, 0}; + __initdata = { 0, 0}; #endif /* CONFIG_SC6600 */ #if defined(CONFIG_SC6600) @@ -440,7 +445,10 @@ struct d_hcfg { int wssbase; int cdrom; int cdrombase; -} decoded_hcfg; +}; + +struct d_hcfg decoded_hcfg __initdata = {0, }; + #endif /* CONFIG_SC6600 */ /* orVals contain the values to be or'ed */ @@ -464,7 +472,7 @@ struct aedsp16_info { * Magic values that the DSP will eat when configuring irq/mirq/dma */ /* DSP IRQ conversion array */ -static struct orVals orIRQ[] = { +static struct orVals orIRQ[] __initdata = { {0x05, 0x28}, {0x07, 0x08}, {0x09, 0x10}, @@ -474,7 +482,7 @@ static struct orVals orIRQ[] = { }; /* MPU-401 IRQ conversion array */ -static struct orVals orMIRQ[] = { +static struct orVals orMIRQ[] __initdata = { {0x05, 0x04}, {0x07, 0x44}, {0x09, 0x84}, @@ -483,14 +491,14 @@ static struct orVals orMIRQ[] = { }; /* DMA Channels conversion array */ -static struct orVals orDMA[] = { +static struct orVals orDMA[] __initdata = { {0x00, 0x01}, {0x01, 0x02}, {0x03, 0x03}, {0x00, 0x00} }; -static struct aedsp16_info ae_config = { +static struct aedsp16_info ae_config __initdata = { DEF_AEDSP16_IOB, DEF_AEDSP16_IRQ, DEF_AEDSP16_MRQ, @@ -503,16 +511,10 @@ static struct aedsp16_info ae_config = { /* * Buffers to store audio card informations */ -static char DSPCopyright[CARDNAMELEN + 1]; -static char DSPVersion[CARDVERLEN + 1]; +static char DSPCopyright[CARDNAMELEN + 1] __initdata = {0, }; +static char DSPVersion[CARDVERLEN + 1] __initdata = {0, }; -static void aedsp16_delay_10msec(void) -{ - for (gc = 0; gc < 1000; gc++) - udelay(10); -} - -static int aedsp16_wait_data(int port) +static int __init aedsp16_wait_data(int port) { int loop = STATUSRETRY; unsigned char ret = 0; @@ -535,7 +537,7 @@ static int aedsp16_wait_data(int port) return FALSE; } -static int aedsp16_read(int port) +static int __init aedsp16_read(int port) { int inbyte; @@ -553,12 +555,12 @@ static int aedsp16_read(int port) return inbyte; } -static int aedsp16_test_dsp(int port) +static int __init aedsp16_test_dsp(int port) { return ((aedsp16_read(port) == 0xaa) ? TRUE : FALSE); } -static int aedsp16_dsp_reset(int port) +static int __init aedsp16_dsp_reset(int port) { /* * Reset DSP @@ -579,7 +581,7 @@ static int aedsp16_dsp_reset(int port) return FALSE; } -static int aedsp16_write(int port, int cmd) +static int __init aedsp16_write(int port, int cmd) { unsigned char ret; int loop = HARDRETRY; @@ -607,7 +609,7 @@ static int aedsp16_write(int port, int cmd) #if defined(CONFIG_SC6600) #if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG) -void aedsp16_pinfo(void) { +void __init aedsp16_pinfo(void) { DBG(("\n Base address: %x\n", decoded_hcfg.iobase)); DBG((" Joystick : %s present\n", decoded_hcfg.joystick?"":" not")); DBG((" WSS addr : %x\n", decoded_hcfg.wssbase)); @@ -617,7 +619,7 @@ void aedsp16_pinfo(void) { } #endif -void aedsp16_hard_decode(void) { +void __init aedsp16_hard_decode(void) { DBG((" aedsp16_hard_decode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1])); @@ -661,7 +663,7 @@ void aedsp16_hard_decode(void) { DBG(("success.\n")); } -void aedsp16_hard_encode(void) { +void __init aedsp16_hard_encode(void) { DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1])); @@ -686,7 +688,7 @@ void aedsp16_hard_encode(void) { } -static int aedsp16_hard_write(int port) { +static int __init aedsp16_hard_write(int port) { DBG(("aedsp16_hard_write:\n")); @@ -721,7 +723,7 @@ static int aedsp16_hard_write(int port) { return TRUE; } -static int aedsp16_hard_read(int port) { +static int __init aedsp16_hard_read(int port) { DBG(("aedsp16_hard_read:\n")); @@ -755,7 +757,7 @@ static int aedsp16_hard_read(int port) { return TRUE; } -static int aedsp16_ext_cfg_write(int port) { +static int __init aedsp16_ext_cfg_write(int port) { int extcfg, val; @@ -809,7 +811,7 @@ static int aedsp16_ext_cfg_write(int port) { #endif /* CONFIG_SC6600 */ -static int aedsp16_cfg_write(int port) { +static int __init aedsp16_cfg_write(int port) { if (aedsp16_write(port, WRITE_MDIRQ_CFG)) { printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); return FALSE; @@ -821,11 +823,11 @@ static int aedsp16_cfg_write(int port) { return TRUE; } -static int aedsp16_init_mss(int port) +static int __init aedsp16_init_mss(int port) { DBG(("aedsp16_init_mss:\n")); - aedsp16_delay_10msec(); + mdelay(10); if (aedsp16_write(port, DSP_INIT_MSS)) { printk("[AEDSP16] aedsp16_init_mss [0x%x]: failed!\n", @@ -833,19 +835,20 @@ static int aedsp16_init_mss(int port) DBG(("failure.\n")); return FALSE; } - aedsp16_delay_10msec(); + + mdelay(10); if (aedsp16_cfg_write(port) == FALSE) return FALSE; - outb(soft_cfg_1, ae_config.mss_base); + outb(soft_cfg_mss, ae_config.mss_base); DBG(("success.\n")); return TRUE; } -static int aedsp16_setup_board(int port) { +static int __init aedsp16_setup_board(int port) { int loop = RETRY; #if defined(CONFIG_SC6600) @@ -873,7 +876,7 @@ static int aedsp16_setup_board(int port) { printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_88); return FALSE; } - aedsp16_delay_10msec(); + mdelay(10); } while ((aedsp16_wait_data(port) == FALSE) && loop--); if (aedsp16_read(port) == -1) { @@ -934,7 +937,7 @@ static int aedsp16_setup_board(int port) { return TRUE; } -static int aedsp16_stdcfg(int port) { +static int __init aedsp16_stdcfg(int port) { if (aedsp16_write(port, WRITE_MDIRQ_CFG)) { printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); return FALSE; @@ -949,7 +952,7 @@ static int aedsp16_stdcfg(int port) { return TRUE; } -static int aedsp16_dsp_version(int port) +static int __init aedsp16_dsp_version(int port) { int len = 0; int ret; @@ -980,7 +983,7 @@ static int aedsp16_dsp_version(int port) return TRUE; } -static int aedsp16_dsp_copyright(int port) +static int __init aedsp16_dsp_copyright(int port) { int len = 0; int ret; @@ -1016,29 +1019,31 @@ static int aedsp16_dsp_copyright(int port) return TRUE; } -static void aedsp16_init_tables(void) +static void __init aedsp16_init_tables(void) { + int i = 0; + memset(DSPCopyright, 0, CARDNAMELEN + 1); memset(DSPVersion, 0, CARDVERLEN + 1); - for (gc = 0; orIRQ[gc].or; gc++) - if (orIRQ[gc].val == ae_config.irq) { - soft_cfg |= orIRQ[gc].or; - soft_cfg_1 |= orIRQ[gc].or; + for (i = 0; orIRQ[i].or; i++) + if (orIRQ[i].val == ae_config.irq) { + soft_cfg |= orIRQ[i].or; + soft_cfg_mss |= orIRQ[i].or; } - for (gc = 0; orMIRQ[gc].or; gc++) - if (orMIRQ[gc].or == ae_config.mpu_irq) - soft_cfg |= orMIRQ[gc].or; + for (i = 0; orMIRQ[i].or; i++) + if (orMIRQ[i].or == ae_config.mpu_irq) + soft_cfg |= orMIRQ[i].or; - for (gc = 0; orDMA[gc].or; gc++) - if (orDMA[gc].val == ae_config.dma) { - soft_cfg |= orDMA[gc].or; - soft_cfg_1 |= orDMA[gc].or; + for (i = 0; orDMA[i].or; i++) + if (orDMA[i].val == ae_config.dma) { + soft_cfg |= orDMA[i].or; + soft_cfg_mss |= orDMA[i].or; } } -static int aedsp16_init_board(void) +static int __init aedsp16_init_board(void) { aedsp16_init_tables(); @@ -1134,12 +1139,12 @@ static int aedsp16_init_board(void) printk("]\n"); #endif /* MODULE || AEDSP16_INFO || AEDSP16_DEBUG */ - aedsp16_delay_10msec(); + mdelay(10); return TRUE; } -static int init_aedsp16_sb(void) +static int __init init_aedsp16_sb(void) { DBG(("init_aedsp16_sb: ")); @@ -1159,7 +1164,7 @@ static int init_aedsp16_sb(void) return TRUE; } -static void uninit_aedsp16_sb(void) +static void __init uninit_aedsp16_sb(void) { DBG(("uninit_aedsp16_sb: ")); @@ -1168,7 +1173,7 @@ static void uninit_aedsp16_sb(void) DBG(("done.\n")); } -static int init_aedsp16_mss(void) +static int __init init_aedsp16_mss(void) { DBG(("init_aedsp16_mss: ")); @@ -1207,7 +1212,7 @@ static int init_aedsp16_mss(void) return TRUE; } -static void uninit_aedsp16_mss(void) +static void __init uninit_aedsp16_mss(void) { DBG(("uninit_aedsp16_mss: ")); @@ -1221,7 +1226,7 @@ static void uninit_aedsp16_mss(void) DBG(("done.\n")); } -static int init_aedsp16_mpu(void) +static int __init init_aedsp16_mpu(void) { DBG(("init_aedsp16_mpu: ")); @@ -1251,7 +1256,7 @@ static int init_aedsp16_mpu(void) return TRUE; } -static void uninit_aedsp16_mpu(void) +static void __init uninit_aedsp16_mpu(void) { DBG(("uninit_aedsp16_mpu: ")); @@ -1266,7 +1271,7 @@ static void uninit_aedsp16_mpu(void) DBG(("done.\n")); } -int init_aedsp16(void) +int __init init_aedsp16(void) { int initialized = FALSE; @@ -1324,7 +1329,7 @@ int init_aedsp16(void) return initialized; } -void uninit_aedsp16(void) +void __init uninit_aedsp16(void) { if (ae_config.mss_base != -1) uninit_aedsp16_mss(); @@ -1344,12 +1349,20 @@ int mss_base = -1; int mpu_base = -1; -MODULE_PARM(io,"i"); -MODULE_PARM(irq,"i"); -MODULE_PARM(dma,"i"); -MODULE_PARM(mpu_irq,"i"); -MODULE_PARM(mss_base,"i"); -MODULE_PARM(mpu_base,"i"); +MODULE_PARM(io, "i"); +MODULE_PARM_DESC(io, "I/O base address (0x220 0x240)"); +MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(irq, "IRQ line (5 7 9 10 11)"); +MODULE_PARM(dma, "i"); +MODULE_PARM_DESC(dma, "dma line (0 1 3)"); +MODULE_PARM(mpu_irq, "i"); +MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ line (5 7 9 10 0)"); +MODULE_PARM(mss_base, "i"); +MODULE_PARM_DESC(mss_base, "MSS emulation I/O base address (0x530 0xE80)"); +MODULE_PARM(mpu_base, "i"); +MODULE_PARM_DESC(mpu_base,"MPU-401 I/O base address (0x300 0x310 0x320 0x330)"); +MODULE_AUTHOR("Riccardo Facchetti "); +MODULE_DESCRIPTION("Audio Excel DSP 16 Driver Version " VERSION); int init_module(void) { printk("Audio Excel DSP 16 init driver Copyright (C) Riccardo Facchetti 1995-98\n"); diff --git a/drivers/sound/lowlevel/miroaci.h b/drivers/sound/lowlevel/miroaci.h new file mode 100644 index 000000000..9d64eaa1e --- /dev/null +++ b/drivers/sound/lowlevel/miroaci.h @@ -0,0 +1,6 @@ +extern int aci_implied_cmd(unsigned char opcode); +extern int aci_write_cmd(unsigned char opcode, unsigned char parameter); +extern int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2); +extern int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter); +extern int aci_indexed_cmd(unsigned char opcode, unsigned char index, unsigned char *parameter); + diff --git a/drivers/sound/lowlevel/soundlow.c b/drivers/sound/lowlevel/soundlow.c index 64ac00ccd..96fdb94be 100644 --- a/drivers/sound/lowlevel/soundlow.c +++ b/drivers/sound/lowlevel/soundlow.c @@ -5,6 +5,7 @@ #include "lowlevel.h" #include #include +#include #include "../soundvers.h" #ifdef LOWLEVEL_MODULE @@ -15,8 +16,8 @@ extern int attach_aci(void); extern void unload_aci(void); extern int attach_awe(void); extern void unload_awe(void); -extern int init_aedsp16(void); -extern void uninit_aedsp16(void); +extern int init_aedsp16(void) __init; +extern void uninit_aedsp16(void) __init; /* * There are two places where you can insert initialization calls of diff --git a/drivers/sound/msnd_pinnacle.c b/drivers/sound/msnd_pinnacle.c index 07bba6bc6..bed4ec1bf 100644 --- a/drivers/sound/msnd_pinnacle.c +++ b/drivers/sound/msnd_pinnacle.c @@ -944,6 +944,7 @@ static struct file_operations dev_fileops = { dev_ioctl, NULL, dev_open, + NULL, /* flush */ dev_close, }; diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c index 3ec472f4d..04b3d7854 100644 --- a/drivers/sound/sb_common.c +++ b/drivers/sound/sb_common.c @@ -694,7 +694,7 @@ int sb_dsp_detect(struct address_info *hw_config) return 1; } -static int sb_dsp_init(struct address_info *hw_config) +int sb_dsp_init(struct address_info *hw_config) { sb_devc *devc; char name[100]; diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index 066d722eb..064342088 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -1208,6 +1208,7 @@ static /*const*/ struct file_operations sv_mixer_fops = { &sv_ioctl_mixdev, NULL, /* mmap */ &sv_open_mixdev, + NULL, /* flush */ &sv_release_mixdev, NULL, /* fsync */ NULL, /* fasync */ @@ -1810,6 +1811,7 @@ static /*const*/ struct file_operations sv_audio_fops = { &sv_ioctl, &sv_mmap, &sv_open, + NULL, /* flush */ &sv_release, NULL, /* fsync */ NULL, /* fasync */ @@ -2054,6 +2056,7 @@ static /*const*/ struct file_operations sv_midi_fops = { NULL, /* ioctl */ NULL, /* mmap */ &sv_midi_open, + NULL, /* flush */ &sv_midi_release, NULL, /* fsync */ NULL, /* fasync */ @@ -2227,6 +2230,7 @@ static /*const*/ struct file_operations sv_dmfm_fops = { &sv_dmfm_ioctl, NULL, /* mmap */ &sv_dmfm_open, + NULL, /* flush */ &sv_dmfm_release, NULL, /* fsync */ NULL, /* fasync */ diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c index 95ef40a0f..63322ec2b 100644 --- a/drivers/sound/sound_core.c +++ b/drivers/sound/sound_core.c @@ -262,6 +262,7 @@ static struct file_operations soundcore_fops= NULL, NULL, NULL, + NULL, NULL }; diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index d679ff8bc..1fbb368d8 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -769,6 +769,7 @@ struct file_operations oss_sound_fops = sound_ioctl, sound_mmap, sound_open, + NULL, /* flush */ sound_release }; diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index 4f9243359..b208392a9 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c @@ -71,6 +71,7 @@ static struct file_operations proc_bus_zorro_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index bdadee2c5..12f7f6f6d 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -27,6 +27,7 @@ static struct file_operations adfs_dir_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync, /* fsync */ NULL, /* fasync */ diff --git a/fs/adfs/file.c b/fs/adfs/file.c index 5627c7db4..a886c68ce 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c @@ -40,6 +40,7 @@ static struct file_operations adfs_file_operations = { NULL, /* ioctl */ generic_file_mmap, /* mmap */ NULL, /* open - not special */ + NULL, /* flush */ NULL, /* release */ file_fsync, /* fsync */ NULL, /* fasync */ diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 4cc742179..51e45b682 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -36,6 +36,7 @@ static struct file_operations affs_dir_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync /* default fsync */ }; diff --git a/fs/affs/file.c b/fs/affs/file.c index 6f0db87fd..1961b4ec3 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -52,6 +52,7 @@ static struct file_operations affs_file_operations = { NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open */ + NULL, /* flush */ NULL, /* release */ file_fsync, /* brute force, but works */ NULL, /* fasync */ @@ -92,6 +93,7 @@ static struct file_operations affs_file_operations_ofs = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open */ + NULL, /* flush */ NULL, /* release */ file_fsync, /* brute force, but works */ NULL, /* fasync */ diff --git a/fs/autofs/dir.c b/fs/autofs/dir.c index 9264806b4..67b2c04bf 100644 --- a/fs/autofs/dir.c +++ b/fs/autofs/dir.c @@ -53,6 +53,7 @@ static struct file_operations autofs_dir_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* open */ + NULL, /* flush */ NULL, /* release */ NULL, /* fsync */ NULL, /* fasync */ diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 0947e40e0..41694e8eb 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -32,6 +32,7 @@ static struct file_operations autofs_root_operations = { autofs_root_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* open */ + NULL, /* flush */ NULL, /* release */ NULL, /* fsync */ NULL, /* fasync */ diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 71106655b..6eee191e8 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -38,6 +38,7 @@ static struct file_operations bad_file_ops = EIO_ERROR, /* ioctl */ EIO_ERROR, /* mmap */ EIO_ERROR, /* open */ + EIO_ERROR, /* flush */ EIO_ERROR, /* release */ EIO_ERROR, /* fsync */ EIO_ERROR, /* fasync */ diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index 122491c7a..e96cb18d5 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -318,7 +318,6 @@ static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs return -ENOEXEC; } - current->personality = PER_LINUX; fd_offset = N_TXTOFF(ex); #ifdef __i386__ @@ -350,6 +349,8 @@ static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs return retval; /* OK, This is the point of no return */ + current->personality = PER_LINUX; + #if defined(__sparc__) && !defined(__sparc_v9__) memcpy(¤t->tss.core_exec, &ex, sizeof(struct exec)); #endif @@ -563,7 +564,7 @@ load_aout_library(int fd) } -__initfunc(int init_aout_binfmt(void)) +int __init init_aout_binfmt(void) { return register_binfmt(&aout_format); } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index a14debe63..976eec390 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1331,7 +1331,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs) } #endif /* USE_ELF_CORE_DUMP */ -__initfunc(int init_elf_binfmt(void)) +int __init init_elf_binfmt(void) { return register_binfmt(&elf_format); } diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c index 133586e69..d1992ca06 100644 --- a/fs/binfmt_em86.c +++ b/fs/binfmt_em86.c @@ -110,7 +110,7 @@ struct linux_binfmt em86_format = { #endif }; -__initfunc(int init_em86_binfmt(void)) +int __init init_em86_binfmt(void) { return register_binfmt(&em86_format); } diff --git a/fs/binfmt_java.c b/fs/binfmt_java.c index 41e66a21a..ca1ad396c 100644 --- a/fs/binfmt_java.c +++ b/fs/binfmt_java.c @@ -174,7 +174,7 @@ static struct linux_binfmt applet_format = { #endif }; -__initfunc(int init_java_binfmt(void)) +int __init init_java_binfmt(void) { register_binfmt(&java_format); return register_binfmt(&applet_format); diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index bc1da662e..8acea3b64 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -488,7 +488,7 @@ static void bm_modcount(struct inode *inode, int fill) } #endif -__initfunc(int init_misc_binfmt(void)) +int __init init_misc_binfmt(void) { struct proc_dir_entry *status = NULL, *reg; int error = -ENOMEM; diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 5a38cf545..6aa1508a4 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -107,7 +107,7 @@ struct linux_binfmt script_format = { #endif }; -__initfunc(int init_script_binfmt(void)) +int __init init_script_binfmt(void) { return register_binfmt(&script_format); } diff --git a/fs/buffer.c b/fs/buffer.c index 7bf6e2824..103caefa3 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1736,7 +1736,7 @@ void show_buffers(void) * Use gfp() for the hash table to decrease TLB misses, use * SLAB cache for buffer heads. */ -__initfunc(void buffer_init(void)) +void __init buffer_init(void) { int order = 5; /* Currently maximum order.. */ unsigned int nr_hash; diff --git a/fs/coda/dir.c b/fs/coda/dir.c index fabc4e3c8..b55541532 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -96,6 +96,7 @@ struct file_operations coda_dir_operations = { NULL, /* ioctl */ NULL, /* mmap */ coda_open, /* open */ + NULL, /* flush */ coda_release, /* release */ coda_fsync, /* fsync */ NULL, diff --git a/fs/coda/file.c b/fs/coda/file.c index 949d9ce00..3635c8ec9 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -66,6 +66,7 @@ struct file_operations coda_file_operations = { NULL, /* ioctl */ coda_file_mmap, /* mmap */ coda_open, /* open */ + NULL, /* flush */ coda_release, /* release */ coda_fsync, /* fsync */ NULL, /* fasync */ diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index aa143afcf..9f86a7ac2 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -65,6 +65,7 @@ struct file_operations coda_ioctl_operations = { coda_pioctl, /* ioctl */ NULL, /* mmap */ coda_ioctl_open, /* open */ + NULL, /* flush */ coda_ioctl_release, /* release */ NULL, /* fsync */ }; diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 73fa6ddfe..3618940e3 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -391,6 +391,7 @@ static struct file_operations coda_psdev_fops = { NULL, /* ioctl */ NULL, /* coda_psdev_mmap */ coda_psdev_open, /* open */ + NULL, /* flush */ coda_psdev_release, /* release */ NULL, /* fsync */ NULL, /* fasync */ diff --git a/fs/dcache.c b/fs/dcache.c index 6cd34bb4a..c37da320e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -916,7 +916,7 @@ out: return ino; } -__initfunc(void dcache_init(void)) +void __init dcache_init(void) { int i; struct list_head *d = dentry_hashtable; diff --git a/fs/devices.c b/fs/devices.c index f0ab040fc..db5cca48b 100644 --- a/fs/devices.c +++ b/fs/devices.c @@ -261,6 +261,7 @@ struct file_operations def_blk_fops = { NULL, /* ioctl */ NULL, /* mmap */ blkdev_open, /* open */ + NULL, /* flush */ NULL, /* release */ }; @@ -313,6 +314,7 @@ struct file_operations def_chr_fops = { NULL, /* ioctl */ NULL, /* mmap */ chrdev_open, /* open */ + NULL, /* flush */ NULL, /* release */ }; diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 9ba675b16..78d3ae625 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -77,13 +77,15 @@ static int devpts_parse_options(char *options, struct devpts_sb_info *sbi) { int setuid = 0; int setgid = 0; - uid_t uid = 0; /* To shut up gcc */ + uid_t uid = 0; gid_t gid = 0; umode_t mode = 0600; char *this_char, *value; - if ( !options ) return 1; - for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) { + this_char = NULL; + if ( options ) + this_char = strtok(options,","); + for ( ; this_char; this_char = strtok(NULL,",")) { if ((value = strchr(this_char,'=')) != NULL) *value++ = 0; if (!strcmp(this_char,"uid")) { diff --git a/fs/devpts/root.c b/fs/devpts/root.c index e5930501c..04215ad40 100644 --- a/fs/devpts/root.c +++ b/fs/devpts/root.c @@ -29,6 +29,7 @@ static struct file_operations devpts_root_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* open */ + NULL, /* flush */ NULL, /* release */ NULL, /* fsync */ NULL, /* fasync */ diff --git a/fs/dquot.c b/fs/dquot.c index 9ec40618e..3179a5d4d 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1063,7 +1063,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction, uid } -__initfunc(void dquot_init_hash(void)) +void __init dquot_init_hash(void) { printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__); diff --git a/fs/exec.c b/fs/exec.c index a76757c93..8633f0dfb 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -67,7 +67,7 @@ asmlinkage int sys_brk(unsigned long); static struct linux_binfmt *formats = (struct linux_binfmt *) NULL; -__initfunc(void binfmt_setup(void)) +void __init binfmt_setup(void) { #ifdef CONFIG_BINFMT_MISC init_misc_binfmt(); diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 40845df97..8f69f0baf 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -213,7 +213,7 @@ static inline int load_block_bitmap (struct super_block * sb, if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 && sb->u.ext2_sb.s_block_bitmap_number[0] == block_group && sb->u.ext2_sb.s_block_bitmap[block_group]) { - slot = 0; + return 0; } /* * Or can we do a fast lookup based on a loaded group on a filesystem diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index cbf6a9020..c5af9d8e1 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -43,6 +43,7 @@ static struct file_operations ext2_dir_operations = { ext2_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ ext2_sync_file, /* fsync */ NULL, /* fasync */ diff --git a/fs/ext2/file.c b/fs/ext2/file.c index d5e74cf35..0a98bad09 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -74,6 +74,7 @@ static struct file_operations ext2_file_operations = { #else ext2_open_file, #endif + NULL, /* flush */ ext2_release_file, /* release */ ext2_sync_file, /* fsync */ NULL, /* fasync */ diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 2e3cbbc0c..7043188f8 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -101,7 +101,8 @@ static int load_inode_bitmap (struct super_block * sb, "block_group = %d, groups_count = %lu", block_group, sb->u.ext2_sb.s_groups_count); if (sb->u.ext2_sb.s_loaded_inode_bitmaps > 0 && - sb->u.ext2_sb.s_inode_bitmap_number[0] == block_group) + sb->u.ext2_sb.s_inode_bitmap_number[0] == block_group && + sb->u.ext2_sb.s_inode_bitmap[0] != NULL) return 0; if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED) { if (sb->u.ext2_sb.s_inode_bitmap[block_group]) { diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 00ad26330..1c44247a0 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -46,6 +46,7 @@ struct file_operations fat_dir_operations = { fat_dir_ioctl, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync /* fsync */ }; diff --git a/fs/fat/file.c b/fs/fat/file.c index 2495400f4..52e36caea 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -39,6 +39,7 @@ static struct file_operations fat_file_operations = { NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ NULL, /* release */ file_fsync /* fsync */ }; @@ -79,6 +80,7 @@ static struct file_operations fat_file_operations_1024 = { NULL, /* ioctl - default */ fat_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ NULL, /* release */ file_fsync /* fsync */ }; @@ -122,6 +124,7 @@ static struct file_operations fat_file_operations_readpage = { NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ NULL, /* release */ file_fsync /* fsync */ }; diff --git a/fs/fifo.c b/fs/fifo.c index 76fb7a530..7536995ac 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -128,6 +128,8 @@ static struct file_operations def_fifo_fops = { NULL, fifo_open, /* will set read or write pipe_fops */ NULL, + NULL, + NULL, NULL }; diff --git a/fs/file_table.c b/fs/file_table.c index 3b5f05f81..6a4b1df43 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -12,6 +12,7 @@ #include #include #include +#include /* SLAB cache for filp's. */ static kmem_cache_t *filp_cache; @@ -44,8 +45,7 @@ static inline void put_inuse(struct file *file) file->f_pprev = &inuse_filps; } -/* N.B. This should be an __initfunc ... */ -void file_table_init(void) +void __init file_table_init(void) { filp_cache = kmem_cache_create("filp", sizeof(struct file), 0, diff --git a/fs/filesystems.c b/fs/filesystems.c index d359b8002..dcd1cf1d4 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c @@ -50,7 +50,7 @@ extern void device_setup(void); extern void binfmt_setup(void); extern void free_initmem(void); -__initfunc(static void do_sys_setup(void)) +static void __init do_sys_setup(void) { device_setup(); diff --git a/fs/hfs/dir_cap.c b/fs/hfs/dir_cap.c index a7bb7f633..a40854e66 100644 --- a/fs/hfs/dir_cap.c +++ b/fs/hfs/dir_cap.c @@ -66,6 +66,7 @@ static struct file_operations hfs_cap_dir_operations = { NULL, /* ioctl - default */ NULL, /* mmap - none */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync, /* fsync - default */ NULL, /* fasync - default */ diff --git a/fs/hfs/dir_dbl.c b/fs/hfs/dir_dbl.c index 553fe8ef9..1e14b3f24 100644 --- a/fs/hfs/dir_dbl.c +++ b/fs/hfs/dir_dbl.c @@ -66,6 +66,7 @@ static struct file_operations hfs_dbl_dir_operations = { NULL, /* ioctl - default */ NULL, /* mmap - none */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync, /* fsync - default */ NULL, /* fasync - default */ diff --git a/fs/hfs/dir_nat.c b/fs/hfs/dir_nat.c index b29bfdc17..b69a6bd70 100644 --- a/fs/hfs/dir_nat.c +++ b/fs/hfs/dir_nat.c @@ -69,6 +69,7 @@ static struct file_operations hfs_nat_dir_operations = { NULL, /* ioctl - default */ NULL, /* mmap - none */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync, /* fsync - default */ NULL, /* fasync - default */ diff --git a/fs/hfs/file.c b/fs/hfs/file.c index e12792036..6157afb47 100644 --- a/fs/hfs/file.c +++ b/fs/hfs/file.c @@ -41,6 +41,7 @@ static struct file_operations hfs_file_operations = { NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* open */ + NULL, /* flush */ NULL, /* release */ file_fsync, /* fsync - default */ NULL, /* fasync - default */ diff --git a/fs/hfs/file_cap.c b/fs/hfs/file_cap.c index 10f39f751..4fbd1f090 100644 --- a/fs/hfs/file_cap.c +++ b/fs/hfs/file_cap.c @@ -55,6 +55,7 @@ static struct file_operations hfs_cap_info_operations = { NULL, /* ioctl - default */ NULL, /* mmap - not yet */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync, /* fsync - default */ NULL, /* fasync - default */ diff --git a/fs/hfs/file_hdr.c b/fs/hfs/file_hdr.c index 049381dd0..b12a4606b 100644 --- a/fs/hfs/file_hdr.c +++ b/fs/hfs/file_hdr.c @@ -48,6 +48,7 @@ static struct file_operations hfs_hdr_operations = { NULL, /* ioctl - default */ NULL, /* mmap - XXX: not yet */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync, /* fsync - default */ NULL, /* fasync - default */ diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 524624572..f73ec5271 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -35,6 +35,7 @@ static struct file_operations isofs_dir_operations = NULL, /* poll - default */ NULL, /* ioctl - default */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ }; diff --git a/fs/isofs/file.c b/fs/isofs/file.c index 0f230e0d2..0a508c90b 100644 --- a/fs/isofs/file.c +++ b/fs/isofs/file.c @@ -31,6 +31,7 @@ static struct file_operations isofs_file_operations = { NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ NULL, /* release */ NULL /* fsync */ }; diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index eec09e3ad..bbfdefc71 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -51,34 +51,39 @@ nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) } /* - * Initialize arguments for GRANTED call + * Initialize arguments for GRANTED call. The nlm_rqst structure + * has been cleared already. */ int nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) { - struct nlm_args *argp = &call->a_args; - struct nlm_lock *alock = &argp->lock; - void *data = NULL; - - if (lock->oh.len > NLMCLNT_OHSIZE - && !(data = kmalloc(lock->oh.len, GFP_KERNEL))) - return 0; + call->a_args.cookie = nlm_cookie++; + call->a_args.lock = *lock; + call->a_args.lock.caller = system_utsname.nodename; + + /* set default data area */ + call->a_args.lock.oh.data = call->a_owner; + + if (lock->oh.len > NLMCLNT_OHSIZE) { + void *data = kmalloc(lock->oh.len, GFP_KERNEL); + if (!data) + return 0; + call->a_args.lock.oh.data = (u8 *) data; + } - argp->cookie = nlm_cookie++; - argp->lock = *lock; - alock->caller = system_utsname.nodename; - if (data) - alock->oh.data = (u8 *) data; - else - alock->oh.data = call->a_owner; - memcpy(alock->oh.data, lock->oh.data, lock->oh.len); + memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len); return 1; } void nlmclnt_freegrantargs(struct nlm_rqst *call) { - kfree(call->a_args.lock.caller); + /* + * Check whether we allocated memory for the owner. + */ + if (call->a_args.lock.oh.data != (u8 *) call->a_owner) { + kfree(call->a_args.lock.oh.data); + } } /* @@ -404,9 +409,15 @@ nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl) static int nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) { + struct nlm_host *host = req->a_host; struct nlm_res *resp = &req->a_res; int status; + /* No monitor, no lock: see nlmclnt_lock(). + * Since this is an UNLOCK, don't try to setup monitoring here. */ + if (!host->h_monitored) + return -ENOLCK; + /* Clean the GRANTED flag now so the lock doesn't get * reclaimed while we're stuck in the unlock call. */ fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED; diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 69a9eeb21..ac650b5f3 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -158,10 +158,8 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, /* Set notifier function for VFS, and init args */ lock->fl.fl_notify = nlmsvc_notify_blocked; - if (!nlmclnt_setgrantargs(&block->b_call, lock)) { - kfree(block); - goto failed; - } + if (!nlmclnt_setgrantargs(&block->b_call, lock)) + goto failed_free; block->b_call.a_args.cookie = cookie; /* see above */ dprintk("lockd: created block %p...\n", block); @@ -182,6 +180,8 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, return block; +failed_free: + kfree(block); failed: nlm_release_host(host); return NULL; diff --git a/fs/minix/dir.c b/fs/minix/dir.c index 4c407817b..dc3e63347 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c @@ -31,6 +31,7 @@ static struct file_operations minix_dir_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync /* default fsync */ }; diff --git a/fs/minix/file.c b/fs/minix/file.c index a44a635b0..f6ddda021 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -42,6 +42,7 @@ static struct file_operations minix_file_operations = { NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ NULL, /* release */ minix_sync_file /* fsync */ }; diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index bec1c55a2..caa2dc261 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -70,6 +70,7 @@ static struct file_operations ncp_dir_operations = ncp_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ }; diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index d26fee881..50d91a2b2 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -252,6 +252,7 @@ static struct file_operations ncp_file_operations = ncp_ioctl, /* ioctl */ ncp_mmap, /* mmap */ NULL, /* open */ + NULL, /* flush */ NULL, /* release */ ncp_fsync, /* fsync */ }; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index ba7a6c6e9..3e5e59aff 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -14,13 +14,6 @@ * Following Linus comments on my original hack, this version * depends only on the dcache stuff and doesn't touch the inode * layer (iput() and friends). - * 04 Aug 1998 Ion Badulescu - * FIFO's need special handling in NFSv2 - */ - -/* - * Fixes: - * Ion Badulescu : FIFO's need special handling in NFSv2 */ #include @@ -86,6 +79,7 @@ static struct file_operations nfs_dir_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ nfs_dir_open, /* open - revalidate */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ }; @@ -652,10 +646,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode) if (dentry->d_name.len > NFS_MAXNAMLEN) goto out; - if (mode & S_IFIFO) - sattr.mode = (mode & ~S_IFMT) | S_IFCHR; - else - sattr.mode = mode; + sattr.mode = mode; sattr.uid = sattr.gid = sattr.size = (unsigned) -1; sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1; @@ -665,15 +656,6 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode) nfs_invalidate_dircache(dir); error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent), dentry->d_name.name, &sattr, &fhandle, &fattr); - /* - * Retry invalid FIFO creates as the original object - * to cover for NFS servers that don't cope. - */ - if (error == -EINVAL && (mode & S_IFIFO)) { - sattr.mode = mode; - error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent), - dentry->d_name.name, &sattr, &fhandle, &fattr); - } if (!error) error = nfs_instantiate(dentry, &fhandle, &fattr); if (error) @@ -703,10 +685,7 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde if (dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - if (mode & S_IFIFO) - sattr.mode = (mode & ~S_IFMT) | S_IFCHR; - else - sattr.mode = mode; + sattr.mode = mode; sattr.uid = sattr.gid = sattr.size = (unsigned) -1; if (S_ISCHR(mode) || S_ISBLK(mode)) sattr.size = rdev; /* get out your barf bag */ @@ -715,11 +694,6 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde nfs_invalidate_dircache(dir); error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent), dentry->d_name.name, &sattr, &fhandle, &fattr); - if (error == -EINVAL && (mode & S_IFIFO)) { - sattr.mode = mode; - error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent), - dentry->d_name.name, &sattr, &fhandle, &fattr); - } if (!error) error = nfs_instantiate(dentry, &fhandle, &fattr); if (error) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 9ec883aff..973ad52ec 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -35,6 +35,7 @@ static int nfs_file_mmap(struct file *, struct vm_area_struct *); static ssize_t nfs_file_read(struct file *, char *, size_t, loff_t *); static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *); +static int nfs_file_flush(struct file *); static int nfs_file_close(struct inode *, struct file *); static int nfs_fsync(struct file *, struct dentry *dentry); @@ -47,6 +48,7 @@ static struct file_operations nfs_file_operations = { NULL, /* ioctl - default */ nfs_file_mmap, /* mmap */ NULL, /* no special open is needed */ + nfs_file_flush, /* flush */ nfs_file_close, /* release */ nfs_fsync, /* fsync */ NULL, /* fasync */ @@ -84,13 +86,7 @@ struct inode_operations nfs_file_inode_operations = { #endif /* - * Flush all dirty pages, and check for write errors. - * - * Note that since the file close operation is called only by the - * _last_ process to close the file, we need to flush _all_ dirty - * pages. This also means that there is little sense in checking - * for errors for this specific process -- we should probably just - * clear all errors. + * Sync the file.. */ static int nfs_file_close(struct inode *inode, struct file *file) @@ -106,6 +102,22 @@ nfs_file_close(struct inode *inode, struct file *file) return status; } +/* + * Flush all dirty pages, and check for write errors. + * + * We should probably do this better - this does get called at every + * close, so we should probably just flush the changes that "this" + * file has done and report on only those. + * + * Right now we use the "flush everything" approach. Overkill, but + * works. + */ +static int +nfs_file_flush(struct file *file) +{ + return nfs_file_close(file->f_dentry->d_inode, file); +} + static ssize_t nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos) { diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e89abdbce..597821270 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -652,6 +652,7 @@ _nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry) int status = 0; struct nfs_fattr fattr; + /* Don't bother revalidating if we've done it recently */ if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode)) goto out; @@ -746,6 +747,20 @@ nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) goto out_changed; /* + * If we have pending write-back entries, we don't want + * to look at the size the server sends us too closely.. + * In particular, ignore the server if it tells us that + * the file is smaller or older than we locally think it + * is.. + */ + if (NFS_WRITEBACK(inode)) { + if (inode->i_size > fattr->size) + fattr->size = inode->i_size; + if (inode->i_mtime > fattr->mtime.seconds) + fattr->mtime.seconds = inode->i_mtime; + } + + /* * If the size or mtime changed from outside, we want * to invalidate the local caches immediately. */ diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 3ecb9bfa6..81da8f996 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -78,7 +78,6 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr) clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; - clnt->cl_intr = 1; } return clnt; } diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index bab335a15..1c6a74a71 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -5,9 +5,6 @@ * * Copyright (C) 1992, 1993, 1994 Rick Sladkey * Copyright (C) 1996 Olaf Kirch - * - * 04 Aug 1998 Ion Badulescu - * FIFO's need special handling in NFSv2 */ #define NFS_NEED_XDR_TYPES @@ -117,11 +114,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) fattr->mtime.useconds = ntohl(*p++); fattr->ctime.seconds = ntohl(*p++); fattr->ctime.useconds = ntohl(*p++); - if (fattr->type == NFCHR && fattr->rdev == NFS_FIFO_DEV) { - fattr->type = NFFIFO; - fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; - fattr->rdev = 0; - } return p; } diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 0a58b6a02..572c413d0 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -63,6 +63,8 @@ * * Until we have a per-mount soft/hard mount policy that we can honour * we must default to hard mounting! + * + * And yes, this should be "interruptible", not soft. */ #define IS_SOFT 0 @@ -442,11 +444,15 @@ schedule_write_request(struct nfs_wreq *req, int sync) sync = 1; if (sync) { + sigset_t oldmask; + struct rpc_clnt *clnt = NFS_CLIENT(inode); dprintk("NFS: %4d schedule_write_request (sync)\n", task->tk_pid); /* Page is already locked */ req->wb_flags |= NFS_WRITE_LOCKED; + rpc_clnt_sigmask(clnt, &oldmask); rpc_execute(task); + rpc_clnt_sigunmask(clnt, &oldmask); } else { dprintk("NFS: %4d schedule_write_request (async)\n", task->tk_pid); @@ -467,19 +473,19 @@ wait_on_write_request(struct nfs_wreq *req) { struct wait_queue wait = { current, NULL }; struct page *page = req->wb_page; - int retval; + int retval; sigset_t oldmask; + struct rpc_clnt *clnt = NFS_CLIENT(req->wb_inode); - rpc_clnt_sigmask(NFS_CLIENT(req->wb_inode), &oldmask); + rpc_clnt_sigmask(clnt, &oldmask); add_wait_queue(&page->wait, &wait); atomic_inc(&page->count); for (;;) { - current->state = IS_SOFT ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; + current->state = TASK_INTERRUPTIBLE; retval = 0; if (!PageLocked(page)) break; retval = -ERESTARTSYS; - /* IS_SOFT is a timeout item .. */ if (signalled()) break; schedule(); @@ -488,7 +494,7 @@ wait_on_write_request(struct nfs_wreq *req) current->state = TASK_RUNNING; /* N.B. page may have been unused, so we must use free_page() */ free_page(page_address(page)); - rpc_clnt_sigunmask(NFS_CLIENT(req->wb_inode), &oldmask); + rpc_clnt_sigunmask(clnt, &oldmask); return retval; } diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c index bf5b8505e..bb489912b 100644 --- a/fs/ntfs/fs.c +++ b/fs/ntfs/fs.c @@ -385,6 +385,7 @@ struct file_operations ntfs_file_operations_nommap = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* open */ + NULL, /* flush */ NULL, /* release */ NULL, /* fsync */ NULL, /* fasync */ @@ -506,6 +507,7 @@ struct file_operations ntfs_file_operations = { NULL, /* ioctl */ generic_file_mmap, NULL, /* open */ + NULL, /* flush */ NULL, /* release */ NULL, /* fsync */ NULL, /* fasync */ @@ -546,6 +548,7 @@ struct file_operations ntfs_dir_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* open */ + NULL, /* flush */ NULL, /* release */ NULL, /* fsync */ NULL, /* fasync */ diff --git a/fs/open.c b/fs/open.c index 0bade427b..e7e1e8246 100644 --- a/fs/open.c +++ b/fs/open.c @@ -770,19 +770,17 @@ asmlinkage int sys_creat(const char * pathname, int mode) /* * Called when retiring the last use of a file pointer. */ -int __fput(struct file *filp) +void __fput(struct file *filp) { struct dentry * dentry = filp->f_dentry; struct inode * inode = dentry->d_inode; - int error = 0; if (filp->f_op && filp->f_op->release) - error = filp->f_op->release(inode, filp); + filp->f_op->release(inode, filp); filp->f_dentry = NULL; if (filp->f_mode & FMODE_WRITE) put_write_access(inode); dput(dentry); - return error; } /* @@ -791,6 +789,7 @@ int __fput(struct file *filp) */ int close_fp(struct file *filp, fl_owner_t id) { + int retval; struct dentry *dentry = filp->f_dentry; if (filp->f_count == 0) { @@ -799,7 +798,11 @@ int close_fp(struct file *filp, fl_owner_t id) } if (dentry->d_inode) locks_remove_posix(filp, id); - return fput(filp); + retval = 0; + if (filp->f_op && filp->f_op->flush) + retval = filp->f_op->flush(filp); + fput(filp); + return retval; } /* diff --git a/fs/pipe.c b/fs/pipe.c index 0e3c2ff39..8308eb06c 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -304,6 +304,7 @@ struct file_operations connecting_fifo_fops = { pipe_ioctl, NULL, /* no mmap on pipes.. surprise */ pipe_read_open, + NULL, /* flush */ pipe_read_release, NULL }; @@ -317,6 +318,7 @@ struct file_operations read_fifo_fops = { pipe_ioctl, NULL, /* no mmap on pipes.. surprise */ pipe_read_open, + NULL, /* flush */ pipe_read_release, NULL }; @@ -330,6 +332,7 @@ struct file_operations write_fifo_fops = { pipe_ioctl, NULL, /* mmap */ pipe_write_open, + NULL, /* flush */ pipe_write_release, NULL }; @@ -343,6 +346,7 @@ struct file_operations rdwr_fifo_fops = { pipe_ioctl, NULL, /* mmap */ pipe_rdwr_open, + NULL, /* flush */ pipe_rdwr_release, NULL }; @@ -356,6 +360,7 @@ struct file_operations read_pipe_fops = { pipe_ioctl, NULL, /* no mmap on pipes.. surprise */ pipe_read_open, + NULL, /* flush */ pipe_read_release, NULL }; @@ -369,6 +374,7 @@ struct file_operations write_pipe_fops = { pipe_ioctl, NULL, /* mmap */ pipe_write_open, + NULL, /* flush */ pipe_write_release, NULL }; @@ -382,6 +388,7 @@ struct file_operations rdwr_pipe_fops = { pipe_ioctl, NULL, /* mmap */ pipe_rdwr_open, + NULL, /* flush */ pipe_rdwr_release, NULL }; diff --git a/fs/proc/array.c b/fs/proc/array.c index d5a979639..f235a56df 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -1390,6 +1390,7 @@ static struct file_operations proc_array_operations = { NULL, /* array_ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; @@ -1437,6 +1438,7 @@ static struct file_operations proc_arraylong_operations = { NULL, /* array_ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/proc/base.c b/fs/proc/base.c index edfe8b758..c9b2d8649 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -24,6 +24,7 @@ static struct file_operations proc_base_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 57f99bfd7..5409e2d67 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -30,6 +30,7 @@ static struct file_operations proc_fd_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/proc/generic.c b/fs/proc/generic.c index a9b00f1f5..54b16f84b 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -42,6 +42,7 @@ static struct file_operations proc_file_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index e21c0cd1c..ff8ec4877 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c @@ -54,6 +54,7 @@ static struct file_operations proc_kmsg_operations = { NULL, /* kmsg_ioctl */ NULL, /* mmap */ kmsg_open, + NULL, /* flush */ kmsg_release, NULL /* can't fsync */ }; diff --git a/fs/proc/link.c b/fs/proc/link.c index 05ab85030..df5ea85e6 100644 --- a/fs/proc/link.c +++ b/fs/proc/link.c @@ -31,6 +31,7 @@ static struct file_operations proc_fd_link_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* very special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/proc/mem.c b/fs/proc/mem.c index 6478dab77..8a8ec9bc0 100644 --- a/fs/proc/mem.c +++ b/fs/proc/mem.c @@ -316,6 +316,7 @@ static struct file_operations proc_mem_operations = { NULL, /* mem_ioctl */ mem_mmap, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/proc/net.c b/fs/proc/net.c index 408c8e0d4..a6d8c5616 100644 --- a/fs/proc/net.c +++ b/fs/proc/net.c @@ -92,6 +92,7 @@ static struct file_operations proc_net_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/proc/omirr.c b/fs/proc/omirr.c index 041e493d2..9bde82e82 100644 --- a/fs/proc/omirr.c +++ b/fs/proc/omirr.c @@ -268,6 +268,7 @@ static struct file_operations omirr_operations = { NULL, /* omirr_ioctl */ NULL, /* mmap */ omirr_open, + NULL, /* flush */ omirr_release, NULL, /* fsync */ NULL, /* fasync */ diff --git a/fs/proc/openpromfs.c b/fs/proc/openpromfs.c index 0380e1899..b3871059e 100644 --- a/fs/proc/openpromfs.c +++ b/fs/proc/openpromfs.c @@ -479,6 +479,7 @@ static struct file_operations openpromfs_prop_ops = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ property_release, /* no special release code */ NULL /* can't fsync */ }; @@ -512,6 +513,7 @@ static struct file_operations openpromfs_nodenum_ops = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; @@ -545,6 +547,7 @@ static struct file_operations openprom_alias_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/proc/root.c b/fs/proc/root.c index e74e91366..18eb65ef9 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -50,6 +50,7 @@ static struct file_operations proc_dir_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; @@ -117,6 +118,7 @@ static struct file_operations proc_root_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* no fsync */ }; @@ -276,6 +278,7 @@ static struct file_operations proc_openprom_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; @@ -901,20 +904,19 @@ int proc_readdir(struct file * filp, * tasklist lock while doing this, and we must release it before * we actually do the filldir itself, so we use a temp buffer.. */ -static int get_pid_list(unsigned int index, unsigned int *pids) +static int get_pid_list(int index, unsigned int *pids) { struct task_struct *p; - int nr = FIRST_PROCESS_ENTRY; int nr_pids = 0; + index -= FIRST_PROCESS_ENTRY; read_lock(&tasklist_lock); for_each_task(p) { - int pid; - if (nr++ < index) - continue; - pid = p->pid; + int pid = p->pid; if (!pid) continue; + if (--index >= 0) + continue; pids[nr_pids] = pid; nr_pids++; if (nr_pids >= PROC_MAXPIDS) diff --git a/fs/proc/scsi.c b/fs/proc/scsi.c index 3bc4b1d59..6f3ad0770 100644 --- a/fs/proc/scsi.c +++ b/fs/proc/scsi.c @@ -50,6 +50,7 @@ static struct file_operations proc_scsi_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index ed547eee6..92cd94363 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -40,6 +40,7 @@ static struct file_operations smb_dir_operations = smb_ioctl, /* ioctl */ NULL, /* mmap */ smb_dir_open, /* open(struct inode *, struct file *) */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ }; diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index 0b886da90..3c3e87aa6 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -389,6 +389,7 @@ static struct file_operations smb_file_operations = smb_ioctl, /* ioctl */ smb_file_mmap, /* mmap(struct file*, struct vm_area_struct*) */ smb_file_open, /* open(struct inode*, struct file*) */ + NULL, /* flush */ smb_file_release, /* release(struct inode*, struct file*) */ smb_fsync, /* fsync(struct file*, struct dentry*) */ NULL, /* fasync(struct file*, int) */ diff --git a/fs/super.c b/fs/super.c index 924a02f8f..843464421 100644 --- a/fs/super.c +++ b/fs/super.c @@ -539,8 +539,8 @@ static struct super_block *get_empty_super(void) if (nr_super_blocks >= max_super_blocks) return NULL; s = kmalloc(sizeof(struct super_block), GFP_USER); - nr_super_blocks++; if (s) { + nr_super_blocks++; memset(s, 0, sizeof(struct super_block)); INIT_LIST_HEAD(&s->s_dirty); list_add (&s->s_list, super_blocks.prev); @@ -1129,7 +1129,7 @@ clean_up: goto dput_and_out; } -__initfunc(void mount_root(void)) +void __init mount_root(void) { struct file_system_type * fs_type; struct super_block * sb; @@ -1228,7 +1228,7 @@ __initfunc(void mount_root(void)) extern int initmem_freed; -__initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old)) +static int __init do_change_root(kdev_t new_root_dev,const char *put_old) { kdev_t old_root_dev; struct vfsmount *vfsmnt; diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index e93f8bb11..ee99164fb 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c @@ -38,6 +38,7 @@ static struct file_operations sysv_dir_operations = { NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ file_fsync /* default fsync */ }; diff --git a/fs/sysv/file.c b/fs/sysv/file.c index f4cf216c5..d60be8fa5 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c @@ -48,6 +48,7 @@ static struct file_operations sysv_file_operations = { NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ NULL, /* release */ sysv_sync_file /* fsync */ }; diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index ee0e85674..03d95fda5 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -199,6 +199,7 @@ static struct file_operations ufs_dir_operations = { NULL, /* ioctl */ NULL, /* mmap */ NULL, /* open */ + NULL, /* flush */ NULL, /* release */ file_fsync, /* fsync */ NULL, /* fasync */ diff --git a/fs/ufs/file.c b/fs/ufs/file.c index a6fa50377..d6bd7c139 100644 --- a/fs/ufs/file.c +++ b/fs/ufs/file.c @@ -61,6 +61,7 @@ static struct file_operations ufs_file_operations = { NULL, /* ioctl */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ ufs_release_file, /* release */ NULL, /* fsync */ NULL, /* fasync */ diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index 3f49d0c2e..5cc8f5727 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -1022,6 +1022,7 @@ static struct file_operations umsdos_dir_operations = UMSDOS_ioctl_dir, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync *//* in original NULL. changed to file_fsync. FIXME? /mn/ */ }; diff --git a/fs/umsdos/file.c b/fs/umsdos/file.c index a9267e122..99bf747cc 100644 --- a/fs/umsdos/file.c +++ b/fs/umsdos/file.c @@ -86,6 +86,7 @@ struct file_operations umsdos_file_operations = NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ NULL, /* release */ file_fsync /* fsync */ }; @@ -123,6 +124,7 @@ struct file_operations umsdos_file_operations_no_bmap = NULL, /* ioctl - default */ fat_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ NULL, /* release */ file_fsync /* fsync */ }; @@ -160,6 +162,7 @@ struct file_operations umsdos_file_operations_readpage = NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ + NULL, /* flush */ NULL, /* release */ file_fsync /* fsync */ }; diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c index f0252254a..5d5cd55af 100644 --- a/fs/umsdos/rdir.c +++ b/fs/umsdos/rdir.c @@ -284,6 +284,7 @@ static struct file_operations umsdos_rdir_operations = UMSDOS_ioctl_dir, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ }; diff --git a/fs/umsdos/symlink.c b/fs/umsdos/symlink.c index 32510a46b..696059ce2 100644 --- a/fs/umsdos/symlink.c +++ b/fs/umsdos/symlink.c @@ -149,6 +149,7 @@ static struct file_operations umsdos_symlink_operations = NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open is needed */ + NULL, /* no flush code */ NULL, /* release */ NULL /* fsync */ }; diff --git a/include/asm-alpha/fcntl.h b/include/asm-alpha/fcntl.h index 7f0e967aa..7df92de11 100644 --- a/include/asm-alpha/fcntl.h +++ b/include/asm-alpha/fcntl.h @@ -17,6 +17,7 @@ #define O_NDELAY O_NONBLOCK #define O_SYNC 040000 #define FASYNC 020000 /* fcntl, for BSD compatibility */ +#define O_DIRECT 040000 /* direct disk access - should check with OSF/1 */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ diff --git a/include/asm-alpha/posix_types.h b/include/asm-alpha/posix_types.h index 3cbf6d573..50967ef96 100644 --- a/include/asm-alpha/posix_types.h +++ b/include/asm-alpha/posix_types.h @@ -40,7 +40,7 @@ typedef struct { #define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) #define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) -#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) +#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0) #define __FD_ZERO(set) \ ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h index 30b4950fe..5e4c118a9 100644 --- a/include/asm-arm/uaccess.h +++ b/include/asm-arm/uaccess.h @@ -60,8 +60,11 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n) { - if (access_ok(VERIFY_READ, from, n)) + char *end = (char *)to + n; + if (access_ok(VERIFY_READ, from, n)) { __do_copy_from_user(to, from, n); + if (n) memset(end - n, 0, n); + } return n; } diff --git a/include/asm-i386/fcntl.h b/include/asm-i386/fcntl.h index dfdd500c6..f0ddc3e61 100644 --- a/include/asm-i386/fcntl.h +++ b/include/asm-i386/fcntl.h @@ -3,19 +3,21 @@ /* open/fcntl - O_SYNC is only implemented on blocks devices and on files located on an ext2 file system */ -#define O_ACCMODE 0003 -#define O_RDONLY 00 -#define O_WRONLY 01 -#define O_RDWR 02 -#define O_CREAT 0100 /* not fcntl */ -#define O_EXCL 0200 /* not fcntl */ -#define O_NOCTTY 0400 /* not fcntl */ -#define O_TRUNC 01000 /* not fcntl */ -#define O_APPEND 02000 -#define O_NONBLOCK 04000 +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 #define O_NDELAY O_NONBLOCK -#define O_SYNC 010000 -#define FASYNC 020000 /* fcntl, for BSD compatibility */ +#define O_SYNC 010000 +#define FASYNC 020000 /* fcntl, for BSD compatibility */ +#define O_DIRECT 040000 /* direct disk access hint - currently ignored */ +#define O_LARGEFILE 0100000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h index c56966f64..dc9d624d7 100644 --- a/include/asm-i386/fixmap.h +++ b/include/asm-i386/fixmap.h @@ -60,6 +60,10 @@ extern void set_fixmap (enum fixed_addresses idx, unsigned long phys); #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) +#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) + +extern void __this_fixmap_does_not_exist(void); + /* * 'index to address' translation. If anyone tries to use the idx * directly without tranlation, we catch the bug with a NULL-deference @@ -71,12 +75,15 @@ extern inline unsigned long fix_to_virt(const unsigned int idx) * this branch gets completely eliminated after inlining, * except when someone tries to use fixaddr indices in an * illegal way. (such as mixing up address types or using - * out-of-range indices) + * out-of-range indices). + * + * If it doesn't get removed, the linker will complain + * loudly with a reasonably clear error message.. */ if (idx >= __end_of_fixed_addresses) - panic("illegal fixaddr index!"); + __this_fixmap_does_not_exist(); - return FIXADDR_TOP - (idx << PAGE_SHIFT); + return __fix_to_virt(idx); } #endif diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index 9da2fff06..dcc56f31c 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -268,13 +268,38 @@ do { \ : "r"(size & 3), "0"(size / 4), "D"(to), "S"(from) \ : "di", "si", "memory") +#define __copy_user_zeroing(to,from,size) \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + " movl %1,%0\n" \ + "1: rep; movsb\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: lea 0(%1,%0,4),%0\n" \ + "4: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosb\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,4b\n" \ + ".previous" \ + : "=&c"(size) \ + : "r"(size & 3), "0"(size / 4), "D"(to), "S"(from) \ + : "di", "si", "memory"); + /* We let the __ versions of copy_from/to_user inline, because they're often * used in fast paths and have only a small space overhead. */ static inline unsigned long __generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n) { - __copy_user(to,from,n); + __copy_user_zeroing(to,from,n); return n; } @@ -369,6 +394,141 @@ do { \ } \ } while (0) +/* Optimize just a little bit when we know the size of the move. */ +#define __constant_copy_user_zeroing(to, from, size) \ +do { \ + switch (size & 3) { \ + default: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1:\n" \ + ".section .fixup,\"ax\"\n" \ + "2: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosl\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " shl $2,%0\n" \ + " jmp 1b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,2b\n" \ + ".previous" \ + : "=c"(size) \ + : "S"(from), "D"(to), "0"(size/4) \ + : "di", "si", "memory"); \ + break; \ + case 1: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1: movsb\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosl\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " shl $2,%0\n" \ + " incl %0\n" \ + " jmp 2b\n" \ + "4: pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " incl %0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,4b\n" \ + ".previous" \ + : "=c"(size) \ + : "S"(from), "D"(to), "0"(size/4) \ + : "di", "si", "memory"); \ + break; \ + case 2: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1: movsw\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosl\n" \ + " stosw\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " shl $2,%0\n" \ + " addl $2,%0\n" \ + " jmp 2b\n" \ + "4: pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " stosw\n" \ + " popl %%eax\n" \ + " addl $2,%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,4b\n" \ + ".previous" \ + : "=c"(size) \ + : "S"(from), "D"(to), "0"(size/4) \ + : "di", "si", "memory"); \ + break; \ + case 3: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1: movsw\n" \ + "2: movsb\n" \ + "3:\n" \ + ".section .fixup,\"ax\"\n" \ + "4: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosl\n" \ + " stosw\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " shl $2,%0\n" \ + " addl $3,%0\n" \ + " jmp 2b\n" \ + "5: pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " stosw\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " addl $3,%0\n" \ + " jmp 2b\n" \ + "6: pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " incl %0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,4b\n" \ + " .long 1b,5b\n" \ + " .long 2b,6b\n" \ + ".previous" \ + : "=c"(size) \ + : "S"(from), "D"(to), "0"(size/4) \ + : "di", "si", "memory"); \ + break; \ + } \ +} while (0) + unsigned long __generic_copy_to_user(void *, const void *, unsigned long); unsigned long __generic_copy_from_user(void *, const void *, unsigned long); @@ -384,7 +544,7 @@ static inline unsigned long __constant_copy_from_user(void *to, const void *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) - __constant_copy_user(to,from,n); + __constant_copy_user_zeroing(to,from,n); return n; } @@ -398,7 +558,7 @@ __constant_copy_to_user_nocheck(void *to, const void *from, unsigned long n) static inline unsigned long __constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n) { - __constant_copy_user(to,from,n); + __constant_copy_user_zeroing(to,from,n); return n; } diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 1b23625c6..ced7f4a20 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -27,7 +27,7 @@ #define __NR_lseek 19 #define __NR_getpid 20 #define __NR_mount 21 -#define __NR_oldumount 22 +#define __NR_umount 22 #define __NR_setuid 23 #define __NR_getuid 24 #define __NR_stime 25 @@ -57,7 +57,7 @@ #define __NR_geteuid 49 #define __NR_getegid 50 #define __NR_acct 51 -#define __NR_umount 52 +#define __NR_umount2 52 #define __NR_lock 53 #define __NR_ioctl 54 #define __NR_fcntl 55 diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h index 64b8be7bd..ffd5567b4 100644 --- a/include/asm-m68k/uaccess.h +++ b/include/asm-m68k/uaccess.h @@ -712,9 +712,16 @@ __constant_copy_to_user(void *to, const void *from, unsigned long n) } #define copy_from_user(to, from, n) \ +{ void *__to = (to); \ + void *__from = (from); \ + unsigned long __n = (n); \ + char *__end = (char *)__to + __n; \ + unsigned long __res = \ (__builtin_constant_p(n) ? \ __constant_copy_from_user(to, from, n) : \ - __generic_copy_from_user(to, from, n)) + __generic_copy_from_user(to, from, n)); \ + if (__res) memset(__end - __res, 0, __res); \ + res; } #define copy_to_user(to, from, n) \ (__builtin_constant_p(n) ? \ diff --git a/include/asm-ppc/uaccess.h b/include/asm-ppc/uaccess.h index df3d3d591..65ca165b7 100644 --- a/include/asm-ppc/uaccess.h +++ b/include/asm-ppc/uaccess.h @@ -211,9 +211,12 @@ extern int __copy_tofrom_user(void *to, const void *from, unsigned long size); extern inline unsigned long copy_from_user(void *to, const void *from, unsigned long n) { - if (access_ok(VERIFY_READ, from, n)) - return __copy_tofrom_user(to, from, n); - return n? -EFAULT: 0; + unsigned long res = n; + if (access_ok(VERIFY_READ, from, n)) { + res = __copy_tofrom_user(to, from, n); + if (res) memset((char *)to + n - res, 0, res); + } + return res; } extern inline unsigned long @@ -221,7 +224,7 @@ copy_to_user(void *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) return __copy_tofrom_user(to, from, n); - return n? -EFAULT: 0; + return n; } #define __copy_from_user(to, from, size) \ diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h index 638e234a0..3f4a58601 100644 --- a/include/asm-sparc/uaccess.h +++ b/include/asm-sparc/uaccess.h @@ -318,11 +318,14 @@ if (__copy_to_user(to,from,n)) \ }) #define copy_from_user(to,from,n) ({ \ +void *__copy_to = (void *) (to); \ void *__copy_from = (void *) (from); \ __kernel_size_t __copy_size = (__kernel_size_t) (n); \ __kernel_size_t __copy_res; \ if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \ -__copy_res = __copy_user((void *) (to), __copy_from, __copy_size); \ +__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ +if(__copy_res) \ +memset((char *)__copy_to + __copy_size - __copy_res, 0, __copy_res); \ } else __copy_res = __copy_size; \ __copy_res; }) diff --git a/include/linux/file.h b/include/linux/file.h index fe7ca60c9..0884fad2f 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -5,7 +5,7 @@ #ifndef __LINUX_FILE_H #define __LINUX_FILE_H -extern int __fput(struct file *); +extern void __fput(struct file *); extern void insert_file_free(struct file *file); /* @@ -58,20 +58,18 @@ extern inline void remove_filp(struct file *file) *file->f_pprev = file->f_next; } -extern inline int fput(struct file *file) +extern inline void fput(struct file *file) { int count = file->f_count-1; - int error = 0; if (!count) { locks_remove_flock(file); - error = __fput(file); + __fput(file); file->f_count = 0; remove_filp(file); insert_file_free(file); } else file->f_count = count; - return error; } extern inline void put_filp(struct file *file) diff --git a/include/linux/fs.h b/include/linux/fs.h index 24b132b24..40728572c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -596,6 +596,7 @@ struct file_operations { int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); + int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *); int (*fasync) (int, struct file *, int); @@ -670,7 +671,6 @@ asmlinkage int sys_close(unsigned int); /* yes, it's really unsigned */ extern int do_truncate(struct dentry *, unsigned long); extern int get_unused_fd(void); extern void put_unused_fd(unsigned int); -extern int __fput(struct file *); extern int close_fp(struct file *, fl_owner_t id); extern char * getname(const char * filename); diff --git a/include/linux/pci.h b/include/linux/pci.h index ba9649294..907039e42 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1,5 +1,5 @@ /* - * $Id: pci.h,v 1.80 1998/07/21 10:06:40 mj Exp $ + * $Id: pci.h,v 1.84 1998/08/17 23:06:43 cort Exp $ * * PCI defines and function prototypes * Copyright 1994, Drew Eckhardt @@ -381,7 +381,9 @@ #define PCI_DEVICE_ID_IBM_82351 0x0022 #define PCI_DEVICE_ID_IBM_SERVERAID 0x002e #define PCI_DEVICE_ID_IBM_TR_WAKE 0x003e +#define PCI_DEVICE_ID_IBM_MPIC 0x0046 #define PCI_DEVICE_ID_IBM_3780IDSP 0x007d +#define PCI_DEVICE_ID_IBM_MPIC_2 0xffff #define PCI_VENDOR_ID_WD 0x101c #define PCI_DEVICE_ID_WD_7197 0x3296 @@ -599,6 +601,9 @@ #define PCI_DEVICE_ID_DATABOOK_87144 0xb106 #define PCI_VENDOR_ID_PLX 0x10b5 +#define PCI_DEVICE_ID_PLX_9060 0x9060 +#define PCI_DEVICE_ID_PLX_9060ES 0x906E +#define PCI_DEVICE_ID_PLX_9060SD 0x906D #define PCI_DEVICE_ID_PLX_9080 0x9080 #define PCI_VENDOR_ID_MADGE 0x10b6 diff --git a/include/linux/shm.h b/include/linux/shm.h index f890c7356..50a7b772c 100644 --- a/include/linux/shm.h +++ b/include/linux/shm.h @@ -64,6 +64,7 @@ asmlinkage int sys_shmget (key_t key, int size, int flag); asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, unsigned long *addr); asmlinkage int sys_shmdt (char *shmaddr); asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf); +extern void shm_unuse(unsigned long entry, unsigned long page); #endif /* __KERNEL__ */ diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 11943bcd7..e089d607e 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -216,7 +216,7 @@ struct video_unit #define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */ #define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */ -#define VIDIOCSCHAN _IOW('v',3,int) /* Set channel */ +#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */ #define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */ #define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */ #define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */ diff --git a/init/main.c b/init/main.c index 554665535..4b3783462 100644 --- a/init/main.c +++ b/init/main.c @@ -469,7 +469,7 @@ static struct dev_name_struct { { NULL, 0 } }; -__initfunc(kdev_t name_to_kdev_t(char *line)) +kdev_t __init name_to_kdev_t(char *line) { int base = 0; if (strncmp(line,"/dev/",5) == 0) { @@ -488,7 +488,7 @@ __initfunc(kdev_t name_to_kdev_t(char *line)) return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16)); } -__initfunc(static void root_dev_setup(char *line, int *num)) +static void __init root_dev_setup(char *line, int *num) { ROOT_DEV = name_to_kdev_t(line); } @@ -816,32 +816,32 @@ static struct kernel_param raw_params[] __initdata = { }; #ifdef CONFIG_BLK_DEV_RAM -__initfunc(static void ramdisk_start_setup(char *str, int *ints)) +static void __init ramdisk_start_setup(char *str, int *ints) { if (ints[0] > 0 && ints[1] >= 0) rd_image_start = ints[1]; } -__initfunc(static void load_ramdisk(char *str, int *ints)) +static void __init load_ramdisk(char *str, int *ints) { if (ints[0] > 0 && ints[1] >= 0) rd_doload = ints[1] & 1; } -__initfunc(static void prompt_ramdisk(char *str, int *ints)) +static void __init prompt_ramdisk(char *str, int *ints) { if (ints[0] > 0 && ints[1] >= 0) rd_prompt = ints[1] & 1; } -__initfunc(static void ramdisk_size(char *str, int *ints)) +static void __init ramdisk_size(char *str, int *ints) { if (ints[0] > 0 && ints[1] >= 0) rd_size = ints[1]; } #endif -__initfunc(static int checksetup(char *line)) +static int __init checksetup(char *line) { int i, ints[11]; @@ -878,7 +878,7 @@ unsigned long loops_per_sec = (1<<12); better than 1% */ #define LPS_PREC 8 -__initfunc(void calibrate_delay(void)) +void __init calibrate_delay(void) { unsigned long ticks, loopbit; int lps_precision = LPS_PREC; @@ -930,7 +930,7 @@ __initfunc(void calibrate_delay(void)) * This routine also checks for options meant for the kernel. * These options are not given to init - they are for internal kernel use only. */ -__initfunc(static void parse_options(char *line)) +static void __init parse_options(char *line) { char *next; int args, envs; @@ -1014,7 +1014,7 @@ int cpu_idle(void *unused) extern int cpu_idle(void * unused); /* Called by boot processor to activate the rest. */ -__initfunc(static void smp_init(void)) +static void __init smp_init(void) { /* Get other processors into their bootup holding patterns. */ smp_boot_cpus(); @@ -1026,7 +1026,7 @@ __initfunc(static void smp_init(void)) * they are finished. */ -__initfunc(static void smp_begin(void)) +static void __init smp_begin(void) { smp_threads_ready=1; smp_commence(); @@ -1040,7 +1040,7 @@ extern void initialize_secondary(void); * Activate the first processor. */ -__initfunc(asmlinkage void start_kernel(void)) +asmlinkage void __init start_kernel(void) { char * command_line; @@ -1188,7 +1188,7 @@ static int do_linuxrc(void * shell) return execve(shell, argv, envp_init); } -__initfunc(static void no_initrd(char *s,int *ints)) +static void __init no_initrd(char *s,int *ints) { mount_initrd = 0; } diff --git a/ipc/sem.c b/ipc/sem.c index 0ab578584..8e8ce2c44 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -56,7 +56,7 @@ static int max_semid = 0; static unsigned short sem_seq = 0; -__initfunc(void sem_init (void)) +void __init sem_init (void) { int i; diff --git a/ipc/shm.c b/ipc/shm.c index c7568b784..0ec61b1e3 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -3,6 +3,7 @@ * Copyright (C) 1992, 1993 Krishna Balasubramanian * Many improvements/fixes by Bruno Haible. * Replaced `struct shm_desc' by `struct vm_area_struct', July 1994. + * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli. */ #include @@ -45,7 +46,7 @@ static ulong swap_attempts = 0; static ulong swap_successes = 0; static ulong used_segs = 0; -__initfunc(void shm_init (void)) +void __init shm_init (void) { int id; @@ -837,3 +838,38 @@ int shm_swap (int prio, int gfp_mask) shm_rss--; return 1; } + +/* + * Free the swap entry and set the new pte for the shm page. + */ +static void shm_unuse_page(struct shmid_ds *shp, unsigned long idx, + unsigned long page, unsigned long entry) +{ + pte_t pte; + + pte = pte_mkdirty(mk_pte(page, PAGE_SHARED)); + shp->shm_pages[idx] = pte_val(pte); + atomic_inc(&mem_map[MAP_NR(page)].count); + shm_rss++; + + swap_free(entry); + shm_swp--; +} + +/* + * unuse_shm() search for an eventually swapped out shm page. + */ +void shm_unuse(unsigned long entry, unsigned long page) +{ + int i, n; + + for (i = 0; i < SHMMNI; i++) + if (shm_segs[i] != IPC_UNUSED && shm_segs[i] != IPC_NOID) + for (n = 0; n < shm_segs[i]->shm_npages; n++) + if (shm_segs[i]->shm_pages[n] == entry) + { + shm_unuse_page(shm_segs[i], n, + page, entry); + return; + } +} diff --git a/ipc/util.c b/ipc/util.c index c7933273a..1938d0be3 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -24,7 +24,7 @@ extern void sem_init (void), msg_init (void), shm_init (void); -__initfunc(void ipc_init (void)) +void __init ipc_init (void) { sem_init(); msg_init(); diff --git a/kernel/capability.c b/kernel/capability.c index 60d4ed6b5..b2a8d43a1 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -147,7 +147,6 @@ asmlinkage int sys_capset(cap_user_header_t header, const cap_user_data_t data) return -EINVAL; } - /* may want to set other processes at some point -- for now demand 0 */ if (get_user(pid, &header->pid)) return -EFAULT; diff --git a/kernel/fork.c b/kernel/fork.c index 6035d7a50..e9508bda9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -125,7 +125,7 @@ int alloc_uid(struct task_struct *p) return 0; } -__initfunc(void uidcache_init(void)) +void __init uidcache_init(void) { int i; @@ -641,7 +641,7 @@ bad_fork_free: goto bad_fork; } -__initfunc(void filescache_init(void)) +void __init filescache_init(void) { files_cachep = kmem_cache_create("files_cache", sizeof(struct files_struct), diff --git a/kernel/kmod.c b/kernel/kmod.c index ec0d85d32..4a7e3ebda 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -116,7 +116,7 @@ int request_module(const char * module_name) /* Block everything but SIGKILL/SIGSTOP */ spin_lock_irq(¤t->sigmask_lock); tmpsig = current->blocked; - siginitset(¤t->blocked, ~(sigmask(SIGKILL)|sigmask(SIGSTOP))); + siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP)); recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); diff --git a/kernel/panic.c b/kernel/panic.c index 3a81eb088..a102a9598 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -25,7 +25,7 @@ extern int C_A_D; int panic_timeout = 0; -__initfunc(void panic_setup(char *str, int *ints)) +void __init panic_setup(char *str, int *ints) { if (ints[0] == 1) panic_timeout = ints[1]; diff --git a/kernel/printk.c b/kernel/printk.c index 2998dbede..0d8287fef 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -58,7 +58,7 @@ static int preferred_console = -1; /* * Setup a list of consoles. Called from init/main.c */ -__initfunc(void console_setup(char *str, int *ints)) +void __init console_setup(char *str, int *ints) { struct console_cmdline *c; char name[sizeof(c->name)]; diff --git a/kernel/resource.c b/kernel/resource.c index dc23b159b..2d6b56eb0 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -182,7 +182,7 @@ unsigned long occupy_region(unsigned long base, unsigned long end, #endif /* Called from init/main.c to reserve IO ports. */ -__initfunc(void reserve_setup(char *str, int *ints)) +void __init reserve_setup(char *str, int *ints) { int i; diff --git a/kernel/sched.c b/kernel/sched.c index ace9d0f13..228a397eb 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1675,7 +1675,7 @@ void show_state(void) read_unlock(&tasklist_lock); } -__initfunc(void sched_init(void)) +void __init sched_init(void) { /* * We have to do a little magic to get the first diff --git a/kernel/signal.c b/kernel/signal.c index b1e0a642c..7469c0d08 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -38,8 +39,7 @@ static kmem_cache_t *signal_queue_cachep; static int nr_queued_signals; static int max_queued_signals = 1024; -void -signals_init(void) +void __init signals_init(void) { signal_queue_cachep = kmem_cache_create("signal_queue", diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 20798b239..132739310 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -95,6 +95,7 @@ struct file_operations proc_sys_file_operations = NULL, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* no special flush code */ NULL, /* no special release code */ NULL /* can't fsync */ }; @@ -251,7 +252,7 @@ static ctl_table dev_table[] = { }; -__initfunc(void sysctl_init(void)) +void __init sysctl_init(void) { #ifdef CONFIG_PROC_FS register_proc_table(root_table, &proc_sys_root); diff --git a/mm/mmap.c b/mm/mmap.c index 172bcd8f1..77b0c5d62 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -688,7 +688,7 @@ void merge_segments (struct mm_struct * mm, unsigned long start_addr, unsigned l mm->mmap_cache = NULL; /* Kill the cache. */ } -__initfunc(void vma_init(void)) +void __init vma_init(void) { vm_area_cachep = kmem_cache_create("vm_area_struct", sizeof(struct vm_area_struct), diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 70766c353..2db2a66e3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -318,7 +318,7 @@ void show_free_areas(void) * - mark all memory queues empty * - clear the memory bitmaps */ -__initfunc(unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem)) +unsigned long __init free_area_init(unsigned long start_mem, unsigned long end_mem) { mem_map_t * p; unsigned long mask = PAGE_MASK; diff --git a/mm/slab.c b/mm/slab.c index 35433b3b8..5a00becdb 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -406,7 +406,7 @@ static kmem_cache_t *cache_slabp = NULL; static unsigned long bufctl_limit = 0; /* Initialisation - setup the `cache' cache. */ -__initfunc(long kmem_cache_init(long start, long end)) +long __init kmem_cache_init(long start, long end) { size_t size, i; @@ -460,7 +460,7 @@ __initfunc(long kmem_cache_init(long start, long end)) /* Initialisation - setup remaining internal and general caches. * Called after the gfp() functions have been enabled, and before smp_init(). */ -__initfunc(void kmem_cache_sizes_init(void)) +void __init kmem_cache_sizes_init(void) { unsigned int found = 0; diff --git a/mm/swapfile.c b/mm/swapfile.c index 0df60f6f0..b644b0680 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -22,6 +22,7 @@ #include /* for blk_size */ #include #include +#include #include #include @@ -325,6 +326,7 @@ static int try_to_unuse(unsigned int type) for_each_task(p) unuse_process(p->mm, entry, page); read_unlock(&tasklist_lock); + shm_unuse(entry, page); /* Now get rid of the extra reference to the temporary page we've been using. */ if (PageSwapCache(page_map)) diff --git a/mm/vmscan.c b/mm/vmscan.c index 63faf5465..961b27022 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -491,7 +492,7 @@ static int do_try_to_free_page(int gfp_mask) * may be printed in the middle of another driver's init * message). It looks very bad when that happens. */ -void kswapd_setup(void) +void __init kswapd_setup(void) { int i; char *revision="$Revision: 1.5 $", *s, *e; diff --git a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c index 94be0069b..288cfd9a9 100644 --- a/net/netlink/netlink_dev.c +++ b/net/netlink/netlink_dev.c @@ -185,6 +185,7 @@ static struct file_operations netlink_fops = { netlink_ioctl, NULL, /* netlink_mmap */ netlink_open, + NULL, /* flush */ netlink_release }; diff --git a/net/socket.c b/net/socket.c index 1d905854d..4ddb606f2 100644 --- a/net/socket.c +++ b/net/socket.c @@ -122,6 +122,7 @@ static struct file_operations socket_file_ops = { sock_ioctl, NULL, /* mmap */ NULL, /* no special open code... */ + NULL, /* flush */ sock_close, NULL, /* no fsync */ sock_fasync @@ -1441,7 +1442,7 @@ int sock_unregister(int family) return 0; } -__initfunc(void proto_init(void)) +void __init proto_init(void) { extern struct net_proto protocols[]; /* Network protocols */ struct net_proto *pro; @@ -1461,7 +1462,7 @@ extern void sk_init(void); extern void wanrouter_init(void); #endif -__initfunc(void sock_init(void)) +void __init sock_init(void) { int i; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index c26906846..9380ff4a4 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -413,7 +413,7 @@ call_allocate(struct rpc_task *task) return; printk("RPC: buffer allocation failed for task %p\n", task); - if (1 || !signalled()) { + if (!signalled()) { xprt_release(task); task->tk_action = call_reserve; rpc_delay(task, HZ); diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 222f905da..c2dcac0e9 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -128,7 +128,7 @@ rpc_add_timer(struct rpc_task *task, rpc_action timer) if (!timer) timer = __rpc_default_timer; if (expires < jiffies) { - printk("RPC: bad timeout value %ld - setting to 10 sec!\n", + printk(KERN_ERR "RPC: bad timeout value %ld - setting to 10 sec!\n", task->tk_timeout); expires = jiffies + 10 * HZ; } @@ -164,7 +164,7 @@ static inline void rpc_make_runnable(struct rpc_task *task) { if (task->tk_timeout) { - printk("RPC: task w/ running timer in rpc_make_runnable!!\n"); + printk(KERN_ERR "RPC: task w/ running timer in rpc_make_runnable!!\n"); return; } if (RPC_IS_ASYNC(task)) { @@ -242,7 +242,7 @@ __rpc_wake_up(struct rpc_task *task) #ifdef RPC_DEBUG if (task->tk_magic != 0xf00baa) { - printk("RPC: attempt to wake up non-existing task!\n"); + printk(KERN_ERR "RPC: attempt to wake up non-existing task!\n"); rpc_debug = ~0; return; } @@ -352,7 +352,6 @@ __rpc_atrun(struct rpc_task *task) /* * This is the RPC `scheduler' (or rather, the finite state machine). */ - static int __rpc_execute(struct rpc_task *task) { @@ -363,7 +362,7 @@ __rpc_execute(struct rpc_task *task) task->tk_pid, task->tk_flags); if (!RPC_IS_RUNNING(task)) { - printk("RPC: rpc_execute called for sleeping task!!\n"); + printk(KERN_WARNING "RPC: rpc_execute called for sleeping task!!\n"); return 0; } @@ -413,18 +412,12 @@ __rpc_execute(struct rpc_task *task) dprintk("RPC: %4d sync task going to sleep\n", task->tk_pid); if (current->pid == rpciod_pid) - printk("RPC: rpciod waiting on sync task!\n"); + printk(KERN_ERR "RPC: rpciod waiting on sync task!\n"); current->timeout = 0; sleep_on(&task->tk_wait); - + /* When the task received a signal, remove from - * any queues etc, and make runnable again. - * - * The "intr" property isnt handled here. rpc_do_call - * has changed the signal mask of the process for - * a synchronous rpc call. If a signal gets through - * this then its real. - */ + * any queues etc, and make runnable again. */ if (signalled()) __rpc_wake_up(task); @@ -467,11 +460,11 @@ rpc_execute(struct rpc_task *task) if (incr) { if (rpc_inhibit) { - printk("RPC: execution inhibited!\n"); + printk(KERN_INFO "RPC: execution inhibited!\n"); return; } if (executing) - printk("RPC: %d tasks executed\n", executing); + printk(KERN_WARNING "RPC: %d tasks executed\n", executing); } executing += incr; @@ -770,6 +763,8 @@ rpc_killall_tasks(struct rpc_clnt *clnt) rpc_inhibit--; } +static struct semaphore rpciod_running = MUTEX_LOCKED; + /* * This is the rpciod kernel thread */ @@ -786,11 +781,16 @@ rpciod(void *ptr) * Let our maker know we're running ... */ rpciod_pid = current->pid; - wake_up(&rpciod_idle); + up(&rpciod_running); exit_files(current); exit_mm(current); + + spin_lock_irq(¤t->sigmask_lock); siginitsetinv(¤t->blocked, sigmask(SIGKILL)); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + current->session = 1; current->pgrp = 1; sprintf(current->comm, "rpciod"); @@ -798,12 +798,7 @@ rpciod(void *ptr) dprintk("RPC: rpciod starting (pid %d)\n", rpciod_pid); while (rpciod_users) { if (signalled()) { - if (sigismember(¤t->signal, SIGKILL)) { - rpciod_killall(); - } else { - printk("rpciod: ignoring signal (%d users)\n", - rpciod_users); - } + rpciod_killall(); flush_signals(current); } __rpc_schedule(); @@ -825,7 +820,7 @@ rpciod(void *ptr) dprintk("RPC: rpciod shutdown commences\n"); if (all_tasks) { - printk("rpciod: active tasks at shutdown?!\n"); + printk(KERN_ERR "rpciod: active tasks at shutdown?!\n"); rpciod_killall(); } @@ -847,7 +842,7 @@ rpciod_killall(void) rpc_killall_tasks(NULL); __rpc_schedule(); if (all_tasks) { -printk("rpciod_killall: waiting for tasks to exit\n"); + dprintk("rpciod_killall: waiting for tasks to exit\n"); current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + 1; schedule(); @@ -878,16 +873,17 @@ rpciod_up(void) * If there's no pid, we should be the first user. */ if (rpciod_users > 1) - printk("rpciod_up: no pid, %d users??\n", rpciod_users); + printk(KERN_WARNING "rpciod_up: no pid, %d users??\n", rpciod_users); /* * Create the rpciod thread and wait for it to start. */ error = kernel_thread(rpciod, &rpciod_killer, 0); if (error < 0) { - printk("rpciod_up: create thread failed, error=%d\n", error); + printk(KERN_WARNING "rpciod_up: create thread failed, error=%d\n", error); + rpciod_users--; goto out; } - sleep_on(&rpciod_idle); + down(&rpciod_running); error = 0; out: up(&rpciod_sema); @@ -907,10 +903,10 @@ rpciod_down(void) if (--rpciod_users) goto out; } else - printk("rpciod_down: pid=%d, no users??\n", rpciod_pid); + printk(KERN_WARNING "rpciod_down: pid=%d, no users??\n", rpciod_pid); if (!rpciod_pid) { - printk("rpciod_down: Nothing to do!\n"); + dprintk("rpciod_down: Nothing to do!\n"); goto out; } @@ -928,9 +924,9 @@ rpciod_down(void) * Display a message if we're going to wait longer. */ while (rpciod_pid) { - printk("rpciod_down: waiting for pid %d to exit\n", rpciod_pid); + dprintk("rpciod_down: waiting for pid %d to exit\n", rpciod_pid); if (signalled()) { - printk("rpciod_down: caught signal\n"); + dprintk("rpciod_down: caught signal\n"); break; } interruptible_sleep_on(&rpciod_killer); diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 518703d07..4566ce5d2 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -140,9 +140,8 @@ xprt_from_sock(struct sock *sk) * Adjust the iovec to move on 'n' bytes */ -extern inline void xprt_move_iov(struct msghdr *msg, int amount) +extern inline void xprt_move_iov(struct msghdr *msg, struct iovec *niv, int amount) { - struct iovec niv[MAX_IOVEC]; struct iovec *iv=msg->msg_iov; /* @@ -187,6 +186,7 @@ xprt_sendmsg(struct rpc_xprt *xprt) struct msghdr msg; mm_segment_t oldfs; int result; + struct iovec niv[MAX_IOVEC]; xprt_pktdump("packet data:", xprt->snd_buf.io_vec->iov_base, @@ -202,7 +202,7 @@ xprt_sendmsg(struct rpc_xprt *xprt) /* Dont repeat bytes */ if(xprt->snd_sent) - xprt_move_iov(&msg, xprt->snd_sent); + xprt_move_iov(&msg, niv, xprt->snd_sent); oldfs = get_fs(); set_fs(get_ds()); result = sock_sendmsg(sock, &msg, xprt->snd_buf.io_len); diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index 088487077..b619e1dae 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -102,6 +102,7 @@ static struct file_operations router_fops = NULL, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; @@ -141,6 +142,7 @@ static struct file_operations wandev_fops = wanrouter_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ + NULL, /* flush */ NULL, /* no special release code */ NULL /* can't fsync */ }; -- 2.11.4.GIT