Commit 1975448f authored by Linus Torvalds's avatar Linus Torvalds Committed by Linus Torvalds

Merge http://linux-scsi.bkbits.net/scsi-for-linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents df4b68ca f4aa5d56
...@@ -45,7 +45,8 @@ const unsigned char scsi_command_size[8] = ...@@ -45,7 +45,8 @@ const unsigned char scsi_command_size[8] =
#define SCSI_SENSE_BUFFERSIZE 64 #define SCSI_SENSE_BUFFERSIZE 64
#endif #endif
int blk_do_rq(request_queue_t *q, struct block_device *bdev, struct request *rq) static int blk_do_rq(request_queue_t *q, struct block_device *bdev,
struct request *rq)
{ {
DECLARE_COMPLETION(wait); DECLARE_COMPLETION(wait);
int err = 0; int err = 0;
...@@ -368,6 +369,7 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev, ...@@ -368,6 +369,7 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev,
goto error; goto error;
switch (opcode) { switch (opcode) {
case SEND_DIAGNOSTIC:
case FORMAT_UNIT: case FORMAT_UNIT:
rq->timeout = FORMAT_UNIT_TIMEOUT; rq->timeout = FORMAT_UNIT_TIMEOUT;
break; break;
...@@ -398,7 +400,8 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev, ...@@ -398,7 +400,8 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev,
if (in_len) if (in_len)
rq->flags |= REQ_RW; rq->flags |= REQ_RW;
err = blk_do_rq(q, bdev, rq); blk_do_rq(q, bdev, rq);
err = rq->errors & 0xff; /* only 8 bit SCSI status */
if (err) { if (err) {
if (rq->sense_len) if (rq->sense_len)
if (copy_to_user(sic->data, rq->sense, rq->sense_len)) if (copy_to_user(sic->data, rq->sense, rq->sense_len))
......
...@@ -1715,6 +1715,11 @@ config SCSI_PC980155 ...@@ -1715,6 +1715,11 @@ config SCSI_PC980155
If you have the NEC PC-9801-55 SCSI interface card or compatibles If you have the NEC PC-9801-55 SCSI interface card or compatibles
for NEC PC-9801/PC-9821, say Y. for NEC PC-9801/PC-9821, say Y.
config WD33C93_PIO
bool
depends on SCSI_PC980155
default y
# bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI # bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI
# bool 'GVP Turbo 040/060 SCSI support (EXPERIMENTAL)' CONFIG_GVP_TURBO_SCSI # bool 'GVP Turbo 040/060 SCSI support (EXPERIMENTAL)' CONFIG_GVP_TURBO_SCSI
endmenu endmenu
......
...@@ -29,6 +29,7 @@ obj-$(CONFIG_WARPENGINE_SCSI) += amiga7xx.o 53c7xx.o ...@@ -29,6 +29,7 @@ obj-$(CONFIG_WARPENGINE_SCSI) += amiga7xx.o 53c7xx.o
obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o
obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o
obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o
obj-$(CONFIG_SCSI_PC980155) += pc980155.o wd33c93.o
obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o
obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o
obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o
......
...@@ -221,11 +221,6 @@ ...@@ -221,11 +221,6 @@
**************************************************************************/ **************************************************************************/
#include <linux/module.h> #include <linux/module.h>
#if defined(PCMCIA)
#undef MODULE
#endif
#include <linux/sched.h> #include <linux/sched.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -244,14 +239,16 @@ ...@@ -244,14 +239,16 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/isapnp.h> #include <linux/isapnp.h>
#include <asm/semaphore.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/blk.h>
#include <asm/semaphore.h>
#include <asm/io.h>
#include <scsi/scsicam.h>
#include "scsi.h"
#include "aha152x.h" #include "aha152x.h"
#include <linux/stat.h>
#include <linux/workqueue.h>
#include <scsi/scsicam.h>
/* DEFINES */ /* DEFINES */
...@@ -338,11 +335,11 @@ enum { ...@@ -338,11 +335,11 @@ enum {
resetting = 0x0400, /* BUS DEVICE RESET is pending */ resetting = 0x0400, /* BUS DEVICE RESET is pending */
}; };
#if defined(MODULE)
MODULE_AUTHOR("Jürgen Fischer"); MODULE_AUTHOR("Jürgen Fischer");
MODULE_DESCRIPTION(AHA152X_REVID); MODULE_DESCRIPTION(AHA152X_REVID);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#if defined(MODULE) && !defined(PCMCIA)
MODULE_PARM(io, "1-2i"); MODULE_PARM(io, "1-2i");
MODULE_PARM_DESC(io,"base io address of controller"); MODULE_PARM_DESC(io,"base io address of controller");
static int io[] = {0, 0}; static int io[] = {0, 0};
...@@ -396,6 +393,7 @@ MODULE_PARM(aha152x1, "1-9i"); ...@@ -396,6 +393,7 @@ MODULE_PARM(aha152x1, "1-9i");
MODULE_PARM_DESC(aha152x1, "parameters for second controller"); MODULE_PARM_DESC(aha152x1, "parameters for second controller");
static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT};
#endif /* !defined(AHA152X_DEBUG) */ #endif /* !defined(AHA152X_DEBUG) */
#endif /* MODULE && !PCMCIA */
#ifdef __ISAPNP__ #ifdef __ISAPNP__
static struct isapnp_device_id id_table[] __devinitdata = { static struct isapnp_device_id id_table[] __devinitdata = {
...@@ -404,28 +402,13 @@ static struct isapnp_device_id id_table[] __devinitdata = { ...@@ -404,28 +402,13 @@ static struct isapnp_device_id id_table[] __devinitdata = {
}; };
MODULE_DEVICE_TABLE(isapnp, id_table); MODULE_DEVICE_TABLE(isapnp, id_table);
#endif /* ISAPNP */ #endif /* ISAPNP */
#endif /* MODULE */
/* set by aha152x_setup according to the command line */ /* set by aha152x_setup according to the command line */
static int setup_count = 0; static int setup_count;
static int registered_count = 0; static int registered_count;
static struct aha152x_setup { static struct aha152x_setup setup[2];
int io_port;
int irq;
int scsiid;
int reconnect;
int parity;
int synchronous;
int delay;
int ext_trans;
int tc1550;
#if defined(AHA152X_DEBUG)
int debug;
#endif
char *conf;
} setup[2];
static struct Scsi_Host *aha152x_host[2]; static struct Scsi_Host *aha152x_host[2];
static Scsi_Host_Template aha152x_driver_template;
/* /*
* internal states of the host * internal states of the host
...@@ -809,7 +792,7 @@ static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, Scsi_Cmnd *SCp) ...@@ -809,7 +792,7 @@ static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, Scsi_Cmnd *SCp)
} }
#if defined(PCMCIA) || !defined(MODULE) #if defined(PCMCIA) || !defined(MODULE)
void aha152x_setup(char *str, int *ints) static void aha152x_setup(char *str, int *ints)
{ {
if(setup_count>=ARRAY_SIZE(setup)) { if(setup_count>=ARRAY_SIZE(setup)) {
printk(KERN_ERR "aha152x: you can only configure up to two controllers\n"); printk(KERN_ERR "aha152x: you can only configure up to two controllers\n");
...@@ -835,10 +818,8 @@ void aha152x_setup(char *str, int *ints) ...@@ -835,10 +818,8 @@ void aha152x_setup(char *str, int *ints)
printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>" printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
"[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n"); "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
#endif #endif
return;
} else { } else {
setup_count++; setup_count++;
return;
} }
} }
#endif #endif
...@@ -973,7 +954,142 @@ static void swintr(int irqno, void *dev_id, struct pt_regs *regs) ...@@ -973,7 +954,142 @@ static void swintr(int irqno, void *dev_id, struct pt_regs *regs)
static struct pnp_dev *pnpdev[2]; static struct pnp_dev *pnpdev[2];
static int num_pnpdevs; static int num_pnpdevs;
#endif #endif
int aha152x_detect(Scsi_Host_Template * tpnt)
struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
{
struct Scsi_Host *shost, *shpnt;
struct aha152x_hostdata *aha;
/* XXX: shpnt is needed for some broken macros */
shost = shpnt = scsi_register(&aha152x_driver_template,
sizeof(struct aha152x_hostdata));
if (!shost) {
printk(KERN_ERR "aha152x: scsi_register failed\n");
return NULL;
}
aha = (struct aha152x_hostdata *)&shost->hostdata;
memset(aha, 0, sizeof(*aha));
shost->io_port = setup->io_port;
shost->n_io_port = IO_RANGE;
shost->irq = setup->irq;
if (!setup->tc1550) {
aha->io_port0 = setup->io_port;
aha->io_port1 = setup->io_port;
} else {
aha->io_port0 = setup->io_port+0x10;
aha->io_port1 = setup->io_port-0x10;
}
spin_lock_init(&aha->lock);
aha->reconnect = setup->reconnect;
aha->synchronous = setup->synchronous;
aha->parity = setup->parity;
aha->delay = setup->delay;
aha->ext_trans = setup->ext_trans;
#if defined(AHA152X_DEBUG)
aha->debug = setup->debug;
#endif
SETPORT(SCSIID, setup->scsiid << 4);
shost->this_id = setup->scsiid;
if (setup->reconnect)
shost->can_queue = AHA152X_MAXQUEUE;
/* RESET OUT */
printk("aha152x: resetting bus...\n");
SETPORT(SCSISEQ, SCSIRSTO);
mdelay(256);
SETPORT(SCSISEQ, 0);
mdelay(DELAY);
reset_ports(shost);
printk(KERN_INFO
"aha152x%d%s: "
"vital data: rev=%x, "
"io=0x%03lx (0x%03lx/0x%03lx), "
"irq=%d, "
"scsiid=%d, "
"reconnect=%s, "
"parity=%s, "
"synchronous=%s, "
"delay=%d, "
"extended translation=%s\n",
shost->host_no, setup->tc1550 ? " (tc1550 mode)" : "",
GETPORT(REV) & 0x7,
shost->io_port, aha->io_port0, aha->io_port1,
shost->irq,
shost->this_id,
aha->reconnect ? "enabled" : "disabled",
aha->parity ? "enabled" : "disabled",
aha->synchronous ? "enabled" : "disabled",
aha->delay,
aha->ext_trans ? "enabled" : "disabled");
if (!request_region(shost->io_port, IO_RANGE, "aha152x"))
goto out_unregister;
/* not expecting any interrupts */
SETPORT(SIMODE0, 0);
SETPORT(SIMODE1, 0);
if (request_irq(shost->irq, swintr, SA_INTERRUPT|SA_SHIRQ,
"aha152x", shost) < 0) {
printk(KERN_ERR "aha152x%d: driver needs an IRQ.\n", shost->host_no);
goto out_release_region;
}
aha->swint = 0;
printk(KERN_INFO "aha152x%d: trying software interrupt, ",
shost->host_no);
SETPORT(DMACNTRL0, SWINT|INTEN);
mdelay(1000);
free_irq(shost->irq, shost);
if (!aha->swint) {
if (TESTHI(DMASTAT, INTSTAT)) {
printk("lost.\n");
} else {
printk("failed.\n");
}
SETPORT(DMACNTRL0, INTEN);
printk(KERN_ERR "aha152x%d: IRQ %d possibly wrong. "
"Please verify.\n", shost->host_no, shost->irq);
goto out_release_region;
}
printk("ok.\n");
/* clear interrupts */
SETPORT(SSTAT0, 0x7f);
SETPORT(SSTAT1, 0xef);
if (request_irq(shost->irq, intr, SA_INTERRUPT|SA_SHIRQ,
"aha152x", shost) < 0) {
printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n",
shost->host_no);
goto out_release_region;
}
aha152x_host[registered_count] = shost;
return shost; /* the pcmcia stub needs the return value; */
out_release_region:
release_region(shost->io_port, IO_RANGE);
out_unregister:
scsi_unregister(shost);
return NULL;
}
static int aha152x_detect(Scsi_Host_Template * tpnt)
{ {
int i, j, ok; int i, j, ok;
#if defined(AUTOCONF) #if defined(AUTOCONF)
...@@ -982,10 +1098,6 @@ int aha152x_detect(Scsi_Host_Template * tpnt) ...@@ -982,10 +1098,6 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
struct pnp_dev *dev = NULL; struct pnp_dev *dev = NULL;
#endif #endif
#endif #endif
tpnt->proc_name = "aha152x";
for (i = 0; i < ARRAY_SIZE(aha152x_host); i++)
aha152x_host[i] = (struct Scsi_Host *) NULL;
if (setup_count) { if (setup_count) {
printk(KERN_INFO "aha152x: processing commandline: "); printk(KERN_INFO "aha152x: processing commandline: ");
...@@ -1040,7 +1152,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) ...@@ -1040,7 +1152,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
} }
#endif #endif
#if defined(MODULE) #if defined(MODULE) && !defined(PCMCIA)
if (setup_count<ARRAY_SIZE(setup) && (aha152x[0]!=0 || io[0]!=0 || irq[0]!=0)) { if (setup_count<ARRAY_SIZE(setup) && (aha152x[0]!=0 || io[0]!=0 || irq[0]!=0)) {
if(aha152x[0]!=0) { if(aha152x[0]!=0) {
setup[setup_count].conf = ""; setup[setup_count].conf = "";
...@@ -1234,185 +1346,16 @@ int aha152x_detect(Scsi_Host_Template * tpnt) ...@@ -1234,185 +1346,16 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
printk("detected %d controller(s)\n", setup_count); printk("detected %d controller(s)\n", setup_count);
for (i=0; i<setup_count; i++) { for (i=0; i<setup_count; i++) {
struct Scsi_Host *shpnt; aha152x_probe_one(&setup[i]);
if (aha152x_host[registered_count])
aha152x_host[registered_count] = shpnt =
scsi_register(tpnt, sizeof(struct aha152x_hostdata));
if(!shpnt) {
printk(KERN_ERR "aha152x: scsi_register failed\n");
continue;
}
registered_count++; registered_count++;
shpnt->io_port = setup[i].io_port;
shpnt->n_io_port = IO_RANGE;
shpnt->irq = setup[i].irq;
if(!setup[i].tc1550) {
HOSTIOPORT0 = setup[i].io_port;
HOSTIOPORT1 = setup[i].io_port;
} else {
HOSTIOPORT0 = setup[i].io_port+0x10;
HOSTIOPORT1 = setup[i].io_port-0x10;
}
ISSUE_SC = 0;
CURRENT_SC = 0;
DONE_SC = 0;
DISCONNECTED_SC = 0;
QLOCK = SPIN_LOCK_UNLOCKED;
STATE = 0;
PREVSTATE = 0;
LASTSTATE = 0;
MSGILEN = 0;
MSGOLEN = 0;
RECONNECT = setup[i].reconnect;
SYNCHRONOUS = setup[i].synchronous;
PARITY = setup[i].parity;
DELAY = setup[i].delay;
EXT_TRANS = setup[i].ext_trans;
#if defined(AHA152X_DEBUG)
HOSTDATA(shpnt)->debug = setup[i].debug;
#endif
HOSTDATA(shpnt)->in_intr = 0;
HOSTDATA(shpnt)->commands = 0;
#if defined(AHA152X_STAT)
HOSTDATA(shpnt)->total_commands=0;
HOSTDATA(shpnt)->disconnections=0;
HOSTDATA(shpnt)->busfree_without_any_action=0;
HOSTDATA(shpnt)->busfree_without_old_command=0;
HOSTDATA(shpnt)->busfree_without_new_command=0;
HOSTDATA(shpnt)->busfree_without_done_command=0;
HOSTDATA(shpnt)->busfree_with_check_condition=0;
for (j = idle; j<maxstate; j++) {
HOSTDATA(shpnt)->count[j]=0;
HOSTDATA(shpnt)->count_trans[j]=0;
HOSTDATA(shpnt)->time[j]=0;
}
#endif
for (j = 0; j < 8; j++) {
HOSTDATA(shpnt)->syncrate[j] = 0;
HOSTDATA(shpnt)->syncneg[j] = 0;
}
SETPORT(SCSIID, setup[i].scsiid << 4);
shpnt->this_id = setup[i].scsiid;
if (setup[i].reconnect)
shpnt->can_queue = AHA152X_MAXQUEUE;
/* RESET OUT */
printk("aha152x: resetting bus...\n");
SETPORT(SCSISEQ, SCSIRSTO);
mdelay(256);
SETPORT(SCSISEQ, 0);
mdelay(DELAY);
reset_ports(shpnt);
printk(KERN_INFO
"aha152x%d%s: "
"vital data: rev=%x, "
"io=0x%03lx (0x%03lx/0x%03lx), "
"irq=%d, "
"scsiid=%d, "
"reconnect=%s, "
"parity=%s, "
"synchronous=%s, "
"delay=%d, "
"extended translation=%s\n",
HOSTNO, setup[i].tc1550 ? " (tc1550 mode)" : "",
GETPORT(REV) & 0x7,
shpnt->io_port, HOSTIOPORT0, HOSTIOPORT1,
shpnt->irq,
shpnt->this_id,
RECONNECT ? "enabled" : "disabled",
PARITY ? "enabled" : "disabled",
SYNCHRONOUS ? "enabled" : "disabled",
DELAY,
EXT_TRANS ? "enabled" : "disabled");
request_region(shpnt->io_port, IO_RANGE, "aha152x");
/* not expecting any interrupts */
SETPORT(SIMODE0, 0);
SETPORT(SIMODE1, 0);
ok = request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt);
if (ok < 0) {
if (ok==-EINVAL)
printk(KERN_ERR "aha152x%d: bad IRQ %d.\n", HOSTNO, shpnt->irq);
else if(ok==-EBUSY)
printk(KERN_ERR "aha152x%d: IRQ %d already in use.\n", HOSTNO, shpnt->irq);
else
printk(KERN_ERR "aha152x%d: Unexpected error code %d on requesting IRQ %d.\n", HOSTNO, ok, shpnt->irq);
printk(KERN_ERR "aha152x%d: driver needs an IRQ.\n", HOSTNO);
scsi_unregister(shpnt);
registered_count--;
release_region(shpnt->io_port, IO_RANGE);
aha152x_host[registered_count] = 0;
shpnt = 0;
continue;
}
HOSTDATA(shpnt)->swint = 0;
printk(KERN_INFO "aha152x%d: trying software interrupt, ", HOSTNO);
SETPORT(DMACNTRL0, SWINT|INTEN);
mdelay(1000);
free_irq(shpnt->irq, shpnt);
if (!HOSTDATA(shpnt)->swint) {
if (TESTHI(DMASTAT, INTSTAT)) {
printk("lost.\n");
} else {
printk("failed.\n");
}
SETPORT(DMACNTRL0, INTEN);
printk(KERN_ERR "aha152x%d: IRQ %d possibly wrong. Please verify.\n", HOSTNO, shpnt->irq);
registered_count--;
release_region(shpnt->io_port, IO_RANGE);
aha152x_host[registered_count] = 0;
scsi_unregister(shpnt);
shpnt=NULL;
continue;
}
printk("ok.\n");
/* clear interrupts */
SETPORT(SSTAT0, 0x7f);
SETPORT(SSTAT1, 0xef);
if (request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) < 0) {
printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n", HOSTNO);
registered_count--;
release_region(shpnt->io_port, IO_RANGE);
aha152x_host[registered_count] = 0;
scsi_unregister(shpnt);
shpnt=NULL;
continue;
}
} }
return registered_count>0; return registered_count>0;
} }
int aha152x_release(struct Scsi_Host *shpnt) static int aha152x_release(struct Scsi_Host *shpnt)
{ {
if (shpnt->irq) if (shpnt->irq)
free_irq(shpnt->irq, shpnt); free_irq(shpnt->irq, shpnt);
...@@ -1474,7 +1417,7 @@ static int setup_expected_interrupts(struct Scsi_Host *shpnt) ...@@ -1474,7 +1417,7 @@ static int setup_expected_interrupts(struct Scsi_Host *shpnt)
/* /*
* Queue a command and setup interrupts for a free bus. * Queue a command and setup interrupts for a free bus.
*/ */
int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, Scsi_Cmnd *done_SC, void (*done)(Scsi_Cmnd *)) static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, Scsi_Cmnd *done_SC, void (*done)(Scsi_Cmnd *))
{ {
struct Scsi_Host *shpnt = SCpnt->device->host; struct Scsi_Host *shpnt = SCpnt->device->host;
unsigned long flags; unsigned long flags;
...@@ -1543,7 +1486,7 @@ int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, S ...@@ -1543,7 +1486,7 @@ int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, S
return 0; return 0;
} }
int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) static int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{ {
#if 0 #if 0
if(*SCpnt->cmnd == REQUEST_SENSE) { if(*SCpnt->cmnd == REQUEST_SENSE) {
...@@ -1562,7 +1505,7 @@ int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -1562,7 +1505,7 @@ int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
* run a command * run a command
* *
*/ */
void internal_done(Scsi_Cmnd *SCpnt) static void internal_done(Scsi_Cmnd *SCpnt)
{ {
#if 0 #if 0
struct Scsi_Host *shpnt = SCpnt->host; struct Scsi_Host *shpnt = SCpnt->host;
...@@ -1573,7 +1516,7 @@ void internal_done(Scsi_Cmnd *SCpnt) ...@@ -1573,7 +1516,7 @@ void internal_done(Scsi_Cmnd *SCpnt)
up(SCSEM(SCpnt)); up(SCSEM(SCpnt));
} }
int aha152x_command(Scsi_Cmnd * SCpnt) static int aha152x_command(Scsi_Cmnd * SCpnt)
{ {
DECLARE_MUTEX_LOCKED(sem); DECLARE_MUTEX_LOCKED(sem);
...@@ -1587,7 +1530,7 @@ int aha152x_command(Scsi_Cmnd * SCpnt) ...@@ -1587,7 +1530,7 @@ int aha152x_command(Scsi_Cmnd * SCpnt)
* Abort a command * Abort a command
* *
*/ */
int aha152x_abort(Scsi_Cmnd *SCpnt) static int aha152x_abort(Scsi_Cmnd *SCpnt)
{ {
struct Scsi_Host *shpnt = SCpnt->device->host; struct Scsi_Host *shpnt = SCpnt->device->host;
Scsi_Cmnd *ptr; Scsi_Cmnd *ptr;
...@@ -1661,7 +1604,7 @@ static void timer_expired(unsigned long p) ...@@ -1661,7 +1604,7 @@ static void timer_expired(unsigned long p)
* FIXME: never seen this live. might lockup... * FIXME: never seen this live. might lockup...
* *
*/ */
int aha152x_device_reset(Scsi_Cmnd * SCpnt) static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
{ {
struct Scsi_Host *shpnt = SCpnt->device->host; struct Scsi_Host *shpnt = SCpnt->device->host;
DECLARE_MUTEX_LOCKED(sem); DECLARE_MUTEX_LOCKED(sem);
...@@ -1719,7 +1662,7 @@ int aha152x_device_reset(Scsi_Cmnd * SCpnt) ...@@ -1719,7 +1662,7 @@ int aha152x_device_reset(Scsi_Cmnd * SCpnt)
return ret; return ret;
} }
void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs) static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs)
{ {
Scsi_Cmnd *ptr; Scsi_Cmnd *ptr;
unsigned long flags; unsigned long flags;
...@@ -1748,7 +1691,7 @@ void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs) ...@@ -1748,7 +1691,7 @@ void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs)
* Reset the bus * Reset the bus
* *
*/ */
int aha152x_bus_reset(Scsi_Cmnd *SCpnt) static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
{ {
struct Scsi_Host *shpnt = SCpnt->device->host; struct Scsi_Host *shpnt = SCpnt->device->host;
unsigned long flags; unsigned long flags;
...@@ -1843,7 +1786,7 @@ int aha152x_host_reset(Scsi_Cmnd * SCpnt) ...@@ -1843,7 +1786,7 @@ int aha152x_host_reset(Scsi_Cmnd * SCpnt)
* Return the "logical geometry" * Return the "logical geometry"
* *
*/ */
int aha152x_biosparam(struct scsi_device *sdev, struct block_device *bdev, static int aha152x_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int *info_array) sector_t capacity, int *info_array)
{ {
struct Scsi_Host *shpnt = sdev->host; struct Scsi_Host *shpnt = sdev->host;
...@@ -3744,7 +3687,7 @@ static int get_ports(struct Scsi_Host *shpnt, char *pos) ...@@ -3744,7 +3687,7 @@ static int get_ports(struct Scsi_Host *shpnt, char *pos)
return (pos - start); return (pos - start);
} }
int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt) static int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
{ {
if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0) if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0)
return -EINVAL; return -EINVAL;
...@@ -3791,7 +3734,7 @@ int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt) ...@@ -3791,7 +3734,7 @@ int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
#define SPRINTF(args...) \ #define SPRINTF(args...) \
do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0) do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
int aha152x_proc_info(char *buffer, char **start, static int aha152x_proc_info(char *buffer, char **start,
off_t offset, int length, int hostno, int inout) off_t offset, int length, int hostno, int inout)
{ {
int i; int i;
...@@ -3935,7 +3878,28 @@ int aha152x_proc_info(char *buffer, char **start, ...@@ -3935,7 +3878,28 @@ int aha152x_proc_info(char *buffer, char **start,
return thislength < length ? thislength : length; return thislength < length ? thislength : length;
} }
/* Eventually this will go into an include file, but this will be later */ static Scsi_Host_Template aha152x_driver_template = {
static Scsi_Host_Template driver_template = AHA152X; .module = THIS_MODULE,
.name = AHA152X_REVID,
.proc_name = "aha152x",
.proc_info = aha152x_proc_info,
.detect = aha152x_detect,
.command = aha152x_command,
.queuecommand = aha152x_queue,
.eh_abort_handler = aha152x_abort,
.eh_device_reset_handler = aha152x_device_reset,
.eh_bus_reset_handler = aha152x_bus_reset,
.eh_host_reset_handler = aha152x_host_reset,
.release = aha152x_release,
.bios_param = aha152x_biosparam,
.can_queue = 1,
.this_id = 7,
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = DISABLE_CLUSTERING,
};
#ifndef PCMCIA
#define driver_template aha152x_driver_template
#include "scsi_module.c" #include "scsi_module.c"
#endif
...@@ -5,54 +5,12 @@ ...@@ -5,54 +5,12 @@
* $Id: aha152x.h,v 2.5 2002/04/14 11:24:12 fischer Exp $ * $Id: aha152x.h,v 2.5 2002/04/14 11:24:12 fischer Exp $
*/ */
#if defined(__KERNEL__)
#include <linux/blk.h>
#include "scsi.h"
#include <asm/io.h>
#include <linux/version.h>
int aha152x_detect(Scsi_Host_Template *);
int aha152x_command(Scsi_Cmnd *);
int aha152x_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int aha152x_abort(Scsi_Cmnd *);
int aha152x_release(struct Scsi_Host *shpnt);
int aha152x_device_reset(Scsi_Cmnd *);
int aha152x_bus_reset(Scsi_Cmnd *);
int aha152x_host_reset(Scsi_Cmnd *);
int aha152x_biosparam(struct scsi_device *, struct block_device *,
sector_t, int*);
int aha152x_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout);
/* number of queueable commands /* number of queueable commands
(unless we support more than 1 cmd_per_lun this should do) */ (unless we support more than 1 cmd_per_lun this should do) */
#define AHA152X_MAXQUEUE 7 #define AHA152X_MAXQUEUE 7
#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.5 $" #define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.5 $"
/* Initial value of Scsi_Host entry */
#define AHA152X { .proc_name = "aha152x", \
.proc_info = aha152x_proc_info, \
.name = AHA152X_REVID, \
.detect = aha152x_detect, \
.command = aha152x_command, \
.queuecommand = aha152x_queue, \
.eh_abort_handler = aha152x_abort, \
.eh_device_reset_handler = aha152x_device_reset, \
.eh_bus_reset_handler = aha152x_bus_reset, \
.eh_host_reset_handler = aha152x_host_reset, \
.release = aha152x_release, \
.bios_param = aha152x_biosparam, \
.can_queue = 1, \
.this_id = 7, \
.sg_tablesize = SG_ALL, \
.cmd_per_lun = 1, \
.present = 0, \
.unchecked_isa_dma = 0, \
.use_clustering = DISABLE_CLUSTERING }
#endif
/* port addresses */ /* port addresses */
#define SCSISEQ (HOSTIOPORT0+0x00) /* SCSI sequence control */ #define SCSISEQ (HOSTIOPORT0+0x00) /* SCSI sequence control */
#define SXFRCTL0 (HOSTIOPORT0+0x01) /* SCSI transfer control 0 */ #define SXFRCTL0 (HOSTIOPORT0+0x01) /* SCSI transfer control 0 */
...@@ -355,4 +313,24 @@ enum { ...@@ -355,4 +313,24 @@ enum {
}; };
#endif #endif
/* for the pcmcia stub */
struct aha152x_setup {
int io_port;
int irq;
int scsiid;
int reconnect;
int parity;
int synchronous;
int delay;
int ext_trans;
int tc1550;
#if defined(AHA152X_DEBUG)
int debug;
#endif
char *conf;
};
struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *);
int aha152x_host_reset(struct scsi_cmnd *);
#endif /* _AHA152X_H */ #endif /* _AHA152X_H */
/*
*
* drivers/scsi/pc980155.c
*
* PC-9801-55 SCSI host adapter driver
*
* Copyright (C) 1997-2003 Kyoto University Microcomputer Club
* (Linux/98 project)
* Tomoharu Ugawa <ohirune@kmc.gr.jp>
*
*/
#include <linux/module.h>
#include <linux/blk.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <asm/dma.h>
#include "scsi.h"
#include "hosts.h"
#include "wd33c93.h"
#include "pc980155.h"
extern int pc98_bios_param(struct scsi_device *, struct block_device *,
sector_t, int *);
static int scsi_pc980155_detect(Scsi_Host_Template *);
static int scsi_pc980155_release(struct Scsi_Host *);
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
#endif
#ifndef CAN_QUEUE
#define CAN_QUEUE 16
#endif
#undef PC_9801_55_DEBUG
#undef PC_9801_55_DEBUG_VERBOSE
#define NR_BASE_IOS 4
static int nr_base_ios = NR_BASE_IOS;
static unsigned int base_ios[NR_BASE_IOS] = {0xcc0, 0xcd0, 0xce0, 0xcf0};
static wd33c93_regs init_regs;
static int io;
static struct Scsi_Host *pc980155_host = NULL;
static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp);
static inline void pc980155_dma_enable(unsigned int base_io)
{
outb(0x01, REG_CWRITE);
}
static inline void pc980155_dma_disable(unsigned int base_io)
{
outb(0x02, REG_CWRITE);
}
static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp)
{
wd33c93_intr(pc980155_host);
}
static int dma_setup(Scsi_Cmnd *sc, int dir_in)
{
/*
* sc->SCp.this_residual : transfer count
* sc->SCp.ptr : distination address (virtual address)
* dir_in : data direction (DATA_OUT_DIR:0 or DATA_IN_DIR:1)
*
* if success return 0
*/
/*
* DMA WRITE MODE
* bit 7,6 01b single mode (this mode only)
* bit 5 inc/dec (default:0 = inc)
* bit 4 auto initialize (normaly:0 = off)
* bit 3,2 01b memory -> io
* 10b io -> memory
* 00b verify
* bit 1,0 channel
*/
disable_dma(sc->device->host->dma_channel);
set_dma_mode(sc->device->host->dma_channel,
0x40 | (dir_in ? 0x04 : 0x08));
clear_dma_ff(sc->device->host->dma_channel);
set_dma_addr(sc->device->host->dma_channel, virt_to_phys(sc->SCp.ptr));
set_dma_count(sc->device->host->dma_channel, sc->SCp.this_residual);
#ifdef PC_9801_55_DEBUG
printk("D%d(%x)D", sc->device->host->dma_channel,
sc->SCp.this_residual);
#endif
enable_dma(sc->device->host->dma_channel);
pc980155_dma_enable(sc->device->host->io_port);
return 0;
}
static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *sc, int status)
{
/*
* instance: Hostadapter's instance
* sc: scsi command
* status: True if success
*/
pc980155_dma_disable(sc->device->host->io_port);
disable_dma(sc->device->host->dma_channel);
}
/* return non-zero on detection */
static inline int pc980155_test_port(wd33c93_regs regs)
{
/* Quick and dirty test for presence of the card. */
if (inb(regs.SASR) == 0xff)
return 0;
return 1;
}
static inline int pc980155_getconfig(unsigned int base_io, wd33c93_regs regs,
unsigned char* irq, unsigned char* dma,
unsigned char* scsi_id)
{
static unsigned char irqs[] = {3, 5, 6, 9, 12, 13};
unsigned char result;
printk(KERN_DEBUG "PC-9801-55: base_io=%x SASR=%x SCMD=%x\n",
base_io, regs.SASR, regs.SCMD);
result = read_pc980155_resetint(regs);
printk(KERN_DEBUG "PC-9801-55: getting config (%x)\n", result);
*scsi_id = result & 0x07;
*irq = (result >> 3) & 0x07;
if (*irq > 5) {
printk(KERN_ERR "PC-9801-55 (base %#x): impossible IRQ (%d)"
" - other device here?\n", base_io, *irq);
return 0;
}
*irq = irqs[*irq];
result = inb(REG_STATRD);
*dma = result & 0x03;
if (*dma == 1) {
printk(KERN_ERR
"PC-9801-55 (base %#x): impossible DMA channl (%d)"
" - other device here?\n", base_io, *dma);
return 0;
}
#ifdef PC_9801_55_DEBUG
printk("PC-9801-55: end of getconfig\n");
#endif
return 1;
}
/* return non-zero on detection */
static int scsi_pc980155_detect(Scsi_Host_Template* tpnt)
{
unsigned int base_io;
unsigned char irq, dma, scsi_id;
int i;
#ifdef PC_9801_55_DEBUG
unsigned char debug;
#endif
if (io) {
base_ios[0] = io;
nr_base_ios = 1;
}
for (i = 0; i < nr_base_ios; i++) {
base_io = base_ios[i];
init_regs.SASR = REG_ADDRST;
init_regs.SCMD = REG_CONTRL;
#ifdef PC_9801_55_DEBUG
printk("PC-9801-55: SASR(%x = %x)\n", SASR, REG_ADDRST);
#endif
if (!request_region(base_io, 6, "PC-9801-55"))
continue;
if (pc980155_test_port(init_regs) &&
pc980155_getconfig(base_io, init_regs,
&irq, &dma, &scsi_id))
goto found;
release_region(base_io, 6);
}
printk("PC-9801-55: not found\n");
return 0;
found:
#ifdef PC_9801_55_DEBUG
printk("PC-9801-55: config: base io = %x, irq = %d, dma channel = %d, scsi id = %d\n", base_io, irq, dma, scsi_id);
#endif
if (request_irq(irq, pc980155_intr_handle, 0, "PC-9801-55", NULL)) {
printk(KERN_ERR "PC-9801-55: unable to allocate IRQ %d\n", irq);
goto err1;
}
if (request_dma(dma, "PC-9801-55")) {
printk(KERN_ERR "PC-9801-55: unable to allocate DMA channel %d\n", dma);
goto err2;
}
pc980155_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
if (pc980155_host) {
pc980155_host->this_id = scsi_id;
pc980155_host->io_port = base_io;
pc980155_host->n_io_port = 6;
pc980155_host->irq = irq;
pc980155_host->dma_channel = dma;
printk("PC-9801-55: scsi host found at %x irq = %d, use dma channel %d.\n", base_io, irq, dma);
pc980155_int_enable(init_regs);
wd33c93_init(pc980155_host, init_regs, dma_setup, dma_stop,
WD33C93_FS_12_15);
return 1;
}
printk(KERN_ERR "PC-9801-55: failed to register device\n");
err2:
free_irq(irq, NULL);
err1:
release_region(base_io, 6);
return 0;
}
static int scsi_pc980155_release(struct Scsi_Host *shost)
{
struct WD33C93_hostdata *hostdata
= (struct WD33C93_hostdata *)shost->hostdata;
pc980155_int_disable(hostdata->regs);
release_region(shost->io_port, shost->n_io_port);
free_irq(shost->irq, NULL);
free_dma(shost->dma_channel);
wd33c93_release();
return 1;
}
static int pc980155_bus_reset(Scsi_Cmnd *cmd)
{
struct WD33C93_hostdata *hostdata
= (struct WD33C93_hostdata *)cmd->device->host->hostdata;
pc980155_int_disable(hostdata->regs);
pc980155_assert_bus_reset(hostdata->regs);
udelay(50);
pc980155_negate_bus_reset(hostdata->regs);
(void) inb(hostdata->regs.SASR);
(void) read_pc980155(hostdata->regs, WD_SCSI_STATUS);
pc980155_int_enable(hostdata->regs);
wd33c93_host_reset(cmd);
return SUCCESS;
}
#ifndef MODULE
static int __init pc980155_setup(char *str)
{
int ints[4];
str = get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0)
io = ints[1];
return 1;
}
__setup("pc980155_io=", pc980155_setup);
#endif
MODULE_PARM(io, "i");
MODULE_AUTHOR("Tomoharu Ugawa <ohirune@kmc.gr.jp>");
MODULE_DESCRIPTION("PC-9801-55 SCSI host adapter driver");
MODULE_LICENSE("GPL");
static Scsi_Host_Template driver_template = {
.proc_info = wd33c93_proc_info,
.name = "SCSI PC-9801-55",
.detect = scsi_pc980155_detect,
.release = scsi_pc980155_release,
.queuecommand = wd33c93_queuecommand,
.eh_abort_handler = wd33c93_abort,
.eh_bus_reset_handler = pc980155_bus_reset,
.eh_host_reset_handler = wd33c93_host_reset,
.bios_param = pc98_bios_param,
.can_queue = CAN_QUEUE,
.this_id = 7,
.sg_tablesize = SG_ALL,
.cmd_per_lun = CMD_PER_LUN, /* dont use link command */
.unchecked_isa_dma = 1, /* use dma **XXXX***/
.use_clustering = ENABLE_CLUSTERING,
.proc_name = "PC_9801_55",
};
#include "scsi_module.c"
/*
*
* drivers/scsi/pc980155.h
*
* PC-9801-55 SCSI host adapter driver
*
* Copyright (C) 1997-2003 Kyoto University Microcomputer Club
* (Linux/98 project)
* Tomoharu Ugawa <ohirune@kmc.gr.jp>
*
*/
#ifndef __PC980155_H
#define __PC980155_H
#include "wd33c93.h"
#define REG_ADDRST (base_io)
#define REG_CONTRL (base_io + 2)
#define REG_CWRITE (base_io + 4)
#define REG_STATRD (base_io + 4)
#define WD_MEMORYBANK 0x30
#define WD_RESETINT 0x33
static inline uchar read_pc980155(const wd33c93_regs regs, uchar reg_num)
{
outb(reg_num, regs.SASR);
return (uchar)inb(regs.SCMD);
}
static inline void write_memorybank(const wd33c93_regs regs, uchar value)
{
outb(WD_MEMORYBANK, regs.SASR);
outb(value, regs.SCMD);
}
#define read_pc980155_resetint(regs) \
read_pc980155((regs), WD_RESETINT)
#define pc980155_int_enable(regs) \
write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) | 0x04)
#define pc980155_int_disable(regs) \
write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) & ~0x04)
#define pc980155_assert_bus_reset(regs) \
write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) | 0x02)
#define pc980155_negate_bus_reset(regs) \
write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) & ~0x02)
#endif /* __PC980155_H */
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#include "aha152x.h"
#include <pcmcia/version.h> #include <pcmcia/version.h>
#include <pcmcia/cs_types.h> #include <pcmcia/cs_types.h>
...@@ -102,8 +103,6 @@ typedef struct scsi_info_t { ...@@ -102,8 +103,6 @@ typedef struct scsi_info_t {
dev_node_t node[8]; dev_node_t node[8];
} scsi_info_t; } scsi_info_t;
extern void aha152x_setup(char *str, int *ints);
static void aha152x_release_cs(u_long arg); static void aha152x_release_cs(u_long arg);
static int aha152x_event(event_t event, int priority, static int aha152x_event(event_t event, int priority,
event_callback_args_t *args); event_callback_args_t *args);
...@@ -111,11 +110,7 @@ static int aha152x_event(event_t event, int priority, ...@@ -111,11 +110,7 @@ static int aha152x_event(event_t event, int priority,
static dev_link_t *aha152x_attach(void); static dev_link_t *aha152x_attach(void);
static void aha152x_detach(dev_link_t *); static void aha152x_detach(dev_link_t *);
#define driver_template aha152x_driver_template static dev_link_t *dev_list;
extern Scsi_Host_Template aha152x_driver_template;
static dev_link_t *dev_list = NULL;
static dev_info_t dev_info = "aha152x_cs"; static dev_info_t dev_info = "aha152x_cs";
/*====================================================================*/ /*====================================================================*/
...@@ -227,11 +222,12 @@ static void aha152x_config_cs(dev_link_t *link) ...@@ -227,11 +222,12 @@ static void aha152x_config_cs(dev_link_t *link)
{ {
client_handle_t handle = link->handle; client_handle_t handle = link->handle;
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
struct aha152x_setup s;
tuple_t tuple; tuple_t tuple;
cisparse_t parse; cisparse_t parse;
int i, last_ret, last_fn, ints[8]; int i, last_ret, last_fn;
u_char tuple_data[64]; u_char tuple_data[64];
Scsi_Device *dev; struct scsi_device *dev;
dev_node_t *node, **tail; dev_node_t *node, **tail;
struct Scsi_Host *host; struct Scsi_Host *host;
...@@ -247,7 +243,6 @@ static void aha152x_config_cs(dev_link_t *link) ...@@ -247,7 +243,6 @@ static void aha152x_config_cs(dev_link_t *link)
link->conf.ConfigBase = parse.config.base; link->conf.ConfigBase = parse.config.base;
/* Configure card */ /* Configure card */
driver_template.module = &__this_module;
link->state |= DEV_CONFIG; link->state |= DEV_CONFIG;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
...@@ -278,27 +273,30 @@ static void aha152x_config_cs(dev_link_t *link) ...@@ -278,27 +273,30 @@ static void aha152x_config_cs(dev_link_t *link)
release_region(link->io.BasePort1, link->io.NumPorts1); release_region(link->io.BasePort1, link->io.NumPorts1);
/* Set configuration options for the aha152x driver */ /* Set configuration options for the aha152x driver */
ints[0] = 7; memset(&s, 0, sizeof(s));
ints[1] = link->io.BasePort1; s.conf = "PCMCIA setup";
ints[2] = link->irq.AssignedIRQ; s.io_port = link->io.BasePort1;
ints[3] = host_id; s.irq = link->irq.AssignedIRQ;
ints[4] = reconnect; s.scsiid = host_id;
ints[5] = parity; s.reconnect = reconnect;
ints[6] = synchronous; s.parity = parity;
ints[7] = reset_delay; s.synchronous = synchronous;
if (ext_trans) { s.delay = reset_delay;
ints[8] = ext_trans; ints[0] = 8; if (ext_trans)
} s.ext_trans = ext_trans;
aha152x_setup("PCMCIA setup", ints);
scsi_register_host(&driver_template);
tail = &link->dev; tail = &link->dev;
info->ndev = 0; info->ndev = 0;
for (host = scsi_host_get_next(NULL); host;
host = scsi_host_get_next(host)) host = aha152x_probe_one(&s);
if (host->hostt == &driver_template) if (host == NULL) {
list_for_each_entry (dev, &host->my_devices, siblings) { printk(KERN_INFO "aha152x_cs: no SCSI devices found\n");
goto cs_failed;
}
scsi_add_host(host, NULL);
list_for_each_entry(dev, &host->my_devices, siblings) {
u_long arg[2], id; u_long arg[2], id;
kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +
...@@ -329,10 +327,8 @@ static void aha152x_config_cs(dev_link_t *link) ...@@ -329,10 +327,8 @@ static void aha152x_config_cs(dev_link_t *link)
info->ndev++; info->ndev++;
info->host = dev->host; info->host = dev->host;
} }
*tail = NULL;
if (info->ndev == 0)
printk(KERN_INFO "aha152x_cs: no SCSI devices found\n");
*tail = NULL;
link->state &= ~DEV_CONFIG_PENDING; link->state &= ~DEV_CONFIG_PENDING;
return; return;
...@@ -340,28 +336,14 @@ static void aha152x_config_cs(dev_link_t *link) ...@@ -340,28 +336,14 @@ static void aha152x_config_cs(dev_link_t *link)
cs_error(link->handle, last_fn, last_ret); cs_error(link->handle, last_fn, last_ret);
aha152x_release_cs((u_long)link); aha152x_release_cs((u_long)link);
return; return;
}
} /* aha152x_config_cs */
/*====================================================================*/
static void aha152x_release_cs(u_long arg) static void aha152x_release_cs(u_long arg)
{ {
dev_link_t *link = (dev_link_t *)arg; dev_link_t *link = (dev_link_t *)arg;
scsi_info_t *info = link->priv;
DEBUG(0, "aha152x_release_cs(0x%p)\n", link); scsi_remove_host(info->host);
#warning This does not protect you. You need some real fix for your races.
#if 0
if (GET_USE_COUNT(driver_template.module) != 0) {
DEBUG(1, "aha152x_cs: release postponed, "
"device still open\n");
link->state |= DEV_STALE_CONFIG;
return;
}
#endif
scsi_unregister_host(&driver_template);
link->dev = NULL; link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
...@@ -369,12 +351,11 @@ static void aha152x_release_cs(u_long arg) ...@@ -369,12 +351,11 @@ static void aha152x_release_cs(u_long arg)
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
scsi_unregister(info->host);
if (link->state & DEV_STALE_LINK) if (link->state & DEV_STALE_LINK)
aha152x_detach(link); aha152x_detach(link);
}
} /* aha152x_release_cs */
/*====================================================================*/
static int aha152x_event(event_t event, int priority, static int aha152x_event(event_t event, int priority,
event_callback_args_t *args) event_callback_args_t *args)
...@@ -414,26 +395,27 @@ static int aha152x_event(event_t event, int priority, ...@@ -414,26 +395,27 @@ static int aha152x_event(event_t event, int priority,
break; break;
} }
return 0; return 0;
} /* aha152x_event */ }
/*====================================================================*/ static struct pcmcia_driver aha152x_cs_driver = {
.owner = THIS_MODULE,
.drv = {
.name = "aha152x_cs",
},
.attach = aha152x_attach,
.detach = aha152x_detach,
};
static int __init init_aha152x_cs(void) { static int __init init_aha152x_cs(void)
servinfo_t serv; {
DEBUG(0, "%s\n", version); return pcmcia_register_driver(&aha152x_cs_driver);
CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "aha152x_cs: Card Services release "
"does not match!\n");
return -1;
}
register_pccard_driver(&dev_info, &aha152x_attach, &aha152x_detach);
return 0;
} }
static void __exit exit_aha152x_cs(void) { static void __exit exit_aha152x_cs(void)
DEBUG(0, "aha152x_cs: unloading\n"); {
unregister_pccard_driver(&dev_info); pcmcia_unregister_driver(&aha152x_cs_driver);
/* XXX: this really needs to move into generic code.. */
while (dev_list != NULL) while (dev_list != NULL)
aha152x_detach(dev_list); aha152x_detach(dev_list);
} }
......
...@@ -379,24 +379,25 @@ static int fdomain_event(event_t event, int priority, ...@@ -379,24 +379,25 @@ static int fdomain_event(event_t event, int priority,
return 0; return 0;
} /* fdomain_event */ } /* fdomain_event */
/*====================================================================*/ static struct pcmcia_driver fdomain_cs_driver = {
.owner = THIS_MODULE,
static int __init init_fdomain_cs(void) { .drv = {
servinfo_t serv; .name = "fdomain_cs",
DEBUG(0, "%s\n", version); },
CardServices(GetCardServicesInfo, &serv); .attach = fdomain_attach,
if (serv.Revision != CS_RELEASE_CODE) { .detach = fdomain_detach,
printk(KERN_NOTICE "fdomain_cs: Card Services release " };
"does not match!\n");
return -1; static int __init init_fdomain_cs(void)
} {
register_pccard_driver(&dev_info, &fdomain_attach, &fdomain_detach); return pcmcia_register_driver(&fdomain_cs_driver);
return 0;
} }
static void __exit exit_fdomain_cs(void) { static void __exit exit_fdomain_cs(void)
DEBUG(0, "fdomain_cs: unloading\n"); {
unregister_pccard_driver(&dev_info); pcmcia_unregister_driver(&fdomain_cs_driver);
/* XXX: this really needs to move into generic code.. */
while (dev_list != NULL) while (dev_list != NULL)
fdomain_detach(dev_list); fdomain_detach(dev_list);
} }
......
...@@ -397,25 +397,26 @@ static int qlogic_event(event_t event, int priority, event_callback_args_t * arg ...@@ -397,25 +397,26 @@ static int qlogic_event(event_t event, int priority, event_callback_args_t * arg
return 0; return 0;
} /* qlogic_event */ } /* qlogic_event */
/*====================================================================*/
static struct pcmcia_driver qlogic_cs_driver = {
.owner = THIS_MODULE,
.drv = {
.name = "qlogic_cs",
},
.attach = qlogic_attach,
.detach = qlogic_detach,
};
static int __init init_qlogic_cs(void) static int __init init_qlogic_cs(void)
{ {
servinfo_t serv; return pcmcia_register_driver(&qlogic_cs_driver);
DEBUG(0, "%s\n", version);
CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "qlogic_cs: Card Services release " "does not match!\n");
return -1;
}
register_pccard_driver(&dev_info, &qlogic_attach, &qlogic_detach);
return 0;
} }
static void __exit exit_qlogic_cs(void) static void __exit exit_qlogic_cs(void)
{ {
DEBUG(0, "qlogic_cs: unloading\n"); pcmcia_unregister_driver(&qlogic_cs_driver);
unregister_pccard_driver(&dev_info);
/* XXX: this really needs to move into generic code.. */
while (dev_list != NULL) while (dev_list != NULL)
qlogic_detach(dev_list); qlogic_detach(dev_list);
} }
......
...@@ -643,6 +643,7 @@ struct isp2x00_hostdata { ...@@ -643,6 +643,7 @@ struct isp2x00_hostdata {
u_char queued; u_char queued;
u_char host_id; u_char host_id;
struct timer_list explore_timer; struct timer_list explore_timer;
struct id_name_map tempmap[QLOGICFC_MAX_ID + 1];
}; };
...@@ -836,22 +837,13 @@ static int isp2x00_make_portdb(struct Scsi_Host *host) ...@@ -836,22 +837,13 @@ static int isp2x00_make_portdb(struct Scsi_Host *host)
short param[8]; short param[8];
int i, j; int i, j;
struct id_name_map *map; /* base of array [QLOGICFC_MAX_ID + 1] */
struct id_name_map *mapx; /* array entry pointer */
struct isp2x00_hostdata *hostdata; struct isp2x00_hostdata *hostdata;
hostdata = (struct isp2x00_hostdata *) host->hostdata;
map = kmalloc((QLOGICFC_MAX_ID + 1) * sizeof(struct id_name_map), GFP_ATOMIC);
if (!map) {
printk("qlogicfc%d : error getting memory -- cannot make port database.\n",
hostdata->host_id);
goto fini;
}
memset(map, 0, (QLOGICFC_MAX_ID + 1) * sizeof(struct id_name_map));
isp2x00_disable_irqs(host); isp2x00_disable_irqs(host);
hostdata = (struct isp2x00_hostdata *) host->hostdata;
memset(hostdata->tempmap, 0, sizeof(hostdata->tempmap));
#if ISP2x00_FABRIC #if ISP2x00_FABRIC
for (i = 0x81; i < QLOGICFC_MAX_ID; i++) { for (i = 0x81; i < QLOGICFC_MAX_ID; i++) {
param[0] = MBOX_PORT_LOGOUT; param[0] = MBOX_PORT_LOGOUT;
...@@ -876,74 +868,72 @@ static int isp2x00_make_portdb(struct Scsi_Host *host) ...@@ -876,74 +868,72 @@ static int isp2x00_make_portdb(struct Scsi_Host *host)
if (param[0] == MBOX_COMMAND_COMPLETE) { if (param[0] == MBOX_COMMAND_COMPLETE) {
hostdata->port_id = ((u_int) param[3]) << 16; hostdata->port_id = ((u_int) param[3]) << 16;
hostdata->port_id |= param[2]; hostdata->port_id |= param[2];
map->loop_id = param[1]; hostdata->tempmap[0].loop_id = param[1];
map->wwn = hostdata->wwn; hostdata->tempmap[0].wwn = hostdata->wwn;
} }
else { else {
printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id); printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id);
} }
for (i = 0, mapx = map; i <= QLOGICFC_MAX_ID; i++, mapx++) for (i = 0; i <=QLOGICFC_MAX_ID; i++)
mapx->loop_id = map->loop_id; hostdata->tempmap[i].loop_id = hostdata->tempmap[0].loop_id;
for (i = 0, j = 1, mapx = map + 1; i <= QLOGICFC_MAX_LOOP_ID; i++) { for (i = 0, j = 1; i <= QLOGICFC_MAX_LOOP_ID; i++) {
param[0] = MBOX_GET_PORT_NAME; param[0] = MBOX_GET_PORT_NAME;
param[1] = (i << 8) & 0xff00; param[1] = (i << 8) & 0xff00;
isp2x00_mbox_command(host, param); isp2x00_mbox_command(host, param);
if (param[0] == MBOX_COMMAND_COMPLETE) { if (param[0] == MBOX_COMMAND_COMPLETE) {
mapx->loop_id = i; hostdata->tempmap[j].loop_id = i;
mapx->wwn = ((u64) (param[2] & 0xff)) << 56; hostdata->tempmap[j].wwn = ((u64) (param[2] & 0xff)) << 56;
mapx->wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48; hostdata->tempmap[j].wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48;
mapx->wwn |= ((u64) (param[3] & 0xff)) << 40; hostdata->tempmap[j].wwn |= ((u64) (param[3] & 0xff)) << 40;
mapx->wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32; hostdata->tempmap[j].wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32;
mapx->wwn |= ((u64) (param[6] & 0xff)) << 24; hostdata->tempmap[j].wwn |= ((u64) (param[6] & 0xff)) << 24;
mapx->wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16; hostdata->tempmap[j].wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16;
mapx->wwn |= ((u64) (param[7] & 0xff)) << 8; hostdata->tempmap[j].wwn |= ((u64) (param[7] & 0xff)) << 8;
mapx->wwn |= ((u64) ((param[7] >> 8) & 0xff)); hostdata->tempmap[j].wwn |= ((u64) ((param[7] >> 8) & 0xff));
j++; j++;
mapx++;
} }
} }
#if ISP2x00_FABRIC #if ISP2x00_FABRIC
isp2x00_init_fabric(host, map, j); isp2x00_init_fabric(host, hostdata->tempmap, j);
#endif #endif
for (i = 0, mapx = map; i <= QLOGICFC_MAX_ID; i++, mapx++) { for (i = 0; i <= QLOGICFC_MAX_ID; i++) {
struct id_name_map *tmap; /* second array entry pointer */ if (hostdata->tempmap[i].wwn != hostdata->port_db[i].wwn) {
if (mapx->wwn != hostdata->port_db[i].wwn) { for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
for (j = 0, tmap = map; j <= QLOGICFC_MAX_ID; j++, tmap++) { if (hostdata->tempmap[j].wwn == hostdata->port_db[i].wwn) {
if (tmap->wwn == hostdata->port_db[i].wwn) { hostdata->port_db[i].loop_id = hostdata->tempmap[j].loop_id;
hostdata->port_db[i].loop_id = tmap->loop_id;
break; break;
} }
} }
if (j == QLOGICFC_MAX_ID + 1) if (j == QLOGICFC_MAX_ID + 1)
hostdata->port_db[i].loop_id = map->loop_id; hostdata->port_db[i].loop_id = hostdata->tempmap[0].loop_id;
for (j = 0; j <= QLOGICFC_MAX_ID; j++) { for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
if (hostdata->port_db[j].wwn == mapx->wwn || !hostdata->port_db[j].wwn) { if (hostdata->port_db[j].wwn == hostdata->tempmap[i].wwn || !hostdata->port_db[j].wwn) {
break; break;
} }
} }
if (j == QLOGICFC_MAX_ID + 1) if (j == QLOGICFC_MAX_ID + 1)
printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id); printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id);
if (!hostdata->port_db[j].wwn) { if (!hostdata->port_db[j].wwn) {
hostdata->port_db[j].loop_id = mapx->loop_id; hostdata->port_db[j].loop_id = hostdata->tempmap[i].loop_id;
hostdata->port_db[j].wwn = mapx->wwn; hostdata->port_db[j].wwn = hostdata->tempmap[i].wwn;
} }
} else } else
hostdata->port_db[i].loop_id = mapx->loop_id; hostdata->port_db[i].loop_id = hostdata->tempmap[i].loop_id;
} }
isp2x00_enable_irqs(host); isp2x00_enable_irqs(host);
kfree(map);
fini:
return 0; return 0;
} }
......
...@@ -442,6 +442,7 @@ extern void scsi_finish_command(Scsi_Cmnd *); ...@@ -442,6 +442,7 @@ extern void scsi_finish_command(Scsi_Cmnd *);
extern int scsi_retry_command(Scsi_Cmnd *); extern int scsi_retry_command(Scsi_Cmnd *);
extern int scsi_attach_device(struct scsi_device *); extern int scsi_attach_device(struct scsi_device *);
extern void scsi_detach_device(struct scsi_device *); extern void scsi_detach_device(struct scsi_device *);
extern void scsi_rescan_device(struct scsi_device *);
extern int scsi_get_device_flags(unsigned char *vendor, unsigned char *model); extern int scsi_get_device_flags(unsigned char *vendor, unsigned char *model);
/* /*
......
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
* add timers for delayed responses [20020721] * add timers for delayed responses [20020721]
* Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031] * Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031]
* Mike Anderson <andmike@us.ibm.com> sysfs work [20021118] * Mike Anderson <andmike@us.ibm.com> sysfs work [20021118]
* dpg: change style of boot options to "scsi_debug.num_devs=2" and * dpg: change style of boot options to "scsi_debug.num_tgts=2" and
* module options to "modprobe scsi_debug num_devs=2" [20021221] * module options to "modprobe scsi_debug num_tgts=2" [20021221]
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -54,18 +54,31 @@ ...@@ -54,18 +54,31 @@
#include "scsi_debug.h" #include "scsi_debug.h"
static const char * scsi_debug_version_str = "Version: 1.68 (20030314)"; static const char * scsi_debug_version_str = "Version: 1.69 (20030329)";
/* Additional Sense Code (ASC) used */
#define NO_ADDED_SENSE 0x0
#define UNRECOVERED_READ_ERR 0x11
#define INVALID_OPCODE 0x20
#define ADDR_OUT_OF_RANGE 0x21
#define INVALID_FIELD_IN_CDB 0x24
#define POWERON_RESET 0x29
#define SAVING_PARAMS_UNSUP 0x39
#define THRESHHOLD_EXCEEDED 0x5d
#define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
/* Default values for driver parameters */ /* Default values for driver parameters */
#define DEF_NUM_DEVS 1 #define DEF_NUM_HOST 1
#define DEF_NUM_TGTS 1
#define DEF_MAX_LUNS 1
/* With these defaults, this driver will make 1 host with 1 target
* (id 0) containing 1 logical unit (lun 0). That is 1 device.
*/
#define DEF_DEV_SIZE_MB 8 #define DEF_DEV_SIZE_MB 8
#define DEF_EVERY_NTH 0 #define DEF_EVERY_NTH 0
#define DEF_DELAY 1 #define DEF_DELAY 1
#define DEF_MAX_LUNS 2
#define DEF_SCSI_LEVEL 3 #define DEF_SCSI_LEVEL 3
#define DEF_NUM_HOST 1
#define DEF_OPTS 0 #define DEF_OPTS 0
/* bit mask values for scsi_debug_opts */ /* bit mask values for scsi_debug_opts */
...@@ -83,8 +96,12 @@ static const char * scsi_debug_version_str = "Version: 1.68 (20030314)"; ...@@ -83,8 +96,12 @@ static const char * scsi_debug_version_str = "Version: 1.68 (20030314)";
* sector on read commands: */ * sector on read commands: */
#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ #define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
/* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
* or "peripheral device" addressing (value 0) */
#define SAM2_LUN_ADDRESS_METHOD 0
static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
static int scsi_debug_num_devs = DEF_NUM_DEVS; /* max devs per host */ static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
static int scsi_debug_opts = DEF_OPTS; static int scsi_debug_opts = DEF_OPTS;
static int scsi_debug_every_nth = DEF_EVERY_NTH; static int scsi_debug_every_nth = DEF_EVERY_NTH;
static int scsi_debug_cmnd_count = 0; static int scsi_debug_cmnd_count = 0;
...@@ -303,7 +320,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -303,7 +320,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
sbuff = devip->sense_buff; sbuff = devip->sense_buff;
memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ? memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ?
bufflen : SDEBUG_SENSE_LEN); bufflen : SDEBUG_SENSE_LEN);
mk_sense_buffer(devip, 0, 0x0, 0, 7); mk_sense_buffer(devip, 0, NO_ADDED_SENSE, 0, 7);
} else { } else {
memset(buff, 0, bufflen); memset(buff, 0, bufflen);
buff[0] = 0x70; buff[0] = 0x70;
...@@ -384,7 +401,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -384,7 +401,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
} }
errsts = resp_read(SCpnt, upper_blk, block, num, devip); errsts = resp_read(SCpnt, upper_blk, block, num, devip);
if (inj_recovered && (0 == errsts)) { if (inj_recovered && (0 == errsts)) {
mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14); mk_sense_buffer(devip, RECOVERED_ERROR,
THRESHHOLD_EXCEEDED, 0, 18);
errsts = check_condition_result; errsts = check_condition_result;
} }
break; break;
...@@ -421,7 +439,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -421,7 +439,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
} }
errsts = resp_write(SCpnt, upper_blk, block, num, devip); errsts = resp_write(SCpnt, upper_blk, block, num, devip);
if (inj_recovered && (0 == errsts)) { if (inj_recovered && (0 == errsts)) {
mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14); mk_sense_buffer(devip, RECOVERED_ERROR,
THRESHHOLD_EXCEEDED, 0, 18);
errsts = check_condition_result; errsts = check_condition_result;
} }
break; break;
...@@ -435,7 +454,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -435,7 +454,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
default: default:
if ((errsts = check_reset(SCpnt, devip))) if ((errsts = check_reset(SCpnt, devip)))
break; break;
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0, 18);
errsts = check_condition_result; errsts = check_condition_result;
break; break;
} }
...@@ -455,7 +474,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip) ...@@ -455,7 +474,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip)
{ {
if (devip->reset) { if (devip->reset) {
devip->reset = 0; devip->reset = 0;
mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14); mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0, 18);
return check_condition_result; return check_condition_result;
} }
return 0; return 0;
...@@ -516,7 +535,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, ...@@ -516,7 +535,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
pq_pdt = PERIPH_DEVICE_TYPE(target); pq_pdt = PERIPH_DEVICE_TYPE(target);
arr[0] = pq_pdt; arr[0] = pq_pdt;
if (0x2 & cmd[1]) { /* CMDDT bit set */ if (0x2 & cmd[1]) { /* CMDDT bit set */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
0, 18);
return check_condition_result; return check_condition_result;
} else if (0x1 & cmd[1]) { /* EVPD bit set */ } else if (0x1 & cmd[1]) { /* EVPD bit set */
int dev_id_num, len; int dev_id_num, len;
...@@ -541,7 +561,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, ...@@ -541,7 +561,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
dev_id_str, len); dev_id_str, len);
} else { } else {
/* Illegal request, invalid field in cdb */ /* Illegal request, invalid field in cdb */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST,
INVALID_FIELD_IN_CDB, 0, 18);
return check_condition_result; return check_condition_result;
} }
memcpy(buff, arr, min_len); memcpy(buff, arr, min_len);
...@@ -654,7 +675,8 @@ static int resp_mode_sense(unsigned char * cmd, int target, ...@@ -654,7 +675,8 @@ static int resp_mode_sense(unsigned char * cmd, int target,
memset(buff, 0, bufflen); memset(buff, 0, bufflen);
memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
if (0x3 == pcontrol) { /* Saving values not supported */ if (0x3 == pcontrol) { /* Saving values not supported */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP,
0, 18);
return check_condition_result; return check_condition_result;
} }
dev_spec = DEV_READONLY(target) ? 0x80 : 0x0; dev_spec = DEV_READONLY(target) ? 0x80 : 0x0;
...@@ -697,7 +719,8 @@ static int resp_mode_sense(unsigned char * cmd, int target, ...@@ -697,7 +719,8 @@ static int resp_mode_sense(unsigned char * cmd, int target,
offset += len; offset += len;
break; break;
default: default:
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
0, 18);
return check_condition_result; return check_condition_result;
} }
if (msense_6) if (msense_6)
...@@ -721,13 +744,15 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -721,13 +744,15 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
unsigned long iflags; unsigned long iflags;
if (upper_blk || (block + num > sdebug_capacity)) { if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
0, 18);
return check_condition_result; return check_condition_result;
} }
if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
(block <= OPT_MEDIUM_ERR_ADDR) && (block <= OPT_MEDIUM_ERR_ADDR) &&
((block + num) > OPT_MEDIUM_ERR_ADDR)) { ((block + num) > OPT_MEDIUM_ERR_ADDR)) {
mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14); mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR,
0, 18);
/* claim unrecoverable read error */ /* claim unrecoverable read error */
return check_condition_result; return check_condition_result;
} }
...@@ -770,7 +795,8 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -770,7 +795,8 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
unsigned long iflags; unsigned long iflags;
if (upper_blk || (block + num > sdebug_capacity)) { if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
0, 18);
return check_condition_result; return check_condition_result;
} }
...@@ -805,23 +831,33 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -805,23 +831,33 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
static int resp_report_luns(unsigned char * cmd, unsigned char * buff, static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
int bufflen, struct sdebug_dev_info * devip) int bufflen, struct sdebug_dev_info * devip)
{ {
unsigned int alloc_len, lun_cnt, i; unsigned int alloc_len;
int lun_cnt, i, upper;
int select_report = (int)cmd[2]; int select_report = (int)cmd[2];
ScsiLun *one_lun; ScsiLun *one_lun;
alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
if ((alloc_len < 16) || (select_report > 2)) { if ((alloc_len < 16) || (select_report > 2)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
0, 18);
return check_condition_result; return check_condition_result;
} }
if (bufflen > 3) { if (bufflen > 8) { /* can produce response with up to 16k luns
lun_cnt = min((int)(bufflen / sizeof(ScsiLun)), (lun 0 to lun 16383) */
(int)scsi_debug_max_luns);
memset(buff, 0, bufflen); memset(buff, 0, bufflen);
buff[3] = 8 * lun_cnt; lun_cnt = scsi_debug_max_luns;
one_lun = (ScsiLun*) &buff[0]; buff[2] = ((sizeof(ScsiLun) * lun_cnt) >> 8) & 0xff;
for (i = 0; i < lun_cnt; i++) buff[3] = (sizeof(ScsiLun) * lun_cnt) & 0xff;
one_lun[i].scsi_lun[1] = i; lun_cnt = min((int)((bufflen - 8) / sizeof(ScsiLun)),
lun_cnt);
one_lun = (ScsiLun*) &buff[8];
for (i = 0; i < lun_cnt; i++) {
upper = (i >> 8) & 0x3f;
if (upper)
one_lun[i].scsi_lun[0] =
(upper | (SAM2_LUN_ADDRESS_METHOD << 6));
one_lun[i].scsi_lun[1] = i & 0xff;
}
} }
return 0; return 0;
} }
...@@ -1159,7 +1195,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd, ...@@ -1159,7 +1195,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
* of sysfs parameters (which module_param doesn't yet support). * of sysfs parameters (which module_param doesn't yet support).
* Sysfs parameters defined explicitly below. * Sysfs parameters defined explicitly below.
*/ */
module_param_named(num_devs, scsi_debug_num_devs, int, 0); module_param_named(num_tgts, scsi_debug_num_tgts, int, 0);
module_param_named(max_luns, scsi_debug_max_luns, int, 0); module_param_named(max_luns, scsi_debug_max_luns, int, 0);
module_param_named(scsi_level, scsi_debug_scsi_level, int, 0); module_param_named(scsi_level, scsi_debug_scsi_level, int, 0);
module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0); module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0);
...@@ -1172,7 +1208,7 @@ MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); ...@@ -1172,7 +1208,7 @@ MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
MODULE_DESCRIPTION("SCSI debug adapter driver"); MODULE_DESCRIPTION("SCSI debug adapter driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM_DESC(num_devs, "number of SCSI devices per host to simulate"); MODULE_PARM_DESC(num_tgts, "number of SCSI targets per host to simulate");
MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate"); MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate");
MODULE_PARM_DESC(scsi_level, "SCSI level to simulate"); MODULE_PARM_DESC(scsi_level, "SCSI level to simulate");
MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs"); MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs");
...@@ -1186,9 +1222,9 @@ static char sdebug_info[256]; ...@@ -1186,9 +1222,9 @@ static char sdebug_info[256];
static const char * scsi_debug_info(struct Scsi_Host * shp) static const char * scsi_debug_info(struct Scsi_Host * shp)
{ {
sprintf(sdebug_info, "scsi_debug, %s, num_devs=%d, " sprintf(sdebug_info, "scsi_debug, %s, num_tgts=%d, "
"dev_size_mb=%d, opts=0x%x", scsi_debug_version_str, "dev_size_mb=%d, opts=0x%x", scsi_debug_version_str,
scsi_debug_num_devs, scsi_debug_dev_size_mb, scsi_debug_num_tgts, scsi_debug_dev_size_mb,
scsi_debug_opts); scsi_debug_opts);
return sdebug_info; return sdebug_info;
} }
...@@ -1221,13 +1257,13 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset, ...@@ -1221,13 +1257,13 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
} }
begin = 0; begin = 0;
pos = len = sprintf(buffer, "scsi_debug adapter driver, %s\n" pos = len = sprintf(buffer, "scsi_debug adapter driver, %s\n"
"num_devs=%d, shared (ram) size=%d MB, opts=0x%x, " "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, "
"every_nth=%d(curr:%d)\n" "every_nth=%d(curr:%d)\n"
"delay=%d, max_luns=%d, scsi_level=%d\n" "delay=%d, max_luns=%d, scsi_level=%d\n"
"sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
"number of aborts=%d, device_reset=%d, bus_resets=%d, " "number of aborts=%d, device_reset=%d, bus_resets=%d, "
"host_resets=%d\n", "host_resets=%d\n",
scsi_debug_version_str, scsi_debug_num_devs, scsi_debug_version_str, scsi_debug_num_tgts,
scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth,
scsi_debug_cmnd_count, scsi_debug_delay, scsi_debug_cmnd_count, scsi_debug_delay,
scsi_debug_max_luns, scsi_debug_scsi_level, scsi_debug_max_luns, scsi_debug_scsi_level,
...@@ -1295,23 +1331,23 @@ static ssize_t sdebug_opts_store(struct device_driver * ddp, ...@@ -1295,23 +1331,23 @@ static ssize_t sdebug_opts_store(struct device_driver * ddp,
DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show, DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show,
sdebug_opts_store) sdebug_opts_store)
static ssize_t sdebug_num_devs_show(struct device_driver * ddp, char * buf) static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_devs); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
} }
static ssize_t sdebug_num_devs_store(struct device_driver * ddp, static ssize_t sdebug_num_tgts_store(struct device_driver * ddp,
const char * buf, size_t count) const char * buf, size_t count)
{ {
int n; int n;
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
scsi_debug_num_devs = n; scsi_debug_num_tgts = n;
return count; return count;
} }
return -EINVAL; return -EINVAL;
} }
DRIVER_ATTR(num_devs, S_IRUGO | S_IWUSR, sdebug_num_devs_show, DRIVER_ATTR(num_tgts, S_IRUGO | S_IWUSR, sdebug_num_tgts_show,
sdebug_num_devs_store) sdebug_num_tgts_store)
static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf)
{ {
...@@ -1342,7 +1378,19 @@ static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) ...@@ -1342,7 +1378,19 @@ static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
} }
DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_show, NULL) static ssize_t sdebug_max_luns_store(struct device_driver * ddp,
const char * buf, size_t count)
{
int n;
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
scsi_debug_max_luns = n;
return count;
}
return -EINVAL;
}
DRIVER_ATTR(max_luns, S_IRUGO | S_IWUSR, sdebug_max_luns_show,
sdebug_max_luns_store)
static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf)
{ {
...@@ -1391,7 +1439,7 @@ static void do_create_driverfs_files() ...@@ -1391,7 +1439,7 @@ static void do_create_driverfs_files()
{ {
driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay); driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts); driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_devs); driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth); driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns); driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
...@@ -1406,7 +1454,7 @@ static void do_remove_driverfs_files() ...@@ -1406,7 +1454,7 @@ static void do_remove_driverfs_files()
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_devs); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay);
} }
...@@ -1567,7 +1615,7 @@ static void sdebug_remove_adapter() ...@@ -1567,7 +1615,7 @@ static void sdebug_remove_adapter()
static int sdebug_driver_probe(struct device * dev) static int sdebug_driver_probe(struct device * dev)
{ {
int k; int k, devs_per_host;
int error = 0; int error = 0;
struct sdebug_host_info *sdbg_host; struct sdebug_host_info *sdbg_host;
struct sdebug_dev_info *sdbg_devinfo; struct sdebug_dev_info *sdbg_devinfo;
...@@ -1584,7 +1632,8 @@ static int sdebug_driver_probe(struct device * dev) ...@@ -1584,7 +1632,8 @@ static int sdebug_driver_probe(struct device * dev)
INIT_LIST_HEAD(&sdbg_host->dev_info_list); INIT_LIST_HEAD(&sdbg_host->dev_info_list);
for (k = 0; k < scsi_debug_num_devs; k++) { devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
for (k = 0; k < devs_per_host; k++) {
sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL); sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
if (NULL == sdbg_devinfo) { if (NULL == sdbg_devinfo) {
printk(KERN_ERR "%s: out of memory at line %d\n", printk(KERN_ERR "%s: out of memory at line %d\n",
...@@ -1608,6 +1657,10 @@ static int sdebug_driver_probe(struct device * dev) ...@@ -1608,6 +1657,10 @@ static int sdebug_driver_probe(struct device * dev)
sdbg_host->shost = hpnt; sdbg_host->shost = hpnt;
sdbg_host->dev = dev; sdbg_host->dev = dev;
if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id))
hpnt->max_id = scsi_debug_num_tgts + 1;
else
hpnt->max_id = scsi_debug_num_tgts;
hpnt->max_lun = scsi_debug_max_luns; hpnt->max_lun = scsi_debug_max_luns;
error = scsi_add_host(hpnt, sdbg_host->dev); error = scsi_add_host(hpnt, sdbg_host->dev);
......
...@@ -298,6 +298,7 @@ int scsi_ioctl_send_command(Scsi_Device * dev, Scsi_Ioctl_Command * sic) ...@@ -298,6 +298,7 @@ int scsi_ioctl_send_command(Scsi_Device * dev, Scsi_Ioctl_Command * sic)
goto error; goto error;
switch (opcode) { switch (opcode) {
case SEND_DIAGNOSTIC:
case FORMAT_UNIT: case FORMAT_UNIT:
timeout = FORMAT_UNIT_TIMEOUT; timeout = FORMAT_UNIT_TIMEOUT;
retries = 1; retries = 1;
......
...@@ -810,7 +810,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, int good_sectors, ...@@ -810,7 +810,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, int good_sectors,
cmd->device->host->host_no, (int) cmd->device->channel, cmd->device->host->host_no, (int) cmd->device->channel,
(int) cmd->device->id, (int) cmd->device->lun); (int) cmd->device->id, (int) cmd->device->lun);
print_command(cmd->data_cmnd); print_command(cmd->data_cmnd);
print_sense("sd", cmd); print_sense("", cmd);
cmd = scsi_end_request(cmd, 0, block_sectors, 1); cmd = scsi_end_request(cmd, 0, block_sectors, 1);
return; return;
default: default:
...@@ -830,7 +830,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, int good_sectors, ...@@ -830,7 +830,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, int good_sectors,
struct Scsi_Device_Template *sdt; struct Scsi_Device_Template *sdt;
sdt = scsi_get_request_dev(cmd->request); sdt = scsi_get_request_dev(cmd->request);
printk("SCSI %s error : host %d channel %d id %d lun %d return code = %x\n", printk("SCSI %s error : <%d %d %d %d> return code = 0x%x\n",
(sdt ? sdt->name : "device"), (sdt ? sdt->name : "device"),
cmd->device->host->host_no, cmd->device->host->host_no,
cmd->device->channel, cmd->device->channel,
...@@ -838,7 +838,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, int good_sectors, ...@@ -838,7 +838,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, int good_sectors,
cmd->device->lun, result); cmd->device->lun, result);
if (driver_byte(result) & DRIVER_SENSE) if (driver_byte(result) & DRIVER_SENSE)
print_sense("sd", cmd); print_sense("", cmd);
/* /*
* Mark a single buffer as not uptodate. Queue the remainder. * Mark a single buffer as not uptodate. Queue the remainder.
* We sometimes get this cruft in the event that a medium error * We sometimes get this cruft in the event that a medium error
......
...@@ -48,7 +48,7 @@ static int pc98_first_bios_param(struct scsi_device *sdev, int *ip) ...@@ -48,7 +48,7 @@ static int pc98_first_bios_param(struct scsi_device *sdev, int *ip)
int pc98_bios_param(struct scsi_device *sdev, struct block_device *bdev, int pc98_bios_param(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int *ip) sector_t capacity, int *ip)
{ {
static struct Scsi_Host *first_real = first_real_host(); struct Scsi_Host *first_real = first_real_host();
if (sdev->host == first_real && sdev->id < 7 && if (sdev->host == first_real && sdev->id < 7 &&
__PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, sdev->id)) __PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, sdev->id))
......
...@@ -191,6 +191,13 @@ struct dev_info scsi_static_device_list[] __initdata = { ...@@ -191,6 +191,13 @@ struct dev_info scsi_static_device_list[] __initdata = {
{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{"SUN", "T300", "*", BLIST_SPARSELUN}, {"SUN", "T300", "*", BLIST_SPARSELUN},
{"SUN", "T4", "*", BLIST_SPARSELUN}, {"SUN", "T4", "*", BLIST_SPARSELUN},
{"SGI", "RAID3", "*", BLIST_SPARSELUN},
{"SGI", "RAID5", "*", BLIST_SPARSELUN},
{"SGI", "TP9100", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{"SGI", "TP9300", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{"SGI", "TP9400", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{"SGI", "TP9500", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{"MYLEX", "DACARMRB", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{ NULL, NULL, NULL, 0 }, { NULL, NULL, NULL, 0 },
}; };
......
...@@ -275,12 +275,8 @@ show_rescan_field (struct device *dev, char *buf) ...@@ -275,12 +275,8 @@ show_rescan_field (struct device *dev, char *buf)
static ssize_t static ssize_t
store_rescan_field (struct device *dev, const char *buf, size_t count) store_rescan_field (struct device *dev, const char *buf, size_t count)
{ {
int ret = ENODEV; scsi_rescan_device(to_scsi_device(dev));
struct scsi_device *sdev; return 0;
sdev = to_scsi_device(dev);
if (sdev)
ret = scsi_rescan_device(sdev);
return ret;
} }
static DEVICE_ATTR(rescan, S_IRUGO | S_IWUSR, show_rescan_field, store_rescan_field) static DEVICE_ATTR(rescan, S_IRUGO | S_IWUSR, show_rescan_field, store_rescan_field)
......
...@@ -4901,6 +4901,11 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) ...@@ -4901,6 +4901,11 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
u_long period; u_long period;
int i; int i;
#ifdef CONFIG_PARISC
char scsi_mode = -1;
struct hardware_path hwpath;
#endif
/* /*
** Wide ? ** Wide ?
*/ */
...@@ -4972,6 +4977,31 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) ...@@ -4972,6 +4977,31 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
*/ */
period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz; period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
#ifdef CONFIG_PARISC
/* Host firmware (PDC) keeps a table for crippling SCSI capabilities.
* Many newer machines export one channel of 53c896 chip
* as SE, 50-pin HD. Also used for Multi-initiator SCSI clusters
* to set the SCSI Initiator ID.
*/
get_pci_node_path(np->pdev, &hwpath);
if (pdc_get_initiator(&hwpath, &np->myaddr, &period, &np->maxwide, &scsi_mode))
{
if (np->maxwide)
np->features |= FE_WIDE;
if (scsi_mode >= 0) {
/* C3000 PDC reports period/mode */
driver_setup.diff_support = 0;
switch(scsi_mode) {
case 0: np->scsi_mode = SMODE_SE; break;
case 1: np->scsi_mode = SMODE_HVD; break;
case 2: np->scsi_mode = SMODE_LVD; break;
default: break;
}
}
}
#endif
if (period <= 250) np->minsync = 10; if (period <= 250) np->minsync = 10;
else if (period <= 303) np->minsync = 11; else if (period <= 303) np->minsync = 11;
else if (period <= 500) np->minsync = 12; else if (period <= 500) np->minsync = 12;
......
...@@ -162,8 +162,8 @@ read_wd33c93(const wd33c93_regs regs, uchar reg_num) ...@@ -162,8 +162,8 @@ read_wd33c93(const wd33c93_regs regs, uchar reg_num)
{ {
uchar data; uchar data;
outb(reg_num, *regs.SASR); outb(reg_num, regs.SASR);
data = inb(*regs.SCMD); data = inb(regs.SCMD);
return data; return data;
} }
...@@ -172,33 +172,33 @@ read_wd33c93_count(const wd33c93_regs regs) ...@@ -172,33 +172,33 @@ read_wd33c93_count(const wd33c93_regs regs)
{ {
unsigned long value; unsigned long value;
outb(WD_TRANSFER_COUNT_MSB, *regs.SASR); outb(WD_TRANSFER_COUNT_MSB, regs.SASR);
value = inb(*regs.SCMD) << 16; value = inb(regs.SCMD) << 16;
value |= inb(*regs.SCMD) << 8; value |= inb(regs.SCMD) << 8;
value |= inb(*regs.SCMD); value |= inb(regs.SCMD);
return value; return value;
} }
static inline uchar static inline uchar
read_aux_stat(const wd33c93_regs regs) read_aux_stat(const wd33c93_regs regs)
{ {
return inb(*regs.SASR); return inb(regs.SASR);
} }
static inline void static inline void
write_wd33c93(const wd33c93_regs regs, uchar reg_num, uchar value) write_wd33c93(const wd33c93_regs regs, uchar reg_num, uchar value)
{ {
outb(reg_num, *regs.SASR); outb(reg_num, regs.SASR);
outb(value, *regs.SCMD); outb(value, regs.SCMD);
} }
static inline void static inline void
write_wd33c93_count(const wd33c93_regs regs, unsigned long value) write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
{ {
outb(WD_TRANSFER_COUNT_MSB, *regs.SASR); outb(WD_TRANSFER_COUNT_MSB, regs.SASR);
outb((value >> 16) & 0xff, *regs.SCMD); outb((value >> 16) & 0xff, regs.SCMD);
outb((value >> 8) & 0xff, *regs.SCMD); outb((value >> 8) & 0xff, regs.SCMD);
outb( value & 0xff, *regs.SCMD); outb( value & 0xff, regs.SCMD);
} }
#define write_wd33c93_cmd(regs, cmd) \ #define write_wd33c93_cmd(regs, cmd) \
...@@ -209,9 +209,9 @@ write_wd33c93_cdb(const wd33c93_regs regs, uint len, uchar cmnd[]) ...@@ -209,9 +209,9 @@ write_wd33c93_cdb(const wd33c93_regs regs, uint len, uchar cmnd[])
{ {
int i; int i;
outb(WD_CDB_1, *regs.SASR); outb(WD_CDB_1, regs.SASR);
for (i=0; i<len; i++) for (i=0; i<len; i++)
outb(cmnd[i], *regs.SCMD); outb(cmnd[i], regs.SCMD);
} }
#else /* CONFIG_WD33C93_PIO */ #else /* CONFIG_WD33C93_PIO */
...@@ -1522,7 +1522,7 @@ reset_wd33c93(struct Scsi_Host *instance) ...@@ -1522,7 +1522,7 @@ reset_wd33c93(struct Scsi_Host *instance)
} }
int int
wd33c93_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) wd33c93_host_reset(Scsi_Cmnd * SCpnt)
{ {
struct Scsi_Host *instance; struct Scsi_Host *instance;
struct WD33C93_hostdata *hostdata; struct WD33C93_hostdata *hostdata;
...@@ -1553,7 +1553,7 @@ wd33c93_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) ...@@ -1553,7 +1553,7 @@ wd33c93_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
reset_wd33c93(instance); reset_wd33c93(instance);
SCpnt->result = DID_RESET << 16; SCpnt->result = DID_RESET << 16;
enable_irq(instance->irq); enable_irq(instance->irq);
return 0; return SUCCESS;
} }
int int
...@@ -1591,7 +1591,7 @@ wd33c93_abort(Scsi_Cmnd * cmd) ...@@ -1591,7 +1591,7 @@ wd33c93_abort(Scsi_Cmnd * cmd)
instance->host_no, cmd->pid); instance->host_no, cmd->pid);
enable_irq(cmd->device->host->irq); enable_irq(cmd->device->host->irq);
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
return SCSI_ABORT_SUCCESS; return SUCCESS;
} }
prev = tmp; prev = tmp;
tmp = (Scsi_Cmnd *) tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble;
...@@ -1666,7 +1666,7 @@ wd33c93_abort(Scsi_Cmnd * cmd) ...@@ -1666,7 +1666,7 @@ wd33c93_abort(Scsi_Cmnd * cmd)
enable_irq(cmd->device->host->irq); enable_irq(cmd->device->host->irq);
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
return SCSI_ABORT_SUCCESS; return SUCCESS;
} }
/* /*
...@@ -1681,9 +1681,9 @@ wd33c93_abort(Scsi_Cmnd * cmd) ...@@ -1681,9 +1681,9 @@ wd33c93_abort(Scsi_Cmnd * cmd)
printk printk
("scsi%d: Abort - command %ld found on disconnected_Q - ", ("scsi%d: Abort - command %ld found on disconnected_Q - ",
instance->host_no, cmd->pid); instance->host_no, cmd->pid);
printk("returning ABORT_SNOOZE. "); printk("Abort SNOOZE. ");
enable_irq(cmd->device->host->irq); enable_irq(cmd->device->host->irq);
return SCSI_ABORT_SNOOZE; return FAILED;
} }
tmp = (Scsi_Cmnd *) tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble;
} }
...@@ -1704,7 +1704,7 @@ wd33c93_abort(Scsi_Cmnd * cmd) ...@@ -1704,7 +1704,7 @@ wd33c93_abort(Scsi_Cmnd * cmd)
enable_irq(cmd->device->host->irq); enable_irq(cmd->device->host->irq);
printk("scsi%d: warning : SCSI command probably completed successfully" printk("scsi%d: warning : SCSI command probably completed successfully"
" before abortion. ", instance->host_no); " before abortion. ", instance->host_no);
return SCSI_ABORT_NOT_RUNNING; return FAILED;
} }
#define MAX_WD33C93_HOSTS 4 #define MAX_WD33C93_HOSTS 4
...@@ -1755,7 +1755,7 @@ wd33c93_setup(char *str) ...@@ -1755,7 +1755,7 @@ wd33c93_setup(char *str)
return 1; return 1;
} }
__setup("wd33c9=", wd33c93_setup); __setup("wd33c93=", wd33c93_setup);
/* check_setup_args() returns index if key found, 0 if not /* check_setup_args() returns index if key found, 0 if not
*/ */
...@@ -2080,7 +2080,7 @@ wd33c93_release(void) ...@@ -2080,7 +2080,7 @@ wd33c93_release(void)
{ {
} }
EXPORT_SYMBOL(wd33c93_reset); EXPORT_SYMBOL(wd33c93_host_reset);
EXPORT_SYMBOL(wd33c93_init); EXPORT_SYMBOL(wd33c93_init);
EXPORT_SYMBOL(wd33c93_release); EXPORT_SYMBOL(wd33c93_release);
EXPORT_SYMBOL(wd33c93_abort); EXPORT_SYMBOL(wd33c93_abort);
......
...@@ -186,8 +186,13 @@ ...@@ -186,8 +186,13 @@
/* This is what the 3393 chip looks like to us */ /* This is what the 3393 chip looks like to us */
typedef struct { typedef struct {
#ifdef CONFIG_WD33C93_PIO
unsigned int SASR;
unsigned int SCMD;
#else
volatile unsigned char *SASR; volatile unsigned char *SASR;
volatile unsigned char *SCMD; volatile unsigned char *SCMD;
#endif
} wd33c93_regs; } wd33c93_regs;
...@@ -334,7 +339,7 @@ int wd33c93_abort (Scsi_Cmnd *cmd); ...@@ -334,7 +339,7 @@ int wd33c93_abort (Scsi_Cmnd *cmd);
int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *));
void wd33c93_intr (struct Scsi_Host *instance); void wd33c93_intr (struct Scsi_Host *instance);
int wd33c93_proc_info(char *, char **, off_t, int, int, int); int wd33c93_proc_info(char *, char **, off_t, int, int, int);
int wd33c93_reset (Scsi_Cmnd *, unsigned int); int wd33c93_host_reset (Scsi_Cmnd *);
void wd33c93_release(void); void wd33c93_release(void);
#endif /* WD33C93_H */ #endif /* WD33C93_H */
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