Deleted Added
sdiff udiff text old ( 164906 ) new ( 168752 )
full compact
1/*-
2 * Copyright (c) 1997 Justin T. Gibbs.
3 * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 54 unchanged lines hidden (view full) ---

63 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
64 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
65 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * SUCH DAMAGE.
68 */
69
70#include <sys/cdefs.h>
71__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_ch.c 164906 2006-12-05 07:45:28Z mjacob $");
72
73#include <sys/param.h>
74#include <sys/queue.h>
75#include <sys/systm.h>
76#include <sys/kernel.h>
77#include <sys/types.h>
78#include <sys/malloc.h>
79#include <sys/fcntl.h>

--- 88 unchanged lines hidden (view full) ---

168 u_int8_t sc_exchangemask[CHET_MAX + 1];
169
170 /*
171 * Quirks; see below. XXX KDM not implemented yet
172 */
173 int sc_settledelay; /* delay for settle */
174};
175
176#define CHUNIT(x) (minor((x)))
177
178static d_open_t chopen;
179static d_close_t chclose;
180static d_ioctl_t chioctl;
181static periph_init_t chinit;
182static periph_ctor_t chregister;
183static periph_oninv_t choninvalidate;
184static periph_dtor_t chcleanup;
185static periph_start_t chstart;

--- 22 unchanged lines hidden (view full) ---

208 chinit, "ch",
209 TAILQ_HEAD_INITIALIZER(chdriver.units), /* generation */ 0
210};
211
212PERIPHDRIVER_DECLARE(ch, chdriver);
213
214static struct cdevsw ch_cdevsw = {
215 .d_version = D_VERSION,
216 .d_flags = D_NEEDGIANT,
217 .d_open = chopen,
218 .d_close = chclose,
219 .d_ioctl = chioctl,
220 .d_name = "ch",
221};
222
223static void
224chinit(void)

--- 146 unchanged lines hidden (view full) ---

