]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/firewire/sbp_targ.c
psm: release resources on attach failure
[FreeBSD/FreeBSD.git] / sys / dev / firewire / sbp_targ.c
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         struct fw_pkt *fp;
1423         uint32_t *orb;
1424         struct corb4 *orb4;
1425         struct orb_info *orbi;
1426         struct ccb_accept_tio *atio;
1427         u_char *bytes;
1428         int i;
1429
1430         orbi = (struct orb_info *)xfer->sc;
1431         if (xfer->resp != 0) {
1432                 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1433                 orbi->status.resp = SBP_TRANS_FAIL;
1434                 orbi->status.status = OBJ_ORB | SBE_TIMEOUT/*XXX*/;
1435                 orbi->status.dead = 1;
1436                 orbi->status.len = 1;
1437                 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
1438
1439                 sbp_targ_status_FIFO(orbi,
1440                     orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
1441                 fw_xfer_free(xfer);
1442                 return;
1443         }
1444         fp = &xfer->recv.hdr;
1445
1446         atio = orbi->atio;
1447
1448         if (orbi->state == ORBI_STATUS_ABORTED) {
1449                 printf("%s: aborted\n", __func__);
1450                 sbp_targ_remove_orb_info(orbi->login, orbi);
1451                 free(orbi, M_SBP_TARG);
1452                 atio->ccb_h.status = CAM_REQ_ABORTED;
1453                 xpt_done((union ccb*)atio);
1454                 goto done0;
1455         }
1456         orbi->state = ORBI_STATUS_ATIO;
1457
1458         orb = orbi->orb;
1459         /* swap payload except SCSI command */
1460         for (i = 0; i < 5; i++)
1461                 orb[i] = ntohl(orb[i]);
1462
1463         orb4 = (struct corb4 *)&orb[4];
1464         if (orb4->rq_fmt != 0) {
1465                 /* XXX */
1466                 printf("%s: rq_fmt(%d) != 0\n", __func__, orb4->rq_fmt);
1467         }
1468
1469         atio->ccb_h.target_id = 0; /* XXX */
1470         atio->ccb_h.target_lun = orbi->login->lstate->lun;
1471         atio->sense_len = 0;
1472         atio->tag_action = MSG_SIMPLE_TASK;
1473         atio->tag_id = orbi->orb_lo;
1474         atio->init_id = orbi->login->id;
1475
1476         atio->ccb_h.flags |= CAM_TAG_ACTION_VALID;
1477         bytes = (u_char *)&orb[5];
1478         if (debug)
1479                 printf("%s: %p %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
1480                     __func__, (void *)atio,
1481                     bytes[0], bytes[1], bytes[2], bytes[3], bytes[4],
1482                     bytes[5], bytes[6], bytes[7], bytes[8], bytes[9]);
1483         switch (bytes[0] >> 5) {
1484         case 0:
1485                 atio->cdb_len = 6;
1486                 break;
1487         case 1:
1488         case 2:
1489                 atio->cdb_len = 10;
1490                 break;
1491         case 4:
1492                 atio->cdb_len = 16;
1493                 break;
1494         case 5:
1495                 atio->cdb_len = 12;
1496                 break;
1497         case 3:
1498         default:
1499                 /* Only copy the opcode. */
1500                 atio->cdb_len = 1;
1501                 printf("Reserved or VU command code type encountered\n");
1502                 break;
1503         }
1504
1505         memcpy(atio->cdb_io.cdb_bytes, bytes, atio->cdb_len);
1506
1507         atio->ccb_h.status |= CAM_CDB_RECVD;
1508
1509         /* next ORB */
1510         if ((orb[0] & (1<<31)) == 0) {
1511                 if (debug)
1512                         printf("%s: fetch next orb\n", __func__);
1513                 orbi->status.src = SRC_NEXT_EXISTS;
1514                 sbp_targ_fetch_orb(orbi->sc, orbi->fwdev,
1515                     orb[0], orb[1], orbi->login, FETCH_CMD);
1516         } else {
1517                 orbi->status.src = SRC_NO_NEXT;
1518                 orbi->login->flags &= ~F_LINK_ACTIVE;
1519         }
1520
1521         orbi->data_hi = orb[2];
1522         orbi->data_lo = orb[3];
1523         orbi->orb4 = *orb4;
1524
1525         xpt_done((union ccb*)atio);
1526 done0:
1527         fw_xfer_free(xfer);
1528         return;
1529 }
1530
1531 static struct sbp_targ_login *
1532 sbp_targ_get_login(struct sbp_targ_softc *sc, struct fw_device *fwdev, int lun)
1533 {
1534         struct sbp_targ_lstate *lstate;
1535         struct sbp_targ_login *login;
1536         int i;
1537
1538         lstate = sc->lstate[lun];
1539
1540         STAILQ_FOREACH(login, &lstate->logins, link)
1541                 if (login->fwdev == fwdev)
1542                         return (login);
1543
1544         for (i = 0; i < MAX_LOGINS; i++)
1545                 if (sc->logins[i] == NULL)
1546                         goto found;
1547
1548         printf("%s: increase MAX_LOGIN\n", __func__);
1549         return (NULL);
1550
1551 found:
1552         login = (struct sbp_targ_login *)malloc(
1553             sizeof(struct sbp_targ_login), M_SBP_TARG, M_NOWAIT | M_ZERO);
1554
1555         if (login == NULL) {
1556                 printf("%s: malloc failed\n", __func__);
1557                 return (NULL);
1558         }
1559
1560         login->id = i;
1561         login->fwdev = fwdev;
1562         login->lstate = lstate;
1563         login->last_hi = 0xffff;
1564         login->last_lo = 0xffffffff;
1565         login->hold_sec = 1;
1566         STAILQ_INIT(&login->orbs);
1567         CALLOUT_INIT(&login->hold_callout);
1568         sc->logins[i] = login;
1569         return (login);
1570 }
1571
1572 static void
1573 sbp_targ_mgm_handler(struct fw_xfer *xfer)
1574 {
1575         struct sbp_targ_lstate *lstate;
1576         struct sbp_targ_login *login;
1577         struct fw_pkt *fp;
1578         uint32_t *orb;
1579         struct morb4 *orb4;
1580         struct orb_info *orbi;
1581         int i;
1582
1583         orbi = (struct orb_info *)xfer->sc;
1584         if (xfer->resp != 0) {
1585                 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1586                 orbi->status.resp = SBP_TRANS_FAIL;
1587                 orbi->status.status = OBJ_ORB | SBE_TIMEOUT/*XXX*/;
1588                 orbi->status.dead = 1;
1589                 orbi->status.len = 1;
1590                 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
1591
1592                 sbp_targ_status_FIFO(orbi,
1593                     orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/0);
1594                 fw_xfer_free(xfer);
1595                 return;
1596         }
1597         fp = &xfer->recv.hdr;
1598
1599         orb = orbi->orb;
1600         /* swap payload */
1601         for (i = 0; i < 8; i++) {
1602                 orb[i] = ntohl(orb[i]);
1603         }
1604         orb4 = (struct morb4 *)&orb[4];
1605         if (debug)
1606                 printf("%s: %s\n", __func__, orb_fun_name[orb4->fun]);
1607
1608         orbi->status.src = SRC_NO_NEXT;
1609
1610         switch (orb4->fun << 16) {
1611         case ORB_FUN_LGI:
1612         {
1613                 int exclusive = 0, lun;
1614
1615                 if (orb[4] & ORB_EXV)
1616                         exclusive = 1;
1617
1618                 lun = orb4->id;
1619                 lstate = orbi->sc->lstate[lun];
1620
1621                 if (lun >= MAX_LUN || lstate == NULL ||
1622                     (exclusive &&
1623                     STAILQ_FIRST(&lstate->logins) != NULL &&
1624                     STAILQ_FIRST(&lstate->logins)->fwdev != orbi->fwdev)
1625                    ) {
1626                         /* error */
1627                         orbi->status.dead = 1;
1628                         orbi->status.status = STATUS_ACCESS_DENY;
1629                         orbi->status.len = 1;
1630                         break;
1631                 }
1632
1633                 /* allocate login */
1634                 login = sbp_targ_get_login(orbi->sc, orbi->fwdev, lun);
1635                 if (login == NULL) {
1636                         printf("%s: sbp_targ_get_login failed\n",
1637                             __func__);
1638                         orbi->status.dead = 1;
1639                         orbi->status.status = STATUS_RES_UNAVAIL;
1640                         orbi->status.len = 1;
1641                         break;
1642                 }
1643                 printf("%s: login id=%d\n", __func__, login->id);
1644
1645                 login->fifo_hi = orb[6];
1646                 login->fifo_lo = orb[7];
1647                 login->loginres.len = htons(sizeof(uint32_t) * 4);
1648                 login->loginres.id = htons(login->id);
1649                 login->loginres.cmd_hi = htons(SBP_TARG_BIND_HI);
1650                 login->loginres.cmd_lo = htonl(SBP_TARG_BIND_LO(login->id));
1651                 login->loginres.recon_hold = htons(login->hold_sec);
1652
1653                 STAILQ_INSERT_TAIL(&lstate->logins, login, link);
1654                 fwmem_write_block(orbi->fwdev, NULL, /*spd*/FWSPD_S400, orb[2], orb[3],
1655                     sizeof(struct sbp_login_res), (void *)&login->loginres,
1656                     fw_asy_callback_free);
1657                 /* XXX return status after loginres is successfully written */
1658                 break;
1659         }
1660         case ORB_FUN_RCN:
1661                 login = orbi->sc->logins[orb4->id];
1662                 if (login != NULL && login->fwdev == orbi->fwdev) {
1663                         login->flags &= ~F_HOLD;
1664                         callout_stop(&login->hold_callout);
1665                         printf("%s: reconnected id=%d\n",
1666                             __func__, login->id);
1667                 } else {
1668                         orbi->status.dead = 1;
1669                         orbi->status.status = STATUS_ACCESS_DENY;
1670                         printf("%s: reconnection faild id=%d\n",
1671                             __func__, orb4->id);
1672                 }
1673                 break;
1674         case ORB_FUN_LGO:
1675                 login = orbi->sc->logins[orb4->id];
1676                 if (login->fwdev != orbi->fwdev) {
1677                         printf("%s: wrong initiator\n", __func__);
1678                         break;
1679                 }
1680                 sbp_targ_dealloc_login(login);
1681                 break;
1682         default:
1683                 printf("%s: %s not implemented yet\n",
1684                     __func__, orb_fun_name[orb4->fun]);
1685                 break;
1686         }
1687         orbi->status.len = 1;
1688         sbp_targ_status_FIFO(orbi, orb[6], orb[7], /*dequeue*/0);
1689         fw_xfer_free(xfer);
1690         return;
1691 }
1692
1693 static void
1694 sbp_targ_pointer_handler(struct fw_xfer *xfer)
1695 {
1696         struct orb_info *orbi;
1697         uint32_t orb0, orb1;
1698
1699         orbi = (struct orb_info *)xfer->sc;
1700         if (xfer->resp != 0) {
1701                 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1702                 goto done;
1703         }
1704
1705         orb0 = ntohl(orbi->orb[0]);
1706         orb1 = ntohl(orbi->orb[1]);
1707         if ((orb0 & (1U << 31)) != 0) {
1708                 printf("%s: invalid pointer\n", __func__);
1709                 goto done;
1710         }
1711         sbp_targ_fetch_orb(orbi->login->lstate->sc, orbi->fwdev,
1712             (uint16_t)orb0, orb1, orbi->login, FETCH_CMD);
1713 done:
1714         free(orbi, M_SBP_TARG);
1715         fw_xfer_free(xfer);
1716         return;
1717 }
1718
1719 static void
1720 sbp_targ_fetch_orb(struct sbp_targ_softc *sc, struct fw_device *fwdev,
1721     uint16_t orb_hi, uint32_t orb_lo, struct sbp_targ_login *login,
1722     int mode)
1723 {
1724         struct orb_info *orbi;
1725
1726         if (debug)
1727                 printf("%s: fetch orb %04x:%08x\n", __func__, orb_hi, orb_lo);
1728         orbi = malloc(sizeof(struct orb_info), M_SBP_TARG, M_NOWAIT | M_ZERO);
1729         if (orbi == NULL) {
1730                 printf("%s: malloc failed\n", __func__);
1731                 return;
1732         }
1733         orbi->sc = sc;
1734         orbi->fwdev = fwdev;
1735         orbi->login = login;
1736         orbi->orb_hi = orb_hi;
1737         orbi->orb_lo = orb_lo;
1738         orbi->status.orb_hi = htons(orb_hi);
1739         orbi->status.orb_lo = htonl(orb_lo);
1740         orbi->page_table = NULL;
1741
1742         switch (mode) {
1743         case FETCH_MGM:
1744                 fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
1745                     sizeof(uint32_t) * 8, &orbi->orb[0],
1746                     sbp_targ_mgm_handler);
1747                 break;
1748         case FETCH_CMD:
1749                 orbi->state = ORBI_STATUS_FETCH;
1750                 login->last_hi = orb_hi;
1751                 login->last_lo = orb_lo;
1752                 login->flags |= F_LINK_ACTIVE;
1753                 /* dequeue */
1754                 SBP_LOCK(sc);
1755                 orbi->atio = (struct ccb_accept_tio *)
1756                     SLIST_FIRST(&login->lstate->accept_tios);
1757                 if (orbi->atio == NULL) {
1758                         SBP_UNLOCK(sc);
1759                         printf("%s: no free atio\n", __func__);
1760                         login->lstate->flags |= F_ATIO_STARVED;
1761                         login->flags |= F_ATIO_STARVED;
1762 #if 0
1763                         /* XXX ?? */
1764                         login->fwdev = fwdev;
1765 #endif
1766                         break;
1767                 }
1768                 SLIST_REMOVE_HEAD(&login->lstate->accept_tios, sim_links.sle);
1769                 STAILQ_INSERT_TAIL(&login->orbs, orbi, link);
1770                 SBP_UNLOCK(sc);
1771                 fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
1772                     sizeof(uint32_t) * 8, &orbi->orb[0],
1773                     sbp_targ_cmd_handler);
1774                 break;
1775         case FETCH_POINTER:
1776                 orbi->state = ORBI_STATUS_POINTER;
1777                 login->flags |= F_LINK_ACTIVE;
1778                 fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
1779                     sizeof(uint32_t) * 2, &orbi->orb[0],
1780                     sbp_targ_pointer_handler);
1781                 break;
1782         default:
1783                 printf("%s: invalid mode %d\n", __func__, mode);
1784         }
1785 }
1786
1787 static void
1788 sbp_targ_resp_callback(struct fw_xfer *xfer)
1789 {
1790         struct sbp_targ_softc *sc;
1791         int s;
1792
1793         if (debug)
1794                 printf("%s: xfer=%p\n", __func__, xfer);
1795         sc = (struct sbp_targ_softc *)xfer->sc;
1796         fw_xfer_unload(xfer);
1797         xfer->recv.pay_len = SBP_TARG_RECV_LEN;
1798         xfer->hand = sbp_targ_recv;
1799         s = splfw();
1800         STAILQ_INSERT_TAIL(&sc->fwb.xferlist, xfer, link);
1801         splx(s);
1802 }
1803
1804 static int
1805 sbp_targ_cmd(struct fw_xfer *xfer, struct fw_device *fwdev, int login_id,
1806     int reg)
1807 {
1808         struct sbp_targ_login *login;
1809         struct sbp_targ_softc *sc;
1810         int rtcode = 0;
1811
1812         if (login_id < 0 || login_id >= MAX_LOGINS)
1813                 return (RESP_ADDRESS_ERROR);
1814
1815         sc = (struct sbp_targ_softc *)xfer->sc;
1816         login = sc->logins[login_id];
1817         if (login == NULL)
1818                 return (RESP_ADDRESS_ERROR);
1819
1820         if (login->fwdev != fwdev) {
1821                 /* XXX */
1822                 return (RESP_ADDRESS_ERROR);
1823         }
1824
1825         switch (reg) {
1826         case 0x08:      /* ORB_POINTER */
1827                 if (debug)
1828                         printf("%s: ORB_POINTER(%d)\n", __func__, login_id);
1829                 if ((login->flags & F_LINK_ACTIVE) != 0) {
1830                         if (debug)
1831                                 printf("link active (ORB_POINTER)\n");
1832                         break;
1833                 }
1834                 sbp_targ_fetch_orb(sc, fwdev,
1835                     ntohl(xfer->recv.payload[0]),
1836                     ntohl(xfer->recv.payload[1]),
1837                     login, FETCH_CMD);
1838                 break;
1839         case 0x04:      /* AGENT_RESET */
1840                 if (debug)
1841                         printf("%s: AGENT RESET(%d)\n", __func__, login_id);
1842                 login->last_hi = 0xffff;
1843                 login->last_lo = 0xffffffff;
1844                 sbp_targ_abort(sc, STAILQ_FIRST(&login->orbs));
1845                 break;
1846         case 0x10:      /* DOORBELL */
1847                 if (debug)
1848                         printf("%s: DOORBELL(%d)\n", __func__, login_id);
1849                 if (login->last_hi == 0xffff &&
1850                     login->last_lo == 0xffffffff) {
1851                         printf("%s: no previous pointer(DOORBELL)\n",
1852                             __func__);
1853                         break;
1854                 }
1855                 if ((login->flags & F_LINK_ACTIVE) != 0) {
1856                         if (debug)
1857                                 printf("link active (DOORBELL)\n");
1858                         break;
1859                 }
1860                 sbp_targ_fetch_orb(sc, fwdev,
1861                     login->last_hi, login->last_lo,
1862                     login, FETCH_POINTER);
1863                 break;
1864         case 0x00:      /* AGENT_STATE */
1865                 printf("%s: AGENT_STATE (%d:ignore)\n", __func__, login_id);
1866                 break;
1867         case 0x14:      /* UNSOLICITED_STATE_ENABLE */
1868                 printf("%s: UNSOLICITED_STATE_ENABLE (%d:ignore)\n",
1869                                                          __func__, login_id);
1870                 break;
1871         default:
1872                 printf("%s: invalid register %d(%d)\n",
1873                                                  __func__, reg, login_id);
1874                 rtcode = RESP_ADDRESS_ERROR;
1875         }
1876
1877         return (rtcode);
1878 }
1879
1880 static int
1881 sbp_targ_mgm(struct fw_xfer *xfer, struct fw_device *fwdev)
1882 {
1883         struct sbp_targ_softc *sc;
1884         struct fw_pkt *fp;
1885
1886         sc = (struct sbp_targ_softc *)xfer->sc;
1887
1888         fp = &xfer->recv.hdr;
1889         if (fp->mode.wreqb.tcode != FWTCODE_WREQB) {
1890                 printf("%s: tcode = %d\n", __func__, fp->mode.wreqb.tcode);
1891                 return (RESP_TYPE_ERROR);
1892         }
1893
1894         sbp_targ_fetch_orb(sc, fwdev,
1895             ntohl(xfer->recv.payload[0]),
1896             ntohl(xfer->recv.payload[1]),
1897             NULL, FETCH_MGM);
1898
1899         return (0);
1900 }
1901
1902 static void
1903 sbp_targ_recv(struct fw_xfer *xfer)
1904 {
1905         struct fw_pkt *fp, *sfp;
1906         struct fw_device *fwdev;
1907         uint32_t lo;
1908         int s, rtcode;
1909         struct sbp_targ_softc *sc;
1910
1911         s = splfw();
1912         sc = (struct sbp_targ_softc *)xfer->sc;
1913         fp = &xfer->recv.hdr;
1914         fwdev = fw_noderesolve_nodeid(sc->fd.fc, fp->mode.wreqb.src & 0x3f);
1915         if (fwdev == NULL) {
1916                 printf("%s: cannot resolve nodeid=%d\n",
1917                     __func__, fp->mode.wreqb.src & 0x3f);
1918                 rtcode = RESP_TYPE_ERROR; /* XXX */
1919                 goto done;
1920         }
1921         lo = fp->mode.wreqb.dest_lo;
1922
1923         if (lo == SBP_TARG_BIND_LO(-1))
1924                 rtcode = sbp_targ_mgm(xfer, fwdev);
1925         else if (lo >= SBP_TARG_BIND_LO(0))
1926                 rtcode = sbp_targ_cmd(xfer, fwdev, SBP_TARG_LOGIN_ID(lo),
1927                     lo % 0x20);
1928         else
1929                 rtcode = RESP_ADDRESS_ERROR;
1930
1931 done:
1932         if (rtcode != 0)
1933                 printf("%s: rtcode = %d\n", __func__, rtcode);
1934         sfp = &xfer->send.hdr;
1935         xfer->send.spd = FWSPD_S400;
1936         xfer->hand = sbp_targ_resp_callback;
1937         sfp->mode.wres.dst = fp->mode.wreqb.src;
1938         sfp->mode.wres.tlrt = fp->mode.wreqb.tlrt;
1939         sfp->mode.wres.tcode = FWTCODE_WRES;
1940         sfp->mode.wres.rtcode = rtcode;
1941         sfp->mode.wres.pri = 0;
1942
1943         fw_asyreq(xfer->fc, -1, xfer);
1944         splx(s);
1945 }
1946
1947 static int
1948 sbp_targ_attach(device_t dev)
1949 {
1950         struct sbp_targ_softc *sc;
1951         struct cam_devq *devq;
1952         struct firewire_comm *fc;
1953
1954         sc = (struct sbp_targ_softc *) device_get_softc(dev);
1955         bzero((void *)sc, sizeof(struct sbp_targ_softc));
1956
1957         mtx_init(&sc->mtx, "sbp_targ", NULL, MTX_DEF);
1958         sc->fd.fc = fc = device_get_ivars(dev);
1959         sc->fd.dev = dev;
1960         sc->fd.post_explore = (void *) sbp_targ_post_explore;
1961         sc->fd.post_busreset = (void *) sbp_targ_post_busreset;
1962
1963         devq = cam_simq_alloc(/*maxopenings*/MAX_LUN*MAX_INITIATORS);
1964         if (devq == NULL)
1965                 return (ENXIO);
1966
1967         sc->sim = cam_sim_alloc(sbp_targ_action, sbp_targ_poll,
1968             "sbp_targ", sc, device_get_unit(dev), &sc->mtx,
1969             /*untagged*/ 1, /*tagged*/ 1, devq);
1970         if (sc->sim == NULL) {
1971                 cam_simq_free(devq);
1972                 return (ENXIO);
1973         }
1974
1975         SBP_LOCK(sc);
1976         if (xpt_bus_register(sc->sim, dev, /*bus*/0) != CAM_SUCCESS)
1977                 goto fail;
1978
1979         if (xpt_create_path(&sc->path, /*periph*/ NULL, cam_sim_path(sc->sim),
1980             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1981                 xpt_bus_deregister(cam_sim_path(sc->sim));
1982                 goto fail;
1983         }
1984         SBP_UNLOCK(sc);
1985
1986         sc->fwb.start = SBP_TARG_BIND_START;
1987         sc->fwb.end = SBP_TARG_BIND_END;
1988
1989         /* pre-allocate xfer */
1990         STAILQ_INIT(&sc->fwb.xferlist);
1991         fw_xferlist_add(&sc->fwb.xferlist, M_SBP_TARG,
1992             /*send*/ 0, /*recv*/ SBP_TARG_RECV_LEN, MAX_LUN /* XXX */,
1993             fc, (void *)sc, sbp_targ_recv);
1994         fw_bindadd(fc, &sc->fwb);
1995         return 0;
1996
1997 fail:
1998         SBP_UNLOCK(sc);
1999         cam_sim_free(sc->sim, /*free_devq*/TRUE);
2000         return (ENXIO);
2001 }
2002
2003 static int
2004 sbp_targ_detach(device_t dev)
2005 {
2006         struct sbp_targ_softc *sc;
2007         struct sbp_targ_lstate *lstate;
2008         int i;
2009
2010         sc = (struct sbp_targ_softc *)device_get_softc(dev);
2011         sc->fd.post_busreset = NULL;
2012
2013         SBP_LOCK(sc);
2014         xpt_free_path(sc->path);
2015         xpt_bus_deregister(cam_sim_path(sc->sim));
2016         cam_sim_free(sc->sim, /*free_devq*/TRUE);
2017         SBP_UNLOCK(sc);
2018
2019         for (i = 0; i < MAX_LUN; i++) {
2020                 lstate = sc->lstate[i];
2021                 if (lstate != NULL) {
2022                         xpt_free_path(lstate->path);
2023                         free(lstate, M_SBP_TARG);
2024                 }
2025         }
2026         if (sc->black_hole != NULL) {
2027                 xpt_free_path(sc->black_hole->path);
2028                 free(sc->black_hole, M_SBP_TARG);
2029         }
2030
2031         fw_bindremove(sc->fd.fc, &sc->fwb);
2032         fw_xferlist_remove(&sc->fwb.xferlist);
2033
2034         mtx_destroy(&sc->mtx);
2035
2036         return 0;
2037 }
2038
2039 static devclass_t sbp_targ_devclass;
2040
2041 static device_method_t sbp_targ_methods[] = {
2042         /* device interface */
2043         DEVMETHOD(device_identify,      sbp_targ_identify),
2044         DEVMETHOD(device_probe,         sbp_targ_probe),
2045         DEVMETHOD(device_attach,        sbp_targ_attach),
2046         DEVMETHOD(device_detach,        sbp_targ_detach),
2047         { 0, 0 }
2048 };
2049
2050 static driver_t sbp_targ_driver = {
2051         "sbp_targ",
2052         sbp_targ_methods,
2053         sizeof(struct sbp_targ_softc),
2054 };
2055
2056 DRIVER_MODULE(sbp_targ, firewire, sbp_targ_driver, sbp_targ_devclass, 0, 0);
2057 MODULE_VERSION(sbp_targ, 1);
2058 MODULE_DEPEND(sbp_targ, firewire, 1, 1, 1);
2059 MODULE_DEPEND(sbp_targ, cam, 1, 1, 1);