1 /* $OpenBSD: mpath_sym.c,v 1.25 2020/06/30 18:43:37 krw 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/kernel.h> 22 #include <sys/malloc.h> 23 #include <sys/device.h> 24 #include <sys/conf.h> 25 #include <sys/queue.h> 26 #include <sys/rwlock.h> 27 #include <sys/pool.h> 28 #include <sys/ioctl.h> 29 #include <sys/poll.h> 30 #include <sys/selinfo.h> 31 32 #include <scsi/scsi_all.h> 33 #include <scsi/scsiconf.h> 34 #include <scsi/mpathvar.h> 35 36 struct sym_softc { 37 struct device sc_dev; 38 struct mpath_path sc_path; 39 }; 40 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) 41 42 int sym_match(struct device *, void *, void *); 43 void sym_attach(struct device *, struct device *, void *); 44 int sym_detach(struct device *, int); 45 int sym_activate(struct device *, int); 46 47 struct cfattach sym_ca = { 48 sizeof(struct sym_softc), 49 sym_match, 50 sym_attach, 51 sym_detach, 52 sym_activate 53 }; 54 55 struct cfdriver sym_cd = { 56 NULL, 57 "sym", 58 DV_DULL 59 }; 60 61 void sym_mpath_start(struct scsi_xfer *); 62 int sym_mpath_checksense(struct scsi_xfer *); 63 void sym_mpath_status(struct scsi_link *); 64 65 const struct mpath_ops sym_mpath_sym_ops = { 66 "sym", 67 sym_mpath_checksense, 68 sym_mpath_status 69 }; 70 71 const struct mpath_ops sym_mpath_asym_ops = { 72 "sym", 73 sym_mpath_checksense, 74 sym_mpath_status 75 }; 76 77 struct sym_device { 78 char *vendor; 79 char *product; 80 }; 81 82 struct sym_device sym_devices[] = { 83 /* " vendor " " device " */ 84 /* "01234567" "0123456789012345" */ 85 { "TOSHIBA ", "MBF" }, 86 { "SEAGATE ", "ST" }, 87 { "SGI ", "ST" }, 88 { "FUJITSU ", "MBD" }, 89 { "FUJITSU ", "MA" } 90 }; 91 92 struct sym_device asym_devices[] = { 93 /* " vendor " " device " */ 94 /* "01234567" "0123456789012345" */ 95 { "DELL ", "MD1220 " }, 96 { "DELL ", "MD3060e " }, 97 { "SUN ", "StorEdge 3510F D" }, 98 { "SUNW ", "SUNWGS INT FCBPL" }, 99 { "Transtec", "PROVIGO1100" }, 100 { "NetBSD", "NetBSD iSCSI" } 101 }; 102 103 int 104 sym_match(struct device *parent, void *match, void *aux) 105 { 106 struct scsi_attach_args *sa = aux; 107 struct scsi_inquiry_data *inq = &sa->sa_sc_link->inqdata; 108 struct sym_device *s; 109 int i; 110 111 if (mpath_path_probe(sa->sa_sc_link) != 0) 112 return (0); 113 114 for (i = 0; i < nitems(sym_devices); i++) { 115 s = &sym_devices[i]; 116 117 if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && 118 bcmp(s->product, inq->product, strlen(s->product)) == 0) 119 return (8); 120 } 121 for (i = 0; i < nitems(asym_devices); i++) { 122 s = &asym_devices[i]; 123 124 if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && 125 bcmp(s->product, inq->product, strlen(s->product)) == 0) 126 return (8); 127 } 128 129 return (0); 130 } 131 132 void 133 sym_attach(struct device *parent, struct device *self, void *aux) 134 { 135 struct sym_softc *sc = (struct sym_softc *)self; 136 struct scsi_attach_args *sa = aux; 137 struct scsi_link *link = sa->sa_sc_link; 138 struct scsi_inquiry_data *inq = &link->inqdata; 139 const struct mpath_ops *ops = &sym_mpath_sym_ops; 140 struct sym_device *s; 141 u_int id = 0; 142 int i; 143 144 printf("\n"); 145 146 /* check if we're an assymetric access device */ 147 for (i = 0; i < nitems(asym_devices); i++) { 148 s = &asym_devices[i]; 149 150 if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && 151 bcmp(s->product, inq->product, strlen(s->product)) == 0) { 152 ops = &sym_mpath_asym_ops; 153 id = sc->sc_dev.dv_unit; 154 break; 155 } 156 } 157 158 /* init link */ 159 link->device_softc = sc; 160 161 /* init path */ 162 scsi_xsh_set(&sc->sc_path.p_xsh, link, sym_mpath_start); 163 sc->sc_path.p_link = link; 164 165 if (mpath_path_attach(&sc->sc_path, id, ops) != 0) 166 printf("%s: unable to attach path\n", DEVNAME(sc)); 167 } 168 169 int 170 sym_detach(struct device *self, int flags) 171 { 172 return (0); 173 } 174 175 int 176 sym_activate(struct device *self, int act) 177 { 178 struct sym_softc *sc = (struct sym_softc *)self; 179 180 switch (act) { 181 case DVACT_DEACTIVATE: 182 if (sc->sc_path.p_group != NULL) 183 mpath_path_detach(&sc->sc_path); 184 break; 185 } 186 return (0); 187 } 188 189 void 190 sym_mpath_start(struct scsi_xfer *xs) 191 { 192 struct sym_softc *sc = xs->sc_link->device_softc; 193 194 mpath_start(&sc->sc_path, xs); 195 } 196 197 int 198 sym_mpath_checksense(struct scsi_xfer *xs) 199 { 200 return (MPATH_SENSE_DECLINED); 201 } 202 203 void 204 sym_mpath_status(struct scsi_link *link) 205 { 206 struct sym_softc *sc = link->device_softc; 207 208 mpath_path_status(&sc->sc_path, MPATH_S_ACTIVE); 209 } 210