1 /*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (C) 2003
5 * Hidetoshi Shimokawa. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 *
18 * This product includes software developed by Hidetoshi Shimokawa.
19 *
20 * 4. Neither the name of the author nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
40 #include <sys/sysctl.h>
41 #include <sys/types.h>
42 #include <sys/conf.h>
43 #include <sys/malloc.h>
44 #include <sys/endian.h>
45
46 #include <sys/bus.h>
47 #include <machine/bus.h>
48
49 #include <dev/firewire/firewire.h>
50 #include <dev/firewire/firewirereg.h>
51 #include <dev/firewire/iec13213.h>
52 #include <dev/firewire/sbp.h>
53 #include <dev/firewire/fwmem.h>
54
55 #include <cam/cam.h>
56 #include <cam/cam_ccb.h>
57 #include <cam/cam_sim.h>
58 #include <cam/cam_xpt_sim.h>
59 #include <cam/cam_debug.h>
60 #include <cam/cam_periph.h>
61 #include <cam/scsi/scsi_all.h>
62 #include <cam/scsi/scsi_message.h>
63
64 #define SBP_TARG_RECV_LEN 8
65 #define MAX_INITIATORS 8
66 #define MAX_LUN 63
67 #define MAX_LOGINS 63
68 #define MAX_NODES 63
69 /*
70 * management/command block agent registers
71 *
72 * BASE 0xffff f001 0000 management port
73 * BASE 0xffff f001 0020 command port for login id 0
74 * BASE 0xffff f001 0040 command port for login id 1
75 *
76 */
77 #define SBP_TARG_MGM 0x10000 /* offset from 0xffff f000 000 */
78 #define SBP_TARG_BIND_HI 0xffff
79 #define SBP_TARG_BIND_LO(l) (0xf0000000 + SBP_TARG_MGM + 0x20 * ((l) + 1))
80 #define SBP_TARG_BIND_START (((u_int64_t)SBP_TARG_BIND_HI << 32) | \
81 SBP_TARG_BIND_LO(-1))
82 #define SBP_TARG_BIND_END (((u_int64_t)SBP_TARG_BIND_HI << 32) | \
83 SBP_TARG_BIND_LO(MAX_LOGINS))
84 #define SBP_TARG_LOGIN_ID(lo) (((lo) - SBP_TARG_BIND_LO(0))/0x20)
85 #define SBP_TARG_MAX_CHUNK 2048 /* max DMA chunk per xfer */
86
87 #define FETCH_MGM 0
88 #define FETCH_CMD 1
89 #define FETCH_POINTER 2
90
91 #define F_LINK_ACTIVE (1 << 0)
92 #define F_ATIO_STARVED (1 << 1)
93 #define F_LOGIN (1 << 2)
94 #define F_HOLD (1 << 3)
95 #define F_FREEZED (1 << 4)
96
97 static MALLOC_DEFINE(M_SBP_TARG, "sbp_targ", "SBP-II/FireWire target mode");
98
99 static int debug = 0;
100
101 SYSCTL_INT(_debug, OID_AUTO, sbp_targ_debug, CTLFLAG_RW, &debug, 0,
102 "SBP target mode debug flag");
103
104 struct sbp_targ_login {
105 struct sbp_targ_lstate *lstate;
106 struct fw_device *fwdev;
107 struct sbp_login_res loginres;
108 uint16_t fifo_hi;
109 uint16_t last_hi;
110 uint32_t fifo_lo;
111 uint32_t last_lo;
112 STAILQ_HEAD(, orb_info) orbs;
113 STAILQ_ENTRY(sbp_targ_login) link;
114 uint16_t hold_sec;
115 uint16_t id;
116 uint8_t flags;
117 uint8_t spd;
118 struct callout hold_callout;
119 };
120
121 struct sbp_targ_lstate {
122 uint16_t lun;
123 struct sbp_targ_softc *sc;
124 struct cam_path *path;
125 struct ccb_hdr_slist accept_tios;
126 struct ccb_hdr_slist immed_notifies;
127 struct crom_chunk model;
128 uint32_t flags;
129 STAILQ_HEAD(, sbp_targ_login) logins;
130 };
131
132 struct sbp_targ_softc {
133 struct firewire_dev_comm fd;
134 struct cam_sim *sim;
135 struct cam_path *path;
136 struct fw_bind fwb;
137 int ndevs;
138 int flags;
139 struct crom_chunk unit;
140 struct sbp_targ_lstate *lstate[MAX_LUN];
141 struct sbp_targ_lstate *black_hole;
142 struct sbp_targ_login *logins[MAX_LOGINS];
143 struct mtx mtx;
144 };
145 #define SBP_LOCK(sc) mtx_lock(&(sc)->mtx)
146 #define SBP_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
147
148 struct corb4 {
149 #if BYTE_ORDER == BIG_ENDIAN
150 uint32_t n:1,
151 rq_fmt:2,
152 :1,
153 dir:1,
154 spd:3,
155 max_payload:4,
156 page_table_present:1,
157 page_size:3,
158 data_size:16;
159 #else
160 uint32_t data_size:16,
161 page_size:3,
162 page_table_present:1,
163 max_payload:4,
164 spd:3,
165 dir:1,
166 :1,
167 rq_fmt:2,
168 n:1;
169 #endif
170 };
171
172 struct morb4 {
173 #if BYTE_ORDER == BIG_ENDIAN
174 uint32_t n:1,
175 rq_fmt:2,
176 :9,
177 fun:4,
178 id:16;
179 #else
180 uint32_t id:16,
181 fun:4,
182 :9,
183 rq_fmt:2,
184 n:1;
185 #endif
186 };
187
188
189 /*
190 * Urestricted page table format
191 * states that the segment length
192 * and high base addr are in the first
193 * 32 bits and the base low is in
194 * the second
195 */
196 struct unrestricted_page_table_fmt {
197 uint16_t segment_len;
198 uint16_t segment_base_high;
199 uint32_t segment_base_low;
200 };
201
202
203 struct orb_info {
204 struct sbp_targ_softc *sc;
205 struct fw_device *fwdev;
206 struct sbp_targ_login *login;
207 union ccb *ccb;
208 struct ccb_accept_tio *atio;
209 uint8_t state;
210 #define ORBI_STATUS_NONE 0
211 #define ORBI_STATUS_FETCH 1
212 #define ORBI_STATUS_ATIO 2
213 #define ORBI_STATUS_CTIO 3
214 #define ORBI_STATUS_STATUS 4
215 #define ORBI_STATUS_POINTER 5
216 #define ORBI_STATUS_ABORTED 7
217 uint8_t refcount;
218 uint16_t orb_hi;
219 uint32_t orb_lo;
220 uint32_t data_hi;
221 uint32_t data_lo;
222 struct corb4 orb4;
223 STAILQ_ENTRY(orb_info) link;
224 uint32_t orb[8];
225 struct unrestricted_page_table_fmt *page_table;
226 struct unrestricted_page_table_fmt *cur_pte;
227 struct unrestricted_page_table_fmt *last_pte;
228 uint32_t last_block_read;
229 struct sbp_status status;
230 };
231
232 static char *orb_fun_name[] = {
233 ORB_FUN_NAMES
234 };
235
236 static void sbp_targ_recv(struct fw_xfer *);
237 static void sbp_targ_fetch_orb(struct sbp_targ_softc *, struct fw_device *,
238 uint16_t, uint32_t, struct sbp_targ_login *, int);
239 static void sbp_targ_xfer_pt(struct orb_info *);
240 static void sbp_targ_abort(struct sbp_targ_softc *, struct orb_info *);
241
242 static void
sbp_targ_identify(driver_t * driver,device_t parent)243 sbp_targ_identify(driver_t *driver, device_t parent)
244 {
245 BUS_ADD_CHILD(parent, 0, "sbp_targ", device_get_unit(parent));
246 }
247
248 static int
sbp_targ_probe(device_t dev)249 sbp_targ_probe(device_t dev)
250 {
251 device_t pa;
252
253 if (fw_get_unit(dev) != NULL)
254 return (ENXIO);
255
256 pa = device_get_parent(dev);
257 if (device_get_unit(dev) != device_get_unit(pa))
258 return (ENXIO);
259
260 device_set_desc(dev, "SBP-2/SCSI over FireWire target mode");
261 return (0);
262 }
263
264 static void
sbp_targ_dealloc_login(struct sbp_targ_login * login)265 sbp_targ_dealloc_login(struct sbp_targ_login *login)
266 {
267 struct orb_info *orbi, *next;
268
269 if (login == NULL) {
270 printf("%s: login = NULL\n", __func__);
271 return;
272 }
273 for (orbi = STAILQ_FIRST(&login->orbs); orbi != NULL; orbi = next) {
274 next = STAILQ_NEXT(orbi, link);
275 if (debug)
276 printf("%s: free orbi %p\n", __func__, orbi);
277 free(orbi, M_SBP_TARG);
278 orbi = NULL;
279 }
280 callout_stop(&login->hold_callout);
281
282 STAILQ_REMOVE(&login->lstate->logins, login, sbp_targ_login, link);
283 login->lstate->sc->logins[login->id] = NULL;
284 if (debug)
285 printf("%s: free login %p\n", __func__, login);
286 free((void *)login, M_SBP_TARG);
287 login = NULL;
288 }
289
290 static void
sbp_targ_hold_expire(void * arg)291 sbp_targ_hold_expire(void *arg)
292 {
293 struct sbp_targ_login *login;
294
295 login = (struct sbp_targ_login *)arg;
296
297 if (login->flags & F_HOLD) {
298 printf("%s: login_id=%d expired\n", __func__, login->id);
299 sbp_targ_dealloc_login(login);
300 } else {
301 printf("%s: login_id=%d not hold\n", __func__, login->id);
302 }
303 }
304
305 static void
sbp_targ_post_busreset(void * arg)306 sbp_targ_post_busreset(void *arg)
307 {
308 struct sbp_targ_softc *sc;
309 struct crom_src *src;
310 struct crom_chunk *root;
311 struct crom_chunk *unit;
312 struct sbp_targ_lstate *lstate;
313 struct sbp_targ_login *login;
314 int i;
315
316 sc = (struct sbp_targ_softc *)arg;
317 src = sc->fd.fc->crom_src;
318 root = sc->fd.fc->crom_root;
319
320 unit = &sc->unit;
321
322 if ((sc->flags & F_FREEZED) == 0) {
323 sc->flags |= F_FREEZED;
324 xpt_freeze_simq(sc->sim, /*count*/1);
325 } else {
326 printf("%s: already freezed\n", __func__);
327 }
328
329 bzero(unit, sizeof(struct crom_chunk));
330
331 crom_add_chunk(src, root, unit, CROM_UDIR);
332 crom_add_entry(unit, CSRKEY_SPEC, CSRVAL_ANSIT10);
333 crom_add_entry(unit, CSRKEY_VER, CSRVAL_T10SBP2);
334 crom_add_entry(unit, CSRKEY_COM_SPEC, CSRVAL_ANSIT10);
335 crom_add_entry(unit, CSRKEY_COM_SET, CSRVAL_SCSI);
336
337 crom_add_entry(unit, CROM_MGM, SBP_TARG_MGM >> 2);
338 crom_add_entry(unit, CSRKEY_UNIT_CH, (10<<8) | 8);
339
340 for (i = 0; i < MAX_LUN; i++) {
341 lstate = sc->lstate[i];
342 if (lstate == NULL)
343 continue;
344 crom_add_entry(unit, CSRKEY_FIRM_VER, 1);
345 crom_add_entry(unit, CROM_LUN, i);
346 crom_add_entry(unit, CSRKEY_MODEL, 1);
347 crom_add_simple_text(src, unit, &lstate->model, "TargetMode");
348 }
349
350 /* Process for reconnection hold time */
351 for (i = 0; i < MAX_LOGINS; i++) {
352 login = sc->logins[i];
353 if (login == NULL)
354 continue;
355 sbp_targ_abort(sc, STAILQ_FIRST(&login->orbs));
356 if (login->flags & F_LOGIN) {
357 login->flags |= F_HOLD;
358 callout_reset(&login->hold_callout,
359 hz * login->hold_sec,
360 sbp_targ_hold_expire, (void *)login);
361 }
362 }
363 }
364
365 static void
sbp_targ_post_explore(void * arg)366 sbp_targ_post_explore(void *arg)
367 {
368 struct sbp_targ_softc *sc;
369
370 sc = (struct sbp_targ_softc *)arg;
371 sc->flags &= ~F_FREEZED;
372 xpt_release_simq(sc->sim, /*run queue*/TRUE);
373 return;
374 }
375
376 static cam_status
sbp_targ_find_devs(struct sbp_targ_softc * sc,union ccb * ccb,struct sbp_targ_lstate ** lstate,int notfound_failure)377 sbp_targ_find_devs(struct sbp_targ_softc *sc, union ccb *ccb,
378 struct sbp_targ_lstate **lstate, int notfound_failure)
379 {
380 u_int lun;
381
382 /* XXX 0 is the only vaild target_id */
383 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD &&
384 ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
385 *lstate = sc->black_hole;
386 if (debug)
387 printf("setting black hole for this target id(%d)\n", ccb->ccb_h.target_id);
388 return (CAM_REQ_CMP);
389 }
390
391 lun = ccb->ccb_h.target_lun;
392 if (lun >= MAX_LUN)
393 return (CAM_LUN_INVALID);
394
395 *lstate = sc->lstate[lun];
396
397 if (notfound_failure != 0 && *lstate == NULL) {
398 if (debug)
399 printf("%s: lstate for lun is invalid, target(%d), lun(%d)\n",
400 __func__, ccb->ccb_h.target_id, lun);
401 return (CAM_PATH_INVALID);
402 } else
403 if (debug)
404 printf("%s: setting lstate for tgt(%d) lun(%d)\n",
405 __func__,ccb->ccb_h.target_id, lun);
406
407 return (CAM_REQ_CMP);
408 }
409
410 static void
sbp_targ_en_lun(struct sbp_targ_softc * sc,union ccb * ccb)411 sbp_targ_en_lun(struct sbp_targ_softc *sc, union ccb *ccb)
412 {
413 struct ccb_en_lun *cel = &ccb->cel;
414 struct sbp_targ_lstate *lstate;
415 cam_status status;
416
417 status = sbp_targ_find_devs(sc, ccb, &lstate, 0);
418 if (status != CAM_REQ_CMP) {
419 ccb->ccb_h.status = status;
420 return;
421 }
422
423 if (cel->enable != 0) {
424 if (lstate != NULL) {
425 xpt_print_path(ccb->ccb_h.path);
426 printf("Lun already enabled\n");
427 ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
428 return;
429 }
430 if (cel->grp6_len != 0 || cel->grp7_len != 0) {
431 ccb->ccb_h.status = CAM_REQ_INVALID;
432 printf("Non-zero Group Codes\n");
433 return;
434 }
435 lstate = (struct sbp_targ_lstate *)
436 malloc(sizeof(*lstate), M_SBP_TARG, M_NOWAIT | M_ZERO);
437 if (lstate == NULL) {
438 xpt_print_path(ccb->ccb_h.path);
439 printf("Couldn't allocate lstate\n");
440 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
441 return;
442 } else {
443 if (debug)
444 printf("%s: malloc'd lstate %p\n",__func__, lstate);
445 }
446 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) {
447 sc->black_hole = lstate;
448 if (debug)
449 printf("Blackhole set due to target id == %d\n",
450 ccb->ccb_h.target_id);
451 } else
452 sc->lstate[ccb->ccb_h.target_lun] = lstate;
453
454 memset(lstate, 0, sizeof(*lstate));
455 lstate->sc = sc;
456 status = xpt_create_path(&lstate->path, /*periph*/NULL,
457 xpt_path_path_id(ccb->ccb_h.path),
458 xpt_path_target_id(ccb->ccb_h.path),
459 xpt_path_lun_id(ccb->ccb_h.path));
460 if (status != CAM_REQ_CMP) {
461 free(lstate, M_SBP_TARG);
462 lstate = NULL;
463 xpt_print_path(ccb->ccb_h.path);
464 printf("Couldn't allocate path\n");
465 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
466 return;
467 }
468 SLIST_INIT(&lstate->accept_tios);
469 SLIST_INIT(&lstate->immed_notifies);
470 STAILQ_INIT(&lstate->logins);
471
472 ccb->ccb_h.status = CAM_REQ_CMP;
473 xpt_print_path(ccb->ccb_h.path);
474 printf("Lun now enabled for target mode\n");
475 /* bus reset */
476 sc->fd.fc->ibr(sc->fd.fc);
477 } else {
478 struct sbp_targ_login *login, *next;
479
480 if (lstate == NULL) {
481 ccb->ccb_h.status = CAM_LUN_INVALID;
482 printf("Invalid lstate for this target\n");
483 return;
484 }
485 ccb->ccb_h.status = CAM_REQ_CMP;
486
487 if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
488 printf("ATIOs pending\n");
489 ccb->ccb_h.status = CAM_REQ_INVALID;
490 }
491
492 if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
493 printf("INOTs pending\n");
494 ccb->ccb_h.status = CAM_REQ_INVALID;
495 }
496
497 if (ccb->ccb_h.status != CAM_REQ_CMP) {
498 printf("status != CAM_REQ_CMP\n");
499 return;
500 }
501
502 xpt_print_path(ccb->ccb_h.path);
503 printf("Target mode disabled\n");
504 xpt_free_path(lstate->path);
505
506 for (login = STAILQ_FIRST(&lstate->logins); login != NULL;
507 login = next) {
508 next = STAILQ_NEXT(login, link);
509 sbp_targ_dealloc_login(login);
510 }
511
512 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD)
513 sc->black_hole = NULL;
514 else
515 sc->lstate[ccb->ccb_h.target_lun] = NULL;
516 if (debug)
517 printf("%s: free lstate %p\n", __func__, lstate);
518 free(lstate, M_SBP_TARG);
519 lstate = NULL;
520
521 /* bus reset */
522 sc->fd.fc->ibr(sc->fd.fc);
523 }
524 }
525
526 static void
sbp_targ_send_lstate_events(struct sbp_targ_softc * sc,struct sbp_targ_lstate * lstate)527 sbp_targ_send_lstate_events(struct sbp_targ_softc *sc,
528 struct sbp_targ_lstate *lstate)
529 {
530 }
531
532
533 static __inline void
sbp_targ_remove_orb_info_locked(struct sbp_targ_login * login,struct orb_info * orbi)534 sbp_targ_remove_orb_info_locked(struct sbp_targ_login *login, struct orb_info *orbi)
535 {
536 STAILQ_REMOVE(&login->orbs, orbi, orb_info, link);
537 }
538
539 static __inline void
sbp_targ_remove_orb_info(struct sbp_targ_login * login,struct orb_info * orbi)540 sbp_targ_remove_orb_info(struct sbp_targ_login *login, struct orb_info *orbi)
541 {
542 SBP_LOCK(orbi->sc);
543 STAILQ_REMOVE(&login->orbs, orbi, orb_info, link);
544 SBP_UNLOCK(orbi->sc);
545 }
546
547 /*
548 * tag_id/init_id encoding
549 *
550 * tag_id and init_id has only 32bit for each.
551 * scsi_target can handle very limited number(up to 15) of init_id.
552 * we have to encode 48bit orb and 64bit EUI64 into these
553 * variables.
554 *
555 * tag_id represents lower 32bit of ORB address.
556 * init_id represents login_id.
557 *
558 */
559
560 static struct orb_info *
sbp_targ_get_orb_info(struct sbp_targ_lstate * lstate,u_int tag_id,u_int init_id)561 sbp_targ_get_orb_info(struct sbp_targ_lstate *lstate,
562 u_int tag_id, u_int init_id)
563 {
564 struct sbp_targ_login *login;
565 struct orb_info *orbi;
566
567 login = lstate->sc->logins[init_id];
568 if (login == NULL) {
569 printf("%s: no such login\n", __func__);
570 return (NULL);
571 }
572 STAILQ_FOREACH(orbi, &login->orbs, link)
573 if (orbi->orb_lo == tag_id)
574 goto found;
575 printf("%s: orb not found tag_id=0x%08x init_id=%d\n",
576 __func__, tag_id, init_id);
577 return (NULL);
578 found:
579 return (orbi);
580 }
581
582 static void
sbp_targ_abort(struct sbp_targ_softc * sc,struct orb_info * orbi)583 sbp_targ_abort(struct sbp_targ_softc *sc, struct orb_info *orbi)
584 {
585 struct orb_info *norbi;
586
587 SBP_LOCK(sc);
588 for (; orbi != NULL; orbi = norbi) {
589 printf("%s: status=%d ccb=%p\n", __func__, orbi->state, orbi->ccb);
590 norbi = STAILQ_NEXT(orbi, link);
591 if (orbi->state != ORBI_STATUS_ABORTED) {
592 if (orbi->ccb != NULL) {
593 orbi->ccb->ccb_h.status = CAM_REQ_ABORTED;
594 xpt_done(orbi->ccb);
595 orbi->ccb = NULL;
596 }
597 if (orbi->state <= ORBI_STATUS_ATIO) {
598 sbp_targ_remove_orb_info_locked(orbi->login, orbi);
599 if (debug)
600 printf("%s: free orbi %p\n", __func__, orbi);
601 free(orbi, M_SBP_TARG);
602 orbi = NULL;
603 } else
604 orbi->state = ORBI_STATUS_ABORTED;
605 }
606 }
607 SBP_UNLOCK(sc);
608 }
609
610 static void
sbp_targ_free_orbi(struct fw_xfer * xfer)611 sbp_targ_free_orbi(struct fw_xfer *xfer)
612 {
613 struct orb_info *orbi;
614
615 if (xfer->resp != 0) {
616 /* XXX */
617 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
618 }
619 orbi = (struct orb_info *)xfer->sc;
620 if ( orbi->page_table != NULL ) {
621 if (debug)
622 printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table);
623 free(orbi->page_table, M_SBP_TARG);
624 orbi->page_table = NULL;
625 }
626 if (debug)
627 printf("%s: free orbi %p\n", __func__, orbi);
628 free(orbi, M_SBP_TARG);
629 orbi = NULL;
630 fw_xfer_free(xfer);
631 }
632
633 static void
sbp_targ_status_FIFO(struct orb_info * orbi,uint32_t fifo_hi,uint32_t fifo_lo,int dequeue)634 sbp_targ_status_FIFO(struct orb_info *orbi,
635 uint32_t fifo_hi, uint32_t fifo_lo, int dequeue)
636 {
637 struct fw_xfer *xfer;
638
639 if (dequeue)
640 sbp_targ_remove_orb_info(orbi->login, orbi);
641
642 xfer = fwmem_write_block(orbi->fwdev, (void *)orbi,
643 /*spd*/FWSPD_S400, fifo_hi, fifo_lo,
644 sizeof(uint32_t) * (orbi->status.len + 1), (char *)&orbi->status,
645 sbp_targ_free_orbi);
646
647 if (xfer == NULL) {
648 /* XXX */
649 printf("%s: xfer == NULL\n", __func__);
650 }
651 }
652
653 /*
654 * Generate the appropriate CAM status for the
655 * target.
656 */
657 static void
sbp_targ_send_status(struct orb_info * orbi,union ccb * ccb)658 sbp_targ_send_status(struct orb_info *orbi, union ccb *ccb)
659 {
660 struct sbp_status *sbp_status;
661 #if 0
662 struct orb_info *norbi;
663 #endif
664
665 sbp_status = &orbi->status;
666
667 orbi->state = ORBI_STATUS_STATUS;
668
669 sbp_status->resp = 0; /* XXX */
670 sbp_status->status = 0; /* XXX */
671 sbp_status->dead = 0; /* XXX */
672
673 ccb->ccb_h.status= CAM_REQ_CMP;
674
675 switch (ccb->csio.scsi_status) {
676 case SCSI_STATUS_OK:
677 if (debug)
678 printf("%s: STATUS_OK\n", __func__);
679 sbp_status->len = 1;
680 break;
681 case SCSI_STATUS_CHECK_COND:
682 if (debug)
683 printf("%s: STATUS SCSI_STATUS_CHECK_COND\n", __func__);
684 goto process_scsi_status;
685 case SCSI_STATUS_BUSY:
686 if (debug)
687 printf("%s: STATUS SCSI_STATUS_BUSY\n", __func__);
688 goto process_scsi_status;
689 case SCSI_STATUS_CMD_TERMINATED:
690 process_scsi_status:
691 {
692 struct sbp_cmd_status *sbp_cmd_status;
693 struct scsi_sense_data *sense;
694 int error_code, sense_key, asc, ascq;
695 uint8_t stream_bits;
696 uint8_t sks[3];
697 uint64_t info;
698 int64_t sinfo;
699 int sense_len;
700
701 sbp_cmd_status = (struct sbp_cmd_status *)&sbp_status->data[0];
702 sbp_cmd_status->status = ccb->csio.scsi_status;
703 sense = &ccb->csio.sense_data;
704
705
706 sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
707 scsi_extract_sense_len(sense, sense_len, &error_code,
708 &sense_key, &asc, &ascq, /*show_errors*/ 0);
709
710 switch (error_code) {
711 case SSD_CURRENT_ERROR:
712 case SSD_DESC_CURRENT_ERROR:
713 sbp_cmd_status->sfmt = SBP_SFMT_CURR;
714 break;
715 default:
716 sbp_cmd_status->sfmt = SBP_SFMT_DEFER;
717 break;
718 }
719
720 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info,
721 &sinfo) == 0) {
722 uint32_t info_trunc;
723 sbp_cmd_status->valid = 1;
724 info_trunc = info;
725
726 sbp_cmd_status->info = htobe32(info_trunc);
727 } else {
728 sbp_cmd_status->valid = 0;
729 }
730
731 sbp_cmd_status->s_key = sense_key;
732
733 if (scsi_get_stream_info(sense, sense_len, NULL,
734 &stream_bits) == 0) {
735 sbp_cmd_status->mark =
736 (stream_bits & SSD_FILEMARK) ? 1 : 0;
737 sbp_cmd_status->eom =
738 (stream_bits & SSD_EOM) ? 1 : 0;
739 sbp_cmd_status->ill_len =
740 (stream_bits & SSD_ILI) ? 1 : 0;
741 } else {
742 sbp_cmd_status->mark = 0;
743 sbp_cmd_status->eom = 0;
744 sbp_cmd_status->ill_len = 0;
745 }
746
747
748 /* add_sense_code(_qual), info, cmd_spec_info */
749 sbp_status->len = 4;
750
751 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_COMMAND,
752 &info, &sinfo) == 0) {
753 uint32_t cmdspec_trunc;
754
755 cmdspec_trunc = info;
756
757 sbp_cmd_status->cdb = htobe32(cmdspec_trunc);
758 }
759
760 sbp_cmd_status->s_code = asc;
761 sbp_cmd_status->s_qlfr = ascq;
762
763 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_FRU, &info,
764 &sinfo) == 0) {
765 sbp_cmd_status->fru = (uint8_t)info;
766 sbp_status->len = 5;
767 } else {
768 sbp_cmd_status->fru = 0;
769 }
770
771 if (scsi_get_sks(sense, sense_len, sks) == 0) {
772 bcopy(sks, &sbp_cmd_status->s_keydep[0], sizeof(sks));
773 sbp_status->len = 5;
774 ccb->ccb_h.status |= CAM_SENT_SENSE;
775 }
776
777 break;
778 }
779 default:
780 printf("%s: unknown scsi status 0x%x\n", __func__,
781 sbp_status->status);
782 }
783
784
785 sbp_targ_status_FIFO(orbi,
786 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
787 }
788
789 /*
790 * Invoked as a callback handler from fwmem_read/write_block
791 *
792 * Process read/write of initiator address space
793 * completion and pass status onto the backend target.
794 * If this is a partial read/write for a CCB then
795 * we decrement the orbi's refcount to indicate
796 * the status of the read/write is complete
797 */
798 static void
sbp_targ_cam_done(struct fw_xfer * xfer)799 sbp_targ_cam_done(struct fw_xfer *xfer)
800 {
801 struct orb_info *orbi;
802 union ccb *ccb;
803
804 orbi = (struct orb_info *)xfer->sc;
805
806 if (debug)
807 printf("%s: resp=%d refcount=%d\n", __func__,
808 xfer->resp, orbi->refcount);
809
810 if (xfer->resp != 0) {
811 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
812 orbi->status.resp = SBP_TRANS_FAIL;
813 orbi->status.status = OBJ_DATA | SBE_TIMEOUT/*XXX*/;
814 orbi->status.dead = 1;
815 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
816 }
817
818 orbi->refcount--;
819
820 ccb = orbi->ccb;
821 if (orbi->refcount == 0) {
822 orbi->ccb = NULL;
823 if (orbi->state == ORBI_STATUS_ABORTED) {
824 if (debug)
825 printf("%s: orbi aborted\n", __func__);
826 sbp_targ_remove_orb_info(orbi->login, orbi);
827 if (orbi->page_table != NULL) {
828 if (debug)
829 printf("%s: free orbi->page_table %p\n",
830 __func__, orbi->page_table);
831 free(orbi->page_table, M_SBP_TARG);
832 }
833 if (debug)
834 printf("%s: free orbi %p\n", __func__, orbi);
835 free(orbi, M_SBP_TARG);
836 orbi = NULL;
837 } else if (orbi->status.resp == ORBI_STATUS_NONE) {
838 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
839 if (debug)
840 printf("%s: CAM_SEND_STATUS set %0x\n", __func__, ccb->ccb_h.flags);
841 sbp_targ_send_status(orbi, ccb);
842 } else {
843 if (debug)
844 printf("%s: CAM_SEND_STATUS not set %0x\n", __func__, ccb->ccb_h.flags);
845 ccb->ccb_h.status = CAM_REQ_CMP;
846 }
847 xpt_done(ccb);
848 } else {
849 orbi->status.len = 1;
850 sbp_targ_status_FIFO(orbi,
851 orbi->login->fifo_hi, orbi->login->fifo_lo,
852 /*dequeue*/1);
853 ccb->ccb_h.status = CAM_REQ_ABORTED;
854 xpt_done(ccb);
855 }
856 }
857
858 fw_xfer_free(xfer);
859 }
860
861 static cam_status
sbp_targ_abort_ccb(struct sbp_targ_softc * sc,union ccb * ccb)862 sbp_targ_abort_ccb(struct sbp_targ_softc *sc, union ccb *ccb)
863 {
864 union ccb *accb;
865 struct sbp_targ_lstate *lstate;
866 struct ccb_hdr_slist *list;
867 struct ccb_hdr *curelm;
868 int found;
869 cam_status status;
870
871 status = sbp_targ_find_devs(sc, ccb, &lstate, 0);
872 if (status != CAM_REQ_CMP)
873 return (status);
874
875 accb = ccb->cab.abort_ccb;
876
877 if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO)
878 list = &lstate->accept_tios;
879 else if (accb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY)
880 list = &lstate->immed_notifies;
881 else
882 return (CAM_UA_ABORT);
883
884 curelm = SLIST_FIRST(list);
885 found = 0;
886 if (curelm == &accb->ccb_h) {
887 found = 1;
888 SLIST_REMOVE_HEAD(list, sim_links.sle);
889 } else {
890 while (curelm != NULL) {
891 struct ccb_hdr *nextelm;
892
893 nextelm = SLIST_NEXT(curelm, sim_links.sle);
894 if (nextelm == &accb->ccb_h) {
895 found = 1;
896 SLIST_NEXT(curelm, sim_links.sle) =
897 SLIST_NEXT(nextelm, sim_links.sle);
898 break;
899 }
900 curelm = nextelm;
901 }
902 }
903 if (found) {
904 accb->ccb_h.status = CAM_REQ_ABORTED;
905 xpt_done(accb);
906 return (CAM_REQ_CMP);
907 }
908 printf("%s: not found\n", __func__);
909 return (CAM_PATH_INVALID);
910 }
911
912 /*
913 * directly execute a read or write to the initiator
914 * address space and set hand(sbp_targ_cam_done) to
915 * process the completion from the SIM to the target.
916 * set orbi->refcount to inidicate that a read/write
917 * is inflight to/from the initiator.
918 */
919 static void
sbp_targ_xfer_buf(struct orb_info * orbi,u_int offset,uint16_t dst_hi,uint32_t dst_lo,u_int size,void (* hand)(struct fw_xfer *))920 sbp_targ_xfer_buf(struct orb_info *orbi, u_int offset,
921 uint16_t dst_hi, uint32_t dst_lo, u_int size,
922 void (*hand)(struct fw_xfer *))
923 {
924 struct fw_xfer *xfer;
925 u_int len, ccb_dir, off = 0;
926 char *ptr;
927
928 if (debug > 1)
929 printf("%s: offset=%d size=%d\n", __func__, offset, size);
930 ccb_dir = orbi->ccb->ccb_h.flags & CAM_DIR_MASK;
931 ptr = (char *)orbi->ccb->csio.data_ptr + offset;
932
933 while (size > 0) {
934 /* XXX assume dst_lo + off doesn't overflow */
935 len = MIN(size, SBP_TARG_MAX_CHUNK);
936 size -= len;
937 orbi->refcount ++;
938 if (ccb_dir == CAM_DIR_OUT) {
939 if (debug)
940 printf("%s: CAM_DIR_OUT --> read block in?\n",__func__);
941 xfer = fwmem_read_block(orbi->fwdev,
942 (void *)orbi, /*spd*/FWSPD_S400,
943 dst_hi, dst_lo + off, len,
944 ptr + off, hand);
945 } else {
946 if (debug)
947 printf("%s: CAM_DIR_IN --> write block out?\n",__func__);
948 xfer = fwmem_write_block(orbi->fwdev,
949 (void *)orbi, /*spd*/FWSPD_S400,
950 dst_hi, dst_lo + off, len,
951 ptr + off, hand);
952 }
953 if (xfer == NULL) {
954 printf("%s: xfer == NULL", __func__);
955 /* XXX what should we do?? */
956 orbi->refcount--;
957 }
958 off += len;
959 }
960 }
961
962 static void
sbp_targ_pt_done(struct fw_xfer * xfer)963 sbp_targ_pt_done(struct fw_xfer *xfer)
964 {
965 struct orb_info *orbi;
966 struct unrestricted_page_table_fmt *pt;
967 uint32_t i;
968
969 orbi = (struct orb_info *)xfer->sc;
970
971 if (orbi->state == ORBI_STATUS_ABORTED) {
972 if (debug)
973 printf("%s: orbi aborted\n", __func__);
974 sbp_targ_remove_orb_info(orbi->login, orbi);
975 if (debug) {
976 printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table);
977 printf("%s: free orbi %p\n", __func__, orbi);
978 }
979 free(orbi->page_table, M_SBP_TARG);
980 free(orbi, M_SBP_TARG);
981 orbi = NULL;
982 fw_xfer_free(xfer);
983 return;
984 }
985 if (xfer->resp != 0) {
986 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
987 orbi->status.resp = SBP_TRANS_FAIL;
988 orbi->status.status = OBJ_PT | SBE_TIMEOUT/*XXX*/;
989 orbi->status.dead = 1;
990 orbi->status.len = 1;
991 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
992
993 if (debug)
994 printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table);
995
996 sbp_targ_status_FIFO(orbi,
997 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
998 free(orbi->page_table, M_SBP_TARG);
999 orbi->page_table = NULL;
1000 fw_xfer_free(xfer);
1001 return;
1002 }
1003 orbi->refcount++;
1004 /*
1005 * Set endianness here so we don't have
1006 * to deal with is later
1007 */
1008 for (i = 0, pt = orbi->page_table; i < orbi->orb4.data_size; i++, pt++) {
1009 pt->segment_len = ntohs(pt->segment_len);
1010 if (debug)
1011 printf("%s:segment_len = %u\n", __func__,pt->segment_len);
1012 pt->segment_base_high = ntohs(pt->segment_base_high);
1013 pt->segment_base_low = ntohl(pt->segment_base_low);
1014 }
1015
1016 sbp_targ_xfer_pt(orbi);
1017
1018 orbi->refcount--;
1019 if (orbi->refcount == 0)
1020 printf("%s: refcount == 0\n", __func__);
1021
1022 fw_xfer_free(xfer);
1023 return;
1024 }
1025
sbp_targ_xfer_pt(struct orb_info * orbi)1026 static void sbp_targ_xfer_pt(struct orb_info *orbi)
1027 {
1028 union ccb *ccb;
1029 uint32_t res, offset, len;
1030
1031 ccb = orbi->ccb;
1032 if (debug)
1033 printf("%s: dxfer_len=%d\n", __func__, ccb->csio.dxfer_len);
1034 res = ccb->csio.dxfer_len;
1035 /*
1036 * If the page table required multiple CTIO's to
1037 * complete, then cur_pte is non NULL
1038 * and we need to start from the last position
1039 * If this is the first pass over a page table
1040 * then we just start at the beginning of the page
1041 * table.
1042 *
1043 * Parse the unrestricted page table and figure out where we need
1044 * to shove the data from this read request.
1045 */
1046 for (offset = 0, len = 0; (res != 0) && (orbi->cur_pte < orbi->last_pte); offset += len) {
1047 len = MIN(orbi->cur_pte->segment_len, res);
1048 res -= len;
1049 if (debug)
1050 printf("%s:page_table: %04x:%08x segment_len(%u) res(%u) len(%u)\n",
1051 __func__, orbi->cur_pte->segment_base_high,
1052 orbi->cur_pte->segment_base_low,
1053 orbi->cur_pte->segment_len,
1054 res, len);
1055 sbp_targ_xfer_buf(orbi, offset,
1056 orbi->cur_pte->segment_base_high,
1057 orbi->cur_pte->segment_base_low,
1058 len, sbp_targ_cam_done);
1059 /*
1060 * If we have only written partially to
1061 * this page table, then we need to save
1062 * our position for the next CTIO. If we
1063 * have completed the page table, then we
1064 * are safe to move on to the next entry.
1065 */
1066 if (len == orbi->cur_pte->segment_len) {
1067 orbi->cur_pte++;
1068 } else {
1069 uint32_t saved_base_low;
1070
1071 /* Handle transfers that cross a 4GB boundary. */
1072 saved_base_low = orbi->cur_pte->segment_base_low;
1073 orbi->cur_pte->segment_base_low += len;
1074 if (orbi->cur_pte->segment_base_low < saved_base_low)
1075 orbi->cur_pte->segment_base_high++;
1076
1077 orbi->cur_pte->segment_len -= len;
1078 }
1079 }
1080 if (debug) {
1081 printf("%s: base_low(%08x) page_table_off(%p) last_block(%u)\n",
1082 __func__, orbi->cur_pte->segment_base_low,
1083 orbi->cur_pte, orbi->last_block_read);
1084 }
1085 if (res != 0)
1086 printf("Warning - short pt encountered. "
1087 "Could not transfer all data.\n");
1088 return;
1089 }
1090
1091 /*
1092 * Create page table in local memory
1093 * and transfer it from the initiator
1094 * in order to know where we are supposed
1095 * to put the data.
1096 */
1097
1098 static void
sbp_targ_fetch_pt(struct orb_info * orbi)1099 sbp_targ_fetch_pt(struct orb_info *orbi)
1100 {
1101 struct fw_xfer *xfer;
1102
1103 /*
1104 * Pull in page table from initiator
1105 * and setup for data from our
1106 * backend device.
1107 */
1108 if (orbi->page_table == NULL) {
1109 orbi->page_table = malloc(orbi->orb4.data_size*
1110 sizeof(struct unrestricted_page_table_fmt),
1111 M_SBP_TARG, M_NOWAIT|M_ZERO);
1112 if (orbi->page_table == NULL)
1113 goto error;
1114 orbi->cur_pte = orbi->page_table;
1115 orbi->last_pte = orbi->page_table + orbi->orb4.data_size;
1116 orbi->last_block_read = orbi->orb4.data_size;
1117 if (debug && orbi->page_table != NULL)
1118 printf("%s: malloc'd orbi->page_table(%p), orb4.data_size(%u)\n",
1119 __func__, orbi->page_table, orbi->orb4.data_size);
1120
1121 xfer = fwmem_read_block(orbi->fwdev, (void *)orbi, /*spd*/FWSPD_S400,
1122 orbi->data_hi, orbi->data_lo, orbi->orb4.data_size*
1123 sizeof(struct unrestricted_page_table_fmt),
1124 (void *)orbi->page_table, sbp_targ_pt_done);
1125
1126 if (xfer != NULL)
1127 return;
1128 } else {
1129 /*
1130 * This is a CTIO for a page table we have
1131 * already malloc'd, so just directly invoke
1132 * the xfer function on the orbi.
1133 */
1134 sbp_targ_xfer_pt(orbi);
1135 return;
1136 }
1137 error:
1138 orbi->ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1139 if (debug)
1140 printf("%s: free orbi->page_table %p due to xfer == NULL\n", __func__, orbi->page_table);
1141 if (orbi->page_table != NULL) {
1142 free(orbi->page_table, M_SBP_TARG);
1143 orbi->page_table = NULL;
1144 }
1145 xpt_done(orbi->ccb);
1146 return;
1147 }
1148
1149 static void
sbp_targ_action1(struct cam_sim * sim,union ccb * ccb)1150 sbp_targ_action1(struct cam_sim *sim, union ccb *ccb)
1151 {
1152 struct sbp_targ_softc *sc;
1153 struct sbp_targ_lstate *lstate;
1154 cam_status status;
1155 u_int ccb_dir;
1156
1157 sc = (struct sbp_targ_softc *)cam_sim_softc(sim);
1158
1159 status = sbp_targ_find_devs(sc, ccb, &lstate, TRUE);
1160
1161 switch (ccb->ccb_h.func_code) {
1162 case XPT_CONT_TARGET_IO:
1163 {
1164 struct orb_info *orbi;
1165
1166 if (debug)
1167 printf("%s: XPT_CONT_TARGET_IO (0x%08x)\n",
1168 __func__, ccb->csio.tag_id);
1169
1170 if (status != CAM_REQ_CMP) {
1171 ccb->ccb_h.status = status;
1172 xpt_done(ccb);
1173 break;
1174 }
1175 /* XXX transfer from/to initiator */
1176 orbi = sbp_targ_get_orb_info(lstate,
1177 ccb->csio.tag_id, ccb->csio.init_id);
1178 if (orbi == NULL) {
1179 ccb->ccb_h.status = CAM_REQ_ABORTED; /* XXX */
1180 xpt_done(ccb);
1181 break;
1182 }
1183 if (orbi->state == ORBI_STATUS_ABORTED) {
1184 if (debug)
1185 printf("%s: ctio aborted\n", __func__);
1186 sbp_targ_remove_orb_info_locked(orbi->login, orbi);
1187 if (debug)
1188 printf("%s: free orbi %p\n", __func__, orbi);
1189 free(orbi, M_SBP_TARG);
1190 ccb->ccb_h.status = CAM_REQ_ABORTED;
1191 xpt_done(ccb);
1192 break;
1193 }
1194 orbi->state = ORBI_STATUS_CTIO;
1195
1196 orbi->ccb = ccb;
1197 ccb_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
1198
1199 /* XXX */
1200 if (ccb->csio.dxfer_len == 0)
1201 ccb_dir = CAM_DIR_NONE;
1202
1203 /* Sanity check */
1204 if (ccb_dir == CAM_DIR_IN && orbi->orb4.dir == 0)
1205 printf("%s: direction mismatch\n", __func__);
1206
1207 /* check page table */
1208 if (ccb_dir != CAM_DIR_NONE && orbi->orb4.page_table_present) {
1209 if (debug)
1210 printf("%s: page_table_present\n",
1211 __func__);
1212 if (orbi->orb4.page_size != 0) {
1213 printf("%s: unsupported pagesize %d != 0\n",
1214 __func__, orbi->orb4.page_size);
1215 ccb->ccb_h.status = CAM_REQ_INVALID;
1216 xpt_done(ccb);
1217 break;
1218 }
1219 sbp_targ_fetch_pt(orbi);
1220 break;
1221 }
1222
1223 /* Sanity check */
1224 if (ccb_dir != CAM_DIR_NONE) {
1225 sbp_targ_xfer_buf(orbi, 0, orbi->data_hi,
1226 orbi->data_lo,
1227 MIN(orbi->orb4.data_size, ccb->csio.dxfer_len),
1228 sbp_targ_cam_done);
1229 if ( orbi->orb4.data_size > ccb->csio.dxfer_len ) {
1230 orbi->data_lo += ccb->csio.dxfer_len;
1231 orbi->orb4.data_size -= ccb->csio.dxfer_len;
1232 }
1233 }
1234
1235 if (ccb_dir == CAM_DIR_NONE) {
1236 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
1237 /* XXX */
1238 SBP_UNLOCK(sc);
1239 sbp_targ_send_status(orbi, ccb);
1240 SBP_LOCK(sc);
1241 }
1242 ccb->ccb_h.status = CAM_REQ_CMP;
1243 xpt_done(ccb);
1244 }
1245 break;
1246 }
1247 case XPT_ACCEPT_TARGET_IO: /* Add Accept Target IO Resource */
1248 if (status != CAM_REQ_CMP) {
1249 ccb->ccb_h.status = status;
1250 xpt_done(ccb);
1251 break;
1252 }
1253 SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
1254 sim_links.sle);
1255 ccb->ccb_h.status = CAM_REQ_INPROG;
1256 if ((lstate->flags & F_ATIO_STARVED) != 0) {
1257 struct sbp_targ_login *login;
1258
1259 if (debug)
1260 printf("%s: new atio arrived\n", __func__);
1261 lstate->flags &= ~F_ATIO_STARVED;
1262 STAILQ_FOREACH(login, &lstate->logins, link)
1263 if ((login->flags & F_ATIO_STARVED) != 0) {
1264 login->flags &= ~F_ATIO_STARVED;
1265 sbp_targ_fetch_orb(lstate->sc,
1266 login->fwdev,
1267 login->last_hi, login->last_lo,
1268 login, FETCH_CMD);
1269 }
1270 }
1271 break;
1272 case XPT_NOTIFY_ACKNOWLEDGE: /* recycle notify ack */
1273 case XPT_IMMEDIATE_NOTIFY: /* Add Immediate Notify Resource */
1274 if (status != CAM_REQ_CMP) {
1275 ccb->ccb_h.status = status;
1276 xpt_done(ccb);
1277 break;
1278 }
1279 SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h,
1280 sim_links.sle);
1281 ccb->ccb_h.status = CAM_REQ_INPROG;
1282 sbp_targ_send_lstate_events(sc, lstate);
1283 break;
1284 case XPT_EN_LUN:
1285 sbp_targ_en_lun(sc, ccb);
1286 xpt_done(ccb);
1287 break;
1288 case XPT_PATH_INQ:
1289 {
1290 struct ccb_pathinq *cpi = &ccb->cpi;
1291
1292 cpi->version_num = 1; /* XXX??? */
1293 cpi->hba_inquiry = PI_TAG_ABLE;
1294 cpi->target_sprt = PIT_PROCESSOR
1295 | PIT_DISCONNECT
1296 | PIT_TERM_IO;
1297 cpi->transport = XPORT_SPI; /* FIXME add XPORT_FW type to cam */
1298 cpi->hba_misc = PIM_NOINITIATOR | PIM_NOBUSRESET |
1299 PIM_NO_6_BYTE;
1300 cpi->hba_eng_cnt = 0;
1301 cpi->max_target = 7; /* XXX */
1302 cpi->max_lun = MAX_LUN - 1;
1303 cpi->initiator_id = 7; /* XXX */
1304 cpi->bus_id = sim->bus_id;
1305 cpi->base_transfer_speed = 400 * 1000 / 8;
1306 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1307 strlcpy(cpi->hba_vid, "SBP_TARG", HBA_IDLEN);
1308 strlcpy(cpi->dev_name, sim->sim_name, DEV_IDLEN);
1309 cpi->unit_number = sim->unit_number;
1310
1311 cpi->ccb_h.status = CAM_REQ_CMP;
1312 xpt_done(ccb);
1313 break;
1314 }
1315 case XPT_ABORT:
1316 {
1317 union ccb *accb = ccb->cab.abort_ccb;
1318
1319 switch (accb->ccb_h.func_code) {
1320 case XPT_ACCEPT_TARGET_IO:
1321 case XPT_IMMEDIATE_NOTIFY:
1322 ccb->ccb_h.status = sbp_targ_abort_ccb(sc, ccb);
1323 break;
1324 case XPT_CONT_TARGET_IO:
1325 /* XXX */
1326 ccb->ccb_h.status = CAM_UA_ABORT;
1327 break;
1328 default:
1329 printf("%s: aborting unknown function %d\n",
1330 __func__, accb->ccb_h.func_code);
1331 ccb->ccb_h.status = CAM_REQ_INVALID;
1332 break;
1333 }
1334 xpt_done(ccb);
1335 break;
1336 }
1337 #ifdef CAM_NEW_TRAN_CODE
1338 case XPT_SET_TRAN_SETTINGS:
1339 ccb->ccb_h.status = CAM_REQ_INVALID;
1340 xpt_done(ccb);
1341 break;
1342 case XPT_GET_TRAN_SETTINGS:
1343 {
1344 struct ccb_trans_settings *cts = &ccb->cts;
1345 struct ccb_trans_settings_scsi *scsi =
1346 &cts->proto_specific.scsi;
1347 struct ccb_trans_settings_spi *spi =
1348 &cts->xport_specific.spi;
1349
1350 cts->protocol = PROTO_SCSI;
1351 cts->protocol_version = SCSI_REV_2;
1352 cts->transport = XPORT_FW; /* should have a FireWire */
1353 cts->transport_version = 2;
1354 spi->valid = CTS_SPI_VALID_DISC;
1355 spi->flags = CTS_SPI_FLAGS_DISC_ENB;
1356 scsi->valid = CTS_SCSI_VALID_TQ;
1357 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
1358 cts->ccb_h.status = CAM_REQ_CMP;
1359 xpt_done(ccb);
1360 break;
1361 }
1362 #endif
1363
1364 default:
1365 printf("%s: unknown function 0x%x\n",
1366 __func__, ccb->ccb_h.func_code);
1367 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1368 xpt_done(ccb);
1369 break;
1370 }
1371 return;
1372 }
1373
1374 static void
sbp_targ_action(struct cam_sim * sim,union ccb * ccb)1375 sbp_targ_action(struct cam_sim *sim, union ccb *ccb)
1376 {
1377
1378 sbp_targ_action1(sim, ccb);
1379 }
1380
1381 static void
sbp_targ_poll(struct cam_sim * sim)1382 sbp_targ_poll(struct cam_sim *sim)
1383 {
1384 /* XXX */
1385 return;
1386 }
1387
1388 static void
sbp_targ_cmd_handler(struct fw_xfer * xfer)1389 sbp_targ_cmd_handler(struct fw_xfer *xfer)
1390 {
1391 uint32_t *orb;
1392 struct corb4 *orb4;
1393 struct orb_info *orbi;
1394 struct ccb_accept_tio *atio;
1395 u_char *bytes;
1396 int i;
1397
1398 orbi = (struct orb_info *)xfer->sc;
1399 if (xfer->resp != 0) {
1400 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1401 orbi->status.resp = SBP_TRANS_FAIL;
1402 orbi->status.status = OBJ_ORB | SBE_TIMEOUT/*XXX*/;
1403 orbi->status.dead = 1;
1404 orbi->status.len = 1;
1405 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
1406
1407 sbp_targ_status_FIFO(orbi,
1408 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
1409 fw_xfer_free(xfer);
1410 return;
1411 }
1412
1413 atio = orbi->atio;
1414
1415 if (orbi->state == ORBI_STATUS_ABORTED) {
1416 printf("%s: aborted\n", __func__);
1417 sbp_targ_remove_orb_info(orbi->login, orbi);
1418 free(orbi, M_SBP_TARG);
1419 atio->ccb_h.status = CAM_REQ_ABORTED;
1420 xpt_done((union ccb*)atio);
1421 goto done0;
1422 }
1423 orbi->state = ORBI_STATUS_ATIO;
1424
1425 orb = orbi->orb;
1426 /* swap payload except SCSI command */
1427 for (i = 0; i < 5; i++)
1428 orb[i] = ntohl(orb[i]);
1429
1430 orb4 = (struct corb4 *)&orb[4];
1431 if (orb4->rq_fmt != 0) {
1432 /* XXX */
1433 printf("%s: rq_fmt(%d) != 0\n", __func__, orb4->rq_fmt);
1434 }
1435
1436 atio->ccb_h.target_id = 0; /* XXX */
1437 atio->ccb_h.target_lun = orbi->login->lstate->lun;
1438 atio->sense_len = 0;
1439 atio->tag_action = MSG_SIMPLE_TASK;
1440 atio->tag_id = orbi->orb_lo;
1441 atio->init_id = orbi->login->id;
1442
1443 atio->ccb_h.flags |= CAM_TAG_ACTION_VALID;
1444 bytes = (u_char *)&orb[5];
1445 if (debug)
1446 printf("%s: %p %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
1447 __func__, (void *)atio,
1448 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4],
1449 bytes[5], bytes[6], bytes[7], bytes[8], bytes[9]);
1450 switch (bytes[0] >> 5) {
1451 case 0:
1452 atio->cdb_len = 6;
1453 break;
1454 case 1:
1455 case 2:
1456 atio->cdb_len = 10;
1457 break;
1458 case 4:
1459 atio->cdb_len = 16;
1460 break;
1461 case 5:
1462 atio->cdb_len = 12;
1463 break;
1464 case 3:
1465 default:
1466 /* Only copy the opcode. */
1467 atio->cdb_len = 1;
1468 printf("Reserved or VU command code type encountered\n");
1469 break;
1470 }
1471
1472 memcpy(atio->cdb_io.cdb_bytes, bytes, atio->cdb_len);
1473
1474 atio->ccb_h.status |= CAM_CDB_RECVD;
1475
1476 /* next ORB */
1477 if ((orb[0] & (1<<31)) == 0) {
1478 if (debug)
1479 printf("%s: fetch next orb\n", __func__);
1480 orbi->status.src = SRC_NEXT_EXISTS;
1481 sbp_targ_fetch_orb(orbi->sc, orbi->fwdev,
1482 orb[0], orb[1], orbi->login, FETCH_CMD);
1483 } else {
1484 orbi->status.src = SRC_NO_NEXT;
1485 orbi->login->flags &= ~F_LINK_ACTIVE;
1486 }
1487
1488 orbi->data_hi = orb[2];
1489 orbi->data_lo = orb[3];
1490 orbi->orb4 = *orb4;
1491
1492 xpt_done((union ccb*)atio);
1493 done0:
1494 fw_xfer_free(xfer);
1495 return;
1496 }
1497
1498 static struct sbp_targ_login *
sbp_targ_get_login(struct sbp_targ_softc * sc,struct fw_device * fwdev,int lun)1499 sbp_targ_get_login(struct sbp_targ_softc *sc, struct fw_device *fwdev, int lun)
1500 {
1501 struct sbp_targ_lstate *lstate;
1502 struct sbp_targ_login *login;
1503 int i;
1504
1505 lstate = sc->lstate[lun];
1506
1507 STAILQ_FOREACH(login, &lstate->logins, link)
1508 if (login->fwdev == fwdev)
1509 return (login);
1510
1511 for (i = 0; i < MAX_LOGINS; i++)
1512 if (sc->logins[i] == NULL)
1513 goto found;
1514
1515 printf("%s: increase MAX_LOGIN\n", __func__);
1516 return (NULL);
1517
1518 found:
1519 login = (struct sbp_targ_login *)malloc(
1520 sizeof(struct sbp_targ_login), M_SBP_TARG, M_NOWAIT | M_ZERO);
1521
1522 if (login == NULL) {
1523 printf("%s: malloc failed\n", __func__);
1524 return (NULL);
1525 }
1526
1527 login->id = i;
1528 login->fwdev = fwdev;
1529 login->lstate = lstate;
1530 login->last_hi = 0xffff;
1531 login->last_lo = 0xffffffff;
1532 login->hold_sec = 1;
1533 STAILQ_INIT(&login->orbs);
1534 CALLOUT_INIT(&login->hold_callout);
1535 sc->logins[i] = login;
1536 return (login);
1537 }
1538
1539 static void
sbp_targ_mgm_handler(struct fw_xfer * xfer)1540 sbp_targ_mgm_handler(struct fw_xfer *xfer)
1541 {
1542 struct sbp_targ_lstate *lstate;
1543 struct sbp_targ_login *login;
1544 uint32_t *orb;
1545 struct morb4 *orb4;
1546 struct orb_info *orbi;
1547 int i;
1548
1549 orbi = (struct orb_info *)xfer->sc;
1550 if (xfer->resp != 0) {
1551 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1552 orbi->status.resp = SBP_TRANS_FAIL;
1553 orbi->status.status = OBJ_ORB | SBE_TIMEOUT/*XXX*/;
1554 orbi->status.dead = 1;
1555 orbi->status.len = 1;
1556 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
1557
1558 sbp_targ_status_FIFO(orbi,
1559 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/0);
1560 fw_xfer_free(xfer);
1561 return;
1562 }
1563
1564 orb = orbi->orb;
1565 /* swap payload */
1566 for (i = 0; i < 8; i++) {
1567 orb[i] = ntohl(orb[i]);
1568 }
1569 orb4 = (struct morb4 *)&orb[4];
1570 if (debug)
1571 printf("%s: %s\n", __func__, orb_fun_name[orb4->fun]);
1572
1573 orbi->status.src = SRC_NO_NEXT;
1574
1575 switch (orb4->fun << 16) {
1576 case ORB_FUN_LGI:
1577 {
1578 int exclusive = 0, lun;
1579
1580 if (orb[4] & ORB_EXV)
1581 exclusive = 1;
1582
1583 lun = orb4->id;
1584 lstate = orbi->sc->lstate[lun];
1585
1586 if (lun >= MAX_LUN || lstate == NULL ||
1587 (exclusive &&
1588 STAILQ_FIRST(&lstate->logins) != NULL &&
1589 STAILQ_FIRST(&lstate->logins)->fwdev != orbi->fwdev)
1590 ) {
1591 /* error */
1592 orbi->status.dead = 1;
1593 orbi->status.status = STATUS_ACCESS_DENY;
1594 orbi->status.len = 1;
1595 break;
1596 }
1597
1598 /* allocate login */
1599 login = sbp_targ_get_login(orbi->sc, orbi->fwdev, lun);
1600 if (login == NULL) {
1601 printf("%s: sbp_targ_get_login failed\n",
1602 __func__);
1603 orbi->status.dead = 1;
1604 orbi->status.status = STATUS_RES_UNAVAIL;
1605 orbi->status.len = 1;
1606 break;
1607 }
1608 printf("%s: login id=%d\n", __func__, login->id);
1609
1610 login->fifo_hi = orb[6];
1611 login->fifo_lo = orb[7];
1612 login->loginres.len = htons(sizeof(uint32_t) * 4);
1613 login->loginres.id = htons(login->id);
1614 login->loginres.cmd_hi = htons(SBP_TARG_BIND_HI);
1615 login->loginres.cmd_lo = htonl(SBP_TARG_BIND_LO(login->id));
1616 login->loginres.recon_hold = htons(login->hold_sec);
1617
1618 STAILQ_INSERT_TAIL(&lstate->logins, login, link);
1619 fwmem_write_block(orbi->fwdev, NULL, /*spd*/FWSPD_S400, orb[2], orb[3],
1620 sizeof(struct sbp_login_res), (void *)&login->loginres,
1621 fw_asy_callback_free);
1622 /* XXX return status after loginres is successfully written */
1623 break;
1624 }
1625 case ORB_FUN_RCN:
1626 login = orbi->sc->logins[orb4->id];
1627 if (login != NULL && login->fwdev == orbi->fwdev) {
1628 login->flags &= ~F_HOLD;
1629 callout_stop(&login->hold_callout);
1630 printf("%s: reconnected id=%d\n",
1631 __func__, login->id);
1632 } else {
1633 orbi->status.dead = 1;
1634 orbi->status.status = STATUS_ACCESS_DENY;
1635 printf("%s: reconnection failed id=%d\n",
1636 __func__, orb4->id);
1637 }
1638 break;
1639 case ORB_FUN_LGO:
1640 login = orbi->sc->logins[orb4->id];
1641 if (login->fwdev != orbi->fwdev) {
1642 printf("%s: wrong initiator\n", __func__);
1643 break;
1644 }
1645 sbp_targ_dealloc_login(login);
1646 break;
1647 default:
1648 printf("%s: %s not implemented yet\n",
1649 __func__, orb_fun_name[orb4->fun]);
1650 break;
1651 }
1652 orbi->status.len = 1;
1653 sbp_targ_status_FIFO(orbi, orb[6], orb[7], /*dequeue*/0);
1654 fw_xfer_free(xfer);
1655 return;
1656 }
1657
1658 static void
sbp_targ_pointer_handler(struct fw_xfer * xfer)1659 sbp_targ_pointer_handler(struct fw_xfer *xfer)
1660 {
1661 struct orb_info *orbi;
1662 uint32_t orb0, orb1;
1663
1664 orbi = (struct orb_info *)xfer->sc;
1665 if (xfer->resp != 0) {
1666 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1667 goto done;
1668 }
1669
1670 orb0 = ntohl(orbi->orb[0]);
1671 orb1 = ntohl(orbi->orb[1]);
1672 if ((orb0 & (1U << 31)) != 0) {
1673 printf("%s: invalid pointer\n", __func__);
1674 goto done;
1675 }
1676 sbp_targ_fetch_orb(orbi->login->lstate->sc, orbi->fwdev,
1677 (uint16_t)orb0, orb1, orbi->login, FETCH_CMD);
1678 done:
1679 free(orbi, M_SBP_TARG);
1680 fw_xfer_free(xfer);
1681 return;
1682 }
1683
1684 static void
sbp_targ_fetch_orb(struct sbp_targ_softc * sc,struct fw_device * fwdev,uint16_t orb_hi,uint32_t orb_lo,struct sbp_targ_login * login,int mode)1685 sbp_targ_fetch_orb(struct sbp_targ_softc *sc, struct fw_device *fwdev,
1686 uint16_t orb_hi, uint32_t orb_lo, struct sbp_targ_login *login,
1687 int mode)
1688 {
1689 struct orb_info *orbi;
1690
1691 if (debug)
1692 printf("%s: fetch orb %04x:%08x\n", __func__, orb_hi, orb_lo);
1693 orbi = malloc(sizeof(struct orb_info), M_SBP_TARG, M_NOWAIT | M_ZERO);
1694 if (orbi == NULL) {
1695 printf("%s: malloc failed\n", __func__);
1696 return;
1697 }
1698 orbi->sc = sc;
1699 orbi->fwdev = fwdev;
1700 orbi->login = login;
1701 orbi->orb_hi = orb_hi;
1702 orbi->orb_lo = orb_lo;
1703 orbi->status.orb_hi = htons(orb_hi);
1704 orbi->status.orb_lo = htonl(orb_lo);
1705 orbi->page_table = NULL;
1706
1707 switch (mode) {
1708 case FETCH_MGM:
1709 fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
1710 sizeof(uint32_t) * 8, &orbi->orb[0],
1711 sbp_targ_mgm_handler);
1712 break;
1713 case FETCH_CMD:
1714 orbi->state = ORBI_STATUS_FETCH;
1715 login->last_hi = orb_hi;
1716 login->last_lo = orb_lo;
1717 login->flags |= F_LINK_ACTIVE;
1718 /* dequeue */
1719 SBP_LOCK(sc);
1720 orbi->atio = (struct ccb_accept_tio *)
1721 SLIST_FIRST(&login->lstate->accept_tios);
1722 if (orbi->atio == NULL) {
1723 SBP_UNLOCK(sc);
1724 printf("%s: no free atio\n", __func__);
1725 login->lstate->flags |= F_ATIO_STARVED;
1726 login->flags |= F_ATIO_STARVED;
1727 break;
1728 }
1729 SLIST_REMOVE_HEAD(&login->lstate->accept_tios, sim_links.sle);
1730 STAILQ_INSERT_TAIL(&login->orbs, orbi, link);
1731 SBP_UNLOCK(sc);
1732 fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
1733 sizeof(uint32_t) * 8, &orbi->orb[0],
1734 sbp_targ_cmd_handler);
1735 break;
1736 case FETCH_POINTER:
1737 orbi->state = ORBI_STATUS_POINTER;
1738 login->flags |= F_LINK_ACTIVE;
1739 fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
1740 sizeof(uint32_t) * 2, &orbi->orb[0],
1741 sbp_targ_pointer_handler);
1742 break;
1743 default:
1744 printf("%s: invalid mode %d\n", __func__, mode);
1745 }
1746 }
1747
1748 static void
sbp_targ_resp_callback(struct fw_xfer * xfer)1749 sbp_targ_resp_callback(struct fw_xfer *xfer)
1750 {
1751 struct sbp_targ_softc *sc;
1752
1753 if (debug)
1754 printf("%s: xfer=%p\n", __func__, xfer);
1755 sc = (struct sbp_targ_softc *)xfer->sc;
1756 fw_xfer_unload(xfer);
1757 xfer->recv.pay_len = SBP_TARG_RECV_LEN;
1758 xfer->hand = sbp_targ_recv;
1759 STAILQ_INSERT_TAIL(&sc->fwb.xferlist, xfer, link);
1760 }
1761
1762 static int
sbp_targ_cmd(struct fw_xfer * xfer,struct fw_device * fwdev,int login_id,int reg)1763 sbp_targ_cmd(struct fw_xfer *xfer, struct fw_device *fwdev, int login_id,
1764 int reg)
1765 {
1766 struct sbp_targ_login *login;
1767 struct sbp_targ_softc *sc;
1768 int rtcode = 0;
1769
1770 if (login_id < 0 || login_id >= MAX_LOGINS)
1771 return (RESP_ADDRESS_ERROR);
1772
1773 sc = (struct sbp_targ_softc *)xfer->sc;
1774 login = sc->logins[login_id];
1775 if (login == NULL)
1776 return (RESP_ADDRESS_ERROR);
1777
1778 if (login->fwdev != fwdev) {
1779 /* XXX */
1780 return (RESP_ADDRESS_ERROR);
1781 }
1782
1783 switch (reg) {
1784 case 0x08: /* ORB_POINTER */
1785 if (debug)
1786 printf("%s: ORB_POINTER(%d)\n", __func__, login_id);
1787 if ((login->flags & F_LINK_ACTIVE) != 0) {
1788 if (debug)
1789 printf("link active (ORB_POINTER)\n");
1790 break;
1791 }
1792 sbp_targ_fetch_orb(sc, fwdev,
1793 ntohl(xfer->recv.payload[0]),
1794 ntohl(xfer->recv.payload[1]),
1795 login, FETCH_CMD);
1796 break;
1797 case 0x04: /* AGENT_RESET */
1798 if (debug)
1799 printf("%s: AGENT RESET(%d)\n", __func__, login_id);
1800 login->last_hi = 0xffff;
1801 login->last_lo = 0xffffffff;
1802 sbp_targ_abort(sc, STAILQ_FIRST(&login->orbs));
1803 break;
1804 case 0x10: /* DOORBELL */
1805 if (debug)
1806 printf("%s: DOORBELL(%d)\n", __func__, login_id);
1807 if (login->last_hi == 0xffff &&
1808 login->last_lo == 0xffffffff) {
1809 printf("%s: no previous pointer(DOORBELL)\n",
1810 __func__);
1811 break;
1812 }
1813 if ((login->flags & F_LINK_ACTIVE) != 0) {
1814 if (debug)
1815 printf("link active (DOORBELL)\n");
1816 break;
1817 }
1818 sbp_targ_fetch_orb(sc, fwdev,
1819 login->last_hi, login->last_lo,
1820 login, FETCH_POINTER);
1821 break;
1822 case 0x00: /* AGENT_STATE */
1823 printf("%s: AGENT_STATE (%d:ignore)\n", __func__, login_id);
1824 break;
1825 case 0x14: /* UNSOLICITED_STATE_ENABLE */
1826 printf("%s: UNSOLICITED_STATE_ENABLE (%d:ignore)\n",
1827 __func__, login_id);
1828 break;
1829 default:
1830 printf("%s: invalid register %d(%d)\n",
1831 __func__, reg, login_id);
1832 rtcode = RESP_ADDRESS_ERROR;
1833 }
1834
1835 return (rtcode);
1836 }
1837
1838 static int
sbp_targ_mgm(struct fw_xfer * xfer,struct fw_device * fwdev)1839 sbp_targ_mgm(struct fw_xfer *xfer, struct fw_device *fwdev)
1840 {
1841 struct sbp_targ_softc *sc;
1842 struct fw_pkt *fp;
1843
1844 sc = (struct sbp_targ_softc *)xfer->sc;
1845
1846 fp = &xfer->recv.hdr;
1847 if (fp->mode.wreqb.tcode != FWTCODE_WREQB) {
1848 printf("%s: tcode = %d\n", __func__, fp->mode.wreqb.tcode);
1849 return (RESP_TYPE_ERROR);
1850 }
1851
1852 sbp_targ_fetch_orb(sc, fwdev,
1853 ntohl(xfer->recv.payload[0]),
1854 ntohl(xfer->recv.payload[1]),
1855 NULL, FETCH_MGM);
1856
1857 return (0);
1858 }
1859
1860 static void
sbp_targ_recv(struct fw_xfer * xfer)1861 sbp_targ_recv(struct fw_xfer *xfer)
1862 {
1863 struct fw_pkt *fp, *sfp;
1864 struct fw_device *fwdev;
1865 uint32_t lo;
1866 int rtcode;
1867 struct sbp_targ_softc *sc;
1868
1869 sc = (struct sbp_targ_softc *)xfer->sc;
1870 fp = &xfer->recv.hdr;
1871 fwdev = fw_noderesolve_nodeid(sc->fd.fc, fp->mode.wreqb.src & 0x3f);
1872 if (fwdev == NULL) {
1873 printf("%s: cannot resolve nodeid=%d\n",
1874 __func__, fp->mode.wreqb.src & 0x3f);
1875 rtcode = RESP_TYPE_ERROR; /* XXX */
1876 goto done;
1877 }
1878 lo = fp->mode.wreqb.dest_lo;
1879
1880 if (lo == SBP_TARG_BIND_LO(-1))
1881 rtcode = sbp_targ_mgm(xfer, fwdev);
1882 else if (lo >= SBP_TARG_BIND_LO(0))
1883 rtcode = sbp_targ_cmd(xfer, fwdev, SBP_TARG_LOGIN_ID(lo),
1884 lo % 0x20);
1885 else
1886 rtcode = RESP_ADDRESS_ERROR;
1887
1888 done:
1889 if (rtcode != 0)
1890 printf("%s: rtcode = %d\n", __func__, rtcode);
1891 sfp = &xfer->send.hdr;
1892 xfer->send.spd = FWSPD_S400;
1893 xfer->hand = sbp_targ_resp_callback;
1894 sfp->mode.wres.dst = fp->mode.wreqb.src;
1895 sfp->mode.wres.tlrt = fp->mode.wreqb.tlrt;
1896 sfp->mode.wres.tcode = FWTCODE_WRES;
1897 sfp->mode.wres.rtcode = rtcode;
1898 sfp->mode.wres.pri = 0;
1899
1900 fw_asyreq(xfer->fc, -1, xfer);
1901 }
1902
1903 static int
sbp_targ_attach(device_t dev)1904 sbp_targ_attach(device_t dev)
1905 {
1906 struct sbp_targ_softc *sc;
1907 struct cam_devq *devq;
1908 struct firewire_comm *fc;
1909
1910 sc = (struct sbp_targ_softc *) device_get_softc(dev);
1911 bzero((void *)sc, sizeof(struct sbp_targ_softc));
1912
1913 mtx_init(&sc->mtx, "sbp_targ", NULL, MTX_DEF);
1914 sc->fd.fc = fc = fw_get_comm(dev);
1915 sc->fd.dev = dev;
1916 sc->fd.post_explore = (void *) sbp_targ_post_explore;
1917 sc->fd.post_busreset = (void *) sbp_targ_post_busreset;
1918
1919 devq = cam_simq_alloc(/*maxopenings*/MAX_LUN*MAX_INITIATORS);
1920 if (devq == NULL)
1921 return (ENXIO);
1922
1923 sc->sim = cam_sim_alloc(sbp_targ_action, sbp_targ_poll,
1924 "sbp_targ", sc, device_get_unit(dev), &sc->mtx,
1925 /*untagged*/ 1, /*tagged*/ 1, devq);
1926 if (sc->sim == NULL) {
1927 cam_simq_free(devq);
1928 return (ENXIO);
1929 }
1930
1931 SBP_LOCK(sc);
1932 if (xpt_bus_register(sc->sim, dev, /*bus*/0) != CAM_SUCCESS)
1933 goto fail;
1934
1935 if (xpt_create_path(&sc->path, /*periph*/ NULL, cam_sim_path(sc->sim),
1936 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1937 xpt_bus_deregister(cam_sim_path(sc->sim));
1938 goto fail;
1939 }
1940 SBP_UNLOCK(sc);
1941
1942 sc->fwb.start = SBP_TARG_BIND_START;
1943 sc->fwb.end = SBP_TARG_BIND_END;
1944
1945 /* pre-allocate xfer */
1946 STAILQ_INIT(&sc->fwb.xferlist);
1947 fw_xferlist_add(&sc->fwb.xferlist, M_SBP_TARG,
1948 /*send*/ 0, /*recv*/ SBP_TARG_RECV_LEN, MAX_LUN /* XXX */,
1949 fc, (void *)sc, sbp_targ_recv);
1950 fw_bindadd(fc, &sc->fwb);
1951 return 0;
1952
1953 fail:
1954 SBP_UNLOCK(sc);
1955 cam_sim_free(sc->sim, /*free_devq*/TRUE);
1956 return (ENXIO);
1957 }
1958
1959 static int
sbp_targ_detach(device_t dev)1960 sbp_targ_detach(device_t dev)
1961 {
1962 struct sbp_targ_softc *sc;
1963 struct sbp_targ_lstate *lstate;
1964 int i;
1965
1966 sc = (struct sbp_targ_softc *)device_get_softc(dev);
1967 sc->fd.post_busreset = NULL;
1968
1969 SBP_LOCK(sc);
1970 xpt_free_path(sc->path);
1971 xpt_bus_deregister(cam_sim_path(sc->sim));
1972 cam_sim_free(sc->sim, /*free_devq*/TRUE);
1973 SBP_UNLOCK(sc);
1974
1975 for (i = 0; i < MAX_LUN; i++) {
1976 lstate = sc->lstate[i];
1977 if (lstate != NULL) {
1978 xpt_free_path(lstate->path);
1979 free(lstate, M_SBP_TARG);
1980 }
1981 }
1982 if (sc->black_hole != NULL) {
1983 xpt_free_path(sc->black_hole->path);
1984 free(sc->black_hole, M_SBP_TARG);
1985 }
1986
1987 fw_bindremove(sc->fd.fc, &sc->fwb);
1988 fw_xferlist_remove(&sc->fwb.xferlist);
1989
1990 mtx_destroy(&sc->mtx);
1991
1992 return 0;
1993 }
1994
1995 static device_method_t sbp_targ_methods[] = {
1996 /* device interface */
1997 DEVMETHOD(device_identify, sbp_targ_identify),
1998 DEVMETHOD(device_probe, sbp_targ_probe),
1999 DEVMETHOD(device_attach, sbp_targ_attach),
2000 DEVMETHOD(device_detach, sbp_targ_detach),
2001 DEVMETHOD_END
2002 };
2003
2004 static driver_t sbp_targ_driver = {
2005 "sbp_targ",
2006 sbp_targ_methods,
2007 sizeof(struct sbp_targ_softc),
2008 };
2009
2010 DRIVER_MODULE(sbp_targ, firewire, sbp_targ_driver, 0, 0);
2011 MODULE_VERSION(sbp_targ, 1);
2012 MODULE_DEPEND(sbp_targ, firewire, 1, 1, 1);
2013 MODULE_DEPEND(sbp_targ, cam, 1, 1, 1);
2014