S: Blacksburg, Virginia 24061
S: USA
+N: Randy Dunlap
+E: randy.dunlap@intel.com
+W: http://home.att.net/~randy.dunlap/
+W: http://www.linux-usb.org
+D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
+S: 5200 NE Elam Young Pkwy., M/S HF3-77
+S: Hillsboro, Oregon 97124
+S: USA
+
N: Cyrus Durgin
E: cider@speakeasy.org
W: http://www.speakeasy.org/~cider/
N: Dave Jones
E: dave@powertweak.com
+E: djones2@glam.ac.uk
W: http://linux.powertweak.com
-D: Centaur/IDT Winchip/Winchip 2 tweaks
+D: Moved PCI bridge tuning to userspace (Powertweak).
+D: Centaur/IDT Winchip/Winchip 2 tweaks.
D: Misc clean ups and other random hacking.
-S: 40, Heol Edward Lewis,
-S: Gelligaer, Hengoed,
-S: Mid Glamorgan, CF82 8EJ,
+S: 28, Laura Street,
+S: Treforest, Pontypridd,
+S: Mid Glamorgan, CF37 1NW,
S: Wales, United Kingdom
N: Bernhard Kaindl
module, say M here and read Documentation/modules.txt as well as
Documentation/networking/net-modules.txt.
- Please email feedback to james.banks@caldera.com.
+ Please email feedback to torben.mathiasen@compaq.com.
VIA Rhine support
CONFIG_VIA_RHINE
multiple device environments, the PARIDE drivers will not do it
automatically. You can however, force a printer reset by doing:
- insmod lp
+ insmod lp reset=1
rmmod lp
If you have one of these marginal cases, you should probably build
card=21 - Lucky Star Image World ConferenceTV
card=22 - Phoebe Tv Master + FM
card=23 - Modular Technology MM205 PCTV, bt878
- card=24 - Magic TView CPH061 (bt878)
+ card=24 - Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)
card=25 - Terratec/Vobis TV-Boostar
card=26 - Newer Hauppauge WinCam (bt878)
card=27 - MAXI TV Video PCI2
card=30 - FlyVideo 98
card=31 - iProTV
card=32 - Intel Create and Share PCI
- card=33 - Askey/Typhoon/Anubis Magic TView
- card=34 - Terratec TerraTValue
+ card=33 - Terratec TerraTValue
tuner.o
type=0 - Temic PAL
MAKEDEV: a script to create the special files for v4l
CARDLIST: List of all supported cards
-Loading just the bttv modules isn't enough for most cards. The
+Loading just the bttv modules isn't enouth for most cards. The
drivers for the i2c tuner/sound chips must also be loaded. bttv tries
to load them automagically by calling request_module() now, but this
obviously works only with kmod enabled.
endif
ifeq ($(CONFIG_PNP),y)
-DRIVERS := $(DRIVERS) drivers/pnp/pnp.a
+DRIVERS := $(DRIVERS) drivers/pnp/isa-pnp.o
endif
ifdef CONFIG_SGI
endif
ifeq ($(CONFIG_USB),y)
-DRIVERS := $(DRIVERS) drivers/usb/usb.a
+DRIVERS := $(DRIVERS) drivers/usb/usbdrv.o
endif
ifeq ($(CONFIG_I2O),y)
walnut_config: clean_config
ln -s configs/walnut_defconfig arch/ppc/defconfig
-tags:
- etags */*.c include/{asm,linux}/*.h arch/ppc/kernel/*.{c,h}
-
archclean:
rm -f arch/ppc/kernel/{mk_defs,ppc_defs.h,find_name,checks}
@$(MAKECOFFBOOT) clean
#include "zlib.h"
#include <asm/bootinfo.h>
#include <asm/processor.h>
-#define __KERNEL__
#include <asm/page.h>
extern void *finddevice(const char *);
#include "zlib.h"
#include <asm/bootinfo.h>
#include <asm/processor.h>
-#define __KERNEL__
#include <asm/page.h>
extern void *finddevice(const char *);
0,
0
};
+int open_pic_irq_offset;
/*
* Accesses to the current processor's registers
* -- Cort
*/
#define check_arg_irq(irq) \
- /*if (irq < 0 || irq >= (NumSources+open_pic.irq_offset)) \
+ /*if (irq < 0 || irq >= (NumSources+open_pic_irq_offset)) \
printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);*/
#define check_arg_cpu(cpu) \
if (cpu < 0 || cpu >= NumProcessors) \
/* Initialize external interrupts */
if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc);
/* SIOint (8259 cascade) is special */
- openpic_initirq(0, 8, open_pic.irq_offset, 1, 1);
+ openpic_initirq(0, 8, open_pic_irq_offset, 1, 1);
openpic_mapirq(0, 1<<0);
for (i = 1; i < NumSources; i++) {
/* Enabled, Priority 8 */
- openpic_initirq(i, 8, open_pic.irq_offset+i, 0,
+ openpic_initirq(i, 8, open_pic_irq_offset+i, 0,
i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
/* Processor 0 */
openpic_mapirq(i, 1<<0);
void openpic_enable_irq(u_int irq)
{
check_arg_irq(irq);
- openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK);
+ openpic_clearfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
}
void openpic_disable_irq(u_int irq)
{
check_arg_irq(irq);
- openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK);
+ openpic_setfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
}
/*
#include <linux/string.h>
#include <linux/init.h>
#include <linux/openpic.h>
+#include <linux/errno.h>
#include <asm/processor.h>
#include <asm/io.h>
#include "pci.h"
-static void __init pcibios_claim_resources(struct pci_bus *);
+static void __init pcibios_claim_resources(struct list_head *);
unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
void __init pcibios_init(void)
{
printk("PCI: Probing PCI hardware\n");
- ioport_resource.end = ~0L;
pci_scan_bus(0, &generic_pci_ops, NULL);
- pcibios_claim_resources(pci_root);
- if ( ppc_md.pcibios_fixup )
+ pcibios_claim_resources(&pci_root_buses);
+ if (ppc_md.pcibios_fixup)
ppc_md.pcibios_fixup();
}
pcibios_align_resource(void *data, struct resource *res, unsigned long size)
{
}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for (idx=0; idx<6; idx++) {
+ r = &dev->resource[idx];
+ if (!r->start && r->end) {
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n",
+ dev->slot_name, old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+/*
+ * Assign new address to PCI resource. We hope our resource information
+ * is complete. We don't re-assign resources unless we are
+ * forced to do so.
+ *
+ * Expects start=0, end=size-1, flags=resource type.
+ */
+
+int pci_assign_resource(struct pci_dev *dev, int i)
+{
+ struct resource *r = &dev->resource[i];
+ struct resource *pr = pci_find_parent_resource(dev, r);
+ unsigned long size = r->end + 1;
+ u32 new, check;
+
+ if (!pr) {
+ printk(KERN_ERR "PCI: Cannot find parent resource for device %s\n", dev->slot_name);
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO) {
+ if (allocate_resource(pr, r, size, 0x100, ~0, size, NULL, NULL)) {
+ printk(KERN_ERR "PCI: Allocation of I/O region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size);
+ return -EBUSY;
+ }
+ } else {
+ if (allocate_resource(pr, r, size, 0x10000, ~0, size, NULL, NULL)) {
+ printk(KERN_ERR "PCI: Allocation of memory region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size);
+ return -EBUSY;
+ }
+ }
+ if (i < 6) {
+ int reg = PCI_BASE_ADDRESS_0 + 4*i;
+ new = r->start | (r->flags & PCI_REGION_FLAG_MASK);
+ pci_write_config_dword(dev, reg, new);
+ pci_read_config_dword(dev, reg, &check);
+ if (new != check)
+ printk(KERN_ERR "PCI: Error while updating region %s/%d (%08x != %08x)\n", dev->slot_name, i, new, check);
+ } else if (i == PCI_ROM_RESOURCE) {
+ r->flags |= PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(dev, dev->rom_base_reg, r->start | (r->flags & PCI_REGION_FLAG_MASK));
+ }
+ printk("PCI: Assigned addresses %08lx-%08lx to region %s/%d\n", r->start, r->end, dev->slot_name, i);
+ return 0;
+}
#include <asm/io.h>
#include <asm/system.h>
#include <asm/prom.h>
+#include <asm/machdep.h>
#include <linux/adb.h>
#include <linux/pmu.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/pgtable.h>
+#include <asm/machdep.h>
#include "time.h"
continue;
val->sharedram += atomic_read(&mem_map[i].count) - 1;
}
- val->totalram <<= PAGE_SHIFT;
- val->sharedram <<= PAGE_SHIFT;
- return;
+ val->mem_unit = PAGE_SIZE;
}
void *
*/
void __init paging_init(void)
{
+ unsigned int zones_size[MAX_NR_ZONES], i;
+
/*
* Grab some memory for bad_page and bad_pagetable to use.
*/
empty_bad_page = alloc_bootmem_pages(PAGE_SIZE);
empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE);
- {
- unsigned int zones_size[MAX_NR_ZONES], i;
- /*
- * All pages are DMA-able so this is wrong - the zone code is
- * assuming both regions have a value so this is necessary for
- * now.
- * -- Cort
- */
-#if 1
- for ( i = 1; i < MAX_NR_ZONES; i++ )
- zones_size[i] = 1<<MAX_ORDER;
- zones_size[0] = (virt_to_phys(end_of_DRAM) >> PAGE_SHIFT) -
- ((MAX_NR_ZONES-1)*(1<<MAX_ORDER));
-#else
- zones_size[0] = virt_to_phys(end_of_DRAM) >> PAGE_SHIFT;
-#endif
- free_area_init(zones_size);
- }
+
+ /*
+ * All pages are DMA-able so we put them all in the DMA zone.
+ */
+ zones_size[0] = virt_to_phys(end_of_DRAM) >> PAGE_SHIFT;
+ for (i = 1; i < MAX_NR_ZONES; i++)
+ zones_size[i] = 0;
+ free_area_init(zones_size);
}
void __init mem_init(void)
/* select primary or secondary channel */
if (hwif->index > 0) { /* drive is on the secondary channel */
- dev = pci_find_slot(dev, dev->devfn+1);
+ dev = pci_find_slot(dev->bus->number, dev->devfn+1);
if (!dev) {
- printk(KERN_ERR "%s: tune_drive: Cannot find secondary interface!\n");
+ printk(KERN_ERR "%s: tune_drive: Cannot find secondary interface!\n", drive->name);
return;
}
}
bttv_bit_setscl(btv,1);
bttv_bit_setsda(btv,1);
-
+
return i2c_bit_add_bus(&btv->i2c_adap);
}
}
/* read EEPROM */
-static void readee(struct bttv *btv, unsigned char *eedata)
+static void readee(struct bttv *btv, unsigned char *eedata, int addr)
{
int i;
- if (I2CWrite(btv, 0xa0, 0, -1, 0)<0) {
+ if (I2CWrite(btv, addr, 0, -1, 0)<0) {
printk(KERN_WARNING "bttv: readee error\n");
return;
}
- btv->i2c_client.addr = 0xa0 >> 1;
+ btv->i2c_client.addr = addr >> 1;
for (i=0; i<256; i+=16) {
if (16 != i2c_master_recv(&btv->i2c_client,eedata+i,16)) {
printk(KERN_WARNING "bttv: readee error\n");
static void
hauppauge_eeprom(struct bttv *btv)
{
- readee(btv, eeprom_data);
+ readee(btv, eeprom_data, 0xa0);
if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER))
{
btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id;
* driver, but using BTTV functions */
static void init_PXC200(struct bttv *btv)
{
- int tmp;
+ static const int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x00 };
+ int i,tmp;
/* Initialise GPIO-connevted stuff */
btwrite(1<<13,BT848_GPIO_OUT_EN); /* Reset pin only */
* argument so the numbers are different */
printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
-
- tmp=I2CWrite(btv,0x1E,0x08,0,1);
- printk(KERN_INFO "I2C Write(0x08) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x09,0,1);
- printk(KERN_INFO "I2C Write(0x09) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x0a,0,1);
- printk(KERN_INFO "I2C Write(0x0a) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x0b,0,1);
- printk(KERN_INFO "I2C Write(0x0b) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x0c,0,1);
- printk(KERN_INFO "I2C Write(0x0c) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x0d,0,1);
- printk(KERN_INFO "I2C Write(0x0d) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x01,0,1);
- printk(KERN_INFO "I2C Write(0x01) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x02,0,1);
- printk(KERN_INFO "I2C Write(0x02) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x03,0,1);
- printk(KERN_INFO "I2C Write(0x03) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x04,0,1);
- printk(KERN_INFO "I2C Write(0x04) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x05,0,1);
- printk(KERN_INFO "I2C Write(0x05) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x06,0,1);
- printk(KERN_INFO "I2C Write(0x06) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
- tmp=I2CWrite(btv,0x1E,0x00,0,1);
- printk(KERN_INFO "I2C Write(0x00) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL));
-
+
+ for (i = 0; i < sizeof(vals)/sizeof(int); i++) {
+ tmp=I2CWrite(btv,0x1E,vals[i],0,1);
+ printk(KERN_INFO "I2C Write(0x08) = %i\nI2C Read () = %x\n\n",
+ tmp,I2CRead(btv,0x1F,NULL));
+ }
printk(KERN_INFO "PXC200 Initialised.\n");
}
/* ----------------------------------------------------------------------- */
+static struct VENDOR {
+ int id;
+ char *name;
+} vendors[] = {
+ { 0x0070, "Hauppauge" },
+ { 0x144f, "Askey" },
+ { -1, NULL }
+};
+
+static struct CARD {
+ int id;
+ int vid;
+ int cardnr;
+ char *name;
+} cards[] = {
+ { 0x13eb, 0x0070, BTTV_HAUPPAUGE878, "WinTV Theater" },
+ { 0x3002, 0x144f, BTTV_MAGICTVIEW061, "Magic TView" },
+ { -1, -1, -1, NULL }
+};
+
struct tvcard
{
char *name;
1,1,1,1,0 },
/* 0x18 */
- { "Magic TView CPH061 (bt878)",
- 3, 1, 0, 2, 0xe00, { 2, 0, 1, 1}, {0x400, 0, 0, 0, 0},0,
+ { "Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)",
+ 3, 1, 0, 2, 0xe00, { 2, 3, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0,
1,1,1,1,0 },
{ "Terratec/Vobis TV-Boostar",
3, 1, 0, 2, 16777215 , { 2, 3, 1, 1}, { 131072, 1, 1638400, 3,4},0,
{ "Intel Create and Share PCI",
4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 4, 4, 4, 4},0,
1,1,1,1,0 },
- { "Askey/Typhoon/Anubis Magic TView",
- 3, 1, 0, 2, 0xe00, { 2, 0, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0,
- 1,1,1,1,0 },
{ "Terratec TerraTValue",
- 3, 1, 0, 2, 0x70000, { 2, 3, 1, 1}, { 0x500, 0, 0x300, 0x900, 0x900},0,
+ 3, 1, 0, 2, 0xf00, { 2, 3, 1, 1}, { 0x500, 0, 0x300, 0x900, 0x900},0,
1,1,1,1,0 },
};
#define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard))
+static void
+dump_eeprom(struct bttv *btv, int addr)
+{
+ int i,id1,id2,n1,n2;
+
+ printk(KERN_DEBUG "bttv%d: dump eeprom @ 0x%02x\n",btv->nr,addr);
+ readee(btv, eeprom_data,addr);
+ for (i = 0; i < 256;) {
+ printk(KERN_DEBUG " %02x:",i);
+ do {
+ printk(" %02x",eeprom_data[i++]);
+ } while (i % 16);
+ printk("\n");
+ }
+ id1 = (eeprom_data[252] << 8) | (eeprom_data[253]);
+ id2 = (eeprom_data[254] << 8) | (eeprom_data[255]);
+ if (id1 != 0 && id1 != 0xffff &&
+ id2 != 0 && id2 != 0xffff) {
+ n1 = -1;
+ n2 = -1;
+ for (i = 0; vendors[i].id != -1; i++)
+ if (vendors[i].id == id2)
+ n2 = i;
+ for (i = 0; cards[i].id != -1; i++)
+ if (cards[i].id == id1 &&
+ cards[i].vid == id2)
+ n1 = i;
+ if (n1 != -1 && n2 != -1) {
+ printk(KERN_INFO " id: %s (0x%04x), vendor: %s (0x%04x)\n",
+ cards[n1].name,id1,vendors[n2].name,id2);
+ printk(KERN_INFO " => card=%d (%s)\n",
+ cards[n1].cardnr,tvcards[cards[n1].cardnr].name);
+#if 1
+ /* not yet, but that's the plan for autodetect... */
+ btv->type = cards[n1].cardnr;
+#endif
+ } else {
+ printk(KERN_INFO " id: %s (0x%04x), vendor: %s (0x%04x)\n",
+ (n1 != -1) ? cards[n1].name : "unknown", id1,
+ (n2 != -1) ? vendors[n2].name : "unknown", id2);
+ printk(KERN_INFO " please mail card type, id + vendor to ");
+ printk(" kraxel@goldbach.in-berlin.de\n");
+ }
+ }
+}
+
/* ----------------------------------------------------------------------- */
static void audio(struct bttv *btv, int mode, int no_irq_context)
}
}
+#if 1
+ /* DEBUG: dump eeprom content if available */
+ if (I2CRead(btv, 0xa0, "eeprom")>=0) {
+ dump_eeprom(btv,0xa0);
+ }
+#endif
+
/* print which board we have found */
printk(KERN_INFO "bttv%d: model: ",btv->nr);
if (btv->type == BTTV_HAUPPAUGE878 ||
btv->type == BTTV_CONFERENCETV ||
btv->type == BTTV_PIXVIEWPLAYTV ||
- btv->type == BTTV_AVERMEDIA98) {
+ btv->type == BTTV_AVERMEDIA98 ||
+ btv->type == BTTV_MAGICTVIEW061) {
btv->pll.pll_ifreq=28636363;
btv->pll.pll_crystal=BT848_IFORM_XT0;
}
request_module("tda9855");
}
- if (tvcards[btv->type].tea63xx &&
- I2CRead(btv, I2C_TEA6300, "TEA63xx") >= 0) {
+ if (tvcards[btv->type].tea63xx /* &&
+ I2CRead(btv, I2C_TEA6300, "TEA63xx") >= 0 */) {
if (autoload)
request_module("tea6300");
}
#endif
{
int i;
-
+
+ printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
+ (BTTV_VERSION_CODE >> 16) & 0xff,
+ (BTTV_VERSION_CODE >> 8) & 0xff,
+ BTTV_VERSION_CODE & 0xff);
handle_chipset();
if (find_bt848()<=0)
return -EIO;
#ifndef _BTTV_H_
#define _BTTV_H_
-#define BTTV_VERSION_CODE 0x00070b
+#define BTTV_VERSION_CODE 0x00070d
#include <linux/types.h>
#include <linux/wait.h>
#define BTTV_TERRATV 0x1c
#define BTTV_PXC200 0x1d
-#if 0
-#define BTTV_UNKNOWN 0x00
-#define BTTV_MIRO 0x01
-#define BTTV_HAUPPAUGE 0x02
-#define BTTV_STB 0x03
-#define BTTV_INTEL 0x04
-#define BTTV_DIAMOND 0x05
-#define BTTV_AVERMEDIA 0x06
-#define BTTV_MATRIX_VISION 0x07
-#define BTTV_FLYVIDEO 0x08
-#define BTTV_TURBOTV 0x09
-#define BTTV_HAUPPAUGE878 0x0a
-#define BTTV_MIROPRO 0x0b
-#define BTTV_TVBOOSTAR 0x0c
-#define BTTV_WINCAM 0x0d
-#define BTTV_MAXI 0x0e
-#define BTTV_VHX 0x10
-#define BTTV_PXC200 0x11
-#define BTTV_AVERMEDIA98 0x12
-#define BTTV_FLYVIDEO98 0x13
-
-#define BTTV_PIXVIEWPLAYTV 0x17
-#define BTTV_WINVIEW_601 0x18
-#define BTTV_CONFERENCETV 0x1c
-#endif
-
#define AUDIO_TUNER 0x00
#define AUDIO_RADIO 0x01
* what works and what doesn't:
*
* AM-Mono
- * probably doesn't (untested)
+ * Support for Hauppauge cards added (decoding handled by tuner) added by
+ * Frederic Crozat <fcrozat@mail.dotcom.fr>
*
* FM-Mono
* should work. The stereo modes are backward compatible to FM-mono,
* should work, no autodetect (i.e. default is mono, but you can
* switch to stereo -- untested)
*
- * NICAM (B/G, used in UK, Scandinavia and Spain)
+ * NICAM (B/G, L , used in UK, Scandinavia, Spain and France)
* should work, with autodetect. Support for NICAM was added by
* Pekka Pietikainen <pp@netppl.fi>
*
#include <asm/pgtable.h>
#include <linux/smp_lock.h>
#endif
-
/* kernel_thread */
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include "audiochip.h"
-
-#define WAIT_QUEUE wait_queue_head_t
+#define WAIT_QUEUE wait_queue_head_t
/* sound mixer stuff */
#include <linux/config.h>
/* NICAM/AM -- L (6.5/5.85) */
{ { -2, -8, -10, 10, 50, 86 }, { -4, -12, -9, 23, 79, 126 },
MSP_CARRIER(6.5), MSP_CARRIER(6.5),
- 0x00c6, 0x0140, 0x0120, 0x7000},
+ 0x00c6, 0x0140, 0x0120, 0x7c03},
};
struct CARRIER_DETECT {
static struct CARRIER_DETECT carrier_detect_65[] = {
/* PAL SAT / SECAM */
- { MSP_CARRIER(5.85), "5.85 PAL D/K NICAM" },
+ { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" },
{ MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" },
{ MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" },
{ MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
if (msp->nicam) {
/* nicam prescale */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0010, 0x3000);
+ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0010, 0x5a00); /* was: 0x3000 */
}
}
case VIDEO_SOUND_STEREO:
src = 0x0020 | nicam;
#if 0
+ /* spatial effect */
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0005,0x4000);
#endif
break;
case VIDEO_SOUND_MONO:
+ if (msp->mode == MSP_MODE_AM_NICAM) {
+ printk("msp3400: switching to AM mono\n");
+ /* AM mono decoding is handled by tuner, not MSP chip */
+ /* so let's redirect sound from tuner via SCART */
+ /* volume prescale for SCART */
+ msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900);
+ /* SCART switching control register*/
+ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, 0xe900);
+ src = 0x0200;
+ break;
+ }
case VIDEO_SOUND_LANG1:
src = 0x0000 | nicam;
break;
val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x18);
if (val > 32768)
val -= 65536;
- dprintk("msp3400: stereo detect register: %d\n",val);
+ dprintk("msp34xx: stereo detect register: %d\n",val);
if (val > 4096) {
newstereo = VIDEO_SOUND_STEREO | VIDEO_SOUND_MONO;
case MSP_MODE_FM_NICAM2:
case MSP_MODE_AM_NICAM:
val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x23);
- dprintk("msp3400: nicam sync=%d, mode=%d\n",val & 1, (val & 0x1e) >> 1);
+ dprintk("msp34xx: nicam sync=%d, mode=%d\n",val & 1, (val & 0x1e) >> 1);
if (val & 1) {
/* nicam synced */
}
newnicam=1;
} else {
- newnicam=0;
-#if 0 /* fixme: quick & dirty for testing */
- if (msp->main == MSP_CARRIER(6.5)) {
- /* This is a french mono channel => AM */
- printk("msp3400: switching to AM mono\n");
- msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
- msp->second = msp->main;
- msp3400c_setmode(msp, MSP_MODE_AM_DETECT);
- msp3400c_setcarrier(client, msp->second, msp->main);
- }
-#endif
+ newnicam = 0;
newstereo = VIDEO_SOUND_MONO;
}
break;
+ case MSP_MODE_BTSC:
+ val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200);
+ dprintk("msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n",
+ val,
+ (val & 0x0002) ? "no" : "yes",
+ (val & 0x0004) ? "no" : "yes",
+ (val & 0x0040) ? "stereo" : "mono",
+ (val & 0x0080) ? ", nicam 2nd mono" : "",
+ (val & 0x0100) ? ", bilingual/SAP" : "");
+ newstereo = VIDEO_SOUND_MONO;
+ if (val & 0x0040) newstereo |= VIDEO_SOUND_STEREO;
+ if (val & 0x0100) newstereo |= VIDEO_SOUND_LANG1;
+ break;
}
if (newstereo != msp->stereo) {
update = 1;
- dprintk("msp3400: watch: stereo %d => %d\n",
+ dprintk("msp34xx: watch: stereo %d => %d\n",
msp->stereo,newstereo);
msp->stereo = newstereo;
}
if (newnicam != msp->nicam_on) {
update = 1;
- dprintk("msp3400: watch: nicam %d => %d\n",
+ dprintk("msp34xx: watch: nicam %d => %d\n",
msp->nicam_on,newnicam);
msp->nicam_on = newnicam;
}
msp->active = 0;
continue;
}
-
+
+ /* some time for the tuner to sync */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/10);
+ if (signal_pending(current))
+ goto done;
+
restart:
+ msp->restart = 0;
msp3400c_setvolume(client, 0, 0);
msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
val1 = val2 = 0;
/* carrier detect pass #1 -- main carrier */
cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main);
+
+ if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
+ /* autodetect doesn't work well with AM ... */
+ max1 = 3;
+ count = 0;
+ dprintk("msp3400: AM sound override\n");
+ }
+
for (this = 0; this < count; this++) {
msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
schedule_timeout(HZ/25);
if (signal_pending(current))
goto done;
- if (msp->restart) {
+ if (msp->restart)
msp->restart = 0;
- goto restart;
- }
val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
if (val1 < val)
val1 = val, max1 = this;
dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name);
}
-
- if (amsound) {
- /* autodetect does'nt work well with AM ... */
- max1 = 3;
- dprintk("msp3400: AM sound override\n");
- }
-
+
/* carrier detect pass #2 -- second (stereo) carrier */
switch (max1) {
case 1: /* 5.5 */
cd = NULL; count = 0;
break;
}
+
+ if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
+ /* autodetect doesn't work well with AM ... */
+ cd = NULL; count = 0; max2 = 0;
+ }
for (this = 0; this < count; this++) {
msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
schedule_timeout(HZ/25);
if (signal_pending(current))
goto done;
- if (msp->restart) {
- msp->restart = 0;
+ if (msp->restart)
goto restart;
- }
val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
if (val2 < val)
msp->nicam_on = 0;
msp3400c_setstereo(client, VIDEO_SOUND_MONO);
msp->watch_stereo = 1;
- } else if (max2 == 0 && msp->nicam &&
+ } else if (max2 == 0 &&
msp->norm == VIDEO_MODE_SECAM) {
- /* L NICAM */
+ /* L NICAM or AM-mono */
msp->second = carrier_detect_65[max2].cdo;
msp3400c_setmode(client, MSP_MODE_AM_NICAM);
- msp->nicam_on = 1;
+ msp->nicam_on = 0;
+ msp3400c_setstereo(client, VIDEO_SOUND_MONO);
msp3400c_setcarrier(client, msp->second, msp->main);
msp->watch_stereo = 1;
} else if (max2 == 0 && msp->nicam) {
msp->active = 1;
if (msp->watch_stereo) {
-#if 1 /* dump status register */
- val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200);
- printk("msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n",
- val,
- (val & 0x0002) ? "no" : "yes",
- (val & 0x0004) ? "no" : "yes",
- (val & 0x0040) ? "stereo" : "mono",
- (val & 0x0080) ? ", nicam 2nd mono" : "",
- (val & 0x0100) ? ", bilingual/SAP" : "");
- msp->watch_stereo = 0;
-#else
- watch_stereo(msp);
-#endif
+ watch_stereo(client);
msp->active = 0;
continue;
}
+ /* some time for the tuner to sync */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/10);
+ if (signal_pending(current))
+ goto done;
+
restart:
+ msp->restart = 0;
del_timer(&msp->wake_stereo);
msp->watch_stereo = 0;
std = 0x0020;
break;
case VIDEO_MODE_SECAM:
+ mode = 0x0003;
+ std = 1;
+ break;
default:
mode = 0x0003;
std = 1;
schedule_timeout(HZ/10);
if (signal_pending(current))
goto done;
- if (msp->restart) {
- msp->restart = 0;
+ if (msp->restart)
goto restart;
- }
/* check results */
val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e);
msp->main = modelist[i].main;
msp->second = modelist[i].second;
+ if (amsound && (msp->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) {
+ /* autodetection has failed, let backup */
+ dprintk("msp3410: autodetection failed, switching to backup mode: %s (0x%04x)\n",
+ modelist[8].name ? modelist[8].name : "unknown",val);
+ val = 0x0009;
+ msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, val);
+ }
+
/* set prescale / stereo */
switch (val) {
- case 0x0009:
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x7c03); /* AM */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* NICAM */
+ case 0x0009:
+ msp->mode = MSP_MODE_AM_NICAM;
+ msp->stereo = VIDEO_SOUND_MONO;
+ msp3400c_setstereo(client,VIDEO_SOUND_MONO);
+ msp->watch_stereo = 1;
break;
case 0x0020: /* BTSC */
/* just turn on stereo */
va->bass = msp->bass;
va->treble = msp->treble;
- if (msp->simple) {
- /* fixme */
- } else {
- autodetect_stereo(client);
- va->mode = msp->stereo;
- }
+ autodetect_stereo(client);
+ va->mode = msp->stereo;
break;
}
case VIDIOCSAUDIO:
msp3400c_setbass(client,msp->bass);
msp3400c_settreble(client,msp->treble);
- if (msp->simple) {
- /* fixme */
- } else if (va->mode != 0) {
+ if (va->mode != 0) {
msp->watch_stereo=0;
del_timer(&msp->wake_stereo);
msp->stereo = va->mode;
msp3400c_settreble(client,msp->treble);
break;
- case AUDC_GET_STEREO:
- if (msp->simple) {
- *sarg = 0; /* fixme */
- } else {
- autodetect_stereo(client);
- *sarg = msp->stereo;
- }
+ case AUDC_GET_STEREO:
+ autodetect_stereo(client);
+ *sarg = msp->stereo;
break;
case AUDC_SET_STEREO:
- if (msp->simple)
- break; /* fixme */
if (*sarg) {
msp->watch_stereo=0;
del_timer(&msp->wake_stereo);
* c-basic-offset: 8
* End:
*/
-
saa_num = 0;
while ((dev = pci_find_device(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, dev))) {
- if (!dev->subsystem_vendor_id)
+ if (!dev->subsystem_vendor)
printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num);
else
printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num);
tda8425_write(client, TDA8425_TR, tda->treble>>12|0xF0);
}
-static void tda8425_init(struct i2c_client *client)
+static void do_tda8425_init(struct i2c_client *client)
{
struct tda8425 *tda = client->data;
if (!tda)
return -ENOMEM;
memset(tda,0,sizeof *tda);
- tda8425_init(client);
+ do_tda8425_init(client);
MOD_INC_USE_COUNT;
strcpy(client->name,"TDA8425");
printk(KERN_INFO "tda8425: init\n");
{
struct tda8425 *tda = client->data;
- tda8425_init(client);
+ do_tda8425_init(client);
i2c_detach_client(client);
kfree(tda);
return 0;
}
-static void tda9855_init(struct i2c_client *client)
+static void do_tda9855_init(struct i2c_client *client)
{
struct tda9855 *t = client->data;
if (!t)
return -ENOMEM;
memset(t,0,sizeof *t);
- tda9855_init(client);
+ do_tda9855_init(client);
MOD_INC_USE_COUNT;
strcpy(client->name,"TDA9855");
printk(KERN_INFO "tda9855: init\n");
{
struct tda9855 *t = client->data;
- tda9855_init(client);
+ do_tda9855_init(client);
i2c_detach_client(client);
kfree(t);
va->mode = ((TDA9855_STP | TDA9855_SAPP) &
tda9855_read(client)) >> 4;
- if (0 == va->mode)
- va->mode = VIDEO_SOUND_MONO;
+ va->mode |= VIDEO_SOUND_MONO;
break;
}
case VIDIOCSAUDIO:
case VIDEO_SOUND_STEREO:
t->c2= TDA9855_STEREO | (t->c2 & 0x3f);
break;
- case VIDEO_SOUND_LANG2:
+ case VIDEO_SOUND_LANG1:
t->c2= TDA9855_SAP | (t->c2 & 0x3f);
break;
}
#ifdef MODULE
void cleanup_module(void)
{
- i2c_add_driver(&driver);
+ i2c_del_driver(&driver);
}
#endif
tea6300_write(client, TEA6300_TR, tea->treble>>12);
}
-static void tea6300_init(struct i2c_client *client)
+static void do_tea6300_init(struct i2c_client *client)
{
struct tea6300 *tea = client->data;
if (!tea)
return -ENOMEM;
memset(tea,0,sizeof *tea);
- tea6300_init(client);
+ do_tea6300_init(client);
MOD_INC_USE_COUNT;
strcpy(client->name,"TEA6300T");
{
struct tea6300 *tea = client->data;
- tea6300_init(client);
+ do_tea6300_init(client);
i2c_detach_client(client);
kfree(tea);
"10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4",
};
-/* Set if the PCI BIOS detects the chips on a multiport board backwards. */
-#ifdef REVERSE_PROBE_ORDER
-static int reverse_probe = 1;
-#else
-static int reverse_probe = 0;
-#endif
-
/* Keep the ring sizes a power of two for efficiency.
Making the Tx ring too large decreases the effectiveness of channel
bonding and packet priority.
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
+#include <linux/init.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
long ioaddr, int irq, int chip_idx, int fnd_cnt);
};
-#ifndef CARDBUS
static struct pci_id_info pci_tbl[] = {
{ "Digital DC21040 Tulip",
0x1011, 0x0002, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
0x1317, 0x0981, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
{ "Compex RL100-TX",
0x11F6, 0x9881, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
+ { "Xircom Cardbus Adapter (DEC 21143 compatible mode)",
+ 0x115D, 0x0003, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
{0},
};
-#endif /* !CARD_BUS */
/* This table use during operation for capabilities and media timer. */
struct tulip_private {
char devname[8]; /* Used only for kernel debugging. */
const char *product_name;
- struct net_device *next_module;
struct tulip_rx_desc rx_ring[RX_RING_SIZE];
struct tulip_tx_desc tx_ring[TX_RING_SIZE];
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
restore_flags(flags);
}
\f
-/* A list of all installed Tulip devices. */
-static struct net_device *root_tulip_dev = NULL;
-
-#ifndef CARDBUS
-int tulip_probe(struct net_device *dev)
-{
- int cards_found = 0;
- int pci_index = 0;
- unsigned char pci_bus, pci_device_fn;
-
- if ( ! pcibios_present())
- return -ENODEV;
-
- for (;pci_index < 0xff; pci_index++) {
- u16 vendor, device, pci_command, new_command;
- int chip_idx;
- int irq;
- long ioaddr;
-
- if (pcibios_find_class
- (PCI_CLASS_NETWORK_ETHERNET << 8,
- reverse_probe ? 0xfe - pci_index : pci_index,
- &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) {
- if (reverse_probe)
- continue;
- else
- break;
- }
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
-
- for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
- if (vendor == pci_tbl[chip_idx].vendor_id
- && (device & pci_tbl[chip_idx].device_id_mask) ==
- pci_tbl[chip_idx].device_id)
- break;
- if (pci_tbl[chip_idx].vendor_id == 0)
- continue;
-
- {
-#if defined(PCI_SUPPORT_VER2)
- struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
- ioaddr = pdev->base_address[0] & ~3;
- irq = pdev->irq;
-#elif defined(PCI_SUPPORT_VER3)
- struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
- ioaddr = pdev->resource[0].start;
- irq = pdev->irq;
-#else
- u32 pci_ioaddr;
- u8 pci_irq_line;
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- ioaddr = pci_ioaddr & ~3;
- irq = pci_irq_line;
-#endif
- }
-
- if (debug > 2)
- printk(KERN_INFO "Found %s at PCI I/O address %#lx.\n",
- pci_tbl[chip_idx].name, ioaddr);
-
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
- new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
- if (pci_command != new_command) {
- printk(KERN_INFO " The PCI BIOS has not enabled the"
- " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n",
- pci_bus, pci_device_fn, pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
- }
-
- dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,
- irq, chip_idx, cards_found);
-
- /* Get and check the bus-master and latency values. */
- if (dev) {
- u8 pci_latency;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < 10) {
- printk(KERN_INFO " PCI latency timer (CFLT) is "
- "unreasonably low at %d. Setting to 64 clocks.\n",
- pci_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, 64);
- }
- }
- dev = 0;
- cards_found++;
- }
-
- return cards_found ? 0 : -ENODEV;
-}
-#endif /* not CARDBUS */
-
static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
struct net_device *dev, long ioaddr, int irq,
int chip_idx, int board_idx)
memset(tp, 0, sizeof(*tp));
dev->priv = tp;
- tp->next_module = root_tulip_dev;
- root_tulip_dev = dev;
-
tp->pci_bus = pci_bus;
tp->pci_devfn = pci_devfn;
tp->chip_id = chip_idx;
outl_CSR6(csr6 | 0x0000, ioaddr, tp->chip_id);
}
\f
-#ifdef CARDBUS
-
-#include <pcmcia/driver_ops.h>
-
-static dev_node_t *tulip_attach(dev_locator_t *loc)
+static int tulip_probe(struct pci_dev *pdev)
{
struct net_device *dev;
- u16 dev_id;
- u16 vendor_id;
- u32 io;
- u8 bus, devfn, irq;
-
- if (loc->bus != LOC_PCI) return NULL;
- bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
- printk(KERN_INFO "tulip_attach(bus %d, function %d)\n", bus, devfn);
- pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
- pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
- pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
- pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
- if (dev_id == 0x0003 && vendor_id == 0x115d)
- dev = tulip_probe1(bus, devfn, NULL, io & ~3, irq, X3201_3, 0);
- else
- dev = tulip_probe1(bus, devfn, NULL, io & ~3, irq, DC21142, 0);
+ int chip_idx;
+ static int board_idx = 0;
+
+ printk(KERN_INFO "tulip_attach(%s)\n", pdev->slot_name);
+
+ for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+ if (pdev->vendor == pci_tbl[chip_idx].vendor_id
+ && (pdev->device & pci_tbl[chip_idx].device_id_mask) ==
+ pci_tbl[chip_idx].device_id)
+ break;
+ if (pci_tbl[chip_idx].vendor_id == 0)
+ return 0;
+
+ pci_set_master(pdev);
+ dev = pci_tbl[chip_idx].probe1(pdev->bus->number, pdev->devfn, NULL,
+ pdev->resource[0].start, pdev->irq,
+ chip_idx, board_idx++);
if (dev) {
- dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
- strcpy(node->dev_name, dev->name);
- node->major = node->minor = 0;
- node->next = NULL;
+ pdev->driver_data = dev;
MOD_INC_USE_COUNT;
- return node;
+ return 1;
}
- return NULL;
+ return 0;
}
-static void tulip_suspend(dev_node_t *node)
+static void tulip_suspend(struct pci_dev *pdev)
{
- struct net_device *dev, *next;
- printk(KERN_INFO "tulip_suspend(%s)\n", node->dev_name);
- for (dev = root_tulip_dev; dev; dev = next) {
- next = ((struct tulip_private *)dev->priv)->next_module;
- if (strcmp(dev->name, node->dev_name) == 0) break;
- }
- if (dev) {
- struct tulip_private *tp = (struct tulip_private *)dev->priv;
- if (tp->open) tulip_down(dev);
- }
+ struct net_device *dev = pdev->driver_data;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ printk(KERN_INFO "tulip_suspend(%s)\n", dev->name);
+ if (tp->open) tulip_down(dev);
}
-static void tulip_resume(dev_node_t *node)
+static void tulip_resume(struct pci_dev *pdev)
{
- struct net_device *dev, *next;
- printk(KERN_INFO "tulip_resume(%s)\n", node->dev_name);
- for (dev = root_tulip_dev; dev; dev = next) {
- next = ((struct tulip_private *)dev->priv)->next_module;
- if (strcmp(dev->name, node->dev_name) == 0) break;
- }
- if (dev) {
- struct tulip_private *tp = (struct tulip_private *)dev->priv;
- if (tp->open) tulip_up(dev);
- }
+ struct net_device *dev = pdev->driver_data;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ printk(KERN_INFO "tulip_resume(%s)\n", dev->name);
+ if (tp->open) tulip_up(dev);
}
-static void tulip_detach(dev_node_t *node)
+static void tulip_remove(struct pci_dev *pdev)
{
- struct net_device **devp, **next;
- printk(KERN_INFO "tulip_detach(%s)\n", node->dev_name);
- for (devp = &root_tulip_dev; *devp; devp = next) {
- next = &((struct tulip_private *)(*devp)->priv)->next_module;
- if (strcmp((*devp)->name, node->dev_name) == 0) break;
- }
- if (*devp) {
- struct net_device *dev = *devp;
- struct tulip_private *tp = dev->priv;
- *devp = *next;
- unregister_netdev(dev);
- kfree(dev);
- kfree(tp);
- kfree(node);
- MOD_DEC_USE_COUNT;
- }
+ struct net_device *dev = pdev->driver_data;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+
+ printk(KERN_INFO "tulip_detach(%s)\n", dev->name);
+ unregister_netdev(dev);
+ kfree(dev);
+ kfree(tp);
}
-struct driver_operations tulip_ops = {
- "tulip_cb", tulip_attach, tulip_suspend, tulip_resume, tulip_detach
+struct pci_driver tulip_ops = {
+ name: "tulip_cb",
+ probe: tulip_probe,
+ remove: tulip_remove,
+ suspend: tulip_suspend,
+ resume: tulip_resume
};
-#endif /* Cardbus support */
-
-#ifdef MODULE
-int init_module(void)
+int __init tulip_init(void)
{
-#ifdef CARDBUS
- reverse_probe = 0; /* Not used. */
- register_driver(&tulip_ops);
+ pci_register_driver(&tulip_ops);
return 0;
-#else
- return tulip_probe(NULL);
-#endif
}
-void cleanup_module(void)
+void __exit tulip_cleanup(void)
{
- struct net_device *next_dev;
-
-#ifdef CARDBUS
- unregister_driver(&tulip_ops);
-#endif
-
- /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
- while (root_tulip_dev) {
- struct tulip_private *tp = (struct tulip_private *)root_tulip_dev->priv;
- next_dev = tp->next_module;
- unregister_netdev(root_tulip_dev);
- release_region(root_tulip_dev->base_addr,
- tulip_tbl[tp->chip_id].io_size);
- kfree(root_tulip_dev);
- root_tulip_dev = next_dev;
- }
+ pci_unregister_driver(&tulip_ops);
}
-#endif /* MODULE */
+module_init(tulip_init);
+module_exit(tulip_cleanup);
\f
/*
* Local variables:
-/********************************************************************
+/*******************************************************************************
*
* Linux ThunderLAN Driver
*
*
* (C) 1997-1998 Caldera, Inc.
* (C) 1998 James Banks
+ * (C) 1999, 2000 Torben Mathiasen
*
* This software may be used and distributed according to the terms
* of the GNU Public License, incorporated herein by reference.
*
* Torben Mathiasen <torben.mathiasen@compaq.com> New Maintainer!
*
- * v1.1 Dec 20 -- Removed linux version checking(patch from
- * Tigran Aivazian). v1.1 includes Alan's SMP
- * opdates. We still have problems on SMP though,
- * but I'm looking into that.
+ * v1.1 Dec 20, 1999 - Removed linux version checking
+ * Patch from Tigran Aivazian.
+ * - v1.1 includes Alan's SMP updates.
+ * - We still have problems on SMP though,
+ * but I'm looking into that.
+ *
+ * v1.2 Jan 02, 2000 - Hopefully fixed the SMP deadlock.
+ * - Removed dependency of HZ being 100.
+ * - We now allow higher priority timers to
+ * overwrite timers like TLAN_TIMER_ACTIVITY
+ * Patch from John Cagle <john.cagle@compaq.com>.
+ * - Fixed a few compiler warnings.
+ *
*
- ********************************************************************/
+ *******************************************************************************/
#include <linux/module.h>
static u8 *TLanPadBuffer;
static char TLanSignature[] = "TLAN";
static int TLanVersionMajor = 1;
-static int TLanVersionMinor = 1;
+static int TLanVersionMinor = 2;
static TLanAdapterEntry TLanAdapterList[] = {
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
- if ( priv->timer.function != NULL ) {
+ if ( priv->timer.function != NULL &&
+ priv->timerType != TLAN_TIMER_ACTIVITY) {
spin_unlock_irqrestore(&priv->lock, flags);
return;
}
if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
if ( priv->timer.function == NULL ) {
- TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY );
+ priv->timer.function = &TLan_Timer;
+ priv->timer.data = (unsigned long) dev;
+ priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
+ priv->timerSetAt = jiffies;
+ priv->timerType = TLAN_TIMER_ACTIVITY;
+ add_timer(&priv->timer);
} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
priv->timerSetAt = jiffies;
}
if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
if ( priv->timer.function == NULL ) {
- TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY );
+ priv->timer.function = &TLan_Timer;
+ priv->timer.data = (unsigned long) dev;
+ priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
+ priv->timerSetAt = jiffies;
+ priv->timerType = TLAN_TIMER_ACTIVITY;
+ add_timer(&priv->timer);
} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
priv->timerSetAt = jiffies;
}
* for a short period to power up the LED so it
* can be seen. This delay can be changed by
* changing the TLAN_TIMER_ACT_DELAY in tlan.h,
- * if desired. 10 jiffies produces a slightly
+ * if desired. 100 ms produces a slightly
* sluggish response.
*
**************************************************************/
struct net_device *dev = (struct net_device *) data;
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
u32 elapsed;
- unsigned long flags;
+ unsigned long flags = 0;
priv->timer.function = NULL;
TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value );
}
- /* Wait for 5 jiffies (50 ms) and powerup
+ /* Wait for 50 ms and powerup
* This is abitrary. It is intended to make sure the
* tranceiver settles.
*/
- TLan_SetTimer( dev, 5, TLAN_TIMER_PHY_PUP );
+ TLan_SetTimer( dev, (50/(1000/HZ)), TLAN_TIMER_PHY_PUP );
} /* TLan_PhyPowerDown */
value = MII_GC_LOOPBK;
TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
- /* Wait for 50 jiffies (500 ms) and reset the
+ /* Wait for 500 ms and reset the
* tranceiver. The TLAN docs say both 50 ms and
* 500 ms, so do the longer, just in case
*/
- TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_RESET );
+ TLan_SetTimer( dev, (HZ/2), TLAN_TIMER_PHY_RESET );
} /* TLan_PhyPowerUp */
}
TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0 );
- /* Wait for 50 jiffies (500 ms) and initialize.
+ /* Wait for 500 ms and initialize.
* I don't remember why I wait this long.
*/
- TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_START_LINK );
+ TLan_SetTimer( dev, (HZ/2), TLAN_TIMER_PHY_START_LINK );
} /* TLan_PhyReset */
TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 );
TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 );
- /* Wait for 400 jiffies (4 sec) for autonegotiation
+ /* Wait for 4 sec for autonegotiation
* to complete. The max spec time is less than this
* but the card need additional time to start AN.
* .5 sec should be plenty extra.
*/
printk( "TLAN: %s: Starting autonegotiation.\n", dev->name );
- TLan_SetTimer( dev, 400, TLAN_TIMER_PHY_FINISH_AN );
+ TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_PHY_FINISH_AN );
return;
}
TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl );
}
- /* Wait for 100 jiffies (1 sec) to give the tranceiver time
+ /* Wait for 1 sec to give the tranceiver time
* to establish link.
*/
- TLan_SetTimer( dev, 100, TLAN_TIMER_FINISH_RESET );
+ TLan_SetTimer( dev, HZ, TLAN_TIMER_FINISH_RESET );
} /* TLan_PhyStartLink */
TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
if ( ! ( status & MII_GS_AUTOCMPLT ) ) {
- /* Wait for 800 jiffies (8 sec) to give the process
+ /* Wait for 8 sec to give the process
* more time. Perhaps we should fail after a while.
*/
printk( "TLAN: Giving autonegotiation more time.\n" );
- TLan_SetTimer( dev, 800, TLAN_TIMER_PHY_FINISH_AN );
+ TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN );
return;
}
}
}
- /* Wait for 10 jiffies (100 ms). No reason in partiticular.
+ /* Wait for 100 ms. No reason in partiticular.
*/
- TLan_SetTimer( dev, 10, TLAN_TIMER_FINISH_RESET );
+ TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET );
} /* TLan_PhyFinishAutoNeg */
int err;
int minten;
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
- unsigned long flags;
+ unsigned long flags = 0;
err = FALSE;
outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
{
u16 sio;
int minten;
- unsigned long flags;
+ unsigned long flags = 0;
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
{
int err;
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
- unsigned long flags;
+ unsigned long flags = 0;
int ret=0;
if ( dev->interrupt == 0 )
* by James Banks
*
* (C) 1997-1998 Caldera, Inc.
- *
+ * (C) 1999-2000 Torben Mathiasen
+ *
* This software may be used and distributed according to the terms
* of the GNU Public License, incorporated herein by reference.
*
#define TLAN_TIMER_PHY_FINISH_AN 7
#define TLAN_TIMER_FINISH_RESET 8
-#define TLAN_TIMER_ACT_DELAY 10
+#define TLAN_TIMER_ACT_DELAY (HZ/10)
* 2 of the License, or (at your option) any later version.
*
* (c) Copyright 1998 Building Number Three Ltd
+ * (c) Copyright 2000 Red Hat Software
*
* Development of this driver was funded by Equiinet Ltd
* http://www.equiinet.com
*
* ChangeLog:
*
- * Asynchronous mode dropped for 2.2. For 2.3 we will attempt the
+ * Asynchronous mode dropped for 2.2. For 2.5 we will attempt the
* unification of all the Z85x30 asynchronous drivers for real.
*
- * To Do:
- *
- * Finish DMA mode support.
+ * DMA now uses get_free_page as kmalloc buffers may span a 64K
+ * boundary.
*
* Performance
*
c->txdma_on = 0;
/*
- * Allocate the DMA flip buffers
+ * Allocate the DMA flip buffers. Limit by page size.
+ * Everyone runs 1500 mtu or less on wan links so this
+ * should be fine.
*/
- c->rx_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
+ if(c->mtu > PAGE_SIZE/2)
+ return -EMSGSIZE;
+
+ c->rx_buf[0]=get_free_page(GFP_KERNEL|GFP_DMA);
if(c->rx_buf[0]==NULL)
return -ENOBUFS;
- c->rx_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
- if(c->rx_buf[1]==NULL)
- {
- kfree(c->rx_buf[0]);
- c->rx_buf[0]=NULL;
- return -ENOBUFS;
- }
+ c->rx_buf[1]=c->rx_buf[0]+PAGE_SIZE/2;
- c->tx_dma_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
+ c->tx_dma_buf[0]=get_free_page(GFP_KERNEL|GFP_DMA);
if(c->tx_dma_buf[0]==NULL)
{
- kfree(c->rx_buf[0]);
- kfree(c->rx_buf[1]);
- c->rx_buf[0]=NULL;
- return -ENOBUFS;
- }
- c->tx_dma_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
- if(c->tx_dma_buf[1]==NULL)
- {
- kfree(c->tx_dma_buf[0]);
- kfree(c->rx_buf[0]);
- kfree(c->rx_buf[1]);
+ free_page(c->rx_buf[0]);
c->rx_buf[0]=NULL;
- c->rx_buf[1]=NULL;
- c->tx_dma_buf[0]=NULL;
return -ENOBUFS;
}
+ c->tx_dma_buf[1]=c->tx_dma_buf[0]+PAGE_SIZE/2;
+
c->tx_dma_used=0;
c->dma_tx = 1;
c->dma_num=0;
if(c->rx_buf[0])
{
- kfree(c->rx_buf[0]);
+ free_page(c->rx_buf[0]);
c->rx_buf[0]=NULL;
}
- if(c->rx_buf[1])
- {
- kfree(c->rx_buf[1]);
- c->rx_buf[1]=NULL;
- }
if(c->tx_dma_buf[0])
{
- kfree(c->tx_dma_buf[0]);
+ free_page(c->tx_dma_buf[0]);
c->tx_dma_buf[0]=NULL;
}
- if(c->tx_dma_buf[1])
- {
- kfree(c->tx_dma_buf[1]);
- c->tx_dma_buf[1]=NULL;
- }
chk=read_zsreg(c,R0);
write_zsreg(c, R3, c->regs[R3]);
z8530_rtsdtr(c,0);
c->rxdma_on = 0;
c->txdma_on = 0;
- c->tx_dma_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
+ /*
+ * Allocate the DMA flip buffers. Limit by page size.
+ * Everyone runs 1500 mtu or less on wan links so this
+ * should be fine.
+ */
+
+ if(c->mtu > PAGE_SIZE/2)
+ return -EMSGSIZE;
+
+ c->tx_dma_buf[0]=get_free_page(GFP_KERNEL|GFP_DMA);
if(c->tx_dma_buf[0]==NULL)
- {
- kfree(c->rx_buf[0]);
- kfree(c->rx_buf[1]);
- c->rx_buf[0]=NULL;
return -ENOBUFS;
- }
- c->tx_dma_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
- if(c->tx_dma_buf[1]==NULL)
- {
- kfree(c->tx_dma_buf[0]);
- kfree(c->rx_buf[0]);
- kfree(c->rx_buf[1]);
- c->rx_buf[0]=NULL;
- c->rx_buf[1]=NULL;
- c->tx_dma_buf[0]=NULL;
- return -ENOBUFS;
- }
+
+ c->tx_dma_buf[1] = c->tx_dma_buf[0] + PAGE_SIZE/2;
+
c->tx_dma_used=0;
c->dma_num=0;
c->dma_ready=1;
if(c->tx_dma_buf[0])
{
- kfree(c->tx_dma_buf[0]);
+ free_page(c->tx_dma_buf[0]);
c->tx_dma_buf[0]=NULL;
}
- if(c->tx_dma_buf[1])
- {
- kfree(c->tx_dma_buf[1]);
- c->tx_dma_buf[1]=NULL;
- }
chk=read_zsreg(c,R0);
write_zsreg(c, R3, c->regs[R3]);
z8530_rtsdtr(c,0);
return 0;
}
+/*
+ * Registration of PCI drivers and handling of hot-pluggable devices.
+ */
+
+static LIST_HEAD(pci_drivers);
+
+void
+pci_register_driver(struct pci_driver *drv)
+{
+ struct pci_dev *dev;
+
+ list_add_tail(&drv->node, &pci_drivers);
+ pci_for_each_dev(dev) {
+ if (!pci_dev_driver(dev) && drv->probe(dev))
+ dev->driver = drv;
+ }
+}
+
+void
+pci_unregister_driver(struct pci_driver *drv)
+{
+ struct pci_dev *dev;
+
+ list_del(&drv->node);
+ pci_for_each_dev(dev) {
+ if (dev->driver == drv) {
+ if (drv->remove)
+ drv->remove(dev);
+ dev->driver = NULL;
+ }
+ }
+}
+
+void
+pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
+{
+ struct list_head *ln;
+
+ list_add_tail(&dev->bus_list, &bus->devices);
+ list_add_tail(&dev->global_list, &pci_devices);
+#ifdef CONFIG_PROC_FS
+ pci_proc_attach_device(dev);
+#endif
+ for(ln=pci_drivers.next; ln != &pci_devices; ln=ln->next) {
+ struct pci_driver *drv = list_entry(ln, struct pci_driver, node);
+ if (drv->probe(dev)) {
+ dev->driver = drv;
+ break;
+ }
+ }
+}
+
+void
+pci_remove_device(struct pci_dev *dev)
+{
+ if (dev->driver->remove)
+ dev->driver->remove(dev);
+ dev->driver = NULL;
+ list_del(&dev->bus_list);
+ list_del(&dev->global_list);
+#ifdef CONFIG_PROC_FS
+ pci_proc_detach_device(dev);
+#endif
+}
+
+static struct pci_driver pci_compat_driver = {
+ name: "compat"
+};
+
+struct pci_driver *
+pci_dev_driver(struct pci_dev *dev)
+{
+ if (dev->driver)
+ return dev->driver;
+ else {
+ int i;
+ for(i=0; i<=PCI_ROM_RESOURCE; i++)
+ if (dev->resource[i].flags & IORESOURCE_BUSY)
+ return &pci_compat_driver;
+ }
+ return NULL;
+}
+
/*
* This interrupt-safe spinlock protects all accesses to PCI
EXPORT_SYMBOL(pci_set_power_state);
EXPORT_SYMBOL(pci_assign_resource);
EXPORT_SYMBOL(pci_setup_device);
-#ifdef CONFIG_PROC_FS
-EXPORT_SYMBOL(pci_proc_attach_device);
-EXPORT_SYMBOL(pci_proc_detach_device);
-#endif
+EXPORT_SYMBOL(pci_insert_device);
+EXPORT_SYMBOL(pci_remove_device);
+EXPORT_SYMBOL(pci_register_driver);
+EXPORT_SYMBOL(pci_unregister_driver);
/* Obsolete functions */
cnt = 0;
pci_for_each_dev(dev) {
+ struct pci_driver *drv = pci_dev_driver(dev);
len = sprintf(buf, "%02x%02x\t%04x%04x\t%x",
dev->bus->number,
dev->devfn,
for(i=0; i<7; i++)
len += sprintf(buf+len, LONG_FORMAT, dev->resource[i].start < dev->resource[i].end ?
dev->resource[i].end - dev->resource[i].start + 1 : 0);
+ buf[len++] = '\t';
+ if (drv)
+ len += sprintf(buf+len, "%s", drv->name);
buf[len++] = '\n';
at += len;
if (at >= pos) {
#define PCDATA_CODE_TYPE 0x0014
#define PCDATA_INDICATOR 0x0015
-#ifndef CONFIG_PROC_FS
-#define pci_proc_attach_device(dev) do { } while (0)
-#define pci_proc_detach_device(dev) do { } while (0)
-#endif
-
typedef struct cb_config_t {
struct pci_dev dev;
} cb_config_t;
}
}
- list_add_tail(&dev->bus_list, &bus->devices);
- list_add_tail(&dev->global_list, &pci_devices);
- pci_proc_attach_device(dev);
+ pci_insert_device(dev, bus);
pci_enable_device(dev);
}
for(i=0; i<s->functions; i++) {
struct pci_dev *dev = &c[i].dev;
- list_del(&dev->bus_list);
- list_del(&dev->global_list);
free_resources(dev);
- pci_proc_detach_device(dev);
+ pci_remove_device(dev);
}
kfree(c);
printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number);
MOD_SUB_DIRS := $(SUB_DIRS)
ALL_SUB_DIRS := $(SUB_DIRS)
-L_TARGET := pnp.a
-MX_OBJS :=
-LX_OBJS :=
-MI_OBJS :=
-MIX_OBJS :=
+ifeq ($(CONFIG_ISAPNP),m)
+M_OBJS := isa-pnp.o
+endif
+
+O_TARGET := isa-pnp.o
+OX_OBJS := isapnp.o
+O_OBJS := quirks.o
-ifeq ($(CONFIG_ISAPNP),y)
- LX_OBJS += isapnp.o quirks.o
-else
- ifeq ($(CONFIG_ISAPNP),m)
- MX_OBJS += isapnp.o quirks.o
- endif
+ifdef CONFIG_PROC_FS
+O_OBJS += isapnp_proc.o
endif
include $(TOPDIR)/Rules.make
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/malloc.h>
-#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/poll.h>
#include <linux/init.h>
-#include <asm/uaccess.h>
#include <linux/isapnp.h>
LIST_HEAD(isapnp_cards);
LIST_HEAD(isapnp_devices);
-#define isapnp_for_each_card(card) \
- for(card = pci_bus_b(isapnp_cards.next); card != pci_bus_b(&isapnp_cards); card = pci_bus_b(card->node.next))
-#define isapnp_for_each_dev(dev) \
- for(dev = pci_dev_g(isapnp_devices.next); dev != pci_dev_g(&isapnp_devices); dev = pci_dev_g(dev->global_list.next))
-
-
-#ifdef CONFIG_PROC_FS
-#include "isapnp_proc.c"
-#endif
-
#if 0
#define ISAPNP_REGION_OK
#endif
if (isapnp_checksum_value != 0x00)
printk("isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
card->checksum = isapnp_checksum_value;
+ INIT_LIST_HEAD(&card->devices);
list_add_tail(&card->node, &isapnp_cards);
}
*
*/
+#define __NO_VERSION__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/poll.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <linux/isapnp.h>
+
struct isapnp_info_buffer {
char *buffer; /* pointer to begin of buffer */
char *curr; /* current position in buffer */
&isapnp_info_entry_operations, /* default sound info directory file-ops */
};
-static int __init isapnp_proc_init(void)
+int __init isapnp_proc_init(void)
{
struct proc_dir_entry *p;
}
#ifdef MODULE
-static int isapnp_proc_done(void)
+int isapnp_proc_done(void)
{
if (isapnp_proc_entry)
remove_proc_entry("isapnp",&proc_root);
static void isapnp_info_read(isapnp_info_buffer_t *buffer)
{
- struct list_head *card_list;
-
- for (card_list = isapnp_cards.next; card_list != &isapnp_cards; card_list = card_list->next) {
- struct pci_bus *card = list_entry(card_list, struct pci_bus, node);
+ struct pci_bus *card;
+
+ isapnp_for_each_card(card) {
struct list_head *dev_list;
isapnp_printf(buffer, "Card %i '", card->number);
if (card->productver)
isapnp_printf(buffer, " Product version %x.%x", card->productver >> 4, card->productver & 0x0f);
isapnp_printf(buffer,"\n");
- for (dev_list = card->devices.next; dev_list != &card->devices; dev_list = dev_list->next) {
- struct pci_dev *dev = list_entry(dev_list, struct pci_dev, bus_list);
- isapnp_print_device(buffer, dev);
- }
+ for (dev_list = card->devices.next; dev_list != &card->devices; dev_list = dev_list->next)
+ isapnp_print_device(buffer, pci_dev_b(dev_list));
}
}
isapnp_info_device = NULL;
isapnp_get_str(index, line, sizeof(index));
csn = simple_strtoul(index, NULL, 0);
+
for (list = isapnp_cards.next; list != &isapnp_cards; list = list->next) {
- isapnp_info_card = list_entry(list, struct pci_bus, node);
+ isapnp_info_card = pci_bus_b(list);
if (isapnp_info_card->number == csn)
break;
}
- if (isapnp_info_card == NULL) {
+ if (list == &isapnp_cards) {
printk("isapnp: cannot find CSN %i\n", csn);
return 1;
}
+Sat Jan 8 22:00 2000 Gerard Roudier (groudier@club-internet.fr)
+ * revision 3.2e
+ - Add year 2000 copyright.
+ - Display correctly bus signals when bus is detected wrong.
+ - Remove the dead code that broke driver 3.2d.
+
Mon Dec 6 22:00 1999 Gerard Roudier (groudier@club-internet.fr)
* revision 3.2d
- Change messages written by the driver at initialisation and
+Sat Jan 8 22:00 2000 Gerard Roudier (groudier@club-internet.fr)
+ * version sym53c8xx-1.5h
+ - Add year 2000 copyright.
+ - Display correctly bus signals when bus is detected wrong.
+ - Some fix for Sparc from DSM that went directly to kernel tree.
+
Mon Dec 6 22:00 1999 Gerard Roudier (groudier@club-internet.fr)
* version sym53c8xx-1.5g
- Change messages written by the driver at initialisation and
*/
/*
-** December 6 1999, version 3.2d
+** January 8 2000, version 3.2e
**
** Supported SCSI-II features:
** Synchronous negotiation
/*
** Name and version of the driver
*/
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2d"
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2e"
#define SCSI_NCR_DEBUG_FLAGS (0)
** We are expecting RESET to be TRUE and other signals to be
** FALSE.
*/
- term = INB(nc_sstat0); /* rst, sdp0 */
- term = ((term & 2) << 7) + ((term & 1) << 16);
- term |= ((INB(nc_sstat2) & 0x01) << 25) | /* sdp1 */
- (INW(nc_sbdl) << 9) | /* d15-0 */
- INB(nc_sbcl); /* req, ack, bsy, sel, atn, msg, cd, io */
+
+ term = INB(nc_sstat0);
+ term = ((term & 2) << 7) + ((term & 1) << 17); /* rst sdp0 */
+ term |= ((INB(nc_sstat2) & 0x01) << 26) | /* sdp1 */
+ ((INW(nc_sbdl) & 0xff) << 9) | /* d7-0 */
+ ((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */
+ INB(nc_sbcl); /* req ack bsy sel atn msg cd io */
if (!(np->features & FE_WIDE))
term &= 0x3ffff;
uint irq;
ulong base, base_2, io_port;
int i;
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- ncr_nvram *nvram = device->nvram;
-#endif
ncr_chip *chip;
/*
device->slot.io_port = io_port;
device->slot.irq = irq;
device->attach_done = 0;
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- if (!nvram)
- goto out;
- /*
- ** Get access to chip IO registers
- */
-#ifdef NCR_IOMAPPED
- request_region(io_port, 128, "ncr53c8xx");
- device->slot.port = io_port;
-#else
- device->slot.reg = (struct ncr_reg *) remap_pci_mem((ulong) base, 128);
- if (!device->slot.reg)
- goto out;
-#endif
-
- /*
- ** Try to read SYMBIOS nvram.
- ** Data can be used to order booting of boards.
- **
- ** Data is saved in ncr_device structure if NVRAM found. This
- ** is then used to find drive boot order for ncr_attach().
- **
- ** NVRAM data is passed to Scsi_Host_Template later during ncr_attach()
- ** for any device set up.
- **
- ** Try to read TEKRAM nvram if Symbios nvram not found.
- */
-
- if (!ncr_get_Symbios_nvram(&device->slot, &nvram->data.Symbios))
- nvram->type = SCSI_NCR_SYMBIOS_NVRAM;
- else if (!ncr_get_Tekram_nvram(&device->slot, &nvram->data.Tekram))
- nvram->type = SCSI_NCR_TEKRAM_NVRAM;
- else
- nvram->type = 0;
-out:
- /*
- ** Release access to chip IO registers
- */
-#ifdef NCR_IOMAPPED
- release_region(device->slot.port, 128);
-#else
- unmap_pci_mem((vm_offset_t) device->slot.reg, (u_long) 128);
-#endif
-
-#endif /* SCSI_NCR_NVRAM_SUPPORT */
return 0;
}
* QLogic ISP1020 Intelligent SCSI Processor Driver (PCI)
* Written by Erik H. Moe, ehm@cris.com
* Copyright 1995, Erik H. Moe
- * Copyright 1996, 1997 Michael A. Griffith <grif@acm.org>
+ * Copyright 1996, 1997 Michael A. Griffith <grif@acm.org>
+ * Copyright 2000, Jayson C. Vantuyl <vantuyl@csc.smsu.edu>
+ * and Bryon W. Roche <bryon@csc.smsu.edu>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
static void isp1020_print_status_entry(struct Status_Entry *);
#endif
+/* memaddr should be used to determine if memmapped port i/o is being used
+ * non-null memaddr == mmap'd
+ * JV 7-Jan-2000
+ */
static inline u_short isp_inw(struct Scsi_Host *host, long offset)
{
struct isp1020_hostdata *h = (struct isp1020_hostdata *)host->hostdata;
hostdata = (struct isp1020_hostdata *) host->hostdata;
memset(hostdata, 0, sizeof(struct isp1020_hostdata));
+
hostdata->pci_dev = pdev;
- if (isp1020_init(host) || isp1020_reset_hardware(host)
+ if (isp1020_init(host)) {
+ scsi_unregister(host);
+ continue;
+ }
+
+ if (isp1020_reset_hardware(host)
#if USE_NVRAM_DEFAULTS
|| isp1020_get_defaults(host)
#else
|| isp1020_set_defaults(host)
#endif /* USE_NVRAM_DEFAULTS */
|| isp1020_load_parameters(host)) {
+ iounmap((void *)hostdata->memaddr);
+ release_region(host->io_port, 0xff);
scsi_unregister(host);
continue;
}
{
printk("qlogicisp : interrupt %d already in use\n",
host->irq);
+ iounmap((void *)hostdata->memaddr);
+ release_region(host->io_port, 0xff);
scsi_unregister(host);
continue;
}
- if (check_region(host->io_port, 0xff)) {
- printk("qlogicisp : i/o region 0x%lx-0x%lx already "
- "in use\n",
- host->io_port, host->io_port + 0xff);
- free_irq(host->irq, host);
- scsi_unregister(host);
- continue;
- }
-
- request_region(host->io_port, 0xff, "qlogicisp");
-
isp_outw(0x0, host, PCI_SEMAPHORE);
isp_outw(HCCR_CLEAR_RISC_INTR, host, HOST_HCCR);
isp1020_enable_irqs(host);
isp_outw(0x0, host, PCI_INTF_CTL);
free_irq(host->irq, host);
+ iounmap((void *)hostdata->memaddr);
+
release_region(host->io_port, 0xff);
LEAVE("isp1020_release");
sprintf(buf,
"QLogic ISP1020 SCSI on PCI bus %02x device %02x irq %d %s base 0x%lx",
hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
- (host->io_port ? "I/O" : "MEM"),
- (host->io_port ? host->io_port : hostdata->memaddr));
+ (hostdata->memaddr ? "MEM" : "I/O"),
+ (hostdata->memaddr ? hostdata->memaddr : host->io_port));
LEAVE("isp1020_info");
command &= ~PCI_COMMAND_MEMORY;
#endif
+ if (!(command & PCI_COMMAND_MASTER)) {
+ printk("qlogicisp : bus mastering is disabled\n");
+ return 1;
+ }
+
+ sh->io_port = io_base;
+
+ if (check_region(sh->io_port, 0xff)) {
+ printk("qlogicisp : i/o region 0x%lx-0x%lx already "
+ "in use\n",
+ sh->io_port, sh->io_port + 0xff);
+ return 1;
+ }
+
+ request_region(sh->io_port, 0xff, "qlogicisp");
+
if ((command & PCI_COMMAND_MEMORY) &&
((mem_flags & 1) == 0)) {
mem_base = (u_long) ioremap(mem_base, PAGE_SIZE);
hostdata->memaddr = mem_base;
- io_base = 0;
} else {
if (command & PCI_COMMAND_IO && (io_flags & 3) != 1)
{
printk("qlogicisp : i/o mapping is disabled\n");
+ release_region(sh->io_port, 0xff);
return 1;
}
- hostdata->memaddr = 0;
- sh->io_port = io_base;
+ hostdata->memaddr = 0; /* zero to signify no i/o mapping */
mem_base = 0;
}
- if (!(command & PCI_COMMAND_MASTER)) {
- printk("qlogicisp : bus mastering is disabled\n");
- return 1;
- }
-
if (revision != ISP1020_REV_ID)
printk("qlogicisp : new isp1020 revision ID (%d)\n", revision);
printk("qlogicisp : can't decode %s address space 0x%lx\n",
(io_base ? "I/O" : "MEM"),
(io_base ? io_base : mem_base));
+ iounmap((void *)hostdata->memaddr);
+ release_region(sh->io_port, 0xff);
return 1;
}
*/
if (count != SCpnt->use_sg) {
printk("Incorrect number of segments after building list\n");
+#ifdef CONFIG_SCSI_DEBUG_QUEUES
dump_stats(req, use_clustering, dma_host, count);
+#endif
}
if (!dma_host) {
return 1;
/******************************************************************************
** High Performance device driver for the Symbios 53C896 controller.
**
-** Copyright (C) 1998-1999 Gerard Roudier <groudier@club-internet.fr>
+** Copyright (C) 1998-2000 Gerard Roudier <groudier@club-internet.fr>
**
** This driver also supports all the Symbios 53C8XX controller family,
** except 53C810 revisions < 16, 53C825 revisions < 16 and all
*/
/*
-** December 6 1999, sym53c8xx 1.5g
+** January 9 2000, sym53c8xx 1.5h
**
** Supported SCSI features:
** Synchronous data transfers
/*
** Name and version of the driver
*/
-#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5g"
+#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5h"
/* #define DEBUG_896R1 */
#define SCSI_NCR_OPTIMIZE_896
** We are expecting RESET to be TRUE and other signals to be
** FALSE.
*/
- term = INB(nc_sstat0); /* rst, sdp0 */
- term = ((term & 2) << 7) + ((term & 1) << 16);
- term |= ((INB(nc_sstat2) & 0x01) << 25) | /* sdp1 */
- (INW(nc_sbdl) << 9) | /* d15-0 */
- INB(nc_sbcl); /* req, ack, bsy, sel, atn, msg, cd, io */
+ term = INB(nc_sstat0);
+ term = ((term & 2) << 7) + ((term & 1) << 17); /* rst sdp0 */
+ term |= ((INB(nc_sstat2) & 0x01) << 26) | /* sdp1 */
+ ((INW(nc_sbdl) & 0xff) << 9) | /* d7-0 */
+ ((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */
+ INB(nc_sbcl); /* req ack bsy sel atn msg cd io */
if (!(np->features & FE_WIDE))
term &= 0x3ffff;
/******************************************************************************
** High Performance device driver for the Symbios 53C896 controller.
**
-** Copyright (C) 1998-1999 Gerard Roudier <groudier@club-internet.fr>
+** Copyright (C) 1998-2000 Gerard Roudier <groudier@club-internet.fr>
**
** This driver also supports all the Symbios 53C8XX controller family,
** except 53C810 revisions < 16, 53C825 revisions < 16 and all
/******************************************************************************
** High Performance device driver for the Symbios 53C896 controller.
**
-** Copyright (C) 1998-1999 Gerard Roudier <groudier@club-internet.fr>
+** Copyright (C) 1998-2000 Gerard Roudier <groudier@club-internet.fr>
**
** This driver also supports all the Symbios 53C8XX controller family,
** except 53C810 revisions < 16, 53C825 revisions < 16 and all
}
#endif /* CONFIG_PMAC_PBOOK */
-#ifdef CONFIG_PMAC_PBOOK
-/*
- * Save the contents of the frame buffer when we go to sleep,
- * and restore it when we wake up again.
- */
-int
-aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
-{
- struct fb_info_aty *info;
- unsigned int pm;
-
- for (info = first_display; info != NULL; info = info->next) {
- struct fb_fix_screeninfo fix;
- int nb;
-
- atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
- nb = fb_display[fg_console].var.yres * fix.line_length;
-
- switch (when) {
- case PBOOK_SLEEP_NOW:
- /* Stop accel engine (stop bus mastering) */
- if (info->current_par.accel_flags & FB_ACCELF_TEXT)
- reset_engine(info);
-#if 1
- /* Backup fb content */
- info->save_framebuffer = vmalloc(nb);
- if (info->save_framebuffer)
- memcpy(info->save_framebuffer,
- (void *)info->frame_buffer, nb);
-#endif
- /* Blank display and LCD */
- atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
-
- /* Set chip to "suspend" mode. Note: There's an HW bug in the
- chip which prevents proper resync on wakeup with automatic
- power management, we handle suspend manually using the
- following (weird) sequence described by ATI. Note2:
- We could enable this for all Rage LT Pro chip ids */
- if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
- pm = aty_ld_le32(POWER_MANAGEMENT, info);
- pm &= ~PWR_MGT_ON;
- aty_st_le32(POWER_MANAGEMENT, pm, info);
- pm = aty_ld_le32(POWER_MANAGEMENT, info);
- pm &= ~(PWR_BLON | AUTO_PWR_UP);
- pm |= SUSPEND_NOW;
- aty_st_le32(POWER_MANAGEMENT, pm, info);
- pm = aty_ld_le32(POWER_MANAGEMENT, info);
- pm |= PWR_MGT_ON;
- aty_st_le32(POWER_MANAGEMENT, pm, info);
- do {
- pm = aty_ld_le32(POWER_MANAGEMENT, info);
- } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
- mdelay(500);
- }
- break;
- case PBOOK_WAKE:
- /* Wakeup chip */
- if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
- pm = aty_ld_le32(POWER_MANAGEMENT, info);
- pm &= ~PWR_MGT_ON;
- aty_st_le32(POWER_MANAGEMENT, pm, info);
- pm = aty_ld_le32(POWER_MANAGEMENT, info);
- pm |= (PWR_BLON | AUTO_PWR_UP);
- pm &= ~SUSPEND_NOW;
- aty_st_le32(POWER_MANAGEMENT, pm, info);
- pm = aty_ld_le32(POWER_MANAGEMENT, info);
- pm |= PWR_MGT_ON;
- aty_st_le32(POWER_MANAGEMENT, pm, info);
- do {
- pm = aty_ld_le32(POWER_MANAGEMENT, info);
- } while ((pm & PWR_MGT_STATUS_MASK) != 0);
- mdelay(500);
- }
-#if 1
- /* Restore fb content */
- if (info->save_framebuffer) {
- memcpy((void *)info->frame_buffer,
- info->save_framebuffer, nb);
- vfree(info->save_framebuffer);
- info->save_framebuffer = 0;
- }
-#endif
- /* Restore display */
- atyfb_set_par(&info->current_par, info);
- atyfbcon_blank(0, (struct fb_info *)info);
- break;
- }
- }
- return PBOOK_SLEEP_OK;
-}
-#endif /* CONFIG_PMAC_PBOOK */
-
#ifdef MODULE
int __init init_module(void)
{
*/
#include <linux/fs.h>
+#include <linux/locks.h>
if (!bh)
return 0;
if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- brelse(bh);
- return -1;
+ /* There can be a parallell read(2) that started read-I/O
+ on the buffer so we can't assume that there's been
+ an I/O error without first waiting I/O completation. */
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh))
+ {
+ brelse (bh);
+ return -1;
+ }
}
if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
+ if (wait)
+ /* when we return from fsync all the blocks
+ must be _just_ stored on disk */
+ wait_on_buffer(bh);
brelse(bh);
return 0;
}
}
if (metadata) {
result = getblk (inode->i_dev, tmp, blocksize);
+ if (!buffer_uptodate(result))
+ wait_on_buffer(result);
memset(result->b_data, 0, blocksize);
mark_buffer_uptodate(result, 1);
mark_buffer_dirty(result, 1);
goto out;
if (metadata) {
result = getblk (bh->b_dev, tmp, blocksize);
+ if (!buffer_uptodate(result))
+ wait_on_buffer(result);
memset(result->b_data, 0, inode->i_sb->s_blocksize);
mark_buffer_uptodate(result, 1);
mark_buffer_dirty(result, 1);
struct buffer_head *bh;
bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
if (buffer_new(&dummy)) {
+ if (!buffer_uptodate(bh))
+ wait_on_buffer(bh);
memset(bh->b_data, 0, inode->i_sb->s_blocksize);
mark_buffer_uptodate(bh, 1);
mark_buffer_dirty(bh, 1);
return 0;
}
- memcpy (maplist, iobuf->maplist, wanted * sizeof(struct page **));
+ memcpy (maplist, iobuf->maplist, iobuf->array_len * sizeof(struct page **));
if (iobuf->array_len > KIO_STATIC_PAGES)
kfree (iobuf->maplist);
* Unfortunately proc_register puts each new entry
* at the beginning of the list. So we rearrange them.
*/
- ent = create_proc_read_entry(de, 0, pp->name,
- property_read_proc, pp);
+ ent = create_proc_read_entry(pp->name, S_IRUGO, de,
+ property_read_proc, pp);
if (ent == 0)
break;
ent->size = pp->length;
l = strlen(p);
if (l > 2 && p[l-2] == '@' && p[l-1] == '0')
l -= 2;
- ent = proc_mkdir(de, p);
+ ent = proc_mkdir(p, de);
if (ent == 0)
break;
*lastp = ent;
if (sib->name && strcmp(sib->name, child->name) == 0)
break;
if (sib == child && strncmp(p, child->name, l) != 0) {
- al = proc_symlink(de, child->name, ent->name);
+ al = proc_symlink(child->name, de, ent->name);
if (al == 0)
break;
*lastp = al;
/*
* Add another directory with the @address part as its name.
*/
- al = proc_symlink(de, at, ent->name);
+ al = proc_symlink(at, de, ent->name);
if (al == 0)
break;
proc_register(de, al);
EXPORT_SYMBOL(proc_root_fs);
EXPORT_SYMBOL(proc_net);
EXPORT_SYMBOL(proc_bus);
+EXPORT_SYMBOL(proc_root_driver);
static struct file_system_type proc_fs_type = {
"proc",
void isapnp_deactivate(unsigned char device);
void isapnp_fixup_device(struct pci_dev *dev);
void *isapnp_alloc(long size);
+int isapnp_proc_init(void);
+int isapnp_proc_done(void);
/* manager */
struct pci_bus *isapnp_find_card(unsigned short vendor,
unsigned short device,
/* init/main.c */
int isapnp_init(void);
+extern struct list_head isapnp_cards;
+extern struct list_head isapnp_devices;
+
+#define isapnp_for_each_card(card) \
+ for(card = pci_bus_b(isapnp_cards.next); card != pci_bus_b(&isapnp_cards); card = pci_bus_b(card->node.next))
+#define isapnp_for_each_dev(dev) \
+ for(dev = pci_dev_g(isapnp_devices.next); dev != pci_dev_g(&isapnp_devices); dev = pci_dev_g(dev->global_list.next))
+
#else /* !CONFIG_ISAPNP */
/* lowlevel configuration */
extern inline void isapnp_write_byte(unsigned char idx, unsigned char val) { ; }
extern inline void isapnp_write_word(unsigned char idx, unsigned short val) { ; }
extern inline void isapnp_write_dword(unsigned char idx, unsigned int val) { ; }
-extern void isapnp_wake(unsigned char csn) { ; }
-extern void isapnp_device(unsigned char device) { ; }
-extern void isapnp_activate(unsigned char device) { ; }
-extern void isapnp_deactivate(unsigned char device) { ; }
+extern inline void isapnp_wake(unsigned char csn) { ; }
+extern inline void isapnp_device(unsigned char device) { ; }
+extern inline void isapnp_activate(unsigned char device) { ; }
+extern inline void isapnp_deactivate(unsigned char device) { ; }
/* manager */
-extern struct pci_bus *isapnp_find_card(unsigned short vendor,
- unsigned short device,
- struct pci_bus *from) { return NULL; }
-extern struct pci_dev *isapnp_find_dev(struct pci_bus *card,
- unsigned short vendor,
- unsigned short function,
+extern inline struct pci_bus *isapnp_find_card(unsigned short vendor,
+ unsigned short device,
+ struct pci_bus *from) { return NULL; }
+extern inline struct pci_dev *isapnp_find_dev(struct pci_bus *card,
+ unsigned short vendor,
+ unsigned short function,
struct pci_dev *from) { return NULL; }
-extern void isapnp_resource_change(struct resource *resource,
- unsigned long start,
- unsigned long size) { ; }
+extern inline void isapnp_resource_change(struct resource *resource,
+ unsigned long start,
+ unsigned long size) { ; }
#endif /* CONFIG_ISAPNP */
unsigned short subsystem_device;
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
u8 hdr_type; /* PCI header type (`multi' flag masked out) */
- u8 rom_base_reg; /* Which config register controls the ROM */
+ u8 rom_base_reg; /* which config register controls the ROM */
- unsigned short regs;
+ struct pci_driver *driver; /* which driver has allocated this device */
+ void *driver_data; /* data private to the driver */
/* device is compatible with these IDs */
unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];
struct resource dma_resource[DEVICE_COUNT_DMA];
struct resource irq_resource[DEVICE_COUNT_IRQ];
- char name[48]; /* Device name */
- char slot_name[8]; /* Slot name */
- int active; /* device is active */
- int ro; /* Read/Only */
+ char name[48]; /* device name */
+ char slot_name[8]; /* slot name */
+ int active; /* ISAPnP: device is active */
+ int ro; /* ISAPnP: read only */
+ unsigned short regs; /* ISAPnP: supported registers */
- int (*prepare)(struct pci_dev *dev);
+ int (*prepare)(struct pci_dev *dev); /* ISAPnP hooks */
int (*activate)(struct pci_dev *dev);
int (*deactivate)(struct pci_dev *dev);
};
void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
int (*)(struct pci_dev *, u8, u8));
+/* New-style probing supporting hot-pluggable devices */
+
+struct pci_driver {
+ struct list_head node;
+ char *name;
+ int (*probe)(struct pci_dev *dev); /* New device inserted, check if known */
+ void (*remove)(struct pci_dev *dev); /* Device removed */
+ void (*suspend)(struct pci_dev *dev); /* Device suspended */
+ void (*resume)(struct pci_dev *dev); /* Device woken up */
+};
+
+void pci_register_driver(struct pci_driver *);
+void pci_unregister_driver(struct pci_driver *);
+void pci_insert_device(struct pci_dev *, struct pci_bus *);
+void pci_remove_device(struct pci_dev *);
+struct pci_driver *pci_dev_driver(struct pci_dev *);
+
/*
* simple PCI probing for drivers (drivers/pci/helper.c)
*/
mode_t mode, struct proc_dir_entry *parent) { return NULL; }
extern inline void remove_proc_entry(const char *name, struct proc_dir_entry *parent) {};
-extern inline proc_dir_entry *proc_symlink(const char *name,
+extern inline struct proc_dir_entry *proc_symlink(const char *name,
struct proc_dir_entry *parent,char *dest) {return NULL;}
-extern inline proc_dir_entry *proc_mknod(const char *name,mode_t mode,
+extern inline struct proc_dir_entry *proc_mknod(const char *name,mode_t mode,
struct proc_dir_entry *parent,kdev_t rdev) {return NULL;}
-extern struct proc_dir_entry *proc_mkdir(const char *name,
+extern inline struct proc_dir_entry *proc_mkdir(const char *name,
struct proc_dir_entry *parent) {return NULL;}
extern inline struct proc_dir_entry *create_proc_read_entry(const char *name,
extern void FASTCALL(wake_up_process(struct task_struct * tsk));
#define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
-#define wake_up_all(x) __wake_up_all((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
+#define wake_up_all(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
#define wake_up_sync(x) __wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
-#define wake_up_interruptible_all(x) __wake_up_all((x),TASK_INTERRUPTIBLE)
+#define wake_up_interruptible_all(x) __wake_up((x),TASK_INTERRUPTIBLE)
#define wake_up_interruptible_sync(x) __wake_up_sync((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
extern int in_group_p(gid_t);
unsigned flags;
#define TCQ_F_BUILTIN 1
#define TCQ_F_THROTTLED 2
+#define TCQ_F_INGRES 4
struct Qdisc_ops *ops;
struct Qdisc *next;
u32 handle;
const unsigned char *p = s;
while (n-- != 0) {
if ((unsigned char)c == *p++) {
- return (void *)p-1;
+ return (void *)(p-1);
}
}
return NULL;