Пример #1
0
static int
ukopen(dev_t dev, int flag, int fmt, struct lwp *l)
{
	int unit, error;
	struct uk_softc *uk;
	struct scsipi_periph *periph;
	struct scsipi_adapter *adapt;

	unit = minor(dev);
	uk = device_lookup_private(&uk_cd, unit);
	if (uk == NULL)
		return ENXIO;

	periph = uk->sc_periph;
	adapt = periph->periph_channel->chan_adapter;

	SC_DEBUG(periph, SCSIPI_DB1,
	    ("ukopen: dev=0x%"PRIx64" (unit %d (of %d))\n", dev, unit,
		uk_cd.cd_ndevs));

	/* Only allow one at a time */
	if (periph->periph_flags & PERIPH_OPEN) {
		aprint_error_dev(uk->sc_dev, "already open\n");
		return EBUSY;
	}

	if ((error = scsipi_adapter_addref(adapt)) != 0)
		return error;
	periph->periph_flags |= PERIPH_OPEN;

	SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
	return 0;
}
Пример #2
0
/*
 * open the device.
 */
int
ukopen(dev_t dev, int flag, int fmt, struct proc *p)
{
	int				unit;
	struct uk_softc			*uk;
	struct scsi_link		*sc_link;

	unit = UKUNIT(dev);
	if (unit >= uk_cd.cd_ndevs)
		return (ENXIO);

	uk = uk_cd.cd_devs[unit];
	if (uk == NULL)
		return (ENXIO);

	sc_link = uk->sc_link;

	SC_DEBUG(sc_link, SDEV_DB1, ("ukopen: dev=0x%x (unit %d (of %d))\n",
	    dev, unit, uk_cd.cd_ndevs));

	/* Only allow one at a time */
	if (sc_link->flags & SDEV_OPEN)
		return (EBUSY);

	sc_link->flags |= SDEV_OPEN;

	SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));

	return (0);
}
/* stop a scan operation in progress */
static int
mustek_rewind_scanner(struct ss_softc *ss)
{
	struct mustek_start_scan_cmd cmd;
	struct scsipi_periph *periph = ss->sc_periph;
	int error;

	if (ss->sio.scan_window_size != 0) {
		/*
		 * only if not all data has been read, the scanner has to be
		 * stopped
		 */
		memset(&cmd, 0, sizeof(cmd));
		cmd.opcode = MUSTEK_START_STOP;
		cmd.mode = MUSTEK_SCAN_STOP;

		/* send the command to the scanner */
		SC_DEBUG(periph, SCSIPI_DB1,
		    ("mustek_rewind_scanner: stop_scan\n"));
		error = scsipi_command(periph,
		    (void *)&cmd, sizeof(cmd),
		    NULL, 0,
		    MUSTEK_RETRIES, 5000, NULL, 0);
		if (error)
			return error;
	}

	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_rewind_scanner: end\n"));

	return 0;
}
Пример #4
0
/*
 * read the requested number of bytes/lines from the scanner
 */
static int
mustek_read(struct ss_softc *ss, struct buf *bp)
{
	struct mustek_read_cmd cmd;
	struct scsipi_xfer *xs;
	struct scsipi_periph *periph = ss->sc_periph;
	u_long lines_to_read;
	int error;

	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_read: start\n"));

	memset(&cmd, 0, sizeof(cmd));
	cmd.opcode = MUSTEK_READ;

	/* instead of the bytes, the mustek wants the number of lines */
	lines_to_read = bp->b_bcount /
	    ((ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8);
	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_read: read %ld lines\n",
	    lines_to_read));
	_lto3b(lines_to_read, cmd.length);

	/*
	 * go ask the adapter to do all this for us
	 */
	xs = scsipi_make_xs(periph,
	    (struct scsipi_generic *) &cmd, sizeof(cmd),
	    (u_char *) bp->b_data, bp->b_bcount,
	    MUSTEK_RETRIES, 10000, bp,
	    XS_CTL_NOSLEEP | XS_CTL_ASYNC | XS_CTL_DATA_IN);
	if (xs == NULL) {
		/*
		 * out of memory. Keep this buffer in the queue, and
		 * retry later.
		 */
		callout_reset(&ss->sc_callout, hz / 2, ssrestart,
		    periph);
		return(0);
	}
#ifdef DIAGNOSTIC
	if (BUFQ_GET(ss->buf_queue) != bp)
		panic("ssstart(): dequeued wrong buf");
#else
	BUFQ_GET(ss->buf_queue);
#endif
	error = scsipi_execute_xs(xs);
	/* with a scsipi_xfer preallocated, scsipi_command can't fail */
	KASSERT(error == 0);
	ss->sio.scan_lines -= lines_to_read;
#if 0
	if (ss->sio.scan_lines < 0)
		ss->sio.scan_lines = 0;
#endif
	ss->sio.scan_window_size -= bp->b_bcount;
#if 0
	if (ss->sio.scan_window_size < 0)
		ss->sio.scan_window_size = 0;
#endif
	return (0);
}
/*
 * check if the scanner is ready to take commands
 *   wait timeout seconds and try only every second
 *   if update, then update picture size info
 *
 *   returns EBUSY if scanner not ready
 */
static int
mustek_get_status(struct ss_softc *ss, int timeout, int update)
{
	struct mustek_get_status_cmd cmd;
	struct mustek_get_status_data data;
	struct scsipi_periph *periph = ss->sc_periph;
	int error, lines, bytes_per_line;

	memset(&cmd, 0, sizeof(cmd));
	cmd.opcode = MUSTEK_GET_STATUS;
	cmd.length = sizeof(data);

	while (1) {
		SC_DEBUG(periph, SCSIPI_DB1, ("mustek_get_status: stat_cmd\n"));
		error = scsipi_command(periph, (void *)&cmd, sizeof(cmd),
		    (void *)&data, sizeof(data),
		    MUSTEK_RETRIES, 5000, NULL, XS_CTL_DATA_IN);
		if (error)
			return error;
		if ((data.ready_busy == MUSTEK_READY) ||
		    (timeout-- <= 0))
			break;
		/* please wait a second */
		tsleep((void *)mustek_get_status, PRIBIO + 1, "mtkrdy", hz);
	}

	if (update) {
		bytes_per_line = _2ltol(data.bytes_per_line);
		lines = _3ltol(data.lines);
		if (lines != ss->sio.scan_lines) {
			printf("mustek: lines actual(%d) != computed(%ld)\n",
			    lines, ss->sio.scan_lines);
			return EIO;
		}
		if (bytes_per_line * lines != ss->sio.scan_window_size) {
			printf("mustek: win-size actual(%d) != computed(%ld)\n",
			    bytes_per_line * lines, ss->sio.scan_window_size);
		    return EIO;
		}

		SC_DEBUG(periph, SCSIPI_DB1,
		    ("mustek_get_size: bpl=%ld, lines=%ld\n",
		    (ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel)
		    / 8, ss->sio.scan_lines));
		SC_DEBUG(periph, SCSIPI_DB1, ("window size = %ld\n",
		    ss->sio.scan_window_size));
	}

	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_get_status: end\n"));
	if (data.ready_busy == MUSTEK_READY)
		return 0;
	else
		return EBUSY;
}
/*
 * trim the requested transfer to a multiple of the line size
 * this is called only from ssread() which guarantees, scanner is triggered
 * In the future, it will trim the transfer to not read to much at a time
 * because the mustek cannot disconnect. It will be calculated by the
 * resolution, the velocity and the number of bytes per line.
 */
static void
mustek_minphys(struct ss_softc *ss, struct buf *bp)
{
#ifdef SCSIPI_DEBUG
	struct scsipi_periph *periph = ss->sc_periph;
#endif

	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_minphys: before: %d\n",
	    bp->b_bcount));
	bp->b_bcount -= bp->b_bcount %
	    ((ss->sio.scan_pixels_per_line * ss->sio.scan_bits_per_pixel) / 8);
	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_minphys: after:  %d\n",
	    bp->b_bcount));
}
Пример #7
0
/*
 * Get the scsi driver to send a full inquiry to the
 * device and use the results to fill out the global
 * parameter structure.
 *
 * called from:
 * attach
 * open
 * ioctl (to reset original blksize)
 */
static int
st_scsibus_mode_sense(struct st_softc *st, int flags)
{
	u_int scsipi_sense_len;
	int error;
	struct scsipi_sense {
		struct scsi_mode_parameter_header_6 header;
		struct scsi_general_block_descriptor blk_desc;
		u_char sense_data[MAX_PAGE_0_SIZE];
	} scsipi_sense;
	struct scsipi_periph *periph = st->sc_periph;

	scsipi_sense_len = sizeof(scsipi_sense.header) +
			   sizeof(scsipi_sense.blk_desc) +
			   st->page_0_size;

	/*
	 * Set up a mode sense
	 * We don't need the results. Just print them for our interest's sake,
	 * if asked, or if we need it as a template for the mode select store
	 * it away.
	 */
	error = scsipi_mode_sense(st->sc_periph, 0, SMS_PCTRL_CURRENT,
	    &scsipi_sense.header, scsipi_sense_len, flags,
	    ST_RETRIES, ST_CTL_TIME);
	if (error)
		return error;

	st->numblks = _3btol(scsipi_sense.blk_desc.nblocks);
	st->media_blksize = _3btol(scsipi_sense.blk_desc.blklen);
	st->media_density = scsipi_sense.blk_desc.density;
	if (scsipi_sense.header.dev_spec & SMH_DSP_WRITE_PROT)
		st->flags |= ST_READONLY;
	else
		st->flags &= ~ST_READONLY;
	SC_DEBUG(periph, SCSIPI_DB3,
	    ("density code %d, %d-byte blocks, write-%s, ",
	    st->media_density, st->media_blksize,
	    st->flags & ST_READONLY ? "protected" : "enabled"));
	SC_DEBUG(periph, SCSIPI_DB3,
	    ("%sbuffered\n",
	    scsipi_sense.header.dev_spec & SMH_DSP_BUFF_MODE ? "" : "un"));
	if (st->page_0_size)
		memcpy(st->sense_data, scsipi_sense.sense_data,
		    st->page_0_size);
	periph->periph_flags |= PERIPH_MEDIA_LOADED;
	return 0;
}
Пример #8
0
int conf_set_attr(const char *attr, const char *val)
{
	int old_len, new_len;
	struct sysconfig *cfg;
	char line[LINE_LEN];
	int ret = 0;

	cfg = _syscfg_open();

	ret = search_attr(cfg, attr);
	if (ret < 0) {
		SC_DEBUG("Attribute \"%s\" does not exists, set attr error\n", attr);
		goto L1;
	}

	old_len = ret + 1; // add  '\n'

	new_len = snprintf(line, sizeof(line), "%s = %s\n", attr, val);
	printf("new attr = %s\n", line);

	if (new_len != old_len) {
		memmove(cfg->data + cfg->offset - old_len + new_len,
			cfg->data + cfg->offset, cfg->size - cfg->offset);
		cfg->size += new_len - old_len;
	}

	memcpy(cfg->data + cfg->offset - old_len, line, new_len);

	cfg->is_dirty = true;

L1:
	_syscfg_close(cfg);

	return ret;
}
Пример #9
0
/*
 * close the device.. only called if we are the LAST
 * occurence of an open device
 */
static int
ssclose(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev));
	struct scsipi_periph *periph = ss->sc_periph;
	struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
	int error;

	SC_DEBUG(ss->sc_periph, SCSIPI_DB1, ("closing\n"));

	if (SSMODE(dev) == MODE_REWIND) {
		if (ss->special && ss->special->rewind_scanner) {
			/* call special handler to rewind/abort scan */
			error = (ss->special->rewind_scanner)(ss);
			if (error)
				return error;
		} else {
			/* XXX add code to restart a SCSI2 scanner, if any */
		}
		ss->sio.scan_window_size = 0;
		ss->flags &= ~SSF_TRIGGERED;
	}

	scsipi_wait_drain(periph);

	scsipi_adapter_delref(adapt);
	periph->periph_flags &= ~PERIPH_OPEN;

	return 0;
}
Пример #10
0
/*
 * Ask the drive what it's min and max blk sizes are.
 */
