1 /* $OpenBSD: mpath_sym.c,v 1.6 2011/07/11 01:02:48 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 int sym_mpath_online(struct scsi_link *); 66 int sym_mpath_offline(struct scsi_link *); 67 68 const struct mpath_ops sym_mpath_sym_ops = { 69 "sym", 70 sym_mpath_checksense, 71 sym_mpath_online, 72 sym_mpath_offline, 73 MPATH_ROUNDROBIN 74 }; 75 76 const struct mpath_ops sym_mpath_asym_ops = { 77 "sym", 78 sym_mpath_checksense, 79 sym_mpath_online, 80 sym_mpath_offline, 81 MPATH_MRU 82 }; 83 84 struct sym_device { 85 char *vendor; 86 char *product; 87 }; 88 89 struct sym_device sym_devices[] = { 90 /* " vendor " " device " */ 91 /* "01234567" "0123456789012345" */ 92 { "SEAGATE ", "ST" }, 93 { "FUJITSU ", "MBD" } 94 }; 95 96 struct sym_device asym_devices[] = { 97 /* " vendor " " device " */ 98 /* "01234567" "0123456789012345" */ 99 { "DELL ", "MD1220 " }, 100 { "Transtec", "PROVIGO1100" } 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_inqbuf; 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 (3); 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 (3); 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 = sa->sa_inqbuf; 139 const struct mpath_ops *ops = &sym_mpath_sym_ops; 140 struct sym_device *s; 141 int i; 142 143 printf("\n"); 144 145 /* check if we're an assymetric access device */ 146 for (i = 0; i < nitems(asym_devices); i++) { 147 s = &asym_devices[i]; 148 149 if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && 150 bcmp(s->product, inq->product, strlen(s->product)) == 0) { 151 ops = &sym_mpath_asym_ops; 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, 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 int rv = 0; 178 179 switch (act) { 180 case DVACT_SUSPEND: 181 case DVACT_RESUME: 182 break; 183 case DVACT_DEACTIVATE: 184 if (sc->sc_path.p_dev != NULL) 185 mpath_path_detach(&sc->sc_path); 186 break; 187 } 188 return (rv); 189 } 190 191 void 192 sym_mpath_start(struct scsi_xfer *xs) 193 { 194 struct sym_softc *sc = xs->sc_link->device_softc; 195 196 mpath_start(&sc->sc_path, xs); 197 } 198 199 int 200 sym_mpath_checksense(struct scsi_xfer *xs) 201 { 202 return (0); 203 } 204 205 int 206 sym_mpath_online(struct scsi_link *link) 207 { 208 return (0); 209 } 210 211 int 212 sym_mpath_offline(struct scsi_link *link) 213 { 214 return (0); 215 } 216