Deleted Added
full compact
scsi_ctl.c (275365) scsi_ctl.c (275942)
1/*-
2 * Copyright (c) 2008, 2009 Silicon Graphics International Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * substantially similar to the "NO WARRANTY" disclaimer below
13 * ("Disclaimer") and any redistribution must be conditioned upon
14 * including a substantially similar Disclaimer requirement for further
15 * binary redistribution.
16 *
17 * NO WARRANTY
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGES.
29 *
30 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/scsi_ctl.c#4 $
31 */
32/*
33 * Peripheral driver interface between CAM and CTL (CAM Target Layer).
34 *
35 * Author: Ken Merry <ken@FreeBSD.org>
36 */
37
38#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2008, 2009 Silicon Graphics International Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * substantially similar to the "NO WARRANTY" disclaimer below
13 * ("Disclaimer") and any redistribution must be conditioned upon
14 * including a substantially similar Disclaimer requirement for further
15 * binary redistribution.
16 *
17 * NO WARRANTY
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGES.
29 *
30 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/scsi_ctl.c#4 $
31 */
32/*
33 * Peripheral driver interface between CAM and CTL (CAM Target Layer).
34 *
35 * Author: Ken Merry <ken@FreeBSD.org>
36 */
37
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: head/sys/cam/ctl/scsi_ctl.c 275365 2014-12-01 13:55:45Z mav $");
39__FBSDID("$FreeBSD: head/sys/cam/ctl/scsi_ctl.c 275942 2014-12-19 20:35:06Z mav $");
40
41#include <sys/param.h>
42#include <sys/queue.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>
45#include <sys/lock.h>
46#include <sys/mutex.h>
47#include <sys/condvar.h>
48#include <sys/malloc.h>
49#include <sys/bus.h>
50#include <sys/endian.h>
51#include <sys/sbuf.h>
52#include <sys/sysctl.h>
53#include <sys/types.h>
54#include <sys/systm.h>
55#include <machine/bus.h>
56
57#include <cam/cam.h>
58#include <cam/cam_ccb.h>
59#include <cam/cam_periph.h>
60#include <cam/cam_queue.h>
61#include <cam/cam_xpt_periph.h>
62#include <cam/cam_debug.h>
63#include <cam/cam_sim.h>
64#include <cam/cam_xpt.h>
65
66#include <cam/scsi/scsi_all.h>
67#include <cam/scsi/scsi_message.h>
68
69#include <cam/ctl/ctl_io.h>
70#include <cam/ctl/ctl.h>
71#include <cam/ctl/ctl_frontend.h>
72#include <cam/ctl/ctl_util.h>
73#include <cam/ctl/ctl_error.h>
74
75struct ctlfe_softc {
76 struct ctl_port port;
77 path_id_t path_id;
78 u_int maxio;
79 struct cam_sim *sim;
80 char port_name[DEV_IDLEN];
81 struct mtx lun_softc_mtx;
82 STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list;
83 STAILQ_ENTRY(ctlfe_softc) links;
84};
85
86STAILQ_HEAD(, ctlfe_softc) ctlfe_softc_list;
87struct mtx ctlfe_list_mtx;
88static char ctlfe_mtx_desc[] = "ctlfelist";
89#ifdef CTLFE_INIT_ENABLE
90static int ctlfe_max_targets = 1;
91static int ctlfe_num_targets = 0;
92#endif
93
94typedef enum {
95 CTLFE_LUN_NONE = 0x00,
96 CTLFE_LUN_WILDCARD = 0x01
97} ctlfe_lun_flags;
98
99struct ctlfe_lun_softc {
100 struct ctlfe_softc *parent_softc;
101 struct cam_periph *periph;
102 ctlfe_lun_flags flags;
103 uint64_t ccbs_alloced;
104 uint64_t ccbs_freed;
105 uint64_t ctios_sent;
106 uint64_t ctios_returned;
107 uint64_t atios_sent;
108 uint64_t atios_returned;
109 uint64_t inots_sent;
110 uint64_t inots_returned;
111 /* bus_dma_tag_t dma_tag; */
112 TAILQ_HEAD(, ccb_hdr) work_queue;
113 STAILQ_ENTRY(ctlfe_lun_softc) links;
114};
115
116typedef enum {
117 CTLFE_CMD_NONE = 0x00,
118 CTLFE_CMD_PIECEWISE = 0x01
119} ctlfe_cmd_flags;
120
121/*
122 * The size limit of this structure is CTL_PORT_PRIV_SIZE, from ctl_io.h.
123 * Currently that is 600 bytes.
124 */
125struct ctlfe_lun_cmd_info {
126 int cur_transfer_index;
127 size_t cur_transfer_off;
128 ctlfe_cmd_flags flags;
129 /*
130 * XXX KDM struct bus_dma_segment is 8 bytes on i386, and 16
131 * bytes on amd64. So with 32 elements, this is 256 bytes on
132 * i386 and 512 bytes on amd64.
133 */
134#define CTLFE_MAX_SEGS 32
135 bus_dma_segment_t cam_sglist[CTLFE_MAX_SEGS];
136};
137CTASSERT(sizeof(struct ctlfe_lun_cmd_info) <= CTL_PORT_PRIV_SIZE);
138
139/*
140 * When we register the adapter/bus, request that this many ctl_ios be
141 * allocated. This should be the maximum supported by the adapter, but we
142 * currently don't have a way to get that back from the path inquiry.
143 * XXX KDM add that to the path inquiry.
144 */
145#define CTLFE_REQ_CTL_IO 4096
146/*
147 * Number of Accept Target I/O CCBs to allocate and queue down to the
148 * adapter per LUN.
149 * XXX KDM should this be controlled by CTL?
150 */
151#define CTLFE_ATIO_PER_LUN 1024
152/*
153 * Number of Immediate Notify CCBs (used for aborts, resets, etc.) to
154 * allocate and queue down to the adapter per LUN.
155 * XXX KDM should this be controlled by CTL?
156 */
157#define CTLFE_IN_PER_LUN 1024
158
159/*
160 * Timeout (in seconds) on CTIO CCB allocation for doing a DMA or sending
161 * status to the initiator. The SIM is expected to have its own timeouts,
162 * so we're not putting this timeout around the CCB execution time. The
163 * SIM should timeout and let us know if it has an issue.
164 */
165#define CTLFE_DMA_TIMEOUT 60
166
167/*
168 * Turn this on to enable extra debugging prints.
169 */
170#if 0
171#define CTLFE_DEBUG
172#endif
173
174/*
175 * Use randomly assigned WWNN/WWPN values. This is to work around an issue
176 * in the FreeBSD initiator that makes it unable to rescan the target if
177 * the target gets rebooted and the WWNN/WWPN stay the same.
178 */
179#if 0
180#define RANDOM_WWNN
181#endif
182
183MALLOC_DEFINE(M_CTLFE, "CAM CTL FE", "CAM CTL FE interface");
184
185#define io_ptr ppriv_ptr0
186
187/* This is only used in the CTIO */
188#define ccb_atio ppriv_ptr1
189
190int ctlfeinitialize(void);
191void ctlfeshutdown(void);
192static periph_init_t ctlfeperiphinit;
193static void ctlfeasync(void *callback_arg, uint32_t code,
194 struct cam_path *path, void *arg);
195static periph_ctor_t ctlferegister;
196static periph_oninv_t ctlfeoninvalidate;
197static periph_dtor_t ctlfecleanup;
198static periph_start_t ctlfestart;
199static void ctlfedone(struct cam_periph *periph,
200 union ccb *done_ccb);
201
202static void ctlfe_onoffline(void *arg, int online);
203static void ctlfe_online(void *arg);
204static void ctlfe_offline(void *arg);
205static int ctlfe_lun_enable(void *arg, struct ctl_id targ_id,
206 int lun_id);
207static int ctlfe_lun_disable(void *arg, struct ctl_id targ_id,
208 int lun_id);
209static void ctlfe_dump_sim(struct cam_sim *sim);
210static void ctlfe_dump_queue(struct ctlfe_lun_softc *softc);
211static void ctlfe_datamove(union ctl_io *io);
212static void ctlfe_done(union ctl_io *io);
213static void ctlfe_dump(void);
214
215static struct periph_driver ctlfe_driver =
216{
217 ctlfeperiphinit, "ctl",
218 TAILQ_HEAD_INITIALIZER(ctlfe_driver.units), /*generation*/ 0,
219 CAM_PERIPH_DRV_EARLY
220};
221
222static struct ctl_frontend ctlfe_frontend =
223{
224 .name = "camtgt",
225 .init = ctlfeinitialize,
226 .fe_dump = ctlfe_dump,
227 .shutdown = ctlfeshutdown,
228};
229CTL_FRONTEND_DECLARE(ctlfe, ctlfe_frontend);
230
40
41#include <sys/param.h>
42#include <sys/queue.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>
45#include <sys/lock.h>
46#include <sys/mutex.h>
47#include <sys/condvar.h>
48#include <sys/malloc.h>
49#include <sys/bus.h>
50#include <sys/endian.h>
51#include <sys/sbuf.h>
52#include <sys/sysctl.h>
53#include <sys/types.h>
54#include <sys/systm.h>
55#include <machine/bus.h>
56
57#include <cam/cam.h>
58#include <cam/cam_ccb.h>
59#include <cam/cam_periph.h>
60#include <cam/cam_queue.h>
61#include <cam/cam_xpt_periph.h>
62#include <cam/cam_debug.h>
63#include <cam/cam_sim.h>
64#include <cam/cam_xpt.h>
65
66#include <cam/scsi/scsi_all.h>
67#include <cam/scsi/scsi_message.h>
68
69#include <cam/ctl/ctl_io.h>
70#include <cam/ctl/ctl.h>
71#include <cam/ctl/ctl_frontend.h>
72#include <cam/ctl/ctl_util.h>
73#include <cam/ctl/ctl_error.h>
74
75struct ctlfe_softc {
76 struct ctl_port port;
77 path_id_t path_id;
78 u_int maxio;
79 struct cam_sim *sim;
80 char port_name[DEV_IDLEN];
81 struct mtx lun_softc_mtx;
82 STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list;
83 STAILQ_ENTRY(ctlfe_softc) links;
84};
85
86STAILQ_HEAD(, ctlfe_softc) ctlfe_softc_list;
87struct mtx ctlfe_list_mtx;
88static char ctlfe_mtx_desc[] = "ctlfelist";
89#ifdef CTLFE_INIT_ENABLE
90static int ctlfe_max_targets = 1;
91static int ctlfe_num_targets = 0;
92#endif
93
94typedef enum {
95 CTLFE_LUN_NONE = 0x00,
96 CTLFE_LUN_WILDCARD = 0x01
97} ctlfe_lun_flags;
98
99struct ctlfe_lun_softc {
100 struct ctlfe_softc *parent_softc;
101 struct cam_periph *periph;
102 ctlfe_lun_flags flags;
103 uint64_t ccbs_alloced;
104 uint64_t ccbs_freed;
105 uint64_t ctios_sent;
106 uint64_t ctios_returned;
107 uint64_t atios_sent;
108 uint64_t atios_returned;
109 uint64_t inots_sent;
110 uint64_t inots_returned;
111 /* bus_dma_tag_t dma_tag; */
112 TAILQ_HEAD(, ccb_hdr) work_queue;
113 STAILQ_ENTRY(ctlfe_lun_softc) links;
114};
115
116typedef enum {
117 CTLFE_CMD_NONE = 0x00,
118 CTLFE_CMD_PIECEWISE = 0x01
119} ctlfe_cmd_flags;
120
121/*
122 * The size limit of this structure is CTL_PORT_PRIV_SIZE, from ctl_io.h.
123 * Currently that is 600 bytes.
124 */
125struct ctlfe_lun_cmd_info {
126 int cur_transfer_index;
127 size_t cur_transfer_off;
128 ctlfe_cmd_flags flags;
129 /*
130 * XXX KDM struct bus_dma_segment is 8 bytes on i386, and 16
131 * bytes on amd64. So with 32 elements, this is 256 bytes on
132 * i386 and 512 bytes on amd64.
133 */
134#define CTLFE_MAX_SEGS 32
135 bus_dma_segment_t cam_sglist[CTLFE_MAX_SEGS];
136};
137CTASSERT(sizeof(struct ctlfe_lun_cmd_info) <= CTL_PORT_PRIV_SIZE);
138
139/*
140 * When we register the adapter/bus, request that this many ctl_ios be
141 * allocated. This should be the maximum supported by the adapter, but we
142 * currently don't have a way to get that back from the path inquiry.
143 * XXX KDM add that to the path inquiry.
144 */
145#define CTLFE_REQ_CTL_IO 4096
146/*
147 * Number of Accept Target I/O CCBs to allocate and queue down to the
148 * adapter per LUN.
149 * XXX KDM should this be controlled by CTL?
150 */
151#define CTLFE_ATIO_PER_LUN 1024
152/*
153 * Number of Immediate Notify CCBs (used for aborts, resets, etc.) to
154 * allocate and queue down to the adapter per LUN.
155 * XXX KDM should this be controlled by CTL?
156 */
157#define CTLFE_IN_PER_LUN 1024
158
159/*
160 * Timeout (in seconds) on CTIO CCB allocation for doing a DMA or sending
161 * status to the initiator. The SIM is expected to have its own timeouts,
162 * so we're not putting this timeout around the CCB execution time. The
163 * SIM should timeout and let us know if it has an issue.
164 */
165#define CTLFE_DMA_TIMEOUT 60
166
167/*
168 * Turn this on to enable extra debugging prints.
169 */
170#if 0
171#define CTLFE_DEBUG
172#endif
173
174/*
175 * Use randomly assigned WWNN/WWPN values. This is to work around an issue
176 * in the FreeBSD initiator that makes it unable to rescan the target if
177 * the target gets rebooted and the WWNN/WWPN stay the same.
178 */
179#if 0
180#define RANDOM_WWNN
181#endif
182
183MALLOC_DEFINE(M_CTLFE, "CAM CTL FE", "CAM CTL FE interface");
184
185#define io_ptr ppriv_ptr0
186
187/* This is only used in the CTIO */
188#define ccb_atio ppriv_ptr1
189
190int ctlfeinitialize(void);
191void ctlfeshutdown(void);
192static periph_init_t ctlfeperiphinit;
193static void ctlfeasync(void *callback_arg, uint32_t code,
194 struct cam_path *path, void *arg);
195static periph_ctor_t ctlferegister;
196static periph_oninv_t ctlfeoninvalidate;
197static periph_dtor_t ctlfecleanup;
198static periph_start_t ctlfestart;
199static void ctlfedone(struct cam_periph *periph,
200 union ccb *done_ccb);
201
202static void ctlfe_onoffline(void *arg, int online);
203static void ctlfe_online(void *arg);
204static void ctlfe_offline(void *arg);
205static int ctlfe_lun_enable(void *arg, struct ctl_id targ_id,
206 int lun_id);
207static int ctlfe_lun_disable(void *arg, struct ctl_id targ_id,
208 int lun_id);
209static void ctlfe_dump_sim(struct cam_sim *sim);
210static void ctlfe_dump_queue(struct ctlfe_lun_softc *softc);
211static void ctlfe_datamove(union ctl_io *io);
212static void ctlfe_done(union ctl_io *io);
213static void ctlfe_dump(void);
214
215static struct periph_driver ctlfe_driver =
216{
217 ctlfeperiphinit, "ctl",
218 TAILQ_HEAD_INITIALIZER(ctlfe_driver.units), /*generation*/ 0,
219 CAM_PERIPH_DRV_EARLY
220};
221
222static struct ctl_frontend ctlfe_frontend =
223{
224 .name = "camtgt",
225 .init = ctlfeinitialize,
226 .fe_dump = ctlfe_dump,
227 .shutdown = ctlfeshutdown,
228};
229CTL_FRONTEND_DECLARE(ctlfe, ctlfe_frontend);
230
231extern struct ctl_softc *control_softc;
232
233void
234ctlfeshutdown(void)
235{
236 return;
237}
238
239int
240ctlfeinitialize(void)
241{
242
243 STAILQ_INIT(&ctlfe_softc_list);
244 mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF);
245 periphdriver_register(&ctlfe_driver);
246 return (0);
247}
248
249void
250ctlfeperiphinit(void)
251{
252 cam_status status;
253
254 status = xpt_register_async(AC_PATH_REGISTERED | AC_PATH_DEREGISTERED |
255 AC_CONTRACT, ctlfeasync, NULL, NULL);
256 if (status != CAM_REQ_CMP) {
257 printf("ctl: Failed to attach async callback due to CAM "
258 "status 0x%x!\n", status);
259 }
260}
261
262static void
263ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
264{
265 struct ctlfe_softc *softc;
266
267#ifdef CTLFEDEBUG
268 printf("%s: entered\n", __func__);
269#endif
270
271 mtx_lock(&ctlfe_list_mtx);
272 STAILQ_FOREACH(softc, &ctlfe_softc_list, links) {
273 if (softc->path_id == xpt_path_path_id(path))
274 break;
275 }
276 mtx_unlock(&ctlfe_list_mtx);
277
278 /*
279 * When a new path gets registered, and it is capable of target
280 * mode, go ahead and attach. Later on, we may need to be more
281 * selective, but for now this will be sufficient.
282 */
283 switch (code) {
284 case AC_PATH_REGISTERED: {
285 struct ctl_port *port;
286 struct ccb_pathinq *cpi;
287 int retval;
288
289 cpi = (struct ccb_pathinq *)arg;
290
291 /* Don't attach if it doesn't support target mode */
292 if ((cpi->target_sprt & PIT_PROCESSOR) == 0) {
293#ifdef CTLFEDEBUG
294 printf("%s: SIM %s%d doesn't support target mode\n",
295 __func__, cpi->dev_name, cpi->unit_number);
296#endif
297 break;
298 }
299
300 if (softc != NULL) {
301#ifdef CTLFEDEBUG
302 printf("%s: CTL port for CAM path %u already exists\n",
303 __func__, xpt_path_path_id(path));
304#endif
305 break;
306 }
307
308#ifdef CTLFE_INIT_ENABLE
309 if (ctlfe_num_targets >= ctlfe_max_targets) {
310 union ccb *ccb;
311
312 ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP,
313 M_NOWAIT | M_ZERO);
314 if (ccb == NULL) {
315 printf("%s: unable to malloc CCB!\n", __func__);
316 return;
317 }
318 xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
319
320 ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
321 ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
322 ccb->knob.xport_specific.fc.role = KNOB_ROLE_INITIATOR;
323
324 xpt_action(ccb);
325
326 if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
327 CAM_REQ_CMP) {
328 printf("%s: SIM %s%d (path id %d) initiator "
329 "enable failed with status %#x\n",
330 __func__, cpi->dev_name,
331 cpi->unit_number, cpi->ccb_h.path_id,
332 ccb->ccb_h.status);
333 } else {
334 printf("%s: SIM %s%d (path id %d) initiator "
335 "enable succeeded\n",
336 __func__, cpi->dev_name,
337 cpi->unit_number, cpi->ccb_h.path_id);
338 }
339
340 free(ccb, M_TEMP);
341
342 break;
343 } else {
344 ctlfe_num_targets++;
345 }
346
347 printf("%s: ctlfe_num_targets = %d\n", __func__,
348 ctlfe_num_targets);
349#endif /* CTLFE_INIT_ENABLE */
350
351 /*
352 * We're in an interrupt context here, so we have to
353 * use M_NOWAIT. Of course this means trouble if we
354 * can't allocate memory.
355 */
356 softc = malloc(sizeof(*softc), M_CTLFE, M_NOWAIT | M_ZERO);
357 if (softc == NULL) {
358 printf("%s: unable to malloc %zd bytes for softc\n",
359 __func__, sizeof(*softc));
360 return;
361 }
362
363 softc->path_id = cpi->ccb_h.path_id;
364 softc->sim = xpt_path_sim(path);
365 if (cpi->maxio != 0)
366 softc->maxio = cpi->maxio;
367 else
368 softc->maxio = DFLTPHYS;
369 mtx_init(&softc->lun_softc_mtx, "LUN softc mtx", NULL, MTX_DEF);
370 STAILQ_INIT(&softc->lun_softc_list);
371
372 port = &softc->port;
373 port->frontend = &ctlfe_frontend;
374
375 /*
376 * XXX KDM should we be more accurate here ?
377 */
378 if (cpi->transport == XPORT_FC)
379 port->port_type = CTL_PORT_FC;
380 else if (cpi->transport == XPORT_SAS)
381 port->port_type = CTL_PORT_SAS;
382 else
383 port->port_type = CTL_PORT_SCSI;
384
385 /* XXX KDM what should the real number be here? */
386 port->num_requested_ctl_io = 4096;
387 snprintf(softc->port_name, sizeof(softc->port_name),
388 "%s%d", cpi->dev_name, cpi->unit_number);
389 /*
390 * XXX KDM it would be nice to allocate storage in the
391 * frontend structure itself.
392 */
393 port->port_name = softc->port_name;
394 port->physical_port = cpi->bus_id;
395 port->virtual_port = 0;
396 port->port_online = ctlfe_online;
397 port->port_offline = ctlfe_offline;
398 port->onoff_arg = softc;
399 port->lun_enable = ctlfe_lun_enable;
400 port->lun_disable = ctlfe_lun_disable;
401 port->targ_lun_arg = softc;
402 port->fe_datamove = ctlfe_datamove;
403 port->fe_done = ctlfe_done;
404 /*
405 * XXX KDM the path inquiry doesn't give us the maximum
406 * number of targets supported.
407 */
408 port->max_targets = cpi->max_target;
409 port->max_target_id = cpi->max_target;
410
411 /*
412 * XXX KDM need to figure out whether we're the master or
413 * slave.
414 */
415#ifdef CTLFEDEBUG
416 printf("%s: calling ctl_port_register() for %s%d\n",
417 __func__, cpi->dev_name, cpi->unit_number);
418#endif
419 retval = ctl_port_register(port);
420 if (retval != 0) {
421 printf("%s: ctl_port_register() failed with "
422 "error %d!\n", __func__, retval);
423 mtx_destroy(&softc->lun_softc_mtx);
424 free(softc, M_CTLFE);
425 break;
426 } else {
427 mtx_lock(&ctlfe_list_mtx);
428 STAILQ_INSERT_TAIL(&ctlfe_softc_list, softc, links);
429 mtx_unlock(&ctlfe_list_mtx);
430 }
431
432 break;
433 }
434 case AC_PATH_DEREGISTERED: {
435
436 if (softc != NULL) {
437 /*
438 * XXX KDM are we certain at this point that there
439 * are no outstanding commands for this frontend?
440 */
441 mtx_lock(&ctlfe_list_mtx);
442 STAILQ_REMOVE(&ctlfe_softc_list, softc, ctlfe_softc,
443 links);
444 mtx_unlock(&ctlfe_list_mtx);
445 ctl_port_deregister(&softc->port);
446 mtx_destroy(&softc->lun_softc_mtx);
447 free(softc, M_CTLFE);
448 }
449 break;
450 }
451 case AC_CONTRACT: {
452 struct ac_contract *ac;
453
454 ac = (struct ac_contract *)arg;
455
456 switch (ac->contract_number) {
457 case AC_CONTRACT_DEV_CHG: {
458 struct ac_device_changed *dev_chg;
459 int retval;
460
461 dev_chg = (struct ac_device_changed *)ac->contract_data;
462
463 printf("%s: WWPN %#jx port 0x%06x path %u target %u %s\n",
464 __func__, dev_chg->wwpn, dev_chg->port,
465 xpt_path_path_id(path), dev_chg->target,
466 (dev_chg->arrived == 0) ? "left" : "arrived");
467
468 if (softc == NULL) {
469 printf("%s: CTL port for CAM path %u not "
470 "found!\n", __func__,
471 xpt_path_path_id(path));
472 break;
473 }
474 if (dev_chg->arrived != 0) {
475 retval = ctl_add_initiator(&softc->port,
476 dev_chg->target, dev_chg->wwpn, NULL);
477 } else {
478 retval = ctl_remove_initiator(&softc->port,
479 dev_chg->target);
480 }
481
482 if (retval < 0) {
483 printf("%s: could not %s port %d iid %u "
484 "WWPN %#jx!\n", __func__,
485 (dev_chg->arrived != 0) ? "add" :
486 "remove", softc->port.targ_port,
487 dev_chg->target,
488 (uintmax_t)dev_chg->wwpn);
489 }
490 break;
491 }
492 default:
493 printf("%s: unsupported contract number %ju\n",
494 __func__, (uintmax_t)ac->contract_number);
495 break;
496 }
497 break;
498 }
499 default:
500 break;
501 }
502}
503
504static cam_status
505ctlferegister(struct cam_periph *periph, void *arg)
506{
507 struct ctlfe_softc *bus_softc;
508 struct ctlfe_lun_softc *softc;
509 union ccb en_lun_ccb;
510 cam_status status;
511 int i;
512
513 softc = (struct ctlfe_lun_softc *)arg;
514 bus_softc = softc->parent_softc;
515
516 TAILQ_INIT(&softc->work_queue);
517 softc->periph = periph;
518 periph->softc = softc;
519
520 xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE);
521 en_lun_ccb.ccb_h.func_code = XPT_EN_LUN;
522 en_lun_ccb.cel.grp6_len = 0;
523 en_lun_ccb.cel.grp7_len = 0;
524 en_lun_ccb.cel.enable = 1;
525 xpt_action(&en_lun_ccb);
526 status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK);
527 if (status != CAM_REQ_CMP) {
528 xpt_print(periph->path, "%s: Enable LUN failed, status 0x%x\n",
529 __func__, en_lun_ccb.ccb_h.status);
530 return (status);
531 }
532
533 status = CAM_REQ_CMP;
534
535 for (i = 0; i < CTLFE_ATIO_PER_LUN; i++) {
536 union ccb *new_ccb;
537 union ctl_io *new_io;
538
539 new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
540 M_ZERO|M_NOWAIT);
541 if (new_ccb == NULL) {
542 status = CAM_RESRC_UNAVAIL;
543 break;
544 }
545 new_io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref);
546 if (new_io == NULL) {
547 free(new_ccb, M_CTLFE);
548 status = CAM_RESRC_UNAVAIL;
549 break;
550 }
551 new_ccb->ccb_h.io_ptr = new_io;
552
553 xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
554 new_ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
555 new_ccb->ccb_h.cbfcnp = ctlfedone;
556 new_ccb->ccb_h.flags |= CAM_UNLOCKED;
557 xpt_action(new_ccb);
558 softc->atios_sent++;
559 status = new_ccb->ccb_h.status;
560 if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
561 ctl_free_io(new_io);
562 free(new_ccb, M_CTLFE);
563 break;
564 }
565 }
566
567 status = cam_periph_acquire(periph);
568 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
569 xpt_print(periph->path, "%s: could not acquire reference "
570 "count, status = %#x\n", __func__, status);
571 return (status);
572 }
573
574 if (i == 0) {
575 xpt_print(periph->path, "%s: could not allocate ATIO CCBs, "
576 "status 0x%x\n", __func__, status);
577 return (CAM_REQ_CMP_ERR);
578 }
579
580 for (i = 0; i < CTLFE_IN_PER_LUN; i++) {
581 union ccb *new_ccb;
582 union ctl_io *new_io;
583
584 new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
585 M_ZERO|M_NOWAIT);
586 if (new_ccb == NULL) {
587 status = CAM_RESRC_UNAVAIL;
588 break;
589 }
590 new_io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref);
591 if (new_io == NULL) {
592 free(new_ccb, M_CTLFE);
593 status = CAM_RESRC_UNAVAIL;
594 break;
595 }
596 new_ccb->ccb_h.io_ptr = new_io;
597
598 xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
599 new_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
600 new_ccb->ccb_h.cbfcnp = ctlfedone;
601 new_ccb->ccb_h.flags |= CAM_UNLOCKED;
602 xpt_action(new_ccb);
603 softc->inots_sent++;
604 status = new_ccb->ccb_h.status;
605 if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
606 /*
607 * Note that we don't free the CCB here. If the
608 * status is not CAM_REQ_INPROG, then we're
609 * probably talking to a SIM that says it is
610 * target-capable but doesn't support the
611 * XPT_IMMEDIATE_NOTIFY CCB. i.e. it supports the
612 * older API. In that case, it'll call xpt_done()
613 * on the CCB, and we need to free it in our done
614 * routine as a result.
615 */
616 break;
617 }
618 }
619 if ((i == 0)
620 || (status != CAM_REQ_INPROG)) {
621 xpt_print(periph->path, "%s: could not allocate immediate "
622 "notify CCBs, status 0x%x\n", __func__, status);
623 return (CAM_REQ_CMP_ERR);
624 }
625 mtx_lock(&bus_softc->lun_softc_mtx);
626 STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, softc, links);
627 mtx_unlock(&bus_softc->lun_softc_mtx);
628 return (CAM_REQ_CMP);
629}
630
631static void
632ctlfeoninvalidate(struct cam_periph *periph)
633{
634 union ccb en_lun_ccb;
635 cam_status status;
636 struct ctlfe_softc *bus_softc;
637 struct ctlfe_lun_softc *softc;
638
639 softc = (struct ctlfe_lun_softc *)periph->softc;
640
641 xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE);
642 en_lun_ccb.ccb_h.func_code = XPT_EN_LUN;
643 en_lun_ccb.cel.grp6_len = 0;
644 en_lun_ccb.cel.grp7_len = 0;
645 en_lun_ccb.cel.enable = 0;
646 xpt_action(&en_lun_ccb);
647 status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK);
648 if (status != CAM_REQ_CMP) {
649 xpt_print(periph->path, "%s: Disable LUN failed, status 0x%x\n",
650 __func__, en_lun_ccb.ccb_h.status);
651 /*
652 * XXX KDM what do we do now?
653 */
654 }
655 xpt_print(periph->path, "LUN removed, %ju ATIOs outstanding, %ju "
656 "INOTs outstanding, %d refs\n", softc->atios_sent -
657 softc->atios_returned, softc->inots_sent -
658 softc->inots_returned, periph->refcount);
659
660 bus_softc = softc->parent_softc;
661 mtx_lock(&bus_softc->lun_softc_mtx);
662 STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links);
663 mtx_unlock(&bus_softc->lun_softc_mtx);
664}
665
666static void
667ctlfecleanup(struct cam_periph *periph)
668{
669 struct ctlfe_lun_softc *softc;
670
671 xpt_print(periph->path, "%s: Called\n", __func__);
672
673 softc = (struct ctlfe_lun_softc *)periph->softc;
674
675 /*
676 * XXX KDM is there anything else that needs to be done here?
677 */
678
679 free(softc, M_CTLFE);
680}
681
682static void
683ctlfedata(struct ctlfe_lun_softc *softc, union ctl_io *io,
684 ccb_flags *flags, uint8_t **data_ptr, uint32_t *dxfer_len,
685 u_int16_t *sglist_cnt)
686{
687 struct ctlfe_softc *bus_softc;
688 struct ctlfe_lun_cmd_info *cmd_info;
689 struct ctl_sg_entry *ctl_sglist;
690 bus_dma_segment_t *cam_sglist;
691 size_t off;
692 int i, idx;
693
694 cmd_info = (struct ctlfe_lun_cmd_info *)io->io_hdr.port_priv;
695 bus_softc = softc->parent_softc;
696
697 /*
698 * Set the direction, relative to the initiator.
699 */
700 *flags &= ~CAM_DIR_MASK;
701 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN)
702 *flags |= CAM_DIR_IN;
703 else
704 *flags |= CAM_DIR_OUT;
705
706 *flags &= ~CAM_DATA_MASK;
707 idx = cmd_info->cur_transfer_index;
708 off = cmd_info->cur_transfer_off;
709 cmd_info->flags &= ~CTLFE_CMD_PIECEWISE;
710 if (io->scsiio.kern_sg_entries == 0) {
711 /* No S/G list. */
712 *data_ptr = io->scsiio.kern_data_ptr + off;
713 if (io->scsiio.kern_data_len - off <= bus_softc->maxio) {
714 *dxfer_len = io->scsiio.kern_data_len - off;
715 } else {
716 *dxfer_len = bus_softc->maxio;
717 cmd_info->cur_transfer_index = -1;
718 cmd_info->cur_transfer_off = bus_softc->maxio;
719 cmd_info->flags |= CTLFE_CMD_PIECEWISE;
720 }
721 *sglist_cnt = 0;
722
723 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
724 *flags |= CAM_DATA_PADDR;
725 else
726 *flags |= CAM_DATA_VADDR;
727 } else {
728 /* S/G list with physical or virtual pointers. */
729 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
730 cam_sglist = cmd_info->cam_sglist;
731 *dxfer_len = 0;
732 for (i = 0; i < io->scsiio.kern_sg_entries - idx; i++) {
733 cam_sglist[i].ds_addr = (bus_addr_t)ctl_sglist[i + idx].addr + off;
734 if (ctl_sglist[i + idx].len - off <= bus_softc->maxio - *dxfer_len) {
735 cam_sglist[i].ds_len = ctl_sglist[idx + i].len - off;
736 *dxfer_len += cam_sglist[i].ds_len;
737 } else {
738 cam_sglist[i].ds_len = bus_softc->maxio - *dxfer_len;
739 cmd_info->cur_transfer_index = idx + i;
740 cmd_info->cur_transfer_off = cam_sglist[i].ds_len + off;
741 cmd_info->flags |= CTLFE_CMD_PIECEWISE;
742 *dxfer_len += cam_sglist[i].ds_len;
743 if (ctl_sglist[i].len != 0)
744 i++;
745 break;
746 }
747 if (i == (CTLFE_MAX_SEGS - 1) &&
748 idx + i < (io->scsiio.kern_sg_entries - 1)) {
749 cmd_info->cur_transfer_index = idx + i + 1;
750 cmd_info->cur_transfer_off = 0;
751 cmd_info->flags |= CTLFE_CMD_PIECEWISE;
752 i++;
753 break;
754 }
755 off = 0;
756 }
757 *sglist_cnt = i;
758 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
759 *flags |= CAM_DATA_SG_PADDR;
760 else
761 *flags |= CAM_DATA_SG;
762 *data_ptr = (uint8_t *)cam_sglist;
763 }
764}
765
766static void
767ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
768{
769 struct ctlfe_lun_softc *softc;
770 struct ctlfe_lun_cmd_info *cmd_info;
771 struct ccb_hdr *ccb_h;
772 struct ccb_accept_tio *atio;
773 struct ccb_scsiio *csio;
774 uint8_t *data_ptr;
775 uint32_t dxfer_len;
776 ccb_flags flags;
777 union ctl_io *io;
778 uint8_t scsi_status;
779
780 softc = (struct ctlfe_lun_softc *)periph->softc;
781 softc->ccbs_alloced++;
782
783 ccb_h = TAILQ_FIRST(&softc->work_queue);
784 if (ccb_h == NULL) {
785 softc->ccbs_freed++;
786 xpt_release_ccb(start_ccb);
787 return;
788 }
789
790 /* Take the ATIO off the work queue */
791 TAILQ_REMOVE(&softc->work_queue, ccb_h, periph_links.tqe);
792 atio = (struct ccb_accept_tio *)ccb_h;
793 io = (union ctl_io *)ccb_h->io_ptr;
794 csio = &start_ccb->csio;
795
796 flags = atio->ccb_h.flags &
797 (CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK);
798 cmd_info = (struct ctlfe_lun_cmd_info *)io->io_hdr.port_priv;
799 cmd_info->cur_transfer_index = 0;
800 cmd_info->cur_transfer_off = 0;
801 cmd_info->flags = 0;
802
803 if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) {
804 /*
805 * Datamove call, we need to setup the S/G list.
806 */
807 scsi_status = 0;
808 csio->cdb_len = atio->cdb_len;
809 ctlfedata(softc, io, &flags, &data_ptr, &dxfer_len,
810 &csio->sglist_cnt);
811 io->scsiio.ext_data_filled += dxfer_len;
812 if (io->scsiio.ext_data_filled > io->scsiio.kern_total_len) {
813 xpt_print(periph->path, "%s: tag 0x%04x "
814 "fill len %u > total %u\n",
815 __func__, io->scsiio.tag_num,
816 io->scsiio.ext_data_filled,
817 io->scsiio.kern_total_len);
818 }
819 } else {
820 /*
821 * We're done, send status back.
822 */
823 if ((io->io_hdr.flags & CTL_FLAG_ABORT) &&
824 (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) {
825 io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED;
826
827 /*
828 * If this command was aborted, we don't
829 * need to send status back to the SIM.
830 * Just free the CTIO and ctl_io, and
831 * recycle the ATIO back to the SIM.
832 */
833 xpt_print(periph->path, "%s: aborted "
834 "command 0x%04x discarded\n",
835 __func__, io->scsiio.tag_num);
836 /*
837 * For a wildcard attachment, commands can
838 * come in with a specific target/lun. Reset
839 * the target and LUN fields back to the
840 * wildcard values before we send them back
841 * down to the SIM. The SIM has a wildcard
842 * LUN enabled, not whatever target/lun
843 * these happened to be.
844 */
845 if (softc->flags & CTLFE_LUN_WILDCARD) {
846 atio->ccb_h.target_id = CAM_TARGET_WILDCARD;
847 atio->ccb_h.target_lun = CAM_LUN_WILDCARD;
848 }
849
850 if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
851 cam_release_devq(periph->path,
852 /*relsim_flags*/0,
853 /*reduction*/0,
854 /*timeout*/0,
855 /*getcount_only*/0);
856 atio->ccb_h.status &= ~CAM_DEV_QFRZN;
857 }
858
859 if (atio->ccb_h.func_code != XPT_ACCEPT_TARGET_IO) {
860 xpt_print(periph->path, "%s: func_code "
861 "is %#x\n", __func__,
862 atio->ccb_h.func_code);
863 }
864 start_ccb->ccb_h.func_code = XPT_ABORT;
865 start_ccb->cab.abort_ccb = (union ccb *)atio;
866
867 /* Tell the SIM that we've aborted this ATIO */
868 xpt_action(start_ccb);
869 softc->ccbs_freed++;
870 xpt_release_ccb(start_ccb);
871
872 /*
873 * Send the ATIO back down to the SIM.
874 */
875 xpt_action((union ccb *)atio);
876 softc->atios_sent++;
877
878 /*
879 * If we still have work to do, ask for
880 * another CCB. Otherwise, deactivate our
881 * callout.
882 */
883 if (!TAILQ_EMPTY(&softc->work_queue))
884 xpt_schedule(periph, /*priority*/ 1);
885 return;
886 }
887 data_ptr = NULL;
888 dxfer_len = 0;
889 csio->sglist_cnt = 0;
890 scsi_status = 0;
891 }
892 if ((io->io_hdr.flags & CTL_FLAG_STATUS_QUEUED) &&
893 (cmd_info->flags & CTLFE_CMD_PIECEWISE) == 0 &&
894 ((io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) == 0 ||
895 io->io_hdr.status == CTL_SUCCESS)) {
896 io->io_hdr.flags |= CTL_FLAG_STATUS_SENT;
897 flags |= CAM_SEND_STATUS;
898 scsi_status = io->scsiio.scsi_status;
899 csio->sense_len = io->scsiio.sense_len;
900#ifdef CTLFEDEBUG
901 printf("%s: tag %04x status %x\n", __func__,
902 atio->tag_id, io->io_hdr.status);
903#endif
904 if (csio->sense_len != 0) {
905 csio->sense_data = io->scsiio.sense_data;
906 flags |= CAM_SEND_SENSE;
907 } else if (scsi_status == SCSI_STATUS_CHECK_COND) {
908 xpt_print(periph->path, "%s: check condition "
909 "with no sense\n", __func__);
910 }
911 }
912
913#ifdef CTLFEDEBUG
914 printf("%s: %s: tag %04x flags %x ptr %p len %u\n", __func__,
915 (flags & CAM_SEND_STATUS) ? "done" : "datamove",
916 atio->tag_id, flags, data_ptr, dxfer_len);
917#endif
918
919 /*
920 * Valid combinations:
921 * - CAM_SEND_STATUS, CAM_DATA_SG = 0, dxfer_len = 0,
922 * sglist_cnt = 0
923 * - CAM_SEND_STATUS = 0, CAM_DATA_SG = 0, dxfer_len != 0,
924 * sglist_cnt = 0
925 * - CAM_SEND_STATUS = 0, CAM_DATA_SG, dxfer_len != 0,
926 * sglist_cnt != 0
927 */
928#ifdef CTLFEDEBUG
929 if (((flags & CAM_SEND_STATUS)
930 && (((flags & CAM_DATA_SG) != 0)
931 || (dxfer_len != 0)
932 || (csio->sglist_cnt != 0)))
933 || (((flags & CAM_SEND_STATUS) == 0)
934 && (dxfer_len == 0))
935 || ((flags & CAM_DATA_SG)
936 && (csio->sglist_cnt == 0))
937 || (((flags & CAM_DATA_SG) == 0)
938 && (csio->sglist_cnt != 0))) {
939 printf("%s: tag %04x cdb %02x flags %#x dxfer_len "
940 "%d sg %u\n", __func__, atio->tag_id,
941 atio->cdb_io.cdb_bytes[0], flags, dxfer_len,
942 csio->sglist_cnt);
943 printf("%s: tag %04x io status %#x\n", __func__,
944 atio->tag_id, io->io_hdr.status);
945 }
946#endif
947 cam_fill_ctio(csio,
948 /*retries*/ 2,
949 ctlfedone,
950 flags,
951 (flags & CAM_TAG_ACTION_VALID) ? MSG_SIMPLE_Q_TAG : 0,
952 atio->tag_id,
953 atio->init_id,
954 scsi_status,
955 /*data_ptr*/ data_ptr,
956 /*dxfer_len*/ dxfer_len,
957 /*timeout*/ 5 * 1000);
958 start_ccb->ccb_h.flags |= CAM_UNLOCKED;
959 start_ccb->ccb_h.ccb_atio = atio;
960 if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED)
961 io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
962 io->io_hdr.flags &= ~(CTL_FLAG_DMA_QUEUED | CTL_FLAG_STATUS_QUEUED);
963
964 softc->ctios_sent++;
965
966 cam_periph_unlock(periph);
967 xpt_action(start_ccb);
968 cam_periph_lock(periph);
969
970 if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
971 cam_release_devq(periph->path,
972 /*relsim_flags*/0,
973 /*reduction*/0,
974 /*timeout*/0,
975 /*getcount_only*/0);
976 atio->ccb_h.status &= ~CAM_DEV_QFRZN;
977 }
978
979 /*
980 * If we still have work to do, ask for another CCB.
981 */
982 if (!TAILQ_EMPTY(&softc->work_queue))
983 xpt_schedule(periph, /*priority*/ 1);
984}
985
986static void
987ctlfe_free_ccb(struct cam_periph *periph, union ccb *ccb)
988{
989 struct ctlfe_lun_softc *softc;
990
991 softc = (struct ctlfe_lun_softc *)periph->softc;
992
993 switch (ccb->ccb_h.func_code) {
994 case XPT_ACCEPT_TARGET_IO:
995 softc->atios_returned++;
996 break;
997 case XPT_IMMEDIATE_NOTIFY:
998 case XPT_NOTIFY_ACKNOWLEDGE:
999 softc->inots_returned++;
1000 break;
1001 default:
1002 break;
1003 }
1004
1005 ctl_free_io(ccb->ccb_h.io_ptr);
1006 free(ccb, M_CTLFE);
1007
1008 KASSERT(softc->atios_returned <= softc->atios_sent, ("%s: "
1009 "atios_returned %ju > atios_sent %ju", __func__,
1010 softc->atios_returned, softc->atios_sent));
1011 KASSERT(softc->inots_returned <= softc->inots_sent, ("%s: "
1012 "inots_returned %ju > inots_sent %ju", __func__,
1013 softc->inots_returned, softc->inots_sent));
1014
1015 /*
1016 * If we have received all of our CCBs, we can release our
1017 * reference on the peripheral driver. It will probably go away
1018 * now.
1019 */
1020 if ((softc->atios_returned == softc->atios_sent)
1021 && (softc->inots_returned == softc->inots_sent)) {
1022 cam_periph_release_locked(periph);
1023 }
1024}
1025
1026static int
1027ctlfe_adjust_cdb(struct ccb_accept_tio *atio, uint32_t offset)
1028{
1029 uint64_t lba;
1030 uint32_t num_blocks, nbc;
1031 uint8_t *cmdbyt = (atio->ccb_h.flags & CAM_CDB_POINTER)?
1032 atio->cdb_io.cdb_ptr : atio->cdb_io.cdb_bytes;
1033
1034 nbc = offset >> 9; /* ASSUMING 512 BYTE BLOCKS */
1035
1036 switch (cmdbyt[0]) {
1037 case READ_6:
1038 case WRITE_6:
1039 {
1040 struct scsi_rw_6 *cdb = (struct scsi_rw_6 *)cmdbyt;
1041 lba = scsi_3btoul(cdb->addr);
1042 lba &= 0x1fffff;
1043 num_blocks = cdb->length;
1044 if (num_blocks == 0)
1045 num_blocks = 256;
1046 lba += nbc;
1047 num_blocks -= nbc;
1048 scsi_ulto3b(lba, cdb->addr);
1049 cdb->length = num_blocks;
1050 break;
1051 }
1052 case READ_10:
1053 case WRITE_10:
1054 {
1055 struct scsi_rw_10 *cdb = (struct scsi_rw_10 *)cmdbyt;
1056 lba = scsi_4btoul(cdb->addr);
1057 num_blocks = scsi_2btoul(cdb->length);
1058 lba += nbc;
1059 num_blocks -= nbc;
1060 scsi_ulto4b(lba, cdb->addr);
1061 scsi_ulto2b(num_blocks, cdb->length);
1062 break;
1063 }
1064 case READ_12:
1065 case WRITE_12:
1066 {
1067 struct scsi_rw_12 *cdb = (struct scsi_rw_12 *)cmdbyt;
1068 lba = scsi_4btoul(cdb->addr);
1069 num_blocks = scsi_4btoul(cdb->length);
1070 lba += nbc;
1071 num_blocks -= nbc;
1072 scsi_ulto4b(lba, cdb->addr);
1073 scsi_ulto4b(num_blocks, cdb->length);
1074 break;
1075 }
1076 case READ_16:
1077 case WRITE_16:
1078 case WRITE_ATOMIC_16:
1079 {
1080 struct scsi_rw_16 *cdb = (struct scsi_rw_16 *)cmdbyt;
1081 lba = scsi_8btou64(cdb->addr);
1082 num_blocks = scsi_4btoul(cdb->length);
1083 lba += nbc;
1084 num_blocks -= nbc;
1085 scsi_u64to8b(lba, cdb->addr);
1086 scsi_ulto4b(num_blocks, cdb->length);
1087 break;
1088 }
1089 default:
1090 return -1;
1091 }
1092 return (0);
1093}
1094
1095static void
1096ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
1097{
1098 struct ctlfe_lun_softc *softc;
1099 struct ctlfe_softc *bus_softc;
1100 struct ccb_accept_tio *atio = NULL;
1101 union ctl_io *io = NULL;
1102 struct mtx *mtx;
1103
1104 KASSERT((done_ccb->ccb_h.flags & CAM_UNLOCKED) != 0,
1105 ("CCB in ctlfedone() without CAM_UNLOCKED flag"));
1106#ifdef CTLFE_DEBUG
1107 printf("%s: entered, func_code = %#x\n", __func__,
1108 done_ccb->ccb_h.func_code);
1109#endif
1110
1111 softc = (struct ctlfe_lun_softc *)periph->softc;
1112 bus_softc = softc->parent_softc;
1113 mtx = cam_periph_mtx(periph);
1114 mtx_lock(mtx);
1115
1116 /*
1117 * If the peripheral is invalid, ATIOs and immediate notify CCBs
1118 * need to be freed. Most of the ATIOs and INOTs that come back
1119 * will be CCBs that are being returned from the SIM as a result of
1120 * our disabling the LUN.
1121 *
1122 * Other CCB types are handled in their respective cases below.
1123 */
1124 if (periph->flags & CAM_PERIPH_INVALID) {
1125 switch (done_ccb->ccb_h.func_code) {
1126 case XPT_ACCEPT_TARGET_IO:
1127 case XPT_IMMEDIATE_NOTIFY:
1128 case XPT_NOTIFY_ACKNOWLEDGE:
1129 ctlfe_free_ccb(periph, done_ccb);
1130 goto out;
1131 default:
1132 break;
1133 }
1134
1135 }
1136 switch (done_ccb->ccb_h.func_code) {
1137 case XPT_ACCEPT_TARGET_IO: {
1138
1139 atio = &done_ccb->atio;
1140
1141 softc->atios_returned++;
1142
1143 resubmit:
1144 /*
1145 * Allocate a ctl_io, pass it to CTL, and wait for the
1146 * datamove or done.
1147 */
1148 mtx_unlock(mtx);
1149 io = done_ccb->ccb_h.io_ptr;
1150 ctl_zero_io(io);
1151
1152 /* Save pointers on both sides */
1153 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = done_ccb;
1154 done_ccb->ccb_h.io_ptr = io;
1155
1156 /*
1157 * Only SCSI I/O comes down this path, resets, etc. come
1158 * down the immediate notify path below.
1159 */
1160 io->io_hdr.io_type = CTL_IO_SCSI;
1161 io->io_hdr.nexus.initid.id = atio->init_id;
1162 io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
1163 io->io_hdr.nexus.targ_target.id = atio->ccb_h.target_id;
1164 io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun;
1165 io->scsiio.tag_num = atio->tag_id;
1166 switch (atio->tag_action) {
1167 case CAM_TAG_ACTION_NONE:
1168 io->scsiio.tag_type = CTL_TAG_UNTAGGED;
1169 break;
1170 case MSG_SIMPLE_TASK:
1171 io->scsiio.tag_type = CTL_TAG_SIMPLE;
1172 break;
1173 case MSG_HEAD_OF_QUEUE_TASK:
1174 io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE;
1175 break;
1176 case MSG_ORDERED_TASK:
1177 io->scsiio.tag_type = CTL_TAG_ORDERED;
1178 break;
1179 case MSG_ACA_TASK:
1180 io->scsiio.tag_type = CTL_TAG_ACA;
1181 break;
1182 default:
1183 io->scsiio.tag_type = CTL_TAG_UNTAGGED;
1184 printf("%s: unhandled tag type %#x!!\n", __func__,
1185 atio->tag_action);
1186 break;
1187 }
1188 if (atio->cdb_len > sizeof(io->scsiio.cdb)) {
1189 printf("%s: WARNING: CDB len %d > ctl_io space %zd\n",
1190 __func__, atio->cdb_len, sizeof(io->scsiio.cdb));
1191 }
1192 io->scsiio.cdb_len = min(atio->cdb_len, sizeof(io->scsiio.cdb));
1193 bcopy(atio->cdb_io.cdb_bytes, io->scsiio.cdb,
1194 io->scsiio.cdb_len);
1195
1196#ifdef CTLFEDEBUG
1197 printf("%s: %ju:%d:%ju:%d: tag %04x CDB %02x\n", __func__,
1198 (uintmax_t)io->io_hdr.nexus.initid.id,
1199 io->io_hdr.nexus.targ_port,
1200 (uintmax_t)io->io_hdr.nexus.targ_target.id,
1201 io->io_hdr.nexus.targ_lun,
1202 io->scsiio.tag_num, io->scsiio.cdb[0]);
1203#endif
1204
1205 ctl_queue(io);
1206 return;
1207 }
1208 case XPT_CONT_TARGET_IO: {
1209 int srr = 0;
1210 uint32_t srr_off = 0;
1211
1212 atio = (struct ccb_accept_tio *)done_ccb->ccb_h.ccb_atio;
1213 io = (union ctl_io *)atio->ccb_h.io_ptr;
1214
1215 softc->ctios_returned++;
1216#ifdef CTLFEDEBUG
1217 printf("%s: got XPT_CONT_TARGET_IO tag %#x flags %#x\n",
1218 __func__, atio->tag_id, done_ccb->ccb_h.flags);
1219#endif
1220 /*
1221 * Handle SRR case were the data pointer is pushed back hack
1222 */
1223 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_MESSAGE_RECV
1224 && done_ccb->csio.msg_ptr != NULL
1225 && done_ccb->csio.msg_ptr[0] == MSG_EXTENDED
1226 && done_ccb->csio.msg_ptr[1] == 5
1227 && done_ccb->csio.msg_ptr[2] == 0) {
1228 srr = 1;
1229 srr_off =
1230 (done_ccb->csio.msg_ptr[3] << 24)
1231 | (done_ccb->csio.msg_ptr[4] << 16)
1232 | (done_ccb->csio.msg_ptr[5] << 8)
1233 | (done_ccb->csio.msg_ptr[6]);
1234 }
1235
1236 if (srr && (io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) {
1237 /*
1238 * If status was being sent, the back end data is now
1239 * history. Hack it up and resubmit a new command with
1240 * the CDB adjusted. If the SIM does the right thing,
1241 * all of the resid math should work.
1242 */
1243 softc->ccbs_freed++;
1244 xpt_release_ccb(done_ccb);
1245 if (ctlfe_adjust_cdb(atio, srr_off) == 0) {
1246 done_ccb = (union ccb *)atio;
1247 goto resubmit;
1248 }
1249 /*
1250 * Fall through to doom....
1251 */
1252 } else if (srr) {
1253 /*
1254 * If we have an srr and we're still sending data, we
1255 * should be able to adjust offsets and cycle again.
1256 */
1257 io->scsiio.kern_rel_offset =
1258 io->scsiio.ext_data_filled = srr_off;
1259 io->scsiio.ext_data_len = io->scsiio.kern_total_len -
1260 io->scsiio.kern_rel_offset;
1261 softc->ccbs_freed++;
1262 io->scsiio.io_hdr.status = CTL_STATUS_NONE;
1263 xpt_release_ccb(done_ccb);
1264 TAILQ_INSERT_HEAD(&softc->work_queue, &atio->ccb_h,
1265 periph_links.tqe);
1266 xpt_schedule(periph, /*priority*/ 1);
1267 break;
1268 }
1269
1270 /*
1271 * If we were sending status back to the initiator, free up
1272 * resources. If we were doing a datamove, call the
1273 * datamove done routine.
1274 */
1275 if ((io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) {
1276 softc->ccbs_freed++;
1277 xpt_release_ccb(done_ccb);
1278 /*
1279 * For a wildcard attachment, commands can come in
1280 * with a specific target/lun. Reset the target
1281 * and LUN fields back to the wildcard values before
1282 * we send them back down to the SIM. The SIM has
1283 * a wildcard LUN enabled, not whatever target/lun
1284 * these happened to be.
1285 */
1286 if (softc->flags & CTLFE_LUN_WILDCARD) {
1287 atio->ccb_h.target_id = CAM_TARGET_WILDCARD;
1288 atio->ccb_h.target_lun = CAM_LUN_WILDCARD;
1289 }
1290 if (periph->flags & CAM_PERIPH_INVALID) {
1291 ctlfe_free_ccb(periph, (union ccb *)atio);
1292 } else {
1293 softc->atios_sent++;
1294 mtx_unlock(mtx);
1295 xpt_action((union ccb *)atio);
1296 return;
1297 }
1298 } else {
1299 struct ctlfe_lun_cmd_info *cmd_info;
1300 struct ccb_scsiio *csio;
1301
1302 csio = &done_ccb->csio;
1303 cmd_info = (struct ctlfe_lun_cmd_info *)
1304 io->io_hdr.port_priv;
1305
1306 io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
1307
1308 io->scsiio.ext_data_len += csio->dxfer_len;
1309 if (io->scsiio.ext_data_len >
1310 io->scsiio.kern_total_len) {
1311 xpt_print(periph->path, "%s: tag 0x%04x "
1312 "done len %u > total %u sent %u\n",
1313 __func__, io->scsiio.tag_num,
1314 io->scsiio.ext_data_len,
1315 io->scsiio.kern_total_len,
1316 io->scsiio.ext_data_filled);
1317 }
1318 /*
1319 * Translate CAM status to CTL status. Success
1320 * does not change the overall, ctl_io status. In
1321 * that case we just set port_status to 0. If we
1322 * have a failure, though, set a data phase error
1323 * for the overall ctl_io.
1324 */
1325 switch (done_ccb->ccb_h.status & CAM_STATUS_MASK) {
1326 case CAM_REQ_CMP:
1327 io->io_hdr.port_status = 0;
1328 break;
1329 default:
1330 /*
1331 * XXX KDM we probably need to figure out a
1332 * standard set of errors that the SIM
1333 * drivers should return in the event of a
1334 * data transfer failure. A data phase
1335 * error will at least point the user to a
1336 * data transfer error of some sort.
1337 * Hopefully the SIM printed out some
1338 * additional information to give the user
1339 * a clue what happened.
1340 */
1341 io->io_hdr.port_status = 0xbad1;
1342 ctl_set_data_phase_error(&io->scsiio);
1343 /*
1344 * XXX KDM figure out residual.
1345 */
1346 break;
1347 }
1348 /*
1349 * If we had to break this S/G list into multiple
1350 * pieces, figure out where we are in the list, and
1351 * continue sending pieces if necessary.
1352 */
1353 if ((cmd_info->flags & CTLFE_CMD_PIECEWISE)
1354 && (io->io_hdr.port_status == 0)) {
1355 ccb_flags flags;
1356 uint8_t scsi_status;
1357 uint8_t *data_ptr;
1358 uint32_t dxfer_len;
1359
1360 flags = atio->ccb_h.flags &
1361 (CAM_DIS_DISCONNECT|
1362 CAM_TAG_ACTION_VALID);
1363
1364 ctlfedata(softc, io, &flags, &data_ptr,
1365 &dxfer_len, &csio->sglist_cnt);
1366
1367 scsi_status = 0;
1368
1369 if (((flags & CAM_SEND_STATUS) == 0)
1370 && (dxfer_len == 0)) {
1371 printf("%s: tag %04x no status or "
1372 "len cdb = %02x\n", __func__,
1373 atio->tag_id,
1374 atio->cdb_io.cdb_bytes[0]);
1375 printf("%s: tag %04x io status %#x\n",
1376 __func__, atio->tag_id,
1377 io->io_hdr.status);
1378 }
1379
1380 cam_fill_ctio(csio,
1381 /*retries*/ 2,
1382 ctlfedone,
1383 flags,
1384 (flags & CAM_TAG_ACTION_VALID) ?
1385 MSG_SIMPLE_Q_TAG : 0,
1386 atio->tag_id,
1387 atio->init_id,
1388 scsi_status,
1389 /*data_ptr*/ data_ptr,
1390 /*dxfer_len*/ dxfer_len,
1391 /*timeout*/ 5 * 1000);
1392
1393 csio->ccb_h.flags |= CAM_UNLOCKED;
1394 csio->resid = 0;
1395 csio->ccb_h.ccb_atio = atio;
1396 io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
1397 softc->ctios_sent++;
1398 mtx_unlock(mtx);
1399 xpt_action((union ccb *)csio);
1400 } else {
1401 /*
1402 * Release the CTIO. The ATIO will be sent back
1403 * down to the SIM once we send status.
1404 */
1405 softc->ccbs_freed++;
1406 xpt_release_ccb(done_ccb);
1407 mtx_unlock(mtx);
1408
1409 /* Call the backend move done callback */
1410 io->scsiio.be_move_done(io);
1411 }
1412 return;
1413 }
1414 break;
1415 }
1416 case XPT_IMMEDIATE_NOTIFY: {
1417 union ctl_io *io;
1418 struct ccb_immediate_notify *inot;
1419 cam_status status;
1420 int frozen, send_ctl_io;
1421
1422 inot = &done_ccb->cin1;
1423
1424 softc->inots_returned++;
1425
1426 frozen = (done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
1427
1428 printf("%s: got XPT_IMMEDIATE_NOTIFY status %#x tag %#x "
1429 "seq %#x\n", __func__, inot->ccb_h.status,
1430 inot->tag_id, inot->seq_id);
1431
1432 io = done_ccb->ccb_h.io_ptr;
1433 ctl_zero_io(io);
1434
1435 send_ctl_io = 1;
1436
1437 io->io_hdr.io_type = CTL_IO_TASK;
1438 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr =done_ccb;
1439 inot->ccb_h.io_ptr = io;
1440 io->io_hdr.nexus.initid.id = inot->initiator_id;
1441 io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
1442 io->io_hdr.nexus.targ_target.id = inot->ccb_h.target_id;
1443 io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun;
1444 /* XXX KDM should this be the tag_id? */
1445 io->taskio.tag_num = inot->seq_id;
1446
1447 status = inot->ccb_h.status & CAM_STATUS_MASK;
1448 switch (status) {
1449 case CAM_SCSI_BUS_RESET:
1450 io->taskio.task_action = CTL_TASK_BUS_RESET;
1451 break;
1452 case CAM_BDR_SENT:
1453 io->taskio.task_action = CTL_TASK_TARGET_RESET;
1454 break;
1455 case CAM_MESSAGE_RECV:
1456 switch (inot->arg) {
1457 case MSG_ABORT_TASK_SET:
1458 io->taskio.task_action =
1459 CTL_TASK_ABORT_TASK_SET;
1460 break;
1461 case MSG_TARGET_RESET:
1462 io->taskio.task_action =
1463 CTL_TASK_TARGET_RESET;
1464 break;
1465 case MSG_ABORT_TASK:
1466 io->taskio.task_action =
1467 CTL_TASK_ABORT_TASK;
1468 break;
1469 case MSG_LOGICAL_UNIT_RESET:
1470 io->taskio.task_action =
1471 CTL_TASK_LUN_RESET;
1472 break;
1473 case MSG_CLEAR_TASK_SET:
1474 io->taskio.task_action =
1475 CTL_TASK_CLEAR_TASK_SET;
1476 break;
1477 case MSG_CLEAR_ACA:
1478 io->taskio.task_action =
1479 CTL_TASK_CLEAR_ACA;
1480 break;
1481 case MSG_NOOP:
1482 send_ctl_io = 0;
1483 break;
1484 default:
1485 xpt_print(periph->path,
1486 "%s: unsupported message 0x%x\n",
1487 __func__, inot->arg);
1488 send_ctl_io = 0;
1489 break;
1490 }
1491 break;
1492 case CAM_REQ_ABORTED:
1493 /*
1494 * This request was sent back by the driver.
1495 * XXX KDM what do we do here?
1496 */
1497 send_ctl_io = 0;
1498 break;
1499 case CAM_REQ_INVALID:
1500 case CAM_PROVIDE_FAIL:
1501 default:
1502 /*
1503 * We should only get here if we're talking
1504 * to a talking to a SIM that is target
1505 * capable but supports the old API. In
1506 * that case, we need to just free the CCB.
1507 * If we actually send a notify acknowledge,
1508 * it will send that back with an error as
1509 * well.
1510 */
1511
1512 if ((status != CAM_REQ_INVALID)
1513 && (status != CAM_PROVIDE_FAIL))
1514 xpt_print(periph->path,
1515 "%s: unsupported CAM status 0x%x\n",
1516 __func__, status);
1517
1518 ctlfe_free_ccb(periph, done_ccb);
1519
1520 goto out;
1521 }
1522 if (send_ctl_io != 0) {
1523 ctl_queue(io);
1524 } else {
1525 done_ccb->ccb_h.status = CAM_REQ_INPROG;
1526 done_ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
1527 xpt_action(done_ccb);
1528 }
1529
1530 if (frozen != 0) {
1531 cam_release_devq(periph->path,
1532 /*relsim_flags*/ 0,
1533 /*opening reduction*/ 0,
1534 /*timeout*/ 0,
1535 /*getcount_only*/ 0);
1536 }
1537 break;
1538 }
1539 case XPT_NOTIFY_ACKNOWLEDGE:
1540 /*
1541 * Queue this back down to the SIM as an immediate notify.
1542 */
1543 done_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
1544 xpt_action(done_ccb);
1545 softc->inots_sent++;
1546 break;
1547 case XPT_SET_SIM_KNOB:
1548 case XPT_GET_SIM_KNOB:
1549 break;
1550 default:
1551 panic("%s: unexpected CCB type %#x", __func__,
1552 done_ccb->ccb_h.func_code);
1553 break;
1554 }
1555
1556out:
1557 mtx_unlock(mtx);
1558}
1559
1560static void
1561ctlfe_onoffline(void *arg, int online)
1562{
1563 struct ctlfe_softc *bus_softc;
1564 union ccb *ccb;
1565 cam_status status;
1566 struct cam_path *path;
1567 int set_wwnn;
1568
1569 bus_softc = (struct ctlfe_softc *)arg;
1570
1571 set_wwnn = 0;
1572
1573 status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
1574 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
1575 if (status != CAM_REQ_CMP) {
1576 printf("%s: unable to create path!\n", __func__);
1577 return;
1578 }
1579 ccb = xpt_alloc_ccb();
1580 xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
1581
1582 /*
1583 * Copan WWN format:
1584 *
1585 * Bits 63-60: 0x5 NAA, IEEE registered name
1586 * Bits 59-36: 0x000ED5 IEEE Company name assigned to Copan
1587 * Bits 35-12: Copan SSN (Sequential Serial Number)
1588 * Bits 11-8: Type of port:
1589 * 1 == N-Port
1590 * 2 == F-Port
1591 * 3 == NL-Port
1592 * Bits 7-0: 0 == Node Name, >0 == Port Number
1593 */
1594
1595 if (online != 0) {
1596
1597 ccb->ccb_h.func_code = XPT_GET_SIM_KNOB;
1598
1599
1600 xpt_action(ccb);
1601
1602
1603 if ((ccb->knob.xport_specific.valid & KNOB_VALID_ADDRESS) != 0){
1604#ifdef RANDOM_WWNN
1605 uint64_t random_bits;
1606#endif
1607
1608 printf("%s: %s current WWNN %#jx\n", __func__,
1609 bus_softc->port_name,
1610 ccb->knob.xport_specific.fc.wwnn);
1611 printf("%s: %s current WWPN %#jx\n", __func__,
1612 bus_softc->port_name,
1613 ccb->knob.xport_specific.fc.wwpn);
1614
1615#ifdef RANDOM_WWNN
1616 arc4rand(&random_bits, sizeof(random_bits), 0);
1617#endif
1618
1619 /*
1620 * XXX KDM this is a bit of a kludge for now. We
1621 * take the current WWNN/WWPN from the card, and
1622 * replace the company identifier and the NL-Port
1623 * indicator and the port number (for the WWPN).
1624 * This should be replaced later with ddb_GetWWNN,
1625 * or possibly a more centralized scheme. (It
1626 * would be nice to have the WWNN/WWPN for each
1627 * port stored in the ctl_port structure.)
1628 */
1629#ifdef RANDOM_WWNN
1630 ccb->knob.xport_specific.fc.wwnn =
1631 (random_bits &
1632 0x0000000fffffff00ULL) |
1633 /* Company ID */ 0x5000ED5000000000ULL |
1634 /* NL-Port */ 0x0300;
1635 ccb->knob.xport_specific.fc.wwpn =
1636 (random_bits &
1637 0x0000000fffffff00ULL) |
1638 /* Company ID */ 0x5000ED5000000000ULL |
1639 /* NL-Port */ 0x3000 |
1640 /* Port Num */ (bus_softc->port.targ_port & 0xff);
1641
1642 /*
1643 * This is a bit of an API break/reversal, but if
1644 * we're doing the random WWNN that's a little
1645 * different anyway. So record what we're actually
1646 * using with the frontend code so it's reported
1647 * accurately.
1648 */
1649 ctl_port_set_wwns(&bus_softc->port,
1650 true, ccb->knob.xport_specific.fc.wwnn,
1651 true, ccb->knob.xport_specific.fc.wwpn);
1652 set_wwnn = 1;
1653#else /* RANDOM_WWNN */
1654 /*
1655 * If the user has specified a WWNN/WWPN, send them
1656 * down to the SIM. Otherwise, record what the SIM
1657 * has reported.
1658 */
1659 if ((bus_softc->port.wwnn != 0)
1660 && (bus_softc->port.wwpn != 0)) {
1661 ccb->knob.xport_specific.fc.wwnn =
1662 bus_softc->port.wwnn;
1663 ccb->knob.xport_specific.fc.wwpn =
1664 bus_softc->port.wwpn;
1665 set_wwnn = 1;
1666 } else {
1667 ctl_port_set_wwns(&bus_softc->port,
1668 true, ccb->knob.xport_specific.fc.wwnn,
1669 true, ccb->knob.xport_specific.fc.wwpn);
1670 }
1671#endif /* RANDOM_WWNN */
1672
1673
1674 if (set_wwnn != 0) {
1675 printf("%s: %s new WWNN %#jx\n", __func__,
1676 bus_softc->port_name,
1677 ccb->knob.xport_specific.fc.wwnn);
1678 printf("%s: %s new WWPN %#jx\n", __func__,
1679 bus_softc->port_name,
1680 ccb->knob.xport_specific.fc.wwpn);
1681 }
1682 } else {
1683 printf("%s: %s has no valid WWNN/WWPN\n", __func__,
1684 bus_softc->port_name);
1685 }
1686 }
1687 ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
1688 ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
1689 if (set_wwnn != 0)
1690 ccb->knob.xport_specific.valid |= KNOB_VALID_ADDRESS;
1691
1692 if (online != 0)
1693 ccb->knob.xport_specific.fc.role = KNOB_ROLE_TARGET;
1694 else
1695 ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE;
1696
1697 xpt_action(ccb);
1698
1699 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1700 printf("%s: SIM %s (path id %d) target %s failed with "
1701 "status %#x\n",
1702 __func__, bus_softc->port_name, bus_softc->path_id,
1703 (online != 0) ? "enable" : "disable",
1704 ccb->ccb_h.status);
1705 } else {
1706 printf("%s: SIM %s (path id %d) target %s succeeded\n",
1707 __func__, bus_softc->port_name, bus_softc->path_id,
1708 (online != 0) ? "enable" : "disable");
1709 }
1710
1711 xpt_free_path(path);
1712 xpt_free_ccb(ccb);
1713}
1714
1715static void
1716ctlfe_online(void *arg)
1717{
1718 struct ctlfe_softc *bus_softc;
1719 struct cam_path *path;
1720 cam_status status;
1721 struct ctlfe_lun_softc *lun_softc;
1722 struct cam_periph *periph;
1723
1724 bus_softc = (struct ctlfe_softc *)arg;
1725
1726 /*
1727 * Create the wildcard LUN before bringing the port online.
1728 */
1729 status = xpt_create_path(&path, /*periph*/ NULL,
1730 bus_softc->path_id, CAM_TARGET_WILDCARD,
1731 CAM_LUN_WILDCARD);
1732 if (status != CAM_REQ_CMP) {
1733 printf("%s: unable to create path for wildcard periph\n",
1734 __func__);
1735 return;
1736 }
1737
1738 lun_softc = malloc(sizeof(*lun_softc), M_CTLFE, M_WAITOK | M_ZERO);
1739
1740 xpt_path_lock(path);
1741 periph = cam_periph_find(path, "ctl");
1742 if (periph != NULL) {
1743 /* We've already got a periph, no need to alloc a new one. */
1744 xpt_path_unlock(path);
1745 xpt_free_path(path);
1746 free(lun_softc, M_CTLFE);
1747 return;
1748 }
1749 lun_softc->parent_softc = bus_softc;
1750 lun_softc->flags |= CTLFE_LUN_WILDCARD;
1751
1752 status = cam_periph_alloc(ctlferegister,
1753 ctlfeoninvalidate,
1754 ctlfecleanup,
1755 ctlfestart,
1756 "ctl",
1757 CAM_PERIPH_BIO,
1758 path,
1759 ctlfeasync,
1760 0,
1761 lun_softc);
1762
1763 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1764 const struct cam_status_entry *entry;
1765
1766 entry = cam_fetch_status_entry(status);
1767 printf("%s: CAM error %s (%#x) returned from "
1768 "cam_periph_alloc()\n", __func__, (entry != NULL) ?
1769 entry->status_text : "Unknown", status);
1770 free(lun_softc, M_CTLFE);
1771 }
1772
1773 xpt_path_unlock(path);
1774 ctlfe_onoffline(arg, /*online*/ 1);
1775 xpt_free_path(path);
1776}
1777
1778static void
1779ctlfe_offline(void *arg)
1780{
1781 struct ctlfe_softc *bus_softc;
1782 struct cam_path *path;
1783 cam_status status;
1784 struct cam_periph *periph;
1785
1786 bus_softc = (struct ctlfe_softc *)arg;
1787
1788 ctlfe_onoffline(arg, /*online*/ 0);
1789
1790 /*
1791 * Disable the wildcard LUN for this port now that we have taken
1792 * the port offline.
1793 */
1794 status = xpt_create_path(&path, /*periph*/ NULL,
1795 bus_softc->path_id, CAM_TARGET_WILDCARD,
1796 CAM_LUN_WILDCARD);
1797 if (status != CAM_REQ_CMP) {
1798 printf("%s: unable to create path for wildcard periph\n",
1799 __func__);
1800 return;
1801 }
1802 xpt_path_lock(path);
1803 if ((periph = cam_periph_find(path, "ctl")) != NULL)
1804 cam_periph_invalidate(periph);
1805 xpt_path_unlock(path);
1806 xpt_free_path(path);
1807}
1808
1809/*
1810 * This will get called to enable a LUN on every bus that is attached to
1811 * CTL. So we only need to create a path/periph for this particular bus.
1812 */
1813static int
1814ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
1815{
1816 struct ctlfe_softc *bus_softc;
1817 struct ctlfe_lun_softc *softc;
1818 struct cam_path *path;
1819 struct cam_periph *periph;
1820 cam_status status;
1821
1822 bus_softc = (struct ctlfe_softc *)arg;
1823
1824 status = xpt_create_path(&path, /*periph*/ NULL,
1825 bus_softc->path_id,
1826 targ_id.id, lun_id);
1827 /* XXX KDM need some way to return status to CTL here? */
1828 if (status != CAM_REQ_CMP) {
1829 printf("%s: could not create path, status %#x\n", __func__,
1830 status);
1831 return (1);
1832 }
1833
1834 softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO);
1835 xpt_path_lock(path);
1836 periph = cam_periph_find(path, "ctl");
1837 if (periph != NULL) {
1838 /* We've already got a periph, no need to alloc a new one. */
1839 xpt_path_unlock(path);
1840 xpt_free_path(path);
1841 free(softc, M_CTLFE);
1842 return (0);
1843 }
1844 softc->parent_softc = bus_softc;
1845
1846 status = cam_periph_alloc(ctlferegister,
1847 ctlfeoninvalidate,
1848 ctlfecleanup,
1849 ctlfestart,
1850 "ctl",
1851 CAM_PERIPH_BIO,
1852 path,
1853 ctlfeasync,
1854 0,
1855 softc);
1856
1857 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1858 const struct cam_status_entry *entry;
1859
1860 entry = cam_fetch_status_entry(status);
1861 printf("%s: CAM error %s (%#x) returned from "
1862 "cam_periph_alloc()\n", __func__, (entry != NULL) ?
1863 entry->status_text : "Unknown", status);
1864 free(softc, M_CTLFE);
1865 }
1866
1867 xpt_path_unlock(path);
1868 xpt_free_path(path);
1869 return (0);
1870}
1871
1872/*
1873 * This will get called when the user removes a LUN to disable that LUN
1874 * on every bus that is attached to CTL.
1875 */
1876static int
1877ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
1878{
1879 struct ctlfe_softc *softc;
1880 struct ctlfe_lun_softc *lun_softc;
1881
1882 softc = (struct ctlfe_softc *)arg;
1883
1884 mtx_lock(&softc->lun_softc_mtx);
1885 STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {
1886 struct cam_path *path;
1887
1888 path = lun_softc->periph->path;
1889
1890 if ((xpt_path_target_id(path) == targ_id.id)
1891 && (xpt_path_lun_id(path) == lun_id)) {
1892 break;
1893 }
1894 }
1895 if (lun_softc == NULL) {
1896 mtx_unlock(&softc->lun_softc_mtx);
1897 printf("%s: can't find target %d lun %d\n", __func__,
1898 targ_id.id, lun_id);
1899 return (1);
1900 }
1901 cam_periph_acquire(lun_softc->periph);
1902 mtx_unlock(&softc->lun_softc_mtx);
1903
1904 cam_periph_lock(lun_softc->periph);
1905 cam_periph_invalidate(lun_softc->periph);
1906 cam_periph_unlock(lun_softc->periph);
1907 cam_periph_release(lun_softc->periph);
1908 return (0);
1909}
1910
1911static void
1912ctlfe_dump_sim(struct cam_sim *sim)
1913{
1914
1915 printf("%s%d: max tagged openings: %d, max dev openings: %d\n",
1916 sim->sim_name, sim->unit_number,
1917 sim->max_tagged_dev_openings, sim->max_dev_openings);
1918}
1919
1920/*
1921 * Assumes that the SIM lock is held.
1922 */
1923static void
1924ctlfe_dump_queue(struct ctlfe_lun_softc *softc)
1925{
1926 struct ccb_hdr *hdr;
1927 struct cam_periph *periph;
1928 int num_items;
1929
1930 periph = softc->periph;
1931 num_items = 0;
1932
1933 TAILQ_FOREACH(hdr, &softc->work_queue, periph_links.tqe) {
1934 union ctl_io *io = hdr->io_ptr;
1935
1936 num_items++;
1937
1938 /*
1939 * Only regular SCSI I/O is put on the work
1940 * queue, so we can print sense here. There may be no
1941 * sense if it's no the queue for a DMA, but this serves to
1942 * print out the CCB as well.
1943 *
1944 * XXX KDM switch this over to scsi_sense_print() when
1945 * CTL is merged in with CAM.
1946 */
1947 ctl_io_error_print(io, NULL);
1948
1949 /*
1950 * Print DMA status if we are DMA_QUEUED.
1951 */
1952 if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) {
1953 xpt_print(periph->path,
1954 "Total %u, Current %u, Resid %u\n",
1955 io->scsiio.kern_total_len,
1956 io->scsiio.kern_data_len,
1957 io->scsiio.kern_data_resid);
1958 }
1959 }
1960
1961 xpt_print(periph->path, "%d requests total waiting for CCBs\n",
1962 num_items);
1963 xpt_print(periph->path, "%ju CCBs outstanding (%ju allocated, %ju "
1964 "freed)\n", (uintmax_t)(softc->ccbs_alloced -
1965 softc->ccbs_freed), (uintmax_t)softc->ccbs_alloced,
1966 (uintmax_t)softc->ccbs_freed);
1967 xpt_print(periph->path, "%ju CTIOs outstanding (%ju sent, %ju "
1968 "returned\n", (uintmax_t)(softc->ctios_sent -
1969 softc->ctios_returned), softc->ctios_sent,
1970 softc->ctios_returned);
1971}
1972
1973/*
1974 * Datamove/done routine called by CTL. Put ourselves on the queue to
1975 * receive a CCB from CAM so we can queue the continue I/O request down
1976 * to the adapter.
1977 */
1978static void
1979ctlfe_datamove(union ctl_io *io)
1980{
1981 union ccb *ccb;
1982 struct cam_periph *periph;
1983 struct ctlfe_lun_softc *softc;
1984
1985 KASSERT(io->io_hdr.io_type == CTL_IO_SCSI,
1986 ("Unexpected io_type (%d) in ctlfe_datamove", io->io_hdr.io_type));
1987
1988 ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
1989 periph = xpt_path_periph(ccb->ccb_h.path);
1990 cam_periph_lock(periph);
1991 softc = (struct ctlfe_lun_softc *)periph->softc;
1992 io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED;
1993 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE)
1994 io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED;
1995 TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h,
1996 periph_links.tqe);
1997 xpt_schedule(periph, /*priority*/ 1);
1998 cam_periph_unlock(periph);
1999}
2000
2001static void
2002ctlfe_done(union ctl_io *io)
2003{
2004 union ccb *ccb;
2005 struct cam_periph *periph;
2006 struct ctlfe_lun_softc *softc;
2007
2008 ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
2009 periph = xpt_path_periph(ccb->ccb_h.path);
2010 cam_periph_lock(periph);
2011 softc = (struct ctlfe_lun_softc *)periph->softc;
2012
2013 if (io->io_hdr.io_type == CTL_IO_TASK) {
2014 /*
2015 * Task management commands don't require any further
2016 * communication back to the adapter. Requeue the CCB
2017 * to the adapter, and free the CTL I/O.
2018 */
2019 xpt_print(ccb->ccb_h.path, "%s: returning task I/O "
2020 "tag %#x seq %#x\n", __func__,
2021 ccb->cin1.tag_id, ccb->cin1.seq_id);
2022 /*
2023 * Send the notify acknowledge down to the SIM, to let it
2024 * know we processed the task management command.
2025 */
2026 ccb->ccb_h.status = CAM_REQ_INPROG;
2027 ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
2028 xpt_action(ccb);
2029 } else if (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) {
2030 if (softc->flags & CTLFE_LUN_WILDCARD) {
2031 ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
2032 ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
2033 }
2034 if (periph->flags & CAM_PERIPH_INVALID) {
2035 ctlfe_free_ccb(periph, ccb);
2036 } else {
2037 softc->atios_sent++;
2038 cam_periph_unlock(periph);
2039 xpt_action(ccb);
2040 return;
2041 }
2042 } else {
2043 io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED;
2044 TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h,
2045 periph_links.tqe);
2046 xpt_schedule(periph, /*priority*/ 1);
2047 }
2048
2049 cam_periph_unlock(periph);
2050}
2051
2052static void
2053ctlfe_dump(void)
2054{
2055 struct ctlfe_softc *bus_softc;
2056 struct ctlfe_lun_softc *lun_softc;
2057
2058 STAILQ_FOREACH(bus_softc, &ctlfe_softc_list, links) {
2059 ctlfe_dump_sim(bus_softc->sim);
2060 STAILQ_FOREACH(lun_softc, &bus_softc->lun_softc_list, links)
2061 ctlfe_dump_queue(lun_softc);
2062 }
2063}
231void
232ctlfeshutdown(void)
233{
234 return;
235}
236
237int
238ctlfeinitialize(void)
239{
240
241 STAILQ_INIT(&ctlfe_softc_list);
242 mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF);
243 periphdriver_register(&ctlfe_driver);
244 return (0);
245}
246
247void
248ctlfeperiphinit(void)
249{
250 cam_status status;
251
252 status = xpt_register_async(AC_PATH_REGISTERED | AC_PATH_DEREGISTERED |
253 AC_CONTRACT, ctlfeasync, NULL, NULL);
254 if (status != CAM_REQ_CMP) {
255 printf("ctl: Failed to attach async callback due to CAM "
256 "status 0x%x!\n", status);
257 }
258}
259
260static void
261ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
262{
263 struct ctlfe_softc *softc;
264
265#ifdef CTLFEDEBUG
266 printf("%s: entered\n", __func__);
267#endif
268
269 mtx_lock(&ctlfe_list_mtx);
270 STAILQ_FOREACH(softc, &ctlfe_softc_list, links) {
271 if (softc->path_id == xpt_path_path_id(path))
272 break;
273 }
274 mtx_unlock(&ctlfe_list_mtx);
275
276 /*
277 * When a new path gets registered, and it is capable of target
278 * mode, go ahead and attach. Later on, we may need to be more
279 * selective, but for now this will be sufficient.
280 */
281 switch (code) {
282 case AC_PATH_REGISTERED: {
283 struct ctl_port *port;
284 struct ccb_pathinq *cpi;
285 int retval;
286
287 cpi = (struct ccb_pathinq *)arg;
288
289 /* Don't attach if it doesn't support target mode */
290 if ((cpi->target_sprt & PIT_PROCESSOR) == 0) {
291#ifdef CTLFEDEBUG
292 printf("%s: SIM %s%d doesn't support target mode\n",
293 __func__, cpi->dev_name, cpi->unit_number);
294#endif
295 break;
296 }
297
298 if (softc != NULL) {
299#ifdef CTLFEDEBUG
300 printf("%s: CTL port for CAM path %u already exists\n",
301 __func__, xpt_path_path_id(path));
302#endif
303 break;
304 }
305
306#ifdef CTLFE_INIT_ENABLE
307 if (ctlfe_num_targets >= ctlfe_max_targets) {
308 union ccb *ccb;
309
310 ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP,
311 M_NOWAIT | M_ZERO);
312 if (ccb == NULL) {
313 printf("%s: unable to malloc CCB!\n", __func__);
314 return;
315 }
316 xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
317
318 ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
319 ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
320 ccb->knob.xport_specific.fc.role = KNOB_ROLE_INITIATOR;
321
322 xpt_action(ccb);
323
324 if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
325 CAM_REQ_CMP) {
326 printf("%s: SIM %s%d (path id %d) initiator "
327 "enable failed with status %#x\n",
328 __func__, cpi->dev_name,
329 cpi->unit_number, cpi->ccb_h.path_id,
330 ccb->ccb_h.status);
331 } else {
332 printf("%s: SIM %s%d (path id %d) initiator "
333 "enable succeeded\n",
334 __func__, cpi->dev_name,
335 cpi->unit_number, cpi->ccb_h.path_id);
336 }
337
338 free(ccb, M_TEMP);
339
340 break;
341 } else {
342 ctlfe_num_targets++;
343 }
344
345 printf("%s: ctlfe_num_targets = %d\n", __func__,
346 ctlfe_num_targets);
347#endif /* CTLFE_INIT_ENABLE */
348
349 /*
350 * We're in an interrupt context here, so we have to
351 * use M_NOWAIT. Of course this means trouble if we
352 * can't allocate memory.
353 */
354 softc = malloc(sizeof(*softc), M_CTLFE, M_NOWAIT | M_ZERO);
355 if (softc == NULL) {
356 printf("%s: unable to malloc %zd bytes for softc\n",
357 __func__, sizeof(*softc));
358 return;
359 }
360
361 softc->path_id = cpi->ccb_h.path_id;
362 softc->sim = xpt_path_sim(path);
363 if (cpi->maxio != 0)
364 softc->maxio = cpi->maxio;
365 else
366 softc->maxio = DFLTPHYS;
367 mtx_init(&softc->lun_softc_mtx, "LUN softc mtx", NULL, MTX_DEF);
368 STAILQ_INIT(&softc->lun_softc_list);
369
370 port = &softc->port;
371 port->frontend = &ctlfe_frontend;
372
373 /*
374 * XXX KDM should we be more accurate here ?
375 */
376 if (cpi->transport == XPORT_FC)
377 port->port_type = CTL_PORT_FC;
378 else if (cpi->transport == XPORT_SAS)
379 port->port_type = CTL_PORT_SAS;
380 else
381 port->port_type = CTL_PORT_SCSI;
382
383 /* XXX KDM what should the real number be here? */
384 port->num_requested_ctl_io = 4096;
385 snprintf(softc->port_name, sizeof(softc->port_name),
386 "%s%d", cpi->dev_name, cpi->unit_number);
387 /*
388 * XXX KDM it would be nice to allocate storage in the
389 * frontend structure itself.
390 */
391 port->port_name = softc->port_name;
392 port->physical_port = cpi->bus_id;
393 port->virtual_port = 0;
394 port->port_online = ctlfe_online;
395 port->port_offline = ctlfe_offline;
396 port->onoff_arg = softc;
397 port->lun_enable = ctlfe_lun_enable;
398 port->lun_disable = ctlfe_lun_disable;
399 port->targ_lun_arg = softc;
400 port->fe_datamove = ctlfe_datamove;
401 port->fe_done = ctlfe_done;
402 /*
403 * XXX KDM the path inquiry doesn't give us the maximum
404 * number of targets supported.
405 */
406 port->max_targets = cpi->max_target;
407 port->max_target_id = cpi->max_target;
408
409 /*
410 * XXX KDM need to figure out whether we're the master or
411 * slave.
412 */
413#ifdef CTLFEDEBUG
414 printf("%s: calling ctl_port_register() for %s%d\n",
415 __func__, cpi->dev_name, cpi->unit_number);
416#endif
417 retval = ctl_port_register(port);
418 if (retval != 0) {
419 printf("%s: ctl_port_register() failed with "
420 "error %d!\n", __func__, retval);
421 mtx_destroy(&softc->lun_softc_mtx);
422 free(softc, M_CTLFE);
423 break;
424 } else {
425 mtx_lock(&ctlfe_list_mtx);
426 STAILQ_INSERT_TAIL(&ctlfe_softc_list, softc, links);
427 mtx_unlock(&ctlfe_list_mtx);
428 }
429
430 break;
431 }
432 case AC_PATH_DEREGISTERED: {
433
434 if (softc != NULL) {
435 /*
436 * XXX KDM are we certain at this point that there
437 * are no outstanding commands for this frontend?
438 */
439 mtx_lock(&ctlfe_list_mtx);
440 STAILQ_REMOVE(&ctlfe_softc_list, softc, ctlfe_softc,
441 links);
442 mtx_unlock(&ctlfe_list_mtx);
443 ctl_port_deregister(&softc->port);
444 mtx_destroy(&softc->lun_softc_mtx);
445 free(softc, M_CTLFE);
446 }
447 break;
448 }
449 case AC_CONTRACT: {
450 struct ac_contract *ac;
451
452 ac = (struct ac_contract *)arg;
453
454 switch (ac->contract_number) {
455 case AC_CONTRACT_DEV_CHG: {
456 struct ac_device_changed *dev_chg;
457 int retval;
458
459 dev_chg = (struct ac_device_changed *)ac->contract_data;
460
461 printf("%s: WWPN %#jx port 0x%06x path %u target %u %s\n",
462 __func__, dev_chg->wwpn, dev_chg->port,
463 xpt_path_path_id(path), dev_chg->target,
464 (dev_chg->arrived == 0) ? "left" : "arrived");
465
466 if (softc == NULL) {
467 printf("%s: CTL port for CAM path %u not "
468 "found!\n", __func__,
469 xpt_path_path_id(path));
470 break;
471 }
472 if (dev_chg->arrived != 0) {
473 retval = ctl_add_initiator(&softc->port,
474 dev_chg->target, dev_chg->wwpn, NULL);
475 } else {
476 retval = ctl_remove_initiator(&softc->port,
477 dev_chg->target);
478 }
479
480 if (retval < 0) {
481 printf("%s: could not %s port %d iid %u "
482 "WWPN %#jx!\n", __func__,
483 (dev_chg->arrived != 0) ? "add" :
484 "remove", softc->port.targ_port,
485 dev_chg->target,
486 (uintmax_t)dev_chg->wwpn);
487 }
488 break;
489 }
490 default:
491 printf("%s: unsupported contract number %ju\n",
492 __func__, (uintmax_t)ac->contract_number);
493 break;
494 }
495 break;
496 }
497 default:
498 break;
499 }
500}
501
502static cam_status
503ctlferegister(struct cam_periph *periph, void *arg)
504{
505 struct ctlfe_softc *bus_softc;
506 struct ctlfe_lun_softc *softc;
507 union ccb en_lun_ccb;
508 cam_status status;
509 int i;
510
511 softc = (struct ctlfe_lun_softc *)arg;
512 bus_softc = softc->parent_softc;
513
514 TAILQ_INIT(&softc->work_queue);
515 softc->periph = periph;
516 periph->softc = softc;
517
518 xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE);
519 en_lun_ccb.ccb_h.func_code = XPT_EN_LUN;
520 en_lun_ccb.cel.grp6_len = 0;
521 en_lun_ccb.cel.grp7_len = 0;
522 en_lun_ccb.cel.enable = 1;
523 xpt_action(&en_lun_ccb);
524 status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK);
525 if (status != CAM_REQ_CMP) {
526 xpt_print(periph->path, "%s: Enable LUN failed, status 0x%x\n",
527 __func__, en_lun_ccb.ccb_h.status);
528 return (status);
529 }
530
531 status = CAM_REQ_CMP;
532
533 for (i = 0; i < CTLFE_ATIO_PER_LUN; i++) {
534 union ccb *new_ccb;
535 union ctl_io *new_io;
536
537 new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
538 M_ZERO|M_NOWAIT);
539 if (new_ccb == NULL) {
540 status = CAM_RESRC_UNAVAIL;
541 break;
542 }
543 new_io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref);
544 if (new_io == NULL) {
545 free(new_ccb, M_CTLFE);
546 status = CAM_RESRC_UNAVAIL;
547 break;
548 }
549 new_ccb->ccb_h.io_ptr = new_io;
550
551 xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
552 new_ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
553 new_ccb->ccb_h.cbfcnp = ctlfedone;
554 new_ccb->ccb_h.flags |= CAM_UNLOCKED;
555 xpt_action(new_ccb);
556 softc->atios_sent++;
557 status = new_ccb->ccb_h.status;
558 if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
559 ctl_free_io(new_io);
560 free(new_ccb, M_CTLFE);
561 break;
562 }
563 }
564
565 status = cam_periph_acquire(periph);
566 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
567 xpt_print(periph->path, "%s: could not acquire reference "
568 "count, status = %#x\n", __func__, status);
569 return (status);
570 }
571
572 if (i == 0) {
573 xpt_print(periph->path, "%s: could not allocate ATIO CCBs, "
574 "status 0x%x\n", __func__, status);
575 return (CAM_REQ_CMP_ERR);
576 }
577
578 for (i = 0; i < CTLFE_IN_PER_LUN; i++) {
579 union ccb *new_ccb;
580 union ctl_io *new_io;
581
582 new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
583 M_ZERO|M_NOWAIT);
584 if (new_ccb == NULL) {
585 status = CAM_RESRC_UNAVAIL;
586 break;
587 }
588 new_io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref);
589 if (new_io == NULL) {
590 free(new_ccb, M_CTLFE);
591 status = CAM_RESRC_UNAVAIL;
592 break;
593 }
594 new_ccb->ccb_h.io_ptr = new_io;
595
596 xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
597 new_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
598 new_ccb->ccb_h.cbfcnp = ctlfedone;
599 new_ccb->ccb_h.flags |= CAM_UNLOCKED;
600 xpt_action(new_ccb);
601 softc->inots_sent++;
602 status = new_ccb->ccb_h.status;
603 if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
604 /*
605 * Note that we don't free the CCB here. If the
606 * status is not CAM_REQ_INPROG, then we're
607 * probably talking to a SIM that says it is
608 * target-capable but doesn't support the
609 * XPT_IMMEDIATE_NOTIFY CCB. i.e. it supports the
610 * older API. In that case, it'll call xpt_done()
611 * on the CCB, and we need to free it in our done
612 * routine as a result.
613 */
614 break;
615 }
616 }
617 if ((i == 0)
618 || (status != CAM_REQ_INPROG)) {
619 xpt_print(periph->path, "%s: could not allocate immediate "
620 "notify CCBs, status 0x%x\n", __func__, status);
621 return (CAM_REQ_CMP_ERR);
622 }
623 mtx_lock(&bus_softc->lun_softc_mtx);
624 STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, softc, links);
625 mtx_unlock(&bus_softc->lun_softc_mtx);
626 return (CAM_REQ_CMP);
627}
628
629static void
630ctlfeoninvalidate(struct cam_periph *periph)
631{
632 union ccb en_lun_ccb;
633 cam_status status;
634 struct ctlfe_softc *bus_softc;
635 struct ctlfe_lun_softc *softc;
636
637 softc = (struct ctlfe_lun_softc *)periph->softc;
638
639 xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE);
640 en_lun_ccb.ccb_h.func_code = XPT_EN_LUN;
641 en_lun_ccb.cel.grp6_len = 0;
642 en_lun_ccb.cel.grp7_len = 0;
643 en_lun_ccb.cel.enable = 0;
644 xpt_action(&en_lun_ccb);
645 status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK);
646 if (status != CAM_REQ_CMP) {
647 xpt_print(periph->path, "%s: Disable LUN failed, status 0x%x\n",
648 __func__, en_lun_ccb.ccb_h.status);
649 /*
650 * XXX KDM what do we do now?
651 */
652 }
653 xpt_print(periph->path, "LUN removed, %ju ATIOs outstanding, %ju "
654 "INOTs outstanding, %d refs\n", softc->atios_sent -
655 softc->atios_returned, softc->inots_sent -
656 softc->inots_returned, periph->refcount);
657
658 bus_softc = softc->parent_softc;
659 mtx_lock(&bus_softc->lun_softc_mtx);
660 STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links);
661 mtx_unlock(&bus_softc->lun_softc_mtx);
662}
663
664static void
665ctlfecleanup(struct cam_periph *periph)
666{
667 struct ctlfe_lun_softc *softc;
668
669 xpt_print(periph->path, "%s: Called\n", __func__);
670
671 softc = (struct ctlfe_lun_softc *)periph->softc;
672
673 /*
674 * XXX KDM is there anything else that needs to be done here?
675 */
676
677 free(softc, M_CTLFE);
678}
679
680static void
681ctlfedata(struct ctlfe_lun_softc *softc, union ctl_io *io,
682 ccb_flags *flags, uint8_t **data_ptr, uint32_t *dxfer_len,
683 u_int16_t *sglist_cnt)
684{
685 struct ctlfe_softc *bus_softc;
686 struct ctlfe_lun_cmd_info *cmd_info;
687 struct ctl_sg_entry *ctl_sglist;
688 bus_dma_segment_t *cam_sglist;
689 size_t off;
690 int i, idx;
691
692 cmd_info = (struct ctlfe_lun_cmd_info *)io->io_hdr.port_priv;
693 bus_softc = softc->parent_softc;
694
695 /*
696 * Set the direction, relative to the initiator.
697 */
698 *flags &= ~CAM_DIR_MASK;
699 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN)
700 *flags |= CAM_DIR_IN;
701 else
702 *flags |= CAM_DIR_OUT;
703
704 *flags &= ~CAM_DATA_MASK;
705 idx = cmd_info->cur_transfer_index;
706 off = cmd_info->cur_transfer_off;
707 cmd_info->flags &= ~CTLFE_CMD_PIECEWISE;
708 if (io->scsiio.kern_sg_entries == 0) {
709 /* No S/G list. */
710 *data_ptr = io->scsiio.kern_data_ptr + off;
711 if (io->scsiio.kern_data_len - off <= bus_softc->maxio) {
712 *dxfer_len = io->scsiio.kern_data_len - off;
713 } else {
714 *dxfer_len = bus_softc->maxio;
715 cmd_info->cur_transfer_index = -1;
716 cmd_info->cur_transfer_off = bus_softc->maxio;
717 cmd_info->flags |= CTLFE_CMD_PIECEWISE;
718 }
719 *sglist_cnt = 0;
720
721 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
722 *flags |= CAM_DATA_PADDR;
723 else
724 *flags |= CAM_DATA_VADDR;
725 } else {
726 /* S/G list with physical or virtual pointers. */
727 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
728 cam_sglist = cmd_info->cam_sglist;
729 *dxfer_len = 0;
730 for (i = 0; i < io->scsiio.kern_sg_entries - idx; i++) {
731 cam_sglist[i].ds_addr = (bus_addr_t)ctl_sglist[i + idx].addr + off;
732 if (ctl_sglist[i + idx].len - off <= bus_softc->maxio - *dxfer_len) {
733 cam_sglist[i].ds_len = ctl_sglist[idx + i].len - off;
734 *dxfer_len += cam_sglist[i].ds_len;
735 } else {
736 cam_sglist[i].ds_len = bus_softc->maxio - *dxfer_len;
737 cmd_info->cur_transfer_index = idx + i;
738 cmd_info->cur_transfer_off = cam_sglist[i].ds_len + off;
739 cmd_info->flags |= CTLFE_CMD_PIECEWISE;
740 *dxfer_len += cam_sglist[i].ds_len;
741 if (ctl_sglist[i].len != 0)
742 i++;
743 break;
744 }
745 if (i == (CTLFE_MAX_SEGS - 1) &&
746 idx + i < (io->scsiio.kern_sg_entries - 1)) {
747 cmd_info->cur_transfer_index = idx + i + 1;
748 cmd_info->cur_transfer_off = 0;
749 cmd_info->flags |= CTLFE_CMD_PIECEWISE;
750 i++;
751 break;
752 }
753 off = 0;
754 }
755 *sglist_cnt = i;
756 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
757 *flags |= CAM_DATA_SG_PADDR;
758 else
759 *flags |= CAM_DATA_SG;
760 *data_ptr = (uint8_t *)cam_sglist;
761 }
762}
763
764static void
765ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
766{
767 struct ctlfe_lun_softc *softc;
768 struct ctlfe_lun_cmd_info *cmd_info;
769 struct ccb_hdr *ccb_h;
770 struct ccb_accept_tio *atio;
771 struct ccb_scsiio *csio;
772 uint8_t *data_ptr;
773 uint32_t dxfer_len;
774 ccb_flags flags;
775 union ctl_io *io;
776 uint8_t scsi_status;
777
778 softc = (struct ctlfe_lun_softc *)periph->softc;
779 softc->ccbs_alloced++;
780
781 ccb_h = TAILQ_FIRST(&softc->work_queue);
782 if (ccb_h == NULL) {
783 softc->ccbs_freed++;
784 xpt_release_ccb(start_ccb);
785 return;
786 }
787
788 /* Take the ATIO off the work queue */
789 TAILQ_REMOVE(&softc->work_queue, ccb_h, periph_links.tqe);
790 atio = (struct ccb_accept_tio *)ccb_h;
791 io = (union ctl_io *)ccb_h->io_ptr;
792 csio = &start_ccb->csio;
793
794 flags = atio->ccb_h.flags &
795 (CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK);
796 cmd_info = (struct ctlfe_lun_cmd_info *)io->io_hdr.port_priv;
797 cmd_info->cur_transfer_index = 0;
798 cmd_info->cur_transfer_off = 0;
799 cmd_info->flags = 0;
800
801 if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) {
802 /*
803 * Datamove call, we need to setup the S/G list.
804 */
805 scsi_status = 0;
806 csio->cdb_len = atio->cdb_len;
807 ctlfedata(softc, io, &flags, &data_ptr, &dxfer_len,
808 &csio->sglist_cnt);
809 io->scsiio.ext_data_filled += dxfer_len;
810 if (io->scsiio.ext_data_filled > io->scsiio.kern_total_len) {
811 xpt_print(periph->path, "%s: tag 0x%04x "
812 "fill len %u > total %u\n",
813 __func__, io->scsiio.tag_num,
814 io->scsiio.ext_data_filled,
815 io->scsiio.kern_total_len);
816 }
817 } else {
818 /*
819 * We're done, send status back.
820 */
821 if ((io->io_hdr.flags & CTL_FLAG_ABORT) &&
822 (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) {
823 io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED;
824
825 /*
826 * If this command was aborted, we don't
827 * need to send status back to the SIM.
828 * Just free the CTIO and ctl_io, and
829 * recycle the ATIO back to the SIM.
830 */
831 xpt_print(periph->path, "%s: aborted "
832 "command 0x%04x discarded\n",
833 __func__, io->scsiio.tag_num);
834 /*
835 * For a wildcard attachment, commands can
836 * come in with a specific target/lun. Reset
837 * the target and LUN fields back to the
838 * wildcard values before we send them back
839 * down to the SIM. The SIM has a wildcard
840 * LUN enabled, not whatever target/lun
841 * these happened to be.
842 */
843 if (softc->flags & CTLFE_LUN_WILDCARD) {
844 atio->ccb_h.target_id = CAM_TARGET_WILDCARD;
845 atio->ccb_h.target_lun = CAM_LUN_WILDCARD;
846 }
847
848 if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
849 cam_release_devq(periph->path,
850 /*relsim_flags*/0,
851 /*reduction*/0,
852 /*timeout*/0,
853 /*getcount_only*/0);
854 atio->ccb_h.status &= ~CAM_DEV_QFRZN;
855 }
856
857 if (atio->ccb_h.func_code != XPT_ACCEPT_TARGET_IO) {
858 xpt_print(periph->path, "%s: func_code "
859 "is %#x\n", __func__,
860 atio->ccb_h.func_code);
861 }
862 start_ccb->ccb_h.func_code = XPT_ABORT;
863 start_ccb->cab.abort_ccb = (union ccb *)atio;
864
865 /* Tell the SIM that we've aborted this ATIO */
866 xpt_action(start_ccb);
867 softc->ccbs_freed++;
868 xpt_release_ccb(start_ccb);
869
870 /*
871 * Send the ATIO back down to the SIM.
872 */
873 xpt_action((union ccb *)atio);
874 softc->atios_sent++;
875
876 /*
877 * If we still have work to do, ask for
878 * another CCB. Otherwise, deactivate our
879 * callout.
880 */
881 if (!TAILQ_EMPTY(&softc->work_queue))
882 xpt_schedule(periph, /*priority*/ 1);
883 return;
884 }
885 data_ptr = NULL;
886 dxfer_len = 0;
887 csio->sglist_cnt = 0;
888 scsi_status = 0;
889 }
890 if ((io->io_hdr.flags & CTL_FLAG_STATUS_QUEUED) &&
891 (cmd_info->flags & CTLFE_CMD_PIECEWISE) == 0 &&
892 ((io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) == 0 ||
893 io->io_hdr.status == CTL_SUCCESS)) {
894 io->io_hdr.flags |= CTL_FLAG_STATUS_SENT;
895 flags |= CAM_SEND_STATUS;
896 scsi_status = io->scsiio.scsi_status;
897 csio->sense_len = io->scsiio.sense_len;
898#ifdef CTLFEDEBUG
899 printf("%s: tag %04x status %x\n", __func__,
900 atio->tag_id, io->io_hdr.status);
901#endif
902 if (csio->sense_len != 0) {
903 csio->sense_data = io->scsiio.sense_data;
904 flags |= CAM_SEND_SENSE;
905 } else if (scsi_status == SCSI_STATUS_CHECK_COND) {
906 xpt_print(periph->path, "%s: check condition "
907 "with no sense\n", __func__);
908 }
909 }
910
911#ifdef CTLFEDEBUG
912 printf("%s: %s: tag %04x flags %x ptr %p len %u\n", __func__,
913 (flags & CAM_SEND_STATUS) ? "done" : "datamove",
914 atio->tag_id, flags, data_ptr, dxfer_len);
915#endif
916
917 /*
918 * Valid combinations:
919 * - CAM_SEND_STATUS, CAM_DATA_SG = 0, dxfer_len = 0,
920 * sglist_cnt = 0
921 * - CAM_SEND_STATUS = 0, CAM_DATA_SG = 0, dxfer_len != 0,
922 * sglist_cnt = 0
923 * - CAM_SEND_STATUS = 0, CAM_DATA_SG, dxfer_len != 0,
924 * sglist_cnt != 0
925 */
926#ifdef CTLFEDEBUG
927 if (((flags & CAM_SEND_STATUS)
928 && (((flags & CAM_DATA_SG) != 0)
929 || (dxfer_len != 0)
930 || (csio->sglist_cnt != 0)))
931 || (((flags & CAM_SEND_STATUS) == 0)
932 && (dxfer_len == 0))
933 || ((flags & CAM_DATA_SG)
934 && (csio->sglist_cnt == 0))
935 || (((flags & CAM_DATA_SG) == 0)
936 && (csio->sglist_cnt != 0))) {
937 printf("%s: tag %04x cdb %02x flags %#x dxfer_len "
938 "%d sg %u\n", __func__, atio->tag_id,
939 atio->cdb_io.cdb_bytes[0], flags, dxfer_len,
940 csio->sglist_cnt);
941 printf("%s: tag %04x io status %#x\n", __func__,
942 atio->tag_id, io->io_hdr.status);
943 }
944#endif
945 cam_fill_ctio(csio,
946 /*retries*/ 2,
947 ctlfedone,
948 flags,
949 (flags & CAM_TAG_ACTION_VALID) ? MSG_SIMPLE_Q_TAG : 0,
950 atio->tag_id,
951 atio->init_id,
952 scsi_status,
953 /*data_ptr*/ data_ptr,
954 /*dxfer_len*/ dxfer_len,
955 /*timeout*/ 5 * 1000);
956 start_ccb->ccb_h.flags |= CAM_UNLOCKED;
957 start_ccb->ccb_h.ccb_atio = atio;
958 if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED)
959 io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
960 io->io_hdr.flags &= ~(CTL_FLAG_DMA_QUEUED | CTL_FLAG_STATUS_QUEUED);
961
962 softc->ctios_sent++;
963
964 cam_periph_unlock(periph);
965 xpt_action(start_ccb);
966 cam_periph_lock(periph);
967
968 if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
969 cam_release_devq(periph->path,
970 /*relsim_flags*/0,
971 /*reduction*/0,
972 /*timeout*/0,
973 /*getcount_only*/0);
974 atio->ccb_h.status &= ~CAM_DEV_QFRZN;
975 }
976
977 /*
978 * If we still have work to do, ask for another CCB.
979 */
980 if (!TAILQ_EMPTY(&softc->work_queue))
981 xpt_schedule(periph, /*priority*/ 1);
982}
983
984static void
985ctlfe_free_ccb(struct cam_periph *periph, union ccb *ccb)
986{
987 struct ctlfe_lun_softc *softc;
988
989 softc = (struct ctlfe_lun_softc *)periph->softc;
990
991 switch (ccb->ccb_h.func_code) {
992 case XPT_ACCEPT_TARGET_IO:
993 softc->atios_returned++;
994 break;
995 case XPT_IMMEDIATE_NOTIFY:
996 case XPT_NOTIFY_ACKNOWLEDGE:
997 softc->inots_returned++;
998 break;
999 default:
1000 break;
1001 }
1002
1003 ctl_free_io(ccb->ccb_h.io_ptr);
1004 free(ccb, M_CTLFE);
1005
1006 KASSERT(softc->atios_returned <= softc->atios_sent, ("%s: "
1007 "atios_returned %ju > atios_sent %ju", __func__,
1008 softc->atios_returned, softc->atios_sent));
1009 KASSERT(softc->inots_returned <= softc->inots_sent, ("%s: "
1010 "inots_returned %ju > inots_sent %ju", __func__,
1011 softc->inots_returned, softc->inots_sent));
1012
1013 /*
1014 * If we have received all of our CCBs, we can release our
1015 * reference on the peripheral driver. It will probably go away
1016 * now.
1017 */
1018 if ((softc->atios_returned == softc->atios_sent)
1019 && (softc->inots_returned == softc->inots_sent)) {
1020 cam_periph_release_locked(periph);
1021 }
1022}
1023
1024static int
1025ctlfe_adjust_cdb(struct ccb_accept_tio *atio, uint32_t offset)
1026{
1027 uint64_t lba;
1028 uint32_t num_blocks, nbc;
1029 uint8_t *cmdbyt = (atio->ccb_h.flags & CAM_CDB_POINTER)?
1030 atio->cdb_io.cdb_ptr : atio->cdb_io.cdb_bytes;
1031
1032 nbc = offset >> 9; /* ASSUMING 512 BYTE BLOCKS */
1033
1034 switch (cmdbyt[0]) {
1035 case READ_6:
1036 case WRITE_6:
1037 {
1038 struct scsi_rw_6 *cdb = (struct scsi_rw_6 *)cmdbyt;
1039 lba = scsi_3btoul(cdb->addr);
1040 lba &= 0x1fffff;
1041 num_blocks = cdb->length;
1042 if (num_blocks == 0)
1043 num_blocks = 256;
1044 lba += nbc;
1045 num_blocks -= nbc;
1046 scsi_ulto3b(lba, cdb->addr);
1047 cdb->length = num_blocks;
1048 break;
1049 }
1050 case READ_10:
1051 case WRITE_10:
1052 {
1053 struct scsi_rw_10 *cdb = (struct scsi_rw_10 *)cmdbyt;
1054 lba = scsi_4btoul(cdb->addr);
1055 num_blocks = scsi_2btoul(cdb->length);
1056 lba += nbc;
1057 num_blocks -= nbc;
1058 scsi_ulto4b(lba, cdb->addr);
1059 scsi_ulto2b(num_blocks, cdb->length);
1060 break;
1061 }
1062 case READ_12:
1063 case WRITE_12:
1064 {
1065 struct scsi_rw_12 *cdb = (struct scsi_rw_12 *)cmdbyt;
1066 lba = scsi_4btoul(cdb->addr);
1067 num_blocks = scsi_4btoul(cdb->length);
1068 lba += nbc;
1069 num_blocks -= nbc;
1070 scsi_ulto4b(lba, cdb->addr);
1071 scsi_ulto4b(num_blocks, cdb->length);
1072 break;
1073 }
1074 case READ_16:
1075 case WRITE_16:
1076 case WRITE_ATOMIC_16:
1077 {
1078 struct scsi_rw_16 *cdb = (struct scsi_rw_16 *)cmdbyt;
1079 lba = scsi_8btou64(cdb->addr);
1080 num_blocks = scsi_4btoul(cdb->length);
1081 lba += nbc;
1082 num_blocks -= nbc;
1083 scsi_u64to8b(lba, cdb->addr);
1084 scsi_ulto4b(num_blocks, cdb->length);
1085 break;
1086 }
1087 default:
1088 return -1;
1089 }
1090 return (0);
1091}
1092
1093static void
1094ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
1095{
1096 struct ctlfe_lun_softc *softc;
1097 struct ctlfe_softc *bus_softc;
1098 struct ccb_accept_tio *atio = NULL;
1099 union ctl_io *io = NULL;
1100 struct mtx *mtx;
1101
1102 KASSERT((done_ccb->ccb_h.flags & CAM_UNLOCKED) != 0,
1103 ("CCB in ctlfedone() without CAM_UNLOCKED flag"));
1104#ifdef CTLFE_DEBUG
1105 printf("%s: entered, func_code = %#x\n", __func__,
1106 done_ccb->ccb_h.func_code);
1107#endif
1108
1109 softc = (struct ctlfe_lun_softc *)periph->softc;
1110 bus_softc = softc->parent_softc;
1111 mtx = cam_periph_mtx(periph);
1112 mtx_lock(mtx);
1113
1114 /*
1115 * If the peripheral is invalid, ATIOs and immediate notify CCBs
1116 * need to be freed. Most of the ATIOs and INOTs that come back
1117 * will be CCBs that are being returned from the SIM as a result of
1118 * our disabling the LUN.
1119 *
1120 * Other CCB types are handled in their respective cases below.
1121 */
1122 if (periph->flags & CAM_PERIPH_INVALID) {
1123 switch (done_ccb->ccb_h.func_code) {
1124 case XPT_ACCEPT_TARGET_IO:
1125 case XPT_IMMEDIATE_NOTIFY:
1126 case XPT_NOTIFY_ACKNOWLEDGE:
1127 ctlfe_free_ccb(periph, done_ccb);
1128 goto out;
1129 default:
1130 break;
1131 }
1132
1133 }
1134 switch (done_ccb->ccb_h.func_code) {
1135 case XPT_ACCEPT_TARGET_IO: {
1136
1137 atio = &done_ccb->atio;
1138
1139 softc->atios_returned++;
1140
1141 resubmit:
1142 /*
1143 * Allocate a ctl_io, pass it to CTL, and wait for the
1144 * datamove or done.
1145 */
1146 mtx_unlock(mtx);
1147 io = done_ccb->ccb_h.io_ptr;
1148 ctl_zero_io(io);
1149
1150 /* Save pointers on both sides */
1151 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = done_ccb;
1152 done_ccb->ccb_h.io_ptr = io;
1153
1154 /*
1155 * Only SCSI I/O comes down this path, resets, etc. come
1156 * down the immediate notify path below.
1157 */
1158 io->io_hdr.io_type = CTL_IO_SCSI;
1159 io->io_hdr.nexus.initid.id = atio->init_id;
1160 io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
1161 io->io_hdr.nexus.targ_target.id = atio->ccb_h.target_id;
1162 io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun;
1163 io->scsiio.tag_num = atio->tag_id;
1164 switch (atio->tag_action) {
1165 case CAM_TAG_ACTION_NONE:
1166 io->scsiio.tag_type = CTL_TAG_UNTAGGED;
1167 break;
1168 case MSG_SIMPLE_TASK:
1169 io->scsiio.tag_type = CTL_TAG_SIMPLE;
1170 break;
1171 case MSG_HEAD_OF_QUEUE_TASK:
1172 io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE;
1173 break;
1174 case MSG_ORDERED_TASK:
1175 io->scsiio.tag_type = CTL_TAG_ORDERED;
1176 break;
1177 case MSG_ACA_TASK:
1178 io->scsiio.tag_type = CTL_TAG_ACA;
1179 break;
1180 default:
1181 io->scsiio.tag_type = CTL_TAG_UNTAGGED;
1182 printf("%s: unhandled tag type %#x!!\n", __func__,
1183 atio->tag_action);
1184 break;
1185 }
1186 if (atio->cdb_len > sizeof(io->scsiio.cdb)) {
1187 printf("%s: WARNING: CDB len %d > ctl_io space %zd\n",
1188 __func__, atio->cdb_len, sizeof(io->scsiio.cdb));
1189 }
1190 io->scsiio.cdb_len = min(atio->cdb_len, sizeof(io->scsiio.cdb));
1191 bcopy(atio->cdb_io.cdb_bytes, io->scsiio.cdb,
1192 io->scsiio.cdb_len);
1193
1194#ifdef CTLFEDEBUG
1195 printf("%s: %ju:%d:%ju:%d: tag %04x CDB %02x\n", __func__,
1196 (uintmax_t)io->io_hdr.nexus.initid.id,
1197 io->io_hdr.nexus.targ_port,
1198 (uintmax_t)io->io_hdr.nexus.targ_target.id,
1199 io->io_hdr.nexus.targ_lun,
1200 io->scsiio.tag_num, io->scsiio.cdb[0]);
1201#endif
1202
1203 ctl_queue(io);
1204 return;
1205 }
1206 case XPT_CONT_TARGET_IO: {
1207 int srr = 0;
1208 uint32_t srr_off = 0;
1209
1210 atio = (struct ccb_accept_tio *)done_ccb->ccb_h.ccb_atio;
1211 io = (union ctl_io *)atio->ccb_h.io_ptr;
1212
1213 softc->ctios_returned++;
1214#ifdef CTLFEDEBUG
1215 printf("%s: got XPT_CONT_TARGET_IO tag %#x flags %#x\n",
1216 __func__, atio->tag_id, done_ccb->ccb_h.flags);
1217#endif
1218 /*
1219 * Handle SRR case were the data pointer is pushed back hack
1220 */
1221 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_MESSAGE_RECV
1222 && done_ccb->csio.msg_ptr != NULL
1223 && done_ccb->csio.msg_ptr[0] == MSG_EXTENDED
1224 && done_ccb->csio.msg_ptr[1] == 5
1225 && done_ccb->csio.msg_ptr[2] == 0) {
1226 srr = 1;
1227 srr_off =
1228 (done_ccb->csio.msg_ptr[3] << 24)
1229 | (done_ccb->csio.msg_ptr[4] << 16)
1230 | (done_ccb->csio.msg_ptr[5] << 8)
1231 | (done_ccb->csio.msg_ptr[6]);
1232 }
1233
1234 if (srr && (io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) {
1235 /*
1236 * If status was being sent, the back end data is now
1237 * history. Hack it up and resubmit a new command with
1238 * the CDB adjusted. If the SIM does the right thing,
1239 * all of the resid math should work.
1240 */
1241 softc->ccbs_freed++;
1242 xpt_release_ccb(done_ccb);
1243 if (ctlfe_adjust_cdb(atio, srr_off) == 0) {
1244 done_ccb = (union ccb *)atio;
1245 goto resubmit;
1246 }
1247 /*
1248 * Fall through to doom....
1249 */
1250 } else if (srr) {
1251 /*
1252 * If we have an srr and we're still sending data, we
1253 * should be able to adjust offsets and cycle again.
1254 */
1255 io->scsiio.kern_rel_offset =
1256 io->scsiio.ext_data_filled = srr_off;
1257 io->scsiio.ext_data_len = io->scsiio.kern_total_len -
1258 io->scsiio.kern_rel_offset;
1259 softc->ccbs_freed++;
1260 io->scsiio.io_hdr.status = CTL_STATUS_NONE;
1261 xpt_release_ccb(done_ccb);
1262 TAILQ_INSERT_HEAD(&softc->work_queue, &atio->ccb_h,
1263 periph_links.tqe);
1264 xpt_schedule(periph, /*priority*/ 1);
1265 break;
1266 }
1267
1268 /*
1269 * If we were sending status back to the initiator, free up
1270 * resources. If we were doing a datamove, call the
1271 * datamove done routine.
1272 */
1273 if ((io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) {
1274 softc->ccbs_freed++;
1275 xpt_release_ccb(done_ccb);
1276 /*
1277 * For a wildcard attachment, commands can come in
1278 * with a specific target/lun. Reset the target
1279 * and LUN fields back to the wildcard values before
1280 * we send them back down to the SIM. The SIM has
1281 * a wildcard LUN enabled, not whatever target/lun
1282 * these happened to be.
1283 */
1284 if (softc->flags & CTLFE_LUN_WILDCARD) {
1285 atio->ccb_h.target_id = CAM_TARGET_WILDCARD;
1286 atio->ccb_h.target_lun = CAM_LUN_WILDCARD;
1287 }
1288 if (periph->flags & CAM_PERIPH_INVALID) {
1289 ctlfe_free_ccb(periph, (union ccb *)atio);
1290 } else {
1291 softc->atios_sent++;
1292 mtx_unlock(mtx);
1293 xpt_action((union ccb *)atio);
1294 return;
1295 }
1296 } else {
1297 struct ctlfe_lun_cmd_info *cmd_info;
1298 struct ccb_scsiio *csio;
1299
1300 csio = &done_ccb->csio;
1301 cmd_info = (struct ctlfe_lun_cmd_info *)
1302 io->io_hdr.port_priv;
1303
1304 io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
1305
1306 io->scsiio.ext_data_len += csio->dxfer_len;
1307 if (io->scsiio.ext_data_len >
1308 io->scsiio.kern_total_len) {
1309 xpt_print(periph->path, "%s: tag 0x%04x "
1310 "done len %u > total %u sent %u\n",
1311 __func__, io->scsiio.tag_num,
1312 io->scsiio.ext_data_len,
1313 io->scsiio.kern_total_len,
1314 io->scsiio.ext_data_filled);
1315 }
1316 /*
1317 * Translate CAM status to CTL status. Success
1318 * does not change the overall, ctl_io status. In
1319 * that case we just set port_status to 0. If we
1320 * have a failure, though, set a data phase error
1321 * for the overall ctl_io.
1322 */
1323 switch (done_ccb->ccb_h.status & CAM_STATUS_MASK) {
1324 case CAM_REQ_CMP:
1325 io->io_hdr.port_status = 0;
1326 break;
1327 default:
1328 /*
1329 * XXX KDM we probably need to figure out a
1330 * standard set of errors that the SIM
1331 * drivers should return in the event of a
1332 * data transfer failure. A data phase
1333 * error will at least point the user to a
1334 * data transfer error of some sort.
1335 * Hopefully the SIM printed out some
1336 * additional information to give the user
1337 * a clue what happened.
1338 */
1339 io->io_hdr.port_status = 0xbad1;
1340 ctl_set_data_phase_error(&io->scsiio);
1341 /*
1342 * XXX KDM figure out residual.
1343 */
1344 break;
1345 }
1346 /*
1347 * If we had to break this S/G list into multiple
1348 * pieces, figure out where we are in the list, and
1349 * continue sending pieces if necessary.
1350 */
1351 if ((cmd_info->flags & CTLFE_CMD_PIECEWISE)
1352 && (io->io_hdr.port_status == 0)) {
1353 ccb_flags flags;
1354 uint8_t scsi_status;
1355 uint8_t *data_ptr;
1356 uint32_t dxfer_len;
1357
1358 flags = atio->ccb_h.flags &
1359 (CAM_DIS_DISCONNECT|
1360 CAM_TAG_ACTION_VALID);
1361
1362 ctlfedata(softc, io, &flags, &data_ptr,
1363 &dxfer_len, &csio->sglist_cnt);
1364
1365 scsi_status = 0;
1366
1367 if (((flags & CAM_SEND_STATUS) == 0)
1368 && (dxfer_len == 0)) {
1369 printf("%s: tag %04x no status or "
1370 "len cdb = %02x\n", __func__,
1371 atio->tag_id,
1372 atio->cdb_io.cdb_bytes[0]);
1373 printf("%s: tag %04x io status %#x\n",
1374 __func__, atio->tag_id,
1375 io->io_hdr.status);
1376 }
1377
1378 cam_fill_ctio(csio,
1379 /*retries*/ 2,
1380 ctlfedone,
1381 flags,
1382 (flags & CAM_TAG_ACTION_VALID) ?
1383 MSG_SIMPLE_Q_TAG : 0,
1384 atio->tag_id,
1385 atio->init_id,
1386 scsi_status,
1387 /*data_ptr*/ data_ptr,
1388 /*dxfer_len*/ dxfer_len,
1389 /*timeout*/ 5 * 1000);
1390
1391 csio->ccb_h.flags |= CAM_UNLOCKED;
1392 csio->resid = 0;
1393 csio->ccb_h.ccb_atio = atio;
1394 io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
1395 softc->ctios_sent++;
1396 mtx_unlock(mtx);
1397 xpt_action((union ccb *)csio);
1398 } else {
1399 /*
1400 * Release the CTIO. The ATIO will be sent back
1401 * down to the SIM once we send status.
1402 */
1403 softc->ccbs_freed++;
1404 xpt_release_ccb(done_ccb);
1405 mtx_unlock(mtx);
1406
1407 /* Call the backend move done callback */
1408 io->scsiio.be_move_done(io);
1409 }
1410 return;
1411 }
1412 break;
1413 }
1414 case XPT_IMMEDIATE_NOTIFY: {
1415 union ctl_io *io;
1416 struct ccb_immediate_notify *inot;
1417 cam_status status;
1418 int frozen, send_ctl_io;
1419
1420 inot = &done_ccb->cin1;
1421
1422 softc->inots_returned++;
1423
1424 frozen = (done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
1425
1426 printf("%s: got XPT_IMMEDIATE_NOTIFY status %#x tag %#x "
1427 "seq %#x\n", __func__, inot->ccb_h.status,
1428 inot->tag_id, inot->seq_id);
1429
1430 io = done_ccb->ccb_h.io_ptr;
1431 ctl_zero_io(io);
1432
1433 send_ctl_io = 1;
1434
1435 io->io_hdr.io_type = CTL_IO_TASK;
1436 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr =done_ccb;
1437 inot->ccb_h.io_ptr = io;
1438 io->io_hdr.nexus.initid.id = inot->initiator_id;
1439 io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
1440 io->io_hdr.nexus.targ_target.id = inot->ccb_h.target_id;
1441 io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun;
1442 /* XXX KDM should this be the tag_id? */
1443 io->taskio.tag_num = inot->seq_id;
1444
1445 status = inot->ccb_h.status & CAM_STATUS_MASK;
1446 switch (status) {
1447 case CAM_SCSI_BUS_RESET:
1448 io->taskio.task_action = CTL_TASK_BUS_RESET;
1449 break;
1450 case CAM_BDR_SENT:
1451 io->taskio.task_action = CTL_TASK_TARGET_RESET;
1452 break;
1453 case CAM_MESSAGE_RECV:
1454 switch (inot->arg) {
1455 case MSG_ABORT_TASK_SET:
1456 io->taskio.task_action =
1457 CTL_TASK_ABORT_TASK_SET;
1458 break;
1459 case MSG_TARGET_RESET:
1460 io->taskio.task_action =
1461 CTL_TASK_TARGET_RESET;
1462 break;
1463 case MSG_ABORT_TASK:
1464 io->taskio.task_action =
1465 CTL_TASK_ABORT_TASK;
1466 break;
1467 case MSG_LOGICAL_UNIT_RESET:
1468 io->taskio.task_action =
1469 CTL_TASK_LUN_RESET;
1470 break;
1471 case MSG_CLEAR_TASK_SET:
1472 io->taskio.task_action =
1473 CTL_TASK_CLEAR_TASK_SET;
1474 break;
1475 case MSG_CLEAR_ACA:
1476 io->taskio.task_action =
1477 CTL_TASK_CLEAR_ACA;
1478 break;
1479 case MSG_NOOP:
1480 send_ctl_io = 0;
1481 break;
1482 default:
1483 xpt_print(periph->path,
1484 "%s: unsupported message 0x%x\n",
1485 __func__, inot->arg);
1486 send_ctl_io = 0;
1487 break;
1488 }
1489 break;
1490 case CAM_REQ_ABORTED:
1491 /*
1492 * This request was sent back by the driver.
1493 * XXX KDM what do we do here?
1494 */
1495 send_ctl_io = 0;
1496 break;
1497 case CAM_REQ_INVALID:
1498 case CAM_PROVIDE_FAIL:
1499 default:
1500 /*
1501 * We should only get here if we're talking
1502 * to a talking to a SIM that is target
1503 * capable but supports the old API. In
1504 * that case, we need to just free the CCB.
1505 * If we actually send a notify acknowledge,
1506 * it will send that back with an error as
1507 * well.
1508 */
1509
1510 if ((status != CAM_REQ_INVALID)
1511 && (status != CAM_PROVIDE_FAIL))
1512 xpt_print(periph->path,
1513 "%s: unsupported CAM status 0x%x\n",
1514 __func__, status);
1515
1516 ctlfe_free_ccb(periph, done_ccb);
1517
1518 goto out;
1519 }
1520 if (send_ctl_io != 0) {
1521 ctl_queue(io);
1522 } else {
1523 done_ccb->ccb_h.status = CAM_REQ_INPROG;
1524 done_ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
1525 xpt_action(done_ccb);
1526 }
1527
1528 if (frozen != 0) {
1529 cam_release_devq(periph->path,
1530 /*relsim_flags*/ 0,
1531 /*opening reduction*/ 0,
1532 /*timeout*/ 0,
1533 /*getcount_only*/ 0);
1534 }
1535 break;
1536 }
1537 case XPT_NOTIFY_ACKNOWLEDGE:
1538 /*
1539 * Queue this back down to the SIM as an immediate notify.
1540 */
1541 done_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
1542 xpt_action(done_ccb);
1543 softc->inots_sent++;
1544 break;
1545 case XPT_SET_SIM_KNOB:
1546 case XPT_GET_SIM_KNOB:
1547 break;
1548 default:
1549 panic("%s: unexpected CCB type %#x", __func__,
1550 done_ccb->ccb_h.func_code);
1551 break;
1552 }
1553
1554out:
1555 mtx_unlock(mtx);
1556}
1557
1558static void
1559ctlfe_onoffline(void *arg, int online)
1560{
1561 struct ctlfe_softc *bus_softc;
1562 union ccb *ccb;
1563 cam_status status;
1564 struct cam_path *path;
1565 int set_wwnn;
1566
1567 bus_softc = (struct ctlfe_softc *)arg;
1568
1569 set_wwnn = 0;
1570
1571 status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
1572 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
1573 if (status != CAM_REQ_CMP) {
1574 printf("%s: unable to create path!\n", __func__);
1575 return;
1576 }
1577 ccb = xpt_alloc_ccb();
1578 xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
1579
1580 /*
1581 * Copan WWN format:
1582 *
1583 * Bits 63-60: 0x5 NAA, IEEE registered name
1584 * Bits 59-36: 0x000ED5 IEEE Company name assigned to Copan
1585 * Bits 35-12: Copan SSN (Sequential Serial Number)
1586 * Bits 11-8: Type of port:
1587 * 1 == N-Port
1588 * 2 == F-Port
1589 * 3 == NL-Port
1590 * Bits 7-0: 0 == Node Name, >0 == Port Number
1591 */
1592
1593 if (online != 0) {
1594
1595 ccb->ccb_h.func_code = XPT_GET_SIM_KNOB;
1596
1597
1598 xpt_action(ccb);
1599
1600
1601 if ((ccb->knob.xport_specific.valid & KNOB_VALID_ADDRESS) != 0){
1602#ifdef RANDOM_WWNN
1603 uint64_t random_bits;
1604#endif
1605
1606 printf("%s: %s current WWNN %#jx\n", __func__,
1607 bus_softc->port_name,
1608 ccb->knob.xport_specific.fc.wwnn);
1609 printf("%s: %s current WWPN %#jx\n", __func__,
1610 bus_softc->port_name,
1611 ccb->knob.xport_specific.fc.wwpn);
1612
1613#ifdef RANDOM_WWNN
1614 arc4rand(&random_bits, sizeof(random_bits), 0);
1615#endif
1616
1617 /*
1618 * XXX KDM this is a bit of a kludge for now. We
1619 * take the current WWNN/WWPN from the card, and
1620 * replace the company identifier and the NL-Port
1621 * indicator and the port number (for the WWPN).
1622 * This should be replaced later with ddb_GetWWNN,
1623 * or possibly a more centralized scheme. (It
1624 * would be nice to have the WWNN/WWPN for each
1625 * port stored in the ctl_port structure.)
1626 */
1627#ifdef RANDOM_WWNN
1628 ccb->knob.xport_specific.fc.wwnn =
1629 (random_bits &
1630 0x0000000fffffff00ULL) |
1631 /* Company ID */ 0x5000ED5000000000ULL |
1632 /* NL-Port */ 0x0300;
1633 ccb->knob.xport_specific.fc.wwpn =
1634 (random_bits &
1635 0x0000000fffffff00ULL) |
1636 /* Company ID */ 0x5000ED5000000000ULL |
1637 /* NL-Port */ 0x3000 |
1638 /* Port Num */ (bus_softc->port.targ_port & 0xff);
1639
1640 /*
1641 * This is a bit of an API break/reversal, but if
1642 * we're doing the random WWNN that's a little
1643 * different anyway. So record what we're actually
1644 * using with the frontend code so it's reported
1645 * accurately.
1646 */
1647 ctl_port_set_wwns(&bus_softc->port,
1648 true, ccb->knob.xport_specific.fc.wwnn,
1649 true, ccb->knob.xport_specific.fc.wwpn);
1650 set_wwnn = 1;
1651#else /* RANDOM_WWNN */
1652 /*
1653 * If the user has specified a WWNN/WWPN, send them
1654 * down to the SIM. Otherwise, record what the SIM
1655 * has reported.
1656 */
1657 if ((bus_softc->port.wwnn != 0)
1658 && (bus_softc->port.wwpn != 0)) {
1659 ccb->knob.xport_specific.fc.wwnn =
1660 bus_softc->port.wwnn;
1661 ccb->knob.xport_specific.fc.wwpn =
1662 bus_softc->port.wwpn;
1663 set_wwnn = 1;
1664 } else {
1665 ctl_port_set_wwns(&bus_softc->port,
1666 true, ccb->knob.xport_specific.fc.wwnn,
1667 true, ccb->knob.xport_specific.fc.wwpn);
1668 }
1669#endif /* RANDOM_WWNN */
1670
1671
1672 if (set_wwnn != 0) {
1673 printf("%s: %s new WWNN %#jx\n", __func__,
1674 bus_softc->port_name,
1675 ccb->knob.xport_specific.fc.wwnn);
1676 printf("%s: %s new WWPN %#jx\n", __func__,
1677 bus_softc->port_name,
1678 ccb->knob.xport_specific.fc.wwpn);
1679 }
1680 } else {
1681 printf("%s: %s has no valid WWNN/WWPN\n", __func__,
1682 bus_softc->port_name);
1683 }
1684 }
1685 ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
1686 ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
1687 if (set_wwnn != 0)
1688 ccb->knob.xport_specific.valid |= KNOB_VALID_ADDRESS;
1689
1690 if (online != 0)
1691 ccb->knob.xport_specific.fc.role = KNOB_ROLE_TARGET;
1692 else
1693 ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE;
1694
1695 xpt_action(ccb);
1696
1697 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1698 printf("%s: SIM %s (path id %d) target %s failed with "
1699 "status %#x\n",
1700 __func__, bus_softc->port_name, bus_softc->path_id,
1701 (online != 0) ? "enable" : "disable",
1702 ccb->ccb_h.status);
1703 } else {
1704 printf("%s: SIM %s (path id %d) target %s succeeded\n",
1705 __func__, bus_softc->port_name, bus_softc->path_id,
1706 (online != 0) ? "enable" : "disable");
1707 }
1708
1709 xpt_free_path(path);
1710 xpt_free_ccb(ccb);
1711}
1712
1713static void
1714ctlfe_online(void *arg)
1715{
1716 struct ctlfe_softc *bus_softc;
1717 struct cam_path *path;
1718 cam_status status;
1719 struct ctlfe_lun_softc *lun_softc;
1720 struct cam_periph *periph;
1721
1722 bus_softc = (struct ctlfe_softc *)arg;
1723
1724 /*
1725 * Create the wildcard LUN before bringing the port online.
1726 */
1727 status = xpt_create_path(&path, /*periph*/ NULL,
1728 bus_softc->path_id, CAM_TARGET_WILDCARD,
1729 CAM_LUN_WILDCARD);
1730 if (status != CAM_REQ_CMP) {
1731 printf("%s: unable to create path for wildcard periph\n",
1732 __func__);
1733 return;
1734 }
1735
1736 lun_softc = malloc(sizeof(*lun_softc), M_CTLFE, M_WAITOK | M_ZERO);
1737
1738 xpt_path_lock(path);
1739 periph = cam_periph_find(path, "ctl");
1740 if (periph != NULL) {
1741 /* We've already got a periph, no need to alloc a new one. */
1742 xpt_path_unlock(path);
1743 xpt_free_path(path);
1744 free(lun_softc, M_CTLFE);
1745 return;
1746 }
1747 lun_softc->parent_softc = bus_softc;
1748 lun_softc->flags |= CTLFE_LUN_WILDCARD;
1749
1750 status = cam_periph_alloc(ctlferegister,
1751 ctlfeoninvalidate,
1752 ctlfecleanup,
1753 ctlfestart,
1754 "ctl",
1755 CAM_PERIPH_BIO,
1756 path,
1757 ctlfeasync,
1758 0,
1759 lun_softc);
1760
1761 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1762 const struct cam_status_entry *entry;
1763
1764 entry = cam_fetch_status_entry(status);
1765 printf("%s: CAM error %s (%#x) returned from "
1766 "cam_periph_alloc()\n", __func__, (entry != NULL) ?
1767 entry->status_text : "Unknown", status);
1768 free(lun_softc, M_CTLFE);
1769 }
1770
1771 xpt_path_unlock(path);
1772 ctlfe_onoffline(arg, /*online*/ 1);
1773 xpt_free_path(path);
1774}
1775
1776static void
1777ctlfe_offline(void *arg)
1778{
1779 struct ctlfe_softc *bus_softc;
1780 struct cam_path *path;
1781 cam_status status;
1782 struct cam_periph *periph;
1783
1784 bus_softc = (struct ctlfe_softc *)arg;
1785
1786 ctlfe_onoffline(arg, /*online*/ 0);
1787
1788 /*
1789 * Disable the wildcard LUN for this port now that we have taken
1790 * the port offline.
1791 */
1792 status = xpt_create_path(&path, /*periph*/ NULL,
1793 bus_softc->path_id, CAM_TARGET_WILDCARD,
1794 CAM_LUN_WILDCARD);
1795 if (status != CAM_REQ_CMP) {
1796 printf("%s: unable to create path for wildcard periph\n",
1797 __func__);
1798 return;
1799 }
1800 xpt_path_lock(path);
1801 if ((periph = cam_periph_find(path, "ctl")) != NULL)
1802 cam_periph_invalidate(periph);
1803 xpt_path_unlock(path);
1804 xpt_free_path(path);
1805}
1806
1807/*
1808 * This will get called to enable a LUN on every bus that is attached to
1809 * CTL. So we only need to create a path/periph for this particular bus.
1810 */
1811static int
1812ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
1813{
1814 struct ctlfe_softc *bus_softc;
1815 struct ctlfe_lun_softc *softc;
1816 struct cam_path *path;
1817 struct cam_periph *periph;
1818 cam_status status;
1819
1820 bus_softc = (struct ctlfe_softc *)arg;
1821
1822 status = xpt_create_path(&path, /*periph*/ NULL,
1823 bus_softc->path_id,
1824 targ_id.id, lun_id);
1825 /* XXX KDM need some way to return status to CTL here? */
1826 if (status != CAM_REQ_CMP) {
1827 printf("%s: could not create path, status %#x\n", __func__,
1828 status);
1829 return (1);
1830 }
1831
1832 softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO);
1833 xpt_path_lock(path);
1834 periph = cam_periph_find(path, "ctl");
1835 if (periph != NULL) {
1836 /* We've already got a periph, no need to alloc a new one. */
1837 xpt_path_unlock(path);
1838 xpt_free_path(path);
1839 free(softc, M_CTLFE);
1840 return (0);
1841 }
1842 softc->parent_softc = bus_softc;
1843
1844 status = cam_periph_alloc(ctlferegister,
1845 ctlfeoninvalidate,
1846 ctlfecleanup,
1847 ctlfestart,
1848 "ctl",
1849 CAM_PERIPH_BIO,
1850 path,
1851 ctlfeasync,
1852 0,
1853 softc);
1854
1855 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1856 const struct cam_status_entry *entry;
1857
1858 entry = cam_fetch_status_entry(status);
1859 printf("%s: CAM error %s (%#x) returned from "
1860 "cam_periph_alloc()\n", __func__, (entry != NULL) ?
1861 entry->status_text : "Unknown", status);
1862 free(softc, M_CTLFE);
1863 }
1864
1865 xpt_path_unlock(path);
1866 xpt_free_path(path);
1867 return (0);
1868}
1869
1870/*
1871 * This will get called when the user removes a LUN to disable that LUN
1872 * on every bus that is attached to CTL.
1873 */
1874static int
1875ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
1876{
1877 struct ctlfe_softc *softc;
1878 struct ctlfe_lun_softc *lun_softc;
1879
1880 softc = (struct ctlfe_softc *)arg;
1881
1882 mtx_lock(&softc->lun_softc_mtx);
1883 STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {
1884 struct cam_path *path;
1885
1886 path = lun_softc->periph->path;
1887
1888 if ((xpt_path_target_id(path) == targ_id.id)
1889 && (xpt_path_lun_id(path) == lun_id)) {
1890 break;
1891 }
1892 }
1893 if (lun_softc == NULL) {
1894 mtx_unlock(&softc->lun_softc_mtx);
1895 printf("%s: can't find target %d lun %d\n", __func__,
1896 targ_id.id, lun_id);
1897 return (1);
1898 }
1899 cam_periph_acquire(lun_softc->periph);
1900 mtx_unlock(&softc->lun_softc_mtx);
1901
1902 cam_periph_lock(lun_softc->periph);
1903 cam_periph_invalidate(lun_softc->periph);
1904 cam_periph_unlock(lun_softc->periph);
1905 cam_periph_release(lun_softc->periph);
1906 return (0);
1907}
1908
1909static void
1910ctlfe_dump_sim(struct cam_sim *sim)
1911{
1912
1913 printf("%s%d: max tagged openings: %d, max dev openings: %d\n",
1914 sim->sim_name, sim->unit_number,
1915 sim->max_tagged_dev_openings, sim->max_dev_openings);
1916}
1917
1918/*
1919 * Assumes that the SIM lock is held.
1920 */
1921static void
1922ctlfe_dump_queue(struct ctlfe_lun_softc *softc)
1923{
1924 struct ccb_hdr *hdr;
1925 struct cam_periph *periph;
1926 int num_items;
1927
1928 periph = softc->periph;
1929 num_items = 0;
1930
1931 TAILQ_FOREACH(hdr, &softc->work_queue, periph_links.tqe) {
1932 union ctl_io *io = hdr->io_ptr;
1933
1934 num_items++;
1935
1936 /*
1937 * Only regular SCSI I/O is put on the work
1938 * queue, so we can print sense here. There may be no
1939 * sense if it's no the queue for a DMA, but this serves to
1940 * print out the CCB as well.
1941 *
1942 * XXX KDM switch this over to scsi_sense_print() when
1943 * CTL is merged in with CAM.
1944 */
1945 ctl_io_error_print(io, NULL);
1946
1947 /*
1948 * Print DMA status if we are DMA_QUEUED.
1949 */
1950 if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) {
1951 xpt_print(periph->path,
1952 "Total %u, Current %u, Resid %u\n",
1953 io->scsiio.kern_total_len,
1954 io->scsiio.kern_data_len,
1955 io->scsiio.kern_data_resid);
1956 }
1957 }
1958
1959 xpt_print(periph->path, "%d requests total waiting for CCBs\n",
1960 num_items);
1961 xpt_print(periph->path, "%ju CCBs outstanding (%ju allocated, %ju "
1962 "freed)\n", (uintmax_t)(softc->ccbs_alloced -
1963 softc->ccbs_freed), (uintmax_t)softc->ccbs_alloced,
1964 (uintmax_t)softc->ccbs_freed);
1965 xpt_print(periph->path, "%ju CTIOs outstanding (%ju sent, %ju "
1966 "returned\n", (uintmax_t)(softc->ctios_sent -
1967 softc->ctios_returned), softc->ctios_sent,
1968 softc->ctios_returned);
1969}
1970
1971/*
1972 * Datamove/done routine called by CTL. Put ourselves on the queue to
1973 * receive a CCB from CAM so we can queue the continue I/O request down
1974 * to the adapter.
1975 */
1976static void
1977ctlfe_datamove(union ctl_io *io)
1978{
1979 union ccb *ccb;
1980 struct cam_periph *periph;
1981 struct ctlfe_lun_softc *softc;
1982
1983 KASSERT(io->io_hdr.io_type == CTL_IO_SCSI,
1984 ("Unexpected io_type (%d) in ctlfe_datamove", io->io_hdr.io_type));
1985
1986 ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
1987 periph = xpt_path_periph(ccb->ccb_h.path);
1988 cam_periph_lock(periph);
1989 softc = (struct ctlfe_lun_softc *)periph->softc;
1990 io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED;
1991 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE)
1992 io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED;
1993 TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h,
1994 periph_links.tqe);
1995 xpt_schedule(periph, /*priority*/ 1);
1996 cam_periph_unlock(periph);
1997}
1998
1999static void
2000ctlfe_done(union ctl_io *io)
2001{
2002 union ccb *ccb;
2003 struct cam_periph *periph;
2004 struct ctlfe_lun_softc *softc;
2005
2006 ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
2007 periph = xpt_path_periph(ccb->ccb_h.path);
2008 cam_periph_lock(periph);
2009 softc = (struct ctlfe_lun_softc *)periph->softc;
2010
2011 if (io->io_hdr.io_type == CTL_IO_TASK) {
2012 /*
2013 * Task management commands don't require any further
2014 * communication back to the adapter. Requeue the CCB
2015 * to the adapter, and free the CTL I/O.
2016 */
2017 xpt_print(ccb->ccb_h.path, "%s: returning task I/O "
2018 "tag %#x seq %#x\n", __func__,
2019 ccb->cin1.tag_id, ccb->cin1.seq_id);
2020 /*
2021 * Send the notify acknowledge down to the SIM, to let it
2022 * know we processed the task management command.
2023 */
2024 ccb->ccb_h.status = CAM_REQ_INPROG;
2025 ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
2026 xpt_action(ccb);
2027 } else if (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) {
2028 if (softc->flags & CTLFE_LUN_WILDCARD) {
2029 ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
2030 ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
2031 }
2032 if (periph->flags & CAM_PERIPH_INVALID) {
2033 ctlfe_free_ccb(periph, ccb);
2034 } else {
2035 softc->atios_sent++;
2036 cam_periph_unlock(periph);
2037 xpt_action(ccb);
2038 return;
2039 }
2040 } else {
2041 io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED;
2042 TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h,
2043 periph_links.tqe);
2044 xpt_schedule(periph, /*priority*/ 1);
2045 }
2046
2047 cam_periph_unlock(periph);
2048}
2049
2050static void
2051ctlfe_dump(void)
2052{
2053 struct ctlfe_softc *bus_softc;
2054 struct ctlfe_lun_softc *lun_softc;
2055
2056 STAILQ_FOREACH(bus_softc, &ctlfe_softc_list, links) {
2057 ctlfe_dump_sim(bus_softc->sim);
2058 STAILQ_FOREACH(lun_softc, &bus_softc->lun_softc_list, links)
2059 ctlfe_dump_queue(lun_softc);
2060 }
2061}