static int
st_scsibus_read_block_limits(struct st_softc *st, int flags)
{
	struct scsi_block_limits cmd;
	struct scsi_block_limits_data block_limits;
	struct scsipi_periph *periph = st->sc_periph;
	int error;

	/*
	 * do a 'Read Block Limits'
	 */
	memset(&cmd, 0, sizeof(cmd));
	cmd.opcode = READ_BLOCK_LIMITS;

	/*
	 * do the command, update the global values
	 */
	error = scsipi_command(periph, (void *)&cmd, sizeof(cmd),
	    (void *)&block_limits, sizeof(block_limits),
	    ST_RETRIES, ST_CTL_TIME, NULL,
	    flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
	if (error)
		return (error);

	st->blkmin = _2btol(block_limits.min_length);
	st->blkmax = _3btol(block_limits.max_length);

	SC_DEBUG(periph, SCSIPI_DB3,
	    ("(%d <= blksize <= %d)\n", st->blkmin, st->blkmax));
	return (0);
}
Пример #11
0
/*
 * ssstart looks to see if there is a buf waiting for the device
 * and that the device is not already busy. If both are true,
 * It dequeues the buf and creates a scsi command to perform the
 * transfer required. The transfer request will call scsipi_done
 * on completion, which will in turn call this routine again
 * so that the next queued transfer is performed.
 * The bufs are queued by the strategy routine (ssstrategy)
 *
 * This routine is also called after other non-queued requests
 * have been made of the scsi driver, to ensure that the queue
 * continues to be drained.
 * ssstart() is called at splbio
 */
static void
ssstart(struct scsipi_periph *periph)
{
	struct ss_softc *ss = device_private(periph->periph_dev);
	struct buf *bp;

	SC_DEBUG(periph, SCSIPI_DB2, ("ssstart "));

	/* See if there is a buf to do and we are not already doing one */
	while (periph->periph_active < periph->periph_openings) {
		/* if a special awaits, let it proceed first */
		if (periph->periph_flags & PERIPH_WAITING) {
			periph->periph_flags &= ~PERIPH_WAITING;
			wakeup((void *)periph);
			return;
		}

		/* See if there is a buf with work for us to do.. */
		if ((bp = bufq_peek(ss->buf_queue)) == NULL)
			return;

		if (ss->special && ss->special->read)
			(ss->special->read)(ss, bp);
		else {
			/* generic scsi2 scanner read */
			/* XXX add code for SCSI2 scanner read */
		}
	}
}
Пример #12
0
int conf_del_attr(const char *attr)
{
	struct sysconfig *cfg;
	int ret = 0;
	int len;

	cfg = _syscfg_open();

	ret = search_attr(cfg, attr);
	if (ret < 0) {
		SC_DEBUG("Attribute \"%s\" does not exist, del attr error!\n", attr);
		goto L1;
	}

	len = ret + 1;

	memcpy(cfg->data + cfg->offset - len, cfg->data + cfg->offset, cfg->size - cfg->offset);

	cfg->size -= len;

	cfg->is_dirty = true;
L1:
	_syscfg_close(cfg);

	return ret;
}
Пример #13
0
/* mustek_attach: attach special functions to ss */
void
mustek_attach(struct ss_softc *ss, struct scsipibus_attach_args *sa)
{
#ifdef SCSIPI_DEBUG
	struct scsipi_periph *periph = sa->sa_periph;
#endif

	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_attach: start\n"));
	ss->sio.scan_scanner_type = 0;

	printf("\n%s: ", device_xname(ss->sc_dev));

	/* first, check the model which determines resolutions */
	if (!memcmp(sa->sa_inqbuf.product, "MFS-06000CX", 11)) {
		ss->sio.scan_scanner_type = MUSTEK_06000CX;
		printf("Mustek 6000CX Flatbed 3-pass color scanner, "
		    "3 - 600 dpi\n");
	}
	if (!memcmp(sa->sa_inqbuf.product, "MFS-12000CX", 11)) {
		ss->sio.scan_scanner_type = MUSTEK_12000CX;
		printf("Mustek 12000CX Flatbed 3-pass color scanner, "
		    "6 - 1200 dpi\n");
	}

	SC_DEBUG(periph, SCSIPI_DB1, ("mustek_attach: scanner_type = %d\n",
	    ss->sio.scan_scanner_type));

	/* install special handlers */
	ss->special = &mustek_special;

	/*
	 * populate the scanio struct with legal values
	 * the default should come from user space
	 */
	ss->sio.scan_width		= 1200;
	ss->sio.scan_height		= 1200;
	ss->sio.scan_x_resolution	= 99;
	ss->sio.scan_y_resolution	= 99;
	ss->sio.scan_x_origin		= 0;
	ss->sio.scan_y_origin		= 0;
	ss->sio.scan_brightness		= 100;
	ss->sio.scan_contrast		= 100;
	ss->sio.scan_quality		= 100;
	ss->sio.scan_image_mode		= SIM_GRAYSCALE;

	mustek_compute_sizes(ss);
}
Пример #14
0
/*
 * Check Errors
 */
int
sd_interpret_sense(struct scsi_xfer *xs)
{
	struct scsi_sense_data *sense = &xs->sense;
	struct scsi_link *sc_link = xs->sc_link;
	struct sd_softc *sc = sc_link->device_softc;
	u_int8_t serr = sense->error_code & SSD_ERRCODE;
	int retval;

	/*
	 * Let the generic code handle everything except a few categories of
	 * LUN not ready errors on open devices.
	 */
	if (((sc_link->flags & SDEV_OPEN) == 0) ||
	    (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED) ||
	    ((sense->flags & SSD_KEY) != SKEY_NOT_READY) ||
	    (sense->extra_len < 6))
		return (scsi_interpret_sense(xs));

	switch (ASC_ASCQ(sense)) {
	case SENSE_NOT_READY_BECOMING_READY:
		SC_DEBUG(sc_link, SDEV_DB1, ("becoming ready.\n"));
		retval = scsi_delay(xs, 5);
		break;

	case SENSE_NOT_READY_INIT_REQUIRED:
		SC_DEBUG(sc_link, SDEV_DB1, ("spinning up\n"));
		retval = scsi_start(sc->sc_link, SSS_START,
		    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_NOSLEEP);
		if (retval == 0)
			retval = ERESTART;
		else if (retval == ENOMEM)
			/* Can't issue the command. Fall back on a delay. */
			retval = scsi_delay(xs, 5);
		else
			SC_DEBUG(sc_link, SDEV_DB1, ("spin up failed (%#x)\n",
			    retval));
		break;

	default:
		retval = scsi_interpret_sense(xs);
		break;
	}

	return (retval);
}
Пример #15
0
void
sd_flush(struct sd_softc *sc, int flags)
{
    struct scsi_link *link = sc->sc_link;
    struct scsi_xfer *xs;
    struct scsi_synchronize_cache *cmd;

    if (link->quirks & SDEV_NOSYNCCACHE)
        return;

    /*
     * Issue a SYNCHRONIZE CACHE. Address 0, length 0 means "all remaining
     * blocks starting at address 0". Ignore ILLEGAL REQUEST in the event
     * that the command is not supported by the device.
     */

    xs = scsi_xs_get(link, flags);
    if (xs == NULL) {
        SC_DEBUG(link, SDEV_DB1, ("cache sync failed to get xs\n"));
        return;
    }

    cmd = (struct scsi_synchronize_cache *)xs->cmd;
    cmd->opcode = SYNCHRONIZE_CACHE;

    xs->cmdlen = sizeof(*cmd);
    xs->timeout = 100000;

    xs->done = sd_flush_done;

    do {
        scsi_xs_exec(xs);
        if (!ISSET(xs->flags, SCSI_POLL)) {
            while (!ISSET(xs->flags, ITSDONE))
                tsleep(xs, PRIBIO, "sdflush", 0);
        }
    } while (xs->status == XS_NO_CCB);

    if (xs->error == XS_NOERROR)
        sc->flags &= ~SDF_DIRTY;
    else
        SC_DEBUG(link, SDEV_DB1, ("cache sync failed\n"));

    scsi_xs_put(xs);
}
Пример #16
0
void
icpsp_intr(struct icp_ccb *ic)
{
	struct scsipi_xfer *xs;
 	struct icp_softc *icp;
 	int soff;

#ifdef DIAGNOSTIC
	struct icpsp_softc *sc = device_private(ic->ic_dv);
#endif
	xs = ic->ic_context;
	icp = device_private(device_parent(ic->ic_dv));
	soff = ICP_SCRATCH_SENSE + ic->ic_ident *
	    sizeof(struct scsi_sense_data);

	SC_DEBUG(xs->xs_periph, SCSIPI_DB2, ("icpsp_intr\n"));

	bus_dmamap_sync(icp->icp_dmat, icp->icp_scr_dmamap, soff,
	    sizeof(xs->sense.scsi_sense), BUS_DMASYNC_POSTREAD);

	if (ic->ic_status == ICP_S_OK) {
		xs->status = SCSI_OK;
		xs->resid = 0;
	} else if (ic->ic_status != ICP_S_RAW_SCSI || icp->icp_info >= 0x100) {
		xs->error = XS_SELTIMEOUT;
		xs->resid = xs->datalen;
	} else {
		xs->status = icp->icp_info;

		switch (xs->status) {
		case SCSI_OK:
#ifdef DIAGNOSTIC
			printf("%s: error return (%d), but SCSI_OK?\n",
			    device_xname(sc->sc_dv), icp->icp_info);
#endif
			xs->resid = 0;
			break;
		case SCSI_CHECK:
			memcpy(&xs->sense.scsi_sense,
			    (char *)icp->icp_scr + soff,
			    sizeof(xs->sense.scsi_sense));
			xs->error = XS_SENSE;
			/* FALLTHROUGH */
		default:
			/*
			 * XXX Don't know how to get residual count.
			 */
			xs->resid = xs->datalen;
			break;
		}
	}

	if (xs->datalen != 0)
		icp_ccb_unmap(icp, ic);
	icp_ccb_free(icp, ic);
	scsipi_done(xs);
}
Пример #17
0
/*
 * Actually translate the requested transfer into one the physical
 * driver can understand The transfer is described by a buf and will
 * include only one physical transfer.
 */
static void
ssstrategy(struct buf *bp)
{
	struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(bp->b_dev));
	struct scsipi_periph *periph = ss->sc_periph;
	int s;

	SC_DEBUG(ss->sc_periph, SCSIPI_DB1,
	    ("ssstrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount,
	    bp->b_blkno));

	/* If the device has been made invalid, error out */
	if (!device_is_active(ss->sc_dev)) {
		if (periph->periph_flags & PERIPH_OPEN)
			bp->b_error = EIO;
		else
			bp->b_error = ENODEV;
		goto done;
	}

	/* If negative offset, error */
	if (bp->b_blkno < 0) {
		bp->b_error = EINVAL;
		goto done;
	}

	if (bp->b_bcount > ss->sio.scan_window_size)
		bp->b_bcount = ss->sio.scan_window_size;

	/* If it's a null transfer, return immediatly */
	if (bp->b_bcount == 0)
		goto done;

	s = splbio();

	/*
	 * Place it in the queue of activities for this scanner
	 * at the end (a bit silly because we only have on user..
	 * (but it could fork()))
	 */
	bufq_put(ss->buf_queue, bp);

	/*
	 * Tell the device to get going on the transfer if it's
	 * not doing anything, otherwise just wait for completion
	 * (All a bit silly if we're only allowing 1 open but..)
	 */
	ssstart(ss->sc_periph);

	splx(s);
	return;
done:
	/* Correctly set the buf to indicate a completed xfer */
	bp->b_resid = bp->b_bcount;
	biodone(bp);
}
Пример #18
0
/*
 * The routine called by the low level scsi routine when it discovers
 * A device suitable for this driver
 * If it is a know special, call special attach routine to install
 * special handlers into the ss_softc structure
 */
