Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
cd509844
Commit
cd509844
authored
Oct 08, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wd7000 indent pass, no code changes
indent -kr -i8 -bri0 -l255 wd7000.{c,h}
parent
6f720ad0
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
919 additions
and
968 deletions
+919
-968
drivers/scsi/wd7000.c
drivers/scsi/wd7000.c
+909
-958
drivers/scsi/wd7000.h
drivers/scsi/wd7000.h
+10
-10
No files found.
drivers/scsi/wd7000.c
View file @
cd509844
...
@@ -216,8 +216,8 @@
...
@@ -216,8 +216,8 @@
*
*
*/
*/
typedef
volatile
struct
mailbox
{
typedef
volatile
struct
mailbox
{
unchar
status
;
unchar
status
;
unchar
scbptr
[
3
];
/* SCSI-style - MSB first (big endian) */
unchar
scbptr
[
3
];
/* SCSI-style - MSB first (big endian) */
}
Mailbox
;
}
Mailbox
;
/*
/*
...
@@ -225,38 +225,36 @@ typedef volatile struct mailbox {
...
@@ -225,38 +225,36 @@ typedef volatile struct mailbox {
* new global per-adapter data should put in here.
* new global per-adapter data should put in here.
*/
*/
typedef
struct
adapter
{
typedef
struct
adapter
{
struct
Scsi_Host
*
sh
;
/* Pointer to Scsi_Host structure */
struct
Scsi_Host
*
sh
;
/* Pointer to Scsi_Host structure */
int
iobase
;
/* This adapter's I/O base address */
int
iobase
;
/* This adapter's I/O base address */
int
irq
;
/* This adapter's IRQ level */
int
irq
;
/* This adapter's IRQ level */
int
dma
;
/* This adapter's DMA channel */
int
dma
;
/* This adapter's DMA channel */
int
int_counter
;
/* This adapter's interrupt counter */
int
int_counter
;
/* This adapter's interrupt counter */
int
bus_on
;
/* This adapter's BUS_ON time */
int
bus_on
;
/* This adapter's BUS_ON time */
int
bus_off
;
/* This adapter's BUS_OFF time */
int
bus_off
;
/* This adapter's BUS_OFF time */
struct
{
/* This adapter's mailboxes */
struct
{
/* This adapter's mailboxes */
Mailbox
ogmb
[
OGMB_CNT
];
/* Outgoing mailboxes */
Mailbox
ogmb
[
OGMB_CNT
];
/* Outgoing mailboxes */
Mailbox
icmb
[
ICMB_CNT
];
/* Incoming mailboxes */
Mailbox
icmb
[
ICMB_CNT
];
/* Incoming mailboxes */
}
mb
;
}
mb
;
int
next_ogmb
;
/* to reduce contention at mailboxes */
int
next_ogmb
;
/* to reduce contention at mailboxes */
unchar
control
;
/* shadows CONTROL port value */
unchar
control
;
/* shadows CONTROL port value */
unchar
rev1
,
rev2
;
/* filled in by wd7000_revision */
unchar
rev1
,
rev2
;
/* filled in by wd7000_revision */
}
Adapter
;
}
Adapter
;
/*
/*
* (linear) base address for ROM BIOS
* (linear) base address for ROM BIOS
*/
*/
static
const
long
wd7000_biosaddr
[]
=
static
const
long
wd7000_biosaddr
[]
=
{
{
0xc0000
,
0xc2000
,
0xc4000
,
0xc6000
,
0xc8000
,
0xca000
,
0xcc000
,
0xce000
,
0xc0000
,
0xc2000
,
0xc4000
,
0xc6000
,
0xc8000
,
0xca000
,
0xcc000
,
0xce000
,
0xd0000
,
0xd2000
,
0xd4000
,
0xd6000
,
0xd8000
,
0xda000
,
0xdc000
,
0xde000
0xd0000
,
0xd2000
,
0xd4000
,
0xd6000
,
0xd8000
,
0xda000
,
0xdc000
,
0xde000
};
};
#define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long))
#define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long))
static
const
unsigned
short
wd7000_iobase
[]
=
static
const
unsigned
short
wd7000_iobase
[]
=
{
{
0x0300
,
0x0308
,
0x0310
,
0x0318
,
0x0320
,
0x0328
,
0x0330
,
0x0338
,
0x0300
,
0x0308
,
0x0310
,
0x0318
,
0x0320
,
0x0328
,
0x0330
,
0x0338
,
0x0340
,
0x0348
,
0x0350
,
0x0358
,
0x0360
,
0x0368
,
0x0370
,
0x0378
,
0x0340
,
0x0348
,
0x0350
,
0x0358
,
0x0360
,
0x0368
,
0x0370
,
0x0378
,
0x0380
,
0x0388
,
0x0390
,
0x0398
,
0x03a0
,
0x03a8
,
0x03b0
,
0x03b8
,
0x0380
,
0x0388
,
0x0390
,
0x0398
,
0x03a0
,
0x03a8
,
0x03b0
,
0x03b8
,
0x03c0
,
0x03c8
,
0x03d0
,
0x03d8
,
0x03e0
,
0x03e8
,
0x03f0
,
0x03f8
0x03c0
,
0x03c8
,
0x03d0
,
0x03d8
,
0x03e0
,
0x03e8
,
0x03f0
,
0x03f8
};
};
#define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short))
#define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short))
...
@@ -270,36 +268,35 @@ static const short wd7000_dma[] = { 5, 6, 7 };
...
@@ -270,36 +268,35 @@ static const short wd7000_dma[] = { 5, 6, 7 };
* The following is set up by wd7000_detect, and used thereafter for
* The following is set up by wd7000_detect, and used thereafter for
* proc and other global ookups
* proc and other global ookups
*/
*/
#define UNITS 8
#define UNITS 8
static
struct
Scsi_Host
*
wd7000_host
[
UNITS
];
static
struct
Scsi_Host
*
wd7000_host
[
UNITS
];
#define BUS_ON 64
/* x 125ns = 8000ns (BIOS default) */
#define BUS_ON 64
/* x 125ns = 8000ns (BIOS default) */
#define BUS_OFF 15
/* x 125ns = 1875ns (BIOS default) */
#define BUS_OFF 15
/* x 125ns = 1875ns (BIOS default) */
/*
/*
* Standard Adapter Configurations - used by wd7000_detect
* Standard Adapter Configurations - used by wd7000_detect
*/
*/
typedef
struct
{
typedef
struct
{
short
irq
;
/* IRQ level */
short
irq
;
/* IRQ level */
short
dma
;
/* DMA channel */
short
dma
;
/* DMA channel */
unsigned
iobase
;
/* I/O base address */
unsigned
iobase
;
/* I/O base address */
short
bus_on
;
/* Time that WD7000 spends on the AT-bus when */
short
bus_on
;
/* Time that WD7000 spends on the AT-bus when */
/* transferring data. BIOS default is 8000ns. */
/* transferring data. BIOS default is 8000ns. */
short
bus_off
;
/* Time that WD7000 spends OFF THE BUS after */
short
bus_off
;
/* Time that WD7000 spends OFF THE BUS after */
/* while it is transferring data. */
/* while it is transferring data. */
/* BIOS default is 1875ns */
/* BIOS default is 1875ns */
}
Config
;
}
Config
;
/*
/*
* Add here your configuration...
* Add here your configuration...
*/
*/
static
Config
configs
[]
=
static
Config
configs
[]
=
{
{
{
15
,
6
,
0x350
,
BUS_ON
,
BUS_OFF
},
/* defaults for single adapter */
{
15
,
6
,
0x350
,
BUS_ON
,
BUS_OFF
},
/* defaults for single adapter */
{
11
,
5
,
0x320
,
BUS_ON
,
BUS_OFF
},
/* defaults for second adapter */
{
11
,
5
,
0x320
,
BUS_ON
,
BUS_OFF
},
/* defaults for second adapter */
{
7
,
6
,
0x350
,
BUS_ON
,
BUS_OFF
},
/* My configuration (Zaga) */
{
7
,
6
,
0x350
,
BUS_ON
,
BUS_OFF
},
/* My configuration (Zaga) */
{
-
1
,
-
1
,
0x0
,
BUS_ON
,
BUS_OFF
}
/* Empty slot */
{
-
1
,
-
1
,
0x0
,
BUS_ON
,
BUS_OFF
}
/* Empty slot */
};
};
#define NUM_CONFIGS (sizeof(configs)/sizeof(Config))
#define NUM_CONFIGS (sizeof(configs)/sizeof(Config))
...
@@ -309,14 +306,13 @@ static Config configs[] =
...
@@ -309,14 +306,13 @@ static Config configs[] =
* added for the Future Domain version.
* added for the Future Domain version.
*/
*/
typedef
struct
signature
{
typedef
struct
signature
{
const
char
*
sig
;
/* String to look for */
const
char
*
sig
;
/* String to look for */
unsigned
long
ofs
;
/* offset from BIOS base address */
unsigned
long
ofs
;
/* offset from BIOS base address */
unsigned
len
;
/* length of string */
unsigned
len
;
/* length of string */
}
Signature
;
}
Signature
;
static
const
Signature
signatures
[]
=
static
const
Signature
signatures
[]
=
{
{
{
"SSTBIOS"
,
0x0000d
,
7
}
/* "SSTBIOS" @ offset 0x0000d */
{
"SSTBIOS"
,
0x0000d
,
7
}
/* "SSTBIOS" @ offset 0x0000d */
};
};
#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
...
@@ -363,14 +359,14 @@ static const Signature signatures[] =
...
@@ -363,14 +359,14 @@ static const Signature signatures[] =
* For INITIALIZATION:
* For INITIALIZATION:
*/
*/
typedef
struct
initCmd
{
typedef
struct
initCmd
{
unchar
op
;
/* command opcode (= 1) */
unchar
op
;
/* command opcode (= 1) */
unchar
ID
;
/* Adapter's SCSI ID */
unchar
ID
;
/* Adapter's SCSI ID */
unchar
bus_on
;
/* Bus on time, x 125ns (see below) */
unchar
bus_on
;
/* Bus on time, x 125ns (see below) */
unchar
bus_off
;
/* Bus off time, "" "" */
unchar
bus_off
;
/* Bus off time, "" "" */
unchar
rsvd
;
/* Reserved */
unchar
rsvd
;
/* Reserved */
unchar
mailboxes
[
3
];
/* Address of Mailboxes, MSB first */
unchar
mailboxes
[
3
];
/* Address of Mailboxes, MSB first */
unchar
ogmbs
;
/* Number of outgoing MBs, max 64, 0,1 = 1 */
unchar
ogmbs
;
/* Number of outgoing MBs, max 64, 0,1 = 1 */
unchar
icmbs
;
/* Number of incoming MBs, "" "" */
unchar
icmbs
;
/* Number of incoming MBs, "" "" */
}
InitCmd
;
}
InitCmd
;
/*
/*
...
@@ -430,29 +426,29 @@ typedef struct initCmd {
...
@@ -430,29 +426,29 @@ typedef struct initCmd {
* WD7000-specific scatter/gather element structure
* WD7000-specific scatter/gather element structure
*/
*/
typedef
struct
sgb
{
typedef
struct
sgb
{
unchar
len
[
3
];
unchar
len
[
3
];
unchar
ptr
[
3
];
/* Also SCSI-style - MSB first */
unchar
ptr
[
3
];
/* Also SCSI-style - MSB first */
}
Sgb
;
}
Sgb
;
typedef
struct
scb
{
/* Command Control Block 5.4.1 */
typedef
struct
scb
{
/* Command Control Block 5.4.1 */
unchar
op
;
/* Command Control Block Operation Code */
unchar
op
;
/* Command Control Block Operation Code */
unchar
idlun
;
/* op=0,2:Target Id, op=1:Initiator Id */
unchar
idlun
;
/* op=0,2:Target Id, op=1:Initiator Id */
/* Outbound data transfer, length is checked */
/* Outbound data transfer, length is checked */
/* Inbound data transfer, length is checked */
/* Inbound data transfer, length is checked */
/* Logical Unit Number */
/* Logical Unit Number */
unchar
cdb
[
12
];
/* SCSI Command Block */
unchar
cdb
[
12
];
/* SCSI Command Block */
volatile
unchar
status
;
/* SCSI Return Status */
volatile
unchar
status
;
/* SCSI Return Status */
volatile
unchar
vue
;
/* Vendor Unique Error Code */
volatile
unchar
vue
;
/* Vendor Unique Error Code */
unchar
maxlen
[
3
];
/* Maximum Data Transfer Length */
unchar
maxlen
[
3
];
/* Maximum Data Transfer Length */
unchar
dataptr
[
3
];
/* SCSI Data Block Pointer */
unchar
dataptr
[
3
];
/* SCSI Data Block Pointer */
unchar
linkptr
[
3
];
/* Next Command Link Pointer */
unchar
linkptr
[
3
];
/* Next Command Link Pointer */
unchar
direc
;
/* Transfer Direction */
unchar
direc
;
/* Transfer Direction */
unchar
reserved2
[
6
];
/* SCSI Command Descriptor Block */
unchar
reserved2
[
6
];
/* SCSI Command Descriptor Block */
/* end of hardware SCB */
/* end of hardware SCB */
Scsi_Cmnd
*
SCpnt
;
/* Scsi_Cmnd using this SCB */
Scsi_Cmnd
*
SCpnt
;
/* Scsi_Cmnd using this SCB */
Sgb
sgb
[
WD7000_SG
];
/* Scatter/gather list for this SCB */
Sgb
sgb
[
WD7000_SG
];
/* Scatter/gather list for this SCB */
Adapter
*
host
;
/* host adapter */
Adapter
*
host
;
/* host adapter */
struct
scb
*
next
;
/* for lists of scbs */
struct
scb
*
next
;
/* for lists of scbs */
}
Scb
;
}
Scb
;
/*
/*
...
@@ -484,56 +480,56 @@ typedef struct scb { /* Command Control Block 5.4.1 */
...
@@ -484,56 +480,56 @@ typedef struct scb { /* Command Control Block 5.4.1 */
#define ICB_OP_GET_EPARMS 0x8F
/* read execution parameters */
#define ICB_OP_GET_EPARMS 0x8F
/* read execution parameters */
typedef
struct
icbRecvCmd
{
typedef
struct
icbRecvCmd
{
unchar
op
;
unchar
op
;
unchar
IDlun
;
/* Initiator SCSI ID/lun */
unchar
IDlun
;
/* Initiator SCSI ID/lun */
unchar
len
[
3
];
/* command buffer length */
unchar
len
[
3
];
/* command buffer length */
unchar
ptr
[
3
];
/* command buffer address */
unchar
ptr
[
3
];
/* command buffer address */
unchar
rsvd
[
7
];
/* reserved */
unchar
rsvd
[
7
];
/* reserved */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
phase
;
/* used by interrupt handler */
volatile
unchar
phase
;
/* used by interrupt handler */
}
IcbRecvCmd
;
}
IcbRecvCmd
;
typedef
struct
icbSendStat
{
typedef
struct
icbSendStat
{
unchar
op
;
unchar
op
;
unchar
IDlun
;
/* Target SCSI ID/lun */
unchar
IDlun
;
/* Target SCSI ID/lun */
unchar
stat
;
/* (outgoing) completion status byte 1 */
unchar
stat
;
/* (outgoing) completion status byte 1 */
unchar
rsvd
[
12
];
/* reserved */
unchar
rsvd
[
12
];
/* reserved */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
phase
;
/* used by interrupt handler */
volatile
unchar
phase
;
/* used by interrupt handler */
}
IcbSendStat
;
}
IcbSendStat
;
typedef
struct
icbRevLvl
{
typedef
struct
icbRevLvl
{
unchar
op
;
unchar
op
;
volatile
unchar
primary
;
/* primary revision level (returned) */
volatile
unchar
primary
;
/* primary revision level (returned) */
volatile
unchar
secondary
;
/* secondary revision level (returned) */
volatile
unchar
secondary
;
/* secondary revision level (returned) */
unchar
rsvd
[
12
];
/* reserved */
unchar
rsvd
[
12
];
/* reserved */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
phase
;
/* used by interrupt handler */
volatile
unchar
phase
;
/* used by interrupt handler */
}
IcbRevLvl
;
}
IcbRevLvl
;
typedef
struct
icbUnsMask
{
/* I'm totally guessing here */
typedef
struct
icbUnsMask
{
/* I'm totally guessing here */
unchar
op
;
unchar
op
;
volatile
unchar
mask
[
14
];
/* mask bits */
volatile
unchar
mask
[
14
];
/* mask bits */
#if 0
#if 0
unchar rsvd[12];
/* reserved */
unchar rsvd[12];
/* reserved */
#endif
#endif
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
phase
;
/* used by interrupt handler */
volatile
unchar
phase
;
/* used by interrupt handler */
}
IcbUnsMask
;
}
IcbUnsMask
;
typedef
struct
icbDiag
{
typedef
struct
icbDiag
{
unchar
op
;
unchar
op
;
unchar
type
;
/* diagnostics type code (0-3) */
unchar
type
;
/* diagnostics type code (0-3) */
unchar
len
[
3
];
/* buffer length */
unchar
len
[
3
];
/* buffer length */
unchar
ptr
[
3
];
/* buffer address */
unchar
ptr
[
3
];
/* buffer address */
unchar
rsvd
[
7
];
/* reserved */
unchar
rsvd
[
7
];
/* reserved */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
phase
;
/* used by interrupt handler */
volatile
unchar
phase
;
/* used by interrupt handler */
}
IcbDiag
;
}
IcbDiag
;
#define ICB_DIAG_POWERUP 0
/* Power-up diags only */
#define ICB_DIAG_POWERUP 0
/* Power-up diags only */
...
@@ -542,34 +538,34 @@ typedef struct icbDiag {
...
@@ -542,34 +538,34 @@ typedef struct icbDiag {
#define ICB_DIAG_FULL 3
/* do both 1 & 2 */
#define ICB_DIAG_FULL 3
/* do both 1 & 2 */
typedef
struct
icbParms
{
typedef
struct
icbParms
{
unchar
op
;
unchar
op
;
unchar
rsvd1
;
/* reserved */
unchar
rsvd1
;
/* reserved */
unchar
len
[
3
];
/* parms buffer length */
unchar
len
[
3
];
/* parms buffer length */
unchar
ptr
[
3
];
/* parms buffer address */
unchar
ptr
[
3
];
/* parms buffer address */
unchar
idx
[
2
];
/* index (MSB-LSB) */
unchar
idx
[
2
];
/* index (MSB-LSB) */
unchar
rsvd2
[
5
];
/* reserved */
unchar
rsvd2
[
5
];
/* reserved */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
phase
;
/* used by interrupt handler */
volatile
unchar
phase
;
/* used by interrupt handler */
}
IcbParms
;
}
IcbParms
;
typedef
struct
icbAny
{
typedef
struct
icbAny
{
unchar
op
;
unchar
op
;
unchar
data
[
14
];
/* format-specific data */
unchar
data
[
14
];
/* format-specific data */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
vue
;
/* vendor-unique error code */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
status
;
/* returned (icmb) status */
volatile
unchar
phase
;
/* used by interrupt handler */
volatile
unchar
phase
;
/* used by interrupt handler */
}
IcbAny
;
}
IcbAny
;
typedef
union
icb
{
typedef
union
icb
{
unchar
op
;
/* ICB opcode */
unchar
op
;
/* ICB opcode */
IcbRecvCmd
recv_cmd
;
/* format for receive command */
IcbRecvCmd
recv_cmd
;
/* format for receive command */
IcbSendStat
send_stat
;
/* format for send status */
IcbSendStat
send_stat
;
/* format for send status */
IcbRevLvl
rev_lvl
;
/* format for get revision level */
IcbRevLvl
rev_lvl
;
/* format for get revision level */
IcbDiag
diag
;
/* format for execute diagnostics */
IcbDiag
diag
;
/* format for execute diagnostics */
IcbParms
eparms
;
/* format for get/set exec parms */
IcbParms
eparms
;
/* format for get/set exec parms */
IcbAny
icb
;
/* generic format */
IcbAny
icb
;
/* generic format */
unchar
data
[
18
];
unchar
data
[
18
];
}
Icb
;
}
Icb
;
#ifdef MODULE
#ifdef MODULE
...
@@ -586,22 +582,19 @@ MODULE_PARM(wd7000, "s");
...
@@ -586,22 +582,19 @@ MODULE_PARM(wd7000, "s");
static
Scb
scbs
[
MAX_SCBS
];
static
Scb
scbs
[
MAX_SCBS
];
static
Scb
*
scbfree
;
/* free list */
static
Scb
*
scbfree
;
/* free list */
static
int
freescbs
=
MAX_SCBS
;
/* free list counter */
static
int
freescbs
=
MAX_SCBS
;
/* free list counter */
static
spinlock_t
scbpool_lock
;
/* guards the scb free list and count */
static
spinlock_t
scbpool_lock
;
/* guards the scb free list and count */
/*
/*
* END of data/declarations - code follows.
* END of data/declarations - code follows.
*/
*/
static
void
__init
setup_error
(
char
*
mesg
,
int
*
ints
)
static
void
__init
setup_error
(
char
*
mesg
,
int
*
ints
)
{
{
if
(
ints
[
0
]
==
3
)
if
(
ints
[
0
]
==
3
)
printk
(
KERN_ERR
"wd7000_setup:
\"
wd7000=%d,%d,0x%x
\"
-> %s
\n
"
,
printk
(
KERN_ERR
"wd7000_setup:
\"
wd7000=%d,%d,0x%x
\"
-> %s
\n
"
,
ints
[
1
],
ints
[
2
],
ints
[
3
],
mesg
);
ints
[
1
],
ints
[
2
],
ints
[
3
],
mesg
);
else
if
(
ints
[
0
]
==
4
)
else
if
(
ints
[
0
]
==
4
)
printk
(
KERN_ERR
"wd7000_setup:
\"
wd7000=%d,%d,0x%x,%d
\"
-> %s
\n
"
,
ints
[
1
],
ints
[
2
],
ints
[
3
],
ints
[
4
],
mesg
);
printk
(
KERN_ERR
"wd7000_setup:
\"
wd7000=%d,%d,0x%x,%d
\"
-> %s
\n
"
,
else
ints
[
1
],
ints
[
2
],
ints
[
3
],
ints
[
4
],
mesg
);
printk
(
KERN_ERR
"wd7000_setup:
\"
wd7000=%d,%d,0x%x,%d,%d
\"
-> %s
\n
"
,
ints
[
1
],
ints
[
2
],
ints
[
3
],
ints
[
4
],
ints
[
5
],
mesg
);
else
printk
(
KERN_ERR
"wd7000_setup:
\"
wd7000=%d,%d,0x%x,%d,%d
\"
-> %s
\n
"
,
ints
[
1
],
ints
[
2
],
ints
[
3
],
ints
[
4
],
ints
[
5
],
mesg
);
}
}
...
@@ -621,23 +614,19 @@ static void __init setup_error(char *mesg, int *ints)
...
@@ -621,23 +614,19 @@ static void __init setup_error(char *mesg, int *ints)
*/
*/
static
int
__init
wd7000_setup
(
char
*
str
)
static
int
__init
wd7000_setup
(
char
*
str
)
{
{
static
short
wd7000_card_num
;
/* .bss will zero this */
static
short
wd7000_card_num
;
/* .bss will zero this */
short
i
;
short
i
;
int
ints
[
6
];
int
ints
[
6
];
(
void
)
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
(
void
)
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
if
(
wd7000_card_num
>=
NUM_CONFIGS
)
{
if
(
wd7000_card_num
>=
NUM_CONFIGS
)
{
printk
(
KERN_ERR
printk
(
KERN_ERR
"%s: Too many
\"
wd7000=
\"
configurations in "
"command line!
\n
"
,
__FUNCTION__
);
"%s: Too many
\"
wd7000=
\"
configurations in "
"command line!
\n
"
,
__FUNCTION__
);
return
0
;
return
0
;
}
}
if
((
ints
[
0
]
<
3
)
||
(
ints
[
0
]
>
5
))
{
if
((
ints
[
0
]
<
3
)
||
(
ints
[
0
]
>
5
))
{
printk
(
KERN_ERR
"%s: Error in command line! "
printk
(
KERN_ERR
"%s: Error in command line! "
"Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>"
"[,<BUS_OFF>]]
\n
"
,
__FUNCTION__
);
"Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>"
"[,<BUS_OFF>]]
\n
"
,
__FUNCTION__
);
}
else
{
}
else
{
for
(
i
=
0
;
i
<
NUM_IRQS
;
i
++
)
for
(
i
=
0
;
i
<
NUM_IRQS
;
i
++
)
if
(
ints
[
1
]
==
wd7000_irq
[
i
])
if
(
ints
[
1
]
==
wd7000_irq
[
i
])
...
@@ -671,8 +660,7 @@ static int __init wd7000_setup(char *str)
...
@@ -671,8 +660,7 @@ static int __init wd7000_setup(char *str)
if
(
ints
[
0
]
>
3
)
{
if
(
ints
[
0
]
>
3
)
{
if
((
ints
[
4
]
<
500
)
||
(
ints
[
4
]
>
31875
))
{
if
((
ints
[
4
]
<
500
)
||
(
ints
[
4
]
>
31875
))
{
setup_error
(
"BUS_ON value is out of range (500"
setup_error
(
"BUS_ON value is out of range (500"
" to 31875 nanoseconds)!"
,
ints
);
" to 31875 nanoseconds)!"
,
ints
);
configs
[
wd7000_card_num
].
bus_on
=
BUS_ON
;
configs
[
wd7000_card_num
].
bus_on
=
BUS_ON
;
}
else
}
else
configs
[
wd7000_card_num
].
bus_on
=
ints
[
4
]
/
125
;
configs
[
wd7000_card_num
].
bus_on
=
ints
[
4
]
/
125
;
...
@@ -681,12 +669,10 @@ static int __init wd7000_setup(char *str)
...
@@ -681,12 +669,10 @@ static int __init wd7000_setup(char *str)
if
(
ints
[
0
]
>
4
)
{
if
(
ints
[
0
]
>
4
)
{
if
((
ints
[
5
]
<
500
)
||
(
ints
[
5
]
>
31875
))
{
if
((
ints
[
5
]
<
500
)
||
(
ints
[
5
]
>
31875
))
{
setup_error
(
"BUS_OFF value is out of range (500"
setup_error
(
"BUS_OFF value is out of range (500"
" to 31875 nanoseconds)!"
,
ints
);
" to 31875 nanoseconds)!"
,
ints
);
configs
[
wd7000_card_num
].
bus_off
=
BUS_OFF
;
configs
[
wd7000_card_num
].
bus_off
=
BUS_OFF
;
}
else
}
else
configs
[
wd7000_card_num
].
bus_off
=
ints
[
5
]
/
configs
[
wd7000_card_num
].
bus_off
=
ints
[
5
]
/
125
;
125
;
}
else
}
else
configs
[
wd7000_card_num
].
bus_off
=
BUS_OFF
;
configs
[
wd7000_card_num
].
bus_off
=
BUS_OFF
;
...
@@ -696,32 +682,22 @@ static int __init wd7000_setup(char *str)
...
@@ -696,32 +682,22 @@ static int __init wd7000_setup(char *str)
for
(;
j
<
wd7000_card_num
;
j
++
)
for
(;
j
<
wd7000_card_num
;
j
++
)
if
(
configs
[
i
].
irq
==
configs
[
j
].
irq
)
{
if
(
configs
[
i
].
irq
==
configs
[
j
].
irq
)
{
setup_error
(
"duplicated IRQ!"
,
setup_error
(
"duplicated IRQ!"
,
ints
);
ints
);
return
0
;
}
if
(
configs
[
i
].
dma
==
configs
[
j
].
dma
)
{
setup_error
(
"duplicated DMA "
"channel!"
,
ints
);
return
0
;
}
if
(
configs
[
i
].
iobase
==
configs
[
j
].
iobase
)
{
setup_error
(
"duplicated I/O "
"base address!"
,
ints
);
return
0
;
return
0
;
}
}
if
(
configs
[
i
].
dma
==
configs
[
j
].
dma
)
{
setup_error
(
"duplicated DMA "
"channel!"
,
ints
);
return
0
;
}
if
(
configs
[
i
].
iobase
==
configs
[
j
].
iobase
)
{
setup_error
(
"duplicated I/O "
"base address!"
,
ints
);
return
0
;
}
}
}
}
}
dprintk
(
KERN_DEBUG
"wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, "
dprintk
(
KERN_DEBUG
"wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, "
"BUS_ON=%dns, BUS_OFF=%dns
\n
"
,
"BUS_ON=%dns, BUS_OFF=%dns
\n
"
,
configs
[
wd7000_card_num
].
irq
,
configs
[
wd7000_card_num
].
dma
,
configs
[
wd7000_card_num
].
iobase
,
configs
[
wd7000_card_num
].
bus_on
*
125
,
configs
[
wd7000_card_num
].
bus_off
*
125
);
configs
[
wd7000_card_num
].
irq
,
configs
[
wd7000_card_num
].
dma
,
configs
[
wd7000_card_num
].
iobase
,
configs
[
wd7000_card_num
].
bus_on
*
125
,
configs
[
wd7000_card_num
].
bus_off
*
125
);
wd7000_card_num
++
;
wd7000_card_num
++
;
}
}
...
@@ -740,29 +716,29 @@ __setup("wd7000=", wd7000_setup);
...
@@ -740,29 +716,29 @@ __setup("wd7000=", wd7000_setup);
* (They were simply 4-byte versions of these routines).
* (They were simply 4-byte versions of these routines).
*/
*/
typedef
union
{
/* let's cheat... */
typedef
union
{
/* let's cheat... */
int
i
;
int
i
;
unchar
u
[
sizeof
(
int
)];
/* the sizeof(int) makes it more portable */
unchar
u
[
sizeof
(
int
)];
/* the sizeof(int) makes it more portable */
}
i_u
;
}
i_u
;
static
inline
void
any2scsi
(
unchar
*
scsi
,
int
any
)
static
inline
void
any2scsi
(
unchar
*
scsi
,
int
any
)
{
{
*
scsi
++
=
((
i_u
)
any
).
u
[
2
];
*
scsi
++
=
((
i_u
)
any
).
u
[
2
];
*
scsi
++
=
((
i_u
)
any
).
u
[
1
];
*
scsi
++
=
((
i_u
)
any
).
u
[
1
];
*
scsi
++
=
((
i_u
)
any
).
u
[
0
];
*
scsi
++
=
((
i_u
)
any
).
u
[
0
];
}
}
static
inline
int
scsi2int
(
unchar
*
scsi
)
static
inline
int
scsi2int
(
unchar
*
scsi
)
{
{
i_u
result
;
i_u
result
;
result
.
i
=
0
;
/* clears unused bytes */
result
.
i
=
0
;
/* clears unused bytes */
result
.
u
[
2
]
=
*
scsi
++
;
result
.
u
[
2
]
=
*
scsi
++
;
result
.
u
[
1
]
=
*
scsi
++
;
result
.
u
[
1
]
=
*
scsi
++
;
result
.
u
[
0
]
=
*
scsi
++
;
result
.
u
[
0
]
=
*
scsi
++
;
return
(
result
.
i
);
return
(
result
.
i
);
}
}
#else
#else
/*
/*
...
@@ -780,63 +756,63 @@ static inline int scsi2int (unchar * scsi)
...
@@ -780,63 +756,63 @@ static inline int scsi2int (unchar * scsi)
#endif
#endif
static
inline
void
wd7000_enable_intr
(
Adapter
*
host
)
static
inline
void
wd7000_enable_intr
(
Adapter
*
host
)
{
{
host
->
control
|=
INT_EN
;
host
->
control
|=
INT_EN
;
outb
(
host
->
control
,
host
->
iobase
+
ASC_CONTROL
);
outb
(
host
->
control
,
host
->
iobase
+
ASC_CONTROL
);
}
}
static
inline
void
wd7000_enable_dma
(
Adapter
*
host
)
static
inline
void
wd7000_enable_dma
(
Adapter
*
host
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
host
->
control
|=
DMA_EN
;
host
->
control
|=
DMA_EN
;
outb
(
host
->
control
,
host
->
iobase
+
ASC_CONTROL
);
outb
(
host
->
control
,
host
->
iobase
+
ASC_CONTROL
);
flags
=
claim_dma_lock
();
flags
=
claim_dma_lock
();
set_dma_mode
(
host
->
dma
,
DMA_MODE_CASCADE
);
set_dma_mode
(
host
->
dma
,
DMA_MODE_CASCADE
);
enable_dma
(
host
->
dma
);
enable_dma
(
host
->
dma
);
release_dma_lock
(
flags
);
release_dma_lock
(
flags
);
}
}
#define WAITnexttimeout 200
/* 2 seconds */
#define WAITnexttimeout 200
/* 2 seconds */
static
inline
short
WAIT
(
unsigned
port
,
unsigned
mask
,
unsigned
allof
,
unsigned
noneof
)
static
inline
short
WAIT
(
unsigned
port
,
unsigned
mask
,
unsigned
allof
,
unsigned
noneof
)
{
{
register
unsigned
WAITbits
;
register
unsigned
WAITbits
;
register
unsigned
long
WAITtimeout
=
jiffies
+
WAITnexttimeout
;
register
unsigned
long
WAITtimeout
=
jiffies
+
WAITnexttimeout
;
while
(
time_before_eq
(
jiffies
,
WAITtimeout
))
{
while
(
time_before_eq
(
jiffies
,
WAITtimeout
))
{
WAITbits
=
inb
(
port
)
&
mask
;
WAITbits
=
inb
(
port
)
&
mask
;
if
(((
WAITbits
&
allof
)
==
allof
)
&&
((
WAITbits
&
noneof
)
==
0
))
if
(((
WAITbits
&
allof
)
==
allof
)
&&
((
WAITbits
&
noneof
)
==
0
))
return
(
0
);
return
(
0
);
}
}
return
(
1
);
return
(
1
);
}
}
static
inline
int
command_out
(
Adapter
*
host
,
unchar
*
cmd
,
int
len
)
static
inline
int
command_out
(
Adapter
*
host
,
unchar
*
cmd
,
int
len
)
{
{
if
(
!
WAIT
(
host
->
iobase
+
ASC_STAT
,
ASC_STATMASK
,
CMD_RDY
,
0
))
{
if
(
!
WAIT
(
host
->
iobase
+
ASC_STAT
,
ASC_STATMASK
,
CMD_RDY
,
0
))
{
while
(
len
--
)
{
while
(
len
--
)
{
do
{
do
{
outb
(
*
cmd
,
host
->
iobase
+
ASC_COMMAND
);
outb
(
*
cmd
,
host
->
iobase
+
ASC_COMMAND
);
WAIT
(
host
->
iobase
+
ASC_STAT
,
ASC_STATMASK
,
CMD_RDY
,
0
);
WAIT
(
host
->
iobase
+
ASC_STAT
,
ASC_STATMASK
,
CMD_RDY
,
0
);
}
while
(
inb
(
host
->
iobase
+
ASC_STAT
)
&
CMD_REJ
);
}
while
(
inb
(
host
->
iobase
+
ASC_STAT
)
&
CMD_REJ
);
cmd
++
;
cmd
++
;
}
}
return
(
1
);
return
(
1
);
}
}
printk
(
KERN_WARNING
"wd7000 command_out: WAIT failed(%d)
\n
"
,
len
+
1
);
printk
(
KERN_WARNING
"wd7000 command_out: WAIT failed(%d)
\n
"
,
len
+
1
);
return
(
0
);
return
(
0
);
}
}
...
@@ -852,654 +828,645 @@ static inline int command_out (Adapter * host, unchar * cmd, int len)
...
@@ -852,654 +828,645 @@ static inline int command_out (Adapter * host, unchar * cmd, int len)
*/
*/
static
inline
Scb
*
alloc_scbs
(
struct
Scsi_Host
*
host
,
int
needed
)
static
inline
Scb
*
alloc_scbs
(
struct
Scsi_Host
*
host
,
int
needed
)
{
{
register
Scb
*
scb
,
*
p
=
NULL
;
register
Scb
*
scb
,
*
p
=
NULL
;
register
unsigned
long
flags
;
register
unsigned
long
flags
;
register
unsigned
long
timeout
=
jiffies
+
WAITnexttimeout
;
register
unsigned
long
timeout
=
jiffies
+
WAITnexttimeout
;
register
unsigned
long
now
;
register
unsigned
long
now
;
int
i
;
int
i
;
if
(
needed
<=
0
)
if
(
needed
<=
0
)
return
(
NULL
);
/* sanity check */
return
(
NULL
);
/* sanity check */
spin_unlock_irq
(
host
->
host_lock
);
spin_unlock_irq
(
host
->
host_lock
);
retry:
retry:
while
(
freescbs
<
needed
)
{
while
(
freescbs
<
needed
)
{
timeout
=
jiffies
+
WAITnexttimeout
;
timeout
=
jiffies
+
WAITnexttimeout
;
do
{
do
{
/* FIXME: can we actually just yield here ?? */
/* FIXME: can we actually just yield here ?? */
for
(
now
=
jiffies
;
now
==
jiffies
;
)
for
(
now
=
jiffies
;
now
==
jiffies
;)
cpu_relax
();
/* wait a jiffy */
cpu_relax
();
/* wait a jiffy */
}
while
(
freescbs
<
needed
&&
time_before_eq
(
jiffies
,
timeout
));
}
while
(
freescbs
<
needed
&&
time_before_eq
(
jiffies
,
timeout
));
/*
/*
* If we get here with enough free Scbs, we can take them.
* If we get here with enough free Scbs, we can take them.
* Otherwise, we timed out and didn't get enough.
* Otherwise, we timed out and didn't get enough.
*/
*/
if
(
freescbs
<
needed
)
{
printk
(
KERN_ERR
"wd7000: can't get enough free SCBs.
\n
"
);
return
(
NULL
);
}
}
/* Take the lock, then check we didnt get beaten, if so try again */
spin_lock_irqsave
(
&
scbpool_lock
,
flags
);
if
(
freescbs
<
needed
)
{
if
(
freescbs
<
needed
)
{
printk
(
KERN_ERR
"wd7000: can't get enough free SCBs.
\n
"
);
spin_unlock_irqrestore
(
&
scbpool_lock
,
flags
);
return
(
NULL
)
;
goto
retry
;
}
}
}
scb
=
scbfree
;
/* Take the lock, then check we didnt get beaten, if so try again */
freescbs
-=
needed
;
spin_lock_irqsave
(
&
scbpool_lock
,
flags
);
for
(
i
=
0
;
i
<
needed
;
i
++
)
{
if
(
freescbs
<
needed
)
p
=
scbfree
;
{
scbfree
=
p
->
next
;
spin_unlock_irqrestore
(
&
scbpool_lock
,
flags
);
}
goto
retry
;
p
->
next
=
NULL
;
}
spin_unlock_irqrestore
(
&
scbpool_lock
,
flags
);
scb
=
scbfree
;
freescbs
-=
needed
;
spin_lock_irq
(
host
->
host_lock
);
for
(
i
=
0
;
i
<
needed
;
i
++
)
{
return
(
scb
);
p
=
scbfree
;
scbfree
=
p
->
next
;
}
p
->
next
=
NULL
;
spin_unlock_irqrestore
(
&
scbpool_lock
,
flags
);
spin_lock_irq
(
host
->
host_lock
);
return
(
scb
);
}
}
static
inline
void
free_scb
(
Scb
*
scb
)
static
inline
void
free_scb
(
Scb
*
scb
)
{
{
register
unsigned
long
flags
;
register
unsigned
long
flags
;
spin_lock_irqsave
(
&
scbpool_lock
,
flags
);
spin_lock_irqsave
(
&
scbpool_lock
,
flags
);
memset
(
scb
,
0
,
sizeof
(
Scb
));
memset
(
scb
,
0
,
sizeof
(
Scb
));
scb
->
next
=
scbfree
;
scb
->
next
=
scbfree
;
scbfree
=
scb
;
scbfree
=
scb
;
freescbs
++
;
freescbs
++
;
spin_unlock_irqrestore
(
&
scbpool_lock
,
flags
);
spin_unlock_irqrestore
(
&
scbpool_lock
,
flags
);
}
}
static
inline
void
init_scbs
(
void
)
static
inline
void
init_scbs
(
void
)
{
{
int
i
;
int
i
;
spin_lock_init
(
&
scbpool_lock
);
spin_lock_init
(
&
scbpool_lock
);
/* This is only ever called before the SCB pool is active */
/* This is only ever called before the SCB pool is active */
scbfree
=
&
(
scbs
[
0
]);
scbfree
=
&
(
scbs
[
0
]);
memset
(
scbs
,
0
,
sizeof
(
scbs
));
memset
(
scbs
,
0
,
sizeof
(
scbs
));
for
(
i
=
0
;
i
<
MAX_SCBS
-
1
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_SCBS
-
1
;
i
++
)
{
scbs
[
i
].
next
=
&
(
scbs
[
i
+
1
]);
scbs
[
i
].
next
=
&
(
scbs
[
i
+
1
]);
scbs
[
i
].
SCpnt
=
NULL
;
scbs
[
i
].
SCpnt
=
NULL
;
}
}
scbs
[
MAX_SCBS
-
1
].
next
=
NULL
;
scbs
[
MAX_SCBS
-
1
].
next
=
NULL
;
scbs
[
MAX_SCBS
-
1
].
SCpnt
=
NULL
;
scbs
[
MAX_SCBS
-
1
].
SCpnt
=
NULL
;
}
}
static
int
mail_out
(
Adapter
*
host
,
Scb
*
scbptr
)
static
int
mail_out
(
Adapter
*
host
,
Scb
*
scbptr
)
/*
/*
* Note: this can also be used for ICBs; just cast to the parm type.
* Note: this can also be used for ICBs; just cast to the parm type.
*/
*/
{
{
register
int
i
,
ogmb
;
register
int
i
,
ogmb
;
register
unsigned
long
flags
;
register
unsigned
long
flags
;
unchar
start_ogmb
;
unchar
start_ogmb
;
Mailbox
*
ogmbs
=
host
->
mb
.
ogmb
;
Mailbox
*
ogmbs
=
host
->
mb
.
ogmb
;
int
*
next_ogmb
=
&
(
host
->
next_ogmb
);
int
*
next_ogmb
=
&
(
host
->
next_ogmb
);
dprintk
(
"wd7000_mail_out: 0x%06lx"
,
(
long
)
scbptr
);
dprintk
(
"wd7000_mail_out: 0x%06lx"
,
(
long
)
scbptr
);
/* We first look for a free outgoing mailbox */
/* We first look for a free outgoing mailbox */
spin_lock_irqsave
(
host
->
sh
->
host_lock
,
flags
);
spin_lock_irqsave
(
host
->
sh
->
host_lock
,
flags
);
ogmb
=
*
next_ogmb
;
ogmb
=
*
next_ogmb
;
for
(
i
=
0
;
i
<
OGMB_CNT
;
i
++
)
{
for
(
i
=
0
;
i
<
OGMB_CNT
;
i
++
)
{
if
(
ogmbs
[
ogmb
].
status
==
0
)
{
if
(
ogmbs
[
ogmb
].
status
==
0
)
{
dprintk
(
" using OGMB 0x%x"
,
ogmb
);
dprintk
(
" using OGMB 0x%x"
,
ogmb
);
ogmbs
[
ogmb
].
status
=
1
;
ogmbs
[
ogmb
].
status
=
1
;
any2scsi
((
unchar
*
)
ogmbs
[
ogmb
].
scbptr
,
(
int
)
scbptr
);
any2scsi
((
unchar
*
)
ogmbs
[
ogmb
].
scbptr
,
(
int
)
scbptr
);
*
next_ogmb
=
(
ogmb
+
1
)
%
OGMB_CNT
;
*
next_ogmb
=
(
ogmb
+
1
)
%
OGMB_CNT
;
break
;
break
;
}
else
ogmb
=
(
ogmb
+
1
)
%
OGMB_CNT
;
}
}
else
spin_unlock_irqrestore
(
host
->
sh
->
host_lock
,
flags
);
ogmb
=
(
ogmb
+
1
)
%
OGMB_CNT
;
}
spin_unlock_irqrestore
(
host
->
sh
->
host_lock
,
flags
);
dprintk
(
", scb is 0x%06lx"
,
(
long
)
scbptr
);
if
(
i
>=
OGMB_CNT
)
{
dprintk
(
", scb is 0x%06lx"
,
(
long
)
scbptr
);
/*
* Alternatively, we might issue the "interrupt on free OGMB",
* and sleep, but it must be ensured that it isn't the init
* task running. Instead, this version assumes that the caller
* will be persistent, and try again. Since it's the adapter
* that marks OGMB's free, waiting even with interrupts off
* should work, since they are freed very quickly in most cases.
*/
dprintk
(
", no free OGMBs.
\n
"
);
return
(
0
);
}
wd7000_enable_intr
(
host
);
if
(
i
>=
OGMB_CNT
)
{
/*
* Alternatively, we might issue the "interrupt on free OGMB",
* and sleep, but it must be ensured that it isn't the init
* task running. Instead, this version assumes that the caller
* will be persistent, and try again. Since it's the adapter
* that marks OGMB's free, waiting even with interrupts off
* should work, since they are freed very quickly in most cases.
*/
dprintk
(
", no free OGMBs.
\n
"
);
return
(
0
);
}
start_ogmb
=
START_OGMB
|
ogmb
;
wd7000_enable_intr
(
host
);
command_out
(
host
,
&
start_ogmb
,
1
);
dprintk
(
", awaiting interrupt.
\n
"
);
start_ogmb
=
START_OGMB
|
ogmb
;
command_out
(
host
,
&
start_ogmb
,
1
);
return
(
1
);
dprintk
(
", awaiting interrupt.
\n
"
);
return
(
1
);
}
}
static
int
make_code
(
unsigned
hosterr
,
unsigned
scsierr
)
static
int
make_code
(
unsigned
hosterr
,
unsigned
scsierr
)
{
{
#ifdef WD7000_DEBUG
#ifdef WD7000_DEBUG
int
in_error
=
hosterr
;
int
in_error
=
hosterr
;
#endif
#endif
switch
((
hosterr
>>
8
)
&
0xff
)
{
switch
((
hosterr
>>
8
)
&
0xff
)
{
case
0
:
/* Reserved */
case
0
:
/* Reserved */
hosterr
=
DID_ERROR
;
hosterr
=
DID_ERROR
;
break
;
break
;
case
1
:
/* Command Complete, no errors */
case
1
:
/* Command Complete, no errors */
hosterr
=
DID_OK
;
hosterr
=
DID_OK
;
break
;
break
;
case
2
:
/* Command complete, error logged in scb status (scsierr) */
case
2
:
/* Command complete, error logged in scb status (scsierr) */
hosterr
=
DID_OK
;
hosterr
=
DID_OK
;
break
;
break
;
case
4
:
/* Command failed to complete - timeout */
case
4
:
/* Command failed to complete - timeout */
hosterr
=
DID_TIME_OUT
;
hosterr
=
DID_TIME_OUT
;
break
;
break
;
case
5
:
/* Command terminated; Bus reset by external device */
case
5
:
/* Command terminated; Bus reset by external device */
hosterr
=
DID_RESET
;
hosterr
=
DID_RESET
;
break
;
break
;
case
6
:
/* Unexpected Command Received w/ host as target */
case
6
:
/* Unexpected Command Received w/ host as target */
hosterr
=
DID_BAD_TARGET
;
hosterr
=
DID_BAD_TARGET
;
break
;
break
;
case
80
:
/* Unexpected Reselection */
case
80
:
/* Unexpected Reselection */
case
81
:
/* Unexpected Selection */
case
81
:
/* Unexpected Selection */
hosterr
=
DID_BAD_INTR
;
hosterr
=
DID_BAD_INTR
;
break
;
break
;
case
82
:
/* Abort Command Message */
case
82
:
/* Abort Command Message */
hosterr
=
DID_ABORT
;
hosterr
=
DID_ABORT
;
break
;
break
;
case
83
:
/* SCSI Bus Software Reset */
case
83
:
/* SCSI Bus Software Reset */
case
84
:
/* SCSI Bus Hardware Reset */
case
84
:
/* SCSI Bus Hardware Reset */
hosterr
=
DID_RESET
;
hosterr
=
DID_RESET
;
break
;
break
;
default:
/* Reserved */
default:
/* Reserved */
hosterr
=
DID_ERROR
;
hosterr
=
DID_ERROR
;
}
}
#ifdef WD7000_DEBUG
#ifdef WD7000_DEBUG
if
(
scsierr
||
hosterr
)
if
(
scsierr
||
hosterr
)
dprintk
(
"
\n
SCSI command error: SCSI 0x%02x host 0x%04x return %d
\n
"
,
dprintk
(
"
\n
SCSI command error: SCSI 0x%02x host 0x%04x return %d
\n
"
,
scsierr
,
in_error
,
hosterr
);
scsierr
,
in_error
,
hosterr
);
#endif
#endif
return
(
scsierr
|
(
hosterr
<<
16
));
return
(
scsierr
|
(
hosterr
<<
16
));
}
}
static
void
wd7000_scsi_done
(
Scsi_Cmnd
*
SCpnt
)
static
void
wd7000_scsi_done
(
Scsi_Cmnd
*
SCpnt
)
{
{
dprintk
(
"wd7000_scsi_done: 0x%06lx
\n
"
,
(
long
)
SCpnt
);
dprintk
(
"wd7000_scsi_done: 0x%06lx
\n
"
,
(
long
)
SCpnt
);
SCpnt
->
SCp
.
phase
=
0
;
SCpnt
->
SCp
.
phase
=
0
;
}
}
#define wd7000_intr_ack(host) outb (0, host->iobase + ASC_INTR_ACK)
#define wd7000_intr_ack(host) outb (0, host->iobase + ASC_INTR_ACK)
static
void
wd7000_intr_handle
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
void
wd7000_intr_handle
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
{
register
int
flag
,
icmb
,
errstatus
,
icmb_status
;
register
int
flag
,
icmb
,
errstatus
,
icmb_status
;
register
int
host_error
,
scsi_error
;
register
int
host_error
,
scsi_error
;
register
Scb
*
scb
;
/* for SCSI commands */
register
Scb
*
scb
;
/* for SCSI commands */
register
IcbAny
*
icb
;
/* for host commands */
register
IcbAny
*
icb
;
/* for host commands */
register
Scsi_Cmnd
*
SCpnt
;
register
Scsi_Cmnd
*
SCpnt
;
Adapter
*
host
=
(
Adapter
*
)
dev_id
;
Adapter
*
host
=
(
Adapter
*
)
dev_id
;
Mailbox
*
icmbs
=
host
->
mb
.
icmb
;
Mailbox
*
icmbs
=
host
->
mb
.
icmb
;
host
->
int_counter
++
;
host
->
int_counter
++
;
dprintk
(
"wd7000_intr_handle: irq = %d, host = 0x%06lx
\n
"
,
irq
,
(
long
)
host
);
dprintk
(
"wd7000_intr_handle: irq = %d, host = 0x%06lx
\n
"
,
irq
,
(
long
)
host
);
flag
=
inb
(
host
->
iobase
+
ASC_INTR_STAT
);
flag
=
inb
(
host
->
iobase
+
ASC_INTR_STAT
);
dprintk
(
"wd7000_intr_handle: intr stat = 0x%02x
\n
"
,
flag
);
dprintk
(
"wd7000_intr_handle: intr stat = 0x%02x
\n
"
,
flag
);
if
(
!
(
inb
(
host
->
iobase
+
ASC_STAT
)
&
INT_IM
))
{
if
(
!
(
inb
(
host
->
iobase
+
ASC_STAT
)
&
INT_IM
))
{
/* NB: these are _very_ possible if IRQ 15 is being used, since
/* NB: these are _very_ possible if IRQ 15 is being used, since
* it's the "garbage collector" on the 2nd 8259 PIC. Specifically,
* it's the "garbage collector" on the 2nd 8259 PIC. Specifically,
* any interrupt signal into the 8259 which can't be identified
* any interrupt signal into the 8259 which can't be identified
* comes out as 7 from the 8259, which is 15 to the host. Thus, it
* comes out as 7 from the 8259, which is 15 to the host. Thus, it
* is a good thing the WD7000 has an interrupt status port, so we
* is a good thing the WD7000 has an interrupt status port, so we
* can sort these out. Otherwise, electrical noise and other such
* can sort these out. Otherwise, electrical noise and other such
* problems would be indistinguishable from valid interrupts...
* problems would be indistinguishable from valid interrupts...
*/
*/
dprintk
(
"wd7000_intr_handle: phantom interrupt...
\n
"
);
dprintk
(
"wd7000_intr_handle: phantom interrupt...
\n
"
);
wd7000_intr_ack
(
host
);
wd7000_intr_ack
(
host
);
return
;
}
if
(
flag
&
MB_INTR
)
{
/* The interrupt is for a mailbox */
if
(
!
(
flag
&
IMB_INTR
))
{
dprintk
(
"wd7000_intr_handle: free outgoing mailbox
\n
"
);
/*
* If sleep_on() and the "interrupt on free OGMB" command are
* used in mail_out(), wake_up() should correspondingly be called
* here. For now, we don't need to do anything special.
*/
wd7000_intr_ack
(
host
);
return
;
}
else
{
/* The interrupt is for an incoming mailbox */
icmb
=
flag
&
MB_MASK
;
icmb_status
=
icmbs
[
icmb
].
status
;
if
(
icmb_status
&
0x80
)
{
/* unsolicited - result in ICMB */
dprintk
(
"wd7000_intr_handle: unsolicited interrupt 0x%02x
\n
"
,
icmb_status
);
wd7000_intr_ack
(
host
);
return
;
return
;
}
}
/* Aaaargh! (Zaga) */
scb
=
isa_bus_to_virt
(
scsi2int
((
unchar
*
)
icmbs
[
icmb
].
scbptr
));
if
(
flag
&
MB_INTR
)
{
icmbs
[
icmb
].
status
=
0
;
/* The interrupt is for a mailbox */
if
(
!
(
scb
->
op
&
ICB_OP_MASK
))
{
/* an SCB is done */
if
(
!
(
flag
&
IMB_INTR
))
{
SCpnt
=
scb
->
SCpnt
;
dprintk
(
"wd7000_intr_handle: free outgoing mailbox
\n
"
);
if
(
--
(
SCpnt
->
SCp
.
phase
)
<=
0
)
{
/* all scbs are done */
/*
host_error
=
scb
->
vue
|
(
icmb_status
<<
8
);
* If sleep_on() and the "interrupt on free OGMB" command are
scsi_error
=
scb
->
status
;
* used in mail_out(), wake_up() should correspondingly be called
errstatus
=
make_code
(
host_error
,
scsi_error
);
* here. For now, we don't need to do anything special.
SCpnt
->
result
=
errstatus
;
*/
wd7000_intr_ack
(
host
);
free_scb
(
scb
);
return
;
}
else
{
SCpnt
->
scsi_done
(
SCpnt
);
/* The interrupt is for an incoming mailbox */
}
icmb
=
flag
&
MB_MASK
;
}
icmb_status
=
icmbs
[
icmb
].
status
;
else
{
/* an ICB is done */
if
(
icmb_status
&
0x80
)
{
/* unsolicited - result in ICMB */
icb
=
(
IcbAny
*
)
scb
;
dprintk
(
"wd7000_intr_handle: unsolicited interrupt 0x%02x
\n
"
,
icmb_status
);
icb
->
status
=
icmb_status
;
wd7000_intr_ack
(
host
);
icb
->
phase
=
0
;
return
;
}
}
}
/* incoming mailbox */
/* Aaaargh! (Zaga) */
}
scb
=
isa_bus_to_virt
(
scsi2int
((
unchar
*
)
icmbs
[
icmb
].
scbptr
));
icmbs
[
icmb
].
status
=
0
;
wd7000_intr_ack
(
host
);
if
(
!
(
scb
->
op
&
ICB_OP_MASK
))
{
/* an SCB is done */
SCpnt
=
scb
->
SCpnt
;
dprintk
(
"wd7000_intr_handle: return from interrupt handler
\n
"
);
if
(
--
(
SCpnt
->
SCp
.
phase
)
<=
0
)
{
/* all scbs are done */
host_error
=
scb
->
vue
|
(
icmb_status
<<
8
);
scsi_error
=
scb
->
status
;
errstatus
=
make_code
(
host_error
,
scsi_error
);
SCpnt
->
result
=
errstatus
;
free_scb
(
scb
);
SCpnt
->
scsi_done
(
SCpnt
);
}
}
else
{
/* an ICB is done */
icb
=
(
IcbAny
*
)
scb
;
icb
->
status
=
icmb_status
;
icb
->
phase
=
0
;
}
}
/* incoming mailbox */
}
wd7000_intr_ack
(
host
);
dprintk
(
"wd7000_intr_handle: return from interrupt handler
\n
"
);
}
}
static
void
do_wd7000_intr_handle
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
void
do_wd7000_intr_handle
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
struct
Scsi_Host
*
host
=
dev_id
;
struct
Scsi_Host
*
host
=
dev_id
;
spin_lock_irqsave
(
host
->
host_lock
,
flags
);
spin_lock_irqsave
(
host
->
host_lock
,
flags
);
wd7000_intr_handle
(
irq
,
dev_id
,
regs
);
wd7000_intr_handle
(
irq
,
dev_id
,
regs
);
spin_unlock_irqrestore
(
host
->
host_lock
,
flags
);
spin_unlock_irqrestore
(
host
->
host_lock
,
flags
);
}
}
static
int
wd7000_queuecommand
(
Scsi_Cmnd
*
SCpnt
,
void
(
*
done
)
(
Scsi_Cmnd
*
))
static
int
wd7000_queuecommand
(
Scsi_Cmnd
*
SCpnt
,
void
(
*
done
)
(
Scsi_Cmnd
*
))
{
{
register
Scb
*
scb
;
register
Scb
*
scb
;
register
Sgb
*
sgb
;
register
Sgb
*
sgb
;
register
unchar
*
cdb
=
(
unchar
*
)
SCpnt
->
cmnd
;
register
unchar
*
cdb
=
(
unchar
*
)
SCpnt
->
cmnd
;
register
unchar
idlun
;
register
unchar
idlun
;
register
short
cdblen
;
register
short
cdblen
;
Adapter
*
host
=
(
Adapter
*
)
SCpnt
->
host
->
hostdata
;
Adapter
*
host
=
(
Adapter
*
)
SCpnt
->
host
->
hostdata
;
cdblen
=
SCpnt
->
cmd_len
;
cdblen
=
SCpnt
->
cmd_len
;
idlun
=
((
SCpnt
->
target
<<
5
)
&
0xe0
)
|
(
SCpnt
->
lun
&
7
);
idlun
=
((
SCpnt
->
target
<<
5
)
&
0xe0
)
|
(
SCpnt
->
lun
&
7
);
SCpnt
->
scsi_done
=
done
;
SCpnt
->
scsi_done
=
done
;
SCpnt
->
SCp
.
phase
=
1
;
SCpnt
->
SCp
.
phase
=
1
;
scb
=
alloc_scbs
(
SCpnt
->
host
,
1
);
scb
=
alloc_scbs
(
SCpnt
->
host
,
1
);
scb
->
idlun
=
idlun
;
scb
->
idlun
=
idlun
;
memcpy
(
scb
->
cdb
,
cdb
,
cdblen
);
memcpy
(
scb
->
cdb
,
cdb
,
cdblen
);
scb
->
direc
=
0x40
;
/* Disable direction check */
scb
->
direc
=
0x40
;
/* Disable direction check */
scb
->
SCpnt
=
SCpnt
;
/* so we can find stuff later */
scb
->
SCpnt
=
SCpnt
;
/* so we can find stuff later */
SCpnt
->
host_scribble
=
(
unchar
*
)
scb
;
SCpnt
->
host_scribble
=
(
unchar
*
)
scb
;
scb
->
host
=
host
;
scb
->
host
=
host
;
if
(
SCpnt
->
use_sg
)
{
if
(
SCpnt
->
use_sg
)
{
struct
scatterlist
*
sg
=
(
struct
scatterlist
*
)
SCpnt
->
request_buffer
;
struct
scatterlist
*
sg
=
(
struct
scatterlist
*
)
SCpnt
->
request_buffer
;
unsigned
i
;
unsigned
i
;
if
(
SCpnt
->
host
->
sg_tablesize
==
SG_NONE
)
{
if
(
SCpnt
->
host
->
sg_tablesize
==
SG_NONE
)
{
panic
(
"wd7000_queuecommand: scatter/gather not supported.
\n
"
);
panic
(
"wd7000_queuecommand: scatter/gather not supported.
\n
"
);
}
}
dprintk
(
"Using scatter/gather with %d elements.
\n
"
,
SCpnt
->
use_sg
);
dprintk
(
"Using scatter/gather with %d elements.
\n
"
,
SCpnt
->
use_sg
);
sgb
=
scb
->
sgb
;
sgb
=
scb
->
sgb
;
scb
->
op
=
1
;
scb
->
op
=
1
;
any2scsi
(
scb
->
dataptr
,
(
int
)
sgb
);
any2scsi
(
scb
->
dataptr
,
(
int
)
sgb
);
any2scsi
(
scb
->
maxlen
,
SCpnt
->
use_sg
*
sizeof
(
Sgb
));
any2scsi
(
scb
->
maxlen
,
SCpnt
->
use_sg
*
sizeof
(
Sgb
));
for
(
i
=
0
;
i
<
SCpnt
->
use_sg
;
i
++
)
{
for
(
i
=
0
;
i
<
SCpnt
->
use_sg
;
i
++
)
{
any2scsi
(
sgb
[
i
].
ptr
,
any2scsi
(
sgb
[
i
].
ptr
,
isa_page_to_bus
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
);
isa_page_to_bus
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
);
any2scsi
(
sgb
[
i
].
len
,
sg
[
i
].
length
);
any2scsi
(
sgb
[
i
].
len
,
sg
[
i
].
length
);
}
}
else
{
scb
->
op
=
0
;
any2scsi
(
scb
->
dataptr
,
isa_virt_to_bus
(
SCpnt
->
request_buffer
));
any2scsi
(
scb
->
maxlen
,
SCpnt
->
request_bufflen
);
}
}
}
else
{
/* FIXME: drop lock and yield here ? */
scb
->
op
=
0
;
any2scsi
(
scb
->
dataptr
,
isa_virt_to_bus
(
SCpnt
->
request_buffer
));
while
(
!
mail_out
(
host
,
scb
))
any2scsi
(
scb
->
maxlen
,
SCpnt
->
request_bufflen
);
cpu_relax
();
/* keep trying */
}
return
0
;
/* FIXME: drop lock and yield here ? */
while
(
!
mail_out
(
host
,
scb
))
cpu_relax
();
/* keep trying */
return
0
;
}
}
static
int
wd7000_command
(
Scsi_Cmnd
*
SCpnt
)
static
int
wd7000_command
(
Scsi_Cmnd
*
SCpnt
)
{
{
wd7000_queuecommand
(
SCpnt
,
wd7000_scsi_done
);
wd7000_queuecommand
(
SCpnt
,
wd7000_scsi_done
);
while
(
SCpnt
->
SCp
.
phase
>
0
)
while
(
SCpnt
->
SCp
.
phase
>
0
)
{
{
cpu_relax
();
cpu_relax
();
barrier
();
/* phase counts scbs down to 0 */
barrier
();
/* phase counts scbs down to 0 */
}
}
return
(
SCpnt
->
result
);
return
(
SCpnt
->
result
);
}
}
static
int
wd7000_diagnostics
(
Adapter
*
host
,
int
code
)
static
int
wd7000_diagnostics
(
Adapter
*
host
,
int
code
)
{
{
static
IcbDiag
icb
=
{
ICB_OP_DIAGNOSTICS
};
static
IcbDiag
icb
=
{
ICB_OP_DIAGNOSTICS
};
static
unchar
buf
[
256
];
static
unchar
buf
[
256
];
unsigned
long
timeout
;
unsigned
long
timeout
;
icb
.
type
=
code
;
icb
.
type
=
code
;
any2scsi
(
icb
.
len
,
sizeof
(
buf
));
any2scsi
(
icb
.
len
,
sizeof
(
buf
));
any2scsi
(
icb
.
ptr
,
(
int
)
&
buf
);
any2scsi
(
icb
.
ptr
,
(
int
)
&
buf
);
icb
.
phase
=
1
;
icb
.
phase
=
1
;
/*
/*
* This routine is only called at init, so there should be OGMBs
* This routine is only called at init, so there should be OGMBs
* available. I'm assuming so here. If this is going to
* available. I'm assuming so here. If this is going to
* fail, I can just let the timeout catch the failure.
* fail, I can just let the timeout catch the failure.
*/
*/
mail_out
(
host
,
(
struct
scb
*
)
&
icb
);
mail_out
(
host
,
(
struct
scb
*
)
&
icb
);
timeout
=
jiffies
+
WAITnexttimeout
;
/* wait up to 2 seconds */
timeout
=
jiffies
+
WAITnexttimeout
;
/* wait up to 2 seconds */
while
(
icb
.
phase
&&
time_before
(
jiffies
,
timeout
))
while
(
icb
.
phase
&&
time_before
(
jiffies
,
timeout
))
{
{
cpu_relax
();
/* wait for completion */
cpu_relax
();
/* wait for completion */
barrier
();
barrier
();
}
}
if
(
icb
.
phase
)
{
if
(
icb
.
phase
)
{
printk
(
"wd7000_diagnostics: timed out.
\n
"
);
printk
(
"wd7000_diagnostics: timed out.
\n
"
);
return
(
0
);
return
(
0
);
}
}
if
(
make_code
(
icb
.
vue
|
(
icb
.
status
<<
8
),
0
))
{
if
(
make_code
(
icb
.
vue
|
(
icb
.
status
<<
8
),
0
))
{
printk
(
"wd7000_diagnostics: failed (0x%02x,0x%02x)
\n
"
,
icb
.
vue
,
icb
.
status
);
printk
(
"wd7000_diagnostics: failed (0x%02x,0x%02x)
\n
"
,
return
(
0
);
icb
.
vue
,
icb
.
status
);
}
return
(
0
);
}
return
(
1
);
return
(
1
);
}
}
static
int
wd7000_adapter_reset
(
Adapter
*
host
)
static
int
wd7000_adapter_reset
(
Adapter
*
host
)
{
{
InitCmd
init_cmd
=
InitCmd
init_cmd
=
{
{
INITIALIZATION
,
INITIALIZATION
,
7
,
7
,
host
->
bus_on
,
host
->
bus_on
,
host
->
bus_off
,
host
->
bus_off
,
0
,
0
,
{
0
,
0
,
0
},
{
0
,
0
,
0
},
OGMB_CNT
,
OGMB_CNT
,
ICMB_CNT
ICMB_CNT
};
};
int
diag
;
int
diag
;
/*
/*
* Reset the adapter - only. The SCSI bus was initialized at power-up,
* Reset the adapter - only. The SCSI bus was initialized at power-up,
* and we need to do this just so we control the mailboxes, etc.
* and we need to do this just so we control the mailboxes, etc.
*/
*/
outb
(
ASC_RES
,
host
->
iobase
+
ASC_CONTROL
);
outb
(
ASC_RES
,
host
->
iobase
+
ASC_CONTROL
);
udelay
(
40
);
/* reset pulse: this is 40us, only need 25us */
udelay
(
40
);
/* reset pulse: this is 40us, only need 25us */
outb
(
0
,
host
->
iobase
+
ASC_CONTROL
);
outb
(
0
,
host
->
iobase
+
ASC_CONTROL
);
host
->
control
=
0
;
/* this must always shadow ASC_CONTROL */
host
->
control
=
0
;
/* this must always shadow ASC_CONTROL */
if
(
WAIT
(
host
->
iobase
+
ASC_STAT
,
ASC_STATMASK
,
CMD_RDY
,
0
))
{
if
(
WAIT
(
host
->
iobase
+
ASC_STAT
,
ASC_STATMASK
,
CMD_RDY
,
0
))
{
printk
(
"wd7000_init: WAIT timed out.
\n
"
);
printk
(
"wd7000_init: WAIT timed out.
\n
"
);
return
-
1
;
/* -1 = not ok */
return
-
1
;
/* -1 = not ok */
}
}
if
((
diag
=
inb
(
host
->
iobase
+
ASC_INTR_STAT
))
!=
1
)
{
if
((
diag
=
inb
(
host
->
iobase
+
ASC_INTR_STAT
))
!=
1
)
{
printk
(
"wd7000_init: "
);
printk
(
"wd7000_init: "
);
switch
(
diag
)
{
switch
(
diag
)
{
case
2
:
case
2
:
printk
(
"RAM failure.
\n
"
);
printk
(
"RAM failure.
\n
"
);
break
;
break
;
case
3
:
printk
(
"FIFO R/W failed
\n
"
);
case
3
:
break
;
printk
(
"FIFO R/W failed
\n
"
);
case
4
:
printk
(
"SBIC register R/W failed
\n
"
);
break
;
break
;
case
4
:
case
5
:
printk
(
"Initialization D-FF failed.
\n
"
);
printk
(
"SBIC register R/W failed
\n
"
);
break
;
break
;
case
6
:
printk
(
"Host IRQ D-FF failed.
\n
"
);
case
5
:
break
;
printk
(
"Initialization D-FF failed.
\n
"
);
case
7
:
printk
(
"ROM checksum error.
\n
"
);
break
;
break
;
case
6
:
default:
printk
(
"diagnostic code 0x%02Xh received.
\n
"
,
diag
);
printk
(
"Host IRQ D-FF failed.
\n
"
);
break
;
case
7
:
printk
(
"ROM checksum error.
\n
"
);
break
;
default:
printk
(
"diagnostic code 0x%02Xh received.
\n
"
,
diag
);
}
return
-
1
;
}
/* Clear mailboxes */
memset
(
&
(
host
->
mb
),
0
,
sizeof
(
host
->
mb
));
/* Execute init command */
any2scsi
((
unchar
*
)
&
(
init_cmd
.
mailboxes
),
(
int
)
&
(
host
->
mb
));
if
(
!
command_out
(
host
,
(
unchar
*
)
&
init_cmd
,
sizeof
(
init_cmd
)))
{
printk
(
KERN_ERR
"wd7000_adapter_reset: adapter initialization failed.
\n
"
);
return
-
1
;
}
if
(
WAIT
(
host
->
iobase
+
ASC_STAT
,
ASC_STATMASK
,
ASC_INIT
,
0
))
{
printk
(
"wd7000_adapter_reset: WAIT timed out.
\n
"
);
return
-
1
;
}
}
return
-
1
;
return
0
;
}
/* Clear mailboxes */
memset
(
&
(
host
->
mb
),
0
,
sizeof
(
host
->
mb
));
/* Execute init command */
any2scsi
((
unchar
*
)
&
(
init_cmd
.
mailboxes
),
(
int
)
&
(
host
->
mb
));
if
(
!
command_out
(
host
,
(
unchar
*
)
&
init_cmd
,
sizeof
(
init_cmd
)))
{
printk
(
KERN_ERR
"wd7000_adapter_reset: adapter initialization failed.
\n
"
);
return
-
1
;
}
if
(
WAIT
(
host
->
iobase
+
ASC_STAT
,
ASC_STATMASK
,
ASC_INIT
,
0
))
{
printk
(
"wd7000_adapter_reset: WAIT timed out.
\n
"
);
return
-
1
;
}
return
0
;
}
}
static
int
wd7000_init
(
Adapter
*
host
)
static
int
wd7000_init
(
Adapter
*
host
)
{
{
if
(
wd7000_adapter_reset
(
host
)
==
-
1
)
if
(
wd7000_adapter_reset
(
host
)
==
-
1
)
return
0
;
return
0
;
if
(
request_irq
(
host
->
irq
,
do_wd7000_intr_handle
,
SA_INTERRUPT
,
"wd7000"
,
host
))
{
printk
(
"wd7000_init: can't get IRQ %d.
\n
"
,
host
->
irq
);
return
(
0
);
}
if
(
request_dma
(
host
->
dma
,
"wd7000"
))
{
printk
(
"wd7000_init: can't get DMA channel %d.
\n
"
,
host
->
dma
);
free_irq
(
host
->
irq
,
host
);
return
(
0
);
}
wd7000_enable_dma
(
host
);
wd7000_enable_intr
(
host
);
if
(
!
wd7000_diagnostics
(
host
,
ICB_DIAG_FULL
))
{
if
(
request_irq
(
host
->
irq
,
do_wd7000_intr_handle
,
SA_INTERRUPT
,
"wd7000"
,
host
))
{
free_dma
(
host
->
dma
);
printk
(
"wd7000_init: can't get IRQ %d.
\n
"
,
host
->
irq
);
free_irq
(
host
->
irq
,
NULL
);
return
(
0
);
return
(
0
);
}
}
if
(
request_dma
(
host
->
dma
,
"wd7000"
))
{
printk
(
"wd7000_init: can't get DMA channel %d.
\n
"
,
host
->
dma
);
free_irq
(
host
->
irq
,
host
);
return
(
0
);
}
wd7000_enable_dma
(
host
);
wd7000_enable_intr
(
host
);
return
(
1
);
if
(
!
wd7000_diagnostics
(
host
,
ICB_DIAG_FULL
))
{
free_dma
(
host
->
dma
);
free_irq
(
host
->
irq
,
NULL
);
return
(
0
);
}
return
(
1
);
}
}
static
void
wd7000_revision
(
Adapter
*
host
)
static
void
wd7000_revision
(
Adapter
*
host
)
{
{
static
IcbRevLvl
icb
=
static
IcbRevLvl
icb
=
{
ICB_OP_GET_REVISION
};
{
ICB_OP_GET_REVISION
};
icb
.
phase
=
1
;
icb
.
phase
=
1
;
/*
/*
* Like diagnostics, this is only done at init time, in fact, from
* Like diagnostics, this is only done at init time, in fact, from
* wd7000_detect, so there should be OGMBs available. If it fails,
* wd7000_detect, so there should be OGMBs available. If it fails,
* the only damage will be that the revision will show up as 0.0,
* the only damage will be that the revision will show up as 0.0,
* which in turn means that scatter/gather will be disabled.
* which in turn means that scatter/gather will be disabled.
*/
*/
mail_out
(
host
,
(
struct
scb
*
)
&
icb
);
mail_out
(
host
,
(
struct
scb
*
)
&
icb
);
while
(
icb
.
phase
)
{
while
(
icb
.
phase
)
cpu_relax
();
/* wait for completion */
{
barrier
();
cpu_relax
();
/* wait for completion */
}
barrier
();
host
->
rev1
=
icb
.
primary
;
}
host
->
rev2
=
icb
.
secondary
;
host
->
rev1
=
icb
.
primary
;
host
->
rev2
=
icb
.
secondary
;
}
}
#undef SPRINTF
#undef SPRINTF
#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
static
int
wd7000_set_info
(
char
*
buffer
,
int
length
,
struct
Scsi_Host
*
host
)
static
int
wd7000_set_info
(
char
*
buffer
,
int
length
,
struct
Scsi_Host
*
host
)
{
{
dprintk
(
"Buffer = <%.*s>, length = %d
\n
"
,
length
,
buffer
,
length
);
dprintk
(
"Buffer = <%.*s>, length = %d
\n
"
,
length
,
buffer
,
length
);
/*
/*
* Currently this is a no-op
* Currently this is a no-op
*/
*/
dprintk
(
"Sorry, this function is currently out of order...
\n
"
);
dprintk
(
"Sorry, this function is currently out of order...
\n
"
);
return
(
length
);
return
(
length
);
}
}
static
int
wd7000_proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
hostno
,
int
inout
)
static
int
wd7000_proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
hostno
,
int
inout
)
{
{
struct
Scsi_Host
*
host
=
NULL
;
struct
Scsi_Host
*
host
=
NULL
;
Scsi_Device
*
scd
;
Scsi_Device
*
scd
;
Adapter
*
adapter
;
Adapter
*
adapter
;
unsigned
long
flags
;
unsigned
long
flags
;
char
*
pos
=
buffer
;
char
*
pos
=
buffer
;
short
i
;
short
i
;
#ifdef WD7000_DEBUG
#ifdef WD7000_DEBUG
Mailbox
*
ogmbs
,
*
icmbs
;
Mailbox
*
ogmbs
,
*
icmbs
;
short
count
;
short
count
;
#endif
#endif
/*
/*
* Find the specified host board.
* Find the specified host board.
*/
*/
for
(
i
=
0
;
i
<
UNITS
;
i
++
)
for
(
i
=
0
;
i
<
UNITS
;
i
++
)
if
(
wd7000_host
[
i
]
&&
(
wd7000_host
[
i
]
->
host_no
==
hostno
))
{
if
(
wd7000_host
[
i
]
&&
(
wd7000_host
[
i
]
->
host_no
==
hostno
))
{
host
=
wd7000_host
[
i
];
host
=
wd7000_host
[
i
];
break
;
break
;
}
}
/*
/*
* Host not found!
* Host not found!
*/
*/
if
(
!
host
)
if
(
!
host
)
return
(
-
ESRCH
);
return
(
-
ESRCH
);
/*
/*
* Has data been written to the file ?
* Has data been written to the file ?
*/
*/
if
(
inout
)
if
(
inout
)
return
(
wd7000_set_info
(
buffer
,
length
,
host
));
return
(
wd7000_set_info
(
buffer
,
length
,
host
));
adapter
=
(
Adapter
*
)
host
->
hostdata
;
adapter
=
(
Adapter
*
)
host
->
hostdata
;
spin_lock_irqsave
(
host
->
host_lock
,
flags
);
spin_lock_irqsave
(
host
->
host_lock
,
flags
);
SPRINTF
(
"Host scsi%d: Western Digital WD-7000 (rev %d.%d)
\n
"
,
hostno
,
adapter
->
rev1
,
adapter
->
rev2
);
SPRINTF
(
"Host scsi%d: Western Digital WD-7000 (rev %d.%d)
\n
"
,
hostno
,
adapter
->
rev1
,
adapter
->
rev2
);
SPRINTF
(
" IO base: 0x%x
\n
"
,
adapter
->
iobase
);
SPRINTF
(
" IO base: 0x%x
\n
"
,
adapter
->
iobase
);
SPRINTF
(
" IRQ: %d
\n
"
,
adapter
->
irq
);
SPRINTF
(
" IRQ: %d
\n
"
,
adapter
->
irq
);
SPRINTF
(
" DMA channel: %d
\n
"
,
adapter
->
dma
);
SPRINTF
(
" DMA channel: %d
\n
"
,
adapter
->
dma
);
SPRINTF
(
" Interrupts: %d
\n
"
,
adapter
->
int_counter
);
SPRINTF
(
" Interrupts: %d
\n
"
,
adapter
->
int_counter
);
SPRINTF
(
" BUS_ON time: %d nanoseconds
\n
"
,
adapter
->
bus_on
*
125
);
SPRINTF
(
" BUS_ON time: %d nanoseconds
\n
"
,
adapter
->
bus_on
*
125
);
SPRINTF
(
" BUS_OFF time: %d nanoseconds
\n
"
,
adapter
->
bus_off
*
125
);
SPRINTF
(
" BUS_OFF time: %d nanoseconds
\n
"
,
adapter
->
bus_off
*
125
);
#ifdef WD7000_DEBUG
#ifdef WD7000_DEBUG
ogmbs
=
adapter
->
mb
.
ogmb
;
ogmbs
=
adapter
->
mb
.
ogmb
;
icmbs
=
adapter
->
mb
.
icmb
;
icmbs
=
adapter
->
mb
.
icmb
;
SPRINTF
(
"
\n
Control port value: 0x%x
\n
"
,
adapter
->
control
);
SPRINTF
(
"
\n
Control port value: 0x%x
\n
"
,
adapter
->
control
);
SPRINTF
(
"Incoming mailbox:
\n
"
);
SPRINTF
(
"Incoming mailbox:
\n
"
);
SPRINTF
(
" size: %d
\n
"
,
ICMB_CNT
);
SPRINTF
(
" size: %d
\n
"
,
ICMB_CNT
);
SPRINTF
(
" queued messages: "
);
SPRINTF
(
" queued messages: "
);
for
(
i
=
count
=
0
;
i
<
ICMB_CNT
;
i
++
)
for
(
i
=
count
=
0
;
i
<
ICMB_CNT
;
i
++
)
if
(
icmbs
[
i
].
status
)
{
if
(
icmbs
[
i
].
status
)
{
count
++
;
count
++
;
SPRINTF
(
"0x%x "
,
i
);
SPRINTF
(
"0x%x "
,
i
);
}
}
SPRINTF
(
count
?
"
\n
"
:
"none
\n
"
);
SPRINTF
(
count
?
"
\n
"
:
"none
\n
"
);
SPRINTF
(
"Outgoing mailbox:
\n
"
);
SPRINTF
(
"Outgoing mailbox:
\n
"
);
SPRINTF
(
" size: %d
\n
"
,
OGMB_CNT
);
SPRINTF
(
" size: %d
\n
"
,
OGMB_CNT
);
SPRINTF
(
" next message: 0x%x
\n
"
,
adapter
->
next_ogmb
);
SPRINTF
(
" next message: 0x%x
\n
"
,
adapter
->
next_ogmb
);
SPRINTF
(
" queued messages: "
);
SPRINTF
(
" queued messages: "
);
for
(
i
=
count
=
0
;
i
<
OGMB_CNT
;
i
++
)
for
(
i
=
count
=
0
;
i
<
OGMB_CNT
;
i
++
)
if
(
ogmbs
[
i
].
status
)
{
if
(
ogmbs
[
i
].
status
)
{
count
++
;
count
++
;
SPRINTF
(
"0x%x "
,
i
);
SPRINTF
(
"0x%x "
,
i
);
}
}
SPRINTF
(
count
?
"
\n
"
:
"none
\n
"
);
SPRINTF
(
count
?
"
\n
"
:
"none
\n
"
);
#endif
#endif
/*
/*
* Display driver information for each device attached to the board.
* Display driver information for each device attached to the board.
*/
*/
scd
=
host
->
host_queue
;
scd
=
host
->
host_queue
;
SPRINTF
(
"
\n
Attached devices: %s
\n
"
,
scd
?
""
:
"none"
);
for
(
;
scd
;
scd
=
scd
->
next
)
if
(
scd
->
host
->
host_no
==
hostno
)
{
SPRINTF
(
" [Channel: %02d, Id: %02d, Lun: %02d] "
,
scd
->
channel
,
scd
->
id
,
scd
->
lun
);
SPRINTF
(
"%s "
,
(
scd
->
type
<
MAX_SCSI_DEVICE_CODE
)
?
scsi_device_types
[(
short
)
scd
->
type
]
:
"Unknown device"
);
for
(
i
=
0
;
(
i
<
8
)
&&
(
scd
->
vendor
[
i
]
>=
0x20
);
i
++
)
SPRINTF
(
"%c"
,
scd
->
vendor
[
i
]);
SPRINTF
(
" "
);
for
(
i
=
0
;
(
i
<
16
)
&&
(
scd
->
model
[
i
]
>=
0x20
);
i
++
)
SPRINTF
(
"%c"
,
scd
->
model
[
i
]);
SPRINTF
(
"
\n
"
);
}
SPRINTF
(
"
\n
"
);
SPRINTF
(
"
\n
Attached devices: %s
\n
"
,
scd
?
""
:
"none
"
);
spin_unlock_irqrestore
(
host
->
host_lock
,
flags
);
for
(;
scd
;
scd
=
scd
->
next
)
if
(
scd
->
host
->
host_no
==
hostno
)
{
SPRINTF
(
" [Channel: %02d, Id: %02d, Lun: %02d] "
,
scd
->
channel
,
scd
->
id
,
scd
->
lun
);
SPRINTF
(
"%s "
,
(
scd
->
type
<
MAX_SCSI_DEVICE_CODE
)
?
scsi_device_types
[(
short
)
scd
->
type
]
:
"Unknown device"
);
/*
for
(
i
=
0
;
(
i
<
8
)
&&
(
scd
->
vendor
[
i
]
>=
0x20
);
i
++
)
* Calculate start of next buffer, and return value.
SPRINTF
(
"%c"
,
scd
->
vendor
[
i
]);
*/
SPRINTF
(
" "
);
*
start
=
buffer
+
offset
;
if
((
pos
-
buffer
)
<
offset
)
for
(
i
=
0
;
(
i
<
16
)
&&
(
scd
->
model
[
i
]
>=
0x20
);
i
++
)
return
(
0
);
SPRINTF
(
"%c"
,
scd
->
model
[
i
]);
else
if
((
pos
-
buffer
-
offset
)
<
length
)
SPRINTF
(
"
\n
"
);
return
(
pos
-
buffer
-
offset
);
}
else
return
(
length
);
SPRINTF
(
"
\n
"
);
spin_unlock_irqrestore
(
host
->
host_lock
,
flags
);
/*
* Calculate start of next buffer, and return value.
*/
*
start
=
buffer
+
offset
;
if
((
pos
-
buffer
)
<
offset
)
return
(
0
);
else
if
((
pos
-
buffer
-
offset
)
<
length
)
return
(
pos
-
buffer
-
offset
);
else
return
(
length
);
}
}
...
@@ -1514,191 +1481,181 @@ static int wd7000_proc_info (char *buffer, char **start, off_t offset, int lengt
...
@@ -1514,191 +1481,181 @@ static int wd7000_proc_info (char *buffer, char **start, off_t offset, int lengt
*
*
*/
*/
static
int
wd7000_detect
(
Scsi_Host_Template
*
tpnt
)
static
int
wd7000_detect
(
Scsi_Host_Template
*
tpnt
)
{
{
short
present
=
0
,
biosaddr_ptr
,
sig_ptr
,
i
,
pass
;
short
present
=
0
,
biosaddr_ptr
,
sig_ptr
,
i
,
pass
;
short
biosptr
[
NUM_CONFIGS
];
short
biosptr
[
NUM_CONFIGS
];
unsigned
iobase
;
unsigned
iobase
;
Adapter
*
host
=
NULL
;
Adapter
*
host
=
NULL
;
struct
Scsi_Host
*
sh
;
struct
Scsi_Host
*
sh
;
int
unit
=
0
;
int
unit
=
0
;
dprintk
(
"wd7000_detect: started
\n
"
);
dprintk
(
"wd7000_detect: started
\n
"
);
#ifdef MODULE
#ifdef MODULE
if
(
wd7000
)
if
(
wd7000
)
wd7000_setup
(
wd7000
);
wd7000_setup
(
wd7000
);
#endif
#endif
for
(
i
=
0
;
i
<
UNITS
;
wd7000_host
[
i
++
]
=
NULL
)
;
for
(
i
=
0
;
i
<
UNITS
;
wd7000_host
[
i
++
]
=
NULL
);
for
(
i
=
0
;
i
<
NUM_CONFIGS
;
biosptr
[
i
++
]
=
-
1
)
;
for
(
i
=
0
;
i
<
NUM_CONFIGS
;
biosptr
[
i
++
]
=
-
1
);
tpnt
->
proc_name
=
"wd7000"
;
tpnt
->
proc_info
=
&
wd7000_proc_info
;
/*
tpnt
->
proc_name
=
"wd7000"
;
* Set up SCB free list, which is shared by all adapters
tpnt
->
proc_info
=
&
wd7000_proc_info
;
*/
init_scbs
();
for
(
pass
=
0
;
pass
<
NUM_CONFIGS
;
pass
++
)
{
/*
/*
*
First, search for BIOS SIGNATURE...
*
Set up SCB free list, which is shared by all adapters
*/
*/
for
(
biosaddr_ptr
=
0
;
biosaddr_ptr
<
NUM_ADDRS
;
biosaddr_ptr
++
)
init_scbs
();
for
(
sig_ptr
=
0
;
sig_ptr
<
NUM_SIGNATURES
;
sig_ptr
++
)
{
for
(
i
=
0
;
i
<
pass
;
i
++
)
if
(
biosptr
[
i
]
==
biosaddr_ptr
)
break
;
if
(
i
==
pass
)
{
void
*
biosaddr
=
ioremap
(
wd7000_biosaddr
[
biosaddr_ptr
]
+
signatures
[
sig_ptr
].
ofs
,
signatures
[
sig_ptr
].
len
);
short
bios_match
=
0
;
if
(
biosaddr
)
bios_match
=
memcmp
((
char
*
)
biosaddr
,
signatures
[
sig_ptr
].
sig
,
signatures
[
sig_ptr
].
len
);
iounmap
(
biosaddr
);
if
(
!
bios_match
)
goto
bios_matched
;
}
}
bios_matched:
/*
* BIOS SIGNATURE has been found.
*/
#ifdef WD7000_DEBUG
dprintk
(
"wd7000_detect: pass %d
\n
"
,
pass
+
1
);
if
(
biosaddr_ptr
==
NUM_ADDRS
)
for
(
pass
=
0
;
pass
<
NUM_CONFIGS
;
pass
++
)
{
dprintk
(
"WD-7000 SST BIOS not detected...
\n
"
);
/*
else
* First, search for BIOS SIGNATURE...
dprintk
(
"WD-7000 SST BIOS detected at 0x%lx: checking...
\n
"
,
*/
wd7000_biosaddr
[
biosaddr_ptr
]);
for
(
biosaddr_ptr
=
0
;
biosaddr_ptr
<
NUM_ADDRS
;
biosaddr_ptr
++
)
#endif
for
(
sig_ptr
=
0
;
sig_ptr
<
NUM_SIGNATURES
;
sig_ptr
++
)
{
for
(
i
=
0
;
i
<
pass
;
i
++
)
if
(
configs
[
pass
].
irq
<
0
)
if
(
biosptr
[
i
]
==
biosaddr_ptr
)
continue
;
break
;
if
(
unit
==
UNITS
)
continue
;
iobase
=
configs
[
pass
].
iobase
;
dprintk
(
"wd7000_detect: check IO 0x%x region...
\n
"
,
iobase
);
if
(
i
==
pass
)
{
void
*
biosaddr
=
ioremap
(
wd7000_biosaddr
[
biosaddr_ptr
]
+
signatures
[
sig_ptr
].
ofs
,
signatures
[
sig_ptr
].
len
);
short
bios_match
=
0
;
if
(
request_region
(
iobase
,
4
,
"wd7000"
))
{
if
(
biosaddr
)
bios_match
=
memcmp
((
char
*
)
biosaddr
,
signatures
[
sig_ptr
].
sig
,
signatures
[
sig_ptr
].
len
);
dprintk
(
"wd7000_detect: ASC reset (IO 0x%x) ..."
,
iobase
);
iounmap
(
biosaddr
);
/*
* ASC reset...
*/
outb
(
ASC_RES
,
iobase
+
ASC_CONTROL
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
/
100
);
outb
(
0
,
iobase
+
ASC_CONTROL
);
if
(
WAIT
(
iobase
+
ASC_STAT
,
ASC_STATMASK
,
CMD_RDY
,
0
))
{
if
(
!
bios_match
)
dprintk
(
"failed!
\n
"
);
goto
bios_matched
;
goto
err_release
;
}
}
else
}
dprintk
(
"ok!
\n
"
);
if
(
inb
(
iobase
+
ASC_INTR_STAT
)
==
1
)
{
bios_matched:
/*
/*
* We register here, to get a pointer to the extra space,
* BIOS SIGNATURE has been found.
* which we'll use as the Adapter structure (host) for
* this adapter. It is located just after the registered
* Scsi_Host structure (sh), and is located by the empty
* array hostdata.
*/
*/
sh
=
scsi_register
(
tpnt
,
sizeof
(
Adapter
));
#ifdef WD7000_DEBUG
if
(
sh
==
NULL
)
dprintk
(
"wd7000_detect: pass %d
\n
"
,
pass
+
1
);
goto
err_release
;
host
=
(
Adapter
*
)
sh
->
hostdata
;
dprintk
(
"wd7000_detect: adapter allocated at 0x%x
\n
"
,
(
int
)
host
);
memset
(
host
,
0
,
sizeof
(
Adapter
));
host
->
irq
=
configs
[
pass
].
irq
;
if
(
biosaddr_ptr
==
NUM_ADDRS
)
host
->
dma
=
configs
[
pass
].
dma
;
dprintk
(
"WD-7000 SST BIOS not detected...
\n
"
);
host
->
iobase
=
iobase
;
else
host
->
int_counter
=
0
;
dprintk
(
"WD-7000 SST BIOS detected at 0x%lx: checking...
\n
"
,
wd7000_biosaddr
[
biosaddr_ptr
]);
host
->
bus_on
=
configs
[
pass
].
bus_on
;
#endif
host
->
bus_off
=
configs
[
pass
].
bus_off
;
host
->
sh
=
wd7000_host
[
unit
]
=
sh
;
unit
++
;
dprintk
(
"wd7000_detect: Trying init WD-7000 card at IO "
if
(
configs
[
pass
].
irq
<
0
)
"0x%x, IRQ %d, DMA %d...
\n
"
,
continue
;
host
->
iobase
,
host
->
irq
,
host
->
dma
);
if
(
!
wd7000_init
(
host
))
/* Initialization failed */
if
(
unit
==
UNITS
)
goto
err_unregister
;
continue
;
/*
iobase
=
configs
[
pass
].
iobase
;
* OK from here - we'll use this adapter/configuration.
*/
wd7000_revision
(
host
);
/* important for scatter/gather */
/*
dprintk
(
"wd7000_detect: check IO 0x%x region...
\n
"
,
iobase
);
* For boards before rev 6.0, scatter/gather isn't supported.
*/
if
(
host
->
rev1
<
6
)
sh
->
sg_tablesize
=
SG_NONE
;
present
++
;
/* count it */
if
(
request_region
(
iobase
,
4
,
"wd7000"
))
{
if
(
biosaddr_ptr
!=
NUM_ADDRS
)
dprintk
(
"wd7000_detect: ASC reset (IO 0x%x) ..."
,
iobase
);
biosptr
[
pass
]
=
biosaddr_ptr
;
/*
* ASC reset...
*/
outb
(
ASC_RES
,
iobase
+
ASC_CONTROL
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
/
100
);
outb
(
0
,
iobase
+
ASC_CONTROL
);
printk
(
KERN_INFO
"Western Digital WD-7000 (rev %d.%d) "
,
if
(
WAIT
(
iobase
+
ASC_STAT
,
ASC_STATMASK
,
CMD_RDY
,
0
))
{
host
->
rev1
,
host
->
rev2
);
dprintk
(
"failed!
\n
"
);
printk
(
"using IO 0x%x, IRQ %d, DMA %d.
\n
"
,
goto
err_release
;
host
->
iobase
,
host
->
irq
,
host
->
dma
);
}
else
printk
(
" BUS_ON time: %dns, BUS_OFF time: %dns
\n
"
,
dprintk
(
"ok!
\n
"
);
host
->
bus_on
*
125
,
host
->
bus_off
*
125
);
}
if
(
inb
(
iobase
+
ASC_INTR_STAT
)
==
1
)
{
}
else
/*
dprintk
(
"wd7000_detect: IO 0x%x region already allocated!
\n
"
,
* We register here, to get a pointer to the extra space,
iobase
);
* which we'll use as the Adapter structure (host) for
* this adapter. It is located just after the registered
* Scsi_Host structure (sh), and is located by the empty
* array hostdata.
*/
sh
=
scsi_register
(
tpnt
,
sizeof
(
Adapter
));
if
(
sh
==
NULL
)
goto
err_release
;
host
=
(
Adapter
*
)
sh
->
hostdata
;
dprintk
(
"wd7000_detect: adapter allocated at 0x%x
\n
"
,
(
int
)
host
);
memset
(
host
,
0
,
sizeof
(
Adapter
));
host
->
irq
=
configs
[
pass
].
irq
;
host
->
dma
=
configs
[
pass
].
dma
;
host
->
iobase
=
iobase
;
host
->
int_counter
=
0
;
host
->
bus_on
=
configs
[
pass
].
bus_on
;
host
->
bus_off
=
configs
[
pass
].
bus_off
;
host
->
sh
=
wd7000_host
[
unit
]
=
sh
;
unit
++
;
dprintk
(
"wd7000_detect: Trying init WD-7000 card at IO "
"0x%x, IRQ %d, DMA %d...
\n
"
,
host
->
iobase
,
host
->
irq
,
host
->
dma
);
if
(
!
wd7000_init
(
host
))
/* Initialization failed */
goto
err_unregister
;
/*
* OK from here - we'll use this adapter/configuration.
*/
wd7000_revision
(
host
);
/* important for scatter/gather */
/*
* For boards before rev 6.0, scatter/gather isn't supported.
*/
if
(
host
->
rev1
<
6
)
sh
->
sg_tablesize
=
SG_NONE
;
present
++
;
/* count it */
if
(
biosaddr_ptr
!=
NUM_ADDRS
)
biosptr
[
pass
]
=
biosaddr_ptr
;
printk
(
KERN_INFO
"Western Digital WD-7000 (rev %d.%d) "
,
host
->
rev1
,
host
->
rev2
);
printk
(
"using IO 0x%x, IRQ %d, DMA %d.
\n
"
,
host
->
iobase
,
host
->
irq
,
host
->
dma
);
printk
(
" BUS_ON time: %dns, BUS_OFF time: %dns
\n
"
,
host
->
bus_on
*
125
,
host
->
bus_off
*
125
);
}
}
else
dprintk
(
"wd7000_detect: IO 0x%x region already allocated!
\n
"
,
iobase
);
continue
;
continue
;
err_unregister:
err_unregister:
scsi_unregister
(
sh
);
scsi_unregister
(
sh
);
err_release:
err_release:
release_region
(
iobase
,
4
);
release_region
(
iobase
,
4
);
}
}
if
(
!
present
)
if
(
!
present
)
printk
(
"Failed initialization of WD-7000 SCSI card!
\n
"
);
printk
(
"Failed initialization of WD-7000 SCSI card!
\n
"
);
return
(
present
);
return
(
present
);
}
}
/*
/*
* I have absolutely NO idea how to do an abort with the WD7000...
* I have absolutely NO idea how to do an abort with the WD7000...
*/
*/
static
int
wd7000_abort
(
Scsi_Cmnd
*
SCpnt
)
static
int
wd7000_abort
(
Scsi_Cmnd
*
SCpnt
)
{
{
Adapter
*
host
=
(
Adapter
*
)
SCpnt
->
host
->
hostdata
;
Adapter
*
host
=
(
Adapter
*
)
SCpnt
->
host
->
hostdata
;
if
(
inb
(
host
->
iobase
+
ASC_STAT
)
&
INT_IM
)
{
if
(
inb
(
host
->
iobase
+
ASC_STAT
)
&
INT_IM
)
{
printk
(
"wd7000_abort: lost interrupt
\n
"
);
printk
(
"wd7000_abort: lost interrupt
\n
"
);
wd7000_intr_handle
(
host
->
irq
,
NULL
,
NULL
);
wd7000_intr_handle
(
host
->
irq
,
NULL
,
NULL
);
return
FAILED
;
}
return
FAILED
;
return
FAILED
;
}
return
FAILED
;
}
}
...
@@ -1706,28 +1663,28 @@ static int wd7000_abort (Scsi_Cmnd *SCpnt)
...
@@ -1706,28 +1663,28 @@ static int wd7000_abort (Scsi_Cmnd *SCpnt)
* I also have no idea how to do a reset...
* I also have no idea how to do a reset...
*/
*/
static
int
wd7000_bus_reset
(
Scsi_Cmnd
*
SCpnt
)
static
int
wd7000_bus_reset
(
Scsi_Cmnd
*
SCpnt
)
{
{
return
FAILED
;
return
FAILED
;
}
}
static
int
wd7000_device_reset
(
Scsi_Cmnd
*
SCpnt
)
static
int
wd7000_device_reset
(
Scsi_Cmnd
*
SCpnt
)
{
{
return
FAILED
;
return
FAILED
;
}
}
/*
/*
* Last resort. Reinitialize the board.
* Last resort. Reinitialize the board.
*/
*/
static
int
wd7000_host_reset
(
Scsi_Cmnd
*
SCpnt
)
static
int
wd7000_host_reset
(
Scsi_Cmnd
*
SCpnt
)
{
{
Adapter
*
host
=
(
Adapter
*
)
SCpnt
->
host
->
hostdata
;
Adapter
*
host
=
(
Adapter
*
)
SCpnt
->
host
->
hostdata
;
if
(
wd7000_adapter_reset
(
host
)
<
0
)
if
(
wd7000_adapter_reset
(
host
)
<
0
)
return
FAILED
;
return
FAILED
;
wd7000_enable_intr
(
host
);
wd7000_enable_intr
(
host
);
return
SUCCESS
;
return
SUCCESS
;
}
}
...
@@ -1735,52 +1692,46 @@ static int wd7000_host_reset (Scsi_Cmnd *SCpnt)
...
@@ -1735,52 +1692,46 @@ static int wd7000_host_reset (Scsi_Cmnd *SCpnt)
* This was borrowed directly from aha1542.c. (Zaga)
* This was borrowed directly from aha1542.c. (Zaga)
*/
*/
static
int
wd7000_biosparam
(
Disk
*
disk
,
struct
block_device
*
bdev
,
int
*
ip
)
static
int
wd7000_biosparam
(
Disk
*
disk
,
struct
block_device
*
bdev
,
int
*
ip
)
{
{
dprintk
(
"wd7000_biosparam: dev=%s, size=%d, "
,
bdevname
(
bdev
),
dprintk
(
"wd7000_biosparam: dev=%s, size=%d, "
,
bdevname
(
bdev
),
disk
->
capacity
);
disk
->
capacity
);
/*
* try default translation
*/
ip
[
0
]
=
64
;
ip
[
1
]
=
32
;
ip
[
2
]
=
disk
->
capacity
>>
11
;
/*
* for disks >1GB do some guessing
*/
if
(
ip
[
2
]
>=
1024
)
{
int
info
[
3
];
/*
/*
* try
to figure out the geometry from the partition table
* try
default translation
*/
*/
if
((
scsicam_bios_param
(
disk
,
bdev
,
info
)
<
0
)
||
ip
[
0
]
=
64
;
!
(((
info
[
0
]
==
64
)
&&
(
info
[
1
]
==
32
))
||
ip
[
1
]
=
32
;
((
info
[
0
]
==
255
)
&&
(
info
[
1
]
==
63
))))
{
ip
[
2
]
=
disk
->
capacity
>>
11
;
printk
(
"wd7000_biosparam: unable to verify geometry for disk with >1GB.
\n
"
" using extended translation.
\n
"
);
/*
* for disks >1GB do some guessing
ip
[
0
]
=
255
;
*/
ip
[
1
]
=
63
;
if
(
ip
[
2
]
>=
1024
)
{
ip
[
2
]
=
(
unsigned
long
)
disk
->
capacity
/
(
255
*
63
);
int
info
[
3
];
}
else
{
/*
ip
[
0
]
=
info
[
0
];
* try to figure out the geometry from the partition table
ip
[
1
]
=
info
[
1
];
*/
ip
[
2
]
=
info
[
2
];
if
((
scsicam_bios_param
(
disk
,
bdev
,
info
)
<
0
)
||
!
(((
info
[
0
]
==
64
)
&&
(
info
[
1
]
==
32
))
||
((
info
[
0
]
==
255
)
&&
(
info
[
1
]
==
63
))))
{
printk
(
"wd7000_biosparam: unable to verify geometry for disk with >1GB.
\n
"
" using extended translation.
\n
"
);
if
(
info
[
0
]
==
255
)
printk
(
KERN_INFO
"%s: current partition table is "
ip
[
0
]
=
255
;
"using extended translation.
\n
"
,
__FUNCTION__
);
ip
[
1
]
=
63
;
ip
[
2
]
=
(
unsigned
long
)
disk
->
capacity
/
(
255
*
63
);
}
else
{
ip
[
0
]
=
info
[
0
];
ip
[
1
]
=
info
[
1
];
ip
[
2
]
=
info
[
2
];
if
(
info
[
0
]
==
255
)
printk
(
KERN_INFO
"%s: current partition table is "
"using extended translation.
\n
"
,
__FUNCTION__
);
}
}
}
}
dprintk
(
"bios geometry: head=%d, sec=%d, cyl=%d
\n
"
,
ip
[
0
],
ip
[
1
],
ip
[
2
]);
dprintk
(
"bios geometry: head=%d, sec=%d, cyl=%d
\n
"
,
ip
[
0
],
ip
[
1
],
ip
[
2
]);
dprintk
(
"WARNING: check, if the bios geometry is correct.
\n
"
);
dprintk
(
"WARNING: check, if the bios geometry is correct.
\n
"
);
return
(
0
);
return
(
0
);
}
}
MODULE_AUTHOR
(
"Thomas Wuensche, John Boyd, Miroslav Zagorac"
);
MODULE_AUTHOR
(
"Thomas Wuensche, John Boyd, Miroslav Zagorac"
);
...
...
drivers/scsi/wd7000.h
View file @
cd509844
...
@@ -13,16 +13,16 @@
...
@@ -13,16 +13,16 @@
#include <linux/types.h>
#include <linux/types.h>
static
int
wd7000_set_info
(
char
*
buffer
,
int
length
,
struct
Scsi_Host
*
host
);
static
int
wd7000_set_info
(
char
*
buffer
,
int
length
,
struct
Scsi_Host
*
host
);
static
int
wd7000_proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
hostno
,
int
inout
);
static
int
wd7000_proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
hostno
,
int
inout
);
static
int
wd7000_detect
(
Scsi_Host_Template
*
);
static
int
wd7000_detect
(
Scsi_Host_Template
*
);
static
int
wd7000_command
(
Scsi_Cmnd
*
);
static
int
wd7000_command
(
Scsi_Cmnd
*
);
static
int
wd7000_queuecommand
(
Scsi_Cmnd
*
,
void
(
*
done
)
(
Scsi_Cmnd
*
));
static
int
wd7000_queuecommand
(
Scsi_Cmnd
*
,
void
(
*
done
)
(
Scsi_Cmnd
*
));
static
int
wd7000_abort
(
Scsi_Cmnd
*
);
static
int
wd7000_abort
(
Scsi_Cmnd
*
);
static
int
wd7000_bus_reset
(
Scsi_Cmnd
*
);
static
int
wd7000_bus_reset
(
Scsi_Cmnd
*
);
static
int
wd7000_host_reset
(
Scsi_Cmnd
*
);
static
int
wd7000_host_reset
(
Scsi_Cmnd
*
);
static
int
wd7000_device_reset
(
Scsi_Cmnd
*
);
static
int
wd7000_device_reset
(
Scsi_Cmnd
*
);
static
int
wd7000_biosparam
(
Disk
*
,
struct
block_device
*
,
int
*
);
static
int
wd7000_biosparam
(
Disk
*
,
struct
block_device
*
,
int
*
);
#ifndef NULL
#ifndef NULL
#define NULL 0L
#define NULL 0L
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment