This driver is for Compaq's SMART2 Intellegent Disk Array Controllers.
-WARNING:
---------
-
-This driver comes with NO WARRANTY. It is not officially supported by
-Compaq. Do not call technical support. Use at your own risk.
-
Supported Cards:
----------------
@@ -22,6+16,7 @@ This driver is known to work with the following cards: * Integrated Smart Array Controller
* SA 4200
* SA 4250ES
+ * SA 431
It should also work with some really old Disk array adapters, but I am
unable to test against these cards:
@@ -199,8+199,9 @@ S: Maintained COMPAQ SMART2 RAID DRIVER
P: Charles White
M: Charles White <arrays@compaq.com>
-L: compaqandlinux@yps.org
-S: Maintained
+L: compaqandlinux@cpqlin.van-dijk.net
+W: ftp.compaq.com/pub/products/drivers/linux
+S: Supported
COMPUTONE INTELLIPORT MULTIPORT CARD
P: Doug McNash
* Copyright (C) 1999 Silicon Graphics, Inc.
* Copyright (C) Vijay Chander(vijay@engr.sgi.com)
*
- * 00/03/29 C. Fleckenstein Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
+ * 00/03/29 C. Fleckenstein Fixed PAL/SAL update issues, began MCA bug fixes,
+ * logging issues,
* added min save state dump, added INIT handler.
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/sched.h>
* Derived from the x86 and Alpha versions. Most of the code in here
* could actually be factored into a common set of routines.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -277,20+277,24 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) goto beyond_if;
}
+ down(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset);
+ up(¤t->mm->mmap_sem);
if (error != N_TXTADDR(ex)) {
send_sig(SIGKILL, current, 0);
return error;
}
+ down(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
+ up(¤t->mm->mmap_sem);
if (error != N_DATADDR(ex)) {
send_sig(SIGKILL, current, 0);
return error;
-/* $Id: sys_sparc32.c,v 1.151 2000/06/22 11:42:25 davem Exp $
+/* $Id: sys_sparc32.c,v 1.152 2000/06/22 17:44:47 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -3778,8+3778,6 @@ static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res return copy_to_user(res32, kres, sizeof(*res32));
}
-extern asmlinkage int sys_nfsservctl(int cmd, void *arg, void *resp);
-
int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
{
struct nfsctl_arg *karg = NULL;
* driver, you'll probably need the Compaq Array Controller Interface
* Specificiation (Document number ECG086/1198)
*/
-#include <linux/config.h>
+#include <linux/config.h> /* CONFIG_PROC_FS */
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq SMART2 Driver (v 1.0.4)"
-#define DRIVER_VERSION SMART2_DRIVER_VERSION(1,0,4)
+#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.0)"
+#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,0)
#define MAJOR_NR COMPAQ_SMART2_MAJOR
#include <linux/blk.h>
#include <linux/blkdev.h>
@@ -73,7+73,7 @@ static int eisa[8] = { 0, 0 ,0 ,0, 0, 0 ,0 ,0 }; * product = Marketing Name for the board
* access = Address of the struct of function pointers
*/
-struct board_type products[] = {
+static struct board_type products[] = {
{ 0x0040110E, "IDA", &smart1_access },
{ 0x0140110E, "IDA-2", &smart1_access },
{ 0x1040110E, "IAES", &smart1_access },
@@ -87,6+87,7 @@ struct board_type products[] = { { 0x40400E11, "Integrated Array", &smart4_access },
{ 0x40500E11, "Smart Array 4200", &smart4_access },
{ 0x40510E11, "Smart Array 4250ES", &smart4_access },
+ { 0x40580E11, "Smart Array 431", &smart4_access },
};
static struct hd_struct * ida;
@@ -95,7+96,7 @@ static int * ida_blocksizes; static int * ida_hardsizes;
static struct gendisk ida_gendisk[MAX_CTLR];
-struct proc_dir_entry *proc_array = NULL;
+static struct proc_dir_entry *proc_array = NULL;
/* Debug... */
#define DBG(s) do { s } while(0)
@@ -106,7+107,7 @@ struct proc_dir_entry *proc_array = NULL; /* Debug Extra Paranoid... */
#define DBGPX(s) do { } while(0)
-void cpqarray_init(void);
+int cpqarray_init(void);
static int cpqarray_pci_detect(void);
static int cpqarray_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn);
static ulong remap_pci_mem(ulong base, ulong size);
@@ -312,9+313,8 @@ EXPORT_NO_SYMBOLS; /* This is a bit of a hack... */
int __init init_module(void)
{
- cpqarray_init();
- if (nr_ctlr == 0)
- return -EIO;
+ if (cpqarray_init() == 0) /* all the block dev numbers already used */
+ return -EIO; /* or no controllers were found */
return 0;
}
@@ -357,8+357,9 @@ void cleanup_module(void) /*
* This is it. Find all the controllers and register them. I really hate
* stealing all these major device numbers.
+ * returns the number of block devices registered.
*/
-void __init cpqarray_init(void)
+int __init cpqarray_init(void)
{
void (*request_fns[MAX_CTLR])(request_queue_t *) = {
do_ida_request0, do_ida_request1,
@@ -367,31+368,52 @@ void __init cpqarray_init(void) do_ida_request6, do_ida_request7,
};
int i,j;
+ int num_cntlrs_reg = 0;
/* detect controllers */
cpqarray_pci_detect();
cpqarray_eisa_detect();
if (nr_ctlr == 0)
- return;
+ return(num_cntlrs_reg);
printk(DRIVER_NAME "\n");
printk("Found %d controller(s)\n", nr_ctlr);
/* allocate space for disk structs */
ida = kmalloc(sizeof(struct hd_struct)*nr_ctlr*NWD*16, GFP_KERNEL);
-
if(ida==NULL)
- goto bail;
- ida_sizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
+ {
+ printk( KERN_ERR "cpqarray: out of memory");
+ return(num_cntlrs_reg);
+ }
+
+ ida_sizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
if(ida_sizes==NULL)
- goto bail2;
+ {
+ kfree(ida);
+ printk( KERN_ERR "cpqarray: out of memory");
+ return(num_cntlrs_reg);
+ }
+
ida_blocksizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
if(ida_blocksizes==NULL)
- goto bail3;
- ida_hardsizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
+ {
+ kfree(ida);
+ kfree(ida_sizes);
+ printk( KERN_ERR "cpqarray: out of memory");
+ return(num_cntlrs_reg);
+ }
+
+ ida_hardsizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
if(ida_hardsizes==NULL)
- goto bail4;
+ {
+ kfree(ida);
+ kfree(ida_sizes);
+ kfree(ida_blocksizes);
+ printk( KERN_ERR "cpqarray: out of memory");
+ return(num_cntlrs_reg);
+ }
memset(ida, 0, sizeof(struct hd_struct)*nr_ctlr*NWD*16);
memset(ida_sizes, 0, sizeof(int)*nr_ctlr*NWD*16);
@@ -399,74+421,90 @@ void __init cpqarray_init(void) memset(ida_hardsizes, 0, sizeof(int)*nr_ctlr*NWD*16);
memset(ida_gendisk, 0, sizeof(struct gendisk)*MAX_CTLR);
- /*
+ /*
* register block devices
* Find disks and fill in structs
* Get an interrupt, set the Q depth and get into /proc
*/
for(i=0; i< nr_ctlr; i++) {
+ /* If this successful it should insure that we are the only */
+ /* instance of the driver */
+ if (register_blkdev(MAJOR_NR+i, hba[i]->devname, &ida_fops)) {
+ printk(KERN_ERR "cpqarray: Unable to get major number %d for ida\n",
+ MAJOR_NR+i);
+ continue;
+ }
+
+
hba[i]->access.set_intr_mask(hba[i], 0);
if (request_irq(hba[i]->intr, do_ida_intr,
SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) {
- printk("Unable to get irq %d for %s\n",
+ printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n",
hba[i]->intr, hba[i]->devname);
+ unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
continue;
}
- if (register_blkdev(MAJOR_NR+i, hba[i]->devname, &ida_fops)) {
- printk("Unable to get major number %d for ida\n",
- MAJOR_NR+i);
- continue;
- }
-
+ num_cntlrs_reg++;
hba[i]->cmd_pool = (cmdlist_t *)kmalloc(
NR_CMDS * sizeof(cmdlist_t), GFP_KERNEL);
hba[i]->cmd_pool_bits = (__u32*)kmalloc(
((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
- if(hba[i]->cmd_pool_bits == NULL || hba[i]->cmd_pool == NULL)
+ if(hba[i]->cmd_pool_bits == NULL || hba[i]->cmd_pool == NULL)
{
- int j;
+ nr_ctlr = i;
if(hba[i]->cmd_pool_bits)
kfree(hba[i]->cmd_pool_bits);
if(hba[i]->cmd_pool)
kfree(hba[i]->cmd_pool);
- for(j=0;i<i;j++)
- {
- free_irq(hba[j]->intr, hba[j]);
- unregister_blkdev(MAJOR_NR+j, hba[j]->devname);
- kfree(hba[j]->cmd_pool_bits);
- kfree(hba[j]->cmd_pool);
- }
free_irq(hba[i]->intr, hba[i]);
unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
- goto bail5;
+ num_cntlrs_reg--;
+ printk( KERN_ERR "cpqarray: out of memory");
+
+ /* If num_cntlrs_reg == 0, no controllers worked.
+ * init_module will fail, so clean up global
+ * memory that clean_module would do.
+ */
+
+ if (num_cntlrs_reg == 0)
+ {
+ kfree(ida);
+ kfree(ida_sizes);
+ kfree(ida_hardsizes);
+ kfree(ida_blocksizes);
+ }
+ return(num_cntlrs_reg);
+
}
memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t));
memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32));
- printk("Finding drives on %s", hba[i]->devname);
+ printk(KERN_INFO "cpqarray: Finding drives on %s",
+ hba[i]->devname);
getgeometry(i);
start_fwbk(i);
hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
+
ida_procinit(i);
-
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i), request_fns[i]);
- blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 0);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i),
+ request_fns[i]);
+ blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 0);
blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256);
hardsect_size[MAJOR_NR+i] = ida_hardsizes + (i*256);
-
read_ahead[MAJOR_NR+i] = READ_AHEAD;
+
ida_gendisk[i].major = MAJOR_NR + i;
ida_gendisk[i].major_name = "ida";
ida_gendisk[i].minor_shift = NWD_SHIFT;
ida_gendisk[i].max_p = 16;
ida_gendisk[i].part = ida + (i*256);
ida_gendisk[i].sizes = ida_sizes + (i*256);
- /* ida_gendisk[i].nr_real is handled by getgeometry */
-
+ ida_gendisk[i].nr_real = 0;
+
/* Get on the disk list */
ida_gendisk[i].next = gendisk_head;
gendisk_head = &ida_gendisk[i];
@@ -479,21+517,13 @@ void __init cpqarray_init(void)
ida_geninit(i);
for(j=0; j<NWD; j++)
- register_disk(&ida_gendisk[i], MKDEV(MAJOR_NR+i,j<<4),
- 16, &ida_fops, hba[i]->drv[j].nr_blks);
+ register_disk(&ida_gendisk[i],
+ MKDEV(MAJOR_NR+i,j<<4),
+ 16, &ida_fops, hba[i]->drv[j].nr_blks);
+
}
/* done ! */
- return;
-bail5:
- kfree(ida_hardsizes);
-bail4:
- kfree(ida_blocksizes);
-bail3:
- kfree(ida_sizes);
-bail2:
- kfree(ida);
-bail:
- printk(KERN_ERR "cpqarray: out of memory.\n");
+ return(num_cntlrs_reg);
}
/*
@@ -506,103+536,68 @@ static int cpqarray_pci_detect(void) {
int index;
unchar bus=0, dev_fn=0;
-
- /* This seems dumb, surely we could use an array of types to match ?? */
-
- for(index=0; ; index++) {
- if (pcibios_find_device(PCI_VENDOR_ID_DEC,
- PCI_DEVICE_ID_COMPAQ_42XX, index, &bus, &dev_fn))
- break;
- printk(KERN_DEBUG "42XX Device has been found at %x %x\n",
- bus, dev_fn);
- if (index == 1000000) break;
- if (nr_ctlr == 8) {
- printk("This driver supports a maximum of "
- "8 controllers.\n");
- break;
- }
-
- hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
- if(hba[nr_ctlr]==NULL)
- {
- printk(KERN_ERR "cpqarray: out of memory.\n");
- continue;
- }
- memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
- if (cpqarray_pci_init(hba[nr_ctlr], bus, dev_fn) != 0)
- continue;
- sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
- hba[nr_ctlr]->ctlr = nr_ctlr;
- nr_ctlr++;
- }
-
- for(index=0; ; index++) {
- unsigned short subvendor=0;
- if (pcibios_find_device(PCI_VENDOR_ID_NCR,
- PCI_DEVICE_ID_NCR_53C1510, index, &bus, &dev_fn))
- break;
- printk(KERN_DEBUG "Integrated RAID Chip has been found at %x %x\n",
- bus, dev_fn);
- if(pcibios_read_config_word(bus, dev_fn,
- PCI_SUBSYSTEM_VENDOR_ID, &subvendor))
- {
- printk(KERN_DEBUG "cpqarray failed to read subvendor\n");
- break;
- }
- if(subvendor != PCI_VENDOR_ID_COMPAQ)
- break;
- printk(KERN_DEBUG "Its a compaq RAID Chip\n");
- if (index == 1000000) break;
- if (nr_ctlr == 8) {
- printk("This driver supports a maximum of "
- "8 controllers.\n");
- break;
- }
+#define IDA_BOARD_TYPES 3
+ static int ida_vendor_id[IDA_BOARD_TYPES] = { PCI_VENDOR_ID_DEC,
+ PCI_VENDOR_ID_NCR, PCI_VENDOR_ID_COMPAQ };
+ static int ida_device_id[IDA_BOARD_TYPES] = { PCI_DEVICE_ID_COMPAQ_42XX, PCI_DEVICE_ID_NCR_53C1510, PCI_DEVICE_ID_COMPAQ_SMART2P };
+ int brdtype;
+
+ /* search for all PCI board types that could be for this driver */
+ for(brdtype=0; brdtype<IDA_BOARD_TYPES; brdtype++)
+ {
+ for(index=0; ; index++) {
+ if (pcibios_find_device(ida_vendor_id[brdtype],
+ ida_device_id[brdtype], index, &bus, &dev_fn))
+ break;
+ printk(KERN_DEBUG "cpqarray: Device %x has been found at %x %x\n",
+ ida_vendor_id[brdtype], bus, dev_fn);
+ if (index == 1000000) break;
+ if (nr_ctlr == 8) {
+ printk(KERN_WARNING "cpqarray: This driver"
+ " supports a maximum of 8 controllers.\n");
+ break;
+ }
- hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
- if(hba[nr_ctlr]==NULL)
- {
- printk(KERN_ERR "cpqarray: out of memory.\n");
- continue;
- }
- memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
- /* DOESNT THIS LEAK MEMORY ?????? - AC */
- if (cpqarray_pci_init(hba[nr_ctlr], bus, dev_fn) != 0)
- continue;
- sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
- hba[nr_ctlr]->ctlr = nr_ctlr;
- nr_ctlr++;
- }
+/* if it is a PCI_DEVICE_ID_NCR_53C1510, make sure it's the Compaq version of the chip */
+
+ if (ida_device_id[brdtype] == PCI_DEVICE_ID_NCR_53C1510) {
+ unsigned short subvendor=0;
+ if(pcibios_read_config_word(bus, dev_fn,
+ PCI_SUBSYSTEM_VENDOR_ID, &subvendor))
+ {
+ printk(KERN_DEBUG "cpqarray: failed to read subvendor\n");
+ continue;
+ }
+ if(subvendor != PCI_VENDOR_ID_COMPAQ)
+ {
+ printk(KERN_DEBUG
+ "cpqarray: not a Compaq integrated array controller\n");
+ continue;
+ }
+ }
- for(index=0; ; index++) {
- if (pcibios_find_device(PCI_VENDOR_ID_COMPAQ,
- PCI_DEVICE_ID_COMPAQ_SMART2P, index, &bus, &dev_fn))
- break;
+ hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL); if(hba[nr_ctlr]==NULL)
+ {
+ printk(KERN_ERR "cpqarray: out of memory.\n");
+ continue;
+ }
+ memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
+ if (cpqarray_pci_init(hba[nr_ctlr], bus, dev_fn) != 0)
+ {
+ kfree(hba[nr_ctlr]);
+ continue;
+ }
+ sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
+ hba[nr_ctlr]->ctlr = nr_ctlr;
+ nr_ctlr++;
- if (index == 1000000) break;
- if (nr_ctlr == 8) {
- printk("This driver supports a maximum of "
- "8 controllers.\n");
- break;
}
-
- hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
- if(hba[nr_ctlr]==NULL)
- {
- printk(KERN_ERR "cpqarray: out of memory.\n");
- continue;
- }
- memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
- if (cpqarray_pci_init(hba[nr_ctlr], bus, dev_fn) != 0)
- continue;
- sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
- hba[nr_ctlr]->ctlr = nr_ctlr;
- nr_ctlr++;
}
return nr_ctlr;
}
+
/*
* Find the IO address of the controller, its IRQ and so forth. Fill
* in some basic stuff into the ctlr_info_t structure.
@@ -671,8+666,9 @@ DBGINFO( }
}
if (i == NR_PRODUCTS) {
- printk("Sorry, I don't know how to access the SMART Array"
- " controller %08lx\n", (unsigned long)board_id);
+ printk(KERN_WARNING "cpqarray: Sorry, I don't know how"
+ " to access the SMART Array controller %08lx\n",
+ (unsigned long)board_id);
return -1;
}
@@ -734,8+730,8 @@ static int cpqarray_eisa_detect(void)
while(i<8 && eisa[i]) {
if (nr_ctlr == 8) {
- printk("This driver supports a maximum of "
- "8 controllers.\n");
+ printk(KERN_WARNING "cpqarray: This driver supports"
+ " a maximum of 8 controllers.\n");
break;
}
board_id = inl(eisa[i]+0xC80);
@@ -744,11+740,11 @@ static int cpqarray_eisa_detect(void) break;
if (j == NR_PRODUCTS) {
- printk("Sorry, I don't know how to access the SMART"
- " Array controller %08lx\n", (unsigned long)board_id);
+ printk(KERN_WARNING "cpqarray: Sorry, I don't know how"
+ " to access the SMART Array controller %08lx\n", (unsigned long)board_id);
continue;
}
- hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+ hba[nr_ctlr] = (ctlr_info_t *) kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
if(hba[nr_ctlr]==NULL)
{
printk(KERN_ERR "cpqarray: out of memory.\n");
@@ -885,21+881,34 @@ static void do_ida_request(int ctlr) queue_head = &blk_dev[MAJOR_NR+ctlr].request_queue.queue_head;
if (list_empty(queue_head))
- goto doreq_done;
+ {
+ start_io(h);
+ return;
+ }
+
creq = blkdev_entry_next_request(queue_head);
if (creq->rq_status == RQ_INACTIVE)
- goto doreq_done;
+ {
+ start_io(h);
+ return;
+ }
+
if (ctlr != MAJOR(creq->rq_dev)-MAJOR_NR ||
- ctlr > nr_ctlr || h == NULL) {
+ ctlr > nr_ctlr || h == NULL)
+ {
printk("doreq cmd for %d, %x at %p\n",
ctlr, creq->rq_dev, creq);
complete_buffers(creq->bh, 0);
- goto doreq_done;
+ start_io(h);
+ return;
}
if ((c = cmd_alloc(h)) == NULL)
- goto doreq_done;
+ {
+ start_io(h);
+ return;
+ }
bh = creq->bh;
@@ -972,9+981,9 @@ DBGPX( printk("Done with %p\n", creq); ); /* Put the request on the tail of the request queue */
addQ(&h->reqQ, c);
h->Qdepth++;
- if (h->Qdepth > h->maxQsinceinit) h->maxQsinceinit = h->Qdepth;
+ if (h->Qdepth > h->maxQsinceinit)
+ h->maxQsinceinit = h->Qdepth;
-doreq_done:
start_io(h);
}
@@ -1022,28+1031,24 @@ static inline void complete_buffers(struct buffer_head *bh, int ok) */
static inline void complete_command(cmdlist_t *cmd, int timeout)
{
- char buf[80];
int ok=1;
if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
(hba[cmd->ctlr]->misc_tflags & MISC_NONFATAL_WARN) == 0) {
- sprintf(buf, "Non Fatal error on ida/c%dd%d\n",
+ printk(KERN_WARNING "Non Fatal error on ida/c%dd%d\n",
cmd->ctlr, cmd->hdr.unit);
- console_print(buf);
hba[cmd->ctlr]->misc_tflags |= MISC_NONFATAL_WARN;
}
if (cmd->req.hdr.rcode & RCODE_FATAL) {
- sprintf(buf, "Fatal error on ida/c%dd%d\n",
+ printk(KERN_WARNING "Fatal error on ida/c%dd%d\n",
cmd->ctlr, cmd->hdr.unit);
- console_print(buf);
ok = 0;
}
if (cmd->req.hdr.rcode & RCODE_INVREQ) {
- sprintf(buf, "Invalid request on ida/c%dd%d = (cmd=%x sect=%d cnt=%d sg=%d ret=%x)\n",
+ printk(KERN_WARNING "Invalid request on ida/c%dd%d = (cmd=%x sect=%d cnt=%d sg=%d ret=%x)\n",
cmd->ctlr, cmd->hdr.unit, cmd->req.hdr.cmd,
cmd->req.hdr.blk, cmd->req.hdr.blk_cnt,
cmd->req.hdr.sg_cnt, cmd->req.hdr.rcode);
- console_print(buf);
ok = 0;
}
if (timeout) ok = 0;
@@ -1077,10+1082,15 @@ static void do_ida_intr(int irq, void *dev_id, struct pt_regs *regs) if (istat & FIFO_NOT_EMPTY) {
while((a = h->access.command_completed(h))) {
a1 = a; a &= ~3;
- if ((c = h->cmpQ) == NULL) goto bad_completion;
+ if ((c = h->cmpQ) == NULL)
+ {
+ printk(KERN_WARNING "cpqarray: Completion of %08lx ignored\n", (unsigned long)a1);
+ continue;
+ }
while(c->busaddr != a) {
c = c->next;
- if (c == h->cmpQ) break;
+ if (c == h->cmpQ)
+ break;
}
/*
* If we've found the command, take it off the
@@ -1096,8+1106,6 @@ static void do_ida_intr(int irq, void *dev_id, struct pt_regs *regs) }
continue;
}
-bad_completion:
- printk("Completion of %08lx ignored\n", (unsigned long)a1);
}
}
@@ -1227,16+1235,27 @@ static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io) switch(io->cmd) {
case PASSTHRU_A:
p = kmalloc(io->sg[0].size, GFP_KERNEL);
- if (!p) { error = -ENOMEM; goto ioctl_err_exit; }
+ if (!p)
+ {
+ error = -ENOMEM;
+ cmd_free(NULL, c);
+ return(error);
+ }
copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
- c->req.bp = virt_to_bus(&(io->c));
+ c->req.hdr.blk = virt_to_bus(&(io->c));
c->req.sg[0].size = io->sg[0].size;
c->req.sg[0].addr = virt_to_bus(p);
c->req.hdr.sg_cnt = 1;
break;
case IDA_READ:
p = kmalloc(io->sg[0].size, GFP_KERNEL);
- if (!p) { error = -ENOMEM; goto ioctl_err_exit; }
+ if (!p)
+ {
+ error = -ENOMEM;
+ cmd_free(NULL, c);
+ return(error);
+ }
+
c->req.sg[0].size = io->sg[0].size;
c->req.sg[0].addr = virt_to_bus(p);
c->req.hdr.sg_cnt = 1;
@@ -1245,7+1264,12 @@ static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io) case IDA_WRITE_MEDIA:
case DIAG_PASS_THRU:
p = kmalloc(io->sg[0].size, GFP_KERNEL);
- if (!p) { error = -ENOMEM; goto ioctl_err_exit; }
+ if (!p)
+ {
+ error = -ENOMEM;
+ cmd_free(NULL, c);
+ return(error);
+ }
copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
c->req.sg[0].size = io->sg[0].size;
c->req.sg[0].addr = virt_to_bus(p);
@@ -1284,10+1308,8 @@ static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io) }
io->rcode = c->req.hdr.rcode;
- error = 0;
-ioctl_err_exit:
cmd_free(NULL, c);
- return error;
+ return(0);
}
/*
@@ -1390,8+1412,8 @@ static int sendcmd( }
udelay(10);
DBG(
- printk("ida%d: idaSendPciCmd FIFO full, waiting!\n",
- ctlr);
+ printk(KERN_WARNING "cpqarray ida%d: idaSendPciCmd FIFO full,"
+ " waiting!\n", ctlr);
);
}
/*
complete = pollcomplete(ctlr);
if (complete != 1) {
if (complete != c->busaddr) {
- printk(
- "ida%d: idaSendPciCmd "
+ printk( KERN_WARNING
+ "cpqarray ida%d: idaSendPciCmd "
"Invalid command list address returned! (%08lx)\n",
ctlr, (unsigned long)complete);
cmd_free(info_p, c);
return (IO_ERROR);
}
} else {
- printk(
- "ida%d: idaSendPciCmd Timeout out, "
+ printk( KERN_WARNING
+ "cpqarray ida%d: idaSendPciCmd Timeout out, "
"No command list address returned!\n",
ctlr);
cmd_free(info_p, c);
if (c->req.hdr.rcode & 0x00FE) {
if (!(c->req.hdr.rcode & BIG_PROBLEM)) {
- printk(
- "ida%d: idaSendPciCmd, error: Controller failed "
- "at init time "
+ printk( KERN_WARNING
+ "cpqarray ida%d: idaSendPciCmd, error: "
+ "Controller failed at init time "
"cmd: 0x%x, return code = 0x%x\n",
ctlr, c->req.hdr.cmd, c->req.hdr.rcode);
@@ -1461,8+1483,8 @@ static int revalidate_allvol(kdev_t dev) spin_lock_irqsave(&io_request_lock, flags);
if (hba[ctlr]->usage_count > 1) {
spin_unlock_irqrestore(&io_request_lock, flags);
- printk("Device busy for volume revalidation (usage=%d)\n",
- hba[ctlr]->usage_count);
+ printk(KERN_WARNING "cpqarray: Device busy for volume"
+ " revalidation (usage=%d)\n", hba[ctlr]->usage_count);
return -EBUSY;
}
spin_unlock_irqrestore(&io_request_lock, flags);
@@ -1514,8+1536,9 @@ static int revalidate_logvol(kdev_t dev, int maxusage) spin_lock_irqsave(&io_request_lock, flags);
if (hba[ctlr]->drv[target].usage_count > maxusage) {
spin_unlock_irqrestore(&io_request_lock, flags);
- printk("Device busy for revalidation (usage=%d)\n",
- hba[ctlr]->drv[target].usage_count);
+ printk(KERN_WARNING "cpqarray: Device busy for "
+ "revalidation (usage=%d)\n",
+ hba[ctlr]->drv[target].usage_count);
return -EBUSY;
}
@@ -1581,22+1604,28 @@ static void start_fwbk(int ctlr) id_ctlr_t *id_ctlr_buf;
int ret_code;
- if( hba[ctlr]->board_id != 0x40400E11)
+ if( (hba[ctlr]->board_id != 0x40400E11)
+ && (hba[ctlr]->board_id != 0x40480E11) )
+
/* Not a Integrated Raid, so there is nothing for us to do */
return;
- printk(KERN_DEBUG "Starting firmware's background processing\n");
+ printk(KERN_DEBUG "cpqarray: Starting firmware's background"
+ " processing\n");
/* Command does not return anything, but idasend command needs a
buffer */
id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
if(id_ctlr_buf==NULL)
{
- printk(KERN_WARNING "Out of memory. Unable to start background processing.\n");
+ printk(KERN_WARNING "cpqarray: Out of memory. "
+ "Unable to start background processing.\n");
return;
}
ret_code = sendcmd(RESUME_BACKGROUND_ACTIVITY, ctlr,
id_ctlr_buf, 0, 0, 0, 0);
if(ret_code != IO_OK)
- printk(KERN_WARNING "Unable to start background processing\n");
+ printk(KERN_WARNING "cpqarray: Unable to start"
+ " background processing\n");
+
kfree(id_ctlr_buf);
}
/*****************************************************************
@@ -1620,16+1649,38 @@ static void getgeometry(int ctlr)
id_ldrive = (id_log_drv_t *)kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
if(id_ldrive == NULL)
+ {
+ printk( KERN_ERR "cpqarray: out of memory.\n");
return;
+ }
+
id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
if(id_ctlr_buf == NULL)
- goto bail2;
+ {
+ kfree(id_ldrive);
+ printk( KERN_ERR "cpqarray: out of memory.\n");
+ return;
+ }
+
id_lstatus_buf = (sense_log_drv_stat_t *)kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
if(id_lstatus_buf == NULL)
- goto bail3;
+ {
+ kfree(id_ctlr_buf);
+ kfree(id_ldrive);
+ printk( KERN_ERR "cpqarray: out of memory.\n");
+ return;
+ }
+
sense_config_buf = (config_t *)kmalloc(sizeof(config_t), GFP_KERNEL);
if(sense_config_buf == NULL)
- goto bail4;
+ {
+ kfree(id_lstatus_buf);
+ kfree(id_ctlr_buf);
+ kfree(id_ldrive);
+ printk( KERN_ERR "cpqarray: out of memory.\n");
+ return;
+ }
+
memset(id_ldrive, 0, sizeof(id_log_drv_t));
memset(id_ctlr_buf, 0, sizeof(id_ctlr_t));
memset(id_lstatus_buf, 0, sizeof(sense_log_drv_stat_t));
@@ -1648,8+1699,15 @@ static void getgeometry(int ctlr) * so the idastubopen will fail on all logical drives
* on the controller.
*/
- goto geo_ret; /* release the buf and return */
- }
+ /* Free all the buffers and return */
+ printk(KERN_ERR "cpqarray: error sending ID controller\n");
+ kfree(sense_config_buf);
+ kfree(id_lstatus_buf);
+ kfree(id_ctlr_buf);
+ kfree(id_ldrive);
+ return;
+ }
+
info_p->log_drives = id_ctlr_buf->nr_drvs;;
*(__u32*)(info_p->firm_rev) = *(__u32*)(id_ctlr_buf->firm_rev);
info_p->ctlr_sig = id_ctlr_buf->cfg_sig;
@@ -1663,8+1721,9 @@ static void getgeometry(int ctlr) * Get drive geometry for all logical drives
*/
if (id_ctlr_buf->nr_drvs > 16)
- printk("ida%d: This driver supports 16 logical drives "
- "per controller.\n. Additional drives will not be "
+ printk(KERN_WARNING "cpqarray ida%d: This driver supports "
+ "16 logical drives per controller.\n. "
+ " Additional drives will not be "
"detected\n", ctlr);
for (log_unit = 0;
@@ -1687,13+1746,17 @@ static void getgeometry(int ctlr) on the controller.
*/
info_p->log_drv_map = 0;
- printk(
- "ida%d: idaGetGeometry - Controller failed "
- "to report status of logical drive %d\n"
+ printk( KERN_WARNING
+ "cpqarray ida%d: idaGetGeometry - Controller"
+ " failed to report status of logical drive %d\n"
"Access to this controller has been disabled\n",
ctlr, log_unit);
- goto geo_ret; /* release the buf and return */
-
+ /* Free all the buffers and return */
+ kfree(sense_config_buf);
+ kfree(id_lstatus_buf);
+ kfree(id_ctlr_buf);
+ kfree(id_ldrive);
+ return;
}
/*
Make sure the logical drive is configured
@@ -1715,14+1778,21 @@ static void getgeometry(int ctlr) drv->sectors = id_ldrive->drv.sect_per_track;
info_p->log_drv_map |= (1 << log_unit);
- printk("ida/c%dd%d: blksz=%d nr_blks=%d\n",
+ printk(KERN_INFO "cpqarray ida/c%dd%d: blksz=%d nr_blks=%d\n",
ctlr, log_unit, drv->blk_size, drv->nr_blks);
ret_code = sendcmd(SENSE_CONFIG,
ctlr, sense_config_buf,
sizeof(config_t), 0, 0, log_unit);
if (ret_code == IO_ERROR) {
info_p->log_drv_map = 0;
- goto geo_ret; /* release the buf and return */
+ /* Free all the buffers and return */
+ printk(KERN_ERR "cpqarray: error sending sense config\n");
+ kfree(sense_config_buf);
+ kfree(id_lstatus_buf);
+ kfree(id_ctlr_buf);
+ kfree(id_ldrive);
+ return;
+
}
info_p->phys_drives =
sense_config_buf->ctlr_phys_drv;
@@ -1736,12+1806,10 @@ static void getgeometry(int ctlr) log_index = log_index + 1;
} /* end of if logical drive configured */
} /* end of for log_unit */
-geo_ret:
kfree(sense_config_buf);
-bail4:
- kfree(id_ldrive);
-bail3:
- kfree(id_lstatus_buf);
-bail2:
+ kfree(id_ldrive);
+ kfree(id_lstatus_buf);
kfree(id_ctlr_buf);
+ return;
+
}
@@ -191,7+191,7 @@ typedef struct { __u8 expn_fail;
__u8 unit_flags;
__u16 big_fail_map[8];
- __u16 big_remap_map[8];
+ __u16 big_remap_map[128];
__u16 big_repl_map[8];
__u16 big_act_spare_map[8];
__u8 big_spar_repl_map[128];
@@ -336,7+336,7 @@ typedef struct { __u32 sense_info;
__u8 sense_code;
__u8 sense_qual;
- __u8 residual;
+ __u32 residual;
__u8 reserved[4];
__u8 cdb[12];
} scsi_param_t;
@@ -62,13+62,14 @@ static void smart4_intr_mask(ctlr_info_t *h, unsigned long val) }
/*
- * For this card fifo is full if reading this port returns 0!
+ * For older cards FIFO Full = 0.
+ * On this card 0 means there is room, anything else FIFO Full.
*
*/
static unsigned long smart4_fifo_full(ctlr_info_t *h)
{
- return (~readl(h->vaddr + S42XX_REQUEST_PORT_OFFSET));
+ return (!readl(h->vaddr + S42XX_REQUEST_PORT_OFFSET));
}
/* This type of controller returns -1 if the fifo is empty,
@@ -81,7+82,7 @@ static unsigned long smart4_completed(ctlr_info_t *h) = readl(h->vaddr + S42XX_REPLY_PORT_OFFSET);
/* Fifo is empty */
- if( register_value == -1)
+ if( register_value == 0xffffffff)
return 0;
/* Need to let it know we got the reply */
@@ -197,7+197,7 @@ endmenu
bool 'FDDI driver support' CONFIG_FDDI
if [ "$CONFIG_FDDI" = "y" ]; then
- dep_tristate ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX $CONFIG_FDDI
+ tristate ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX
tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP
fi
@@ -74,14+74,14 @@ comment 'USB HID' if [ "$CONFIG_INPUT_IFORCE_USB" != "n" ]; then
define_tristate CONFIG_INPUT_IFORCE $CONFIG_INPUT_IFORCE_USB
fi
- dep_tristate ' Keyboard support' CONFIG_INPUT_KEYBDEV
- dep_tristate ' Mouse support' CONFIG_INPUT_MOUSEDEV
+ dep_tristate ' Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_USB
+ dep_tristate ' Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_USB
if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
int ' Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
int ' Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768
fi
- dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV
- dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV
+ dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_USB
+ dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_USB
fi
endmenu
@@ -1044,7+1044,7 @@ static int proc_ioctl (struct dev_state *ps, void *arg) kfree (buf);
return -EFAULT;
} else
- memset (arg, size, 0);
+ memset (arg, 0, size);
}
/* ioctl to device */
/*
- * $Id: evdev.c,v 1.8 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: evdev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $
*
* Copyright (c) 1999-2000 Vojtech Pavlik
*
#include <linux/input.h>
struct evdev {
- int used;
+ int exist;
int open;
int minor;
struct input_handle handle;
@@ -99,13+99,14 @@ static int evdev_release(struct inode * inode, struct file * file) listptr = &((*listptr)->next);
*listptr = (*listptr)->next;
- if (!--list->evdev->open)
- input_close_device(&list->evdev->handle);
-
- if (!--list->evdev->used) {
- input_unregister_minor(list->evdev->devfs);
- evdev_table[list->evdev->minor] = NULL;
- kfree(list->evdev);
+ if (!--list->evdev->open) {
+ if (list->evdev->exist) {
+ input_close_device(&list->evdev->handle);
+ } else {
+ input_unregister_minor(list->evdev->devfs);
+ evdev_table[list->evdev->minor] = NULL;
+ kfree(list->evdev);
+ }
}
kfree(list);
@@ -121,9+122,8 @@ static int evdev_open(struct inode * inode, struct file * file) if (i > EVDEV_MINORS || !evdev_table[i])
return -ENODEV;
- if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) {
+ if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
return -ENOMEM;
- }
memset(list, 0, sizeof(struct evdev_list));
list->evdev = evdev_table[i];
@@ -132,10+132,9 @@ static int evdev_open(struct inode * inode, struct file * file)
file->private_data = list;
- list->evdev->used++;
-
if (!list->evdev->open++)
- input_open_device(&list->evdev->handle);
+ if (list->evdev->exist)
+ input_open_device(&list->evdev->handle);
return 0;
}
@@ -303,7+302,7 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct evdev->handle.handler = handler;
evdev->handle.private = evdev;
- evdev->used = 1;
+ evdev->exist = 1;
evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
@@ -316,10+315,11 @@ static void evdev_disconnect(struct input_handle *handle) {
struct evdev *evdev = handle->private;
- if (evdev->open)
- input_close_device(handle);
+ evdev->exist = 0;
- if (!--evdev->used) {
+ if (evdev->open) {
+ input_close_device(handle);
+ } else {
input_unregister_minor(evdev->devfs);
evdev_table[evdev->minor] = NULL;
kfree(evdev);
/*
- * $Id: joydev.c,v 1.7 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: joydev.c,v 1.11 2000/06/23 09:23:00 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
+ * Copyright (c) 1999-2000 Vojtech Pavlik
* Copyright (c) 1999 Colin Van Dyke
*
* Joystick device driver for the input driver suite.
#define JOYDEV_BUFFER_SIZE 64
struct joydev {
- int used;
+ int exist;
int open;
int minor;
struct input_handle handle;
@@ -66,6+66,7 @@ struct joydev { __u16 keypam[KEY_MAX - BTN_MISC];
__u8 absmap[ABS_MAX];
__u8 abspam[ABS_MAX];
+ __s16 abs[ABS_MAX];
};
struct joydev_list {
@@ -121,7+122,9 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne case EV_ABS:
event.type = JS_EVENT_AXIS;
event.number = joydev->absmap[code];
- event.value = joydev_correct(value, &joydev->corr[event.number]);
+ event.value = joydev_correct(value, joydev->corr + event.number);
+ if (event.value == joydev->abs[event.number]) return;
+ joydev->abs[event.number] = event.value;
break;
default:
@@ -165,13+168,14 @@ static int joydev_release(struct inode * inode, struct file * file) listptr = &((*listptr)->next);
*listptr = (*listptr)->next;
- if (!--list->joydev->open)
- input_close_device(&list->joydev->handle);
-
- if (!--list->joydev->used) {
- input_unregister_minor(list->joydev->devfs);
- joydev_table[list->joydev->minor] = NULL;
- kfree(list->joydev);
+ if (!--list->joydev->open) {
+ if (list->joydev->exist) {
+ input_close_device(&list->joydev->handle);
+ } else {
+ input_unregister_minor(list->joydev->devfs);
+ joydev_table[list->joydev->minor] = NULL;
+ kfree(list->joydev);
+ }
}
kfree(list);
@@ -187,9+191,8 @@ static int joydev_open(struct inode *inode, struct file *file) if (i > JOYDEV_MINORS || !joydev_table[i])
return -ENODEV;
- if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) {
+ if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
return -ENOMEM;
- }
memset(list, 0, sizeof(struct joydev_list));
list->joydev = joydev_table[i];
@@ -198,10+201,9 @@ static int joydev_open(struct inode *inode, struct file *file)
file->private_data = list;
- list->joydev->used++;
-
if (!list->joydev->open++)
- input_open_device(&list->joydev->handle);
+ if (list->joydev->exist)
+ input_open_device(&list->joydev->handle);
return 0;
}
@@ -228,8+230,8 @@ static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *p
data.buttons = ((joydev->nkey > 0 && test_bit(joydev->keypam[0], input->key)) ? 1 : 0) |
((joydev->nkey > 1 && test_bit(joydev->keypam[1], input->key)) ? 2 : 0);
- data.x = ((joydev_correct(input->abs[ABS_X], &joydev->corr[0]) / 256) + 128) >> joydev->glue.JS_CORR.x;
- data.y = ((joydev_correct(input->abs[ABS_Y], &joydev->corr[1]) / 256) + 128) >> joydev->glue.JS_CORR.y;
+ data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
+ data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
return -EFAULT;
@@ -274,13+276,12 @@ static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *p
if (list->startup < joydev->nkey) {
event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
- event.value = !!test_bit(joydev->keypam[list->startup], input->key);
event.number = list->startup;
+ event.value = !!test_bit(joydev->keypam[event.number], input->key);
} else {
event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
- event.value = joydev_correct(input->abs[joydev->abspam[list->startup - joydev->nkey]],
- &joydev->corr[list->startup - joydev->nkey]);
event.number = list->startup - joydev->nkey;
+ event.value = joydev->abs[event.number];
}
if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
@@ -407,7+408,7 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct joydev->handle.handler = handler;
joydev->handle.private = joydev;
- joydev->used = 1;
+ joydev->exist = 1;
for (i = 0; i < ABS_MAX; i++)
if (test_bit(i, dev->absbit)) {
@@ -442,6+443,8 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
joydev->corr[i].coef[2] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
+
+ joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
}
joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
@@ -455,10+458,11 @@ static void joydev_disconnect(struct input_handle *handle) {
struct joydev *joydev = handle->private;
- if (joydev->open)
- input_close_device(handle);
+ joydev->exist = 0;
- if (!--joydev->used) {
+ if (joydev->open) {
+ input_close_device(handle);
+ } else {
input_unregister_minor(joydev->devfs);
joydev_table[joydev->minor] = NULL;
kfree(joydev);
/*
- * $Id: mousedev.c,v 1.8 2000/05/28 17:31:36 vojtech Exp $
+ * $Id: mousedev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $
*
* Copyright (c) 1999-2000 Vojtech Pavlik
*
#endif
struct mousedev {
- int used;
+ int exist;
int open;
int minor;
wait_queue_head_t wait;
@@ -172,22+172,30 @@ static int mousedev_release(struct inode * inode, struct file * file) struct input_handle *handle = mousedev_handler.handle;
while (handle) {
struct mousedev *mousedev = handle->private;
- if (!mousedev->open)
- input_close_device(handle);
+ if (!mousedev->open) {
+ if (mousedev->exist) {
+ input_close_device(&mousedev->handle);
+ } else {
+ input_unregister_minor(mousedev->devfs);
+ mousedev_table[mousedev->minor] = NULL;
+ kfree(mousedev);
+ }
+ }
handle = handle->hnext;
}
} else {
- if (!mousedev_mix.open)
- input_close_device(&list->mousedev->handle);
+ if (!mousedev_mix.open) {
+ if (list->mousedev->exist) {
+ input_close_device(&list->mousedev->handle);
+ } else {
+ input_unregister_minor(list->mousedev->devfs);
+ mousedev_table[list->mousedev->minor] = NULL;
+ kfree(list->mousedev);
+ }
+ }
}
}
- if (!--list->mousedev->used) {
- input_unregister_minor(list->mousedev->devfs);
- mousedev_table[list->mousedev->minor] = NULL;
- kfree(list->mousedev);
- }
-
kfree(list);
return 0;
@@ -210,20+218,20 @@ static int mousedev_open(struct inode * inode, struct file * file) mousedev_table[i]->list = list;
file->private_data = list;
- list->mousedev->used++;
-
if (!list->mousedev->open++) {
if (list->mousedev->minor == MOUSEDEV_MIX) {
struct input_handle *handle = mousedev_handler.handle;
while (handle) {
struct mousedev *mousedev = handle->private;
if (!mousedev->open)
- input_open_device(handle);
+ if (mousedev->exist)
+ input_open_device(handle);
handle = handle->hnext;
}
} else {
- if (!mousedev_mix.open)
- input_open_device(&list->mousedev->handle);
+ if (!mousedev_mix.open)
+ if (list->mousedev->exist)
+ input_open_device(&list->mousedev->handle);
}
}
@@ -402,7+410,7 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru memset(mousedev, 0, sizeof(struct mousedev));
init_waitqueue_head(&mousedev->wait);
- mousedev->used = 1;
+ mousedev->exist = 1;
mousedev->minor = minor;
mousedev_table[minor] = mousedev;
@@ -424,10+432,13 @@ static void mousedev_disconnect(struct input_handle *handle) {
struct mousedev *mousedev = handle->private;
- if (mousedev->open || mousedev_mix.open)
- input_close_device(handle);
+ mousedev->exist = 0;
- if (!--mousedev->used) {
+ if (mousedev->open) {
+ input_close_device(handle);
+ } else {
+ if (mousedev_mix.open)
+ input_close_device(handle);
input_unregister_minor(mousedev->devfs);
mousedev_table[mousedev->minor] = NULL;
kfree(mousedev);
@@ -449,7+460,7 @@ static int __init mousedev_init(void) memset(&mousedev_mix, 0, sizeof(struct mousedev));
init_waitqueue_head(&mousedev_mix.wait);
mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
- mousedev_mix.used = 1;
+ mousedev_mix.exist = 1;
mousedev_mix.minor = MOUSEDEV_MIX;
mousedev_mix.devfs = input_register_minor("mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE);
/*
** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller
**
-** Copyright (R) 1999,2000 Petko Manolov - Petkan (petkan@spct.net)
+** Copyright (c) 1999,2000 Petko Manolov - Petkan (petkan@spct.net)
+**
**
-** Distribute under GPL version 2 or later.
+** ChangeLog:
+** .... Most of the time spend reading sources & docs.
+** v0.2.x First official release for the Linux kernel.
+** v0.3.0 Beutified and structured, some bugs fixed.
+** v0.3.x URBifying bulk requests and bugfixing. First relatively
+** stable release. Still can touch device's registers only
+** from top-halves.
+** v0.4.0 Control messages remained unurbified are now URBs.
+** Now we can touch the HW at any time.
*/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/usb.h>
-static const char *version = __FILE__ ": v0.3.14 2000/06/09 (C) 1999-2000 Petko Manolov (petkan@spct.net)\n";
+static const char *version = __FILE__ ": v0.4.0 2000/06/15 (C) 1999-2000 Petko Manolov (petkan@spct.net)\n";
#define PEGASUS_MTU 1500
@@ -24,17+50,39 @@ static const char *version = __FILE__ ": v0.3.14 2000/06/09 (C) 1999-2000 Petko #define SROM_WRITE 0x01
#define SROM_READ 0x02
#define PEGASUS_TX_TIMEOUT (HZ*5)
+#define PEGASUS_CTRL_TIMEOUT 1000
#define PEGASUS_RESET 1
#define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES)))
+enum pegasus_registers {
+ EthCtrl0 = 0,
+ EthCtrl1 = 1,
+ EthCtrl2 = 2,
+ EthID = 0x10,
+ EpromOffset = 0x20,
+ EpromData = 0x21, /* 0x21 low, 0x22 high byte */
+ EpromCtrl = 0x23,
+ PhyAddr = 0x25,
+ PhyData = 0x26, /* 0x26 low, 0x27 high byte */
+ PhyCtrl = 0x28,
+ UsbStst = 0x2a,
+ EthTxStat0 = 0x2b,
+ EthTxStat1 = 0x2c,
+ EthRxStat = 0x2d,
+ Gpio0 = 0x7e,
+ Gpio1 = 0x7f,
+};
+
+
struct pegasus {
struct usb_device *usb;
struct net_device *net;
struct net_device_stats stats;
int flags;
- spinlock_t pegasus_lock;
- struct urb rx_urb, tx_urb, intr_urb;
+ spinlock_t pegasus_lock, ctrl_lock;
+ struct urb rx_urb, tx_urb, intr_urb, ctrl_urb;
+ devrequest dr;
unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]);
unsigned char ALIGN(tx_buff[PEGASUS_MAX_MTU]);
unsigned char ALIGN(intr_buff[8]);
@@ -64,7+112,7 @@ static struct usb_eth_dev usb_dev_id[] = { {"D-Link DSB-650TX", 0x2001, 0x4001, NULL},
{"D-Link DSB-650TX", 0x2001, 0x4002, NULL},
{"D-Link DSB-650TX(PNA)", 0x2001, 0x4003, NULL},
- {"D-Link DU-10", 0x07b8, 0xabc1, NULL},
+ {"D-Link DU-E10", 0x07b8, 0xabc1, NULL},
{"D-Link DU-E100", 0x07b8, 0x4002, NULL},
{"Linksys USB100TX", 0x066b, 0x2203, NULL},
{"Linksys USB100TX", 0x066b, 0x2204, NULL},
@@ -78,23+126,120 @@ static struct usb_eth_dev usb_dev_id[] = { };
-#define pegasus_get_registers(dev, indx, size, data)\
- usb_control_msg(dev, usb_rcvctrlpipe(dev,0), 0xf0, 0xc0, 0, indx, data, size, HZ);
-#define pegasus_set_registers(dev, indx, size, data)\
- usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0xf1, 0x40, 0, indx, data, size, HZ);
-#define pegasus_set_register(dev, indx, value) \
- { __u8 __data = value; \
- usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0xf1, 0x40, __data, indx, &__data, 1, HZ);}
+
+static void pegasus_ctrl_end( urb_t *urb )
+{
+ if ( urb->status )
+ warn("ctrl_urb end status %d", urb->status);
+}
-static int pegasus_read_phy_word(struct usb_device *dev, __u8 index, __u16 *regdata)
+static int pegasus_ctrl_timeout( urb_t *ctrl_urb )
+{
+ int timeout=0;
+
+ while ( ctrl_urb->status == -EINPROGRESS ) {
+ if ( timeout++ < PEGASUS_CTRL_TIMEOUT ) {
+ udelay(100);
+ continue;
+ }
+ err("ctrl urb busy %d", ctrl_urb->status);
+ usb_unlink_urb( ctrl_urb );
+ return ctrl_urb->status;
+ }
+ return 0;
+}
+
+
+static int pegasus_get_registers( struct pegasus *pegasus, __u16 indx, __u16 size, void *data )
+{
+ int ret;
+
+
+ spin_lock( &pegasus->ctrl_lock );
+ pegasus->dr.requesttype = 0xc0;
+ pegasus->dr.request = 0xf0;
+ pegasus->dr.value = 0x0;
+ pegasus->dr.index = indx;
+ pegasus->dr.length = pegasus->ctrl_urb.transfer_buffer_length = size;
+
+ FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
+ usb_rcvctrlpipe(pegasus->usb,0), (char *)&pegasus->dr,
+ data, size, pegasus_ctrl_end, pegasus );
+
+ if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) )
+ err("BAD CTRLs %d", ret);
+ else
+ ret = pegasus_ctrl_timeout( &pegasus->ctrl_urb );
+
+ spin_unlock( &pegasus->ctrl_lock );
+
+ return ret;
+}
+
+
+static int pegasus_set_registers( struct pegasus *pegasus, __u16 indx, __u16 size, void *data )
+{
+ int ret;
+
+
+ spin_lock( &pegasus->ctrl_lock );
+ pegasus->dr.requesttype = 0x40;
+ pegasus->dr.request = 0xf1;
+ pegasus->dr.value = 0x0;
+ pegasus->dr.index = indx;
+ pegasus->dr.length = pegasus->ctrl_urb.transfer_buffer_length = size;
+
+ FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
+ usb_sndctrlpipe(pegasus->usb,0), (char *)&pegasus->dr,
+ data, size, pegasus_ctrl_end, pegasus );
+
+ if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) )
+ err("BAD CTRL %d", ret);
+ else
+ ret = pegasus_ctrl_timeout( &pegasus->ctrl_urb );
+
+ spin_unlock( &pegasus->ctrl_lock );
+
+ return ret;
+}
+
+
+static int pegasus_set_register( struct pegasus *pegasus, __u16 indx,__u8 data )
+{
+ int ret;
+
+
+ spin_lock( &pegasus->ctrl_lock );
+ pegasus->dr.requesttype = 0x40;
+ pegasus->dr.request = 0xf1;
+ pegasus->dr.value = data;
+ pegasus->dr.index = indx;
+ pegasus->dr.length = pegasus->ctrl_urb.transfer_buffer_length = 1;
+
+ FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
+ usb_sndctrlpipe(pegasus->usb,0), (char *)&pegasus->dr,
+ &data, 1, pegasus_ctrl_end, pegasus );
+
+ if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) )
+ err("BAD CTRL %d", ret);
+ else
+ ret = pegasus_ctrl_timeout( &pegasus->ctrl_urb );
+
+ spin_unlock( &pegasus->ctrl_lock );
+
+ return ret;
+}
+
+
+static int pegasus_read_phy_word(struct pegasus *pegasus, __u8 index, __u16 *regdata)
{
int i;
__u8 data[4] = { 1, 0, 0, 0x40 + index };
- pegasus_set_registers(dev, 0x25, 4, data);
+ pegasus_set_registers(pegasus, PhyAddr, 4, data);
for (i = 0; i < 100; i++) {
- pegasus_get_registers(dev, 0x26, 3, data);
+ pegasus_get_registers(pegasus, PhyData, 3, data);
if (data[2] & 0x80) {
*regdata = *(__u16 *)(data);
return 0;
@@ -107,14+252,14 @@ static int pegasus_read_phy_word(struct usb_device *dev, __u8 index, __u16 *regd }
-static int pegasus_write_phy_word(struct usb_device *dev, __u8 index, __u16 regdata)
+static int pegasus_write_phy_word(struct pegasus *pegasus, __u8 index, __u16 regdata)
{
int i;
__u8 data[4] = { 1, regdata, regdata >> 8, 0x20 + index };
- pegasus_set_registers(dev, 0x25, 4, data);
+ pegasus_set_registers(pegasus, PhyAddr, 4, data);
for (i = 0; i < 100; i++) {
- pegasus_get_registers(dev, 0x28, 1, data);
+ pegasus_get_registers(pegasus, PhyCtrl, 1, data);
if (data[0] & 0x80)
return 0;
udelay(100);
@@ -125,51+270,51 @@ static int pegasus_write_phy_word(struct usb_device *dev, __u8 index, __u16 regd }
-static int pegasus_rw_srom_word(struct usb_device *dev, __u8 index, __u16 *retdata, __u8 direction)
+static int pegasus_rw_eprom_word(struct pegasus *pegasus, __u8 index, __u16 *retdata, __u8 direction)
{
int i;
__u8 data[4] = { index, 0, 0, direction };
- pegasus_set_registers(dev, 0x20, 4, data);
+ pegasus_set_registers(pegasus, EpromOffset, 4, data);
for (i = 0; i < 100; i++) {
- pegasus_get_registers(dev, 0x23, 1, data);
+ pegasus_get_registers(pegasus, EpromCtrl, 1, data);
if (data[0] & 4) {
- pegasus_get_registers(dev, 0x21, 2, data);
+ pegasus_get_registers(pegasus, EpromData, 2, data);
*retdata = *(__u16 *)data;
return 0;
}
}
- warn("pegasus_rw_srom_word() failed");
+ warn("pegasus_rw_eprom_word() failed");
return 1;
}
-static int pegasus_get_node_id(struct usb_device *dev, __u8 *id)
+static int pegasus_get_node_id(struct pegasus *pegasus, __u8 *id)
{
int i;
for (i = 0; i < 3; i++)
- if (pegasus_rw_srom_word(dev,i,(__u16 *)&id[i * 2],SROM_READ))
+ if (pegasus_rw_eprom_word(pegasus,i,(__u16 *)&id[i*2],SROM_READ))
return 1;
return 0;
}
-static int pegasus_reset_mac(struct usb_device *dev)
+static int pegasus_reset_mac(struct pegasus *pegasus)
{
__u8 data = 0x8;
int i;
- pegasus_set_register(dev, 1, data);
+ pegasus_set_register(pegasus, EthCtrl1, data);
for (i = 0; i < 100; i++) {
- pegasus_get_registers(dev, 1, 1, &data);
+ pegasus_get_registers(pegasus, EthCtrl1, 1, &data);
if (~data & 0x08) {
if (loopback & 1)
return 0;
if (loopback & 2)
- pegasus_write_phy_word(dev, 0, 0x4000);
- pegasus_set_register(dev, 0x7e, 0x24);
- pegasus_set_register(dev, 0x7e, 0x27);
+ pegasus_write_phy_word(pegasus, 0, 0x4000);
+ pegasus_set_register(pegasus, Gpio0, 0x24);
+ pegasus_set_register(pegasus, Gpio0, 0x27);
return 0;
}
}
@@ -183,22+328,22 @@ static int pegasus_start_net(struct net_device *dev, struct usb_device *usb) __u16 partmedia, temp;
__u8 node_id[6];
__u8 data[4];
+ struct pegasus *pegasus = dev->priv;
- if (pegasus_get_node_id(usb, node_id))
+ if (pegasus_get_node_id(pegasus, node_id))
return 1;
- pegasus_set_registers(usb, 0x10, 6, node_id);
+ pegasus_set_registers(pegasus, EthID, 6, node_id);
memcpy(dev->dev_addr, node_id, 6);
- if (pegasus_read_phy_word(usb, 1, &temp))
+ if (pegasus_read_phy_word(pegasus, 1, &temp))
return 2;
if ((~temp & 4) && !loopback) {
- warn("%s: link NOT established (0x%x), check the cable.",
+ warn("%s: link NOT established (0x%x) - check the cable.",
dev->name, temp);
- /* return 3; FIXME */
}
- if (pegasus_read_phy_word(usb, 5, &partmedia))
+ if (pegasus_read_phy_word(pegasus, 5, &partmedia))
return 4;
if ((partmedia & 0x1f) != 1) {
@@ -210,7+355,7 @@ static int pegasus_start_net(struct net_device *dev, struct usb_device *usb) data[1] = (partmedia & 0x100) ? 0x30 : ((partmedia & 0x80) ? 0x10 : 0);
data[2] = (loopback & 1) ? 0x09 : 0x01;
- pegasus_set_registers(usb, 0, 3, data);
+ pegasus_set_registers(pegasus, EthCtrl0, 3, data);
return 0;
}
@@ -281,24+426,26 @@ static void pegasus_write_bulk(struct urb *urb) {
struct pegasus *pegasus = urb->context;
- spin_lock(&pegasus->pegasus_lock);
if (urb->status)
info("%s: TX status %d", pegasus->net->name, urb->status);
+#if 1 /* Should be fixed */
+ if (urb->status == -ETIMEDOUT)
+ pegasus_reset_mac(pegasus);
+#endif
netif_wake_queue(pegasus->net);
-
- spin_unlock(&pegasus->pegasus_lock);
}
static void pegasus_tx_timeout(struct net_device *net)
{
struct pegasus *pegasus = net->priv;
- warn("%s: Tx timed out. Reseting...", net->name);
+
usb_unlink_urb(&pegasus->tx_urb);
+ warn("%s: Tx timed out. Reseting...", net->name);
+ pegasus_reset_mac( pegasus );
pegasus->stats.tx_errors++;
net->trans_start = jiffies;
- pegasus->flags |= PEGASUS_RESET;
netif_wake_queue(net);
}
@@ -372,6+519,8 @@ static int pegasus_close(struct net_device *net)
netif_stop_queue(net);
+ if ( pegasus->ctrl_urb.status == -EINPROGRESS )
+ usb_unlink_urb(&pegasus->ctrl_urb);
if ( pegasus->rx_urb.status == -EINPROGRESS )
usb_unlink_urb(&pegasus->rx_urb);
if ( pegasus->tx_urb.status == -EINPROGRESS )
@@ -394,12+543,12 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) case SIOCDEVPRIVATE:
data[0] = 1;
case SIOCDEVPRIVATE+1:
- pegasus_read_phy_word(pegasus->usb, data[1] & 0x1f, &data[3]);
+ pegasus_read_phy_word(pegasus, data[1] & 0x1f, &data[3]);
return 0;
case SIOCDEVPRIVATE+2:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- pegasus_write_phy_word(pegasus->usb, data[1] & 0x1f, data[2]);
+ pegasus_write_phy_word(pegasus, data[1] & 0x1f, data[2]);
return 0;
default:
return -EOPNOTSUPP;
@@ -410,19+559,23 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) static void pegasus_set_rx_mode(struct net_device *net)
{
struct pegasus *pegasus = net->priv;
+ __u8 tmp;
netif_stop_queue(net);
if (net->flags & IFF_PROMISC) {
info("%s: Promiscuous mode enabled", net->name);
-/* pegasus_set_register(pegasus->usb, 2, 0x04); FIXME */
+ pegasus_get_registers(pegasus, EthCtrl2, 1, &tmp);
+ pegasus_set_register(pegasus, EthCtrl2, tmp | 4);
} else if ((net->mc_count > multicast_filter_limit) ||
(net->flags & IFF_ALLMULTI)) {
- pegasus_set_register(pegasus->usb, 0, 0xfa);
- pegasus_set_register(pegasus->usb, 2, 0);
+ pegasus_set_register(pegasus, EthCtrl0, 0xfa);
+ pegasus_set_register(pegasus, EthCtrl2, 0);
info("%s set allmulti", net->name);
} else {
info("%s: set Rx mode", net->name);
+ pegasus_get_registers(pegasus, EthCtrl2, 1, &tmp);
+ pegasus_set_register(pegasus, EthCtrl2, tmp & ~4);
}
netif_wake_queue(net);
@@ -464,12+617,6 @@ static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum) }
memset(pegasus, 0, sizeof(struct pegasus));
- if (pegasus_reset_mac(dev)) {
- err("can't reset MAC");
- kfree(pegasus);
- return NULL;
- }
-
net = init_etherdev(0, 0);
net->priv = pegasus;
net->open = pegasus_open;
@@ -485,6+632,7 @@ static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum) pegasus->usb = dev;
pegasus->net = net;
pegasus->pegasus_lock = SPIN_LOCK_UNLOCKED;
+ pegasus->ctrl_lock = SPIN_LOCK_UNLOCKED;
FILL_BULK_URB(&pegasus->rx_urb, dev, usb_rcvbulkpipe(dev, 1),
pegasus->rx_buff, PEGASUS_MAX_MTU, pegasus_read_bulk,
@@ -495,7+643,12 @@ static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum) FILL_INT_URB(&pegasus->intr_urb, dev, usb_rcvintpipe(dev, 3),
pegasus->intr_buff, 8, pegasus_irq, pegasus, 500);
-
+ if (pegasus_reset_mac(pegasus)) {
+ err("can't reset MAC");
+ kfree(pegasus);
+ return NULL;
+ }
+
printk(KERN_INFO "%s: %s\n", net->name, usb_dev_id[dev_indx].name);
return pegasus;
@@ -515,7+668,9 @@ static void pegasus_disconnect(struct usb_device *dev, void *ptr) dev_close(pegasus->net);
unregister_netdev(pegasus->net);
-
+
+ if ( pegasus->ctrl_urb.status == -EINPROGRESS )
+ usb_unlink_urb(&pegasus->ctrl_urb);
if ( pegasus->rx_urb.status == -EINPROGRESS )
usb_unlink_urb(&pegasus->rx_urb);
if ( pegasus->tx_urb.status == -EINPROGRESS )
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (06/23/2000) gkh
+ * Cleaned up debugging statements in a quest to find UHCI timeout bug.
+ *
* (05/22/2000) gkh
* Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be
* removed from the individual device source files.
@@ -358,7+361,7 @@ static struct usb_serial *get_free_serial (int num_ports, int *minor) int i, j;
int good_spot;
- dbg("get_free_serial %d", num_ports);
+ dbg(__FUNCTION__ " %d", num_ports);
*minor = 0;
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
@@ -373,14+376,14 @@ static struct usb_serial *get_free_serial (int num_ports, int *minor) continue;
if (!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) {
- err("Out of memory");
+ err(__FUNCTION__ " - Out of memory");
return NULL;
}
memset(serial, 0, sizeof(struct usb_serial));
serial->magic = USB_SERIAL_MAGIC;
serial_table[i] = serial;
*minor = i;
- dbg("minor base = %d", *minor);
+ dbg(__FUNCTION__ " - minor base = %d", *minor);
for (i = *minor+1; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
serial_table[i] = serial;
return serial;
@@ -393,7+396,7 @@ static void return_serial (struct usb_serial *serial) {
int i;
- dbg("return_serial");
+ dbg(__FUNCTION__);
if (serial == NULL)
return;
@@ -418,7+421,7 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da // dbg("ezusb_writememory %x, %d", address, length);
if (!transfer_buffer) {
- err("ezusb_writememory: kmalloc(%d) failed.", length);
+ err(__FUNCTION__ " - kmalloc(%d) failed.", length);
return -ENOMEM;
}
memcpy (transfer_buffer, data, length);
@@ -431,10+434,10 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
{
int response;
- dbg("ezusb_set_reset: %d", reset_bit);
+ dbg(__FUNCTION__ " - %d", reset_bit);
response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0) {
- err("ezusb_set_reset %d failed", reset_bit);
+ err(__FUNCTION__ "- %d failed", reset_bit);
}
return response;
}
@@ -451,7+454,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp) struct usb_serial_port *port;
int portNumber;
- dbg("serial_open");
+ dbg(__FUNCTION__);
/* initialize the pointer incase something fails */
tty->driver_data = NULL;
@@ -459,7+462,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp) /* get the serial object associated with this tty pointer */
serial = get_serial_by_minor (MINOR(tty->device));
- if (serial_paranoia_check (serial, "serial_open")) {
+ if (serial_paranoia_check (serial, __FUNCTION__)) {
return -ENODEV;
}
@@ -481,16+484,16 @@ static int serial_open (struct tty_struct *tty, struct file * filp) static void serial_close(struct tty_struct *tty, struct file * filp)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, "serial_close");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
return;
}
- dbg("serial_close port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (!port->active) {
- dbg ("port not opened");
+ dbg (__FUNCTION__ " - port not opened");
return;
}
@@ -506,16+509,16 @@ static void serial_close(struct tty_struct *tty, struct file * filp) static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, "serial_write");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
return -ENODEV;
}
- dbg("serial_write port %d, %d byte(s)", port->number, count);
+ dbg(__FUNCTION__ " - port %d, %d byte(s)", port->number, count);
if (!port->active) {
- dbg ("port not opened");
+ dbg (__FUNCTION__ " - port not opened");
return -EINVAL;
}
@@ -531,16+534,16 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned static int serial_write_room (struct tty_struct *tty)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, "serial_write_room");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
return -ENODEV;
}
- dbg("serial_write_room port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (!port->active) {
- dbg ("port not open");
+ dbg (__FUNCTION__ " - port not open");
return -EINVAL;
}
@@ -556,14+559,14 @@ static int serial_write_room (struct tty_struct *tty) static int serial_chars_in_buffer (struct tty_struct *tty)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, "serial_chars_in_buffer");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
return -ENODEV;
}
if (!port->active) {
- dbg ("port not open");
+ dbg (__FUNCTION__ " - port not open");
return -EINVAL;
}
@@ -579,16+582,16 @@ static int serial_chars_in_buffer (struct tty_struct *tty) static void serial_throttle (struct tty_struct * tty)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, "serial_throttle");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
return;
}
- dbg("serial_throttle port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (!port->active) {
- dbg ("port not open");
+ dbg (__FUNCTION__ " - port not open");
return;
}
@@ -604,16+607,16 @@ static void serial_throttle (struct tty_struct * tty) static void serial_unthrottle (struct tty_struct * tty)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, "serial_unthrottle");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
return;
}
- dbg("serial_unthrottle port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (!port->active) {
- dbg ("port not open");
+ dbg (__FUNCTION__ " - port not open");
return;
}
@@ -629,16+632,16 @@ static void serial_unthrottle (struct tty_struct * tty) static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, "serial_ioctl");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
return -ENODEV;
}
- dbg("serial_ioctl port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (!port->active) {
- dbg ("port not open");
+ dbg (__FUNCTION__ " - port not open");
return -ENODEV;
}
@@ -654,16+657,16 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in static void serial_set_termios (struct tty_struct *tty, struct termios * old)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, "serial_set_termios");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
return;
}
- dbg("serial_set_termios port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (!port->active) {
- dbg ("port not open");
+ dbg (__FUNCTION__ " - port not open");
return;
}
@@ -679,16+682,16 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old) static void serial_break (struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, "serial_break");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial) {
return;
}
- dbg("serial_break port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (!port->active) {
- dbg ("port not open");
+ dbg (__FUNCTION__ " - port not open");
return;
}
@@ -708,10+711,10 @@ static int generic_open (struct usb_serial_port *port, struct file *filp) {
struct usb_serial *serial = port->serial;
- dbg("generic_open port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (port->active) {
- dbg ("device already open");
+ dbg (__FUNCTION__ " - device already open");
return -EINVAL;
}
port->active = 1;
@@ -720,7+723,7 @@ static int generic_open (struct usb_serial_port *port, struct file *filp) if (serial->num_bulk_in) {
/*Start reading from the device*/
if (usb_submit_urb(port->read_urb))
- dbg("usb_submit_urb(read bulk) failed");
+ dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed");
}
return (0);
@@ -731,7+734,7 @@ static void generic_close (struct usb_serial_port *port, struct file * filp) {
struct usb_serial *serial = port->serial;
- dbg("generic_close port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
/* shutdown any bulk reads that might be going on */
if (serial->num_bulk_out) {
@@ -749,22+752,33 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns {
struct usb_serial *serial = port->serial;
- dbg("generic_serial_write port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (count == 0) {
- dbg("write request of 0 bytes");
+ dbg(__FUNCTION__ " - write request of 0 bytes");
return (0);
}
/* only do something if we have a bulk out endpoint */
if (serial->num_bulk_out) {
if (port->write_urb->status == -EINPROGRESS) {
- dbg ("already writing");
+ dbg (__FUNCTION__ " - already writing");
return (0);
}
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+#ifdef DEBUG
+ {
+ int i;
+ printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count);
+ for (i = 0; i < count; ++i) {
+ printk ("%.2x ", buf[i]);
+ }
+ printk ("\n");
+ }
+#endif
+
if (from_user) {
copy_from_user(port->write_urb->transfer_buffer, buf, count);
}
@@ -776,7+790,7 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns port->write_urb->transfer_buffer_length = count;
if (usb_submit_urb(port->write_urb))
- dbg("usb_submit_urb(write bulk) failed");
+ dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed");
return (count);
}
@@ -791,14+805,14 @@ static int generic_write_room (struct usb_serial_port *port) struct usb_serial *serial = port->serial;
int room;
- dbg("generic_write_room port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (serial->num_bulk_out) {
if (port->write_urb->status == -EINPROGRESS)
room = 0;
else
room = port->bulk_out_size;
- dbg("generic_write_room returns %d", room);
+ dbg(__FUNCTION__ " returns %d", room);
return (room);
}
@@ -810,7+824,7 @@ static int generic_chars_in_buffer (struct usb_serial_port *port) {
struct usb_serial *serial = port->serial;
- dbg("generic_chars_in_buffer port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (serial->num_bulk_out) {
if (port->write_urb->status == -EINPROGRESS) {
@@ -825,23+839,25 @@ static int generic_chars_in_buffer (struct usb_serial_port *port) static void generic_read_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct usb_serial *serial = get_usb_serial (port, "generic_read_bulk_callback");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int i;
+ dbg (__FUNCTION__ " - enter");
+
if (!serial) {
return;
}
if (urb->status) {
- dbg("nonzero read bulk status received: %d", urb->status);
+ dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
return;
}
#ifdef DEBUG
if (urb->actual_length) {
- printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length);
+ printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", urb->actual_length);
for (i = 0; i < urb->actual_length; ++i) {
printk ("%.2x ", data[i]);
}
@@ -859,8+875,10 @@ static void generic_read_bulk_callback (struct urb *urb)
/* Continue trying to always read */
if (usb_submit_urb(urb))
- dbg("failed resubmitting read urb");
+ dbg(__FUNCTION__ " - failed resubmitting read urb");
+ dbg (__FUNCTION__ " - exit");
+
return;
}
@@ -868,15+886,17 @@ static void generic_read_bulk_callback (struct urb *urb) static void generic_write_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct usb_serial *serial = get_usb_serial (port, "generic_write_bulk_callback");
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
struct tty_struct *tty;
+ dbg (__FUNCTION__ " - enter");
+
if (!serial) {
return;
}
if (urb->status) {
- dbg("nonzero write bulk status received: %d", urb->status);
+ dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
return;
}
@@ -886,6+906,8 @@ static void generic_write_bulk_callback (struct urb *urb)
wake_up_interruptible(&tty->write_wait);
+ dbg (__FUNCTION__ " - exit");
+
return;
}
@@ -1255,7+1277,7 @@ int usb_serial_init(void) serial_tty_driver.init_termios = tty_std_termios;
serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
if (tty_register_driver (&serial_tty_driver)) {
- err("failed to register tty driver");
+ err(__FUNCTION__ " - failed to register tty driver");
return -1;
}
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (06/23/2000) gkh
+ * Cleaned up debugging statements in a quest to find UHCI timeout bug.
+ *
* (04/27/2000) Ryan VanderBijl
* Fixed memory leak in visor_close
*
@@ -80,10+83,10 @@ struct usb_serial_device_type handspring_device = { ******************************************************************************/
static int visor_open (struct usb_serial_port *port, struct file *filp)
{
- dbg("visor_open port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (port->active) {
- dbg ("device already open");
+ dbg (__FUNCTION__ " - device already open");
return -EINVAL;
}
@@ -91,7+94,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
/*Start reading from the device*/
if (usb_submit_urb(port->read_urb))
- dbg("usb_submit_urb(read bulk) failed");
+ dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed");
return (0);
}
@@ -102,10+105,10 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) struct usb_serial *serial = port->serial;
unsigned char *transfer_buffer = kmalloc (0x12, GFP_KERNEL);
- dbg("visor_close port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (!transfer_buffer) {
- err("visor_close: kmalloc(%d) failed.", 0x12);
+ err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
} else {
/* send a shutdown message to the device */
usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION,
@@ -122,7+125,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
static void visor_throttle (struct usb_serial_port *port)
{
- dbg("visor_throttle port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
usb_unlink_urb (port->read_urb);
@@ -132,10+135,10 @@ static void visor_throttle (struct usb_serial_port *port)
static void visor_unthrottle (struct usb_serial_port *port)
{
- dbg("visor_unthrottle port %d", port->number);
+ dbg(__FUNCTION__ " - port %d", port->number);
if (usb_unlink_urb (port->read_urb))
- dbg("usb_submit_urb(read bulk) failed");
+ dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed");
return;
}
@@ -148,20+151,20 @@ static int visor_startup (struct usb_serial *serial) unsigned char *transfer_buffer = kmalloc (256, GFP_KERNEL);
if (!transfer_buffer) {
- err("visor_startup: kmalloc(%d) failed.", 256);
+ err(__FUNCTION__ " - kmalloc(%d) failed.", 256);
return -ENOMEM;
}
- dbg("visor_startup");
+ dbg(__FUNCTION__);
- dbg("visor_setup: Set config to 1");
+ dbg(__FUNCTION__ " - Set config to 1");
usb_set_configuration (serial->dev, 1);
/* send a get connection info request */
response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION,
0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
if (response < 0) {
- err("visor_startup: error getting connection information");
+ err(__FUNCTION__ " - error getting connection information");
} else {
struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer;
char *string;
@@ -195,7+198,7 @@ static int visor_startup (struct usb_serial *serial) response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE,
0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
if (response < 0) {
- err("visor_startup: error getting bytes available request");
+ err(__FUNCTION__ " - error getting bytes available request");
}
kfree (transfer_buffer);
/* Driver for USB Mass Storage compliant devices
*
- * Initial work by:
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
+ * $Id: usb-storage.c,v 1.11 2000/06/20 03:19:31 mdharm Exp $
*
* Current development and maintainance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
+ * Developed with the assistance of:
+ * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
+ *
+ * Initial work by:
+ * (c) 1999 Michael Gee (michael@linuxspecific.com)
+ *
* This driver is based on the 'USB Mass Storage Class' document. This
* describes in detail the protocol used to communicate with such
* devices. Clearly, the designers had SCSI and ATAPI commands in
*
* Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
* information about this driver.
+ *
+ * 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 <linux/module.h>
@@ -88,6+107,7 @@ struct us_data { char *protocol_name;
u8 subclass;
u8 protocol;
+ u8 max_lun;
/* information about the device -- only good if device is attached */
u8 ifnum; /* interface number */
@@ -536,8+556,9 @@ static void invoke_transport(Scsi_Cmnd *srb, struct us_data *us) /* save the old command */
memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);
+ /* set the command and the LUN */
srb->cmnd[0] = REQUEST_SENSE;
- srb->cmnd[1] = 0;
+ srb->cmnd[1] = old_cmnd[1] & 0xE0;
srb->cmnd[2] = 0;
srb->cmnd[3] = 0;
srb->cmnd[4] = 18;
@@ -791,7+812,7 @@ static int Bulk_max_lun(struct us_data *us) result, data);
/* if we have a successful request, return the result */
- if (!result)
+ if (result == 1)
return data;
/* if we get a STALL, clear the stall */
@@ -839,6+860,9 @@ static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
usb_clear_halt(us->pusb_dev, pipe);
+ } else if (result) {
+ /* unknown error -- we've got a problem */
+ return USB_STOR_TRANSPORT_ERROR;
}
/* if the command transfered well, then we go to the data stage */
@@ -976,25+1000,17 @@ static void ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) srb->cmnd[0] = srb->cmnd[0] | 0x20;
break;
} /* end switch on cmnd[0] */
+
+ /* convert MODE_SELECT data here */
+ if (old_cmnd == MODE_SELECT)
+ usb_stor_scsiSense6to10(srb);
/* send the command to the transport layer */
invoke_transport(srb, us);
- /* Fix the MODE_SENSE data if we translated the command
- */
- if (old_cmnd == MODE_SENSE) {
- unsigned char *dta = (unsigned char *)us->srb->request_buffer;
-
- /* FIXME: we need to compress the entire data structure here
- */
- dta[0] = dta[1]; /* data len */
- dta[1] = dta[2]; /* med type */
- dta[2] = dta[3]; /* dev-spec prm */
- dta[3] = dta[7]; /* block desc len */
- printk (KERN_DEBUG USB_STORAGE
- "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n",
- dta[0], dta[1], dta[2], dta[3]);
- }
+ /* Fix the MODE_SENSE data if we translated the command */
+ if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD))
+ usb_stor_scsiSense10to6(srb);
/* Fix-up the return data from an INQUIRY command to show
* ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
@@ -1084,24+1100,16 @@ static void ufi_command(Scsi_Cmnd *srb, struct us_data *us) break;
} /* end switch on cmnd[0] */
+ /* convert MODE_SELECT data here */
+ if (old_cmnd == MODE_SELECT)
+ usb_stor_scsiSense6to10(srb);
+
/* send the command to the transport layer */
invoke_transport(srb, us);
- /* Fix the MODE_SENSE data here if we had to translate the command
- */
- if (old_cmnd == MODE_SENSE) {
- unsigned char *dta = (unsigned char *)us->srb->request_buffer;
-
- /* FIXME: we need to compress the entire data structure here
- */
- dta[0] = dta[1]; /* data len */
- dta[1] = dta[2]; /* med type */
- dta[2] = dta[3]; /* dev-spec prm */
- dta[3] = dta[7]; /* block desc len */
- printk (KERN_DEBUG USB_STORAGE
- "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n",
- dta[0], dta[1], dta[2], dta[3]);
- }
+ /* Fix the MODE_SENSE data if we translated the command */
+ if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD))
+ usb_stor_scsiSense10to6(srb);
/* Fix-up the return data from an INQUIRY command to show
* ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
@@ -1310,9+1318,8 @@ static int us_release(struct Scsi_Host *psh) down(&(us->notify));
/* free the data structure we were using */
- US_DEBUGP("-- freeing private host data structure\n");
+ US_DEBUGP("-- freeing URB\n");
kfree(us->current_urb);
- kfree(us);
(struct us_data*)psh->hostdata[0] = NULL;
/* we always have a successful release */
@@ -1536,11+1543,10 @@ static int usb_stor_control_thread(void * __us)
switch (action) {
case US_ACT_COMMAND:
- /* reject if target != 0 or if single-lun device
- * and LUN != 0
+ /* reject if target != 0 or if LUN is higher than
+ * the maximum known LUN
*/
- if (us->srb->target ||
- ((us->flags & US_FL_SINGLE_LUN) && us->srb->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);
@@ -1623,32+1629,37 @@ static int usb_stor_control_thread(void * __us)
/* This is the list of devices we recognize, along with their flag data */
static struct us_unusual_dev us_unusual_dev_list[] = {
- { 0x03f0, 0x0107, 0x0200,
- "HP USB CD-Writer Plus", US_SC_8070, US_PR_CB, 0},
- { 0x04e6, 0x0001, 0x0200,
- "Matshita LS-120", US_SC_8020, US_PR_CB, US_FL_SINGLE_LUN},
- { 0x04e6, 0x0002, 0x0100,
- "Shuttle eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
- { 0x04e6, 0x0006, 0x0100,
- "Shuttle eUSB MMC Adapter", US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN},
- { 0x057b, 0x0000, 0x0114,
- "Y-E Data Flashbuster-U", US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN},
- { 0x059b, 0x0030, 0x0100,
- "Iomega Zip 250", US_SC_SCSI, US_PR_BULK, US_FL_SINGLE_LUN},
- { 0x0693, 0x0002, 0x0100,
- "Hagiwara FlashGate SmartMedia", US_SC_SCSI, US_PR_BULK,
- US_FL_ALT_LENGTH},
- { 0x0781, 0x0001, 0x0200,
- "Sandisk ImageMate (SDDR-01)", US_SC_SCSI, US_PR_CB,
- US_FL_SINGLE_LUN | US_FL_START_STOP},
- { 0x0781, 0x0002, 0x0009,
- "Sandisk Imagemate (SDDR-31)", US_SC_SCSI, US_PR_BULK,
- US_FL_SINGLE_LUN | US_FL_IGNORE_SER},
- { 0x07af, 0x0005, 0x0100,
- "Microtech USB-SCSI-HD50", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
- { 0x0000, 0x0000, 0x0,
- "", 0, 0, 0}
-};
+ { 0x03f0, 0x0107, 0x0200, 0x0200, "HP USB CD-Writer Plus",
+ US_SC_8070, US_PR_CB, 0},
+ { 0x04e6, 0x0001, 0x0200, 0x0200, "Matshita LS-120",
+ US_SC_8020, US_PR_CB, US_FL_SINGLE_LUN},
+ { 0x04e6, 0x0002, 0x0100, 0x0100, "Shuttle eUSCSI Bridge",
+ US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
+ { 0x04e6, 0x0006, 0x0100, 0x0100, "Shuttle eUSB MMC Adapter",
+ US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN},
+ { 0x054c, 0x0010, 0x0210, 0x0210, "Sony DSC-S30",
+ US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP |
+ US_FL_MODE_XLATE | US_FL_ALT_LENGTH},
+ { 0x054c, 0x002d, 0x0100, 0x0100, "Sony Memorystick MSAC-US1",
+ US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP |
+ US_FL_MODE_XLATE | US_FL_ALT_LENGTH},
+ { 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data Flashbuster-U",
+ US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN},
+ { 0x057b, 0x0000, 0x0300, 0x9999, "Y-E Data Flashbuster-U",
+ 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)",
+ US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP},
+ { 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk Imagemate (SDDR-31)",
+ US_SC_SCSI, US_PR_BULK, US_FL_IGNORE_SER},
+ { 0x07af, 0x0005, 0x0100, 0x0100, "Microtech USB-SCSI-HD50",
+ US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
+ { 0x05ab, 0x0031, 0x0100, 0x0100, "In-System USB/IDE Bridge",
+ US_SC_8070, US_PR_BULK, US_FL_ALT_LENGTH},
+ { 0x0693, 0x0005, 0x0100, 0x0100, "Hagiwara Flashgate",
+ US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
+ { 0 }};
/* Search our ususual device list, based on vendor/product combinations
* to see if we can support this device. Returns a pointer to a structure
@@ -1667,7+1678,8 @@ static struct us_unusual_dev* us_find_dev(u16 idVendor, u16 idProduct, while ((ptr->idVendor != 0x0000) &&
!((ptr->idVendor == idVendor) &&
(ptr->idProduct == idProduct) &&
- (ptr->bcdDevice == bcdDevice)))
+ (ptr->bcdDeviceMin <= bcdDevice) &&
+ (ptr->bcdDeviceMax >= bcdDevice)))
ptr++;
/* if the search ended because we hit the end record, we failed */
@@ -1968,20+1980,21 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) ss->transport_name = "Control/Bulk";
ss->transport = CB_transport;
ss->transport_reset = CB_reset;
+ ss->max_lun = 7;
break;
case US_PR_CBI:
ss->transport_name = "Control/Bulk/Interrupt";
ss->transport = CBI_transport;
ss->transport_reset = CB_reset;
+ ss->max_lun = 7;
break;
case US_PR_BULK:
ss->transport_name = "Bulk";
ss->transport = Bulk_transport;
ss->transport_reset = Bulk_reset;
- /* FIXME: for testing purposes only */
- Bulk_max_lun(ss);
+ ss->max_lun = Bulk_max_lun(ss);
break;
default:
@@ -1994,6+2007,10 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) }
US_DEBUGP("Transport: %s\n", ss->transport_name);
+ /* fix for single-lun devices */
+ if (ss->flags & US_FL_SINGLE_LUN)
+ ss->max_lun = 0;
+
switch (ss->subclass) {
case US_SC_RBC:
ss->protocol_name = "Reduced Block Commands (RBC)";
@@ -2134,6+2151,576 @@ static void storage_disconnect(struct usb_device *dev, void *ptr) up(&(ss->dev_semaphore));
}
+/**************************************************************
+ **************************************************************/
+
+#define USB_STOR_SCSI_SENSE_HDRSZ 4
+#define USB_STOR_SCSI_SENSE_10_HDRSZ 8
+
+struct usb_stor_scsi_sense_hdr
+{
+ __u8* dataLength;
+ __u8* mediumType;
+ __u8* devSpecParms;
+ __u8* blkDescLength;
+};
+
+typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr;
+
+union usb_stor_scsi_sense_hdr_u
+{
+ Usb_Stor_Scsi_Sense_Hdr hdr;
+ __u8* array[USB_STOR_SCSI_SENSE_HDRSZ];
+};
+
+typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u;
+
+struct usb_stor_scsi_sense_hdr_10
+{
+ __u8* dataLengthMSB;
+ __u8* dataLengthLSB;
+ __u8* mediumType;
+ __u8* devSpecParms;
+ __u8* reserved1;
+ __u8* reserved2;
+ __u8* blkDescLengthMSB;
+ __u8* blkDescLengthLSB;
+};
+
+typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10;
+
+union usb_stor_scsi_sense_hdr_10_u
+{
+ Usb_Stor_Scsi_Sense_Hdr_10 hdr;
+ __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ];
+};
+
+typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u;
+
+void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*,
+ Usb_Stor_Scsi_Sense_Hdr_10_u*, int* );
+void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd );
+
+int
+usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
+{
+ __u8 *buffer=0;
+ int outputBufferSize = 0;
+ int length=0;
+ struct scatterlist *sg = 0;
+ int i=0, j=0, element=0;
+ Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
+ Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
+ int sb=0,si=0,db=0,di=0;
+ int sgLength=0;
+
+#if 0
+ /* Make sure we get a MODE_SENSE_10 command */
+ if ( the10->cmnd[0] != MODE_SENSE_10 )
+ {
+ printk( KERN_ERR USB_STORAGE
+ "Scsi_Cmnd was not a MODE_SENSE_10.\n" );
+ return -1;
+ }
+
+ /* Now start to format the output */
+ the10->cmnd[0] = MODE_SENSE;
+#endif
+ US_DEBUGP("-- converting 10 byte sense data to 6 byte\n");
+ the10->cmnd[0] = the10->cmnd[0] & 0xBF;
+
+ /* Determine buffer locations */
+ usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations,
+ &length );
+
+ /* Work out minimum buffer to output */
+ outputBufferSize = *the10Locations.hdr.dataLengthLSB;
+ outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ;
+
+ /* Check to see if we need to truncate the output */
+ if ( outputBufferSize > length )
+ {
+ printk( KERN_WARNING USB_STORAGE
+ "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" );
+ printk( KERN_WARNING USB_STORAGE
+ "outputBufferSize is %d and length is %d.\n",
+ outputBufferSize, length );
+ }
+ outputBufferSize = length;
+
+ /* Data length */
+ if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */
+ {
+ printk( KERN_WARNING USB_STORAGE
+ "Command will be truncated to fit in SENSE6 buffer.\n" );
+ *the6Locations.hdr.dataLength = 0xff;
+ }
+ else
+ {
+ *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB;
+ }
+
+ /* Medium type and DevSpecific parms */
+ *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType;
+ *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms;
+
+ /* Block descriptor length */
+ if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */
+ {
+ printk( KERN_WARNING USB_STORAGE
+ "Command will be truncated to fit in SENSE6 buffer.\n" );
+ *the6Locations.hdr.blkDescLength = 0xff;
+ }
+ else
+ {
+ *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB;
+ }
+
+ if ( the10->use_sg == 0 )
+ {
+ buffer = the10->request_buffer;
+ /* Copy the rest of the data */
+ memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
+ &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
+ outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ );
+ /* initialise last bytes left in buffer due to smaller header */
+ memset( &(buffer[outputBufferSize
+ -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]),
+ 0,
+ USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
+ }
+ else
+ {
+ sg = (struct scatterlist *) the10->request_buffer;
+ /* scan through this scatterlist and figure out starting positions */
+ for ( i=0; i < the10->use_sg; i++)
+ {
+ sgLength = sg[i].length;
+ for ( j=0; j<sgLength; j++ )
+ {
+ /* get to end of header */
+ if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
+ {
+ db=i;
+ di=j;
+ }
+ if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
+ {
+ sb=i;
+ si=j;
+ /* we've found both sets now, exit loops */
+ j=sgLength;
+ i=the10->use_sg;
+ }
+ element++;
+ }
+ }
+
+ /* Now we know where to start the copy from */
+ element = USB_STOR_SCSI_SENSE_HDRSZ;
+ while ( element < outputBufferSize
+ -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
+ {
+ /* check limits */
+ if ( sb >= the10->use_sg ||
+ si >= sg[sb].length ||
+ db >= the10->use_sg ||
+ di >= sg[db].length )
+ {
+ printk( KERN_ERR USB_STORAGE
+ "Buffer overrun averted, this shouldn't happen!\n" );
+ break;
+ }
+
+ /* copy one byte */
+ sg[db].address[di] = sg[sb].address[si];
+
+ /* get next destination */
+ if ( sg[db].length-1 == di )
+ {
+ db++;
+ di=0;
+ }
+ else
+ {
+ di++;
+ }
+
+ /* get next source */
+ if ( sg[sb].length-1 == si )
+ {
+ sb++;
+ si=0;
+ }
+ else
+ {
+ si++;
+ }
+
+ element++;
+ }
+ /* zero the remaining bytes */
+ while ( element < outputBufferSize )
+ {
+ /* check limits */
+ if ( db >= the10->use_sg ||
+ di >= sg[db].length )
+ {
+ printk( KERN_ERR USB_STORAGE
+ "Buffer overrun averted, this shouldn't happen!\n" );
+ break;
+ }
+
+ sg[db].address[di] = 0;
+
+ /* get next destination */
+ if ( sg[db].length-1 == di )
+ {
+ db++;
+ di=0;
+ }
+ else
+ {
+ di++;
+ }
+ element++;
+ }
+ }
+
+ /* All done any everything was fine */
+ return 0;
+}
+
+int
+usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
+{
+ /* will be used to store part of buffer */
+ __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ],
+ *buffer=0;
+ int outputBufferSize = 0;
+ int length=0;
+ struct scatterlist *sg = 0;
+ int i=0, j=0, element=0;
+ Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
+ Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
+ int sb=0,si=0,db=0,di=0;
+ int lsb=0,lsi=0,ldb=0,ldi=0;
+
+#if 0
+ /* Make sure we get a MODE_SENSE command */
+ if ( the6->cmnd[0] != MODE_SENSE )
+ {
+ printk( KERN_ERR USB_STORAGE
+ "Scsi_Cmnd was not MODE_SENSE.\n" );
+ return -1;
+ }
+
+ /* Now start to format the output */
+ the6->cmnd[0] = MODE_SENSE_10;
+#endif
+ US_DEBUGP("-- converting 6 byte sense data to 10 byte\n");
+ the6->cmnd[0] = the6->cmnd[0] | 0x40;
+
+ /* Determine buffer locations */
+ usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations,
+ &length );
+
+ /* Work out minimum buffer to output */
+ outputBufferSize = *the6Locations.hdr.dataLength;
+ outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ;
+
+ /* Check to see if we need to trucate the output */
+ if ( outputBufferSize > length )
+ {
+ printk( KERN_WARNING USB_STORAGE
+ "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" );
+ printk( KERN_WARNING USB_STORAGE
+ "outputBufferSize is %d and length is %d.\n",
+ outputBufferSize, length );
+ }
+ outputBufferSize = length;
+
+ /* Block descriptor length - save these before overwriting */
+ tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB;
+ tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB;
+ *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength;
+ *the10Locations.hdr.blkDescLengthMSB = 0;
+
+ /* reserved - save these before overwriting */
+ tempBuffer[0] = *the10Locations.hdr.reserved1;
+ tempBuffer[1] = *the10Locations.hdr.reserved2;
+ *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0;
+
+ /* Medium type and DevSpecific parms */
+ *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms;
+ *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType;
+
+ /* Data length */
+ *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength;
+ *the10Locations.hdr.dataLengthMSB = 0;
+
+ if ( !the6->use_sg )
+ {
+ buffer = the6->request_buffer;
+ /* Copy the rest of the data */
+ memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
+ &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
+ outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ );
+ /* Put the first four bytes (after header) in place */
+ memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
+ tempBuffer,
+ USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
+ }
+ else
+ {
+ sg = (struct scatterlist *) the6->request_buffer;
+ /* scan through this scatterlist and figure out ending positions */
+ for ( i=0; i < the6->use_sg; i++)
+ {
+ for ( j=0; j<sg[i].length; j++ )
+ {
+ /* get to end of header */
+ if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
+ {
+ ldb=i;
+ ldi=j;
+ }
+ if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
+ {
+ lsb=i;
+ lsi=j;
+ /* we've found both sets now, exit loops */
+ j=sg[i].length;
+ i=the6->use_sg;
+ break;
+ }
+ element++;
+ }
+ }
+ /* scan through this scatterlist and figure out starting positions */
+ element = length-1;
+ /* destination is the last element */
+ db=the6->use_sg-1;
+ di=sg[db].length-1;
+ for ( i=the6->use_sg-1; i >= 0; i--)
+ {
+ for ( j=sg[i].length-1; j>=0; j-- )
+ {
+ /* get to end of header and find source for copy */
+ if ( element == length - 1
+ - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
+ {
+ sb=i;
+ si=j;
+ /* we've found both sets now, exit loops */
+ j=-1;
+ i=-1;
+ }
+ element--;
+ }
+ }
+ /* Now we know where to start the copy from */
+ element = length-1
+ - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ);
+ while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ )
+ {
+ /* check limits */
+ if ( ( sb <= lsb && si < lsi ) ||
+ ( db <= ldb && di < ldi ) )
+ {
+ printk( KERN_ERR USB_STORAGE
+ "Buffer overrun averted, this shouldn't happen!\n" );
+ break;
+ }
+
+ /* copy one byte */
+ sg[db].address[di] = sg[sb].address[si];
+
+ /* get next destination */
+ if ( di == 0 )
+ {
+ db--;
+ di=sg[db].length-1;
+ }
+ else
+ {
+ di--;
+ }
+
+ /* get next source */
+ if ( si == 0 )
+ {
+ sb--;
+ si=sg[sb].length-1;
+ }
+ else
+ {
+ si--;
+ }
+
+ element--;
+ }
+ /* copy the remaining four bytes */
+ while ( element >= USB_STOR_SCSI_SENSE_HDRSZ )
+ {
+ /* check limits */
+ if ( db <= ldb && di < ldi )
+ {
+ printk( KERN_ERR USB_STORAGE
+ "Buffer overrun averted, this shouldn't happen!\n" );
+ break;
+ }
+
+ sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
+
+ /* get next destination */
+ if ( di == 0 )
+ {
+ db--;
+ di=sg[db].length-1;
+ }
+ else
+ {
+ di--;
+ }
+ element--;
+ }
+ }
+
+ /* All done and everything was fine */
+ return 0;
+}
+
+void
+usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6,
+ Usb_Stor_Scsi_Sense_Hdr_10_u* the10,
+ int* length_p )
+
+{
+ int i = 0, j=0, element=0;
+ struct scatterlist *sg = 0;
+ int length = 0;
+ __u8* buffer=0;
+
+ /* are we scatter-gathering? */
+ if ( srb->use_sg != 0 )
+ {
+ /* loop over all the scatter gather structures and
+ * get pointer to the data members in the headers
+ * (also work out the length while we're here)
+ */
+ sg = (struct scatterlist *) srb->request_buffer;
+ for (i = 0; i < srb->use_sg; i++)
+ {
+ length += sg[i].length;
+ /* We only do the inner loop for the headers */
+ if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
+ {
+ /* scan through this scatterlist */
+ for ( j=0; j<sg[i].length; j++ )
+ {
+ if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
+ {
+ /* fill in the pointers for both header types */
+ the6->array[element] = &(sg[i].address[j]);
+ the10->array[element] = &(sg[i].address[j]);
+ }
+ else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
+ {
+ /* only the longer headers still cares now */
+ the10->array[element] = &(sg[i].address[j]);
+ }
+ /* increase element counter */
+ element++;
+ }
+ }
+ }
+ }
+ else
+ {
+ length = srb->request_bufflen;
+ buffer = srb->request_buffer;
+ if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ )
+ printk( KERN_ERR USB_STORAGE
+ "Buffer length smaller than header!!" );
+ for( i=0; i<USB_STOR_SCSI_SENSE_10_HDRSZ; i++ )
+ {
+ if ( i < USB_STOR_SCSI_SENSE_HDRSZ )
+ {
+ the6->array[i] = &(buffer[i]);
+ the10->array[i] = &(buffer[i]);
+ }
+ else
+ {
+ the10->array[i] = &(buffer[i]);
+ }
+ }
+ }
+
+ /* Set value of length passed in */
+ *length_p = length;
+}
+
+void
+usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd )
+{
+ int i=0, bufferSize = cmd->request_bufflen;
+ __u8* buffer = cmd->request_buffer;
+ struct scatterlist* sg = (struct scatterlist*)cmd->request_buffer;
+
+ printk( KERN_ERR "Dumping information about %p.\n", cmd );
+ printk( KERN_ERR "cmd->cmnd[0] value is %d.\n", cmd->cmnd[0] );
+ printk( KERN_ERR "(MODE_SENSE is %d and MODE_SENSE_10 is %d)\n",
+ MODE_SENSE, MODE_SENSE_10 );
+
+ printk( KERN_ERR "buffer is %p with length %d.\n", buffer, bufferSize );
+ for ( i=0; i<bufferSize; i+=16 )
+ {
+ printk( KERN_ERR "%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n",
+ buffer[i],
+ buffer[i+1],
+ buffer[i+2],
+ buffer[i+3],
+ buffer[i+4],
+ buffer[i+5],
+ buffer[i+6],
+ buffer[i+7],
+ buffer[i+8],
+ buffer[i+9],
+ buffer[i+10],
+ buffer[i+11],
+ buffer[i+12],
+ buffer[i+13],
+ buffer[i+14],
+ buffer[i+15] );
+ }
+
+ printk( KERN_ERR "Buffer has %d scatterlists.\n", cmd->use_sg );
+ for ( i=0; i<cmd->use_sg; i++ )
+ {
+ printk( KERN_ERR "Length of scatterlist %d is %d.\n", i, sg[i].length );
+ printk( KERN_ERR "%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n",
+ sg[i].address[0],
+ sg[i].address[1],
+ sg[i].address[2],
+ sg[i].address[3],
+ sg[i].address[4],
+ sg[i].address[5],
+ sg[i].address[6],
+ sg[i].address[7],
+ sg[i].address[8],
+ sg[i].address[9],
+ sg[i].address[10],
+ sg[i].address[11],
+ sg[i].address[12],
+ sg[i].address[13],
+ sg[i].address[14],
+ sg[i].address[15] );
+ }
+}
+
+/**************************************************************
+ **************************************************************/
/***********************************************************************
* Initialization and registration
@@ -2183,6+2770,11 @@ void __exit usb_stor_exit(void) US_DEBUGP("-- calling scsi_unregister_module()\n");
scsi_unregister_module(MODULE_SCSI_HA, &(us_list->htmplt));
+ /* Now that scsi_unregister_module is done with the host
+ * template, we can free the us_data structure (the host
+ * template is inline in this structure). */
+ kfree (us_list);
+
/* advance the list pointer */
us_list = next;
}
@@ -139,7+139,8 @@ struct us_unusual_dev { /* we search the list based on these parameters */
__u16 idVendor;
__u16 idProduct;
- __u16 bcdDevice;
+ __u16 bcdDeviceMin;
+ __u16 bcdDeviceMax;
/* the list specifies these parameters */
const char* name;
@@ -120,6+120,7 @@ if [ "$CONFIG_FB" = "y" ]; then tristate ' ATI Mach64 display support (EXPERIMENTAL)' CONFIG_FB_ATY
tristate ' ATI Rage 128 display support (EXPERIMENTAL)' CONFIG_FB_ATY128
bool ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX
+ tristate ' SIS 630/540 display support (EXPERIMENTAL)' CONFIG_FB_SIS
fi
fi
if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
#define FALSE 0
#define TRUE 1
-/* Draw Function */
+/* Draw Function
#define FBIOGET_GLYPH 0x4620
#define FBIOGET_HWCINFO 0x4621
+*/
#define BR(x) (0x8200 | (x) << 2)
#define BITBLT 0x00000000
#define MMIO_SIZE 0x20000 /* 128K MMIO capability */
#define MAX_ROM_SCAN 0x10000
-#define RESERVED_MEM_SIZE 0x400000 /* 4M */
+#define RESERVED_MEM_SIZE_4M 0x400000 /* 4M */
+#define RESERVED_MEM_SIZE_8M 0x800000 /* 8M */
/* Mode set stuff */
#define DEFAULT_MODE 0
@@ -173,9+175,9 @@ static struct board { const char *name;
} dev_list[] = {
{
- PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_300, "SIS 300"}, {
- PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_540, "SIS 540"}, {
- PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_630, "SIS 630"}, {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"}, {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540, "SIS 540"}, {
+ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, "SIS 630"}, {
0, 0, NULL}
};
@@ -1020,8+1022,11 @@ static int sisfb_heap_init(void) struct OH *poh;
u8 jTemp, tq_state;
- heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE;
- //heap_start = (unsigned long)ivideo.video_vbase + (video_size - RESERVED_MEM_SIZE);
+ if(ivideo.video_size > 0x800000) /* video ram is large than 8M */
+ heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_8M;
+ else
+ heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_4M;
+
heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
heap_size = heap_end - heap_start;
@@ -1398,6+1403,7 @@ static u32 get_reg3(u16 port)
static u16 get_modeID_length(unsigned long ROMAddr, u16 ModeNo)
{
+#if 0
unsigned char ModeID;
u16 modeidlength;
u16 usModeIDOffset;
@@ -1411,6+1417,8 @@ static u16 get_modeID_length(unsigned long ROMAddr, u16 ModeNo) ModeID = *((unsigned char *) (ROMAddr + usModeIDOffset));
}
return (modeidlength);
+#endif
+ return(10);
}
static int search_modeID(unsigned long ROMAddr, u16 ModeNo)
@@ -2467,7+2475,11 @@ static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, strcpy(fix->id, fb_info.modename);
fix->smem_start = ivideo.video_base;
- fix->smem_len = RESERVED_MEM_SIZE; /* reserved for Xserver */
+ if(ivideo.video_size > 0x800000)
+ fix->smem_len = RESERVED_MEM_SIZE_8M; /* reserved for Xserver */
+ else
+ fix->smem_len = RESERVED_MEM_SIZE_4M; /* reserved for Xserver */
+
fix->type = video_type;
fix->type_aux = 0;
if (ivideo.video_bpp == 8)
@@ -450,7+450,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (elf_ppnt->p_type == PT_INTERP) {
retval = -EINVAL;
if (elf_interpreter)
- goto out_free_interp;
+ goto out_free_dentry;
/* This is the program interpreter used for
* shared libraries - for now assume that this
@@ -484,6+484,8 @@ int flush_old_exec(struct linux_binprm * bprm) /* This is the point of no return */
release_old_signals(oldsig);
+ current->sas_ss_sp = current->sas_ss_size = 0;
+
if (current->euid == current->uid && current->egid == current->gid)
current->dumpable = 1;
name = bprm->filename;
@@ -585,21+587,18 @@ int prepare_binprm(struct linux_binprm *bprm) cap_clear(bprm->cap_effective);
/* To support inheritance of root-permissions and suid-root
- * executables under compatibility mode, we raise the
- * effective and inherited bitmasks of the executable file
- * (translation: we set the executable "capability dumb" and
- * set the allowed set to maximum). We don't set any forced
- * bits.
+ * executables under compatibility mode, we raise all three
+ * capability sets for the file.
*
* If only the real uid is 0, we only raise the inheritable
- * bitmask of the executable file (translation: we set the
- * allowed set to maximum and the application to "capability
- * smart").
+ * and permitted sets of the executable file.
*/
if (!issecure(SECURE_NOROOT)) {
- if (bprm->e_uid == 0 || current->uid == 0)
+ if (bprm->e_uid == 0 || current->uid == 0) {
cap_set_full(bprm->cap_inheritable);
+ cap_set_full(bprm->cap_permitted);
+ }
if (bprm->e_uid == 0)
cap_set_full(bprm->cap_effective);
}
@@ -610,10+609,12 @@ int prepare_binprm(struct linux_binprm *bprm) * privilege does not go against other system constraints.
* The new Permitted set is defined below -- see (***). */
{
- kernel_cap_t working =
- cap_combine(bprm->cap_permitted,
- cap_intersect(bprm->cap_inheritable,
- current->cap_inheritable));
+ kernel_cap_t permitted, working;
+
+ permitted = cap_intersect(bprm->cap_permitted, cap_bset);
+ working = cap_intersect(bprm->cap_inheritable,
+ current->cap_inheritable);
+ working = cap_combine(permitted, working);
if (!cap_issubset(working, current->cap_permitted)) {
cap_raised = 1;
}
@@ -646,26+647,29 @@ int prepare_binprm(struct linux_binprm *bprm) * The formula used for evolving capabilities is:
*
* pI' = pI
- * (***) pP' = fP | (fI & pI)
+ * (***) pP' = (fP & X) | (fI & pI)
* pE' = pP' & fE [NB. fE is 0 or ~0]
*
* I=Inheritable, P=Permitted, E=Effective // p=process, f=file
- * ' indicates post-exec().
+ * ' indicates post-exec(), and X is the global 'cap_bset'.
*/
void compute_creds(struct linux_binprm *bprm)
{
- int new_permitted = cap_t(bprm->cap_permitted) |
- (cap_t(bprm->cap_inheritable) &
- cap_t(current->cap_inheritable));
+ kernel_cap_t new_permitted, working;
+
+ new_permitted = cap_intersect(bprm->cap_permitted, cap_bset);
+ working = cap_intersect(bprm->cap_inheritable,
+ current->cap_inheritable);
+ new_permitted = cap_combine(new_permitted, working);
/* For init, we want to retain the capabilities set
* in the init_task struct. Thus we skip the usual
* capability rules */
if (current->pid != 1) {
- cap_t(current->cap_permitted) = new_permitted;
- cap_t(current->cap_effective) = new_permitted &
- cap_t(bprm->cap_effective);
+ current->cap_permitted = new_permitted;
+ current->cap_effective =
+ cap_intersect(new_permitted, bprm->cap_effective);
}
/* AUD: Audit candidate if current->cap_effective is set */
@@ -235,7+235,10 @@ lockd_up(void) }
if ((error = svc_makesock(serv, IPPROTO_UDP, 0)) < 0
- || (error = svc_makesock(serv, IPPROTO_TCP, 0)) < 0) {
+#ifdef CONFIG_NFSD_TCP
+ || (error = svc_makesock(serv, IPPROTO_TCP, 0)) < 0
+#endif
+ ) {
if (warned++ == 0)
printk(KERN_WARNING
"lockd_up: makesock failed, error=%d\n", error);
@@ -79,7+79,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, goto out_unlock;
memset(file, 0, sizeof(*file));
- file->f_handle = *f;
+ memcpy(&file->f_handle, f, sizeof(struct nfs_fh));
file->f_hash = hash;
init_MUTEX(&file->f_sema);
@@ -86,7+86,7 @@ nlm_decode_fh(u32 *p, struct nfs_fh *f)
if ((len = ntohl(*p++)) != NFS2_FHSIZE) {
printk(KERN_NOTICE
- "lockd: bad fhandle size %x (should be %u)\n",
+ "lockd: bad fhandle size %x (should be %Zu)\n",
len, NFS2_FHSIZE);
return NULL;
}
#include <linux/nfs_mount.h>
#include <linux/pagemap.h>
-#include <asm/segment.h> /* for fs functions */
-
#define NFS_PARANOIA 1
/* #define NFS_DEBUG_VERBOSE 1 */
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
-#include <asm/segment.h>
#include <asm/system.h>
#define NFSDBG_FACILITY NFSDBG_FILE
@@ -705,7+705,7 @@ nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle, (long long)fattr->fileid);
/* Install the file handle in the dentry */
- *((struct nfs_fh *) dentry->d_fsdata) = *fhandle;
+ memcpy(dentry->d_fsdata, fhandle, sizeof(struct nfs_fh));
#ifdef CONFIG_NFS_SNAPSHOT
/*
#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
-#include <asm/segment.h>
-
#define NFSDBG_FACILITY NFSDBG_PROC
/*
#include <linux/nfs2.h>
#include <linux/nfs_fs.h>
-#include <asm/segment.h>
-
#define NFSDBG_FACILITY NFSDBG_PROC
/*
@@ -203,7+201,7 @@ nfs_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr, if (S_ISFIFO(mode)) {
sattr->ia_mode = (mode & ~S_IFMT) | S_IFCHR;
sattr->ia_valid &= ~ATTR_SIZE;
- } else if (S_ISCHR(rdev) || S_ISBLK(rdev)) {
+ } else if (S_ISCHR(mode) || S_ISBLK(mode)) {
sattr->ia_valid |= ATTR_SIZE;
sattr->ia_size = rdev; /* get out your barf bag */
}
#include <linux/nfs_flushd.h>
#include <linux/smp_lock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -430,13+430,12 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino, * fh must be initialized before calling fh_compose
*/
fh_init(&fh, maxsize);
- if (fh_compose(&fh, exp, nd.dentry))
+ if (fh_compose(&fh, exp, dget(nd.dentry)))
err = -EINVAL;
else
err = 0;
memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
fh_put(&fh);
- return err;
out:
path_release(&nd);
@@ -658,7+658,7 @@ struct svc_procedure nfsd_procedures3[22] = { PROC(mknod, mknod, create, fhandle2, RC_REPLBUFF),
PROC(remove, dirop, wccstat, fhandle, RC_REPLBUFF),
PROC(rmdir, dirop, wccstat, fhandle, RC_REPLBUFF),
- PROC(rename, rename, rename, fhandle, RC_REPLBUFF),
+ PROC(rename, rename, rename, fhandle2, RC_REPLBUFF),
PROC(link, link, link, fhandle2, RC_REPLBUFF),
PROC(readdir, readdir, readdir, fhandle, RC_NOCACHE),
PROC(readdirplus,readdirplus, readdir, fhandle, RC_NOCACHE),
@@ -698,17+698,9 @@ encode_entry(struct readdir_cd *cd, const char *name, cd->eob = 1;
return -EINVAL;
}
- *p++ = xdr_one; /* mark entry present */
- p = xdr_encode_hyper(p, ino); /* file id */
- p[slen - 1] = 0; /* don't leak kernel data */
-#ifdef XDR_ENCODE_STRING_TAKES_LENGTH
- p = xdr_encode_string(p, name, namlen); /* name length & name */
-#else
- /* just like nfsproc.c */
- *p++ = htonl((u32) namlen);
- memcpy(p, name, namlen);
- p += slen;
-#endif
+ *p++ = xdr_one; /* mark entry present */
+ p = xdr_encode_hyper(p, ino); /* file id */
+ p = xdr_encode_array(p, name, namlen);/* name length & name */
cd->offset = p; /* remember pointer */
p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
@@ -60,7+60,7 @@ nfsd_cache_init(void) nfscache = (struct svc_cacherep *)
__get_free_pages(GFP_KERNEL, order);
if (!nfscache) {
- printk (KERN_ERR "nfsd: cannot allocate %Zu bytes for reply cache\n", i);
+ printk (KERN_ERR "nfsd: cannot allocate %d bytes for reply cache\n", i);
return;
}
memset(nfscache, 0, i);
@@ -70,7+70,7 @@ nfsd_cache_init(void) if (!hash_list) {
free_pages ((unsigned long)nfscache, order);
nfscache = NULL;
- printk (KERN_ERR "nfsd: cannot allocate %Zu bytes for hash list\n", i);
+ printk (KERN_ERR "nfsd: cannot allocate %d bytes for hash list\n", i);
return;
}
@@ -367,7+367,7 @@ find_fh_dentry(struct super_block *sb, ino_t ino, int generation, ino_t dirino, /* It's a directory, or we are required to confirm the file's
* location in the tree.
*/
- dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,(long) ino);
+ dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,ino);
down(&sb->s_nfsd_free_path_sem);
/* claiming the semaphore might have allowed things to get fixed up */
@@ -412,11+412,9 @@ nfssvc_encode_entry(struct readdir_cd *cd, const char *name, cd->eob = 1;
return -EINVAL;
}
- *p++ = xdr_one; /* mark entry present */
- *p++ = htonl((u32) ino); /* file id */
- *p++ = htonl((u32) namlen); /* name length & name */
- memcpy(p, name, namlen);
- p += slen;
+ *p++ = xdr_one; /* mark entry present */
+ *p++ = htonl((u32) ino); /* file id */
+ p = xdr_encode_array(p, name, namlen);/* name length & name */
cd->offset = p; /* remember pointer */
*p++ = ~(u32) 0; /* offset of next entry */
#include <linux/unistd.h>
#include <linux/malloc.h>
#include <linux/in.h>
+#define __NO_VERSION__
+#include <linux/module.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
@@ -451,7+453,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, goto out_nfserr;
memset(filp, 0, sizeof(*filp));
- filp->f_op = inode->i_fop;
+ filp->f_op = fops_get(inode->i_fop);
atomic_set(&filp->f_count, 1);
filp->f_dentry = dentry;
if (access & MAY_WRITE) {
@@ -467,6+469,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, if (filp->f_op && filp->f_op->open) {
err = filp->f_op->open(inode, filp);
if (err) {
+ fops_put(filp->f_op);
if (access & MAY_WRITE)
put_write_access(inode);
@@ -494,6+497,7 @@ nfsd_close(struct file *filp)
if (filp->f_op && filp->f_op->release)
filp->f_op->release(inode, filp);
+ fops_put(filp->f_op);
if (filp->f_mode & FMODE_WRITE)
put_write_access(inode);
}
@@ -66,8+66,10 @@ static void __init copro_timeout(void) static double __initdata x = 4195835.0;
static double __initdata y = 3145727.0;
+#ifdef CONFIG_X86_XMM
static float __initdata zero[4] = { 0.0, 0.0, 0.0, 0.0 };
static float __initdata one[4] = { 1.0, 1.0, 1.0, 1.0 };
+#endif
static void __init check_fpu(void)
{
#ifndef __ASM_IO_APIC_H
#define __ASM_IO_APIC_H
+#include <linux/config.h>
#include <asm/types.h>
/*
* Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
*/
-#include <linux/config.h>
-
#include <asm/mman.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/bitops.h>
#include <asm/mmu_context.h>
-#include <asm/processor.h>
#include <asm/system.h>
/*
* Andrew G. Morgan <morgan@transmeta.com>
* Alexander Kjeldaas <astor@guardian.no>
* with help from Aleph1, Roland Buresund and Andrew Main.
+ *
+ * See here for the libcap library ("POSIX draft" compliance):
+ *
+ * ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.2/
*/
#ifndef _LINUX_CAPABILITY_H
@@ -170,8+174,8 @@ typedef __u32 kernel_cap_t;
#define CAP_IPC_OWNER 15
-/* Insert and remove kernel modules */
-
+/* Insert and remove kernel modules - modify kernel without limit */
+/* Modify cap_bset */
#define CAP_SYS_MODULE 16
/* Allow ioperm/iopl access */
@@ -294,12+298,12 @@ extern kernel_cap_t cap_bset; #define CAP_EMPTY_SET to_cap_t(0)
#define CAP_FULL_SET to_cap_t(~0)
#define CAP_INIT_EFF_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
-#define CAP_INIT_INH_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
+#define CAP_INIT_INH_SET to_cap_t(0)
#define CAP_TO_MASK(x) (1 << (x))
#define cap_raise(c, flag) (cap_t(c) |= CAP_TO_MASK(flag))
#define cap_lower(c, flag) (cap_t(c) &= ~CAP_TO_MASK(flag))
-#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag) & cap_bset)
+#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag))
static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b)
{
#define FBIOGET_VBLANK _IOR('F', 0x12, struct fb_vblank)
#define FBIO_ALLOC 0x4613
#define FBIO_FREE 0x4614
+#define FBIOGET_GLYPH 0x4615
+#define FBIOGET_HWCINFO 0x4616
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
#define FB_TYPE_PLANES 1 /* Non interleaved planes */
#define PCI_DEVICE_ID_SI_6205 0x0205
#define PCI_DEVICE_ID_SI_501 0x0406
#define PCI_DEVICE_ID_SI_496 0x0496
+#define PCI_DEVICE_ID_SI_300 0x0300
#define PCI_DEVICE_ID_SI_530 0x0530
-#define PCI_DEVICE_ID_SI_540 0x0540
+#define PCI_DEVICE_ID_SI_540 0x5300
#define PCI_DEVICE_ID_SI_601 0x0601
#define PCI_DEVICE_ID_SI_620 0x0620
-#define PCI_DEVICE_ID_SI_630 0x0630
+#define PCI_DEVICE_ID_SI_630 0x6300
#define PCI_DEVICE_ID_SI_5107 0x5107
#define PCI_DEVICE_ID_SI_5511 0x5511
#define PCI_DEVICE_ID_SI_5513 0x5513
#define PCI_DEVICE_ID_ARK_STING 0xa091
#define PCI_DEVICE_ID_ARK_STINGARK 0xa099
#define PCI_DEVICE_ID_ARK_2000MT 0xa0a1
-
-#define PCI_VENDOR_ID_SIS 0x1039
-#define PCI_DEVICE_ID_SIS_300 0x0300
-#define PCI_DEVICE_ID_SIS_540 0x5300
-#define PCI_DEVICE_ID_SIS_630 0x6300
@@ -233,6+233,25 @@ static struct dev_name_struct { { "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
{ "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
#endif
+#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
+ { "ida/c0d0p",0x4800 },
+ { "ida/c0d1p",0x4810 },
+ { "ida/c0d2p",0x4820 },
+ { "ida/c0d3p",0x4830 },
+ { "ida/c0d4p",0x4840 },
+ { "ida/c0d5p",0x4850 },
+ { "ida/c0d6p",0x4860 },
+ { "ida/c0d7p",0x4870 },
+ { "ida/c0d8p",0x4880 },
+ { "ida/c0d9p",0x4890 },
+ { "ida/c0d10p",0x48A0 },
+ { "ida/c0d11p",0x48B0 },
+ { "ida/c0d12p",0x48C0 },
+ { "ida/c0d13p",0x48D0 },
+ { "ida/c0d14p",0x48E0 },
+ { "ida/c0d15p",0x48F0 },
+#endif
+
{ NULL, 0 }
};
#include <linux/mm.h>
#include <asm/uaccess.h>
+kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
+
/* Note: never hold tasklist_lock while spinning for this one */
spinlock_t task_capability_lock = SPIN_LOCK_UNLOCKED;
@@ -17,8+19,6 @@ spinlock_t task_capability_lock = SPIN_LOCK_UNLOCKED; * uninteresting and/or not to be changed.
*/
-kernel_cap_t cap_bset = CAP_FULL_SET;
-
asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
{
int error, pid;
@@ -95,9+95,8 @@ int exec_usermodehelper(char *program_path, char *argv[], char *envp[]) /* Drop the "current user" thing */
free_uid(current);
- /* Give kmod all privileges.. */
+ /* Give kmod all effective privileges.. */
current->uid = current->euid = current->fsuid = 0;
- cap_set_full(current->cap_inheritable);
cap_set_full(current->cap_effective);
/* Allow execve args to be in kernel space. */
@@ -803,8+803,11 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp, int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp)
{
+ if (!capable(CAP_SYS_MODULE)) {
+ return -EPERM;
+ }
return do_proc_dointvec(table,write,filp,buffer,lenp,1,
- (current->pid == 1) ? OP_SET : OP_AND);
+ (current->pid == 1) ? OP_SET : OP_AND);
}
int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,