📄 sr.c
字号:
#ident "@(#)sr.c 1.1 92/07/30 SMI"/* @(#)sr.c 1.1 92/07/30 SMI *//* * Copyright (c) 1988-1991 by Sun Microsystems, Inc. */#include "sr.h"#if NSR > 0/* * * SCSI CDROM driver (for CDROM, read-only) * *//* * * * Includes, Declarations and Local Data * * */#include <scsi/scsi.h>#include <scsi/targets/srdef.h>#include <scsi/impl/uscsi.h>#include <vm/hat.h>#include <vm/seg.h>#include <vm/as.h>/* * * Local definitions, for clarity of code * */#ifdef OPENPROMS#define DRIVER sr_ops#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 DRIVER srdriver#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_mc->mc_ctlr#endif OPENPROMS#define UPTR ((struct scsi_disk *)(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 SRUNIT(dev) (minor((dev))>>3)#define SRPART(dev) (minor((dev))&0x7)#define New_state(un, s) (un)->un_last_state=(un)->un_state, (un)->un_state=(s)#define Restore_state(un) \ { u_char tmp = (un)->un_last_state; New_state((un), tmp); }/* * Parameters */ /* * 180 seconds is a reasonable amount of time for CDROM operations */#define DEFAULT_SR_TIMEOUT 180 /* * 180 seconds is what we'll wait if we get a Busy Status back * Note: worse case timeout with 30 second x (1 + 5 retrys) = 180 */#define SRTIMEOUT 180*hz /* 180 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 SR_RETRY_COUNT 1 /* * Maximum number of retries to handle unit attention key */#define SR_UNIT_ATTENTION_RETRY 40 /* * Maximum number of units (controlled by space in minor device byte) */#define SR_MAXUNIT 32 /* * Maximum number of retry when trying to read the capacity from * the disk. */#define MAX_RETRY 20/* * Debugging macros */#define DEBUGGING ((scsi_options & SCSI_DEBUG_TGT) || srdebug > 1)#define DEBUGGING_ALL ((scsi_options & SCSI_DEBUG_TGT) || srdebug)#define DPRINTF if (DEBUGGING) printf#define DPRINTF_ALL if (DEBUGGING || srdebug > 0) printf#define DPRINTF_IOCTL DPRINTF_ALL/* * * Global Data Definitions and references * */struct scsi_device *srunits[SR_MAXUNIT];int nsr = SR_MAXUNIT;extern int maxphys, dkn;/* * * Local Static Data * */static struct scsi_address *srsvdaddr[SR_MAXUNIT];static int srpri = 0;static int srdebug = 0;static int sr_error_reporting = SRERR_RETRYABLE;static struct sr_drivetype sr_drivetypes[] = {/* SONY CDU-541 */{ "Sony", 0, CTYPE_CCS, 4, "SONY" },{ "Hitachi", 0, CTYPE_CCS, 7, "HITACHI" },};/* * Generic CCS scsi drive with very pessimistic assumptions as to capabilities. * Well, for now, assume it has reconnect capacities. */static struct sr_drivetype generic_ccs ={ "CCS", 0, CTYPE_CCS, 4, "<??>" };#define MAX_SRTYPES (sizeof sr_drivetypes/ (sizeof sr_drivetypes[0]))/* * Configuration Data */#ifdef OPENPROMS/* * Device driver ops vector */int srslave(), srattach(), sropen(), srclose(), srread();int srstrategy(), srioctl(), srsize();extern int nulldev(), nodev();struct dev_ops sr_ops = { 1, srslave, srattach, sropen, srclose, srread, nodev, srstrategy, nodev, srsize, srioctl};#else OPENPROMS/* * srdriver is only used to attach */int srslave(), srattach(), sropen(), srclose(), srread();int srstrategy(), srdump(), srioctl(), srsize();extern int nulldev(), nodev();struct mb_driver srdriver = { nulldev, srslave, srattach, nodev, nodev, nulldev, 0, "sr", 0, 0, 0, 0};#endif/* * * Local Function Declarations * */static void clean_print(), srintr();static void srerrmsg(), srintr_adaptec(), srdone(), sr_offline();static void make_sr_cmd(), srstart(), srdone(), sr_error_code_print();static int srrunout(), sr_findslave(), sr_unit_ready(), sr_medium_removal();static void makecom_all();static int sr_pause_resume(), sr_play_msf(), sr_play_trkind();static int sr_read_tochdr(), sr_read_tocentry();static void sr_not_ready();static void sr_ejected();#ifdef OLDCODEstatic int sr_read_new_disc();#endif OLDCODEstatic int sr_read_mode2(), sr_read_mode1();static int sr_mode_1(), sr_mode_2();static int sr_handle_ua();static int sr_lock_door();static void sr_setup_openflags();#ifndef FIVETWELVEstatic int sr_two_k();#endif FIVETWELVE#ifdef OPENPROMSstatic void sr_set_dkn();#endif OPENPROMS/**//* * * * Autoconfiguration Routines * * */intsrslave(devp)struct scsi_device *devp;{ int r; /* * fill in our local array */ if (DUNIT >= nsr) return (0); srunits[DUNIT] = devp;#ifdef OPENPROMS srpri = MAX(srpri, ipltospl(devp->sd_dev->devi_intr->int_pri));#else srpri = MAX(srpri, pritospl(devp->sd_dev->md_intpri));#endif /* * Turn around and call real slave routine. If it returns -1, * then try and save the address structure for a possible later open. */ r = sr_findslave (devp, 0); if (r < 0) { srsvdaddr[DUNIT] = (struct scsi_address *) kmem_zalloc(sizeof (struct scsi_address)); if (srsvdaddr[DUNIT]) { srunits[DUNIT] = 0; *srsvdaddr[DUNIT] = devp->sd_address; } else { r = 0; } } return (r);}static intsr_findslave(devp, canwait)register struct scsi_device *devp;int canwait;{ struct scsi_pkt *rqpkt; struct scsi_disk *un; struct sr_drivetype *dp; 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. The sd_sense structure * will also be allocated. * */ switch (scsi_slave(devp, canwait)) { default: case SCSIPROBE_NOMEM: case SCSIPROBE_FAILURE: case SCSIPROBE_NORESP: case SCSIPROBE_NONCCS: if (devp->sd_inq) { IOPBFREE (devp->sd_inq, sizeof (struct scsi_inquiry)); devp->sd_inq = (struct scsi_inquiry *) 0; } return (-1); case SCSIPROBE_EXISTS: /* * The only type of device that we're * interested in is READ ONLY DIRECT ACCESS. */ if (devp->sd_inq->inq_dtype != DTYPE_RODIRECT) { IOPBFREE (devp->sd_inq, sizeof (struct scsi_inquiry)); devp->sd_inq = (struct scsi_inquiry *) 0; return (-1); } /* * XXX: should you check to make sure that the inq_rmb * XXX: is set? So that all the eject code doesn't * XXX: barf? */ break; } /* * allocate a request sense packet */ rqpkt = get_pktiopb(ROUTE, (caddr_t *)&devp->sd_sense, CDB_GROUP0, 1, SENSE_LENGTH, B_READ, f); if (!rqpkt) { return (0); } makecom_g0(rqpkt, devp, 0, SCMD_REQUEST_SENSE, 0, SENSE_LENGTH); rqpkt->pkt_pmon = -1; /* * fill up some of the scsi disk information. */ un = UPTR = (struct scsi_disk *)kmem_zalloc(sizeof (struct scsi_disk)); if (!un) { printf("%s%d: no memory for disk structure\n", DNAME, DUNIT); free_pktiopb(rqpkt, (caddr_t)devp->sd_sense, SENSE_LENGTH); return (0); } 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) { printf("srslave: no memory for raw or special buffer\n"); if (un->un_rbufp) (void) kmem_free((caddr_t)un->un_rbufp, sizeof (struct buf)); (void) kmem_free((caddr_t)un, sizeof (struct scsi_disk)); free_pktiopb(rqpkt, (caddr_t)devp->sd_sense, SENSE_LENGTH); return (0); } /* * For sure the drive is present, and we're going to keep it. * Since this is (we hope) removable media, we don't need to read the * media at this point. We'll do it during the first open. */ devp->sd_present = 1; /* * 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. */ for (dp = &sr_drivetypes[0]; dp < &sr_drivetypes[MAX_SRTYPES]; dp++) { if (bcmp(devp->sd_inq->inq_vid, dp->id, dp->idlen) == 0) { un->un_dp = dp; break; } } if (dp == &sr_drivetypes[MAX_SRTYPES]) { /* * assume CCS drive, don't assume anything else. */ printf("%s%d: Unrecongized Vendor '", DNAME, DUNIT); clean_print(&(devp->sd_inq->inq_vid[0]), 8); printf("', product '"); clean_print(&(devp->sd_inq->inq_pid[0]), 16); printf("'"); un->un_dp = (struct sr_drivetype *) kmem_zalloc(sizeof (struct sr_drivetype)); if (!un->un_dp || !(un->un_dp->name = kmem_zalloc(8))) { un->un_dp = &generic_ccs; } else { bcopy(devp->sd_inq->inq_vid, un->un_dp->name, 8); un->un_dp->name[7] = 0; bcopy(devp->sd_inq->inq_vid, un->un_dp->id, IDMAX); un->un_dp->idlen = IDMAX; un->un_dp->ctype = CTYPE_CCS; } } un->un_capacity = -1; un->un_lbasize = -1; /* * initialize open and exclusive open flags */ un->un_open0 = un->un_open1 = 0; un->un_exclopen = 0; rqpkt->pkt_comp = srintr; rqpkt->pkt_time = DEFAULT_SR_TIMEOUT; if (un->un_dp->options & SR_NODISC) rqpkt->pkt_flags |= FLAG_NODISCON; un->un_rqs = rqpkt; un->un_sd = devp; un->un_dev = DUNIT<<3;#ifdef OPENPROMS devp->sd_dev->devi_driver = &sr_ops;#endif return (1);}/* * Attach disk. The controller is there. Since this is a CDROM, * there is no need to check the label. */intsrattach(devp)struct scsi_device *devp;{ register struct scsi_disk *un; if (!(un = UPTR)) { return; }#ifndef FIVETWELVE /* * Set the drive's sector size to 2048 */ (void)sr_two_k(devp);#endif FIVETWELVE /* * initialize the geometry and partition table. */ bzero((caddr_t) & un->un_g, sizeof (struct dk_geom)); bzero((caddr_t)un->un_map, NDKMAP * (sizeof (struct dk_map))); /* * It's CDROM, therefore, no label. But it is still necessary * to set up various geometry information. And we are doing * this here. * For the number of sector per track, we put the maximum * number, assuming a CDROM can hold up to 600 Mbytes of data. * For the rpm, we use the minimum for the disk. */ un->un_g.dkg_ncyl = 1; un->un_g.dkg_acyl = 0; un->un_g.dkg_bcyl = 0; un->un_g.dkg_nhead = 1; un->un_g.dkg_nsect = 0; un->un_g.dkg_intrlv = 1; un->un_g.dkg_rpm = 200; un->un_gvalid = 1; /* * dk instrumentation */#ifdef OPENPROMS if ((un->un_dkn = (char) newdk("sr", DUNIT)) >= 0) { int intrlv = un->un_g.dkg_intrlv; if (intrlv <= 0 || intrlv >= un->un_g.dkg_nsect) { intrlv = 1; } dk_bps[un->un_dkn] = (SECSIZE * 60 * un->un_g.dkg_nsect) / intrlv; }#endif OPENPROMS }static voidclean_print(p, l)char *p;int l;{ char a[2]; register unsigned i = 0, c; while (i < l) { if ((c = *p++) < ' ' || c >= 0177) printf("\\%o", c&0xff); else { a[0] = c; a[1] = 0; printf("%s", a); } i++; }}#ifdef OPENPROMSstatic voidsr_set_dkn(devp)struct scsi_device *devp;{ register struct scsi_disk *un; un = UPTR; if ((un->un_dkn = (char) newdk("sr", DUNIT)) >= 0) { int intrlv = un->un_g.dkg_intrlv; if (intrlv <= 0 || intrlv >= un->un_g.dkg_nsect) { intrlv = 1; } dk_bps[un->un_dkn] = (SECSIZE * 60 * un->un_g.dkg_nsect) / intrlv; }}#endif OPENPROMS/**//* * * * Unix Entry Points * * *//*ARGSUSED*/intsropen(dev, flag)dev_t dev;int flag;{ register struct scsi_device *devp; register struct scsi_disk *un; register int unit, s; DPRINTF("in sropen\n"); if ((unit = SRUNIT(dev)) >= nsr) { return (ENXIO); } if (!(devp = srunits[unit])) { struct scsi_address *sa = srsvdaddr[unit]; if (sa) { if (scsi_add_device(sa, &DRIVER, "sr", unit) == 0) { return (ENXIO); } devp = srunits[unit]; if (!devp) panic("sropen"); (void) kmem_free((caddr_t) sa, sizeof (*sa)); srsvdaddr[unit] = (struct scsi_address *) 0; } else { return (ENXIO); } } else if (!devp->sd_present) { s = splr(srpri); if (sr_findslave (devp, 1) > 0) { printf("%s%d at %s%d target %d lun %d\n", DNAME, DUNIT, CNAME, CUNIT, Tgt(devp), Lun(devp)); srattach(devp); } else { (void) splx(s); return (ENXIO); } (void) splx(s); } un = UPTR; /* * check for previous exclusive open */ if ((un->un_exclopen) || ((flag & FEXCL) && ((un->un_open0 != 0) || (un->un_open1 != 0)))) { return (EBUSY); } DPRINTF("un->un_state is %d\n", un->un_state); if ((un->un_state == SR_STATE_NIL) || (un->un_state == SR_STATE_CLOSED) || (un->un_state == SR_STATE_EJECTED)) { u_char state;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -