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