From 7f2f1b784ee071a56749d256472016d911a4d1dc Mon Sep 17 00:00:00 2001 From: Julian Elischer Date: Wed, 6 May 1998 22:14:48 +0000 Subject: [PATCH] Add dump support to the DEVFS/slice code. now we can actually catch our crashes :-) Submitted by: Luoqi Chen (the man who's everywhere) --- sys/amd64/amd64/autoconf.c | 7 +- sys/dev/fdc/fdc.c | 6 +- sys/dev/slice/disklabel.c | 22 ++++- sys/dev/slice/mbr.c | 22 ++++- sys/dev/slice/slice.h | 4 +- sys/dev/slice/slice_device.c | 29 ++++++- sys/dev/vn/vn.c | 19 ++++- sys/i386/i386/autoconf.c | 7 +- sys/i386/isa/fd.c | 6 +- sys/i386/isa/wd.c | 161 ++++++++++++++++++++++++++++++++++- sys/isa/fd.c | 6 +- sys/kern/kern_shutdown.c | 11 ++- sys/scsi/sd.c | 103 +++++++++++++++++++++- 13 files changed, 371 insertions(+), 32 deletions(-) diff --git a/sys/amd64/amd64/autoconf.c b/sys/amd64/amd64/autoconf.c index ff061a605ec8..90bee3c87f5b 100644 --- a/sys/amd64/amd64/autoconf.c +++ b/sys/amd64/amd64/autoconf.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 - * $Id: autoconf.c,v 1.94 1998/04/20 03:57:23 julian Exp $ + * $Id: autoconf.c,v 1.95 1998/04/20 21:53:07 julian Exp $ */ /* @@ -398,6 +398,7 @@ setdumpdev(dev) { int maj, psize; long newdumplo; + struct partinfo pi; if (dev == NODEV) { dumpdev = dev; @@ -418,7 +419,9 @@ setdumpdev(dev) * and nuke dodump sysctl (too many knobs), and move this to * kern_shutdown.c... */ - if (dkpart(dev) != SWAP_PART) + if (bdevsw[maj]->d_ioctl(dev, DIOCGPART, (caddr_t)&pi, 0, NULL) != 0) + return (ENODEV); + if (pi.part->p_fstype != FS_SWAP) return (ENODEV); newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; if (newdumplo < 0) diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index 2d74c99ef626..9afadd283571 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -43,7 +43,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.109 1998/04/19 23:31:41 julian Exp $ + * $Id: fd.c,v 1.110 1998/04/22 10:25:15 julian Exp $ * */ @@ -2196,9 +2196,9 @@ fdsopen(void *private, int flags, int mode, struct proc *p) sd = private; if((flags & (FREAD|FWRITE)) != 0) { - return(Fdopen(makedev(0,sd->minor), 0 , 0, p)); + return(Fdopen(makedev(0,sd->minor), flags , mode, p)); } else { - return(fdclose(makedev(0,sd->minor), 0 , 0, p)); + return(fdclose(makedev(0,sd->minor), 0 , mode, p)); } } diff --git a/sys/dev/slice/disklabel.c b/sys/dev/slice/disklabel.c index ff8c6f6abe1b..2934745ee2fc 100644 --- a/sys/dev/slice/disklabel.c +++ b/sys/dev/slice/disklabel.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: disklabel.c,v 1.2 1998/04/22 10:25:09 julian Exp $ + * $Id: disklabel.c,v 1.3 1998/04/22 19:27:51 julian Exp $ */ #define BAD144 @@ -74,6 +74,7 @@ static sl_h_claim_t dkl_claim; /* upwards travelling claim */ static sl_h_revoke_t dkl_revoke;/* upwards travelling revokation */ static sl_h_verify_t dkl_verify;/* things changed, are we stil valid? */ static sl_h_upconfig_t dkl_upconfig;/* config requests from below */ +static sl_h_dump_t dkl_dump; /* core dump req downward */ static struct slice_handler slicetype = { "disklabel", @@ -88,7 +89,8 @@ static struct slice_handler slicetype = { &dkl_revoke, /* revoke */ &dkl_claim, /* claim */ &dkl_verify, /* verify */ - &dkl_upconfig /* subslice manipulation */ + &dkl_upconfig, /* subslice manipulation */ + &dkl_dump }; static void @@ -828,6 +830,7 @@ dkl_upconfig(struct slice *slice, int cmd, caddr_t addr, int flag, struct proc * case SLCIOCRESET: return (0); +#ifdef BAD144 case SLCIOCTRANSBAD: { struct private_data *pd; @@ -838,6 +841,7 @@ dkl_upconfig(struct slice *slice, int cmd, caddr_t addr, int flag, struct proc * *(daddr_t*)addr = dkl_transbad144(pd, *(daddr_t*)addr); return (0); } +#endif /* These don't really make sense. keep the headers for a reminder */ default: @@ -916,3 +920,17 @@ dkcksum(lp) } #endif /* 0 */ +static int +dkl_dump(void *private, int32_t blkoff, int32_t blkcnt) +{ + struct private_data *pd; + struct subdev *sdp; + register struct slice *slice; + +RR; + sdp = private; + pd = sdp->pd; + slice = pd->slice_down; + blkoff += sdp->offset; + return (*slice->handler_down->dump)(slice->private_down, blkoff, blkcnt); +} diff --git a/sys/dev/slice/mbr.c b/sys/dev/slice/mbr.c index 5558775f1f20..08e8b3596ec6 100644 --- a/sys/dev/slice/mbr.c +++ b/sys/dev/slice/mbr.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mbr.c,v 1.2 1998/04/22 10:25:09 julian Exp $ + * $Id: mbr.c,v 1.3 1998/04/22 19:27:51 julian Exp $ */ #include @@ -85,6 +85,7 @@ static sl_h_claim_t mbr_claim; /* upwards travelling claim */ static sl_h_revoke_t mbr_revoke;/* upwards travelling revokation */ static sl_h_verify_t mbr_verify;/* things changed, are we stil valid? */ static sl_h_upconfig_t mbr_upconfig;/* config request from below */ +static sl_h_dump_t mbr_dump; /* core dump req downward */ static struct slice_handler slicetype = { "MBR", @@ -99,7 +100,8 @@ static struct slice_handler slicetype = { &mbr_revoke, /* revoke */ &mbr_claim, /* claim */ &mbr_verify, /* verify */ - &mbr_upconfig /* config from below */ + &mbr_upconfig, /* config from below */ + &mbr_dump }; static void @@ -839,6 +841,8 @@ mbr_upconfig(struct slice *slice, int cmd, caddr_t addr, daddr_t blkno; int part; + if (!slice->handler_up) + return (0); blkno = *(daddr_t *)addr; pd = slice->private_up; sdp = pd->subdevs; @@ -868,3 +872,17 @@ mbr_upconfig(struct slice *slice, int cmd, caddr_t addr, return (0); } +static int +mbr_dump(void *private, int32_t blkoff, int32_t blkcnt) +{ + struct private_data *pd; + struct subdev *sdp; + register struct slice *slice; + +RR; + sdp = private; + pd = sdp->pd; + slice = pd->slice_down; + blkoff += sdp->offset; + return (*slice->handler_down->dump)(slice->private_down, blkoff, blkcnt); +} diff --git a/sys/dev/slice/slice.h b/sys/dev/slice/slice.h index 553bdb51a9a8..ee7cd36f75a4 100644 --- a/sys/dev/slice/slice.h +++ b/sys/dev/slice/slice.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: $ + * $Id: slice.h,v 1.1 1998/04/19 23:31:10 julian Exp $ */ typedef struct slice_handler *sh_p; @@ -125,6 +125,7 @@ typedef int sl_h_claim_t(struct slice * slice, struct slice * lower, typedef int sl_h_verify_t(struct slice *slice); typedef int sl_h_upconfig_t(struct slice *slice, int cmd, caddr_t data, int fflag, struct proc *p); +typedef int sl_h_dump_t(void *private, int32_t blkoff, int32_t blkcnt); struct slice_handler { char *name; @@ -140,6 +141,7 @@ struct slice_handler { sl_h_claim_t *claim; /* claim a new slice */ sl_h_verify_t *verify; /* verify that a slice as it was before */ sl_h_upconfig_t *upconf; /* config requests from slice below */ + sl_h_dump_t *dump; /* dump the core */ }; /* diff --git a/sys/dev/slice/slice_device.c b/sys/dev/slice/slice_device.c index d471bd46dd65..d5c418afa700 100644 --- a/sys/dev/slice/slice_device.c +++ b/sys/dev/slice/slice_device.c @@ -23,9 +23,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: slice_device.c,v 1.3 1998/04/22 19:27:52 julian Exp $ + * $Id: slice_device.c,v 1.4 1998/04/24 07:53:55 julian Exp $ */ #define DIAGNOSTIC 1 +#include "opt_hw_wdog.h" #include #include @@ -39,7 +40,9 @@ #include /* DEVFS defintitions */ #include /* temporary location */ - +#include +#include +#include /* Function prototypes (these should all be static except for slicenew()) */ static d_open_t slcdevopen; @@ -369,8 +372,26 @@ static int slcdevdump(dev_t dev) { sl_p slice = minor_to_slice(minor(dev)); + static int slcdoingdump = 0; + int32_t num, nblocks, lo; RR; - if (slice == NULL) + if (!slice || !(slice->flags & SLF_OPEN_DEV_WR) || + !slice->handler_down->dump) return (ENXIO); - return (0); + + /* Toss any characters present prior to dump. */ + while (cncheckc() != -1) + ; + + if (slcdoingdump) + return (EFAULT); + + num = (int32_t)(Maxmem * PAGE_SIZE / slice->limits.blksize); + nblocks = (int32_t)(slice->limits.slicesize / slice->limits.blksize); + lo = dumplo * DEV_BSIZE / slice->limits.blksize; + if (lo < 0 || lo + num > nblocks) + return (EINVAL); + + slcdoingdump = 1; + return (*slice->handler_down->dump)(slice->private_down, lo, num); } diff --git a/sys/dev/vn/vn.c b/sys/dev/vn/vn.c index 0ee88718957c..516a9f8a25d7 100644 --- a/sys/dev/vn/vn.c +++ b/sys/dev/vn/vn.c @@ -38,7 +38,7 @@ * from: Utah Hdr: vn.c 1.13 94/04/02 * * from: @(#)vn.c 8.6 (Berkeley) 4/1/94 - * $Id: vn.c,v 1.57 1998/04/22 10:25:12 julian Exp $ + * $Id: vn.c,v 1.58 1998/04/24 07:53:59 julian Exp $ */ /* @@ -114,6 +114,7 @@ static sl_h_IO_req_t nvsIOreq; /* IO req downward (to device) */ static sl_h_ioctl_t nvsioctl; /* ioctl req downward (to device) */ static sl_h_open_t nvsopen; /* downwards travelling open */ /*static sl_h_close_t nvsclose; */ /* downwards travelling close */ +static sl_h_dump_t nvsdump; /* core dump req downward */ static struct slice_handler slicetype = { "vn", @@ -128,7 +129,8 @@ static struct slice_handler slicetype = { NULL, /* revoke */ NULL, /* claim */ NULL, /* verify */ - NULL /* upconfig */ + NULL, /* upconfig */ + &nvsdump }; #endif @@ -448,6 +450,14 @@ nvsIOreq(void *private ,struct buf *bp) bn = bp->b_pblkno; bp->b_resid = bp->b_bcount;/* XXX best place to set this? */ sz = howmany(bp->b_bcount, DEV_BSIZE); + if (bn < 0 || bn + sz > vn->sc_size) { + if (bn != vn->sc_size) { + bp->b_error = EINVAL; + bp->b_flags |= B_ERROR; + } + biodone(bp); + return; + } if( (bp->b_flags & B_PAGING) == 0) { aiov.iov_base = bp->b_data; @@ -936,5 +946,10 @@ nvsioctl( void *private, int cmd, caddr_t addr, int flag, struct proc *p) return(vnioctl(makedev(0,vn->mynor), cmd, addr, flag, p)); } +static int +nvsdump(void *private, int32_t blkoff, int32_t blkcnt) +{ + return (ENODEV); +} #endif #endif diff --git a/sys/i386/i386/autoconf.c b/sys/i386/i386/autoconf.c index ff061a605ec8..90bee3c87f5b 100644 --- a/sys/i386/i386/autoconf.c +++ b/sys/i386/i386/autoconf.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 - * $Id: autoconf.c,v 1.94 1998/04/20 03:57:23 julian Exp $ + * $Id: autoconf.c,v 1.95 1998/04/20 21:53:07 julian Exp $ */ /* @@ -398,6 +398,7 @@ setdumpdev(dev) { int maj, psize; long newdumplo; + struct partinfo pi; if (dev == NODEV) { dumpdev = dev; @@ -418,7 +419,9 @@ setdumpdev(dev) * and nuke dodump sysctl (too many knobs), and move this to * kern_shutdown.c... */ - if (dkpart(dev) != SWAP_PART) + if (bdevsw[maj]->d_ioctl(dev, DIOCGPART, (caddr_t)&pi, 0, NULL) != 0) + return (ENODEV); + if (pi.part->p_fstype != FS_SWAP) return (ENODEV); newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; if (newdumplo < 0) diff --git a/sys/i386/isa/fd.c b/sys/i386/isa/fd.c index 2d74c99ef626..9afadd283571 100644 --- a/sys/i386/isa/fd.c +++ b/sys/i386/isa/fd.c @@ -43,7 +43,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.109 1998/04/19 23:31:41 julian Exp $ + * $Id: fd.c,v 1.110 1998/04/22 10:25:15 julian Exp $ * */ @@ -2196,9 +2196,9 @@ fdsopen(void *private, int flags, int mode, struct proc *p) sd = private; if((flags & (FREAD|FWRITE)) != 0) { - return(Fdopen(makedev(0,sd->minor), 0 , 0, p)); + return(Fdopen(makedev(0,sd->minor), flags , mode, p)); } else { - return(fdclose(makedev(0,sd->minor), 0 , 0, p)); + return(fdclose(makedev(0,sd->minor), 0 , mode, p)); } } diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c index 6dafca1f4fda..06ac100e8454 100644 --- a/sys/i386/isa/wd.c +++ b/sys/i386/isa/wd.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.163 1998/04/24 07:54:00 julian Exp $ + * $Id: wd.c,v 1.164 1998/05/05 14:27:26 sos Exp $ */ /* TODO: @@ -263,6 +263,7 @@ static sl_h_IO_req_t wdsIOreq; /* IO req downward (to device) */ static sl_h_ioctl_t wdsioctl; /* ioctl req downward (to device) */ static sl_h_open_t wdsopen; /* downwards travelling open */ /*static sl_h_close_t wdsclose; */ /* downwards travelling close */ +static sl_h_dump_t wdsdump; /* core dump req downward */ static void wds_init(void*); static struct slice_handler slicetype = { @@ -278,7 +279,8 @@ static struct slice_handler slicetype = { NULL, /* revoke */ NULL, /* claim */ NULL, /* verify */ - NULL /* upconfig */ + NULL, /* upconfig */ + &wdsdump }; #endif @@ -970,7 +972,7 @@ wdstart(int ctrlr) blknum - ds_offset) + ds_offset; } #else - if (du->dk_flags & DKFL_SINGLE) { + if (du->dk_flags & DKFL_SINGLE && du->slice->handler_up) { (void) (*du->slice->handler_up->upconf)(du->slice, SLCIOCTRANSBAD, (caddr_t)&blknum, 0, 0); } @@ -2782,5 +2784,158 @@ wdsioctl( void *private, int cmd, caddr_t addr, int flag, struct proc *p) } } +static int +wdsdump(void *private, int32_t start, int32_t num) +{ + register struct disk *du; + long blknum, blkchk, blkcnt, blknext; + long cylin, head, sector; + long secpertrk, secpercyl, nblocks; + char *addr; + + du = private; + if (du->dk_state < OPEN) + return (ENXIO); + + secpertrk = du->dk_dd.d_nsectors; + secpercyl = du->dk_dd.d_secpercyl; + + /* Recalibrate the drive. */ + DELAY(5); /* ATA spec XXX NOT */ + if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0 + || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0 + || wdsetctlr(du) != 0) { + wderror((struct buf *)NULL, du, "wddump: recalibrate failed"); + return (EIO); + } + + du->dk_flags |= DKFL_SINGLE; + addr = (char *) 0; + blknum = start; + while (num > 0) { + blkcnt = num; + if (blkcnt > MAXTRANSFER) + blkcnt = MAXTRANSFER; + /* Keep transfer within current cylinder. */ + if ((blknum + blkcnt - 1) / secpercyl != blknum / secpercyl) + blkcnt = secpercyl - (blknum % secpercyl); + blknext = blknum + blkcnt; + + /* + * See if one of the sectors is in the bad sector list + * (if we have one). If the first sector is bad, then + * reduce the transfer to this one bad sector; if another + * sector is bad, then reduce reduce the transfer to + * avoid any bad sectors. + */ + if (du->dk_flags & DKFL_SINGLE && du->slice->handler_up) { + for (blkchk = blknum; blkchk < blknum + blkcnt; blkchk++) { + daddr_t blknew = blkchk; + (void) (*du->slice->handler_up->upconf)(du->slice, + SLCIOCTRANSBAD, (caddr_t)&blknew, 0, 0); + if (blknew != blkchk) { + /* Found bad block. */ + blkcnt = blkchk - blknum; + if (blkcnt > 0) { + blknext = blknum + blkcnt; + goto out; + } + blkcnt = 1; + blknext = blknum + blkcnt; +#if 1 || defined(WDDEBUG) + printf("bad block %lu -> %lu\n", + blknum, blknew); +#endif + break; + } + } + } +out: + + /* Compute disk address. */ + cylin = blknum / secpercyl; + head = (blknum % secpercyl) / secpertrk; + sector = blknum % secpertrk; + +#if 0 + /* Let's just talk about this first... */ + pg("cylin l%d head %ld sector %ld addr 0x%x count %ld", + cylin, head, sector, addr, blkcnt); +#endif + + /* Do the write. */ + if (wdcommand(du, cylin, head, sector, blkcnt, WDCC_WRITE) + != 0) { + wderror((struct buf *)NULL, du, + "wdsdump: timeout waiting to to give command"); + return (EIO); + } + while (blkcnt != 0) { + if (is_physical_memory((vm_offset_t)addr)) + pmap_enter(kernel_pmap, (vm_offset_t)CADDR1, + trunc_page(addr), VM_PROT_READ, TRUE); + else + pmap_enter(kernel_pmap, (vm_offset_t)CADDR1, + trunc_page(0), VM_PROT_READ, TRUE); + + /* Ready to send data? */ + DELAY(5); /* ATA spec */ + if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT) + < 0) { + wderror((struct buf *)NULL, du, + "wdsdump: timeout waiting for DRQ"); + return (EIO); + } + if (du->dk_flags & DKFL_32BIT) + outsl(du->dk_port + wd_data, + CADDR1 + ((int)addr & PAGE_MASK), + DEV_BSIZE / sizeof(long)); + else + outsw(du->dk_port + wd_data, + CADDR1 + ((int)addr & PAGE_MASK), + DEV_BSIZE / sizeof(short)); + addr += DEV_BSIZE; + /* + * If we are dumping core, it may take a while. + * So reassure the user and hold off any watchdogs. + */ + if ((unsigned)addr % (1024 * 1024) == 0) { +#ifdef HW_WDOG + if (wdog_tickler) + (*wdog_tickler)(); +#endif /* HW_WDOG */ + printf("%ld ", num / (1024 * 1024 / DEV_BSIZE)); + } + num--; + blkcnt--; + } + + /* Wait for completion. */ + DELAY(5); /* ATA spec XXX NOT */ + if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) < 0) { + wderror((struct buf *)NULL, du, + "wdsdump: timeout waiting for status"); + return (EIO); + } + + /* Check final status. */ + if (du->dk_status + & (WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ | WDCS_ERR) + != (WDCS_READY | WDCS_SEEKCMPLT)) { + wderror((struct buf *)NULL, du, + "wdsdump: extra DRQ, or error"); + return (EIO); + } + + /* Update block count. */ + blknum = blknext; + + /* Operator aborting dump? */ + if (cncheckc() != -1) + return (EINTR); + } + return (0); +} + #endif /* SLICE */ #endif /* NWDC > 0 */ diff --git a/sys/isa/fd.c b/sys/isa/fd.c index 2d74c99ef626..9afadd283571 100644 --- a/sys/isa/fd.c +++ b/sys/isa/fd.c @@ -43,7 +43,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.109 1998/04/19 23:31:41 julian Exp $ + * $Id: fd.c,v 1.110 1998/04/22 10:25:15 julian Exp $ * */ @@ -2196,9 +2196,9 @@ fdsopen(void *private, int flags, int mode, struct proc *p) sd = private; if((flags & (FREAD|FWRITE)) != 0) { - return(Fdopen(makedev(0,sd->minor), 0 , 0, p)); + return(Fdopen(makedev(0,sd->minor), flags , mode, p)); } else { - return(fdclose(makedev(0,sd->minor), 0 , 0, p)); + return(fdclose(makedev(0,sd->minor), 0 , mode, p)); } } diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index c6dd9c17bbda..40704d8821ba 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94 - * $Id: kern_shutdown.c,v 1.28 1998/02/16 23:57:44 eivind Exp $ + * $Id: kern_shutdown.c,v 1.29 1998/03/08 09:56:54 julian Exp $ */ #include "opt_ddb.h" @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -358,17 +359,21 @@ SYSINIT(dump_conf, SI_SUB_DUMP_CONF, SI_ORDER_FIRST, dump_conf, NULL) static void dumpsys(void) { + struct partinfo pi; if (!dodump) return; if (dumpdev == NODEV) return; - if ((minor(dumpdev)&07) != 1) - return; if (!(bdevsw[major(dumpdev)])) return; if (!(bdevsw[major(dumpdev)]->d_dump)) return; + if ((*bdevsw[major(dumpdev)]->d_ioctl)(dumpdev, DIOCGPART, + (caddr_t)&pi, 0, NULL)) + return; + if (pi.part->p_fstype != FS_SWAP) + return; dumpsize = Maxmem; printf("\ndumping to dev %lx, offset %ld\n", dumpdev, dumplo); printf("dump "); diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index b1c642c1f2f3..ee3625f993f7 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -14,7 +14,7 @@ * * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992 * - * $Id: sd.c,v 1.125 1998/04/22 10:25:27 julian Exp $ + * $Id: sd.c,v 1.126 1998/04/27 11:36:06 des Exp $ */ #include "opt_bounce.h" @@ -144,6 +144,7 @@ static sl_h_ioctl_t sdsioctl; /* ioctl req downward (to device) */ static sl_h_open_t sdsopen; /* downwards travelling open */ /*static sl_h_close_t sdsclose; */ /* downwards travelling close */ static void sds_init (void *arg); +static sl_h_dump_t sdsdump; /* core dump req downward */ static struct slice_handler slicetype = { "scsidisk", @@ -158,7 +159,8 @@ static struct slice_handler slicetype = { NULL, /* revoke */ NULL, /* claim */ NULL, /* verify */ - NULL /* upconfig */ + NULL, /* upconfig */ + &sdsdump }; #endif @@ -1313,4 +1315,101 @@ sdsioctl( void *private, int cmd, caddr_t addr, int flag, struct proc *p) return(sdioctl(makedev(0,sd->mynor), cmd, addr, flag, p)); } +static int +sdsdump(void *private, int32_t start, int32_t num) +{ /* dump core after a system crash */ + register struct scsi_data *sd; /* disk unit to do the IO */ + struct scsi_link *sc_link; + int32_t blkoff, blknum, blkcnt = MAXTRANSFER; + char *addr; + struct scsi_rw_big cmd; + struct scsi_xfer *xs = &sx; + errval retval; + + addr = (char *) 0; /* starting address */ + + sd = private; + sc_link = sd->sc_link; + + /* was it ever initialized etc. ? */ + if (!(sd->flags & SDINIT)) + return (ENXIO); + if ((sc_link->flags & SDEV_MEDIA_LOADED) != SDEV_MEDIA_LOADED) + return (ENXIO); + + blknum = start; + while (num > 0) { + if (is_physical_memory((vm_offset_t)addr)) + pmap_enter(kernel_pmap, (vm_offset_t)CADDR1, + trunc_page(addr), VM_PROT_READ, TRUE); + else + pmap_enter(kernel_pmap, (vm_offset_t)CADDR1, + trunc_page(0), VM_PROT_READ, TRUE); + /* + * Fill out the scsi command + */ + bzero(&cmd, sizeof(cmd)); + cmd.op_code = WRITE_BIG; + cmd.addr_3 = (blknum & 0xff000000) >> 24; + cmd.addr_2 = (blknum & 0xff0000) >> 16; + cmd.addr_1 = (blknum & 0xff00) >> 8; + cmd.addr_0 = blknum & 0xff; + cmd.length2 = (blkcnt & 0xff00) >> 8; + cmd.length1 = (blkcnt & 0xff); + /* + * Fill out the scsi_xfer structure + * Note: we cannot sleep as we may be an interrupt + * don't use scsi_scsi_cmd() as it may want + * to wait for an xs. + */ + bzero(xs, sizeof(sx)); + xs->flags |= SCSI_NOMASK | SCSI_NOSLEEP | INUSE | SCSI_DATA_OUT; + xs->sc_link = sc_link; + xs->retries = SD_RETRIES; + xs->timeout = 10000; /* 10000 millisecs for a disk ! */ + xs->cmd = (struct scsi_generic *) &cmd; + xs->cmdlen = sizeof(cmd); + xs->resid = 0; + xs->error = XS_NOERROR; + xs->bp = 0; + xs->data = (u_char *) CADDR1; /* XXX use pmap_enter() */ + xs->datalen = blkcnt * sd->params.secsiz; + + /* + * Pass all this info to the scsi driver. + */ + retval = (*(sc_link->adapter->scsi_cmd)) (xs); + switch (retval) { + case SUCCESSFULLY_QUEUED: + case HAD_ERROR: + return (ENXIO); /* we said not to sleep! */ + case COMPLETE: + break; + default: + return (ENXIO); /* we said not to sleep! */ + } + + /* + * If we are dumping core, it may take a while. + * So reassure the user and hold off any watchdogs. + */ + if ((unsigned)addr % (1024 * 1024) == 0) { +#ifdef HW_WDOG + if (wdog_tickler) + (*wdog_tickler)(); +#endif /* HW_WDOG */ + printf("%ld ", num / 2048); + } + /* update block count */ + num -= blkcnt; + blknum += blkcnt; + (int) addr += blkcnt * sd->params.secsiz; + + /* operator aborting dump? */ + if (cncheckc() != -1) + return (EINTR); + } + return (0); +} + #endif