📄 sf.c
字号:
#include "sf.h"#if NSF > 0/************************************************************************ ************************************************************************ * * * * * SCSI floppy disk driver * * * * * ************************************************************************ ************************************************************************//* * Copyright (C) 1989 Sun Microsystems, Inc. */#ident "@(#)sf.c 1.1 92/07/30 SMI"/************************************************************************ ************************************************************************ * * * * * Includes, Declarations and Local Data * * * * * ************************************************************************ ************************************************************************/#include <scsi/scsi.h>#include <scsi/targets/sfdef.h>#include <sun/vddrv.h>#include <vm/hat.h>#include <vm/seg.h>#include <vm/as.h>/************************************************************************ * * * Local definitions, for clarity of code * * * ************************************************************************/#ifdef OPENPROMS#define DNAME devp->sd_dev->devi_name#define DUNIT devp->sd_dev->devi_unit#define CNAME devp->sd_dev->devi_parent->devi_name#define CUNIT devp->sd_dev->devi_parent->devi_unit#else OPENPROMS#define DNAME devp->sd_dev->md_driver->mdr_dname#define DUNIT devp->sd_dev->md_unit#define CNAME devp->sd_dev->md_driver->mdr_cname#define CUNIT devp->sd_dev->md_ctlr->mc_ctlr#endif OPENPROMS#define UPTR ((struct scsi_floppy *)(devp)->sd_private)#define SCBP(pkt) ((struct scsi_status *)(pkt)->pkt_scbp)#define SCBP_C(pkt) ((*(pkt)->pkt_scbp) & STATUS_MASK)#define CDBP(pkt) ((union scsi_cdb *)(pkt)->pkt_cdbp)#define ROUTE (&devp->sd_address)#define BP_PKT(bp) ((struct scsi_pkt *)bp->av_back)#define Tgt(devp) (devp->sd_address.a_target)#define Lun(devp) (devp->sd_address.a_lun)#define SFUNIT(dev) (minor((dev))>>3)#define SFPART(dev) (minor((dev))&0x7)/* * Parameters */ /* * 120 seconds is a *very* reasonable amount of time for most floppy * operations. */#define DEFAULT_SF_TIMEOUT 120 /* * 5 seconds is what we'll wait if we get a Busy Status back */#define SFTIMEOUT 5*hz /* 2 seconds Busy Waiting */ /* * Number of times we'll retry a normal operation. * * XXX This includes retries due to transport failure * XXX Need to distinguish between Target and Transport * XXX failure. */#define SF_RETRY_COUNT 30 /* * maximum number of supported units */#define SF_MAXUNIT 2/* * Debugging macros */#define DEBUGGING ((scsi_options & SCSI_DEBUG_TGT) || sfdebug > 1)#define DEBUGGING_ALL ((scsi_options & SCSI_DEBUG_TGT) || sfdebug)#define DPRINTF if(DEBUGGING) printf#define DPRINTF_ALL if (DEBUGGING || sfdebug > 0) printf#define DPRINTF_IOCTL DPRINTF_ALL/************************************************************************ * * * Gloabal Data Definitions * * * ************************************************************************/struct scsi_device *sfunits[SF_MAXUNIT];extern int nsf = SF_MAXUNIT;/************************************************************************ * * * Local Static Data * * * ************************************************************************/static int sfpri = 0;static int sfdebug = 0;static int sf_error_reporting = SDERR_RETRYABLE;static struct sf_drivetype sf_drivetypes[] = {/* Emulex MD21 */{ "SMS", 0, CTYPE_SMS, 3, "SMS" },/* Connor */{ "NCR", 0, CTYPE_NCR, 3, "NCR" },};#define MAX_SFTYPES (sizeof sf_drivetypes/ (sizeof sf_drivetypes[0]))static u_char media_types[] = { /* * first one must be ff (replaced with whatever the drive starts with) */ 0xff, 0x1e, };/* * Configuration Data */#ifdef OPENPROMS/* * Device driver ops vector */int sfslave(), sfopen(), sfclose(), sfread(), sfwrite();int sfstrategy(), sfioctl(), sfsize();extern int nulldev(), nodev();struct dev_ops sf_ops = { 1, sfslave, nulldev, sfopen, sfclose, sfread, sfwrite, sfstrategy, nodev, sfsize, sfioctl}; #else OPENPROMSXXX * BARF * XXX#endif/************************************************************************ * * * Local Function Declarations * * * ************************************************************************/static void sfintr(), sferrmsg(), sfdone(), make_sf_cmd(), sfstart(), sfdone();static int sfrunout(), sf_findslave(), sf_unit_ready();/**/#if defined(VDDRV) && defined(LOADABLE)/*********************************************************************** ************************************************************************ * * * * * Loadable Module support * * * * * ************************************************************************ ************************************************************************/#ifndef OPENPROMSXXXXXXXXXXXXXXXXXXXXXXXXXX BLETCH XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX#endif/* * Loadable module support: * for a loadable driver * modload modstat & modunload */int nsf = NSF;struct scsi_device *sfunits[NSF];/* * awk. */static int targetid = 6;static int sf_can_load(), sf_can_unload();extern int seltrue();static struct bdevsw sf_bdevsw = { sfopen, sfclose, sfstrategy, nodev, sfsize, 0};static struct cdevsw sf_cdevsw = { sfopen, sfclose, sfread, sfwrite, sfioctl, nulldev, seltrue, 0, 0};static struct vdldrv sfdrv = { VDMAGIC_DRV, "SCSI Floppy Driver", &sf_ops, &sf_bdevsw, &sf_cdevsw, 9, 33};sfinit(fcn, vdp, vdi, vds)int fcn;register struct vddrv *vdp;caddr_t vdi;struct vdstat *vds;{ extern struct scsi_device *sd_root; struct scsi_device *devp; int status = 0; switch (fcn) { case VDLOAD: status = sf_can_load(); if (status == 0) { vdp->vdd_vdtab = (struct vdlinkage *)&sfdrv; } break; case VDUNLOAD: status = sf_can_unload(); break; case VDSTAT: break; default: printf("sfinit: unknown function 0x%x\n", fcn); status = EINVAL; } return status;}static intsf_can_load(){ register scsi_device *devp, *newdevp; register i, s; if (sfpri == 0) sfpri = pritospl(SPLMB); s = splr(sfpri); for (i = 0; i < nsf; i++) { if (sfunits[i]) { (void) splx(s); return (EBUSY); } } if (devp = sd_root) { for (;;) { if (devp->sd_address.a_target == targetid) { (void) splx(s); return (EBUSY); } if (devp->sd_next) { devp = devp->sd_next; } else break; } } (void) splx(s); newdevp = (struct scsi_device *) kmem_zalloc((unsigned) sizeof (*devp)); if (!newdevp) return (ENOMEM); newdevp->sd_address = devp->sd_address; newdevp->sd_address.a_target = targetid; newdevp->sd_address.a_lun = 0; devp->sd_next = newdevp;}#endif defined(VDDRV) && defined(LOADABLE)/************************************************************************ ************************************************************************ * * * * * Autoconfiguration Routines * * * * * ************************************************************************ ************************************************************************/intsfslave(devp)struct scsi_device *devp;{ /* * fill in our local array */ if (DUNIT >= nsf) return (0); sfunits[DUNIT] = devp;#ifdef OPENPROMS sfpri = MAX(sfpri,ipltospl(devp->sd_dev->devi_intr->int_pri));#else XXX BARF XXX sfpri = MAX(sfpri,pritospl(devp->sd_dev->md_inr));#endif /* * Turn around and call real slave routine.. */ return (sf_findslave(devp,0));}static intsf_findslave(devp,canwait)register struct scsi_device *devp;int canwait;{ static char *badtyp1 = "%s%d:\tdevice is a '%s' device\n\texpected a '%s' device\n"; static char *badtyp2 = "\tat target %d lun %d on %s%d\n"; static char *nonccs ="%s%d: non-CCS device found at target %d lun %d on %s%d- not supported\n"; struct scsi_pkt *pkt, *rqpkt; struct scsi_floppy *un; struct scsi_capacity *cap; struct sf_drivetype *dp; long capacity, lbasize; auto int (*f)() = (canwait == 0)? NULL_FUNC: SLEEP_FUNC; /* * Call the routine scsi_slave to do some of the dirty work. * All scsi_slave does is do a TEST UNIT READY (and possibly * a non-extended REQUEST SENSE or two), and an INQUIRY command. * If the INQUIRY command succeeds, the field sd_inq in the * device structure will be filled in. * * XXX NEED TO CHANGE scsi_slave TO JUST DO REQUEST_SENSE * XXX AND INQUIRY- THAT WAY WE CAN DO THE TEST_UNIT_READY * XXX HERE AND POSSIBLY SEND A START UNIT COMMAND IF IT * XXX ISN'T READY.. */ switch (scsi_slave(devp,canwait)) { default: case SCSIPROBE_NOMEM: case SCSIPROBE_FAILURE: case SCSIPROBE_NORESP: return (0); case SCSIPROBE_NONCCS: printf(nonccs,DNAME,DUNIT,Tgt(devp),Lun(devp),CNAME,CUNIT); return (0); case SCSIPROBE_EXISTS: if(devp->sd_inq->inq_dtype != DTYPE_DIRECT) { printf(badtyp1,DNAME,DUNIT, scsi_dname((int)devp->sd_inq->inq_dtype), scsi_dname(DTYPE_DIRECT)); printf(badtyp2,Tgt(devp),Lun(devp),CNAME,CUNIT); return (0); } break; } /* * Sigh. Look through our list of supported drives to dredge * up information that we haven't figured out a clever way * to get inference yet. */ /* * The actual unit is present. * Now is the time to fill in the rest of our info.. */ un = UPTR = (struct scsi_floppy *) kmem_zalloc(sizeof(struct scsi_floppy)); if (!un) { printf("%s%d: no memory for disk structure\n",DNAME,DUNIT); return (0); } for (dp = &sf_drivetypes[0]; dp < &sf_drivetypes[MAX_SFTYPES]; dp++) { if (bcmp(devp->sd_inq->inq_vid,dp->vid,dp->vidlen) == 0) { un->un_dp = dp; break; } } if (dp == &sf_drivetypes[MAX_SFTYPES]) { printf("%s%d: unknown drive not supported\n",DNAME,DUNIT); (void) kmem_free((caddr_t) un, (unsigned) sizeof (struct scsi_floppy)); return 0; } /* * now allocate a request sense packet */ rqpkt = scsi_pktiopb(ROUTE,(caddr_t *)&devp->sd_sense,CDB_GROUP0, 1,SENSE_LENGTH,B_READ,f); if (!rqpkt) { (void) kmem_free((caddr_t) un, (unsigned) sizeof (struct scsi_floppy)); return (0); } makecom_g0(rqpkt,devp,0,SCMD_REQUEST_SENSE,0,SENSE_LENGTH); rqpkt->pkt_pmon = -1; un->un_mode = (caddr_t) rmalloc(iopbmap, (long) MSIZE); un->un_rbufp = (struct buf *) kmem_zalloc(sizeof (struct buf)); un->un_sbufp = (struct buf *) kmem_zalloc(sizeof (struct buf)); if (!un->un_rbufp || !un->un_sbufp || !un->un_mode) { printf("sfslave: no memory for data structures\n"); if (un->un_sbufp) (void) kmem_free((caddr_t)un->un_rbufp,sizeof (struct buf)); if (un->un_rbufp) (void) kmem_free((caddr_t)un->un_rbufp,sizeof (struct buf)); if (un->un_mode) (void) rmfree(iopbmap, (long) MSIZE, (u_long) un->un_mode); (void) kmem_free((caddr_t) un,sizeof (struct scsi_floppy)); (void) rmfree(iopbmap, (long) SENSE_LENGTH, (u_long) devp->sd_sense); scsi_resfree(rqpkt); return 0; } devp->sd_present = 1; un->un_capacity = -1; /* XXX */ un->un_lbasize = SECSIZE; /* XXX */ rqpkt->pkt_comp = sfintr; rqpkt->pkt_time = DEFAULT_SF_TIMEOUT; un->un_rqs = rqpkt; un->un_sd = devp; un->un_dev = DUNIT<<3;#ifdef OPENPROMS devp->sd_dev->devi_driver = &sf_ops;#endif un->un_g.dkg_ncyl = 78; un->un_g.dkg_acyl = 0; un->un_g.dkg_pcyl = 80; un->un_g.dkg_nhead = 2; un->un_g.dkg_nsect = 9; return (1);}/**//************************************************************************ ************************************************************************ * * * * * Unix Entry Points * * * * * ************************************************************************ ************************************************************************/intsfopen(dev, flag)dev_t dev;int flag;{ register struct scsi_device *devp; register struct scsi_floppy *un; register int unit, s; if((unit = SFUNIT(dev)) >= nsf) { return ENXIO; } else if (!(devp = sfunits[unit])) { return ENXIO; } else if (!devp->sd_present) { s = splr(sfpri); if (sf_findslave(devp,1)) { printf("%s%d at %s%d target %d lun %d\n",DNAME,DUNIT, CNAME,CUNIT,Tgt(devp),Lun(devp)); } else { (void) splx(s); return ENXIO; } (void) splx(s); } un = UPTR; if (un->un_state >= SF_STATE_OPEN) return (0); un->un_last_state = un->un_state; un->un_state = SF_STATE_OPENING; /* * sf_unit_ready just determines whether a diskette is inserted * */ if (sf_unit_ready(dev) == 0) { un->un_state = un->un_last_state; un->un_last_state = SF_STATE_OPENING; return (ENXIO); } /* * sf_get_density will run through all known density modes * to try and read the device. If that fails, it must be * either an unformatted disk, or must be a density we cannot * hack. In either case, we will allow only a format command * of this device at this point to open the device. */ if (sf_get_density(dev) == 0) { /* * Are we opening this for format(8) or fdformat? */ if ((flag & (FNDELAY|FNBIO)) == 0 || cdevsw[major(dev)].d_open != sfopen) { un->un_last_state = un->un_state; un->un_state = SF_STATE_CLOSED; return ENXIO; } /* * XXX: put in a block here- opening for formatting is * XXX: exclusive use. */ if (sf_set_density(dev) == 0) { un->un_last_state = un->un_state; un->un_state = SF_STATE_CLOSED; return EIO; } } un->un_last_state = un->un_state; un->un_state = SF_STATE_OPEN; un->un_open |= (1<<SFPART(dev)); return (0);}intsfclose(dev)dev_t dev;{ register struct scsi_device *devp; register struct scsi_floppy *un; int unit;#ifdef NOT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -