⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gscdd.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: gscdd.c,v 1.1 2001/04/15 11:12:37 ant Exp $ * Copyright (c) 1996, 1997 by Matthew Jacob * *	This software is free software; you can redistribute it and/or *	modify it under the terms of the GNU Library General Public *	License as published by the Free Software Foundation; version 2. * *	This software is distributed in the hope that it will be useful, *	but WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *	Library General Public License for more details. * *	You should have received a copy of the GNU Library General Public *	License along with this software; if not, write to the Free *	Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *	The author may be reached via electronic communications at * *		mjacob@feral.com * *	or, via United States Postal Address * *		Matthew Jacob *		1831 Castro Street *		San Francisco, CA, 94131 */#include <stdio.h>#include <sys/types.h>#include <sys/errno.h>#include <sys/sysmacros.h>#include <sys/syspest.h>#include <sys/ioctl.h>#include <sys/i_machine.h>#include <sys/systm.h>#include <sys/conf.h>#include <sys/devinfo.h>#include <sys/lockl.h>#include <sys/device.h>#include <sys/uio.h>#include <sys/watchdog.h>#include <sys/errids.h>#include <sys/trchkid.h>#include <sys/priv.h>#include <sys/iostat.h>#include <sys/bootrecord.h>#include <sys/scsi.h>#include <sys/malloc.h>#include <sys/sleep.h>#include <sys/fp_io.h>#include <sys/pin.h>#include <sys/lock_alloc.h>#define	DD_LOCK	37#include "gscdds.h"static int strlen(char *s) { char *p = s; while (*p) p++; return p - s; }static void memset(void *x, int val, size_t amt){ char *p = (char *)x; while (--amt) *p++ = (char) val; }static void memcpy(void *dst, void *src, size_t amt) { char *dest = dst, *source = src; while (--amt) *dest++ = *source++; }#define	bcopy(src, dst, nbytes)	memcpy(dst, src, nbytes)/* * Local Definitions */#define	HKWD_GSC_DD	0x66600000#define	_COM_TRACE(b, var)	\	var = strlen(b); trcgenk(0, HKWD_GSC_DD, var, var, b)#define	Trace0(val, str)	\	if (scudebug >= val) { \		int icxq; \		_COM_TRACE(str, icxq); \	}#define	Trace1(val, fmt, arg1)	\	if (scudebug >= val) { \		int icxq; char buf[256]; \		(void) sprintf(buf, fmt, arg1); \		_COM_TRACE(buf, icxq); \	}#define	Trace2(val, fmt, arg1, arg2)	\	if (scudebug >= val) { \		int icxq; char buf[256]; \		(void) sprintf(buf, fmt, arg1, arg2); \		_COM_TRACE(buf, icxq); \	}#define	Trace3(val, fmt, arg1, arg2, arg3)	\	if (scudebug >= val) { \		int icxq; char buf[256]; \		(void) sprintf(buf, fmt, arg1, arg2, arg3); \		_COM_TRACE(buf, icxq); \	}#define	Trace4(val, fmt, arg1, arg2, arg3, arg4)	\	if (scudebug >= val) { \		int icxq; char buf[256]; \		(void) sprintf(buf, fmt, arg1, arg2, arg3, arg4); \		_COM_TRACE(buf, icxq); \	}#define	Trace5(val, fmt, arg1, arg2, arg3, arg4, arg5)	\	if (scudebug >= val) { \		int icxq; char buf[256]; \		(void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5); \		_COM_TRACE(buf, icxq); \	}#define	Trace6(val, fmt, arg1, arg2, arg3, arg4, arg5, arg6)	\	if (scudebug >= val) { \		int icxq; char buf[256]; \		(void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); \		_COM_TRACE(buf, icxq); \	}#define	MJ_RTN(VAL)	simple_unlock(&sp->dd_lock); return (VAL)typedef struct {    struct sc_buf scsibuf;    uint index;} gsc_buf_t;typedef struct {    Simple_lock dd_lock;    Simple_lock buf_lock;    struct file *fp;		/* file pointer */    gsc_buf_t cbuf;#define	cmdbuf cbuf.scsibuf	/* buffer for command */    gsc_buf_t rbuf;#define rqsbuf rbuf.scsibuf	/* buffer for request sense */    dev_t dev;			/* Adapter dev */    u_char tgt;			/* target ID */    u_char lun;			/* logical unit */    u_char isopen;		/* device is open */    u_char iscfg;		/* non-zero to show this as configured */    u_char unstart;		/* stop device on unconfigure */    u_char needresume;		/* needs an SC_RESUME with next command */} gsc_softc_t;/* * External References */extern int copyin(void *, void *, int);extern int copyout(void *, void *, int);extern int devstrat(struct buf *);extern int nodev(void);extern void setuerror(int);/* * Device Driver Entry Points */int gsc_config(dev_t, int, struct uio *);static int gsc_open(dev_t);static int gsc_close(dev_t);static int gsc_ioctl(dev_t, int, void *, ulong);static void gscdd_intr(struct buf *);/* * Static Data */static int scudebug = 10;static int nunits = 0;static gsc_softc_t softinfo[MAX_UNITS] = { 0 };lock_t config_lock = { LOCK_AVAIL };/* * Local Function Prototypes */static int gsopen(gsc_softc_t *);static void gsclose(gsc_softc_t *, dev_t);static int gsccmd(dev_t, scmd_t *, ulong);static int make_rqs(gsc_softc_t *, char, char *, int, int);/* * Configuration Routines */intgsc_config(dev_t devno, int cmd, struct uio * uiop){    struct gsc_ddsinfo ddsinfo;    gsc_softc_t *sp;    int result, i, unit;    extern int nodev();    static struct devsw gsc_dsw = {	gsc_open,	/* entry point for open routine */	gsc_close,	/* entry point for close routine */	nodev,		/* entry point for read routine */	nodev,		/* entry point for write routine */	gsc_ioctl,	/* entry point for ioctl routine */	nodev,		/* entry point for strategy routine */	0,		/* pointer to tty device structure */	nodev,		/* entry point for select routine */	gsc_config,	/* entry point for config routine */	nodev,		/* entry point for print routine */	nodev,		/* entry point for dump routine */	nodev,		/* entry point for mpx routine */	nodev,		/* entry point for revoke routine */	NULL,		/* pointer to device specific data */	NULL,		/* select pointer */	DEV_MPSAFE    };    if (lockl(&config_lock, LOCK_SHORT) != LOCK_SUCC) {	return (EINVAL);    }    unit = minor(devno);    if (unit < 0 || unit >= MAX_UNITS) {	Trace2(0, "%d: bad unit %d", __LINE__, unit);	result = EINVAL;	unlockl(&config_lock);	return (result);    }    switch (cmd) {    case CFG_INIT:	Trace2(2, "CFG_INIT: unit %d nunit %d\n", unit, nunits);	/*	 * Initialize softinfo, first time around.	 */	if (nunits == 0) {	    memset(softinfo, 0, sizeof (softinfo));	}	/*	 * Copy in DDS information	 */	uiomove((caddr_t) &ddsinfo, sizeof ddsinfo, UIO_WRITE, uiop);	sp = &softinfo[unit];	if (sp->iscfg) {	    Trace1(0, "CFG_INIT: unit %d already configd", unit);	    result = EBUSY;	    break;	}	lock_alloc(&sp->dd_lock, LOCK_ALLOC_PIN, DD_LOCK, -1);	lock_alloc(&sp->buf_lock, LOCK_ALLOC_PIN, DD_LOCK, -1);	simple_lock_init(&sp->dd_lock);	sp->dev = ddsinfo.busid;	sp->tgt = ddsinfo.target;	sp->lun = ddsinfo.lun;	sp->cbuf.index = sp->rbuf.index = unit;	/*	 * If this is the first time through:	 *   Add entry to the device switch table to call this driver	 *   Pin driver code.	 */	if (nunits == 0) {	    result = devswadd(devno, &gsc_dsw);	    if (result != 0) {		Trace1(0, "CFG_INIT: devswadd result: %d", result);		break;	    }	    result = pincode((int (*) ()) gscdd_intr);	    if (result) {		Trace1(0, "CFG_INIT: pincode result: %d", result);		devswdel(devno);		break;	    }	}	sp->iscfg = 1;	result = gsopen(sp);	if (result) {	    Trace2(0, "CFG_INIT: gsopen returns %d for unit %d", result, unit);	    sp->iscfg = 0;	    gsclose(sp, devno);	    break;	}	if (nunits <= unit)	    nunits = unit + 1;	sp->iscfg = 1;	break;    case CFG_TERM:	Trace1(2, "CFG_TERM unit %d", unit);	result = 0;	sp = &softinfo[unit];	if (sp->iscfg == 0) {	    Trace1(0, "CFG_TERM: unit %d not already configd", unit);	    result = ENXIO;	    break;	} else if (sp->isopen) {	    Trace1(0, "CFG_TERM: unit %d open", unit);	    result = EBUSY;	    break;	}	sp->iscfg = 0;	/* block further actions */	gsclose(sp, devno);	break;    default:	result = EINVAL;	break;    }    unlockl(&config_lock);    return (result);}/* * Validate that devno is indeed for a SCSI adapter, and set up stuff for it. */static intgsopen(gsc_softc_t * sp){    struct file *fp;    int r;    struct devinfo di;    Trace2(2, "gsopen: %d.%d", major(sp->dev), minor(sp->dev));    sp->fp = NULL;    r = fp_opendev(sp->dev, DREAD|DWRITE|DKERNEL, NULL, 0, &fp);    if (r) {	Trace3(0, "%d: fp_opendev unit %d=%d", __LINE__, sp->cbuf.index, r);	return (r);    }    r = fp_ioctl(fp, IOCINFO, (caddr_t) &di, NULL);    if (r) {	Trace3(0, "%d: fp_ioctl unit %d=%d", __LINE__, sp->cbuf.index, r);	(void) fp_close(fp);	return (r);    }    if (di.devtype != DD_BUS || di.devsubtype != DS_SCSI) {	Trace2(0, "%d: not SCSI bus on unit %d", __LINE__,  sp->cbuf.index);	(void) fp_close(fp);	return (r);    }    sp->fp = fp;    sp->unstart = 1;    if (fp_ioctl(sp->fp, SCIOSTART, (caddr_t) IDLUN(sp->tgt, sp->lun), NULL)) {	sp->unstart = 0;    }    return (0);}/* * Shut down a device */static voidgsclose(gsc_softc_t *sp, dev_t devno){    int i;    if (sp->fp != NULL && sp->unstart) {	(void) fp_ioctl(sp->fp, SCIOSTOP, (caddr_t) IDLUN(sp->tgt, sp->lun), NULL);	sp->unstart = 0;    }    if (sp->fp) {	(void) fp_close(sp->fp);	sp->fp = NULL;    }    for (i = 0; i < MAX_UNITS; i++) {	if (softinfo[i].iscfg) {	    Trace1(0, "gsclose: unit %d still confd", i);	    break;	}    }    if (i == MAX_UNITS) {	Trace0(0, "gsclose: All unconfigured now");	(void) devswdel(devno);	unpincode((int (*) ()) gscdd_intr);    }}/* * VFS entry points */static intgsc_open(dev_t devno){    gsc_softc_t *sp;    int unit = minor(devno);    Trace1(2, "gsc_open: open unit %d", unit);    if (unit < 0 || unit >= MAX_UNITS) {	return (ENODEV);    }    sp = &softinfo[unit];    if (sp->iscfg == 0 || sp->fp == NULL) {	Trace2(0, "%d: bad unit (%d)", __LINE__, unit);	return (ENODEV);    }    simple_lock(&sp->dd_lock);    if (sp->isopen) {	simple_unlock(&sp->dd_lock);	return (EBUSY);    }    sp->isopen = 1;    simple_unlock(&sp->dd_lock);    return (0);}static intgsc_close(dev_t dev){    gsc_softc_t *sp;    int unit = minor(dev);    Trace1(2, "gsc_close: close unit %d", unit);    if (unit < 0 || unit >= MAX_UNITS) {	return (ENODEV);    }    sp = &softinfo[unit];    if (sp->iscfg == 0) {	return (ENODEV);    }    simple_lock(&sp->dd_lock);    sp->isopen = 0;    simple_unlock(&sp->dd_lock);    return (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -