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; }
/* * 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; }
/* * 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)); }
/* * 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; }
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; }
/* * 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; }
/* * 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); }
/* * 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 */ } } }
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; }
/* 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); }
/* * 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); }
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); }
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); }
/* * 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); }
/* * 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; }
/* * 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); }
/* * 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); }
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); }
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); }
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; }
/* * 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); }
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; }
/* * 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); }
/* * 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"); }
/* * 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"); }
/* * 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)); } }
/* * 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); }