Line data Source code
1 : /* $OpenBSD: mpath_sym.c,v 1.23 2015/03/14 03:38:52 jsg 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 0 : sym_match(struct device *parent, void *match, void *aux)
105 : {
106 0 : struct scsi_attach_args *sa = aux;
107 0 : struct scsi_inquiry_data *inq = sa->sa_inqbuf;
108 : struct sym_device *s;
109 : int i;
110 :
111 0 : if (mpath_path_probe(sa->sa_sc_link) != 0)
112 0 : return (0);
113 :
114 0 : for (i = 0; i < nitems(sym_devices); i++) {
115 0 : s = &sym_devices[i];
116 :
117 0 : if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 &&
118 0 : bcmp(s->product, inq->product, strlen(s->product)) == 0)
119 0 : return (8);
120 : }
121 0 : for (i = 0; i < nitems(asym_devices); i++) {
122 0 : s = &asym_devices[i];
123 :
124 0 : if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 &&
125 0 : bcmp(s->product, inq->product, strlen(s->product)) == 0)
126 0 : return (8);
127 : }
128 :
129 0 : return (0);
130 0 : }
131 :
132 : void
133 0 : sym_attach(struct device *parent, struct device *self, void *aux)
134 : {
135 0 : struct sym_softc *sc = (struct sym_softc *)self;
136 0 : struct scsi_attach_args *sa = aux;
137 0 : struct scsi_link *link = sa->sa_sc_link;
138 0 : struct scsi_inquiry_data *inq = sa->sa_inqbuf;
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 0 : printf("\n");
145 :
146 : /* check if we're an assymetric access device */
147 0 : for (i = 0; i < nitems(asym_devices); i++) {
148 0 : s = &asym_devices[i];
149 :
150 0 : if (bcmp(s->vendor, inq->vendor, strlen(s->vendor)) == 0 &&
151 0 : bcmp(s->product, inq->product, strlen(s->product)) == 0) {
152 : ops = &sym_mpath_asym_ops;
153 0 : id = sc->sc_dev.dv_unit;
154 0 : break;
155 : }
156 : }
157 :
158 : /* init link */
159 0 : link->device_softc = sc;
160 :
161 : /* init path */
162 0 : scsi_xsh_set(&sc->sc_path.p_xsh, link, sym_mpath_start);
163 0 : sc->sc_path.p_link = link;
164 :
165 0 : if (mpath_path_attach(&sc->sc_path, id, ops) != 0)
166 0 : printf("%s: unable to attach path\n", DEVNAME(sc));
167 0 : }
168 :
169 : int
170 0 : sym_detach(struct device *self, int flags)
171 : {
172 0 : return (0);
173 : }
174 :
175 : int
176 0 : sym_activate(struct device *self, int act)
177 : {
178 0 : struct sym_softc *sc = (struct sym_softc *)self;
179 : int rv = 0;
180 :
181 0 : switch (act) {
182 : case DVACT_DEACTIVATE:
183 0 : if (sc->sc_path.p_group != NULL)
184 0 : mpath_path_detach(&sc->sc_path);
185 : break;
186 : }
187 0 : return (rv);
188 : }
189 :
190 : void
191 0 : sym_mpath_start(struct scsi_xfer *xs)
192 : {
193 0 : struct sym_softc *sc = xs->sc_link->device_softc;
194 :
195 0 : mpath_start(&sc->sc_path, xs);
196 0 : }
197 :
198 : int
199 0 : sym_mpath_checksense(struct scsi_xfer *xs)
200 : {
201 0 : return (MPATH_SENSE_DECLINED);
202 : }
203 :
204 : void
205 0 : sym_mpath_status(struct scsi_link *link)
206 : {
207 0 : struct sym_softc *sc = link->device_softc;
208 :
209 0 : mpath_path_status(&sc->sc_path, MPATH_S_ACTIVE);
210 0 : }
|