371 */
372 softc->device_stats = devstat_new_entry("ch",
373 periph->unit_number, 0,
374 DEVSTAT_NO_BLOCKSIZE | DEVSTAT_NO_ORDERED_TAGS,
375 SID_TYPE(&cgd->inq_data)| DEVSTAT_TYPE_IF_SCSI,
376 DEVSTAT_PRIORITY_OTHER);
377
378 /* Register the device */
379 softc->dev = make_dev(&ch_cdevsw, periph->unit_number, UID_ROOT,
380 GID_OPERATOR, 0600, "%s%d", periph->periph_name,
381 periph->unit_number);
382 softc->dev->si_drv1 = periph;
383
384 /*
385 * Add an async callback so that we get
386 * notified if this device goes away.
387 */
388 xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5);
389 csa.ccb_h.func_code = XPT_SASYNC_CB;
390 csa.event_enable = AC_LOST_DEVICE;
391 csa.callback = chasync;
392 csa.callback_arg = periph;
393 xpt_action((union ccb *)&csa);
394
395 /*
396 * Lock this peripheral until we are setup.
397 * This first call can't block
398 */
399 (void)cam_periph_lock(periph, PRIBIO);
400 xpt_schedule(periph, /*priority*/5);
401
402 return(CAM_REQ_CMP);
403}
404
405static int
406chopen(struct cdev *dev, int flags, int fmt, struct thread *td)
407{
408 struct cam_periph *periph;
409 struct ch_softc *softc;
410 int error;
411 int s;
412
413 periph = (struct cam_periph *)dev->si_drv1;
414 if (periph == NULL)
415 return(ENXIO);
416
417 softc = (struct ch_softc *)periph->softc;
418
419 s = splsoftcam();
420 if (softc->flags & CH_FLAG_INVALID) {
421 splx(s);
422 return(ENXIO);
423 }
424
425 if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) {
426 splx(s);
427 return (error);
428 }
429
430 splx(s);
431
432 if ((softc->flags & CH_FLAG_OPEN) == 0) {
433 if (cam_periph_acquire(periph) != CAM_REQ_CMP)
434 return(ENXIO);
435 softc->flags |= CH_FLAG_OPEN;
436 }
437
438 /*
439 * Load information about this changer device into the softc.
440 */
441 if ((error = chgetparams(periph)) != 0) {
442 softc->flags &= ~CH_FLAG_OPEN;
443 cam_periph_unlock(periph);
444 cam_periph_release(periph);
445 return(error);
446 }
447
448 cam_periph_unlock(periph);
449
450 return(error);
451}
452
453static int
454chclose(struct cdev *dev, int flag, int fmt, struct thread *td)
455{

--- 4 unchanged lines hidden (view full) ---

460 error = 0;
461
462 periph = (struct cam_periph *)dev->si_drv1;
463 if (periph == NULL)
464 return(ENXIO);
465
466 softc = (struct ch_softc *)periph->softc;
467
468 if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
469 return(error);
470
471 softc->flags &= ~CH_FLAG_OPEN;
472
473 cam_periph_unlock(periph);
474 cam_periph_release(periph);
475
476 return(0);
477}
478
479static void
480chstart(struct cam_periph *periph, union ccb *start_ccb)
481{
482 struct ch_softc *softc;
483 int s;
484
485 softc = (struct ch_softc *)periph->softc;
486
487 switch (softc->state) {
488 case CH_STATE_NORMAL:
489 {
490 s = splbio();
491 if (periph->immediate_priority <= periph->pinfo.priority){
492 start_ccb->ccb_h.ccb_state = CH_CCB_WAITING;
493
494 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
495 periph_links.sle);
496 periph->immediate_priority = CAM_PRIORITY_NONE;
497 splx(s);
498 wakeup(&periph->ccb_list);
499 } else
500 splx(s);
501 break;
502 }
503 case CH_STATE_PROBE:
504 {
505 int mode_buffer_len;
506 void *mode_buffer;
507
508 /*

--- 156 unchanged lines hidden (view full) ---

665 * Since our peripheral may be invalidated by an error
666 * above or an external event, we must release our CCB
667 * before releasing the probe lock on the peripheral.
668 * The peripheral will only go away once the last lock
669 * is removed, and we need it around for the CCB release
670 * operation.
671 */
672 xpt_release_ccb(done_ccb);
673 cam_periph_unlock(periph);
674 return;
675 }
676 case CH_CCB_WAITING:
677 {
678 /* Caller will release the CCB */
679 wakeup(&done_ccb->ccb_h.cbfcnp);
680 return;
681 }

--- 22 unchanged lines hidden (view full) ---

704 struct cam_periph *periph;
705 struct ch_softc *softc;
706 int error;
707
708 periph = (struct cam_periph *)dev->si_drv1;
709 if (periph == NULL)
710 return(ENXIO);
711
712 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering chioctl\n"));
713
714 softc = (struct ch_softc *)periph->softc;
715
716 error = 0;
717
718 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
719 ("trying to do ioctl %#lx\n", cmd));

--- 4 unchanged lines hidden (view full) ---

