Now getting these from arch/sun3/sun3
This commit is contained in:
parent
8749290f0a
commit
5cf8aa219a
@ -1,377 +0,0 @@
|
||||
/* $NetBSD: conf.c,v 1.1.1.1 1997/01/14 20:57:08 gwr Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1994 Adam Glass, Gordon W. Ross
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 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
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)conf.c 8.2 (Berkeley) 11/14/93
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include "cd.h"
|
||||
bdev_decl(cd);
|
||||
cdev_decl(cd);
|
||||
|
||||
#include "ccd.h"
|
||||
bdev_decl(ccd);
|
||||
cdev_decl(ccd);
|
||||
|
||||
#include "rd.h"
|
||||
bdev_decl(rd);
|
||||
/* no cdev for rd */
|
||||
|
||||
#include "sd.h"
|
||||
bdev_decl(sd);
|
||||
cdev_decl(sd);
|
||||
|
||||
#include "st.h"
|
||||
bdev_decl(st);
|
||||
cdev_decl(st);
|
||||
|
||||
/* swap device (required) */
|
||||
bdev_decl(sw);
|
||||
cdev_decl(sw);
|
||||
|
||||
#include "vnd.h"
|
||||
bdev_decl(vnd);
|
||||
cdev_decl(vnd);
|
||||
|
||||
#include "xd.h"
|
||||
bdev_decl(xd);
|
||||
cdev_decl(xd);
|
||||
|
||||
#define NXT 0 /* XXX */
|
||||
bdev_decl(xt);
|
||||
cdev_decl(xt);
|
||||
|
||||
#include "xy.h"
|
||||
bdev_decl(xy);
|
||||
cdev_decl(xy);
|
||||
|
||||
struct bdevsw bdevsw[] =
|
||||
{
|
||||
bdev_notdef(), /* 0 */
|
||||
bdev_notdef(), /* 1: tapemaster tape */
|
||||
bdev_notdef(), /* 2 */
|
||||
bdev_disk_init(NXY,xy), /* 3: SMD disk on Xylogics 450/451 */
|
||||
bdev_swap_init(1,sw), /* 4: swap pseudo-device */
|
||||
bdev_disk_init(NVND,vnd), /* 5: vnode disk driver */
|
||||
bdev_notdef(), /* 6 */
|
||||
bdev_disk_init(NSD,sd), /* 7: SCSI disk */
|
||||
bdev_tape_init(NXT,xt), /* 8: Xylogics tape */
|
||||
bdev_disk_init(NCCD,ccd), /* 9: concatenated disk driver */
|
||||
bdev_disk_init(NXD,xd), /* 10: SMD disk on Xylogics 7053 */
|
||||
bdev_tape_init(NST,st), /* 11: SCSI tape */
|
||||
bdev_notdef(), /* 12: Sun ns? */
|
||||
bdev_disk_init(NRD,rd), /* 13: RAM disk - for install tape */
|
||||
bdev_notdef(), /* 14: Sun ft? */
|
||||
bdev_notdef(), /* 15: Sun hd? */
|
||||
bdev_notdef(), /* 16: Sun fd? */
|
||||
bdev_notdef(), /* 17: Sun vd_unused */
|
||||
bdev_disk_init(NCD,cd), /* 18: SCSI CD-ROM */
|
||||
bdev_notdef(), /* 19: Sun vd_unused */
|
||||
bdev_notdef(), /* 20: Sun vd_unused */
|
||||
bdev_notdef(), /* 21: Sun vd_unused */
|
||||
bdev_notdef(), /* 22: Sun IPI disks... */
|
||||
bdev_notdef(), /* 23: Sun IPI disks... */
|
||||
};
|
||||
int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
|
||||
|
||||
/*
|
||||
* Devices that have only CHR nodes are declared below.
|
||||
*/
|
||||
|
||||
cdev_decl(cn);
|
||||
cdev_decl(ctty);
|
||||
#define mmread mmrw
|
||||
#define mmwrite mmrw
|
||||
cdev_decl(mm);
|
||||
|
||||
#include "zstty.h"
|
||||
cdev_decl(zs);
|
||||
|
||||
#include "kbd.h"
|
||||
cdev_decl(kbd);
|
||||
cdev_decl(kd);
|
||||
|
||||
#include "ms.h"
|
||||
cdev_decl(ms);
|
||||
|
||||
#include "pty.h"
|
||||
#define ptstty ptytty
|
||||
#define ptsioctl ptyioctl
|
||||
cdev_decl(pts);
|
||||
#define ptctty ptytty
|
||||
#define ptcioctl ptyioctl
|
||||
cdev_decl(ptc);
|
||||
|
||||
/* frame-buffer devices */
|
||||
#define fbpoll seltrue
|
||||
cdev_decl(fb);
|
||||
|
||||
#include "bwtwo.h"
|
||||
#define bw2poll seltrue
|
||||
cdev_decl(bw2);
|
||||
|
||||
#include "cgtwo.h"
|
||||
#define cg2poll seltrue
|
||||
cdev_decl(cg2);
|
||||
|
||||
#include "cgfour.h"
|
||||
#define cg4poll seltrue
|
||||
cdev_decl(cg4);
|
||||
|
||||
cdev_decl(log);
|
||||
cdev_decl(fd);
|
||||
|
||||
#include "bpfilter.h"
|
||||
cdev_decl(bpf);
|
||||
|
||||
#include "tun.h"
|
||||
cdev_decl(tun);
|
||||
|
||||
dev_decl(filedesc,open);
|
||||
|
||||
|
||||
struct cdevsw cdevsw[] =
|
||||
{
|
||||
cdev_cn_init(1,cn), /* 0: virtual console */
|
||||
cdev_tty_init(NKBD,kd), /* 1: Sun keyboard/display */
|
||||
cdev_ctty_init(1,ctty), /* 2: controlling terminal */
|
||||
cdev_mm_init(1,mm), /* 3: /dev/{null,mem,kmem,...} */
|
||||
cdev_notdef(), /* 4: was PROM console */
|
||||
cdev_notdef(), /* 5: tapemaster tape */
|
||||
cdev_notdef(), /* 6: systech/versatec */
|
||||
cdev_swap_init(1,sw), /* 7: /dev/drum {swap pseudo-device) */
|
||||
cdev_notdef(), /* 8: Archive QIC-11 tape */
|
||||
cdev_disk_init(NXY,xy), /* 9: SMD disk on Xylogics 450/451 */
|
||||
cdev_notdef(), /* 10: systech multi-terminal board */
|
||||
cdev_notdef(), /* 11: DES encryption chip */
|
||||
cdev_tty_init(NZSTTY,zs), /* 12: Zilog 8350 serial port */
|
||||
cdev_mouse_init(NMS,ms), /* 13: Sun mouse */
|
||||
cdev_notdef(), /* 14: cgone */
|
||||
cdev_notdef(), /* 15: /dev/winXXX */
|
||||
cdev_log_init(1,log), /* 16: /dev/klog */
|
||||
cdev_disk_init(NSD,sd), /* 17: SCSI disk */
|
||||
cdev_tape_init(NST,st), /* 18: SCSI tape */
|
||||
cdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
|
||||
cdev_tty_init(NPTY,pts), /* 20: pseudo-tty slave */
|
||||
cdev_ptc_init(NPTY,ptc), /* 21: pseudo-tty master */
|
||||
cdev_fb_init(1,fb), /* 22: /dev/fb indirect driver */
|
||||
cdev_fd_init(1,filedesc), /* 23: file descriptor pseudo-device */
|
||||
cdev_bpftun_init(NTUN,tun), /* 24: network tunnel */
|
||||
cdev_notdef(), /* 25: sun pi? */
|
||||
cdev_notdef(), /* 26: bwone */
|
||||
cdev_fb_init(NBWTWO,bw2), /* 27: bwtwo */
|
||||
cdev_notdef(), /* 28: Systech VPC-2200 versatec/centronics */
|
||||
cdev_mouse_init(NKBD,kbd), /* 29: Sun keyboard */
|
||||
cdev_tape_init(NXT,xt), /* 30: Xylogics tape */
|
||||
cdev_fb_init(NCGTWO,cg2), /* 31: cgtwo */
|
||||
cdev_notdef(), /* 32: /dev/gpone */
|
||||
cdev_disk_init(NCCD,ccd), /* 33: concatenated disk driver */
|
||||
cdev_notdef(), /* 34: floating point accelerator */
|
||||
cdev_notdef(), /* 35 */
|
||||
cdev_bpftun_init(NBPFILTER,bpf),/* 36: Berkeley packet filter */
|
||||
cdev_notdef(), /* 37 */
|
||||
cdev_notdef(), /* 38 */
|
||||
cdev_fb_init(NCGFOUR,cg4), /* 39: cgfour */
|
||||
cdev_notdef(), /* 40: (sni) */
|
||||
cdev_notdef(), /* 41: (sun dump) */
|
||||
cdev_disk_init(NXD,xd), /* 42: SMD disk on Xylogics 7053 */
|
||||
cdev_notdef(), /* 43: (sun hrc) */
|
||||
cdev_notdef(), /* 44: (mcp) */
|
||||
cdev_notdef(), /* 45: (sun ifd) */
|
||||
cdev_notdef(), /* 46: (dcp) */
|
||||
cdev_notdef(), /* 47: (dna) */
|
||||
cdev_notdef(), /* 48: (tbi) */
|
||||
cdev_notdef(), /* 49: (chat) */
|
||||
cdev_notdef(), /* 50: (chut) */
|
||||
cdev_notdef(), /* 51: (chut) */
|
||||
cdev_notdef(), /* 52: RAM disk - for install tape */
|
||||
cdev_notdef(), /* 53: (hd - N/A) */
|
||||
cdev_notdef(), /* 54: (fd - N/A) */
|
||||
cdev_notdef(), /* 55: cgthree */
|
||||
cdev_notdef(), /* 56: (pp) */
|
||||
cdev_notdef(), /* 57: (vd) Loadable Module control */
|
||||
cdev_disk_init(NCD,cd), /* 58: SCSI CD-ROM */
|
||||
cdev_notdef(), /* 59: (vd) Loadable Module stub */
|
||||
cdev_notdef(), /* 60: || || || || */
|
||||
cdev_notdef(), /* 61: || || || || */
|
||||
cdev_notdef(), /* 62: (taac) */
|
||||
cdev_notdef(), /* 63: (tcp/tli) */
|
||||
cdev_notdef(), /* 64: cgeight */
|
||||
cdev_notdef(), /* 65: old IPI */
|
||||
cdev_notdef(), /* 66: (mcp) parallel printer */
|
||||
cdev_notdef(), /* 67: cgsix */
|
||||
cdev_notdef(), /* 68: cgnine */
|
||||
cdev_notdef(), /* 69: /dev/audio */
|
||||
cdev_notdef(), /* 70: open prom */
|
||||
cdev_notdef(), /* 71: (sg?) */
|
||||
};
|
||||
int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
|
||||
|
||||
int mem_no = 3; /* major device number of memory special file */
|
||||
|
||||
/*
|
||||
* Swapdev is a fake device implemented
|
||||
* in sw.c used only internally to get to swstrategy.
|
||||
* It cannot be provided to the users, because the
|
||||
* swstrategy routine munches the b_dev and b_blkno entries
|
||||
* before calling the appropriate driver. This would horribly
|
||||
* confuse, e.g. the hashing routines. Instead, /dev/drum is
|
||||
* provided as a character (raw) device.
|
||||
*/
|
||||
dev_t swapdev = makedev(4, 0);
|
||||
|
||||
/*
|
||||
* Returns true if dev is /dev/mem or /dev/kmem.
|
||||
*/
|
||||
int
|
||||
iskmemdev(dev)
|
||||
dev_t dev;
|
||||
{
|
||||
|
||||
return (major(dev) == mem_no && minor(dev) < 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if dev is /dev/zero.
|
||||
*/
|
||||
int
|
||||
iszerodev(dev)
|
||||
dev_t dev;
|
||||
{
|
||||
|
||||
return (major(dev) == mem_no && minor(dev) == 12);
|
||||
}
|
||||
|
||||
static int chrtoblktbl[] = {
|
||||
/* XXXX This needs to be dynamic for LKMs. */
|
||||
/*VCHR*/ /*VBLK*/
|
||||
/* 0 */ NODEV,
|
||||
/* 1 */ NODEV,
|
||||
/* 2 */ NODEV,
|
||||
/* 3 */ NODEV,
|
||||
/* 4 */ NODEV,
|
||||
/* 5 */ 1,
|
||||
/* 6 */ NODEV,
|
||||
/* 7 */ NODEV,
|
||||
/* 8 */ NODEV,
|
||||
/* 9 */ 3,
|
||||
/* 10 */ NODEV,
|
||||
/* 11 */ NODEV,
|
||||
/* 12 */ NODEV,
|
||||
/* 13 */ NODEV,
|
||||
/* 14 */ NODEV,
|
||||
/* 15 */ NODEV,
|
||||
/* 16 */ NODEV,
|
||||
/* 17 */ 7,
|
||||
/* 18 */ 11,
|
||||
/* 19 */ 5,
|
||||
/* 20 */ NODEV,
|
||||
/* 21 */ NODEV,
|
||||
/* 22 */ NODEV,
|
||||
/* 23 */ NODEV,
|
||||
/* 24 */ NODEV,
|
||||
/* 25 */ NODEV,
|
||||
/* 26 */ NODEV,
|
||||
/* 27 */ NODEV,
|
||||
/* 28 */ NODEV,
|
||||
/* 29 */ NODEV,
|
||||
/* 30 */ 8,
|
||||
/* 31 */ NODEV,
|
||||
/* 32 */ NODEV,
|
||||
/* 33 */ 9,
|
||||
/* 34 */ NODEV,
|
||||
/* 35 */ NODEV,
|
||||
/* 36 */ NODEV,
|
||||
/* 37 */ NODEV,
|
||||
/* 38 */ NODEV,
|
||||
/* 39 */ NODEV,
|
||||
/* 40 */ NODEV,
|
||||
/* 41 */ NODEV,
|
||||
/* 42 */ NODEV,
|
||||
/* 43 */ 10,
|
||||
/* 44 */ NODEV,
|
||||
/* 45 */ NODEV,
|
||||
/* 46 */ NODEV,
|
||||
/* 47 */ NODEV,
|
||||
/* 48 */ NODEV,
|
||||
/* 49 */ NODEV,
|
||||
/* 50 */ NODEV,
|
||||
/* 51 */ NODEV,
|
||||
/* 52 */ 13,
|
||||
/* 53 */ NODEV,
|
||||
/* 54 */ NODEV,
|
||||
/* 55 */ NODEV,
|
||||
/* 56 */ NODEV,
|
||||
/* 57 */ NODEV,
|
||||
/* 58 */ 18,
|
||||
/* 59 */ NODEV,
|
||||
/* 60 */ NODEV,
|
||||
/* 61 */ NODEV,
|
||||
/* 62 */ NODEV,
|
||||
/* 63 */ NODEV,
|
||||
/* 64 */ NODEV,
|
||||
/* 65 */ NODEV,
|
||||
/* 66 */ NODEV,
|
||||
/* 67 */ NODEV,
|
||||
/* 68 */ NODEV,
|
||||
/* 69 */ NODEV,
|
||||
/* 70 */ NODEV,
|
||||
/* 71 */ NODEV,
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert a character device number to a block device number.
|
||||
*/
|
||||
int
|
||||
chrtoblk(dev)
|
||||
dev_t dev;
|
||||
{
|
||||
int blkmaj;
|
||||
|
||||
if (major(dev) >= nchrdev)
|
||||
return (NODEV);
|
||||
blkmaj = chrtoblktbl[major(dev)];
|
||||
if (blkmaj == NODEV)
|
||||
return (NODEV);
|
||||
return (makedev(blkmaj, minor(dev)));
|
||||
}
|
||||
|
@ -1,475 +0,0 @@
|
||||
/* $NetBSD: disksubr.c,v 1.1.1.1 1997/01/14 20:57:08 gwr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Gordon W. Ross
|
||||
* Copyright (c) 1994 Theo de Raadt
|
||||
* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 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
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Credits:
|
||||
* This file was based mostly on the i386/disksubr.c file:
|
||||
* @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
|
||||
* The functions: disklabel_sun_to_bsd, disklabel_bsd_to_sun
|
||||
* were originally taken from arch/sparc/scsi/sun_disklabel.c
|
||||
* (which was written by Theo de Raadt) and then substantially
|
||||
* rewritten by Gordon W. Ross.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/dkbad.h>
|
||||
|
||||
#include <machine/sun_disklabel.h>
|
||||
|
||||
/* XXX encoding of disk minor numbers, should be elsewhere... */
|
||||
#define dkpart(dev) (minor(dev) & 7)
|
||||
|
||||
#define b_cylin b_resid
|
||||
|
||||
#if LABELSECTOR != 0
|
||||
#error "Default value of LABELSECTOR no longer zero?"
|
||||
#endif
|
||||
|
||||
static char * disklabel_sun_to_bsd(char *, struct disklabel *);
|
||||
static int disklabel_bsd_to_sun(struct disklabel *, char *);
|
||||
|
||||
/*
|
||||
* Attempt to read a disk label from a device
|
||||
* using the indicated stategy routine.
|
||||
* The label must be partly set up before this:
|
||||
* secpercyl, secsize and anything required for a block i/o read
|
||||
* operation in the driver's strategy/start routines
|
||||
* must be filled in before calling us.
|
||||
*
|
||||
* Return buffer for use in signalling errors if requested.
|
||||
*
|
||||
* Returns null on success and an error string on failure.
|
||||
*/
|
||||
char *
|
||||
readdisklabel(dev, strat, lp, clp)
|
||||
dev_t dev;
|
||||
void (*strat) __P((struct buf *));
|
||||
struct disklabel *lp;
|
||||
struct cpu_disklabel *clp;
|
||||
{
|
||||
struct buf *bp;
|
||||
struct disklabel *dlp;
|
||||
struct sun_disklabel *slp;
|
||||
int error;
|
||||
|
||||
/* minimal requirements for archtypal disk label */
|
||||
if (lp->d_secperunit == 0)
|
||||
lp->d_secperunit = 0x1fffffff;
|
||||
lp->d_npartitions = 1;
|
||||
if (lp->d_partitions[0].p_size == 0)
|
||||
lp->d_partitions[0].p_size = 0x1fffffff;
|
||||
lp->d_partitions[0].p_offset = 0;
|
||||
|
||||
/* obtain buffer to probe drive with */
|
||||
bp = geteblk((int)lp->d_secsize);
|
||||
|
||||
/* next, dig out disk label */
|
||||
bp->b_dev = dev;
|
||||
bp->b_blkno = LABELSECTOR;
|
||||
bp->b_cylin = 0;
|
||||
bp->b_bcount = lp->d_secsize;
|
||||
bp->b_flags = B_BUSY | B_READ;
|
||||
(*strat)(bp);
|
||||
|
||||
/* if successful, locate disk label within block and validate */
|
||||
error = biowait(bp);
|
||||
if (!error) {
|
||||
/* Save the whole block in case it has info we need. */
|
||||
bcopy(bp->b_un.b_addr, clp->cd_block, sizeof(clp->cd_block));
|
||||
}
|
||||
bp->b_flags = B_INVAL | B_AGE | B_READ;
|
||||
brelse(bp);
|
||||
if (error)
|
||||
return("disk label read error");
|
||||
|
||||
/* Check for a Sun disk label (for PROM compatibility). */
|
||||
slp = (struct sun_disklabel *) clp->cd_block;
|
||||
if (slp->sl_magic == SUN_DKMAGIC) {
|
||||
return(disklabel_sun_to_bsd(clp->cd_block, lp));
|
||||
}
|
||||
|
||||
/* Check for a NetBSD disk label (PROM can not boot it). */
|
||||
dlp = (struct disklabel *) (clp->cd_block + LABELOFFSET);
|
||||
if (dlp->d_magic == DISKMAGIC) {
|
||||
if (dkcksum(dlp))
|
||||
return("NetBSD disk label corrupted");
|
||||
*lp = *dlp; /* struct assignment */
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
bzero(clp->cd_block, sizeof(clp->cd_block));
|
||||
return("no disk label");
|
||||
}
|
||||
|
||||
/*
|
||||
* Check new disk label for sensibility
|
||||
* before setting it.
|
||||
*/
|
||||
int
|
||||
setdisklabel(olp, nlp, openmask, clp)
|
||||
struct disklabel *olp, *nlp;
|
||||
u_long openmask;
|
||||
struct cpu_disklabel *clp;
|
||||
{
|
||||
struct partition *opp, *npp;
|
||||
int i;
|
||||
|
||||
/* sanity clause */
|
||||
if ((nlp->d_secpercyl == 0) || (nlp->d_secsize == 0) ||
|
||||
(nlp->d_secsize % DEV_BSIZE) != 0)
|
||||
return(EINVAL);
|
||||
|
||||
/* special case to allow disklabel to be invalidated */
|
||||
if (nlp->d_magic == 0xffffffff) {
|
||||
*olp = *nlp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (nlp->d_magic != DISKMAGIC ||
|
||||
nlp->d_magic2 != DISKMAGIC ||
|
||||
dkcksum(nlp) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
while (openmask != 0) {
|
||||
i = ffs(openmask) - 1;
|
||||
openmask &= ~(1 << i);
|
||||
if (nlp->d_npartitions <= i)
|
||||
return (EBUSY);
|
||||
opp = &olp->d_partitions[i];
|
||||
npp = &nlp->d_partitions[i];
|
||||
if (npp->p_offset != opp->p_offset ||
|
||||
npp->p_size < opp->p_size)
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
/* We did not modify the new label, so the checksum is OK. */
|
||||
*olp = *nlp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write disk label back to device after modification.
|
||||
* Current label is already in clp->cd_block[]
|
||||
*/
|
||||
int
|
||||
writedisklabel(dev, strat, lp, clp)
|
||||
dev_t dev;
|
||||
void (*strat) __P((struct buf *));
|
||||
struct disklabel *lp;
|
||||
struct cpu_disklabel *clp;
|
||||
{
|
||||
struct buf *bp;
|
||||
int error;
|
||||
|
||||
error = disklabel_bsd_to_sun(lp, clp->cd_block);
|
||||
if (error)
|
||||
return(error);
|
||||
|
||||
#if 0 /* XXX - Allow writing NetBSD disk labels? */
|
||||
{
|
||||
struct disklabel *dlp;
|
||||
dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET);
|
||||
*dlp = *lp; /* struct assignment */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get a buffer and copy the new label into it. */
|
||||
bp = geteblk((int)lp->d_secsize);
|
||||
bcopy(clp->cd_block, bp->b_un.b_addr, sizeof(clp->cd_block));
|
||||
|
||||
/* Write out the updated label. */
|
||||
bp->b_dev = dev;
|
||||
bp->b_blkno = LABELSECTOR;
|
||||
bp->b_cylin = 0;
|
||||
bp->b_bcount = lp->d_secsize;
|
||||
bp->b_flags = B_WRITE;
|
||||
(*strat)(bp);
|
||||
error = biowait(bp);
|
||||
brelse(bp);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the size of the transfer, and make sure it is
|
||||
* within the boundaries of the partition. Adjust transfer
|
||||
* if needed, and signal errors or early completion.
|
||||
*/
|
||||
int
|
||||
bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
|
||||
{
|
||||
struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
|
||||
int maxsz = p->p_size;
|
||||
int sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
|
||||
|
||||
/* overwriting disk label ? */
|
||||
/* XXX should also protect bootstrap in first 8K */
|
||||
/* XXX PR#2598: labelsect is always sector zero. */
|
||||
if (((bp->b_blkno + p->p_offset) <= LABELSECTOR) &&
|
||||
((bp->b_flags & B_READ) == 0) && (wlabel == 0))
|
||||
{
|
||||
bp->b_error = EROFS;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* beyond partition? */
|
||||
if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
|
||||
/* if exactly at end of disk, return an EOF */
|
||||
if (bp->b_blkno == maxsz) {
|
||||
bp->b_resid = bp->b_bcount;
|
||||
return(0);
|
||||
}
|
||||
/* or truncate if part of it fits */
|
||||
sz = maxsz - bp->b_blkno;
|
||||
if (sz <= 0) {
|
||||
bp->b_error = EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
bp->b_bcount = sz << DEV_BSHIFT;
|
||||
}
|
||||
|
||||
/* calculate cylinder for disksort to order transfers with */
|
||||
bp->b_cylin = (bp->b_blkno + p->p_offset) / lp->d_secpercyl;
|
||||
return(1);
|
||||
|
||||
bad:
|
||||
bp->b_flags |= B_ERROR;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function appears to be called by each disk driver.
|
||||
* Aparently this is to give this MD code a chance to do
|
||||
* additional "device registration" types of work. (?)
|
||||
* For example, the sparc port uses this to record the
|
||||
* device node for the PROM-specified boot device.
|
||||
*/
|
||||
void
|
||||
dk_establish(dk, dev)
|
||||
struct disk *dk;
|
||||
struct device *dev;
|
||||
{
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* The rest of this was taken from arch/sparc/scsi/sun_disklabel.c
|
||||
* and then substantially rewritten by Gordon W. Ross
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
/* What partition types to assume for Sun disklabels: */
|
||||
static u_char
|
||||
sun_fstypes[8] = {
|
||||
FS_BSDFFS, /* a */
|
||||
FS_SWAP, /* b */
|
||||
FS_OTHER, /* c - whole disk */
|
||||
FS_BSDFFS, /* d */
|
||||
FS_BSDFFS, /* e */
|
||||
FS_BSDFFS, /* f */
|
||||
FS_BSDFFS, /* g */
|
||||
FS_BSDFFS, /* h */
|
||||
};
|
||||
|
||||
/*
|
||||
* Given a SunOS disk label, set lp to a BSD disk label.
|
||||
* Returns NULL on success, else an error string.
|
||||
*
|
||||
* The BSD label is cleared out before this is called.
|
||||
*/
|
||||
static char *
|
||||
disklabel_sun_to_bsd(cp, lp)
|
||||
char *cp;
|
||||
struct disklabel *lp;
|
||||
{
|
||||
struct sun_disklabel *sl;
|
||||
struct partition *npp;
|
||||
struct sun_dkpart *spp;
|
||||
int i, secpercyl;
|
||||
u_short cksum, *sp1, *sp2;
|
||||
|
||||
sl = (struct sun_disklabel *)cp;
|
||||
|
||||
/* Verify the XOR check. */
|
||||
sp1 = (u_short *)sl;
|
||||
sp2 = (u_short *)(sl + 1);
|
||||
cksum = 0;
|
||||
while (sp1 < sp2)
|
||||
cksum ^= *sp1++;
|
||||
if (cksum != 0)
|
||||
return("SunOS disk label, bad checksum");
|
||||
|
||||
/* Format conversion. */
|
||||
lp->d_magic = DISKMAGIC;
|
||||
lp->d_magic2 = DISKMAGIC;
|
||||
memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));
|
||||
|
||||
lp->d_secsize = 512;
|
||||
lp->d_nsectors = sl->sl_nsectors;
|
||||
lp->d_ntracks = sl->sl_ntracks;
|
||||
lp->d_ncylinders = sl->sl_ncylinders;
|
||||
|
||||
secpercyl = sl->sl_nsectors * sl->sl_ntracks;
|
||||
lp->d_secpercyl = secpercyl;
|
||||
lp->d_secperunit = secpercyl * sl->sl_ncylinders;
|
||||
|
||||
lp->d_sparespercyl = sl->sl_sparespercyl;
|
||||
lp->d_acylinders = sl->sl_acylinders;
|
||||
lp->d_rpm = sl->sl_rpm;
|
||||
lp->d_interleave = sl->sl_interleave;
|
||||
|
||||
lp->d_npartitions = 8;
|
||||
/* These are as defined in <ufs/ffs/fs.h> */
|
||||
lp->d_bbsize = 8192; /* XXX */
|
||||
lp->d_sbsize = 8192; /* XXX */
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
spp = &sl->sl_part[i];
|
||||
npp = &lp->d_partitions[i];
|
||||
npp->p_offset = spp->sdkp_cyloffset * secpercyl;
|
||||
npp->p_size = spp->sdkp_nsectors;
|
||||
if (npp->p_size == 0)
|
||||
npp->p_fstype = FS_UNUSED;
|
||||
else {
|
||||
/* Partition has non-zero size. Set type, etc. */
|
||||
npp->p_fstype = sun_fstypes[i];
|
||||
/*
|
||||
* The sun label does not store the FFS fields,
|
||||
* so just set them with default values here.
|
||||
* XXX: This keeps newfs from trying to rewrite
|
||||
* XXX: the disk label in the most common case.
|
||||
* XXX: (Should remove that code from newfs...)
|
||||
*/
|
||||
if (npp->p_fstype == FS_BSDFFS) {
|
||||
npp->p_fsize = 1024;
|
||||
npp->p_frag = 8;
|
||||
npp->p_cpg = 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lp->d_checksum = 0;
|
||||
lp->d_checksum = dkcksum(lp);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a BSD disk label, update the Sun disklabel
|
||||
* pointed to by cp with the new info. Note that the
|
||||
* Sun disklabel may have other info we need to keep.
|
||||
* Returns zero or error code.
|
||||
*/
|
||||
static int
|
||||
disklabel_bsd_to_sun(lp, cp)
|
||||
struct disklabel *lp;
|
||||
char *cp;
|
||||
{
|
||||
struct sun_disklabel *sl;
|
||||
struct partition *npp;
|
||||
struct sun_dkpart *spp;
|
||||
int i, secpercyl;
|
||||
u_short cksum, *sp1, *sp2;
|
||||
|
||||
if (lp->d_secsize != 512)
|
||||
return (EINVAL);
|
||||
|
||||
sl = (struct sun_disklabel *)cp;
|
||||
|
||||
/* Format conversion. */
|
||||
memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname));
|
||||
sl->sl_rpm = lp->d_rpm;
|
||||
sl->sl_pcyl = lp->d_ncylinders + lp->d_acylinders; /* XXX */
|
||||
sl->sl_sparespercyl = lp->d_sparespercyl;
|
||||
sl->sl_interleave = lp->d_interleave;
|
||||
sl->sl_ncylinders = lp->d_ncylinders;
|
||||
sl->sl_acylinders = lp->d_acylinders;
|
||||
sl->sl_ntracks = lp->d_ntracks;
|
||||
sl->sl_nsectors = lp->d_nsectors;
|
||||
|
||||
secpercyl = sl->sl_nsectors * sl->sl_ntracks;
|
||||
for (i = 0; i < 8; i++) {
|
||||
spp = &sl->sl_part[i];
|
||||
npp = &lp->d_partitions[i];
|
||||
|
||||
if (npp->p_offset % secpercyl)
|
||||
return (EINVAL);
|
||||
spp->sdkp_cyloffset = npp->p_offset / secpercyl;
|
||||
spp->sdkp_nsectors = npp->p_size;
|
||||
}
|
||||
sl->sl_magic = SUN_DKMAGIC;
|
||||
|
||||
/* Correct the XOR check. */
|
||||
sp1 = (u_short *)sl;
|
||||
sp2 = (u_short *)(sl + 1);
|
||||
sl->sl_cksum = cksum = 0;
|
||||
while (sp1 < sp2)
|
||||
cksum ^= *sp1++;
|
||||
sl->sl_cksum = cksum;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Search the bad sector table looking for the specified sector.
|
||||
* Return index if found.
|
||||
* Return -1 if not found.
|
||||
*/
|
||||
int
|
||||
isbad(bt, cyl, trk, sec)
|
||||
register struct dkbad *bt;
|
||||
{
|
||||
register int i;
|
||||
register long blk, bblk;
|
||||
|
||||
blk = ((long)cyl << 16) + (trk << 8) + sec;
|
||||
for (i = 0; i < 126; i++) {
|
||||
bblk = ((long)bt->bt_bad[i].bt_cyl << 16) +
|
||||
bt->bt_bad[i].bt_trksec;
|
||||
if (blk == bblk)
|
||||
return (i);
|
||||
if (blk < bblk || bblk < 0)
|
||||
break;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
@ -1,303 +0,0 @@
|
||||
/* $NetBSD: isr.c,v 1.1.1.1 1997/01/14 20:57:09 gwr Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Adam Glass and Gordon W. Ross.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 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 NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This handles multiple attach of autovectored interrupts,
|
||||
* and the handy software interrupt request register.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/vmmeter.h>
|
||||
|
||||
#include <net/netisr.h>
|
||||
|
||||
#include <machine/autoconf.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/mon.h>
|
||||
#include <machine/obio.h>
|
||||
|
||||
#include "machdep.h"
|
||||
#include "vector.h"
|
||||
|
||||
extern int intrcnt[]; /* statistics */
|
||||
|
||||
#define NUM_LEVELS 8
|
||||
|
||||
struct isr {
|
||||
struct isr *isr_next;
|
||||
isr_func_t isr_intr;
|
||||
void *isr_arg;
|
||||
int isr_ipl;
|
||||
};
|
||||
|
||||
void set_vector_entry __P((int, void *));
|
||||
void * get_vector_entry __P((int));
|
||||
|
||||
/*
|
||||
* These are called from locore. The "struct clockframe" arg
|
||||
* is really just the normal H/W interrupt frame format.
|
||||
* (kern_clock really wants it to be named that...)
|
||||
*/
|
||||
void isr_autovec __P((struct clockframe));
|
||||
void isr_vectored __P((struct clockframe));
|
||||
|
||||
|
||||
void
|
||||
isr_add_custom(level, handler)
|
||||
int level;
|
||||
void *handler;
|
||||
{
|
||||
set_vector_entry(AUTOVEC_BASE + level, handler);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* netisr junk...
|
||||
* XXX - This really belongs in some common file,
|
||||
* i.e. src/sys/net/netisr.c
|
||||
* Also, should use an array of chars instead of
|
||||
* a bitmask to avoid atomicity locking issues.
|
||||
*/
|
||||
|
||||
#include "ether.h" /* for NETHER */
|
||||
#include "ppp.h"
|
||||
|
||||
/*
|
||||
* Declarations for the netisr functions...
|
||||
* They are in the header files, but that's not
|
||||
* really a good reason to drag all those in.
|
||||
*/
|
||||
void arpintr __P((void));
|
||||
void ipintr __P((void));
|
||||
void nsintr __P((void));
|
||||
void clnlintr __P((void));
|
||||
void ccittintr __P((void));
|
||||
void pppintr __P((void));
|
||||
|
||||
void netintr()
|
||||
{
|
||||
int n, s;
|
||||
|
||||
s = splhigh();
|
||||
n = netisr;
|
||||
netisr = 0;
|
||||
splx(s);
|
||||
|
||||
#if NETHER > 0
|
||||
if (n & (1 << NETISR_ARP))
|
||||
arpintr();
|
||||
#endif
|
||||
#ifdef INET
|
||||
if (n & (1 << NETISR_IP))
|
||||
ipintr();
|
||||
#endif
|
||||
#ifdef NS
|
||||
if (n & (1 << NETISR_NS))
|
||||
nsintr();
|
||||
#endif
|
||||
#ifdef ISO
|
||||
if (n & (1 << NETISR_ISO))
|
||||
clnlintr();
|
||||
#endif
|
||||
#ifdef CCITT
|
||||
if (n & (1 << NETISR_CCITT)) {
|
||||
ccittintr();
|
||||
}
|
||||
#endif
|
||||
#if NPPP > 0
|
||||
if (n & (1 << NETISR_PPP)) {
|
||||
pppintr();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static struct isr *isr_autovec_list[NUM_LEVELS];
|
||||
|
||||
/*
|
||||
* This is called by the assembly routines
|
||||
* for handling auto-vectored interupts.
|
||||
*/
|
||||
void isr_autovec(cf)
|
||||
struct clockframe cf;
|
||||
{
|
||||
struct isr *isr;
|
||||
register int n, ipl, vec;
|
||||
|
||||
vec = (cf.cf_vo & 0xFFF) >> 2;
|
||||
if ((vec < AUTOVEC_BASE) || (vec >= (AUTOVEC_BASE+8)))
|
||||
panic("isr_autovec: bad vec");
|
||||
ipl = vec - 0x18;
|
||||
|
||||
n = intrcnt[ipl];
|
||||
intrcnt[ipl] = n+1;
|
||||
cnt.v_intr++;
|
||||
|
||||
isr = isr_autovec_list[ipl];
|
||||
if (isr == NULL) {
|
||||
if (n == 0)
|
||||
printf("isr_autovec: ipl %d unexpected\n", ipl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Give all the handlers a chance. */
|
||||
n = 0;
|
||||
while (isr) {
|
||||
n |= isr->isr_intr(isr->isr_arg);
|
||||
isr = isr->isr_next;
|
||||
}
|
||||
if (!n)
|
||||
printf("isr_autovec: ipl %d not claimed\n", ipl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Establish an interrupt handler.
|
||||
* Called by driver attach functions.
|
||||
*/
|
||||
void isr_add_autovect(handler, arg, level)
|
||||
isr_func_t handler;
|
||||
void *arg;
|
||||
int level;
|
||||
{
|
||||
struct isr *new_isr;
|
||||
|
||||
if ((level < 0) || (level >= NUM_LEVELS))
|
||||
panic("isr_add: bad level=%d", level);
|
||||
new_isr = (struct isr *)
|
||||
malloc(sizeof(struct isr), M_DEVBUF, M_NOWAIT);
|
||||
if (!new_isr)
|
||||
panic("isr_add: malloc failed");
|
||||
|
||||
new_isr->isr_intr = handler;
|
||||
new_isr->isr_arg = arg;
|
||||
new_isr->isr_ipl = level;
|
||||
new_isr->isr_next = isr_autovec_list[level];
|
||||
isr_autovec_list[level] = new_isr;
|
||||
}
|
||||
|
||||
struct vector_handler {
|
||||
isr_func_t func;
|
||||
void *arg;
|
||||
};
|
||||
static struct vector_handler isr_vector_handlers[192];
|
||||
|
||||
/*
|
||||
* This is called by the assembly glue
|
||||
* for handling vectored interupts.
|
||||
*/
|
||||
void
|
||||
isr_vectored(cf)
|
||||
struct clockframe cf;
|
||||
{
|
||||
struct vector_handler *vh;
|
||||
register int ipl, vec;
|
||||
|
||||
vec = (cf.cf_vo & 0xFFF) >> 2;
|
||||
ipl = getsr();
|
||||
ipl = (ipl >> 8) & 7;
|
||||
|
||||
intrcnt[ipl]++;
|
||||
cnt.v_intr++;
|
||||
|
||||
if (vec < 64 || vec >= 256) {
|
||||
printf("isr_vectored: vector=0x%x (invalid)\n", vec);
|
||||
return;
|
||||
}
|
||||
vh = &isr_vector_handlers[vec - 64];
|
||||
if (vh->func == NULL) {
|
||||
printf("isr_vectored: vector=0x%x (nul func)\n", vec);
|
||||
set_vector_entry(vec, (void *)badtrap);
|
||||
return;
|
||||
}
|
||||
|
||||
/* OK, call the isr function. */
|
||||
if (vh->func(vh->arg) == 0)
|
||||
printf("isr_vectored: vector=0x%x (not claimed)\n", vec);
|
||||
}
|
||||
|
||||
/*
|
||||
* Establish an interrupt handler.
|
||||
* Called by driver attach functions.
|
||||
*/
|
||||
extern void _isr_vectored __P((void));
|
||||
void
|
||||
isr_add_vectored(func, arg, level, vec)
|
||||
isr_func_t func;
|
||||
void *arg;
|
||||
int level, vec;
|
||||
{
|
||||
struct vector_handler *vh;
|
||||
|
||||
if (vec < 64 || vec >= 256) {
|
||||
printf("isr_add_vectored: vect=0x%x (invalid)\n", vec);
|
||||
return;
|
||||
}
|
||||
vh = &isr_vector_handlers[vec - 64];
|
||||
if (vh->func) {
|
||||
printf("isr_add_vectored: vect=0x%x (in use)\n", vec);
|
||||
return;
|
||||
}
|
||||
vh->func = func;
|
||||
vh->arg = arg;
|
||||
set_vector_entry(vec, (void *)_isr_vectored);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - could just kill these...
|
||||
*/
|
||||
void
|
||||
set_vector_entry(entry, handler)
|
||||
int entry;
|
||||
void *handler;
|
||||
{
|
||||
if ((entry <0) || (entry >= NVECTORS))
|
||||
panic("set_vector_entry: setting vector too high or low\n");
|
||||
vector_table[entry] = handler;
|
||||
}
|
||||
|
||||
void *
|
||||
get_vector_entry(entry)
|
||||
int entry;
|
||||
{
|
||||
if ((entry <0) || (entry >= NVECTORS))
|
||||
panic("get_vector_entry: setting vector too high or low\n");
|
||||
return ((void *) vector_table[entry]);
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/* $NetBSD: kgdb_proto.h,v 1.1.1.1 1997/01/14 20:57:09 gwr Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* 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, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 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
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)kgdb_proto.h 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* Message types.
|
||||
*/
|
||||
#define KGDB_MEM_R 0x01
|
||||
#define KGDB_MEM_W 0x02
|
||||
#define KGDB_REG_R 0x03
|
||||
#define KGDB_REG_W 0x04
|
||||
#define KGDB_CONT 0x05
|
||||
#define KGDB_STEP 0x06
|
||||
#define KGDB_KILL 0x07
|
||||
#define KGDB_SIGNAL 0x08
|
||||
#define KGDB_EXEC 0x09
|
||||
#define KGDB_HALT 0x0a
|
||||
#define KGDB_BOOT 0x0b
|
||||
|
||||
#define KGDB_CMD(x) ((x) & 0x0f)
|
||||
|
||||
/*
|
||||
* Message flags.
|
||||
*/
|
||||
#define KGDB_ACK 0x80
|
||||
#define KGDB_DELTA 0x40
|
||||
#define KGDB_MORE 0x20
|
||||
#define KGDB_SEQ 0x10
|
@ -1,621 +0,0 @@
|
||||
/* $NetBSD: kgdb_stub.c,v 1.1.1.1 1997/01/14 20:57:09 gwr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* 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, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 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
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* "Stub" to allow remote cpu to debug over a serial line using gdb.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
||||
#include <machine/control.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/trap.h>
|
||||
|
||||
#include <sun3/sun3/kgdb_proto.h>
|
||||
#include <machine/db_machdep.h>
|
||||
#include <machine/remote-sl.h>
|
||||
|
||||
#ifndef KGDBDEV
|
||||
#define KGDBDEV -1
|
||||
#endif
|
||||
#ifndef KGDBRATE
|
||||
#define KGDBRATE 19200
|
||||
#endif
|
||||
|
||||
int kgdb_dev = KGDBDEV; /* remote debugging device (-1 if none) */
|
||||
int kgdb_rate = KGDBRATE; /* remote debugging baud rate */
|
||||
int kgdb_active = 0; /* remote debugging active if != 0 */
|
||||
int kgdb_debug_init = 0; /* != 0 waits for remote at system init */
|
||||
int kgdb_debug_panic = 0; /* != 0 waits for remote on panic */
|
||||
|
||||
static void kgdb_send __P((u_int, u_char *, int));
|
||||
static int kgdb_recv __P((u_char *, int *));
|
||||
static int computeSignal __P((int));
|
||||
int kgdb_trap __P((int, struct trapframe *));
|
||||
int kgdb_acc __P((caddr_t, int));
|
||||
|
||||
static int (*kgdb_getc) __P((void *));
|
||||
static void (*kgdb_putc) __P((void *, int));
|
||||
static void *kgdb_ioarg;
|
||||
|
||||
#define GETC() ((*kgdb_getc)(kgdb_ioarg))
|
||||
#define PUTC(c) ((*kgdb_putc)(kgdb_ioarg, c))
|
||||
#define PUTESC(c) do { \
|
||||
if (c == FRAME_END) { \
|
||||
PUTC(FRAME_ESCAPE); \
|
||||
c = TRANS_FRAME_END; \
|
||||
} else if (c == FRAME_ESCAPE) { \
|
||||
PUTC(FRAME_ESCAPE); \
|
||||
c = TRANS_FRAME_ESCAPE; \
|
||||
} else if (c == FRAME_START) { \
|
||||
PUTC(FRAME_ESCAPE); \
|
||||
c = TRANS_FRAME_START; \
|
||||
} \
|
||||
PUTC(c); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* This is called by the approprite tty driver.
|
||||
* In our case, by dev/zs_kgdb.c:zs_kgdb_init()
|
||||
*/
|
||||
void
|
||||
kgdb_attach(getfn, putfn, ioarg)
|
||||
int (*getfn) __P((void *));
|
||||
void (*putfn) __P((void *, int));
|
||||
void *ioarg;
|
||||
{
|
||||
|
||||
kgdb_getc = getfn;
|
||||
kgdb_putc = putfn;
|
||||
kgdb_ioarg = ioarg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a message. The host gets one chance to read it.
|
||||
*/
|
||||
static void
|
||||
kgdb_send(type, bp, len)
|
||||
register u_int type;
|
||||
register u_char *bp;
|
||||
register int len;
|
||||
{
|
||||
register u_char csum;
|
||||
register u_char *ep = bp + len;
|
||||
|
||||
PUTC(FRAME_START);
|
||||
PUTESC(type);
|
||||
|
||||
csum = type;
|
||||
while (bp < ep) {
|
||||
type = *bp++;
|
||||
csum += type;
|
||||
PUTESC(type);
|
||||
}
|
||||
csum = -csum;
|
||||
PUTESC(csum);
|
||||
PUTC(FRAME_END);
|
||||
}
|
||||
|
||||
static int
|
||||
kgdb_recv(bp, lenp)
|
||||
u_char *bp;
|
||||
int *lenp;
|
||||
{
|
||||
register u_char c, csum;
|
||||
register int escape, len;
|
||||
register int type;
|
||||
|
||||
restart:
|
||||
csum = len = escape = 0;
|
||||
type = -1;
|
||||
while (1) {
|
||||
c = GETC();
|
||||
switch (c) {
|
||||
|
||||
case FRAME_ESCAPE:
|
||||
escape = 1;
|
||||
continue;
|
||||
|
||||
case TRANS_FRAME_ESCAPE:
|
||||
if (escape)
|
||||
c = FRAME_ESCAPE;
|
||||
break;
|
||||
|
||||
case TRANS_FRAME_END:
|
||||
if (escape)
|
||||
c = FRAME_END;
|
||||
break;
|
||||
|
||||
case TRANS_FRAME_START:
|
||||
if (escape)
|
||||
c = FRAME_START;
|
||||
break;
|
||||
|
||||
case FRAME_START:
|
||||
goto restart;
|
||||
|
||||
case FRAME_END:
|
||||
if (type < 0 || --len < 0) {
|
||||
csum = len = escape = 0;
|
||||
type = -1;
|
||||
continue;
|
||||
}
|
||||
if (csum != 0)
|
||||
return (0);
|
||||
*lenp = len;
|
||||
return (type);
|
||||
}
|
||||
csum += c;
|
||||
if (type < 0) {
|
||||
type = c;
|
||||
escape = 0;
|
||||
continue;
|
||||
}
|
||||
if (++len > SL_RPCSIZE) {
|
||||
while (GETC() != FRAME_END)
|
||||
continue;
|
||||
return (0);
|
||||
}
|
||||
*bp++ = c;
|
||||
escape = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a trap number into a unix compatible signal value.
|
||||
* (gdb only understands unix signal numbers).
|
||||
*/
|
||||
static int
|
||||
computeSignal(type)
|
||||
int type;
|
||||
{
|
||||
int sigval;
|
||||
|
||||
switch (type) {
|
||||
case T_BUSERR:
|
||||
sigval = SIGBUS;
|
||||
break;
|
||||
case T_ADDRERR:
|
||||
sigval = SIGBUS;
|
||||
break;
|
||||
case T_ILLINST:
|
||||
sigval = SIGILL;
|
||||
break;
|
||||
case T_ZERODIV:
|
||||
sigval = SIGFPE;
|
||||
break;
|
||||
case T_CHKINST:
|
||||
sigval = SIGFPE;
|
||||
break;
|
||||
case T_TRAPVINST:
|
||||
sigval = SIGFPE;
|
||||
break;
|
||||
case T_PRIVINST:
|
||||
sigval = SIGILL;
|
||||
break;
|
||||
case T_TRACE:
|
||||
sigval = SIGTRAP;
|
||||
break;
|
||||
case T_MMUFLT:
|
||||
sigval = SIGSEGV;
|
||||
break;
|
||||
case T_SSIR:
|
||||
sigval = SIGSEGV;
|
||||
break;
|
||||
case T_FMTERR:
|
||||
sigval = SIGILL;
|
||||
break;
|
||||
case T_FPERR:
|
||||
sigval = SIGFPE;
|
||||
break;
|
||||
case T_COPERR:
|
||||
sigval = SIGFPE;
|
||||
break;
|
||||
case T_ASTFLT:
|
||||
sigval = SIGINT;
|
||||
break;
|
||||
case T_TRAP15:
|
||||
sigval = SIGTRAP;
|
||||
break;
|
||||
default:
|
||||
sigval = SIGEMT;
|
||||
break;
|
||||
}
|
||||
return (sigval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Trap into kgdb to wait for debugger to connect,
|
||||
* noting on the console why nothing else is going on.
|
||||
*/
|
||||
void
|
||||
kgdb_connect(verbose)
|
||||
int verbose;
|
||||
{
|
||||
|
||||
if (kgdb_dev < 0 || kgdb_getc == NULL)
|
||||
return;
|
||||
fb_unblank();
|
||||
if (verbose)
|
||||
printf("kgdb waiting...");
|
||||
Debugger(); /* XXX: trap into kgdb */
|
||||
if (verbose)
|
||||
printf("connected.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Decide what to do on panic.
|
||||
* (This is called by panic, like Debugger())
|
||||
*/
|
||||
void
|
||||
kgdb_panic()
|
||||
{
|
||||
|
||||
if (kgdb_dev >= 0 && kgdb_getc != NULL &&
|
||||
kgdb_active == 0 && kgdb_debug_panic)
|
||||
{
|
||||
/* XXX: Just call Debugger() instead? */
|
||||
kgdb_connect(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Definitions exported from gdb.
|
||||
*/
|
||||
#define NUM_REGS 18
|
||||
#define REGISTER_BYTES (NUM_REGS * 4)
|
||||
#define REGISTER_BYTE(n) ((n) * 4)
|
||||
|
||||
#define GDB_SR 16
|
||||
#define GDB_PC 17
|
||||
|
||||
/*
|
||||
* This little routine exists simply so that bcopy() can be debugged.
|
||||
*/
|
||||
static void
|
||||
kgdb_copy(vsrc, vdst, len)
|
||||
void *vsrc, *vdst;
|
||||
register int len;
|
||||
{
|
||||
register char *src = vsrc;
|
||||
register char *dst = vdst;
|
||||
|
||||
while (--len >= 0)
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
/* ditto for bzero */
|
||||
static void
|
||||
kgdb_zero(vptr, len)
|
||||
void *vptr;
|
||||
register int len;
|
||||
{
|
||||
register char *ptr = vptr;
|
||||
|
||||
while (--len >= 0)
|
||||
*ptr++ = (char) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate the values stored in the kernel regs struct to the format
|
||||
* understood by gdb.
|
||||
*
|
||||
* There is a short pad word between SP (A7) and SR which keeps the
|
||||
* kernel stack long word aligned (note that this is in addition to
|
||||
* the stack adjust short that we treat as the upper half of a longword
|
||||
* SR). We must skip this when copying into and out of gdb.
|
||||
*/
|
||||
static void
|
||||
regs_to_gdb(tf, gdb_regs)
|
||||
struct trapframe *tf;
|
||||
u_long *gdb_regs;
|
||||
{
|
||||
kgdb_copy(tf->tf_regs, gdb_regs, 16*4);
|
||||
gdb_regs[GDB_SR] = tf->tf_sr;
|
||||
gdb_regs[GDB_PC] = tf->tf_pc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reverse the above.
|
||||
*/
|
||||
static void
|
||||
gdb_to_regs(tf, gdb_regs)
|
||||
struct trapframe *tf;
|
||||
u_long *gdb_regs;
|
||||
{
|
||||
kgdb_copy(gdb_regs, tf->tf_regs, 16*4);
|
||||
tf->tf_sr = gdb_regs[GDB_SR];
|
||||
tf->tf_pc = gdb_regs[GDB_PC];
|
||||
}
|
||||
|
||||
static u_long reg_cache[NUM_REGS];
|
||||
static u_char inbuffer[SL_RPCSIZE];
|
||||
static u_char outbuffer[SL_RPCSIZE];
|
||||
|
||||
/*
|
||||
* This function does all command procesing for interfacing to
|
||||
* a remote gdb.
|
||||
*/
|
||||
int
|
||||
kgdb_trap(type, tf)
|
||||
int type;
|
||||
struct trapframe *tf;
|
||||
{
|
||||
register u_long len;
|
||||
caddr_t addr;
|
||||
register u_char *cp;
|
||||
register u_char out, in;
|
||||
register int outlen;
|
||||
int inlen;
|
||||
u_long gdb_regs[NUM_REGS];
|
||||
|
||||
if (kgdb_dev < 0 || kgdb_getc == NULL) {
|
||||
/* not debugging */
|
||||
return (0);
|
||||
}
|
||||
if (kgdb_active == 0) {
|
||||
if (type != T_BREAKPOINT) {
|
||||
/* No debugger active -- let trap handle this. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the packet that woke us up isn't an exec packet,
|
||||
* ignore it since there is no active debugger. Also,
|
||||
* we check that it's not an ack to be sure that the
|
||||
* remote side doesn't send back a response after the
|
||||
* local gdb has exited. Otherwise, the local host
|
||||
* could trap into gdb if it's running a gdb kernel too.
|
||||
*/
|
||||
in = GETC();
|
||||
/*
|
||||
* If we came in asynchronously through the serial line,
|
||||
* the framing character is eaten by the receive interrupt,
|
||||
* but if we come in through a synchronous trap (i.e., via
|
||||
* kgdb_connect()), we will see the extra character.
|
||||
*/
|
||||
if (in == FRAME_START)
|
||||
in = GETC();
|
||||
|
||||
/*
|
||||
* Check that this is a debugger exec message. If so,
|
||||
* slurp up the entire message then ack it, and fall
|
||||
* through to the recv loop.
|
||||
*/
|
||||
if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0)
|
||||
return (0);
|
||||
while (GETC() != FRAME_END)
|
||||
continue;
|
||||
/*
|
||||
* Do the printf *before* we ack the message. This way
|
||||
* we won't drop any inbound characters while we're
|
||||
* doing the polling printf.
|
||||
*/
|
||||
printf("kgdb started from device %x\n", kgdb_dev);
|
||||
kgdb_send(in | KGDB_ACK, (u_char *)0, 0);
|
||||
kgdb_active = 1;
|
||||
}
|
||||
/*
|
||||
* Stick frame regs into our reg cache then tell remote host
|
||||
* that an exception has occured.
|
||||
*/
|
||||
regs_to_gdb(tf, gdb_regs);
|
||||
if (type != T_BREAKPOINT) {
|
||||
/*
|
||||
* XXX - Which is right? The code or the comment? -gwr
|
||||
* Only send an asynchronous SIGNAL message when we hit
|
||||
* a breakpoint. Otherwise, we will drop the incoming
|
||||
* packet while we output this one (and on entry the other
|
||||
* side isn't interested in the SIGNAL type -- if it is,
|
||||
* it will have used a signal packet.)
|
||||
*/
|
||||
outbuffer[0] = computeSignal(type);
|
||||
kgdb_send(KGDB_SIGNAL, outbuffer, 1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
in = kgdb_recv(inbuffer, &inlen);
|
||||
if (in == 0 || (in & KGDB_ACK))
|
||||
/* Ignore inbound acks and error conditions. */
|
||||
continue;
|
||||
|
||||
out = in | KGDB_ACK;
|
||||
switch (KGDB_CMD(in)) {
|
||||
|
||||
case KGDB_SIGNAL:
|
||||
/*
|
||||
* if this command came from a running gdb,
|
||||
* answer it -- the other guy has no way of
|
||||
* knowing if we're in or out of this loop
|
||||
* when he issues a "remote-signal". (Note
|
||||
* that without the length check, we could
|
||||
* loop here forever if the output line is
|
||||
* looped back or the remote host is echoing.)
|
||||
*/
|
||||
if (inlen == 0) {
|
||||
outbuffer[0] = computeSignal(type);
|
||||
kgdb_send(KGDB_SIGNAL, outbuffer, 1);
|
||||
}
|
||||
continue;
|
||||
|
||||
case KGDB_REG_R:
|
||||
case KGDB_REG_R | KGDB_DELTA:
|
||||
cp = outbuffer;
|
||||
outlen = 0;
|
||||
for (len = inbuffer[0]; len < NUM_REGS; ++len) {
|
||||
if (reg_cache[len] != gdb_regs[len] ||
|
||||
(in & KGDB_DELTA) == 0) {
|
||||
if (outlen + 5 > SL_MAXDATA) {
|
||||
out |= KGDB_MORE;
|
||||
break;
|
||||
}
|
||||
cp[outlen] = len;
|
||||
kgdb_copy(&gdb_regs[len],
|
||||
&cp[outlen + 1], 4);
|
||||
reg_cache[len] = gdb_regs[len];
|
||||
outlen += 5;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KGDB_REG_W:
|
||||
case KGDB_REG_W | KGDB_DELTA:
|
||||
cp = inbuffer;
|
||||
for (len = 0; len < inlen; len += 5) {
|
||||
register int j = cp[len];
|
||||
|
||||
kgdb_copy(&cp[len + 1],
|
||||
&gdb_regs[j], 4);
|
||||
reg_cache[j] = gdb_regs[j];
|
||||
}
|
||||
gdb_to_regs(tf, gdb_regs);
|
||||
outlen = 0;
|
||||
break;
|
||||
|
||||
case KGDB_MEM_R:
|
||||
len = inbuffer[0];
|
||||
kgdb_copy(&inbuffer[1], &addr, 4);
|
||||
if (len > SL_MAXDATA) {
|
||||
outlen = 1;
|
||||
outbuffer[0] = E2BIG;
|
||||
} else if (!kgdb_acc(addr, len)) {
|
||||
outlen = 1;
|
||||
outbuffer[0] = EFAULT;
|
||||
} else {
|
||||
outlen = len + 1;
|
||||
outbuffer[0] = 0;
|
||||
db_read_bytes((vm_offset_t)addr, (size_t)len,
|
||||
(char *)&outbuffer[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case KGDB_MEM_W:
|
||||
len = inlen - 4;
|
||||
kgdb_copy(inbuffer, &addr, 4);
|
||||
outlen = 1;
|
||||
if (!kgdb_acc(addr, len))
|
||||
outbuffer[0] = EFAULT;
|
||||
else {
|
||||
outbuffer[0] = 0;
|
||||
db_write_bytes((vm_offset_t)addr, (size_t)len,
|
||||
(char *)&inbuffer[4]);
|
||||
}
|
||||
break;
|
||||
|
||||
case KGDB_KILL:
|
||||
kgdb_active = 0;
|
||||
printf("kgdb detached\n");
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case KGDB_CONT:
|
||||
kgdb_send(out, 0, 0);
|
||||
tf->tf_sr &=~ PSL_T;
|
||||
goto out;
|
||||
|
||||
case KGDB_STEP:
|
||||
kgdb_send(out, 0, 0);
|
||||
tf->tf_sr |= PSL_T;
|
||||
goto out;
|
||||
|
||||
case KGDB_HALT:
|
||||
kgdb_send(out, 0, 0);
|
||||
sun3_mon_halt();
|
||||
/* NOTREACHED */
|
||||
|
||||
case KGDB_BOOT:
|
||||
kgdb_send(out, 0, 0);
|
||||
sun3_mon_reboot("");
|
||||
/* NOTREACHED */
|
||||
|
||||
case KGDB_EXEC:
|
||||
default:
|
||||
/* Unknown command. Ack with a null message. */
|
||||
outlen = 0;
|
||||
break;
|
||||
}
|
||||
/* Send the reply */
|
||||
kgdb_send(out, outbuffer, outlen);
|
||||
}
|
||||
out:
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: Determine if the memory at addr..(addr+len) is valid.
|
||||
* XXX: Should we just use the PTE bits? Why not?
|
||||
* XXX: Better yet, setup a fault handler?
|
||||
*/
|
||||
kgdb_acc(addr, len)
|
||||
caddr_t addr;
|
||||
int len;
|
||||
{
|
||||
vm_offset_t va;
|
||||
int pgoff;
|
||||
mmu_short_pte_t pte;
|
||||
|
||||
va = (vm_offset_t) addr;
|
||||
pgoff = va & PGOFSET;
|
||||
va -= pgoff;
|
||||
len += pgoff;
|
||||
|
||||
do {
|
||||
pte = get_pte(va);
|
||||
if (MMU_VALID_DT(pte) == 0)
|
||||
return (0);
|
||||
va += NBPG;
|
||||
len -= NBPG;
|
||||
} while (len > 0);
|
||||
|
||||
return (1);
|
||||
}
|
@ -1,426 +0,0 @@
|
||||
/* $NetBSD: vm_machdep.c,v 1.1.1.1 1997/01/14 20:57:09 gwr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Gordon W. Ross
|
||||
* Copyright (c) 1993 Adam Glass
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
* Copyright (c) 1982, 1986, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Systems Programming Group of the University of Utah Computer
|
||||
* Science Department.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 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
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Utah $Hdr: vm_machdep.c 1.21 91/04/06$
|
||||
* from: @(#)vm_machdep.c 8.6 (Berkeley) 1/12/94
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/core.h>
|
||||
#include <sys/exec.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_kern.h>
|
||||
/* #include <vm/vm_map.h> */
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/pmap.h>
|
||||
|
||||
#include "machdep.h"
|
||||
|
||||
extern int fpu_type;
|
||||
|
||||
extern void proc_do_uret __P((void));
|
||||
extern void proc_trampoline __P((void));
|
||||
|
||||
/*
|
||||
* Finish a fork operation, with process p2 nearly set up.
|
||||
* Copy and update the kernel stack and pcb, making the child
|
||||
* ready to run, and marking it so that it can return differently
|
||||
* than the parent. Returns 1 in the child process, 0 in the parent.
|
||||
*/
|
||||
void
|
||||
cpu_fork(p1, p2)
|
||||
register struct proc *p1, *p2;
|
||||
{
|
||||
register struct pcb *p1pcb = &p1->p_addr->u_pcb;
|
||||
register struct pcb *p2pcb = &p2->p_addr->u_pcb;
|
||||
register struct trapframe *p2tf;
|
||||
register struct switchframe *p2sf;
|
||||
|
||||
/*
|
||||
* Before copying the PCB from the current process,
|
||||
* make sure it is up-to-date. (p1 == curproc)
|
||||
*/
|
||||
if (p1 == curproc)
|
||||
savectx(p1pcb);
|
||||
|
||||
/* copy over the machdep part of struct proc */
|
||||
p2->p_md.md_flags = p1->p_md.md_flags;
|
||||
|
||||
/* Copy pcb from proc p1 to p2. */
|
||||
bcopy(p1pcb, p2pcb, sizeof(*p2pcb));
|
||||
|
||||
/* Child can start with low IPL (XXX - right?) */
|
||||
p2pcb->pcb_ps = PSL_LOWIPL;
|
||||
|
||||
/*
|
||||
* Our cpu_switch MUST always call PMAP_ACTIVATE on a
|
||||
* process switch so there is no need to do it here.
|
||||
* (Our PMAP_ACTIVATE call allocates an MMU context.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create the child's kernel stack, from scratch.
|
||||
* Pick a stack pointer, leaving room for a trapframe;
|
||||
* copy trapframe from parent so return to user mode
|
||||
* will be to right address, with correct registers.
|
||||
* Leave one word unused at the end of the kernel stack
|
||||
* so the system stack pointer stays within the page.
|
||||
*/
|
||||
p2tf = (struct trapframe *)((char*)p2pcb + USPACE-4) - 1;
|
||||
p2->p_md.md_regs = (int *)p2tf;
|
||||
bcopy(p1->p_md.md_regs, p2tf, sizeof(*p2tf));
|
||||
|
||||
/*
|
||||
* Create a "switch frame" such that when cpu_switch returns,
|
||||
* this process will be in proc_do_uret() going to user mode.
|
||||
*/
|
||||
p2sf = (struct switchframe *)p2tf - 1;
|
||||
p2sf->sf_pc = (u_int)proc_do_uret;
|
||||
p2pcb->pcb_regs[11] = (int)p2sf; /* SSP */
|
||||
|
||||
/*
|
||||
* This will "push a call" to an arbitrary kernel function
|
||||
* onto the stack of p2, very much like signal delivery.
|
||||
* When p2 runs, it will find itself in child_return().
|
||||
*/
|
||||
cpu_set_kpc(p2, child_return);
|
||||
}
|
||||
|
||||
/*
|
||||
* cpu_set_kpc:
|
||||
*
|
||||
* Arrange for in-kernel execution of a process to continue in the
|
||||
* named function, as if that function were called with one argument,
|
||||
* the current process's process pointer.
|
||||
*
|
||||
* Note that it's assumed that when the named process returns,
|
||||
* rei() should be invoked, to return to user mode. That is
|
||||
* accomplished by having cpu_fork set the initial frame with a
|
||||
* return address pointing to proc_do_uret() which does the rte.
|
||||
*
|
||||
* The design allows this function to be implemented as a general
|
||||
* "kernel sendsig" utility, that can "push" a call to a kernel
|
||||
* function onto any other process kernel stack, in a way very
|
||||
* similar to how signal delivery works on a user stack. When
|
||||
* the named process is switched to, it will call the function
|
||||
* we "pushed" and then proc_trampoline will pop the args that
|
||||
* were pushed here and return to where it would have returned
|
||||
* before we "pushed" this call.
|
||||
*/
|
||||
void
|
||||
cpu_set_kpc(proc, func)
|
||||
struct proc *proc;
|
||||
void (*func)(struct proc *);
|
||||
{
|
||||
struct pcb *pcbp;
|
||||
struct ksigframe {
|
||||
struct switchframe sf;
|
||||
void (*func)(struct proc *);
|
||||
void *proc;
|
||||
} *ksfp;
|
||||
|
||||
pcbp = &proc->p_addr->u_pcb;
|
||||
|
||||
/* Push a ksig frame onto the kernel stack. */
|
||||
ksfp = (struct ksigframe *)pcbp->pcb_regs[11] - 1;
|
||||
pcbp->pcb_regs[11] = (int)ksfp;
|
||||
|
||||
/* Now fill it in for proc_trampoline. */
|
||||
ksfp->sf.sf_pc = (u_int)proc_trampoline;
|
||||
ksfp->func = func;
|
||||
ksfp->proc = proc;
|
||||
}
|
||||
|
||||
/*
|
||||
* cpu_exit is called as the last action during exit.
|
||||
* We release the address space and machine-dependent resources,
|
||||
* including the memory for the user structure and kernel stack.
|
||||
* Once finished, we call switch_exit, which switches to a temporary
|
||||
* pcb and stack and never returns. We block memory allocation
|
||||
* until switch_exit has made things safe again.
|
||||
*/
|
||||
void
|
||||
cpu_exit(p)
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
vmspace_free(p->p_vmspace);
|
||||
|
||||
(void) splimp();
|
||||
cnt.v_swtch++;
|
||||
switch_exit(p);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* Do any additional state-saving necessary before swapout.
|
||||
*/
|
||||
void
|
||||
cpu_swapout(p)
|
||||
register struct proc *p;
|
||||
{
|
||||
|
||||
/*
|
||||
* This will have real work to do when we implement the
|
||||
* context-switch optimization of not switching FPU state
|
||||
* until the new process actually uses FPU instructions.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Do any additional state-restoration after swapin.
|
||||
*/
|
||||
void
|
||||
cpu_swapin(p)
|
||||
register struct proc *p;
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX - Just for debugging... (later).
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the machine specific segment at the start of a core dump.
|
||||
* This means the CPU and FPU registers. The format used here is
|
||||
* the same one ptrace uses, so gdb can be machine independent.
|
||||
*
|
||||
* XXX - Generate Sun format core dumps for Sun executables?
|
||||
*/
|
||||
struct md_core {
|
||||
struct reg intreg;
|
||||
struct fpreg freg;
|
||||
};
|
||||
int
|
||||
cpu_coredump(p, vp, cred, chdr)
|
||||
struct proc *p;
|
||||
struct vnode *vp;
|
||||
struct ucred *cred;
|
||||
struct core *chdr;
|
||||
{
|
||||
struct md_core md_core;
|
||||
struct coreseg cseg;
|
||||
int error;
|
||||
|
||||
/* XXX: Make sure savectx() was done? */
|
||||
|
||||
CORE_SETMAGIC(*chdr, COREMAGIC, MID_M68K, 0);
|
||||
chdr->c_hdrsize = ALIGN(sizeof(*chdr));
|
||||
chdr->c_seghdrsize = ALIGN(sizeof(cseg));
|
||||
chdr->c_cpusize = sizeof(md_core);
|
||||
|
||||
/* Save integer registers. */
|
||||
error = process_read_regs(p, &md_core.intreg);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Save floating point registers. */
|
||||
error = process_read_fpregs(p, &md_core.freg);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_M68K, CORE_CPU);
|
||||
cseg.c_addr = 0;
|
||||
cseg.c_size = chdr->c_cpusize;
|
||||
|
||||
error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
|
||||
(off_t)chdr->c_hdrsize, UIO_SYSSPACE,
|
||||
IO_NODELOCKED|IO_UNIT, cred, (int *)0, p);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core),
|
||||
(off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
|
||||
IO_NODELOCKED|IO_UNIT, cred, (int *)0, p);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
chdr->c_nseg++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move pages from one kernel virtual address to another.
|
||||
* Both addresses are assumed to reside in the kernel map,
|
||||
* and size must be a multiple of CLSIZE.
|
||||
*/
|
||||
void
|
||||
pagemove(from, to, size)
|
||||
register caddr_t from, to;
|
||||
size_t size;
|
||||
{
|
||||
register vm_offset_t pa;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (size & CLOFSET || (int)from & CLOFSET || (int)to & CLOFSET)
|
||||
panic("pagemove 1");
|
||||
#endif
|
||||
while (size > 0) {
|
||||
pa = pmap_extract(pmap_kernel(), (vm_offset_t)from);
|
||||
#ifdef DIAGNOSTIC
|
||||
if (pa == 0)
|
||||
panic("pagemove 2");
|
||||
#endif
|
||||
/* this does the cache flush work itself */
|
||||
pmap_remove(pmap_kernel(),
|
||||
(vm_offset_t)from, (vm_offset_t)from + NBPG);
|
||||
pmap_enter(pmap_kernel(),
|
||||
(vm_offset_t)to, pa, VM_PROT_READ|VM_PROT_WRITE, 1);
|
||||
from += NBPG;
|
||||
to += NBPG;
|
||||
size -= NBPG;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Map an IO request into kernel virtual address space.
|
||||
* Requests fall into one of five catagories:
|
||||
*
|
||||
* B_PHYS|B_UAREA: User u-area swap.
|
||||
* Address is relative to start of u-area (p_addr).
|
||||
* B_PHYS|B_PAGET: User page table swap.
|
||||
* Address is a kernel VA in usrpt (Usrptmap).
|
||||
* B_PHYS|B_DIRTY: Dirty page push.
|
||||
* Address is a VA in proc2's address space.
|
||||
* B_PHYS|B_PGIN: Kernel pagein of user pages.
|
||||
* Address is VA in user's address space.
|
||||
* B_PHYS: User "raw" IO request.
|
||||
* Address is VA in user's address space.
|
||||
*
|
||||
* All requests are (re)mapped into kernel VA space via the kernel_map
|
||||
*
|
||||
* This routine has user context and can sleep
|
||||
* (called only by physio).
|
||||
*
|
||||
* XXX we allocate KVA space by using kmem_alloc_wait which we know
|
||||
* allocates space without backing physical memory. This implementation
|
||||
* is a total crock, the multiple mappings of these physical pages should
|
||||
* be reflected in the higher-level VM structures to avoid problems.
|
||||
*/
|
||||
void
|
||||
vmapbuf(bp, sz)
|
||||
register struct buf *bp;
|
||||
vm_size_t sz;
|
||||
{
|
||||
register vm_offset_t addr, kva, pa;
|
||||
register vm_size_t size, off;
|
||||
register int npf;
|
||||
struct proc *p;
|
||||
register struct vm_map *map;
|
||||
|
||||
if ((bp->b_flags & B_PHYS) == 0)
|
||||
panic("vmapbuf");
|
||||
p = bp->b_proc;
|
||||
map = &p->p_vmspace->vm_map;
|
||||
bp->b_saveaddr = bp->b_data;
|
||||
addr = (vm_offset_t)bp->b_saveaddr;
|
||||
off = addr & PGOFSET;
|
||||
addr = trunc_page(addr);
|
||||
size = round_page(bp->b_bcount + off);
|
||||
kva = kmem_alloc_wait(kernel_map, size);
|
||||
bp->b_data = (caddr_t)(kva + off);
|
||||
|
||||
npf = btoc(size);
|
||||
while (npf--) {
|
||||
pa = pmap_extract(vm_map_pmap(map), (vm_offset_t)addr);
|
||||
pa = trunc_page(pa); /* page type in low bits? */
|
||||
if (pa == 0)
|
||||
panic("vmapbuf: null page frame");
|
||||
|
||||
/* XXX: flush write-back on old mappings? */
|
||||
/* XXX: cache_flush_page((vm_offset_t)addr); */
|
||||
|
||||
pmap_enter(pmap_kernel(), kva,
|
||||
pa | PMAP_NC,
|
||||
VM_PROT_READ|VM_PROT_WRITE, 1);
|
||||
addr += NBPG;
|
||||
kva += NBPG;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the io mappings associated with this I/O operation.
|
||||
* The mappings in the I/O map (phys_map) were non-cached,
|
||||
* so there are no write-back modifications to flush.
|
||||
* Also note, kmem_free_wakeup will remove the mappings.
|
||||
*
|
||||
* This routine has user context and can sleep
|
||||
* (called only by physio).
|
||||
*/
|
||||
void
|
||||
vunmapbuf(bp, sz)
|
||||
register struct buf *bp;
|
||||
vm_size_t sz;
|
||||
{
|
||||
register vm_offset_t kva, pgva;
|
||||
register vm_size_t size, off;
|
||||
|
||||
if ((bp->b_flags & B_PHYS) == 0)
|
||||
panic("vunmapbuf");
|
||||
|
||||
kva = (vm_offset_t)bp->b_data;
|
||||
off = kva & PGOFSET;
|
||||
pgva = trunc_page(kva);
|
||||
size = round_page(bp->b_bcount + off);
|
||||
|
||||
/* XXX: Actually remove mappings, which does cache flush. */
|
||||
pmap_remove(pmap_kernel(), pgva, pgva + size);
|
||||
|
||||
/*
|
||||
* Now remove the map entry, which may also call
|
||||
* pmap_remove but that will do nothing since we
|
||||
* already removed the actual mappings.
|
||||
*/
|
||||
kmem_free_wakeup(kernel_map, pgva, size);
|
||||
bp->b_data = bp->b_saveaddr;
|
||||
bp->b_saveaddr = NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user