1 /* $OpenBSD: mpath_sym.c,v 1.21 2014/01/31 02:55:46 dlg Exp $ */ 2 3 /* 4 * Copyright (c) 2010 David Gwynne <dlg@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/buf.h> 22 #include <sys/kernel.h> 23 #include <sys/malloc.h> 24 #include <sys/device.h> 25 #include <sys/proc.h> 26 #include <sys/conf.h> 27 #include <sys/queue.h> 28 #include <sys/rwlock.h> 29 #include <sys/pool.h> 30 #include <sys/ioctl.h> 31 #include <sys/poll.h> 32 #include <sys/selinfo.h> 33 34 #include <scsi/scsi_all.h> 35 #include <scsi/scsiconf.h> 36 #include <scsi/mpathvar.h> 37 38 struct sym_softc { 39 struct device sc_dev; 40 struct mpath_path sc_path; 41 }; 42 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) 43 44 int sym_match(struct device *, void *, void *); 45 void sym_attach(struct device *, struct device *, void *); 46 int sym_detach(struct device *, int); 47 int sym_activate(struct device *, int); 48 49 struct cfattach sym_ca = { 50 sizeof(struct sym_softc), 51 sym_match, 52 sym_attach, 53 sym_detach, 54 sym_activate 55 }; 56 57 struct cfdriver sym_cd = { 58 NULL, 59 "sym", 60 DV_DULL 61 }; 62 63 void sym_mpath_start(struct scsi_xfer *); 64 int sym_mpath_checksense(struct scsi_xfer *); 65 void sym_mpath_status(struct scsi_link *); 66 67 const struct mpath_ops sym_mpath_sym_ops = { 68 "sym", 69 sym_mpath_checksense, 70 sym_mpath_status 71 }; 72 73 const struct mpath_ops sym_mpath_asym_ops = { 74 "sym", 75 sym_mpath_checksense, 76 sym_mpath_status 77 }; 78 79 struct sym_device { 80 char *vendor; 81 char *product; 82 }; 83 84 struct sym_device sym_devices[] = { 85 /* " vendor " " device " */ 86 /* "01234567" "0123456789012345" */ 87 { "TOSHIBA ", "MBF" }, 88 { "SEAGATE ", "ST" }, 89 { "SGI ", "ST" }, 90 { "FUJITSU ", "MBD" }, 91 { "FUJITSU ", "MA" } 92 }; 93 94 struct sym_device asym_devices[] = { 95 /* " vendor " " device " */ 96 /* "01234567" "0123456789012345" */ 97 { "DELL ", "MD1220 " }, 98 { "DELL ", "MD3060e " }, 99 { "SUN ", "StorEdge 3510F D" }, 100 { "SUNW ", "SUNWGS INT FCBPL" }, 101 { "Transtec", "PROVIGO1100" }, 102 { "NetBSD", "NetBSD iSCSI" } 103 }; 104 105 int 106 sym_match(struct device *parent, void *match, void *aux) 107 { 108 struct scsi_attach_args *sa = aux; 109 struct scsi_inquiry_data *inq = sa->sa_inqbuf; 110 struct sym_device *s; 111 int i; 112 113 if (mpath_path_probe(sa->sa_sc_link) != 0) 114 return (0); 115 116 for (i = 0; i < nitems(sym_devices); i++) { 117 s = &sym_devices[i]; 118 119 if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && 120 bcmp(s->product, inq->product, strlen(s->product)) == 0) 121 return (8); 122 } 123 for (i = 0; i < nitems(asym_devices); i++) { 124 s = &asym_devices[i]; 125 126 if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && 127 bcmp(s->product, inq->product, strlen(s->product)) == 0) 128 return (8); 129 } 130 131 return (0); 132 } 133 134 void 135 sym_attach(struct device *parent, struct device *self, void *aux) 136 { 137 struct sym_softc *sc = (struct sym_softc *)self; 138 struct scsi_attach_args *sa = aux; 139 struct scsi_link *link = sa->sa_sc_link; 140 struct scsi_inquiry_data *inq = sa->sa_inqbuf; 141 const struct mpath_ops *ops = &sym_mpath_sym_ops; 142 struct sym_device *s; 143 u_int id = 0; 144 int i; 145 146 printf("\n"); 147 148 /* check if we're an assymetric access device */ 149 for (i = 0; i < nitems(asym_devices); i++) { 150 s = &asym_devices[i]; 151 152 if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && 153 bcmp(s->product, inq->product, strlen(s->product)) == 0) { 154 ops = &sym_mpath_asym_ops; 155 id = sc->sc_dev.dv_unit; 156 break; 157 } 158 } 159 160 /* init link */ 161 link->device_softc = sc; 162 163 /* init path */ 164 scsi_xsh_set(&sc->sc_path.p_xsh, link, sym_mpath_start); 165 sc->sc_path.p_link = link; 166 167 if (mpath_path_attach(&sc->sc_path, id, ops) != 0) 168 printf("%s: unable to attach path\n", DEVNAME(sc)); 169 } 170 171 int 172 sym_detach(struct device *self, int flags) 173 { 174 return (0); 175 } 176 177 int 178 sym_activate(struct device *self, int act) 179 { 180 struct sym_softc *sc = (struct sym_softc *)self; 181 int rv = 0; 182 183 switch (act) { 184 case DVACT_DEACTIVATE: 185 if (sc->sc_path.p_group != NULL) 186 mpath_path_detach(&sc->sc_path); 187 break; 188 } 189 return (rv); 190 } 191 192 void 193 sym_mpath_start(struct scsi_xfer *xs) 194 { 195 struct sym_softc *sc = xs->sc_link->device_softc; 196 197 mpath_start(&sc->sc_path, xs); 198 } 199 200 int 201 sym_mpath_checksense(struct scsi_xfer *xs) 202 { 203 return (MPATH_SENSE_DECLINED); 204 } 205 206 void 207 sym_mpath_status(struct scsi_link *link) 208 { 209 struct sym_softc *sc = link->device_softc; 210 211 mpath_path_status(&sc->sc_path, MPATH_S_ACTIVE); 212 } 213