1 /* $OpenBSD: mpath_sym.c,v 1.7 2012/03/23 13:46:47 claudio 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 { "NetBSD", "NetBSD iSCSI" } 102 }; 103 104 int 105 sym_match(struct device *parent, void *match, void *aux) 106 { 107 struct scsi_attach_args *sa = aux; 108 struct scsi_inquiry_data *inq = sa->sa_inqbuf; 109 struct sym_device *s; 110 int i; 111 112 if (mpath_path_probe(sa->sa_sc_link) != 0) 113 return (0); 114 115 for (i = 0; i < nitems(sym_devices); i++) { 116 s = &sym_devices[i]; 117 118 if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && 119 bcmp(s->product, inq->product, strlen(s->product)) == 0) 120 return (3); 121 } 122 for (i = 0; i < nitems(asym_devices); i++) { 123 s = &asym_devices[i]; 124 125 if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 && 126 bcmp(s->product, inq->product, strlen(s->product)) == 0) 127 return (3); 128 } 129 130 return (0); 131 } 132 133 void 134 sym_attach(struct device *parent, struct device *self, void *aux) 135 { 136 struct sym_softc *sc = (struct sym_softc *)self; 137 struct scsi_attach_args *sa = aux; 138 struct scsi_link *link = sa->sa_sc_link; 139 struct scsi_inquiry_data *inq = sa->sa_inqbuf; 140 const struct mpath_ops *ops = &sym_mpath_sym_ops; 141 struct sym_device *s; 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 break; 154 } 155 } 156 157 /* init link */ 158 link->device_softc = sc; 159 160 /* init path */ 161 scsi_xsh_set(&sc->sc_path.p_xsh, link, sym_mpath_start); 162 sc->sc_path.p_link = link; 163 164 if (mpath_path_attach(&sc->sc_path, ops) != 0) 165 printf("%s: unable to attach path\n", DEVNAME(sc)); 166 } 167 168 int 169 sym_detach(struct device *self, int flags) 170 { 171 return (0); 172 } 173 174 int 175 sym_activate(struct device *self, int act) 176 { 177 struct sym_softc *sc = (struct sym_softc *)self; 178 int rv = 0; 179 180 switch (act) { 181 case DVACT_SUSPEND: 182 case DVACT_RESUME: 183 break; 184 case DVACT_DEACTIVATE: 185 if (sc->sc_path.p_dev != 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 (0); 204 } 205 206 int 207 sym_mpath_online(struct scsi_link *link) 208 { 209 return (0); 210 } 211 212 int 213 sym_mpath_offline(struct scsi_link *link) 214 { 215 return (0); 216 } 217