static void
ssattach(struct device *parent, struct device *self, void *aux)
{
	struct ss_softc *ss = device_private(self);
	struct scsipibus_attach_args *sa = aux;
	struct scsipi_periph *periph = sa->sa_periph;

	SC_DEBUG(periph, SCSIPI_DB2, ("ssattach: "));

	ss->flags |= SSF_AUTOCONF;

	/*
	 * Store information needed to contact our base driver
	 */
	ss->sc_periph = periph;
	periph->periph_dev = &ss->sc_dev;
	periph->periph_switch = &ss_switch;

	printf("\n");

	/*
	 * Set up the buf queue for this device
	 */
	bufq_alloc(&ss->buf_queue, "fcfs", 0);

	callout_init(&ss->sc_callout, 0);

	/*
	 * look for non-standard scanners with help of the quirk table
	 * and install functions for special handling
	 */
	SC_DEBUG(periph, SCSIPI_DB2, ("ssattach:\n"));
	if (memcmp(sa->sa_inqbuf.vendor, "MUSTEK", 6) == 0)
		mustek_attach(ss, sa);
	if (memcmp(sa->sa_inqbuf.vendor, "HP      ", 8) == 0 &&
	    memcmp(sa->sa_inqbuf.product, "ScanJet 5300C", 13) != 0)
		scanjet_attach(ss, sa);
	if (ss->special == NULL) {
		/* XXX add code to restart a SCSI2 scanner, if any */
	}

	ss->flags &= ~SSF_AUTOCONF;
}
Пример #19
0
/*
 * close the device.. only called if we are the LAST
 * occurrence of an open device
 */
