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