summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/block_ioctl.c1
-rw-r--r--drivers/ide/Config.help73
-rw-r--r--drivers/ide/Config.in37
-rw-r--r--drivers/ide/Makefile1
-rw-r--r--drivers/ide/amd74xx.c41
-rw-r--r--drivers/ide/ide-disk.c128
-rw-r--r--drivers/ide/ide-pci.c37
-rw-r--r--drivers/ide/ide-proc.c12
-rw-r--r--drivers/ide/ide-taskfile.c312
-rw-r--r--drivers/ide/pdc4030.c8
-rw-r--r--drivers/ide/piix.c901
-rw-r--r--drivers/ide/slc90e66.c384
-rw-r--r--drivers/pci/pci.c55
-rw-r--r--drivers/pci/pci.ids47
-rw-r--r--drivers/pnp/isapnp.c56
-rw-r--r--drivers/usb/Config.help1
-rw-r--r--drivers/usb/catc.c291
-rw-r--r--drivers/usb/hid-core.c72
-rw-r--r--drivers/usb/hid.h3
-rw-r--r--drivers/usb/hiddev.c116
-rw-r--r--drivers/usb/printer.c603
-rw-r--r--drivers/usb/serial/cyberjack.c8
-rw-r--r--drivers/usb/serial/digi_acceleport.c14
-rw-r--r--drivers/usb/serial/empeg.c8
-rw-r--r--drivers/usb/serial/ftdi_sio.c4
-rw-r--r--drivers/usb/serial/io_edgeport.c18
-rw-r--r--drivers/usb/serial/ipaq.c4
-rw-r--r--drivers/usb/serial/ir-usb.c4
-rw-r--r--drivers/usb/serial/keyspan.c14
-rw-r--r--drivers/usb/serial/keyspan_pda.c4
-rw-r--r--drivers/usb/serial/kl5kusb105.c8
-rw-r--r--drivers/usb/serial/mct_u232.c2
-rw-r--r--drivers/usb/serial/omninet.c4
-rw-r--r--drivers/usb/serial/pl2303.c8
-rw-r--r--drivers/usb/serial/usbserial.c4
-rw-r--r--drivers/usb/serial/visor.c10
-rw-r--r--drivers/usb/serial/whiteheat.c2
37 files changed, 1702 insertions, 1593 deletions
diff --git a/drivers/block/block_ioctl.c b/drivers/block/block_ioctl.c
index e206157da22d..60b2fb3c0c64 100644
--- a/drivers/block/block_ioctl.c
+++ b/drivers/block/block_ioctl.c
@@ -27,6 +27,7 @@
#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/blk.h>
+#include <linux/completion.h>
#include <linux/cdrom.h>
diff --git a/drivers/ide/Config.help b/drivers/ide/Config.help
index e8bc233729fd..248d80742c20 100644
--- a/drivers/ide/Config.help
+++ b/drivers/ide/Config.help
@@ -352,19 +352,10 @@ CONFIG_WDC_ALI15X3
SAY N!
CONFIG_BLK_DEV_AMD74XX
- This driver ensures (U)DMA support for the AMD756/760 Viper
- chipsets.
-
- If you say Y here, you also need to say Y to "Use DMA by default
- when available", above.
- Please read the comments at the top of <file:drivers/ide/amd74xx.c>.
-
- If unsure, say N.
-
-CONFIG_AMD74XX_OVERRIDE
- This option auto-forces the ata66 flag.
- This effect can be also invoked by calling "idex=ata66"
- If unsure, say N.
+ This driver adds explicit support for AMD-7xx and AMD-8111 chips
+ and also for the nVidia nForce chip. This allows the kernel to
+ change PIO, DMA and UDMA speeds and to configure the chip to
+ optimum performance.
CONFIG_BLK_DEV_CMD64X
Say Y here if you have an IDE controller which uses any of these
@@ -435,28 +426,10 @@ CONFIG_BLK_DEV_SVWKS
chipsets.
CONFIG_BLK_DEV_PIIX
- This driver adds PIO mode setting and tuning for all PIIX IDE
- controllers by Intel. Since the BIOS can sometimes improperly tune
- PIO 0-4 mode settings, this allows dynamic tuning of the chipset
- via the standard end-user tool 'hdparm'.
-
- Please read the comments at the top of <file:drivers/ide/piix.c>.
-
- If you say Y here, you should also say Y to "PIIXn Tuning support",
- below.
-
- If unsure, say N.
-
-CONFIG_PIIX_TUNING
- This driver extension adds DMA mode setting and tuning for all PIIX
- IDE controllers by Intel. Since the BIOS can sometimes improperly
- set up the device/adapter combination and speed limits, it has
- become a necessity to back/forward speed devices as needed.
-
- Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode
- 2 if the BIOS can not perform this task at initialization.
-
- If unsure, say N.
+ This driver adds explicit support for Intel PIIX and ICH chips
+ and also for the Efar Victory66 (slc90e66) chip. This allows
+ the kernel to change PIO, DMA and UDMA speeds and to configure
+ the chip to optimum performance.
CONFIG_BLK_DEV_PDC202XX
Promise Ultra33 or PDC20246
@@ -513,19 +486,6 @@ CONFIG_BLK_DEV_SIS5513
Please read the comments at the top of <file:drivers/ide/sis5513.c>.
-CONFIG_BLK_DEV_SLC90E66
- This driver ensures (U)DMA support for Victroy66 SouthBridges for
- SMsC with Intel NorthBridges. This is an Ultra66 based chipset.
- The nice thing about it is that you can mix Ultra/DMA/PIO devices
- and it will handle timing cycles. Since this is an improved
- look-a-like to the PIIX4 it should be a nice addition.
-
- If you say Y here, you need to say Y to "Use DMA by default when
- available" as well.
-
- Please read the comments at the top of
- <file:drivers/ide/slc90e66.c>.
-
CONFIG_BLK_DEV_SL82C105
If you have a Winbond SL82c105 IDE controller, say Y here to enable
special configuration for this chip. This is common on various CHRP
@@ -538,20 +498,9 @@ CONFIG_BLK_DEV_TRM290
Please read the comments at the top of <file:drivers/ide/trm290.c>.
CONFIG_BLK_DEV_VIA82CXXX
- This allows you to configure your chipset for a better use while
- running PIO/(U)DMA, it will allow you to enable efficiently the
- second channel dma usage, as it may not be set by BIOS. It will try
- to set fifo configuration at its best. It will allow you to get
- information from /proc/ide/via provided you enabled "/proc file
- system" support.
-
- Please read the comments at the top of
- <file:drivers/ide/via82cxxx.c>.
-
- If you say Y here, then say Y to "Use DMA by default when available"
- as well.
-
- If unsure, say N.
+ This driver adds explicit support for VIA BusMastering IDE chips.
+ This allows the kernel to change PIO, DMA and UDMA speeds and to
+ configure the chip to optimum performance.
CONFIG_BLK_DEV_IDE_RAPIDE
Say Y here if you want to support the Yellowstone RapIDE controller
diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in
index ffbc8697a02e..342d76d0073d 100644
--- a/drivers/ide/Config.in
+++ b/drivers/ide/Config.in
@@ -53,18 +53,14 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_mbool ' AEC62XX Tuning support' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX
dep_bool ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_mbool ' ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3
- dep_bool ' AMD Viper support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI
- dep_mbool ' AMD Viper ATA-66 Override (WIP)' CONFIG_AMD74XX_OVERRIDE $CONFIG_BLK_DEV_AMD74XX $CONFIG_IDEDMA_PCI_WIP
+ dep_bool ' AMD and nVidia chipset support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' CMD64X chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' HPT34X chipset support' CONFIG_BLK_DEV_HPT34X $CONFIG_BLK_DEV_IDEDMA_PCI
dep_mbool ' HPT34X AUTODMA support (WIP)' CONFIG_HPT34X_AUTODMA $CONFIG_BLK_DEV_HPT34X $CONFIG_IDEDMA_PCI_WIP
dep_bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 $CONFIG_BLK_DEV_IDEDMA_PCI
- if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then
- dep_mbool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI
- dep_mbool ' PIIXn Tuning support' CONFIG_PIIX_TUNING $CONFIG_BLK_DEV_PIIX $CONFIG_IDEDMA_PCI_AUTO
- fi
+ dep_bool ' Intel and Efar (SMsC) chipset support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI
if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then
dep_mbool ' IT8172 IDE support' CONFIG_BLK_DEV_IT8172 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_mbool ' IT8172 IDE Tuning support' CONFIG_IT8172_TUNING $CONFIG_BLK_DEV_IT8172 $CONFIG_IDEDMA_PCI_AUTO
@@ -77,9 +73,8 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_bool ' Special FastTrak Feature' CONFIG_PDC202XX_FORCE $CONFIG_BLK_DEV_PDC202XX
dep_bool ' ServerWorks OSB4/CSB5 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
dep_bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
- dep_bool ' SLC90E66 chipset support' CONFIG_BLK_DEV_SLC90E66 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
dep_bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI
- dep_bool ' VIA82CXXX chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI
+ dep_bool ' VIA chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI
fi
if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
@@ -167,32 +162,6 @@ else
define_bool CONFIG_DMA_NONPCI n
fi
-if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
- "$CONFIG_BLK_DEV_AEC62XX" = "y" -o \
- "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \
- "$CONFIG_BLK_DEV_AMD74XX" = "y" -o \
- "$CONFIG_BLK_DEV_CMD640" = "y" -o \
- "$CONFIG_BLK_DEV_CMD64X" = "y" -o \
- "$CONFIG_BLK_DEV_CS5530" = "y" -o \
- "$CONFIG_BLK_DEV_CY82C693" = "y" -o \
- "$CONFIG_BLK_DEV_HPT34X" = "y" -o \
- "$CONFIG_BLK_DEV_HPT366" = "y" -o \
- "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \
- "$CONFIG_BLK_DEV_OPTI621" = "y" -o \
- "$CONFIG_BLK_DEV_SVWKS" = "y" -o \
- "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \
- "$CONFIG_BLK_DEV_PIIX" = "y" -o \
- "$CONFIG_BLK_DEV_IT8172" = "y" -o \
- "$CONFIG_BLK_DEV_SIS5513" = "y" -o \
- "$CONFIG_BLK_DEV_SLC90E66" = "y" -o \
- "$CONFIG_BLK_DEV_SL82C105" = "y" -o \
- "$CONFIG_BLK_DEV_VIA82CXXX" = "y" -o \
- "$CONFIG_BLK_DEV_MPC8xx_IDE" = "y" ]; then
- define_bool CONFIG_BLK_DEV_IDE_MODES y
-else
- define_bool CONFIG_BLK_DEV_IDE_MODES n
-fi
-
dep_tristate 'Support for IDE Raid controllers' CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL
dep_tristate ' Support Promise software RAID (Fasttrak(tm))' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
dep_tristate ' Highpoint 370 software RAID' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index b72a5bedd157..3142a91f6f01 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -60,7 +60,6 @@ ide-obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
ide-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
ide-obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o
ide-obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o
-ide-obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o
ide-obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o
ide-obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o
ide-obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index df0532a881c6..c1c036e36fb4 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -1,5 +1,5 @@
/*
- * $Id: amd74xx.c,v 2.7 2002/09/01 17:37:00 vojtech Exp $
+ * $Id: amd74xx.c,v 2.8 2002/03/14 11:52:20 vojtech Exp $
*
* Copyright (c) 2000-2002 Vojtech Pavlik
*
@@ -46,13 +46,13 @@
#include "ata-timing.h"
-#define AMD_IDE_ENABLE 0x40
-#define AMD_IDE_CONFIG 0x41
-#define AMD_CABLE_DETECT 0x42
-#define AMD_DRIVE_TIMING 0x48
-#define AMD_8BIT_TIMING 0x4e
-#define AMD_ADDRESS_SETUP 0x4c
-#define AMD_UDMA_TIMING 0x50
+#define AMD_IDE_ENABLE (0x00 + amd_config->base)
+#define AMD_IDE_CONFIG (0x01 + amd_config->base)
+#define AMD_CABLE_DETECT (0x02 + amd_config->base)
+#define AMD_DRIVE_TIMING (0x08 + amd_config->base)
+#define AMD_8BIT_TIMING (0x0e + amd_config->base)
+#define AMD_ADDRESS_SETUP (0x0c + amd_config->base)
+#define AMD_UDMA_TIMING (0x10 + amd_config->base)
#define AMD_UDMA 0x07
#define AMD_UDMA_33 0x01
@@ -66,18 +66,19 @@
*/
static struct amd_ide_chip {
- char *name;
unsigned short id;
unsigned char rev;
+ unsigned int base;
unsigned char flags;
} amd_ide_chips[] = {
- { "8111", PCI_DEVICE_ID_AMD_8111_IDE, 0x00, AMD_UDMA_100 },
- { "768 Opus", PCI_DEVICE_ID_AMD_OPUS_7441, 0x00, AMD_UDMA_100 },
- { "766 Viper", PCI_DEVICE_ID_AMD_VIPER_7411, 0x00, AMD_UDMA_100 | AMD_BAD_FIFO },
- { "756/c4+ Viper", PCI_DEVICE_ID_AMD_VIPER_7409, 0x07, AMD_UDMA_66 },
- { "756 Viper", PCI_DEVICE_ID_AMD_VIPER_7409, 0x00, AMD_UDMA_66 | AMD_BAD_SWDMA },
- { "755 Cobra", PCI_DEVICE_ID_AMD_COBRA_7401, 0x00, AMD_UDMA_33 | AMD_BAD_SWDMA },
- { NULL }
+ { PCI_DEVICE_ID_AMD_8111_IDE, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-8111 */
+ { PCI_DEVICE_ID_AMD_OPUS_7441, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-768 Opus */
+ { PCI_DEVICE_ID_AMD_VIPER_7411, 0x00, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO }, /* AMD-766 Viper */
+ { PCI_DEVICE_ID_AMD_VIPER_7409, 0x07, 0x40, AMD_UDMA_66 }, /* AMD-756/c4+ Viper */
+ { PCI_DEVICE_ID_AMD_VIPER_7409, 0x00, 0x40, AMD_UDMA_66 | AMD_BAD_SWDMA }, /* AMD-756 Viper */
+ { PCI_DEVICE_ID_AMD_COBRA_7401, 0x00, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA }, /* AMD-755 Cobra */
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x00, 0x50, AMD_UDMA_100 }, /* nVidia nForce */
+ { 0 }
};
static struct amd_ide_chip *amd_config;
@@ -119,8 +120,8 @@ static int amd_get_info(char *buffer, char **addr, off_t offset, int count)
amd_print("----------AMD BusMastering IDE Configuration----------------");
- amd_print("Driver Version: 2.7");
- amd_print("South Bridge: AMD-%s", amd_config->name);
+ amd_print("Driver Version: 2.8");
+ amd_print("South Bridge: %s", bmide_dev->name);
pci_read_config_byte(dev, PCI_REVISION_ID, &t);
amd_print("Revision: IDE %#x", t);
@@ -389,8 +390,8 @@ unsigned int __init pci_init_amd74xx(struct pci_dev *dev, const char *name)
*/
pci_read_config_byte(dev, PCI_REVISION_ID, &t);
- printk(KERN_INFO "AMD_IDE: AMD-%s (rev %02x) IDE %s controller on pci%s\n",
- amd_config->name, t, amd_dma[amd_config->flags & AMD_UDMA], dev->slot_name);
+ printk(KERN_INFO "AMD_IDE: %s (rev %02x) %s controller on pci%s\n",
+ dev->name, t, amd_dma[amd_config->flags & AMD_UDMA], dev->slot_name);
/*
* Register /proc/ide/amd74xx entry
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index f218a1916a17..5f598354bd6a 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -106,40 +106,51 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
return 0; /* lba_capacity value may be bad */
}
-static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block);
-static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block);
-static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block);
+static ide_startstop_t chs_do_request(ide_drive_t *drive, struct request *rq, unsigned long block);
+static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct request *rq, unsigned long block);
+static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct request *rq, unsigned long long block);
/*
- * do_rw_disk() issues READ and WRITE commands to a disk,
- * using LBA if supported, or CHS otherwise, to address sectors.
- * It also takes care of issuing special DRIVE_CMDs.
+ * Issue a READ or WRITE command to a disk, using LBA if supported, or CHS
+ * otherwise, to address sectors. It also takes care of issuing special
+ * DRIVE_CMDs.
*/
-static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t idedisk_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
{
- if (drive->blocked)
- panic("ide: Request while drive blocked? You don't like your data intact?");
+ /*
+ * Wait until all request have bin finished.
+ */
+
+ while (drive->blocked) {
+ yield();
+ // panic("ide: Request while drive blocked?");
+ }
+
if (!(rq->flags & REQ_CMD)) {
- blk_dump_rq_flags(rq, "do_rw_disk, bad command");
+ blk_dump_rq_flags(rq, "idedisk_do_request - bad command");
ide_end_request(drive, 0);
return ide_stopped;
}
if (IS_PDC4030_DRIVE) {
extern ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long);
+
return promise_rw_disk(drive, rq, block);
}
- if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) /* 48-bit LBA */
- return lba_48_rw_disk(drive, rq, block);
- if (drive->select.b.lba) /* 28-bit LBA */
- return lba_28_rw_disk(drive, rq, block);
+ /* 48-bit LBA */
+ if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing))
+ return lba48_do_request(drive, rq, block);
+
+ /* 28-bit LBA */
+ if (drive->select.b.lba)
+ return lba28_do_request(drive, rq, block);
- /* 28-bit CHS : DIE DIE DIE piece of legacy crap!!! */
- return chs_rw_disk(drive, rq, block);
+ /* 28-bit CHS */
+ return chs_do_request(drive, rq, block);
}
-static task_ioreg_t get_command (ide_drive_t *drive, int cmd)
+static task_ioreg_t get_command(ide_drive_t *drive, int cmd)
{
int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
@@ -147,23 +158,25 @@ static task_ioreg_t get_command (ide_drive_t *drive, int cmd)
lba48bit = drive->addressing;
#endif
- if ((cmd == READ) && (drive->using_dma))
- return (lba48bit) ? WIN_READDMA_EXT : WIN_READDMA;
- else if ((cmd == READ) && (drive->mult_count))
- return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD;
- else if (cmd == READ)
- return (lba48bit) ? WIN_READ_EXT : WIN_READ;
- else if ((cmd == WRITE) && (drive->using_dma))
- return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
- else if ((cmd == WRITE) && (drive->mult_count))
- return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
- else if (cmd == WRITE)
- return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE;
- else
- return WIN_NOP;
+ if (cmd == READ) {
+ if (drive->using_dma)
+ return (lba48bit) ? WIN_READDMA_EXT : WIN_READDMA;
+ else if (drive->mult_count)
+ return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD;
+ else
+ return (lba48bit) ? WIN_READ_EXT : WIN_READ;
+ } else if (cmd == WRITE) {
+ if (drive->using_dma)
+ return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
+ else if (drive->mult_count)
+ return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
+ else
+ return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE;
+ }
+ return WIN_NOP;
}
-static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t chs_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
{
struct hd_drive_task_hdr taskfile;
struct hd_drive_hob_hdr hobfile;
@@ -203,19 +216,15 @@ static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsi
memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
- args.command_type = ide_cmd_type_parser(&args);
- args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile);
- args.handler = ide_handler_parser(&taskfile, &hobfile);
- args.posthandler = NULL;
- args.rq = (struct request *) rq;
- args.block = block;
- rq->special = NULL;
- rq->special = (ide_task_t *)&args;
+ ide_cmd_type_parser(&args);
+ args.rq = rq;
+ args.block = block;
+ rq->special = &args;
return do_rw_taskfile(drive, &args);
}
-static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
{
struct hd_drive_task_hdr taskfile;
struct hd_drive_hob_hdr hobfile;
@@ -250,14 +259,10 @@ static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, u
memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
- args.command_type = ide_cmd_type_parser(&args);
- args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile);
- args.handler = ide_handler_parser(&taskfile, &hobfile);
- args.posthandler = NULL;
- args.rq = (struct request *) rq;
- args.block = block;
- rq->special = NULL;
- rq->special = (ide_task_t *)&args;
+ ide_cmd_type_parser(&args);
+ args.rq = rq;
+ args.block = block;
+ rq->special = &args;
return do_rw_taskfile(drive, &args);
}
@@ -268,7 +273,7 @@ static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, u
* 1073741822 == 549756 MB or 48bit addressing fake drive
*/
-static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block)
+static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct request *rq, unsigned long long block)
{
struct hd_drive_task_hdr taskfile;
struct hd_drive_hob_hdr hobfile;
@@ -314,13 +319,10 @@ static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, u
memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
- args.command_type = ide_cmd_type_parser(&args);
- args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile);
- args.handler = ide_handler_parser(&taskfile, &hobfile);
- args.posthandler = NULL;
- args.rq = (struct request *) rq;
- args.block = block;
- rq->special = (ide_task_t *)&args;
+ ide_cmd_type_parser(&args);
+ args.rq = rq;
+ args.block = block;
+ rq->special = &args;
return do_rw_taskfile(drive, &args);
}
@@ -637,9 +639,9 @@ static ide_startstop_t idedisk_special (ide_drive_t *drive)
taskfile.high_cylinder = drive->cyl>>8;
taskfile.device_head = ((drive->head-1)|drive->select.all)&0xBF;
if (!IS_PDC4030_DRIVE) {
- taskfile.sector_count = drive->sect;
- taskfile.command = WIN_SPECIFY;
- handler = ide_handler_parser(&taskfile, &hobfile);
+ taskfile.sector_count = drive->sect;
+ taskfile.command = WIN_SPECIFY;
+ handler = set_geometry_intr;;
}
do_taskfile(drive, &taskfile, &hobfile, handler);
} else if (s->b.recalibrate) {
@@ -651,7 +653,7 @@ static ide_startstop_t idedisk_special (ide_drive_t *drive)
memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
taskfile.sector_count = drive->sect;
taskfile.command = WIN_RESTORE;
- do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));
+ do_taskfile(drive, &taskfile, &hobfile, recal_intr);
}
} else if (s->b.set_multmode) {
s->b.set_multmode = 0;
@@ -1089,7 +1091,7 @@ static struct ata_operations idedisk_driver = {
owner: THIS_MODULE,
cleanup: idedisk_cleanup,
standby: idedisk_standby,
- do_request: do_rw_disk,
+ do_request: idedisk_do_request,
end_request: NULL,
ioctl: NULL,
open: idedisk_open,
@@ -1127,7 +1129,7 @@ int idedisk_init (void)
{
ide_drive_t *drive;
int failed = 0;
-
+
MOD_INC_USE_COUNT;
while ((drive = ide_scan_devices(ATA_DISK, "ide-disk", NULL, failed++)) != NULL) {
if (ide_register_subdriver (drive, &idedisk_driver)) {
diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c
index a1f65de568f5..d8c32aca8a7b 100644
--- a/drivers/ide/ide-pci.c
+++ b/drivers/ide/ide-pci.c
@@ -119,6 +119,7 @@ extern void ide_init_pdc202xx(ide_hwif_t *);
extern unsigned int pci_init_piix(struct pci_dev *);
extern unsigned int ata66_piix(ide_hwif_t *);
extern void ide_init_piix(ide_hwif_t *);
+extern void ide_dmacapable_piix(ide_hwif_t *, unsigned long);
#endif
#ifdef CONFIG_BLK_DEV_IT8172
@@ -142,12 +143,6 @@ extern unsigned int ata66_sis5513(ide_hwif_t *);
extern void ide_init_sis5513(ide_hwif_t *);
#endif
-#ifdef CONFIG_BLK_DEV_SLC90E66
-extern unsigned int pci_init_slc90e66(struct pci_dev *);
-extern unsigned int ata66_slc90e66(ide_hwif_t *);
-extern void ide_init_slc90e66(ide_hwif_t *);
-#endif
-
#ifdef CONFIG_BLK_DEV_SL82C105
extern unsigned int pci_init_sl82c105(struct pci_dev *);
extern void dma_init_sl82c105(ide_hwif_t *, unsigned long);
@@ -197,19 +192,18 @@ typedef struct ide_pci_device_s {
static ide_pci_device_t pci_chipsets[] __initdata = {
#ifdef CONFIG_BLK_DEV_PIIX
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, NULL, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, NULL, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, NULL, NULL, ide_init_piix, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0, ATA_F_NODMA },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, ATA_F_NOADMA },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
#endif
#ifdef CONFIG_BLK_DEV_VIA82CXXX
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, pci_init_via82cxxx, ata66_via82cxxx, ide_init_via82cxxx, ide_dmacapable_via82cxxx, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0, ATA_F_NOADMA },
@@ -289,13 +283,11 @@ static ide_pci_device_t pci_chipsets[] __initdata = {
{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0, 0 },
{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0, 0 },
{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x50,0x01,0x01}, {0x50,0x02,0x02}}, ON_BOARD, 0, 0 },
#endif
#ifdef CONFIG_BLK_DEV_PDC_ADMA
{PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_1841, pci_init_pdcadma, ata66_pdcadma, ide_init_pdcadma, ide_dmacapable_pdcadma, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_NODMA },
#endif
-#ifdef CONFIG_BLK_DEV_SLC90E66
- {PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, pci_init_slc90e66, ata66_slc90e66, ide_init_slc90e66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
-#endif
#ifdef CONFIG_BLK_DEV_SVWKS
{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, pci_init_svwks, ata66_svwks, ide_init_svwks, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_DMA },
{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, pci_init_svwks, ata66_svwks, ide_init_svwks, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
@@ -311,6 +303,7 @@ static ide_pci_device_t pci_chipsets[] __initdata = {
{PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0, 0 },
{PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
{PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, NULL, NULL, NULL, NULL, {{0x6D,0x80,0x80}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_NODMA },
{PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_FIXIRQ },
{PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_FIXIRQ },
{PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_FIXIRQ },
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 0891bcc1e2c4..83f517e2ae5c 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -118,10 +118,6 @@ int (*svwks_display_info)(char *, char **, off_t, int) = NULL;
extern byte sis_proc;
int (*sis_display_info)(char *, char **, off_t, int) = NULL;
#endif /* CONFIG_BLK_DEV_SIS5513 */
-#ifdef CONFIG_BLK_DEV_SLC90E66
-extern byte slc90e66_proc;
-int (*slc90e66_display_info)(char *, char **, off_t, int) = NULL;
-#endif /* CONFIG_BLK_DEV_SLC90E66 */
#ifdef CONFIG_BLK_DEV_VIA82CXXX
extern byte via_proc;
int (*via_display_info)(char *, char **, off_t, int) = NULL;
@@ -593,10 +589,6 @@ void proc_ide_create(void)
if ((sis_display_info) && (sis_proc))
create_proc_info_entry("sis", 0, proc_ide_root, sis_display_info);
#endif /* CONFIG_BLK_DEV_SIS5513 */
-#ifdef CONFIG_BLK_DEV_SLC90E66
- if ((slc90e66_display_info) && (slc90e66_proc))
- create_proc_info_entry("slc90e66", 0, proc_ide_root, slc90e66_display_info);
-#endif /* CONFIG_BLK_DEV_SLC90E66 */
#ifdef CONFIG_BLK_DEV_VIA82CXXX
if ((via_display_info) && (via_proc))
create_proc_info_entry("via", 0, proc_ide_root, via_display_info);
@@ -653,10 +645,6 @@ void proc_ide_destroy(void)
if ((sis_display_info) && (sis_proc))
remove_proc_entry("ide/sis", 0);
#endif /* CONFIG_BLK_DEV_SIS5513 */
-#ifdef CONFIG_BLK_DEV_SLC90E66
- if ((slc90e66_display_info) && (slc90e66_proc))
- remove_proc_entry("ide/slc90e66",0);
-#endif /* CONFIG_BLK_DEV_SLC90E66 */
#ifdef CONFIG_BLK_DEV_VIA82CXXX
if ((via_display_info) && (via_proc))
remove_proc_entry("ide/via",0);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 138d5e7fdae7..29ccab91a897 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -38,6 +38,8 @@
#define DTF(x...)
#endif
+#define SUPPORT_VLB_SYNC 1
+
/*
* for now, taskfile requests are special :/
*/
@@ -56,7 +58,7 @@ static inline void ide_unmap_rq(struct request *rq, char *to,
bio_kunmap_irq(to, flags);
}
-static void ata_bswap_data (void *buffer, int wcount)
+static void bswap_data (void *buffer, int wcount)
{
u16 *p = buffer;
@@ -74,18 +76,20 @@ static void ata_bswap_data (void *buffer, int wcount)
* of the sector count register location, with interrupts disabled
* to ensure that the reads all happen together.
*/
-static inline void task_vlb_sync(ide_ioreg_t port)
+static inline void task_vlb_sync(ide_drive_t *drive)
{
- IN_BYTE (port);
- IN_BYTE (port);
- IN_BYTE (port);
+ ide_ioreg_t port = IDE_NSECTOR_REG;
+
+ IN_BYTE(port);
+ IN_BYTE(port);
+ IN_BYTE(port);
}
#endif
/*
* This is used for most PIO data transfers *from* the IDE interface
*/
-void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+void ata_input_data(ide_drive_t *drive, void *buffer, unsigned int wcount)
{
byte io_32bit;
@@ -107,7 +111,7 @@ void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
unsigned long flags;
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
- task_vlb_sync(IDE_NSECTOR_REG);
+ task_vlb_sync(drive);
insl(IDE_DATA_REG, buffer, wcount);
__restore_flags(flags); /* local CPU only */
} else
@@ -130,7 +134,7 @@ void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
/*
* This is used for most PIO data transfers *to* the IDE interface
*/
-void ata_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+void ata_output_data(ide_drive_t *drive, void *buffer, unsigned int wcount)
{
byte io_32bit;
@@ -147,7 +151,7 @@ void ata_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
unsigned long flags;
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
- task_vlb_sync(IDE_NSECTOR_REG);
+ task_vlb_sync(drive);
outsl(IDE_DATA_REG, buffer, wcount);
__restore_flags(flags); /* local CPU only */
} else
@@ -188,7 +192,7 @@ void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount
insw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
return;
}
-#endif /* CONFIG_ATARI */
+#endif
ata_input_data (drive, buffer, bytecount / 4);
if ((bytecount & 0x03) >= 2)
insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
@@ -208,25 +212,25 @@ void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecoun
outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
return;
}
-#endif /* CONFIG_ATARI */
+#endif
ata_output_data (drive, buffer, bytecount / 4);
if ((bytecount & 0x03) >= 2)
- outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
+ outsw(IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
}
-void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+void taskfile_input_data(ide_drive_t *drive, void *buffer, unsigned int wcount)
{
ata_input_data(drive, buffer, wcount);
if (drive->bswap)
- ata_bswap_data(buffer, wcount);
+ bswap_data(buffer, wcount);
}
-void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+void taskfile_output_data(ide_drive_t *drive, void *buffer, unsigned int wcount)
{
if (drive->bswap) {
- ata_bswap_data(buffer, wcount);
+ bswap_data(buffer, wcount);
ata_output_data(drive, buffer, wcount);
- ata_bswap_data(buffer, wcount);
+ bswap_data(buffer, wcount);
} else {
ata_output_data(drive, buffer, wcount);
}
@@ -235,7 +239,7 @@ void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount
/*
* Needed for PCI irq sharing
*/
-int drive_is_ready (ide_drive_t *drive)
+int drive_is_ready(ide_drive_t *drive)
{
byte stat = 0;
if (drive->waiting_for_dma)
@@ -255,7 +259,7 @@ int drive_is_ready (ide_drive_t *drive)
if (IDE_CONTROL_REG)
stat = GET_ALTSTAT();
else
-#endif /* CONFIG_IDEPCI_SHARE_IRQ */
+#endif
stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */
if (stat & BUSY_STAT)
@@ -291,7 +295,7 @@ static ide_startstop_t bio_mulout_intr(ide_drive_t *drive);
* Called directly from execute_drive_cmd for the first bunch of sectors,
* afterwards only by the ISR
*/
-static ide_startstop_t task_mulout_intr (ide_drive_t *drive)
+static ide_startstop_t task_mulout_intr(ide_drive_t *drive)
{
unsigned int msect, nsect;
byte stat = GET_STAT();
@@ -314,6 +318,7 @@ static ide_startstop_t task_mulout_intr (ide_drive_t *drive)
* necessary
*/
ide_end_request(drive, 1);
+
return ide_stopped;
}
@@ -341,13 +346,14 @@ static ide_startstop_t task_mulout_intr (ide_drive_t *drive)
ide_unmap_rq(rq, pBuf, &flags);
drive->io_32bit = io_32bit;
rq->errors = 0;
+ /* Are we sure that this as all been already transfered? */
rq->current_nr_sectors -= nsect;
if (hwgroup->handler == NULL)
ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
return ide_started;
}
-ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ide_startstop_t do_rw_taskfile(ide_drive_t *drive, ide_task_t *task)
{
task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
@@ -399,7 +405,9 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
return ide_started;
}
-void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, ide_handler_t *handler)
+void do_taskfile(ide_drive_t *drive, struct hd_drive_task_hdr *taskfile,
+ struct hd_drive_hob_hdr *hobfile,
+ ide_handler_t *handler)
{
struct hd_driveid *id = drive->id;
byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
@@ -440,10 +448,6 @@ void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct
}
/*
- * Handler for special commands without a data phase from ide-disk
- */
-
-/*
* This is invoked on completion of a WIN_SETMULT cmd.
*/
ide_startstop_t set_multmode_intr (ide_drive_t *drive)
@@ -463,7 +467,7 @@ ide_startstop_t set_multmode_intr (ide_drive_t *drive)
/*
* This is invoked on completion of a WIN_SPECIFY cmd.
*/
-static ide_startstop_t set_geometry_intr (ide_drive_t *drive)
+ide_startstop_t set_geometry_intr (ide_drive_t *drive)
{
byte stat;
@@ -480,7 +484,7 @@ static ide_startstop_t set_geometry_intr (ide_drive_t *drive)
/*
* This is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
*/
-static ide_startstop_t recal_intr (ide_drive_t *drive)
+ide_startstop_t recal_intr(ide_drive_t *drive)
{
byte stat = GET_STAT();
@@ -713,37 +717,6 @@ static ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
return ide_started;
}
-/* Called by internal to feature out type of command being called */
-ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
-{
- switch(taskfile->command) {
- /* IDE_DRIVE_TASK_RAW_WRITE */
- /* IDE_DRIVE_TASK_OUT */
- case WIN_WRITE:
- case WIN_WRITE_EXT:
- case WIN_WRITE_VERIFY:
- case WIN_WRITE_BUFFER:
- case CFA_WRITE_SECT_WO_ERASE:
- case WIN_DOWNLOAD_MICROCODE:
- return &pre_task_out_intr;
- case CFA_WRITE_MULTI_WO_ERASE:
- case WIN_MULTWRITE:
- case WIN_MULTWRITE_EXT:
- return &pre_bio_out_intr;
- case WIN_SMART:
- if (taskfile->feature == SMART_WRITE_LOG_SECTOR)
- return &pre_task_out_intr;
- case WIN_WRITEDMA:
- case WIN_WRITEDMA_QUEUED:
- case WIN_WRITEDMA_EXT:
- case WIN_WRITEDMA_QUEUED_EXT:
- /* IDE_DRIVE_TASK_OUT */
- default:
- break;
- }
- return(NULL);
-}
-
/*
* Handler for command with Read Multiple
*/
@@ -798,154 +771,85 @@ static ide_startstop_t task_mulin_intr(ide_drive_t *drive)
return ide_started;
}
-/* Called by internal to feature out type of command being called */
-ide_handler_t * ide_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
-{
- switch(taskfile->command) {
- case WIN_IDENTIFY:
- case WIN_PIDENTIFY:
- case CFA_TRANSLATE_SECTOR:
- case WIN_READ_BUFFER:
- case WIN_READ:
- case WIN_READ_EXT:
- return &task_in_intr;
- case WIN_SECURITY_DISABLE:
- case WIN_SECURITY_ERASE_UNIT:
- case WIN_SECURITY_SET_PASS:
- case WIN_SECURITY_UNLOCK:
- case WIN_DOWNLOAD_MICROCODE:
- case CFA_WRITE_SECT_WO_ERASE:
- case WIN_WRITE_BUFFER:
- case WIN_WRITE_VERIFY:
- case WIN_WRITE:
- case WIN_WRITE_EXT:
- return &task_out_intr;
- case WIN_MULTREAD:
- case WIN_MULTREAD_EXT:
- return &task_mulin_intr;
- case CFA_WRITE_MULTI_WO_ERASE:
- case WIN_MULTWRITE:
- case WIN_MULTWRITE_EXT:
- return &bio_mulout_intr;
- case WIN_SMART:
- switch(taskfile->feature) {
- case SMART_READ_VALUES:
- case SMART_READ_THRESHOLDS:
- case SMART_READ_LOG_SECTOR:
- return &task_in_intr;
- case SMART_WRITE_LOG_SECTOR:
- return &task_out_intr;
- default:
- return &task_no_data_intr;
- }
- case CFA_REQ_EXT_ERROR_CODE:
- case CFA_ERASE_SECTORS:
- case WIN_VERIFY:
- case WIN_VERIFY_EXT:
- case WIN_SEEK:
- return &task_no_data_intr;
- case WIN_SPECIFY:
- return &set_geometry_intr;
- case WIN_RESTORE:
- return &recal_intr;
- case WIN_DIAGNOSE:
- case WIN_FLUSH_CACHE:
- case WIN_FLUSH_CACHE_EXT:
- case WIN_STANDBYNOW1:
- case WIN_STANDBYNOW2:
- case WIN_SLEEPNOW1:
- case WIN_SLEEPNOW2:
- case WIN_SETIDLE1:
- case WIN_CHECKPOWERMODE1:
- case WIN_CHECKPOWERMODE2:
- case WIN_GETMEDIASTATUS:
- case WIN_MEDIAEJECT:
- return &task_no_data_intr;
- case WIN_SETMULT:
- return &set_multmode_intr;
- case WIN_READ_NATIVE_MAX:
- case WIN_SET_MAX:
- case WIN_READ_NATIVE_MAX_EXT:
- case WIN_SET_MAX_EXT:
- case WIN_SECURITY_ERASE_PREPARE:
- case WIN_SECURITY_FREEZE_LOCK:
- case WIN_DOORLOCK:
- case WIN_DOORUNLOCK:
- case WIN_SETFEATURES:
- return &task_no_data_intr;
- case DISABLE_SEAGATE:
- case EXABYTE_ENABLE_NEST:
- return &task_no_data_intr;
-#ifdef CONFIG_BLK_DEV_IDEDMA
- case WIN_READDMA:
- case WIN_IDENTIFY_DMA:
- case WIN_READDMA_QUEUED:
- case WIN_READDMA_EXT:
- case WIN_READDMA_QUEUED_EXT:
- case WIN_WRITEDMA:
- case WIN_WRITEDMA_QUEUED:
- case WIN_WRITEDMA_EXT:
- case WIN_WRITEDMA_QUEUED_EXT:
-#endif
- case WIN_FORMAT:
- case WIN_INIT:
- case WIN_DEVICE_RESET:
- case WIN_QUEUED_SERVICE:
- case WIN_PACKETCMD:
- default:
- return NULL;
- }
-}
-
/* Called by ioctl to feature out type of command being called */
-int ide_cmd_type_parser (ide_task_t *args)
+void ide_cmd_type_parser(ide_task_t *args)
{
struct hd_drive_task_hdr *taskfile = (struct hd_drive_task_hdr *) args->tfRegister;
- struct hd_drive_hob_hdr *hobfile = (struct hd_drive_hob_hdr *) args->hobRegister;
- args->prehandler = ide_pre_handler_parser(taskfile, hobfile);
- args->handler = ide_handler_parser(taskfile, hobfile);
+ args->prehandler = NULL;
+ args->handler = NULL;
switch(args->tfRegister[IDE_COMMAND_OFFSET]) {
case WIN_IDENTIFY:
case WIN_PIDENTIFY:
- return IDE_DRIVE_TASK_IN;
+ args->handler = task_in_intr;
+ args->command_type = IDE_DRIVE_TASK_IN;
+ return;
+
case CFA_TRANSLATE_SECTOR:
case WIN_READ:
case WIN_READ_EXT:
case WIN_READ_BUFFER:
- return IDE_DRIVE_TASK_IN;
+ args->handler = task_in_intr;
+ args->command_type = IDE_DRIVE_TASK_IN;
+ return;
+
case WIN_WRITE:
case WIN_WRITE_EXT:
case WIN_WRITE_VERIFY:
case WIN_WRITE_BUFFER:
case CFA_WRITE_SECT_WO_ERASE:
case WIN_DOWNLOAD_MICROCODE:
- return IDE_DRIVE_TASK_RAW_WRITE;
+ args->prehandler = pre_task_out_intr;
+ args->handler = task_out_intr;
+ args->command_type = IDE_DRIVE_TASK_RAW_WRITE;
+ return;
+
case WIN_MULTREAD:
case WIN_MULTREAD_EXT:
- return IDE_DRIVE_TASK_IN;
+ args->handler = task_mulin_intr;
+ args->command_type = IDE_DRIVE_TASK_IN;
+ return;
+
case CFA_WRITE_MULTI_WO_ERASE:
case WIN_MULTWRITE:
case WIN_MULTWRITE_EXT:
- return IDE_DRIVE_TASK_RAW_WRITE;
+ args->prehandler = pre_bio_out_intr;
+ args->handler = bio_mulout_intr;
+ args->command_type = IDE_DRIVE_TASK_RAW_WRITE;
+ return;
+
case WIN_SECURITY_DISABLE:
case WIN_SECURITY_ERASE_UNIT:
case WIN_SECURITY_SET_PASS:
case WIN_SECURITY_UNLOCK:
- return IDE_DRIVE_TASK_OUT;
+ args->handler = task_out_intr;
+ args->command_type = IDE_DRIVE_TASK_OUT;
+ return;
+
case WIN_SMART:
+ if (taskfile->feature == SMART_WRITE_LOG_SECTOR)
+ args->prehandler = pre_task_out_intr;
args->tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
args->tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
case SMART_READ_VALUES:
case SMART_READ_THRESHOLDS:
case SMART_READ_LOG_SECTOR:
- return IDE_DRIVE_TASK_IN;
+ args->handler = task_in_intr;
+ args->command_type = IDE_DRIVE_TASK_IN;
+ return;
+
case SMART_WRITE_LOG_SECTOR:
- return IDE_DRIVE_TASK_OUT;
+ args->handler = task_out_intr;
+ args->command_type = IDE_DRIVE_TASK_OUT;
+ return;
+
default:
- return IDE_DRIVE_TASK_NO_DATA;
+ args->handler = task_no_data_intr;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ return;
+
}
#ifdef CONFIG_BLK_DEV_IDEDMA
case WIN_READDMA:
@@ -953,17 +857,23 @@ int ide_cmd_type_parser (ide_task_t *args)
case WIN_READDMA_QUEUED:
case WIN_READDMA_EXT:
case WIN_READDMA_QUEUED_EXT:
- return IDE_DRIVE_TASK_IN;
+ args->command_type = IDE_DRIVE_TASK_IN;
+ return;
+
case WIN_WRITEDMA:
case WIN_WRITEDMA_QUEUED:
case WIN_WRITEDMA_EXT:
case WIN_WRITEDMA_QUEUED_EXT:
- return IDE_DRIVE_TASK_RAW_WRITE;
+ args->command_type = IDE_DRIVE_TASK_RAW_WRITE;
+ return;
+
#endif
case WIN_SETFEATURES:
+ args->handler = task_no_data_intr;
switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
case SETFEATURES_XFER:
- return IDE_DRIVE_TASK_SET_XFER;
+ args->command_type = IDE_DRIVE_TASK_SET_XFER;
+ return;
case SETFEATURES_DIS_DEFECT:
case SETFEATURES_EN_APM:
case SETFEATURES_DIS_MSN:
@@ -980,16 +890,20 @@ int ide_cmd_type_parser (ide_task_t *args)
case SETFEATURES_DIS_RI:
case SETFEATURES_DIS_SI:
default:
- return IDE_DRIVE_TASK_NO_DATA;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ return;
}
- case WIN_NOP:
- case CFA_REQ_EXT_ERROR_CODE:
- case CFA_ERASE_SECTORS:
- case WIN_VERIFY:
- case WIN_VERIFY_EXT:
- case WIN_SEEK:
+
case WIN_SPECIFY:
+ args->handler = set_geometry_intr;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ return;
+
case WIN_RESTORE:
+ args->handler = recal_intr;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ return;
+
case WIN_DIAGNOSE:
case WIN_FLUSH_CACHE:
case WIN_FLUSH_CACHE_EXT:
@@ -998,29 +912,48 @@ int ide_cmd_type_parser (ide_task_t *args)
case WIN_SLEEPNOW1:
case WIN_SLEEPNOW2:
case WIN_SETIDLE1:
- case DISABLE_SEAGATE:
case WIN_CHECKPOWERMODE1:
case WIN_CHECKPOWERMODE2:
case WIN_GETMEDIASTATUS:
case WIN_MEDIAEJECT:
- case WIN_SETMULT:
+ case CFA_REQ_EXT_ERROR_CODE:
+ case CFA_ERASE_SECTORS:
+ case WIN_VERIFY:
+ case WIN_VERIFY_EXT:
+ case WIN_SEEK:
case WIN_READ_NATIVE_MAX:
case WIN_SET_MAX:
case WIN_READ_NATIVE_MAX_EXT:
case WIN_SET_MAX_EXT:
case WIN_SECURITY_ERASE_PREPARE:
case WIN_SECURITY_FREEZE_LOCK:
- case EXABYTE_ENABLE_NEST:
case WIN_DOORLOCK:
case WIN_DOORUNLOCK:
- return IDE_DRIVE_TASK_NO_DATA;
+ case DISABLE_SEAGATE:
+ case EXABYTE_ENABLE_NEST:
+
+ args->handler = task_no_data_intr;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ return;
+
+ case WIN_SETMULT:
+ args->handler = set_multmode_intr;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ return;
+
+ case WIN_NOP:
+
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ return;
+
case WIN_FORMAT:
case WIN_INIT:
case WIN_DEVICE_RESET:
case WIN_QUEUED_SERVICE:
case WIN_PACKETCMD:
default:
- return IDE_DRIVE_TASK_INVALID;
+ args->command_type = IDE_DRIVE_TASK_INVALID;
+ return;
}
}
@@ -1067,7 +1000,7 @@ int ide_wait_taskfile(ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, st
ide_init_drive_taskfile(&rq);
/* This is kept for internal use only !!! */
- args.command_type = ide_cmd_type_parser (&args);
+ ide_cmd_type_parser(&args);
if (args.command_type != IDE_DRIVE_TASK_NO_DATA)
rq.current_nr_sectors = rq.nr_sectors = (hobfile->sector_count << 8) | taskfile->sector_count;
@@ -1232,14 +1165,13 @@ EXPORT_SYMBOL(taskfile_output_data);
EXPORT_SYMBOL(do_rw_taskfile);
EXPORT_SYMBOL(do_taskfile);
+EXPORT_SYMBOL(recal_intr);
+EXPORT_SYMBOL(set_geometry_intr);
EXPORT_SYMBOL(set_multmode_intr);
-
EXPORT_SYMBOL(task_no_data_intr);
EXPORT_SYMBOL(ide_wait_taskfile);
EXPORT_SYMBOL(ide_raw_taskfile);
-EXPORT_SYMBOL(ide_pre_handler_parser);
-EXPORT_SYMBOL(ide_handler_parser);
EXPORT_SYMBOL(ide_cmd_type_parser);
EXPORT_SYMBOL(ide_cmd_ioctl);
EXPORT_SYMBOL(ide_task_ioctl);
diff --git a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c
index 16758e96f042..04e6ad2871bd 100644
--- a/drivers/ide/pdc4030.c
+++ b/drivers/ide/pdc4030.c
@@ -654,14 +654,14 @@ ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigne
memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
memcpy(args.hobRegister, NULL, sizeof(struct hd_drive_hob_hdr));
- args.command_type = ide_cmd_type_parser(&args);
+ ide_cmd_type_parser(&args);
+ /* We don't use the generic inerrupt handlers here? */
args.prehandler = NULL;
args.handler = NULL;
- args.posthandler = NULL;
- args.rq = (struct request *) rq;
+ args.rq = rq;
args.block = block;
rq->special = NULL;
- rq->special = (ide_task_t *)&args;
+ rq->special = &args;
return do_pdc4030_io(drive, &args);
}
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index de7f2e74d32e..384ea0b2380a 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -1,499 +1,578 @@
/*
- * linux/drivers/ide/piix.c Version 0.32 June 9, 2000
+ * $Id: piix.c,v 1.2 2002/03/13 22:50:43 vojtech Exp $
*
- * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
- * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * May be copied or modified under the terms of the GNU General Public License
+ * Copyright (c) 2000-2002 Vojtech Pavlik
*
- * PIO mode setting function for Intel chipsets.
- * For use instead of BIOS settings.
+ * Based on the work of:
+ * Andrzej Krzysztofowicz
+ * Andre Hedrick
*
- * 40-41
- * 42-43
- *
- * 41
- * 43
- *
- * | PIO 0 | c0 | 80 | 0 | piix_tune_drive(drive, 0);
- * | PIO 2 | SW2 | d0 | 90 | 4 | piix_tune_drive(drive, 2);
- * | PIO 3 | MW1 | e1 | a1 | 9 | piix_tune_drive(drive, 3);
- * | PIO 4 | MW2 | e3 | a3 | b | piix_tune_drive(drive, 4);
- *
- * sitre = word40 & 0x4000; primary
- * sitre = word42 & 0x4000; secondary
- *
- * 44 8421|8421 hdd|hdb
- *
- * 48 8421 hdd|hdc|hdb|hda udma enabled
- *
- * 0001 hda
- * 0010 hdb
- * 0100 hdc
- * 1000 hdd
- *
- * 4a 84|21 hdb|hda
- * 4b 84|21 hdd|hdc
+ * Thanks to Daniela Egbert for advice on PIIX bugs.
+ */
+
+/*
+ * Intel PIIX/ICH and Efar Victory66 IDE driver for Linux.
*
- * ata-33/82371AB
- * ata-33/82371EB
- * ata-33/82801AB ata-66/82801AA
- * 00|00 udma 0 00|00 reserved
- * 01|01 udma 1 01|01 udma 3
- * 10|10 udma 2 10|10 udma 4
- * 11|11 reserved 11|11 reserved
+ * UDMA66 and higher modes are autoenabled only in case the BIOS has detected a
+ * 80 wire cable. To ignore the BIOS data and assume the cable is present, use
+ * 'ide0=ata66' or 'ide1=ata66' on the kernel command line.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * 54 8421|8421 ata66 drive|ata66 enable
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, &reg48);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, &reg54);
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/config.h>
-#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
+#include <linux/blkdev.h>
#include <linux/pci.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
-#include <linux/delay.h>
#include <linux/init.h>
-
+#include <linux/ide.h>
#include <asm/io.h>
#include "ata-timing.h"
-#define PIIX_DEBUG_DRIVE_INFO 0
+#define PIIX_IDETIM0 0x40
+#define PIIX_IDETIM1 0x42
+#define PIIX_SIDETIM 0x44
+#define PIIX_IDESTAT 0x47
+#define PIIX_UDMACTL 0x48
+#define PIIX_UDMATIM 0x4a
+#define PIIX_IDECFG 0x54
+
+#define PIIX_UDMA 0x07
+#define PIIX_UDMA_NONE 0x00
+#define PIIX_UDMA_33 0x01
+#define PIIX_UDMA_66 0x02
+#define PIIX_UDMA_V66 0x03
+#define PIIX_UDMA_100 0x04
+#define PIIX_NO_SITRE 0x08 /* Chip doesn't have separate slave timing */
+#define PIIX_PINGPONG 0x10 /* Enable ping-pong buffers */
+#define PIIX_VICTORY 0x20 /* Efar Victory66 has a different UDMA setup */
+#define PIIX_CHECK_REV 0x40 /* May be a buggy revision of PIIX */
+#define PIIX_NODMA 0x80 /* Don't do DMA with this chip */
+
+/*
+ * Intel IDE chips
+ */
+
+static struct piix_ide_chip {
+ unsigned short id;
+ unsigned char flags;
+} piix_ide_chips[] = {
+ { PCI_DEVICE_ID_INTEL_82801CA_11, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801CA ICH3 */
+ { PCI_DEVICE_ID_INTEL_82801CA_10, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801CAM ICH3-M */
+ { PCI_DEVICE_ID_INTEL_82801BA_9, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801BA ICH2 */
+ { PCI_DEVICE_ID_INTEL_82801BA_8, PIIX_UDMA_100 | PIIX_PINGPONG }, /* Intel 82801BAM ICH2-M */
+ { PCI_DEVICE_ID_INTEL_82801AB_1, PIIX_UDMA_33 | PIIX_PINGPONG }, /* Intel 82801AB ICH0 */
+ { PCI_DEVICE_ID_INTEL_82801AA_1, PIIX_UDMA_66 | PIIX_PINGPONG }, /* Intel 82801AA ICH */
+ { PCI_DEVICE_ID_INTEL_82372FB_1, PIIX_UDMA_66 }, /* Intel 82372FB PIIX5 */
+ { PCI_DEVICE_ID_INTEL_82443MX_1, PIIX_UDMA_33 }, /* Intel 82443MX MPIIX4 */
+ { PCI_DEVICE_ID_INTEL_82371AB, PIIX_UDMA_33 }, /* Intel 82371AB/EB PIIX4/4E */
+ { PCI_DEVICE_ID_INTEL_82371SB_1, PIIX_UDMA_NONE }, /* Intel 82371SB PIIX3 */
+ { PCI_DEVICE_ID_INTEL_82371FB_1, PIIX_UDMA_NONE | PIIX_NO_SITRE | PIIX_CHECK_REV }, /* Intel 82371FB PIIX */
+ { PCI_DEVICE_ID_EFAR_SLC90E66_1, PIIX_UDMA_V66 | PIIX_VICTORY }, /* Efar Victory66 */
+ { 0 }
+};
+
+static struct piix_ide_chip *piix_config;
+static unsigned char piix_enabled;
+static unsigned int piix_80w;
+static unsigned int piix_clock;
+
+static char *piix_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA66", "UDMA100" };
+
+/*
+ * PIIX/ICH /proc entry.
+ */
-#define DISPLAY_PIIX_TIMINGS
+#ifdef CONFIG_PROC_FS
-#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
#include <linux/proc_fs.h>
-static int piix_get_info(char *, char **, off_t, int);
-extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+byte piix_proc;
+int piix_base;
static struct pci_dev *bmide_dev;
+extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+
+#define piix_print(format, arg...) p += sprintf(p, format "\n" , ## arg)
+#define piix_print_drive(name, format, arg...)\
+ p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n");
-static int piix_get_info (char *buffer, char **addr, off_t offset, int count)
+static int piix_get_info(char *buffer, char **addr, off_t offset, int count)
{
+ int speed[4], cycle[4], active[4], recover[4], dmaen[4], uen[4], udma[4], umul;
+ struct pci_dev *dev = bmide_dev;
+ unsigned int i, u;
+ unsigned short c, d, e;
+ unsigned char t;
char *p = buffer;
- u32 bibma = pci_resource_start(bmide_dev, 4);
- u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
- u8 c0 = 0, c1 = 0;
- u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0;
-
- if (bmide_dev->device == PCI_DEVICE_ID_INTEL_82371MX) {
- p += sprintf(p, "\n Intel MPIIX Chipset.\n");
- return p-buffer; /* => must be less than 4k! */
- }
- pci_read_config_word(bmide_dev, 0x40, &reg40);
- pci_read_config_word(bmide_dev, 0x42, &reg42);
- pci_read_config_byte(bmide_dev, 0x44, &reg44);
- pci_read_config_byte(bmide_dev, 0x48, &reg48);
- pci_read_config_byte(bmide_dev, 0x4a, &reg4a);
- pci_read_config_byte(bmide_dev, 0x4b, &reg4b);
- pci_read_config_byte(bmide_dev, 0x54, &reg54);
- pci_read_config_byte(bmide_dev, 0x55, &reg55);
-
- psitre = (reg40 & 0x4000) ? 1 : 0;
- ssitre = (reg42 & 0x4000) ? 1 : 0;
-
- /*
- * at that point bibma+0x2 et bibma+0xa are byte registers
- * to investigate:
- */
- c0 = inb_p((unsigned short)bibma + 0x02);
- c1 = inb_p((unsigned short)bibma + 0x0a);
-
- p += sprintf(p, "\n %s Chipset.\n", bmide_dev->name);
- p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
- p += sprintf(p, " %sabled %sabled\n",
- (c0&0x80) ? "dis" : " en",
- (c1&0x80) ? "dis" : " en");
- p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
- p += sprintf(p, "DMA enabled: %s %s %s %s\n",
- (c0&0x20) ? "yes" : "no ",
- (c0&0x40) ? "yes" : "no ",
- (c1&0x20) ? "yes" : "no ",
- (c1&0x40) ? "yes" : "no " );
- p += sprintf(p, "UDMA enabled: %s %s %s %s\n",
- (reg48&0x01) ? "yes" : "no ",
- (reg48&0x02) ? "yes" : "no ",
- (reg48&0x04) ? "yes" : "no ",
- (reg48&0x08) ? "yes" : "no " );
- p += sprintf(p, "UDMA enabled: %s %s %s %s\n",
- ((reg54&0x11) && (reg55&0x10) && (reg4a&0x01)) ? "5" :
- ((reg54&0x11) && (reg4a&0x02)) ? "4" :
- ((reg54&0x11) && (reg4a&0x01)) ? "3" :
- (reg4a&0x02) ? "2" :
- (reg4a&0x01) ? "1" :
- (reg4a&0x00) ? "0" : "X",
- ((reg54&0x22) && (reg55&0x20) && (reg4a&0x10)) ? "5" :
- ((reg54&0x22) && (reg4a&0x20)) ? "4" :
- ((reg54&0x22) && (reg4a&0x10)) ? "3" :
- (reg4a&0x20) ? "2" :
- (reg4a&0x10) ? "1" :
- (reg4a&0x00) ? "0" : "X",
- ((reg54&0x44) && (reg55&0x40) && (reg4b&0x03)) ? "5" :
- ((reg54&0x44) && (reg4b&0x02)) ? "4" :
- ((reg54&0x44) && (reg4b&0x01)) ? "3" :
- (reg4b&0x02) ? "2" :
- (reg4b&0x01) ? "1" :
- (reg4b&0x00) ? "0" : "X",
- ((reg54&0x88) && (reg55&0x80) && (reg4b&0x30)) ? "5" :
- ((reg54&0x88) && (reg4b&0x20)) ? "4" :
- ((reg54&0x88) && (reg4b&0x10)) ? "3" :
- (reg4b&0x20) ? "2" :
- (reg4b&0x10) ? "1" :
- (reg4b&0x00) ? "0" : "X");
-
- p += sprintf(p, "UDMA\n");
- p += sprintf(p, "DMA\n");
- p += sprintf(p, "PIO\n");
+ piix_print("----------PIIX BusMastering IDE Configuration---------------");
-/*
- * FIXME.... Add configuration junk data....blah blah......
- */
+ piix_print("Driver Version: 1.2");
+ piix_print("South Bridge: %s", bmide_dev->name);
- return p-buffer; /* => must be less than 4k! */
-}
-#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */
+ pci_read_config_byte(dev, PCI_REVISION_ID, &t);
+ piix_print("Revision: IDE %#x", t);
+ piix_print("Highest DMA rate: %s", piix_config->flags & PIIX_NODMA ? "No DMA"
+ : piix_dma[piix_config->flags & PIIX_UDMA]);
-/*
- * Used to set Fifo configuration via kernel command line:
- */
+ piix_print("BM-DMA base: %#x", piix_base);
+ piix_print("PCI clock: %d.%dMHz", piix_clock / 1000, piix_clock / 100 % 10);
-byte piix_proc = 0;
+ piix_print("-----------------------Primary IDE-------Secondary IDE------");
-extern char *ide_xfer_verbose (byte xfer_rate);
+ pci_read_config_word(dev, PIIX_IDETIM0, &d);
+ pci_read_config_word(dev, PIIX_IDETIM1, &e);
+ piix_print("Enabled: %10s%20s", (d & 0x8000) ? "yes" : "no", (e & 0x8000) ? "yes" : "no");
-#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING)
-/*
- *
- */
-static byte piix_dma_2_pio (byte xfer_rate) {
- switch(xfer_rate) {
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- case XFER_MW_DMA_2:
- case XFER_PIO_4:
- return 4;
- case XFER_MW_DMA_1:
- case XFER_PIO_3:
- return 3;
- case XFER_SW_DMA_2:
- case XFER_PIO_2:
- return 2;
- case XFER_MW_DMA_0:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
- case XFER_PIO_1:
- case XFER_PIO_0:
- case XFER_PIO_SLOW:
- default:
- return 0;
+ c = inb(piix_base + 0x02) | (inb(piix_base + 0x0a) << 8);
+ piix_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no");
+
+ piix_print("Cable Type: %10s%20s", (piix_80w & 1) ? "80w" : "40w", (piix_80w & 2) ? "80w" : "40w");
+
+ if (!piix_clock)
+ return p - buffer;
+
+ piix_print("-------------------drive0----drive1----drive2----drive3-----");
+
+ piix_print_drive("Prefetch+Post: ", "%10s", (((i & 2) ? d : e) & (1 << (2 + ((i & 1) << 2)))) ? "yes" : "no");
+
+ for (i = 0; i < 4; i++) {
+
+ pci_read_config_word(dev, PIIX_IDETIM0 + (i & 2), &d);
+ if (~piix_config->flags & PIIX_NO_SITRE)
+ pci_read_config_byte(dev, PIIX_SIDETIM, &t);
+
+ umul = 4;
+ udma[i] = uen[i] = 0;
+ active[i] = 12;
+ recover[i] = 18;
+
+ switch (i & 1) {
+ case 1: if (~d & 0x10) break;
+ if ((~piix_config->flags & PIIX_NO_SITRE) && (d & 0x4000)) {
+ active[i] = 5 - ((t >> (((i & 2) << 1) + 2)) & 3);
+ recover[i] = 4 - ((t >> (((i & 2) << 1) + 0)) & 3);
+ break;
+ }
+
+ case 0: if (~d & 0x01) break;
+ active[i] = 5 - ((d >> 12) & 3);
+ recover[i] = 4 - ((d >> 8) & 3);
+ }
+
+ dmaen[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2));
+ cycle[i] = 1000000 / piix_clock * (active[i] + recover[i]);
+ speed[i] = 2 * piix_clock / (active[i] + recover[i]);
+
+ if (!(piix_config->flags & PIIX_UDMA))
+ continue;
+
+ pci_read_config_byte(dev, PIIX_UDMACTL, &t);
+ uen[i] = (t & (1 << i)) ? dmaen[i] : 0;
+
+ if (!uen[i])
+ continue;
+
+ pci_read_config_word(dev, PIIX_UDMATIM, &e);
+ pci_read_config_dword(dev, PIIX_IDECFG, &u);
+
+ if (~piix_config->flags & PIIX_VICTORY) {
+ if ((piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_66 && (u & (1 << i))) umul = 2;
+ if ((piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_100 && (u & ((1 << i) + 12))) umul = 1;
+ udma[i] = (4 - ((e >> (i << 2)) & 3)) * umul;
+ } else udma[i] = (8 - ((e >> (i << 2)) & 7)) * 2;
+
+ speed[i] = 8 * piix_clock / udma[i];
+ cycle[i] = 250000 * udma[i] / piix_clock;
}
+
+ piix_print_drive("Transfer Mode: ", "%10s", dmaen[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO");
+
+ piix_print_drive("Address Setup: ", "%8dns", (1000000 / piix_clock) * 3);
+ piix_print_drive("Cmd Active: ", "%8dns", (1000000 / piix_clock) * 12);
+ piix_print_drive("Cmd Recovery: ", "%8dns", (1000000 / piix_clock) * 18);
+ piix_print_drive("Data Active: ", "%8dns", (1000000 / piix_clock) * active[i]);
+ piix_print_drive("Data Recovery: ", "%8dns", (1000000 / piix_clock) * recover[i]);
+ piix_print_drive("Cycle Time: ", "%8dns", cycle[i]);
+ piix_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10);
+
+ return p - buffer; /* hoping it is less than 4K... */
}
-#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */
+
+#endif
/*
- * Based on settings done by AMI BIOS
- * (might be useful if drive is not registered in CMOS for any reason).
+ * piix_set_speed() writes timing values to the chipset registers
*/
-static void piix_tune_drive (ide_drive_t *drive, byte pio)
-{
- unsigned long flags;
- u16 master_data;
- u8 slave_data;
- int is_slave = (&HWIF(drive)->drives[1] == drive);
- int master_port = HWIF(drive)->index ? 0x42 : 0x40;
- int slave_port = 0x44;
- /* ISP RTC */
- byte timings[][2] = { { 0, 0 },
- { 0, 0 },
- { 1, 0 },
- { 2, 1 },
- { 2, 3 }, };
-
- if (pio == 255)
- pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
- else
- pio = min_t(byte, pio, 4);
-
- pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
- if (is_slave) {
- master_data = master_data | 0x4000;
- if (pio > 1)
- /* enable PPE, IE and TIME */
- master_data = master_data | 0x0070;
- pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data);
- slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0);
- slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1])
- << (HWIF(drive)->index ? 4 : 0));
- } else {
- master_data = master_data & 0xccf8;
- if (pio > 1)
- /* enable PPE, IE and TIME */
- master_data = master_data | 0x0007;
- master_data = master_data | (timings[pio][0] << 12) |
- (timings[pio][1] << 8);
- }
- save_flags(flags);
- cli();
- pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
- if (is_slave)
- pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
- restore_flags(flags);
-}
-#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING)
-static int piix_tune_chipset (ide_drive_t *drive, byte speed)
+static void piix_set_speed(struct pci_dev *dev, unsigned char dn, struct ata_timing *timing, int umul)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- byte maslave = hwif->channel ? 0x42 : 0x40;
- int a_speed = 3 << (drive->dn * 4);
- int u_flag = 1 << drive->dn;
- int v_flag = 0x01 << drive->dn;
- int w_flag = 0x10 << drive->dn;
- int u_speed = 0;
- int err = 0;
- int sitre;
- short reg4042, reg44, reg48, reg4a, reg54;
- byte reg55;
-
- pci_read_config_word(dev, maslave, &reg4042);
- sitre = (reg4042 & 0x4000) ? 1 : 0;
- pci_read_config_word(dev, 0x44, &reg44);
- pci_read_config_word(dev, 0x48, &reg48);
- pci_read_config_word(dev, 0x4a, &reg4a);
- pci_read_config_word(dev, 0x54, &reg54);
- pci_read_config_byte(dev, 0x55, &reg55);
-
- switch(speed) {
- case XFER_UDMA_4:
- case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
- case XFER_UDMA_5:
- case XFER_UDMA_3:
- case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
- case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_SW_DMA_2: break;
- default: return -1;
+ unsigned short t;
+ unsigned char u;
+ unsigned int c;
+
+ pci_read_config_word(dev, PIIX_IDETIM0 + (dn & 2), &t);
+
+ switch (dn & 1) {
+
+ case 1:
+ if (timing->cycle > 9) {
+ t &= ~0x30;
+ break;
+ }
+
+ if (~piix_config->flags & PIIX_NO_SITRE) {
+ pci_read_config_byte(dev, PIIX_SIDETIM, &u);
+ u &= ~(0xf << ((dn & 2) << 1));
+ t |= 0x30;
+ u |= (4 - FIT(timing->recover, 1, 4)) << ((dn & 2) << 1);
+ u |= (5 - FIT(timing->active, 2, 5)) << (((dn & 2) << 1) + 2);
+ pci_write_config_byte(dev, PIIX_SIDETIM, u);
+ break;
+ }
+
+ case 0:
+ if ((~dn & 1) && timing->cycle > 9) {
+ t &= ~0x03;
+ break;
+ }
+
+ t &= 0xccff;
+ t |= 0x03 << ((dn & 1) << 2);
+ t |= (4 - FIT(timing->recover, 1, 4)) << 8;
+ t |= (5 - FIT(timing->active, 2, 5)) << 12;
}
- if (speed >= XFER_UDMA_0) {
- if (!(reg48 & u_flag))
- pci_write_config_word(dev, 0x48, reg48|u_flag);
- if (speed == XFER_UDMA_5) {
- pci_write_config_byte(dev, 0x55, (byte) reg55|w_flag);
+ pci_write_config_word(dev, PIIX_IDETIM0 + (dn & 2), t);
+
+ if (!(piix_config->flags & PIIX_UDMA)) return;
+
+ pci_read_config_byte(dev, PIIX_UDMACTL, &u);
+ u &= ~(1 << dn);
+
+ if (timing->udma) {
+
+ u |= 1 << dn;
+
+ pci_read_config_word(dev, PIIX_UDMATIM, &t);
+
+ if (piix_config->flags & PIIX_VICTORY) {
+ t &= ~(0x07 << (dn << 2));
+ t |= (8 - FIT(timing->udma, 2, 8)) << (dn << 2);
} else {
- pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag);
- }
- if (!(reg4a & u_speed)) {
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
- pci_write_config_word(dev, 0x4a, reg4a|u_speed);
+ t &= ~(0x03 << (dn << 2));
+ t |= (4 - FIT(timing->udma, 2, 4)) << (dn << 2);
}
- if (speed > XFER_UDMA_2) {
- if (!(reg54 & v_flag)) {
- pci_write_config_word(dev, 0x54, reg54|v_flag);
+
+ pci_write_config_word(dev, PIIX_UDMATIM, t);
+
+ if ((piix_config->flags & PIIX_UDMA) > PIIX_UDMA_33
+ && ~piix_config->flags & PIIX_VICTORY) {
+
+ pci_read_config_dword(dev, PIIX_IDECFG, &c);
+
+ if ((piix_config->flags & PIIX_UDMA) > PIIX_UDMA_66)
+ c &= ~(1 << (dn + 12));
+ c &= ~(1 << dn);
+
+ switch (umul) {
+ case 2: c |= 1 << dn; break;
+ case 4: c |= 1 << (dn + 12); break;
}
- } else {
- pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
+
+ pci_write_config_dword(dev, PIIX_IDECFG, c);
}
}
- if (speed < XFER_UDMA_0) {
- if (reg48 & u_flag)
- pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
- if (reg4a & a_speed)
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
- if (reg54 & v_flag)
- pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
- if (reg55 & w_flag)
- pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag);
+
+ pci_write_config_byte(dev, PIIX_UDMACTL, u);
+}
+
+/*
+ * piix_set_drive() computes timing values configures the drive and
+ * the chipset to a desired transfer mode. It also can be called
+ * by upper layers.
+ */
+
+static int piix_set_drive(ide_drive_t *drive, unsigned char speed)
+{
+ ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+ struct ata_timing t, p;
+ int err, T, UT, umul;
+
+ if (speed != XFER_PIO_SLOW && speed != drive->current_speed)
+ if ((err = ide_config_drive_speed(drive, speed)))
+ return err;
+
+ umul = min((speed > XFER_UDMA_4) ? 4 : ((speed > XFER_UDMA_2) ? 2 : 1),
+ piix_config->flags & PIIX_UDMA);
+
+ if (piix_config->flags & PIIX_VICTORY)
+ umul = 2;
+
+ T = 1000000000 / piix_clock;
+ UT = T / umul;
+
+ ata_timing_compute(drive, speed, &t, T, UT);
+
+ if ((piix_config->flags & PIIX_NO_SITRE) && peer->present) {
+ ata_timing_compute(peer, peer->current_speed, &p, T, UT);
+ if (t.cycle <= 9 && p.cycle <= 9)
+ ata_timing_merge(&p, &t, &t, IDE_TIMING_ALL);
}
- piix_tune_drive(drive, piix_dma_2_pio(speed));
+ piix_set_speed(HWIF(drive)->pci_dev, drive->dn, &t, umul);
-#if PIIX_DEBUG_DRIVE_INFO
- printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
-#endif /* PIIX_DEBUG_DRIVE_INFO */
- if (!drive->init_speed)
+ if (!drive->init_speed)
drive->init_speed = speed;
- err = ide_config_drive_speed(drive, speed);
drive->current_speed = speed;
- return err;
+
+ return 0;
}
-static int piix_config_drive_for_dma (ide_drive_t *drive)
+/*
+ * piix_tune_drive() is a callback from upper layers for
+ * PIO-only tuning.
+ */
+
+static void piix_tune_drive(ide_drive_t *drive, unsigned char pio)
{
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- byte speed;
-
- byte udma_66 = eighty_ninty_three(drive);
- int ultra100 = ((dev->device == PCI_DEVICE_ID_INTEL_82801BA_8) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801BA_9) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801CA_10)) ? 1 : 0;
- int ultra66 = ((ultra100) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0;
- int ultra = ((ultra66) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82451NX) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0;
-
- speed = ata_timing_mode(drive, XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA
- | (ultra ? XFER_UDMA : 0) | ((udma_66 & ultra66) ? XFER_UDMA_66 : 0)
- | ((udma_66 & ultra100) ? XFER_UDMA_100 : 0));
-
- (void) piix_tune_chipset(drive, speed);
-
- return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
- ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
- ((id->dma_mword >> 8) & 7) ? ide_dma_on :
- ((id->dma_1word >> 8) & 7) ? ide_dma_on :
- ide_dma_off_quietly);
+ if (!((piix_enabled >> HWIF(drive)->channel) & 1))
+ return;
+
+ if (pio == 255) {
+ piix_set_drive(drive, ata_timing_mode(drive, XFER_PIO | XFER_EPIO));
+ return;
+ }
+
+ piix_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
}
-static void config_chipset_for_pio (ide_drive_t *drive)
+#ifdef CONFIG_BLK_DEV_IDEDMA
+
+/*
+ * piix_dmaproc() is a callback from upper layers that can do
+ * a lot, but we use it for DMA/PIO tuning only, delegating everything
+ * else to the default ide_dmaproc().
+ */
+
+int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
{
- piix_tune_drive(drive, ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0);
+
+ if (func == ide_dma_check) {
+
+ short w80 = HWIF(drive)->udma_four;
+
+ short speed = ata_timing_mode(drive,
+ XFER_PIO | XFER_EPIO |
+ (piix_config->flags & PIIX_NODMA ? 0 : (XFER_SWDMA | XFER_MWDMA |
+ (piix_config->flags & PIIX_UDMA ? XFER_UDMA : 0) |
+ (w80 && (piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_66 ? XFER_UDMA_66 : 0) |
+ (w80 && (piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_100 ? XFER_UDMA_100 : 0))));
+
+ piix_set_drive(drive, speed);
+
+ func = (HWIF(drive)->autodma && (speed & XFER_MODE) != XFER_PIO)
+ ? ide_dma_on : ide_dma_off_quietly;
+
+ }
+
+ return ide_dmaproc(func, drive);
}
-static int config_drive_xfer_rate (ide_drive_t *drive)
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+/*
+ * The initialization callback. Here we determine the IDE chip type
+ * and initialize its drive independent registers.
+ */
+
+unsigned int __init pci_init_piix(struct pci_dev *dev, const char *name)
{
- struct hd_driveid *id = drive->id;
- ide_dma_action_t dma_func = ide_dma_on;
-
- if (id && (id->capability & 1) && HWIF(drive)->autodma) {
- /* Consult the list of known "bad" drives */
- if (ide_dmaproc(ide_dma_bad_drive, drive)) {
- dma_func = ide_dma_off;
- goto fast_ata_pio;
- }
- dma_func = ide_dma_off_quietly;
- if (id->field_valid & 4) {
- if (id->dma_ultra & 0x003F) {
- /* Force if Capable UltraDMA */
- dma_func = piix_config_drive_for_dma(drive);
- if ((id->field_valid & 2) &&
- (dma_func != ide_dma_on))
- goto try_dma_modes;
- }
- } else if (id->field_valid & 2) {
-try_dma_modes:
- if ((id->dma_mword & 0x0007) ||
- (id->dma_1word & 0x007)) {
- /* Force if Capable regular DMA modes */
- dma_func = piix_config_drive_for_dma(drive);
- if (dma_func != ide_dma_on)
- goto no_dma_set;
+ unsigned int u;
+ unsigned short w;
+ unsigned char t;
+ int i;
+
+/*
+ * Find out which Intel IDE this is.
+ */
+
+ for (piix_config = piix_ide_chips; piix_config->id != 0; ++piix_config)
+ if (dev->device == piix_config->id)
+ break;
+
+ if (!piix_config->id) {
+ printk(KERN_WARNING "PIIX: Unknown PIIX/ICH chip %#x, contact Vojtech Pavlik <vojtech@ucw.cz>\n", dev->device);
+ return -ENODEV;
+ }
+
+/*
+ * Check for possibly broken DMA configs.
+ */
+
+ {
+ struct pci_dev *orion = NULL;
+
+ if (piix_config->flags & PIIX_CHECK_REV) {
+ pci_read_config_byte(dev, PCI_REVISION_ID, &t);
+ if (t < 2) {
+ printk(KERN_INFO "PIIX: Found buggy old PIIX rev %#x, disabling DMA\n", t);
+ piix_config->flags |= PIIX_NODMA;
}
- } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
- if (id->eide_dma_time > 150) {
- goto no_dma_set;
+ }
+
+ if ((orion = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, NULL))) {
+ pci_read_config_byte(orion, PCI_REVISION_ID, &t);
+ if (t < 4) {
+ printk(KERN_INFO "PIIX: Found buggy 82454GX Orion bridge rev %#x, disabling DMA\n", t);
+ piix_config->flags |= PIIX_NODMA;
}
- /* Consult the list of known "good" drives */
- dma_func = piix_config_drive_for_dma(drive);
- if (dma_func != ide_dma_on)
- goto no_dma_set;
- } else {
- goto fast_ata_pio;
}
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
- dma_func = ide_dma_off_quietly;
-no_dma_set:
- config_chipset_for_pio(drive);
}
- return HWIF(drive)->dmaproc(dma_func, drive);
-}
-static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
- switch (func) {
- case ide_dma_check:
- return config_drive_xfer_rate(drive);
- default :
+/*
+ * Check 80-wire cable presence.
+ */
+
+ switch (piix_config->flags & PIIX_UDMA) {
+
+ case PIIX_UDMA_66:
+ case PIIX_UDMA_100:
+ pci_read_config_dword(dev, PIIX_IDECFG, &u);
+ piix_80w = ((u & 0x30) ? 1 : 0) | ((u & 0xc0) ? 2 : 0);
+ break;
+
+ case PIIX_UDMA_V66:
+ pci_read_config_byte(dev, PIIX_IDESTAT, &t);
+ piix_80w = ((t & 2) ? 1 : 0) | ((t & 1) ? 2 : 0);
break;
}
- /* Other cases are done by generic IDE-DMA code. */
- return ide_dmaproc(func, drive);
-}
-#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */
-unsigned int __init pci_init_piix(struct pci_dev *dev)
-{
-#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
+/*
+ * Enable ping-pong buffers where applicable.
+ */
+
+ if (piix_config->flags & PIIX_PINGPONG) {
+ pci_read_config_dword(dev, PIIX_IDECFG, &u);
+ u |= 0x400;
+ pci_write_config_dword(dev, PIIX_IDECFG, u);
+ }
+
+/*
+ * Detect enabled interfaces, enable slave separate timing if possible.
+ */
+
+ for (i = 0; i < 2; i++) {
+ pci_read_config_word(dev, PIIX_IDETIM0 + (i << 1), &w);
+ piix_enabled |= (w & 0x8000) ? (1 << i) : 0;
+ w &= 0x8c00;
+ if (~piix_config->flags & PIIX_NO_SITRE) w |= 0x4000;
+ w |= 0x44;
+ pci_write_config_word(dev, PIIX_IDETIM0 + (i << 1), w);
+ }
+
+/*
+ * Determine the system bus clock.
+ */
+
+ piix_clock = system_bus_speed * 1000;
+
+ switch (piix_clock) {
+ case 33000: piix_clock = 33333; break;
+ case 37000: piix_clock = 37500; break;
+ case 41000: piix_clock = 41666; break;
+ }
+
+ if (piix_clock < 20000 || piix_clock > 50000) {
+ printk(KERN_WARNING "PIIX: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", piix_clock);
+ printk(KERN_WARNING "PIIX: Use ide0=ata66 if you want to assume 80-wire cable\n");
+ piix_clock = 33333;
+ }
+
+/*
+ * Print the boot message.
+ */
+
+ printk(KERN_INFO "PIIX: %s %s controller on pci%s\n",
+ dev->name, piix_dma[piix_config->flags & PIIX_UDMA], dev->slot_name);
+
+/*
+ * Register /proc/ide/piix entry
+ */
+
+#ifdef CONFIG_PROC_FS
if (!piix_proc) {
- piix_proc = 1;
+ piix_base = pci_resource_start(dev, 4);
bmide_dev = dev;
piix_display_info = &piix_get_info;
+ piix_proc = 1;
}
-#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */
+#endif
+
return 0;
}
-/*
- * Sheesh, someone at Intel needs to go read the ATA-4/5 T13 standards.
- * It does not specify device detection, but channel!!!
- * You determine later if bit 13 of word93 is set...
- */
-unsigned int __init ata66_piix (ide_hwif_t *hwif)
+unsigned int __init ata66_piix(ide_hwif_t *hwif)
{
- byte reg54h = 0, reg55h = 0, ata66 = 0;
- byte mask = hwif->channel ? 0xc0 : 0x30;
-
- pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
- pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
-
- ata66 = (reg54h & mask) ? 1 : 0;
-
- return ata66;
+ return ((piix_enabled & piix_80w) >> hwif->channel) & 1;
}
-void __init ide_init_piix (ide_hwif_t *hwif)
+void __init ide_init_piix(ide_hwif_t *hwif)
{
-#ifndef CONFIG_IA64
- if (!hwif->irq)
- hwif->irq = hwif->channel ? 15 : 14;
-#endif /* CONFIG_IA64 */
+ int i;
- if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) {
- /* This is a painful system best to let it self tune for now */
- return;
+ hwif->tuneproc = &piix_tune_drive;
+ hwif->speedproc = &piix_set_drive;
+ hwif->autodma = 0;
+
+ for (i = 0; i < 2; i++) {
+ hwif->drives[i].io_32bit = 1;
+ hwif->drives[i].unmask = 1;
+ hwif->drives[i].autotune = 1;
+ hwif->drives[i].dn = hwif->channel * 2 + i;
}
- hwif->tuneproc = &piix_tune_drive;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (hwif->dma_base) {
+ hwif->highmem = 1;
+ hwif->dmaproc = &piix_dmaproc;
+#ifdef CONFIG_IDEDMA_AUTO
+ if (!noautodma)
+ hwif->autodma = 1;
+#endif
+ }
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+}
- if (!hwif->dma_base)
- return;
+/*
+ * We allow the BM-DMA driver only work on enabled interfaces,
+ * and only if DMA is safe with the chip and bridge.
+ */
- hwif->highmem = 1;
-#ifndef CONFIG_BLK_DEV_IDEDMA
- hwif->autodma = 0;
-#else /* CONFIG_BLK_DEV_IDEDMA */
-#ifdef CONFIG_PIIX_TUNING
- if (!noautodma)
- hwif->autodma = 1;
- hwif->dmaproc = &piix_dmaproc;
- hwif->speedproc = &piix_tune_chipset;
-#endif /* CONFIG_PIIX_TUNING */
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
+void __init ide_dmacapable_piix(ide_hwif_t *hwif, unsigned long dmabase)
+{
+ if (((piix_enabled >> hwif->channel) & 1)
+ && !(piix_config->flags & PIIX_NODMA))
+ ide_setup_dma(hwif, dmabase, 8);
}
diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c
deleted file mode 100644
index 95159248e95f..000000000000
--- a/drivers/ide/slc90e66.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * linux/drivers/ide/slc90e66.c Version 0.10 October 4, 2000
- *
- * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
- * May be copied or modified under the terms of the GNU General Public License
- *
- * 00:07.1 IDE interface: EFAR Microsystems:
- * Unknown device 9130 (prog-if 8a [Master SecP PriP])
- * Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV-
- * VGASnoop- ParErr- Stepping- SERR- FastB2B-
- * Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium
- * >TAbort- <TAbort- <MAbort- >SERR- <PERR-
- * Latency: 64
- * Interrupt: pin A routed to IRQ 255
- * Region 4: I/O ports at 1050
- *
- * 00: 55 10 30 91 05 00 00 02 00 8a 01 01 00 40 00 00
- * 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 20: 51 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 30: 00 00 00 00 00 00 00 00 00 00 00 00 ff 01 00 00
- * 40: 37 e3 33 e3 b9 55 01 00 0d 00 04 22 00 00 00 00
- * 50: 00 00 ff a0 00 00 00 08 40 00 00 00 00 00 00 00
- * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- *
- * This a look-a-like variation of the ICH0 PIIX4 Ultra-66,
- * but this keeps the ISA-Bridge and slots alive.
- *
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#include "ata-timing.h"
-
-#define SLC90E66_DEBUG_DRIVE_INFO 0
-
-#define DISPLAY_SLC90E66_TIMINGS
-
-#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static int slc90e66_get_info(char *, char **, off_t, int);
-extern int (*slc90e66_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-static struct pci_dev *bmide_dev;
-
-static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count)
-{
- char *p = buffer;
- u32 bibma = pci_resource_start(bmide_dev, 4);
- u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
- u8 c0 = 0, c1 = 0;
- u8 reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0;
-
- pci_read_config_word(bmide_dev, 0x40, &reg40);
- pci_read_config_word(bmide_dev, 0x42, &reg42);
- pci_read_config_byte(bmide_dev, 0x44, &reg44);
- pci_read_config_byte(bmide_dev, 0x47, &reg47);
- pci_read_config_byte(bmide_dev, 0x48, &reg48);
- pci_read_config_byte(bmide_dev, 0x4a, &reg4a);
- pci_read_config_byte(bmide_dev, 0x4b, &reg4b);
-
- psitre = (reg40 & 0x4000) ? 1 : 0;
- ssitre = (reg42 & 0x4000) ? 1 : 0;
-
- /*
- * at that point bibma+0x2 et bibma+0xa are byte registers
- * to investigate:
- */
-#ifdef __mips__ /* only for mips? */
- c0 = inb_p(bibma + 0x02);
- c1 = inb_p(bibma + 0x0a);
-#else
- c0 = inb_p((unsigned short)bibma + 0x02);
- c1 = inb_p((unsigned short)bibma + 0x0a);
-#endif
-
- p += sprintf(p, " SLC90E66 Chipset.\n");
- p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
- p += sprintf(p, " %sabled %sabled\n",
- (c0&0x80) ? "dis" : " en",
- (c1&0x80) ? "dis" : " en");
- p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
- p += sprintf(p, "DMA enabled: %s %s %s %s\n",
- (c0&0x20) ? "yes" : "no ",
- (c0&0x40) ? "yes" : "no ",
- (c1&0x20) ? "yes" : "no ",
- (c1&0x40) ? "yes" : "no " );
- p += sprintf(p, "UDMA enabled: %s %s %s %s\n",
- (reg48&0x01) ? "yes" : "no ",
- (reg48&0x02) ? "yes" : "no ",
- (reg48&0x04) ? "yes" : "no ",
- (reg48&0x08) ? "yes" : "no " );
- p += sprintf(p, "UDMA enabled: %s %s %s %s\n",
- ((reg4a&0x04)==0x04) ? "4" :
- ((reg4a&0x03)==0x03) ? "3" :
- (reg4a&0x02) ? "2" :
- (reg4a&0x01) ? "1" :
- (reg4a&0x00) ? "0" : "X",
- ((reg4a&0x40)==0x40) ? "4" :
- ((reg4a&0x30)==0x30) ? "3" :
- (reg4a&0x20) ? "2" :
- (reg4a&0x10) ? "1" :
- (reg4a&0x00) ? "0" : "X",
- ((reg4b&0x04)==0x04) ? "4" :
- ((reg4b&0x03)==0x03) ? "3" :
- (reg4b&0x02) ? "2" :
- (reg4b&0x01) ? "1" :
- (reg4b&0x00) ? "0" : "X",
- ((reg4b&0x40)==0x40) ? "4" :
- ((reg4b&0x30)==0x30) ? "3" :
- (reg4b&0x20) ? "2" :
- (reg4b&0x10) ? "1" :
- (reg4b&0x00) ? "0" : "X");
-
- p += sprintf(p, "UDMA\n");
- p += sprintf(p, "DMA\n");
- p += sprintf(p, "PIO\n");
-
-/*
- * FIXME.... Add configuration junk data....blah blah......
- */
-
- return p-buffer; /* => must be less than 4k! */
-}
-#endif /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-/*
- * Used to set Fifo configuration via kernel command line:
- */
-
-byte slc90e66_proc = 0;
-
-extern char *ide_xfer_verbose (byte xfer_rate);
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-/*
- *
- */
-static byte slc90e66_dma_2_pio (byte xfer_rate) {
- switch(xfer_rate) {
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- case XFER_MW_DMA_2:
- case XFER_PIO_4:
- return 4;
- case XFER_MW_DMA_1:
- case XFER_PIO_3:
- return 3;
- case XFER_SW_DMA_2:
- case XFER_PIO_2:
- return 2;
- case XFER_MW_DMA_0:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
- case XFER_PIO_1:
- case XFER_PIO_0:
- case XFER_PIO_SLOW:
- default:
- return 0;
- }
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-/*
- * Based on settings done by AMI BIOS
- * (might be useful if drive is not registered in CMOS for any reason).
- */
-static void slc90e66_tune_drive (ide_drive_t *drive, byte pio)
-{
- unsigned long flags;
- u16 master_data;
- byte slave_data;
- int is_slave = (&HWIF(drive)->drives[1] == drive);
- int master_port = HWIF(drive)->index ? 0x42 : 0x40;
- int slave_port = 0x44;
- /* ISP RTC */
- byte timings[][2] = { { 0, 0 },
- { 0, 0 },
- { 1, 0 },
- { 2, 1 },
- { 2, 3 }, };
-
- if (pio == 255)
- pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
- else
- pio = min_t(byte, pio, 4);
-
- pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
- if (is_slave) {
- master_data = master_data | 0x4000;
- if (pio > 1)
- /* enable PPE, IE and TIME */
- master_data = master_data | 0x0070;
- pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data);
- slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0);
- slave_data = slave_data | ((timings[pio][0] << 2) | (timings[pio][1]
- << (HWIF(drive)->index ? 4 : 0)));
- } else {
- master_data = master_data & 0xccf8;
- if (pio > 1)
- /* enable PPE, IE and TIME */
- master_data = master_data | 0x0007;
- master_data = master_data | (timings[pio][0] << 12) |
- (timings[pio][1] << 8);
- }
- save_flags(flags);
- cli();
- pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
- if (is_slave)
- pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
- restore_flags(flags);
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static int slc90e66_tune_chipset (ide_drive_t *drive, byte speed)
-{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- byte maslave = hwif->channel ? 0x42 : 0x40;
- int a_speed = 7 << (drive->dn * 4);
- int u_flag = 1 << drive->dn;
- int u_speed = 0;
- int err = 0;
- int sitre;
- short reg4042, reg44, reg48, reg4a;
-
- pci_read_config_word(dev, maslave, &reg4042);
- sitre = (reg4042 & 0x4000) ? 1 : 0;
- pci_read_config_word(dev, 0x44, &reg44);
- pci_read_config_word(dev, 0x48, &reg48);
- pci_read_config_word(dev, 0x4a, &reg4a);
-
- switch(speed) {
- case XFER_UDMA_4: u_speed = 4 << (drive->dn * 4); break;
- case XFER_UDMA_3: u_speed = 3 << (drive->dn * 4); break;
- case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
- case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
- case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_SW_DMA_2: break;
-#if 0 /* allow PIO modes */
- default: return -1;
-#endif
- }
-
- if (speed >= XFER_UDMA_0) {
- if (!(reg48 & u_flag))
- pci_write_config_word(dev, 0x48, reg48|u_flag);
- if ((reg4a & u_speed) != u_speed) {
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
- pci_read_config_word(dev, 0x4a, &reg4a);
- pci_write_config_word(dev, 0x4a, reg4a|u_speed);
- }
- }
- if (speed < XFER_UDMA_0) {
- if (reg48 & u_flag)
- pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
- if (reg4a & a_speed)
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
- }
-
- slc90e66_tune_drive(drive, slc90e66_dma_2_pio(speed));
-
-#if SLC90E66_DEBUG_DRIVE_INFO
- printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
-#endif /* SLC90E66_DEBUG_DRIVE_INFO */
- if (!drive->init_speed)
- drive->init_speed = speed;
- err = ide_config_drive_speed(drive, speed);
- drive->current_speed = speed;
- return err;
-}
-
-static int slc90e66_config_drive_for_dma (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
- int ultra = 1;
- byte speed = 0;
- byte udma_66 = eighty_ninty_three(drive);
-
-#if 1 /* allow PIO modes */
- if (!HWIF(drive)->autodma) {
- speed = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
- (void) slc90e66_tune_chipset(drive, speed);
- return ((int) ide_dma_off_quietly);
- }
-#endif
-
- speed = ata_timing_mode(drive, XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA
- | (ultra ? XFER_UDMA : 0) | ((ultra && udma_66) ? XFER_UDMA_66 : 0));
-
- (void) slc90e66_tune_chipset(drive, speed);
-
- return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
- ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
- ((id->dma_mword >> 8) & 7) ? ide_dma_on :
- ((id->dma_1word >> 8) & 7) ? ide_dma_on :
- ide_dma_off_quietly);
-}
-
-static int slc90e66_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
- switch (func) {
- case ide_dma_check:
- return ide_dmaproc((ide_dma_action_t) slc90e66_config_drive_for_dma(drive), drive);
- default :
- break;
- }
- /* Other cases are done by generic IDE-DMA code. */
- return ide_dmaproc(func, drive);
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-unsigned int __init pci_init_slc90e66(struct pci_dev *dev)
-{
-#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS)
- if (!slc90e66_proc) {
- slc90e66_proc = 1;
- bmide_dev = dev;
- slc90e66_display_info = &slc90e66_get_info;
- }
-#endif /* DISPLAY_SLC90E66_TIMINGS && CONFIG_PROC_FS */
- return 0;
-}
-
-unsigned int __init ata66_slc90e66 (ide_hwif_t *hwif)
-{
-#if 1
- byte reg47 = 0, ata66 = 0;
- byte mask = hwif->channel ? 0x01 : 0x02; /* bit0:Primary */
-
- pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
-
- ata66 = (reg47 & mask) ? 0 : 1; /* bit[0(1)]: 0:80, 1:40 */
-#else
- byte ata66 = 0;
-#endif
- return ata66;
-}
-
-void __init ide_init_slc90e66 (ide_hwif_t *hwif)
-{
- if (!hwif->irq)
- hwif->irq = hwif->channel ? 15 : 14;
-
- hwif->tuneproc = &slc90e66_tune_drive;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
- if (!hwif->dma_base)
- return;
-
- hwif->autodma = 0;
- hwif->highmem = 1;
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (!noautodma)
- hwif->autodma = 1;
- hwif->dmaproc = &slc90e66_dmaproc;
- hwif->speedproc = &slc90e66_tune_chipset;
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
-}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 890ca713c999..a8fa051737f8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1710,7 +1710,6 @@ struct pci_pool { /* the pool */
spinlock_t lock;
size_t blocks_per_page;
size_t size;
- int flags;
struct pci_dev *dev;
size_t allocation;
char name [32];
@@ -1727,8 +1726,6 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
#define POOL_POISON_BYTE 0xa7
-// #define CONFIG_PCIPOOL_DEBUG
-
/**
* pci_pool_create - Creates a pool of pci consistent memory blocks, for dma.
@@ -1737,7 +1734,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
* @size: size of the blocks in this pool.
* @align: alignment requirement for blocks; must be a power of two
* @allocation: returned blocks won't cross this boundary (or zero)
- * @flags: SLAB_* flags (not all are supported).
+ * @mem_flags: SLAB_* flags.
*
* Returns a pci allocation pool with the requested characteristics, or
* null if one can't be created. Given one of these pools, pci_pool_alloc()
@@ -1753,7 +1750,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
*/
struct pci_pool *
pci_pool_create (const char *name, struct pci_dev *pdev,
- size_t size, size_t align, size_t allocation, int flags)
+ size_t size, size_t align, size_t allocation, int mem_flags)
{
struct pci_pool *retval;
@@ -1777,13 +1774,9 @@ pci_pool_create (const char *name, struct pci_dev *pdev,
} else if (allocation < size)
return 0;
- if (!(retval = kmalloc (sizeof *retval, flags)))
+ if (!(retval = kmalloc (sizeof *retval, mem_flags)))
return retval;
-#ifdef CONFIG_PCIPOOL_DEBUG
- flags |= SLAB_POISON;
-#endif
-
strncpy (retval->name, name, sizeof retval->name);
retval->name [sizeof retval->name - 1] = 0;
@@ -1791,17 +1784,10 @@ pci_pool_create (const char *name, struct pci_dev *pdev,
INIT_LIST_HEAD (&retval->page_list);
spin_lock_init (&retval->lock);
retval->size = size;
- retval->flags = flags;
retval->allocation = allocation;
retval->blocks_per_page = allocation / size;
init_waitqueue_head (&retval->waitq);
-#ifdef CONFIG_PCIPOOL_DEBUG
- printk (KERN_DEBUG "pcipool create %s/%s size %d, %d/page (%d alloc)\n",
- pdev ? pdev->slot_name : NULL, retval->name, size,
- retval->blocks_per_page, allocation);
-#endif
-
return retval;
}
@@ -1824,8 +1810,9 @@ pool_alloc_page (struct pci_pool *pool, int mem_flags)
&page->dma);
if (page->vaddr) {
memset (page->bitmap, 0xff, mapsize); // bit set == free
- if (pool->flags & SLAB_POISON)
- memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+#ifdef CONFIG_DEBUG_SLAB
+ memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+#endif
list_add (&page->page_list, &pool->page_list);
} else {
kfree (page);
@@ -1851,8 +1838,9 @@ pool_free_page (struct pci_pool *pool, struct pci_page *page)
{
dma_addr_t dma = page->dma;
- if (pool->flags & SLAB_POISON)
- memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+#ifdef CONFIG_DEBUG_SLAB
+ memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+#endif
pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma);
list_del (&page->page_list);
kfree (page);
@@ -1871,12 +1859,6 @@ pci_pool_destroy (struct pci_pool *pool)
{
unsigned long flags;
-#ifdef CONFIG_PCIPOOL_DEBUG
- printk (KERN_DEBUG "pcipool destroy %s/%s\n",
- pool->dev ? pool->dev->slot_name : NULL,
- pool->name);
-#endif
-
spin_lock_irqsave (&pool->lock, flags);
while (!list_empty (&pool->page_list)) {
struct pci_page *page;
@@ -2010,30 +1992,27 @@ pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
pool->name, vaddr, (unsigned long) dma);
return;
}
-#ifdef CONFIG_PCIPOOL_DEBUG
- if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
- printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n",
- pool->dev ? pool->dev->slot_name : NULL,
- pool->name, vaddr, (unsigned long) dma);
- return;
- }
-#endif
block = dma - page->dma;
block /= pool->size;
map = block / BITS_PER_LONG;
block %= BITS_PER_LONG;
-#ifdef CONFIG_PCIPOOL_DEBUG
+#ifdef CONFIG_DEBUG_SLAB
+ if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
+ printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n",
+ pool->dev ? pool->dev->slot_name : NULL,
+ pool->name, vaddr, (unsigned long) dma);
+ return;
+ }
if (page->bitmap [map] & (1UL << block)) {
printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n",
pool->dev ? pool->dev->slot_name : NULL,
pool->name, dma);
return;
}
+ memset (vaddr, POOL_POISON_BYTE, pool->size);
#endif
- if (pool->flags & SLAB_POISON)
- memset (vaddr, POOL_POISON_BYTE, pool->size);
spin_lock_irqsave (&pool->lock, flags);
set_bit (block, &page->bitmap [map]);
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
index 9c67a2796b87..29a97f2b8138 100644
--- a/drivers/pci/pci.ids
+++ b/drivers/pci/pci.ids
@@ -526,8 +526,10 @@
2040 79c974
7006 AMD-751 [Irongate] System Controller
7007 AMD-751 [Irongate] AGP Bridge
- 700e AMD-760 [Irongate] System Controller
- 700f AMD-760 [Irongate] AGP Bridge
+ 700c AMD-760 MP [IGD4-2P] System Controller
+ 700d AMD-760 MP [IGD4-2P] AGP Bridge
+ 700e AMD-760 [IGD4-1P] System Controller
+ 700f AMD-760 [IGD4-1P] AGP Bridge
7400 AMD-755 [Cobra] ISA
7401 AMD-755 [Cobra] IDE
7403 AMD-755 [Cobra] ACPI
@@ -540,11 +542,21 @@
7411 AMD-765 [Viper] IDE
7413 AMD-765 [Viper] ACPI
7414 AMD-765 [Viper] USB
- 7440 AMD-768 [??] ISA
- 7441 AMD-768 [??] IDE
- 7443 AMD-768 [??] ACPI
- 7448 AMD-768 [??] PCI
- 7449 AMD-768 [??] USB
+ 7440 AMD-768 [Opus] ISA
+ 7441 AMD-768 [Opus] IDE
+ 7443 AMD-768 [Opus] ACPI
+ 7448 AMD-768 [Opus] PCI
+ 7449 AMD-768 [Opus] USB
+ 7454 AMD-8151 System Controller
+ 7455 AMD-8151 AGP Bridge
+ 7460 AMD-8111 PCI
+ 7461 AMD-8111 USB
+ 7462 AMD-8111 Ethernet
+ 7468 AMD-8111 LPC
+ 7469 AMD-8111 IDE
+ 746a AMD-8111 SMBus 2.0
+ 746b AMD-8111 ACPI
+ 746d AMD-8111 AC97 Audio
1023 Trident Microsystems
0194 82C194
2000 4DWave DX
@@ -1055,11 +1067,11 @@
1052 ?Young Micro Systems
1053 Young Micro Systems
1054 Hitachi, Ltd
-1055 EFAR Microsystems
- 9130 EIDE Controller
- 9460 PCI to ISA Bridge
- 9462 USB Universal Host Controller [OHCI]
- 9463 Power Management Controller [Bridge]
+1055 Efar Microsystems
+ 9130 slc90e66 [Victory66] IDE
+ 9460 slc90e66 [Victory66] ISA
+ 9462 slc90e66 [Victory66] USB
+ 9463 slc90e66 [Victory66] ACPI
1056 ICL
# Motorola made a mistake and used 1507 instead of 1057 in some chips. Please look at the 1507 entry as well when updating this.
1057 Motorola
@@ -1925,6 +1937,7 @@
0151 NV15 DDR (GeForce2 GTS)
0152 NV15 Bladerunner (GeForce2 Ultra)
0153 NV15 GL (Quadro2 Pro)
+ 01bc nForce IDE
0200 NV20 (GeForce3)
0203 Quadro DCC
10df Emulex Corporation
@@ -5066,6 +5079,8 @@
244c 82820 820 (Camino 2) Chipset ISA Bridge (ICH2-M)
244e 82820 820 (Camino 2) Chipset PCI
2485 AC'97 Audio Controller
+ 248a 82801CAM ICH3-M IDE
+ 248b 82801CA ICH3 IDE
2500 82820 820 (Camino) Chipset Host Bridge (MCH)
1043 801c P3C-2000 system chipset
2501 82820 820 (Camino) Chipset Host Bridge (MCH)
@@ -5118,10 +5133,10 @@
71a0 440GX - 82443GX Host bridge
71a1 440GX - 82443GX AGP bridge
71a2 440GX - 82443GX Host bridge (AGP disabled)
- 7600 82372FB PCI to ISA Bridge
- 7601 82372FB PIIX4 IDE
- 7602 82372FB [PCI-to-USB UHCI]
- 7603 82372FB System Management Bus Controller
+ 7600 82372FB PIIX5 ISA
+ 7601 82372FB PIIX5 IDE
+ 7602 82372FB PIIX5 USB
+ 7603 82372FB PIIX5 SMBus
7800 i740
1092 0100 Stealth II G460
8086 0100 Intel740 Graphics Accelerator
diff --git a/drivers/pnp/isapnp.c b/drivers/pnp/isapnp.c
index 2b23cf559079..d81324484ff8 100644
--- a/drivers/pnp/isapnp.c
+++ b/drivers/pnp/isapnp.c
@@ -2273,6 +2273,39 @@ EXPORT_SYMBOL(isapnp_resource_change);
EXPORT_SYMBOL(isapnp_register_driver);
EXPORT_SYMBOL(isapnp_unregister_driver);
+static struct device_driver isapnp_device_driver = {};
+
+static inline int isapnp_init_device_tree(void)
+{
+ struct pci_bus *card;
+ struct pci_dev *parent = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
+
+ isapnp_for_each_card(card) {
+ struct list_head *devlist;
+
+ card->dev = isapnp_alloc(sizeof(*card->dev));
+ if (!card->dev)
+ break;
+ snprintf(card->dev->name, sizeof(card->dev->name), "%s", card->name);
+ sprintf(card->dev->bus_id, "isapnp%d", card->number);
+ card->dev->parent = parent ? &parent->dev : NULL;
+ card->dev->driver = &isapnp_device_driver;
+ device_register(card->dev);
+
+ for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
+ struct pci_dev *dev = pci_dev_b(devlist);
+
+ snprintf(dev->dev.name, sizeof(dev->dev.name), "%s", dev->name);
+ sprintf(dev->dev.bus_id, "%d", dev->devfn);
+ dev->dev.parent = card->dev;
+ dev->dev.driver = &isapnp_device_driver;
+ device_register(&dev->dev);
+ }
+ }
+
+ return 0;
+}
+
int __init isapnp_init(void)
{
int cards;
@@ -2351,6 +2384,9 @@ int __init isapnp_init(void)
} else {
printk(KERN_INFO "isapnp: No Plug & Play card found\n");
}
+
+ isapnp_init_device_tree();
+
#ifdef CONFIG_PROC_FS
isapnp_proc_init();
#endif
@@ -2361,10 +2397,28 @@ subsys_initcall(isapnp_init);
#ifdef MODULE
+static inline void isapnp_cleanup_device_tree(void)
+{
+ struct pci_bus *card;
+
+ isapnp_for_each_card(card) {
+ struct list_head *devlist;
+
+ for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
+ struct pci_dev *dev = pci_dev_b(devlist);
+
+ put_device(&dev->dev);
+ }
+ put_device(card->dev);
+ }
+}
+
void cleanup_module(void)
{
- if (isapnp_detected)
+ if (isapnp_detected) {
+ isapnp_cleanup_device_tree();
isapnp_free_all_resources();
+ }
}
#else
diff --git a/drivers/usb/Config.help b/drivers/usb/Config.help
index f76202f07b7a..28a88d96a72c 100644
--- a/drivers/usb/Config.help
+++ b/drivers/usb/Config.help
@@ -382,6 +382,7 @@ CONFIG_USB_KAWETH
CONFIG_USB_CATC
Say Y if you want to use one of the following 10Mbps USB Ethernet
device based on the EL1210A chip. Supported devices are:
+ Belkin F5U011
Belkin F5U111
CATC NetMate
CATC NetMate II
diff --git a/drivers/usb/catc.c b/drivers/usb/catc.c
index 3bea97a3c04e..37a300d9e2d0 100644
--- a/drivers/usb/catc.c
+++ b/drivers/usb/catc.c
@@ -7,6 +7,9 @@
*
* Based on the work of
* Donald Becker
+ *
+ * Old chipset support added by Simon Evans <spse@secret.org.uk> 2002
+ * - adds support for Belkin F5U011
*/
/*
@@ -70,6 +73,7 @@ MODULE_LICENSE("GPL");
#define RX_MAX_BURST 15 /* Max packets per rx buffer (> 0, < 16) */
#define TX_MAX_BURST 15 /* Max full sized packets per tx buffer (> 0) */
#define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */
+#define RX_PKT_SZ 1600 /* Max size of receive packet for F5U011 */
/*
* Control requests.
@@ -80,6 +84,7 @@ enum control_requests {
GetMac = 0xf2,
Reset = 0xf4,
SetMac = 0xf5,
+ SetRxMode = 0xf5, /* F5U011 only */
WriteROM = 0xf8,
SetReg = 0xfa,
GetReg = 0xfb,
@@ -127,6 +132,7 @@ enum rx_filter_bits {
RxForceOK = 0x04,
RxMultiCast = 0x08,
RxPromisc = 0x10,
+ AltRxPromisc = 0x20, /* F5U011 uses different bit */
};
enum led_values {
@@ -137,6 +143,12 @@ enum led_values {
LEDLink = 0x08,
};
+enum link_status {
+ LinkNoChange = 0,
+ LinkGood = 1,
+ LinkBad = 2
+};
+
/*
* The catc struct.
*/
@@ -180,6 +192,10 @@ struct catc {
} ctrl_queue[CTRL_QUEUE];
struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb;
+
+ u8 is_f5u011; /* Set if device is an F5U011 */
+ u8 rxmode[2]; /* Used for F5U011 */
+ atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */
};
/*
@@ -193,6 +209,10 @@ struct catc {
#define catc_write_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size)
#define catc_read_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_IN, ReadMem, 0, addr, buf, size)
+#define f5u011_rxmode(catc, rxmode) catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2)
+#define f5u011_rxmode_async(catc, rxmode) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL)
+#define f5u011_mchash_async(catc, hash) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL)
+
#define catc_set_reg_async(catc, reg, val) catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL)
#define catc_get_reg_async(catc, reg, cb) catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb)
#define catc_write_mem_async(catc, addr, buf, size) catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL)
@@ -206,9 +226,12 @@ static void catc_rx_done(struct urb *urb)
struct catc *catc = urb->context;
u8 *pkt_start = urb->transfer_buffer;
struct sk_buff *skb;
- int pkt_len;
+ int pkt_len, pkt_offset = 0;
- clear_bit(RX_RUNNING, &catc->flags);
+ if (!catc->is_f5u011) {
+ clear_bit(RX_RUNNING, &catc->flags);
+ pkt_offset = 2;
+ }
if (urb->status) {
dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
@@ -216,19 +239,22 @@ static void catc_rx_done(struct urb *urb)
}
do {
- pkt_len = le16_to_cpup((u16*)pkt_start);
-
- if (pkt_len > urb->actual_length) {
- catc->stats.rx_length_errors++;
- catc->stats.rx_errors++;
- break;
+ if(!catc->is_f5u011) {
+ pkt_len = le16_to_cpup((u16*)pkt_start);
+ if (pkt_len > urb->actual_length) {
+ catc->stats.rx_length_errors++;
+ catc->stats.rx_errors++;
+ break;
+ }
+ } else {
+ pkt_len = urb->actual_length;
}
if (!(skb = dev_alloc_skb(pkt_len)))
return;
skb->dev = catc->netdev;
- eth_copy_and_sum(skb, pkt_start + 2, pkt_len, 0);
+ eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, catc->netdev);
@@ -237,11 +263,28 @@ static void catc_rx_done(struct urb *urb)
catc->stats.rx_packets++;
catc->stats.rx_bytes += pkt_len;
+ /* F5U011 only does one packet per RX */
+ if (catc->is_f5u011)
+ break;
pkt_start += (((pkt_len + 1) >> 6) + 1) << 6;
} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
catc->netdev->last_rx = jiffies;
+
+ if (catc->is_f5u011) {
+ if (atomic_read(&catc->recq_sz)) {
+ int status;
+ atomic_dec(&catc->recq_sz);
+ dbg("getting extra packet");
+ urb->dev = catc->usbdev;
+ if ((status = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
+ dbg("submit(rx_urb) status %d", status);
+ }
+ } else {
+ clear_bit(RX_RUNNING, &catc->flags);
+ }
+ }
}
static void catc_irq_done(struct urb *urb)
@@ -249,29 +292,48 @@ static void catc_irq_done(struct urb *urb)
struct catc *catc = urb->context;
u8 *data = urb->transfer_buffer;
int status;
+ unsigned int hasdata = 0, linksts = LinkNoChange;
+
+ if (!catc->is_f5u011) {
+ hasdata = data[1] & 0x80;
+ if (data[1] & 0x40)
+ linksts = LinkGood;
+ else if (data[1] & 0x20)
+ linksts = LinkBad;
+ } else {
+ hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
+ if (data[0] == 0x90)
+ linksts = LinkGood;
+ else if (data[0] == 0xA0)
+ linksts = LinkBad;
+ }
if (urb->status) {
dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
return;
}
- if ((data[1] & 0x80) && !test_and_set_bit(RX_RUNNING, &catc->flags)) {
- catc->rx_urb->dev = catc->usbdev;
- if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
- err("submit(rx_urb) status %d", status);
- return;
- }
- }
-
- if (data[1] & 0x40) {
+ if (linksts == LinkGood) {
netif_carrier_on(catc->netdev);
dbg("link ok");
}
- if (data[1] & 0x20) {
+ if (linksts == LinkBad) {
netif_carrier_off(catc->netdev);
dbg("link bad");
}
+
+ if (hasdata) {
+ if (test_and_set_bit(RX_RUNNING, &catc->flags)) {
+ if (catc->is_f5u011)
+ atomic_inc(&catc->recq_sz);
+ } else {
+ catc->rx_urb->dev = catc->usbdev;
+ if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
+ err("submit(rx_urb) status %d", status);
+ }
+ }
+ }
}
/*
@@ -282,6 +344,9 @@ static void catc_tx_run(struct catc *catc)
{
int status;
+ if (catc->is_f5u011)
+ catc->tx_ptr = (catc->tx_ptr + 63) & ~63;
+
catc->tx_urb->transfer_buffer_length = catc->tx_ptr;
catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
catc->tx_urb->dev = catc->usbdev;
@@ -338,14 +403,15 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
- *((u16*)tx_buf) = cpu_to_le16((u16)skb->len);
+ *((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
memcpy(tx_buf + 2, skb->data, skb->len);
catc->tx_ptr += skb->len + 2;
if (!test_and_set_bit(TX_RUNNING, &catc->flags))
catc_tx_run(catc);
- if (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2)))
+ if ((catc->is_f5u011 && catc->tx_ptr)
+ || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
netif_stop_queue(netdev);
spin_unlock_irqrestore(&catc->tx_lock, flags);
@@ -554,17 +620,32 @@ static void catc_set_multicast_list(struct net_device *netdev)
if (netdev->flags & IFF_PROMISC) {
memset(catc->multicast, 0xff, 64);
- rx |= RxPromisc;
+ rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc;
}
- if (netdev->flags & IFF_ALLMULTI)
+ if (netdev->flags & IFF_ALLMULTI) {
memset(catc->multicast, 0xff, 64);
-
- for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next)
- catc_multicast(mc->dmi_addr, catc->multicast);
-
- catc_set_reg_async(catc, RxUnit, rx);
- catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
+ } else {
+ for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) {
+ u32 crc = ether_crc_le(6, mc->dmi_addr);
+ if (!catc->is_f5u011) {
+ catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
+ } else {
+ catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7);
+ }
+ }
+ }
+ if (!catc->is_f5u011) {
+ catc_set_reg_async(catc, RxUnit, rx);
+ catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
+ } else {
+ f5u011_mchash_async(catc, catc->multicast);
+ if (catc->rxmode[0] != rx) {
+ catc->rxmode[0] = rx;
+ dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0], catc->rxmode[1]);
+ f5u011_rxmode_async(catc, catc->rxmode);
+ }
+ }
}
/*
@@ -591,6 +672,29 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
return -EFAULT;
return 0;
}
+
+ /* get settings */
+ case ETHTOOL_GSET:
+ if (catc->is_f5u011) {
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET,
+ SUPPORTED_10baseT_Half | SUPPORTED_TP,
+ ADVERTISED_10baseT_Half | ADVERTISED_TP,
+ SPEED_10,
+ DUPLEX_HALF,
+ PORT_TP,
+ 0,
+ XCVR_INTERNAL,
+ AUTONEG_DISABLE,
+ 1,
+ 1
+ };
+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+ return -EFAULT;
+ return 0;
+ } else {
+ return -EOPNOTSUPP;
+ }
+
/* get link status */
case ETHTOOL_GLINK: {
struct ethtool_value edata = {ETHTOOL_GLINK};
@@ -632,7 +736,8 @@ static int catc_open(struct net_device *netdev)
netif_start_queue(netdev);
- mod_timer(&catc->timer, jiffies + STATS_UPDATE);
+ if (!catc->is_f5u011)
+ mod_timer(&catc->timer, jiffies + STATS_UPDATE);
return 0;
}
@@ -643,7 +748,8 @@ static int catc_stop(struct net_device *netdev)
netif_stop_queue(netdev);
- del_timer_sync(&catc->timer);
+ if (!catc->is_f5u011)
+ del_timer_sync(&catc->timer);
usb_unlink_urb(catc->rx_urb);
usb_unlink_urb(catc->tx_urb);
@@ -662,7 +768,7 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
struct net_device *netdev;
struct catc *catc;
u8 broadcast[6];
- int i;
+ int i, pktsz;
if (usb_set_interface(usbdev, ifnum, 1)) {
err("Can't set altsetting 1.");
@@ -670,9 +776,16 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
}
catc = kmalloc(sizeof(struct catc), GFP_KERNEL);
+ if (!catc)
+ return NULL;
+
memset(catc, 0, sizeof(struct catc));
netdev = init_etherdev(0, 0);
+ if (!netdev) {
+ kfree(catc);
+ return NULL;
+ }
netdev->open = catc_open;
netdev->hard_start_xmit = catc_hard_start_xmit;
@@ -701,9 +814,26 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) {
err("No free urbs available.");
+ if (catc->ctrl_urb) usb_free_urb(catc->ctrl_urb);
+ if (catc->tx_urb) usb_free_urb(catc->tx_urb);
+ if (catc->rx_urb) usb_free_urb(catc->rx_urb);
+ if (catc->irq_urb) usb_free_urb(catc->irq_urb);
+ kfree(netdev);
+ kfree(catc);
return NULL;
}
+ /* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
+ if (usbdev->descriptor.idVendor == 0x0423 && usbdev->descriptor.idProduct == 0xa &&
+ catc->usbdev->descriptor.bcdDevice == 0x0130 ) {
+ dbg("Testing for f5u011");
+ catc->is_f5u011 = 1;
+ atomic_set(&catc->recq_sz, 0);
+ pktsz = RX_PKT_SZ;
+ } else {
+ pktsz = RX_MAX_BURST * (PKT_SZ + 2);
+ }
+
FILL_CONTROL_URB(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
NULL, NULL, 0, catc_ctrl_done, catc);
@@ -711,20 +841,21 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
NULL, 0, catc_tx_done, catc);
FILL_BULK_URB(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
- catc->rx_buf, RX_MAX_BURST * (PKT_SZ + 2), catc_rx_done, catc);
+ catc->rx_buf, pktsz, catc_rx_done, catc);
FILL_INT_URB(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
catc->irq_buf, 2, catc_irq_done, catc, 1);
- dbg("Checking memory size\n");
-
- i = 0x12345678;
- catc_write_mem(catc, 0x7a80, &i, 4);
- i = 0x87654321;
- catc_write_mem(catc, 0xfa80, &i, 4);
- catc_read_mem(catc, 0x7a80, &i, 4);
+ if (!catc->is_f5u011) {
+ dbg("Checking memory size\n");
- switch (i) {
+ i = 0x12345678;
+ catc_write_mem(catc, 0x7a80, &i, 4);
+ i = 0x87654321;
+ catc_write_mem(catc, 0xfa80, &i, 4);
+ catc_read_mem(catc, 0x7a80, &i, 4);
+
+ switch (i) {
case 0x12345678:
catc_set_reg(catc, TxBufCount, 8);
catc_set_reg(catc, RxBufCount, 32);
@@ -737,44 +868,52 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
catc_set_reg(catc, RxBufCount, 16);
dbg("32k Memory\n");
break;
+ }
+
+ dbg("Getting MAC from SEEROM.");
+
+ catc_get_mac(catc, netdev->dev_addr);
+
+ dbg("Setting MAC into registers.");
+
+ for (i = 0; i < 6; i++)
+ catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
+
+ dbg("Filling the multicast list.");
+
+ memset(broadcast, 0xff, 6);
+ catc_multicast(broadcast, catc->multicast);
+ catc_multicast(netdev->dev_addr, catc->multicast);
+ catc_write_mem(catc, 0xfa80, catc->multicast, 64);
+
+ dbg("Clearing error counters.");
+
+ for (i = 0; i < 8; i++)
+ catc_set_reg(catc, EthStats + i, 0);
+ catc->last_stats = jiffies;
+
+ dbg("Enabling.");
+
+ catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
+ catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
+ catc_set_reg(catc, LEDCtrl, LEDLink);
+ catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
+ } else {
+ dbg("Performing reset\n");
+ catc_reset(catc);
+ catc_get_mac(catc, netdev->dev_addr);
+
+ dbg("Setting RX Mode");
+ catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;
+ catc->rxmode[1] = 0;
+ f5u011_rxmode(catc, catc->rxmode);
}
-
- dbg("Getting MAC from SEEROM.");
-
- catc_get_mac(catc, netdev->dev_addr);
-
- dbg("Setting MAC into registers.");
-
- for (i = 0; i < 6; i++)
- catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
-
- dbg("Filling the multicast list.");
-
- memset(broadcast, 0xff, 8);
- catc_multicast(broadcast, catc->multicast);
- catc_multicast(netdev->dev_addr, catc->multicast);
- catc_write_mem(catc, 0xfa80, catc->multicast, 64);
-
- dbg("Clearing error counters.");
-
- for (i = 0; i < 8; i++)
- catc_set_reg(catc, EthStats + i, 0);
- catc->last_stats = jiffies;
-
- dbg("Enabling.");
-
- catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
- catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
- catc_set_reg(catc, LEDCtrl, LEDLink);
- catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
-
dbg("Init done.");
-
- printk(KERN_INFO "%s: CATC EL1210A NetMate USB Ethernet at usb%d:%d.%d, ",
- netdev->name, usbdev->bus->busnum, usbdev->devnum, ifnum);
+ printk(KERN_INFO "%s: %s USB Ethernet at usb%d:%d.%d, ",
+ netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",
+ usbdev->bus->busnum, usbdev->devnum, ifnum);
for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);
printk("%2.2x.\n", netdev->dev_addr[i]);
-
return catc;
}
@@ -795,7 +934,7 @@ static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr)
*/
static struct usb_device_id catc_id_table [] = {
- { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate */
+ { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate, Belkin F5U011 */
{ USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */
{ USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */
{ }
diff --git a/drivers/usb/hid-core.c b/drivers/usb/hid-core.c
index 5b3f0c64273e..0bb17425bc39 100644
--- a/drivers/usb/hid-core.c
+++ b/drivers/usb/hid-core.c
@@ -110,10 +110,11 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+ values * sizeof(unsigned));
- report->field[report->maxfield++] = field;
+ report->field[report->maxfield] = field;
field->usage = (struct hid_usage *)(field + 1);
field->value = (unsigned *)(field->usage + usages);
field->report = report;
+ field->index = report->maxfield++;
return field;
}
@@ -741,8 +742,20 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_hid_event(hid, field, usage, value);
#ifdef CONFIG_USB_HIDDEV
- if (hid->claimed & HID_CLAIMED_HIDDEV)
- hiddev_hid_event(hid, usage->hid, value);
+ if (hid->claimed & HID_CLAIMED_HIDDEV) {
+ struct hiddev_usage_ref uref;
+ unsigned type = field->report_type;
+ uref.report_type =
+ (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
+ ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
+ ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+ uref.report_id = field->report->id;
+ uref.field_index = field->index;
+ uref.usage_index = (usage - field->usage);
+ uref.usage_code = usage->hid;
+ uref.value = value;
+ hiddev_hid_event(hid, &uref);
+ }
#endif
}
@@ -839,6 +852,21 @@ static int hid_input_report(int type, struct urb *urb)
return -1;
}
+#ifdef CONFIG_USB_HIDDEV
+ /* Notify listeners that a report has been received */
+ if (hid->claimed & HID_CLAIMED_HIDDEV) {
+ struct hiddev_usage_ref uref;
+ memset(&uref, 0, sizeof(uref));
+ uref.report_type =
+ (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
+ ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
+ ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+ uref.report_id = report->id;
+ uref.field_index = HID_FIELD_INDEX_NONE;
+ hiddev_hid_event(hid, &uref);
+ }
+#endif
+
size = ((report->size - 1) >> 3) + 1;
if (len < size) {
@@ -1096,6 +1124,9 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
int head;
unsigned long flags;
+ if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
+ return;
+
if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
spin_lock_irqsave(&hid->outlock, flags);
@@ -1238,18 +1269,27 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_POWERMATE 0x0410
#define USB_DEVICE_ID_SOUNDKNOB 0x04AA
+#define USB_VENDOR_ID_ATEN 0x0557
+#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
+#define USB_DEVICE_ID_ATEN_CS124U 0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
+
struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
+ unsigned quirks;
} hid_blacklist[] = {
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1},
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2},
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3},
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4},
- { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE },
- { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
{ 0, 0 }
};
@@ -1258,13 +1298,17 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
struct hid_descriptor *hdesc;
struct hid_device *hid;
- unsigned rsize = 0;
+ unsigned quirks = 0, rsize = 0;
char *buf;
int n;
for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
- (hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL;
+ (hid_blacklist[n].idProduct == dev->descriptor.idProduct))
+ quirks = hid_blacklist[n].quirks;
+
+ if (quirks & HID_QUIRK_IGNORE)
+ return NULL;
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
@@ -1302,6 +1346,8 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
}
}
+ hid->quirks = quirks;
+
for (n = 0; n < interface->bNumEndpoints; n++) {
struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
diff --git a/drivers/usb/hid.h b/drivers/usb/hid.h
index 77a656f2bcc9..ed72dc6acfd1 100644
--- a/drivers/usb/hid.h
+++ b/drivers/usb/hid.h
@@ -203,6 +203,8 @@ struct hid_item {
#define HID_QUIRK_INVERT 0x01
#define HID_QUIRK_NOTOUCH 0x02
+#define HID_QUIRK_IGNORE 0x04
+#define HID_QUIRK_NOGET 0x08
/*
* This is the global enviroment of the parser. This information is
@@ -276,6 +278,7 @@ struct hid_field {
__s32 unit_exponent;
unsigned unit;
struct hid_report *report; /* associated report */
+ unsigned index; /* index into report->field[] */
};
#define HID_MAX_FIELDS 64
diff --git a/drivers/usb/hiddev.c b/drivers/usb/hiddev.c
index 886a30825a92..5d4029259899 100644
--- a/drivers/usb/hiddev.c
+++ b/drivers/usb/hiddev.c
@@ -50,9 +50,10 @@ struct hiddev {
};
struct hiddev_list {
- struct hiddev_event buffer[HIDDEV_BUFFER_SIZE];
+ struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE];
int head;
int tail;
+ unsigned flags;
struct fasync_struct *fasync;
struct hiddev *hiddev;
struct hiddev_list *next;
@@ -146,17 +147,19 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
* This is where hid.c calls into hiddev to pass an event that occurred over
* the interrupt pipe
*/
-void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value)
+void hiddev_hid_event(struct hid_device *hid, struct hiddev_usage_ref *uref)
{
struct hiddev *hiddev = hid->hiddev;
struct hiddev_list *list = hiddev->list;
while (list) {
- list->buffer[list->head].hid = usage;
- list->buffer[list->head].value = value;
- list->head = (list->head + 1) & (HIDDEV_BUFFER_SIZE - 1);
-
- kill_fasync(&list->fasync, SIGIO, POLL_IN);
+ if (uref->field_index != HID_FIELD_INDEX_NONE ||
+ (list->flags & HIDDEV_FLAG_REPORT) != 0) {
+ list->buffer[list->head] = *uref;
+ list->head = (list->head + 1) &
+ (HIDDEV_BUFFER_SIZE - 1);
+ kill_fasync(&list->fasync, SIGIO, POLL_IN);
+ }
list = list->next;
}
@@ -257,43 +260,67 @@ static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
{
DECLARE_WAITQUEUE(wait, current);
struct hiddev_list *list = file->private_data;
+ int event_size;
int retval = 0;
- if (list->head == list->tail) {
-
- add_wait_queue(&list->hiddev->wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
+ event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
+ sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
- while (list->head == list->tail) {
+ if (count < event_size) return 0;
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- if (!list->hiddev->exist) {
- retval = -EIO;
- break;
+ while (retval == 0) {
+ if (list->head == list->tail) {
+ add_wait_queue(&list->hiddev->wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (list->head == list->tail) {
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (!list->hiddev->exist) {
+ retval = -EIO;
+ break;
+ }
+
+ schedule();
}
- schedule();
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&list->hiddev->wait, &wait);
}
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&list->hiddev->wait, &wait);
- }
-
- if (retval)
- return retval;
+ if (retval)
+ return retval;
+
+
+ while (list->head != list->tail &&
+ retval + event_size <= count) {
+ if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
+ if (list->buffer[list->tail].field_index !=
+ HID_FIELD_INDEX_NONE) {
+ struct hiddev_event event;
+ event.hid = list->buffer[list->tail].usage_code;
+ event.value = list->buffer[list->tail].value;
+ if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
+ return -EFAULT;
+ retval += sizeof(struct hiddev_event);
+ }
+ } else {
+ if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
+ (list->flags & HIDDEV_FLAG_REPORT) != 0) {
+ if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
+ return -EFAULT;
+ retval += sizeof(struct hiddev_usage_ref);
+ }
+ }
+ list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
+ }
- while (list->head != list->tail && retval + sizeof(struct hiddev_event) <= count) {
- if (copy_to_user(buffer + retval, list->buffer + list->tail,
- sizeof(struct hiddev_event))) return -EFAULT;
- list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
- retval += sizeof(struct hiddev_event);
}
return retval;
@@ -358,6 +385,25 @@ static int hiddev_ioctl(struct inode *inode, struct file *file,
return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
}
+ case HIDIOCGFLAG:
+ return put_user(list->flags, (int *) arg);
+
+ case HIDIOCSFLAG:
+ {
+ int newflags;
+ if (get_user(newflags, (int *) arg))
+ return -EFAULT;
+
+ if ((newflags & ~HIDDEV_FLAGS) != 0 ||
+ ((newflags & HIDDEV_FLAG_REPORT) != 0 &&
+ (newflags & HIDDEV_FLAG_UREF) == 0))
+ return -EINVAL;
+
+ list->flags = newflags;
+
+ return 0;
+ }
+
case HIDIOCGSTRING:
{
int idx, len;
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index 6025a0176103..00ea80dfca00 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -1,10 +1,12 @@
/*
- * printer.c Version 0.8
+ * printer.c Version 0.12
*
* Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
* Copyright (c) 2000 Randy Dunlap <randy.dunlap@intel.com>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
+ # Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com>
+ # Copyright (c) 2001 David Paschal <paschal@rcsis.com>
*
* USB Printer Device Class driver for USB printers and printer cables
*
@@ -17,10 +19,12 @@
* v0.4 - fixes in unidirectional mode
* v0.5 - add DEVICE_ID string support
* v0.6 - never time out
- * v0.7 - fixed bulk-IN read and poll (David Paschal, paschal@rcsis.com)
+ * v0.7 - fixed bulk-IN read and poll (David Paschal)
* v0.8 - add devfs support
* v0.9 - fix unplug-while-open paths
* v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
+ * v0.11 - add proto_bias option (Pete Zaitcev)
+ * v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
*/
/*
@@ -55,16 +59,36 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.10"
-#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap"
+#define DRIVER_VERSION "v0.12"
+#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
#define DRIVER_DESC "USB Printer Device Class driver"
#define USBLP_BUF_SIZE 8192
#define DEVICE_ID_SIZE 1024
-#define IOCNR_GET_DEVICE_ID 1
-#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) /* get device_id string */
+/* ioctls: */
#define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
+#define IOCNR_GET_DEVICE_ID 1
+#define IOCNR_GET_PROTOCOLS 2
+#define IOCNR_SET_PROTOCOL 3
+#define IOCNR_HP_SET_CHANNEL 4
+#define IOCNR_GET_BUS_ADDRESS 5
+#define IOCNR_GET_VID_PID 6
+/* Get device_id string: */
+#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
+/* The following ioctls were added for http://hpoj.sourceforge.net: */
+/* Get two-int array:
+ * [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
+ * [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */
+#define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len)
+/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */
+#define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0)
+/* Set channel number (HP Vendor-specific command): */
+#define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0)
+/* Get two-int array: [0]=bus number, [1]=device address: */
+#define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
+/* Get two-int array: [0]=vendor ID, [1]=product ID: */
+#define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
/*
* A DEVICE_ID string may include the printer's serial number.
@@ -78,26 +102,40 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
* USB Printer Requests
*/
-#define USBLP_REQ_GET_ID 0x00
-#define USBLP_REQ_GET_STATUS 0x01
-#define USBLP_REQ_RESET 0x02
+#define USBLP_REQ_GET_ID 0x00
+#define USBLP_REQ_GET_STATUS 0x01
+#define USBLP_REQ_RESET 0x02
+#define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST 0x00 /* HP Vendor-specific */
#define USBLP_MINORS 16
#define USBLP_MINOR_BASE 0
#define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */
+#define USBLP_FIRST_PROTOCOL 1
+#define USBLP_LAST_PROTOCOL 3
+#define USBLP_MAX_PROTOCOLS (USBLP_LAST_PROTOCOL+1)
+
struct usblp {
struct usb_device *dev; /* USB device */
devfs_handle_t devfs; /* devfs device */
struct semaphore sem; /* locks this struct, especially "dev" */
+ char *buf; /* writeurb->transfer_buffer */
struct urb *readurb, *writeurb; /* The urbs */
wait_queue_head_t wait; /* Zzzzz ... */
int readcount; /* Counter for reads */
int ifnum; /* Interface number */
+ /* Alternate-setting numbers and endpoints for each protocol
+ * (7/1/{index=1,2,3}) that the device supports: */
+ struct {
+ int alt_setting;
+ struct usb_endpoint_descriptor *epwrite;
+ struct usb_endpoint_descriptor *epread;
+ } protocol[USBLP_MAX_PROTOCOLS];
+ int current_protocol;
int minor; /* minor number of device */
int wcomplete; /* writing is completed */
- int rcomplete; /* reading is completed */
+ int rcomplete; /* reading is completed */
unsigned int quirks; /* quirks flags */
unsigned char used; /* True if open */
unsigned char bidir; /* interface is bidirectional */
@@ -105,6 +143,35 @@ struct usblp {
/* first 2 bytes are (big-endian) length */
};
+#ifdef DEBUG
+static void usblp_dump(struct usblp *usblp) {
+ int p;
+
+ dbg("usblp=0x%p", usblp);
+ dbg("dev=0x%p", usblp->dev);
+ dbg("devfs=0x%p", usblp->devfs);
+ dbg("buf=0x%p", usblp->buf);
+ dbg("readcount=%d", usblp->readcount);
+ dbg("ifnum=%d", usblp->ifnum);
+ for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
+ dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
+ dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
+ dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
+ }
+ dbg("current_protocol=%d", usblp->current_protocol);
+ dbg("minor=%d", usblp->minor);
+ dbg("wcomplete=%d", usblp->wcomplete);
+ dbg("rcomplete=%d", usblp->rcomplete);
+ dbg("quirks=%d", usblp->quirks);
+ dbg("used=%d", usblp->used);
+ dbg("bidir=%d", usblp->bidir);
+ dbg("device_id_string=\"%s\"",
+ usblp->device_id_string ?
+ usblp->device_id_string + 2 :
+ (unsigned char *)"(null)");
+}
+#endif
+
extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
static struct usblp *usblp_table[USBLP_MINORS];
@@ -126,29 +193,45 @@ static struct quirk_printer_struct quirk_printers[] = {
{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
+ { 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
{ 0, 0 }
};
+static int usblp_select_alts(struct usblp *usblp);
+static int usblp_set_protocol(struct usblp *usblp, int protocol);
+static int usblp_cache_device_id_string(struct usblp *usblp);
+
+
/*
* Functions for usblp control messages.
*/
-static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, int value, void *buf, int len)
+static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len)
{
int retval = usb_control_msg(usblp->dev,
dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
- request, USB_TYPE_CLASS | dir | recip, value, usblp->ifnum, buf, len, HZ * 5);
+ request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT);
dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
request, !!dir, recip, value, len, retval);
return retval < 0 ? retval : 0;
}
#define usblp_read_status(usblp, status)\
- usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
+ usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
#define usblp_get_id(usblp, config, id, maxlen)\
- usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
+ usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
#define usblp_reset(usblp)\
- usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
+ usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
+
+#define usblp_hp_channel_change_request(usblp, channel, buffer) \
+ usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1)
+
+/*
+ * See the description for usblp_select_alts() below for the usage
+ * explanation. Look into your /proc/bus/usb/devices and dmesg in
+ * case of any trouble.
+ */
+static int proto_bias = -1;
/*
* URB callback.
@@ -276,7 +359,7 @@ static void usblp_cleanup (struct usblp *usblp)
{
devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL;
- info ("usblp%d: removed", usblp->minor);
+ info("usblp%d: removed", usblp->minor);
kfree (usblp->writeurb->transfer_buffer);
kfree (usblp->device_id_string);
@@ -285,6 +368,13 @@ static void usblp_cleanup (struct usblp *usblp)
kfree (usblp);
}
+static void usblp_unlink_urbs(struct usblp *usblp)
+{
+ usb_unlink_urb(usblp->writeurb);
+ if (usblp->bidir)
+ usb_unlink_urb(usblp->readurb);
+}
+
static int usblp_release(struct inode *inode, struct file *file)
{
struct usblp *usblp = file->private_data;
@@ -293,9 +383,7 @@ static int usblp_release(struct inode *inode, struct file *file)
lock_kernel();
usblp->used = 0;
if (usblp->dev) {
- if (usblp->bidir)
- usb_unlink_urb(usblp->readurb);
- usb_unlink_urb(usblp->writeurb);
+ usblp_unlink_urbs(usblp);
up(&usblp->sem);
} else /* finish cleanup from disconnect */
usblp_cleanup (usblp);
@@ -315,8 +403,9 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct usblp *usblp = file->private_data;
- int length, err;
- unsigned char status;
+ int length, err, i;
+ unsigned char status, newChannel;
+ int twoints[2];
int retval = 0;
down (&usblp->sem);
@@ -335,32 +424,128 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
goto done;
}
- err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
+ length = usblp_cache_device_id_string(usblp);
+ if (length < 0) {
+ retval = length;
+ goto done;
+ }
+ if (length > _IOC_SIZE(cmd))
+ length = _IOC_SIZE(cmd); /* truncate */
+
+ if (copy_to_user((unsigned char *) arg,
+ usblp->device_id_string,
+ (unsigned long) length)) {
+ retval = -EFAULT;
+ goto done;
+ }
+
+ break;
+
+ case IOCNR_GET_PROTOCOLS:
+ if (_IOC_DIR(cmd) != _IOC_READ ||
+ _IOC_SIZE(cmd) < sizeof(twoints)) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+ twoints[0] = usblp->current_protocol;
+ twoints[1] = 0;
+ for (i = USBLP_FIRST_PROTOCOL;
+ i <= USBLP_LAST_PROTOCOL; i++) {
+ if (usblp->protocol[i].alt_setting >= 0)
+ twoints[1] |= (1<<i);
+ }
+
+ if (copy_to_user((unsigned char *)arg,
+ (unsigned char *)twoints,
+ sizeof(twoints))) {
+ retval = -EFAULT;
+ goto done;
+ }
+
+ break;
+
+ case IOCNR_SET_PROTOCOL:
+ if (_IOC_DIR(cmd) != _IOC_WRITE) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+#ifdef DEBUG
+ if (arg == -10) {
+ usblp_dump(usblp);
+ break;
+ }
+#endif
+
+ usblp_unlink_urbs(usblp);
+ retval = usblp_set_protocol(usblp, arg);
+ if (retval < 0) {
+ usblp_set_protocol(usblp,
+ usblp->current_protocol);
+ }
+ break;
+
+ case IOCNR_HP_SET_CHANNEL:
+ if (_IOC_DIR(cmd) != _IOC_WRITE ||
+ usblp->dev->descriptor.idVendor != 0x03F0 ||
+ usblp->quirks & USBLP_QUIRK_BIDIR) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+ err = usblp_hp_channel_change_request(usblp,
+ arg, &newChannel);
if (err < 0) {
- dbg ("usblp%d: error = %d reading IEEE-1284 Device ID string",
+ err("usblp%d: error = %d setting "
+ "HP channel",
usblp->minor, err);
- usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
retval = -EIO;
goto done;
}
- length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
- if (length < DEVICE_ID_SIZE)
- usblp->device_id_string[length] = '\0';
- else
- usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
+ dbg("usblp%d requested/got HP channel %ld/%d",
+ usblp->minor, arg, newChannel);
+ break;
- dbg ("usblp%d Device ID string [%d/max %d]='%s'",
- usblp->minor, length, _IOC_SIZE(cmd), &usblp->device_id_string[2]);
+ case IOCNR_GET_BUS_ADDRESS:
+ if (_IOC_DIR(cmd) != _IOC_READ ||
+ _IOC_SIZE(cmd) < sizeof(twoints)) {
+ retval = -EINVAL;
+ goto done;
+ }
- if (length > _IOC_SIZE(cmd)) length = _IOC_SIZE(cmd); /* truncate */
+ twoints[0] = usblp->dev->bus->busnum;
+ twoints[1] = usblp->dev->devnum;
+ if (copy_to_user((unsigned char *)arg,
+ (unsigned char *)twoints,
+ sizeof(twoints))) {
+ retval = -EFAULT;
+ goto done;
+ }
- if (copy_to_user((unsigned char *) arg,
- usblp->device_id_string, (unsigned long) length)) {
+ dbg("usblp%d is bus=%d, device=%d",
+ usblp->minor, twoints[0], twoints[1]);
+ break;
+
+ case IOCNR_GET_VID_PID:
+ if (_IOC_DIR(cmd) != _IOC_READ ||
+ _IOC_SIZE(cmd) < sizeof(twoints)) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+ twoints[0] = usblp->dev->descriptor.idVendor;
+ twoints[1] = usblp->dev->descriptor.idProduct;
+ if (copy_to_user((unsigned char *)arg,
+ (unsigned char *)twoints,
+ sizeof(twoints))) {
retval = -EFAULT;
goto done;
}
+ dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
+ usblp->minor, twoints[0], twoints[1]);
break;
default:
@@ -593,155 +778,268 @@ static struct file_operations usblp_fops = {
static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
- struct usb_interface_descriptor *interface;
- struct usb_endpoint_descriptor *epread, *epwrite;
- struct usblp *usblp;
- int minor, i, bidir = 0, quirks;
- int alts = dev->actconfig->interface[ifnum].act_altsetting;
- int length, err;
- char *buf;
+ struct usblp *usblp = 0;
+ int protocol;
char name[6];
- /* If a bidirectional interface exists, use it. */
- for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) {
-
- interface = &dev->actconfig->interface[ifnum].altsetting[i];
-
- if (interface->bInterfaceClass != 7 || interface->bInterfaceSubClass != 1 ||
- interface->bInterfaceProtocol < 1 || interface->bInterfaceProtocol > 3 ||
- (interface->bInterfaceProtocol > 1 && interface->bNumEndpoints < 2))
- continue;
-
- if (interface->bInterfaceProtocol > 1) {
- bidir = 1;
- alts = i;
- break;
- }
- }
-
- interface = &dev->actconfig->interface[ifnum].altsetting[alts];
- if (usb_set_interface(dev, ifnum, alts))
- err("can't set desired altsetting %d on interface %d", alts, ifnum);
-
- epwrite = interface->endpoint + 0;
- epread = bidir ? interface->endpoint + 1 : NULL;
-
- if ((epwrite->bEndpointAddress & 0x80) == 0x80) {
- if (interface->bNumEndpoints == 1)
- return NULL;
- epwrite = interface->endpoint + 1;
- epread = bidir ? interface->endpoint + 0 : NULL;
- }
-
- if ((epwrite->bEndpointAddress & 0x80) == 0x80)
- return NULL;
-
- if (bidir && (epread->bEndpointAddress & 0x80) != 0x80)
- return NULL;
-
- for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++);
- if (usblp_table[minor]) {
- err("no more free usblp devices");
- return NULL;
- }
-
+ /* Malloc and start initializing usblp structure so we can use it
+ * directly. */
if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
- err("out of memory");
- return NULL;
+ err("out of memory for usblp");
+ goto abort;
}
memset(usblp, 0, sizeof(struct usblp));
- init_MUTEX (&usblp->sem);
-
- /* lookup quirks for this printer */
- quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
-
- if (bidir && (quirks & USBLP_QUIRK_BIDIR)) {
- bidir = 0;
- epread = NULL;
- info ("Disabling reads from problem bidirectional printer on usblp%d",
- minor);
- }
-
usblp->dev = dev;
+ init_MUTEX (&usblp->sem);
+ init_waitqueue_head(&usblp->wait);
usblp->ifnum = ifnum;
- usblp->minor = minor;
- usblp->bidir = bidir;
- usblp->quirks = quirks;
- init_waitqueue_head(&usblp->wait);
+ /* Look for a free usblp_table entry. */
+ while (usblp_table[usblp->minor]) {
+ usblp->minor++;
+ if (usblp->minor >= USBLP_MINORS) {
+ err("no more free usblp devices");
+ goto abort;
+ }
+ }
usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->writeurb) {
err("out of memory");
- kfree(usblp);
- return NULL;
+ goto abort;
}
usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->readurb) {
err("out of memory");
- usb_free_urb(usblp->writeurb);
- kfree(usblp);
- return NULL;
+ goto abort;
}
- if (!(buf = kmalloc(USBLP_BUF_SIZE * (bidir ? 2 : 1), GFP_KERNEL))) {
- err("out of memory");
- usb_free_urb(usblp->writeurb);
- usb_free_urb(usblp->readurb);
- kfree(usblp);
- return NULL;
+ /* Malloc device ID string buffer to the largest expected length,
+ * since we can re-query it on an ioctl and a dynamic string
+ * could change in length. */
+ if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
+ err("out of memory for device_id_string");
+ goto abort;
}
- if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
- err("out of memory");
- usb_free_urb(usblp->writeurb);
- usb_free_urb(usblp->readurb);
- kfree(usblp);
- kfree(buf);
- return NULL;
+ /* Malloc write/read buffers in one chunk. We somewhat wastefully
+ * malloc both regardless of bidirectionality, because the
+ * alternate setting can be changed later via an ioctl. */
+ if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
+ err("out of memory for buf");
+ goto abort;
}
- FILL_BULK_URB(usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
- buf, 0, usblp_bulk_write, usblp);
+ /* Lookup quirks for this printer. */
+ usblp->quirks = usblp_quirks(
+ dev->descriptor.idVendor,
+ dev->descriptor.idProduct);
+
+ /* Analyze and pick initial alternate settings and endpoints. */
+ protocol = usblp_select_alts(usblp);
+ if (protocol < 0) {
+ dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
+ dev->descriptor.idVendor,
+ dev->descriptor.idProduct);
+ goto abort;
+ }
- if (bidir)
- FILL_BULK_URB(usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
- buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk_read, usblp);
+ /* Setup the selected alternate setting and endpoints. */
+ if (usblp_set_protocol(usblp, protocol) < 0)
+ goto abort;
- /* Get the device_id string if possible. FIXME: Could make this kmalloc(length). */
- err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
- if (err >= 0) {
- length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
- if (length < DEVICE_ID_SIZE)
- usblp->device_id_string[length] = '\0';
- else
- usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
- dbg ("usblp%d Device ID string [%d]=%s",
- minor, length, &usblp->device_id_string[2]);
- }
- else {
- err ("usblp%d: error = %d reading IEEE-1284 Device ID string",
- minor, err);
- usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
- }
+ /* Retrieve and store the device ID string. */
+ usblp_cache_device_id_string(usblp);
#ifdef DEBUG
usblp_check_status(usblp, 0);
#endif
- sprintf(name, "lp%d", minor);
-
- /* if we have devfs, create with perms=660 */
+ /* If we have devfs, create with perms=660. */
+ sprintf(name, "lp%d", usblp->minor);
usblp->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
- USBLP_MINOR_BASE + minor,
+ USBLP_MINOR_BASE + usblp->minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &usblp_fops, NULL);
- info("usblp%d: USB %sdirectional printer dev %d if %d alt %d",
- minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
+ info("usblp%d: USB %sdirectional printer dev %d "
+ "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
+ usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, ifnum,
+ usblp->protocol[usblp->current_protocol].alt_setting,
+ usblp->current_protocol, usblp->dev->descriptor.idVendor,
+ usblp->dev->descriptor.idProduct);
- return usblp_table[minor] = usblp;
+ return usblp_table[usblp->minor] = usblp;
+
+abort:
+ if (usblp) {
+ usb_free_urb(usblp->writeurb);
+ usb_free_urb(usblp->readurb);
+ if (usblp->buf) kfree(usblp->buf);
+ if (usblp->device_id_string) kfree(usblp->device_id_string);
+ kfree(usblp);
+ }
+ return NULL;
+}
+
+/*
+ * We are a "new" style driver with usb_device_id table,
+ * but our requirements are too intricate for simple match to handle.
+ *
+ * The "proto_bias" option may be used to specify the preferred protocol
+ * for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3). If the device
+ * supports the preferred protocol, then we bind to it.
+ *
+ * The best interface for us is 7/1/2, because it is compatible
+ * with a stream of characters. If we find it, we bind to it.
+ *
+ * Note that the people from hpoj.sourceforge.net need to be able to
+ * bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
+ *
+ * Failing 7/1/2, we look for 7/1/3, even though it's probably not
+ * stream-compatible, because this matches the behaviour of the old code.
+ *
+ * If nothing else, we bind to 7/1/1 - the unidirectional interface.
+ */
+static int usblp_select_alts(struct usblp *usblp)
+{
+ struct usb_interface *if_alt;
+ struct usb_interface_descriptor *ifd;
+ struct usb_endpoint_descriptor *epd, *epwrite, *epread;
+ int p, i, e;
+
+ if_alt = &usblp->dev->actconfig->interface[usblp->ifnum];
+
+ for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
+ usblp->protocol[p].alt_setting = -1;
+
+ /* Find out what we have. */
+ for (i = 0; i < if_alt->num_altsetting; i++) {
+ ifd = &if_alt->altsetting[i];
+
+ if (ifd->bInterfaceClass != 7 || ifd->bInterfaceSubClass != 1)
+ continue;
+
+ if (ifd->bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
+ ifd->bInterfaceProtocol > USBLP_LAST_PROTOCOL)
+ continue;
+
+ /* Look for bulk OUT and IN endpoints. */
+ epwrite = epread = 0;
+ for (e = 0; e < ifd->bNumEndpoints; e++) {
+ epd = &ifd->endpoint[e];
+
+ if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
+ USB_ENDPOINT_XFER_BULK)
+ continue;
+
+ if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
+ if (!epwrite) epwrite=epd;
+
+ } else {
+ if (!epread) epread=epd;
+ }
+ }
+
+ /* Ignore buggy hardware without the right endpoints. */
+ if (!epwrite || (ifd->bInterfaceProtocol > 1 && !epread))
+ continue;
+
+ /* Turn off reads for 7/1/1 (unidirectional) interfaces
+ * and buggy bidirectional printers. */
+ if (ifd->bInterfaceProtocol == 1) {
+ epread = NULL;
+ } else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
+ info("Disabling reads from problem bidirectional "
+ "printer on usblp%d", usblp->minor);
+ epread = NULL;
+ }
+
+ usblp->protocol[ifd->bInterfaceProtocol].alt_setting = i;
+ usblp->protocol[ifd->bInterfaceProtocol].epwrite = epwrite;
+ usblp->protocol[ifd->bInterfaceProtocol].epread = epread;
+ }
+
+ /* If our requested protocol is supported, then use it. */
+ if (proto_bias >= USBLP_FIRST_PROTOCOL &&
+ proto_bias <= USBLP_LAST_PROTOCOL &&
+ usblp->protocol[proto_bias].alt_setting != -1)
+ return proto_bias;
+
+ /* Ordering is important here. */
+ if (usblp->protocol[2].alt_setting != -1) return 2;
+ if (usblp->protocol[1].alt_setting != -1) return 1;
+ if (usblp->protocol[3].alt_setting != -1) return 3;
+
+ /* If nothing is available, then don't bind to this device. */
+ return -1;
+}
+
+static int usblp_set_protocol(struct usblp *usblp, int protocol)
+{
+ int r, alts;
+
+ if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
+ return -EINVAL;
+
+ alts = usblp->protocol[protocol].alt_setting;
+ if (alts < 0) return -EINVAL;
+ r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
+ if (r < 0) {
+ err("can't set desired altsetting %d on interface %d",
+ alts, usblp->ifnum);
+ return r;
+ }
+
+ FILL_BULK_URB(usblp->writeurb, usblp->dev,
+ usb_sndbulkpipe(usblp->dev,
+ usblp->protocol[protocol].epwrite->bEndpointAddress),
+ usblp->buf, 0,
+ usblp_bulk_write, usblp);
+
+ usblp->bidir = (usblp->protocol[protocol].epread != 0);
+ if (usblp->bidir)
+ FILL_BULK_URB(usblp->readurb, usblp->dev,
+ usb_rcvbulkpipe(usblp->dev,
+ usblp->protocol[protocol].epread->bEndpointAddress),
+ usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
+ usblp_bulk_read, usblp);
+
+ usblp->current_protocol = protocol;
+ dbg("usblp%d set protocol %d", usblp->minor, protocol);
+ return 0;
+}
+
+/* Retrieves and caches device ID string.
+ * Returns length, including length bytes but not null terminator.
+ * On error, returns a negative errno value. */
+static int usblp_cache_device_id_string(struct usblp *usblp)
+{
+ int err, length;
+
+ err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
+ if (err < 0) {
+ dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
+ usblp->minor, err);
+ usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
+ return -EIO;
+ }
+
+ /* First two bytes are length in big-endian.
+ * They count themselves, and we copy them into
+ * the user's buffer. */
+ length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
+ if (length < 2)
+ length = 2;
+ else if (length >= DEVICE_ID_SIZE)
+ length = DEVICE_ID_SIZE - 1;
+ usblp->device_id_string[length] = '\0';
+
+ dbg("usblp%d Device ID string [len=%d]=\"%s\"",
+ usblp->minor, length, &usblp->device_id_string[2]);
+
+ return length;
}
static void usblp_disconnect(struct usb_device *dev, void *ptr)
@@ -757,9 +1055,7 @@ static void usblp_disconnect(struct usb_device *dev, void *ptr)
lock_kernel();
usblp->dev = NULL;
- usb_unlink_urb(usblp->writeurb);
- if (usblp->bidir)
- usb_unlink_urb(usblp->readurb);
+ usblp_unlink_urbs(usblp);
if (!usblp->used)
usblp_cleanup (usblp);
@@ -794,7 +1090,7 @@ static int __init usblp_init(void)
{
if (usb_register(&usblp_driver))
return -1;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ info(DRIVER_VERSION ": " DRIVER_DESC);
return 0;
}
@@ -808,5 +1104,6 @@ module_exit(usblp_exit);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_PARM(proto_bias, "i");
+MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index f185987c6541..812726b110fa 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -262,7 +262,7 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u
port);
/* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
/* Throw away data. No better idea what to do with it. */
@@ -331,7 +331,7 @@ static void cyberjack_read_int_callback( struct urb *urb )
if( !old_rdtodo ) {
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if( result )
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
@@ -387,7 +387,7 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
/* Continue to read if we have still urbs to do. */
if( priv->rdtodo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
@@ -440,7 +440,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
port);
/* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
/* Throw away data. No better idea what to do with it. */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 621af4d63ebc..a03c9b4a9a1d 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -676,7 +676,7 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, co
oob_port->write_urb->transfer_buffer_length = len;
oob_port->write_urb->dev = port->serial->dev;
- if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) {
oob_priv->dp_write_urb_in_use = 1;
count -= len;
buf += len;
@@ -764,7 +764,7 @@ count );
}
port->write_urb->dev = port->serial->dev;
- if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
count -= len;
@@ -841,7 +841,7 @@ port_priv->dp_port_num, modem_signals );
oob_port->write_urb->transfer_buffer_length = 8;
oob_port->write_urb->dev = port->serial->dev;
- if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) {
oob_priv->dp_write_urb_in_use = 1;
port_priv->dp_modem_signals =
(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
@@ -962,7 +962,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
/* restart read chain */
if( priv->dp_throttle_restart ) {
port->read_urb->dev = port->serial->dev;
- ret = usb_submit_urb( port->read_urb, GFP_KERNEL );
+ ret = usb_submit_urb( port->read_urb, GFP_ATOMIC );
}
/* turn throttle off */
@@ -1323,7 +1323,7 @@ priv->dp_port_num, count, from_user, in_interrupt() );
/* copy in new data */
memcpy( data, from_user ? user_buf : buf, new_len );
- if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1;
ret = new_len;
priv->dp_out_buf_len = 0;
@@ -1399,7 +1399,7 @@ dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf,
priv->dp_out_buf_len );
- if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
}
@@ -1837,7 +1837,7 @@ dbg( "digi_read_bulk_callback: TOP" );
/* continue read */
urb->dev = port->serial->dev;
- if( (ret=usb_submit_urb(urb, GFP_KERNEL)) != 0 ) {
+ if( (ret=usb_submit_urb(urb, GFP_ATOMIC)) != 0 ) {
err( __FUNCTION__ ": failed resubmitting urb, ret=%d, port=%d",
ret, priv->dp_port_num );
}
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 3a636d7a4740..fa390d5c32cc 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -256,7 +256,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
}
if (urb->transfer_buffer == NULL) {
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
err(__FUNCTION__" no more kernel memory...");
goto exit;
@@ -288,7 +288,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
- status = usb_submit_urb(urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
bytes_sent = status;
@@ -441,7 +441,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_flags |= USB_QUEUE_BULK;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
@@ -466,7 +466,7 @@ static void empeg_unthrottle (struct usb_serial_port *port)
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 911d3ac53f94..fc07f8f67835 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -469,7 +469,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
port->write_urb->transfer_buffer, count,
ftdi_sio_write_bulk_callback, port);
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
return 0;
@@ -631,7 +631,7 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ftdi_sio_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 60194ede19d8..393fbafd21e2 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -790,7 +790,7 @@ static void edge_interrupt_callback (struct urb *urb)
/* we have pending bytes on the bulk in pipe, send a request */
edge_serial->read_urb->dev = edge_serial->serial->dev;
- result = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (result) {
dbg(__FUNCTION__" - usb_submit_urb(read bulk) failed with result = %d", result);
}
@@ -867,7 +867,7 @@ static void edge_bulk_in_callback (struct urb *urb)
/* there is, so resubmit our urb */
edge_serial->read_urb->dev = edge_serial->serial->dev;
- status = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL);
+ status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (status) {
err(__FUNCTION__" - usb_submit_urb(read bulk) failed, status = %d", status);
}
@@ -1435,7 +1435,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
/* build the data header for the buffer and port that we are about to send out */
count = fifo->count;
- buffer = kmalloc (count+2, GFP_KERNEL);
+ buffer = kmalloc (count+2, GFP_ATOMIC);
if (buffer == NULL) {
err(__FUNCTION__" - no more kernel memory...");
edge_port->write_in_progress = FALSE;
@@ -1474,7 +1474,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
urb->transfer_flags |= USB_QUEUE_BULK;
urb->dev = edge_serial->serial->dev;
- status = usb_submit_urb(urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
@@ -2431,7 +2431,7 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
dbg(__FUNCTION__" - %d, %d", command, param);
- buffer = kmalloc (10, GFP_KERNEL);
+ buffer = kmalloc (10, GFP_ATOMIC);
if (!buffer) {
err(__FUNCTION__" - kmalloc(%d) failed.\n", 10);
return -ENOMEM;
@@ -2467,7 +2467,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer);
/* Allocate our next urb */
- urb = usb_alloc_urb (0, GFP_KERNEL);
+ urb = usb_alloc_urb (0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
@@ -2482,7 +2482,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
urb->transfer_flags |= USB_QUEUE_BULK;
edge_port->commandPending = TRUE;
- status = usb_submit_urb(urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
@@ -2532,7 +2532,7 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
}
// Alloc memory for the string of commands.
- cmdBuffer = kmalloc (0x100, GFP_KERNEL);
+ cmdBuffer = kmalloc (0x100, GFP_ATOMIC);
if (!cmdBuffer) {
err(__FUNCTION__" - kmalloc(%d) failed.\n", 0x100);
return -ENOMEM;
@@ -2618,7 +2618,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
dbg (__FUNCTION__" - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", regValue);
// Alloc memory for the string of commands.
- cmdBuffer = kmalloc (0x10, GFP_KERNEL);
+ cmdBuffer = kmalloc (0x10, GFP_ATOMIC);
if (cmdBuffer == NULL ) {
return -ENOMEM;
}
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index c839920d236a..c3e9c8791fa9 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -297,7 +297,7 @@ static void ipaq_read_bulk_callback(struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ipaq_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
@@ -412,7 +412,7 @@ static int ipaq_write_flush(struct usb_serial_port *port)
usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
port);
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
}
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index f44ae514529a..5a8f68918b67 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -405,7 +405,7 @@ static int ir_write (struct usb_serial_port *port, int from_user, const unsigned
= USB_QUEUE_BULK
| USB_ZERO_PACKET;
- result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
else
@@ -515,7 +515,7 @@ static void ir_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_flags = USB_QUEUE_BULK;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err("%s - failed resubmitting read urb, error %d",
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index d8d8a2e83bb2..2879204149e1 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -378,7 +378,7 @@ static int keyspan_write(struct usb_serial_port *port, int from_user,
this_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
this_urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
dbg("usb_submit_urb(write bulk) failed (%d)\n", err);
}
p_priv->tx_start_time[flip] = jiffies;
@@ -436,7 +436,7 @@ static void usa26_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
return;
@@ -535,7 +535,7 @@ static void usa26_instat_callback(struct urb *urb)
exit:
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
@@ -586,7 +586,7 @@ static void usa28_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n",
err);
}
@@ -671,7 +671,7 @@ static void usa28_instat_callback(struct urb *urb)
exit:
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
@@ -764,7 +764,7 @@ exit:
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
@@ -819,7 +819,7 @@ static void usa49_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index ae37c1ff9b86..54b09b26e43c 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -292,7 +292,7 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
/* just restart the receive interrupt URB */
dbg("keyspan_pda_rx_unthrottle port %d", port->number);
port->interrupt_in_urb->dev = port->serial->dev;
- if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
+ if (usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC))
dbg(" usb_submit_urb(read urb) failed");
return;
}
@@ -584,7 +584,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user,
priv->tx_room -= count;
port->write_urb->dev = port->serial->dev;
- rc = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ rc = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (rc) {
dbg(" usb_submit_urb(write bulk) failed");
goto exit;
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 3aa9c40e2c61..5b0e1b944dcb 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -519,7 +519,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
}
if (urb->transfer_buffer == NULL) {
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
err(__FUNCTION__ " - no more kernel memory...");
goto exit;
@@ -555,7 +555,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
/* send the data out the bulk port */
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__
" - failed submitting write urb, error %d", result);
@@ -721,7 +721,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer_length,
klsi_105_read_bulk_callback,
port);
- rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (rc)
err(__FUNCTION__
" - failed resubmitting read urb, error %d", rc);
@@ -1019,7 +1019,7 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number);
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d",
result);
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 1151d0d2170a..125c4a647ab3 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -470,7 +470,7 @@ static int mct_u232_write (struct usb_serial_port *port, int from_user,
port);
/* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__
" - failed submitting write urb, error %d", result);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 2eb34c553790..457984644e9b 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -265,7 +265,7 @@ static void omninet_read_bulk_callback (struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
urb->transfer_buffer, urb->transfer_buffer_length,
omninet_read_bulk_callback, port);
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
@@ -316,7 +316,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns
wport->write_urb->transfer_buffer_length = 64;
wport->write_urb->dev = serial->dev;
- result = usb_submit_urb(wport->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 57dedd00441c..23adb9024f46 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -195,7 +195,7 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const uns
port->write_urb->transfer_buffer_length = count;
port->write_urb->dev = port->serial->dev;
- result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else
@@ -643,7 +643,7 @@ static void pl2303_read_bulk_callback (struct urb *urb)
dbg (__FUNCTION__ " - caught -EPROTO, resubmitting the urb");
urb->status = 0;
urb->dev = serial->dev;
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
@@ -668,7 +668,7 @@ static void pl2303_read_bulk_callback (struct urb *urb)
/* Schedule the next read _if_ we are still open */
if (port->open_count) {
urb->dev = serial->dev;
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
@@ -697,7 +697,7 @@ static void pl2303_write_bulk_callback (struct urb *urb)
dbg (__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
port->write_urb->transfer_buffer_length = 1;
port->write_urb->dev = port->serial->dev;
- result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting write urb, error %d", result);
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
index 4746b8107f45..6271ade640d6 100644
--- a/drivers/usb/serial/usbserial.c
+++ b/drivers/usb/serial/usbserial.c
@@ -899,7 +899,7 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns
generic_write_bulk_callback), port);
/* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else
@@ -989,7 +989,7 @@ static void generic_read_bulk_callback (struct urb *urb)
((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback :
generic_read_bulk_callback), port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 2ac4489b92d8..29415d2e2fb1 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -344,13 +344,13 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
dbg(__FUNCTION__ " - port %d", port->number);
- buffer = kmalloc (count, GFP_KERNEL);
+ buffer = kmalloc (count, GFP_ATOMIC);
if (!buffer) {
err ("out of memory");
return -ENOMEM;
}
- urb = usb_alloc_urb(0, GFP_KERNEL);
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
err ("no more free urbs");
kfree (buffer);
@@ -377,7 +377,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
- status = usb_submit_urb(urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
count = status;
@@ -491,7 +491,7 @@ static void visor_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
visor_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
@@ -512,7 +512,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number);
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
}
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 4485b3d26936..3a1dcf663a3a 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -240,7 +240,7 @@ static void command_port_read_callback (struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
command_port_read_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
dbg(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}