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