int
ukclose(dev_t dev, int flag, int fmt, struct proc *p)
{
	struct uk_softc			*uk = uk_cd.cd_devs[UKUNIT(dev)];

	SC_DEBUG(uk->sc_link, SDEV_DB1, ("closing\n"));
	uk->sc_link->flags &= ~SDEV_OPEN;

	return (0);
}
Пример #20
0
/*
 * Actually translate the requested transfer into one the physical driver
 * can understand.  The transfer is described by a buf and will include
 * only one physical transfer.
 */
void
sdstrategy(struct buf *bp)
{
	struct sd_softc *sc;
	int s;

	sc = sdlookup(DISKUNIT(bp->b_dev));
	if (sc == NULL) {
		bp->b_error = ENXIO;
		goto bad;
	}
	if (sc->flags & SDF_DYING) {
		bp->b_error = ENXIO;
		goto bad;
	}

	SC_DEBUG(sc->sc_link, SDEV_DB2, ("sdstrategy: %ld bytes @ blk %lld\n",
	    bp->b_bcount, (long long)bp->b_blkno));
	/*
	 * If the device has been made invalid, error out
	 */
	if ((sc->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
		if (sc->sc_link->flags & SDEV_OPEN)
			bp->b_error = EIO;
		else
			bp->b_error = ENODEV;
		goto bad;
	}

	/* Validate the request. */
	if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1)
		goto done;

	/* Place it in the queue of disk activities for this disk. */
	bufq_queue(&sc->sc_bufq, bp);

	/*
	 * Tell the device to get going on the transfer if it's
	 * not doing anything, otherwise just wait for completion
	 */
	scsi_xsh_add(&sc->sc_xsh);

	device_unref(&sc->sc_dev);
	return;

 bad:
	bp->b_flags |= B_ERROR;
	bp->b_resid = bp->b_bcount;
 done:
	s = splbio();
	biodone(bp);
	splx(s);
	if (sc != NULL)
		device_unref(&sc->sc_dev);
}
Пример #21
0
int
sd_flush(struct sd_softc *sc, int flags)
{
	struct scsi_link *link = sc->sc_link;
	struct scsi_xfer *xs;
	struct scsi_synchronize_cache *cmd;
	int error;

	if (link->quirks & SDEV_NOSYNCCACHE)
		return (0);

	/*
	 * Issue a SYNCHRONIZE CACHE. Address 0, length 0 means "all remaining
	 * blocks starting at address 0". Ignore ILLEGAL REQUEST in the event
	 * that the command is not supported by the device.
	 */

	xs = scsi_xs_get(link, flags);
	if (xs == NULL) {
		SC_DEBUG(link, SDEV_DB1, ("cache sync failed to get xs\n"));
		return (EIO);
	}

	cmd = (struct scsi_synchronize_cache *)xs->cmd;
	cmd->opcode = SYNCHRONIZE_CACHE;

	xs->cmdlen = sizeof(*cmd);
	xs->timeout = 100000;
	xs->flags |= SCSI_IGNORE_ILLEGAL_REQUEST;

	error = scsi_xs_sync(xs);

	scsi_xs_put(xs);

	if (error)
		SC_DEBUG(link, SDEV_DB1, ("cache sync failed\n"));
	else
		sc->flags &= ~SDF_DIRTY;

	return (error);
}
Пример #22
0
int
_init()
{
	int err = 0;

	mutex_init(&sc_gptwo_config_list_lock, NULL, MUTEX_DRIVER, NULL);
	sc_gptwo_config_list = NULL;

	/*
	 * CPU/PCI devices are already registered by their respective modules,
	 * so all we need to do now is install.
	 */
	if ((err = mod_install(&modlinkage)) != 0) {
		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg failed to load, error=%d\n",
			err));
		mutex_destroy(&sc_gptwo_config_list_lock);
	} else {
		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg has been loaded.\n"));
	}
	return (err);
}
Пример #23
0
int conf_load()
{
	struct sysconfig *cfg = _syscfg_get();

	if (strncmp(GB_SYSCFG_MAGIC, (char *)cfg->data, strlen(GB_SYSCFG_MAGIC)))
		return -EINVAL;

	cfg->size = _g_sysconfig_len;
	SC_DEBUG("sysconf: base = 0x%p, size = %d\n", cfg->data, cfg->size);

	conf_check_default();

	return 0;
}
Пример #24
0
/*
 * Send a filled out parameter structure to the drive to
 * set it into the desire modes etc.
 */
