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