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