summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/Makefile107
-rw-r--r--drivers/char/drm/agpsupport.c1
-rw-r--r--drivers/char/drm/auth.c2
-rw-r--r--drivers/char/drm/drm_syms.c146
-rw-r--r--drivers/char/drm/memory.c1
-rw-r--r--drivers/char/drm/r128_bufs.c1
-rw-r--r--drivers/char/drm/r128_drv.c2
-rw-r--r--drivers/char/drm/tdfx_drv.c2
-rw-r--r--drivers/char/n_tty.c4
-rw-r--r--drivers/i2c/Config.in2
-rw-r--r--drivers/ide/pdc202xx.c1
-rw-r--r--drivers/net/acenic.c2
-rw-r--r--drivers/net/gmac.c2
-rw-r--r--drivers/pci/quirks.c14
-rw-r--r--drivers/scsi/README.ibmmca500
-rw-r--r--drivers/scsi/ibmmca.c1917
-rw-r--r--drivers/scsi/ibmmca.h77
-rw-r--r--drivers/scsi/scsi.c2
-rw-r--r--drivers/scsi/sg.c43
-rw-r--r--drivers/sound/Makefile2
-rw-r--r--drivers/usb/acm.c3
-rw-r--r--drivers/usb/audio.c2
-rw-r--r--drivers/usb/dabusb.c1
-rw-r--r--drivers/usb/dsbr100.c3
-rw-r--r--drivers/usb/evdev.c3
-rw-r--r--drivers/usb/hid.c3
-rw-r--r--drivers/usb/ibmcam.c15
-rw-r--r--drivers/usb/iforce.c1
-rw-r--r--drivers/usb/input.c1
-rw-r--r--drivers/usb/joydev.c1
-rw-r--r--drivers/usb/keybdev.c3
-rw-r--r--drivers/usb/microtek.c3
-rw-r--r--drivers/usb/mousedev.c3
-rw-r--r--drivers/usb/ov511.c11
-rw-r--r--drivers/usb/pegasus.c2
-rw-r--r--drivers/usb/printer.c3
-rw-r--r--drivers/usb/rio500.c2
-rw-r--r--drivers/usb/serial/Makefile8
-rw-r--r--drivers/usb/serial/digi_acceleport.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/keyspan.c2
-rw-r--r--drivers/usb/serial/keyspan_pda.c2
-rw-r--r--drivers/usb/serial/visor.c2
-rw-r--r--drivers/usb/serial/whiteheat.c2
-rw-r--r--drivers/usb/storage/Makefile7
-rw-r--r--drivers/usb/storage/scsiglue.c17
-rw-r--r--drivers/usb/storage/scsiglue.h3
-rw-r--r--drivers/usb/storage/sddr09.c635
-rw-r--r--drivers/usb/storage/sddr09.h31
-rw-r--r--drivers/usb/storage/shuttle_usbat.c (renamed from drivers/usb/storage/scm.c)651
-rw-r--r--drivers/usb/storage/shuttle_usbat.h (renamed from drivers/usb/storage/scm.h)60
-rw-r--r--drivers/usb/storage/transport.c34
-rw-r--r--drivers/usb/storage/transport.h9
-rw-r--r--drivers/usb/storage/usb.c44
-rw-r--r--drivers/usb/uhci.c4
-rw-r--r--drivers/usb/usb-ohci.c59
-rw-r--r--drivers/usb/usb-uhci.c2
-rw-r--r--drivers/usb/usbkbd.c1
-rw-r--r--drivers/usb/usbmouse.c1
-rw-r--r--drivers/usb/wacom.c1
-rw-r--r--drivers/video/riva/fbdev.c6
61 files changed, 3213 insertions, 1260 deletions
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 085c48c8f..a83719fb7 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -23,7 +23,7 @@ obj- :=
SUB_DIRS :=
MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia rio
+ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia rio drm agp
#
# This file contains the font map for the default (hardware) font
@@ -109,16 +109,7 @@ else
endif
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
-
obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
-ifeq ($(CONFIG_ATARI_DSP56K),y)
-S = y
-else
- ifeq ($(CONFIG_ATARI_DSP56K),m)
- SM = y
- endif
-endif
-
obj-$(CONFIG_ROCKETPORT) += rocket.o
obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
@@ -135,10 +126,6 @@ obj-$(CONFIG_SYNCLINK) += synclink.o
obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_SPECIALIX) += specialix.o
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
-
-# After much ado, we found that an object can safely be declared as
-# both a module and into the kernel. Below that is filtered out.
-# So this should simply provide the wanted functionality!
obj-$(CONFIG_SX) += sx.o generic_serial.o
obj-$(CONFIG_RIO) += rio/rio.o generic_serial.o
obj-$(CONFIG_SH_SCI) += sh-sci.o generic_serial.o
@@ -166,14 +153,6 @@ else
endif
obj-$(CONFIG_BUSMOUSE) += busmouse.o
-ifeq ($(CONFIG_BUSMOUSE),y)
-M = y
-else
- ifeq ($(CONFIG_BUSMOUSE),m)
- MM = m
- endif
-endif
-
obj-$(CONFIG_DTLK) += dtlk.o
obj-$(CONFIG_R3964) += n_r3964.o
obj-$(CONFIG_APPLICOM) += applicom.o
@@ -203,72 +182,17 @@ obj-$(CONFIG_977_WATCHDOG) += wdt977.o
obj-$(CONFIG_DS1620) += ds1620.o
obj-$(CONFIG_INTEL_RNG) += i810_rng.o
-#
-# for external dependencies in arm/config.in and video/config.in
-#
-ifeq ($(CONFIG_BUS_I2C),y)
- L_I2C=y
-else
- ifeq ($(CONFIG_BUS_I2C),m)
- L_I2C=m
- endif
-endif
-
+obj-$(CONFIG_BUS_I2C) += i2c-old.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o \
- tda7432.o tda8425.o tda985x.o tda9875.o tea6300.o tea6420.o
-ifeq ($(CONFIG_VIDEO_BT848),y)
-L_TUNERS=y
-else
- ifeq ($(CONFIG_VIDEO_BT848),m)
- L_TUNERS=m
- endif
-endif
+ tda7432.o tda8425.o tda985x.o tda9875.o tea6300.o tea6420.o tuner.o
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
-obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
-ifeq ($(CONFIG_VIDEO_ZR36120),y)
-L_I2C=y
-L_TUNERS=y
-L_DECODERS=y
-else
- ifeq ($(CONFIG_VIDEO_ZR36120),m)
- L_I2C=m
- L_TUNERS=m
- L_DECODERS=m
- endif
-endif
-
-obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
-ifeq ($(CONFIG_I2C_PARPORT),y)
-L_I2C = y
-else
- ifeq ($(CONFIG_I2C_PARPORT),m)
- L_I2C = m
- endif
-endif
-
-obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
-ifeq ($(CONFIG_VIDEO_SAA5249),y)
-L_I2C=y
-else
- ifeq ($(CONFIG_VIDEO_SAA5249),m)
- L_I2C=m
- endif
-endif
-
+obj-$(CONFIG_VIDEO_ZR36120) += zoran.o i2c-old.o tuner.o saa7110.o saa7111.o saa7185.o
+obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o i2c-old.o
+obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o i2c-old.o
obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
-obj-$(CONFIG_VIDEO_ZORAN) += buz.o
-ifeq ($(CONFIG_VIDEO_ZORAN),y)
-L_I2C=y
-L_DECODERS=y
-else
- ifeq ($(CONFIG_VIDEO_ZORAN),m)
- L_I2C=m
- L_DECODERS=m
- endif
-endif
-
+obj-$(CONFIG_VIDEO_ZORAN) += buz.o i2c-old.o saa7110.o saa7111.o saa7185.o
obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o
obj-$(CONFIG_VIDEO_PMS) += pms.o
obj-$(CONFIG_VIDEO_PLANB) += planb.o
@@ -305,24 +229,17 @@ endif
obj-$(CONFIG_H8) += h8.o
obj-$(CONFIG_PPDEV) += ppdev.o
-
-# set when a framegrabber supports external tuners
-obj-$(L_TUNERS) += tuner.o
-
-# set when a framegrabber supports external decoders
-obj-$(L_DECODERS) += saa7110.o saa7111.o saa7185.o
-
-# set when a framegrabber implements i2c support
-obj-$(L_I2C) += i2c-old.o
-
obj-$(CONFIG_DZ) += dz.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
ifeq ($(CONFIG_DRM),y)
SUB_DIRS += drm
- ALL_SUB_DIRS += drm
MOD_SUB_DIRS += drm
+else
+ ifeq ($(CONFIG_DRM),m)
+ MOD_SUB_DIRS += drm
+ endif
endif
ifeq ($(CONFIG_PCMCIA),y)
@@ -336,11 +253,9 @@ endif
ifeq ($(CONFIG_AGP), y)
SUB_DIRS += agp
- ALL_SUB_DIRS += agp
MOD_SUB_DIRS += agp
else
ifeq ($(CONFIG_AGP), m)
- ALL_SUB_DIRS += agp
MOD_SUB_DIRS += agp
endif
endif
diff --git a/drivers/char/drm/agpsupport.c b/drivers/char/drm/agpsupport.c
index 628e8cad5..48a6aa5f9 100644
--- a/drivers/char/drm/agpsupport.c
+++ b/drivers/char/drm/agpsupport.c
@@ -30,6 +30,7 @@
#define __NO_VERSION__
#include "drmP.h"
+#include <linux/module.h>
drm_agp_func_t drm_agp = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
diff --git a/drivers/char/drm/auth.c b/drivers/char/drm/auth.c
index 3ee85388e..9f81c5391 100644
--- a/drivers/char/drm/auth.c
+++ b/drivers/char/drm/auth.c
@@ -45,8 +45,6 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
down(&dev->struct_sem);
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
- if (pt->priv->authenticated)
- continue;
if (pt->magic == magic) {
retval = pt->priv;
break;
diff --git a/drivers/char/drm/drm_syms.c b/drivers/char/drm/drm_syms.c
new file mode 100644
index 000000000..e7aaf569d
--- /dev/null
+++ b/drivers/char/drm/drm_syms.c
@@ -0,0 +1,146 @@
+#include <linux/config.h>
+#include "drmP.h"
+
+/* Misc. support (init.c) */
+EXPORT_SYMBOL(drm_flags);
+EXPORT_SYMBOL(drm_parse_options);
+EXPORT_SYMBOL(drm_cpu_valid);
+
+/* Device support (fops.c) */
+EXPORT_SYMBOL(drm_open_helper);
+EXPORT_SYMBOL(drm_flush);
+EXPORT_SYMBOL(drm_release);
+EXPORT_SYMBOL(drm_fasync);
+EXPORT_SYMBOL(drm_read);
+EXPORT_SYMBOL(drm_write_string);
+EXPORT_SYMBOL(drm_poll);
+
+/* Mapping support (vm.c) */
+#if LINUX_VERSION_CODE < 0x020317
+EXPORT_SYMBOL(drm_vm_nopage);
+EXPORT_SYMBOL(drm_vm_shm_nopage);
+EXPORT_SYMBOL(drm_vm_dma_nopage);
+#else
+/* Return type changed in 2.3.23 */
+EXPORT_SYMBOL(drm_vm_nopage);
+EXPORT_SYMBOL(drm_vm_shm_nopage);
+EXPORT_SYMBOL(drm_vm_dma_nopage);
+#endif
+
+EXPORT_SYMBOL(drm_vm_open);
+EXPORT_SYMBOL(drm_vm_close);
+EXPORT_SYMBOL(drm_mmap_dma);
+EXPORT_SYMBOL(drm_mmap);
+
+/* Proc support (proc.c) */
+EXPORT_SYMBOL(drm_proc_init);
+EXPORT_SYMBOL(drm_proc_cleanup);
+
+/* Memory management support (memory.c) */
+EXPORT_SYMBOL(drm_mem_init);
+EXPORT_SYMBOL(drm_mem_info);
+EXPORT_SYMBOL(drm_alloc);
+EXPORT_SYMBOL(drm_realloc);
+EXPORT_SYMBOL(drm_strdup);
+EXPORT_SYMBOL(drm_strfree);
+EXPORT_SYMBOL(drm_free);
+EXPORT_SYMBOL(drm_alloc_pages);
+EXPORT_SYMBOL(drm_free_pages);
+EXPORT_SYMBOL(drm_ioremap);
+EXPORT_SYMBOL(drm_ioremapfree);
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+EXPORT_SYMBOL(drm_alloc_agp);
+EXPORT_SYMBOL(drm_free_agp);
+EXPORT_SYMBOL(drm_bind_agp);
+EXPORT_SYMBOL(drm_unbind_agp);
+#endif
+
+/* Buffer management support (bufs.c) */
+EXPORT_SYMBOL(drm_order);
+EXPORT_SYMBOL(drm_addmap);
+EXPORT_SYMBOL(drm_addbufs);
+EXPORT_SYMBOL(drm_infobufs);
+EXPORT_SYMBOL(drm_markbufs);
+EXPORT_SYMBOL(drm_freebufs);
+EXPORT_SYMBOL(drm_mapbufs);
+
+/* Buffer list management support (lists.c) */
+EXPORT_SYMBOL(drm_waitlist_create);
+EXPORT_SYMBOL(drm_waitlist_destroy);
+EXPORT_SYMBOL(drm_waitlist_put);
+EXPORT_SYMBOL(drm_waitlist_get);
+EXPORT_SYMBOL(drm_freelist_create);
+EXPORT_SYMBOL(drm_freelist_destroy);
+EXPORT_SYMBOL(drm_freelist_put);
+EXPORT_SYMBOL(drm_freelist_get);
+
+/* DMA support (gen_dma.c) */
+EXPORT_SYMBOL(drm_dma_setup);
+EXPORT_SYMBOL(drm_dma_takedown);
+EXPORT_SYMBOL(drm_free_buffer);
+EXPORT_SYMBOL(drm_reclaim_buffers);
+EXPORT_SYMBOL(drm_context_switch);
+EXPORT_SYMBOL(drm_context_switch_complete);
+EXPORT_SYMBOL(drm_clear_next_buffer);
+EXPORT_SYMBOL(drm_select_queue);
+EXPORT_SYMBOL(drm_dma_enqueue);
+EXPORT_SYMBOL(drm_dma_get_buffers);
+#if DRM_DMA_HISTOGRAM
+EXPORT_SYMBOL(drm_histogram_slot);
+EXPORT_SYMBOL(drm_histogram_compute);
+#endif
+
+/* Misc. IOCTL support (ioctl.c) */
+EXPORT_SYMBOL(drm_irq_busid);
+EXPORT_SYMBOL(drm_getunique);
+EXPORT_SYMBOL(drm_setunique);
+
+/* Context IOCTL support (context.c) */
+EXPORT_SYMBOL(drm_resctx);
+EXPORT_SYMBOL(drm_addctx);
+EXPORT_SYMBOL(drm_modctx);
+EXPORT_SYMBOL(drm_getctx);
+EXPORT_SYMBOL(drm_switchctx);
+EXPORT_SYMBOL(drm_newctx);
+EXPORT_SYMBOL(drm_rmctx);
+
+/* Drawable IOCTL support (drawable.c) */
+EXPORT_SYMBOL(drm_adddraw);
+EXPORT_SYMBOL(drm_rmdraw);
+
+/* Authentication IOCTL support (auth.c) */
+EXPORT_SYMBOL(drm_add_magic);
+EXPORT_SYMBOL(drm_remove_magic);
+EXPORT_SYMBOL(drm_getmagic);
+EXPORT_SYMBOL(drm_authmagic);
+
+/* Locking IOCTL support (lock.c) */
+EXPORT_SYMBOL(drm_block);
+EXPORT_SYMBOL(drm_unblock);
+EXPORT_SYMBOL(drm_lock_take);
+EXPORT_SYMBOL(drm_lock_transfer);
+EXPORT_SYMBOL(drm_lock_free);
+EXPORT_SYMBOL(drm_finish);
+EXPORT_SYMBOL(drm_flush_unblock);
+EXPORT_SYMBOL(drm_flush_block_and_flush);
+
+/* Context Bitmap support (ctxbitmap.c) */
+EXPORT_SYMBOL(drm_ctxbitmap_init);
+EXPORT_SYMBOL(drm_ctxbitmap_cleanup);
+EXPORT_SYMBOL(drm_ctxbitmap_next);
+EXPORT_SYMBOL(drm_ctxbitmap_free);
+
+/* AGP/GART support (agpsupport.c) */
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+EXPORT_SYMBOL(drm_agp);
+EXPORT_SYMBOL(drm_agp_init);
+EXPORT_SYMBOL(drm_agp_uninit);
+EXPORT_SYMBOL(drm_agp_acquire);
+EXPORT_SYMBOL(drm_agp_release);
+EXPORT_SYMBOL(drm_agp_enable);
+EXPORT_SYMBOL(drm_agp_info);
+EXPORT_SYMBOL(drm_agp_alloc);
+EXPORT_SYMBOL(drm_agp_free);
+EXPORT_SYMBOL(drm_agp_unbind);
+EXPORT_SYMBOL(drm_agp_bind);
+#endif
diff --git a/drivers/char/drm/memory.c b/drivers/char/drm/memory.c
index e1f462bdd..5023de808 100644
--- a/drivers/char/drm/memory.c
+++ b/drivers/char/drm/memory.c
@@ -30,6 +30,7 @@
*/
#define __NO_VERSION__
+#include <linux/config.h>
#include "drmP.h"
typedef struct drm_mem_stats {
diff --git a/drivers/char/drm/r128_bufs.c b/drivers/char/drm/r128_bufs.c
index d02fc5e00..bd81dcdc0 100644
--- a/drivers/char/drm/r128_bufs.c
+++ b/drivers/char/drm/r128_bufs.c
@@ -31,6 +31,7 @@
*/
#define __NO_VERSION__
+#include <linux/config.h>
#include "drmP.h"
#include "r128_drv.h"
#include "linux/un.h"
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index 27b16614c..b382a13c5 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -466,8 +466,6 @@ int r128_open(struct inode *inode, struct file *filp)
spin_unlock(&dev->count_lock);
}
- unlock_kernel();
-
return retcode;
}
diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
index 85f88044d..896705e97 100644
--- a/drivers/char/drm/tdfx_drv.c
+++ b/drivers/char/drm/tdfx_drv.c
@@ -446,9 +446,11 @@ int tdfx_release(struct inode *inode, struct file *filp)
atomic_read(&dev->ioctl_count),
dev->blocked);
spin_unlock(&dev->count_lock);
+ unlock_kernel();
return -EBUSY;
}
spin_unlock(&dev->count_lock);
+ unlock_kernel();
return tdfx_takedown(dev);
}
spin_unlock(&dev->count_lock);
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 0e9d7b57f..6f4ebe44c 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -1154,9 +1154,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
nr -= num;
if (nr == 0)
break;
- current->state = TASK_RUNNING;
get_user(c, b);
- current->state = TASK_INTERRUPTIBLE;
if (opost(c, tty) < 0)
break;
b++; nr--;
@@ -1164,9 +1162,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
if (tty->driver.flush_chars)
tty->driver.flush_chars(tty);
} else {
- current->state = TASK_RUNNING;
c = tty->driver.write(tty, 1, b, nr);
- current->state = TASK_INTERRUPTIBLE;
if (c < 0) {
retval = c;
goto break_out;
diff --git a/drivers/i2c/Config.in b/drivers/i2c/Config.in
index 9050f3528..405121edc 100644
--- a/drivers/i2c/Config.in
+++ b/drivers/i2c/Config.in
@@ -10,7 +10,7 @@ if [ "$CONFIG_I2C" != "n" ]; then
dep_tristate 'I2C bit-banging interfaces' CONFIG_I2C_ALGOBIT $CONFIG_I2C
if [ "$CONFIG_I2C_ALGOBIT" != "n" ]; then
- dep_tristate ' Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT
+ dep_tristate ' Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT $CONFIG_PARPORT
dep_tristate ' ELV adapter' CONFIG_I2C_ELV $CONFIG_I2C_ALGOBIT
dep_tristate ' Velleman K9000 adapter' CONFIG_I2C_VELLEMAN $CONFIG_I2C_ALGOBIT
fi
diff --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c
index 6385cd81b..72dd50134 100644
--- a/drivers/ide/pdc202xx.c
+++ b/drivers/ide/pdc202xx.c
@@ -862,7 +862,6 @@ void __init ide_init_pdc202xx (ide_hwif_t *hwif)
(hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20265) ||
(hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20267)) {
hwif->resetproc = &pdc202xx_reset;
- hwif->tri_proc = &pdc202xx_tristate;
}
#ifdef CONFIG_BLK_DEV_IDEDMA
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 29d5d7638..ae023616a 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -607,6 +607,7 @@ MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
+#endif
void __exit ace_module_cleanup(void)
{
@@ -695,7 +696,6 @@ void __exit ace_module_cleanup(void)
root_dev = next;
}
}
-#endif
int __init ace_module_init(void)
diff --git a/drivers/net/gmac.c b/drivers/net/gmac.c
index 4717a652c..17d328294 100644
--- a/drivers/net/gmac.c
+++ b/drivers/net/gmac.c
@@ -9,8 +9,6 @@
*/
#include <linux/module.h>
-
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 1d5efdfc4..8d0d245b3 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -223,6 +223,18 @@ static void __init quirk_piix3usb(struct pci_dev *dev)
}
/*
+ * VIA VT82C598 has its device ID settable and many BIOSes
+ * set it to the ID of VT82C597 for backward compatibility.
+ * We need to switch it off to be able to recognize the real
+ * type of the chip.
+ */
+static void __init quirk_vt82c598_id(struct pci_dev *dev)
+{
+ pci_write_config_byte(dev, 0xfc, 0);
+ pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
+}
+
+/*
* The main table of quirks.
*/
@@ -232,7 +244,6 @@ static struct pci_fixup pci_fixups[] __initdata = {
/*
* Its not totally clear which chipsets are the problematic ones
* We know 82C586 and 82C596 variants are affected.
- *
*/
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs },
@@ -251,6 +262,7 @@ static struct pci_fixup pci_fixups[] __initdata = {
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi },
diff --git a/drivers/scsi/README.ibmmca b/drivers/scsi/README.ibmmca
index 61fd18e51..313690c26 100644
--- a/drivers/scsi/README.ibmmca
+++ b/drivers/scsi/README.ibmmca
@@ -10,10 +10,10 @@
General Public License. Originally written by Martin Kolinek, December 1995.
Officially maintained by Michael Lang since January 1999.
- Version 3.1e
+ Version 3.2
- Last update: 20 February 1999
+ Last update: 29 July 2000
Authors of this Driver
@@ -23,7 +23,8 @@
- Klaus Kudielka (multiple SCSI-host management/detection, adaption to
Linux Kernel 2.1.x, module support)
- Michael Lang (assigning original pun,lun mapping, dynamical ldn
- assignment, this file, patch, official driver maintenance)
+ assignment, this file, patch, official driver maintenance
+ and subsequent pains related with the driver :-))
Table of Contents
-----------------
@@ -51,7 +52,11 @@
5.3 Bugreports
5.4 Support WWW-page
6 References
- 7 Trademarks
+ 7 Credits to
+ 7.1 People
+ 7.2 Sponsors & Supporters
+ 8 Trademarks
+ 9 Disclaimer
* * *
@@ -64,7 +69,7 @@
quite outdated. The history of the driver development is also kept inside
here. Multiple historical developments have been summarized to shorten the
textsize a bit. At the end of this file you can find a small manual for
- this driver and hints to get it running even on your machine (hopefully).
+ this driver and hints to get it running on your machine.
2 Driver Description
--------------------
@@ -74,27 +79,35 @@
Microchannel-bus support is enabled, as the IBM SCSI-subsystem needs the
Microchannel. In a next step, a free interrupt is chosen and the main
interrupt handler is connected to it to handle answers of the SCSI-
- subsystem(s). In a further step, it is checked, wether there was a forced
- detection of the adapter via the kernel commandline, where the I/O port
- and the SCSI-subsystem id can be specified. The next step checks if there
- is an integrated SCSI-subsystem installed. This register area is fixed
- through all IBM PS/2 MCA-machines and appears as something like a virtual
- slot 10 of the MCA-bus. If POS-register 2 is not 0xff, there must be a SCSI-
+ subsystem(s). If the F/W SCSI-adapter is forced by the BIOS to use IRQ11
+ instead of IRQ14, IRQ11 is used for the IBM SCSI-2 F/W adapter. In a
+ further step it is checked, if the adapter gets detected by force from
+ the kernel commandline, where the I/O port and the SCSI-subsystem id can
+ be specified. The next step checks if there is an integrated SCSI-subsystem
+ installed. This register area is fixed through all IBM PS/2 MCA-machines
+ and appears as something like a virtual slot 10 of the MCA-bus. On most
+ PS/2 machines, the POS registers of slot 10 are set to 0xff or 0x00 if not
+ integrated SCSI-controller is available. But on certain PS/2s, like model
+ 9595, this slot 10 is used to store other information which at earlier
+ stage confused the driver and resulted in the detection of some ghost-SCSI.
+ If POS-register 2 and 3 are not 0x00 and not 0xff, but all other POS
+ registers are either 0xff or 0x00, there must be an integrated SCSI-
subsystem present and it will be registered as IBM Integrated SCSI-
Subsystem. The next step checks, if there is a slot-adapter installed on
the MCA-bus. To get this, the first two POS-registers, that represent the
adapter ID are checked. If they fit to one of the ids, stored in the
- adapter list, a SCSI-subsystem is assumed to be found and will be
+ adapter list, a SCSI-subsystem is assumed to be found in a slot and will be
registered. This check is done through all possible MCA-bus slots to allow
more than one SCSI-adapter to be present in the PS/2-system and this is
already the first point of problems. Looking into the technical reference
manual for the IBM PS/2 common interfaces, the POS2 register must have
- different interpretation of its single bits. While one can assume, that the
- integrated subsystem has a fix I/O-address at 0x3540 - 0x3547, further
- installed IBM SCSI-adapters must use a different I/O-address. This is
- expressed by bit 1 to 3 of POS2 (multiplied by 8 + 0x3540). Bits 2 and 3
- are reserved for the integrated subsystem, but not for the adapters! The
- following list shows, how the bits of POS2 and POS3 should be interpreted.
+ different interpretation of its single bits to avoid overlapping I/O
+ regions. While one can assume, that the integrated subsystem has a fix
+ I/O-address at 0x3540 - 0x3547, further installed IBM SCSI-adapters must
+ use a different I/O-address. This is expressed by bit 1 to 3 of POS2
+ (multiplied by 8 + 0x3540). Bits 2 and 3 are reserved for the integrated
+ subsystem, but not for the adapters! The following list shows, how the
+ bits of POS2 and POS3 should be interpreted.
The POS2-register of all PS/2 models' integrated SCSI-subsystems has the
following interpretation of bits:
@@ -102,20 +115,25 @@
Bit 3 - 2 : Reserved
Bit 1 : 8k NVRAM Disabled
Bit 0 : Chip Enable (EN-Signal)
- The POS3-register is interpreted as follows (for ALL IBM SCSI-subsys.):
+ The POS3-register is interpreted as follows (for most IBM SCSI-subsys.):
Bit 7 - 5 : SCSI ID
Bit 4 - 0 : Reserved = 0
- (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common
- Interfaces (1991)").
- In short words, this means, that IBM PS/2 machines only support 1 single
- subsystem by default. But (additional) slot-adapters must have another
- configuration on pos2 in order to be enabled to use more than one IBM SCSI-
- subsystem, e.g. for a network server. From tests with the IBM SCSI Adapter
- w/cache, the POS2-register for slot adapters should be interpreted in the
- following way:
- Bit 7 - 4 : Chip Revision ID (Release)
- Bit 3 - 1 : port offset factor ( * 8 + 0x3540 )
- Bit 0 : Chip Enable (EN-Signal)
+ The slot-adapters have different interpretation of these bits. The IBM SCSI
+ adapter (w/Cache) and the IBM SCSI-2 F/W adapter use the following
+ interpretation of the POS2 register:
+ Bit 7 - 4 : ROM Segment Address Select
+ Bit 3 - 1 : Adapter I/O Address Select (*8+0x3540)
+ Bit 0 : Adapter Enable (EN-Signal)
+ and for the POS3 register:
+ Bit 7 - 5 : SCSI ID
+ Bit 4 : Fairness Enable (SCSI ID3 f. F/W)
+ Bit 3 - 0 : Arbitration Level
+ The most modern product of the series is the IBM SCSI-2 F/W adapter, it
+ allows dual-bus SCSI and SCSI-wide addressing, which means, PUNs may be
+ between 0 and 15. Here, Bit 4 is the high-order bit of the 4-bit wide
+ adapter PUN expression. In short words, this means, that IBM PS/2 machines
+ can only support 1 single integrated subsystem by default. Additional
+ slot-adapters get ports assigned by the automatic configuration tool.
One day I found a patch in ibmmca_detect(), forcing the I/O-address to be
0x3540 for integrated SCSI-subsystems, there was a remark placed, that on
@@ -156,12 +174,18 @@
number or pun, also called the scsi id, this is the number you select
with hardware jumpers), and each physical unit can have up to 8
"logical units" (each identified by logical unit number, or lun,
- between 0 and 7).
+ between 0 and 7). The IBM SCSI-2 F/W adapter offers this on up to two
+ busses and provides support for 30 logical devices at the same time, where
+ in wide-addressing mode you can have 16 puns with 32 luns on each device.
+ This section dexribes you the handling of devices on non-F/W adapters.
+ Just imagine, that you can have 16 * 32 = 512 devices on a F/W adapter
+ which means a lot of possible devices for such a small machine.
Typically the adapter has pun=7, so puns of other physical units
- are between 0 and 6. Almost all physical units have only one
- logical unit, with lun=0. A CD-ROM jukebox would be an example of
- a physical unit with more than one logical unit.
+ are between 0 and 6(15). On a wide-adapter a pun higher than 7 is
+ possible, but is normally not used. Almost all physical units have only
+ one logical unit, with lun=0. A CD-ROM jukebox would be an example of a
+ physical unit with more than one logical unit.
The embedded microprocessor of the IBM SCSI-subsystem hides the complex
two-dimensional (pun,lun) organization from the operating system.
@@ -169,7 +193,8 @@
checks, on its own, all 56 possible (pun,lun) combinations, and the first
15 devices found are assigned into a one-dimensional array of so-called
"logical devices", identified by "logical device numbers" or ldn. The last
- ldn=15 is reserved for the subsystem itself.
+ ldn=15 is reserved for the subsystem itself. Wide adapters may have
+ to check up to 15 * 8 = 120 pun/lun combinations.
2.3 SCSI-Device Recognition and dynamical ldn Assignment
--------------------------------------------------------
@@ -177,8 +202,12 @@
numbers are also hidden. The two possibilities to get around this problem
is to offer fake pun/lun combinations to the operating system or to
delete the whole mapping of the adapter and to reassign the ldns, using
- the immediate assign command of the SCSI-subsystem. At the beginning of the
- development of this driver, the following approach was used:
+ the immediate assign command of the SCSI-subsystem for probing through
+ all possible pun/lun combinations. a ldn is a "logical device number"
+ which is used by IBM SCSI-subsystems to access some valid SCSI-device.
+ At the beginning of the development of this driver, the following approach
+ was used:
+
First, the driver checked the ldn's (0 to 6) to find out which ldn's
have devices assigned. This was done by the functions check_devices() and
device_exists(). The interrupt handler has a special paragraph of code
@@ -199,7 +228,7 @@
and later, realizes the device recognition in the following way:
The physical SCSI-devices on the SCSI-bus are probed via immediate_assign-
and device_inquiry-commands, that is all implemented in a completely new
- made check_devices() subroutine. This delivers a exact map of the physical
+ made check_devices() subroutine. This delivers an exact map of the physical
SCSI-world that is now stored in the get_scsi[][]-array. This means,
that the once hidden pun,lun assignment is now known to this driver.
It no longer believes in default-settings of the subsystem and maps all
@@ -230,7 +259,7 @@
can be different from the old, faked puns. Therefore, Linux will eventually
change /dev/sdXXX assignments and prompt you for corrupted superblock
repair on boottime. In this case DO NOT PANIC, YOUR DISKS ARE STILL OK!!!
- You have to reboot (CTRL-D) with a old kernel and set the /etc/fstab-file
+ You have to reboot (CTRL-D) with an old kernel and set the /etc/fstab-file
entries right. After that, the system should come up as errorfree as before.
If your boot-partition is not coming up, also edit the /etc/lilo.conf-file
in a Linux session booted on old kernel and run lilo before reboot. Check
@@ -332,17 +361,19 @@
----------------------------------
The following IBM SCSI-subsystems are supported by this driver:
- - IBM Fast SCSI-2 Adapter
+ - IBM Fast/Wide SCSI-2 Adapter
- IBM 7568 Industrial Computer SCSI Adapter w/cache
- IBM Expansion Unit SCSI Controller
- IBM SCSI Adapter w/Cache
- IBM SCSI Adapter
- IBM Integrated SCSI Controller
+ - All clones, 100% compatible with the chipset and subsystem command
+ system of IBM SCSI-adapters (forced detection)
2.14 Linux Kernel Versions
--------------------------
The IBM SCSI-subsystem low level driver is prepared to be used with
- all versions of Linux between 2.0.x and 2.2.x. The compatibility checks
+ all versions of Linux between 2.0.x and 2.4.x. The compatibility checks
are fully implemented up from version 3.1e of the driver. This means, that
you just need the latest ibmmca.h and ibmmca.c file and copy it in the
linux/drivers/scsi directory. The code is automatically adapted during
@@ -717,18 +748,149 @@
addition more flexibility.
- Michael Lang
+ Apr 23, 2000 (v3.2pre1)
+ 1) During a very long time, I collected a huge amount of bugreports from
+ various people, trying really quite different things on their SCSI-
+ PS/2s. Today, all these bugreports are taken into account and should be
+ mostly solved. The major topics were:
+ - Driver crashes during boottime by no obvious reason.
+ - Driver panics while the midlevel-SCSI-driver is trying to inquire
+ the SCSI-device properties, even though hardware is in perfect state.
+ - Displayed info for the various slot-cards is interpreted wrong.
+ The main reasons for the crashes were two:
+ 1) The commands to check for device information like INQUIRY,
+ TEST_UNIT_READY, REQUEST_SENSE and MODE_SENSE cause the devices
+ to deliver information of up to 255 bytes. Midlevel drivers offer
+ 1024 bytes of space for the answer, but the IBM-SCSI-adapters do
+ not accept this, as they stick quite near to ANSI-SCSI and report
+ a COMMAND_ERROR message which causes the driver to panic. The main
+ problem was located around the INQUIRY command. Now, for all the
+ mentioned commands, the buffersize, sent to the adapter is at
+ maximum 255 which seems to be a quite reasonable solution.
+ TEST_UNIT_READY gets a buffersize of 0 to make sure, that no
+ data is transferred in order to avoid any possible command failure.
+ 2) On unsuccessful TEST_UNIT_READY, the midlevel-driver has to send
+ a REQUEST_SENSE in order to see, where the problem is located. This
+ REQUEST_SENSE may have various length in its answer-buffer. IBM
+ SCSI-subsystems report a command failure, if the returned buffersize
+ is different from the sent buffersize, but this can be supressed by
+ a special bit, which is now done and problems seem to be solved.
+ 2) Code adaption to all kernel-releases. Now, the 3.2 code compiles on
+ 2.0.x, 2.1.x, 2.2.x and 2.3.x kernel releases without any code-changes.
+ 3) Commandline-parameters are recognized again, even under Kernel 2.3.x or
+ higher.
+ - Michael Lang
+
+ April 27, 2000 (v3.2pre2)
+ 1) Bypassed commands get read by the adapter by one cycle instead of two.
+ This increases SCSI-performance.
+ 2) Synchronous datatransfer is provided for sure to be 5 MHz on older
+ SCSI and 10 MHz on internal F/W SCSI-adapter.
+ 3) New commandline parameters allow to force the adapter to slow down while
+ in synchronous transfer. Could be helpful for very old devices.
+ - Michael Lang
+
+ June 2, 2000 (v3.2pre5)
+ 1) Added Jim Shorney's contribution to make the activity indicator
+ flashing in addition to the LED-alphanumeric display-panel on
+ models 95A. To be enabled to choose this feature freely, a new
+ commandline parameter is added, called 'activity'.
+ 2) Added the READ_CONTROL bit for test_unit_ready SCSI-command.
+ 3) Added some suppress_exception bits to read_device_capacity and
+ all device_inquiry occurences in the driver code.
+ 4) Complaints about the various KERNEL_VERSION implementations are
+ taken into account. Every local_LinuxKernelVersion occurence is
+ now replaced by KERNEL_VERSION, defined in linux/version.h.
+ Corresponding changes were applied to ibmmca.h, too. This was a
+ contribution to all kernel-parts by Philipp Hahn.
+ - Michael Lang
+
+ July 17, 2000 (v3.2pre8)
+ A long period of collecting bugreports from all corners of the world
+ now lead to the following corrections to the code:
+ 1) SCSI-2 F/W support crashed with a COMMAND ERROR. The reason for this
+ was, that it is possible to disbale Fast-SCSI for the external bus.
+ The feature-control command, where this crash appeared regularly tried
+ to set the maximum speed of 10MHz synchronous transfer speed and that
+ reports a COMMAND ERROR, if external bus Fast-SCSI is disabled. Now,
+ the feature-command probes down from maximum speed until the adapter
+ stops to complain, which is at the same time the maximum possible
+ speed selected in the reference program. So, F/W external can run at
+ 5 MHz (slow-) or 10 MHz (fast-SCSI). During feature probing, the
+ COMMAND ERROR message is used to detect if the adapter does not complain.
+ 2) Up to now, only combined busmode is supported, if you use external
+ SCSI-devices, attached to the F/W-controller. If dual bus is selected,
+ only the internal SCSI-devices get accessed by Linux. For most
+ applications, this should do fine.
+ 3) Wide-SCSI-addressing (16-Bit) is now possible for the internal F/W
+ bus on the F/W adapter. If F/W adapter is detected, the driver
+ automatically uses the extended PUN/LUN <-> LDN mapping tables, which
+ are now new from 3.2pre8. This allows PUNs between 0 and 15 and should
+ provide more fun with the F/W adapter.
+ 4) Several machines use the SCSI: POS registers for internal/undocumented
+ storage of system relevant info. This confused the driver, mainly on
+ models 9595, as it expected no onboard SCSI only, if all POS in
+ the integrated SCSI-area are set to 0x00 or 0xff. Now, the mechanism
+ to check for integrated SCSI is much more restrictive and these problems
+ should be history.
+ - Michael Lang
+
+ July 18, 2000 (v3.2pre9)
+ This develop rather quickly at the moment. Two major things were still
+ missing in 3.2pre8:
+ 1) The adapter PUN for F/W adapters has 4-bits, while all other adapters
+ have 3-bits. This is now taken into account for F/W.
+ 2) When you select CONFIG_IBMMCA_SCSI_ORDER_STANDARD, you should
+ normally get the inverse probing order of your devices on the SCSI-bus.
+ The ANSI device order gets scrambled in version 3.2pre8!! Now, a new
+ and tested algorithm inverts the device-order on the SCSI-bus and
+ automatically avoids accidental access to whatever SCSI PUN the adapter
+ is set and works with SCSI- and Wide-SCSI-addressing.
+ - Michael Lang
+
+ July 23, 2000 (v3.2pre10 unpublished)
+ 1) LED panel display supports wide-addressing in ibmmca=display mode.
+ 2) Adapter-information and autoadaption to address-space is done.
+ 3) Auto-probing for maximum synchronous SCSI transfer rate is working.
+ 4) Optimization to some embedded function calls is applied.
+ 5) Added some comment for the user to wait for SCSI-devices beeing probed.
+ 6) Finished version 3.2 for Kernel 2.4.0. It least, I thought it is but...
+ - Michael Lang
+
+ July 26, 2000 (v3.2pre11)
+ 1) I passed a horrible weekend getting mad with NMIs on kernel 2.2.14 and
+ a model 9595. Asking around in the community, nobody except of me has
+ seen such errors. Weired, but I am trying to recompile everything on
+ the model 9595. Maybe, as I use a specially modified gcc, that could
+ cause problems. But, it was not the reason. The true background was,
+ that the kernel was compiled for i386 and the 9595 has a 486DX-2.
+ Normally, no troubles should appear, but for this special machine,
+ only the right processor support is working fine!
+ 2) Previous problems with synchronous speed, slowing down from one adapter
+ to the next during probing are corrected. Now, local variables store
+ the synchronous bitmask for every single adapter found on the MCA bus.
+ 3) LED alphanumeric panel support for XX95 systems is now showing some
+ alive rotator during boottime. This makes sense, when no monitor is
+ connected to the system. You can get rid of all display activity, if
+ you do not use any parameter or just ibmmcascsi=activity, for the
+ harddrive activity LED, existant on all PS/2, except models 8595-XXX.
+ If no monitor is available, please use ibmmcascsi=display, which works
+ fine together with the linuxinfo utility for the LED-panel.
+ - Michael Lang
+
+ July 29, 2000 (v3.2)
+ 1) Submission of this driver for kernel 2.4test-XX and 2.2.17.
+ - Michael Lang
+
4 To do
-------
+ - IBM SCSI-2 F/W external SCSI bus support in seperate mode.
- It seems that the handling of bad disks is really bad -
non-existent, in fact.
- More testing of the full driver-controlled dynamical ldn
- (re)mapping for up to 56 SCSI-devices.
- - Support more of the SCSI-command set.
- - Support some of the caching abilities, particularly Read Prefetch.
- This fetches data into the cache, which later gets hit by the
- regular Read Data. (<--- This is coming soon!!!!)
- - Abort and Reset functions still slightly buggy or better say,
- it is the new episode, called SCREAM III.
+ (re)mapping for up to 56 SCSI-devices. I guess, it won't work
+ at the moment, but nobody ever really tried it.
+ - Abort and Reset functions still slightly buggy.
5 Users' Manual
---------------
@@ -749,7 +911,13 @@
where '-' stays dark, 'D' shows the SCSI-device id
and 'A' shows the SCSI hostindex, beeing currently
- accessed.
+ accessed. During boottime, this will give the message
+
+ SCSIini*
+
+ on the LED-panel, where the * represents a rotator,
+ showing the activity during the probing phase of the
+ driver which can take up to two minutes per SCSI-adapter.
adisplay This works like display, but gives more optical overview
of the activities on the SCSI-bus. The display will have
the following output:
@@ -761,7 +929,22 @@
hostindex. If display nor adisplay is set, the internal
PS/2 harddisk LED is used for media-activities. So, if
you really do not have a system with a LED-display, you
- should not set display or adisplay.
+ should not set display or adisplay. Keep in mind, that
+ display and adisplay can only be used alternatively. It
+ is not recommended to use this option, if you have some
+ wide-addressed devices e.g. at the SCSI-2 F/W adapter in
+ your system. In addition, the usage of the display for
+ other tasks in parallel, like the linuxinfo-utility makes
+ no sense with this option.
+ activity This enables the PS/2 harddisk LED activity indicator.
+ Most PS/2 have no alphanumeric LED display, but some
+ indicator. So you should use this parameter to activate it.
+ If you own model 9595 (Server95), you can have both, the
+ LED panel and the activity indicator in parallel. However,
+ some PS/2s, like the 8595 do not have any harddisk LED
+ activity indicator, which means, that you must use the
+ alphanumeric LED display if you want to monitor SCSI-
+ activity.
bypass This commandline parameter forces the driver never to use
SCSI-subsystems' integrated SCSI-command set. Except of
the immediate assign, which is of vital importance for
@@ -775,7 +958,10 @@
this flag will slow-down SCSI-accesses slightly, as the
software generated commands are always slower than the
hardware. Non-harddisk devices always get read/write-
- commands in bypass mode.
+ commands in bypass mode. On the most recent releases of
+ the Linux IBM-SCSI-driver, the bypass command should be
+ no longer a necessary thing, if you are sure about your
+ SCSI-hardware!
normal This is the parameter, introduced on the 2.0.x development
rail by ZP Gu. This parameter defines the SCSI-device
scan order in the new industry standard. This means, that
@@ -789,6 +975,19 @@
pun=6 gets sda and a harddisk at pun=0 gets sdb. If you
like to have the same SCSI-device order, as in DOS, OS-9
or OS/2, just use this parameter.
+ fast SCSI-I/O in synchronous mode is done at 5 MHz for IBM-
+ SCSI-devices. SCSI-2 Fast/Wide Adapter/A external bus
+ should then run at 10 MHz if Fast-SCSI is enabled,
+ and at 5 MHz if Fast-SCSI is disabled on the external
+ bus. This is the default setting when nothing is
+ specified here.
+ medium Synchronous rate is at 50% approximately, which means
+ 2.5 MHz for IBM SCSI-adapters and 5.0 MHz for F/W ext.
+ SCSI-bus (when Fast-SCSI speed enabled on external bus).
+ slow The slowest possible synchronous transfer rate is set.
+ This means 1.82 MHz for IBM SCSI-adapters and 2.0 MHz
+ for F/W external bus at Fast-SCSI speed on the external
+ bus.
A further option is that you can force the SCSI-driver to accept a SCSI-
subsystem at a certain I/O-address with a predefined adapter PUN. This
@@ -805,7 +1004,7 @@
ibmmcascsi=adisplay,bypass
This will use the advanced display mode for the model 95 LED display and
- every SCSI-command passed to a attached device will get bypassed in order
+ every SCSI-command passed to an attached device will get bypassed in order
not to use any of the subsystem built-in commands.
ibmmcascsi=display,0x3558,7
@@ -837,9 +1036,9 @@
with OS/2 and DOS, you have to activate this flag in the kernel
configuration or you should set 'ansi' as parameter for the kernel.
The parameter 'normal' sets the new industry standard, starting
- from pun 0, scaning up to pun 6. This allows you to change your
+ from pun 0, scanning up to pun 6. This allows you to change your
opinion still after having already compiled the kernel.
- Q: Why can I not find the IBM MCA SCSI support in the config menue?
+ Q: Why I cannot find the IBM MCA SCSI support in the config menue?
A: You have to activate MCA bus support, first.
Q: Where can I find the latest info about this driver?
A: See the file MAINTAINERS for the current WWW-address, which offers
@@ -849,13 +1048,9 @@
A: Just force it to be recognized by kernel parameters. See section 5.1.
Q: The driver screws up, if it starts to probe SCSI-devices, is there
some way out of it?
- A: This is based on some problems with the driver. In such cases, send
- e-mail to the maintainer. If you are owner of a model with the serial
- number 95XX, just send as subject NOTIFY 95XX PROBLEM and the
- maintainer immediately knows about your problem. But please:
- Check your hardware and only if it works fine with other operating
- systems, send E-Mail to me to notify the troubles. See the homepage
- for how to send bug-reports or please read the next Q/A, here:
+ A: Yes, that was some recognition problem of the correct SCSI-adapter
+ and its I/O base addresses. Upgrade your driver to the latest release
+ and it should be fine again.
Q: I get a message: panic IBM MCA SCSI: command error .... , what can
I do against this?
A: Previously, I followed the way by ignoring command errors by using
@@ -867,8 +1062,8 @@
ibmmcascsi=forgiveall. Are there other possibilities to prevent
such panics?
A: No, get just the latest release of the driver and it should work
- better and better with increasing version number. Forget this
- ibmmcascsi=forgiveall, as also ignorecmd are obsolete.
+ better and better with increasing version number. Forget about this
+ ibmmcascsi=forgiveall, as also ignorecmd are obsolete.!
Q: Linux panics or stops without any comment, but it is probable, that my
harddisk(s) have bad blocks.
A: Sorry, the bad-block handling is still a feeble point of this driver,
@@ -893,10 +1088,45 @@
Astonishingly, reset works in most cases quite ok, but the harddisks
won't run in synchonous mode anymore after a reset, until you reboot.
Q: Why does my XXX w/Cache adapter not use read-prefetch?
- A: w/Cache technical manuals are incoming here, so if I understood the
- command of read-prefetch, it should be an easy thing to get harddisks
- read in read-prefetch with w/Cache controllers. Some weeks or months,
- still ahead and a lot of work still to do, sigh ...
+ A: Ok, that is not completely possible. If a cache is present, the
+ adapter tries to use it internally. Explicitly, one can use the cache
+ with a read prefetch command, maybe in future, but this requires
+ some major overhead of SCSI-commands that risks the performance to
+ go down more than it gets improved. Tests with that are running.
+ Q: I have a IBM SCSI-2 Fast/Wide adapter, it boots in some way and hangs.
+ A: Yes, that is understood, as for sure, your SCSI-2 Fast/Wide adapter
+ was in such a case recognized as integrated SCSI-adapter or something
+ else, but not as the correct adapter. As the I/O-ports get assigned
+ wrongly by that reason, the system should crash in most cases. You
+ should upgrade to the latest release of the SCSI-driver. The
+ recommended version is 3.2 or later. Here, the F/W support is in
+ a stable and reliable condition. Wide-addressing is in addition
+ supported.
+ Q: I get a Ooops message and something like "killing interrupt".
+ A: The reason for this is that the IBM SCSI-subsystem only sends a
+ termination status back, if some error appeared. In former releases
+ of the driver, it was not checked, if the termination status block
+ is NULL. From version 3.2, it is taken care of this.
+ Q: I have a F/W adapter and the driver sees my internal SCSI-devices,
+ but ignores the external ones.
+ A: Select combined busmode in the config-program and check for that
+ no SCSI-id on the external devices appears on internal devices.
+ Reboot afterwards. Dual busmode is supported, but works only for the
+ internal bus, yet. External bus is still ignored. Take care for your
+ SCSI-ids. If combined bus-mode is activated, on some adapters,
+ the wide-addressing is not possible, so devices with ids between 8
+ and 15 get ignored by the driver & adapter!
+ Q: I have a 9595 and I get a NMI during heavy SCSI I/O e.g. during fsck.
+ A COMMAND ERROR is reported and characters on the screen are missing.
+ Warm reboot is not possible. Things look like quite weired.
+ A: Check the processor type of your 9595. If you have an 80486 or 486DX-2
+ processor complex on your mainboard and you compiled a kernel that
+ supports 80386 processors, it is possible, that the kernel cannot
+ keep track of the PS/2 interrupt handling and stops on an NMI. Just
+ compile a kernel for the correct processor type of your PS/2 and
+ everything should be fine. This is necessary even if one assumes,
+ that some 80486 system should be downward compatible to 80386
+ software.
5.3 Bugreports
--------------
@@ -909,7 +1139,9 @@
Zubkoff, as Linus is burried in E-Mail and Leonard is supervising all
SCSI-drivers and won't have the time left to look inside every single
driver to fix a bug and especially DO NOT send modified code to Linus
- Torvalds, which has not been checked here!!! Recently, I got a lot of
+ Torvalds or Alan J. Cox which has not been checked here!!! They are both
+ quite burried in E-mail (as me, sometimes, too) and one should first check
+ for problems on my local teststand. Recently, I got a lot of
bugreports for errors in the ibmmca.c code, which I could not imagine, but
a look inside some Linux-distribution showed me quite often some modified
code, which did no longer work on most other machines than the one of the
@@ -934,23 +1166,36 @@
http://www.uni-mainz.de/~langm000/linux.html
Here you can find info about the background of this driver, patches,
- news and a bugreport form.
+ troubleshooting support, news and a bugreport form. Please check that
+ WWW-page regularly for latest hints.
+
+ For the bugreport, please fill out the formular on the corresponding
+ WWW-page. Read the dedicated instructions and write as much as you
+ know about your problem. If you do not like such formulars, please send
+ some e-mail directly, but at least with the same information as required by
+ the formular.
+
+ If you have extensive bugreports, including Ooops messages and
+ screen-shots, please feel free to send it directly to the address
+ of the maintainer, too. The current address of the maintainer is:
+
+ Michael Lang <langa2@kph.uni-mainz.de>
6 References
------------
- The source of information is "Update for the PS/2 Hardware
- Interface Technical Reference, Common Interfaces", September 1991,
- part number 04G3281, available in the U.S. for $21.75 at
- 1-800-IBM-PCTB, elsewhere call your local friendly IBM
- representative. E.g. in Germany, "Hallo IBM" works really great.
- In addition to SCSI subsystem, this update contains fairly detailed
- (at hardware register level) sections on diskette controller,
- keyboard controller, serial port controller, VGA, and XGA.
+ IBM Corp., "Update for the PS/2 Hardware Interface Technical Reference,
+ Common Interfaces", Armonk, September 1991, PN 04G3281,
+ (available in the U.S. for $21.75 at 1-800-IBM-PCTB or in Germany for
+ around 40,-DM at "Hallo IBM").
- Additional information from "Personal System/2 Micro Channel SCSI
- Adapter with Cache Technical Reference", March 1990, PN 68X2365,
- probably available from the same source (or possibly found buried
- in officemates desk).
+ IBM Corp., "Personal System/2 Micro Channel SCSI
+ Adapter with Cache Technical Reference", Armonk, March 1990, PN 68X2365.
+
+ IBM Corp., "Personal System/2 Micro Channel SCSI
+ Adapter Technical Reference", Armonk, March 1990, PN 68X2397.
+
+ IBM Corp., "SCSI-2 Fast/Wide Adapter/A Technical Reference - Dual Bus",
+ Armonk, March 1994, PN 83G7545.
Friedhelm Schmidt, "SCSI-Bus und IDE-Schnittstelle - Moderne Peripherie-
Schnittstellen: Hardware, Protokollbeschreibung und Anwendung", 2. Aufl.
@@ -965,14 +1210,101 @@
Helmut Rompel, "IBM Computerwelt GUIDE", What is what bei IBM., Systeme *
Programme * Begriffe, IWT-Verlag GmbH - Muenchen, 1988
- 7 Trademarks
+ 7 Credits to
+ ------------
+ 7.1 People
+ ----------
+ Klaus Grimm
+ who already a long time ago gave me the old code from the
+ SCSI-driver in order to get it running for some old machine
+ in our institute.
+ Martin Kolinek
+ who wrote the first release of the IBM SCSI-subsystem driver.
+ Chris Beauregard
+ who for a long time maintained MCA-Linux and the SCSI-driver
+ in the beginning. Chris, wherever you are: Cheers to you!
+ Klaus Kudielka
+ with whom in the 2.1.x times, I had a quite fruitful
+ cooperation to get the driver running as a module and to get
+ it running with multiple SCSI-adapters.
+ David Weinehall
+ for his excellent maintenance of the MCA-stuff and the quite
+ detailed bug reports and ideas for this driver (and his
+ patience ;-)).
+ Alan J. Cox
+ for his bugreports and his bold activities in cross-checking
+ the driver-code with his teststand.
+
+ 7.2 Sponsors & Supporters
+ -------------------------
+ "Hallo IBM",
+ IBM-Deutschland GmbH
+ the service of IBM-Deutschland for customers. Their E-Mail
+ service is unbeatable. Whatever old stuff I asked for, I
+ always got some helpful answers.
+ Karl-Otto Reimers,
+ IBM Klub - Sparte IBM Geschichte, Sindelfingen
+ for sending me a copy of the w/Cache manual from the
+ IBM-Deutschland archives.
+ Harald Staiger
+ for his extensive hardware donations which allows me today
+ still to test the driver in various constellations.
+ Erich Fritscher
+ for his very kind sponsoring.
+ Louis Ohland,
+ Charles Lasitter
+ for support by shipping me an IBM SCSI-2 Fast/Wide manual.
+ In addition, the contribution of various hardware is quite
+ decessive and will make it possible to add FWSR (RAID)
+ adapter support to the driver in the near future! So,
+ complaints about no RAID support won't remain forever.
+ Yes, folks, that is no joke, RAID support is going to rise!
+ Erik Weber
+ for the great deal we made about a model 9595 and the nice
+ surrounding equipment and the cool trip to Mannheim
+ second-hand computer market.
+ Anthony Hogbin
+ for his direct shipment of a SCSI F/W adapter, which allowed
+ me immediately on the first stage to try it on model 8557
+ together with onboard SCSI adapter and some SCSI w/Cache.
+ Andreas Hotz
+ for his support by memory and an IBM SCSI-adapter. Collecting
+ all this together now allows me to try really things with
+ the driver at maximum load and variety on various models in
+ a very quick and efficient way.
+ Peter Jennewein
+ for his model 30, which serves me as part of my teststand
+ and his cool remark about how you make an ordinary diskette
+ drive working and how to connect it to an IBM-diskette port.
+ Johannes Gutenberg-University, Mainz &
+ Institut fuer Kernphysik, MAMI
+ for the offered space, the link, placed on the central
+ homepage and the space to store and offer the driver and
+ related material and the free working times, which allow
+ me to answer all your e-mail.
+
+ 8 Trademarks
------------
IBM, PS/2, OS/2, Microchannel are registered trademarks of International
- Business Machines Corp.
+ Business Machines Corporation
MS-DOS is a registered trademark of Microsoft Corporation
- OS-9 is a registered trademark of Microware Systems
+ Microware, OS-9 are registered trademarks of Microware Systems
+
+ 9 Disclaimer
+ ------------
+ Beside the GNU public license and the dependant disclaimers and disclaimers
+ concerning the Linux-kernel in special, this SCSI-driver comes without any
+ warranty. Its functionality is tested as good as possible on certain
+ machines and combinations of computer hardware, which does not exclude,
+ that dataloss or severe damage of hardware is possible while using this
+ part of software on some arbitrary computer hardware or in combination
+ with other software packages. It is highly recommended to make backup
+ copies of your data before using this software.
+
+ This driver supports hardware, produced by International Business Machines
+ Corporation (IBM).
------
Michael Lang
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 393cf909e..aa4cca390 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -7,7 +7,7 @@
* See the file README.ibmmca for a detailed description of this driver,
* the commandline arguments and the history of its development.
* See the WWW-page: http://www.uni-mainz.de/~langm000/linux.html for latest
- * updates and info.
+ * updates, info and ADF-files for adapters supported by this driver.
*/
/******************* HEADER FILE INCLUDES ************************************/
@@ -16,9 +16,12 @@
#endif
/* choose adaption for Kernellevel */
-#define local_LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,65)
+#define OLDKERN
+#else
+#undef OLDKERN
+#endif
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/ctype.h>
@@ -31,8 +34,13 @@
#include <linux/stat.h>
#include <linux/mca.h>
#include <asm/system.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17)
#include <linux/spinlock.h>
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#include <asm/spinlock.h>
+#endif
#include <asm/io.h>
+#include <linux/init.h>
#include "sd.h"
#include "scsi.h"
#include "hosts.h"
@@ -42,6 +50,7 @@
/******************* LOCAL DEFINES *******************************************/
+/* milliseconds of delay for timing out reset. */
#ifndef mdelay
#define mdelay(a) udelay((a) * 1000)
#endif
@@ -49,7 +58,7 @@
/*--------------------------------------------------------------------*/
/* current version of this driver-source: */
-#define IBMMCA_SCSI_DRIVER_VERSION "3.1e"
+#define IBMMCA_SCSI_DRIVER_VERSION "3.2"
/*--------------------------------------------------------------------*/
@@ -60,17 +69,17 @@
/* driver debugging - #undef all for normal operation */
/* if defined: count interrupts and ignore this special one: */
-#undef IM_DEBUG_TIMEOUT 50
+#undef IM_DEBUG_TIMEOUT 50
#define TIMEOUT_PUN 0
#define TIMEOUT_LUN 0
/* verbose interrupt: */
-#undef IM_DEBUG_INT
+#undef IM_DEBUG_INT
/* verbose queuecommand: */
-#undef IM_DEBUG_CMD
+#undef IM_DEBUG_CMD
/* verbose queucommand for specific SCSI-device type: */
-#undef IM_DEBUG_CMD_SPEC_DEV
+#undef IM_DEBUG_CMD_SPEC_DEV
/* verbose device probing */
-#undef IM_DEBUG_PROBE
+#define IM_DEBUG_PROBE
/* device type that shall be displayed on syslog (only during debugging): */
#define IM_DEBUG_CMD_DEVICE TYPE_TAPE
@@ -103,6 +112,7 @@
/*note: the lower nibble specifies the device(0-14), or subsystem(15) */
#define IM_SCB_CMD_COMPLETED 0x10
#define IM_SCB_CMD_COMPLETED_WITH_RETRIES 0x50
+#define IM_LOOP_SCATTER_BUFFER_FULL 0x60
#define IM_ADAPTER_HW_FAILURE 0x70
#define IM_IMMEDIATE_CMD_COMPLETED 0xa0
#define IM_CMD_COMPLETED_WITH_FAILURE 0xc0
@@ -146,7 +156,7 @@ struct im_scb
unsigned short length; /*block length, on SCSI device */
}
blk;
- unsigned char scsi_command[12]; /*other scsi command */
+ unsigned char scsi_command[12]; /*other scsi command */
}
u2;
};
@@ -158,6 +168,31 @@ struct im_sge
unsigned long byte_length;
};
+/*structure returned by a get_pos_info command: */
+struct im_pos_info
+ {
+ unsigned short pos_id; /* adapter id */
+ unsigned char pos_3a; /* pos 3 (if pos 6 = 0) */
+ unsigned char pos_2; /* pos 2 */
+ unsigned char int_level; /* interrupt level IRQ 11 or 14 */
+ unsigned char pos_4a; /* pos 4 (if pos 6 = 0) */
+ unsigned short connector_size; /* MCA connector size: 16 or 32 Bit */
+ unsigned char num_luns; /* number of supported luns per device */
+ unsigned char num_puns; /* number of supported puns */
+ unsigned char pacing_factor; /* pacing factor */
+ unsigned char num_ldns; /* number of ldns available */
+ unsigned char eoi_off; /* time EOI and interrupt inactive */
+ unsigned char max_busy; /* time between reset and busy on */
+ unsigned short cache_stat; /* ldn cachestat. Bit=1 = not cached */
+ unsigned short retry_stat; /* retry status of ldns. Bit=1=disabled */
+ unsigned char pos_4b; /* pos 4 (if pos 6 = 1) */
+ unsigned char pos_3b; /* pos 3 (if pos 6 = 1) */
+ unsigned char pos_6; /* pos 6 */
+ unsigned char pos_5; /* pos 5 */
+ unsigned short max_overlap; /* maximum overlapping requests */
+ unsigned short num_bus; /* number of SCSI-busses */
+ };
+
/*values for SCB command word */
#define IM_NO_SYNCHRONOUS 0x0040 /*flag for any command */
#define IM_NO_DISCONNECT 0x0080 /*flag for any command */
@@ -168,6 +203,7 @@ struct im_sge
#define IM_REQUEST_SENSE_CMD 0x1c08
#define IM_READ_CAPACITY_CMD 0x1c09
#define IM_DEVICE_INQUIRY_CMD 0x1c0b
+#define IM_READ_LOGICAL_CMD 0x1c2a
#define IM_OTHER_SCSI_CMD_CMD 0x241f
/* unused, but supported, SCB commands */
@@ -183,6 +219,7 @@ struct im_sge
#define IM_RETRY_ENABLE 0x2000
#define IM_POINTER_TO_LIST 0x1000
#define IM_SUPRESS_EXCEPTION_SHORT 0x0400
+#define IM_BYPASS_BUFFER 0x0200
#define IM_CHAIN_ON_NO_ERROR 0x0001
/*TSB (Termination Status Block) structure */
@@ -204,15 +241,17 @@ struct im_tsb
};
/*subsystem uses interrupt request level 14 */
-#define IM_IRQ 14
+#define IM_IRQ 14
+/*SCSI-2 F/W may evade to interrupt 11 */
+#define IM_IRQ_FW 11
/*--------------------------------------------------------------------*/
/*
The model 95 doesn't have a standard activity light. Instead it
- has a row of LEDs on the front. We use the last one as the activity
- indicator if we think we're on a model 95. I suspect the model id
- check will be either too narrow or too general, and some machines
- won't have an activity indicator. Oh well...
+ has a row of alphanumerial LEDs on the front. We use the last one
+ as the activity indicator if we think we're on a model 95. I suspect
+ the model id check will be either too narrow or too general, and some
+ machines won't have an activity indicator. Oh well...
The regular PS/2 disk led is turned on/off by bits 6,7 of system
control port.
@@ -222,6 +261,12 @@ struct im_tsb
#define MOD95_LED_PORT 0x108
/* system-control-register of PS/2s with diskindicator */
#define PS2_SYS_CTR 0x92
+/* activity displaying methods */
+#define LED_DISP 1
+#define LED_ADISP 2
+#define LED_ACTIVITY 4
+
+#define CMD_FAIL 255
/* The SCSI-ID(!) of the accessed SCSI-device is shown on PS/2-95 machines' LED
displays. ldn is no longer displayed here, because the ldn mapping is now
@@ -230,30 +275,39 @@ struct im_tsb
interest, debugging or just for having fun. The left number gives the
host-adapter number and the right shows the accessed SCSI-ID. */
-/* use_display is set by the ibmmcascsi=display command line arg */
-static int use_display = 0;
-/* use_adisplay is set by ibmmcascsi=adisplay, which offers a higher
- * level of displayed luxus on PS/2 95 (really fancy! :-))) */
-static int use_adisplay = 0;
-
+/* display_mode is set by the ibmmcascsi= command line arg */
+static int display_mode = 0;
+/* set default adapter timeout */
+static unsigned int adapter_timeout = 45;
+/* for probing on feature-command: */
+static unsigned int global_command_error_excuse = 0;
+/* global setting by command line for adapter_speed */
+static int global_adapter_speed = 0; /* full speed by default */
+
+/* Panel / LED on, do it right for F/W addressin, too. adisplay will
+ * just ignore ids>7, as the panel has only 7 digits available */
#define PS2_DISK_LED_ON(ad,id) {\
- if( use_display ) { outb((char)(id+48), MOD95_LED_PORT ); \
- outb((char)(ad+48), MOD95_LED_PORT+1); } \
- else if( use_adisplay ) { if (id<7) outb((char)(id+48), \
- MOD95_LED_PORT+1+id); outb((char)(ad+48), MOD95_LED_PORT); } \
- else outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); \
+ if (display_mode & LED_DISP) { \
+ if (id>9) \
+ outw((ad+48)|((id+55)<<8), MOD95_LED_PORT ); \
+ else \
+ outw((ad+48)|((id+48)<<8), MOD95_LED_PORT ); } \
+ else if (display_mode & LED_ADISP) { \
+ if (id<7) outb((char)(id+48),MOD95_LED_PORT+1+id); \
+ outb((char)(ad+48), MOD95_LED_PORT); } \
+ if ((display_mode & LED_ACTIVITY)||(!display_mode)) \
+ outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); \
}
-
+/* Panel / LED off */
/* bug fixed, Dec 15, 1997, where | was replaced by & here */
#define PS2_DISK_LED_OFF() {\
- if( use_display ) { outb( ' ', MOD95_LED_PORT ); \
- outb(' ', MOD95_LED_PORT+1); } \
- if ( use_adisplay ) { outb(' ',MOD95_LED_PORT ); \
- outb(' ',MOD95_LED_PORT+1); outb(' ',MOD95_LED_PORT+2); \
- outb(' ',MOD95_LED_PORT+3); outb(' ',MOD95_LED_PORT+4); \
- outb(' ',MOD95_LED_PORT+5); outb(' ',MOD95_LED_PORT+6); \
- outb(' ',MOD95_LED_PORT+7); } \
- else outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); \
+ if (display_mode & LED_DISP) \
+ outw(0x2020, MOD95_LED_PORT ); \
+ else if (display_mode & LED_ADISP) { \
+ outl(0x20202020,MOD95_LED_PORT); \
+ outl(0x20202020,MOD95_LED_PORT+4); } \
+ if ((display_mode & LED_ACTIVITY)||(!display_mode)) \
+ outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); \
}
/*--------------------------------------------------------------------*/
@@ -265,15 +319,37 @@ struct subsys_list_struct
char *description;
};
+/* types of different supported hardware that goes to hostdata special */
+#define IBM_SCSI2_FW 0
+#define IBM_7568_WCACHE 1
+#define IBM_EXP_UNIT 2
+#define IBM_SCSI_WCACHE 3
+#define IBM_SCSI 4
+
+/* other special flags for hostdata structure */
+#define FORCED_DETECTION 100
+#define INTEGRATED_SCSI 101
+
/* List of possible IBM-SCSI-adapters */
struct subsys_list_struct subsys_list[] =
{
- {0x8efc, "IBM Fast SCSI-2 Adapter"}, /* special = 0 */
- {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/cache"}, /* special = 1 */
+ {0x8efc, "IBM SCSI-2 F/W Adapter"}, /* special = 0 */
+ {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/Cache"}, /* special = 1 */
{0x8ef8, "IBM Expansion Unit SCSI Controller"},/* special = 2 */
{0x8eff, "IBM SCSI Adapter w/Cache"}, /* special = 3 */
{0x8efe, "IBM SCSI Adapter"}, /* special = 4 */
+};
+
+/*for /proc filesystem, only valid in older kernel releases */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,27)
+struct proc_dir_entry proc_scsi_ibmmca =
+{
+ PROC_SCSI_IBMMCA, 6, "ibmmca",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2,
+ 0, 0, 0, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL
};
+#endif
/* Max number of logical devices (can be up from 0 to 14). 15 is the address
of the adapter itself. */
@@ -286,11 +362,12 @@ struct logical_device
struct im_tsb tsb; /* SCSI command complete status block structure */
struct im_sge sge[16]; /* scatter gather list structure */
unsigned char buf[256]; /* SCSI command return data buffer */
- Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */
-
+ Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */
int device_type; /* type of the SCSI-device. See include/scsi/scsi.h
for interpretation of the possible values */
int block_length;/* blocksize of a particular logical SCSI-device */
+ int cache_flag; /* 1 if this is uncached, 0 if cache is present for ldn */
+ int retry_flag; /* 1 if adapter retry is disabled, 0 if enabled */
};
/* statistics of the driver during operations (for proc_info) */
@@ -302,6 +379,8 @@ struct Driver_Statistics
int ldn_write_access[MAX_LOG_DEV+1]; /* total write-access on a ldn */
int ldn_inquiry_access[MAX_LOG_DEV+1]; /* total inquiries on a ldn */
int ldn_modeselect_access[MAX_LOG_DEV+1]; /* total mode selects on ldn */
+ int scbs; /* short SCBs queued */
+ int long_scbs; /* long SCBs queued */
int total_accesses; /* total accesses on all ldns */
int total_interrupts; /* total interrupts (should be
same as total_accesses) */
@@ -318,12 +397,12 @@ struct Driver_Statistics
struct ibmmca_hostdata
{
/* array of logical devices: */
- struct logical_device _ld[MAX_LOG_DEV+1];
+ struct logical_device _ld[MAX_LOG_DEV+1];
/* array to convert (pun, lun) into logical device number: */
- unsigned char _get_ldn[8][8];
+ unsigned char _get_ldn[16][8];
/*array that contains the information about the physical SCSI-devices
attached to this host adapter: */
- unsigned char _get_scsi[8][8];
+ unsigned char _get_scsi[16][8];
/* used only when checking logical devices: */
int _local_checking_phase_flag;
/* report received interrupt: */
@@ -336,21 +415,30 @@ struct ibmmca_hostdata
int _last_scsi_command[MAX_LOG_DEV+1];
/* identifier of the last SCSI-command type */
int _last_scsi_type[MAX_LOG_DEV+1];
- /* Counter that points on the next reassignable ldn for dynamical
- remapping. The default value is 7, that is the first reassignable
+ /* last blockcount */
+ int _last_scsi_blockcount[MAX_LOG_DEV+1];
+ /* last locgical block address */
+ unsigned long _last_scsi_logical_block[MAX_LOG_DEV+1];
+ /* Counter that points on the next reassignable ldn for dynamical
+ remapping. The default value is 7, that is the first reassignable
number in the list at boottime: */
int _next_ldn;
/* Statistics-structure for this IBM-SCSI-host: */
struct Driver_Statistics _IBM_DS;
- /* This hostadapters pos-registers pos2 and pos3 */
- unsigned _pos2, _pos3;
+ /* This hostadapters pos-registers pos2 until pos6 */
+ unsigned _pos2, _pos3, _pos4, _pos5, _pos6;
/* assign a special variable, that contains dedicated info about the
adaptertype */
int _special;
+ /* connector size on the MCA bus */
+ int _connector_size;
+ /* synchronous SCSI transfer rate bitpattern */
+ int _adapter_speed;
};
/* macros to access host data structure */
#define subsystem_pun(hi) (hosts[(hi)]->this_id)
+#define subsystem_maxid(hi) (hosts[(hi)]->max_id)
#define ld(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_ld)
#define get_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_ldn)
#define get_scsi(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_scsi)
@@ -360,13 +448,21 @@ struct ibmmca_hostdata
#define reset_status(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_reset_status)
#define last_scsi_command(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_command)
#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
+#define last_scsi_blockcount(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_blockcount)
+#define last_scsi_logical_block(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_logical_block)
+#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
#define next_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_next_ldn)
#define IBM_DS(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_IBM_DS)
#define special(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_special)
+#define subsystem_connector_size(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_connector_size)
+#define adapter_speed(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_adapter_speed)
#define pos2(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos2)
#define pos3(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos3)
+#define pos4(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos4)
+#define pos5(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos5)
+#define pos6(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos6)
-/* Define a arbitrary number as subsystem-marker-type. This number is, as
+/* Define a arbitrary number as subsystem-marker-type. This number is, as
described in the ANSI-SCSI-standard, not occupied by other device-types. */
#define TYPE_IBM_SCSI_ADAPTER 0x2F
@@ -396,10 +492,6 @@ struct ibmmca_hostdata
#define IM_RESET_NOT_IN_PROGRESS_NO_INT 4
#define IM_RESET_FINISHED_OK_NO_INT 5
-/* special flags for hostdata structure */
-#define FORCED_DETECTION 100
-#define INTEGRATED_SCSI 101
-
/* define undefined SCSI-command */
#define NO_SCSI 0xffff
@@ -409,22 +501,40 @@ struct ibmmca_hostdata
static int io_port[IM_MAX_HOSTS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static int scsi_id[IM_MAX_HOSTS] = { 7, 7, 7, 7, 7, 7, 7, 7 };
+/* fill module-parameters only, when this define is present.
+ (that is kernel version 2.1.x) */
+#if defined(MODULE)
+static char *boot_options = NULL;
+#include <linux/module.h>
+MODULE_PARM(boot_options, "s");
+MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
+MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
+MODULE_PARM(display, "1i");
+MODULE_PARM(adisplay, "1i");
+MODULE_PARM(bypass, "1i");
+MODULE_PARM(normal, "1i");
+MODULE_PARM(ansi, "1i");
+#endif
/*counter of concurrent disk read/writes, to turn on/off disk led */
static int disk_rw_in_progress = 0;
/* spinlock handling to avoid command clash while in operation */
+#ifndef OLDKERN
spinlock_t info_lock = SPIN_LOCK_UNLOCKED;
spinlock_t proc_lock = SPIN_LOCK_UNLOCKED;
spinlock_t abort_lock = SPIN_LOCK_UNLOCKED;
spinlock_t reset_lock = SPIN_LOCK_UNLOCKED;
spinlock_t issue_lock = SPIN_LOCK_UNLOCKED;
spinlock_t intr_lock = SPIN_LOCK_UNLOCKED;
+#endif
/* host information */
static int found = 0;
-static struct Scsi_Host *hosts[IM_MAX_HOSTS+1] = { NULL };
-static unsigned int pos[8]; /* whole pos register-line */
+static struct Scsi_Host *hosts[IM_MAX_HOSTS+1] = { NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL };
+static unsigned int pos[8]; /* whole pos register-line for diagnosis */
/* Taking into account the additions, made by ZP Gu.
* This selects now the preset value from the configfile and
* offers the 'normal' commandline option to be accepted */
@@ -439,32 +549,40 @@ static char ibm_ansi_order = 0;
/******************* FUNCTIONS IN FORWARD DECLARATION ************************/
static void interrupt_handler (int, void *, struct pt_regs *);
+#ifndef OLDKERN
static void do_interrupt_handler (int, void *, struct pt_regs *);
+#endif
static void issue_cmd (int, unsigned long, unsigned char);
static void internal_done (Scsi_Cmnd * cmd);
-static void check_devices (int);
-static int immediate_assign(int, unsigned int, unsigned int, unsigned int,
+static void check_devices (int, int);
+static int immediate_assign(int, unsigned int, unsigned int, unsigned int,
unsigned int);
+static int immediate_feature(int, unsigned int, unsigned int);
#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
static int immediate_reset(int, unsigned int);
#endif
static int device_inquiry(int, int);
static int read_capacity(int, int);
+static int get_pos_info(int);
static char *ti_p(int);
static char *ti_l(int);
+static char *ibmrate(unsigned int, int);
+static int probe_display(int);
+static int probe_bus_mode(int);
static int device_exists (int, int, int *, int *);
static struct Scsi_Host *ibmmca_register(Scsi_Host_Template *,
- int, int, char *);
-
+ int, int, int, char *);
/* local functions needed for proc_info */
static int ldn_access_load(int, int);
static int ldn_access_total_read_write(int);
static int bypass_controller = 0; /* bypass integrated SCSI-cmd set flag */
+
/*--------------------------------------------------------------------*/
/******************* LOCAL FUNCTIONS IMPLEMENTATION *************************/
+#ifndef OLDKERN
/* newer Kernels need the spinlock interrupt handler */
static void do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
{
@@ -473,8 +591,9 @@ static void do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
spin_lock_irqsave(&io_request_lock, flags);
interrupt_handler(irq, dev_id, regs);
spin_unlock_irqrestore(&io_request_lock, flags);
- return;
+ return;
}
+#endif
static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
{
@@ -482,20 +601,17 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
unsigned int intr_reg;
unsigned int cmd_result;
unsigned int ldn;
- static unsigned long flags;
+ unsigned long flags;
Scsi_Cmnd *cmd;
- int errorflag;
- int interror;
-
- host_index=0; /* make sure, host_index is 0, else this won't work and
- never dare to ask, what happens, if an interrupt-handler
- does not work :-((( .... */
+ int lastSCSI;
+
+ host_index = 0; /* make sure, host_index is 0 */
/* search for one adapter-response on shared interrupt */
while (hosts[host_index]
&& !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST))
host_index++;
-
+
/* return if some other device on this IRQ caused the interrupt */
if (!hosts[host_index]) return;
@@ -507,88 +623,126 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS;
return;
}
-
- /*get command result and logical device */
- intr_reg = inb (IM_INTR_REG(host_index));
- cmd_result = intr_reg & 0xf0;
- ldn = intr_reg & 0x0f;
-
+
/*must wait for attention reg not busy, then send EOI to subsystem */
- while (1)
+ while (1)
{
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
spin_lock_irqsave(&intr_lock, flags);
- if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+#endif
+ /* if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY)) */
+ if ((inb(IM_STAT_REG(host_index)) & 0xf) == (IM_CMD_REG_EMPTY | IM_INTR_REQUEST))
break;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&intr_lock, flags);
+#endif
}
- outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+ /*get command result and logical device */
+ intr_reg = (unsigned char)(inb (IM_INTR_REG(host_index)));
+ cmd_result = intr_reg & 0xf0;
+ ldn = intr_reg & 0x0f;
+
/* get the last_scsi_command here */
- interror = last_scsi_command(host_index)[ldn];
- spin_unlock_irqrestore(&intr_lock, flags);
- errorflag = 0; /* no errors by default */
+ lastSCSI = last_scsi_command(host_index)[ldn];
+
/*these should never happen (hw fails, or a local programming bug) */
- if (cmd_result == IM_ADAPTER_HW_FAILURE)
- {
- printk("\n");
- printk("IBM MCA SCSI: ERROR - subsystem hardware failure!\n");
- printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n",
- last_scsi_command(host_index)[ldn],ldn,host_index);
- errorflag = 1;
- }
- if (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR)
- {
- printk("\n");
- printk("IBM MCA SCSI: ERROR - software sequencing error!\n");
- printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n",
- last_scsi_command(host_index)[ldn],ldn,host_index);
- errorflag = 1;
- }
- if (cmd_result == IM_CMD_ERROR)
- {
- printk("\n");
- printk("IBM MCA SCSI: ERROR - command error!\n");
- printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n",
- last_scsi_command(host_index)[ldn],ldn,host_index);
- errorflag = 1;
+ if (!global_command_error_excuse)
+ {
+ switch (cmd_result)
+ { /* Prevent from Ooopsing on error to show the real reason */
+ case IM_ADAPTER_HW_FAILURE:
+ case IM_SOFTWARE_SEQUENCING_ERROR:
+ case IM_CMD_ERROR:
+ printk("\nIBM MCA SCSI: Fatal Subsystem ERROR!\n");
+ printk(" Last cmd=0x%x, ena=%x, len=",lastSCSI,
+ ld(host_index)[ldn].scb.enable);
+ if (ld(host_index)[ldn].cmd)
+ printk("%ld/%ld",(long)(ld(host_index)[ldn].cmd->request_bufflen),
+ (long)(ld(host_index)[ldn].scb.sys_buf_length));
+ else
+ printk("none");
+ printk(", ");
+ if (ld(host_index)[ldn].cmd)
+ printk("Blocksize=%d",ld(host_index)[ldn].scb.u2.blk.length);
+ else
+ printk("Blocksize=none");
+ printk(", host=0x%x, ldn=0x%x\n",host_index, ldn);
+ if (ld(host_index)[ldn].cmd)
+ {
+ printk("Blockcount=%d/%d\n",last_scsi_blockcount(host_index)[ldn],
+ ld(host_index)[ldn].scb.u2.blk.count);
+ printk("Logical block=%lx/%lx\n",last_scsi_logical_block(host_index)[ldn],
+ ld(host_index)[ldn].scb.u1.log_blk_adr);
+ }
+ printk("Reason given: %s\n",
+ (cmd_result==IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" :
+ (cmd_result==IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" :
+ (cmd_result==IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN");
+ /* if errors appear, enter this section to give detailed info */
+ printk("IBM MCA SCSI: Subsystem Error-Status follows:\n");
+ printk(" Command Type................: %x\n",
+ last_scsi_type(host_index)[ldn]);
+ printk(" Attention Register..........: %x\n",
+ inb (IM_ATTN_REG(host_index)));
+ printk(" Basic Control Register......: %x\n",
+ inb (IM_CTR_REG(host_index)));
+ printk(" Interrupt Status Register...: %x\n",
+ intr_reg);
+ printk(" Basic Status Register.......: %x\n",
+ inb (IM_STAT_REG(host_index)));
+ if ((last_scsi_type(host_index)[ldn]==IM_SCB)||
+ (last_scsi_type(host_index)[ldn]==IM_LONG_SCB))
+ {
+ printk(" SCB-Command.................: %x\n",
+ ld(host_index)[ldn].scb.command);
+ printk(" SCB-Enable..................: %x\n",
+ ld(host_index)[ldn].scb.enable);
+ printk(" SCB-logical block address...: %lx\n",
+ ld(host_index)[ldn].scb.u1.log_blk_adr);
+ printk(" SCB-system buffer address...: %lx\n",
+ ld(host_index)[ldn].scb.sys_buf_adr);
+ printk(" SCB-system buffer length....: %lx\n",
+ ld(host_index)[ldn].scb.sys_buf_length);
+ printk(" SCB-tsb address.............: %lx\n",
+ ld(host_index)[ldn].scb.tsb_adr);
+ printk(" SCB-Chain address...........: %lx\n",
+ ld(host_index)[ldn].scb.scb_chain_adr);
+ printk(" SCB-block count.............: %x\n",
+ ld(host_index)[ldn].scb.u2.blk.count);
+ printk(" SCB-block length............: %x\n",
+ ld(host_index)[ldn].scb.u2.blk.length);
+ }
+ printk(" Send this report to the maintainer.\n");
+ panic("IBM MCA SCSI: Fatal errormessage from the subsystem (0x%X,0x%X)!\n",
+ lastSCSI,cmd_result);
+ break;
+ }
}
- if (errorflag)
- { /* if errors appear, enter this section to give detailed info */
- printk("IBM MCA SCSI: Subsystem Error-Status follows:\n");
- printk(" Command Type................: %x\n",
- last_scsi_type(host_index)[ldn]);
- printk(" Attention Register..........: %x\n",
- inb (IM_ATTN_REG(host_index)));
- printk(" Basic Control Register......: %x\n",
- inb (IM_CTR_REG(host_index)));
- printk(" Interrupt Status Register...: %x\n",
- intr_reg);
- printk(" Basic Status Register.......: %x\n",
- inb (IM_STAT_REG(host_index)));
- if ((last_scsi_type(host_index)[ldn]==IM_SCB)||
- (last_scsi_type(host_index)[ldn]==IM_LONG_SCB))
+ else
+ { /* The command error handling is made silent, but we tell the
+ * calling function, that there is a reported error from the
+ * adapter. */
+ switch (cmd_result)
{
- printk(" SCB End Status Word.........: %x\n",
- ld(host_index)[ldn].tsb.end_status);
- printk(" Command Status..............: %x\n",
- ld(host_index)[ldn].tsb.cmd_status);
- printk(" Device Status...............: %x\n",
- ld(host_index)[ldn].tsb.dev_status);
- printk(" Command Error...............: %x\n",
- ld(host_index)[ldn].tsb.cmd_error);
- printk(" Device Error................: %x\n",
- ld(host_index)[ldn].tsb.dev_error);
- printk(" Last SCB Address (LSW)......: %x\n",
- ld(host_index)[ldn].tsb.low_of_last_scb_adr);
- printk(" Last SCB Address (MSW)......: %x\n",
- ld(host_index)[ldn].tsb.high_of_last_scb_adr);
+ case IM_ADAPTER_HW_FAILURE:
+ case IM_SOFTWARE_SEQUENCING_ERROR:
+ case IM_CMD_ERROR:
+ global_command_error_excuse = CMD_FAIL;
+ break;
+ default:
+ global_command_error_excuse = 0;
+ break;
}
- printk(" Send report to the maintainer.\n");
- panic("IBM MCA SCSI: Fatal errormessage from the subsystem!\n");
- }
-
+ }
+
/* if no panic appeared, increase the interrupt-counter */
IBM_DS(host_index).total_interrupts++;
-
+
/*only for local checking phase */
if (local_checking_phase_flag(host_index))
{
@@ -596,8 +750,15 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
got_interrupt(host_index) = 1;
reset_status(host_index) = IM_RESET_FINISHED_OK;
last_scsi_command(host_index)[ldn] = NO_SCSI;
+
+ outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
+#endif
return;
- }
+ }
/*handling of commands coming from upper level of scsi driver */
else
{
@@ -622,24 +783,39 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
}
stat_result(host_index) = cmd_result;
last_scsi_command(host_index)[ldn] = NO_SCSI;
+ last_scsi_type(host_index)[ldn] = 0;
+ outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
+#endif
return;
}
else if (last_scsi_command(host_index)[ldn] == IM_ABORT_IMM_CMD)
{ /* react on SCSI abort command */
#ifdef IM_DEBUG_PROBE
printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n");
-#endif
+#endif
disk_rw_in_progress = 0;
PS2_DISK_LED_OFF();
cmd = ld(host_index)[ldn].cmd;
+ ld(host_index)[ldn].cmd = NULL;
if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
cmd->result = DID_NO_CONNECT << 16;
else
cmd->result = DID_ABORT << 16;
stat_result(host_index) = cmd_result;
last_scsi_command(host_index)[ldn] = NO_SCSI;
+ last_scsi_type(host_index)[ldn] = 0;
+ outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
+#endif
if (cmd->scsi_done)
- (cmd->scsi_done) (cmd); /* should be the internal_done */
+ (cmd->scsi_done)(cmd); /* should be the internal_done */
return;
}
else
@@ -649,36 +825,59 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
reset_status(host_index) = IM_RESET_FINISHED_OK;
stat_result(host_index) = cmd_result;
last_scsi_command(host_index)[ldn] = NO_SCSI;
+
+ outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
+#endif
return;
- }
+ }
}
last_scsi_command(host_index)[ldn] = NO_SCSI;
+ last_scsi_type(host_index)[ldn] = 0;
cmd = ld(host_index)[ldn].cmd;
+ ld(host_index)[ldn].cmd = NULL;
#ifdef IM_DEBUG_TIMEOUT
if (cmd)
{
- if ((cmd->target == TIMEOUT_PUN)&&(cmd->lun == TIMEOUT_LUN))
+ if ((cmd->target == TIMEOUT_PUN)&&
+ (cmd->lun == TIMEOUT_LUN))
{
printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n",
cmd->target, cmd->lun);
+ outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
+#endif
return;
}
}
#endif
/*if no command structure, just return, else clear cmd */
if (!cmd)
- return;
- ld(host_index)[ldn].cmd = NULL;
-
+ {
+ outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
+#endif
+ return;
+ }
+
#ifdef IM_DEBUG_INT
- printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n",
- cmd->cmnd[0], intr_reg,
- ld(host_index)[ldn].tsb.dev_status,
+ printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n",
+ cmd->cmnd[0], intr_reg,
+ ld(host_index)[ldn].tsb.dev_status,
ld(host_index)[ldn].tsb.cmd_status,
- ld(host_index)[ldn].tsb.dev_error,
+ ld(host_index)[ldn].tsb.dev_error,
ld(host_index)[ldn].tsb.cmd_error);
#endif
-
+
/*if this is end of media read/write, may turn off PS/2 disk led */
if ((ld(host_index)[ldn].device_type!=TYPE_NO_LUN)&&
(ld(host_index)[ldn].device_type!=TYPE_NO_DEVICE))
@@ -697,41 +896,73 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
}
/* IBM describes the status-mask to be 0x1e, but this is not conform
- * with SCSI-defintion, I suppose, it is a printing error in the
- * technical reference and assume as mask 0x3e. (ML) */
- cmd->result = (ld(host_index)[ldn].tsb.dev_status & 0x3e);
- /* write device status into cmd->result, and call done function */
+ * with SCSI-defintion, I suppose, the reason for it is that IBM
+ * adapters do not support CMD_TERMINATED, TASK_SET_FULL and
+ * ACA_ACTIVE as returning statusbyte information. (ML) */
if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
- IBM_DS(host_index).total_errors++;
- if (interror == NO_SCSI) /* unexpected interrupt :-( */
- cmd->result |= DID_BAD_INTR << 16;
+ {
+ cmd->result = (unsigned char)(ld(host_index)[ldn].tsb.dev_status & 0x1e);
+ IBM_DS(host_index).total_errors++;
+ }
else
+ cmd->result = 0;
+ /* write device status into cmd->result, and call done function */
+ if (lastSCSI == NO_SCSI) /* unexpected interrupt :-( */
+ cmd->result |= DID_BAD_INTR << 16;
+ else /* things went right :-) */
cmd->result |= DID_OK << 16;
- (cmd->scsi_done) (cmd);
- }
- if (interror == NO_SCSI)
+ outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
+#endif
+ /* This is for Kernel 2.2.x. Something weired happens here.
+ * Between the command got queued and the interrupt is released,
+ * the flags sometimes contain different values, which must
+ * be a strange thing. E.g. it appears when cold-booting with a
+ * tape drive at id0. */
+ cmd->flags &= 0x3f;
+ if (cmd->scsi_done)
+ (cmd->scsi_done)(cmd);
+ }
+ if (lastSCSI == NO_SCSI)
printk("IBM MCA SCSI: WARNING - Interrupt from non-pending SCSI-command!\n");
return;
}
/*--------------------------------------------------------------------*/
-static void issue_cmd (int host_index, unsigned long cmd_reg,
+static void issue_cmd (int host_index, unsigned long cmd_reg,
unsigned char attn_reg)
{
static unsigned long flags;
- /* must wait for attention reg not busy */
+ /* must wait for attention reg not busy */
while (1)
{
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
spin_lock_irqsave(&issue_lock, flags);
- if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+#endif
+ if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
break;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&issue_lock, flags);
+#endif
}
/*write registers and enable system interrupts */
outl (cmd_reg, IM_CMD_REG(host_index));
outb (attn_reg, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&issue_lock, flags);
+#endif
+ return;
}
/*--------------------------------------------------------------------*/
@@ -739,75 +970,70 @@ static void issue_cmd (int host_index, unsigned long cmd_reg,
static void internal_done (Scsi_Cmnd * cmd)
{
cmd->SCp.Status++;
+ return;
}
/*--------------------------------------------------------------------*/
/* SCSI-SCB-command for device_inquiry */
static int device_inquiry(int host_index, int ldn)
-{
+{
int retries;
- Scsi_Cmnd *cmd;
+ Scsi_Cmnd cmd;
struct im_scb *scb;
struct im_tsb *tsb;
unsigned char *buf;
-
+
scb = &(ld(host_index)[ldn].scb);
tsb = &(ld(host_index)[ldn].tsb);
buf = (unsigned char *)(&(ld(host_index)[ldn].buf));
ld(host_index)[ldn].tsb.dev_status = 0; /* prepare stusblock */
- cmd = kmalloc(sizeof(*cmd), GFP_KERNEL|GFP_DMA);
- if(cmd==NULL)
- {
- printk(KERN_ERR "ibmmca: out of memory for inquiry.\n");
- return 0;
- }
if (bypass_controller)
{ /* fill the commonly known field for device-inquiry SCSI cmnd */
- cmd->cmd_len = 6;
- memset (&(cmd->cmnd), 0x0, sizeof(char) * cmd->cmd_len);
- cmd->cmnd[0] = INQUIRY; /* device inquiry */
- cmd->cmnd[4] = 0xff; /* return buffer size = 255 */
- }
+ cmd.cmd_len = 6;
+ memset (&(cmd.cmnd), 0x0, sizeof(char) * cmd.cmd_len);
+ cmd.cmnd[0] = INQUIRY; /* device inquiry */
+ cmd.cmnd[4] = 0xff; /* return buffer size = 255 */
+ }
for (retries = 0; retries < 3; retries++)
{
if (bypass_controller)
{ /* bypass the hardware integrated command set */
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy (scb->u2.scsi_command, &(cmd->cmnd), cmd->cmd_len);
+ scb->command = IM_OTHER_SCSI_CMD_CMD | IM_NO_DISCONNECT;
+ scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
+ scb->u1.scsi_cmd_length = cmd.cmd_len;
+ memcpy (scb->u2.scsi_command, &(cmd.cmnd), cmd.cmd_len);
last_scsi_command(host_index)[ldn] = INQUIRY;
- last_scsi_type(host_index)[ldn] = IM_SCB;
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
}
else
{
/*fill scb with inquiry command */
- scb->command = IM_DEVICE_INQUIRY_CMD;
- scb->enable = IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT;
+ scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;
- last_scsi_type(host_index)[ldn] = IM_SCB;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
}
scb->sys_buf_adr = virt_to_bus(buf);
scb->sys_buf_length = 0xff; /* maximum bufferlength gives max info */
scb->tsb_adr = virt_to_bus(tsb);
-
+
/*issue scb to passed ldn, and busy wait for interrupt */
got_interrupt(host_index) = 0;
- issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+ if ((scb->command & IM_OTHER_SCSI_CMD_CMD) == IM_OTHER_SCSI_CMD_CMD)
+ issue_cmd (host_index, virt_to_bus(scb), IM_LONG_SCB | ldn);
+ else
+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
while (!got_interrupt(host_index))
barrier ();
-
+
/*if command succesful, break */
if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||
(stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
- {
- return 1;
- }
+ return 1;
}
- kfree(cmd);
-
+
/*if all three retries failed, return "no device at this ldn" */
if (retries >= 3)
return 0;
@@ -822,25 +1048,25 @@ static int read_capacity(int host_index, int ldn)
struct im_scb *scb;
struct im_tsb *tsb;
unsigned char *buf;
-
+
scb = &(ld(host_index)[ldn].scb);
tsb = &(ld(host_index)[ldn].tsb);
buf = (unsigned char *)(&(ld(host_index)[ldn].buf));
ld(host_index)[ldn].tsb.dev_status = 0;
-
+
if (bypass_controller)
{ /* read capacity in commonly known default SCSI-format */
cmd.cmd_len = 10;
memset (&(cmd.cmnd), 0x0, sizeof(char) * cmd.cmd_len);
cmd.cmnd[0] = READ_CAPACITY; /* read capacity */
- }
+ }
for (retries = 0; retries < 3; retries++)
{
/*fill scb with read capacity command */
if (bypass_controller)
{ /* bypass the SCSI-command */
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL;
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
scb->u1.scsi_cmd_length = cmd.cmd_len;
memcpy (scb->u2.scsi_command, &(cmd.cmnd), cmd.cmd_len);
last_scsi_command(host_index)[ldn] = READ_CAPACITY;
@@ -849,26 +1075,27 @@ static int read_capacity(int host_index, int ldn)
else
{
scb->command = IM_READ_CAPACITY_CMD;
- scb->enable = IM_READ_CONTROL;
+ scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;
- last_scsi_type(host_index)[ldn] = IM_SCB;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
}
scb->sys_buf_adr = virt_to_bus(buf);
scb->sys_buf_length = 8;
scb->tsb_adr = virt_to_bus(tsb);
-
+
/*issue scb to passed ldn, and busy wait for interrupt */
got_interrupt(host_index) = 0;
- issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+ if ((scb->command & IM_OTHER_SCSI_CMD_CMD) == IM_OTHER_SCSI_CMD_CMD)
+ issue_cmd (host_index, virt_to_bus(scb), IM_LONG_SCB | ldn);
+ else
+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
while (!got_interrupt(host_index))
barrier ();
-
- /*if got capacity, get block length and return one device found */
+
+ /*if got capacity, get block length and return one device found */
if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||
(stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
- {
- return 1;
- }
+ return 1;
}
/*if all three retries failed, return "no device at this ldn" */
if (retries >= 3)
@@ -877,41 +1104,141 @@ static int read_capacity(int host_index, int ldn)
return 1;
}
+static int get_pos_info(int host_index)
+{
+ int retries;
+ struct im_scb *scb;
+ struct im_tsb *tsb;
+ unsigned char *buf;
+
+ scb = &(ld(host_index)[MAX_LOG_DEV].scb);
+ tsb = &(ld(host_index)[MAX_LOG_DEV].tsb);
+ buf = (unsigned char *)(&(ld(host_index)[MAX_LOG_DEV].buf));
+ ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0;
+
+ for (retries = 0; retries < 3; retries++)
+ {
+ /*fill scb with get_pos_info command */
+ scb->command = IM_GET_POS_INFO_CMD;
+ scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER | IM_SUPRESS_EXCEPTION_SHORT;
+ last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
+ last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB;
+
+ scb->sys_buf_adr = virt_to_bus(buf);
+ if (special(host_index)==IBM_SCSI2_FW)
+ scb->sys_buf_length = 256; /* get all info from F/W adapter */
+ else
+ scb->sys_buf_length = 18; /* get exactly 18 bytes for other SCSI */
+
+ scb->tsb_adr = virt_to_bus(tsb);
+
+ /*issue scb to ldn=15, and busy wait for interrupt */
+ got_interrupt(host_index) = 0;
+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
+ while (!got_interrupt(host_index))
+ barrier ();
+
+ /*if got POS-stuff, get block length and return one device found */
+ if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||
+ (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+ return 1;
+ }
+ /* if all three retries failed, return "no device at this ldn" */
+ if (retries >= 3)
+ return 0;
+ else
+ return 1;
+}
+
/* SCSI-immediate-command for assign. This functions maps/unmaps specific
ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
subsystem and for dynamical remapping od ldns. */
-static int immediate_assign(int host_index, unsigned int pun,
- unsigned int lun, unsigned int ldn,
+static int immediate_assign(int host_index, unsigned int pun,
+ unsigned int lun, unsigned int ldn,
unsigned int operation)
{
int retries;
unsigned long imm_command;
-
+
for (retries=0; retries<3; retries ++)
{
- imm_command = inl(IM_CMD_REG(host_index));
- imm_command &= (unsigned long)(0xF8000000); /* keep reserved bits */
- imm_command |= (unsigned long)(IM_ASSIGN_IMM_CMD);
- imm_command |= (unsigned long)((lun & 7) << 24);
- imm_command |= (unsigned long)((operation & 1) << 23);
- imm_command |= (unsigned long)((pun & 7) << 20);
- imm_command |= (unsigned long)((ldn & 15) << 16);
-
- last_scsi_command(host_index)[0xf] = IM_ASSIGN_IMM_CMD;
- last_scsi_type(host_index)[0xf] = IM_IMM_CMD;
+ /* select mutation level of the SCSI-adapter */
+ switch (special(host_index))
+ {
+ case IBM_SCSI2_FW:
+ imm_command = (unsigned long)(IM_ASSIGN_IMM_CMD);
+ imm_command |= (unsigned long)((lun & 7) << 24);
+ imm_command |= (unsigned long)((operation & 1) << 23);
+ imm_command |= (unsigned long)((pun & 7)<< 20)|((pun & 8)<< 24);
+ imm_command |= (unsigned long)((ldn & 15) << 16);
+ break;
+ default:
+ imm_command = inl(IM_CMD_REG(host_index));
+ imm_command &= (unsigned long)(0xF8000000); /* keep reserved bits */
+ imm_command |= (unsigned long)(IM_ASSIGN_IMM_CMD);
+ imm_command |= (unsigned long)((lun & 7) << 24);
+ imm_command |= (unsigned long)((operation & 1) << 23);
+ imm_command |= (unsigned long)((pun & 7) << 20);
+ imm_command |= (unsigned long)((ldn & 15) << 16);
+ break;
+ }
+ last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
+ last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
got_interrupt(host_index) = 0;
- issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | 0xf);
+ issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | MAX_LOG_DEV);
while (!got_interrupt(host_index))
barrier ();
-
+
/*if command succesful, break */
if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+ return 1;
+ }
+ if (retries >= 3)
+ return 0;
+ else
+ return 1;
+}
+
+static int immediate_feature(int host_index, unsigned int speed,
+ unsigned int timeout)
+{
+ int retries;
+ unsigned long imm_command;
+
+ for (retries=0; retries<3; retries ++)
+ {
+ /* select mutation level of the SCSI-adapter */
+ switch (special(host_index))
{
- return 1;
+ default:
+ imm_command = IM_FEATURE_CTR_IMM_CMD;
+ imm_command |= (unsigned long)((speed & 0x7) << 29);
+ imm_command |= (unsigned long)((timeout & 0x1fff) << 16);
+ break;
+ }
+ last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
+ last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
+ got_interrupt(host_index) = 0;
+ /* we need to run into command errors in order to probe for the
+ * right speed! */
+ global_command_error_excuse = 1;
+ issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | MAX_LOG_DEV);
+ while (!got_interrupt(host_index))
+ barrier ();
+ if (global_command_error_excuse == CMD_FAIL)
+ {
+ global_command_error_excuse = 0;
+ return 2;
}
+ else
+ global_command_error_excuse = 0;
+
+ /*if command succesful, break */
+ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+ return 1;
}
-
- if (retries >= 3)
+
+ if (retries >= 3)
return 0;
else
return 1;
@@ -923,7 +1250,7 @@ static int immediate_reset(int host_index, unsigned int ldn)
int retries;
int ticks;
unsigned long imm_command;
-
+
for (retries=0; retries<3; retries ++)
{
imm_command = inl(IM_CMD_REG(host_index));
@@ -933,31 +1260,29 @@ static int immediate_reset(int host_index, unsigned int ldn)
last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
got_interrupt(host_index) = 0;
- reset_status(host_index) = IM_RESET_IN_PROGRESS;
+ reset_status(host_index) = IM_RESET_IN_PROGRESS;
issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | ldn);
- ticks = IM_RESET_DELAY*HZ;
- while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks)
+ ticks = IM_RESET_DELAY*HZ;
+ while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks)
{
mdelay(1+999/HZ);
barrier();
}
/* if reset did not complete, just claim */
- if (!ticks)
+ if (!ticks)
{
printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
IM_RESET_DELAY);
- reset_status(host_index) = IM_RESET_FINISHED_OK;
+ reset_status(host_index) = IM_RESET_FINISHED_OK;
/* did not work, finish */
return 1;
}
/*if command succesful, break */
if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
- {
- return 1;
- }
+ return 1;
}
-
- if (retries >= 3)
+
+ if (retries >= 3)
return 0;
else
return 1;
@@ -990,17 +1315,108 @@ static char *ti_l(int value)
{
const char hex[16] = "0123456789abcdef";
static char answer[2];
-
+
answer[1] = (char)(0x0);
if (value<=MAX_LOG_DEV)
answer[0] = hex[value];
else
answer[0] = '-';
-
+
return (char *)&answer;
}
-/*
+/* transfers bitpattern of the feature command to values in MHz */
+static char *ibmrate(unsigned int speed, int adaptertype)
+{
+ int i;
+ i=adaptertype;
+ switch (speed)
+ {
+ case 0: if (i) return "5.00"; else return "10.00"; break;
+ case 1: if (i) return "4.00"; else return "8.00"; break;
+ case 2: if (i) return "3.33"; else return "6.66"; break;
+ case 3: if (i) return "2.86"; else return "5.00"; break;
+ case 4: if (i) return "2.50"; else return "4.00"; break;
+ case 5: if (i) return "2.22"; else return "3.10"; break;
+ case 6: if (i) return "2.00"; else return "2.50"; break;
+ case 7: if (i) return "1.82"; else return "2.00"; break;
+ }
+ return "---";
+}
+
+static int probe_display(int what)
+{
+ static int rotator = 0;
+ const char rotor[] = "|/-\\";
+
+ if (!(display_mode & LED_DISP))
+ return 0;
+ if (!what)
+ {
+ outl(0x20202020,MOD95_LED_PORT);
+ outl(0x20202020,MOD95_LED_PORT+4);
+ }
+ else
+ {
+ outb('S',MOD95_LED_PORT+7);
+ outb('C',MOD95_LED_PORT+6);
+ outb('S',MOD95_LED_PORT+5);
+ outb('I',MOD95_LED_PORT+4);
+ outb('i',MOD95_LED_PORT+3);
+ outb('n',MOD95_LED_PORT+2);
+ outb('i',MOD95_LED_PORT+1);
+ outb((char)(rotor[rotator]),MOD95_LED_PORT);
+ rotator++;
+ if (rotator>3)
+ rotator=0;
+ }
+ return 0;
+}
+
+static int probe_bus_mode(int host_index)
+{
+ struct im_pos_info *info;
+ int num_bus = 0;
+ int ldn;
+
+ info = (struct im_pos_info *)(&(ld(host_index)[MAX_LOG_DEV].buf));
+
+ if (get_pos_info(host_index))
+ {
+ if (info->connector_size & 0xf000)
+ subsystem_connector_size(host_index)=16;
+ else
+ subsystem_connector_size(host_index)=32;
+ num_bus |= (info->pos_4b & 8) >> 3;
+ for (ldn=0; ldn<=MAX_LOG_DEV; ldn++)
+ {
+ if ((special(host_index)==IBM_SCSI_WCACHE)||
+ (special(host_index)==IBM_7568_WCACHE))
+ {
+ if (!((info->cache_stat >> ldn) & 1))
+ ld(host_index)[ldn].cache_flag = 0;
+ }
+ if (!((info->retry_stat >> ldn) & 1))
+ ld(host_index)[ldn].retry_flag = 0;
+ }
+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: SCSI-Cache bits: ");
+ for (ldn=0; ldn<=MAX_LOG_DEV; ldn++)
+ {
+ printk("%d",ld(host_index)[ldn].cache_flag);
+ }
+ printk("\nIBM MCA SCSI: SCSI-Retry bits: ");
+ for (ldn=0; ldn<=MAX_LOG_DEV; ldn++)
+ {
+ printk("%d",ld(host_index)[ldn].retry_flag);
+ }
+ printk("\n");
+#endif
+ }
+ return num_bus;
+}
+
+/*
The following routine probes the SCSI-devices in four steps:
1. The current ldn -> pun,lun mapping is removed on the SCSI-adapter.
2. ldn 0 is used to go through all possible combinations of pun,lun and
@@ -1020,32 +1436,36 @@ static char *ti_l(int value)
The assignment of ALL ldns avoids dynamical remapping by the adapter
itself.
*/
-static void check_devices (int host_index)
+static void check_devices (int host_index, int adaptertype)
{
int id, lun, ldn, ticks;
int count_devices; /* local counter for connected device */
-
+ int max_pun;
+ int num_bus;
+ int speedrun; /* local adapter_speed check variable */
+
/* assign default values to certain variables */
-
ticks = 0;
count_devices = 0;
IBM_DS(host_index).dyn_flag = 0; /* normally no need for dynamical ldn management */
IBM_DS(host_index).total_errors = 0; /* set errorcounter to 0 */
next_ldn(host_index) = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired'*/
+
+ /* initialize the very important driver-informational arrays/structs */
+ memset (ld(host_index), 0,
+ sizeof(ld(host_index)));
for (ldn=0; ldn<=MAX_LOG_DEV; ldn++)
{
last_scsi_command(host_index)[ldn] = NO_SCSI; /* emptify last SCSI-command storage */
last_scsi_type(host_index)[ldn] = 0;
+ ld(host_index)[ldn].cache_flag = 1;
+ ld(host_index)[ldn].retry_flag = 1;
}
-
- /* initialize the very important driver-informational arrays/structs */
- memset (ld(host_index), 0,
- sizeof(ld(host_index)));
- memset (get_ldn(host_index), TYPE_NO_DEVICE,
+ memset (get_ldn(host_index), TYPE_NO_DEVICE,
sizeof(get_ldn(host_index))); /* this is essential ! */
memset (get_scsi(host_index), TYPE_NO_DEVICE,
sizeof(get_scsi(host_index))); /* this is essential ! */
-
+
for (lun=0; lun<8; lun++) /* mark the adapter at its pun on all luns*/
{
get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER;
@@ -1054,13 +1474,58 @@ static void check_devices (int host_index)
luns. */
}
+ probe_display(0); /* Supercool display usage during SCSI-probing. */
+ /* This makes sense, when booting without any */
+ /* monitor connected on model XX95. */
+
/* STEP 1: */
+ adapter_speed(host_index) = global_adapter_speed;
+ speedrun = adapter_speed(host_index);
+ while (immediate_feature(host_index,speedrun,adapter_timeout)==2)
+ {
+ probe_display(1);
+ if (speedrun==7)
+ panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n");
+ speedrun++;
+ if (speedrun>7)
+ speedrun=7;
+ }
+ adapter_speed(host_index) = speedrun;
+ /* Get detailed information about the current adapter, necessary for
+ * device operations: */
+ num_bus=probe_bus_mode(host_index);
+
+ /* num_bus contains only valid data for the F/W adapter! */
+ if (adaptertype==IBM_SCSI2_FW) /* F/W SCSI adapter: */
+ {
+ /* F/W adapter PUN-space extension evaluation: */
+ if (num_bus)
+ {
+ printk("IBM MCA SCSI: Seperate bus mode (wide-addressing enabled)\n");
+ subsystem_maxid(host_index) = 16;
+ }
+ else
+ {
+ printk("IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n");
+ subsystem_maxid(host_index) = 8;
+ }
+ printk("IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n",
+ ibmrate(speedrun,adaptertype));
+ }
+ else /* all other IBM SCSI adapters: */
+ printk("IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n",
+ ibmrate(speedrun,adaptertype));
+
+ /* assign correct PUN device space */
+ max_pun = subsystem_maxid(host_index);
+
#ifdef IM_DEBUG_PROBE
printk("IBM MCA SCSI: Current SCSI-host index: %d\n",host_index);
#endif
printk("IBM MCA SCSI: Removing default logical SCSI-device mapping.");
for (ldn=0; ldn<MAX_LOG_DEV; ldn++)
{
+ probe_display(1);
#ifdef IM_DEBUG_PROBE
printk(".");
#endif
@@ -1068,14 +1533,20 @@ static void check_devices (int host_index)
}
lun = 0; /* default lun is 0 */
-
+
/* STEP 2: */
- printk("\nIBM MCA SCSI: Probing SCSI-devices.");
- for (id=0; id<8; id++)
+ printk("\nIBM MCA SCSI: Probing SCSI-devices");
+#ifndef IM_DEBUG_PROBE
+ printk(" (this can take up to 2 minutes)");
+#endif
+ printk(".");
+
+ for (id=0; id<max_pun ; id++)
#ifdef CONFIG_SCSI_MULTI_LUN
for (lun=0; lun<8; lun++)
#endif
{
+ probe_display(1);
#ifdef IM_DEBUG_PROBE
printk(".");
#endif
@@ -1095,31 +1566,32 @@ static void check_devices (int host_index)
immediate_assign(host_index,id,lun,PROBE_LDN,REMOVE_LDN);
}
}
-
- /* STEP 3: */
+
+ /* STEP 3: */
printk("\nIBM MCA SCSI: Mapping SCSI-devices.");
-
+
ldn = 0;
lun = 0;
-
-#ifdef CONFIG_SCSI_MULTI_LUN
+
+#ifdef CONFIG_SCSI_MULTI_LUN
for (lun=0; lun<8 && ldn<MAX_LOG_DEV; lun++)
#endif
- for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
+ for (id=0; id<max_pun && ldn<MAX_LOG_DEV; id++)
{
+ probe_display(1);
#ifdef IM_DEBUG_PROBE
printk(".");
#endif
if (id != subsystem_pun(host_index))
{
- if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN &&
+ if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN &&
get_scsi(host_index)[id][lun] != TYPE_NO_DEVICE)
{
- /* Only map if accepted type. Always enter for
+ /* Only map if accepted type. Always enter for
lun == 0 to get no gaps into ldn-mapping for ldn<7. */
immediate_assign(host_index,id,lun,ldn,SET_LDN);
get_ldn(host_index)[id][lun]=ldn; /* map ldn */
- if (device_exists (host_index, ldn,
+ if (device_exists (host_index, ldn,
&ld(host_index)[ldn].block_length,
&ld(host_index)[ldn].device_type))
{
@@ -1149,18 +1621,19 @@ static void check_devices (int host_index)
get_ldn(host_index)[id][lun]=ldn; /* map ldn */
ldn++;
}
- }
+ }
}
-
+
/* STEP 4: */
-
+
/* map remaining ldns to non-existing devices */
for (lun=1; lun<8 && ldn<MAX_LOG_DEV; lun++)
- for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
+ for (id=0; id<max_pun && ldn<MAX_LOG_DEV; id++)
{
if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN ||
get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE)
{
+ probe_display(1);
/* Map remaining ldns only to NON-existing pun,lun
combinations to make sure an inquiry will fail.
For MULTI_LUN, it is needed to avoid adapter autonome
@@ -1169,20 +1642,20 @@ static void check_devices (int host_index)
get_ldn(host_index)[id][lun]=ldn;
ldn++;
}
- }
-
+ }
+
printk("\n");
if (ibm_ansi_order)
printk("IBM MCA SCSI: Device order: IBM/ANSI (pun=7 is first).\n");
else
printk("IBM MCA SCSI: Device order: New Industry Standard (pun=0 is first).\n");
-
+
#ifdef IM_DEBUG_PROBE
/* Show the physical and logical mapping during boot. */
printk("IBM MCA SCSI: Determined SCSI-device-mapping:\n");
printk(" Physical SCSI-Device Map Logical SCSI-Device Map\n");
printk("ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n");
- for (id=0; id<8; id++)
+ for (id=0; id<max_pun; id++)
{
printk("%2d ",id);
for (lun=0; lun<8; lun++)
@@ -1193,52 +1666,54 @@ static void check_devices (int host_index)
printk("\n");
}
#endif
-
+
/* assign total number of found SCSI-devices to the statistics struct */
IBM_DS(host_index).total_scsi_devices = count_devices;
-
+
/* decide for output in /proc-filesystem, if the configuration of
SCSI-devices makes dynamical reassignment of devices necessary */
- if (count_devices>=MAX_LOG_DEV)
+ if (count_devices>=MAX_LOG_DEV)
IBM_DS(host_index).dyn_flag = 1; /* dynamical assignment is necessary */
- else
+ else
IBM_DS(host_index).dyn_flag = 0; /* dynamical assignment is not necessary */
-
+
/* If no SCSI-devices are assigned, return 1 in order to cause message. */
if (ldn == 0)
printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n");
-
+
/* reset the counters for statistics on the current adapter */
+ IBM_DS(host_index).scbs = 0;
+ IBM_DS(host_index).long_scbs = 0;
IBM_DS(host_index).total_accesses = 0;
IBM_DS(host_index).total_interrupts = 0;
IBM_DS(host_index).dynamical_assignments = 0;
- memset (IBM_DS(host_index).ldn_access, 0x0,
+ memset (IBM_DS(host_index).ldn_access, 0x0,
sizeof (IBM_DS(host_index).ldn_access));
- memset (IBM_DS(host_index).ldn_read_access, 0x0,
+ memset (IBM_DS(host_index).ldn_read_access, 0x0,
sizeof (IBM_DS(host_index).ldn_read_access));
- memset (IBM_DS(host_index).ldn_write_access, 0x0,
+ memset (IBM_DS(host_index).ldn_write_access, 0x0,
sizeof (IBM_DS(host_index).ldn_write_access));
- memset (IBM_DS(host_index).ldn_inquiry_access, 0x0,
+ memset (IBM_DS(host_index).ldn_inquiry_access, 0x0,
sizeof (IBM_DS(host_index).ldn_inquiry_access));
- memset (IBM_DS(host_index).ldn_modeselect_access, 0x0,
+ memset (IBM_DS(host_index).ldn_modeselect_access, 0x0,
sizeof (IBM_DS(host_index).ldn_modeselect_access));
- memset (IBM_DS(host_index).ldn_assignments, 0x0,
+ memset (IBM_DS(host_index).ldn_assignments, 0x0,
sizeof (IBM_DS(host_index).ldn_assignments));
-
+ probe_display(0);
return;
}
/*--------------------------------------------------------------------*/
-static int device_exists (int host_index, int ldn, int *block_length,
+static int device_exists (int host_index, int ldn, int *block_length,
int *device_type)
{
unsigned char *buf;
-
+
/* if no valid device found, return immediately with 0 */
if (!(device_inquiry(host_index, ldn)))
return 0;
-
+
buf = (unsigned char *)(&(ld(host_index)[ldn].buf));
/*if device is CD_ROM, assume block size 2048 and return */
@@ -1248,64 +1723,64 @@ static int device_exists (int host_index, int ldn, int *block_length,
*block_length = 2048; /* (standard blocksize for yellow-/red-book) */
return 1;
}
-
- if (*buf == TYPE_WORM) /* CD-burner, WORM, Linux handles this as CD-ROM
+
+ if (*buf == TYPE_WORM) /* CD-burner, WORM, Linux handles this as CD-ROM
therefore, the block_length is also 2048. */
{
*device_type = TYPE_WORM;
*block_length = 2048;
return 1;
}
-
+
/* if device is disk, use "read capacity" to find its block size */
if (*buf == TYPE_DISK)
{
*device_type = TYPE_DISK;
if (read_capacity( host_index, ldn))
{
- *block_length = *(buf+7) + (*(buf+6) << 8) +
+ *block_length = *(buf+7) + (*(buf+6) << 8) +
(*(buf+5) << 16) + (*(buf+4) << 24);
return 1;
}
else
return 0;
}
-
+
/* if this is a magneto-optical drive, treat it like a harddisk */
if (*buf == TYPE_MOD)
{
*device_type = TYPE_MOD;
if (read_capacity( host_index, ldn))
{
- *block_length = *(buf+7) + (*(buf+6) << 8) +
+ *block_length = *(buf+7) + (*(buf+6) << 8) +
(*(buf+5) << 16) + (*(buf+4) << 24);
return 1;
}
else
return 0;
- }
-
+ }
+
if (*buf == TYPE_TAPE) /* TAPE-device found */
{
*device_type = TYPE_TAPE;
*block_length = 0; /* not in use (setting by mt and mtst in op.) */
- return 1;
+ return 1;
}
-
+
if (*buf == TYPE_PROCESSOR) /* HP-Scanners, diverse SCSI-processing units*/
{
*device_type = TYPE_PROCESSOR;
*block_length = 0; /* they set their stuff on drivers */
return 1;
}
-
+
if (*buf == TYPE_SCANNER) /* other SCSI-scanners */
{
*device_type = TYPE_SCANNER;
*block_length = 0; /* they set their stuff on drivers */
return 1;
}
-
+
if (*buf == TYPE_MEDIUM_CHANGER) /* Medium-Changer */
{
*device_type = TYPE_MEDIUM_CHANGER;
@@ -1313,60 +1788,54 @@ static int device_exists (int host_index, int ldn, int *block_length,
changer device. */
return 1;
}
-
+
/* Up to now, no SCSI-devices that are known up to kernel 2.1.31 are
- ignored! MO-drives are now supported and treated as harddisk. */
+ ignored! MO-drives are now supported and treated as harddisk. */
return 0;
}
/*--------------------------------------------------------------------*/
-
+
#ifdef CONFIG_SCSI_IBMMCA
-void ibmmca_scsi_setup (char *str, int *ints)
+void internal_ibmmca_scsi_setup (char *str, int *ints)
{
int i, j, io_base, id_base;
char *token;
-
+
io_base = 0;
id_base = 0;
-
+
if (str)
{
token = strtok(str,",");
j = 0;
while (token)
{
+ if (!strcmp(token,"activity"))
+ display_mode |= LED_ACTIVITY;
if (!strcmp(token,"display"))
- {
- use_display = 1;
- }
+ display_mode |= LED_DISP;
if (!strcmp(token,"adisplay"))
- {
- use_adisplay = 1;
- }
+ display_mode |= LED_ADISP;
if (!strcmp(token,"bypass"))
- {
- bypass_controller = 1;
- }
+ bypass_controller = 1;
if (!strcmp(token,"normal"))
- {
- ibm_ansi_order = 0;
- }
+ ibm_ansi_order = 0;
if (!strcmp(token,"ansi"))
- {
- ibm_ansi_order = 1;
- }
+ ibm_ansi_order = 1;
+ if (!strcmp(token,"fast"))
+ global_adapter_speed = 0;
+ if (!strcmp(token,"medium"))
+ global_adapter_speed = 4;
+ if (!strcmp(token,"slow"))
+ global_adapter_speed = 7;
if ( (*token == '-') || (isdigit(*token)) )
{
if (!(j%2) && (io_base < IM_MAX_HOSTS))
- {
- io_port[io_base++] = simple_strtoul(token,NULL,0);
- }
+ io_port[io_base++] = simple_strtoul(token,NULL,0);
if ((j%2) && (id_base < IM_MAX_HOSTS))
- {
- scsi_id[id_base++] = simple_strtoul(token,NULL,0);
- }
+ scsi_id[id_base++] = simple_strtoul(token,NULL,0);
j++;
}
token = strtok(NULL,",");
@@ -1374,7 +1843,7 @@ void ibmmca_scsi_setup (char *str, int *ints)
}
else if (ints)
{
- for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++)
+ for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++)
{
io_port[i] = ints[2*i+2];
scsi_id[i] = ints[2*i+2];
@@ -1390,28 +1859,34 @@ void ibmmca_scsi_setup (char *str, int *ints)
static int ibmmca_getinfo (char *buf, int slot, void *dev)
{
struct Scsi_Host *shpnt;
- int len, special;
+ int len, speciale,connectore;
unsigned int pos2, pos3;
static unsigned long flags;
-
+
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
spin_lock_irqsave(&info_lock, flags);
-
+#endif
+
shpnt = dev; /* assign host-structure to local pointer */
len = 0; /* set filled text-buffer index to 0 */
/* get the _special contents of the hostdata structure */
- special = ((struct ibmmca_hostdata *)shpnt->hostdata)->_special;
+ speciale = ((struct ibmmca_hostdata *)shpnt->hostdata)->_special;
+ connectore = ((struct ibmmca_hostdata *)shpnt->hostdata)->_connector_size;
pos2 = ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2;
pos3 = ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3;
-
- if (special == FORCED_DETECTION) /* forced detection */
+
+ if (speciale == FORCED_DETECTION) /* forced detection */
{
- len += sprintf (buf + len, "Adapter cathegory: forced detected\n");
+ len += sprintf (buf + len, "Adapter category: forced detected\n");
len += sprintf(buf + len, "***************************************\n");
len += sprintf(buf + len, "*** Forced detected SCSI Adapter ***\n");
len += sprintf(buf + len, "*** No chip-information available ***\n");
len += sprintf(buf + len, "***************************************\n");
}
- else if (special == INTEGRATED_SCSI)
+ else if (speciale == INTEGRATED_SCSI)
{ /* if the integrated subsystem has been found automatically: */
len += sprintf (buf + len, "Adapter category: integrated\n");
len += sprintf (buf + len, "Chip revision level: %d\n",
@@ -1421,15 +1896,19 @@ static int ibmmca_getinfo (char *buf, int slot, void *dev)
len += sprintf (buf + len, "8 kByte NVRAM status: %s\n",
(pos2 & 2) ? "locked" : "accessible");
}
- else if ((special>=0)&&
- (special<(sizeof(subsys_list)/sizeof(struct subsys_list_struct))))
- { /* if the subsystem is a slot adapter */
+ else if ((speciale>=0)&&
+ (speciale<(sizeof(subsys_list)/sizeof(struct subsys_list_struct))))
+ { /* if the subsystem is a slot adapter */
len += sprintf (buf + len, "Adapter category: slot-card\n");
- len += sprintf (buf + len, "Chip revision level: %d\n",
- ((pos2 & 0xf0) >> 4));
+ len += sprintf (buf + len, "ROM Segment Address: ");
+ if ((pos2 & 0xf0) == 0xf0)
+ len += sprintf (buf + len, "off\n");
+ else
+ len += sprintf (buf + len, "0x%x\n",
+ ((pos2 & 0xf0) << 13) + 0xc0000);
len += sprintf (buf + len, "Chip status: %s\n",
(pos2 & 1) ? "enabled" : "disabled");
- len += sprintf (buf + len, "Port offset: 0x%x\n",
+ len += sprintf (buf + len, "Adapter I/O Offset: 0x%x\n",
((pos2 & 0x0e) << 2));
}
else
@@ -1438,10 +1917,11 @@ static int ibmmca_getinfo (char *buf, int slot, void *dev)
}
/* common subsystem information to write to the slotn file */
len += sprintf (buf + len, "Subsystem PUN: %d\n", shpnt->this_id);
- len += sprintf (buf + len, "I/O base address range: 0x%x-0x%x",
+ len += sprintf (buf + len, "I/O base address range: 0x%x-0x%x\n",
(unsigned int)(shpnt->io_port),
(unsigned int)(shpnt->io_port+7));
- /* Now make sure, the bufferlength is divisible by 4 to avoid
+ len += sprintf (buf + len, "MCA-slot size: %d bits",connectore);
+ /* Now make sure, the bufferlength is devidable by 4 to avoid
* paging problems of the buffer. */
while ( len % sizeof( int ) != ( sizeof ( int ) - 1 ) )
{
@@ -1449,34 +1929,59 @@ static int ibmmca_getinfo (char *buf, int slot, void *dev)
}
len += sprintf (buf + len, "\n");
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&info_lock, flags);
+#endif
return len;
}
-
+
int ibmmca_detect (Scsi_Host_Template * scsi_template)
{
struct Scsi_Host *shpnt;
int port, id, i, j, list_size, slot;
-
+ int devices_on_irq_11 = 0;
+ int devices_on_irq_14 = 0;
+ int IRQ14_registered = 0;
+ int IRQ11_registered = 0;
+
found = 0; /* make absolutely sure, that found is set to 0 */
+ /* First of all, print the version number of the driver. This is
+ * important to allow better user bugreports in case of already
+ * having problems with the MCA_bus probing. */
+ printk("IBM MCA SCSI: Version %s\n",IBMMCA_SCSI_DRIVER_VERSION);
/* if this is not MCA machine, return "nothing found" */
if (!MCA_bus)
{
- printk("IBM MCA SCSI: No Microchannel-bus support present -> Aborting.\n");
+ printk("IBM MCA SCSI: No Microchannel-bus present --> Aborting.\n");
+ printk(" This machine does not have any IBM MCA-bus\n");
+ printk(" or the MCA-Kernel-support is not enabled!\n");
return 0;
}
- else
- printk("IBM MCA SCSI: Version %s\n",IBMMCA_SCSI_DRIVER_VERSION);
+#ifdef MODULE
+ /* If the driver is run as module, read from conf.modules or cmd-line */
+ if (boot_options)
+ option_setup(boot_options);
+#endif
+
/* get interrupt request level */
+#ifdef OLDKERN
+ if (request_irq (IM_IRQ, interrupt_handler, SA_SHIRQ, "ibmmcascsi",
+ hosts))
+#else
if (request_irq (IM_IRQ, do_interrupt_handler, SA_SHIRQ, "ibmmcascsi",
hosts))
+#endif
{
printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ);
return 0;
}
-
+ else
+ IRQ14_registered++;
+
/* if ibmmcascsi setup option was passed to kernel, return "found" */
for (i = 0; i < IM_MAX_HOSTS; i++)
if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8)
@@ -1484,20 +1989,25 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template)
printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n",
io_port[i], scsi_id[i]);
if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i],
+ FORCED_DETECTION,
"forced detected SCSI Adapter")))
{
((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = 0;
((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = 0;
- ((struct ibmmca_hostdata *)shpnt->hostdata)->_special =
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos4 = 0;
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos5 = 0;
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos6 = 0;
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_special =
FORCED_DETECTION;
- mca_set_adapter_name(MCA_INTEGSCSI, "forcibly detected SCSI Adapter");
+ mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter");
mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo,
shpnt);
mca_mark_as_used(MCA_INTEGSCSI);
- }
+ devices_on_irq_14++;
+ }
}
if (found) return found;
-
+
/* The POS2-register of all PS/2 model SCSI-subsystems has the following
* interpretation of bits:
* Bit 7 - 4 : Chip Revision ID (Release)
@@ -1509,16 +2019,16 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template)
* Bit 4 : Reserved = 0
* Bit 3 - 0 : Reserved = 0
* (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common
- * Interfaces (1991)").
- * In short words, this means, that IBM PS/2 machines only support
- * 1 single subsystem by default. The slot-adapters must have another
+ * Interfaces (1991)").
+ * In short words, this means, that IBM PS/2 machines only support
+ * 1 single subsystem by default. The slot-adapters must have another
* configuration on pos2. Here, one has to assume the following
* things for POS2-register:
* Bit 7 - 4 : Chip Revision ID (Release)
* Bit 3 - 1 : port offset factor
* Bit 0 : Chip Enable (EN-Signal)
* As I found a patch here, setting the IO-registers to 0x3540 forced,
- * as there was a 0x05 in POS2 on a model 56, I assume, that the
+ * as there was a 0x05 in POS2 on a model 56, I assume, that the
* port 0x3540 must be fix for integrated SCSI-controllers.
* Ok, this discovery leads to the following implementation: (M.Lang) */
@@ -1526,13 +2036,15 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template)
for (j=0;j<8;j++) /* read the pos-information */
pos[j] = mca_read_stored_pos(MCA_INTEGSCSI,j);
/* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present */
- if (( pos[2] != 0xff) || (pos[3] != 0xff ))
+ /* if (( pos[2] != 0xff) || (pos[3] != 0xff )) */
+ /* Previous if-arguments do fail! Therefore, we use now the following to
+ * make sure, we see a real integrated onboard SCSI-interface: */
+ if ((!pos[0] && !pos[1] && pos[2]>0 && pos[3]>0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) ||
+ (pos[0]==0xff && pos[1]==0xff && pos[2]<0xff && pos[3]<0xff && pos[4]==0xff && pos[5]==0xff && pos[6]==0xff && pos[7]==0xff))
{
if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */
- {
- port = IM_IO_PORT;
- }
- else
+ port = IM_IO_PORT;
+ else
{ /* if disabled, no IRQs will be generated, as the chip won't
* listen to the incomming commands and will do really nothing,
* except for listening to the pos-register settings. If this
@@ -1543,10 +2055,10 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template)
port = IM_IO_PORT; /* anyway, set the portnumber and warn */
printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
printk(" SCSI-operations may not work.\n");
- }
+ }
id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */
-
- /* give detailed information on the subsystem. This helps me
+
+ /* give detailed information on the subsystem. This helps me
* additionally during debugging and analyzing bug-reports. */
printk("IBM MCA SCSI: IBM Integrated SCSI Controller found, io=0x%x, scsi id=%d,\n",
port, id);
@@ -1556,20 +2068,25 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template)
/* register the found integrated SCSI-subsystem */
if ((shpnt = ibmmca_register(scsi_template, port, id,
+ INTEGRATED_SCSI,
"IBM Integrated SCSI Controller")))
{
((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2];
((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3];
- ((struct ibmmca_hostdata *)shpnt->hostdata)->_special =
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos4 = pos[4];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos5 = pos[5];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos6 = pos[6];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_special =
INTEGRATED_SCSI;
mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller");
mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo,
shpnt);
mca_mark_as_used(MCA_INTEGSCSI);
+ devices_on_irq_14++;
}
}
-
- /* now look for other adapters in MCA slots, */
+
+ /* now look for other adapters in MCA slots, */
/* determine the number of known IBM-SCSI-subsystem types */
/* see the pos[2] dependence to get the adapter port-offset. */
list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct);
@@ -1584,54 +2101,189 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template)
if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */
{ /* (explanations see above) */
port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
- }
- else
+ }
+ else
{ /* anyway, set the portnumber and warn */
- port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
+ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
printk(" SCSI-operations may not work.\n");
+ }
+ if ((i==IBM_SCSI2_FW)&&(pos[6]!=0))
+ {
+ printk("IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
+ printk(" Impossible to determine adapter PUN!\n");
+ printk(" Guessing adapter PUN = 7.\n");
+ id = 7;
+ }
+ else
+ {
+ id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */
+ if (i==IBM_SCSI2_FW)
+ {
+ id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit
+ * for F/W adapters */
+ }
+ }
+ if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0))
+ { /* IRQ11 is used by SCSI-2 F/W Adapter/A */
+ printk("IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
+ /* get interrupt request level */
+#ifdef OLDKERN
+ if (request_irq (IM_IRQ_FW, interrupt_handler, SA_SHIRQ,
+ "ibmmcascsi", hosts))
+#else
+ if (request_irq (IM_IRQ_FW, do_interrupt_handler, SA_SHIRQ,
+ "ibmmcascsi", hosts))
+#endif
+ {
+ printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n",
+ IM_IRQ_FW);
+ }
+ else
+ IRQ11_registered++;
}
- id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */
printk("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n",
subsys_list[i].description, slot + 1, port, id);
- printk(" chip rev.=%d, port-offset=0x%x, subsystem=%s\n",
- ((pos[2] & 0xf0) >> 4),
+ if ((pos[2] & 0xf0) == 0xf0)
+ printk(" ROM Addr.=off,");
+ else
+ printk(" ROM Addr.=0x%x,",
+ ((pos[2] & 0xf0) << 13) + 0xc0000);
+ printk(" port-offset=0x%x, subsystem=%s\n",
((pos[2] & 0x0e) << 2),
(pos[2] & 1) ? "enabled." : "disabled.");
-
+
/* register the hostadapter */
- if ((shpnt = ibmmca_register(scsi_template, port, id,
+ if ((shpnt = ibmmca_register(scsi_template, port, id, i,
subsys_list[i].description)))
{
((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2];
((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos4 = pos[4];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos5 = pos[5];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos6 = pos[6];
((struct ibmmca_hostdata *)shpnt->hostdata)->_special = i;
mca_set_adapter_name (slot, subsys_list[i].description);
mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo,
shpnt);
mca_mark_as_used(slot);
+ if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0))
+ devices_on_irq_11++;
+ else
+ devices_on_irq_14++;
}
slot++; /* advance to next slot */
} /* advance to next adapter id in the list of IBM-SCSI-subsystems*/
}
- if (!found)
- { /* maybe ESDI, or other producers' SCSI-hosts */
- free_irq (IM_IRQ, hosts);
- printk("IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n");
+
+ /* now look for SCSI-adapters, by bugs mapped to the integrated SCSI
+ * area. E.g. a W/Cache in MCA-slot 9 ???? Arrrrgh!! */
+ list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct);
+ for (i = 0; i < list_size; i++)
+ { /* scan each slot for a fitting adapter id */
+ slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI);
+ if (slot != MCA_NOTFOUND)
+ { /* scan through all slots */
+ for (j=0;j<8;j++) /* read the pos-information */
+ pos[j] = mca_read_stored_pos(slot, j);
+ if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */
+ { /* (explanations see above) */
+ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
+ }
+ else
+ { /* anyway, set the portnumber and warn */
+ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
+ printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
+ printk(" SCSI-operations may not work.\n");
+ }
+ if ((i==IBM_SCSI2_FW)&&(pos[6]!=0))
+ {
+ printk("IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
+ printk(" Impossible to determine adapter PUN!\n");
+ printk(" Guessing adapter PUN = 7.\n");
+ id = 7;
+ }
+ else
+ {
+ id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */
+ if (i==IBM_SCSI2_FW)
+ {
+ id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit
+ * for F/W adapters */
+ }
+ }
+ if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0))
+ { /* IRQ11 is used by SCSI-2 F/W Adapter/A */
+ printk("IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
+ /* get interrupt request level */
+#ifdef OLDKERN
+ if (request_irq (IM_IRQ_FW, interrupt_handler, SA_SHIRQ,
+ "ibmmcascsi", hosts))
+#else
+ if (request_irq (IM_IRQ_FW, do_interrupt_handler, SA_SHIRQ,
+ "ibmmcascsi", hosts))
+#endif
+ {
+ printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n",
+ IM_IRQ_FW);
+ }
+ else
+ IRQ11_registered++;
+ }
+ printk("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n",
+ subsys_list[i].description, slot + 1, port, id);
+ if ((pos[2] & 0xf0) == 0xf0)
+ printk(" ROM Addr.=off,");
+ else
+ printk(" ROM Addr.=0x%x,",
+ ((pos[2] & 0xf0) << 13) + 0xc0000);
+ printk(" port-offset=0x%x, subsystem=%s\n",
+ ((pos[2] & 0x0e) << 2),
+ (pos[2] & 1) ? "enabled." : "disabled.");
+
+ /* register the hostadapter */
+ if ((shpnt = ibmmca_register(scsi_template, port, id, i,
+ subsys_list[i].description)))
+ {
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos4 = pos[4];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos5 = pos[5];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos6 = pos[6];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = i;
+
+ mca_set_adapter_name (slot, subsys_list[i].description);
+ mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo,
+ shpnt);
+ mca_mark_as_used(slot);
+ if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0))
+ devices_on_irq_11++;
+ else
+ devices_on_irq_14++;
+ }
+ slot++; /* advance to next slot */
+ } /* advance to next adapter id in the list of IBM-SCSI-subsystems*/
}
+
+ if ( IRQ11_registered && !devices_on_irq_11 )
+ free_irq(IM_IRQ_FW, hosts); /* no devices on IRQ 11 */
+ if ( IRQ14_registered && !devices_on_irq_14 )
+ free_irq(IM_IRQ, hosts); /* no devices on IRQ 14 */
+ if ( !devices_on_irq_11 && !devices_on_irq_14 )
+ printk("IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n");
return found; /* return the number of found SCSI hosts. Should be 1 or 0. */
}
static struct Scsi_Host *
-ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id,
- char *hostname)
+ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id,
+ int adaptertype, char *hostname)
{
struct Scsi_Host *shpnt;
int i, j;
unsigned int ctrl;
-
+
/* check I/O region */
if (check_region(port, IM_N_IO_PORT))
{
@@ -1639,7 +2291,7 @@ ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id,
port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT);
return NULL;
}
-
+
/* register host */
shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata));
if (!shpnt)
@@ -1647,18 +2299,21 @@ ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id,
printk("IBM MCA SCSI: Unable to register host.\n");
return NULL;
}
-
+
/* request I/O region */
request_region(port, IM_N_IO_PORT, hostname);
-
+
hosts[found] = shpnt; /* add new found hostadapter to the list */
+ special(found) = adaptertype; /* important assignment or else crash! */
+ subsystem_connector_size(found) = 0; /* preset slot-size */
shpnt->irq = IM_IRQ; /* assign necessary stuff for the adapter */
shpnt->io_port = port;
shpnt->n_io_port = IM_N_IO_PORT;
shpnt->this_id = id;
+ shpnt->max_id = 8; /* 8 PUNs are default */
/* now, the SCSI-subsystem is connected to Linux */
-
- ctrl = (unsigned int)(inb(IM_CTR_REG(found))); /* get control-register status */
+
+ ctrl = (unsigned int)(inb(IM_CTR_REG(found))); /* get control-register status */
#ifdef IM_DEBUG_PROBE
printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n",
ctrl,inb(IM_STAT_REG(found)));
@@ -1669,18 +2324,19 @@ ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id,
if (bypass_controller)
printk("IBM MCA SCSI: Subsystem SCSI-commands get bypassed.\n");
#endif
-
+
reset_status(found) = IM_RESET_NOT_IN_PROGRESS;
- for (i = 0; i < 8; i++) /* reset the tables */
+ for (i = 0; i < 16; i++) /* reset the tables */
for (j = 0; j < 8; j++)
get_ldn(found)[i][j] = MAX_LOG_DEV;
/* check which logical devices exist */
- local_checking_phase_flag(found) = 1;
- check_devices(found); /* call by value, using the global variable hosts*/
+ /* after this line, local interrupting is possible: */
+ local_checking_phase_flag(found) = 1;
+ check_devices(found,adaptertype); /* call by value, using the global variable hosts*/
local_checking_phase_flag(found) = 0;
-
+
found++; /* now increase index to be prepared for next found subsystem */
/* an ibm mca subsystem has been detected */
return shpnt;
@@ -1710,21 +2366,21 @@ int ibmmca_release(struct Scsi_Host *shpnt)
/*--------------------------------------------------------------------*/
/* The following routine is the SCSI command queue. The old edition is
- now improved by dynamical reassignment of ldn numbers that are
+ now improved by dynamical reassignment of ldn numbers that are
currently not assigned. The mechanism works in a way, that first
the physical structure is checked. If at a certain pun,lun a device
should be present, the routine proceeds to the ldn check from
get_ldn. An answer of 0xff would show-up, that the aimed device is
- currently not assigned any ldn. At this point, the dynamical
+ currently not assigned any ldn. At this point, the dynamical
remapping algorithm is called. It works in a way, that it goes in
cyclic order through the ldns from 7 to 14. If a ldn is assigned,
it takes 8 dynamical reassignment calls, until a device looses its
- ldn again. With this method it is assured, that while doing
+ ldn again. With this method it is assured, that while doing
intense I/O between up to eight devices, no dynamical remapping is
done there. ldns 0 through 6(!) are left untouched, which means, that
puns 0 through 7(!) on lun=0 are always accessible without remapping.
- These ldns are statically assigned by this driver. The subsystem always
- occupies at least one pun, therefore 7 ldns (at lun=0) for other devices
+ These ldns are statically assigned by this driver. The subsystem always
+ occupies at least one pun, therefore 7 ldns (at lun=0) for other devices
are sufficient. (The adapter uses always ldn=15, at whatever pun it is.) */
int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
{
@@ -1736,33 +2392,46 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
int id,lun;
int target;
int host_index;
-
- if (ibm_ansi_order)
- target = 6 - cmd->target;
- else
- target = cmd->target;
-
+ int max_pun;
+ int i;
+ struct scatterlist *sl;
+
shpnt = cmd->host;
/* search for the right hostadapter */
for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
-
+
if (!hosts[host_index])
{ /* invalid hostadapter descriptor address */
cmd->result = DID_NO_CONNECT << 16;
- done (cmd);
+ if (done)
+ done (cmd);
return 0;
}
-
+
+ max_pun = subsystem_maxid(host_index);
+
+ if (ibm_ansi_order)
+ {
+ target = max_pun - 1 - cmd->target;
+ if ((target <= subsystem_pun(host_index))&&(cmd->target <= subsystem_pun(host_index)))
+ target--;
+ else if ((target >= subsystem_pun(host_index))&&(cmd->target >= subsystem_pun(host_index)))
+ target++;
+ }
+ else
+ target = cmd->target;
+
/*if (target,lun) is NO LUN or not existing at all, return error */
if ((get_scsi(host_index)[target][cmd->lun] == TYPE_NO_LUN)||
(get_scsi(host_index)[target][cmd->lun] == TYPE_NO_DEVICE))
{
cmd->result = DID_NO_CONNECT << 16;
- done (cmd);
+ if (done)
+ done (cmd);
return 0;
}
-
+
/*if (target,lun) unassigned, do further checks... */
ldn = get_ldn(host_index)[target][cmd->lun];
if (ldn >= MAX_LOG_DEV) /* on invalid ldn do special stuff */
@@ -1773,7 +2442,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
while (ld(host_index)[next_ldn(host_index)].cmd) /* search for a occupied, but not in */
{ /* command-processing ldn. */
next_ldn(host_index)++;
- if (next_ldn(host_index)>=MAX_LOG_DEV)
+ if (next_ldn(host_index)>=MAX_LOG_DEV)
next_ldn(host_index) = 7;
if (current_ldn == next_ldn(host_index)) /* One circle done ? */
{ /* no non-processing ldn found */
@@ -1782,18 +2451,19 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
printk(" Reporting DID_NO_CONNECT for device (%d,%d).\n",
target, cmd->lun);
cmd->result = DID_NO_CONNECT << 16;/* return no connect*/
- done (cmd);
+ if (done)
+ done (cmd);
return 0;
}
}
-
+
/* unmap non-processing ldn */
- for (id=0; id<8; id ++)
+ for (id=0; id<max_pun; id ++)
for (lun=0; lun<8; lun++)
{
if (get_ldn(host_index)[id][lun] == next_ldn(host_index))
{
- get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
+ get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
/* unmap entry */
}
}
@@ -1808,66 +2478,69 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
/* change ldn to the right value, that is now next_ldn */
ldn = next_ldn(host_index);
/* get device information for ld[ldn] */
- if (device_exists (host_index, ldn,
+ if (device_exists (host_index, ldn,
&ld(host_index)[ldn].block_length,
&ld(host_index)[ldn].device_type))
{
ld(host_index)[ldn].cmd = 0; /* To prevent panic set 0, because
devices that were not assigned,
should have nothing in progress. */
-
+
/* increase assignment counters for statistics in /proc */
IBM_DS(host_index).dynamical_assignments++;
IBM_DS(host_index).ldn_assignments[ldn]++;
}
else
- /* panic here, because a device, found at boottime has
+ /* panic here, because a device, found at boottime has
vanished */
panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n",
ldn, target, cmd->lun);
-
+
/* set back to normal interrupt_handling */
local_checking_phase_flag(host_index) = 0;
-
+
/* Information on syslog terminal */
printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n",
ldn, target, cmd->lun);
-
- /* increase next_ldn for next dynamical assignment */
+
+ /* increase next_ldn for next dynamical assignment */
next_ldn(host_index)++;
- if (next_ldn(host_index)>=MAX_LOG_DEV)
+ if (next_ldn(host_index)>=MAX_LOG_DEV)
next_ldn(host_index) = 7;
- }
+ }
else
- { /* wall against Linux accesses to the subsystem adapter */
+ { /* wall against Linux accesses to the subsystem adapter */
cmd->result = DID_BAD_TARGET << 16;
- done (cmd);
+ if (done)
+ done (cmd);
return 0;
}
}
-
+
/*verify there is no command already in progress for this log dev */
if (ld(host_index)[ldn].cmd)
panic ("IBM MCA SCSI: cmd already in progress for this ldn.\n");
-
+
/*save done in cmd, and save cmd for the interrupt handler */
cmd->scsi_done = done;
ld(host_index)[ldn].cmd = cmd;
-
+
/*fill scb information independent of the scsi command */
scb = &(ld(host_index)[ldn].scb);
ld(host_index)[ldn].tsb.dev_status = 0;
- scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR;
+ scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE;
scb->tsb_adr = virt_to_bus(&(ld(host_index)[ldn].tsb));
+ scsi_cmd = cmd->cmnd[0];
+
if (cmd->use_sg)
{
- int i = cmd->use_sg;
- struct scatterlist *sl = (struct scatterlist *) cmd->request_buffer;
+ i = cmd->use_sg;
+ sl = (struct scatterlist *)(cmd->request_buffer);
if (i > 16)
panic ("IBM MCA SCSI: scatter-gather list too long.\n");
while (--i >= 0)
{
- ld(host_index)[ldn].sge[i].address = (void *) virt_to_bus(sl[i].address);
+ ld(host_index)[ldn].sge[i].address = (void *)(virt_to_bus(sl[i].address));
ld(host_index)[ldn].sge[i].byte_length = sl[i].length;
}
scb->enable |= IM_POINTER_TO_LIST;
@@ -1877,31 +2550,45 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
else
{
scb->sys_buf_adr = virt_to_bus(cmd->request_buffer);
- scb->sys_buf_length = cmd->request_bufflen;
+ /* recent Linux midlevel SCSI places 1024 byte for inquiry
+ * command. Far too much for old PS/2 hardware. */
+ switch (scsi_cmd)
+ { /* avoid command errors by setting bufferlengths to
+ * ANSI-standard. */
+ case INQUIRY:
+ case REQUEST_SENSE:
+ case MODE_SENSE:
+ case MODE_SELECT:
+ scb->sys_buf_length = 255;
+ break;
+ case TEST_UNIT_READY:
+ scb->sys_buf_length = 0;
+ break;
+ default:
+ scb->sys_buf_length = cmd->request_bufflen;
+ break;
+ }
}
-
/*fill scb information dependent on scsi command */
- scsi_cmd = cmd->cmnd[0];
-
+
#ifdef IM_DEBUG_CMD
printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn);
#endif
-
+
/* for specific device-type debugging: */
#ifdef IM_DEBUG_CMD_SPEC_DEV
if (ld(host_index)[ldn].device_type==IM_DEBUG_CMD_DEVICE)
- printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n",
+ printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n",
ld(host_index)[ldn].device_type, scsi_cmd, ldn);
#endif
-
+
/* for possible panics store current command */
- last_scsi_command(host_index)[ldn] = scsi_cmd;
- last_scsi_type(host_index)[ldn] = IM_SCB;
-
+ last_scsi_command(host_index)[ldn] = scsi_cmd;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
/* update statistical info */
IBM_DS(host_index).total_accesses++;
IBM_DS(host_index).ldn_access[ldn]++;
-
+
switch (scsi_cmd)
{
case READ_6:
@@ -1909,54 +2596,48 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
case READ_10:
case WRITE_10:
case READ_12:
- case WRITE_12:
- /* statistics for proc_info */
- if ((scsi_cmd == READ_6)||(scsi_cmd == READ_10)||(scsi_cmd == READ_12))
- IBM_DS(host_index).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */
- else if ((scsi_cmd == WRITE_6)||(scsi_cmd == WRITE_10)||
- (scsi_cmd == WRITE_12))
- IBM_DS(host_index).ldn_write_access[ldn]++; /* increase write-count on ldn stat.*/
-
+ case WRITE_12:
/* Distinguish between disk and other devices. Only disks (that are the
- most frequently accessed devices) should be supported by the
- IBM-SCSI-Subsystem commands. */
+ most frequently accessed devices) should be supported by the
+ IBM-SCSI-Subsystem commands. */
switch (ld(host_index)[ldn].device_type)
{
case TYPE_DISK: /* for harddisks enter here ... */
case TYPE_MOD: /* ... try it also for MO-drives (send flames as */
/* you like, if this won't work.) */
- if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
+ if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
scsi_cmd == READ_12)
{ /* read command preparations */
+ scb->enable |= IM_READ_CONTROL;
+ IBM_DS(host_index).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */
if (bypass_controller)
{
scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL;
+ scb->enable |= IM_BYPASS_BUFFER;
scb->u1.scsi_cmd_length = cmd->cmd_len;
memcpy(scb->u2.scsi_command,cmd->cmnd,cmd->cmd_len);
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
}
else
- {
- scb->command = IM_READ_DATA_CMD;
- scb->enable |= IM_READ_CONTROL;
- }
+ scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT;
}
else
{ /* write command preparations */
+ IBM_DS(host_index).ldn_write_access[ldn]++; /* increase write-count on ldn stat.*/
if (bypass_controller)
{
scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_BYPASS_BUFFER;
scb->u1.scsi_cmd_length = cmd->cmd_len;
memcpy(scb->u2.scsi_command,cmd->cmnd,cmd->cmd_len);
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
}
else
- {
- scb->command = IM_WRITE_DATA_CMD;
- }
+ scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT;
}
-
+
if (!bypass_controller)
- {
+ {
if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6)
{
scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) |
@@ -1973,12 +2654,14 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) |
(((unsigned) cmd->cmnd[7]) << 8);
}
+ last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr;
+ last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count;
scb->u2.blk.length = ld(host_index)[ldn].block_length;
- }
+ }
if (++disk_rw_in_progress == 1)
PS2_DISK_LED_ON (shpnt->host_no, target);
break;
-
+
/* for other devices, enter here. Other types are not known by
Linux! TYPE_NO_LUN is forbidden as valid device. */
case TYPE_ROM:
@@ -1986,31 +2669,29 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
case TYPE_PROCESSOR:
case TYPE_WORM:
case TYPE_SCANNER:
- case TYPE_MEDIUM_CHANGER:
-
+ case TYPE_MEDIUM_CHANGER:
/* If there is a sequential-device, IBM recommends to use
- IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE.
+ IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE.
Good/modern CD-ROM-drives are capable of
reading sequential AND random-access. This leads to the problem,
- that random-accesses are covered by the subsystem, but
+ that random-accesses are covered by the subsystem, but
sequentials are not, as like for tape-drives. Therefore, it is
the easiest way to use IM_OTHER_SCSI_CMD_CMD for all read-ops
on CD-ROM-drives in order not to run into timing problems and
to have a stable state. In addition, data-access on CD-ROMs
works faster like that. Strange, but obvious. */
-
+
scb->command = IM_OTHER_SCSI_CMD_CMD;
- if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
+ if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
scsi_cmd == READ_12) /* enable READ */
- {
- scb->enable |= IM_READ_CONTROL;
- }
-
+ scb->enable |= IM_READ_CONTROL;
+ scb->enable |= IM_BYPASS_BUFFER;
scb->u1.scsi_cmd_length = cmd->cmd_len;
memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
-
- /* Read/write on this non-disk devices is also displayworthy,
- so flash-up the LED/display. */
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+
+ /* Read/write on this non-disk devices is also displayworthy,
+ so flash-up the LED/display. */
if (++disk_rw_in_progress == 1)
PS2_DISK_LED_ON (shpnt->host_no, target);
break;
@@ -2021,17 +2702,27 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
if (bypass_controller)
{
scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
+ scb->u1.log_blk_adr = 0;
scb->u1.scsi_cmd_length = cmd->cmd_len;
memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
}
else
{
scb->command = IM_DEVICE_INQUIRY_CMD;
scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ scb->u1.log_blk_adr = 0;
}
break;
-
+ case TEST_UNIT_READY:
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
+ scb->u1.log_blk_adr = 0;
+ scb->u1.scsi_cmd_length = 6;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, 6);
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+ break;
case READ_CAPACITY:
/* the length of system memory buffer must be exactly 8 bytes */
if (scb->sys_buf_length > 8)
@@ -2039,55 +2730,67 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
if (bypass_controller)
{
scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
scb->u1.scsi_cmd_length = cmd->cmd_len;
memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
}
else
{
scb->command = IM_READ_CAPACITY_CMD;
- scb->enable |= IM_READ_CONTROL;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
}
break;
-
- /* Commands that need read-only-mode (system <- device): */
+
+ /* Commands that need read-only-mode (system <- device): */
case REQUEST_SENSE:
- if (bypass_controller)
+ if (bypass_controller)
{
scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
scb->u1.scsi_cmd_length = cmd->cmd_len;
memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
}
else
{
scb->command = IM_REQUEST_SENSE_CMD;
- scb->enable |= IM_READ_CONTROL;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
}
break;
-
- /* Commands that need write-only-mode (system -> device): */
+
+ /* Commands that need write-only-mode (system -> device): */
case MODE_SELECT:
case MODE_SELECT_10:
IBM_DS(host_index).ldn_modeselect_access[ldn]++;
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /*Select needs WRITE-enabled*/
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; /*Select needs WRITE-enabled*/
scb->u1.scsi_cmd_length = cmd->cmd_len;
memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
break;
-
- /* For other commands, read-only is useful. Most other commands are
+
+ /* For other commands, read-only is useful. Most other commands are
running without an input-data-block. */
default:
scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
scb->u1.scsi_cmd_length = cmd->cmd_len;
memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
break;
}
-
/*issue scb command, and return */
- issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+ if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB)
+ {
+ issue_cmd (host_index, virt_to_bus(scb), IM_LONG_SCB | ldn);
+ IBM_DS(host_index).long_scbs++;
+ }
+ else
+ {
+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+ IBM_DS(host_index).scbs++;
+ }
return 0;
}
@@ -2098,36 +2801,50 @@ int ibmmca_abort (Scsi_Cmnd * cmd)
/* Abort does not work, as the adapter never generates an interrupt on
* whatever situation is simulated, even when really pending commands
* are running on the adapters' hardware ! */
-
+
struct Scsi_Host *shpnt;
unsigned int ldn;
void (*saved_done) (Scsi_Cmnd *);
int target;
int host_index;
+ int max_pun;
static unsigned long flags;
unsigned long imm_command;
/* return SCSI_ABORT_SNOOZE ; */
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
spin_lock_irqsave(&abort_lock, flags);
- if (ibm_ansi_order)
- target = 6 - cmd->target;
- else
- target = cmd->target;
-
+#endif
shpnt = cmd->host;
/* search for the right hostadapter */
- for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
-
+ for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
+
if (!hosts[host_index])
{ /* invalid hostadapter descriptor address */
cmd->result = DID_NO_CONNECT << 16;
if (cmd->scsi_done)
- (cmd->done) (cmd);
+ (cmd->scsi_done) (cmd);
return SCSI_ABORT_SNOOZE;
}
-
+
+ max_pun = subsystem_maxid(host_index);
+
+ if (ibm_ansi_order)
+ {
+ target = max_pun - 1 - cmd->target;
+ if ((target <= subsystem_pun(host_index))&&(cmd->target <= subsystem_pun(host_index)))
+ target--;
+ else if ((target >= subsystem_pun(host_index))&&(cmd->target >= subsystem_pun(host_index)))
+ target++;
+ }
+ else
+ target = cmd->target;
+
/*get logical device number, and disable system interrupts */
printk ("IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n",
target, cmd->lun);
@@ -2136,13 +2853,17 @@ int ibmmca_abort (Scsi_Cmnd * cmd)
/*if cmd for this ldn has already finished, no need to abort */
if (!ld(host_index)[ldn].cmd)
{
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&abort_lock, flags);
+#endif
return SCSI_ABORT_NOT_RUNNING;
}
- /* Clear ld.cmd, save done function, install internal done,
- * send abort immediate command (this enables sys. interrupts),
- * and wait until the interrupt arrives.
+ /* Clear ld.cmd, save done function, install internal done,
+ * send abort immediate command (this enables sys. interrupts),
+ * and wait until the interrupt arrives.
*/
saved_done = cmd->scsi_done;
cmd->scsi_done = internal_done;
@@ -2157,22 +2878,34 @@ int ibmmca_abort (Scsi_Cmnd * cmd)
{
if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
break;
+#ifdef OLDKERN
+ restore_flags (flags);
+#else
spin_unlock_irqrestore(&abort_lock, flags);
-
+#endif
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
spin_lock_irqsave(&abort_lock, flags);
+#endif
}
/*write registers and enable system interrupts */
outl (imm_command, IM_CMD_REG(host_index));
outb (IM_IMM_CMD | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags (flags);
+#else
spin_unlock_irqrestore(&abort_lock, flags);
-
+#endif
+
#ifdef IM_DEBUG_PROBE
printk("IBM MCA SCSI: Abort submitted, waiting for adapter response...\n");
-#endif
+#endif
while (!cmd->SCp.Status)
- barrier ();
- cmd->scsi_done = saved_done;
- /*if abort went well, call saved done, then return success or error */
+ barrier ();
+ cmd->scsi_done = saved_done;
+ /*if abort went well, call saved done, then return success or error */
if (cmd->result == (DID_ABORT << 16))
{
cmd->result |= DID_ABORT << 16;
@@ -2181,7 +2914,7 @@ int ibmmca_abort (Scsi_Cmnd * cmd)
ld(host_index)[ldn].cmd = NULL;
#ifdef IM_DEBUG_PROBE
printk("IBM MCA SCSI: Abort finished with success.\n");
-#endif
+#endif
return SCSI_ABORT_SUCCESS;
}
else
@@ -2192,7 +2925,7 @@ int ibmmca_abort (Scsi_Cmnd * cmd)
ld(host_index)[ldn].cmd = NULL;
#ifdef IM_DEBUG_PROBE
printk("IBM MCA SCSI: Abort failed.\n");
-#endif
+#endif
return SCSI_ABORT_ERROR;
}
}
@@ -2208,7 +2941,17 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
static unsigned long flags;
unsigned long imm_command;
+ if (cmd == NULL)
+ {
+ printk("IBM MCA SCSI: Reset called with NULL-command!\n");
+ return(SCSI_RESET_SNOOZE);
+ }
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
spin_lock_irqsave(&reset_lock, flags);
+#endif
ticks = IM_RESET_DELAY*HZ;
shpnt = cmd->host;
/* search for the right hostadapter */
@@ -2218,9 +2961,19 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
{ /* invalid hostadapter descriptor address */
if (!local_checking_phase_flag(host_index))
{
- cmd->result = DID_NO_CONNECT << 16;
- if (cmd->scsi_done)
- (cmd->done) (cmd);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132)
+ if (flags & SCSI_RESET_SYNCHRONOUS)
+ {
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+ cmd->result = DID_NO_CONNECT << 16;
+ if (cmd->scsi_done)
+ (cmd->scsi_done) (cmd);
+ }
+#endif
}
return SCSI_ABORT_SNOOZE;
}
@@ -2228,7 +2981,11 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
if (local_checking_phase_flag(host_index))
{
printk("IBM MCA SCSI: unable to reset while checking devices.\n");
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&reset_lock, flags);
+#endif
return SCSI_RESET_SNOOZE;
}
@@ -2245,8 +3002,17 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
{
if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
break;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
spin_lock_irqsave(&reset_lock, flags);
+#endif
}
/*write registers and enable system interrupts */
outl (imm_command, IM_CMD_REG(host_index));
@@ -2263,10 +3029,14 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
IM_RESET_DELAY);
reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&reset_lock, flags);
+#endif
return SCSI_RESET_ERROR;
}
-
+
if ((inb(IM_INTR_REG(host_index)) & 0x8f)==0x8f)
{ /* analysis done by this routine and not by the intr-routine */
if (inb(IM_INTR_REG(host_index))==0xaf)
@@ -2276,18 +3046,26 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
else /* failed, 4get it */
reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
outb (IM_EOI | 0xf, IM_ATTN_REG(host_index));
- }
-
+ }
+
/* if reset failed, just return an error */
if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) {
printk("IBM MCA SCSI: reset failed.\n");
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&reset_lock, flags);
+#endif
return SCSI_RESET_ERROR;
}
-
+
/* so reset finished ok - call outstanding done's, and return success */
- printk ("IBM MCA SCSI: Reset completed without known error.\n");
+ printk ("IBM MCA SCSI: Reset successfully completed.\n");
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&reset_lock, flags);
+#endif
for (i = 0; i < MAX_LOG_DEV; i++)
{
cmd_aid = ld(host_index)[i].cmd;
@@ -2295,10 +3073,22 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
{
ld(host_index)[i].cmd = NULL;
cmd_aid->result = DID_RESET << 16;
- (cmd_aid->scsi_done) (cmd_aid);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132)
+ if (flags & SCSI_RESET_SYNCHRONOUS)
+ {
+ cmd_aid->result = DID_BUS_BUSY << 16;
+ if (cmd_aid->scsi_done)
+ (cmd_aid->scsi_done) (cmd_aid);
+ }
+#endif
}
}
- return SCSI_RESET_SUCCESS;
+ if (flags & SCSI_RESET_SUGGEST_HOST_RESET)
+ return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
+ else if (flags & SCSI_RESET_SUGGEST_BUS_RESET)
+ return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET);
+ else
+ return SCSI_RESET_SUCCESS;
}
/*--------------------------------------------------------------------*/
@@ -2338,7 +3128,7 @@ static int ldn_access_total_read_write(int host_index)
{
int a;
int i;
-
+
a = 0;
for (i=0; i<=MAX_LOG_DEV; i++)
a+=IBM_DS(host_index).ldn_read_access[i]+IBM_DS(host_index).ldn_write_access[i];
@@ -2349,7 +3139,7 @@ static int ldn_access_total_inquiry(int host_index)
{
int a;
int i;
-
+
a = 0;
for (i=0; i<=MAX_LOG_DEV; i++)
a+=IBM_DS(host_index).ldn_inquiry_access[i];
@@ -2360,7 +3150,7 @@ static int ldn_access_total_modeselect(int host_index)
{
int a;
int i;
-
+
a = 0;
for (i=0; i<=MAX_LOG_DEV; i++)
a+=IBM_DS(host_index).ldn_modeselect_access[i];
@@ -2375,17 +3165,24 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
int i,id,lun,host_index;
struct Scsi_Host *shpnt;
unsigned long flags;
-
+ int max_pun;
+
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
spin_lock_irqsave(&proc_lock, flags);
+#endif
for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++);
shpnt = hosts[i];
host_index = i;
if (!shpnt) {
- len += sprintf(buffer+len, "\nCan't find adapter for host number %d\n", hostno);
+ len += sprintf(buffer+len, "\nIBM MCA SCSI: Can't find adapter for host number %d\n", hostno);
return len;
}
-
+ max_pun = subsystem_maxid(host_index);
+
len += sprintf(buffer+len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n",
IBMMCA_SCSI_DRIVER_VERSION);
len += sprintf(buffer+len, " SCSI Access-Statistics:\n");
@@ -2406,8 +3203,12 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
(bypass_controller) ? "software" : "hardware integrated");
len += sprintf(buffer+len, " Total Interrupts.........: %d\n",
IBM_DS(host_index).total_interrupts);
- len += sprintf(buffer+len, " Total SCSI Accesses......: %d\n",
+ len += sprintf(buffer+len, " Total SCSI Accesses......: %d\n",
IBM_DS(host_index).total_accesses);
+ len += sprintf(buffer+len, " Total short SCBs.........: %d\n",
+ IBM_DS(host_index).scbs);
+ len += sprintf(buffer+len, " Total long SCBs..........: %d\n",
+ IBM_DS(host_index).long_scbs);
len += sprintf(buffer+len, " Total SCSI READ/WRITE..: %d\n",
ldn_access_total_read_write(host_index));
len += sprintf(buffer+len, " Total SCSI Inquiries...: %d\n",
@@ -2428,11 +3229,11 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i],
IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]);
len += sprintf(buffer+len, " -----------------------------------------------------------\n\n");
-
+
len += sprintf(buffer+len, " Dynamical-LDN-Assignment-Statistics:\n");
len += sprintf(buffer+len, " Number of physical SCSI-devices..: %d (+ Adapter)\n",
IBM_DS(host_index).total_scsi_devices);
- len += sprintf(buffer+len, " Dynamical Assignment necessaray..: %s\n",
+ len += sprintf(buffer+len, " Dynamical Assignment necessary...: %s\n",
IBM_DS(host_index).dyn_flag ? "Yes" : "No ");
len += sprintf(buffer+len, " Next LDN to be assigned..........: 0x%x\n",
next_ldn(host_index));
@@ -2442,47 +3243,63 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
len += sprintf(buffer+len, "\n Current SCSI-Device-Mapping:\n");
len += sprintf(buffer+len, " Physical SCSI-Device Map Logical SCSI-Device Map\n");
len += sprintf(buffer+len, " ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n");
- for (id=0; id<=7; id++)
+ for (id=0; id<max_pun; id++)
{
len += sprintf(buffer+len, " %2d ",id);
for (lun=0; lun<8; lun++)
- len += sprintf(buffer+len,"%2s ",ti_p(get_scsi(host_index)[id][lun]));
-
+ len += sprintf(buffer+len,"%2s ",ti_p(get_scsi(host_index)[id][lun]));
len += sprintf(buffer+len, " %2d ",id);
for (lun=0; lun<8; lun++)
len += sprintf(buffer+len,"%2s ",ti_l(get_ldn(host_index)[id][lun]));
len += sprintf(buffer+len,"\n");
}
-
+
len += sprintf(buffer+len, "(A = IBM-Subsystem, D = Harddisk, T = Tapedrive, P = Processor, W = WORM,\n");
len += sprintf(buffer+len, " R = CD-ROM, S = Scanner, M = MO-Drive, C = Medium-Changer, + = unprovided LUN,\n");
len += sprintf(buffer+len, " - = nothing found, nothing assigned or unprobed LUN)\n\n");
-
+
*start = buffer + offset;
len -= offset;
- if (len > length)
+ if (len > length)
len = length;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
spin_unlock_irqrestore(&proc_lock, flags);
+#endif
return len;
}
+void ibmmca_scsi_setup (char *str, int *ints)
+{
+ internal_ibmmca_scsi_setup (str, ints);
+}
+
+static int option_setup(char *str)
+{
+ int ints[IM_MAX_HOSTS];
+ char *cur = str;
+ int i = 1;
+
+ while (cur && isdigit(*cur) && i <= IM_MAX_HOSTS) {
+ ints[i++] = simple_strtoul(cur, NULL, 0);
+ if ((cur = strchr(cur,',')) != NULL) cur++;
+ }
+ ints[0] = i - 1;
+ internal_ibmmca_scsi_setup(cur, ints);
+ return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
+__setup("ibmmcascsi=", option_setup);
+#endif
+
#ifdef MODULE
/* Eventually this will go into an include file, but this will be later */
Scsi_Host_Template driver_template = IBMMCA;
#include "scsi_module.c"
-
-/*
- * Module parameters
- */
-
-MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
-MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
-MODULE_PARM(display, "1i");
-MODULE_PARM(adisplay, "1i");
-MODULE_PARM(bypass, "1i");
-MODULE_PARM(normal, "1i");
-MODULE_PARM(ansi, "1i");
#endif
/*--------------------------------------------------------------------*/
+
diff --git a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h
index 99d0fe90f..52cd7386b 100644
--- a/drivers/scsi/ibmmca.h
+++ b/drivers/scsi/ibmmca.h
@@ -1,3 +1,9 @@
+/*
+ * Low Level Driver for the IBM Microchannel SCSI Subsystem
+ * (Headerfile, see README.ibmmca for description of the IBM MCA SCSI-driver
+ * For use under the GNU public license within the Linux-kernel project.
+ */
+
#ifndef _IBMMCA_H
#define _IBMMCA_H
@@ -5,18 +11,15 @@
#include <linux/version.h>
#endif
-#ifndef ibmmca_header_linux_version
-#define ibmmca_header_linux_version(v,p,s) (((v)<<16)+((p)<<8)+(s))
-#endif
-
-/*
- * Low Level Driver for the IBM Microchannel SCSI Subsystem
- * (Headerfile, see README.ibmmca for description of the IBM MCA SCSI-driver)
- */
+/* Note to the Linux-toplevel-maintainers:
+ * This file contains the unified header for all available Linux-distributions.
+ * For reasons of maintenance, it is recommended to keep this unmodified to
+ * be downward compatible until I no longer get any requests from people
+ * using older kernel releases on their PS/2 machines. (23 Apr 2000, M.Lang) */
/* Common forward declarations for all Linux-versions: */
-/*services provided to the higher level of Linux SCSI driver */
+/* Interfaces to the midlevel Linux SCSI driver */
extern int ibmmca_proc_info (char *, char **, off_t, int, int, int);
extern int ibmmca_detect (Scsi_Host_Template *);
extern int ibmmca_release (struct Scsi_Host *);
@@ -27,14 +30,39 @@ extern int ibmmca_reset (Scsi_Cmnd *, unsigned int);
extern int ibmmca_biosparam (Disk *, kdev_t, int *);
/*structure for /proc filesystem */
+extern struct proc_dir_entry proc_scsi_ibmmca;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,75)
+/* Stuff for Linux >= 2.1.75: */
/*
* 2/8/98
* Note to maintainer of IBMMCA. Do not change this initializer back to
* the old format. Please ask eric@andante.jic.com if you have any questions
* about this, but it will break things in the future.
*/
-#define IBMMCA { \
+/*initialization for Scsi_host_template type (Linux >= 2.1.75 && < 2.3.27) */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,27)
+#define IBMMCA { \
+ proc_dir: &proc_scsi_ibmmca, /*proc_dir*/ \
+ proc_info: ibmmca_proc_info, /*proc info fn*/ \
+ name: "IBM SCSI-Subsystem", /*name*/ \
+ detect: ibmmca_detect, /*detect fn*/ \
+ release: ibmmca_release, /*release fn*/ \
+ command: ibmmca_command, /*command fn*/ \
+ queuecommand: ibmmca_queuecommand, /*queuecommand fn*/ \
+ abort: ibmmca_abort, /*abort fn*/ \
+ reset: ibmmca_reset, /*reset fn*/ \
+ bios_param: ibmmca_biosparam, /*bios fn*/ \
+ can_queue: 16, /*can_queue*/ \
+ this_id: 7, /*set by detect*/ \
+ sg_tablesize: 16, /*sg_tablesize*/ \
+ cmd_per_lun: 1, /*cmd_per_lun*/ \
+ unchecked_isa_dma: 0, /*32-Bit Busmaster */ \
+ use_clustering: ENABLE_CLUSTERING /*use_clustering*/ \
+ }
+#else
+#define IBMMCA { \
proc_name: "ibmmca", /*proc_name*/ \
proc_info: ibmmca_proc_info, /*proc info fn*/ \
name: "IBM SCSI-Subsystem", /*name*/ \
@@ -52,5 +80,34 @@ extern int ibmmca_biosparam (Disk *, kdev_t, int *);
unchecked_isa_dma: 0, /*32-Bit Busmaster */ \
use_clustering: ENABLE_CLUSTERING /*use_clustering*/ \
}
+#endif
+#else
+/* Stuff for Linux < 2.1.75: */
+
+/*initialization for Scsi_host_template type (Linux < 2.1.75) */
+#define IBMMCA { \
+ NULL, /*next*/ \
+ NULL, /*usage_count*/ \
+ &proc_scsi_ibmmca, /*proc_dir*/ \
+ ibmmca_proc_info, /*proc info fn*/ \
+ "IBM SCSI-Subsystem", /*name*/ \
+ ibmmca_detect, /*detect fn*/ \
+ ibmmca_release, /*release fn*/ \
+ NULL, /*info fn*/ \
+ ibmmca_command, /*command fn*/ \
+ ibmmca_queuecommand, /*queuecommand fn*/ \
+ ibmmca_abort, /*abort fn*/ \
+ ibmmca_reset, /*reset fn*/ \
+ NULL, /*slave_attach fn*/ \
+ ibmmca_biosparam, /*bios fn*/ \
+ 16, /*can_queue*/ \
+ 7, /*set by detect*/ \
+ 16, /*sg_tablesize*/ \
+ 1, /*cmd_per_lun*/ \
+ 0, /*present*/ \
+ 0, /*unchecked_isa_dma*/ \
+ ENABLE_CLUSTERING /*use_clustering*/ \
+ }
+#endif /* kernelversion selection */
#endif /* _IBMMCA_H */
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 3494e793e..10b65fa2d 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1912,7 +1912,7 @@ out:
* their hosts through the modules entrypoints, and don't use the big
* list in hosts.c.
*/
-#if defined(CONFIG_MODULES) || defined(CONFIG_BLK_DEV_IDESCSI) || defined(CONFIG_USB_STORAGE) /* a big #ifdef block... */
+#if defined(CONFIG_MODULES) || defined(CONFIG_BLK_DEV_IDESCSI) || defined(CONFIG_USB_STORAGE) || defined(CONFIG_USB_MICROTEK) /* a big #ifdef block... */
/*
* This entry point should be called by a loadable module if it is trying
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 4ac3dbcfb..cc5bb1c48 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -17,8 +17,8 @@
* any later version.
*
*/
- static char * sg_version_str = "Version: 3.1.15 (20000528)";
- static int sg_version_num = 30115; /* 2 digits for each component */
+ static char * sg_version_str = "Version: 3.1.16 (20000716)";
+ static int sg_version_num = 30116; /* 2 digits for each component */
/*
* D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
* - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
@@ -1890,9 +1890,9 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
Sg_scatter_hold * req_schp = &srp->data;
Sg_scatter_hold * rsv_schp = &sfp->reserve;
+ srp->res_used = 1;
SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size));
- /* round request up to next highest SG_SECTOR_SZ byte boundary */
- size = (size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
+ size = (size + 1) & (~1); /* round to even for aha1542 */
if (rsv_schp->k_use_sg > 0) {
int k, num;
int rem = size;
@@ -1901,22 +1901,26 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
num = (int)sclp->length;
if (rem <= num) {
- sfp->save_scat_len = num;
- sclp->length = (unsigned)rem;
- break;
+ if (0 == k) {
+ req_schp->k_use_sg = 0;
+ req_schp->buffer = sclp->address;
+ }
+ else {
+ sfp->save_scat_len = num;
+ sclp->length = (unsigned)rem;
+ req_schp->k_use_sg = k + 1;
+ req_schp->sglist_len = rsv_schp->sglist_len;
+ req_schp->buffer = rsv_schp->buffer;
+ }
+ req_schp->bufflen = size;
+ req_schp->buffer_mem_src = rsv_schp->buffer_mem_src;
+ req_schp->b_malloc_len = rsv_schp->b_malloc_len;
+ break;
}
else
rem -= num;
}
- if (k < rsv_schp->k_use_sg) {
- req_schp->k_use_sg = k + 1; /* adjust scatter list length */
- req_schp->bufflen = size;
- req_schp->sglist_len = rsv_schp->sglist_len;
- req_schp->buffer = rsv_schp->buffer;
- req_schp->buffer_mem_src = rsv_schp->buffer_mem_src;
- req_schp->b_malloc_len = rsv_schp->b_malloc_len;
- }
- else
+ if (k >= rsv_schp->k_use_sg)
SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
}
else {
@@ -1924,10 +1928,8 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
req_schp->bufflen = size;
req_schp->buffer = rsv_schp->buffer;
req_schp->buffer_mem_src = rsv_schp->buffer_mem_src;
- req_schp->k_use_sg = rsv_schp->k_use_sg;
req_schp->b_malloc_len = rsv_schp->b_malloc_len;
}
- srp->res_used = 1;
}
static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
@@ -1937,7 +1939,7 @@ static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n",
(int)req_schp->k_use_sg));
- if (rsv_schp->k_use_sg > 0) {
+ if ((rsv_schp->k_use_sg > 0) && (req_schp->k_use_sg > 0)) {
struct scatterlist * sclp = (struct scatterlist *)rsv_schp->buffer;
if (sfp->save_scat_len > 0)
@@ -2118,13 +2120,12 @@ static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev)
}
static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
-{ /* if this is to be locked remember that it is called from _bh */
+{
Sg_request * srp;
Sg_request * tsrp;
int dirty = 0;
int res = 0;
- /* no lock since not expecting any parallel action on this fd */
srp = sfp->headrp;
if (srp) {
while (srp) {
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 399148c74..2c7dbb018 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -62,7 +62,7 @@ obj-$(CONFIG_SOUND_VMIDI) += v_midi.o
obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o
obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o
obj-$(CONFIG_SOUND_SGALAXY) += sgalaxy.o ad1848.o
-obj-$(CONFIG_SOUND_AD1816) += ad1816.o
+obj-$(CONFIG_SOUND_AD1816) += ad1816.o sound.o
obj-$(CONFIG_SOUND_ACI_MIXER) += aci.o
obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o
diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c
index b60733b4a..49f881a8c 100644
--- a/drivers/usb/acm.c
+++ b/drivers/usb/acm.c
@@ -689,3 +689,6 @@ static void __exit acm_exit(void)
module_init(acm_init);
module_exit(acm_exit);
+
+MODULE_AUTHOR("Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik");
+MODULE_DESCRIPTION("USB Abstract Control Model driver for USB modems and ISDN adapters");
diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c
index 4560ad602..5d6def562 100644
--- a/drivers/usb/audio.c
+++ b/drivers/usb/audio.c
@@ -3732,4 +3732,6 @@ void cleanup_module(void)
usb_deregister(&usb_audio_driver);
}
+MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>, Thomas Sailer (sailer@ife.ee.ethz.ch)");
+MODULE_DESCRIPTION("USB Audio Class driver");
#endif
diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c
index 7b19729a9..d04d3eaaa 100644
--- a/drivers/usb/dabusb.c
+++ b/drivers/usb/dabusb.c
@@ -841,6 +841,7 @@ void __exit dabusb_cleanup (void)
MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");
MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999");
MODULE_PARM (buffers, "i");
+MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
int __init init_module (void)
{
diff --git a/drivers/usb/dsbr100.c b/drivers/usb/dsbr100.c
index e2056a2e3..6ffffdc6f 100644
--- a/drivers/usb/dsbr100.c
+++ b/drivers/usb/dsbr100.c
@@ -347,6 +347,9 @@ void cleanup_module(void)
usb_deregister(&usb_dsbr100_driver);
}
+MODULE_AUTHOR("Markus Demleitner <msdemlei@tucana.harvard.edu>");
+MODULE_DESCRIPTION("D-Link DSB-R100 USB radio driver");
+
/*
vi: ts=8
Sigh. Of course, I am one of the ts=2 heretics, but Linus' wish is
diff --git a/drivers/usb/evdev.c b/drivers/usb/evdev.c
index e11327cef..65109e9ca 100644
--- a/drivers/usb/evdev.c
+++ b/drivers/usb/evdev.c
@@ -351,3 +351,6 @@ static void __exit evdev_exit(void)
module_init(evdev_init);
module_exit(evdev_exit);
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Event character device driver");
diff --git a/drivers/usb/hid.c b/drivers/usb/hid.c
index ae529b746..68a981e27 100644
--- a/drivers/usb/hid.c
+++ b/drivers/usb/hid.c
@@ -1524,3 +1524,6 @@ static void __exit hid_exit(void)
module_init(hid_init);
module_exit(hid_exit);
+
+MODULE_AUTHOR("Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("USB HID support drivers");
diff --git a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c
index d70c99ddf..6b85a15f0 100644
--- a/drivers/usb/ibmcam.c
+++ b/drivers/usb/ibmcam.c
@@ -127,21 +127,36 @@ static int init_model2_sat = -1;
static int init_model2_yb = -1;
MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
MODULE_PARM(flags, "i");
+MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=seperate frames, 6=clean frames");
MODULE_PARM(framerate, "i");
+MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
MODULE_PARM(lighting, "i");
+MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
MODULE_PARM(sharpness, "i");
+MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
MODULE_PARM(videosize, "i");
+MODULE_PARM_DESC(videosize, "Image size: 0=128x96, 1=176x144, 2=352x288, 3=320x240, 4=352x240 (default=1)");
MODULE_PARM(init_brightness, "i");
+MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
MODULE_PARM(init_contrast, "i");
+MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
MODULE_PARM(init_color, "i");
+MODULE_PARM_DESC(init_color, "Dolor preconfiguration: 0-255 (default=128)");
MODULE_PARM(init_hue, "i");
+MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
MODULE_PARM(hue_correction, "i");
+MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
MODULE_PARM(init_model2_rg, "i");
+MODULE_PARM_DESC(init_model2_rg, "Model2 preconfiguration: 0-255 (default=112)");
MODULE_PARM(init_model2_rg2, "i");
+MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");
MODULE_PARM(init_model2_sat, "i");
+MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");
MODULE_PARM(init_model2_yb, "i");
+MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
MODULE_AUTHOR ("module author");
MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
diff --git a/drivers/usb/iforce.c b/drivers/usb/iforce.c
index a61b7801f..d70bfd90e 100644
--- a/drivers/usb/iforce.c
+++ b/drivers/usb/iforce.c
@@ -38,6 +38,7 @@
#include <linux/config.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_WMFORCE 0xc281
diff --git a/drivers/usb/input.c b/drivers/usb/input.c
index 98f1a1109..f3701965e 100644
--- a/drivers/usb/input.c
+++ b/drivers/usb/input.c
@@ -34,6 +34,7 @@
#include <linux/random.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Input layer module");
EXPORT_SYMBOL(input_register_device);
EXPORT_SYMBOL(input_unregister_device);
diff --git a/drivers/usb/joydev.c b/drivers/usb/joydev.c
index 2210ad0d1..99b17a3cd 100644
--- a/drivers/usb/joydev.c
+++ b/drivers/usb/joydev.c
@@ -83,6 +83,7 @@ struct joydev_list {
static struct joydev *joydev_table[JOYDEV_MINORS];
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Joystick device driver");
MODULE_SUPPORTED_DEVICE("input/js");
static int joydev_correct(int value, struct js_corr *corr)
diff --git a/drivers/usb/keybdev.c b/drivers/usb/keybdev.c
index 76496349b..95fce5e80 100644
--- a/drivers/usb/keybdev.c
+++ b/drivers/usb/keybdev.c
@@ -195,3 +195,6 @@ static void __exit keybdev_exit(void)
module_init(keybdev_init);
module_exit(keybdev_exit);
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Input driver to keyboard driver binding");
diff --git a/drivers/usb/microtek.c b/drivers/usb/microtek.c
index a3de2b732..b8eb74c77 100644
--- a/drivers/usb/microtek.c
+++ b/drivers/usb/microtek.c
@@ -1050,3 +1050,6 @@ void __exit microtek_drv_exit(void)
module_init(microtek_drv_init);
module_exit(microtek_drv_exit);
+
+MODULE_AUTHOR("John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>");
+MODULE_DESCRIPTION("Microtek Scanmaker X6 USB scanner driver");
diff --git a/drivers/usb/mousedev.c b/drivers/usb/mousedev.c
index ea5ad301b..ccb118520 100644
--- a/drivers/usb/mousedev.c
+++ b/drivers/usb/mousedev.c
@@ -481,3 +481,6 @@ static void __exit mousedev_exit(void)
module_init(mousedev_init);
module_exit(mousedev_exit);
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver");
diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c
index 462a49957..73e3a5be1 100644
--- a/drivers/usb/ov511.c
+++ b/drivers/usb/ov511.c
@@ -108,16 +108,27 @@ static int cams = 1;
static int retry_sync = 0;
MODULE_PARM(autoadjust, "i");
+MODULE_PARM_DESC(autoadjust, "CCD dynamically changes exposure");
MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level: 0=none, 1=init/detection, 2=warning, 3=config/control, 4=function call, 5=max");
MODULE_PARM(fix_rgb_offset, "i");
+MODULE_PARM_DESC(fix_rgb_offset, "Fix vertical misalignment of red and blue at 640x480");
MODULE_PARM(snapshot, "i");
+MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
MODULE_PARM(sensor, "i");
+MODULE_PARM_DESC(sensor, "Override sensor detection");
MODULE_PARM(i2c_detect_tries, "i");
+MODULE_PARM_DESC(i2c_detect_tries, "Number of tries to detect sensor");
MODULE_PARM(aperture, "i");
+MODULE_PARM_DESC(aperture, "Read the OV7610/7620 specs");
MODULE_PARM(force_rgb, "i");
+MODULE_PARM_DESC(force_rgb, "Read RBG instead of BGR");
MODULE_PARM(buf_timeout, "i");
+MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation");
MODULE_PARM(cams, "i");
+MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
MODULE_PARM(retry_sync, "i");
+MODULE_PARM_DESC(retry_sync, "Prevent apps from timing out");
MODULE_AUTHOR("Mark McClelland <mmcclelland@delphi.com> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>");
MODULE_DESCRIPTION("OV511 USB Camera Driver");
diff --git a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c
index 8c588f79e..0a264faaf 100644
--- a/drivers/usb/pegasus.c
+++ b/drivers/usb/pegasus.c
@@ -103,7 +103,7 @@ static int multicast_filter_limit = 32;
MODULE_AUTHOR("Petko Manolov <petkan@spct.net>");
MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver");
MODULE_PARM(loopback, "i");
-
+MODULE_PARM_DESC(loopback, "Enable loopback mode (Bit 0) and ??? (Bit 1)");
static struct usb_eth_dev usb_dev_id[] = {
{"Billionton USB-100", 0x08dd, 0x0986, NULL},
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index 987f1a8b5..96fa971d8 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -527,3 +527,6 @@ static void __exit usblp_exit(void)
module_init(usblp_init);
module_exit(usblp_exit);
+
+MODULE_AUTHOR("Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap");
+MODULE_DESCRIPTION("USB Printer Device Class driver");
diff --git a/drivers/usb/rio500.c b/drivers/usb/rio500.c
index 011f853f6..c84a01fa6 100644
--- a/drivers/usb/rio500.c
+++ b/drivers/usb/rio500.c
@@ -445,3 +445,5 @@ void usb_rio_cleanup(void)
module_init(usb_rio_init);
module_exit(usb_rio_cleanup);
+MODULE_AUTHOR("Cesar Miquel <miquel@df.uba.ar>");
+MODULE_DESCRIPTION("USB Rio 500 driver");
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 146090ab2..31f913ff9 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -14,13 +14,7 @@ obj-m :=
obj-n :=
obj- :=
-ifeq ($(CONFIG_USB_SERIAL),y)
- obj-y += usbserial.o
-endif
-ifeq ($(CONFIG_USB_SERIAL),m)
- obj-m += usbserial.o
-endif
-
+obj-$(CONFIG_USB_SERIAL) += usbserial.o
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 9ecd1370b..c5c403b2b 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -1768,4 +1768,6 @@ void digi_exit (void)
module_init(digi_init);
module_exit(digi_exit);
+MODULE_AUTHOR("Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>");
+MODULE_DESCRIPTION("Digi AccelePort USB-4 Serial Converter driver");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index f78ff752b..aa156ba8d 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -741,3 +741,5 @@ void ftdi_sio_exit (void)
module_init(ftdi_sio_init);
module_exit(ftdi_sio_exit);
+MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>");
+MODULE_DESCRIPTION("USB FTDI SIO driver");
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 2fecdca12..64a1f709e 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -721,3 +721,5 @@ void keyspan_exit (void)
module_init(keyspan_init);
module_exit(keyspan_exit);
+MODULE_AUTHOR("Hugh Blemings <hugh@linuxcare.com>");
+MODULE_DESCRIPTION("Keyspan USB to Serial Converter driver");
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index aca2a38c5..675764ad4 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -720,3 +720,5 @@ void keyspan_pda_exit (void)
module_init(keyspan_pda_init);
module_exit(keyspan_pda_exit);
+MODULE_AUTHOR("Brian Warner <warner@lothar.com>");
+MODULE_DESCRIPTION("USB Keyspan PDA Converter driver");
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index f8145c37f..568f2b5cd 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -434,3 +434,5 @@ void visor_exit (void)
module_init(visor_init);
module_exit(visor_exit);
+MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
+MODULE_DESCRIPTION("USB HandSpring Visor driver");
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index a6ca6ebcb..7ec405501 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -549,3 +549,5 @@ void whiteheat_exit (void)
module_init(whiteheat_init);
module_exit(whiteheat_exit);
+MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
+MODULE_DESCRIPTION("USB ConnectTech WhiteHEAT driver");
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index aaf1072db..1b204ab28 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -12,18 +12,19 @@ CFLAGS_protocol.o:= -I../../scsi/
CFLAGS_transport.o:= -I../../scsi/
CFLAGS_debug.o:= -I../../scsi/
CFLAGS_usb.o:= -I../../scsi/
-CFLAGS_scm.o:= -I../../scsi/
+CFLAGS_shuttle_usbat.o:= -I../../scsi/
+CFLAGS_sddr09.o:= -I../../scsi/
ifeq ($(CONFIG_USB_STORAGE_DEBUG),y)
O_OBJS += debug.o
endif
ifeq ($(CONFIG_USB_STORAGE_HP8200e),y)
- O_OBJS += scm.o
+ O_OBJS += shuttle_usbat.o
endif
ifeq ($(CONFIG_USB_STORAGE_SDDR09),y)
- O_OBJS += scm.o
+ O_OBJS += sddr09.o
endif
ifeq ($(CONFIG_USB_STORAGE_FREECOM),y)
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 21fe3ec97..25328669b 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* SCSI layer glue code
*
- * $Id: scsiglue.c,v 1.5 2000/07/24 18:55:39 mdharm Exp $
+ * $Id: scsiglue.c,v 1.6 2000/07/25 23:04:47 mdharm Exp $
*
* Current development and maintainance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -49,21 +49,6 @@
#include <linux/malloc.h>
-/* direction table -- this indicates the direction of the data
- * transfer for each command code -- a 1 indicates input
- */
-/* FIXME: we need to use the new direction indicators in the Scsi_Cmnd
- * structure, not this table. First we need to evaluate if it's being set
- * correctly for us, though
- */
-unsigned char us_direction[256/8] = {
- 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
- 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-
/*
* kernel thread actions
*/
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
index e9da1bcc0..f81787678 100644
--- a/drivers/usb/storage/scsiglue.h
+++ b/drivers/usb/storage/scsiglue.h
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* SCSI Connecting Glue Header File
*
- * $Id: scsiglue.h,v 1.2 2000/07/19 22:12:07 mdharm Exp $
+ * $Id: scsiglue.h,v 1.3 2000/07/25 23:04:47 mdharm Exp $
*
* Current development and maintainance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -46,7 +46,6 @@
#include "hosts.h"
extern unsigned char usb_stor_sense_notready[18];
-extern unsigned char us_direction[256/8];
extern Scsi_Host_Template usb_stor_host_template;
extern int usb_stor_scsiSense10to6(Scsi_Cmnd*);
extern int usb_stor_scsiSense6to10(Scsi_Cmnd*);
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
new file mode 100644
index 000000000..275712961
--- /dev/null
+++ b/drivers/usb/storage/sddr09.c
@@ -0,0 +1,635 @@
+/* Driver for SanDisk SDDR-09 SmartMedia reader
+ *
+ * SDDR09 driver v0.1:
+ *
+ * First release
+ *
+ * Current development and maintainance by:
+ * (c) 2000 Robert Baruch (autophile@dol.net)
+ *
+ * The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip.
+ * This chip is a programmable USB controller. In the SDDR-09, it has
+ * been programmed to obey a certain limited set of SCSI commands. This
+ * driver translates the "real" SCSI commands to the SDDR-09 SCSI
+ * commands.
+ *
+ * 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, or (at your option) any
+ * later version.
+ *
+ * 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.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "transport.h"
+#include "protocol.h"
+#include "usb.h"
+#include "debug.h"
+#include "sddr09.h"
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+
+extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
+ u8 request, u8 requesttype, u16 value, u16 index,
+ void *data, u16 size);
+extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
+ unsigned int len, unsigned int *act_len);
+
+#define short_pack(b1,b2) ( ((u16)(b1)) | ( ((u16)(b2))<<8 ) )
+#define LSB_of(s) ((s)&0xFF)
+#define MSB_of(s) ((s)>>8)
+
+/*
+ * Send a control message and wait for the response.
+ *
+ * us - the pointer to the us_data structure for the device to use
+ *
+ * request - the URB Setup Packet's first 6 bytes. The first byte always
+ * corresponds to the request type, and the second byte always corresponds
+ * to the request. The other 4 bytes do not correspond to value and index,
+ * since they are used in a custom way by the SCM protocol.
+ *
+ * xfer_data - a buffer from which to get, or to which to store, any data
+ * that gets send or received, respectively, with the URB. Even though
+ * it looks like we allocate a buffer in this code for the data, xfer_data
+ * must contain enough allocated space.
+ *
+ * xfer_len - the number of bytes to send or receive with the URB.
+ *
+ */
+
+static int sddr09_send_control(struct us_data *us,
+ int pipe,
+ unsigned char request,
+ unsigned char requesttype,
+ unsigned short value,
+ unsigned short index,
+ unsigned char *xfer_data,
+ unsigned int xfer_len) {
+
+ int result;
+
+ // If data is going to be sent or received with the URB,
+ // then allocate a buffer for it. If data is to be sent,
+ // copy the data into the buffer.
+/*
+ if (xfer_len > 0) {
+ buffer = kmalloc(xfer_len, GFP_KERNEL);
+ if (!(command[0] & USB_DIR_IN))
+ memcpy(buffer, xfer_data, xfer_len);
+ }
+*/
+ // Send the URB to the device and wait for a response.
+
+ /* Why are request and request type reversed in this call? */
+
+ result = usb_stor_control_msg(us, pipe,
+ request, requesttype, value, index,
+ xfer_data, xfer_len);
+
+
+ // If data was sent or received with the URB, free the buffer we
+ // allocated earlier, but not before reading the data out of the
+ // buffer if we wanted to receive data.
+/*
+ if (xfer_len > 0) {
+ if (command[0] & USB_DIR_IN)
+ memcpy(xfer_data, buffer, xfer_len);
+ kfree(buffer);
+ }
+*/
+ // Check the return code for the command.
+
+ if (result < 0) {
+ /* if the command was aborted, indicate that */
+ if (result == -ENOENT)
+ return USB_STOR_TRANSPORT_ABORTED;
+
+ /* a stall is a fatal condition from the device */
+ if (result == -EPIPE) {
+ US_DEBUGP("-- Stall on control pipe. Clearing\n");
+ result = usb_clear_halt(us->pusb_dev, pipe);
+ US_DEBUGP("-- usb_clear_halt() returns %d\n", result);
+ return USB_STOR_TRANSPORT_FAILED;
+ }
+
+ /* Uh oh... serious problem here */
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sddr09_raw_bulk(struct us_data *us,
+ int direction,
+ unsigned char *data,
+ unsigned short len) {
+
+ int result;
+ int act_len;
+ int pipe;
+
+ if (direction == SCSI_DATA_READ)
+ pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
+ else
+ pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
+
+ result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);
+
+ /* if we stall, we need to clear it before we go on */
+ if (result == -EPIPE) {
+ US_DEBUGP("EPIPE: clearing endpoint halt for"
+ " pipe 0x%x, stalled at %d bytes\n",
+ pipe, act_len);
+ usb_clear_halt(us->pusb_dev, pipe);
+ }
+
+ if (result) {
+
+ /* NAK - that means we've retried a few times already */
+ if (result == -ETIMEDOUT) {
+ US_DEBUGP("usbat_raw_bulk():"
+ " device NAKed\n");
+ return US_BULK_TRANSFER_FAILED;
+ }
+
+ /* -ENOENT -- we canceled this transfer */
+ if (result == -ENOENT) {
+ US_DEBUGP("usbat_raw_bulk():"
+ " transfer aborted\n");
+ return US_BULK_TRANSFER_ABORTED;
+ }
+
+ if (result == -EPIPE) {
+ US_DEBUGP("usbat_raw_bulk():"
+ " output pipe stalled\n");
+ return USB_STOR_TRANSPORT_FAILED;
+ }
+
+ /* the catch-all case */
+ US_DEBUGP("us_transfer_partial(): unknown error\n");
+ return US_BULK_TRANSFER_FAILED;
+ }
+
+ if (act_len != len) {
+ US_DEBUGP("Warning: Transferred only %d bytes\n",
+ act_len);
+ return US_BULK_TRANSFER_SHORT;
+ }
+
+ US_DEBUGP("Transfered %d of %d bytes\n", act_len, len);
+
+ return US_BULK_TRANSFER_GOOD;
+}
+
+/*
+ * Note: direction must be set if command_len == 0.
+ */
+
+static int sddr09_bulk_transport(struct us_data *us,
+ unsigned char *command,
+ unsigned short command_len,
+ int direction,
+ unsigned char *data,
+ unsigned short len,
+ int use_sg) {
+
+ int result = USB_STOR_TRANSPORT_GOOD;
+ int transferred = 0;
+ unsigned char execute[8] = {
+ 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ int i;
+ struct scatterlist *sg;
+ char string[64];
+/*
+ if (command_len != 0) {
+
+ // Fix up the command's data length
+
+ command[6] = len&0xFF;
+ command[7] = (len>>8)&0xFF;
+
+ result = sddr09_send_control(us,
+ execute,
+ command,
+ command_len);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+ }
+*/
+ if (len==0)
+ return USB_STOR_TRANSPORT_GOOD;
+
+
+ /* transfer the data payload for the command, if there is any */
+
+
+ if (command_len != 0)
+ direction = (command[0]&0x80) ? SCSI_DATA_READ :
+ SCSI_DATA_WRITE;
+
+ if (direction == SCSI_DATA_WRITE) {
+
+ /* Debug-print the first 48 bytes of the write transfer */
+
+ if (!use_sg) {
+ string[0] = 0;
+ for (i=0; i<len && i<48; i++) {
+ sprintf(string+strlen(string), "%02X ",
+ data[i]);
+ if ((i%16)==15) {
+ US_DEBUGP("%s\n", string);
+ string[0] = 0;
+ }
+ }
+ if (string[0]!=0)
+ US_DEBUGP("%s\n", string);
+ }
+ }
+
+
+ US_DEBUGP("SCM data %s transfer %d sg buffers %d\n",
+ ( direction==SCSI_DATA_READ ? "in" : "out"),
+ len, use_sg);
+
+ if (!use_sg)
+ result = sddr09_raw_bulk(us, direction, data, len);
+ else {
+ sg = (struct scatterlist *)data;
+ for (i=0; i<use_sg && transferred<len; i++) {
+ result = sddr09_raw_bulk(us, direction,
+ sg[i].address,
+ len-transferred > sg[i].length ?
+ sg[i].length : len-transferred);
+ if (result!=US_BULK_TRANSFER_GOOD)
+ break;
+ transferred += sg[i].length;
+ }
+ }
+
+ return result;
+}
+
+int sddr09_read_data(struct us_data *us,
+ unsigned long address,
+ unsigned short sectors,
+ unsigned char *content,
+ int use_sg) {
+
+ int result;
+ unsigned char command[12] = {
+ 0xe8, 0x20, MSB_of(address>>16),
+ LSB_of(address>>16), MSB_of(address&0xFFFF),
+ LSB_of(address&0xFFFF), 0, 0, 0, 0,
+ MSB_of(sectors), LSB_of(sectors)
+ };
+
+ result = sddr09_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0,
+ 0x41,
+ 0,
+ 0,
+ command,
+ 12);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ result = sddr09_bulk_transport(us,
+ NULL, 0, SCSI_DATA_READ, content,
+ sectors*512, use_sg);
+
+ return result;
+}
+
+int sddr09_read_control(struct us_data *us,
+ unsigned long address,
+ unsigned short sectors,
+ unsigned char *content,
+ int use_sg) {
+
+ int result;
+ unsigned char command[12] = {
+ 0xe8, 0x21, MSB_of(address>>16),
+ LSB_of(address>>16), MSB_of(address&0xFFFF),
+ LSB_of(address&0xFFFF), 0, 0, 0, 0,
+ MSB_of(sectors), LSB_of(sectors)
+ };
+
+ result = sddr09_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0,
+ 0x41,
+ 0,
+ 0,
+ command,
+ 12);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ result = sddr09_bulk_transport(us,
+ NULL, 0, SCSI_DATA_READ, content,
+ sectors*64, use_sg);
+
+ return result;
+}
+
+int sddr09_read_deviceID(struct us_data *us,
+ unsigned char *manufacturerID,
+ unsigned char *deviceID) {
+
+ int result;
+ unsigned char command[12] = {
+ 0xed, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ unsigned char content[64];
+
+ result = sddr09_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0,
+ 0x41,
+ 0,
+ 0,
+ command,
+ 12);
+
+ US_DEBUGP("Result of send_control for device ID is %d\n",
+ result);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ result = sddr09_bulk_transport(us,
+ NULL, 0, SCSI_DATA_READ, content,
+ 64, 0);
+
+ *manufacturerID = content[0];
+ *deviceID = content[1];
+
+ return result;
+}
+
+int sddr09_read_status(struct us_data *us,
+ unsigned char *status) {
+
+ int result;
+ unsigned char command[12] = {
+ 0xec, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ unsigned char content[2];
+
+ result = sddr09_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0,
+ 0x41,
+ 0,
+ 0,
+ command,
+ 12);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ result = sddr09_bulk_transport(us,
+ NULL, 0, SCSI_DATA_READ, status,
+ 1, 0);
+
+ return result;
+}
+
+int sddr09_reset(struct us_data *us) {
+
+ int result;
+ unsigned char command[12] = {
+ 0xeb, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ result = sddr09_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0,
+ 0x41,
+ 0,
+ 0,
+ command,
+ 12);
+
+ return result;
+}
+
+/*
+static int init_sddr09(struct us_data *us) {
+
+ int result;
+ unsigned char data[14];
+ unsigned char command[8] = {
+ 0xc1, 0x01, 0, 0, 0, 0, 0, 0
+ };
+ unsigned char command2[8] = {
+ 0x41, 0, 0, 0, 0, 0, 0, 0
+ };
+ unsigned char tur[12] = {
+ 0x03, 0x20, 0, 0, 0x0e, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ if ( (result = sddr09_send_control(us, command, data, 2)) !=
+ USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);
+
+ command[1] = 0x08;
+
+ if ( (result = sddr09_send_control(us, command, data, 2)) !=
+ USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);
+
+ if ( (result = sddr09_send_control(us, command2, tur, 12)) !=
+ USB_STOR_TRANSPORT_GOOD) {
+ US_DEBUGP("SDDR09: request sense failed\n");
+ return result;
+ }
+
+ if ( (result = sddr09_raw_bulk(
+ us, SCSI_DATA_READ, data, 14)) !=
+ USB_STOR_TRANSPORT_GOOD) {
+ US_DEBUGP("SDDR09: request sense bulk in failed\n");
+ return result;
+ }
+
+ US_DEBUGP("SDDR09: request sense worked\n");
+
+ return result;
+}
+*/
+
+/*
+ * Transport for the Sandisk SDDR-09
+ */
+int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
+{
+ int result;
+ unsigned char send_scsi_command[8] = {
+ 0x41, 0, 0, 0, 0, 0, 0, 0
+ };
+ int i;
+ char string[64];
+ unsigned char inquiry_response[36] = {
+ 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00,
+ 'S', 'a', 'n', 'D', 'i', 's', 'k', ' ',
+ 'I', 'm', 'a', 'g', 'e', 'M', 'a', 't',
+ 'e', ' ', 'S', 'D', 'D', 'R', '0', '9',
+ ' ', ' ', ' ', ' '
+ };
+ unsigned char deviceID;
+ unsigned char manufacturerID;
+ unsigned char *ptr;
+
+/*
+ if (us->flags & US_FL_NEED_INIT) {
+ US_DEBUGP("SDDR-09: initializing\n");
+ init_sddr09(us);
+ us->flags &= ~US_FL_NEED_INIT;
+ }
+*/
+
+ ptr = (unsigned char *)srb->request_buffer;
+
+ /* Dummy up a response for INQUIRY since SDDR09 doesn't
+ respond to INQUIRY commands */
+
+ if (srb->cmnd[0] == INQUIRY) {
+ memcpy(srb->request_buffer, inquiry_response, 36);
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ if (srb->cmnd[0] == READ_CAPACITY) {
+
+ US_DEBUGP("Reading capacity...\n");
+
+ result = sddr09_read_deviceID(us,
+ &manufacturerID,
+ &deviceID);
+
+ US_DEBUGP("Result of read_deviceID is %d\n",
+ result);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ US_DEBUGP("Device ID = %02X\n", deviceID);
+ US_DEBUGP("Manuf ID = %02X\n", manufacturerID);
+
+ ptr[0] = 0;
+ ptr[1] = 0;
+ ptr[2] = 0;
+ ptr[3] = 0;
+
+ switch (deviceID) {
+
+ case 0x6e: // 1MB
+ case 0xe8:
+ case 0xec:
+ ptr[4] = 0;
+ ptr[5] = 0x10;
+ break;
+
+ case 0xea: // 2MB
+ case 0x64:
+ case 0x5d:
+ ptr[4] = 0;
+ ptr[5] = 0x20;
+ break;
+
+ case 0xe3: // 4MB
+ case 0xe5:
+ case 0x6b:
+ case 0xd5:
+ ptr[4] = 0;
+ ptr[5] = 0x40;
+ break;
+
+ case 0xe6: // 8MB
+ case 0xd6:
+ ptr[4] = 0;
+ ptr[5] = 0x80;
+ break;
+
+ case 0x75: // 32MB
+ ptr[4] = 0x02;
+ ptr[5] = 0;
+ break;
+
+ default: // unknown
+ ptr[4] = 0;
+ ptr[5] = 0;
+
+ }
+
+ ptr[6] = 0;
+ ptr[7] = 0;
+
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ for (; srb->cmd_len<12; srb->cmd_len++)
+ srb->cmnd[srb->cmd_len] = 0;
+
+ srb->cmnd[1] = 0x20;
+
+ string[0] = 0;
+ for (i=0; i<12; i++)
+ sprintf(string+strlen(string), "%02X ", srb->cmnd[i]);
+
+ US_DEBUGP("SDDR09: Send control for command %s\n",
+ string);
+
+ if ( (result = sddr09_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0,
+ 0x41,
+ 0,
+ 0,
+ srb->cmnd,
+ 12)) != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ US_DEBUGP("SDDR09: Control for command OK\n");
+
+ if (srb->request_bufflen == 0)
+ return USB_STOR_TRANSPORT_GOOD;
+
+ if (srb->sc_data_direction == SCSI_DATA_WRITE ||
+ srb->sc_data_direction == SCSI_DATA_READ) {
+
+ US_DEBUGP("SDDR09: %s %d bytes\n",
+ srb->sc_data_direction==SCSI_DATA_WRITE ?
+ "sending" : "receiving",
+ srb->request_bufflen);
+
+ result = sddr09_bulk_transport(us,
+ NULL, 0, srb->sc_data_direction,
+ srb->request_buffer,
+ srb->request_bufflen, srb->use_sg);
+
+ return result;
+
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
new file mode 100644
index 000000000..76a749528
--- /dev/null
+++ b/drivers/usb/storage/sddr09.h
@@ -0,0 +1,31 @@
+/* Driver for SanDisk SDDR-09 SmartMedia reader
+ * Header File
+ *
+ * Current development and maintainance by:
+ * (c) 2000 Robert Baruch (autophile@dol.net)
+ *
+ * See sddr09.c for more explanation
+ *
+ * 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, or (at your option) any
+ * later version.
+ *
+ * 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.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _USB_SHUTTLE_EUSB_SDDR09_H
+#define _USB_SHUTTLE_EUSB_SDDR09_H
+
+/* Sandisk SDDR-09 stuff */
+
+extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us);
+
+#endif
diff --git a/drivers/usb/storage/scm.c b/drivers/usb/storage/shuttle_usbat.c
index 7bae5e623..f68595c47 100644
--- a/drivers/usb/storage/scm.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1,7 +1,5 @@
/* Driver for SCM Microsystems USB-ATAPI cable
*
- * $Id: scm.c,v 1.4 2000/07/24 19:19:52 mdharm Exp $
- *
* SCM driver v0.2:
*
* Removed any reference to maxlen for bulk transfers.
@@ -52,7 +50,7 @@
#include "protocol.h"
#include "usb.h"
#include "debug.h"
-#include "scm.h"
+#include "shuttle_usbat.h"
#include <linux/sched.h>
#include <linux/errno.h>
@@ -64,6 +62,10 @@ extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
unsigned int len, unsigned int *act_len);
+#define short_pack(b1,b2) ( ((u16)(b1)) | ( ((u16)(b2))<<8 ) )
+#define LSB_of(s) ((s)&0xFF)
+#define MSB_of(s) ((s)>>8)
+
/*
* Send a control message and wait for the response.
*
@@ -83,62 +85,53 @@ extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
*
*/
-static int scm_send_control(struct us_data *us,
- unsigned char command[8],
- unsigned char *xfer_data,
- unsigned int xfer_len) {
+static int usbat_send_control(struct us_data *us,
+ int pipe,
+ unsigned char request,
+ unsigned char requesttype,
+ unsigned short value,
+ unsigned short index,
+ unsigned char *xfer_data,
+ unsigned int xfer_len) {
int result;
- int pipe;
- void *buffer = NULL;
-
- command[6] = xfer_len&0xFF;
- command[7] = (xfer_len>>8)&0xFF;
-
- // Get the receive or send control pipe number, based on
- // the direction indicated by the request type.
-
- if (command[0] & USB_DIR_IN)
- pipe = usb_rcvctrlpipe(us->pusb_dev,0);
- else
- pipe = usb_sndctrlpipe(us->pusb_dev,0);
-
// If data is going to be sent or received with the URB,
// then allocate a buffer for it. If data is to be sent,
// copy the data into the buffer.
-
+/*
if (xfer_len > 0) {
buffer = kmalloc(xfer_len, GFP_KERNEL);
if (!(command[0] & USB_DIR_IN))
memcpy(buffer, xfer_data, xfer_len);
}
-
+*/
// Send the URB to the device and wait for a response.
/* Why are request and request type reversed in this call? */
result = usb_stor_control_msg(us, pipe,
- command[1], command[0],
- (((unsigned short)command[3])<<8) | command[2],
- (((unsigned short)command[5])<<8) | command[3],
- buffer,
- xfer_len);
+ request, requesttype, value, index,
+ xfer_data, xfer_len);
// If data was sent or received with the URB, free the buffer we
// allocated earlier, but not before reading the data out of the
// buffer if we wanted to receive data.
-
+/*
if (xfer_len > 0) {
if (command[0] & USB_DIR_IN)
memcpy(xfer_data, buffer, xfer_len);
kfree(buffer);
}
-
+*/
// Check the return code for the command.
if (result < 0) {
+ /* if the command was aborted, indicate that */
+ if (result == -ENOENT)
+ return USB_STOR_TRANSPORT_ABORTED;
+
/* a stall is a fatal condition from the device */
if (result == -EPIPE) {
US_DEBUGP("-- Stall on control pipe. Clearing\n");
@@ -154,7 +147,7 @@ static int scm_send_control(struct us_data *us,
return USB_STOR_TRANSPORT_GOOD;
}
-static int scm_raw_bulk(struct us_data *us,
+static int usbat_raw_bulk(struct us_data *us,
int direction,
unsigned char *data,
unsigned short len) {
@@ -182,20 +175,20 @@ static int scm_raw_bulk(struct us_data *us,
/* NAK - that means we've retried a few times already */
if (result == -ETIMEDOUT) {
- US_DEBUGP("scm_raw_bulk():"
+ US_DEBUGP("usbat_raw_bulk():"
" device NAKed\n");
return US_BULK_TRANSFER_FAILED;
}
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
- US_DEBUGP("scm_raw_bulk():"
+ US_DEBUGP("usbat_raw_bulk():"
" transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
if (result == -EPIPE) {
- US_DEBUGP("scm_raw_bulk():"
+ US_DEBUGP("usbat_raw_bulk():"
" output pipe stalled\n");
return USB_STOR_TRANSPORT_FAILED;
}
@@ -220,7 +213,7 @@ static int scm_raw_bulk(struct us_data *us,
* Note: direction must be set if command_len == 0.
*/
-static int scm_bulk_transport(struct us_data *us,
+static int usbat_bulk_transport(struct us_data *us,
unsigned char *command,
unsigned short command_len,
int direction,
@@ -236,15 +229,19 @@ static int scm_bulk_transport(struct us_data *us,
int i;
struct scatterlist *sg;
char string[64];
+ int pipe;
+/*
if (command_len != 0) {
- /* Fix up the command's data length */
+ // Fix up the command's data length
command[6] = len&0xFF;
command[7] = (len>>8)&0xFF;
- result = scm_send_control(us,
+
+
+ result = usbat_send_control(us,
execute,
command,
command_len);
@@ -252,7 +249,7 @@ static int scm_bulk_transport(struct us_data *us,
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
}
-
+*/
if (len==0)
return USB_STOR_TRANSPORT_GOOD;
@@ -289,11 +286,11 @@ static int scm_bulk_transport(struct us_data *us,
len, use_sg);
if (!use_sg)
- result = scm_raw_bulk(us, direction, data, len);
+ result = usbat_raw_bulk(us, direction, data, len);
else {
sg = (struct scatterlist *)data;
for (i=0; i<use_sg && transferred<len; i++) {
- result = scm_raw_bulk(us, direction,
+ result = usbat_raw_bulk(us, direction,
sg[i].address,
len-transferred > sg[i].length ?
sg[i].length : len-transferred);
@@ -306,7 +303,7 @@ static int scm_bulk_transport(struct us_data *us,
return result;
}
-int scm_read(struct us_data *us,
+int usbat_read(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char *content) {
@@ -316,17 +313,21 @@ int scm_read(struct us_data *us,
0xC0, access, reg, 0x00, 0x00, 0x00, 0x00, 0x00
};
- result = scm_send_control(us, command, content, 1);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // US_DEBUGP("SCM: Reg %d -> %02X\n", reg, *content);
+ result = usbat_send_control(us,
+ usb_rcvctrlpipe(us->pusb_dev,0),
+ access,
+ 0xC0,
+ (u16)reg,
+ 0,
+ content,
+ 1);
+
+ // result = usbat_send_control(us, command, content, 1);
return result;
}
-int scm_write(struct us_data *us,
+int usbat_write(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char content) {
@@ -336,17 +337,21 @@ int scm_write(struct us_data *us,
0x40, access|0x01, reg, content, 0x00, 0x00, 0x00, 0x00
};
- result = scm_send_control(us, command, NULL, 0);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // US_DEBUGP("SCM: Reg %d <- %02X\n", reg, content);
+ result = usbat_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ access|0x01,
+ 0x40,
+ short_pack(reg, content),
+ 0,
+ NULL,
+ 0);
+
+ // result = usbat_send_control(us, command, NULL, 0);
return result;
}
-int scm_set_shuttle_features(struct us_data *us,
+int usbat_set_shuttle_features(struct us_data *us,
unsigned char external_trigger,
unsigned char epp_control,
unsigned char mask_byte,
@@ -360,15 +365,21 @@ int scm_set_shuttle_features(struct us_data *us,
test_pattern, mask_byte, subcountL, subcountH
};
- result = scm_bulk_transport(us, command, 8, 0, NULL, 0, 0);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
+ result = usbat_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0x80,
+ 0x40,
+ 0,
+ 0,
+ command,
+ 8);
+
+ // result = usbat_bulk_transport(us, command, 8, 0, NULL, 0, 0);
return result;
}
-int scm_read_block(struct us_data *us,
+int usbat_read_block(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char *content,
@@ -377,16 +388,27 @@ int scm_read_block(struct us_data *us,
int result;
unsigned char command[8] = {
- 0xC0, access|0x02, reg, 0x00, 0x00, 0x00, 0x00, 0x00
+ 0xC0, access|0x02, reg, 0x00, 0x00, 0x00,
+ LSB_of(len), MSB_of(len)
};
- result = scm_bulk_transport(us,
- command, 8, 0, content, len, use_sg);
+ result = usbat_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0x80,
+ 0x40,
+ 0,
+ 0,
+ command,
+ 8);
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- // US_DEBUGP("SCM: Read data, result %d\n", result);
+ result = usbat_bulk_transport(us,
+ NULL, 0, SCSI_DATA_READ, content, len, use_sg);
+
+ // result = usbat_bulk_transport(us,
+ // command, 8, 0, content, len, use_sg);
return result;
}
@@ -396,7 +418,7 @@ int scm_read_block(struct us_data *us,
* an error condition.
*/
-int scm_wait_not_busy(struct us_data *us) {
+int usbat_wait_not_busy(struct us_data *us) {
int i;
int result;
@@ -406,7 +428,7 @@ int scm_wait_not_busy(struct us_data *us) {
but probably not more than 15 minutes or so */
for (i=0; i<500; i++) {
- result = scm_read(us, SCM_ATA, 0x17, &status);
+ result = usbat_read(us, USBAT_ATA, 0x17, &status);
US_DEBUGP("SCM: Write ATA data status is %02X\n", status);
if (result!=USB_STOR_TRANSPORT_GOOD)
return result;
@@ -432,7 +454,7 @@ int scm_wait_not_busy(struct us_data *us) {
return USB_STOR_TRANSPORT_GOOD;
}
-int scm_write_block(struct us_data *us,
+int usbat_write_block(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char *content,
@@ -441,19 +463,35 @@ int scm_write_block(struct us_data *us,
int result;
unsigned char command[8] = {
- 0x40, access|0x03, reg, 0x00, 0x00, 0x00, 0x00, 0x00
+ 0x40, access|0x03, reg, 0x00, 0x00, 0x00,
+ LSB_of(len), MSB_of(len)
};
- result = scm_bulk_transport(us,
- command, 8, 0, content, len, use_sg);
+ result = usbat_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0x80,
+ 0x40,
+ 0,
+ 0,
+ command,
+ 8);
- if (result!=USB_STOR_TRANSPORT_GOOD)
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ result = usbat_bulk_transport(us,
+ NULL, 0, SCSI_DATA_WRITE, content, len, use_sg);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- return scm_wait_not_busy(us);
+ // result = usbat_bulk_transport(us,
+ // command, 8, 0, content, len, use_sg);
+
+ return usbat_wait_not_busy(us);
}
-int scm_write_block_test(struct us_data *us,
+int usbat_write_block_test(struct us_data *us,
unsigned char access,
unsigned char *registers,
unsigned char *data_out,
@@ -467,10 +505,15 @@ int scm_write_block_test(struct us_data *us,
int use_sg) {
int result;
+
+ // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
+ // but that's what came out of the trace.
+
unsigned char command[16] = {
- 0x40, access|0x07, 0x07, 0x17, 0xfc, 0xe7, 0x00, 0x00,
+ 0x40, access|0x07, 0x07, 0x17, 0xfc, 0xe7,
+ LSB_of(num_registers*2), MSB_of(num_registers*2),
0x40, access|0x05, data_reg, status_reg,
- qualifier, timeout, 0x00, 0x00
+ qualifier, timeout, LSB_of(len), MSB_of(len)
};
int i;
unsigned char data[num_registers*2];
@@ -478,28 +521,44 @@ int scm_write_block_test(struct us_data *us,
struct scatterlist *sg;
char string[64];
- command[14] = len&0xFF;
- command[15] = (len>>8)&0xFF;
-
for (i=0; i<num_registers; i++) {
data[i<<1] = registers[i];
data[1+(i<<1)] = data_out[i];
}
- result = scm_bulk_transport(us,
- command, 16, 0, data, num_registers*2, 0);
+ result = usbat_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0x80,
+ 0x40,
+ 0,
+ 0,
+ command,
+ 16);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ result = usbat_bulk_transport(us,
+ NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0);
+
+ // result = usbat_bulk_transport(us,
+ // command, 16, 0, data, num_registers*2, 0);
if (result!=USB_STOR_TRANSPORT_GOOD)
return result;
- transferred = 0;
+ // transferred = 0;
US_DEBUGP("Transfer out %d bytes, sg buffers %d\n",
len, use_sg);
+ result = usbat_bulk_transport(us,
+ NULL, 0, SCSI_DATA_WRITE, content, len, use_sg);
+
+/*
if (!use_sg) {
- /* Debug-print the first 48 bytes of the transfer */
+ // Debug-print the first 48 bytes of the transfer
string[0] = 0;
for (i=0; i<len && i<48; i++) {
@@ -513,13 +572,13 @@ int scm_write_block_test(struct us_data *us,
if (string[0]!=0)
US_DEBUGP("%s\n", string);
- result = scm_raw_bulk(us, SCSI_DATA_WRITE, content, len);
+ result = usbat_raw_bulk(us, SCSI_DATA_WRITE, content, len);
} else {
sg = (struct scatterlist *)content;
for (i=0; i<use_sg && transferred<len; i++) {
- result = scm_raw_bulk(us, SCSI_DATA_WRITE,
+ result = usbat_raw_bulk(us, SCSI_DATA_WRITE,
sg[i].address,
len-transferred > sg[i].length ?
sg[i].length : len-transferred);
@@ -528,14 +587,14 @@ int scm_write_block_test(struct us_data *us,
transferred += sg[i].length;
}
}
-
+*/
if (result!=USB_STOR_TRANSPORT_GOOD)
return result;
- return scm_wait_not_busy(us);
+ return usbat_wait_not_busy(us);
}
-int scm_multiple_write(struct us_data *us,
+int usbat_multiple_write(struct us_data *us,
unsigned char access,
unsigned char *registers,
unsigned char *data_out,
@@ -544,8 +603,9 @@ int scm_multiple_write(struct us_data *us,
int result;
unsigned char data[num_registers*2];
int i;
- unsigned char cmd[8] = {
- 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ unsigned char command[8] = {
+ 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00,
+ LSB_of(num_registers*2), MSB_of(num_registers*2)
};
for (i=0; i<num_registers; i++) {
@@ -553,12 +613,73 @@ int scm_multiple_write(struct us_data *us,
data[1+(i<<1)] = data_out[i];
}
- result = scm_bulk_transport(us, cmd, 8, 0, data, num_registers*2, 0);
+ result = usbat_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0x80,
+ 0x40,
+ 0,
+ 0,
+ command,
+ 8);
+
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ result = usbat_bulk_transport(us,
+ NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0);
+
+ // result = usbat_bulk_transport(us, cmd, 8, 0,
+ // data, num_registers*2, 0);
if (result!=USB_STOR_TRANSPORT_GOOD)
return result;
- return scm_wait_not_busy(us);
+ return usbat_wait_not_busy(us);
+}
+
+int usbat_read_user_io(struct us_data *us,
+ unsigned char *data_flags) {
+
+ unsigned char command[8] = {
+ 0xC0, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ int result;
+
+ result = usbat_send_control(us,
+ usb_rcvctrlpipe(us->pusb_dev,0),
+ 0x82,
+ 0xC0,
+ 0,
+ 0,
+ data_flags,
+ 1);
+
+ // result = usbat_send_control(us, command, data_flags, 1);
+
+ return result;
+}
+
+int usbat_write_user_io(struct us_data *us,
+ unsigned char enable_flags,
+ unsigned char data_flags) {
+
+ unsigned char command[8] = {
+ 0x40, 0x82, enable_flags, data_flags, 0x00, 0x00, 0x00, 0x00
+ };
+ int result;
+
+ result = usbat_send_control(us,
+ usb_sndctrlpipe(us->pusb_dev,0),
+ 0x82,
+ 0x40,
+ short_pack(enable_flags, data_flags),
+ 0,
+ NULL,
+ 0);
+
+ // result = usbat_send_control(us, command, NULL, 0);
+
+ return result;
}
static int hp_8200e_select_and_test_registers(struct us_data *us) {
@@ -571,39 +692,39 @@ static int hp_8200e_select_and_test_registers(struct us_data *us) {
for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
- if ( (result = scm_write(us, SCM_ATA, 0x16, selector)) !=
+ if ( (result = usbat_write(us, USBAT_ATA, 0x16, selector)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read(us, SCM_ATA, 0x17, &status)) !=
+ if ( (result = usbat_read(us, USBAT_ATA, 0x17, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read(us, SCM_ATA, 0x16, &status)) !=
+ if ( (result = usbat_read(us, USBAT_ATA, 0x16, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read(us, SCM_ATA, 0x14, &status)) !=
+ if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read(us, SCM_ATA, 0x15, &status)) !=
+ if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_write(us, SCM_ATA, 0x14, 0x55)) !=
+ if ( (result = usbat_write(us, USBAT_ATA, 0x14, 0x55)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_write(us, SCM_ATA, 0x15, 0xAA)) !=
+ if ( (result = usbat_write(us, USBAT_ATA, 0x15, 0xAA)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read(us, SCM_ATA, 0x14, &status)) !=
+ if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read(us, SCM_ATA, 0x15, &status)) !=
+ if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
}
@@ -611,89 +732,6 @@ static int hp_8200e_select_and_test_registers(struct us_data *us) {
return result;
}
-int scm_read_user_io(struct us_data *us,
- unsigned char *data_flags) {
-
- unsigned char command[8] = {
- 0xC0, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- int result;
-
- result = scm_send_control(us, command, data_flags, 1);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // US_DEBUGP("SCM: User I/O flags -> %02X\n", *data_flags);
-
- return result;
-}
-
-int scm_write_user_io(struct us_data *us,
- unsigned char enable_flags,
- unsigned char data_flags) {
-
- unsigned char command[8] = {
- 0x40, 0x82, enable_flags, data_flags, 0x00, 0x00, 0x00, 0x00
- };
- int result;
-
- result = scm_send_control(us, command, NULL, 0);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // US_DEBUGP("SCM: User I/O flags <- %02X\n", data_flags);
-
- return result;
-}
-
-static int init_sddr09(struct us_data *us) {
-
- int result;
- unsigned char data[14];
- unsigned char command[8] = {
- 0xc1, 0x01, 0, 0, 0, 0, 0, 0
- };
- unsigned char command2[8] = {
- 0x41, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char tur[12] = {
- 0x03, 0x20, 0, 0, 0x0e, 0, 0, 0, 0, 0, 0, 0
- };
-
- if ( (result = scm_send_control(us, command, data, 2)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);
-
- command[1] = 0x08;
-
- if ( (result = scm_send_control(us, command, data, 2)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);
-/*
- if ( (result = scm_send_control(us, command2, tur, 12)) !=
- USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("SDDR09: request sense failed\n");
- return result;
- }
-
- if ( (result = scm_raw_bulk(
- us, SCSI_DATA_READ, data, 14)) !=
- USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("SDDR09: request sense bulk in failed\n");
- return result;
- }
-
- US_DEBUGP("SDDR09: request sense worked\n");
-*/
- return result;
-}
-
static int init_8200e(struct us_data *us) {
int result;
@@ -701,89 +739,119 @@ static int init_8200e(struct us_data *us) {
// Enable peripheral control signals
- if ( (result = scm_write_user_io(us,
- SCM_UIO_OE1 | SCM_UIO_OE0,
- SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
+ if ( (result = usbat_write_user_io(us,
+ USBAT_UIO_OE1 | USBAT_UIO_OE0,
+ USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 1\n");
+
wait_ms(2000);
- if ( (result = scm_read_user_io(us, &status)) !=
+ if ( (result = usbat_read_user_io(us, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read_user_io(us, &status)) !=
+ US_DEBUGP("INIT 2\n");
+
+ if ( (result = usbat_read_user_io(us, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 3\n");
+
// Reset peripheral, enable periph control signals
// (bring reset signal up)
- if ( (result = scm_write_user_io(us,
- SCM_UIO_DRVRST | SCM_UIO_OE1 | SCM_UIO_OE0,
- SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
+ if ( (result = usbat_write_user_io(us,
+ USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
+ USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 4\n");
+
// Enable periph control signals
// (bring reset signal down)
- if ( (result = scm_write_user_io(us,
- SCM_UIO_OE1 | SCM_UIO_OE0,
- SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
+ if ( (result = usbat_write_user_io(us,
+ USBAT_UIO_OE1 | USBAT_UIO_OE0,
+ USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 5\n");
+
wait_ms(250);
// Write 0x80 to ISA port 0x3F
- if ( (result = scm_write(us, SCM_ISA, 0x3F, 0x80)) !=
+ if ( (result = usbat_write(us, USBAT_ISA, 0x3F, 0x80)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 6\n");
+
// Read ISA port 0x27
- if ( (result = scm_read(us, SCM_ISA, 0x27, &status)) !=
+ if ( (result = usbat_read(us, USBAT_ISA, 0x27, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read_user_io(us, &status)) !=
+ US_DEBUGP("INIT 7\n");
+
+ if ( (result = usbat_read_user_io(us, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 8\n");
+
if ( (result = hp_8200e_select_and_test_registers(us)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read_user_io(us, &status)) !=
+ US_DEBUGP("INIT 9\n");
+
+ if ( (result = usbat_read_user_io(us, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 10\n");
+
// Enable periph control signals and card detect
- if ( (result = scm_write_user_io(us,
- SCM_UIO_ACKD |SCM_UIO_OE1 | SCM_UIO_OE0,
- SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
+ if ( (result = usbat_write_user_io(us,
+ USBAT_UIO_ACKD |USBAT_UIO_OE1 | USBAT_UIO_OE0,
+ USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_read_user_io(us, &status)) !=
+ US_DEBUGP("INIT 11\n");
+
+ if ( (result = usbat_read_user_io(us, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 12\n");
+
wait_ms(1400);
- if ( (result = scm_read_user_io(us, &status)) !=
+ if ( (result = usbat_read_user_io(us, &status)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 13\n");
+
if ( (result = hp_8200e_select_and_test_registers(us)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
- if ( (result = scm_set_shuttle_features(us,
+ US_DEBUGP("INIT 14\n");
+
+ if ( (result = usbat_set_shuttle_features(us,
0x83, 0x00, 0x88, 0x08, 0x15, 0x14)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
+ US_DEBUGP("INIT 15\n");
+
return result;
}
@@ -923,7 +991,7 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7];
}
- result = scm_write_block_test(us, SCM_ATA,
+ result = usbat_write_block_test(us, USBAT_ATA,
registers, data, 19,
0x10, 0x17, 0xFD, 0x30,
srb->request_buffer,
@@ -932,16 +1000,16 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
return result;
}
- if ( (result = scm_multiple_write(us,
- SCM_ATA,
+ if ( (result = usbat_multiple_write(us,
+ USBAT_ATA,
registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) {
return result;
}
// Write the 12-byte command header.
- if ( (result = scm_write_block(us,
- SCM_ATA, 0x10, srb->cmnd, 12, 0)) !=
+ if ( (result = usbat_write_block(us,
+ USBAT_ATA, 0x10, srb->cmnd, 12, 0)) !=
USB_STOR_TRANSPORT_GOOD) {
return result;
}
@@ -953,14 +1021,15 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
// How many bytes to read in? Check cylL register
- if ( (result = scm_read(us, SCM_ATA, 0x14, &status)) !=
+ if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) !=
USB_STOR_TRANSPORT_GOOD) {
return result;
}
if (len>0xFF) { // need to read cylH also
len = status;
- if ( (result = scm_read(us, SCM_ATA, 0x15, &status)) !=
+ if ( (result = usbat_read(us, USBAT_ATA, 0x15,
+ &status)) !=
USB_STOR_TRANSPORT_GOOD) {
return result;
}
@@ -970,7 +1039,7 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
len = status;
- result = scm_read_block(us, SCM_ATA, 0x10,
+ result = usbat_read_block(us, USBAT_ATA, 0x10,
srb->request_buffer, len, srb->use_sg);
/* Debug-print the first 32 bytes of the transfer */
@@ -996,161 +1065,3 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
}
-/*
- * Transport for the Sandisk SDDR-09
- */
-int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- int result;
- unsigned int len;
- unsigned char send_scsi_command[8] = {
- 0x41, 0, 0, 0, 0, 0, 0, 0
- };
- int i;
- char string[64];
- unsigned char *ptr;
- unsigned char inquiry_response[36] = {
- 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00,
- 'S', 'a', 'n', 'D', 'i', 's', 'k', ' ',
- 'I', 'm', 'a', 'g', 'e', 'M', 'a', 't',
- 'e', ' ', 'S', 'D', 'D', 'R', '0', '9',
- ' ', ' ', ' ', ' '
- };
-
- /* This table tells us:
- X = command not supported
- L = return length in cmnd[4] (8 bits).
- H = return length in cmnd[7] and cmnd[8] (16 bits).
- D = return length in cmnd[6] to cmnd[9] (32 bits).
- B = return length/blocksize in cmnd[6] to cmnd[8].
- T = return length in cmnd[6] to cmnd[8] (24 bits).
- 0-9 = fixed return length
- W = 24 bytes
- h = return length/2048 in cmnd[7-8].
- */
-
- static char *lengths =
-
- /* 0123456789ABCDEF 0123456789ABCDEF */
-
- "0XXL0XXXXXXXXXXX" "XXLXXXXXXXX0XX0X" /* 00-1F */
- "XXXXX8XXhXH0XXX0" "XXXXX0XXXXXXXXXX" /* 20-3F */
- "XXHHL0X0XXH0XX0X" "XHH00HXX0TH0H0XX" /* 40-5F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */
- "X0XXX0XXDXDXXXXX" "XXXXXXXXX000XHBX" /* A0-BF */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */
- "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */
-
- if (us->flags & US_FL_NEED_INIT) {
- US_DEBUGP("SDDR-09: initializing\n");
- init_sddr09(us);
- us->flags &= ~US_FL_NEED_INIT;
- }
-
- /* if (srb->sc_data_direction == SCSI_DATA_WRITE) */
- len = srb->request_bufflen;
- /* else {
-
- switch (lengths[srb->cmnd[0]]) {
-
- case 'L':
- len = srb->cmnd[4];
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- len = lengths[srb->cmnd[0]]-'0';
- break;
- case 'H':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- break;
- case 'h':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- len <<= 11; // *2048
- break;
- case 'T':
- len = (((unsigned int)srb->cmnd[6])<<16) |
- (((unsigned int)srb->cmnd[7])<<8) |
- srb->cmnd[8];
- break;
- case 'D':
- len = (((unsigned int)srb->cmnd[6])<<24) |
- (((unsigned int)srb->cmnd[7])<<16) |
- (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
- case 'W':
- len = 24;
- break;
- case 'B':
- // Let's try using the command structure's
- // request_bufflen here
- len = srb->request_bufflen;
- break;
- default:
- US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n",
- srb->cmnd[0]);
- return USB_STOR_TRANSPORT_ERROR;
- }
- } */
-
- if (srb->request_bufflen > 0xFFFF) {
- US_DEBUGP("Error: len = %08X... what do I do now?\n",
- len);
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* Dummy up a response for INQUIRY since SDDR09 doesn't
- respond to INQUIRY commands */
-
- if (srb->cmnd[0] == INQUIRY) {
- memcpy(srb->request_buffer, inquiry_response, 36);
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- for (; srb->cmd_len<12; srb->cmd_len++)
- srb->cmnd[srb->cmd_len] = 0;
-
- srb->cmnd[1] = 0x20;
-
- string[0] = 0;
- for (i=0; i<12; i++)
- sprintf(string+strlen(string), "%02X ", srb->cmnd[i]);
-
- US_DEBUGP("SDDR09: Send control for command %s\n",
- string);
-
- if ( (result = scm_send_control(us, send_scsi_command,
- srb->cmnd, 12)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("SDDR09: Control for command OK\n");
-
- if (srb->sc_data_direction == SCSI_DATA_WRITE ||
- srb->sc_data_direction == SCSI_DATA_READ) {
-
- US_DEBUGP("SDDR09: %s %d bytes\n",
- srb->sc_data_direction==SCSI_DATA_WRITE ?
- "sending" : "receiving",
- len);
-
- result = scm_bulk_transport(us,
- NULL, 0, srb->sc_data_direction,
- srb->request_buffer,
- len, srb->use_sg);
-
- return result;
-
- }
-
- return result;
-}
-
diff --git a/drivers/usb/storage/scm.h b/drivers/usb/storage/shuttle_usbat.h
index f57463a1e..eede2651f 100644
--- a/drivers/usb/storage/scm.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -1,8 +1,6 @@
/* Driver for SCM Microsystems USB-ATAPI cable
* Header File
*
- * $Id: scm.h,v 1.3 2000/07/24 19:19:52 mdharm Exp $
- *
* Current development and maintainance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
*
@@ -23,60 +21,56 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifndef _USB_SCM_H
-#define _USB_SCM_H
+#ifndef _USB_SHUTTLE_USBAT_H
+#define _USB_SHUTTLE_USBAT_H
-#define SCM_EPP_PORT 0x10
-#define SCM_EPP_REGISTER 0x30
-#define SCM_ATA 0x40
-#define SCM_ISA 0x50
+#define USBAT_EPP_PORT 0x10
+#define USBAT_EPP_REGISTER 0x30
+#define USBAT_ATA 0x40
+#define USBAT_ISA 0x50
/* SCM User I/O Data registers */
-#define SCM_UIO_EPAD 0x80 // Enable Peripheral Control Signals
-#define SCM_UIO_CDT 0x40 // Card Detect (Read Only)
+#define USBAT_UIO_EPAD 0x80 // Enable Peripheral Control Signals
+#define USBAT_UIO_CDT 0x40 // Card Detect (Read Only)
// CDT = ACKD & !UI1 & !UI0
-#define SCM_UIO_1 0x20 // I/O 1
-#define SCM_UIO_0 0x10 // I/O 0
-#define SCM_UIO_EPP_ATA 0x08 // 1=EPP mode, 0=ATA mode
-#define SCM_UIO_UI1 0x04 // Input 1
-#define SCM_UIO_UI0 0x02 // Input 0
-#define SCM_UIO_INTR_ACK 0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP)
+#define USBAT_UIO_1 0x20 // I/O 1
+#define USBAT_UIO_0 0x10 // I/O 0
+#define USBAT_UIO_EPP_ATA 0x08 // 1=EPP mode, 0=ATA mode
+#define USBAT_UIO_UI1 0x04 // Input 1
+#define USBAT_UIO_UI0 0x02 // Input 0
+#define USBAT_UIO_INTR_ACK 0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP)
/* SCM User I/O Enable registers */
-#define SCM_UIO_DRVRST 0x80 // Reset Peripheral
-#define SCM_UIO_ACKD 0x40 // Enable Card Detect
-#define SCM_UIO_OE1 0x20 // I/O 1 set=output/clr=input
+#define USBAT_UIO_DRVRST 0x80 // Reset Peripheral
+#define USBAT_UIO_ACKD 0x40 // Enable Card Detect
+#define USBAT_UIO_OE1 0x20 // I/O 1 set=output/clr=input
// If ACKD=1, set OE1 to 1 also.
-#define SCM_UIO_OE0 0x10 // I/O 0 set=output/clr=input
-#define SCM_UIO_ADPRST 0x01 // Reset SCM chip
+#define USBAT_UIO_OE0 0x10 // I/O 0 set=output/clr=input
+#define USBAT_UIO_ADPRST 0x01 // Reset SCM chip
-/* SCM-specific commands */
+/* USBAT-specific commands */
-extern int scm_read(struct us_data *us, unsigned char access,
+extern int usbat_read(struct us_data *us, unsigned char access,
unsigned char reg, unsigned char *content);
-extern int scm_write(struct us_data *us, unsigned char access,
+extern int usbat_write(struct us_data *us, unsigned char access,
unsigned char reg, unsigned char content);
-extern int scm_read_block(struct us_data *us, unsigned char access,
+extern int usbat_read_block(struct us_data *us, unsigned char access,
unsigned char reg, unsigned char *content, unsigned short len,
int use_sg);
-extern int scm_write_block(struct us_data *us, unsigned char access,
+extern int usbat_write_block(struct us_data *us, unsigned char access,
unsigned char reg, unsigned char *content, unsigned short len,
int use_sg);
-extern int scm_multiple_write(struct us_data *us, unsigned char access,
+extern int usbat_multiple_write(struct us_data *us, unsigned char access,
unsigned char *registers, unsigned char *data_out,
unsigned short num_registers);
-extern int scm_read_user_io(struct us_data *us, unsigned char *data_flags);
-extern int scm_write_user_io(struct us_data *us,
+extern int usbat_read_user_io(struct us_data *us, unsigned char *data_flags);
+extern int usbat_write_user_io(struct us_data *us,
unsigned char enable_flags, unsigned char data_flags);
/* HP 8200e stuff */
extern int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us);
-/* Sandisk SDDR-09 stuff */
-
-extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us);
-
#endif
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 88c847641..69dfcfde8 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: transport.c,v 1.3 2000/07/20 01:06:40 mdharm Exp $
+ * $Id: transport.c,v 1.4 2000/07/25 23:04:47 mdharm Exp $
*
* Current development and maintainance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -203,7 +203,7 @@ static int us_transfer_partial(struct us_data *us, char *buf, int length)
int pipe;
/* calculate the appropriate pipe information */
- if (US_DIRECTION(us->srb->cmnd[0]))
+ if (us->srb->sc_data_direction == SCSI_DATA_READ)
pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
else
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
@@ -258,7 +258,7 @@ static int us_transfer_partial(struct us_data *us, char *buf, int length)
* function simply determines if we're going to use scatter-gather or not,
* and acts appropriately. For now, it also re-interprets the error codes.
*/
-static void us_transfer(Scsi_Cmnd *srb, struct us_data* us, int dir_in)
+static void us_transfer(Scsi_Cmnd *srb, struct us_data* us)
{
int i;
int result = -1;
@@ -414,8 +414,9 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
if (need_auto_sense) {
int temp_result;
void* old_request_buffer;
- int old_sg;
- int old_request_bufflen;
+ unsigned short old_sg;
+ unsigned old_request_bufflen;
+ unsigned char old_sc_data_direction;
unsigned char old_cmnd[MAX_COMMAND_SIZE];
US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
@@ -431,13 +432,21 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
srb->cmnd[4] = 18;
srb->cmnd[5] = 0;
- /* set the buffer length for transfer */
+ /* set the transfer direction */
+ old_sc_data_direction = srb->sc_data_direction;
+ srb->sc_data_direction = SCSI_DATA_READ;
+
+ /* use the new buffer we have */
old_request_buffer = srb->request_buffer;
+ srb->request_buffer = srb->sense_buffer;
+
+ /* set the buffer length for transfer */
old_request_bufflen = srb->request_bufflen;
+ srb->request_bufflen = 18;
+
+ /* set up for no scatter-gather use */
old_sg = srb->use_sg;
srb->use_sg = 0;
- srb->request_bufflen = 18;
- srb->request_buffer = srb->sense_buffer;
/* issue the auto-sense command */
temp_result = us->transport(us->srb, us);
@@ -462,6 +471,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
srb->request_buffer = old_request_buffer;
srb->request_bufflen = old_request_bufflen;
srb->use_sg = old_sg;
+ srb->sc_data_direction = old_sc_data_direction;
memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
/* If things are really okay, then let's show that */
@@ -555,7 +565,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
if (us_transfer_length(srb, us)) {
- us_transfer(srb, us, US_DIRECTION(srb->cmnd[0]));
+ us_transfer(srb, us);
US_DEBUGP("CBI data stage result is 0x%x\n", srb->result);
/* if it was aborted, we need to indicate that */
@@ -656,7 +666,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
if (us_transfer_length(srb, us)) {
- us_transfer(srb, us, US_DIRECTION(srb->cmnd[0]));
+ us_transfer(srb, us);
US_DEBUGP("CB data stage result is 0x%x\n", srb->result);
/* if it was aborted, we need to indicate that */
@@ -718,7 +728,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb, us));
- bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7;
+ bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb.Tag = srb->serial_number;
bcb.Lun = srb->cmnd[1] >> 5;
bcb.Length = srb->cmd_len;
@@ -755,7 +765,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
if (result == 0) {
/* send/receive data payload, if there is any */
if (bcb.DataTransferLength) {
- us_transfer(srb, us, bcb.Flags);
+ us_transfer(srb, us);
US_DEBUGP("Bulk data transfer result 0x%x\n",
srb->result);
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 55e12f79f..9d0993c1e 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* Transport Functions Header File
*
- * $Id: transport.h,v 1.4 2000/07/23 18:40:38 groovyjava Exp $
+ * $Id: transport.h,v 1.6 2000/07/27 14:42:43 groovyjava Exp $
*
* Current development and maintainance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -46,10 +46,6 @@
#include "usb.h"
#include "scsi.h"
-/* bit set if input */
-extern unsigned char us_direction[256/8];
-#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
-
/* Protocols */
#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */
@@ -59,7 +55,8 @@ extern unsigned char us_direction[256/8];
#define US_PR_SCM_ATAPI 0x80 /* SCM-ATAPI bridge */
#endif
#ifdef CONFIG_USB_STORAGE_SDDR09
-#define US_PR_SCM_SCSI 0x81 /* SCM-SCSI bridge */
+#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for
+ SDDR-09 */
#endif
/*
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 99986371f..c82d7e914 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: usb.c,v 1.11 2000/07/24 20:37:24 mdharm Exp $
+ * $Id: usb.c,v 1.14 2000/07/27 14:42:43 groovyjava Exp $
*
* Current development and maintainance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -50,8 +50,11 @@
#include "transport.h"
#include "protocol.h"
#include "debug.h"
-#if defined(CONFIG_USB_STORAGE_HP8200e) || defined(CONFIG_USB_STORAGE_SDDR09)
-#include "scm.h"
+#ifdef CONFIG_USB_STORAGE_HP8200e
+#include "shuttle_usbat.h"
+#endif
+#ifdef CONFIG_USB_STORAGE_SDDR09
+#include "sddr09.h"
#endif
#include <linux/module.h>
@@ -117,9 +120,9 @@ static int usb_stor_control_thread(void * __us)
/* signal that we've started the thread */
up(&(us->notify));
+ set_current_state(TASK_INTERRUPTIBLE);
for(;;) {
- set_current_state(TASK_INTERRUPTIBLE);
US_DEBUGP("*** thread sleeping.\n");
schedule();
US_DEBUGP("*** thread awakened.\n");
@@ -137,15 +140,27 @@ static int usb_stor_control_thread(void * __us)
switch (action) {
case US_ACT_COMMAND:
+ /* reject the command if the direction indicator
+ * is UNKNOWN
+ */
+ if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
+ US_DEBUGP("UNKNOWN data direction\n");
+ us->srb->result = DID_ERROR;
+ set_current_state(TASK_INTERRUPTIBLE);
+ us->srb->scsi_done(us->srb);
+ us->srb = NULL;
+ break;
+ }
+
/* reject if target != 0 or if LUN is higher than
* the maximum known LUN
*/
if (us->srb->target || (us->srb->lun > us->max_lun)) {
US_DEBUGP("Bad device number (%d/%d)\n",
us->srb->target, us->srb->lun);
-
us->srb->result = DID_BAD_TARGET << 16;
+ set_current_state(TASK_INTERRUPTIBLE);
us->srb->scsi_done(us->srb);
us->srb = NULL;
break;
@@ -155,6 +170,8 @@ static int usb_stor_control_thread(void * __us)
if ((us->srb->cmnd[0] == START_STOP) &&
(us->flags & US_FL_START_STOP)) {
us->srb->result = GOOD;
+
+ set_current_state(TASK_INTERRUPTIBLE);
us->srb->scsi_done(us->srb);
us->srb = NULL;
break;
@@ -194,9 +211,11 @@ static int usb_stor_control_thread(void * __us)
if (us->srb->result != DID_ABORT << 16) {
US_DEBUGP("scsi cmd done, result=0x%x\n",
us->srb->result);
+ set_current_state(TASK_INTERRUPTIBLE);
us->srb->scsi_done(us->srb);
} else {
US_DEBUGP("scsi command aborted\n");
+ set_current_state(TASK_INTERRUPTIBLE);
up(&(us->notify));
}
us->srb = NULL;
@@ -253,12 +272,12 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
US_SC_UFI, US_PR_CBI, US_FL_SINGLE_LUN},
{ 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara FlashGate SmartMedia",
US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
- { 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk ImageMate (SDDR-01)",
+ { 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk ImageMate (SDDR-05a)",
US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP},
#ifdef CONFIG_USB_STORAGE_SDDR09
{ 0x0781, 0x0200, 0x0100, 0x0100, "Sandisk ImageMate (SDDR-09)",
- US_SC_SCSI, US_PR_SCM_SCSI,
- US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_NEED_INIT},
+ US_SC_SCSI, US_PR_EUSB_SDDR09,
+ US_FL_SINGLE_LUN | US_FL_START_STOP},
#endif
{ 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk Imagemate (SDDR-31)",
US_SC_SCSI, US_PR_BULK, US_FL_IGNORE_SER},
@@ -447,7 +466,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
/* set the interface -- STALL is an acceptable response here */
#ifdef CONFIG_USB_STORAGE_SDDR09
- if (protocol != US_PR_SCM_SCSI)
+ if (protocol != US_PR_EUSB_SDDR09)
result = usb_set_interface(dev,
altsetting->bInterfaceNumber, 0);
else
@@ -631,8 +650,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
#endif
#ifdef CONFIG_USB_STORAGE_SDDR09
- case US_PR_SCM_SCSI:
- ss->transport_name = "SCM/SCSI";
+ case US_PR_EUSB_SDDR09:
+ ss->transport_name = "EUSB/SDDR09";
ss->transport = sddr09_transport;
ss->transport_reset = usb_stor_CB_reset;
ss->max_lun = 1;
@@ -855,3 +874,6 @@ void __exit usb_stor_exit(void)
module_init(usb_stor_init) ;
module_exit(usb_stor_exit) ;
+
+MODULE_AUTHOR("Michael Gee <michael@linuxspecific.com>, David L. Brown, Jr. <usb-storage@davidb.org>, Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
+MODULE_DESCRIPTION("USB Mass Storage driver");
diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c
index 31be1c0e2..8423b448a 100644
--- a/drivers/usb/uhci.c
+++ b/drivers/usb/uhci.c
@@ -49,6 +49,7 @@ static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data);
static int debug = 1;
MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level");
static kmem_cache_t *uhci_td_cachep;
static kmem_cache_t *uhci_qh_cachep;
@@ -2541,5 +2542,8 @@ void cleanup_module(void)
pm_unregister_all(handle_pm_event);
uhci_cleanup();
}
+
+MODULE_AUTHOR("Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
+MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
#endif //MODULE
diff --git a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c
index 48a5df48e..cfa871503 100644
--- a/drivers/usb/usb-ohci.c
+++ b/drivers/usb/usb-ohci.c
@@ -65,6 +65,9 @@
*/
#include <linux/adb.h>
#include <linux/pmu.h>
+#ifndef CONFIG_PM
+#define CONFIG_PM
+#endif
#endif
@@ -415,9 +418,11 @@ static int sohci_submit_urb (urb_t * urb)
int i, size = 0;
unsigned long flags;
- if (!urb->dev || !urb->dev->bus) return -EINVAL;
+ if (!urb->dev || !urb->dev->bus)
+ return -EINVAL;
- if (urb->hcpriv) return -EINVAL; /* urb already in use */
+ if (urb->hcpriv) /* urb already in use */
+ return -EINVAL;
// if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)))
// return -EPIPE;
@@ -435,8 +440,10 @@ static int sohci_submit_urb (urb_t * urb)
/* when controller's hung, permit only roothub cleanup attempts
* such as powering down ports */
- if (ohci->disabled)
+ if (ohci->disabled) {
+ usb_dec_dev_use (urb->dev);
return -ESHUTDOWN;
+ }
/* every endpoint has a ed, locate and fill it */
if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1))) {
@@ -1730,7 +1737,9 @@ static int rh_submit_urb (urb_t * urb)
urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe));
#endif
- if (urb->complete) urb->complete (urb);
+ if (urb->complete)
+ urb->complete (urb);
+ usb_dec_dev_use (urb->dev);
return 0;
}
@@ -1880,7 +1889,9 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r)
ohci->ohci_dev->slot_name);
// e.g. due to PCI Master/Target Abort
-#ifndef DEBUG
+#ifdef DEBUG
+ ohci_dump (ohci, 1);
+#else
// FIXME: be optimistic, hope that bug won't repeat often.
// Make some non-interrupt context restart the controller.
// Count and limit the retries though; either hardware or
@@ -1910,6 +1921,8 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r)
}
writel (ints, &regs->intrstatus);
writel (OHCI_INTR_MIE, &regs->intrenable);
+
+ /* FIXME: check URB timeouts */
}
/*-------------------------------------------------------------------------*/
@@ -1921,7 +1934,7 @@ static ohci_t * __devinit hc_alloc_ohci (void * mem_base)
ohci_t * ohci;
struct usb_bus * bus;
- ohci = (ohci_t *) __get_free_pages (GFP_KERNEL, 1);
+ ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL);
if (!ohci)
return NULL;
@@ -1932,7 +1945,7 @@ static ohci_t * __devinit hc_alloc_ohci (void * mem_base)
bus = usb_alloc_bus (&sohci_device_operations);
if (!bus) {
- free_pages ((unsigned long) ohci, 1);
+ kfree (ohci);
return NULL;
}
@@ -1974,7 +1987,7 @@ static void hc_release_ohci (ohci_t * ohci)
/* unmap the IO address space */
iounmap (ohci->regs);
- free_pages ((unsigned long) ohci, 1);
+ kfree (ohci);
}
/*-------------------------------------------------------------------------*/
@@ -2085,13 +2098,27 @@ static void hc_restart (ohci_t *ohci)
static int __devinit
ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
- unsigned long mem_resource;
+ unsigned long mem_resource, mem_len;
u8 latency, limit;
void *mem_base;
if (pci_enable_device(dev) < 0)
return -ENODEV;
+ /* we read its hardware registers as memory */
+ mem_resource = pci_resource_start(dev, 0);
+ mem_len = pci_resource_len(dev, 0);
+ if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
+ dbg ("controller already in use");
+ return -EBUSY;
+ }
+
+ mem_base = ioremap_nocache (mem_resource, mem_len);
+ if (!mem_base) {
+ err("Error mapping OHCI memory");
+ return -EFAULT;
+ }
+
/* controller writes into our memory */
pci_set_master (dev);
pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
@@ -2103,15 +2130,6 @@ ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
}
}
- /* we read its hardware registers as memory */
- mem_resource = pci_resource_start(dev, 0);
- /* request_mem_region ... */
- mem_base = ioremap_nocache (mem_resource, 4096);
- if (!mem_base) {
- err("Error mapping OHCI memory");
- return -EFAULT;
- }
-
return hc_found_ohci (dev, dev->irq, mem_base);
}
@@ -2145,6 +2163,8 @@ ohci_pci_remove (struct pci_dev *dev)
&ohci->regs->control);
hc_release_ohci (ohci);
+
+ release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
}
@@ -2233,7 +2253,7 @@ ohci_pci_resume (struct pci_dev *dev)
/*-------------------------------------------------------------------------*/
-static const struct __devinitdata pci_device_id ohci_pci_ids [] = { {
+static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
/* handle any USB OHCI controller */
class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10),
@@ -2328,4 +2348,5 @@ module_exit (ohci_hcd_cleanup);
#endif /* MODULE */
+MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>");
MODULE_DESCRIPTION ("USB OHCI Host Controller Driver");
diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c
index 626bfc93c..e82fa78a0 100644
--- a/drivers/usb/usb-uhci.c
+++ b/drivers/usb/usb-uhci.c
@@ -2885,4 +2885,6 @@ void cleanup_module (void)
uhci_cleanup ();
}
+MODULE_AUTHOR("Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
+MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
#endif //MODULE
diff --git a/drivers/usb/usbkbd.c b/drivers/usb/usbkbd.c
index 42f82604e..89cc76537 100644
--- a/drivers/usb/usbkbd.c
+++ b/drivers/usb/usbkbd.c
@@ -36,6 +36,7 @@
#include <linux/usb.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("USB HID Boot Protocol keyboard driver");
static unsigned char usb_kbd_keycode[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
diff --git a/drivers/usb/usbmouse.c b/drivers/usb/usbmouse.c
index 55bd14fdb..39df8e5e0 100644
--- a/drivers/usb/usbmouse.c
+++ b/drivers/usb/usbmouse.c
@@ -36,6 +36,7 @@
#include <linux/usb.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("USB HID Boot Protocol mouse driver");
struct usb_mouse {
signed char data[8];
diff --git a/drivers/usb/wacom.c b/drivers/usb/wacom.c
index de2821e47..b74a003e8 100644
--- a/drivers/usb/wacom.c
+++ b/drivers/usb/wacom.c
@@ -51,6 +51,7 @@
#include <linux/usb.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("USB Wacom Graphire and Wacom Intuos tablet driver");
/*
* Wacom Graphire packet:
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 4b388f60b..f206bef56 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -857,7 +857,7 @@ static int rivafb_set_var (struct fb_var_screeninfo *var, int con,
v.blue.offset = 0;
#endif
v.red.length = 5;
- v.green.length = 5;
+ v.green.length = 6;
v.blue.length = 5;
break;
#endif
@@ -1390,8 +1390,8 @@ static int riva_setcolreg (unsigned regno, unsigned red, unsigned green,
((green & 0xf800) << 2) | ((blue & 0xf800) >> 3);
#else
rivainfo->con_cmap.cfb16[regno] =
- ((red & 0xf800) >> 1) |
- ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
+ ((red & 0xf800) >> 0) |
+ ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
#endif
break;
#endif /* FBCON_HAS_CFB16 */