* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Van Jacobson of Lawrence Berkeley Laboratory.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)sd.c 8.9 (Berkeley) 5/14/95
* SCSI CCS (Command Command Set) disk driver.
static char rcsid
[] = "$Header: /sys.lite/hp300/dev/RCS/sd.c,v 1.2 1994/01/10 18:29:19 mike Exp mike $";
#include <sys/disklabel.h>
#include <hp/dev/device.h>
#include <hp300/dev/scsireg.h>
#include <hp300/dev/sdvar.h>
#include <hp300/hp300/led.h>
extern int scsi_test_unit_rdy();
extern int scsi_request_sense();
extern int scsi_inquiry();
extern int scsi_read_capacity();
extern int scsi_tt_write();
extern void scsi_delay();
void sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr();
struct driver sddriver
= {
sdinit
, "sd", (int (*)())sdstart
, (int (*)())sdgo
, (int (*)())sdintr
,
#define SDB_CAPACITY 0x04
struct sd_softc sd_softc
[NSD
];
struct sdstats sdstats
[NSD
];
struct scsi_fmt_cdb sdcmd
[NSD
];
struct scsi_fmt_sense sdsense
[NSD
];
static struct scsi_fmt_cdb sd_read_cmd
= { 10, CMD_READ_EXT
};
static struct scsi_fmt_cdb sd_write_cmd
= { 10, CMD_WRITE_EXT
};
* Table of scsi commands users are allowed to access via "format"
* mode. 0 means not legal. 1 means "immediate" (doesn't need dma).
* -1 means needs dma and/or wait for intr.
static char legal_cmds
[256] = {
/***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/*00*/ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
/*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
static struct scsi_inquiry inqbuf
;
static struct scsi_fmt_cdb inq
= {
CMD_INQUIRY
, 0, 0, 0, sizeof(inqbuf
), 0
register int ctlr
, slave
;
* See if unit exists and is a disk then read block size & nblocks.
while ((i
= scsi_test_unit_rdy(ctlr
, slave
, unit
)) != 0) {
if (i
== -1 || --tries
< 0) {
/* doesn't exist or not a CCS device */
if (i
== STS_CHECKCOND
) {
struct scsi_xsense
*sp
= (struct scsi_xsense
*)sensebuf
;
scsi_request_sense(ctlr
, slave
, unit
, sensebuf
,
* Not ready -- might be removable media
* device with no media. Assume as much,
* if it really isn't, the inquiry commmand
/* drive doing an RTZ -- give it a while */
if (scsi_immed_command(ctlr
, slave
, unit
, &inq
,
(u_char
*)&inqbuf
, sizeof(inqbuf
), B_READ
))
case 7: /* Magneto-optical */
default: /* not a disk */
switch (inqbuf
.version
) {
bcopy((caddr_t
)&inqbuf
.vendor_id
, (caddr_t
)idstr
, 28);
for (i
= 27; i
> 23; --i
)
bcopy("UNKNOWN", &idstr
[0], 8);
bcopy("DRIVE TYPE", &idstr
[8], 11);
sc
->sc_flags
|= SDF_RMEDIA
;
if (sdgetcapacity(sc
, hd
, NODEV
) < 0)
switch (inqbuf
.version
) {
printf("sd%d: %s %s rev %s", hd
->hp_unit
, idstr
, &idstr
[8],
printf("sd%d: type 0x%x, qual 0x%x, ver %d", hd
->hp_unit
,
inqbuf
.type
, inqbuf
.qual
, inqbuf
.version
);
printf(", %d %d byte blocks",
sc
->sc_blks
>> sc
->sc_bshift
, sc
->sc_blksize
);
sc
->sc_wpms
= 32 * (60 * DEV_BSIZE
/ 2); /* XXX */
register struct hp_device
*hd
;
register struct sd_softc
*sc
= &sd_softc
[hd
->hp_unit
];
* XXX formerly 0 meant unused but now pid 0 can legitimately
* use this interface (sdgetcapacity).
sc
->sc_punit
= sdpunit(hd
->hp_flags
);
sc
->sc_type
= sdident(sc
, hd
);
sc
->sc_dq
.dq_ctlr
= hd
->hp_ctlr
;
sc
->sc_dq
.dq_unit
= hd
->hp_unit
;
sc
->sc_dq
.dq_slave
= hd
->hp_slave
;
sc
->sc_dq
.dq_driver
= &sddriver
;
sc
->sc_flags
|= SDF_ALIVE
;
register struct sd_softc
*sc
;
register struct hp_device
*hd
;
sdstats
[hd
->hp_unit
].sdresets
++;
* Determine capacity of a drive.
* Returns -1 on a failure, 0 on success, 1 on a failure that is probably
sdgetcapacity(sc
, hd
, dev
)
static struct scsi_fmt_cdb cap
= {
CMD_READ_CAPACITY
, 0, 0, 0, 0, 0, 0, 0, 0, 0
* Cannot use stack space for this buffer since stack KVA may not
* be valid (i.e. in context of this process) when the operation
capbuf
= malloc(capbufsize
, M_DEVBUF
, M_WAITOK
);
i
= scsi_immed_command(hd
->hp_ctlr
, hd
->hp_slave
, sc
->sc_punit
,
&cap
, capbuf
, capbufsize
, B_READ
);
if (sc
->sc_format_pid
>= 0)
bp
= malloc(sizeof *bp
, M_DEVBUF
, M_WAITOK
);
sc
->sc_format_pid
= curproc
->p_pid
;
bcopy((caddr_t
)&cap
, (caddr_t
)&sdcmd
[hd
->hp_unit
], sizeof cap
);
bp
->b_flags
= B_READ
| B_BUSY
;
bp
->b_un
.b_addr
= (caddr_t
)capbuf
;
bp
->b_bcount
= capbufsize
;
i
= biowait(bp
) ? sdsense
[hd
->hp_unit
].status
: 0;
if (i
!= STS_CHECKCOND
|| (sc
->sc_flags
& SDF_RMEDIA
) == 0) {
if (sddebug
& SDB_CAPACITY
)
printf("sd%d: read_capacity returns %d\n",
* XXX assume unformatted or non-existant media
sc
->sc_blksize
= DEV_BSIZE
;
if (sddebug
& SDB_CAPACITY
)
printf("sd%d: removable media not present\n",
sc
->sc_blks
= *(u_int
*)&capbuf
[0];
sc
->sc_blksize
= *(int *)&capbuf
[4];
/* return value of read capacity is last valid block number */
if (sc
->sc_blksize
!= DEV_BSIZE
) {
if (sc
->sc_blksize
< DEV_BSIZE
) {
printf("sd%d: need at least %d byte blocks - %s\n",
hd
->hp_unit
, DEV_BSIZE
, "drive ignored");
for (i
= sc
->sc_blksize
; i
> DEV_BSIZE
; i
>>= 1)
sc
->sc_blks
<<= sc
->sc_bshift
;
if (sddebug
& SDB_CAPACITY
)
printf("sd%d: blks=%d, blksize=%d, bshift=%d\n", hd
->hp_unit
,
sc
->sc_blks
, sc
->sc_blksize
, sc
->sc_bshift
);
* Read or constuct a disklabel
register struct sd_softc
*sc
= &sd_softc
[unit
];
register struct disklabel
*lp
= &sc
->sc_info
.si_label
;
register struct partition
*pi
;
char *msg
, *readdisklabel();
* For CD-ROM just define a single partition
bzero((caddr_t
)lp
, sizeof *lp
);
* If removable media or the size unavailable at boot time
* (i.e. unformatted hard disk), attempt to set the capacity
if ((sc
->sc_flags
& SDF_RMEDIA
) || sc
->sc_blks
== 0) {
switch (sdgetcapacity(sc
, sc
->sc_hd
, dev
)) {
* Hard error, just return (open will fail).
* XXX return 0 so open can continue just in case
* the media is unformatted and we want to format it.
* We set the error flag so they cannot do much else.
sc
->sc_flags
|= SDF_ERROR
;
msg
= "unformatted/missing media";
* Set some default values to use while reading the label
* (or to use if there isn't a label) and try reading it.
lp
->d_secsize
= DEV_BSIZE
;
lp
->d_partitions
[2].p_offset
= 0;
/* XXX we can open a device even without SDF_ALIVE */
sc
->sc_blksize
= DEV_BSIZE
;
/* XXX ensure size is at least one device block */
lp
->d_partitions
[2].p_size
=
roundup(LABELSECTOR
+1, btodb(sc
->sc_blksize
));
msg
= readdisklabel(sdlabdev(dev
), sdstrategy
, lp
);
printf("sd%d: WARNING: %s, ", unit
, msg
);
printf("using old default partitioning\n");
sdmakedisklabel(unit
, lp
);
printf("defining `c' partition as entire disk\n");
pi
[2].p_size
= sc
->sc_blks
;
/* XXX reset other info since readdisklabel screws with it */
sdopen(dev
, flags
, mode
, p
)
register int unit
= sdunit(dev
);
register struct sd_softc
*sc
= &sd_softc
[unit
];
if (unit
>= NSD
|| (sc
->sc_flags
& SDF_ALIVE
) == 0)
* Wait for any pending opens/closes to complete
while (sc
->sc_flags
& (SDF_OPENING
|SDF_CLOSING
))
sleep((caddr_t
)sc
, PRIBIO
);
* On first open, get label and partition info.
* We may block reading the label, so be careful
* to stop any other opens.
if (sc
->sc_info
.si_open
== 0) {
sc
->sc_flags
|= SDF_OPENING
;
sc
->sc_flags
&= ~SDF_OPENING
;
if (sc
->sc_hd
->hp_dk
>= 0)
dk_wpms
[sc
->sc_hd
->hp_dk
] = sc
->sc_wpms
;
sc
->sc_info
.si_copen
|= mask
;
sc
->sc_info
.si_bopen
|= mask
;
sc
->sc_info
.si_open
|= mask
;
sdclose(dev
, flag
, mode
, p
)
register struct sd_softc
*sc
= &sd_softc
[unit
];
register struct sdinfo
*si
= &sc
->sc_info
;
si
->si_open
= si
->si_bopen
| si
->si_copen
;
* On last close, we wait for all activity to cease since
* the label/parition info will become invalid. Since we
* might sleep, we must block any opens while we are here.
* Note we don't have to about other closes since we know
sc
->sc_flags
|= SDF_CLOSING
;
while (sdtab
[unit
].b_active
) {
sc
->sc_flags
|= SDF_WANTED
;
sleep((caddr_t
)&sdtab
[unit
], PRIBIO
);
sc
->sc_flags
&= ~(SDF_CLOSING
|SDF_WLABEL
|SDF_ERROR
);
* This routine is called for partial block transfers and non-aligned
* transfers (the latter only being possible on devices with a block size
* larger than DEV_BSIZE). The operation is performed in three steps
* using a locally allocated buffer:
* 1. transfer any initial partial block
* 2. transfer full blocks
* 3. transfer any final partial block
register struct buf
*cbp
= (struct buf
*)malloc(sizeof(struct buf
),
caddr_t cbuf
= (caddr_t
)malloc(bsize
, M_DEVBUF
, M_WAITOK
);
bzero((caddr_t
)cbp
, sizeof(*cbp
));
cbp
->b_proc
= curproc
; /* XXX */
if (sddebug
& SDB_PARTIAL
)
printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n",
bp
, bp
->b_flags
, bn
, resid
, addr
);
register int boff
= dbtob(bn
) & (bsize
- 1);
if (boff
|| resid
< bsize
) {
sdstats
[sdunit(bp
->b_dev
)].sdpartials
++;
count
= min(resid
, bsize
- boff
);
cbp
->b_flags
= B_BUSY
| B_PHYS
| B_READ
;
cbp
->b_blkno
= bn
- btodb(boff
);
if (sddebug
& SDB_PARTIAL
)
printf(" readahead: bn %x cnt %x off %x addr %x\n",
cbp
->b_blkno
, count
, boff
, addr
);
if (cbp
->b_flags
& B_ERROR
) {
bp
->b_error
= cbp
->b_error
;
if (bp
->b_flags
& B_READ
) {
bcopy(&cbuf
[boff
], addr
, count
);
bcopy(addr
, &cbuf
[boff
], count
);
if (sddebug
& SDB_PARTIAL
)
printf(" writeback: bn %x cnt %x off %x addr %x\n",
cbp
->b_blkno
, count
, boff
, addr
);
count
= resid
& ~(bsize
- 1);
if (sddebug
& SDB_PARTIAL
)
printf(" fulltrans: bn %x cnt %x addr %x\n",
cbp
->b_blkno
, count
, addr
);
cbp
->b_flags
= B_BUSY
| B_PHYS
| (bp
->b_flags
& B_READ
);
if (cbp
->b_flags
& B_ERROR
) {
bp
->b_error
= cbp
->b_error
;
if (sddebug
& SDB_PARTIAL
)
printf(" done: bn %x resid %x addr %x\n",
int unit
= sdunit(bp
->b_dev
);
register struct sd_softc
*sc
= &sd_softc
[unit
];
register struct buf
*dp
= &sdtab
[unit
];
register struct partition
*pinfo
;
if (sc
->sc_format_pid
>= 0) {
if (sc
->sc_format_pid
!= curproc
->p_pid
) { /* XXX */
if (sc
->sc_flags
& SDF_ERROR
) {
sz
= howmany(bp
->b_bcount
, DEV_BSIZE
);
pinfo
= &sc
->sc_info
.si_label
.d_partitions
[sdpart(bp
->b_dev
)];
if (bn
< 0 || bn
+ sz
> pinfo
->p_size
) {
bp
->b_resid
= bp
->b_bcount
;
bp
->b_bcount
= dbtob(sz
);
* Check for write to write protected label
if (bn
+ pinfo
->p_offset
<= LABELSECTOR
&&
bn
+ pinfo
->p_offset
+ sz
> LABELSECTOR
&&
!(bp
->b_flags
& B_READ
) && !(sc
->sc_flags
& SDF_WLABEL
)) {
* Non-aligned or partial-block transfers handled specially.
if ((dbtob(bn
) & s
) || (bp
->b_bcount
& s
)) {
sdlblkstrat(bp
, sc
->sc_blksize
);
bp
->b_cylin
= (bn
+ pinfo
->p_offset
) >> sc
->sc_bshift
;
if (scsireq(&sd_softc
[unit
].sc_dq
))
* 0 if not really an error
* <0 if we should do a retry
sderror(unit
, sc
, hp
, stat
)
register struct sd_softc
*sc
;
register struct hp_device
*hp
;
sdsense
[unit
].status
= stat
;
if (stat
& STS_CHECKCOND
) {
scsi_request_sense(hp
->hp_ctlr
, hp
->hp_slave
,
sc
->sc_punit
, sdsense
[unit
].sense
,
sizeof(sdsense
[unit
].sense
));
sp
= (struct scsi_xsense
*)sdsense
[unit
].sense
;
printf("sd%d: scsi sense class %d, code %d", unit
,
printf(", key %d", sp
->key
);
printf(", blk %d", *(int *)&sp
->info1
);
/* no sense, try again */
/* recovered error, not a problem */
/* possible media change */
* For removable media, if we are doing the
* first open (i.e. reading the label) go
* ahead and retry, otherwise someone has
* changed the media out from under us and
* we should abort any further operations
if (sc
->sc_flags
& SDF_RMEDIA
) {
if (sc
->sc_flags
& SDF_OPENING
)
sc
->sc_flags
|= SDF_ERROR
;
register struct sd_softc
*sc
;
register struct buf
*dp
= &sdtab
[unit
];
if (sc
->sc_flags
& SDF_WANTED
) {
sc
->sc_flags
&= ~SDF_WANTED
;
register struct sd_softc
*sc
= &sd_softc
[unit
];
register struct hp_device
*hp
= sc
->sc_hd
;
* we have the SCSI bus -- in format mode, we may or may not need dma
if (sc
->sc_format_pid
>= 0 && legal_cmds
[sdcmd
[unit
].cdb
[0]] > 0) {
register struct buf
*bp
= sdtab
[unit
].b_actf
;
sdtab
[unit
].b_errcnt
= 0;
sts
= scsi_immed_command(hp
->hp_ctlr
, hp
->hp_slave
,
sc
->sc_punit
, &sdcmd
[unit
],
bp
->b_un
.b_addr
, bp
->b_bcount
,
sdsense
[unit
].status
= sts
;
(sts
= sderror(unit
, sc
, hp
, sts
)) == 0)
if (sts
> 0 || sdtab
[unit
].b_errcnt
++ >= SDRETRY
) {
} else if (scsiustart(hp
->hp_ctlr
))
register struct sd_softc
*sc
= &sd_softc
[unit
];
register struct hp_device
*hp
= sc
->sc_hd
;
register struct buf
*bp
= sdtab
[unit
].b_actf
;
register struct scsi_fmt_cdb
*cmd
;
if (sc
->sc_format_pid
>= 0) {
* Drive is in an error state, abort all operations
if (sc
->sc_flags
& SDF_ERROR
) {
cmd
= bp
->b_flags
& B_READ
? &sd_read_cmd
: &sd_write_cmd
;
*(int *)(&cmd
->cdb
[2]) = bp
->b_cylin
;
pad
= howmany(bp
->b_bcount
, sc
->sc_blksize
);
*(u_short
*)(&cmd
->cdb
[7]) = pad
;
pad
= (bp
->b_bcount
& (sc
->sc_blksize
- 1)) != 0;
printf("sd%d: partial block xfer -- %x bytes\n",
sdstats
[unit
].sdtransfers
++;
ledcontrol(0, 0, LED_DISK
);
if (scsigo(hp
->hp_ctlr
, hp
->hp_slave
, sc
->sc_punit
, bp
, cmd
, pad
) == 0) {
dk_busy
|= 1 << hp
->hp_dk
;
dk_wds
[hp
->hp_dk
] += bp
->b_bcount
>> 6;
printf("sd%d: sdstart: %s adr %d blk %d len %d ecnt %d\n",
unit
, bp
->b_flags
& B_READ
? "read" : "write",
bp
->b_un
.b_addr
, bp
->b_cylin
, bp
->b_bcount
,
register struct sd_softc
*sc
= &sd_softc
[unit
];
register struct buf
*bp
= sdtab
[unit
].b_actf
;
register struct hp_device
*hp
= sc
->sc_hd
;
printf("sd%d: bp == NULL\n", unit
);
dk_busy
&=~ (1 << hp
->hp_dk
);
printf("sd%d: sdintr: bad scsi status 0x%x\n",
cond
= sderror(unit
, sc
, hp
, stat
);
if (cond
< 0 && sdtab
[unit
].b_errcnt
++ < SDRETRY
) {
printf("sd%d: retry #%d\n",
unit
, sdtab
[unit
].b_errcnt
);
register int unit
= sdunit(dev
);
if ((pid
= sd_softc
[unit
].sc_format_pid
) >= 0 &&
pid
!= uio
->uio_procp
->p_pid
)
return (physio(sdstrategy
, NULL
, dev
, B_READ
, minphys
, uio
));
register int unit
= sdunit(dev
);
if ((pid
= sd_softc
[unit
].sc_format_pid
) >= 0 &&
pid
!= uio
->uio_procp
->p_pid
)
return (physio(sdstrategy
, NULL
, dev
, B_WRITE
, minphys
, uio
));
sdioctl(dev
, cmd
, data
, flag
, p
)
register struct sd_softc
*sc
= &sd_softc
[unit
];
register struct disklabel
*lp
= &sc
->sc_info
.si_label
;
*(struct disklabel
*)data
= *lp
;
((struct partinfo
*)data
)->disklab
= lp
;
((struct partinfo
*)data
)->part
=
&lp
->d_partitions
[sdpart(dev
)];
if ((flag
& FWRITE
) == 0)
sc
->sc_flags
|= SDF_WLABEL
;
sc
->sc_flags
&= ~SDF_WLABEL
;
if ((flag
& FWRITE
) == 0)
error
= setdisklabel(lp
, (struct disklabel
*)data
,
(sc
->sc_flags
& SDF_WLABEL
) ? 0
if ((flag
& FWRITE
) == 0)
error
= setdisklabel(lp
, (struct disklabel
*)data
,
(sc
->sc_flags
& SDF_WLABEL
) ? 0
sc
->sc_flags
= SDF_ALIVE
| SDF_WLABEL
;
error
= writedisklabel(sdlabdev(dev
), sdstrategy
, lp
);
/* take this device into or out of "format" mode */
if (suser(p
->p_ucred
, &p
->p_acflag
))
if (sc
->sc_format_pid
>= 0)
sc
->sc_format_pid
= p
->p_pid
;
/* find out who has the device in format mode */
*(int *)data
= sc
->sc_format_pid
;
* Save what user gave us as SCSI cdb to use with next
* read or write to the char device.
if (sc
->sc_format_pid
!= p
->p_pid
)
if (legal_cmds
[((struct scsi_fmt_cdb
*)data
)->cdb
[0]] == 0)
bcopy(data
, (caddr_t
)&sdcmd
[unit
], sizeof(sdcmd
[0]));
* return the SCSI sense data saved after the last
* operation that completed with "check condition" status.
bcopy((caddr_t
)&sdsense
[unit
], data
, sizeof(sdsense
[0]));
register int unit
= sdunit(dev
);
register struct sd_softc
*sc
= &sd_softc
[unit
];
if (unit
>= NSD
|| (sc
->sc_flags
& SDF_ALIVE
) == 0)
* We get called very early on (via swapconf)
* without the device being open so we may need
if (sc
->sc_info
.si_open
== 0) {
if (sdopen(dev
, FREAD
|FWRITE
, S_IFBLK
, NULL
))
psize
= sc
->sc_info
.si_label
.d_partitions
[sdpart(dev
)].p_size
;
(void) sdclose(dev
, FREAD
|FWRITE
, S_IFBLK
, NULL
);
* Non-interrupt driven, non-dma dump routine.
register struct sd_softc
*sc
= &sd_softc
[unit
];
register struct hp_device
*hp
= sc
->sc_hd
;
register struct partition
*pinfo
;
extern int lowram
, dumpsize
;
if (unit
>= NSD
|| (sc
->sc_flags
& SDF_ALIVE
) == 0)
pinfo
= &sc
->sc_info
.si_label
.d_partitions
[part
];
/* dump parameters in range? */
if (dumplo
< 0 || dumplo
>= pinfo
->p_size
||
pinfo
->p_fstype
!= FS_SWAP
)
if (dumplo
+ ctod(pages
) > pinfo
->p_size
)
pages
= dtoc(pinfo
->p_size
- dumplo
);
baddr
= dumplo
+ pinfo
->p_offset
;
if (!scsireq(&sc
->sc_dq
)) {
printf("[ drive %d reset ] ", unit
);
for (i
= 0; i
< pages
; i
++) {
#define NPGMB (1024*1024/NBPG)
/* print out how many Mbs we have dumped */
if (i
&& (i
% NPGMB
) == 0)
printf("%d ", i
/ NPGMB
);
pmap_enter(kernel_pmap
, (vm_offset_t
)vmmap
, maddr
,
stat
= scsi_tt_write(hp
->hp_ctlr
, hp
->hp_slave
, sc
->sc_punit
,
vmmap
, NBPG
, baddr
, sc
->sc_bshift
);
printf("sddump: scsi write error 0x%x\n", stat
);