724 */
725 switch (cmd) {
726 case CHIOGPICKER:
727 case CHIOGPARAMS:
728 case CHIOGSTATUS:
729 break;
730
731 default:
732 if ((flag & FWRITE) == 0)
733 return (EBADF);
734 }
735
736 switch (cmd) {
737 case CHIOMOVE:
738 error = chmove(periph, (struct changer_move *)addr);
739 break;
740
741 case CHIOEXCHANGE:

--- 7 unchanged lines hidden (view full) ---

749 case CHIOGPICKER:
750 *(int *)addr = softc->sc_picker - softc->sc_firsts[CHET_MT];
751 break;
752
753 case CHIOSPICKER:
754 {
755 int new_picker = *(int *)addr;
756
757 if (new_picker > (softc->sc_counts[CHET_MT] - 1))
758 return (EINVAL);
759 softc->sc_picker = softc->sc_firsts[CHET_MT] + new_picker;
760 break;
761 }
762 case CHIOGPARAMS:
763 {
764 struct changer_params *cp = (struct changer_params *)addr;
765
766 cp->cp_npickers = softc->sc_counts[CHET_MT];

--- 22 unchanged lines hidden (view full) ---

789
790 /* Implement prevent/allow? */
791
792 default:
793 error = cam_periph_ioctl(periph, cmd, addr, cherror);
794 break;
795 }
796
797 return (error);
798}
799
800static int
801chmove(struct cam_periph *periph, struct changer_move *cm)
802{
803 struct ch_softc *softc;
804 u_int16_t fromelem, toelem;

--- 281 unchanged lines hidden (view full) ---

1086 return (EINVAL);
1087
1088 /*
1089 * Request one descriptor for the given element type. This
1090 * is used to determine the size of the descriptor so that
1091 * we can allocate enough storage for all of them. We assume
1092 * that the first one can fit into 1k.
1093 */
1094 data = (caddr_t)malloc(1024, M_DEVBUF, M_WAITOK);
1095
1096 ccb = cam_periph_getccb(periph, /*priority*/ 1);
1097
1098 scsi_read_element_status(&ccb->csio,
1099 /* retries */ 1,
1100 /* cbfcnp */ chdone,
1101 /* tag_action */ MSG_SIMPLE_Q_TAG,
1102 /* voltag */ want_voltags,
1103 /* sea */ softc->sc_firsts[chet],

--- 4 unchanged lines hidden (view full) ---

1108 /* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS);
1109
1110 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
1111 /*sense_flags*/ SF_RETRY_UA,
1112 softc->device_stats);
1113
1114 if (error)
1115 goto done;
1116
1117 st_hdr = (struct read_element_status_header *)data;
1118 pg_hdr = (struct read_element_status_page_header *)((uintptr_t)st_hdr +
1119 sizeof(struct read_element_status_header));
1120 desclen = scsi_2btoul(pg_hdr->edl);
1121
1122 size = sizeof(struct read_element_status_header) +
1123 sizeof(struct read_element_status_page_header) +
1124 (desclen * cesr->cesr_element_count);
1125
1126 /*
1127 * Reallocate storage for descriptors and get them from the
1128 * device.
1129 */
1130 free(data, M_DEVBUF);
1131 data = (caddr_t)malloc(size, M_DEVBUF, M_WAITOK);
1132
1133 scsi_read_element_status(&ccb->csio,
1134 /* retries */ 1,
1135 /* cbfcnp */ chdone,
1136 /* tag_action */ MSG_SIMPLE_Q_TAG,
1137 /* voltag */ want_voltags,
1138 /* sea */ softc->sc_firsts[chet]
1139 + cesr->cesr_element_base,
1140 /* count */ cesr->cesr_element_count,
1141 /* data_ptr */ data,
1142 /* dxfer_len */ size,
1143 /* sense_len */ SSD_FULL_SIZE,
1144 /* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS);
1145
1146 error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
1147 /*sense_flags*/ SF_RETRY_UA,
1148 softc->device_stats);
1149
1150 if (error)
1151 goto done;
1152
1153 /*
1154 * Fill in the user status array.
1155 */
1156 st_hdr = (struct read_element_status_header *)data;
1157 pg_hdr = (struct read_element_status_page_header *)((uintptr_t)st_hdr +
1158 sizeof(struct read_element_status_header));
1159 avail = scsi_2btoul(st_hdr->count);

--- 21 unchanged lines hidden (view full) ---

1181 desc = (struct read_element_status_descriptor *)
1182 ((uintptr_t)desc + desclen);
1183 }
1184
1185 /* Copy element status structures out to userspace. */
1186 error = copyout(user_data,
1187 cesr->cesr_element_status,
1188 avail * sizeof(struct changer_element_status));
1189
1190 done:
1191 xpt_release_ccb(ccb);
1192
1193 if (data != NULL)
1194 free(data, M_DEVBUF);
1195 if (user_data != NULL)
1196 free(user_data, M_DEVBUF);

--- 488 unchanged lines hidden ---