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