static int
st_scsibus_mode_select(struct st_softc *st, int flags)
{
	u_int scsi_select_len;
	struct scsi_select {
		struct scsi_mode_parameter_header_6 header;
		struct scsi_general_block_descriptor blk_desc;
		u_char sense_data[MAX_PAGE_0_SIZE];
	} scsi_select;
	struct scsipi_periph *periph = st->sc_periph;

	scsi_select_len = 12 + st->page_0_size;

	/*
	 * This quirk deals with drives that have only one valid mode
	 * and think this gives them license to reject all mode selects,
	 * even if the selected mode is the one that is supported.
	 */
	if (st->quirks & ST_Q_UNIMODAL) {
		SC_DEBUG(periph, SCSIPI_DB3,
		    ("not setting density 0x%x blksize 0x%x\n",
		    st->density, st->blksize));
		return (0);
	}

	/*
	 * Set up for a mode select
	 */
	memset(&scsi_select, 0, scsi_select_len);
	scsi_select.header.blk_desc_len = sizeof(struct scsi_general_block_descriptor);
	scsi_select.header.dev_spec &= ~SMH_DSP_BUFF_MODE;
	scsi_select.blk_desc.density = st->density;
	if (st->flags & ST_DONTBUFFER)
		scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_OFF;
	else
		scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
	if (st->flags & ST_FIXEDBLOCKS)
		_lto3b(st->blksize, scsi_select.blk_desc.blklen);
	if (st->page_0_size)
		memcpy(scsi_select.sense_data, st->sense_data, st->page_0_size);

	/*
	 * do the command
	 */
	return scsipi_mode_select(periph, 0, &scsi_select.header,
	    scsi_select_len, flags | XS_CTL_DATA_ONSTACK,
	    ST_RETRIES, ST_CTL_TIME);
}
Пример #25
0
static int
ukclose(dev_t dev, int flag, int fmt, struct lwp *l)
{
	struct uk_softc *uk = device_lookup_private(&uk_cd, minor(dev));
	struct scsipi_periph *periph = uk->sc_periph;
	struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;

	SC_DEBUG(uk->sc_periph, SCSIPI_DB1, ("closing\n"));

	scsipi_wait_drain(periph);

	scsipi_adapter_delref(adapt);
	periph->periph_flags &= ~PERIPH_OPEN;

	return 0;
}
Пример #26
0
/*
 * ask the scsi driver to perform a command for us.
 * tell it where to read/write the data, and how
 * long the data is supposed to be. If we have  a buf
 * to associate with the transfer, we need that too.
 */
void
scsi_scsipi_cmd(struct scsipi_xfer *xs)
{
	struct scsipi_periph *periph = xs->xs_periph;

	SC_DEBUG(periph, SCSIPI_DB2, ("scsi_scsipi_cmd\n"));

	/*
	 * Set the LUN in the CDB if we have an older device.  We also
	 * set it for more modern SCSI-2 devices "just in case".
	 */
	if (periph->periph_version <= 2)
		xs->cmd->bytes[0] |=
		    ((periph->periph_lun << SCSI_CMD_LUN_SHIFT) &
			SCSI_CMD_LUN_MASK);
}
Пример #27
0
/*
 * The routine called by the low level scsi routine when it discovers
 * a device suitable for this driver.
 */
