From 433b8708b5594e539f468dc9ce434889066c4c48 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:27:32 -0500 Subject: [PATCH] Import 2.3.20pre2 --- arch/i386/kernel/bios32.c | 7 ++-- drivers/Makefile | 9 +++-- drivers/char/ppdev.c | 36 +++++++++++++++++++ drivers/char/ppdev.h | 7 ++++ drivers/parport/init.c | 2 ++ drivers/parport/parport_pc.c | 3 +- drivers/parport/share.c | 8 +++-- drivers/pci/Makefile | 2 +- drivers/pci/helper.c | 69 ++++++++++++++++++++++++++++++++++++ drivers/sound/esssolo1.c | 29 ++++++++++++--- include/linux/parport.h | 1 + include/linux/pci.h | 25 +++++++++++++ 12 files changed, 183 insertions(+), 15 deletions(-) create mode 100644 drivers/pci/helper.c diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c index cee8e7fcd8ca..770e8592fc55 100644 --- a/arch/i386/kernel/bios32.c +++ b/arch/i386/kernel/bios32.c @@ -1053,14 +1053,17 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) */ if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) return; +/* This just can't be right even with the fixes */ +#if 0 DBG("PCI: IDE base address fixup for %s\n", d->slot_name); - for(i=0; i<4; i += 2) { + for(i=0; i<4; i++) { struct resource *r = &d->resource[i]; - if (r->start) { + if ((r->start & ~0x80) == 0x374) { r->start += 2; r->end = r->start; } } +#endif } struct pci_fixup pcibios_fixups[] = { diff --git a/drivers/Makefile b/drivers/Makefile index 28542ded07fd..ece4a192c679 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -11,7 +11,7 @@ SUB_DIRS := block char net parport sound misc MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) pci sgi scsi sbus cdrom isdn pnp i2o \ macintosh video dio zorro fc4 usb \ - nubus tc ap1000 atm + nubus tc ap1000 atm pcmcia ifdef CONFIG_DIO SUB_DIRS += dio @@ -22,8 +22,12 @@ ifdef CONFIG_PCI SUB_DIRS += pci endif -ifdef CONFIG_PCMCIA +ifeq ($(CONFIG_PCMCIA),y) SUB_DIRS += pcmcia +else + ifeq ($(CONFIG_PCMCIA),m) + MOD_SUB_DIRS += pcmcia + endif endif ifdef CONFIG_SBUS @@ -117,7 +121,6 @@ endif ifeq ($(CONFIG_AP1000),y) SUB_DIRS += ap1000 -ALL_SUB_DIRS += ap1000 endif ifeq ($(CONFIG_FC4),y) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index c210b07853b2..d73f128d87c3 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -34,8 +34,12 @@ * YIELD parport_yield_blocking * WCTLONIRQ on interrupt, set control lines * CLRIRQ clear (and return) interrupt count + * SETTIME sets device timeout (struct timeval) + * GETTIME gets device timeout (struct timeval) * read/write read or write in current IEEE 1284 protocol * select wait for interrupt (in readfds) + * + * Added SETTIME/GETTIME ioctl, Fred Barnes 1999. */ #include @@ -74,6 +78,9 @@ struct pp_struct { #define PP_BUFFER_SIZE 256 #define PARDEVICE_MAX 8 +/* ROUND_UP macro from fs/select.c */ +#define ROUND_UP(x,y) (((x)+(y)-1)/(y)) + static inline void enable_irq (struct pp_struct *pp) { struct parport *port = pp->pdev->port; @@ -356,6 +363,8 @@ static int pp_ioctl(struct inode *inode, struct file *file, unsigned char mask; int mode; int ret; + struct timeval par_timeout; + long to_jiffies; case PPRSTATUS: reg = parport_read_status (port); @@ -451,6 +460,33 @@ static int pp_ioctl(struct inode *inode, struct file *file, atomic_sub (ret, &pp->irqc); return 0; + case PPSETTIME: + if (copy_from_user (&par_timeout, (struct timeval *)arg, + sizeof(struct timeval))) { + return -EFAULT; + } + /* Convert to jiffies, place in pp->pdev->timeout */ + if ((par_timeout.tv_sec < 0) || (par_timeout.tv_usec < 0)) { + return -EINVAL; + } + to_jiffies = ROUND_UP(par_timeout.tv_usec, 1000000/HZ); + to_jiffies += par_timeout.tv_sec * (long)HZ; + if (to_jiffies <= 0) { + return -EINVAL; + } + pp->pdev->timeout = to_jiffies; + return 0; + + case PPGETTIME: + to_jiffies = pp->pdev->timeout; + par_timeout.tv_sec = to_jiffies / HZ; + par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ); + if (copy_to_user ((struct timeval *)arg, &par_timeout, + sizeof(struct timeval))) { + return -EFAULT; + } + return 0; + default: printk (KERN_DEBUG CHRDEV "%x: What? (cmd=0x%x)\n", minor, cmd); diff --git a/drivers/char/ppdev.h b/drivers/char/ppdev.h index 976374aed09e..40f013556c5f 100644 --- a/drivers/char/ppdev.h +++ b/drivers/char/ppdev.h @@ -10,6 +10,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * + * Added PPGETTIME/PPSETTIME, Fred Barnes, 1999 */ #define PP_MAJOR 99 @@ -72,3 +73,9 @@ struct ppdev_frob_struct { /* Set the IEEE 1284 phase that we're in (e.g. IEEE1284_PH_FWD_IDLE) */ #define PPSETPHASE _IOW(PP_IOCTL, 0x94, int) + +/* Set and get port timeout (struct timeval's) */ +#define PPGETTIME _IOW(PP_IOCTL, 0x95, struct timeval) +#define PPSETTIME _IOR(PP_IOCTL, 0x96, struct timeval) + + diff --git a/drivers/parport/init.c b/drivers/parport/init.c index 8f30d60c1aed..432fede95faf 100644 --- a/drivers/parport/init.c +++ b/drivers/parport/init.c @@ -91,6 +91,8 @@ static int __init parport_setup (char *str) if (sep++) { if (!strncmp (sep, "auto", 4)) dma[parport_setup_ptr] = PARPORT_DMA_AUTO; + else if (!strncmp (sep, "nofifo", 6)) + dma[parport_setup_ptr] = PARPORT_DMA_NOFIFO; else if (strncmp (sep, "none", 4)) { val = simple_strtoul (sep, &endptr, 0); if (endptr == sep) { diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index efa644f8010a..3dcf334cdddc 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -1604,7 +1604,8 @@ struct parport *__maybe_init parport_pc_probe_port (unsigned long int base, p->dma = PARPORT_DMA_NONE; #ifdef CONFIG_PARPORT_PC_FIFO - if (priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) { + if (p->dma != PARPORT_DMA_NOFIFO && + priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) { p->ops->compat_write_data = parport_pc_compat_write_block_pio; #ifdef CONFIG_PARPORT_1284 p->ops->ecp_write_data = parport_pc_ecp_write_block_pio; diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 94b9f035b163..7c127fd18a8b 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -633,7 +633,7 @@ void parport_release(struct pardevice *dev) } static int parport_parse_params (int nports, const char *str[], int val[], - int automatic, int none) + int automatic, int none, int nofifo) { unsigned int i; for (i = 0; i < nports && str[i]; i++) { @@ -641,6 +641,8 @@ static int parport_parse_params (int nports, const char *str[], int val[], val[i] = automatic; else if (!strncmp(str[i], "none", 4)) val[i] = none; + else if (nofifo && !strncmp(str[i], "nofifo", 4)) + val[i] = nofifo; else { char *ep; unsigned long r = simple_strtoul(str[i], &ep, 0); @@ -659,11 +661,11 @@ static int parport_parse_params (int nports, const char *str[], int val[], int parport_parse_irqs(int nports, const char *irqstr[], int irqval[]) { return parport_parse_params (nports, irqstr, irqval, PARPORT_IRQ_AUTO, - PARPORT_IRQ_NONE); + PARPORT_IRQ_NONE, 0); } int parport_parse_dmas(int nports, const char *dmastr[], int dmaval[]) { return parport_parse_params (nports, dmastr, dmaval, PARPORT_DMA_AUTO, - PARPORT_DMA_NONE); + PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO); } diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 4511040eee84..0503f4af1cae 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -25,7 +25,7 @@ ifdef CONFIG_PROC_FS L_OBJS += proc.o endif -L_OBJS += compat.o quirks.o names.o +L_OBJS += compat.o quirks.o names.o helper.o ifndef CONFIG_X86 L_OBJS += syscall.o setup.o diff --git a/drivers/pci/helper.c b/drivers/pci/helper.c new file mode 100644 index 000000000000..928cec4b5a6f --- /dev/null +++ b/drivers/pci/helper.c @@ -0,0 +1,69 @@ +/* + * $Id$ + * + * drivers/pci/helper.c + * + * Copyright 1999 Jeff Garzik + * This software is free. See the file COPYING for licensing details. + * + */ + +#include +#include +#include + + +int pci_simple_probe (struct pci_simple_probe_entry *list, size_t match_limit, + pci_simple_probe_callback cb, void *drvr_data) +{ + struct pci_dev *dev; + struct pci_simple_probe_entry *ent; + size_t matches = 0; + unsigned short vendor, device; + int rc; + + if (!list || !cb) + return -1; + + dev = pci_find_device (PCI_ANY_ID, PCI_ANY_ID, NULL); + while (dev) { + ent = list; + while (ent->vendor && ent->device) { + vendor = ent->vendor; + device = ent->device; + + if (((vendor != 0xFFFF) && + (vendor != dev->vendor)) || + ((device != 0xFFFF) && + (device != dev->device))) { + ent++; + continue; + } + + if (((ent->subsys_vendor) && + (ent->subsys_vendor != dev->subsystem_vendor)) || + ((ent->subsys_device) && + (ent->subsys_device != dev->subsystem_device))) { + ent++; + continue; + } + + rc = (* cb) (dev, matches, ent, drvr_data); + if (rc < 0) + return rc; + + matches++; + + if (match_limit && match_limit == matches) + return matches; + + ent++; + } + + dev = pci_find_device (PCI_ANY_ID, PCI_ANY_ID, dev); + } + + return matches; +} + + diff --git a/drivers/sound/esssolo1.c b/drivers/sound/esssolo1.c index 90ccaf342e9b..ec41d0b6a1d8 100644 --- a/drivers/sound/esssolo1.c +++ b/drivers/sound/esssolo1.c @@ -58,6 +58,8 @@ * replaced current->state = x with set_current_state(x) * 03.09.99 0.8 change read semantics for MIDI to match * OSS more closely; remove possible wakeup race + * 07.10.99 0.9 Fix initialization; complain if sequencer writes time out + * Revised resource grabbing for the FM synthesizer * */ @@ -108,6 +110,7 @@ #define MPUBASE_EXTENT 4 #define GPBASE_EXTENT 4 +#define FMSYNTH_EXTENT 4 /* MIDI buffer sizes */ @@ -207,7 +210,7 @@ extern inline void write_seq(struct solo1_state *s, unsigned char data) { int i; unsigned long flags; - + /* the __cli stunt is to send the data within the command window */ for (i = 0; i < 0xffff; i++) { __save_flags(flags); @@ -219,6 +222,8 @@ extern inline void write_seq(struct solo1_state *s, unsigned char data) } __restore_flags(flags); } + printk(KERN_ERR "esssolo1: write_seq timeout\n"); + outb(data, s->sbbase+0xc); } extern inline int read_seq(struct solo1_state *s, unsigned char *data) @@ -232,6 +237,7 @@ extern inline int read_seq(struct solo1_state *s, unsigned char *data) *data = inb(s->sbbase+0xa); return 1; } + printk(KERN_ERR "esssolo1: read_seq timeout\n"); return 0; } @@ -1993,6 +1999,12 @@ static int solo1_dmfm_open(struct inode *inode, struct file *file) return -ERESTARTSYS; down(&s->open_sem); } + if (check_region(s->sbbase, FMSYNTH_EXTENT)) { + up(&s->open_sem); + printk(KERN_ERR "solo1: FM synth io ports in use, opl3 loaded?\n"); + return -EBUSY; + } + request_region(s->sbbase, FMSYNTH_EXTENT, "ESS Solo1"); /* init the stuff */ outb(1, s->sbbase); outb(0x20, s->sbbase+1); /* enable waveforms */ @@ -2020,6 +2032,7 @@ static int solo1_dmfm_release(struct inode *inode, struct file *file) outb(regb, s->sbbase+2); outb(0, s->sbbase+3); } + release_region(s->sbbase, FMSYNTH_EXTENT); up(&s->open_sem); wake_up(&s->open_wait); MOD_DEC_USE_COUNT; @@ -2113,14 +2126,14 @@ static int __init init_solo1(void) s->gpbase = RSRCADDRESS(pcidev, 4); s->irq = pcidev->irq; if (check_region(s->iobase, IOBASE_EXTENT) || - check_region(s->sbbase+4, SBBASE_EXTENT-4) || + check_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT) || check_region(s->ddmabase, DDMABASE_EXTENT) || check_region(s->mpubase, MPUBASE_EXTENT)) { printk(KERN_ERR "solo1: io ports in use\n"); goto err_region; } request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1"); - request_region(s->sbbase+4, SBBASE_EXTENT-4, "ESS Solo1"); /* allow OPL3 synth module */ + request_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT, "ESS Solo1"); request_region(s->ddmabase, DDMABASE_EXTENT, "ESS Solo1"); request_region(s->mpubase, MPUBASE_EXTENT, "ESS Solo1"); if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) { @@ -2147,6 +2160,10 @@ static int __init init_solo1(void) if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0) goto err_dev4; /* initialize the chips */ + if (!reset_ctrl(s)) { + printk(KERN_ERR "esssolo1: cannot reset controller\n"); + goto err; + } outb(0xb0, s->iobase+7); /* enable A1, A2, MPU irq's */ /* initialize mixer regs */ @@ -2181,6 +2198,8 @@ static int __init init_solo1(void) index++; continue; + err: + unregister_sound_dsp(s->dev_dmfm); err_dev4: unregister_sound_dsp(s->dev_midi); err_dev3: @@ -2192,7 +2211,7 @@ static int __init init_solo1(void) free_irq(s->irq, s); err_irq: release_region(s->iobase, IOBASE_EXTENT); - release_region(s->sbbase+4, SBBASE_EXTENT-4); + release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT); release_region(s->ddmabase, DDMABASE_EXTENT); release_region(s->mpubase, MPUBASE_EXTENT); err_region: @@ -2222,7 +2241,7 @@ static void __exit cleanup_solo1(void) pci_write_config_word(s->pcidev, 0x60, 0); /* turn off DDMA controller address space */ free_irq(s->irq, s); release_region(s->iobase, IOBASE_EXTENT); - release_region(s->sbbase+4, SBBASE_EXTENT-4); + release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT); release_region(s->ddmabase, DDMABASE_EXTENT); release_region(s->mpubase, MPUBASE_EXTENT); unregister_sound_dsp(s->dev_audio); diff --git a/include/linux/parport.h b/include/linux/parport.h index 50256a87d882..f1c6cb5af2c6 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -13,6 +13,7 @@ #define PARPORT_DMA_NONE -1 #define PARPORT_IRQ_AUTO -2 #define PARPORT_DMA_AUTO -2 +#define PARPORT_DMA_NOFIFO -3 #define PARPORT_DISABLE -2 #define PARPORT_IRQ_PROBEONLY -3 diff --git a/include/linux/pci.h b/include/linux/pci.h index abb2879e80b7..a5279999718e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -470,6 +470,28 @@ void pci_set_bus_ranges(void); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), int (*)(struct pci_dev *, u8, u8)); +/* + * simple PCI probing for drivers + */ + +struct pci_simple_probe_entry; +typedef int (*pci_simple_probe_callback) (struct pci_dev *dev, int match_num, + const struct pci_simple_probe_entry *ent, + void *drvr_data); + +struct pci_simple_probe_entry { + unsigned short vendor; /* vendor id, PCI_ANY_ID, or 0 for last entry */ + unsigned short device; /* device id, PCI_ANY_ID, or 0 for last entry */ + unsigned short subsys_vendor; /* subsystem vendor id, 0 for don't care */ + unsigned short subsys_device; /* subsystem device id, 0 for don't care */ + void *dev_data; /* driver-private, entry-specific data */ +}; + +int pci_simple_probe (struct pci_simple_probe_entry *list, size_t match_limit, + pci_simple_probe_callback cb, void *drvr_data); + + + /* * If the system does not have PCI, clearly these return errors. Define * these as simple inline functions to avoid hair in drivers. @@ -505,6 +527,9 @@ unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from) extern inline void pci_set_master(struct pci_dev *dev) { return; } +extern inline int pci_simple_probe (struct pci_simple_probe_entry *list, size_t match_limit, + pci_simple_probe_callback cb, void *drvr_data) +{ return 0; } #endif /* !CONFIG_PCI */ -- 2.39.5