Commit a53bc21c authored by Linus Torvalds's avatar Linus Torvalds

Linux-2.4.0-test2

There's a "test2" kernel out there now, integrating most of the -ac
patches, and some code that wasn't in -ac.

Normally, when you integrate almost 5MB of patches, bad things happen.
This time, a miracle occurred. As I uploaded the resultant kernel, a
specter of the holy penguin appeared before me, and said "It is Good. It
is Bugfree".

As if wanting to re-assure me that yes, it really =was= the holy penguin,
it finally added "Do you have any Herring?" before fading out in a puff of
holy penguin-smoke. Only a faint whiff of rancid fish remains as I type in
these words..

In short, not only are most of Alan's patches integrated, I have it on
higher authority that the result is perfect.

So if it doesn't compile for you, you must be doing something wrong.

		Linus
parent a2c3c74c
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
......
......@@ -9,9 +9,11 @@
* 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>
......
......@@ -7,6 +7,7 @@
* 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(&current->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(&current->mm->mmap_sem);
if (error != N_TXTADDR(ex)) {
send_sig(SIGKILL, current, 0);
return error;
}
down(&current->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(&current->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;
......
......@@ -22,7 +22,7 @@
* 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>
......@@ -44,8 +44,8 @@
#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;
{
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;
{
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);
......@@ -405,20 +427,25 @@ void __init cpqarray_init(void)
* 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(
......@@ -426,46 +453,57 @@ void __init cpqarray_init(void)
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_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;
......@@ -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),
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);
}
/*
......@@ -507,102 +537,67 @@ 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 ?? */
#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(PCI_VENDOR_ID_DEC,
PCI_DEVICE_ID_COMPAQ_42XX, index, &bus, &dev_fn))
if (pcibios_find_device(ida_vendor_id[brdtype],
ida_device_id[brdtype], index, &bus, &dev_fn))
break;
printk(KERN_DEBUG "42XX Device has been found at %x %x\n",
bus, dev_fn);
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("This driver supports a maximum of "
"8 controllers.\n");
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));
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 */
for(index=0; ; index++) {
if (ida_device_id[brdtype] == PCI_DEVICE_ID_NCR_53C1510) {
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;
printk(KERN_DEBUG "cpqarray: failed to read subvendor\n");
continue;
}
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;
}
hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
if(hba[nr_ctlr]==NULL)
{
printk(KERN_ERR "cpqarray: out of memory.\n");
printk(KERN_DEBUG
"cpqarray: not a Compaq integrated array controller\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++;
}
for(index=0; ; index++) {
if (pcibios_find_device(PCI_VENDOR_ID_COMPAQ,
PCI_DEVICE_ID_COMPAQ_SMART2P, index, &bus, &dev_fn))
break;
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)
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++;
}
}
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);
);
}
/*
......@@ -1401,16 +1423,16 @@ DBG(
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);
......@@ -1419,9 +1441,9 @@ DBG(
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,7 +1536,8 @@ 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",
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_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
*
......@@ -39,7 +39,7 @@
#include <linux/input.h>
struct evdev {
int used;
int exist;
int open;
int minor;
struct input_handle handle;
......@@ -99,14 +99,15 @@ static int evdev_release(struct inode * inode, struct file * file)
listptr = &((*listptr)->next);
*listptr = (*listptr)->next;
if (!--list->evdev->open)
if (!--list->evdev->open) {
if (list->evdev->exist) {
input_close_device(&list->evdev->handle);
if (!--list->evdev->used) {
} 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,9 +132,8 @@ static int evdev_open(struct inode * inode, struct file * file)
file->private_data = list;
list->evdev->used++;
if (!list->evdev->open++)
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 Colin Van Dyke
......@@ -50,7 +50,7 @@
#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,14 +168,15 @@ static int joydev_release(struct inode * inode, struct file * file)
listptr = &((*listptr)->next);
*listptr = (*listptr)->next;
if (!--list->joydev->open)
if (!--list->joydev->open) {
if (list->joydev->exist) {
input_close_device(&list->joydev->handle);
if (!--list->joydev->used) {
} 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,9 +201,8 @@ static int joydev_open(struct inode *inode, struct file *file)
file->private_data = list;
list->joydev->used++;
if (!list->joydev->open++)
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
*
......@@ -47,7 +47,7 @@
#endif
struct mousedev {
int used;
int exist;
int open;
int minor;
wait_queue_head_t wait;
......@@ -172,21 +172,29 @@ 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)
if (!mousedev_mix.open) {
if (list->mousedev->exist) {
input_close_device(&list->mousedev->handle);
}
}
if (!--list->mousedev->used) {
} else {
input_unregister_minor(list->mousedev->devfs);
mousedev_table[list->mousedev->minor] = NULL;
kfree(list->mousedev);
}
}
}
}
kfree(list);
......@@ -210,19 +218,19 @@ 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)
if (mousedev->exist)
input_open_device(handle);
handle = handle->hnext;
}
} else {
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>
......@@ -16,7 +42,7 @@
#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,6 +643,11 @@ 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);
......@@ -516,6 +669,8 @@ static void pegasus_disconnect(struct usb_device *dev, void *ptr)
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 )
......
......@@ -14,6 +14,9 @@
*
* 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,7 +875,9 @@ 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;
}
......
......@@ -11,6 +11,9 @@
*
* 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
......@@ -22,6 +27,20 @@
*
* 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 */
......@@ -977,24 +1001,16 @@ static void ATAPI_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 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
......
......@@ -43,9 +43,10 @@
#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
......@@ -115,7 +116,8 @@
#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;
}
......
......@@ -30,8 +30,6 @@
#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 */
......
......@@ -30,7 +30,6 @@
#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
/*
......
......@@ -15,8 +15,6 @@
#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
#include <asm/segment.h>
#define NFSDBG_FACILITY NFSDBG_PROC
/*
......
......@@ -42,8 +42,6 @@
#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 */
}
......
......@@ -30,7 +30,6 @@
#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),
......
......@@ -700,15 +700,7 @@ encode_entry(struct readdir_cd *cd, const char *name,
}
*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_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 */
......
......@@ -414,9 +414,7 @@ nfssvc_encode_entry(struct readdir_cd *cd, const char *name,
}
*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_encode_array(p, name, namlen);/* name length & name */
cd->offset = p; /* remember pointer */
*p++ = ~(u32) 0; /* offset of next entry */
......
......@@ -30,6 +30,8 @@
#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>
/*
......
......@@ -12,8 +12,6 @@
* 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>
......@@ -113,7 +111,6 @@
#include <asm/bitops.h>
#include <asm/mmu_context.h>
#include <asm/processor.h>
#include <asm/system.h>
/*
......
......@@ -4,6 +4,10 @@
* 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)
{
......
......@@ -27,6 +27,8 @@
#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 */
......
......@@ -329,11 +329,12 @@
#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
......@@ -1284,8 +1285,3 @@
#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 }
};
......
......@@ -8,6 +8,8 @@
#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,6 +803,9 @@ 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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment