1 /* $NetBSD: sbpscsi.c,v 1.7 2004/02/13 21:22:13 enami Exp $ */
2
3 /*
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by James Chacon.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: sbpscsi.c,v 1.7 2004/02/13 21:22:13 enami Exp $");
41
42 #include <sys/param.h>
43 #include <sys/kernel.h>
44 #include <sys/device.h>
45 #include <sys/systm.h>
46 #include <sys/malloc.h>
47 #include <sys/buf.h>
48
49 #include <machine/bus.h>
50 #include <machine/limits.h>
51
52 #include <dev/scsipi/scsi_all.h>
53 #include <dev/scsipi/scsipi_all.h>
54 #include <dev/scsipi/scsiconf.h>
55
56 #include <dev/ieee1394/ieee1394reg.h>
57 #include <dev/ieee1394/ieee1394var.h>
58 #include <dev/ieee1394/sbp2reg.h>
59 #include <dev/ieee1394/sbp2var.h>
60 #include <dev/ieee1394/sbpscsireg.h>
61 #include <dev/ieee1394/sbpscsivar.h>
62
63 #ifdef SBPSCSI_DEBUG
64 #define DPRINTF(x) if (sbpscsidebug) printf x
65 #define DPRINTFN(n,x) if (sbpscsidebug>(n)) printf x
66 int sbpscsidebug = 3;
67 #else
68 #define DPRINTF(x)
69 #define DPRINTFN(n,x)
70 #endif
71
72 static int sbpscsi_match(struct device *, struct cfdata *, void *);
73 static void sbpscsi_attach(struct device *, struct device *, void *);
74 static int sbpscsi_detach(struct device *, int);
75 static void sbpscsi_scsipi_request(struct scsipi_channel *,
76 scsipi_adapter_req_t, void *);
77 static void sbpscsi_status(struct sbp2_status *, void *);
78 static void sbpscsi_timeout(void *);
79 static void sbpscsi_minphys(struct buf *);
80
81 CFATTACH_DECL(sbpscsi, sizeof(struct sbpscsi_softc),
82 sbpscsi_match, sbpscsi_attach, sbpscsi_detach, NULL);
83
84 static int
85 sbpscsi_match(struct device *parent, struct cfdata *match, void *aux)
86 {
87 struct p1212_dir **udirs = aux;
88 struct sbp2* sbp2;
89 struct sbp2_lun *lun;
90 int ret;
91
92 sbp2 = NULL;
93 ret = 0;
94 if (sbp2_match(*udirs)) {
95 sbp2 = sbp2_init((struct ieee1394_softc *) parent, *udirs);
96 TAILQ_FOREACH(lun, &sbp2->luns, lun_list) {
97 if ((lun->cmd_spec_id == SBPSCSI_COMMAND_SET_SPEC_ID) &&
98 (lun->cmd_set == SBPSCSI_COMMAND_SET))
99 ret = 1;
100 }
101 }
102 if (sbp2)
103 sbp2_free(sbp2);
104 return ret;
105 }
106
107 static void
108 sbpscsi_attach(struct device *parent, struct device *self, void *aux)
109 {
110 struct p1212_dir **udirs = aux;
111 struct sbpscsi_softc *sc = (struct sbpscsi_softc *)self;
112 struct ieee1394_softc *psc = (struct ieee1394_softc *) parent;
113 int found;
114
115 found = 0;
116
117 if (sbp2_match(*udirs)) {
118 sc->sbp2 = sbp2_init(psc, *udirs);
119 found = 1;
120 }
121
122 if (!found) {
123 DPRINTF(("Can't match an SBP capable scsi lun?"));
124 return;
125 }
126
127 sc->sc_adapter.adapt_dev = &sc->sc_dev;
128 sc->sc_adapter.adapt_nchannels = 1;
129 sc->sc_adapter.adapt_max_periph = 1;
130 sc->sc_adapter.adapt_request = sbpscsi_scsipi_request;
131 sc->sc_adapter.adapt_minphys = sbpscsi_minphys;
132 sc->sc_adapter.adapt_openings = 8; /*Start with some. Grow as needed.*/
133
134 sc->sc_channel.chan_adapter = &sc->sc_adapter;
135 sc->sc_channel.chan_bustype = &scsi_bustype;
136 sc->sc_channel.chan_defquirks = PQUIRK_ONLYBIG;
137 sc->sc_channel.chan_channel = 0;
138 sc->sc_channel.chan_flags = SCSIPI_CHAN_CANGROW | SCSIPI_CHAN_NOSETTLE;
139
140 sc->sc_channel.chan_ntargets = 1;
141 sc->sc_channel.chan_nluns = sc->sbp2->luncnt;
142 sc->sc_channel.chan_id = 1;
143
144 printf("\n");
145
146 sc->sc_bus = config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
147
148 return;
149 }
150
151 static int
152 sbpscsi_detach(struct device *self, int flags)
153 {
154 struct sbpscsi_softc *sc = (struct sbpscsi_softc *)self;
155
156 if (sc->sbp2)
157 sbp2_free(sc->sbp2);
158 if (sc->sc_bus)
159 config_detach(sc->sc_bus, 0);
160 return 0;
161 }
162
163 static void
164 sbpscsi_scsipi_request(struct scsipi_channel *channel, scsipi_adapter_req_t req,
165 void *arg)
166 {
167 int i;
168 void *handle;
169 struct sbpscsi_softc *sc =
170 (struct sbpscsi_softc *)channel->chan_adapter->adapt_dev;
171 struct sbp2 *sbp2 = sc->sbp2;
172 struct scsipi_xfer *xs = arg;
173 struct sbp2_cmd cmd;
174
175 DPRINTFN(1, ("Called sbpscsi_scsipi_request\n"));
176
177 switch (req) {
178 case ADAPTER_REQ_RUN_XFER:
179 DPRINTFN(1, ("Got req_run_xfer\n"));
180 DPRINTFN(1, ("xs control: 0x%08x, timeout: %d\n",
181 xs->xs_control, xs->timeout));
182 DPRINTFN(1, ("opcode: 0x%02x\n", (int)xs->cmd->opcode));
183 for (i = 0; i < 15; i++)
184 DPRINTFN(1, ("0x%02x ",(int)xs->cmd->bytes[i]));
185 DPRINTFN(1, ("\n"));
186 if (xs->xs_control & XS_CTL_RESET) {
187 sbp2_reset_lun(sbp2, xs->xs_periph->periph_lun);
188 return;
189 }
190 if (xs->cmdlen > SBPSCSI_SBP2_MAX_CDB) {
191 DPRINTF(("sbp doesn't support cdb's larger than %d "
192 "bytes\n", SBPSCSI_SBP2_MAX_CDB));
193 xs->error = XS_DRIVER_STUFFUP;
194 scsipi_done(xs);
195 return;
196 }
197 cmd.lun = xs->xs_periph->periph_lun;
198 cmd.data = xs->data;
199 cmd.datalen = xs->datalen;
200 memset(cmd.cmd, 0, 12);
201 cmd.cmd[0] = xs->cmd->opcode;
202 for (i = 0; i < xs->cmdlen; i++)
203 cmd.cmd[i + 1] = xs->cmd->bytes[i];
204 cmd.cmdlen = 12;
205 if (xs->xs_control & XS_CTL_DATA_IN)
206 cmd.rw = SBP_WRITE;
207 if (xs->xs_control & XS_CTL_DATA_OUT)
208 cmd.rw = SBP_READ;
209 cmd.cb = sbpscsi_status;
210 cmd.cb_arg = xs;
211 handle = sbp2_runcmd(sbp2, &cmd);
212 if (handle)
213 callout_reset(&xs->xs_callout, mstohz(xs->timeout),
214 sbpscsi_timeout, handle);
215 else {
216 DPRINTF(("Got an error from sbp2_runcmd\n"));
217 xs->error = XS_DRIVER_STUFFUP;
218 scsipi_done(xs);
219 }
220 break;
221 case ADAPTER_REQ_GROW_RESOURCES:
222 DPRINTFN(1, ("Got req_grow_resources\n"));
223 break;
224 case ADAPTER_REQ_SET_XFER_MODE:
225 DPRINTFN(1, ("Got set xfer mode\n"));
226 break;
227 default:
228 panic("Unknown request: %d\n", (int)req);
229 }
230 }
231
232 static void
233 sbpscsi_timeout(void *arg)
234 {
235 struct scsipi_xfer *xs;
236
237 xs = sbp2_abort(arg);
238
239 xs->error = XS_TIMEOUT;
240 scsipi_done(xs);
241 }
242
243 static void
244 sbpscsi_status(struct sbp2_status *status, void *arg)
245 {
246 struct scsipi_xfer *xs = arg;
247 u_int8_t smft, vflag, iflag, mflag, eflag;
248
249 callout_stop(&xs->xs_callout);
250
251 DPRINTFN(1, ("status: resp 0x%04x, sbp_status 0x%04x\n", status->resp,
252 status->sbp_status));
253
254 if ((status->resp != SBP2_STATUS_REQUEST_COMPLETE) ||
255 (status->sbp_status != SBP2_STATUS_NOERROR)) {
256 #ifdef SBPSCSI_DEBUG
257 #endif
258 } else {
259 xs->error = XS_NOERROR;
260 xs->resid = 0;
261 }
262
263 if (status->datalen) {
264 xs->sense.scsi_sense.error_code =
265 SBPSCSI_STATUS_GET_STATUS(status->data[0]);
266 vflag = SBPSCSI_STATUS_GET_VFLAG(status->data[0]);
267 mflag = SBPSCSI_STATUS_GET_MFLAG(status->data[0]);
268 eflag = SBPSCSI_STATUS_GET_EFLAG(status->data[0]);
269 iflag = SBPSCSI_STATUS_GET_IFLAG(status->data[0]);
270 smft = SBPSCSI_STATUS_GET_SMFT(status->data[0]);
271
272 if (iflag)
273 xs->sense.scsi_sense.flags |= SSD_ILI;
274 if (eflag)
275 xs->sense.scsi_sense.flags |= SSD_EOM;
276 if (mflag)
277 xs->sense.scsi_sense.flags |= SSD_FILEMARK;
278 xs->sense.scsi_sense.flags |=
279 SBPSCSI_STATUS_GET_SENSEKEY(status->data[0]);
280 if (((smft == 0) || (smft == 1)) && vflag) {
281 xs->sense.scsi_sense.info[0] =
282 (status->data[1] & 0xff000000) >> 24;
283 xs->sense.scsi_sense.info[1] =
284 (status->data[1] & 0x00ff0000) >> 16;
285 xs->sense.scsi_sense.info[2] =
286 (status->data[1] & 0x0000ff00) >> 8;
287 xs->sense.scsi_sense.info[3] =
288 status->data[1] & 0x000000ff;
289 }
290 xs->sense.scsi_sense.cmd_spec_info[0] =
291 (status->data[2] & 0xff000000) >> 24;
292 xs->sense.scsi_sense.cmd_spec_info[1] =
293 (status->data[2] & 0x00ff0000) >> 16;
294 xs->sense.scsi_sense.cmd_spec_info[2] =
295 (status->data[2] & 0x0000ff00) >> 8;
296 xs->sense.scsi_sense.cmd_spec_info[3] =
297 status->data[2] & 0x000000ff;
298 xs->sense.scsi_sense.add_sense_code =
299 SBPSCSI_STATUS_GET_SENSECODE(status->data[0]);
300 xs->sense.scsi_sense.add_sense_code_qual =
301 SBPSCSI_STATUS_GET_SENSEQUAL(status->data[0]);
302 xs->sense.scsi_sense.fru =
303 SBPSCSI_STATUS_GET_FRU(status->data[3]);
304 xs->sense.scsi_sense.sense_key_spec_1 =
305 SBPSCSI_STATUS_GET_SENSE1(status->data[3]);
306 xs->sense.scsi_sense.sense_key_spec_2 =
307 SBPSCSI_STATUS_GET_SENSE2(status->data[3]);
308 xs->sense.scsi_sense.sense_key_spec_3 =
309 SBPSCSI_STATUS_GET_SENSE3(status->data[3]);
310 }
311 scsipi_done(xs);
312 }
313
314 static void
315 sbpscsi_minphys(bp)
316 struct buf *bp;
317 {
318
319 minphys(bp);
320 }
Cache object: 064cba45e7f7f7b2bdd2ea2b3a2dc851
|