static void
ukattach(device_t parent, device_t self, void *aux)
{
	struct uk_softc *uk = device_private(self);
	struct scsipibus_attach_args *sa = aux;
	struct scsipi_periph *periph = sa->sa_periph;

	SC_DEBUG(periph, SCSIPI_DB2, ("ukattach: "));
	uk->sc_dev = self;

	/* Store information needed to contact our base driver */
	uk->sc_periph = periph;
	periph->periph_dev = uk->sc_dev;

	printf("\n");
}
Пример #28
0
/*
 * The routine called by the low level scsi routine when it discovers
 * a device suitable for this driver.
 */
void
ukattach(struct device *parent, struct device *self, void *aux)
{
	struct uk_softc			*uk = (void *)self;
	struct scsi_attach_args		*sa = aux;
	struct scsi_link		*sc_link = sa->sa_sc_link;

	SC_DEBUG(sc_link, SDEV_DB2, ("ukattach: "));

	/* Store information needed to contact our base driver */
	uk->sc_link = sc_link;
	sc_link->device = &uk_switch;
	sc_link->device_softc = uk;
	sc_link->openings = 1;

	printf("\n");
}
Пример #29
0
/*
 * Look at the returned sense and act on the error and detirmine
 * The unix error number to pass back... (0 = report no error)
 *                            (-1 = continue processing)
 */
int
ch_interpret_sense(struct scsi_xfer *xs)
{
	struct scsi_sense_data *sense = &xs->sense;
	struct scsi_link *sc_link = xs->sc_link;
	u_int8_t serr = sense->error_code & SSD_ERRCODE;
	u_int8_t skey = sense->flags & SSD_KEY;

	if (((sc_link->flags & SDEV_OPEN) == 0) ||
	    (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED))
		return (scsi_interpret_sense(xs));

	switch (skey) {

	/*
	 * We do custom processing in ch for the unit becoming ready case.
	 * in this case we do not allow xs->retries to be decremented
	 * only on the "Unit Becoming Ready" case. This is because tape
	 * changers report "Unit Becoming Ready" when they rescan their
	 * state (i.e. when the door got opened) and can take a long time
	 * for large units. Rather than having a massive timeout for
	 * all operations (which would cause other problems) we allow
	 * changers to wait (but be interruptable with Ctrl-C) forever
	 * as long as they are reporting that they are becoming ready.
	 * all other cases are handled as per the default.
	 */
	case SKEY_NOT_READY:
		if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0)
			return (0);
		switch (ASC_ASCQ(sense)) {
		case SENSE_NOT_READY_BECOMING_READY:
			SC_DEBUG(sc_link, SDEV_DB1, ("not ready: busy (%#x)\n",
			    sense->add_sense_code_qual));
			/* don't count this as a retry */
			xs->retries++;
			return (scsi_delay(xs, 1));
		default:
			return (scsi_interpret_sense(xs));
	}
	default:
		return (scsi_interpret_sense(xs));
	}
}
Пример #30
0
/*
 * The routine called by the low level scsi routine when it discovers
 * A device suitable for this driver
 */
void
cdattach(struct device *parent, struct device *self, void *aux)
{
	struct scsi_attach_args *sa = aux;
	struct scsi_link *sc_link = sa->sa_sc_link;
	struct cd_softc *cd = (struct cd_softc *)self;

	SC_DEBUG(sc_link, SDEV_DB2, ("cdattach:\n"));

	/*
	 * Store information needed to contact our base driver
	 */
	cd->sc_link = sc_link;
	sc_link->device = &cd_switch;
	sc_link->device_softc = cd;
	if (sc_link->openings > CDOUTSTANDING)
		sc_link->openings = CDOUTSTANDING;

	/*
	 * Initialize and attach the disk structure.
	 */
  	cd->sc_dk.dk_driver = &cddkdriver;
	cd->sc_dk.dk_name = cd->sc_dev.dv_xname;
	disk_attach(&cd->sc_dk);

	/*
	 * Note if this device is ancient.  This is used in cdminphys().
	 */
	if (!(sc_link->flags & SDEV_ATAPI) &&
	    SCSISPC(sa->sa_inqbuf->version) == 0)
		cd->flags |= CDF_ANCIENT;

	printf("\n");

	timeout_set(&cd->sc_timeout, cdrestart, cd);

	if ((cd->sc_cdpwrhook = powerhook_establish(cd_powerhook, cd)) == NULL)
		printf("%s: WARNING: unable to establish power hook\n",
		    cd->sc_dev.dv_xname);
}