* Standalone driver for Adaptech 1542 SCSI
* Pace Willisson pace@blitz.com April 8, 1992
#include "i386/isa/asreg.h"
#define ASPRINT(x) { printf x; DELAY (10000); }
struct mailbox_entry mailbox
[2];
if (io
->i_unit
< 0 || io
->i_unit
> 8
|| io
->i_part
< 0 || io
->i_part
> 8
|| io
->i_ctlr
< 0 || io
->i_ctlr
> 0)
/* dma setup: see page 5-31 in the Adaptech manual */
ASPRINT (("resetting adaptech card... "));
outb (as_port
+ AS_CONTROL
, AS_CONTROL_SRST
);
for (i
= 0; i
< 100; i
++)
while (inb (as_port
+ AS_STATUS
) != (AS_STATUS_INIT
| AS_STATUS_IDLE
))
as_put_byte (AS_CMD_MAILBOX_INIT
);
as_put_byte (1); /* one mailbox out, one in */
as_put_byte ((int)mailbox
>> 16);
as_put_byte ((int)mailbox
>> 8);
as_put_byte ((int)mailbox
);
while (inb (as_port
+ AS_STATUS
) & AS_STATUS_INIT
)
ASPRINT (("mailbox init ok "));
/* do mode select to set the logical block size */
cdb
[0] = 0x15; /* MODE SELECT */
cdb
[4] = 12; /* parameter list length */
data
[3] = 8; /* block descriptor length */
data
[9] = DEV_BSIZE
>> 16;
data
[10] = DEV_BSIZE
>> 8;
if (ascmd (io
->i_unit
, 0, cdb
, 6, data
, 12, 1) < 0) {
printf ("as%d: error setting logical block size\n",
if (asstrategy (&aio
, F_READ
) == DEV_BSIZE
) {
dd
= (struct disklabel
*)aio
.i_ma
;
io
->i_boff
= dd
->d_partitions
[io
->i_part
].p_offset
;
ASPRINT (("partition offset %d ", io
->i_boff
));
extern struct disklabel disklabel
;
io
->i_boff
= disklabel
.d_partitions
[io
->i_part
].p_offset
;
ASPRINT (("partition offset %d ", io
->i_boff
));
ASPRINT (("asopen ok "));
/* func is F_WRITE or F_READ
* io->i_unit, io->i_part, io->i_bn is starting block
* io->i_ma is memory address
* io->i_boff is block offset for this partition (set up in asopen)
ASPRINT (("asstrategy(target=%d, block=%d+%d, count=%d) ",
io
->i_unit
, io
->i_bn
, io
->i_boff
, io
->i_cc
));
printf ("as%d: write not supported\n", io
->i_unit
);
if (io
->i_cc
% DEV_BSIZE
!= 0) {
printf ("as%d: transfer size not multiple of %d\n",
/* retry in case we get a unit-attention error, which just
* means the drive has been reset since the last command
for (retry
= 0; retry
< NRETRIES
; retry
++) {
blkno
= io
->i_bn
+ io
->i_boff
;
cdb
[0] = 8; /* scsi read opcode */
cdb
[1] = (blkno
>> 16) & 0x1f;
cdb
[4] = io
->i_cc
/ DEV_BSIZE
;
cdb
[5] = 0; /* control byte (used in linking) */
if (ascmd (io
->i_unit
, 1, cdb
, 6, io
->i_ma
, io
->i_cc
,
retry
== NRETRIES
- 1) >= 0) {
ASPRINT (("asstrategy ok "));
ASPRINT (("asstrategy failed "));
ascmd (target
, readflag
, cdb
, cdblen
, data
, datalen
, printerr
)
/* this can't happen, unless the card flakes */
_stop ("asstart: mailbox not available\n");
bzero (&ccb
, sizeof ccb
);
ccb
.ccb_addr_and_control
= target
<< 5;
ccb
.ccb_addr_and_control
|= readflag
? 8 : 0x10;
ccb
.ccb_addr_and_control
|= 0x18;
ccb
.ccb_data_len_msb
= datalen
>> 16;
ccb
.ccb_data_len_mid
= datalen
>> 8;
ccb
.ccb_data_len_lsb
= datalen
;
ccb
.ccb_requst_sense_allocation_len
= MAXSENSE
;
ccb
.ccb_data_ptr_msb
= physaddr
>> 16;
ccb
.ccb_data_ptr_mid
= physaddr
>> 8;
ccb
.ccb_data_ptr_lsb
= physaddr
;
ccb
.ccb_scsi_command_len
= cdblen
;
bcopy (cdb
, ccb
.ccb_cdb
, cdblen
);
printf ("%x ", ((unsigned char *)&ccb
)[i
]);
mailbox
[0].msb
= physaddr
>> 16;
mailbox
[0].mid
= physaddr
>> 8;
mailbox
[0].lsb
= physaddr
;
/* tell controller to look in its mailbox */
outb (as_port
+ AS_CONTROL
, AS_CONTROL_IRST
);
as_put_byte (AS_CMD_START_SCSI_COMMAND
);
ASPRINT (("waiting for status..."));
while (mailbox
[1].cmd
== 0)
if (ccb
.ccb_host_status
!= 0 || ccb
.ccb_target_status
!= 0) {
printf ("as%d error: hst=%x tst=%x sense=",
while (inb (as_port
+ AS_STATUS
) & AS_STATUS_CDF
)
outb (as_port
+ AS_DATA_OUT
, val
);