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